* [PATCH 01/13] dt-bindings: soc: Introduce device bindings for CESTA Resource Manager
2026-04-20 16:28 [PATCH 00/13] Add support to control clocks using CESTA Resource manager Jagadeesh Kona
@ 2026-04-20 16:28 ` Jagadeesh Kona
2026-04-20 17:39 ` Dmitry Baryshkov
2026-04-22 7:37 ` Krzysztof Kozlowski
2026-04-20 16:28 ` [PATCH 02/13] dt-bindings: clock: qcom,sm8550-dispcc: Add display CESTA support on SM8750 Jagadeesh Kona
` (10 subsequent siblings)
11 siblings, 2 replies; 24+ messages in thread
From: Jagadeesh Kona @ 2026-04-20 16:28 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones
Cc: Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree, linux-kernel,
linux-clk, Maulik Shah, Taniya Das, Jagadeesh Kona
From: Maulik Shah <maulik.shah@oss.qualcomm.com>
Add device binding documentation for Qualcomm Technologies, Inc. (QTI)
CESTA (Client State Aggregation) Resource Manager which is responsible
for client side management and aggregation of local resources.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
---
.../devicetree/bindings/soc/qcom/qcom,crm.yaml | 83 ++++++++++++++++++++++
1 file changed, 83 insertions(+)
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,crm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,crm.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a1485db8b7476b0cb0b4e8a41adc8fb4092b731f
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,crm.yaml
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/qcom/qcom,crm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. (QTI) CESTA Resource Manager (CRM)
+
+maintainers:
+ - Maulik Shah <maulik.shah@oss.qualcomm.com>
+
+description:
+ Support for communication with the hardened-CRM blocks. A set of SW
+ client Direct Resource Voters (DRVs) in CRM provides interface to vote
+ desired power state of resources local to a subsystem.
+
+properties:
+ compatible:
+ enum:
+ - qcom,sm8750-disp-crm
+
+ label:
+ $ref: /schemas/types.yaml#/definitions/string-array
+ oneOf:
+ - description: Specifies the name of the CRM.
+ items:
+ - enum:
+ - disp_crm
+
+ reg:
+ minItems: 2
+
+ power-domains:
+ maxItems: 1
+
+ interrupts:
+ minItems: 1
+ maxItems: 6
+ description:
+ One interrupt for each DRV. The interrupt trips when a message complete/response is
+ received from the accelerators for the desired power state. Number of interrupts must
+ match number of DRV blocks.
+
+ qcom,sw-drv-ids:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 1
+ maxItems: 6
+ items:
+ minimum: 0
+ maximum: 5
+ description:
+ List of SW DRV IDs used within kernel. May contain holes as some DRVs can
+ be allocated to DSPs / can be spare.
+
+required:
+ - compatible
+ - label
+ - reg
+ - interrupts
+ - qcom,sw-drv-ids
+
+additionalProperties: false
+
+examples:
+ # Example of Display CRM device with SW DRVs
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/power/qcom,rpmhpd.h>
+ disp_crm: crm@af21000 {
+ compatible = "qcom,sm8750-disp-crm";
+ label = "disp_crm";
+ reg = <0x0af21000 0x6000>,
+ <0x0af29f00 0x100>;
+ power-domains = <&rpmhpd RPMHPD_MMCX>;
+ interrupts = <GIC_SPI 703 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 708 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 714 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 68 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 96 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 249 IRQ_TYPE_EDGE_RISING>;
+ qcom,sw-drv-ids = <0 1 2 3 4 5>;
+ };
+...
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* Re: [PATCH 01/13] dt-bindings: soc: Introduce device bindings for CESTA Resource Manager
2026-04-20 16:28 ` [PATCH 01/13] dt-bindings: soc: Introduce device bindings for CESTA Resource Manager Jagadeesh Kona
@ 2026-04-20 17:39 ` Dmitry Baryshkov
2026-04-22 7:37 ` Krzysztof Kozlowski
1 sibling, 0 replies; 24+ messages in thread
From: Dmitry Baryshkov @ 2026-04-20 17:39 UTC (permalink / raw)
To: Jagadeesh Kona
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones, Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree,
linux-kernel, linux-clk, Maulik Shah, Taniya Das
On Mon, Apr 20, 2026 at 09:58:54PM +0530, Jagadeesh Kona wrote:
> From: Maulik Shah <maulik.shah@oss.qualcomm.com>
>
> Add device binding documentation for Qualcomm Technologies, Inc. (QTI)
> CESTA (Client State Aggregation) Resource Manager which is responsible
> for client side management and aggregation of local resources.
>
> Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
> Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
> ---
> .../devicetree/bindings/soc/qcom/qcom,crm.yaml | 83 ++++++++++++++++++++++
> 1 file changed, 83 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,crm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,crm.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..a1485db8b7476b0cb0b4e8a41adc8fb4092b731f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,crm.yaml
> @@ -0,0 +1,83 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/soc/qcom/qcom,crm.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Qualcomm Technologies, Inc. (QTI) CESTA Resource Manager (CRM)
> +
> +maintainers:
> + - Maulik Shah <maulik.shah@oss.qualcomm.com>
> +
> +description:
> + Support for communication with the hardened-CRM blocks. A set of SW
> + client Direct Resource Voters (DRVs) in CRM provides interface to vote
> + desired power state of resources local to a subsystem.
> +
> +properties:
> + compatible:
> + enum:
> + - qcom,sm8750-disp-crm
Is it specific to the display? Are there any other CRM blocks?
> +
> + label:
> + $ref: /schemas/types.yaml#/definitions/string-array
> + oneOf:
> + - description: Specifies the name of the CRM.
> + items:
> + - enum:
> + - disp_crm
What for?
> +
> + reg:
> + minItems: 2
> +
> + power-domains:
> + maxItems: 1
> +
> + interrupts:
> + minItems: 1
> + maxItems: 6
> + description:
> + One interrupt for each DRV. The interrupt trips when a message complete/response is
> + received from the accelerators for the desired power state. Number of interrupts must
> + match number of DRV blocks.
> +
> + qcom,sw-drv-ids:
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + minItems: 1
> + maxItems: 6
> + items:
> + minimum: 0
> + maximum: 5
> + description:
> + List of SW DRV IDs used within kernel. May contain holes as some DRVs can
> + be allocated to DSPs / can be spare.
is this list defined by the kernel? Or by the fact that it's a display
CRM on SM8750? Why do we need it in the DT?
> +
> +required:
> + - compatible
> + - label
> + - reg
> + - interrupts
> + - qcom,sw-drv-ids
> +
> +additionalProperties: false
> +
> +examples:
> + # Example of Display CRM device with SW DRVs
> + - |
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> + #include <dt-bindings/power/qcom,rpmhpd.h>
> + disp_crm: crm@af21000 {
> + compatible = "qcom,sm8750-disp-crm";
> + label = "disp_crm";
> + reg = <0x0af21000 0x6000>,
> + <0x0af29f00 0x100>;
> + power-domains = <&rpmhpd RPMHPD_MMCX>;
> + interrupts = <GIC_SPI 703 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 708 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 714 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 68 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 96 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 249 IRQ_TYPE_EDGE_RISING>;
> + qcom,sw-drv-ids = <0 1 2 3 4 5>;
> + };
> +...
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH 01/13] dt-bindings: soc: Introduce device bindings for CESTA Resource Manager
2026-04-20 16:28 ` [PATCH 01/13] dt-bindings: soc: Introduce device bindings for CESTA Resource Manager Jagadeesh Kona
2026-04-20 17:39 ` Dmitry Baryshkov
@ 2026-04-22 7:37 ` Krzysztof Kozlowski
1 sibling, 0 replies; 24+ messages in thread
From: Krzysztof Kozlowski @ 2026-04-22 7:37 UTC (permalink / raw)
To: Jagadeesh Kona
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones, Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree,
linux-kernel, linux-clk, Maulik Shah, Taniya Das
On Mon, Apr 20, 2026 at 09:58:54PM +0530, Jagadeesh Kona wrote:
> From: Maulik Shah <maulik.shah@oss.qualcomm.com>
>
> Add device binding documentation for Qualcomm Technologies, Inc. (QTI)
> CESTA (Client State Aggregation) Resource Manager which is responsible
> for client side management and aggregation of local resources.
>
> Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
> Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
A nit, subject: drop second/last, redundant "device bindings for". The
"dt-bindings" prefix is already stating that these are bindings and they
cannot be for a "non-device".
See also:
https://elixir.bootlin.com/linux/v6.17-rc3/source/Documentation/devicetree/bindings/submitting-patches.rst#L18
> ---
> .../devicetree/bindings/soc/qcom/qcom,crm.yaml | 83 ++++++++++++++++++++++
> 1 file changed, 83 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,crm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,crm.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..a1485db8b7476b0cb0b4e8a41adc8fb4092b731f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,crm.yaml
Filename must match compatible.
> @@ -0,0 +1,83 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/soc/qcom/qcom,crm.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Qualcomm Technologies, Inc. (QTI) CESTA Resource Manager (CRM)
> +
> +maintainers:
> + - Maulik Shah <maulik.shah@oss.qualcomm.com>
> +
> +description:
> + Support for communication with the hardened-CRM blocks. A set of SW
What is a hardened-CRM device? How can you harden a block? Are we
talking about steel manufacturing or software security?
> + client Direct Resource Voters (DRVs) in CRM provides interface to vote
> + desired power state of resources local to a subsystem.
I still don't get what this device is doing.
> +
> +properties:
> + compatible:
> + enum:
> + - qcom,sm8750-disp-crm
> +
> + label:
> + $ref: /schemas/types.yaml#/definitions/string-array
> + oneOf:
> + - description: Specifies the name of the CRM.
> + items:
> + - enum:
> + - disp_crm
Nope, same as compatible so pointless.
> +
> + reg:
> + minItems: 2
There is no such syntax. And if you did run it via internal review tool,
that tool would probably tell you that.
> +
> + power-domains:
> + maxItems: 1
> +
> + interrupts:
> + minItems: 1
> + maxItems: 6
Nope. Standard bindings rules - we do not have flexible lists. Please
follow writing bindings or any of previous DTS speech slides.
> + description:
> + One interrupt for each DRV. The interrupt trips when a message complete/response is
> + received from the accelerators for the desired power state. Number of interrupts must
> + match number of DRV blocks.
> +
> + qcom,sw-drv-ids:
Drop the property. For sure we do not want drivers in the bindings.
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + minItems: 1
> + maxItems: 6
> + items:
> + minimum: 0
> + maximum: 5
> + description:
> + List of SW DRV IDs used within kernel. May contain holes as some DRVs can
> + be allocated to DSPs / can be spare.
> +
> +required:
> + - compatible
> + - label
> + - reg
> + - interrupts
> + - qcom,sw-drv-ids
> +
> +additionalProperties: false
> +
> +examples:
> + # Example of Display CRM device with SW DRVs
Drop
> + - |
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> + #include <dt-bindings/power/qcom,rpmhpd.h>
> + disp_crm: crm@af21000 {
Drop label.
Node names should be generic. See also an explanation and list of
examples (not exhaustive) in DT specification:
https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation
If you cannot find a name matching your device, please check in kernel
sources for similar cases or you can grow the spec (via pull request to
DT spec repo).
> + compatible = "qcom,sm8750-disp-crm";
> + label = "disp_crm";
> + reg = <0x0af21000 0x6000>,
> + <0x0af29f00 0x100>;
> + power-domains = <&rpmhpd RPMHPD_MMCX>;
> + interrupts = <GIC_SPI 703 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 708 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 714 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 68 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 96 IRQ_TYPE_EDGE_RISING>,
> + <GIC_SPI 249 IRQ_TYPE_EDGE_RISING>;
> + qcom,sw-drv-ids = <0 1 2 3 4 5>;
Pointless property :/
Run this binding via internal review first, because it does not match
expected upstream submission quality and YOU ARE expected to have it
internally reviewed first.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 02/13] dt-bindings: clock: qcom,sm8550-dispcc: Add display CESTA support on SM8750
2026-04-20 16:28 [PATCH 00/13] Add support to control clocks using CESTA Resource manager Jagadeesh Kona
2026-04-20 16:28 ` [PATCH 01/13] dt-bindings: soc: Introduce device bindings for CESTA Resource Manager Jagadeesh Kona
@ 2026-04-20 16:28 ` Jagadeesh Kona
2026-04-20 17:45 ` Dmitry Baryshkov
2026-04-22 7:41 ` Krzysztof Kozlowski
2026-04-20 16:28 ` [PATCH 03/13] dt-bindings: mfd: syscon: Add qcom,crmc-syscon compatible Jagadeesh Kona
` (9 subsequent siblings)
11 siblings, 2 replies; 24+ messages in thread
From: Jagadeesh Kona @ 2026-04-20 16:28 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones
Cc: Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree, linux-kernel,
linux-clk, Maulik Shah, Taniya Das, Jagadeesh Kona
On SM8750, a subset of DISPCC clocks is controlled by the display CESTA
(Client State Aggregator) hardware. These clocks can be scaled to the
desired frequency by sending votes to the display CRM(CESTA Resource
manager) instead of programming DISPCC registers directly.
Add bindings to allow the DISPCC node to reference the display CRM node
for sending votes to CESTA hardware and the CRMC syscon regmap node
which is used to read the frequency look up tables provided by CRM and
populate this data in RCG's frequency tables for CESTA controlled clocks.
Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
---
.../bindings/clock/qcom,sm8550-dispcc.yaml | 48 ++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8550-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8550-dispcc.yaml
index 591ce91b8d54dd6f78a66d029882bcd94b53beda..3e049b2160a1781c866bb30b29f0da5c9e156b61 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm8550-dispcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8550-dispcc.yaml
@@ -60,6 +60,18 @@ properties:
A phandle to an OPP node describing required MMCX performance point.
maxItems: 1
+ qcom,crm:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the display CRM (CESTA Resource Manager) node, used to communicate
+ with the display CESTA (Client State Aggregator) hardware.
+
+ qcom,crmc-regmap:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the syscon providing the CRMC (CRM clock) regmap used
+ to read frequency LUTs (lookup tables) populated by the CRM.
+
required:
- compatible
- clocks
@@ -100,4 +112,40 @@ examples:
power-domains = <&rpmhpd RPMHPD_MMCX>;
required-opps = <&rpmhpd_opp_low_svs>;
};
+
+ - |
+ // Display clock controller node that controls some clocks
+ // using display CESTA(Client state Aggregator) hardware
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ #include <dt-bindings/power/qcom,rpmhpd.h>
+
+ clock-controller@af00000 {
+ compatible = "qcom,sm8750-dispcc";
+ reg = <0x0af00000 0x20000>;
+ clocks = <&rpmhcc RPMH_CXO_CLK>,
+ <&rpmhcc RPMH_CXO_CLK_A>,
+ <&gcc GCC_DISP_AHB_CLK>,
+ <&sleep_clk>,
+ <&dsi0_phy 0>,
+ <&dsi0_phy 1>,
+ <&dsi1_phy 0>,
+ <&dsi1_phy 1>,
+ <&dp0_phy 0>,
+ <&dp0_phy 1>,
+ <&dp1_phy 0>,
+ <&dp1_phy 1>,
+ <&dp2_phy 0>,
+ <&dp2_phy 1>,
+ <&dp3_phy 0>,
+ <&dp3_phy 1>;
+ power-domains = <&rpmhpd RPMHPD_MMCX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+
+ qcom,crm = <&disp_crm>;
+ qcom,crmc-regmap = <&disp_crmc>;
+
+ #clock-cells = <1>;
+ #power-domain-cells = <1>;
+ #reset-cells = <1>;
+ };
...
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* Re: [PATCH 02/13] dt-bindings: clock: qcom,sm8550-dispcc: Add display CESTA support on SM8750
2026-04-20 16:28 ` [PATCH 02/13] dt-bindings: clock: qcom,sm8550-dispcc: Add display CESTA support on SM8750 Jagadeesh Kona
@ 2026-04-20 17:45 ` Dmitry Baryshkov
2026-04-22 7:41 ` Krzysztof Kozlowski
1 sibling, 0 replies; 24+ messages in thread
From: Dmitry Baryshkov @ 2026-04-20 17:45 UTC (permalink / raw)
To: Jagadeesh Kona
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones, Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree,
linux-kernel, linux-clk, Maulik Shah, Taniya Das
On Mon, Apr 20, 2026 at 09:58:55PM +0530, Jagadeesh Kona wrote:
> On SM8750, a subset of DISPCC clocks is controlled by the display CESTA
> (Client State Aggregator) hardware. These clocks can be scaled to the
> desired frequency by sending votes to the display CRM(CESTA Resource
> manager) instead of programming DISPCC registers directly.
>
> Add bindings to allow the DISPCC node to reference the display CRM node
> for sending votes to CESTA hardware and the CRMC syscon regmap node
> which is used to read the frequency look up tables provided by CRM and
> populate this data in RCG's frequency tables for CESTA controlled clocks.
>
> Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
> ---
> .../bindings/clock/qcom,sm8550-dispcc.yaml | 48 ++++++++++++++++++++++
> 1 file changed, 48 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8550-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8550-dispcc.yaml
> index 591ce91b8d54dd6f78a66d029882bcd94b53beda..3e049b2160a1781c866bb30b29f0da5c9e156b61 100644
> --- a/Documentation/devicetree/bindings/clock/qcom,sm8550-dispcc.yaml
> +++ b/Documentation/devicetree/bindings/clock/qcom,sm8550-dispcc.yaml
> @@ -60,6 +60,18 @@ properties:
> A phandle to an OPP node describing required MMCX performance point.
> maxItems: 1
>
> + qcom,crm:
> + $ref: /schemas/types.yaml#/definitions/phandle
> + description:
> + Phandle to the display CRM (CESTA Resource Manager) node, used to communicate
> + with the display CESTA (Client State Aggregator) hardware.
Is it going to be shared by several entities? If not, can be make a part
of the dispcc and get rid of the extra CC <-> CRM API?
> +
> + qcom,crmc-regmap:
> + $ref: /schemas/types.yaml#/definitions/phandle
> + description:
> + Phandle to the syscon providing the CRMC (CRM clock) regmap used
> + to read frequency LUTs (lookup tables) populated by the CRM.
Why is this coming as a syscon? Why isn't it just a register region of
the dispcc?
> +
> required:
> - compatible
> - clocks
> @@ -100,4 +112,40 @@ examples:
> power-domains = <&rpmhpd RPMHPD_MMCX>;
> required-opps = <&rpmhpd_opp_low_svs>;
> };
> +
> + - |
> + // Display clock controller node that controls some clocks
> + // using display CESTA(Client state Aggregator) hardware
> + #include <dt-bindings/clock/qcom,rpmh.h>
> + #include <dt-bindings/power/qcom,rpmhpd.h>
> +
> + clock-controller@af00000 {
> + compatible = "qcom,sm8750-dispcc";
> + reg = <0x0af00000 0x20000>;
> + clocks = <&rpmhcc RPMH_CXO_CLK>,
> + <&rpmhcc RPMH_CXO_CLK_A>,
> + <&gcc GCC_DISP_AHB_CLK>,
> + <&sleep_clk>,
> + <&dsi0_phy 0>,
> + <&dsi0_phy 1>,
> + <&dsi1_phy 0>,
> + <&dsi1_phy 1>,
> + <&dp0_phy 0>,
> + <&dp0_phy 1>,
> + <&dp1_phy 0>,
> + <&dp1_phy 1>,
> + <&dp2_phy 0>,
> + <&dp2_phy 1>,
> + <&dp3_phy 0>,
> + <&dp3_phy 1>;
> + power-domains = <&rpmhpd RPMHPD_MMCX>;
> + required-opps = <&rpmhpd_opp_low_svs>;
> +
> + qcom,crm = <&disp_crm>;
> + qcom,crmc-regmap = <&disp_crmc>;
> +
> + #clock-cells = <1>;
> + #power-domain-cells = <1>;
> + #reset-cells = <1>;
> + };
> ...
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH 02/13] dt-bindings: clock: qcom,sm8550-dispcc: Add display CESTA support on SM8750
2026-04-20 16:28 ` [PATCH 02/13] dt-bindings: clock: qcom,sm8550-dispcc: Add display CESTA support on SM8750 Jagadeesh Kona
2026-04-20 17:45 ` Dmitry Baryshkov
@ 2026-04-22 7:41 ` Krzysztof Kozlowski
1 sibling, 0 replies; 24+ messages in thread
From: Krzysztof Kozlowski @ 2026-04-22 7:41 UTC (permalink / raw)
To: Jagadeesh Kona
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones, Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree,
linux-kernel, linux-clk, Maulik Shah, Taniya Das
On Mon, Apr 20, 2026 at 09:58:55PM +0530, Jagadeesh Kona wrote:
> On SM8750, a subset of DISPCC clocks is controlled by the display CESTA
> (Client State Aggregator) hardware. These clocks can be scaled to the
> desired frequency by sending votes to the display CRM(CESTA Resource
> manager) instead of programming DISPCC registers directly.
This looks like completely new, vendor clock API, so no.
Resource voting or clock scaling is nothing new and you do not get a
vendor phandle to do it. That's like basic upstreaming 101: we do not
want another vendor re-implementation of common or typical solutions.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 03/13] dt-bindings: mfd: syscon: Add qcom,crmc-syscon compatible
2026-04-20 16:28 [PATCH 00/13] Add support to control clocks using CESTA Resource manager Jagadeesh Kona
2026-04-20 16:28 ` [PATCH 01/13] dt-bindings: soc: Introduce device bindings for CESTA Resource Manager Jagadeesh Kona
2026-04-20 16:28 ` [PATCH 02/13] dt-bindings: clock: qcom,sm8550-dispcc: Add display CESTA support on SM8750 Jagadeesh Kona
@ 2026-04-20 16:28 ` Jagadeesh Kona
2026-04-22 7:39 ` Krzysztof Kozlowski
2026-04-20 16:28 ` [PATCH 04/13] soc: qcom: Introduce CESTA resource manager driver Jagadeesh Kona
` (8 subsequent siblings)
11 siblings, 1 reply; 24+ messages in thread
From: Jagadeesh Kona @ 2026-04-20 16:28 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones
Cc: Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree, linux-kernel,
linux-clk, Maulik Shah, Taniya Das, Jagadeesh Kona
Document the qcom,crmc-syscon compatible for the CRMC
(CESTA Resource Manager Clock) syscon device. This syscon
provides access to the frequency lookup tables provided by
CRM (CESTA Resource Manager) for clocks controlled by CESTA
hardware, so the SW frequency tables of these clocks can be
populated from this data.
Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
---
Documentation/devicetree/bindings/mfd/syscon.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index e228670880631429836b542ea5d40100b73d69e1..231e30144a5f3704eacf3387187cebde39c7148d 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -107,6 +107,7 @@ select:
- nxp,s32g3-gpr
- qcom,apq8064-mmss-sfpb
- qcom,apq8064-sps-sic
+ - qcom,crmc-syscon
- rockchip,px30-qos
- rockchip,rk3036-qos
- rockchip,rk3066-qos
@@ -221,6 +222,7 @@ properties:
- nxp,s32g3-gpr
- qcom,apq8064-mmss-sfpb
- qcom,apq8064-sps-sic
+ - qcom,crmc-syscon
- rockchip,px30-qos
- rockchip,rk3036-qos
- rockchip,rk3066-qos
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* Re: [PATCH 03/13] dt-bindings: mfd: syscon: Add qcom,crmc-syscon compatible
2026-04-20 16:28 ` [PATCH 03/13] dt-bindings: mfd: syscon: Add qcom,crmc-syscon compatible Jagadeesh Kona
@ 2026-04-22 7:39 ` Krzysztof Kozlowski
0 siblings, 0 replies; 24+ messages in thread
From: Krzysztof Kozlowski @ 2026-04-22 7:39 UTC (permalink / raw)
To: Jagadeesh Kona
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones, Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree,
linux-kernel, linux-clk, Maulik Shah, Taniya Das
On Mon, Apr 20, 2026 at 09:58:56PM +0530, Jagadeesh Kona wrote:
> Document the qcom,crmc-syscon compatible for the CRMC
> (CESTA Resource Manager Clock) syscon device. This syscon
Whatever CESTA is, CESTA and "CESTA CRM" are not syscons. Drop the
binding.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 04/13] soc: qcom: Introduce CESTA resource manager driver
2026-04-20 16:28 [PATCH 00/13] Add support to control clocks using CESTA Resource manager Jagadeesh Kona
` (2 preceding siblings ...)
2026-04-20 16:28 ` [PATCH 03/13] dt-bindings: mfd: syscon: Add qcom,crmc-syscon compatible Jagadeesh Kona
@ 2026-04-20 16:28 ` Jagadeesh Kona
2026-04-22 7:50 ` Krzysztof Kozlowski
2026-04-20 16:28 ` [PATCH 05/13] clk: qcom: common: Add helpers to control clocks using CRM Jagadeesh Kona
` (7 subsequent siblings)
11 siblings, 1 reply; 24+ messages in thread
From: Jagadeesh Kona @ 2026-04-20 16:28 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones
Cc: Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree, linux-kernel,
linux-clk, Maulik Shah, Taniya Das, Jagadeesh Kona
From: Maulik Shah <maulik.shah@oss.qualcomm.com>
Add driver for QCOM SoC that have hardware based resource management.
The hardware IP known as CESTA (Client State Aggregation) have different
Resource Manager (CESTA Resource Manager) or CRM.
CRM can be of 4 different types,
- CRMC is CRM for clocks local to subsystem
- CRMB is CRM for bandwidth votes local to subsystem
- CRMB_PT is pass through CRM for bandwidth votes global to subsystem
- CRMV is CRM for voltage rail / LDO requirements global to subsystem
A set of SW DRVs (Direct Resource Voters) can vote to all/subset of
CRMC/CRMB/CRMB_PT which then takes care of the respective resource voting.
There is no direct voter on CRMV, rather the CRMC votes picks up the
respective voltage from LUTs and scales the voltage accordingly required
for clocks or bandwidth votes.
Some important aspects of the CRM communication -
- Resource votes can be placed in the form of performance operating
levels or bandwidth votes for local/global NoCs
- SW DRVs vote can be of the Active / Sleep / Wake type
- All the resource votes are in the form of CESTA command
(resource id, value) pair.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
---
drivers/soc/qcom/Kconfig | 10 +
drivers/soc/qcom/Makefile | 2 +
drivers/soc/qcom/crm.c | 996 +++++++++++++++++++++++++++++++++++++++++++
drivers/soc/qcom/trace-crm.h | 111 +++++
include/soc/qcom/crm.h | 72 ++++
5 files changed, 1191 insertions(+)
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 2caadbbcf8307ff94f5afbdd1481e5e5e291749f..50f6c3cbf12f87ca2bab183e7996dba7312b9f58 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -26,6 +26,16 @@ config QCOM_COMMAND_DB
resource on a RPM-hardened platform must use this database to get
SoC specific identifier and information for the shared resources.
+config QCOM_CRM
+ tristate "Qualcomm Technologies, Inc. (QTI) CESTA Resource Manager (CRM) driver"
+ depends on QCOM_RPMH && (ARCH_QCOM || COMPILE_TEST)
+ help
+ Support for communication with the hardened-CRM blocks in
+ Qualcomm Technologies, Inc. (QTI) SoCs. CRM provides interface
+ to vote desired power state of resources local or global to a subsystem.
+ A set of hardware components aggregate requests for these resources and
+ help apply the aggregated power state on the resource.
+
config QCOM_GENI_SE
tristate "QCOM GENI Serial Engine Driver"
depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index b7f1d2a5736748b8772c090fd24462fa91f321c6..7f465e86c1b8a4c2657870783a22acc4315a7407 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,9 +1,11 @@
# SPDX-License-Identifier: GPL-2.0
+CFLAGS_crm.o := -I$(src)
CFLAGS_rpmh-rsc.o := -I$(src)
CFLAGS_qcom_aoss.o := -I$(src)
obj-$(CONFIG_QCOM_AOSS_QMP) += qcom_aoss.o
obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o
obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+obj-$(CONFIG_QCOM_CRM) += crm.o
obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
diff --git a/drivers/soc/qcom/crm.c b/drivers/soc/qcom/crm.c
new file mode 100644
index 0000000000000000000000000000000000000000..9fc4460a65f7f0b4cc262da48f49b769db434082
--- /dev/null
+++ b/drivers/soc/qcom/crm.c
@@ -0,0 +1,996 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+
+#include <soc/qcom/crm.h>
+
+#define CREATE_TRACE_POINTS
+#include "trace-crm.h"
+
+#undef field_get
+#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
+
+#define MAX_NAME_LENGTH 20
+
+/* Applicable for SW DRVs BW Registers */
+#define PERF_OL_VALUE_BITS 0x7
+
+/* Applicable for SW DRVs BW Registers */
+#define BW_VOTE_VALID BIT(29)
+/* Applicable only for SW DRVs BW PT Registers */
+#define BW_PT_VOTE_VALID BIT(29)
+#define BW_PT_VOTE_TRIGGER BIT(0)
+/* Applicable only for SW DRVs BW Registers */
+#define BW_VOTE_RESP_REQ BIT(31)
+
+/* Set 1 to Enable IRQ for each VCD */
+#define IRQ_ENABLE_BIT BIT(0)
+#define IRQ_CLEAR_BIT BIT(0)
+
+/* SW DRV has ACTIVE, SLEEP and WAKE PWR STATES */
+
+#define MAX_SW_DRV_PWR_STATES 3
+/* Time out for ACTIVE Only PWR STATE completion IRQ */
+#define CRM_TIMEOUT_MS msecs_to_jiffies(10000)
+
+/*
+ * Here's a high level overview of CESTA - Client State Aggregation
+ *
+ * - CESTA resource manager (CRM) is used for client side resource management.
+ * These local resources can be clocks or NoCs. A vote can be placed by DRVs
+ * (Direct Resource Voters) which can be either SW DRV or HW DRV.
+ *
+ * - Current driver supports placing votes via SW DRVs.
+ *
+ * - A resource vote can be placed by voting to VCD (Virtual Clock Domain) or
+ * Node (ND).
+ * Vote can be in the form of
+ * (1) performance operating level votes - Local clocks scaling
+ * (2) bandwidth votes - Local NoCs scaling (Camera / Display NoC)
+ * (3) bandwidth pass through votes - Global resource scaling (DDR)
+ * Not all CRM can vote via all three forms
+ *
+ * - The base crm address is the DRV base of a register space that is used to place votes.
+ * Each VCD/ND/PT_ND has IRQ Status/Clear/Enable registers.
+ *
+ * - The config crm address is used to find overall configuration of the hardware including
+ * version, num_perf_ol_vcds, num_nds and num_nds_pt and no. of SW DRVs.
+ *
+ * Here's a picture:
+ *
+ * +--------------------------------------------------------+
+ * | CRM |
+ * | |
+ * | +----------------------------------------------------+ |
+ * | | SW DRV0 | |
+ * | | | |
+ * | | +--------------------------------------------- --+ | |
+ * | | | PERF OL VCDs | | |
+ * | | | +--------------------------------------------+ | | |
+ * | | | |VCD 0 |VCD 1 |....num_perf_ol_vcds| | | |
+ * | | | |-----------|--------------------------------| | | |
+ * | | | |IRQ STATUS |IRQ STATUS |... IRQ_STATUS | | | |
+ * | | | |IRQ CLEAR |IRQ CLEAR |... IRQ CLEAR | | | |
+ * | | | |IRQ ENABLE |IRQ ENABLE |... IRQ ENABLE | | | |
+ * | | | +--------------------------------------------+ | | |
+ * | | | | | |
+ * | | +------------------------------------------------+ | |
+ * | | | BW VOTE Nodes | | |
+ * | | | +--------------------------------------------+ | | |
+ * | | | |Node 0 |Node 1 |....num_nds | | | |
+ * | | | |-----------|--------------------------------| | | |
+ * | | | |IRQ STATUS |IRQ STATUS |... IRQ_STATUS | | | |
+ * | | | |IRQ CLEAR |IRQ CLEAR |... IRQ CLEAR | | | |
+ * | | | |IRQ ENABLE |IRQ ENABLE |... IRQ ENABLE | | | |
+ * | | | +--------------------------------------------+ | | |
+ * | | | | | |
+ * | | +------------------------------------------------+ | |
+ * | | | BW PT VOTE Nodes | | |
+ * | | | +--------------------------------------------+ | | |
+ * | | | |PT Node 0 |PT Node 1 |....num_nds_pt | | | |
+ * | | | |-----------|--------------------------------| | | |
+ * | | | |IRQ STATUS | | | |
+ * | | | |IRQ CLEAR | | | |
+ * | | | |IRQ ENABLE | | | |
+ * | | | +--------------------------------------------+ | | |
+ * | | | | | | |
+ * | | +------------------------------------------------+ | |
+ * | | ...... | |
+ * | +----------------------------------------------------+ |
+ * | | | |
+ * | +----------------------------------------------------+ |
+ * | | SW DRV1 | |
+ * | | (same as DRV0) | |
+ * | +----------------------------------------------------+ |
+ * | ...... |
+ * | +----------------------------------------------------+ |
+ * | |Configuration | |
+ * | | +------------------------------------------------+ | |
+ * | | | |VERSION | CFG 1 |CFG 2 | | | |
+ * | | | |---------|------------------|---------------| | | |
+ * | | | |Major | num_perf_ol_vcds |num_nds | | | |
+ * | | | |Minor | num_nds_pt | | | | |
+ * | | | | | num_sw_drvs | | | | |
+ * | | | +--------------------------------------------+ | | |
+ * | | +------------------------------------------------+ | |
+ * | +----------------------------------------------------+ |
+ * +--------------------------------------------------------+
+ *
+ */
+
+ /**
+ * enum crm_cfg - Configuration registers space description for CRM
+ *
+ * This enumeration is used for three registers (CRM_VERSION, CRM_CFG_PARAM_1
+ * and CRM_CFG_PARAM_2) which are read only along with their bit meanings.
+ * The CRM_ENABLE indicates if the CRM is setup and enabled by firmware to be
+ * used. These are used during probe to setup DRVs.
+ *
+ * @CRM_VERSION: Overall CRM version identifier.
+ * @MAJOR_VERSION: Major version number of the CRM module.
+ * @MINOR_VERSION: Minor version number of the CRM module.
+ * @CRM_CFG_PARAM_1: Configuration parameter 1.
+ * @NUM_OF_NODES_PT: Number of Pass through (PT) nodes in the power topology.
+ * @NUM_VCD_VOTED_BY_BW: Number of VCD (voltage/current domains) voted by bandwidth.
+ * @NUM_SW_DRVS: Number of software drivers interacting with CRM.
+ * @NUM_OF_RAILS: Number of power rails managed by CRM.
+ * @NUM_VCD_VOTED_BY_PERF_OL: Number of VCDs voted by performance operating levels.
+ * @CRM_CFG_PARAM_2: Configuration parameter 2.
+ * @NUM_OF_NODES: Total number of nodes managed by CRM.
+ * @CRM_ENABLE: Flag to enable or disable CRM functionality.
+ * @CFG_REG_MAX: Maximum number of configuration registers.
+ * Used as a boundary marker for array sizing.
+ */
+enum crm_cfg {
+ CRM_VERSION,
+ MAJOR_VERSION,
+ MINOR_VERSION,
+ CRM_CFG_PARAM_1,
+ NUM_OF_NODES_PT,
+ NUM_VCD_VOTED_BY_BW,
+ NUM_SW_DRVS,
+ NUM_OF_RAILS,
+ NUM_VCD_VOTED_BY_PERF_OL,
+ CRM_CFG_PARAM_2,
+ NUM_OF_NODES,
+ CRM_ENABLE,
+ CFG_REG_MAX,
+};
+
+/**
+ * enum crm_vcd_type - Types of VCD (Voltage/Clock Domain) requests
+ *
+ * This enumeration defines the various types of VCD (Voltage/Clock Domain)
+ * requests that can be made by the CRM (Clock and Resource Manager) DRVs.
+ * These types are used to categorize and handle different performance and
+ * bandwidth-related requests.
+ *
+ * @PERF_OL_VCD: Votes are placed interms of Performance operating levels.
+ * @BW_VOTE_VCD: Votes are placed interms of Bandwidth for local resources.
+ * @BW_PT_VOTE_VCD: Votes are placed interms of Bandwidth for global resources.
+ * @MAX_VCD_TYPE: Maximum number of VCD types. Not a valid type itself,
+ * but used for bounds checking and array sizing.
+ */
+enum crm_vcd_type {
+ PERF_OL_VCD,
+ BW_VOTE_VCD,
+ BW_PT_VOTE_VCD,
+ MAX_VCD_TYPE,
+};
+
+/**
+ * enum crm_client - CRM (Clock and Resource Manager) client register space
+ *
+ * This enumeration defines the various registers used by CRM clients.
+ * They are used for managing driver base addresses, updating power state,
+ * interrupt handling and other CRM-related operations.
+ *
+ * @DRV_BASE: Base address register for the driver.
+ * @DRV_DISTANCE: Offset from the base to DRV registers.
+ * @DRV_RESOURCE_DISTANCE: Distance between each VCD or ND resources.
+ *
+ * @PWR_ST0: Power state register 0 for the driver.
+ * @PWR_ST1: Power state register 1 for the driver.
+ * @PWR_ST2: Power state register 2 for the driver.
+ * @PWR_ST3: Power state register 3 for the driver.
+ * @PWR_ST4: Power state register 4 for the driver.
+ *
+ * @IRQ_STATUS: Interrupt status register for a VCD or ND.
+ * @IRQ_CLEAR: Interrupt clear register for a VCD or ND.
+ * @IRQ_ENABLE: Interrupt enable register for a VCD or ND.
+ *
+ * @CRMB_PT_TRIGGER: Trigger register for CRM bandwidth/performance point.
+ *
+ * @CRM_CLIENT_REG_MAX: Maximum number of CRM client register types. Used for
+ * bounds checking and array sizing.
+ */
+
+enum crm_client {
+ DRV_BASE,
+ DRV_DISTANCE,
+ DRV_RESOURCE_DISTANCE,
+ ACTIVE_VOTE,
+ SLEEP_VOTE,
+ WAKE_VOTE,
+ IRQ_STATUS,
+ IRQ_CLEAR,
+ IRQ_ENABLE,
+ CRMB_PT_TRIGGER,
+ CRM_CLIENT_REG_MAX,
+};
+
+/**
+ * enum crm_capability - CRM capability types
+ * @PERF_OL_VOTING_CAPABLE: Indicates support for performance operating level (OL) voting
+ * @BW_VOTING_CAPABLE: Indicates support for bandwidth (BW) voting
+ * @BW_PT_VOTING_CAPABLE: Indicates support for bandwidth power throttle (PT) voting
+ *
+ * This enumeration defines the various capabilities that a CRM (Clock and Resource Manager)
+ * instance may support. These capabilities determine the types of resource management
+ * operations the CRM can perform.
+ */
+enum crm_capability {
+ PERF_OL_VOTING_CAPABLE,
+ BW_VOTING_CAPABLE,
+ BW_PT_VOTING_CAPABLE,
+};
+
+/**
+ * struct crm_desc: CRM register and capability description
+ *
+ * @crm_capability: Capability if H/W can vote on PERF_OL/BW_VOTE/BW_PT_VOTE via
+ * crm_write_perf_ol(), crm_write_bw_vote() and crm_write_bw_pt_vote()
+ * APIs.
+ * @cfg_regs: Configuration registers, memory mapped.
+ * @sw_drv_perf_ol_vcd_regs: PERF_OL voting registers
+ * @sw_drv_bw_vote_vcd_regs: BW_VOTE voting registers
+ * @sw_drv_bw_pt_vote_vcd_regs: BW_PT_VOTE voting registers
+ */
+struct crm_desc {
+ u32 crm_capability;
+ u32 *cfg_regs;
+ u32 sw_drv_perf_ol_vcd_regs[CRM_CLIENT_REG_MAX];
+ u32 sw_drv_bw_vote_vcd_regs[CRM_CLIENT_REG_MAX];
+ u32 sw_drv_bw_pt_vote_vcd_regs[CRM_CLIENT_REG_MAX];
+};
+
+/**
+ * struct crm_sw_votes: SW DRV's ACTIVE_VOTEs in progress.
+ * One per VCD.
+ *
+ * @cmd: The ACTIVE_VOTE being sent to CRM.
+ * @compl: Wait for completion if the cmd->wait is set.
+ * Applicable only for ACTIVE_VOTEs.
+ * @in_progress: Indicates if the cmd is in flight.
+ * @wait: Wait queue used to wait for @in_progress to be false.
+ * This is needed because HW do not keep a record of new
+ * requests issued until current one is completed.
+ */
+struct crm_sw_votes {
+ struct crm_cmd cmd;
+ struct completion compl;
+ bool in_progress;
+ wait_queue_head_t wait;
+};
+
+/**
+ * struct crm_vcd: The Virtual Clock Domain's (VCDs) of the CRM.
+ * One instance per VCD type (PERF_OL/ BW_VOTE/ BW_PT_VOTE).
+ *
+ * @num_pwr_states: Number of pwr state that DRV VCD can vote for
+ * @num_resources: Number of VCD resources (for PERF_OL votes) OR
+ * Number of Node resoureces (for BW votes)
+ * @offsets: Register offsets for DRV controller
+ * @sw_votes: Cache of SW DRV's ACTIVE_VOTEs
+ */
+struct crm_vcd {
+ u32 num_pwr_states;
+ u32 num_resources;
+ u32 *offsets;
+ struct crm_sw_votes *sw_votes;
+};
+
+/**
+ * struct crm_drv: The Direct Resource Voter (DRV) of the
+ * CESTA Resource manager (CRM).
+ *
+ * @name: Controller name
+ * @base: Base address of the CRM device
+ * @drv_id: DRV (Direct Resource Voter) number
+ * @vcd: VCDs in this DRV.
+ * @lock: Used to synchronize SW DRV's vote placement. Must
+ * be acquired before modifying ACTIVE/SLEEP/WAKE votes
+ * @irq: Completion IRQ, Received for ACTIVE votes which gets
+ * instant applied.
+ * @initialized: Whether DRV is initialized
+ */
+struct crm_drv {
+ char name[MAX_NAME_LENGTH];
+ void __iomem *base;
+ u32 drv_id;
+ struct crm_vcd vcd[MAX_VCD_TYPE];
+ spinlock_t lock;
+ int irq;
+ bool initialized;
+};
+
+/**
+ * struct crm_drv_top: Our representation of the top CRM device.
+ *
+ * @name: CRM device name
+ * @crm_enabled: Indicates if CRM is enabled
+ * @cfg: Configuration address of the CRM device
+ * Includes version and VCDs information
+ * @base: Base address of the CRM device
+ * @sw_drvs: Controller for each SW DRV
+ * @num_sw_drvs: Number of SW DRV controllers in the CRM device
+ * @max_sw_drv: Max id of SW DRV controller in use
+ * @list: CRM device added in crm_dev_list.
+ * @desc: CRM description
+ * @dev: CRM dev
+ * @pdev: CRM platform device
+ */
+struct crm_drv_top {
+ char name[MAX_NAME_LENGTH];
+ bool crm_enabled;
+ void __iomem *cfg;
+ void __iomem *base;
+ struct crm_drv *sw_drvs;
+ int num_sw_drvs;
+ int max_sw_drv;
+ struct list_head list;
+ const struct crm_desc *desc;
+ struct device *dev;
+ struct platform_device *pdev;
+};
+
+static inline void __iomem *crm_get_offset(const struct crm_drv *drv, u32 reg, u32 ch,
+ u32 vcd_type, u32 resource_idx)
+{
+ const struct crm_vcd *vcd = &drv->vcd[vcd_type];
+ u32 offset;
+
+ offset = vcd->offsets[DRV_BASE] + drv->drv_id * vcd->offsets[DRV_DISTANCE];
+ offset += vcd->offsets[reg];
+ offset += resource_idx * vcd->offsets[DRV_RESOURCE_DISTANCE];
+
+ return drv->base + offset;
+}
+
+static struct crm_drv *get_crm_drv(const struct device *dev, u32 drv_id, u32 capability)
+{
+ struct crm_drv_top *crm = NULL;
+ int i;
+
+ if (!dev)
+ goto exit;
+
+ crm = dev_get_drvdata(dev);
+ if (IS_ERR_OR_NULL(crm) || !crm->crm_enabled)
+ goto exit;
+
+ if (!(crm->desc->crm_capability & capability))
+ goto exit;
+
+ for (i = 0; i < crm->num_sw_drvs; i++) {
+ if (drv_id == crm->sw_drvs[i].drv_id)
+ return &crm->sw_drvs[i];
+ }
+
+exit:
+ return ERR_PTR(-ENODEV);
+}
+
+static void crm_vote_completion(struct crm_sw_votes *votes)
+{
+ struct completion *compl = &votes->compl;
+
+ votes->in_progress = false;
+ complete(compl);
+}
+
+/**
+ * crm_vote_complete_irq() - Vote completion interrupt handler for SW DRVs.
+ * @irq: The IRQ number.
+ * @p: Pointer to "struct crm_drv".
+ *
+ * Called for ACTIVE_VOTE transfers (those are the only ones we enable the
+ * IRQ for) when a transfer is done.
+ *
+ * Return: IRQ_HANDLED
+ */
+static irqreturn_t crm_vote_complete_irq(int irq, void *p)
+{
+ struct crm_drv_top *crm = p;
+ struct crm_drv *drv;
+ struct crm_vcd *vcd;
+ struct crm_sw_votes *votes;
+ unsigned long irq_status;
+ int i, j, k, num_irq;
+ void __iomem *addr;
+
+ for (i = 0; i < crm->num_sw_drvs; i++) {
+ drv = &crm->sw_drvs[i];
+ if (!drv->initialized && drv->irq != irq)
+ continue;
+
+ spin_lock(&drv->lock);
+ for (j = 0; j < MAX_VCD_TYPE; j++) {
+ if (!(crm->desc->crm_capability & BIT(j)))
+ continue;
+ vcd = &drv->vcd[j];
+
+ num_irq = j == BW_PT_VOTE_VCD ? 1 : vcd->num_resources;
+
+ for (k = 0; k < num_irq; k++) {
+ addr = crm_get_offset(drv, IRQ_STATUS, 0, j, k);
+ irq_status = readl_relaxed(addr);
+ if (!irq_status)
+ continue;
+
+ addr = crm_get_offset(drv, IRQ_CLEAR, 0, j, k);
+ writel_relaxed(IRQ_CLEAR_BIT, addr);
+ trace_crm_irq(drv->name, j, k, irq_status);
+
+ votes = &vcd->sw_votes[k];
+ if (WARN_ON_ONCE(!votes->in_progress))
+ continue;
+
+ if (votes->cmd.wait)
+ crm_vote_completion(votes);
+ }
+ }
+ spin_unlock(&drv->lock);
+ }
+
+ return IRQ_HANDLED;
+}
+
+
+/**
+ * crm_send_cmd - Send a command to the CRM hardware
+ * @drv: Pointer to the CRM driver structure
+ * @vcd_type: Type of VCD (PERF_OL_VCD, BW_VOTE_VCD or BW_PT_VOTE_VCD)
+ * @cmd: Pointer to the CRM structure containing command parameters
+ * @pt_trigger: Boolean flag indicating whether this is a pass through command
+ *
+ * This function sends a command to the CRM hardware for the specified VCD type.
+ * It assumes that the command has already been validated
+ * (e.g., using crm_is_invalid_cmd()).
+ *
+ * May sleep.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+static int crm_send_cmd(struct crm_drv *drv, u32 vcd_type, const struct crm_cmd *cmd,
+ bool pt_trigger)
+{
+ struct crm_vcd *vcd = &drv->vcd[vcd_type];
+ struct completion *compl = NULL;
+ u32 time_left = CRM_TIMEOUT_MS;
+ u32 data = cmd->data, irq_idx;
+ void __iomem *addr;
+
+ spin_lock_irq(&drv->lock);
+
+ /* Note: Set BIT(31) for RESP_REQ */
+ if (vcd_type == BW_VOTE_VCD && cmd->wait)
+ data |= BW_VOTE_RESP_REQ;
+
+ irq_idx = vcd_type == BW_PT_VOTE_VCD ? 0 : cmd->resource_idx;
+
+ switch (cmd->pwr_state) {
+ case CRM_ACTIVE_STATE:
+ /* Wait forever for a previous request to complete */
+ wait_event_lock_irq(vcd->sw_votes[irq_idx].wait,
+ !vcd->sw_votes[irq_idx].in_progress,
+ drv->lock);
+
+ compl = &vcd->sw_votes[irq_idx].compl;
+ init_completion(compl);
+ memcpy(&vcd->sw_votes[irq_idx], cmd, sizeof(struct crm_cmd));
+ vcd->sw_votes[irq_idx].in_progress = true;
+ addr = crm_get_offset(drv, ACTIVE_VOTE, 0, vcd_type, cmd->resource_idx);
+ writel_relaxed(data, addr);
+ break;
+ case CRM_SLEEP_STATE:
+ addr = crm_get_offset(drv, SLEEP_VOTE, 0, vcd_type, cmd->resource_idx);
+ writel_relaxed(data, addr);
+ break;
+ case CRM_WAKE_STATE:
+ addr = crm_get_offset(drv, WAKE_VOTE, 0, vcd_type, cmd->resource_idx);
+ writel_relaxed(data, addr);
+ break;
+ }
+
+ /* Set COMMIT to start aggregating votes */
+ if (pt_trigger) {
+ addr = crm_get_offset(drv, CRMB_PT_TRIGGER, 0, vcd_type, 0);
+ writel_relaxed(BW_PT_VOTE_TRIGGER, addr);
+
+ udelay(1);
+
+ addr = crm_get_offset(drv, CRMB_PT_TRIGGER, 0, vcd_type, 0);
+ writel_relaxed(0, addr);
+ }
+
+ spin_unlock_irq(&drv->lock);
+ trace_crm_write_vcd_votes(drv->name, vcd_type, cmd->resource_idx, cmd->pwr_state, data);
+
+ if (compl && cmd->wait) {
+ time_left = wait_for_completion_timeout(compl, CRM_TIMEOUT_MS);
+ WARN_ON(!time_left);
+ /* Unblock new requests for same VCD */
+ wake_up(&vcd->sw_votes[irq_idx].wait);
+ }
+
+ return (time_left > 0) ? 0 : -ETIMEDOUT;
+}
+
+/**
+ * crm_is_invalid_cmd - Validate a CRM command structure
+ * @drv: Pointer to the CRM driver structure
+ * @vcd_type: Type of VCD (Voltage/Clock Domain)
+ * @cmd: Pointer to the CRM command structure
+ *
+ * This function checks whether the given CRM command is valid for the
+ * specified VCD type. It performs the following validations:
+ * - Ensures that the driver and command pointers are not NULL or erroneous.
+ * - Checks that the power state index is within the valid range.
+ * - Checks that the resource index is within the valid range.
+ * - For BW_VOTE_VCD, ensures the BW_VOTE_VALID bit is set in the data field.
+ * - For BW_PT_VOTE_VCD, ensures the BW_PT_VOTE_VALID bit is set in the data field.
+ * - For PERF_OL_VCD, ensures only valid bits are set in the data field.
+ *
+ * Return: true if the command is invalid, false otherwise.
+ */
+static bool crm_is_invalid_cmd(struct crm_drv *drv, u32 vcd_type, const struct crm_cmd *cmd)
+{
+ struct crm_vcd *vcd;
+
+ if (IS_ERR_OR_NULL(drv) || IS_ERR_OR_NULL(cmd))
+ return true;
+
+ vcd = &drv->vcd[vcd_type];
+
+ if (cmd->pwr_state >= vcd->num_pwr_states)
+ return true;
+ else if (cmd->resource_idx >= vcd->num_resources)
+ return true;
+ else if (vcd_type == BW_VOTE_VCD && !(cmd->data & BW_VOTE_VALID))
+ return true;
+ else if (vcd_type == BW_PT_VOTE_VCD && !(cmd->data & BW_PT_VOTE_VALID))
+ return true;
+ else if (vcd_type == PERF_OL_VCD && (cmd->data & ~PERF_OL_VALUE_BITS))
+ return true;
+
+ return false;
+}
+
+/**
+ * crm_write_perf_ol() - Write a perf ol vote for a resource
+ * @dev: The device making the request, dev->parent must be CRM device
+ * @drv_id: DRV ID for which the votes are sent
+ * @cmd: The CRM CMD
+ *
+ * Caches the votes for logging and immediately sends the votes for SW DRVs
+ * if the @cmd have .wait set and is for ACTIVE_VOTE then waits for completion
+ * IRQ before return. for SLEEP_VOTE and WAKE_VOTE no completion IRQ is sent
+ * and they are triggered within HW during idle/awake scenarios.
+ *
+ * Return:
+ * * 0 - Success
+ * * -Error - Error code
+ */
+int crm_write_perf_ol(const struct device *dev, u32 drv_id, const struct crm_cmd *cmd)
+{
+ struct crm_drv *drv = get_crm_drv(dev, drv_id, PERF_OL_VOTING_CAPABLE);
+ int ret;
+
+ ret = crm_is_invalid_cmd(drv, PERF_OL_VCD, cmd);
+ if (ret)
+ return -EINVAL;
+
+ return crm_send_cmd(drv, PERF_OL_VCD, cmd, false);
+}
+EXPORT_SYMBOL_GPL(crm_write_perf_ol);
+
+/**
+ * crm_write_bw_vote() - Write a bw vote for a resource
+ * @dev: The device making the request, dev->parent must be CRM device
+ * @drv_id: DRV ID for which the votes are sent
+ * @cmd: The CRM CMD
+ *
+ * Caches the votes for logging and immediately sends the votes for SW DRVs
+ * if the @cmd have .wait set and is for ACTIVE_VOTE then waits for completion
+ * IRQ before return. for SLEEP_VOTE and WAKE_VOTE no completion IRQ is sent
+ * and they are triggered within HW during idle/awake scenarios.
+ *
+ * Return:
+ * * 0 - Success
+ * * -Error - Error code
+ */
+int crm_write_bw_vote(const struct device *dev, u32 drv_id, const struct crm_cmd *cmd)
+{
+ struct crm_drv *drv = get_crm_drv(dev, drv_id, BW_VOTING_CAPABLE);
+ int ret;
+
+ ret = crm_is_invalid_cmd(drv, BW_VOTE_VCD, cmd);
+ if (ret)
+ return -EINVAL;
+
+ return crm_send_cmd(drv, BW_VOTE_VCD, cmd, false);
+}
+EXPORT_SYMBOL_GPL(crm_write_bw_vote);
+
+/**
+ * crm_write_bw_pt_vote() - Write a bw vote for a resource
+ * @dev: The device making the request, dev->parent must be CRM device
+ * @drv_id: DRV ID for which the votes are sent
+ * @cmd: The CRM CMD
+ *
+ * Caches the votes for logging and immediately sends the votes for SW DRVs
+ * if the @cmd have .wait set and is for ACTIVE_VOTE then waits for completion
+ * IRQ before return. For SLEEP_VOTE and WAKE_VOTE no completion IRQ is sent
+ * and they are triggered within HW during idle/awake scenarios.
+ *
+ * Return:
+ * * 0 - Success
+ * * -Error - Error code
+ */
+int crm_write_bw_pt_vote(const struct device *dev, u32 drv_id, const struct crm_cmd *cmd)
+{
+ struct crm_drv *drv = get_crm_drv(dev, drv_id, BW_PT_VOTING_CAPABLE);
+ int ret;
+
+ ret = crm_is_invalid_cmd(drv, BW_PT_VOTE_VCD, cmd);
+ if (ret)
+ return -EINVAL;
+
+ return crm_send_cmd(drv, BW_PT_VOTE_VCD, cmd, true);
+}
+EXPORT_SYMBOL_GPL(crm_write_bw_pt_vote);
+
+/**
+ * crm_get() - Get a crm handle from a device
+ * @dev: Client device pointer
+ *
+ * Return: Handle to crm device on success, ERR_PTR() on failure
+ */
+struct device *crm_get(const struct device *dev)
+{
+ struct platform_device *pdev;
+ struct crm_drv_top *crm;
+ struct device_node *np;
+
+ if (!dev || !dev->of_node)
+ return ERR_PTR(-EINVAL);
+
+ np = of_parse_phandle(dev->of_node, "qcom,crm", 0);
+ if (!np)
+ return ERR_PTR(-ENODEV);
+
+ pdev = of_find_device_by_node(np);
+ of_node_put(np);
+ if (!pdev)
+ return ERR_PTR(-EINVAL);
+
+ crm = platform_get_drvdata(pdev);
+ if (!crm) {
+ put_device(&pdev->dev);
+ return ERR_PTR(-ENODEV);
+ }
+
+ return crm->dev;
+}
+EXPORT_SYMBOL_GPL(crm_get);
+
+static int crm_probe_get_irqs(struct crm_drv_top *crm)
+{
+ struct crm_drv *drvs = crm->sw_drvs;
+ struct crm_vcd *vcd;
+ int i, j, k, irq, ret;
+ void __iomem *addr;
+
+ /* Only SW DRVs have associated vote completion IRQ */
+ for (i = 0; i < crm->num_sw_drvs; i++) {
+ if (!crm->sw_drvs[i].initialized)
+ continue;
+
+ irq = platform_get_irq(crm->pdev, drvs[i].drv_id);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_irq(crm->dev, irq, crm_vote_complete_irq,
+ IRQF_TRIGGER_RISING, drvs[i].name, crm);
+ if (ret)
+ return ret;
+
+ drvs[i].irq = irq;
+
+ /* Additionally allocate memory for sw_votes */
+ for (j = 0; j < MAX_VCD_TYPE; j++) {
+ if (!(crm->desc->crm_capability & BIT(j)))
+ continue;
+
+ vcd = &drvs[i].vcd[j];
+ vcd->sw_votes = devm_kcalloc(crm->dev, vcd->num_resources,
+ sizeof(struct crm_sw_votes),
+ GFP_KERNEL);
+ if (!vcd->sw_votes)
+ return -ENOMEM;
+
+ /* Enable IRQs for all VCDs */
+ for (k = 0; k < vcd->num_resources; k++) {
+ init_waitqueue_head(&vcd->sw_votes[k].wait);
+ addr = crm_get_offset(&drvs[i], IRQ_ENABLE, 0, j, k);
+ writel_relaxed(IRQ_ENABLE_BIT, addr);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int crm_probe_set_vcd_caches(struct crm_drv_top *crm, u32 crm_cfg, u32 crm_cfg_2)
+{
+ struct crm_vcd *vcd;
+ struct crm_drv *drv;
+ u32 num_perf_ol_vcds, num_nds, num_nds_pt;
+ int i, j;
+
+ num_perf_ol_vcds = field_get(crm->desc->cfg_regs[NUM_VCD_VOTED_BY_PERF_OL], crm_cfg);
+ num_nds = field_get(crm->desc->cfg_regs[NUM_OF_NODES], crm_cfg_2);
+ num_nds_pt = field_get(crm->desc->cfg_regs[NUM_OF_NODES_PT], crm_cfg);
+
+ for (i = 0; i < crm->num_sw_drvs; i++) {
+ drv = &crm->sw_drvs[i];
+
+ if (!drv->initialized)
+ continue;
+
+ for (j = 0; j < MAX_VCD_TYPE; j++) {
+ if (!(crm->desc->crm_capability & BIT(j)))
+ continue;
+ vcd = &drv->vcd[j];
+
+ if (j == PERF_OL_VCD) {
+ vcd->offsets = (u32 *)&crm->desc->sw_drv_perf_ol_vcd_regs;
+ vcd->num_resources = num_perf_ol_vcds;
+ } else if (j == BW_VOTE_VCD) {
+ vcd->offsets = (u32 *)&crm->desc->sw_drv_bw_vote_vcd_regs;
+ /* BW_VOTE_VCD can have multiple NDs with which BW can be voted */
+ vcd->num_resources = num_nds;
+ } else {
+ vcd->offsets = (u32 *)&crm->desc->sw_drv_bw_pt_vote_vcd_regs;
+ vcd->num_resources = num_nds_pt;
+ }
+ vcd->num_pwr_states = MAX_SW_DRV_PWR_STATES;
+ }
+ }
+
+ return 0;
+}
+
+static struct crm_drv *crm_probe_get_drvs(struct crm_drv_top *crm, int num_drvs,
+ const char *prop_name, const char *name)
+{
+ struct device_node *dn = crm->dev->of_node;
+ u32 *drv_ids;
+ int i, id;
+ int ret;
+ struct crm_drv *drvs;
+
+ if (!num_drvs)
+ return ERR_PTR(-EINVAL);
+
+ drvs = devm_kcalloc(crm->dev, num_drvs, sizeof(struct crm_drv), GFP_KERNEL);
+ if (!drvs)
+ return ERR_PTR(-ENOMEM);
+
+ drv_ids = kcalloc(num_drvs, sizeof(u32), GFP_KERNEL);
+ if (!drv_ids)
+ return ERR_PTR(-ENOMEM);
+
+ ret = of_property_read_variable_u32_array(dn, prop_name, drv_ids, 1, num_drvs);
+ if (ret < 0) {
+ kfree(drv_ids);
+ return ERR_PTR(ret);
+ }
+
+ for (i = 0; i < num_drvs; i++) {
+ id = drv_ids[i];
+
+ scnprintf(drvs[i].name, sizeof(drvs[i].name), "%s_%s_%d", crm->name, name, id);
+ spin_lock_init(&drvs[i].lock);
+ drvs[i].drv_id = id;
+ drvs[i].base = crm->base;
+ drvs[i].initialized = true;
+ }
+
+ kfree(drv_ids);
+ return drvs;
+}
+
+static int crm_probe_drvs(struct crm_drv_top *crm, struct device_node *dn)
+{
+ u32 crm_ver, major_ver, minor_ver;
+ u32 crm_cfg, crm_cfg_2;
+
+ crm_ver = readl_relaxed(crm->cfg + crm->desc->cfg_regs[CRM_VERSION]);
+ major_ver = field_get(crm->desc->cfg_regs[MAJOR_VERSION], crm_ver);
+ minor_ver = field_get(crm->desc->cfg_regs[MINOR_VERSION], crm_ver);
+ dev_info(crm->dev, "CRM %s version major=%u minor=%u\n", crm->name, major_ver, minor_ver);
+
+ crm_cfg = readl_relaxed(crm->cfg + crm->desc->cfg_regs[CRM_CFG_PARAM_1]);
+ crm->max_sw_drv = field_get(crm->desc->cfg_regs[NUM_SW_DRVS], crm_cfg);
+
+ crm->num_sw_drvs = of_property_count_u32_elems(dn, "qcom,sw-drv-ids");
+ if (crm->num_sw_drvs < 0)
+ return -EINVAL;
+
+ crm->sw_drvs = crm_probe_get_drvs(crm, crm->num_sw_drvs, "qcom,sw-drv-ids", "sw_drv");
+ if (IS_ERR(crm->sw_drvs))
+ return PTR_ERR(crm->sw_drvs);
+
+ if (crm->num_sw_drvs > crm->max_sw_drv || !crm->num_sw_drvs)
+ return -EINVAL;
+
+ crm_cfg_2 = readl_relaxed(crm->cfg + crm->desc->cfg_regs[CRM_CFG_PARAM_2]);
+
+ return crm_probe_set_vcd_caches(crm, crm_cfg, crm_cfg_2);
+}
+
+static int crm_probe(struct platform_device *pdev)
+{
+ struct device_node *dn = pdev->dev.of_node;
+ struct crm_drv_top *crm;
+ const char *name;
+ int ret;
+
+ crm = devm_kzalloc(&pdev->dev, sizeof(*crm), GFP_KERNEL);
+ if (!crm)
+ return -ENOMEM;
+
+ crm->desc = of_device_get_match_data(&pdev->dev);
+ if (!crm->desc)
+ return -EINVAL;
+
+ name = of_get_property(dn, "label", NULL);
+ if (!name)
+ name = dev_name(&pdev->dev);
+
+ crm->pdev = pdev;
+ crm->dev = &pdev->dev;
+ scnprintf(crm->name, sizeof(crm->name), "%s", name);
+
+ crm->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
+ if (IS_ERR(crm->base))
+ return -ENOMEM;
+
+ crm->cfg = devm_platform_get_and_ioremap_resource(pdev, 1, NULL);
+ if (IS_ERR(crm->cfg))
+ return -ENOMEM;
+
+ if (pdev->dev.pm_domain) {
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret)
+ return ret;
+ }
+
+ crm->crm_enabled = readl_relaxed(crm->cfg + crm->desc->cfg_regs[CRM_ENABLE]);
+ if (!crm->crm_enabled) {
+ dev_err(crm->dev, "%s not enabled, exiting\n", crm->name);
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ ret = crm_probe_drvs(crm, dn);
+ if (ret)
+ goto exit;
+
+ ret = crm_probe_get_irqs(crm);
+ if (ret)
+ goto exit;
+
+ dev_set_drvdata(&pdev->dev, crm);
+exit:
+ if (pdev->dev.pm_domain)
+ pm_runtime_put(&pdev->dev);
+
+ return ret;
+}
+
+static u32 crm_v2_cfg[] = {
+ [CRM_VERSION] = 0x0,
+ [MAJOR_VERSION] = GENMASK(23, 16),
+ [MINOR_VERSION] = GENMASK(15, 8),
+ [CRM_CFG_PARAM_1] = 0x4,
+ [NUM_OF_NODES_PT] = GENMASK(31, 27),
+ [NUM_VCD_VOTED_BY_BW] = GENMASK(26, 24),
+ [NUM_SW_DRVS] = GENMASK(23, 20),
+ [NUM_OF_RAILS] = GENMASK(15, 12),
+ [NUM_VCD_VOTED_BY_PERF_OL] = GENMASK(11, 8),
+ [CRM_CFG_PARAM_2] = 0x8,
+ [NUM_OF_NODES] = GENMASK(30, 26),
+ [CRM_ENABLE] = 0xc,
+};
+
+static const struct crm_desc disp_crm_desc_v2 = {
+ .crm_capability = PERF_OL_VOTING_CAPABLE | BW_VOTING_CAPABLE | BW_PT_VOTING_CAPABLE,
+ .cfg_regs = crm_v2_cfg,
+ .sw_drv_perf_ol_vcd_regs = {
+ [DRV_BASE] = 0xe0,
+ [DRV_DISTANCE] = 0x1000,
+ [DRV_RESOURCE_DISTANCE] = 0x20,
+ [ACTIVE_VOTE] = 0x0,
+ [SLEEP_VOTE] = 0x4,
+ [WAKE_VOTE] = 0x8,
+ [IRQ_STATUS] = 0x10,
+ [IRQ_CLEAR] = 0x14,
+ [IRQ_ENABLE] = 0x18,
+ },
+ .sw_drv_bw_vote_vcd_regs = {
+ [DRV_BASE] = 0xe0,
+ [DRV_DISTANCE] = 0x1000,
+ [DRV_RESOURCE_DISTANCE] = 0x10,
+ [ACTIVE_VOTE] = 0x20,
+ [SLEEP_VOTE] = 0x24,
+ [WAKE_VOTE] = 0x28,
+ [IRQ_STATUS] = 0x90,
+ [IRQ_CLEAR] = 0x94,
+ [IRQ_ENABLE] = 0x98,
+ },
+ .sw_drv_bw_pt_vote_vcd_regs = {
+ [DRV_BASE] = 0xe0,
+ [DRV_DISTANCE] = 0x1000,
+ [DRV_RESOURCE_DISTANCE] = 0x10,
+ [ACTIVE_VOTE] = 0x30,
+ [SLEEP_VOTE] = 0x34,
+ [WAKE_VOTE] = 0x38,
+ [IRQ_STATUS] = 0xa0,
+ [IRQ_CLEAR] = 0xa4,
+ [IRQ_ENABLE] = 0xa8,
+ [CRMB_PT_TRIGGER] = 0x100,
+ },
+};
+
+static const struct of_device_id crm_drv_match[] = {
+ { .compatible = "qcom,sm8750-disp-crm", .data = &disp_crm_desc_v2 },
+ { }
+};
+MODULE_DEVICE_TABLE(of, crm_drv_match);
+
+static struct platform_driver crm_driver = {
+ .probe = crm_probe,
+ .driver = {
+ .name = "crm",
+ .of_match_table = crm_drv_match,
+ .suppress_bind_attrs = true,
+ },
+};
+module_platform_driver(crm_driver);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. (QTI) CRM Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/soc/qcom/trace-crm.h b/drivers/soc/qcom/trace-crm.h
new file mode 100644
index 0000000000000000000000000000000000000000..838e4b51132a16ab6b1e73d3cccfd76859de2e95
--- /dev/null
+++ b/drivers/soc/qcom/trace-crm.h
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#if !defined(_TRACE_CRM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_CRM_H
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM crm
+
+#include <linux/tracepoint.h>
+#include <soc/qcom/crm.h>
+
+DECLARE_EVENT_CLASS(crm_vcd_votes,
+
+ TP_PROTO(const char *name, u32 vcd_type, u32 resource_idx, u32 pwr_state, u32 data),
+
+ TP_ARGS(name, vcd_type, resource_idx, pwr_state, data),
+
+ TP_STRUCT__entry(
+ __string(name, name)
+ __field(u32, vcd_type)
+ __field(u32, resource_idx)
+ __field(u32, pwr_state)
+ __field(u32, data)
+ ),
+
+ TP_fast_assign(
+ __assign_str(name);
+ __entry->vcd_type = vcd_type;
+ __entry->resource_idx = resource_idx;
+ __entry->pwr_state = pwr_state;
+ __entry->data = data;
+ ),
+
+ TP_printk("%s: vcd_type: %u resource_idx: %u pwr_state: %u data: %#x",
+ __get_str(name), __entry->vcd_type, __entry->resource_idx,
+ __entry->pwr_state, __entry->data)
+);
+
+DEFINE_EVENT(crm_vcd_votes, crm_cache_vcd_votes,
+
+ TP_PROTO(const char *name, u32 vcd_type, u32 resource_idx, u32 pwr_state, u32 data),
+
+ TP_ARGS(name, vcd_type, resource_idx, pwr_state, data)
+);
+
+DEFINE_EVENT(crm_vcd_votes, crm_write_vcd_votes,
+
+ TP_PROTO(const char *name, u32 vcd_type, u32 resource_idx, u32 pwr_state, u32 data),
+
+ TP_ARGS(name, vcd_type, resource_idx, pwr_state, data)
+);
+
+TRACE_EVENT(crm_irq,
+
+ TP_PROTO(const char *name, u32 vcd_type, u32 resource_idx, unsigned long irq_status),
+
+ TP_ARGS(name, vcd_type, resource_idx, irq_status),
+
+ TP_STRUCT__entry(
+ __string(name, name)
+ __field(u32, vcd_type)
+ __field(u32, resource_idx)
+ __field(unsigned long, irq_status)
+ ),
+
+ TP_fast_assign(
+ __assign_str(name);
+ __entry->vcd_type = vcd_type;
+ __entry->resource_idx = resource_idx;
+ __entry->irq_status = irq_status;
+ ),
+
+ TP_printk("%s: IRQ vcd_type: %u resource_idx: %u irq_status: %lu",
+ __get_str(name), __entry->vcd_type, __entry->resource_idx,
+ __entry->irq_status)
+);
+
+TRACE_EVENT(crm_switch_channel,
+
+ TP_PROTO(const char *name, int ch, int ret),
+
+ TP_ARGS(name, ch, ret),
+
+ TP_STRUCT__entry(
+ __string(name, name)
+ __field(int, ch)
+ __field(int, ret)
+ ),
+
+ TP_fast_assign(
+ __assign_str(name);
+ __entry->ch = ch;
+ __entry->ret = ret;
+ ),
+
+ TP_printk("%s: channel switched to: %d ret: %d",
+ __get_str(name), __entry->ch, __entry->ret)
+);
+
+#endif /* _TRACE_CRM_H */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace-crm
+
+#include <trace/define_trace.h>
diff --git a/include/soc/qcom/crm.h b/include/soc/qcom/crm.h
new file mode 100644
index 0000000000000000000000000000000000000000..5411336f4cf222fcddf9197ba2e13aa3d41d16ec
--- /dev/null
+++ b/include/soc/qcom/crm.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef __SOC_QCOM_CRM_H__
+#define __SOC_QCOM_CRM_H__
+
+#include <linux/platform_device.h>
+
+/**
+ * enum crm_sw_drv_state: Power states for the SW DRV request
+ *
+ * @CRM_ACTIVE_STATE: Active or AMC mode requests. Resource state
+ * is aggregated immediately.
+ * @CRM_SLEEP_STATE: State of the resource when the subsystem is
+ * powered down. There is no client using the
+ * resource actively.
+ * @CRM_WAKE_STATE: Resume resource state to the value previously
+ * requested before the subsystem was powered down.
+ */
+enum crm_sw_drv_state {
+ CRM_ACTIVE_STATE,
+ CRM_SLEEP_STATE,
+ CRM_WAKE_STATE,
+};
+
+/**
+ * struct crm_cmd: The message to be sent to CRM
+ *
+ * @pwr_state: The pwr_state for HW/SW DRV
+ * @resource_idx: The index of the VCD OR ND to apply data
+ * @data: The Clock Plan index for the VCDs voted by PERF_OL.
+ * BW vote for the VCDs voted by BW.
+ * @wait: Set by the client want if want to wait for the vote completion IRQ.
+ * Applicable for only SW DRV client.
+ * Don't care for HW DRV client.
+ */
+struct crm_cmd {
+ enum crm_sw_drv_state pwr_state;
+ u32 resource_idx;
+ u32 data;
+ bool wait;
+};
+
+#if IS_ENABLED(CONFIG_QCOM_CRM)
+int crm_write_perf_ol(const struct device *dev, u32 drv_id, const struct crm_cmd *cmd);
+int crm_write_bw_vote(const struct device *dev, u32 drv_id, const struct crm_cmd *cmd);
+int crm_write_bw_pt_vote(const struct device *dev, u32 drv_id, const struct crm_cmd *cmd);
+struct device *crm_get(const struct device *dev);
+#else
+
+static inline int crm_write_perf_ol(const struct device *dev,
+ u32 drv_id,
+ const struct crm_cmd *cmd)
+{ return -ENODEV; }
+
+static inline int crm_write_bw_vote(const struct device *dev,
+ u32 drv_id,
+ const struct crm_cmd *cmd)
+{ return -ENODEV; }
+
+static inline int crm_write_bw_pt_vote(const struct device *dev,
+ u32 drv_id,
+ const struct crm_cmd *cmd)
+{ return -ENODEV; }
+static inline struct device *crm_get(const struct device *dev)
+{ return NULL; }
+
+#endif /* CONFIG_QCOM_CRM */
+
+#endif /* __SOC_QCOM_CRM_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* Re: [PATCH 04/13] soc: qcom: Introduce CESTA resource manager driver
2026-04-20 16:28 ` [PATCH 04/13] soc: qcom: Introduce CESTA resource manager driver Jagadeesh Kona
@ 2026-04-22 7:50 ` Krzysztof Kozlowski
0 siblings, 0 replies; 24+ messages in thread
From: Krzysztof Kozlowski @ 2026-04-22 7:50 UTC (permalink / raw)
To: Jagadeesh Kona
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones, Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree,
linux-kernel, linux-clk, Maulik Shah, Taniya Das
On Mon, Apr 20, 2026 at 09:58:57PM +0530, Jagadeesh Kona wrote:
> From: Maulik Shah <maulik.shah@oss.qualcomm.com>
>
> Add driver for QCOM SoC that have hardware based resource management.
>
> The hardware IP known as CESTA (Client State Aggregation) have different
> Resource Manager (CESTA Resource Manager) or CRM.
>
> CRM can be of 4 different types,
> - CRMC is CRM for clocks local to subsystem
> - CRMB is CRM for bandwidth votes local to subsystem
> - CRMB_PT is pass through CRM for bandwidth votes global to subsystem
> - CRMV is CRM for voltage rail / LDO requirements global to subsystem
>
> A set of SW DRVs (Direct Resource Voters) can vote to all/subset of
> CRMC/CRMB/CRMB_PT which then takes care of the respective resource voting.
> There is no direct voter on CRMV, rather the CRMC votes picks up the
> respective voltage from LUTs and scales the voltage accordingly required
> for clocks or bandwidth votes.
>
> Some important aspects of the CRM communication -
> - Resource votes can be placed in the form of performance operating
> levels or bandwidth votes for local/global NoCs
> - SW DRVs vote can be of the Active / Sleep / Wake type
> - All the resource votes are in the form of CESTA command
> (resource id, value) pair.
>
> Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
> Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
> ---
> drivers/soc/qcom/Kconfig | 10 +
> drivers/soc/qcom/Makefile | 2 +
> drivers/soc/qcom/crm.c | 996 +++++++++++++++++++++++++++++++++++++++++++
> drivers/soc/qcom/trace-crm.h | 111 +++++
> include/soc/qcom/crm.h | 72 ++++
> 5 files changed, 1191 insertions(+)
>
> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
> index 2caadbbcf8307ff94f5afbdd1481e5e5e291749f..50f6c3cbf12f87ca2bab183e7996dba7312b9f58 100644
> --- a/drivers/soc/qcom/Kconfig
> +++ b/drivers/soc/qcom/Kconfig
> @@ -26,6 +26,16 @@ config QCOM_COMMAND_DB
> resource on a RPM-hardened platform must use this database to get
> SoC specific identifier and information for the shared resources.
>
> +config QCOM_CRM
> + tristate "Qualcomm Technologies, Inc. (QTI) CESTA Resource Manager (CRM) driver"
Just "Qualcomm CESTA Resource Manager (CRM) driver"
Eveyrthing is Qualcomm Technologies, Inc. (QTI) and you make it
completely unreadable for the menuconfig.
> + depends on QCOM_RPMH && (ARCH_QCOM || COMPILE_TEST)
What do you need from rpmh for compile test?
> + help
> + Support for communication with the hardened-CRM blocks in
> + Qualcomm Technologies, Inc. (QTI) SoCs. CRM provides interface
> + to vote desired power state of resources local or global to a subsystem.
> + A set of hardware components aggregate requests for these resources and
> + help apply the aggregated power state on the resource.
> +
> config QCOM_GENI_SE
> tristate "QCOM GENI Serial Engine Driver"
> depends on ARCH_QCOM || COMPILE_TEST
> diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> index b7f1d2a5736748b8772c090fd24462fa91f321c6..7f465e86c1b8a4c2657870783a22acc4315a7407 100644
> --- a/drivers/soc/qcom/Makefile
> +++ b/drivers/soc/qcom/Makefile
> @@ -1,9 +1,11 @@
> # SPDX-License-Identifier: GPL-2.0
> +CFLAGS_crm.o := -I$(src)
> CFLAGS_rpmh-rsc.o := -I$(src)
> CFLAGS_qcom_aoss.o := -I$(src)
> obj-$(CONFIG_QCOM_AOSS_QMP) += qcom_aoss.o
> obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o
> obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
> +obj-$(CONFIG_QCOM_CRM) += crm.o
> obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
> obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
> obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
> diff --git a/drivers/soc/qcom/crm.c b/drivers/soc/qcom/crm.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..9fc4460a65f7f0b4cc262da48f49b769db434082
> --- /dev/null
> +++ b/drivers/soc/qcom/crm.c
> @@ -0,0 +1,996 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/wait.h>
> +
> +#include <soc/qcom/crm.h>
> +
> +#define CREATE_TRACE_POINTS
> +#include "trace-crm.h"
> +
> +#undef field_get
> +#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
> +
> +#define MAX_NAME_LENGTH 20
> +
> +/* Applicable for SW DRVs BW Registers */
> +#define PERF_OL_VALUE_BITS 0x7
> +
> +/* Applicable for SW DRVs BW Registers */
> +#define BW_VOTE_VALID BIT(29)
> +/* Applicable only for SW DRVs BW PT Registers */
> +#define BW_PT_VOTE_VALID BIT(29)
> +#define BW_PT_VOTE_TRIGGER BIT(0)
> +/* Applicable only for SW DRVs BW Registers */
> +#define BW_VOTE_RESP_REQ BIT(31)
> +
> +/* Set 1 to Enable IRQ for each VCD */
> +#define IRQ_ENABLE_BIT BIT(0)
> +#define IRQ_CLEAR_BIT BIT(0)
> +
> +/* SW DRV has ACTIVE, SLEEP and WAKE PWR STATES */
> +
> +#define MAX_SW_DRV_PWR_STATES 3
> +/* Time out for ACTIVE Only PWR STATE completion IRQ */
> +#define CRM_TIMEOUT_MS msecs_to_jiffies(10000)
> +
> +/*
> + * Here's a high level overview of CESTA - Client State Aggregation
> + *
> + * - CESTA resource manager (CRM) is used for client side resource management.
> + * These local resources can be clocks or NoCs. A vote can be placed by DRVs
> + * (Direct Resource Voters) which can be either SW DRV or HW DRV.
> + *
> + * - Current driver supports placing votes via SW DRVs.
> + *
> + * - A resource vote can be placed by voting to VCD (Virtual Clock Domain) or
> + * Node (ND).
> + * Vote can be in the form of
> + * (1) performance operating level votes - Local clocks scaling
> + * (2) bandwidth votes - Local NoCs scaling (Camera / Display NoC)
> + * (3) bandwidth pass through votes - Global resource scaling (DDR)
> + * Not all CRM can vote via all three forms
> + *
> + * - The base crm address is the DRV base of a register space that is used to place votes.
> + * Each VCD/ND/PT_ND has IRQ Status/Clear/Enable registers.
> + *
> + * - The config crm address is used to find overall configuration of the hardware including
> + * version, num_perf_ol_vcds, num_nds and num_nds_pt and no. of SW DRVs.
Wrap the code to match Linux coding style.
...
> +static int crm_probe(struct platform_device *pdev)
> +{
> + struct device_node *dn = pdev->dev.of_node;
This is NOT called 'dn', but 'np'. Always. Don't copy buggy rpmh code or
other weird drivers.
> + struct crm_drv_top *crm;
> + const char *name;
> + int ret;
> +
> + crm = devm_kzalloc(&pdev->dev, sizeof(*crm), GFP_KERNEL);
> + if (!crm)
> + return -ENOMEM;
> +
> + crm->desc = of_device_get_match_data(&pdev->dev);
> + if (!crm->desc)
> + return -EINVAL;
> +
> + name = of_get_property(dn, "label", NULL);
> + if (!name)
> + name = dev_name(&pdev->dev);
> +
> + crm->pdev = pdev;
> + crm->dev = &pdev->dev;
> + scnprintf(crm->name, sizeof(crm->name), "%s", name);
> +
> + crm->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
> + if (IS_ERR(crm->base))
> + return -ENOMEM;
> +
> + crm->cfg = devm_platform_get_and_ioremap_resource(pdev, 1, NULL);
> + if (IS_ERR(crm->cfg))
> + return -ENOMEM;
> +
> + if (pdev->dev.pm_domain) {
> + ret = devm_pm_runtime_enable(&pdev->dev);
> + if (ret)
> + return ret;
> +
> + ret = pm_runtime_resume_and_get(&pdev->dev);
> + if (ret)
> + return ret;
> + }
> +
> + crm->crm_enabled = readl_relaxed(crm->cfg + crm->desc->cfg_regs[CRM_ENABLE]);
> + if (!crm->crm_enabled) {
> + dev_err(crm->dev, "%s not enabled, exiting\n", crm->name);
How is this an error? If FW did not enable CRM, it did it on purpose, so
why are you reporting it as an error to the user? What user should do
with that? File a bug report for the FW?
> + ret = -ENODEV;
> + goto exit;
> + }
> +
> + ret = crm_probe_drvs(crm, dn);
> + if (ret)
> + goto exit;
> +
> + ret = crm_probe_get_irqs(crm);
> + if (ret)
> + goto exit;
> +
> + dev_set_drvdata(&pdev->dev, crm);
> +exit:
> + if (pdev->dev.pm_domain)
> + pm_runtime_put(&pdev->dev);
> +
> + return ret;
> +}
> +
> +static u32 crm_v2_cfg[] = {
Why isn't this const?
> + [CRM_VERSION] = 0x0,
> + [MAJOR_VERSION] = GENMASK(23, 16),
> + [MINOR_VERSION] = GENMASK(15, 8),
> + [CRM_CFG_PARAM_1] = 0x4,
> + [NUM_OF_NODES_PT] = GENMASK(31, 27),
> + [NUM_VCD_VOTED_BY_BW] = GENMASK(26, 24),
> + [NUM_SW_DRVS] = GENMASK(23, 20),
> + [NUM_OF_RAILS] = GENMASK(15, 12),
> + [NUM_VCD_VOTED_BY_PERF_OL] = GENMASK(11, 8),
> + [CRM_CFG_PARAM_2] = 0x8,
> + [NUM_OF_NODES] = GENMASK(30, 26),
> + [CRM_ENABLE] = 0xc,
> +};
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 05/13] clk: qcom: common: Add helpers to control clocks using CRM
2026-04-20 16:28 [PATCH 00/13] Add support to control clocks using CESTA Resource manager Jagadeesh Kona
` (3 preceding siblings ...)
2026-04-20 16:28 ` [PATCH 04/13] soc: qcom: Introduce CESTA resource manager driver Jagadeesh Kona
@ 2026-04-20 16:28 ` Jagadeesh Kona
2026-04-20 16:28 ` [PATCH 06/13] clk: qcom: clk-alpha-pll: Add support for CRM based PLL ops Jagadeesh Kona
` (6 subsequent siblings)
11 siblings, 0 replies; 24+ messages in thread
From: Jagadeesh Kona @ 2026-04-20 16:28 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones
Cc: Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree, linux-kernel,
linux-clk, Maulik Shah, Taniya Das, Jagadeesh Kona
CESTA Resource Manager (CRM) scales clock frequencies based on
performance operating levels. Introduce qcom_find_crm_freq_index()
to convert a requested clock rate into a CRM LUT performance level.
Additionally, add clk_crm and qcom_clk_crm_soc_data structures, which
capture the CRM-specific clock configuration for a clock controller
(register layout, LUT information, CRM device etc). This info is used
to read frequency lookup tables provided by CRM and for sending votes
through CRM to scale the clock frequencies.
Co-developed-by: Taniya Das <taniya.das@oss.qualcomm.com>
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
---
drivers/clk/qcom/common.c | 39 +++++++++++++++++++++++++++++++++++++++
drivers/clk/qcom/common.h | 38 +++++++++++++++++++++++++++++++++++++-
2 files changed, 76 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index eec369d2173b5ce24bc1ca860d2ac1bbdce04524..968e19997daf5eebec65315974cd0c41e08e55ec 100644
--- a/drivers/clk/qcom/common.c
+++ b/drivers/clk/qcom/common.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/export.h>
@@ -80,6 +81,44 @@ const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
}
EXPORT_SYMBOL_GPL(qcom_find_freq_floor);
+/**
+ * qcom_find_crm_freq_index - Map a clock rate to a CRM LUT performance level
+ * @f: pointer to the frequency table
+ * @rate: requested clock rate in Hz
+ *
+ * Convert a requested clock rate into a CRM LUT performance level index.
+ * CRM treats performance level 0 as CLK_OFF, so valid performance levels
+ * start from 1.
+ *
+ * Return: a non-negative performance level index on success, or -EINVAL
+ * if @f is NULL or the frequency table is empty.
+ */
+
+int qcom_find_crm_freq_index(const struct freq_tbl *f, unsigned long rate)
+{
+ int index;
+
+ if (!f || !f->freq)
+ return -EINVAL;
+
+ /* Return 0 for CRM to disable the clocks */
+ if (!rate)
+ return 0;
+
+ /*
+ * Calculate the perf level for supported frequencies starting
+ * from 1, since PERF_OL 0 is treated as CLK_OFF by CRM.
+ */
+ for (index = 1; f->freq; f++, index++) {
+ if (rate <= f->freq)
+ return index;
+ }
+
+ /* Default to highest corner */
+ return index - 1;
+}
+EXPORT_SYMBOL_GPL(qcom_find_crm_freq_index);
+
int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src)
{
int i, num_parents = clk_hw_get_num_parents(hw);
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index 6f2406f8839e8f432ef34ce32c930cf045f6ae7a..9987cec84324a258f3405c7b9093237f52a41b45 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -1,5 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved. */
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
#ifndef __QCOM_CLK_COMMON_H__
#define __QCOM_CLK_COMMON_H__
@@ -62,6 +65,39 @@ struct parent_map {
u8 cfg;
};
+/**
+ * struct qcom_clk_crm_soc_data - CRM clock register layout for a clock controller
+ *
+ * @reg_cfg_rcgr_lut_base: Base register address for CFG_RCGR LUT values
+ * @reg_l_val_lut_base: Base register address for PLL L and ALPHA LUT values
+ * @vcd_offset: Offset between consecutive VCD blocks
+ * @lut_level_offset: Offset between consecutive LUT levels within a VCD
+ */
+struct qcom_clk_crm_soc_data {
+ u32 reg_cfg_rcgr_lut_base;
+ u32 reg_l_val_lut_base;
+ u32 vcd_offset;
+ u32 lut_level_offset;
+};
+
+/**
+ * struct clk_crm - Clock CRM used to communicate with CRM
+ *
+ * @crm_dev: Pointer to CRM device structure used to communicate with CESTA
+ * @regmap_crmc: regmap for the crmc instance to read frequency look up tables
+ * @regs: CRMC (CRM clock) base register addresses and offsets
+ * @max_perf_ol: Maximum number of performance operating levels supported
+ * @client_idx: SW Client Index
+ */
+struct clk_crm {
+ struct device *crm_dev;
+ struct regmap *regmap_crmc;
+ struct qcom_clk_crm_soc_data regs;
+ u8 max_perf_ol;
+ u8 client_idx;
+};
+
+extern int qcom_find_crm_freq_index(const struct freq_tbl *f, unsigned long rate);
extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
unsigned long rate);
extern const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH 06/13] clk: qcom: clk-alpha-pll: Add support for CRM based PLL ops
2026-04-20 16:28 [PATCH 00/13] Add support to control clocks using CESTA Resource manager Jagadeesh Kona
` (4 preceding siblings ...)
2026-04-20 16:28 ` [PATCH 05/13] clk: qcom: common: Add helpers to control clocks using CRM Jagadeesh Kona
@ 2026-04-20 16:28 ` Jagadeesh Kona
2026-04-22 18:25 ` Dmitry Baryshkov
2026-04-20 16:29 ` [PATCH 07/13] clk: qcom: clk-alpha-pll: Add support to skip PLL configuration Jagadeesh Kona
` (5 subsequent siblings)
11 siblings, 1 reply; 24+ messages in thread
From: Jagadeesh Kona @ 2026-04-20 16:28 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones
Cc: Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree, linux-kernel,
linux-clk, Maulik Shah, Taniya Das, Jagadeesh Kona
Add clock ops for PLLs that are controlled by the CESTA Resource
Manager(CRM). For these PLLs, CRM programs the hardware based on
aggregated votes, so the clock driver does not need to program the
PLL registers directly, but can still model the PLLs and expose
them as parents to RCGs in the common clock framework.
Co-developed-by: Taniya Das <taniya.das@oss.qualcomm.com>
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
---
drivers/clk/qcom/clk-alpha-pll.c | 7 +++++++
drivers/clk/qcom/clk-alpha-pll.h | 3 +++
2 files changed, 10 insertions(+)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index f8313f9d0e30ffd5393e3163ebc0e51b2bd96437..67fc97739d0d4c26aec0bac5d43d1b87d297bc6a 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2021, 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/kernel.h>
@@ -2585,6 +2586,12 @@ const struct clk_ops clk_alpha_pll_reset_lucid_evo_ops = {
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_reset_lucid_evo_ops);
+const struct clk_ops clk_alpha_pll_crm_ops = {
+ .recalc_rate = alpha_pll_lucid_evo_recalc_rate,
+ .determine_rate = clk_alpha_pll_determine_rate,
+};
+EXPORT_SYMBOL_GPL(clk_alpha_pll_crm_ops);
+
static int alpha_pll_pongo_elu_prepare(struct clk_hw *hw)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 42d3344921457c39deadcca5c43d72ded3b572a3..1ef515708ce19e636eb9a59b126df5048e262d85 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2015, 2018, 2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
@@ -219,6 +220,8 @@ extern const struct clk_ops clk_alpha_pll_rivian_evo_ops;
extern const struct clk_ops clk_alpha_pll_regera_ops;
extern const struct clk_ops clk_alpha_pll_slew_ops;
+extern const struct clk_ops clk_alpha_pll_crm_ops;
+
void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config);
void clk_huayra_2290_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* Re: [PATCH 06/13] clk: qcom: clk-alpha-pll: Add support for CRM based PLL ops
2026-04-20 16:28 ` [PATCH 06/13] clk: qcom: clk-alpha-pll: Add support for CRM based PLL ops Jagadeesh Kona
@ 2026-04-22 18:25 ` Dmitry Baryshkov
0 siblings, 0 replies; 24+ messages in thread
From: Dmitry Baryshkov @ 2026-04-22 18:25 UTC (permalink / raw)
To: Jagadeesh Kona
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones, Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree,
linux-kernel, linux-clk, Maulik Shah, Taniya Das
On Mon, Apr 20, 2026 at 09:58:59PM +0530, Jagadeesh Kona wrote:
> Add clock ops for PLLs that are controlled by the CESTA Resource
> Manager(CRM). For these PLLs, CRM programs the hardware based on
> aggregated votes, so the clock driver does not need to program the
> PLL registers directly, but can still model the PLLs and expose
> them as parents to RCGs in the common clock framework.
>
> Co-developed-by: Taniya Das <taniya.das@oss.qualcomm.com>
> Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
> Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
> ---
> drivers/clk/qcom/clk-alpha-pll.c | 7 +++++++
> drivers/clk/qcom/clk-alpha-pll.h | 3 +++
> 2 files changed, 10 insertions(+)
>
> diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
> index f8313f9d0e30ffd5393e3163ebc0e51b2bd96437..67fc97739d0d4c26aec0bac5d43d1b87d297bc6a 100644
> --- a/drivers/clk/qcom/clk-alpha-pll.c
> +++ b/drivers/clk/qcom/clk-alpha-pll.c
> @@ -2,6 +2,7 @@
> /*
> * Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
> * Copyright (c) 2021, 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
Note: you are supposed to absorb th QuIC copyright.
> */
>
> #include <linux/kernel.h>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 07/13] clk: qcom: clk-alpha-pll: Add support to skip PLL configuration
2026-04-20 16:28 [PATCH 00/13] Add support to control clocks using CESTA Resource manager Jagadeesh Kona
` (5 preceding siblings ...)
2026-04-20 16:28 ` [PATCH 06/13] clk: qcom: clk-alpha-pll: Add support for CRM based PLL ops Jagadeesh Kona
@ 2026-04-20 16:29 ` Jagadeesh Kona
2026-04-22 18:28 ` Dmitry Baryshkov
2026-04-20 16:29 ` [PATCH 08/13] clk: qcom: clk-rcg2: Add support for CRM based RCG ops Jagadeesh Kona
` (4 subsequent siblings)
11 siblings, 1 reply; 24+ messages in thread
From: Jagadeesh Kona @ 2026-04-20 16:29 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones
Cc: Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree, linux-kernel,
linux-clk, Maulik Shah, Taniya Das, Jagadeesh Kona
Some PLLs are already configured as part of CRM(CESTA Resource
manager) initialization. Add support to skip PLL reconfiguration
for such PLLs that are already configured.
Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
---
drivers/clk/qcom/clk-alpha-pll.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 67fc97739d0d4c26aec0bac5d43d1b87d297bc6a..2f4ebf4d3884b92c981dbe0e67245704a88881ad 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -2332,7 +2332,7 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_zonda_ops);
void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config)
{
- u32 lval = config->l;
+ u32 lval = config->l, regval;
/*
* If the bootloader left the PLL enabled it's likely that there are
@@ -2343,6 +2343,12 @@ void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regma
return;
}
+ /* Return early if PLL is already configured */
+ regmap_read(regmap, PLL_L_VAL(pll), ®val);
+ regval &= LUCID_EVO_PLL_L_VAL_MASK;
+ if (regval)
+ return;
+
if (config->cal_l)
lval |= config->cal_l << LUCID_EVO_PLL_CAL_L_VAL_SHIFT;
else
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* Re: [PATCH 07/13] clk: qcom: clk-alpha-pll: Add support to skip PLL configuration
2026-04-20 16:29 ` [PATCH 07/13] clk: qcom: clk-alpha-pll: Add support to skip PLL configuration Jagadeesh Kona
@ 2026-04-22 18:28 ` Dmitry Baryshkov
0 siblings, 0 replies; 24+ messages in thread
From: Dmitry Baryshkov @ 2026-04-22 18:28 UTC (permalink / raw)
To: Jagadeesh Kona
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones, Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree,
linux-kernel, linux-clk, Maulik Shah, Taniya Das
On Mon, Apr 20, 2026 at 09:59:00PM +0530, Jagadeesh Kona wrote:
> Some PLLs are already configured as part of CRM(CESTA Resource
> manager) initialization. Add support to skip PLL reconfiguration
> for such PLLs that are already configured.
>
> Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
> ---
> drivers/clk/qcom/clk-alpha-pll.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
> index 67fc97739d0d4c26aec0bac5d43d1b87d297bc6a..2f4ebf4d3884b92c981dbe0e67245704a88881ad 100644
> --- a/drivers/clk/qcom/clk-alpha-pll.c
> +++ b/drivers/clk/qcom/clk-alpha-pll.c
> @@ -2332,7 +2332,7 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_zonda_ops);
> void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
> const struct alpha_pll_config *config)
> {
> - u32 lval = config->l;
> + u32 lval = config->l, regval;
>
> /*
> * If the bootloader left the PLL enabled it's likely that there are
> @@ -2343,6 +2343,12 @@ void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regma
> return;
> }
>
> + /* Return early if PLL is already configured */
> + regmap_read(regmap, PLL_L_VAL(pll), ®val);
> + regval &= LUCID_EVO_PLL_L_VAL_MASK;
> + if (regval)
> + return;
> +
Why is it being applied only to Lucid EVO PLLs?
> if (config->cal_l)
> lval |= config->cal_l << LUCID_EVO_PLL_CAL_L_VAL_SHIFT;
> else
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 08/13] clk: qcom: clk-rcg2: Add support for CRM based RCG ops
2026-04-20 16:28 [PATCH 00/13] Add support to control clocks using CESTA Resource manager Jagadeesh Kona
` (6 preceding siblings ...)
2026-04-20 16:29 ` [PATCH 07/13] clk: qcom: clk-alpha-pll: Add support to skip PLL configuration Jagadeesh Kona
@ 2026-04-20 16:29 ` Jagadeesh Kona
2026-04-20 16:29 ` [PATCH 09/13] clk: qcom: common: Add support to register and control clocks using CRM Jagadeesh Kona
` (3 subsequent siblings)
11 siblings, 0 replies; 24+ messages in thread
From: Jagadeesh Kona @ 2026-04-20 16:29 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones
Cc: Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree, linux-kernel,
linux-clk, Maulik Shah, Taniya Das, Jagadeesh Kona
Add clock ops to control RCGs via the CESTA Resource Manager(CRM).
This adds support for clk_rcg2_crmb_ops where the RCG's frequency
table is dynamically populated by reading the LUT entries provided
by CRM. For scaling the RCG, the RCG frequency is converted to BCM
TCS bandwidth vote and sent to CESTA HW using CRM APIs. The CESTA
HW would then scale the RCG to the desired frequency requested via
CRM.
Co-developed-by: Taniya Das <taniya.das@oss.qualcomm.com>
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
---
drivers/clk/qcom/clk-rcg.h | 23 ++++-
drivers/clk/qcom/clk-rcg2.c | 242 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 264 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index 4fbdf4880d0308714a2d1dc8c510ec3819206b9e..4872e7f9caa1096bdebca36dfbb439dc790638ef 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -1,5 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2013, 2018, The Linux Foundation. All rights reserved. */
+/*
+ * Copyright (c) 2013, 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
#ifndef __QCOM_CLK_RCG_H__
#define __QCOM_CLK_RCG_H__
@@ -175,9 +178,26 @@ struct clk_rcg2 {
u8 cfg_off;
u32 parked_cfg;
bool hw_clk_ctrl;
+
+};
+
+/**
+ * struct clk_rcg2_crm - root clock generator controlled via CRM
+ * (CESTA Resource Manager)
+ *
+ * @rcg: root clock generator
+ * @crm_vcd: Virtual Clock Domain(VCD) index for a CRM controlled RCG
+ * @crm: pointer to CLK CRM instance used for reading frequency LUTs
+ * and to communicate with CESTA HW
+ */
+struct clk_rcg2_crm {
+ struct clk_rcg2 rcg;
+ u8 crm_vcd;
+ struct clk_crm *crm;
};
#define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
+#define to_clk_rcg2_crm(_hw) container_of(to_clk_rcg2(_hw), struct clk_rcg2_crm, rcg)
struct clk_rcg2_gfx3d {
u8 div;
@@ -202,6 +222,7 @@ extern const struct clk_ops clk_rcg2_shared_ops;
extern const struct clk_ops clk_rcg2_shared_floor_ops;
extern const struct clk_ops clk_rcg2_shared_no_init_park_ops;
extern const struct clk_ops clk_dp_ops;
+extern const struct clk_ops clk_rcg2_crmb_ops;
struct clk_rcg_dfs_data {
struct clk_rcg2 *rcg;
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 6064a0e17d5190e9d228688c04c0d4947876b4e6..668115b94a0f202cf3ac4f68efe3cef1684055be 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2013, 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/kernel.h>
@@ -16,9 +17,12 @@
#include <linux/math64.h>
#include <linux/gcd.h>
#include <linux/minmax.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <asm/div64.h>
+#include <soc/qcom/crm.h>
+#include <soc/qcom/tcs.h>
#include "clk-rcg.h"
#include "common.h"
@@ -59,6 +63,33 @@
#define SE_PERF_M_DFSR(level) (0x5c + 0x4 * (level))
#define SE_PERF_N_DFSR(level) (0x9c + 0x4 * (level))
+/* Cesta configuration*/
+#define MAX_CRM_SW_DRV_STATE 3
+
+/* Address offset for specific VCD */
+#define CRMC_OFFS_VCD(crm, _vcd) \
+ ((crm)->regs.vcd_offset * (_vcd))
+
+/* LUT registers address offset for specific vcd and lut entry level */
+#define CRMC_OFFS_LUT(crm, vcd, _level) \
+ (CRMC_OFFS_VCD(crm, vcd) + ((crm)->regs.lut_level_offset * (_level)))
+
+/* CFG_RCGR LUT register address offset for specific vcd and lut entry level */
+#define CRMC_OFFS_CFG_RCGR(crm, vcd, level) \
+ (CRMC_OFFS_LUT(crm, vcd, level) + (crm)->regs.reg_cfg_rcgr_lut_base)
+
+/* L_VAL LUT register address offset for specific vcd and lut entry level */
+#define CRMC_OFFS_L_VAL(crm, vcd, level) \
+ (CRMC_OFFS_LUT(crm, vcd, level) + (crm)->regs.reg_l_val_lut_base)
+
+#define PLL_L_VAL_MASK GENMASK(7, 0)
+#define PLL_ALPHA_VAL_MASK GENMASK(31, 16)
+#define PLL_ALPHA_VAL_SHIFT 16
+#define PERF_OL_OFF 0
+#define XO_FREQ 19200000ULL
+#define CALC_PLL_RATE(l, a) ((XO_FREQ * (l)) + ((XO_FREQ * (a)) >> 16))
+#define HZ_TO_MHZ(rate) (rate / 1000000ULL)
+
enum freq_policy {
FLOOR,
CEIL,
@@ -1859,3 +1890,214 @@ const struct clk_ops clk_dp_ops = {
.determine_rate = clk_rcg2_dp_determine_rate,
};
EXPORT_SYMBOL_GPL(clk_dp_ops);
+
+static int clk_rcg2_crm_populate_freq(struct clk_hw *hw, unsigned int lut_index,
+ struct freq_tbl *f)
+{
+ u32 mask, cfg_rcgr, src, pll_lval, lval, alpha_val, num_parents, pindex;
+ struct clk_rcg2_crm *rcg_crm = to_clk_rcg2_crm(hw);
+ struct clk_rcg2 *rcg = &rcg_crm->rcg;
+ struct clk_crm *crm = rcg_crm->crm;
+ u32 vcd = rcg_crm->crm_vcd;
+ unsigned long prate = 0;
+ struct clk_hw *parent;
+
+ /* Read CFG_RCGR and PLL LUT entries */
+ regmap_read(crm->regmap_crmc, CRMC_OFFS_CFG_RCGR(crm, vcd, lut_index), &cfg_rcgr);
+ regmap_read(crm->regmap_crmc, CRMC_OFFS_L_VAL(crm, vcd, lut_index), &pll_lval);
+
+ /* Calculate the pre_div and parent source from LUT entry */
+ mask = BIT(rcg->hid_width) - 1;
+ f->pre_div = 1;
+ if (cfg_rcgr & mask)
+ f->pre_div = cfg_rcgr & mask;
+
+ src = cfg_rcgr & CFG_SRC_SEL_MASK;
+ src >>= CFG_SRC_SEL_SHIFT;
+
+ lval = pll_lval & PLL_L_VAL_MASK;
+ alpha_val = (pll_lval & PLL_ALPHA_VAL_MASK) >> PLL_ALPHA_VAL_SHIFT;
+
+ /* Find the matching parent and calculate it's rate for LUT entry */
+ num_parents = clk_hw_get_num_parents(hw);
+ for (pindex = 0; pindex < num_parents; pindex++) {
+ if (src == rcg->parent_map[pindex].cfg) {
+ f->src = rcg->parent_map[pindex].src;
+
+ parent = clk_hw_get_parent_by_index(hw, pindex);
+ if (!parent)
+ return -EINVAL;
+
+ if (!lval)
+ prate = clk_hw_get_rate(parent);
+ else
+ prate = CALC_PLL_RATE(lval, alpha_val);
+
+ break;
+ }
+ }
+
+ if (!prate)
+ return -EINVAL;
+
+ /* Calculate the RCG's rate from parent rate */
+ f->freq = calc_rate(prate, 0, 0, 0, f->pre_div);
+
+ return 0;
+}
+
+static int clk_rcg2_crm_populate_freq_table(struct clk_hw *hw)
+{
+ struct freq_tbl *freq_tbl, *curr_freq_tbl;
+ struct clk_rcg2_crm *rcg_crm = to_clk_rcg2_crm(hw);
+ struct clk_rcg2 *rcg = &rcg_crm->rcg;
+ struct clk_crm *crm = rcg_crm->crm;
+ u32 prev_freq = 0;
+ int i, ret;
+
+ /* Allocate space for 1 extra since table is NULL terminated */
+ freq_tbl = kcalloc(crm->max_perf_ol + 1, sizeof(*freq_tbl), GFP_KERNEL);
+ if (!freq_tbl)
+ return -ENOMEM;
+
+ for (i = 0; i < crm->max_perf_ol; i++) {
+ /* Skip first LUT entry as first entry is used to disable RCG */
+ ret = clk_rcg2_crm_populate_freq(hw, i + 1, freq_tbl + i);
+ if (ret) {
+ kfree(freq_tbl);
+ return ret;
+ }
+
+ curr_freq_tbl = freq_tbl + i;
+
+ /* Two of the same/decreasing frequencies means end of LUT */
+ if (prev_freq >= curr_freq_tbl->freq) {
+ curr_freq_tbl->freq = 0;
+ break;
+ }
+
+ prev_freq = curr_freq_tbl->freq;
+ }
+
+ rcg->freq_tbl = freq_tbl;
+
+ return 0;
+}
+
+static int clk_rcg2_crm_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct device *dev = clk_hw_get_dev(hw);
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+ int ret;
+
+ if (!rcg->freq_tbl) {
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_rcg2_crm_populate_freq_table(hw);
+ if (ret) {
+ pm_runtime_put(dev);
+ return ret;
+ }
+
+ pm_runtime_put(dev);
+ }
+
+ return clk_rcg2_determine_rate(hw, req);
+}
+
+static unsigned long
+clk_rcg2_crm_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+
+ if (!rcg->freq_tbl)
+ return clk_rcg2_recalc_rate(hw, parent_rate);
+
+ return rcg->freq_tbl[rcg->parked_cfg].freq;
+}
+
+static int clk_rcg2_crm_init(struct clk_hw *hw)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+
+ rcg->freq_tbl = NULL;
+
+ return 0;
+}
+
+static int clk_rcg2_vote_bw(struct clk_hw *hw, unsigned long rate)
+{
+ struct clk_rcg2_crm *rcg_crm = to_clk_rcg2_crm(hw);
+ struct clk_crm *crm = rcg_crm->crm;
+ struct crm_cmd cmd;
+ int ret, i;
+
+ cmd.resource_idx = 0;
+ cmd.wait = true;
+ cmd.data = BCM_TCS_CMD(1, 1, 0, HZ_TO_MHZ(rate));
+
+ for (i = 0; i < MAX_CRM_SW_DRV_STATE; i++) {
+ cmd.pwr_state = i;
+ ret = crm_write_bw_vote(crm->crm_dev, crm->client_idx, &cmd);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int clk_rcg2_crmb_prepare(struct clk_hw *hw)
+{
+ unsigned long rate = clk_hw_get_rate(hw);
+
+ if (!rate)
+ return -EINVAL;
+
+ return clk_rcg2_vote_bw(hw, rate);
+}
+
+static void clk_rcg2_crmb_unprepare(struct clk_hw *hw)
+{
+ clk_rcg2_vote_bw(hw, PERF_OL_OFF);
+}
+
+static int clk_rcg2_crmb_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_rcg2_crm *rcg_crm = to_clk_rcg2_crm(hw);
+ struct clk_rcg2 *rcg = &rcg_crm->rcg;
+ struct clk_crm *crm = rcg_crm->crm;
+ int perf_index;
+
+ perf_index = qcom_find_crm_freq_index(rcg->freq_tbl, rate);
+ if (perf_index <= PERF_OL_OFF || perf_index > crm->max_perf_ol)
+ return -EINVAL;
+
+ /*
+ * perf_index returned from qcom_find_crm_freq_index() starts from
+ * index 1 since 0 is treated as OFF by CRM, but RCG's frequency
+ * table starts from index 0, store parked_cfg aligning to RCG's
+ * frequency table index.
+ */
+ rcg->parked_cfg = perf_index - 1;
+
+ if (!clk_hw_is_prepared(hw))
+ return 0;
+
+ return clk_rcg2_vote_bw(hw, rate);
+}
+
+const struct clk_ops clk_rcg2_crmb_ops = {
+ .prepare = clk_rcg2_crmb_prepare,
+ .unprepare = clk_rcg2_crmb_unprepare,
+ .is_enabled = clk_rcg2_is_enabled,
+ .get_parent = clk_rcg2_get_parent,
+ .set_rate = clk_rcg2_crmb_set_rate,
+ .determine_rate = clk_rcg2_crm_determine_rate,
+ .recalc_rate = clk_rcg2_crm_recalc_rate,
+ .init = clk_rcg2_crm_init,
+};
+EXPORT_SYMBOL_GPL(clk_rcg2_crmb_ops);
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH 09/13] clk: qcom: common: Add support to register and control clocks using CRM
2026-04-20 16:28 [PATCH 00/13] Add support to control clocks using CESTA Resource manager Jagadeesh Kona
` (7 preceding siblings ...)
2026-04-20 16:29 ` [PATCH 08/13] clk: qcom: clk-rcg2: Add support for CRM based RCG ops Jagadeesh Kona
@ 2026-04-20 16:29 ` Jagadeesh Kona
2026-04-20 16:29 ` [PATCH 10/13] clk: qcom: dispcc-sm8750: Add support to control MDP clocks using CESTA Jagadeesh Kona
` (2 subsequent siblings)
11 siblings, 0 replies; 24+ messages in thread
From: Jagadeesh Kona @ 2026-04-20 16:29 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones
Cc: Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree, linux-kernel,
linux-clk, Maulik Shah, Taniya Das, Jagadeesh Kona
Add support for helper macros to maintain the list of CRM clocks in a
clock controller. Add support for qcom_cc_register_cesta_clks() which takes
this list of CRM clocks and update the ops of these clocks to CRM clock ops
only if CRM is enabled.
Co-developed-by: Taniya Das <taniya.das@oss.qualcomm.com>
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
---
drivers/clk/qcom/common.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/qcom/common.h | 19 +++++++++++++++++
2 files changed, 73 insertions(+)
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index 968e19997daf5eebec65315974cd0c41e08e55ec..14dfae80e567852d09a5972858ae14c62e5074ee 100644
--- a/drivers/clk/qcom/common.c
+++ b/drivers/clk/qcom/common.c
@@ -10,10 +10,13 @@
#include <linux/platform_device.h>
#include <linux/clk-provider.h>
#include <linux/interconnect-clk.h>
+#include <linux/mfd/syscon.h>
#include <linux/pm_runtime.h>
#include <linux/reset-controller.h>
#include <linux/of.h>
+#include <soc/qcom/crm.h>
+
#include "common.h"
#include "clk-alpha-pll.h"
#include "clk-branch.h"
@@ -266,6 +269,47 @@ int qcom_cc_register_sleep_clk(struct device *dev)
}
EXPORT_SYMBOL_GPL(qcom_cc_register_sleep_clk);
+static void qcom_register_crm_clk(const struct crm_clk_data *data)
+{
+ struct clk_init_data *init = data->init;
+
+ switch (data->flags) {
+ case CRM_PLL:
+ init->ops = &clk_alpha_pll_crm_ops;
+ break;
+ case CRM_RCG_CRMB:
+ init->ops = &clk_rcg2_crmb_ops;
+ break;
+ default:
+ pr_err("Invalid CRM flag for %s\n", init->name);
+ break;
+ }
+}
+
+static int qcom_cc_register_crm_clks(struct device *dev, struct clk_crm *crm,
+ const struct crm_clk_data *clks, size_t len)
+{
+ int i;
+
+ crm->crm_dev = crm_get(dev);
+ if (IS_ERR(crm->crm_dev))
+ return PTR_ERR(crm->crm_dev);
+
+ if (crm->crm_dev && crm->max_perf_ol) {
+ crm->regmap_crmc = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "qcom,crmc-regmap");
+ if (IS_ERR(crm->regmap_crmc))
+ return PTR_ERR(crm->regmap_crmc);
+
+ for (i = 0; i < len; i++)
+ qcom_register_crm_clk(&clks[i]);
+
+ return 0;
+ }
+
+ return -EOPNOTSUPP;
+}
+
/* Drop 'protected-clocks' from the list of clocks to register */
static void qcom_cc_drop_protected(struct device *dev, struct qcom_cc *cc)
{
@@ -439,6 +483,16 @@ int qcom_cc_really_probe(struct device *dev,
goto put_rpm;
}
+ if (desc->driver_data &&
+ desc->driver_data->crm) {
+ ret = qcom_cc_register_crm_clks(dev, desc->driver_data->crm,
+ desc->driver_data->crm_clks,
+ desc->driver_data->num_crm_clks);
+ if (ret)
+ dev_err_probe(dev, ret,
+ "Failed to register clocks with CRM, ret: %d\n", ret);
+ }
+
cc->rclks = rclks;
cc->num_rclks = num_clks;
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index 9987cec84324a258f3405c7b9093237f52a41b45..d00376f058ce1de7aa82ff760f92826282b1606f 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -35,6 +35,9 @@ struct qcom_cc_driver_data {
size_t num_clk_cbcrs;
const struct clk_rcg_dfs_data *dfs_rcgs;
size_t num_dfs_rcgs;
+ struct clk_crm *crm;
+ const struct crm_clk_data *crm_clks;
+ size_t num_crm_clks;
void (*clk_regs_configure)(struct device *dev, struct regmap *regmap);
};
@@ -97,6 +100,22 @@ struct clk_crm {
u8 client_idx;
};
+struct crm_clk_data {
+ struct clk_init_data *init;
+#define CRM_PLL BIT(0)
+#define CRM_RCG_CRMB BIT(1)
+ u8 flags;
+};
+
+#define CRM_CLK(clk, flag) \
+{ \
+ .init = &clk##_init, \
+ .flags = flag, \
+}
+
+#define CRM_CLK_PLL(clk) CRM_CLK(clk, CRM_PLL)
+#define CRM_CLK_RCG_CRMB(clk) CRM_CLK(clk, CRM_RCG_CRMB)
+
extern int qcom_find_crm_freq_index(const struct freq_tbl *f, unsigned long rate);
extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
unsigned long rate);
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH 10/13] clk: qcom: dispcc-sm8750: Add support to control MDP clocks using CESTA
2026-04-20 16:28 [PATCH 00/13] Add support to control clocks using CESTA Resource manager Jagadeesh Kona
` (8 preceding siblings ...)
2026-04-20 16:29 ` [PATCH 09/13] clk: qcom: common: Add support to register and control clocks using CRM Jagadeesh Kona
@ 2026-04-20 16:29 ` Jagadeesh Kona
2026-04-22 18:33 ` Dmitry Baryshkov
2026-04-20 17:24 ` [PATCH 11/13] arm64: dts: qcom: sm8750: Add Display CRM device Jagadeesh Kona
2026-04-20 17:28 ` [PATCH 12/13] arm64: dts: qcom: sm8750: Add disp_crmc node and CRM properties to dispcc Jagadeesh Kona
11 siblings, 1 reply; 24+ messages in thread
From: Jagadeesh Kona @ 2026-04-20 16:29 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones
Cc: Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree, linux-kernel,
linux-clk, Maulik Shah, Taniya Das, Jagadeesh Kona
Add support to control the DISPCC MDSS MDP RCG and the associated display
PLL0 using display CESTA hardware on SM8750 platform. If display CRM is
enabled, the clock ops of these clocks will be updated by the common code
before registration to use CRM specific clock ops, allowing these clocks
to be controlled using display CRM (CESTA Resource Manager) hardware.
Co-developed-by: Taniya Das <taniya.das@oss.qualcomm.com>
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
---
drivers/clk/qcom/dispcc-sm8750.c | 89 +++++++++++++++++++++++++---------------
1 file changed, 56 insertions(+), 33 deletions(-)
diff --git a/drivers/clk/qcom/dispcc-sm8750.c b/drivers/clk/qcom/dispcc-sm8750.c
index ca09da111a50e811481fd862b54d454de024d1c9..328e43b52192702dbbfd1ed65737520acdd4a649 100644
--- a/drivers/clk/qcom/dispcc-sm8750.c
+++ b/drivers/clk/qcom/dispcc-sm8750.c
@@ -71,6 +71,16 @@ enum {
P_SLEEP_CLK,
};
+static struct clk_crm disp_crm = {
+ .max_perf_ol = 10,
+ .regs = {
+ .reg_cfg_rcgr_lut_base = 0xd8,
+ .reg_l_val_lut_base = 0xdc,
+ .vcd_offset = 0x268,
+ .lut_level_offset = 0x28,
+ },
+};
+
static const struct pll_vco pongo_elu_vco[] = {
{ 38400000, 38400000, 0 },
};
@@ -89,21 +99,22 @@ static struct alpha_pll_config disp_cc_pll0_config = {
.user_ctl_hi_val = 0x00000002,
};
+static struct clk_init_data disp_cc_pll0_init = {
+ .name = "disp_cc_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ .ops = &clk_alpha_pll_taycan_elu_ops,
+};
+
static struct clk_alpha_pll disp_cc_pll0 = {
.offset = 0x0,
.vco_table = taycan_elu_vco,
.num_vco = ARRAY_SIZE(taycan_elu_vco),
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_ELU],
- .clkr = {
- .hw.init = &(const struct clk_init_data) {
- .name = "disp_cc_pll0",
- .parent_data = &(const struct clk_parent_data) {
- .index = DT_BI_TCXO,
- },
- .num_parents = 1,
- .ops = &clk_alpha_pll_taycan_elu_ops,
- },
- },
+ .clkr.hw.init = &disp_cc_pll0_init,
};
static struct alpha_pll_config disp_cc_pll1_config = {
@@ -681,25 +692,25 @@ static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = {
{ }
};
-static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {
- .cmd_rcgr = 0x8150,
- .mnd_width = 0,
- .hid_width = 5,
- .parent_map = disp_cc_parent_map_9,
- .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,
- .clkr.hw.init = &(const struct clk_init_data) {
- .name = "disp_cc_mdss_mdp_clk_src",
- .parent_data = disp_cc_parent_data_9,
- .num_parents = ARRAY_SIZE(disp_cc_parent_data_9),
- .flags = CLK_SET_RATE_PARENT,
- /*
- * TODO: Downstream does not manage the clock directly, but
- * places votes via new hardware block called "cesta".
- * It is not clear whether such approach should be taken instead
- * of manual control.
- */
- .ops = &clk_rcg2_shared_ops,
+static struct clk_init_data disp_cc_mdss_mdp_clk_src_init = {
+ .name = "disp_cc_mdss_mdp_clk_src",
+ .parent_data = disp_cc_parent_data_9,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_9),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+};
+
+static struct clk_rcg2_crm disp_cc_mdss_mdp_clk_src = {
+ .rcg = {
+ .cmd_rcgr = 0x8150,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_9,
+ .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,
+ .clkr.hw.init = &disp_cc_mdss_mdp_clk_src_init,
},
+ .crm_vcd = 1,
+ .crm = &disp_crm,
};
static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = {
@@ -1562,7 +1573,7 @@ static struct clk_branch disp_cc_mdss_mdp1_clk = {
.hw.init = &(const struct clk_init_data) {
.name = "disp_cc_mdss_mdp1_clk",
.parent_hws = (const struct clk_hw*[]) {
- &disp_cc_mdss_mdp_clk_src.clkr.hw,
+ &disp_cc_mdss_mdp_clk_src.rcg.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1580,7 +1591,7 @@ static struct clk_branch disp_cc_mdss_mdp_clk = {
.hw.init = &(const struct clk_init_data) {
.name = "disp_cc_mdss_mdp_clk",
.parent_hws = (const struct clk_hw*[]) {
- &disp_cc_mdss_mdp_clk_src.clkr.hw,
+ &disp_cc_mdss_mdp_clk_src.rcg.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1598,7 +1609,7 @@ static struct clk_branch disp_cc_mdss_mdp_lut1_clk = {
.hw.init = &(const struct clk_init_data) {
.name = "disp_cc_mdss_mdp_lut1_clk",
.parent_hws = (const struct clk_hw*[]) {
- &disp_cc_mdss_mdp_clk_src.clkr.hw,
+ &disp_cc_mdss_mdp_clk_src.rcg.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1616,7 +1627,7 @@ static struct clk_branch disp_cc_mdss_mdp_lut_clk = {
.hw.init = &(const struct clk_init_data) {
.name = "disp_cc_mdss_mdp_lut_clk",
.parent_hws = (const struct clk_hw*[]) {
- &disp_cc_mdss_mdp_clk_src.clkr.hw,
+ &disp_cc_mdss_mdp_clk_src.rcg.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1844,7 +1855,7 @@ static struct clk_regmap *disp_cc_sm8750_clocks[] = {
[DISP_CC_MDSS_ESC1_CLK_SRC] = &disp_cc_mdss_esc1_clk_src.clkr,
[DISP_CC_MDSS_MDP1_CLK] = &disp_cc_mdss_mdp1_clk.clkr,
[DISP_CC_MDSS_MDP_CLK] = &disp_cc_mdss_mdp_clk.clkr,
- [DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.clkr,
+ [DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.rcg.clkr,
[DISP_CC_MDSS_MDP_LUT1_CLK] = &disp_cc_mdss_mdp_lut1_clk.clkr,
[DISP_CC_MDSS_MDP_LUT_CLK] = &disp_cc_mdss_mdp_lut_clk.clkr,
[DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp_cc_mdss_non_gdsc_ahb_clk.clkr,
@@ -1866,6 +1877,11 @@ static struct clk_regmap *disp_cc_sm8750_clocks[] = {
[DISP_CC_XO_CLK_SRC] = &disp_cc_xo_clk_src.clkr,
};
+static const struct crm_clk_data disp_cc_sm8750_crm_clks[] = {
+ CRM_CLK_PLL(disp_cc_pll0),
+ CRM_CLK_RCG_CRMB(disp_cc_mdss_mdp_clk_src),
+};
+
static const struct qcom_reset_map disp_cc_sm8750_resets[] = {
[DISP_CC_MDSS_CORE_BCR] = { 0x8000 },
[DISP_CC_MDSS_CORE_INT2_BCR] = { 0xa000 },
@@ -1885,6 +1901,12 @@ static const struct regmap_config disp_cc_sm8750_regmap_config = {
.fast_io = true,
};
+static struct qcom_cc_driver_data disp_cc_sm8750_driver_data = {
+ .crm = &disp_crm,
+ .crm_clks = disp_cc_sm8750_crm_clks,
+ .num_crm_clks = ARRAY_SIZE(disp_cc_sm8750_crm_clks),
+};
+
static const struct qcom_cc_desc disp_cc_sm8750_desc = {
.config = &disp_cc_sm8750_regmap_config,
.clks = disp_cc_sm8750_clocks,
@@ -1893,6 +1915,7 @@ static const struct qcom_cc_desc disp_cc_sm8750_desc = {
.num_resets = ARRAY_SIZE(disp_cc_sm8750_resets),
.gdscs = disp_cc_sm8750_gdscs,
.num_gdscs = ARRAY_SIZE(disp_cc_sm8750_gdscs),
+ .driver_data = &disp_cc_sm8750_driver_data,
};
static const struct of_device_id disp_cc_sm8750_match_table[] = {
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* Re: [PATCH 10/13] clk: qcom: dispcc-sm8750: Add support to control MDP clocks using CESTA
2026-04-20 16:29 ` [PATCH 10/13] clk: qcom: dispcc-sm8750: Add support to control MDP clocks using CESTA Jagadeesh Kona
@ 2026-04-22 18:33 ` Dmitry Baryshkov
0 siblings, 0 replies; 24+ messages in thread
From: Dmitry Baryshkov @ 2026-04-22 18:33 UTC (permalink / raw)
To: Jagadeesh Kona
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones, Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree,
linux-kernel, linux-clk, Maulik Shah, Taniya Das
On Mon, Apr 20, 2026 at 09:59:03PM +0530, Jagadeesh Kona wrote:
> Add support to control the DISPCC MDSS MDP RCG and the associated display
> PLL0 using display CESTA hardware on SM8750 platform. If display CRM is
> enabled, the clock ops of these clocks will be updated by the common code
> before registration to use CRM specific clock ops, allowing these clocks
> to be controlled using display CRM (CESTA Resource Manager) hardware.
>
> Co-developed-by: Taniya Das <taniya.das@oss.qualcomm.com>
> Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
> Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
> ---
> drivers/clk/qcom/dispcc-sm8750.c | 89 +++++++++++++++++++++++++---------------
> 1 file changed, 56 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/clk/qcom/dispcc-sm8750.c b/drivers/clk/qcom/dispcc-sm8750.c
> index ca09da111a50e811481fd862b54d454de024d1c9..328e43b52192702dbbfd1ed65737520acdd4a649 100644
> --- a/drivers/clk/qcom/dispcc-sm8750.c
> +++ b/drivers/clk/qcom/dispcc-sm8750.c
> @@ -71,6 +71,16 @@ enum {
> P_SLEEP_CLK,
> };
>
> +static struct clk_crm disp_crm = {
> + .max_perf_ol = 10,
> + .regs = {
> + .reg_cfg_rcgr_lut_base = 0xd8,
> + .reg_l_val_lut_base = 0xdc,
> + .vcd_offset = 0x268,
> + .lut_level_offset = 0x28,
Seeing this configuration makes me even more sure. There is no separate
CRM or disp-crm. The CRM resources should be consumed by dispcc.
> + },
> +};
> +
> static const struct pll_vco pongo_elu_vco[] = {
> { 38400000, 38400000, 0 },
> };
> @@ -89,21 +99,22 @@ static struct alpha_pll_config disp_cc_pll0_config = {
> .user_ctl_hi_val = 0x00000002,
> };
>
> +static struct clk_init_data disp_cc_pll0_init = {
> + .name = "disp_cc_pll0",
> + .parent_data = &(const struct clk_parent_data) {
> + .index = DT_BI_TCXO,
> + },
> + .num_parents = 1,
> + .flags = CLK_GET_RATE_NOCACHE,
Why? It wasn't there beforehand.
> + .ops = &clk_alpha_pll_taycan_elu_ops,
> +};
> +
> static struct clk_alpha_pll disp_cc_pll0 = {
> .offset = 0x0,
> .vco_table = taycan_elu_vco,
> .num_vco = ARRAY_SIZE(taycan_elu_vco),
> .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_ELU],
> - .clkr = {
> - .hw.init = &(const struct clk_init_data) {
> - .name = "disp_cc_pll0",
> - .parent_data = &(const struct clk_parent_data) {
> - .index = DT_BI_TCXO,
> - },
> - .num_parents = 1,
> - .ops = &clk_alpha_pll_taycan_elu_ops,
> - },
> - },
> + .clkr.hw.init = &disp_cc_pll0_init,
> };
>
> static struct alpha_pll_config disp_cc_pll1_config = {
> @@ -681,25 +692,25 @@ static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = {
> { }
> };
>
> -static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {
> - .cmd_rcgr = 0x8150,
> - .mnd_width = 0,
> - .hid_width = 5,
> - .parent_map = disp_cc_parent_map_9,
> - .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,
> - .clkr.hw.init = &(const struct clk_init_data) {
> - .name = "disp_cc_mdss_mdp_clk_src",
> - .parent_data = disp_cc_parent_data_9,
> - .num_parents = ARRAY_SIZE(disp_cc_parent_data_9),
> - .flags = CLK_SET_RATE_PARENT,
> - /*
> - * TODO: Downstream does not manage the clock directly, but
> - * places votes via new hardware block called "cesta".
> - * It is not clear whether such approach should be taken instead
> - * of manual control.
> - */
> - .ops = &clk_rcg2_shared_ops,
> +static struct clk_init_data disp_cc_mdss_mdp_clk_src_init = {
> + .name = "disp_cc_mdss_mdp_clk_src",
> + .parent_data = disp_cc_parent_data_9,
> + .num_parents = ARRAY_SIZE(disp_cc_parent_data_9),
> + .flags = CLK_SET_RATE_PARENT,
> + .ops = &clk_rcg2_shared_ops,
> +};
> +
> +static struct clk_rcg2_crm disp_cc_mdss_mdp_clk_src = {
> + .rcg = {
> + .cmd_rcgr = 0x8150,
> + .mnd_width = 0,
> + .hid_width = 5,
> + .parent_map = disp_cc_parent_map_9,
> + .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,
> + .clkr.hw.init = &disp_cc_mdss_mdp_clk_src_init,
> },
> + .crm_vcd = 1,
> + .crm = &disp_crm,
> };
>
> static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = {
> @@ -1562,7 +1573,7 @@ static struct clk_branch disp_cc_mdss_mdp1_clk = {
> .hw.init = &(const struct clk_init_data) {
> .name = "disp_cc_mdss_mdp1_clk",
> .parent_hws = (const struct clk_hw*[]) {
> - &disp_cc_mdss_mdp_clk_src.clkr.hw,
> + &disp_cc_mdss_mdp_clk_src.rcg.clkr.hw,
> },
> .num_parents = 1,
> .flags = CLK_SET_RATE_PARENT,
> @@ -1580,7 +1591,7 @@ static struct clk_branch disp_cc_mdss_mdp_clk = {
> .hw.init = &(const struct clk_init_data) {
> .name = "disp_cc_mdss_mdp_clk",
> .parent_hws = (const struct clk_hw*[]) {
> - &disp_cc_mdss_mdp_clk_src.clkr.hw,
> + &disp_cc_mdss_mdp_clk_src.rcg.clkr.hw,
> },
> .num_parents = 1,
> .flags = CLK_SET_RATE_PARENT,
> @@ -1598,7 +1609,7 @@ static struct clk_branch disp_cc_mdss_mdp_lut1_clk = {
> .hw.init = &(const struct clk_init_data) {
> .name = "disp_cc_mdss_mdp_lut1_clk",
> .parent_hws = (const struct clk_hw*[]) {
> - &disp_cc_mdss_mdp_clk_src.clkr.hw,
> + &disp_cc_mdss_mdp_clk_src.rcg.clkr.hw,
> },
> .num_parents = 1,
> .flags = CLK_SET_RATE_PARENT,
> @@ -1616,7 +1627,7 @@ static struct clk_branch disp_cc_mdss_mdp_lut_clk = {
> .hw.init = &(const struct clk_init_data) {
> .name = "disp_cc_mdss_mdp_lut_clk",
> .parent_hws = (const struct clk_hw*[]) {
> - &disp_cc_mdss_mdp_clk_src.clkr.hw,
> + &disp_cc_mdss_mdp_clk_src.rcg.clkr.hw,
> },
> .num_parents = 1,
> .flags = CLK_SET_RATE_PARENT,
> @@ -1844,7 +1855,7 @@ static struct clk_regmap *disp_cc_sm8750_clocks[] = {
> [DISP_CC_MDSS_ESC1_CLK_SRC] = &disp_cc_mdss_esc1_clk_src.clkr,
> [DISP_CC_MDSS_MDP1_CLK] = &disp_cc_mdss_mdp1_clk.clkr,
> [DISP_CC_MDSS_MDP_CLK] = &disp_cc_mdss_mdp_clk.clkr,
> - [DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.clkr,
> + [DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.rcg.clkr,
> [DISP_CC_MDSS_MDP_LUT1_CLK] = &disp_cc_mdss_mdp_lut1_clk.clkr,
> [DISP_CC_MDSS_MDP_LUT_CLK] = &disp_cc_mdss_mdp_lut_clk.clkr,
> [DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp_cc_mdss_non_gdsc_ahb_clk.clkr,
> @@ -1866,6 +1877,11 @@ static struct clk_regmap *disp_cc_sm8750_clocks[] = {
> [DISP_CC_XO_CLK_SRC] = &disp_cc_xo_clk_src.clkr,
> };
>
> +static const struct crm_clk_data disp_cc_sm8750_crm_clks[] = {
> + CRM_CLK_PLL(disp_cc_pll0),
> + CRM_CLK_RCG_CRMB(disp_cc_mdss_mdp_clk_src),
> +};
> +
> static const struct qcom_reset_map disp_cc_sm8750_resets[] = {
> [DISP_CC_MDSS_CORE_BCR] = { 0x8000 },
> [DISP_CC_MDSS_CORE_INT2_BCR] = { 0xa000 },
> @@ -1885,6 +1901,12 @@ static const struct regmap_config disp_cc_sm8750_regmap_config = {
> .fast_io = true,
> };
>
> +static struct qcom_cc_driver_data disp_cc_sm8750_driver_data = {
> + .crm = &disp_crm,
> + .crm_clks = disp_cc_sm8750_crm_clks,
> + .num_crm_clks = ARRAY_SIZE(disp_cc_sm8750_crm_clks),
> +};
> +
> static const struct qcom_cc_desc disp_cc_sm8750_desc = {
> .config = &disp_cc_sm8750_regmap_config,
> .clks = disp_cc_sm8750_clocks,
> @@ -1893,6 +1915,7 @@ static const struct qcom_cc_desc disp_cc_sm8750_desc = {
> .num_resets = ARRAY_SIZE(disp_cc_sm8750_resets),
> .gdscs = disp_cc_sm8750_gdscs,
> .num_gdscs = ARRAY_SIZE(disp_cc_sm8750_gdscs),
> + .driver_data = &disp_cc_sm8750_driver_data,
> };
>
> static const struct of_device_id disp_cc_sm8750_match_table[] = {
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 11/13] arm64: dts: qcom: sm8750: Add Display CRM device
2026-04-20 16:28 [PATCH 00/13] Add support to control clocks using CESTA Resource manager Jagadeesh Kona
` (9 preceding siblings ...)
2026-04-20 16:29 ` [PATCH 10/13] clk: qcom: dispcc-sm8750: Add support to control MDP clocks using CESTA Jagadeesh Kona
@ 2026-04-20 17:24 ` Jagadeesh Kona
2026-04-20 17:28 ` [PATCH 12/13] arm64: dts: qcom: sm8750: Add disp_crmc node and CRM properties to dispcc Jagadeesh Kona
11 siblings, 0 replies; 24+ messages in thread
From: Jagadeesh Kona @ 2026-04-20 17:24 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones
Cc: Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree, linux-kernel,
linux-clk, Maulik Shah, Taniya Das, Jagadeesh Kona
From: Maulik Shah <maulik.shah@oss.qualcomm.com>
CESTA Resource Manager (CRM) device provides DRVs for global and local
resource voting. Add CRM device to vote for resources needed for display
subsytem.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/sm8750.dtsi | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi
index 18fb52c14acd..5d2c59f37015 100644
--- a/arch/arm64/boot/dts/qcom/sm8750.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi
@@ -3436,6 +3436,22 @@ dispcc: clock-controller@af00000 {
#power-domain-cells = <1>;
};
+ disp_crm: crm@af21000 {
+ compatible = "qcom,sm8750-disp-crm";
+ label = "disp_crm";
+ reg = <0x0 0x0af21000 0x0 0x6000>,
+ <0x0 0x0af29f00 0x0 0x100>;
+ power-domains = <&rpmhpd RPMHPD_MMCX>;
+ interrupts = <GIC_SPI 703 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 708 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 714 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 68 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 96 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 249 IRQ_TYPE_EDGE_RISING>;
+ qcom,sw-drv-ids = <0 1 2 3 4 5>;
+ };
+
+
pdc: interrupt-controller@b220000 {
compatible = "qcom,sm8750-pdc", "qcom,pdc";
reg = <0x0 0x0b220000 0x0 0x10000>, <0x0 0x164400f0 0x0 0x64>;
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH 12/13] arm64: dts: qcom: sm8750: Add disp_crmc node and CRM properties to dispcc
2026-04-20 16:28 [PATCH 00/13] Add support to control clocks using CESTA Resource manager Jagadeesh Kona
` (10 preceding siblings ...)
2026-04-20 17:24 ` [PATCH 11/13] arm64: dts: qcom: sm8750: Add Display CRM device Jagadeesh Kona
@ 2026-04-20 17:28 ` Jagadeesh Kona
2026-04-20 17:28 ` [PATCH 13/13] arm64: defconfig: Enable Qualcomm CESTA Resource Manager Jagadeesh Kona
11 siblings, 1 reply; 24+ messages in thread
From: Jagadeesh Kona @ 2026-04-20 17:28 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones
Cc: Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree, linux-kernel,
linux-clk, Maulik Shah, Taniya Das, Jagadeesh Kona
On SM8750, some display MDP clocks are controlled by display CESTA
hardware. Add the required CRM properties to the dispcc node so it can
communicate with CESTA through display CRM node and control these clocks
using CESTA.
Also add the display CRMC syscon node, which is used to read the clock
frequency lookup tables populated by CESTA for CRM-controlled clocks.
Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/sm8750.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sm8750.dtsi b/arch/arm64/boot/dts/qcom/sm8750.dtsi
index 5d2c59f37015..0db586b02131 100644
--- a/arch/arm64/boot/dts/qcom/sm8750.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8750.dtsi
@@ -3431,6 +3431,9 @@ dispcc: clock-controller@af00000 {
power-domains = <&rpmhpd RPMHPD_MMCX>;
required-opps = <&rpmhpd_opp_low_svs>;
+ qcom,crm = <&disp_crm>;
+ qcom,crmc-regmap = <&disp_crmc>;
+
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
@@ -3451,6 +3454,10 @@ disp_crm: crm@af21000 {
qcom,sw-drv-ids = <0 1 2 3 4 5>;
};
+ disp_crmc: syscon@af27800 {
+ compatible = "qcom,crmc-syscon", "syscon";
+ reg = <0x0 0x0af27800 0x0 0x2000>;
+ };
pdc: interrupt-controller@b220000 {
compatible = "qcom,sm8750-pdc", "qcom,pdc";
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH 13/13] arm64: defconfig: Enable Qualcomm CESTA Resource Manager
2026-04-20 17:28 ` [PATCH 12/13] arm64: dts: qcom: sm8750: Add disp_crmc node and CRM properties to dispcc Jagadeesh Kona
@ 2026-04-20 17:28 ` Jagadeesh Kona
2026-04-20 17:47 ` Dmitry Baryshkov
0 siblings, 1 reply; 24+ messages in thread
From: Jagadeesh Kona @ 2026-04-20 17:28 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones
Cc: Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree, linux-kernel,
linux-clk, Maulik Shah, Taniya Das, Jagadeesh Kona
From: Maulik Shah <maulik.shah@oss.qualcomm.com>
CESTA Resource manager/CRM is used for local and/or global
resource voting on Qualcomm SoCs. Enable as built-in.
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
---
arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index dd1ac01ee29b..94d226693004 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1658,6 +1658,7 @@ CONFIG_MTK_PMIC_WRAP=y
CONFIG_MTK_SVS=m
CONFIG_QCOM_AOSS_QMP=y
CONFIG_QCOM_COMMAND_DB=y
+CONFIG_QCOM_CRM=y
CONFIG_QCOM_GENI_SE=y
CONFIG_QCOM_LLCC=m
CONFIG_QCOM_OCMEM=m
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 13/13] arm64: defconfig: Enable Qualcomm CESTA Resource Manager
2026-04-20 17:28 ` [PATCH 13/13] arm64: defconfig: Enable Qualcomm CESTA Resource Manager Jagadeesh Kona
@ 2026-04-20 17:47 ` Dmitry Baryshkov
0 siblings, 0 replies; 24+ messages in thread
From: Dmitry Baryshkov @ 2026-04-20 17:47 UTC (permalink / raw)
To: Jagadeesh Kona
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Michael Turquette, Stephen Boyd, Neil Armstrong,
Lee Jones, Ajit Pandey, Imran Shaik, linux-arm-msm, devicetree,
linux-kernel, linux-clk, Maulik Shah, Taniya Das
On Mon, Apr 20, 2026 at 10:58:03PM +0530, Jagadeesh Kona wrote:
> From: Maulik Shah <maulik.shah@oss.qualcomm.com>
>
> CESTA Resource manager/CRM is used for local and/or global
> resource voting on Qualcomm SoCs. Enable as built-in.
Which SoCs? Which devices is it going to be used for? Why is it a
built-in rather than a module?
>
> Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
> Signed-off-by: Jagadeesh Kona <jagadeesh.kona@oss.qualcomm.com>
> ---
> arch/arm64/configs/defconfig | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index dd1ac01ee29b..94d226693004 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -1658,6 +1658,7 @@ CONFIG_MTK_PMIC_WRAP=y
> CONFIG_MTK_SVS=m
> CONFIG_QCOM_AOSS_QMP=y
> CONFIG_QCOM_COMMAND_DB=y
> +CONFIG_QCOM_CRM=y
> CONFIG_QCOM_GENI_SE=y
> CONFIG_QCOM_LLCC=m
> CONFIG_QCOM_OCMEM=m
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 24+ messages in thread