]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
Merge branches 'clk-tegra', 'clk-imx', 'clk-sifive', 'clk-mediatek' and 'clk-summary...
authorStephen Boyd <sboyd@kernel.org>
Mon, 21 Dec 2020 01:17:37 +0000 (17:17 -0800)
committerStephen Boyd <sboyd@kernel.org>
Mon, 21 Dec 2020 01:17:37 +0000 (17:17 -0800)
 - Support for SiFive FU740 PRCI
 - Add hardware enable information to clk_summary debugfs

* clk-tegra:
  clk: tegra: Fix duplicated SE clock entry
  clk: tegra: bpmp: Clamp clock rates on requests
  clk: tegra: Do not return 0 on failure

* clk-imx: (24 commits)
  clk: imx: scu: remove the calling of device_is_bound
  clk: imx: scu: Make pd_np with static keyword
  clk: imx8mq: drop of_match_ptr from of_device_id table
  clk: imx8mp: drop of_match_ptr from of_device_id table
  clk: imx8mn: drop of_match_ptr from of_device_id table
  clk: imx8mm: drop of_match_ptr from of_device_id table
  clk: imx: gate2: Remove unused variable ret
  clk: imx: gate2: Add locking in is_enabled op
  clk: imx: gate2: Add cgr_mask for more flexible number of control bits
  clk: imx: gate2: Check if clock is enabled against cgr_val
  clk: imx: gate2: Keep the register writing in on place
  clk: imx: gate2: Remove the IMX_CLK_GATE2_SINGLE_BIT special case
  clk: imx: scu: fix build break when compiled as modules
  clk: imx: remove redundant assignment to pointer np
  clk: imx: remove unneeded semicolon
  clk: imx: lpcg: add suspend/resume support
  clk: imx: clk-imx8qxp-lpcg: add runtime pm support
  clk: imx: lpcg: allow lpcg clk to take device pointer
  clk: imx: imx8qxp-lpcg: add parsing clocks from device tree
  clk: imx: scu: add suspend/resume support
  ...

* clk-sifive:
  clk: sifive: Add clock enable and disable ops
  clk: sifive: Fix the wrong bit field shift
  clk: sifive: Add a driver for the SiFive FU740 PRCI IP block
  clk: sifive: Use common name for prci configuration
  clk: sifive: Extract prci core to common base
  dt-bindings: fu740: prci: add YAML documentation for the FU740 PRCI

* clk-mediatek:
  clk: mediatek: Make mtk_clk_register_mux() a static function

* clk-summary:
  clk: Add hardware-enable column to clk summary

96 files changed:
Documentation/devicetree/bindings/clock/fsl,flexspi-clock.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/clock/qcom,aoncc-sm8250.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/clock/qcom,audiocc-sm8250.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml
Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt [deleted file]
Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/clock/sifive/fu740-prci.yaml [new file with mode: 0644]
MAINTAINERS
arch/riscv/Kconfig.socs
arch/sh/boards/of-generic.c
arch/xtensa/kernel/time.c
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/clk-composite.c
drivers/clk/clk-divider.c
drivers/clk/clk-fsl-flexspi.c [new file with mode: 0644]
drivers/clk/clk-fsl-sai.c
drivers/clk/clk-pwm.c
drivers/clk/clk-qoriq.c
drivers/clk/clk-scpi.c
drivers/clk/clk.c
drivers/clk/imx/clk-gate2.c
drivers/clk/imx/clk-imx8mm.c
drivers/clk/imx/clk-imx8mn.c
drivers/clk/imx/clk-imx8mp.c
drivers/clk/imx/clk-imx8mq.c
drivers/clk/imx/clk-imx8qxp-lpcg.c
drivers/clk/imx/clk-imx8qxp.c
drivers/clk/imx/clk-lpcg-scu.c
drivers/clk/imx/clk-pll14xx.c
drivers/clk/imx/clk-scu.c
drivers/clk/imx/clk-scu.h
drivers/clk/imx/clk.h
drivers/clk/meson/Kconfig
drivers/clk/meson/axg-aoclk.c
drivers/clk/meson/axg.c
drivers/clk/meson/axg.h
drivers/clk/meson/g12a-aoclk.c
drivers/clk/meson/g12a.c
drivers/clk/meson/g12a.h
drivers/clk/meson/gxbb-aoclk.c
drivers/clk/meson/gxbb.c
drivers/clk/meson/meson-aoclk.c
drivers/clk/meson/meson-eeclk.c
drivers/clk/qcom/Kconfig
drivers/clk/qcom/Makefile
drivers/clk/qcom/camcc-sc7180.c [new file with mode: 0644]
drivers/clk/qcom/clk-alpha-pll.c
drivers/clk/qcom/clk-alpha-pll.h
drivers/clk/qcom/clk-rpmh.c
drivers/clk/qcom/dispcc-sm8250.c
drivers/clk/qcom/gcc-sc7180.c
drivers/clk/qcom/gcc-sdx55.c [new file with mode: 0644]
drivers/clk/qcom/lpass-gfm-sm8250.c [new file with mode: 0644]
drivers/clk/qcom/lpasscorecc-sc7180.c
drivers/clk/renesas/clk-sh73a0.c
drivers/clk/renesas/r8a774a1-cpg-mssr.c
drivers/clk/renesas/r8a774b1-cpg-mssr.c
drivers/clk/renesas/r8a774c0-cpg-mssr.c
drivers/clk/renesas/r8a779a0-cpg-mssr.c
drivers/clk/renesas/rcar-gen3-cpg.c
drivers/clk/renesas/rcar-gen3-cpg.h
drivers/clk/renesas/rcar-usb2-clock-sel.c
drivers/clk/renesas/renesas-cpg-mssr.c
drivers/clk/rockchip/Kconfig
drivers/clk/rockchip/clk-rk3188.c
drivers/clk/rockchip/clk.c
drivers/clk/samsung/Kconfig
drivers/clk/samsung/Makefile
drivers/clk/samsung/clk-pll.c
drivers/clk/sifive/Kconfig
drivers/clk/sifive/Makefile
drivers/clk/sifive/fu540-prci.c
drivers/clk/sifive/fu540-prci.h [new file with mode: 0644]
drivers/clk/sifive/fu740-prci.c [new file with mode: 0644]
drivers/clk/sifive/fu740-prci.h [new file with mode: 0644]
drivers/clk/sifive/sifive-prci.c [new file with mode: 0644]
drivers/clk/sifive/sifive-prci.h [new file with mode: 0644]
drivers/clk/tegra/clk-bpmp.c
drivers/clk/tegra/clk-dfll.c
drivers/clk/tegra/clk-id.h
drivers/clk/tegra/clk-tegra-periph.c
include/dt-bindings/clock/axg-clkc.h
include/dt-bindings/clock/fsl,qoriq-clockgen.h [new file with mode: 0644]
include/dt-bindings/clock/g12a-clkc.h
include/dt-bindings/clock/qcom,camcc-sc7180.h [new file with mode: 0644]
include/dt-bindings/clock/qcom,gcc-sdx55.h [new file with mode: 0644]
include/dt-bindings/clock/qcom,rpmh.h
include/dt-bindings/clock/qcom,sm8250-lpass-aoncc.h [new file with mode: 0644]
include/dt-bindings/clock/qcom,sm8250-lpass-audiocc.h [new file with mode: 0644]
include/dt-bindings/clock/sifive-fu740-prci.h [new file with mode: 0644]
include/linux/clk-provider.h
include/linux/clk.h
include/linux/clk/samsung.h

diff --git a/Documentation/devicetree/bindings/clock/fsl,flexspi-clock.yaml b/Documentation/devicetree/bindings/clock/fsl,flexspi-clock.yaml
new file mode 100644 (file)
index 0000000..1fa390e
--- /dev/null
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/fsl,flexspi-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale FlexSPI clock driver for Layerscape SoCs
+
+maintainers:
+  - Michael Walle <michael@walle.cc>
+
+description:
+  The Freescale Layerscape SoCs have a special FlexSPI clock which is
+  derived from the platform PLL.
+
+properties:
+  compatible:
+    enum:
+      - fsl,ls1028a-flexspi-clk
+      - fsl,lx2160a-flexspi-clk
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  '#clock-cells':
+    const: 0
+
+  clock-output-names:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    dcfg {
+        #address-cells = <1>;
+        #size-cells = <1>;
+
+        fspi_clk: clock-controller@900 {
+            compatible = "fsl,ls1028a-flexspi-clk";
+            reg = <0x900 0x4>;
+            #clock-cells = <0>;
+            clocks = <&parentclk>;
+            clock-output-names = "fspi_clk";
+        };
+    };
diff --git a/Documentation/devicetree/bindings/clock/qcom,aoncc-sm8250.yaml b/Documentation/devicetree/bindings/clock/qcom,aoncc-sm8250.yaml
new file mode 100644 (file)
index 0000000..c40a74b
--- /dev/null
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,aoncc-sm8250.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Clock bindings for LPASS Always ON Clock Controller on SM8250 SoCs
+
+maintainers:
+  - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+description: |
+  The clock consumer should specify the desired clock by having the clock
+  ID in its "clocks" phandle cell.
+  See include/dt-bindings/clock/qcom,sm8250-lpass-aoncc.h for the full list
+  of Audio Clock controller clock IDs.
+
+properties:
+  compatible:
+    const: qcom,sm8250-lpass-aon
+
+  reg:
+    maxItems: 1
+
+  '#clock-cells':
+    const: 1
+
+  clocks:
+    items:
+      - description: LPASS Core voting clock
+      - description: Glitch Free Mux register clock
+
+  clock-names:
+    items:
+      - const: core
+      - const: bus
+
+required:
+  - compatible
+  - reg
+  - '#clock-cells'
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,sm8250-lpass-aoncc.h>
+    #include <dt-bindings/sound/qcom,q6afe.h>
+    clock-controller@3800000 {
+      #clock-cells = <1>;
+      compatible = "qcom,sm8250-lpass-aon";
+      reg = <0x03380000 0x40000>;
+      clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+               <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+      clock-names = "core", "bus";
+    };
diff --git a/Documentation/devicetree/bindings/clock/qcom,audiocc-sm8250.yaml b/Documentation/devicetree/bindings/clock/qcom,audiocc-sm8250.yaml
new file mode 100644 (file)
index 0000000..915d762
--- /dev/null
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,audiocc-sm8250.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Clock bindings for LPASS Audio Clock Controller on SM8250 SoCs
+
+maintainers:
+  - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+description: |
+  The clock consumer should specify the desired clock by having the clock
+  ID in its "clocks" phandle cell.
+  See include/dt-bindings/clock/qcom,sm8250-lpass-audiocc.h for the full list
+  of Audio Clock controller clock IDs.
+
+properties:
+  compatible:
+    const: qcom,sm8250-lpass-audiocc
+
+  reg:
+    maxItems: 1
+
+  '#clock-cells':
+    const: 1
+
+  clocks:
+    items:
+      - description: LPASS Core voting clock
+      - description: Glitch Free Mux register clock
+
+  clock-names:
+    items:
+      - const: core
+      - const: bus
+
+required:
+  - compatible
+  - reg
+  - '#clock-cells'
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,sm8250-lpass-audiocc.h>
+    #include <dt-bindings/sound/qcom,q6afe.h>
+    clock-controller@3300000 {
+      #clock-cells = <1>;
+      compatible = "qcom,sm8250-lpass-audiocc";
+      reg = <0x03300000 0x30000>;
+      clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+               <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+      clock-names = "core", "bus";
+    };
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml
new file mode 100644 (file)
index 0000000..1121b39
--- /dev/null
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,gcc-sdx55.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Global Clock & Reset Controller Binding for SDX55
+
+maintainers:
+  - Vinod Koul <vkoul@kernel.org>
+  - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+description: |
+  Qualcomm global clock control module which supports the clocks, resets and
+  power domains on SDX55
+
+  See also:
+  - dt-bindings/clock/qcom,gcc-sdx55.h
+
+properties:
+  compatible:
+    const: qcom,gcc-sdx55
+
+  clocks:
+    items:
+      - description: Board XO source
+      - description: Sleep clock source
+      - description: PLL test clock source (Optional clock)
+    minItems: 2
+    maxItems: 3
+
+  clock-names:
+    items:
+      - const: bi_tcxo
+      - const: sleep_clk
+      - const: core_bi_pll_test_se # Optional clock
+    minItems: 2
+    maxItems: 3
+
+  '#clock-cells':
+    const: 1
+
+  '#reset-cells':
+    const: 1
+
+  '#power-domain-cells':
+    const: 1
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - clocks
+  - clock-names
+  - reg
+  - '#clock-cells'
+  - '#reset-cells'
+  - '#power-domain-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,rpmh.h>
+    clock-controller@100000 {
+      compatible = "qcom,gcc-sdx55";
+      reg = <0x00100000 0x1f0000>;
+      clocks = <&rpmhcc RPMH_CXO_CLK>,
+               <&sleep_clk>, <&pll_test_clk>;
+      clock-names = "bi_tcxo", "sleep_clk", "core_bi_pll_test_se";
+      #clock-cells = <1>;
+      #reset-cells = <1>;
+      #power-domain-cells = <1>;
+    };
+
+...
index a46a3a799a708fa55182d606900286c20c3209b9..12c9cbc0ebf92979ffb0793e17c0e827970cbf08 100644 (file)
@@ -19,8 +19,10 @@ properties:
     enum:
       - qcom,sc7180-rpmh-clk
       - qcom,sdm845-rpmh-clk
+      - qcom,sdx55-rpmh-clk
       - qcom,sm8150-rpmh-clk
       - qcom,sm8250-rpmh-clk
+      - qcom,sm8350-rpmh-clk
 
   clocks:
     maxItems: 1
diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml
new file mode 100644 (file)
index 0000000..f49027e
--- /dev/null
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,sc7180-camcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Camera Clock & Reset Controller Binding for SC7180
+
+maintainers:
+  - Taniya Das <tdas@codeaurora.org>
+
+description: |
+  Qualcomm camera clock control module which supports the clocks, resets and
+  power domains on SC7180.
+
+  See also:
+  - dt-bindings/clock/qcom,camcc-sc7180.h
+
+properties:
+  compatible:
+    const: qcom,sc7180-camcc
+
+  clocks:
+    items:
+      - description: Board XO source
+      - description: Camera_ahb clock from GCC
+      - description: Camera XO clock from GCC
+
+  clock-names:
+    items:
+      - const: bi_tcxo
+      - const: iface
+      - const: xo
+
+  '#clock-cells':
+    const: 1
+
+  '#reset-cells':
+    const: 1
+
+  '#power-domain-cells':
+    const: 1
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - '#clock-cells'
+  - '#reset-cells'
+  - '#power-domain-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,gcc-sc7180.h>
+    #include <dt-bindings/clock/qcom,rpmh.h>
+    clock-controller@ad00000 {
+      compatible = "qcom,sc7180-camcc";
+      reg = <0x0ad00000 0x10000>;
+      clocks = <&rpmhcc RPMH_CXO_CLK>,
+               <&gcc GCC_CAMERA_AHB_CLK>,
+               <&gcc GCC_CAMERA_XO_CLK>;
+      clock-names = "bi_tcxo", "iface", "xo";
+      #clock-cells = <1>;
+      #reset-cells = <1>;
+      #power-domain-cells = <1>;
+    };
+...
diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt
deleted file mode 100644 (file)
index da92f57..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-* Renesas R-Car USB 2.0 clock selector
-
-This file provides information on what the device node for the R-Car USB 2.0
-clock selector.
-
-If you connect an external clock to the USB_EXTAL pin only, you should set
-the clock rate to "usb_extal" node only.
-If you connect an oscillator to both the USB_XTAL and USB_EXTAL, this module
-is not needed because this is default setting. (Of course, you can set the
-clock rates to both "usb_extal" and "usb_xtal" nodes.
-
-Case 1: An external clock connects to R-Car SoC
-       +----------+   +--- R-Car ---------------------+
-       |External  |---|USB_EXTAL ---> all usb channels|
-       |clock     |   |USB_XTAL                       |
-       +----------+   +-------------------------------+
-In this case, we need this driver with "usb_extal" clock.
-
-Case 2: An oscillator connects to R-Car SoC
-       +----------+   +--- R-Car ---------------------+
-       |Oscillator|---|USB_EXTAL -+-> all usb channels|
-       |          |---|USB_XTAL --+                   |
-       +----------+   +-------------------------------+
-In this case, we don't need this selector.
-
-Required properties:
-- compatible: "renesas,r8a7795-rcar-usb2-clock-sel" if the device is a part of
-             an R8A7795 SoC.
-             "renesas,r8a7796-rcar-usb2-clock-sel" if the device if a part of
-             an R8A77960 SoC.
-             "renesas,r8a77961-rcar-usb2-clock-sel" if the device if a part of
-             an R8A77961 SoC.
-             "renesas,rcar-gen3-usb2-clock-sel" for a generic R-Car Gen3
-             compatible device.
-
-             When compatible with the generic version, nodes must list the
-             SoC-specific version corresponding to the platform first
-             followed by the generic version.
-
-- reg: offset and length of the USB 2.0 clock selector register block.
-- clocks: A list of phandles and specifier pairs.
-- clock-names: Name of the clocks.
- - The functional clock of USB 2.0 host side must be "ehci_ohci"
- - The functional clock of HS-USB side must be "hs-usb-if"
- - The USB_EXTAL clock pin must be "usb_extal"
- - The USB_XTAL clock pin must be "usb_xtal"
-- #clock-cells: Must be 0
-- power-domains: A phandle and symbolic PM domain specifier.
-                 See power/renesas,rcar-sysc.yaml.
-- resets: A list of phandles and specifier pairs.
-- reset-names: Name of the resets.
- - The reset of USB 2.0 host side must be "ehci_ohci"
- - The reset of HS-USB side must be "hs-usb-if"
-
-Example (R-Car H3):
-
-       usb2_clksel: clock-controller@e6590630 {
-               compatible = "renesas,r8a7795-rcar-usb2-clock-sel",
-                            "renesas,rcar-gen3-usb2-clock-sel";
-               reg = <0 0xe6590630 0 0x02>;
-               clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>,
-                        <&usb_extal>, <&usb_xtal>;
-               clock-names = "ehci_ohci", "hs-usb-if", "usb_extal", "usb_xtal";
-               #clock-cells = <0>;
-               power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
-               resets = <&cpg 703>, <&cpg 704>;
-               reset-names = "ehci_ohci", "hs-usb-if";
-       };
diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml
new file mode 100644 (file)
index 0000000..5be1229
--- /dev/null
@@ -0,0 +1,100 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/clock/renesas,rcar-usb2-clock-sel.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Renesas R-Car USB 2.0 clock selector
+
+maintainers:
+  - Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+
+description: |
+  If you connect an external clock to the USB_EXTAL pin only, you should set
+  the clock rate to "usb_extal" node only.
+  If you connect an oscillator to both the USB_XTAL and USB_EXTAL, this module
+  is not needed because this is default setting. (Of course, you can set the
+  clock rates to both "usb_extal" and "usb_xtal" nodes.
+
+  Case 1: An external clock connects to R-Car SoC
+    +----------+   +--- R-Car ---------------------+
+    |External  |---|USB_EXTAL ---> all usb channels|
+    |clock     |   |USB_XTAL                       |
+    +----------+   +-------------------------------+
+
+  In this case, we need this driver with "usb_extal" clock.
+
+  Case 2: An oscillator connects to R-Car SoC
+    +----------+   +--- R-Car ---------------------+
+    |Oscillator|---|USB_EXTAL -+-> all usb channels|
+    |          |---|USB_XTAL --+                   |
+    +----------+   +-------------------------------+
+  In this case, we don't need this selector.
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - renesas,r8a7795-rcar-usb2-clock-sel  # R-Car H3
+          - renesas,r8a7796-rcar-usb2-clock-sel  # R-Car M3-W
+          - renesas,r8a77961-rcar-usb2-clock-sel # R-Car M3-W+
+      - const: renesas,rcar-gen3-usb2-clock-sel
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    minItems: 4
+    maxItems: 4
+
+  clock-names:
+    items:
+      - const: ehci_ohci
+      - const: hs-usb-if
+      - const: usb_extal
+      - const: usb_xtal
+
+  '#clock-cells':
+    const: 0
+
+  power-domains:
+    maxItems: 1
+
+  resets:
+    minItems: 2
+    maxItems: 2
+
+  reset-names:
+    items:
+      - const: ehci_ohci
+      - const: hs-usb-if
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - '#clock-cells'
+  - power-domains
+  - resets
+  - reset-names
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/r8a7795-cpg-mssr.h>
+    #include <dt-bindings/power/r8a7795-sysc.h>
+
+    usb2_clksel: clock-controller@e6590630 {
+        compatible = "renesas,r8a7795-rcar-usb2-clock-sel",
+                     "renesas,rcar-gen3-usb2-clock-sel";
+        reg = <0xe6590630 0x02>;
+        clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>,
+                 <&usb_extal>, <&usb_xtal>;
+        clock-names = "ehci_ohci", "hs-usb-if", "usb_extal", "usb_xtal";
+        #clock-cells = <0>;
+        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+        resets = <&cpg 703>, <&cpg 704>;
+        reset-names = "ehci_ohci", "hs-usb-if";
+    };
diff --git a/Documentation/devicetree/bindings/clock/sifive/fu740-prci.yaml b/Documentation/devicetree/bindings/clock/sifive/fu740-prci.yaml
new file mode 100644 (file)
index 0000000..e17143c
--- /dev/null
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2020 SiFive, Inc.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/sifive/fu740-prci.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: SiFive FU740 Power Reset Clock Interrupt Controller (PRCI)
+
+maintainers:
+  - Zong Li <zong.li@sifive.com>
+  - Paul Walmsley  <paul.walmsley@sifive.com>
+
+description:
+  On the FU740 family of SoCs, most system-wide clock and reset integration
+  is via the PRCI IP block.
+  The clock consumer should specify the desired clock via the clock ID
+  macros defined in include/dt-bindings/clock/sifive-fu740-prci.h.
+  These macros begin with PRCI_CLK_.
+
+  The hfclk and rtcclk nodes are required, and represent physical
+  crystals or resonators located on the PCB.  These nodes should be present
+  underneath /, rather than /soc.
+
+properties:
+  compatible:
+    const: sifive,fu740-c000-prci
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: high frequency clock.
+      - description: RTL clock.
+
+  clock-names:
+    items:
+      - const: hfclk
+      - const: rtcclk
+
+  "#clock-cells":
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    prci: clock-controller@10000000 {
+      compatible = "sifive,fu740-c000-prci";
+      reg = <0x10000000 0x1000>;
+      clocks = <&hfclk>, <&rtcclk>;
+      #clock-cells = <1>;
+    };
index e73636b75f29de8644c5c260b60f029e36df635a..595e1023b3987b92713c2862b0f8330a7055d76b 100644 (file)
@@ -14888,7 +14888,7 @@ RENESAS CLOCK DRIVERS
 M:     Geert Uytterhoeven <geert+renesas@glider.be>
 L:     linux-renesas-soc@vger.kernel.org
 S:     Supported
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git clk-renesas
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git renesas-clk
 F:     Documentation/devicetree/bindings/clock/renesas,*
 F:     drivers/clk/renesas/
 
index 8a55f6156661d450c81a81e9ac22895989e19531..3284d5c291be541f0cc7d7316b9938b66e4c4ec3 100644 (file)
@@ -5,7 +5,7 @@ config SOC_SIFIVE
        select SERIAL_SIFIVE if TTY
        select SERIAL_SIFIVE_CONSOLE if TTY
        select CLK_SIFIVE
-       select CLK_SIFIVE_FU540_PRCI
+       select CLK_SIFIVE_PRCI
        select SIFIVE_PLIC
        help
          This enables support for SiFive SoC platform hardware.
index bffbe69b2236a1eefde40598fc3b896a02e52ee3..921d76fc33583f78df736dca730018d83986a916 100644 (file)
@@ -6,10 +6,10 @@
  */
 
 #include <linux/of.h>
+#include <linux/of_clk.h>
 #include <linux/of_fdt.h>
 #include <linux/clocksource.h>
 #include <linux/irqchip.h>
-#include <linux/clk-provider.h>
 #include <asm/machvec.h>
 #include <asm/rtc.h>
 
index 77971fe4cc95ba2b8bd55667b892392b1aa7bdaf..e8ceb1528608188cb1f335b187e2279dde841b3c 100644 (file)
@@ -13,7 +13,7 @@
  */
 
 #include <linux/clk.h>
-#include <linux/clk-provider.h>
+#include <linux/of_clk.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/time.h>
index c715d4681a0b81885def111498c791d3490207fe..85856cff506c01660841d71840225f37fc21df91 100644 (file)
@@ -188,6 +188,14 @@ config COMMON_CLK_CS2000_CP
        help
          If you say yes here you get support for the CS2000 clock multiplier.
 
+config COMMON_CLK_FSL_FLEXSPI
+       tristate "Clock driver for FlexSPI on Layerscape SoCs"
+       depends on ARCH_LAYERSCAPE || COMPILE_TEST
+       default ARCH_LAYERSCAPE && SPI_NXP_FLEXSPI
+       help
+         On Layerscape SoCs there is a special clock for the FlexSPI
+         interface.
+
 config COMMON_CLK_FSL_SAI
        bool "Clock driver for BCLK of Freescale SAI cores"
        depends on ARCH_LAYERSCAPE || COMPILE_TEST
@@ -246,7 +254,8 @@ config COMMON_CLK_AXI_CLKGEN
 
 config CLK_QORIQ
        bool "Clock driver for Freescale QorIQ platforms"
-       depends on (PPC_E500MC || ARM || ARM64 || COMPILE_TEST) && OF
+       depends on OF
+       depends on PPC_E500MC || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST
        help
          This adds the clock driver support for Freescale QorIQ platforms
          using common clock framework.
index da8fcf147eb132ce2a15f5f748912775d893ac5a..dbdc590e7de3aca81ef39256b690b11e26dfc760 100644 (file)
@@ -30,6 +30,7 @@ obj-$(CONFIG_COMMON_CLK_CS2000_CP)    += clk-cs2000-cp.o
 obj-$(CONFIG_ARCH_EFM32)               += clk-efm32gg.o
 obj-$(CONFIG_ARCH_SPARX5)              += clk-sparx5.o
 obj-$(CONFIG_COMMON_CLK_FIXED_MMIO)    += clk-fixed-mmio.o
+obj-$(CONFIG_COMMON_CLK_FSL_FLEXSPI)   += clk-fsl-flexspi.o
 obj-$(CONFIG_COMMON_CLK_FSL_SAI)       += clk-fsl-sai.o
 obj-$(CONFIG_COMMON_CLK_GEMINI)                += clk-gemini.o
 obj-$(CONFIG_COMMON_CLK_ASPEED)                += clk-aspeed.o
index 2ddb54f7d3abc610fac0da49c77b9ef12734f36c..0506046a5f4b9fc2dcfb6bd9ee88a8ac96d2e9aa 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/device.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 
@@ -405,3 +406,52 @@ void clk_hw_unregister_composite(struct clk_hw *hw)
        kfree(composite);
 }
 EXPORT_SYMBOL_GPL(clk_hw_unregister_composite);
+
+static void devm_clk_hw_release_composite(struct device *dev, void *res)
+{
+       clk_hw_unregister_composite(*(struct clk_hw **)res);
+}
+
+static struct clk_hw *__devm_clk_hw_register_composite(struct device *dev,
+                       const char *name, const char * const *parent_names,
+                       const struct clk_parent_data *pdata, int num_parents,
+                       struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
+                       struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
+                       struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+                       unsigned long flags)
+{
+       struct clk_hw **ptr, *hw;
+
+       ptr = devres_alloc(devm_clk_hw_release_composite, sizeof(*ptr),
+                          GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       hw = __clk_hw_register_composite(dev, name, parent_names, pdata,
+                                        num_parents, mux_hw, mux_ops, rate_hw,
+                                        rate_ops, gate_hw, gate_ops, flags);
+
+       if (!IS_ERR(hw)) {
+               *ptr = hw;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return hw;
+}
+
+struct clk_hw *devm_clk_hw_register_composite_pdata(struct device *dev,
+                       const char *name,
+                       const struct clk_parent_data *parent_data,
+                       int num_parents,
+                       struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
+                       struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
+                       struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+                       unsigned long flags)
+{
+       return __devm_clk_hw_register_composite(dev, name, NULL, parent_data,
+                                               num_parents, mux_hw, mux_ops,
+                                               rate_hw, rate_ops, gate_hw,
+                                               gate_ops, flags);
+}
index 8de12cb0c43d895fc51608edb50a05ab52a5d5bf..c499799693cccc8d45d6a821a27a7f2720f3e556 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/device.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/io.h>
@@ -578,3 +579,36 @@ void clk_hw_unregister_divider(struct clk_hw *hw)
        kfree(div);
 }
 EXPORT_SYMBOL_GPL(clk_hw_unregister_divider);
+
+static void devm_clk_hw_release_divider(struct device *dev, void *res)
+{
+       clk_hw_unregister_divider(*(struct clk_hw **)res);
+}
+
+struct clk_hw *__devm_clk_hw_register_divider(struct device *dev,
+               struct device_node *np, const char *name,
+               const char *parent_name, const struct clk_hw *parent_hw,
+               const struct clk_parent_data *parent_data, unsigned long flags,
+               void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
+               const struct clk_div_table *table, spinlock_t *lock)
+{
+       struct clk_hw **ptr, *hw;
+
+       ptr = devres_alloc(devm_clk_hw_release_divider, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       hw = __clk_hw_register_divider(dev, np, name, parent_name, parent_hw,
+                                      parent_data, flags, reg, shift, width,
+                                      clk_divider_flags, table, lock);
+
+       if (!IS_ERR(hw)) {
+               *ptr = hw;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return hw;
+}
+EXPORT_SYMBOL_GPL(__devm_clk_hw_register_divider);
diff --git a/drivers/clk/clk-fsl-flexspi.c b/drivers/clk/clk-fsl-flexspi.c
new file mode 100644 (file)
index 0000000..8432d68
--- /dev/null
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Layerscape FlexSPI clock driver
+ *
+ * Copyright 2020 Michael Walle <michael@walle.cc>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static const struct clk_div_table ls1028a_flexspi_divs[] = {
+       { .val = 0, .div = 1, },
+       { .val = 1, .div = 2, },
+       { .val = 2, .div = 3, },
+       { .val = 3, .div = 4, },
+       { .val = 4, .div = 5, },
+       { .val = 5, .div = 6, },
+       { .val = 6, .div = 7, },
+       { .val = 7, .div = 8, },
+       { .val = 11, .div = 12, },
+       { .val = 15, .div = 16, },
+       { .val = 16, .div = 20, },
+       { .val = 17, .div = 24, },
+       { .val = 18, .div = 28, },
+       { .val = 19, .div = 32, },
+       { .val = 20, .div = 80, },
+       {}
+};
+
+static const struct clk_div_table lx2160a_flexspi_divs[] = {
+       { .val = 1, .div = 2, },
+       { .val = 3, .div = 4, },
+       { .val = 5, .div = 6, },
+       { .val = 7, .div = 8, },
+       { .val = 11, .div = 12, },
+       { .val = 15, .div = 16, },
+       { .val = 16, .div = 20, },
+       { .val = 17, .div = 24, },
+       { .val = 18, .div = 28, },
+       { .val = 19, .div = 32, },
+       { .val = 20, .div = 80, },
+       {}
+};
+
+static int fsl_flexspi_clk_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       const char *clk_name = np->name;
+       const char *clk_parent;
+       struct resource *res;
+       void __iomem *reg;
+       struct clk_hw *hw;
+       const struct clk_div_table *divs;
+
+       divs = device_get_match_data(dev);
+       if (!divs)
+               return -ENOENT;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENOENT;
+
+       /*
+        * Can't use devm_ioremap_resource() or devm_of_iomap() because the
+        * resource might already be taken by the parent device.
+        */
+       reg = devm_ioremap(dev, res->start, resource_size(res));
+       if (!reg)
+               return -ENOMEM;
+
+       clk_parent = of_clk_get_parent_name(np, 0);
+       if (!clk_parent)
+               return -EINVAL;
+
+       of_property_read_string(np, "clock-output-names", &clk_name);
+
+       hw = devm_clk_hw_register_divider_table(dev, clk_name, clk_parent, 0,
+                                               reg, 0, 5, 0, divs, NULL);
+       if (IS_ERR(hw))
+               return PTR_ERR(hw);
+
+       return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
+}
+
+static const struct of_device_id fsl_flexspi_clk_dt_ids[] = {
+       { .compatible = "fsl,ls1028a-flexspi-clk", .data = &ls1028a_flexspi_divs },
+       { .compatible = "fsl,lx2160a-flexspi-clk", .data = &lx2160a_flexspi_divs },
+       {}
+};
+MODULE_DEVICE_TABLE(of, fsl_flexspi_clk_dt_ids);
+
+static struct platform_driver fsl_flexspi_clk_driver = {
+       .driver = {
+               .name = "fsl-flexspi-clk",
+               .of_match_table = fsl_flexspi_clk_dt_ids,
+       },
+       .probe = fsl_flexspi_clk_probe,
+};
+module_platform_driver(fsl_flexspi_clk_driver);
+
+MODULE_DESCRIPTION("FlexSPI clock driver for Layerscape SoCs");
+MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
+MODULE_LICENSE("GPL");
index 0221180a4dd734c36d732663cfcc60c8ae094b48..6238fcea04673052e60e6a2293f021bd44d34d40 100644 (file)
@@ -58,13 +58,13 @@ static int fsl_sai_clk_probe(struct platform_device *pdev)
        /* set clock direction, we are the BCLK master */
        writel(CR2_BCD, base + I2S_CR2);
 
-       hw = clk_hw_register_composite_pdata(dev, dev->of_node->name,
-                                            &pdata, 1, NULL, NULL,
-                                            &sai_clk->div.hw,
-                                            &clk_divider_ops,
-                                            &sai_clk->gate.hw,
-                                            &clk_gate_ops,
-                                            CLK_SET_RATE_GATE);
+       hw = devm_clk_hw_register_composite_pdata(dev, dev->of_node->name,
+                                                 &pdata, 1, NULL, NULL,
+                                                 &sai_clk->div.hw,
+                                                 &clk_divider_ops,
+                                                 &sai_clk->gate.hw,
+                                                 &clk_gate_ops,
+                                                 CLK_SET_RATE_GATE);
        if (IS_ERR(hw))
                return PTR_ERR(hw);
 
index 86f2e2d3fc022dedaf965cb6a7fb5cfa030cc026..da2c8eddfd9ff6a0114f4ca7ec6f8d60ec65e058 100644 (file)
@@ -147,7 +147,7 @@ static struct platform_driver clk_pwm_driver = {
        .remove = clk_pwm_remove,
        .driver = {
                .name = "pwm-clock",
-               .of_match_table = of_match_ptr(clk_pwm_dt_ids),
+               .of_match_table = clk_pwm_dt_ids,
        },
 };
 
index 46101c6a20f261830e6195498d09ab2ef6359636..70aa521e7e7fa52f89a4180169a8583a2c3326fa 100644 (file)
@@ -7,6 +7,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <dt-bindings/clock/fsl,qoriq-clockgen.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
@@ -1368,33 +1369,33 @@ static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data)
        idx = clkspec->args[1];
 
        switch (type) {
-       case 0:
+       case QORIQ_CLK_SYSCLK:
                if (idx != 0)
                        goto bad_args;
                clk = cg->sysclk;
                break;
-       case 1:
+       case QORIQ_CLK_CMUX:
                if (idx >= ARRAY_SIZE(cg->cmux))
                        goto bad_args;
                clk = cg->cmux[idx];
                break;
-       case 2:
+       case QORIQ_CLK_HWACCEL:
                if (idx >= ARRAY_SIZE(cg->hwaccel))
                        goto bad_args;
                clk = cg->hwaccel[idx];
                break;
-       case 3:
+       case QORIQ_CLK_FMAN:
                if (idx >= ARRAY_SIZE(cg->fman))
                        goto bad_args;
                clk = cg->fman[idx];
                break;
-       case 4:
+       case QORIQ_CLK_PLATFORM_PLL:
                pll = &cg->pll[PLATFORM_PLL];
                if (idx >= ARRAY_SIZE(pll->div))
                        goto bad_args;
                clk = pll->div[idx].clk;
                break;
-       case 5:
+       case QORIQ_CLK_CORECLK:
                if (idx != 0)
                        goto bad_args;
                clk = cg->coreclk;
index 5a9b140dd8c80ffba69cd890c36b0f1ba4898ffb..a39af7616b13c5fc3b0adf56e3adeaca1ae77bd0 100644 (file)
@@ -129,7 +129,7 @@ static const struct clk_ops scpi_dvfs_ops = {
        .set_rate = scpi_dvfs_set_rate,
 };
 
-static const struct of_device_id scpi_clk_match[] = {
+static const struct of_device_id scpi_clk_match[] __maybe_unused = {
        { .compatible = "arm,scpi-dvfs-clocks", .data = &scpi_dvfs_ops, },
        { .compatible = "arm,scpi-variable-clocks", .data = &scpi_clk_ops, },
        {}
index f83dac54ed853440f76ac20249dcd9f40c4e769a..a3041f9a546879d176133c111791ec9bf9bb07e2 100644 (file)
@@ -420,7 +420,7 @@ static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
 static void clk_core_fill_parent_index(struct clk_core *core, u8 index)
 {
        struct clk_parent_map *entry = &core->parents[index];
-       struct clk_core *parent = ERR_PTR(-ENOENT);
+       struct clk_core *parent;
 
        if (entry->hw) {
                parent = entry->hw->core;
@@ -2931,7 +2931,14 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
        else
                seq_puts(s, "-----");
 
-       seq_printf(s, " %6d\n", clk_core_get_scaled_duty_cycle(c, 100000));
+       seq_printf(s, " %6d", clk_core_get_scaled_duty_cycle(c, 100000));
+
+       if (c->ops->is_enabled)
+               seq_printf(s, " %9c\n", clk_core_is_enabled(c) ? 'Y' : 'N');
+       else if (!c->ops->enable)
+               seq_printf(s, " %9c\n", 'Y');
+       else
+               seq_printf(s, " %9c\n", '?');
 }
 
 static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
@@ -2950,9 +2957,9 @@ static int clk_summary_show(struct seq_file *s, void *data)
        struct clk_core *c;
        struct hlist_head **lists = (struct hlist_head **)s->private;
 
-       seq_puts(s, "                                 enable  prepare  protect                                duty\n");
-       seq_puts(s, "   clock                          count    count    count        rate   accuracy phase  cycle\n");
-       seq_puts(s, "---------------------------------------------------------------------------------------------\n");
+       seq_puts(s, "                                 enable  prepare  protect                                duty  hardware\n");
+       seq_puts(s, "   clock                          count    count    count        rate   accuracy phase  cycle    enable\n");
+       seq_puts(s, "-------------------------------------------------------------------------------------------------------\n");
 
        clk_prepare_lock();
 
@@ -3667,6 +3674,24 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
        return clk;
 }
 
+/**
+ * clk_hw_get_clk - get clk consumer given an clk_hw
+ * @hw: clk_hw associated with the clk being consumed
+ * @con_id: connection ID string on device
+ *
+ * Returns: new clk consumer
+ * This is the function to be used by providers which need
+ * to get a consumer clk and act on the clock element
+ * Calls to this function must be balanced with calls clk_put()
+ */
+struct clk *clk_hw_get_clk(struct clk_hw *hw, const char *con_id)
+{
+       struct device *dev = hw->core->dev;
+
+       return clk_hw_create_clk(dev, hw, dev_name(dev), con_id);
+}
+EXPORT_SYMBOL(clk_hw_get_clk);
+
 static int clk_cpy_name(const char **dst_p, const char *src, bool must_exist)
 {
        const char *dst;
@@ -4068,12 +4093,12 @@ void clk_hw_unregister(struct clk_hw *hw)
 }
 EXPORT_SYMBOL_GPL(clk_hw_unregister);
 
-static void devm_clk_release(struct device *dev, void *res)
+static void devm_clk_unregister_cb(struct device *dev, void *res)
 {
        clk_unregister(*(struct clk **)res);
 }
 
-static void devm_clk_hw_release(struct device *dev, void *res)
+static void devm_clk_hw_unregister_cb(struct device *dev, void *res)
 {
        clk_hw_unregister(*(struct clk_hw **)res);
 }
@@ -4093,7 +4118,7 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
        struct clk *clk;
        struct clk **clkp;
 
-       clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL);
+       clkp = devres_alloc(devm_clk_unregister_cb, sizeof(*clkp), GFP_KERNEL);
        if (!clkp)
                return ERR_PTR(-ENOMEM);
 
@@ -4123,7 +4148,7 @@ int devm_clk_hw_register(struct device *dev, struct clk_hw *hw)
        struct clk_hw **hwp;
        int ret;
 
-       hwp = devres_alloc(devm_clk_hw_release, sizeof(*hwp), GFP_KERNEL);
+       hwp = devres_alloc(devm_clk_hw_unregister_cb, sizeof(*hwp), GFP_KERNEL);
        if (!hwp)
                return -ENOMEM;
 
@@ -4167,7 +4192,7 @@ static int devm_clk_hw_match(struct device *dev, void *res, void *data)
  */
 void devm_clk_unregister(struct device *dev, struct clk *clk)
 {
-       WARN_ON(devres_release(dev, devm_clk_release, devm_clk_match, clk));
+       WARN_ON(devres_release(dev, devm_clk_unregister_cb, devm_clk_match, clk));
 }
 EXPORT_SYMBOL_GPL(devm_clk_unregister);
 
@@ -4182,11 +4207,54 @@ EXPORT_SYMBOL_GPL(devm_clk_unregister);
  */
 void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw)
 {
-       WARN_ON(devres_release(dev, devm_clk_hw_release, devm_clk_hw_match,
+       WARN_ON(devres_release(dev, devm_clk_hw_unregister_cb, devm_clk_hw_match,
                                hw));
 }
 EXPORT_SYMBOL_GPL(devm_clk_hw_unregister);
 
+static void devm_clk_release(struct device *dev, void *res)
+{
+       clk_put(*(struct clk **)res);
+}
+
+/**
+ * devm_clk_hw_get_clk - resource managed clk_hw_get_clk()
+ * @dev: device that is registering this clock
+ * @hw: clk_hw associated with the clk being consumed
+ * @con_id: connection ID string on device
+ *
+ * Managed clk_hw_get_clk(). Clocks got with this function are
+ * automatically clk_put() on driver detach. See clk_put()
+ * for more information.
+ */
+struct clk *devm_clk_hw_get_clk(struct device *dev, struct clk_hw *hw,
+                               const char *con_id)
+{
+       struct clk *clk;
+       struct clk **clkp;
+
+       /* This should not happen because it would mean we have drivers
+        * passing around clk_hw pointers instead of having the caller use
+        * proper clk_get() style APIs
+        */
+       WARN_ON_ONCE(dev != hw->core->dev);
+
+       clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL);
+       if (!clkp)
+               return ERR_PTR(-ENOMEM);
+
+       clk = clk_hw_get_clk(hw, con_id);
+       if (!IS_ERR(clk)) {
+               *clkp = clk;
+               devres_add(dev, clkp);
+       } else {
+               devres_free(clkp);
+       }
+
+       return clk;
+}
+EXPORT_SYMBOL_GPL(devm_clk_hw_get_clk);
+
 /*
  * clkdev helpers
  */
@@ -4334,6 +4402,42 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(clk_notifier_unregister);
 
+struct clk_notifier_devres {
+       struct clk *clk;
+       struct notifier_block *nb;
+};
+
+static void devm_clk_notifier_release(struct device *dev, void *res)
+{
+       struct clk_notifier_devres *devres = res;
+
+       clk_notifier_unregister(devres->clk, devres->nb);
+}
+
+int devm_clk_notifier_register(struct device *dev, struct clk *clk,
+                              struct notifier_block *nb)
+{
+       struct clk_notifier_devres *devres;
+       int ret;
+
+       devres = devres_alloc(devm_clk_notifier_release,
+                             sizeof(*devres), GFP_KERNEL);
+
+       if (!devres)
+               return -ENOMEM;
+
+       ret = clk_notifier_register(clk, nb);
+       if (!ret) {
+               devres->clk = clk;
+               devres->nb = nb;
+       } else {
+               devres_free(devres);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(devm_clk_notifier_register);
+
 #ifdef CONFIG_OF
 static void clk_core_reparent_orphans(void)
 {
index 7eed7083f46e2545571716cd487e5daa27c6be31..f16c4019f402e87a7f3312989e2aa1a544217dc9 100644 (file)
@@ -30,6 +30,7 @@ struct clk_gate2 {
        void __iomem    *reg;
        u8              bit_idx;
        u8              cgr_val;
+       u8              cgr_mask;
        u8              flags;
        spinlock_t      *lock;
        unsigned int    *share_count;
@@ -37,37 +38,38 @@ struct clk_gate2 {
 
 #define to_clk_gate2(_hw) container_of(_hw, struct clk_gate2, hw)
 
-static int clk_gate2_enable(struct clk_hw *hw)
+static void clk_gate2_do_shared_clks(struct clk_hw *hw, bool enable)
 {
        struct clk_gate2 *gate = to_clk_gate2(hw);
        u32 reg;
+
+       reg = readl(gate->reg);
+       reg &= ~(gate->cgr_mask << gate->bit_idx);
+       if (enable)
+               reg |= (gate->cgr_val & gate->cgr_mask) << gate->bit_idx;
+       writel(reg, gate->reg);
+}
+
+static int clk_gate2_enable(struct clk_hw *hw)
+{
+       struct clk_gate2 *gate = to_clk_gate2(hw);
        unsigned long flags;
-       int ret = 0;
 
        spin_lock_irqsave(gate->lock, flags);
 
        if (gate->share_count && (*gate->share_count)++ > 0)
                goto out;
 
-       if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) {
-               ret = clk_gate_ops.enable(hw);
-       } else {
-               reg = readl(gate->reg);
-               reg &= ~(3 << gate->bit_idx);
-               reg |= gate->cgr_val << gate->bit_idx;
-               writel(reg, gate->reg);
-       }
-
+       clk_gate2_do_shared_clks(hw, true);
 out:
        spin_unlock_irqrestore(gate->lock, flags);
 
-       return ret;
+       return 0;
 }
 
 static void clk_gate2_disable(struct clk_hw *hw)
 {
        struct clk_gate2 *gate = to_clk_gate2(hw);
-       u32 reg;
        unsigned long flags;
 
        spin_lock_irqsave(gate->lock, flags);
@@ -79,23 +81,17 @@ static void clk_gate2_disable(struct clk_hw *hw)
                        goto out;
        }
 
-       if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT) {
-               clk_gate_ops.disable(hw);
-       } else {
-               reg = readl(gate->reg);
-               reg &= ~(3 << gate->bit_idx);
-               writel(reg, gate->reg);
-       }
-
+       clk_gate2_do_shared_clks(hw, false);
 out:
        spin_unlock_irqrestore(gate->lock, flags);
 }
 
-static int clk_gate2_reg_is_enabled(void __iomem *reg, u8 bit_idx)
+static int clk_gate2_reg_is_enabled(void __iomem *reg, u8 bit_idx,
+                                       u8 cgr_val, u8 cgr_mask)
 {
        u32 val = readl(reg);
 
-       if (((val >> bit_idx) & 1) == 1)
+       if (((val >> bit_idx) & cgr_mask) == cgr_val)
                return 1;
 
        return 0;
@@ -104,29 +100,28 @@ static int clk_gate2_reg_is_enabled(void __iomem *reg, u8 bit_idx)
 static int clk_gate2_is_enabled(struct clk_hw *hw)
 {
        struct clk_gate2 *gate = to_clk_gate2(hw);
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(gate->lock, flags);
 
-       if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT)
-               return clk_gate_ops.is_enabled(hw);
+       ret = clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx,
+                                       gate->cgr_val, gate->cgr_mask);
 
-       return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
+       spin_unlock_irqrestore(gate->lock, flags);
+
+       return ret;
 }
 
 static void clk_gate2_disable_unused(struct clk_hw *hw)
 {
        struct clk_gate2 *gate = to_clk_gate2(hw);
        unsigned long flags;
-       u32 reg;
-
-       if (gate->flags & IMX_CLK_GATE2_SINGLE_BIT)
-               return;
 
        spin_lock_irqsave(gate->lock, flags);
 
-       if (!gate->share_count || *gate->share_count == 0) {
-               reg = readl(gate->reg);
-               reg &= ~(3 << gate->bit_idx);
-               writel(reg, gate->reg);
-       }
+       if (!gate->share_count || *gate->share_count == 0)
+               clk_gate2_do_shared_clks(hw, false);
 
        spin_unlock_irqrestore(gate->lock, flags);
 }
@@ -140,7 +135,7 @@ static const struct clk_ops clk_gate2_ops = {
 
 struct clk_hw *clk_hw_register_gate2(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
-               void __iomem *reg, u8 bit_idx, u8 cgr_val,
+               void __iomem *reg, u8 bit_idx, u8 cgr_val, u8 cgr_mask,
                u8 clk_gate2_flags, spinlock_t *lock,
                unsigned int *share_count)
 {
@@ -157,6 +152,7 @@ struct clk_hw *clk_hw_register_gate2(struct device *dev, const char *name,
        gate->reg = reg;
        gate->bit_idx = bit_idx;
        gate->cgr_val = cgr_val;
+       gate->cgr_mask = cgr_mask;
        gate->flags = clk_gate2_flags;
        gate->lock = lock;
        gate->share_count = share_count;
index 0de0be0cf5484ce12124cdbf5a9f86166e2b5a22..e27890b61fb6bbda7ae7a5969b62d26b5eaf2734 100644 (file)
@@ -653,7 +653,7 @@ static struct platform_driver imx8mm_clk_driver = {
                 * reloading the driver will crash or break devices.
                 */
                .suppress_bind_attrs = true,
-               .of_match_table = of_match_ptr(imx8mm_clk_of_match),
+               .of_match_table = imx8mm_clk_of_match,
        },
 };
 module_platform_driver(imx8mm_clk_driver);
index e984de543f0bcd9b3a091718485522e27e76325b..18f81419f355da0e626a7e5dfb8d83c8573857f3 100644 (file)
@@ -604,7 +604,7 @@ static struct platform_driver imx8mn_clk_driver = {
                 * reloading the driver will crash or break devices.
                 */
                .suppress_bind_attrs = true,
-               .of_match_table = of_match_ptr(imx8mn_clk_of_match),
+               .of_match_table = imx8mn_clk_of_match,
        },
 };
 module_platform_driver(imx8mn_clk_driver);
index 12ce4770f702a41a849b848897f2f4219d6492ff..165bfe23fb3410cd9968eb90387ba4f4cd48a966 100644 (file)
@@ -425,7 +425,7 @@ static struct clk **uart_clks[ARRAY_SIZE(uart_clk_ids) + 1];
 static int imx8mp_clocks_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
+       struct device_node *np;
        void __iomem *anatop_base, *ccm_base;
        int i;
 
@@ -763,7 +763,7 @@ static struct platform_driver imx8mp_clk_driver = {
                 * reloading the driver will crash or break devices.
                 */
                .suppress_bind_attrs = true,
-               .of_match_table = of_match_ptr(imx8mp_clk_of_match),
+               .of_match_table = imx8mp_clk_of_match,
        },
 };
 module_platform_driver(imx8mp_clk_driver);
index 8265d1d48af4231cc763b250aa93d51728533b64..75186888ecae0fef8c2877da7d01205d0d34f41b 100644 (file)
@@ -639,7 +639,7 @@ static struct platform_driver imx8mq_clk_driver = {
                 * reloading the driver will crash or break devices.
                 */
                .suppress_bind_attrs = true,
-               .of_match_table = of_match_ptr(imx8mq_clk_of_match),
+               .of_match_table = imx8mq_clk_of_match,
        },
 };
 module_platform_driver(imx8mq_clk_driver);
index e947a70054acd8c47ce73d87ad0c701033852f21..d3e905cf867d7eb9c553b772c321202cc1f1ab40 100644 (file)
@@ -9,8 +9,10 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
 #include "clk-scu.h"
@@ -157,6 +159,135 @@ static const struct imx8qxp_ss_lpcg imx8qxp_ss_lsio = {
        .num_max = IMX_LSIO_LPCG_CLK_END,
 };
 
+#define IMX_LPCG_MAX_CLKS      8
+
+static struct clk_hw *imx_lpcg_of_clk_src_get(struct of_phandle_args *clkspec,
+                                             void *data)
+{
+       struct clk_hw_onecell_data *hw_data = data;
+       unsigned int idx = clkspec->args[0] / 4;
+
+       if (idx >= hw_data->num) {
+               pr_err("%s: invalid index %u\n", __func__, idx);
+               return ERR_PTR(-EINVAL);
+       }
+
+       return hw_data->hws[idx];
+}
+
+static int imx_lpcg_parse_clks_from_dt(struct platform_device *pdev,
+                                      struct device_node *np)
+{
+       const char *output_names[IMX_LPCG_MAX_CLKS];
+       const char *parent_names[IMX_LPCG_MAX_CLKS];
+       unsigned int bit_offset[IMX_LPCG_MAX_CLKS];
+       struct clk_hw_onecell_data *clk_data;
+       struct clk_hw **clk_hws;
+       struct resource *res;
+       void __iomem *base;
+       int count;
+       int idx;
+       int ret;
+       int i;
+
+       if (!of_device_is_compatible(np, "fsl,imx8qxp-lpcg"))
+               return -EINVAL;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       count = of_property_count_u32_elems(np, "clock-indices");
+       if (count < 0) {
+               dev_err(&pdev->dev, "failed to count clocks\n");
+               return -EINVAL;
+       }
+
+       /*
+        * A trick here is that we set the num of clks to the MAX instead
+        * of the count from clock-indices because one LPCG supports up to
+        * 8 clock outputs which each of them is fixed to 4 bits. Then we can
+        * easily get the clock by clk-indices (bit-offset) / 4.
+        * And the cost is very limited few pointers.
+        */
+
+       clk_data = devm_kzalloc(&pdev->dev, struct_size(clk_data, hws,
+                               IMX_LPCG_MAX_CLKS), GFP_KERNEL);
+       if (!clk_data)
+               return -ENOMEM;
+
+       clk_data->num = IMX_LPCG_MAX_CLKS;
+       clk_hws = clk_data->hws;
+
+       ret = of_property_read_u32_array(np, "clock-indices", bit_offset,
+                                        count);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to read clock-indices\n");
+               return -EINVAL;
+       }
+
+       ret = of_clk_parent_fill(np, parent_names, count);
+       if (ret != count) {
+               dev_err(&pdev->dev, "failed to get clock parent names\n");
+               return count;
+       }
+
+       ret = of_property_read_string_array(np, "clock-output-names",
+                                           output_names, count);
+       if (ret != count) {
+               dev_err(&pdev->dev, "failed to read clock-output-names\n");
+               return -EINVAL;
+       }
+
+       pm_runtime_get_noresume(&pdev->dev);
+       pm_runtime_set_active(&pdev->dev);
+       pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+
+       for (i = 0; i < count; i++) {
+               idx = bit_offset[i] / 4;
+               if (idx > IMX_LPCG_MAX_CLKS) {
+                       dev_warn(&pdev->dev, "invalid bit offset of clock %d\n",
+                                i);
+                       ret = -EINVAL;
+                       goto unreg;
+               }
+
+               clk_hws[idx] = imx_clk_lpcg_scu_dev(&pdev->dev, output_names[i],
+                                                   parent_names[i], 0, base,
+                                                   bit_offset[i], false);
+               if (IS_ERR(clk_hws[idx])) {
+                       dev_warn(&pdev->dev, "failed to register clock %d\n",
+                                idx);
+                       ret = PTR_ERR(clk_hws[idx]);
+                       goto unreg;
+               }
+       }
+
+       ret = devm_of_clk_add_hw_provider(&pdev->dev, imx_lpcg_of_clk_src_get,
+                                         clk_data);
+       if (ret)
+               goto unreg;
+
+       pm_runtime_mark_last_busy(&pdev->dev);
+       pm_runtime_put_autosuspend(&pdev->dev);
+
+       return 0;
+
+unreg:
+       while (--i >= 0) {
+               idx = bit_offset[i] / 4;
+               if (clk_hws[idx])
+                       imx_clk_lpcg_scu_unregister(clk_hws[idx]);
+       }
+
+       pm_runtime_disable(&pdev->dev);
+
+       return ret;
+}
+
 static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -167,8 +298,14 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
        struct resource *res;
        struct clk_hw **clks;
        void __iomem *base;
+       int ret;
        int i;
 
+       /* try new binding to parse clocks from device tree first */
+       ret = imx_lpcg_parse_clks_from_dt(pdev, np);
+       if (!ret)
+               return 0;
+
        ss_lpcg = of_device_get_match_data(dev);
        if (!ss_lpcg)
                return -ENODEV;
@@ -219,6 +356,7 @@ static const struct of_device_id imx8qxp_lpcg_match[] = {
        { .compatible = "fsl,imx8qxp-lpcg-adma", &imx8qxp_ss_adma, },
        { .compatible = "fsl,imx8qxp-lpcg-conn", &imx8qxp_ss_conn, },
        { .compatible = "fsl,imx8qxp-lpcg-lsio", &imx8qxp_ss_lsio, },
+       { .compatible = "fsl,imx8qxp-lpcg", NULL },
        { /* sentinel */ }
 };
 
@@ -226,6 +364,7 @@ static struct platform_driver imx8qxp_lpcg_clk_driver = {
        .driver = {
                .name = "imx8qxp-lpcg-clk",
                .of_match_table = imx8qxp_lpcg_match,
+               .pm = &imx_clk_lpcg_scu_pm_ops,
                .suppress_bind_attrs = true,
        },
        .probe = imx8qxp_lpcg_clk_probe,
index d650ca33cdc80c31a787ee3cb12e02fcf5b12cbb..5b3d4ede7c7c4685a22bdf31f8eb5570ce097bb7 100644 (file)
@@ -22,9 +22,10 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
        struct device_node *ccm_node = pdev->dev.of_node;
        struct clk_hw_onecell_data *clk_data;
        struct clk_hw **clks;
+       u32 clk_cells;
        int ret, i;
 
-       ret = imx_clk_scu_init();
+       ret = imx_clk_scu_init(ccm_node);
        if (ret)
                return ret;
 
@@ -33,6 +34,9 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
        if (!clk_data)
                return -ENOMEM;
 
+       if (of_property_read_u32(ccm_node, "#clock-cells", &clk_cells))
+               return -EINVAL;
+
        clk_data->num = IMX_SCU_CLK_END;
        clks = clk_data->hws;
 
@@ -55,78 +59,78 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
        clks[IMX_LSIO_BUS_CLK]          = clk_hw_register_fixed_rate(NULL, "lsio_bus_clk_root", NULL, 0, 100000000);
 
        /* ARM core */
-       clks[IMX_A35_CLK]               = imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU);
+       clks[IMX_A35_CLK]               = imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU, clk_cells);
 
        /* LSIO SS */
-       clks[IMX_LSIO_PWM0_CLK]         = imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER);
-       clks[IMX_LSIO_PWM1_CLK]         = imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER);
-       clks[IMX_LSIO_PWM2_CLK]         = imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER);
-       clks[IMX_LSIO_PWM3_CLK]         = imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER);
-       clks[IMX_LSIO_PWM4_CLK]         = imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER);
-       clks[IMX_LSIO_PWM5_CLK]         = imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER);
-       clks[IMX_LSIO_PWM6_CLK]         = imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER);
-       clks[IMX_LSIO_PWM7_CLK]         = imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER);
-       clks[IMX_LSIO_GPT0_CLK]         = imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER);
-       clks[IMX_LSIO_GPT1_CLK]         = imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER);
-       clks[IMX_LSIO_GPT2_CLK]         = imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER);
-       clks[IMX_LSIO_GPT3_CLK]         = imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER);
-       clks[IMX_LSIO_GPT4_CLK]         = imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER);
-       clks[IMX_LSIO_FSPI0_CLK]        = imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER);
-       clks[IMX_LSIO_FSPI1_CLK]        = imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER);
+       clks[IMX_LSIO_PWM0_CLK]         = imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_LSIO_PWM1_CLK]         = imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_LSIO_PWM2_CLK]         = imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_LSIO_PWM3_CLK]         = imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_LSIO_PWM4_CLK]         = imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_LSIO_PWM5_CLK]         = imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_LSIO_PWM6_CLK]         = imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_LSIO_PWM7_CLK]         = imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_LSIO_GPT0_CLK]         = imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_LSIO_GPT1_CLK]         = imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_LSIO_GPT2_CLK]         = imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_LSIO_GPT3_CLK]         = imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_LSIO_GPT4_CLK]         = imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_LSIO_FSPI0_CLK]        = imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_LSIO_FSPI1_CLK]        = imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER, clk_cells);
 
        /* ADMA SS */
-       clks[IMX_ADMA_UART0_CLK]        = imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_UART1_CLK]        = imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_UART2_CLK]        = imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_UART3_CLK]        = imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_SPI0_CLK]         = imx_clk_scu("spi0_clk",  IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_SPI1_CLK]         = imx_clk_scu("spi1_clk",  IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_SPI2_CLK]         = imx_clk_scu("spi2_clk",  IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_SPI3_CLK]         = imx_clk_scu("spi3_clk",  IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_CAN0_CLK]         = imx_clk_scu("can0_clk",  IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_I2C0_CLK]         = imx_clk_scu("i2c0_clk",  IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_I2C1_CLK]         = imx_clk_scu("i2c1_clk",  IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_I2C2_CLK]         = imx_clk_scu("i2c2_clk",  IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_I2C3_CLK]         = imx_clk_scu("i2c3_clk",  IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_FTM0_CLK]         = imx_clk_scu("ftm0_clk",  IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_FTM1_CLK]         = imx_clk_scu("ftm1_clk",  IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_ADC0_CLK]         = imx_clk_scu("adc0_clk",  IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_PWM_CLK]          = imx_clk_scu("pwm_clk",   IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER);
-       clks[IMX_ADMA_LCD_CLK]          = imx_clk_scu("lcd_clk",   IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER);
+       clks[IMX_ADMA_UART0_CLK]        = imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_UART1_CLK]        = imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_UART2_CLK]        = imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_UART3_CLK]        = imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_SPI0_CLK]         = imx_clk_scu("spi0_clk",  IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_SPI1_CLK]         = imx_clk_scu("spi1_clk",  IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_SPI2_CLK]         = imx_clk_scu("spi2_clk",  IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_SPI3_CLK]         = imx_clk_scu("spi3_clk",  IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_CAN0_CLK]         = imx_clk_scu("can0_clk",  IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_I2C0_CLK]         = imx_clk_scu("i2c0_clk",  IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_I2C1_CLK]         = imx_clk_scu("i2c1_clk",  IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_I2C2_CLK]         = imx_clk_scu("i2c2_clk",  IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_I2C3_CLK]         = imx_clk_scu("i2c3_clk",  IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_FTM0_CLK]         = imx_clk_scu("ftm0_clk",  IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_FTM1_CLK]         = imx_clk_scu("ftm1_clk",  IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_ADC0_CLK]         = imx_clk_scu("adc0_clk",  IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_PWM_CLK]          = imx_clk_scu("pwm_clk",   IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_ADMA_LCD_CLK]          = imx_clk_scu("lcd_clk",   IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER, clk_cells);
 
        /* Connectivity */
-       clks[IMX_CONN_SDHC0_CLK]        = imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER);
-       clks[IMX_CONN_SDHC1_CLK]        = imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER);
-       clks[IMX_CONN_SDHC2_CLK]        = imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER);
-       clks[IMX_CONN_ENET0_ROOT_CLK]   = imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER);
-       clks[IMX_CONN_ENET0_BYPASS_CLK] = imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS);
-       clks[IMX_CONN_ENET0_RGMII_CLK]  = imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0);
-       clks[IMX_CONN_ENET1_ROOT_CLK]   = imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER);
-       clks[IMX_CONN_ENET1_BYPASS_CLK] = imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS);
-       clks[IMX_CONN_ENET1_RGMII_CLK]  = imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0);
-       clks[IMX_CONN_GPMI_BCH_IO_CLK]  = imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS);
-       clks[IMX_CONN_GPMI_BCH_CLK]     = imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER);
-       clks[IMX_CONN_USB2_ACLK]        = imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER);
-       clks[IMX_CONN_USB2_BUS_CLK]     = imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS);
-       clks[IMX_CONN_USB2_LPM_CLK]     = imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC);
+       clks[IMX_CONN_SDHC0_CLK]        = imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_CONN_SDHC1_CLK]        = imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_CONN_SDHC2_CLK]        = imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_CONN_ENET0_ROOT_CLK]   = imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_CONN_ENET0_BYPASS_CLK] = imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS, clk_cells);
+       clks[IMX_CONN_ENET0_RGMII_CLK]  = imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0, clk_cells);
+       clks[IMX_CONN_ENET1_ROOT_CLK]   = imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_CONN_ENET1_BYPASS_CLK] = imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS, clk_cells);
+       clks[IMX_CONN_ENET1_RGMII_CLK]  = imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0, clk_cells);
+       clks[IMX_CONN_GPMI_BCH_IO_CLK]  = imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS, clk_cells);
+       clks[IMX_CONN_GPMI_BCH_CLK]     = imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_CONN_USB2_ACLK]        = imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_CONN_USB2_BUS_CLK]     = imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS, clk_cells);
+       clks[IMX_CONN_USB2_LPM_CLK]     = imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC, clk_cells);
 
        /* Display controller SS */
-       clks[IMX_DC0_DISP0_CLK]         = imx_clk_scu("dc0_disp0_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0);
-       clks[IMX_DC0_DISP1_CLK]         = imx_clk_scu("dc0_disp1_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1);
+       clks[IMX_DC0_DISP0_CLK]         = imx_clk_scu("dc0_disp0_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0, clk_cells);
+       clks[IMX_DC0_DISP1_CLK]         = imx_clk_scu("dc0_disp1_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1, clk_cells);
 
        /* MIPI-LVDS SS */
-       clks[IMX_MIPI0_I2C0_CLK]        = imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2);
-       clks[IMX_MIPI0_I2C1_CLK]        = imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2);
+       clks[IMX_MIPI0_I2C0_CLK]        = imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2, clk_cells);
+       clks[IMX_MIPI0_I2C1_CLK]        = imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2, clk_cells);
 
        /* MIPI CSI SS */
-       clks[IMX_CSI0_CORE_CLK]         = imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER);
-       clks[IMX_CSI0_ESC_CLK]          = imx_clk_scu("mipi_csi0_esc_clk",  IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC);
-       clks[IMX_CSI0_I2C0_CLK]         = imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER);
-       clks[IMX_CSI0_PWM0_CLK]         = imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER);
+       clks[IMX_CSI0_CORE_CLK]         = imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_CSI0_ESC_CLK]          = imx_clk_scu("mipi_csi0_esc_clk",  IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC, clk_cells);
+       clks[IMX_CSI0_I2C0_CLK]         = imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_CSI0_PWM0_CLK]         = imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells);
 
        /* GPU SS */
-       clks[IMX_GPU0_CORE_CLK]         = imx_clk_scu("gpu_core0_clk",   IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER);
-       clks[IMX_GPU0_SHADER_CLK]       = imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC);
+       clks[IMX_GPU0_CORE_CLK]         = imx_clk_scu("gpu_core0_clk",   IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER, clk_cells);
+       clks[IMX_GPU0_SHADER_CLK]       = imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC, clk_cells);
 
        for (i = 0; i < clk_data->num; i++) {
                if (IS_ERR(clks[i]))
@@ -134,7 +138,19 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
                                i, PTR_ERR(clks[i]));
        }
 
-       return of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data);
+       if (clk_cells == 2) {
+               ret = of_clk_add_hw_provider(ccm_node, imx_scu_of_clk_src_get, imx_scu_clks);
+               if (ret)
+                       imx_clk_scu_unregister();
+       } else {
+               /*
+                * legacy binding code path doesn't unregister here because
+                * it will be removed later.
+                */
+               ret = of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data);
+       }
+
+       return ret;
 }
 
 static const struct of_device_id imx8qxp_match[] = {
index 1f0e44f921aee77e0c29af309b1ce22f736cb068..77be7632866d7f8fb85bf03cb883854c769db719 100644 (file)
@@ -34,6 +34,9 @@ struct clk_lpcg_scu {
        void __iomem *reg;
        u8 bit_idx;
        bool hw_gate;
+
+       /* for state save&restore */
+       u32 state;
 };
 
 #define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw)
@@ -81,9 +84,9 @@ static const struct clk_ops clk_lpcg_scu_ops = {
        .disable = clk_lpcg_scu_disable,
 };
 
-struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
-                               unsigned long flags, void __iomem *reg,
-                               u8 bit_idx, bool hw_gate)
+struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name,
+                                 const char *parent_name, unsigned long flags,
+                                 void __iomem *reg, u8 bit_idx, bool hw_gate)
 {
        struct clk_lpcg_scu *clk;
        struct clk_init_data init;
@@ -107,11 +110,53 @@ struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
        clk->hw.init = &init;
 
        hw = &clk->hw;
-       ret = clk_hw_register(NULL, hw);
+       ret = clk_hw_register(dev, hw);
        if (ret) {
                kfree(clk);
                hw = ERR_PTR(ret);
        }
 
+       if (dev)
+               dev_set_drvdata(dev, clk);
+
        return hw;
 }
+
+void imx_clk_lpcg_scu_unregister(struct clk_hw *hw)
+{
+       struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
+
+       clk_hw_unregister(&clk->hw);
+       kfree(clk);
+}
+
+static int __maybe_unused imx_clk_lpcg_scu_suspend(struct device *dev)
+{
+       struct clk_lpcg_scu *clk = dev_get_drvdata(dev);
+
+       clk->state = readl_relaxed(clk->reg);
+       dev_dbg(dev, "save lpcg state 0x%x\n", clk->state);
+
+       return 0;
+}
+
+static int __maybe_unused imx_clk_lpcg_scu_resume(struct device *dev)
+{
+       struct clk_lpcg_scu *clk = dev_get_drvdata(dev);
+
+       /*
+        * FIXME: Sometimes writes don't work unless the CPU issues
+        * them twice
+        */
+
+       writel(clk->state, clk->reg);
+       writel(clk->state, clk->reg);
+       dev_dbg(dev, "restore lpcg state 0x%x\n", clk->state);
+
+       return 0;
+}
+
+const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops = {
+       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_lpcg_scu_suspend,
+                                     imx_clk_lpcg_scu_resume)
+};
index aba36e4217d2d846ae04ec6b7664cd7caee1d44d..2b5ed86b9dbbbdf19a57119798a8a75fab258354 100644 (file)
@@ -416,7 +416,7 @@ struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name,
                       __func__, name);
                kfree(pll);
                return ERR_PTR(-EINVAL);
-       };
+       }
 
        pll->base = base;
        pll->hw.init = &init;
index b8b2072742a5608ff6fe7abf0bfbf9a34fdca4f0..1f5518b7ab39eded6fdc00799c9a5dc0b1f4eaa5 100644 (file)
@@ -8,6 +8,10 @@
 #include <linux/arm-smccc.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
 #include "clk-scu.h"
 #define IMX_SIP_SET_CPUFREQ            0x00
 
 static struct imx_sc_ipc *ccm_ipc_handle;
+static struct device_node *pd_np;
+static struct platform_driver imx_clk_scu_driver;
+
+struct imx_scu_clk_node {
+       const char *name;
+       u32 rsrc;
+       u8 clk_type;
+       const char * const *parents;
+       int num_parents;
+
+       struct clk_hw *hw;
+       struct list_head node;
+};
+
+struct list_head imx_scu_clks[IMX_SC_R_LAST];
 
 /*
  * struct clk_scu - Description of one SCU clock
@@ -27,6 +46,10 @@ struct clk_scu {
        struct clk_hw hw;
        u16 rsrc_id;
        u8 clk_type;
+
+       /* for state save&restore */
+       bool is_enabled;
+       u32 rate;
 };
 
 /*
@@ -128,9 +151,28 @@ static inline struct clk_scu *to_clk_scu(struct clk_hw *hw)
        return container_of(hw, struct clk_scu, hw);
 }
 
-int imx_clk_scu_init(void)
+int imx_clk_scu_init(struct device_node *np)
 {
-       return imx_scu_get_handle(&ccm_ipc_handle);
+       u32 clk_cells;
+       int ret, i;
+
+       ret = imx_scu_get_handle(&ccm_ipc_handle);
+       if (ret)
+               return ret;
+
+       of_property_read_u32(np, "#clock-cells", &clk_cells);
+
+       if (clk_cells == 2) {
+               for (i = 0; i < IMX_SC_R_LAST; i++)
+                       INIT_LIST_HEAD(&imx_scu_clks[i]);
+
+               /* pd_np will be used to attach power domains later */
+               pd_np = of_find_compatible_node(NULL, NULL, "fsl,scu-pd");
+               if (!pd_np)
+                       return -EINVAL;
+       }
+
+       return platform_driver_register(&imx_clk_scu_driver);
 }
 
 /*
@@ -344,8 +386,9 @@ static const struct clk_ops clk_scu_cpu_ops = {
        .unprepare = clk_scu_unprepare,
 };
 
-struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
-                            int num_parents, u32 rsrc_id, u8 clk_type)
+struct clk_hw *__imx_clk_scu(struct device *dev, const char *name,
+                            const char * const *parents, int num_parents,
+                            u32 rsrc_id, u8 clk_type)
 {
        struct clk_init_data init;
        struct clk_scu *clk;
@@ -379,11 +422,185 @@ struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
        clk->hw.init = &init;
 
        hw = &clk->hw;
-       ret = clk_hw_register(NULL, hw);
+       ret = clk_hw_register(dev, hw);
        if (ret) {
                kfree(clk);
                hw = ERR_PTR(ret);
        }
 
+       if (dev)
+               dev_set_drvdata(dev, clk);
+
        return hw;
 }
+
+struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec,
+                                     void *data)
+{
+       unsigned int rsrc = clkspec->args[0];
+       unsigned int idx = clkspec->args[1];
+       struct list_head *scu_clks = data;
+       struct imx_scu_clk_node *clk;
+
+       list_for_each_entry(clk, &scu_clks[rsrc], node) {
+               if (clk->clk_type == idx)
+                       return clk->hw;
+       }
+
+       return ERR_PTR(-ENODEV);
+}
+
+static int imx_clk_scu_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct imx_scu_clk_node *clk = dev_get_platdata(dev);
+       struct clk_hw *hw;
+       int ret;
+
+       pm_runtime_set_suspended(dev);
+       pm_runtime_set_autosuspend_delay(dev, 50);
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_enable(dev);
+
+       ret = pm_runtime_get_sync(dev);
+       if (ret) {
+               pm_runtime_disable(dev);
+               return ret;
+       }
+
+       hw = __imx_clk_scu(dev, clk->name, clk->parents, clk->num_parents,
+                          clk->rsrc, clk->clk_type);
+       if (IS_ERR(hw)) {
+               pm_runtime_disable(dev);
+               return PTR_ERR(hw);
+       }
+
+       clk->hw = hw;
+       list_add_tail(&clk->node, &imx_scu_clks[clk->rsrc]);
+
+       pm_runtime_mark_last_busy(&pdev->dev);
+       pm_runtime_put_autosuspend(&pdev->dev);
+
+       dev_dbg(dev, "register SCU clock rsrc:%d type:%d\n", clk->rsrc,
+               clk->clk_type);
+
+       return 0;
+}
+
+static int __maybe_unused imx_clk_scu_suspend(struct device *dev)
+{
+       struct clk_scu *clk = dev_get_drvdata(dev);
+
+       clk->rate = clk_hw_get_rate(&clk->hw);
+       clk->is_enabled = clk_hw_is_enabled(&clk->hw);
+
+       if (clk->rate)
+               dev_dbg(dev, "save rate %d\n", clk->rate);
+
+       if (clk->is_enabled)
+               dev_dbg(dev, "save enabled state\n");
+
+       return 0;
+}
+
+static int __maybe_unused imx_clk_scu_resume(struct device *dev)
+{
+       struct clk_scu *clk = dev_get_drvdata(dev);
+       int ret = 0;
+
+       if (clk->rate) {
+               ret = clk_scu_set_rate(&clk->hw, clk->rate, 0);
+               dev_dbg(dev, "restore rate %d %s\n", clk->rate,
+                       !ret ? "success" : "failed");
+       }
+
+       if (clk->is_enabled) {
+               ret = clk_scu_prepare(&clk->hw);
+               dev_dbg(dev, "restore enabled state %s\n",
+                       !ret ? "success" : "failed");
+       }
+
+       return ret;
+}
+
+static const struct dev_pm_ops imx_clk_scu_pm_ops = {
+       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_scu_suspend,
+                                     imx_clk_scu_resume)
+};
+
+static struct platform_driver imx_clk_scu_driver = {
+       .driver = {
+               .name = "imx-scu-clk",
+               .suppress_bind_attrs = true,
+               .pm = &imx_clk_scu_pm_ops,
+       },
+       .probe = imx_clk_scu_probe,
+};
+
+static int imx_clk_scu_attach_pd(struct device *dev, u32 rsrc_id)
+{
+       struct of_phandle_args genpdspec = {
+               .np = pd_np,
+               .args_count = 1,
+               .args[0] = rsrc_id,
+       };
+
+       if (rsrc_id == IMX_SC_R_A35 || rsrc_id == IMX_SC_R_A53 ||
+           rsrc_id == IMX_SC_R_A72)
+               return 0;
+
+       return of_genpd_add_device(&genpdspec, dev);
+}
+
+struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
+                                    const char * const *parents,
+                                    int num_parents, u32 rsrc_id, u8 clk_type)
+{
+       struct imx_scu_clk_node clk = {
+               .name = name,
+               .rsrc = rsrc_id,
+               .clk_type = clk_type,
+               .parents = parents,
+               .num_parents = num_parents,
+       };
+       struct platform_device *pdev;
+       int ret;
+
+       pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE);
+       if (!pdev) {
+               pr_err("%s: failed to allocate scu clk dev rsrc %d type %d\n",
+                      name, rsrc_id, clk_type);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       ret = platform_device_add_data(pdev, &clk, sizeof(clk));
+       if (ret) {
+               platform_device_put(pdev);
+               return ERR_PTR(ret);
+       }
+
+       pdev->driver_override = "imx-scu-clk";
+
+       ret = imx_clk_scu_attach_pd(&pdev->dev, rsrc_id);
+       if (ret)
+               pr_warn("%s: failed to attached the power domain %d\n",
+                       name, ret);
+
+       platform_device_add(pdev);
+
+       /* For API backwards compatiblilty, simply return NULL for success */
+       return NULL;
+}
+
+void imx_clk_scu_unregister(void)
+{
+       struct imx_scu_clk_node *clk;
+       int i;
+
+       for (i = 0; i < IMX_SC_R_LAST; i++) {
+               list_for_each_entry(clk, &imx_scu_clks[i], node) {
+                       clk_hw_unregister(clk->hw);
+                       kfree(clk);
+               }
+       }
+}
index 2bcfaf06a4586cc2a2523f8db607ac5409cfcd09..e8352164923e0e76a8192c7d3ed560ebdbb88bd0 100644 (file)
@@ -8,25 +8,61 @@
 #define __IMX_CLK_SCU_H
 
 #include <linux/firmware/imx/sci.h>
+#include <linux/of.h>
 
-int imx_clk_scu_init(void);
+extern struct list_head imx_scu_clks[];
+extern const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops;
 
-struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
-                            int num_parents, u32 rsrc_id, u8 clk_type);
+int imx_clk_scu_init(struct device_node *np);
+struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec,
+                                     void *data);
+struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
+                                    const char * const *parents,
+                                    int num_parents, u32 rsrc_id, u8 clk_type);
+
+struct clk_hw *__imx_clk_scu(struct device *dev, const char *name,
+                            const char * const *parents, int num_parents,
+                            u32 rsrc_id, u8 clk_type);
+
+void imx_clk_scu_unregister(void);
+
+struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name,
+                                 const char *parent_name, unsigned long flags,
+                                 void __iomem *reg, u8 bit_idx, bool hw_gate);
+void imx_clk_lpcg_scu_unregister(struct clk_hw *hw);
 
 static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id,
-                                        u8 clk_type)
+                                        u8 clk_type, u8 clk_cells)
 {
-       return __imx_clk_scu(name, NULL, 0, rsrc_id, clk_type);
+       if (clk_cells == 2)
+               return imx_clk_scu_alloc_dev(name, NULL, 0, rsrc_id, clk_type);
+       else
+               return __imx_clk_scu(NULL, name, NULL, 0, rsrc_id, clk_type);
 }
 
 static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *parents,
-                                         int num_parents, u32 rsrc_id, u8 clk_type)
+                                         int num_parents, u32 rsrc_id, u8 clk_type,
+                                         u8 clk_cells)
+{
+       if (clk_cells == 2)
+               return imx_clk_scu_alloc_dev(name, parents, num_parents, rsrc_id, clk_type);
+       else
+               return __imx_clk_scu(NULL, name, parents, num_parents, rsrc_id, clk_type);
+}
+
+static inline struct clk_hw *imx_clk_lpcg_scu_dev(struct device *dev, const char *name,
+                                                 const char *parent_name, unsigned long flags,
+                                                 void __iomem *reg, u8 bit_idx, bool hw_gate)
 {
-       return __imx_clk_scu(name, parents, num_parents, rsrc_id, clk_type);
+       return __imx_clk_lpcg_scu(dev, name, parent_name, flags, reg,
+                                 bit_idx, hw_gate);
 }
 
-struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
-                               unsigned long flags, void __iomem *reg,
-                               u8 bit_idx, bool hw_gate);
+static inline struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
+                                             unsigned long flags, void __iomem *reg,
+                                             u8 bit_idx, bool hw_gate)
+{
+       return __imx_clk_lpcg_scu(NULL, name, parent_name, flags, reg,
+                                 bit_idx, hw_gate);
+}
 #endif
index 3b796b3da2498c36a65494fbbc01dd8f85127724..3d8e40b4edbf0f03893ef3f04865dc7404bb2b90 100644 (file)
@@ -6,8 +6,6 @@
 #include <linux/spinlock.h>
 #include <linux/clk-provider.h>
 
-#define IMX_CLK_GATE2_SINGLE_BIT       1
-
 extern spinlock_t imx_ccm_lock;
 
 void imx_check_clocks(struct clk *clks[], unsigned int count);
@@ -68,9 +66,9 @@ extern struct imx_pll14xx_clk imx_1443x_dram_pll;
        to_clk(imx_clk_hw_cpu(name, parent_name, div, mux, pll, step))
 
 #define clk_register_gate2(dev, name, parent_name, flags, reg, bit_idx, \
-                               cgr_val, clk_gate_flags, lock, share_count) \
+                               cgr_val, cgr_mask, clk_gate_flags, lock, share_count) \
        to_clk(clk_hw_register_gate2(dev, name, parent_name, flags, reg, bit_idx, \
-                               cgr_val, clk_gate_flags, lock, share_count))
+                               cgr_val, cgr_mask, clk_gate_flags, lock, share_count))
 
 #define imx_clk_pllv3(type, name, parent_name, base, div_mask) \
        to_clk(imx_clk_hw_pllv3(type, name, parent_name, base, div_mask))
@@ -198,7 +196,7 @@ struct clk_hw *imx_clk_hw_pllv4(const char *name, const char *parent_name,
 
 struct clk_hw *clk_hw_register_gate2(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
-               void __iomem *reg, u8 bit_idx, u8 cgr_val,
+               void __iomem *reg, u8 bit_idx, u8 cgr_val, u8 cgr_mask,
                u8 clk_gate_flags, spinlock_t *lock,
                unsigned int *share_count);
 
@@ -351,14 +349,14 @@ static inline struct clk_hw *imx_clk_hw_gate2(const char *name, const char *pare
                void __iomem *reg, u8 shift)
 {
        return clk_hw_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
-                       shift, 0x3, 0, &imx_ccm_lock, NULL);
+                       shift, 0x3, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
 static inline struct clk_hw *imx_clk_hw_gate2_flags(const char *name, const char *parent,
                void __iomem *reg, u8 shift, unsigned long flags)
 {
        return clk_hw_register_gate2(NULL, name, parent, flags | CLK_SET_RATE_PARENT, reg,
-                       shift, 0x3, 0, &imx_ccm_lock, NULL);
+                       shift, 0x3, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
 static inline struct clk_hw *imx_clk_hw_gate2_shared(const char *name,
@@ -366,7 +364,7 @@ static inline struct clk_hw *imx_clk_hw_gate2_shared(const char *name,
                unsigned int *share_count)
 {
        return clk_hw_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
-                       shift, 0x3, 0, &imx_ccm_lock, share_count);
+                       shift, 0x3, 0x3, 0, &imx_ccm_lock, share_count);
 }
 
 static inline struct clk_hw *imx_clk_hw_gate2_shared2(const char *name,
@@ -374,7 +372,7 @@ static inline struct clk_hw *imx_clk_hw_gate2_shared2(const char *name,
                unsigned int *share_count)
 {
        return clk_hw_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT |
-                                 CLK_OPS_PARENT_ENABLE, reg, shift, 0x3, 0,
+                                 CLK_OPS_PARENT_ENABLE, reg, shift, 0x3, 0x3, 0,
                                  &imx_ccm_lock, share_count);
 }
 
@@ -384,16 +382,15 @@ static inline struct clk_hw *imx_dev_clk_hw_gate_shared(struct device *dev,
                                unsigned int *share_count)
 {
        return clk_hw_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT |
-                                       CLK_OPS_PARENT_ENABLE, reg, shift, 0x3,
-                                       IMX_CLK_GATE2_SINGLE_BIT,
-                                       &imx_ccm_lock, share_count);
+                                       CLK_OPS_PARENT_ENABLE, reg, shift, 0x1,
+                                       0x1, 0, &imx_ccm_lock, share_count);
 }
 
 static inline struct clk *imx_clk_gate2_cgr(const char *name,
                const char *parent, void __iomem *reg, u8 shift, u8 cgr_val)
 {
        return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
-                       shift, cgr_val, 0, &imx_ccm_lock, NULL);
+                       shift, cgr_val, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
 static inline struct clk_hw *imx_clk_hw_gate3(const char *name, const char *parent,
@@ -421,7 +418,7 @@ static inline struct clk_hw *imx_clk_hw_gate4(const char *name, const char *pare
 {
        return clk_hw_register_gate2(NULL, name, parent,
                        CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
-                       reg, shift, 0x3, 0, &imx_ccm_lock, NULL);
+                       reg, shift, 0x3, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
 static inline struct clk_hw *imx_clk_hw_gate4_flags(const char *name,
@@ -430,7 +427,7 @@ static inline struct clk_hw *imx_clk_hw_gate4_flags(const char *name,
 {
        return clk_hw_register_gate2(NULL, name, parent,
                        flags | CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
-                       reg, shift, 0x3, 0, &imx_ccm_lock, NULL);
+                       reg, shift, 0x3, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
 #define imx_clk_gate4_flags(name, parent, reg, shift, flags) \
index 034da203e8e0e3707fbab40dbc03977f0db364fb..fc002c155bc3e0ddfa24ddf915578ccaef40cd33 100644 (file)
@@ -58,7 +58,7 @@ config COMMON_CLK_MESON8B
          want peripherals and CPU frequency scaling to work.
 
 config COMMON_CLK_GXBB
-       bool "GXBB and GXL SoC clock controllers support"
+       tristate "GXBB and GXL SoC clock controllers support"
        depends on ARM64
        default y
        select COMMON_CLK_MESON_REGMAP
@@ -74,7 +74,7 @@ config COMMON_CLK_GXBB
          Say Y if you want peripherals and CPU frequency scaling to work.
 
 config COMMON_CLK_AXG
-       bool "AXG SoC clock controllers support"
+       tristate "AXG SoC clock controllers support"
        depends on ARM64
        default y
        select COMMON_CLK_MESON_REGMAP
@@ -100,7 +100,7 @@ config COMMON_CLK_AXG_AUDIO
          aka axg, Say Y if you want audio subsystem to work.
 
 config COMMON_CLK_G12A
-       bool "G12 and SM1 SoC clock controllers support"
+       tristate "G12 and SM1 SoC clock controllers support"
        depends on ARM64
        default y
        select COMMON_CLK_MESON_REGMAP
@@ -110,6 +110,7 @@ config COMMON_CLK_G12A
        select COMMON_CLK_MESON_AO_CLKC
        select COMMON_CLK_MESON_EE_CLKC
        select COMMON_CLK_MESON_CPU_DYNDIV
+       select COMMON_CLK_MESON_VID_PLL_DIV
        select MFD_SYSCON
        help
          Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2
index b488b40c9d0e3f56bd94d0a7145abd475a263d3d..af6db437bcd82f863b64963c7e40507619bf61bd 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/platform_device.h>
 #include <linux/reset-controller.h>
 #include <linux/mfd/syscon.h>
+#include <linux/module.h>
 #include "meson-aoclk.h"
 #include "axg-aoclk.h"
 
@@ -326,6 +327,7 @@ static const struct of_device_id axg_aoclkc_match_table[] = {
        },
        { }
 };
+MODULE_DEVICE_TABLE(of, axg_aoclkc_match_table);
 
 static struct platform_driver axg_aoclkc_driver = {
        .probe          = meson_aoclkc_probe,
@@ -335,4 +337,5 @@ static struct platform_driver axg_aoclkc_driver = {
        },
 };
 
-builtin_platform_driver(axg_aoclkc_driver);
+module_platform_driver(axg_aoclkc_driver);
+MODULE_LICENSE("GPL v2");
index 13fc0006f63d82f4de17a376ecafe9344907e93f..0e44695b8772defee1aa35b6c8647fe52fe6e720 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/module.h>
 
 #include "clk-regmap.h"
 #include "clk-pll.h"
@@ -1026,6 +1027,743 @@ static struct clk_regmap axg_sd_emmc_c_clk0 = {
        },
 };
 
+/* VPU Clock */
+
+static const struct clk_hw *axg_vpu_parent_hws[] = {
+       &axg_fclk_div4.hw,
+       &axg_fclk_div3.hw,
+       &axg_fclk_div5.hw,
+       &axg_fclk_div7.hw,
+};
+
+static struct clk_regmap axg_vpu_0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VPU_CLK_CNTL,
+               .mask = 0x3,
+               .shift = 9,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vpu_0_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_hws = axg_vpu_parent_hws,
+               .num_parents = ARRAY_SIZE(axg_vpu_parent_hws),
+               /* We need a specific parent for VPU clock source, let it be set in DT */
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap axg_vpu_0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VPU_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vpu_0_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vpu_0_sel.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap axg_vpu_0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VPU_CLK_CNTL,
+               .bit_idx = 8,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vpu_0",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vpu_0_div.hw },
+               .num_parents = 1,
+               /*
+                * We want to avoid CCF to disable the VPU clock if
+                * display has been set by Bootloader
+                */
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vpu_1_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VPU_CLK_CNTL,
+               .mask = 0x3,
+               .shift = 25,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vpu_1_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_hws = axg_vpu_parent_hws,
+               .num_parents = ARRAY_SIZE(axg_vpu_parent_hws),
+               /* We need a specific parent for VPU clock source, let it be set in DT */
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap axg_vpu_1_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VPU_CLK_CNTL,
+               .shift = 16,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vpu_1_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vpu_1_sel.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap axg_vpu_1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VPU_CLK_CNTL,
+               .bit_idx = 24,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vpu_1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vpu_1_div.hw },
+               .num_parents = 1,
+               /*
+                * We want to avoid CCF to disable the VPU clock if
+                * display has been set by Bootloader
+                */
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vpu = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VPU_CLK_CNTL,
+               .mask = 1,
+               .shift = 31,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vpu",
+               .ops = &clk_regmap_mux_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vpu_0.hw,
+                       &axg_vpu_1.hw
+               },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+/* VAPB Clock */
+
+static struct clk_regmap axg_vapb_0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .mask = 0x3,
+               .shift = 9,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vapb_0_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_hws = axg_vpu_parent_hws,
+               .num_parents = ARRAY_SIZE(axg_vpu_parent_hws),
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap axg_vapb_0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vapb_0_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vapb_0_sel.hw
+               },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap axg_vapb_0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .bit_idx = 8,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vapb_0",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vapb_0_div.hw
+               },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vapb_1_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .mask = 0x3,
+               .shift = 25,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vapb_1_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_hws = axg_vpu_parent_hws,
+               .num_parents = ARRAY_SIZE(axg_vpu_parent_hws),
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap axg_vapb_1_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .shift = 16,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vapb_1_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vapb_1_sel.hw
+               },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap axg_vapb_1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .bit_idx = 24,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vapb_1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vapb_1_div.hw
+               },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vapb_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .mask = 1,
+               .shift = 31,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vapb_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vapb_0.hw,
+                       &axg_vapb_1.hw
+               },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap axg_vapb = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .bit_idx = 30,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vapb",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vapb_sel.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+/* Video Clocks */
+
+static const struct clk_hw *axg_vclk_parent_hws[] = {
+       &axg_gp0_pll.hw,
+       &axg_fclk_div4.hw,
+       &axg_fclk_div3.hw,
+       &axg_fclk_div5.hw,
+       &axg_fclk_div2.hw,
+       &axg_fclk_div7.hw,
+       &axg_mpll1.hw,
+};
+
+static struct clk_regmap axg_vclk_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VID_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 16,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_hws = axg_vclk_parent_hws,
+               .num_parents = ARRAY_SIZE(axg_vclk_parent_hws),
+               .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap axg_vclk2_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VIID_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 16,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk2_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_hws = axg_vclk_parent_hws,
+               .num_parents = ARRAY_SIZE(axg_vclk_parent_hws),
+               .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap axg_vclk_input = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_DIV,
+               .bit_idx = 16,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk_input",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vclk_sel.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vclk2_input = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VIID_CLK_DIV,
+               .bit_idx = 16,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk2_input",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vclk2_sel.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vclk_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VID_CLK_DIV,
+               .shift = 0,
+               .width = 8,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vclk_input.hw
+               },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap axg_vclk2_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VIID_CLK_DIV,
+               .shift = 0,
+               .width = 8,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk2_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vclk2_input.hw
+               },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap axg_vclk = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL,
+               .bit_idx = 19,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vclk_div.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vclk2 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VIID_CLK_CNTL,
+               .bit_idx = 19,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk2",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vclk2_div.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vclk_div1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL,
+               .bit_idx = 0,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk_div1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vclk.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vclk_div2_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL,
+               .bit_idx = 1,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk_div2_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vclk.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vclk_div4_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL,
+               .bit_idx = 2,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk_div4_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vclk.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vclk_div6_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL,
+               .bit_idx = 3,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk_div6_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vclk.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vclk_div12_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL,
+               .bit_idx = 4,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk_div12_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vclk.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vclk2_div1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VIID_CLK_CNTL,
+               .bit_idx = 0,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk2_div1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vclk2.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vclk2_div2_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VIID_CLK_CNTL,
+               .bit_idx = 1,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk2_div2_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vclk2.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vclk2_div4_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VIID_CLK_CNTL,
+               .bit_idx = 2,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk2_div4_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vclk2.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vclk2_div6_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VIID_CLK_CNTL,
+               .bit_idx = 3,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk2_div6_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vclk2.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap axg_vclk2_div12_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VIID_CLK_CNTL,
+               .bit_idx = 4,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk2_div12_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) { &axg_vclk2.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_fixed_factor axg_vclk_div2 = {
+       .mult = 1,
+       .div = 2,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk_div2",
+               .ops = &clk_fixed_factor_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vclk_div2_en.hw
+               },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor axg_vclk_div4 = {
+       .mult = 1,
+       .div = 4,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk_div4",
+               .ops = &clk_fixed_factor_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vclk_div4_en.hw
+               },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor axg_vclk_div6 = {
+       .mult = 1,
+       .div = 6,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk_div6",
+               .ops = &clk_fixed_factor_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vclk_div6_en.hw
+               },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor axg_vclk_div12 = {
+       .mult = 1,
+       .div = 12,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk_div12",
+               .ops = &clk_fixed_factor_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vclk_div12_en.hw
+               },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor axg_vclk2_div2 = {
+       .mult = 1,
+       .div = 2,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk2_div2",
+               .ops = &clk_fixed_factor_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vclk2_div2_en.hw
+               },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor axg_vclk2_div4 = {
+       .mult = 1,
+       .div = 4,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk2_div4",
+               .ops = &clk_fixed_factor_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vclk2_div4_en.hw
+               },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor axg_vclk2_div6 = {
+       .mult = 1,
+       .div = 6,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk2_div6",
+               .ops = &clk_fixed_factor_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vclk2_div6_en.hw
+               },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor axg_vclk2_div12 = {
+       .mult = 1,
+       .div = 12,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk2_div12",
+               .ops = &clk_fixed_factor_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vclk2_div12_en.hw
+               },
+               .num_parents = 1,
+       },
+};
+
+static u32 mux_table_cts_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
+static const struct clk_hw *axg_cts_parent_hws[] = {
+       &axg_vclk_div1.hw,
+       &axg_vclk_div2.hw,
+       &axg_vclk_div4.hw,
+       &axg_vclk_div6.hw,
+       &axg_vclk_div12.hw,
+       &axg_vclk2_div1.hw,
+       &axg_vclk2_div2.hw,
+       &axg_vclk2_div4.hw,
+       &axg_vclk2_div6.hw,
+       &axg_vclk2_div12.hw,
+};
+
+static struct clk_regmap axg_cts_encl_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VIID_CLK_DIV,
+               .mask = 0xf,
+               .shift = 12,
+               .table = mux_table_cts_sel,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cts_encl_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_hws = axg_cts_parent_hws,
+               .num_parents = ARRAY_SIZE(axg_cts_parent_hws),
+               .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap axg_cts_encl = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL2,
+               .bit_idx = 3,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "cts_encl",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_cts_encl_sel.hw
+               },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+/* MIPI DSI Host Clock */
+
+static u32 mux_table_axg_vdin_meas[]    = { 0, 1, 2, 3, 6, 7 };
+static const struct clk_parent_data axg_vdin_meas_parent_data[] = {
+       { .fw_name = "xtal", },
+       { .hw = &axg_fclk_div4.hw },
+       { .hw = &axg_fclk_div3.hw },
+       { .hw = &axg_fclk_div5.hw },
+       { .hw = &axg_fclk_div2.hw },
+       { .hw = &axg_fclk_div7.hw },
+};
+
+static struct clk_regmap axg_vdin_meas_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VDIN_MEAS_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 21,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+               .table = mux_table_axg_vdin_meas,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdin_meas_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_data = axg_vdin_meas_parent_data,
+               .num_parents = ARRAY_SIZE(axg_vdin_meas_parent_data),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap axg_vdin_meas_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VDIN_MEAS_CLK_CNTL,
+               .shift = 12,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdin_meas_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vdin_meas_sel.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap axg_vdin_meas = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VDIN_MEAS_CLK_CNTL,
+               .bit_idx = 20,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vdin_meas",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &axg_vdin_meas_div.hw },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
 static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8,
                                    9, 10, 11, 13, 14, };
 static const struct clk_parent_data gen_clk_parent_data[] = {
@@ -1246,6 +1984,52 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = {
                [CLKID_HIFI_PLL_DCO]            = &axg_hifi_pll_dco.hw,
                [CLKID_PCIE_PLL_DCO]            = &axg_pcie_pll_dco.hw,
                [CLKID_PCIE_PLL_OD]             = &axg_pcie_pll_od.hw,
+               [CLKID_VPU_0_DIV]               = &axg_vpu_0_div.hw,
+               [CLKID_VPU_0_SEL]               = &axg_vpu_0_sel.hw,
+               [CLKID_VPU_0]                   = &axg_vpu_0.hw,
+               [CLKID_VPU_1_DIV]               = &axg_vpu_1_div.hw,
+               [CLKID_VPU_1_SEL]               = &axg_vpu_1_sel.hw,
+               [CLKID_VPU_1]                   = &axg_vpu_1.hw,
+               [CLKID_VPU]                     = &axg_vpu.hw,
+               [CLKID_VAPB_0_DIV]              = &axg_vapb_0_div.hw,
+               [CLKID_VAPB_0_SEL]              = &axg_vapb_0_sel.hw,
+               [CLKID_VAPB_0]                  = &axg_vapb_0.hw,
+               [CLKID_VAPB_1_DIV]              = &axg_vapb_1_div.hw,
+               [CLKID_VAPB_1_SEL]              = &axg_vapb_1_sel.hw,
+               [CLKID_VAPB_1]                  = &axg_vapb_1.hw,
+               [CLKID_VAPB_SEL]                = &axg_vapb_sel.hw,
+               [CLKID_VAPB]                    = &axg_vapb.hw,
+               [CLKID_VCLK]                    = &axg_vclk.hw,
+               [CLKID_VCLK2]                   = &axg_vclk2.hw,
+               [CLKID_VCLK_SEL]                = &axg_vclk_sel.hw,
+               [CLKID_VCLK2_SEL]               = &axg_vclk2_sel.hw,
+               [CLKID_VCLK_INPUT]              = &axg_vclk_input.hw,
+               [CLKID_VCLK2_INPUT]             = &axg_vclk2_input.hw,
+               [CLKID_VCLK_DIV]                = &axg_vclk_div.hw,
+               [CLKID_VCLK2_DIV]               = &axg_vclk2_div.hw,
+               [CLKID_VCLK_DIV2_EN]            = &axg_vclk_div2_en.hw,
+               [CLKID_VCLK_DIV4_EN]            = &axg_vclk_div4_en.hw,
+               [CLKID_VCLK_DIV6_EN]            = &axg_vclk_div6_en.hw,
+               [CLKID_VCLK_DIV12_EN]           = &axg_vclk_div12_en.hw,
+               [CLKID_VCLK2_DIV2_EN]           = &axg_vclk2_div2_en.hw,
+               [CLKID_VCLK2_DIV4_EN]           = &axg_vclk2_div4_en.hw,
+               [CLKID_VCLK2_DIV6_EN]           = &axg_vclk2_div6_en.hw,
+               [CLKID_VCLK2_DIV12_EN]          = &axg_vclk2_div12_en.hw,
+               [CLKID_VCLK_DIV1]               = &axg_vclk_div1.hw,
+               [CLKID_VCLK_DIV2]               = &axg_vclk_div2.hw,
+               [CLKID_VCLK_DIV4]               = &axg_vclk_div4.hw,
+               [CLKID_VCLK_DIV6]               = &axg_vclk_div6.hw,
+               [CLKID_VCLK_DIV12]              = &axg_vclk_div12.hw,
+               [CLKID_VCLK2_DIV1]              = &axg_vclk2_div1.hw,
+               [CLKID_VCLK2_DIV2]              = &axg_vclk2_div2.hw,
+               [CLKID_VCLK2_DIV4]              = &axg_vclk2_div4.hw,
+               [CLKID_VCLK2_DIV6]              = &axg_vclk2_div6.hw,
+               [CLKID_VCLK2_DIV12]             = &axg_vclk2_div12.hw,
+               [CLKID_CTS_ENCL_SEL]            = &axg_cts_encl_sel.hw,
+               [CLKID_CTS_ENCL]                = &axg_cts_encl.hw,
+               [CLKID_VDIN_MEAS_SEL]           = &axg_vdin_meas_sel.hw,
+               [CLKID_VDIN_MEAS_DIV]           = &axg_vdin_meas_div.hw,
+               [CLKID_VDIN_MEAS]               = &axg_vdin_meas.hw,
                [NR_CLKS]                       = NULL,
        },
        .num = NR_CLKS,
@@ -1341,6 +2125,42 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
        &axg_hifi_pll_dco,
        &axg_pcie_pll_dco,
        &axg_pcie_pll_od,
+       &axg_vpu_0_div,
+       &axg_vpu_0_sel,
+       &axg_vpu_0,
+       &axg_vpu_1_div,
+       &axg_vpu_1_sel,
+       &axg_vpu_1,
+       &axg_vpu,
+       &axg_vapb_0_div,
+       &axg_vapb_0_sel,
+       &axg_vapb_0,
+       &axg_vapb_1_div,
+       &axg_vapb_1_sel,
+       &axg_vapb_1,
+       &axg_vapb_sel,
+       &axg_vapb,
+       &axg_vclk,
+       &axg_vclk2,
+       &axg_vclk_sel,
+       &axg_vclk2_sel,
+       &axg_vclk_input,
+       &axg_vclk2_input,
+       &axg_vclk_div,
+       &axg_vclk2_div,
+       &axg_vclk_div2_en,
+       &axg_vclk_div4_en,
+       &axg_vclk_div6_en,
+       &axg_vclk_div12_en,
+       &axg_vclk2_div2_en,
+       &axg_vclk2_div4_en,
+       &axg_vclk2_div6_en,
+       &axg_vclk2_div12_en,
+       &axg_cts_encl_sel,
+       &axg_cts_encl,
+       &axg_vdin_meas_sel,
+       &axg_vdin_meas_div,
+       &axg_vdin_meas,
 };
 
 static const struct meson_eeclkc_data axg_clkc_data = {
@@ -1354,6 +2174,7 @@ static const struct of_device_id clkc_match_table[] = {
        { .compatible = "amlogic,axg-clkc", .data = &axg_clkc_data },
        {}
 };
+MODULE_DEVICE_TABLE(of, clkc_match_table);
 
 static struct platform_driver axg_driver = {
        .probe          = meson_eeclkc_probe,
@@ -1363,4 +2184,5 @@ static struct platform_driver axg_driver = {
        },
 };
 
-builtin_platform_driver(axg_driver);
+module_platform_driver(axg_driver);
+MODULE_LICENSE("GPL v2");
index 0431dabac6294e43e29adf38dcbe3cfd77a8a685..481b307ea3cbbb95c8d929f06ea9bfe94e733a96 100644 (file)
 #define CLKID_HIFI_PLL_DCO                     88
 #define CLKID_PCIE_PLL_DCO                     89
 #define CLKID_PCIE_PLL_OD                      90
+#define CLKID_VPU_0_DIV                                91
+#define CLKID_VPU_1_DIV                                94
+#define CLKID_VAPB_0_DIV                       98
+#define CLKID_VAPB_1_DIV                       101
+#define CLKID_VCLK_SEL                         108
+#define CLKID_VCLK2_SEL                                109
+#define CLKID_VCLK_INPUT                       110
+#define CLKID_VCLK2_INPUT                      111
+#define CLKID_VCLK_DIV                         112
+#define CLKID_VCLK2_DIV                                113
+#define CLKID_VCLK_DIV2_EN                     114
+#define CLKID_VCLK_DIV4_EN                     115
+#define CLKID_VCLK_DIV6_EN                     116
+#define CLKID_VCLK_DIV12_EN                    117
+#define CLKID_VCLK2_DIV2_EN                    118
+#define CLKID_VCLK2_DIV4_EN                    119
+#define CLKID_VCLK2_DIV6_EN                    120
+#define CLKID_VCLK2_DIV12_EN                   121
+#define CLKID_CTS_ENCL_SEL                     132
+#define CLKID_VDIN_MEAS_SEL                    134
+#define CLKID_VDIN_MEAS_DIV                    135
 
-#define NR_CLKS                                        91
+#define NR_CLKS                                        137
 
 /* include the CLKIDs that have been made part of the DT binding */
 #include <dt-bindings/clock/axg-clkc.h>
index 62499563e4f5a5f2942cbcadaf624376c82ff9e9..b52990e574d2a5fc88e48a3dab69f98e12fb0e65 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/platform_device.h>
 #include <linux/reset-controller.h>
 #include <linux/mfd/syscon.h>
+#include <linux/module.h>
 #include "meson-aoclk.h"
 #include "g12a-aoclk.h"
 
@@ -461,6 +462,7 @@ static const struct of_device_id g12a_aoclkc_match_table[] = {
        },
        { }
 };
+MODULE_DEVICE_TABLE(of, g12a_aoclkc_match_table);
 
 static struct platform_driver g12a_aoclkc_driver = {
        .probe          = meson_aoclkc_probe,
@@ -470,4 +472,5 @@ static struct platform_driver g12a_aoclkc_driver = {
        },
 };
 
-builtin_platform_driver(g12a_aoclkc_driver);
+module_platform_driver(g12a_aoclkc_driver);
+MODULE_LICENSE("GPL v2");
index b814d44917a5db9d471da8c9086afd5e17aa08cd..b080359b4645eadc4d36dede77db9d7091cd8618 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/module.h>
 
 #include "clk-mpll.h"
 #include "clk-pll.h"
@@ -3657,6 +3658,68 @@ static struct clk_regmap g12a_hdmi_tx = {
        },
 };
 
+/* MIPI DSI Host Clocks */
+
+static const struct clk_hw *g12a_mipi_dsi_pxclk_parent_hws[] = {
+       &g12a_vid_pll.hw,
+       &g12a_gp0_pll.hw,
+       &g12a_hifi_pll.hw,
+       &g12a_mpll1.hw,
+       &g12a_fclk_div2.hw,
+       &g12a_fclk_div2p5.hw,
+       &g12a_fclk_div3.hw,
+       &g12a_fclk_div7.hw,
+};
+
+static struct clk_regmap g12a_mipi_dsi_pxclk_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_MIPIDSI_PHY_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 12,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mipi_dsi_pxclk_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_hws = g12a_mipi_dsi_pxclk_parent_hws,
+               .num_parents = ARRAY_SIZE(g12a_mipi_dsi_pxclk_parent_hws),
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap g12a_mipi_dsi_pxclk_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_MIPIDSI_PHY_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mipi_dsi_pxclk_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &g12a_mipi_dsi_pxclk_sel.hw
+               },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_mipi_dsi_pxclk = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MIPIDSI_PHY_CLK_CNTL,
+               .bit_idx = 8,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "mipi_dsi_pxclk",
+               .ops = &clk_regmap_gate_ops,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &g12a_mipi_dsi_pxclk_div.hw
+               },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
 /* HDMI Clocks */
 
 static const struct clk_parent_data g12a_hdmi_parent_data[] = {
@@ -4402,6 +4465,9 @@ static struct clk_hw_onecell_data g12a_hw_onecell_data = {
                [CLKID_SPICC1_SCLK_SEL]         = &g12a_spicc1_sclk_sel.hw,
                [CLKID_SPICC1_SCLK_DIV]         = &g12a_spicc1_sclk_div.hw,
                [CLKID_SPICC1_SCLK]             = &g12a_spicc1_sclk.hw,
+               [CLKID_MIPI_DSI_PXCLK_SEL]      = &g12a_mipi_dsi_pxclk_sel.hw,
+               [CLKID_MIPI_DSI_PXCLK_DIV]      = &g12a_mipi_dsi_pxclk_div.hw,
+               [CLKID_MIPI_DSI_PXCLK]          = &g12a_mipi_dsi_pxclk.hw,
                [NR_CLKS]                       = NULL,
        },
        .num = NR_CLKS,
@@ -4657,6 +4723,9 @@ static struct clk_hw_onecell_data g12b_hw_onecell_data = {
                [CLKID_SPICC1_SCLK_SEL]         = &g12a_spicc1_sclk_sel.hw,
                [CLKID_SPICC1_SCLK_DIV]         = &g12a_spicc1_sclk_div.hw,
                [CLKID_SPICC1_SCLK]             = &g12a_spicc1_sclk.hw,
+               [CLKID_MIPI_DSI_PXCLK_SEL]      = &g12a_mipi_dsi_pxclk_sel.hw,
+               [CLKID_MIPI_DSI_PXCLK_DIV]      = &g12a_mipi_dsi_pxclk_div.hw,
+               [CLKID_MIPI_DSI_PXCLK]          = &g12a_mipi_dsi_pxclk.hw,
                [NR_CLKS]                       = NULL,
        },
        .num = NR_CLKS,
@@ -4903,6 +4972,9 @@ static struct clk_hw_onecell_data sm1_hw_onecell_data = {
                [CLKID_NNA_CORE_CLK_SEL]        = &sm1_nna_core_clk_sel.hw,
                [CLKID_NNA_CORE_CLK_DIV]        = &sm1_nna_core_clk_div.hw,
                [CLKID_NNA_CORE_CLK]            = &sm1_nna_core_clk.hw,
+               [CLKID_MIPI_DSI_PXCLK_SEL]      = &g12a_mipi_dsi_pxclk_sel.hw,
+               [CLKID_MIPI_DSI_PXCLK_DIV]      = &g12a_mipi_dsi_pxclk_div.hw,
+               [CLKID_MIPI_DSI_PXCLK]          = &g12a_mipi_dsi_pxclk.hw,
                [NR_CLKS]                       = NULL,
        },
        .num = NR_CLKS,
@@ -5150,16 +5222,20 @@ static struct clk_regmap *const g12a_clk_regmaps[] = {
        &sm1_nna_core_clk_sel,
        &sm1_nna_core_clk_div,
        &sm1_nna_core_clk,
+       &g12a_mipi_dsi_pxclk_sel,
+       &g12a_mipi_dsi_pxclk_div,
+       &g12a_mipi_dsi_pxclk,
 };
 
 static const struct reg_sequence g12a_init_regs[] = {
        { .reg = HHI_MPLL_CNTL0,        .def = 0x00000543 },
 };
 
-static int meson_g12a_dvfs_setup_common(struct platform_device *pdev,
+#define DVFS_CON_ID "dvfs"
+
+static int meson_g12a_dvfs_setup_common(struct device *dev,
                                        struct clk_hw **hws)
 {
-       const char *notifier_clk_name;
        struct clk *notifier_clk;
        struct clk_hw *xtal;
        int ret;
@@ -5168,21 +5244,22 @@ static int meson_g12a_dvfs_setup_common(struct platform_device *pdev,
 
        /* Setup clock notifier for cpu_clk_postmux0 */
        g12a_cpu_clk_postmux0_nb_data.xtal = xtal;
-       notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk_postmux0.hw);
-       notifier_clk = __clk_lookup(notifier_clk_name);
-       ret = clk_notifier_register(notifier_clk,
-                                   &g12a_cpu_clk_postmux0_nb_data.nb);
+       notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk_postmux0.hw,
+                                          DVFS_CON_ID);
+       ret = devm_clk_notifier_register(dev, notifier_clk,
+                                        &g12a_cpu_clk_postmux0_nb_data.nb);
        if (ret) {
-               dev_err(&pdev->dev, "failed to register the cpu_clk_postmux0 notifier\n");
+               dev_err(dev, "failed to register the cpu_clk_postmux0 notifier\n");
                return ret;
        }
 
        /* Setup clock notifier for cpu_clk_dyn mux */
-       notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk_dyn.hw);
-       notifier_clk = __clk_lookup(notifier_clk_name);
-       ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
+       notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk_dyn.hw,
+                                          DVFS_CON_ID);
+       ret = devm_clk_notifier_register(dev, notifier_clk,
+                                        &g12a_cpu_clk_mux_nb);
        if (ret) {
-               dev_err(&pdev->dev, "failed to register the cpu_clk_dyn notifier\n");
+               dev_err(dev, "failed to register the cpu_clk_dyn notifier\n");
                return ret;
        }
 
@@ -5192,33 +5269,34 @@ static int meson_g12a_dvfs_setup_common(struct platform_device *pdev,
 static int meson_g12b_dvfs_setup(struct platform_device *pdev)
 {
        struct clk_hw **hws = g12b_hw_onecell_data.hws;
-       const char *notifier_clk_name;
+       struct device *dev = &pdev->dev;
        struct clk *notifier_clk;
        struct clk_hw *xtal;
        int ret;
 
-       ret = meson_g12a_dvfs_setup_common(pdev, hws);
+       ret = meson_g12a_dvfs_setup_common(dev, hws);
        if (ret)
                return ret;
 
        xtal = clk_hw_get_parent_by_index(hws[CLKID_CPU_CLK_DYN1_SEL], 0);
 
        /* Setup clock notifier for cpu_clk mux */
-       notifier_clk_name = clk_hw_get_name(&g12b_cpu_clk.hw);
-       notifier_clk = __clk_lookup(notifier_clk_name);
-       ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
+       notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpu_clk.hw,
+                                          DVFS_CON_ID);
+       ret = devm_clk_notifier_register(dev, notifier_clk,
+                                        &g12a_cpu_clk_mux_nb);
        if (ret) {
-               dev_err(&pdev->dev, "failed to register the cpu_clk notifier\n");
+               dev_err(dev, "failed to register the cpu_clk notifier\n");
                return ret;
        }
 
        /* Setup clock notifier for sys1_pll */
-       notifier_clk_name = clk_hw_get_name(&g12b_sys1_pll.hw);
-       notifier_clk = __clk_lookup(notifier_clk_name);
-       ret = clk_notifier_register(notifier_clk,
-                                   &g12b_cpu_clk_sys1_pll_nb_data.nb);
+       notifier_clk = devm_clk_hw_get_clk(dev, &g12b_sys1_pll.hw,
+                                          DVFS_CON_ID);
+       ret = devm_clk_notifier_register(dev, notifier_clk,
+                                        &g12b_cpu_clk_sys1_pll_nb_data.nb);
        if (ret) {
-               dev_err(&pdev->dev, "failed to register the sys1_pll notifier\n");
+               dev_err(dev, "failed to register the sys1_pll notifier\n");
                return ret;
        }
 
@@ -5226,40 +5304,39 @@ static int meson_g12b_dvfs_setup(struct platform_device *pdev)
 
        /* Setup clock notifier for cpub_clk_postmux0 */
        g12b_cpub_clk_postmux0_nb_data.xtal = xtal;
-       notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk_postmux0.hw);
-       notifier_clk = __clk_lookup(notifier_clk_name);
-       ret = clk_notifier_register(notifier_clk,
-                                   &g12b_cpub_clk_postmux0_nb_data.nb);
+       notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk_postmux0.hw,
+                                          DVFS_CON_ID);
+       ret = devm_clk_notifier_register(dev, notifier_clk,
+                                        &g12b_cpub_clk_postmux0_nb_data.nb);
        if (ret) {
-               dev_err(&pdev->dev, "failed to register the cpub_clk_postmux0 notifier\n");
+               dev_err(dev, "failed to register the cpub_clk_postmux0 notifier\n");
                return ret;
        }
 
        /* Setup clock notifier for cpub_clk_dyn mux */
-       notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk_dyn.hw);
-       notifier_clk = __clk_lookup(notifier_clk_name);
-       ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
+       notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk_dyn.hw, "dvfs");
+       ret = devm_clk_notifier_register(dev, notifier_clk,
+                                        &g12a_cpu_clk_mux_nb);
        if (ret) {
-               dev_err(&pdev->dev, "failed to register the cpub_clk_dyn notifier\n");
+               dev_err(dev, "failed to register the cpub_clk_dyn notifier\n");
                return ret;
        }
 
        /* Setup clock notifier for cpub_clk mux */
-       notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk.hw);
-       notifier_clk = __clk_lookup(notifier_clk_name);
-       ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
+       notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk.hw, DVFS_CON_ID);
+       ret = devm_clk_notifier_register(dev, notifier_clk,
+                                        &g12a_cpu_clk_mux_nb);
        if (ret) {
-               dev_err(&pdev->dev, "failed to register the cpub_clk notifier\n");
+               dev_err(dev, "failed to register the cpub_clk notifier\n");
                return ret;
        }
 
        /* Setup clock notifier for sys_pll */
-       notifier_clk_name = clk_hw_get_name(&g12a_sys_pll.hw);
-       notifier_clk = __clk_lookup(notifier_clk_name);
-       ret = clk_notifier_register(notifier_clk,
-                                   &g12b_cpub_clk_sys_pll_nb_data.nb);
+       notifier_clk = devm_clk_hw_get_clk(dev, &g12a_sys_pll.hw, DVFS_CON_ID);
+       ret = devm_clk_notifier_register(dev, notifier_clk,
+                                        &g12b_cpub_clk_sys_pll_nb_data.nb);
        if (ret) {
-               dev_err(&pdev->dev, "failed to register the sys_pll notifier\n");
+               dev_err(dev, "failed to register the sys_pll notifier\n");
                return ret;
        }
 
@@ -5269,29 +5346,29 @@ static int meson_g12b_dvfs_setup(struct platform_device *pdev)
 static int meson_g12a_dvfs_setup(struct platform_device *pdev)
 {
        struct clk_hw **hws = g12a_hw_onecell_data.hws;
-       const char *notifier_clk_name;
+       struct device *dev = &pdev->dev;
        struct clk *notifier_clk;
        int ret;
 
-       ret = meson_g12a_dvfs_setup_common(pdev, hws);
+       ret = meson_g12a_dvfs_setup_common(dev, hws);
        if (ret)
                return ret;
 
        /* Setup clock notifier for cpu_clk mux */
-       notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk.hw);
-       notifier_clk = __clk_lookup(notifier_clk_name);
-       ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb);
+       notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk.hw, DVFS_CON_ID);
+       ret = devm_clk_notifier_register(dev, notifier_clk,
+                                   &g12a_cpu_clk_mux_nb);
        if (ret) {
-               dev_err(&pdev->dev, "failed to register the cpu_clk notifier\n");
+               dev_err(dev, "failed to register the cpu_clk notifier\n");
                return ret;
        }
 
        /* Setup clock notifier for sys_pll */
-       notifier_clk_name = clk_hw_get_name(&g12a_sys_pll.hw);
-       notifier_clk = __clk_lookup(notifier_clk_name);
-       ret = clk_notifier_register(notifier_clk, &g12a_sys_pll_nb_data.nb);
+       notifier_clk = devm_clk_hw_get_clk(dev, &g12a_sys_pll.hw, DVFS_CON_ID);
+       ret = devm_clk_notifier_register(dev, notifier_clk,
+                                        &g12a_sys_pll_nb_data.nb);
        if (ret) {
-               dev_err(&pdev->dev, "failed to register the sys_pll notifier\n");
+               dev_err(dev, "failed to register the sys_pll notifier\n");
                return ret;
        }
 
@@ -5370,6 +5447,7 @@ static const struct of_device_id clkc_match_table[] = {
        },
        {}
 };
+MODULE_DEVICE_TABLE(of, clkc_match_table);
 
 static struct platform_driver g12a_driver = {
        .probe          = meson_g12a_probe,
@@ -5379,4 +5457,5 @@ static struct platform_driver g12a_driver = {
        },
 };
 
-builtin_platform_driver(g12a_driver);
+module_platform_driver(g12a_driver);
+MODULE_LICENSE("GPL v2");
index 69b6a69549c77581a098ff23ac8579e402e0b711..a97613df38b347d02d184d1a73c985fd65be6810 100644 (file)
 #define CLKID_NNA_AXI_CLK_DIV                  263
 #define CLKID_NNA_CORE_CLK_SEL                 265
 #define CLKID_NNA_CORE_CLK_DIV                 266
+#define CLKID_MIPI_DSI_PXCLK_DIV               268
 
-#define NR_CLKS                                        268
+#define NR_CLKS                                        271
 
 /* include the CLKIDs that have been made part of the DT binding */
 #include <dt-bindings/clock/g12a-clkc.h>
index e940861a396b591c190da58042b108f2e81ac9e8..fce95cf89836f26701bc2b2702b53b989a5db6eb 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include <linux/platform_device.h>
 #include <linux/mfd/syscon.h>
+#include <linux/module.h>
 #include "meson-aoclk.h"
 #include "gxbb-aoclk.h"
 
@@ -287,6 +288,7 @@ static const struct of_device_id gxbb_aoclkc_match_table[] = {
        },
        { }
 };
+MODULE_DEVICE_TABLE(of, gxbb_aoclkc_match_table);
 
 static struct platform_driver gxbb_aoclkc_driver = {
        .probe          = meson_aoclkc_probe,
@@ -295,4 +297,5 @@ static struct platform_driver gxbb_aoclkc_driver = {
                .of_match_table = gxbb_aoclkc_match_table,
        },
 };
-builtin_platform_driver(gxbb_aoclkc_driver);
+module_platform_driver(gxbb_aoclkc_driver);
+MODULE_LICENSE("GPL v2");
index 0a68af6eec3ddf31e470fe52031410a297d53fb8..d6eed760327d031d1df0730eb016ddf14a9d211c 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/module.h>
 
 #include "gxbb.h"
 #include "clk-regmap.h"
@@ -3519,6 +3520,7 @@ static const struct of_device_id clkc_match_table[] = {
        { .compatible = "amlogic,gxl-clkc", .data = &gxl_clkc_data },
        {},
 };
+MODULE_DEVICE_TABLE(of, clkc_match_table);
 
 static struct platform_driver gxbb_driver = {
        .probe          = meson_eeclkc_probe,
@@ -3528,4 +3530,5 @@ static struct platform_driver gxbb_driver = {
        },
 };
 
-builtin_platform_driver(gxbb_driver);
+module_platform_driver(gxbb_driver);
+MODULE_LICENSE("GPL v2");
index 3a6d84cd66012dc1e36cbf7054c0a319292e280d..27cd2c1f3f6123fceb5216bffccf159d3c0d318f 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/reset-controller.h>
 #include <linux/mfd/syscon.h>
 #include <linux/of_device.h>
+#include <linux/module.h>
+
 #include <linux/slab.h>
 #include "meson-aoclk.h"
 
@@ -84,3 +86,5 @@ int meson_aoclkc_probe(struct platform_device *pdev)
        return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
                (void *) data->hw_data);
 }
+EXPORT_SYMBOL_GPL(meson_aoclkc_probe);
+MODULE_LICENSE("GPL v2");
index a7cb1e7aedc463f83df2008a47aedd39bd53cfd6..8d5a5dab955a85c5ef7042d887def12cda1de439 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
+#include <linux/module.h>
 
 #include "clk-regmap.h"
 #include "meson-eeclk.h"
@@ -54,3 +55,5 @@ int meson_eeclkc_probe(struct platform_device *pdev)
        return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
                                           data->hw_onecell_data);
 }
+EXPORT_SYMBOL_GPL(meson_eeclkc_probe);
+MODULE_LICENSE("GPL v2");
index 3a965bd326d5ff9458f4cf9b73ff4ba5890bb593..d32bb12cd8d0c06123e22956161836c7e8be4e48 100644 (file)
@@ -44,7 +44,7 @@ config QCOM_CLK_APCC_MSM8996
        help
          Support for the CPU clock controller on msm8996 devices.
          Say Y if you want to support CPU clock scaling using CPUfreq
-         drivers for dyanmic power management.
+         drivers for dynamic power management.
 
 config QCOM_CLK_RPM
        tristate "RPM based Clock Controller"
@@ -290,6 +290,15 @@ config QCS_GCC_404
          Say Y if you want to use multimedia devices or peripheral
          devices such as UART, SPI, I2C, USB, SD/eMMC, PCIe etc.
 
+config SC_CAMCC_7180
+       tristate "SC7180 Camera Clock Controller"
+       select SC_GCC_7180
+       help
+         Support for the camera clock controller on Qualcomm Technologies, Inc
+         SC7180 devices.
+         Say Y if you want to support camera devices and functionality such as
+         capturing pictures.
+
 config SC_DISPCC_7180
        tristate "SC7180 Display Clock Controller"
        select SC_GCC_7180
@@ -413,6 +422,14 @@ config SDM_LPASSCC_845
          Say Y if you want to use the LPASS branch clocks of the LPASS clock
          controller to reset the LPASS subsystem.
 
+config SDX_GCC_55
+       tristate "SDX55 Global Clock Controller"
+       select QCOM_GDSC
+       help
+         Support for the global clock controller on SDX55 devices.
+         Say Y if you want to use peripheral devices such as UART,
+         SPI, I2C, USB, SD/UFS, PCIe etc.
+
 config SM_DISPCC_8250
        tristate "SM8150 and SM8250 Display Clock Controller"
        depends on SM_GCC_8150 || SM_GCC_8250
@@ -502,4 +519,10 @@ config KRAITCC
          Support for the Krait CPU clocks on Qualcomm devices.
          Say Y if you want to support CPU frequency scaling.
 
+config CLK_GFM_LPASS_SM8250
+       tristate "SM8250 GFM LPASS Clocks"
+       help
+         Support for the Glitch Free Mux (GFM) Low power audio
+          subsystem (LPASS) clocks found on SM8250 SoCs.
+
 endif
index 11ae86febe873ce6f4439dbb26266ba8b5510075..9e5e0e3cb7b48e79822d9483d7bcf909e864be3b 100644 (file)
@@ -19,6 +19,7 @@ clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
 # Keep alphabetically sorted by config
 obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
 obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
+obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o
 obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o
 obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o
 obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
@@ -51,6 +52,7 @@ obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
 obj-$(CONFIG_QCS_GCC_404) += gcc-qcs404.o
 obj-$(CONFIG_QCS_Q6SSTOP_404) += q6sstop-qcs404.o
 obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o
+obj-$(CONFIG_SC_CAMCC_7180) += camcc-sc7180.o
 obj-$(CONFIG_SC_DISPCC_7180) += dispcc-sc7180.o
 obj-$(CONFIG_SC_GCC_7180) += gcc-sc7180.o
 obj-$(CONFIG_SC_GPUCC_7180) += gpucc-sc7180.o
@@ -64,6 +66,7 @@ obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
 obj-$(CONFIG_SDM_GPUCC_845) += gpucc-sdm845.o
 obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o
 obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
+obj-$(CONFIG_SDX_GCC_55) += gcc-sdx55.o
 obj-$(CONFIG_SM_DISPCC_8250) += dispcc-sm8250.o
 obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o
 obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o
diff --git a/drivers/clk/qcom/camcc-sc7180.c b/drivers/clk/qcom/camcc-sc7180.c
new file mode 100644 (file)
index 0000000..dbac565
--- /dev/null
@@ -0,0 +1,1732 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,camcc-sc7180.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+       P_BI_TCXO,
+       P_CAM_CC_PLL0_OUT_EVEN,
+       P_CAM_CC_PLL1_OUT_EVEN,
+       P_CAM_CC_PLL2_OUT_AUX,
+       P_CAM_CC_PLL2_OUT_EARLY,
+       P_CAM_CC_PLL3_OUT_MAIN,
+       P_CORE_BI_PLL_TEST_SE,
+};
+
+static const struct pll_vco agera_vco[] = {
+       { 600000000, 3300000000UL, 0 },
+};
+
+static const struct pll_vco fabia_vco[] = {
+       { 249600000, 2000000000UL, 0 },
+};
+
+/* 600MHz configuration */
+static const struct alpha_pll_config cam_cc_pll0_config = {
+       .l = 0x1f,
+       .alpha = 0x4000,
+       .config_ctl_val = 0x20485699,
+       .config_ctl_hi_val = 0x00002067,
+       .test_ctl_val = 0x40000000,
+       .user_ctl_hi_val = 0x00004805,
+       .user_ctl_val = 0x00000001,
+};
+
+static struct clk_alpha_pll cam_cc_pll0 = {
+       .offset = 0x0,
+       .vco_table = fabia_vco,
+       .num_vco = ARRAY_SIZE(fabia_vco),
+       .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
+       .clkr = {
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_pll0",
+                       .parent_data = &(const struct clk_parent_data){
+                               .fw_name = "bi_tcxo",
+                       },
+                       .num_parents = 1,
+                       .ops = &clk_alpha_pll_fabia_ops,
+               },
+       },
+};
+
+/* 860MHz configuration */
+static const struct alpha_pll_config cam_cc_pll1_config = {
+       .l = 0x2a,
+       .alpha = 0x1555,
+       .config_ctl_val = 0x20485699,
+       .config_ctl_hi_val = 0x00002067,
+       .test_ctl_val = 0x40000000,
+       .user_ctl_hi_val = 0x00004805,
+};
+
+static struct clk_alpha_pll cam_cc_pll1 = {
+       .offset = 0x1000,
+       .vco_table = fabia_vco,
+       .num_vco = ARRAY_SIZE(fabia_vco),
+       .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
+       .clkr = {
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_pll1",
+                       .parent_data = &(const struct clk_parent_data){
+                               .fw_name = "bi_tcxo",
+                       },
+                       .num_parents = 1,
+                       .ops = &clk_alpha_pll_fabia_ops,
+               },
+       },
+};
+
+/* 1920MHz configuration */
+static const struct alpha_pll_config cam_cc_pll2_config = {
+       .l = 0x64,
+       .config_ctl_val = 0x20000800,
+       .config_ctl_hi_val = 0x400003D2,
+       .test_ctl_val = 0x04000400,
+       .test_ctl_hi_val = 0x00004000,
+       .user_ctl_val = 0x0000030F,
+};
+
+static struct clk_alpha_pll cam_cc_pll2 = {
+       .offset = 0x2000,
+       .vco_table = agera_vco,
+       .num_vco = ARRAY_SIZE(agera_vco),
+       .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_AGERA],
+       .clkr = {
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_pll2",
+                       .parent_data = &(const struct clk_parent_data){
+                               .fw_name = "bi_tcxo",
+                       },
+                       .num_parents = 1,
+                       .ops = &clk_alpha_pll_agera_ops,
+               },
+       },
+};
+
+static struct clk_fixed_factor cam_cc_pll2_out_early = {
+       .mult = 1,
+       .div = 2,
+       .hw.init = &(struct clk_init_data){
+               .name = "cam_cc_pll2_out_early",
+               .parent_names = (const char *[]){ "cam_cc_pll2" },
+               .num_parents = 1,
+               .ops = &clk_fixed_factor_ops,
+       },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll2_out_aux[] = {
+       { 0x3, 4 },
+       { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll2_out_aux = {
+       .offset = 0x2000,
+       .post_div_shift = 8,
+       .post_div_table = post_div_table_cam_cc_pll2_out_aux,
+       .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll2_out_aux),
+       .width = 2,
+       .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_AGERA],
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_pll2_out_aux",
+               .parent_data = &(const struct clk_parent_data){
+                       .hw = &cam_cc_pll2.clkr.hw,
+               },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+               .ops = &clk_alpha_pll_postdiv_ops,
+       },
+};
+
+/* 1080MHz configuration */
+static const struct alpha_pll_config cam_cc_pll3_config = {
+       .l = 0x38,
+       .alpha = 0x4000,
+       .config_ctl_val = 0x20485699,
+       .config_ctl_hi_val = 0x00002067,
+       .test_ctl_val = 0x40000000,
+       .user_ctl_hi_val = 0x00004805,
+};
+
+static struct clk_alpha_pll cam_cc_pll3 = {
+       .offset = 0x3000,
+       .vco_table = fabia_vco,
+       .num_vco = ARRAY_SIZE(fabia_vco),
+       .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
+       .clkr = {
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_pll3",
+                       .parent_data = &(const struct clk_parent_data){
+                               .fw_name = "bi_tcxo",
+                       },
+                       .num_parents = 1,
+                       .ops = &clk_alpha_pll_fabia_ops,
+               },
+       },
+};
+
+static const struct parent_map cam_cc_parent_map_0[] = {
+       { P_BI_TCXO, 0 },
+       { P_CAM_CC_PLL1_OUT_EVEN, 2 },
+       { P_CAM_CC_PLL0_OUT_EVEN, 6 },
+       { P_CORE_BI_PLL_TEST_SE, 7 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_0[] = {
+       { .fw_name = "bi_tcxo" },
+       { .hw = &cam_cc_pll1.clkr.hw },
+       { .hw = &cam_cc_pll0.clkr.hw },
+       { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" },
+};
+
+static const struct parent_map cam_cc_parent_map_1[] = {
+       { P_BI_TCXO, 0 },
+       { P_CAM_CC_PLL2_OUT_AUX, 1 },
+       { P_CORE_BI_PLL_TEST_SE, 7 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_1[] = {
+       { .fw_name = "bi_tcxo" },
+       { .hw = &cam_cc_pll2_out_aux.clkr.hw },
+       { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" },
+};
+
+static const struct parent_map cam_cc_parent_map_2[] = {
+       { P_BI_TCXO, 0 },
+       { P_CAM_CC_PLL2_OUT_EARLY, 4 },
+       { P_CAM_CC_PLL3_OUT_MAIN, 5 },
+       { P_CAM_CC_PLL0_OUT_EVEN, 6 },
+       { P_CORE_BI_PLL_TEST_SE, 7 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_2[] = {
+       { .fw_name = "bi_tcxo" },
+       { .hw = &cam_cc_pll2_out_early.hw },
+       { .hw = &cam_cc_pll3.clkr.hw },
+       { .hw = &cam_cc_pll0.clkr.hw },
+       { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" },
+};
+
+static const struct parent_map cam_cc_parent_map_3[] = {
+       { P_BI_TCXO, 0 },
+       { P_CAM_CC_PLL1_OUT_EVEN, 2 },
+       { P_CAM_CC_PLL2_OUT_EARLY, 4 },
+       { P_CAM_CC_PLL3_OUT_MAIN, 5 },
+       { P_CAM_CC_PLL0_OUT_EVEN, 6 },
+       { P_CORE_BI_PLL_TEST_SE, 7 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_3[] = {
+       { .fw_name = "bi_tcxo" },
+       { .hw = &cam_cc_pll1.clkr.hw },
+       { .hw = &cam_cc_pll2_out_early.hw },
+       { .hw = &cam_cc_pll3.clkr.hw },
+       { .hw = &cam_cc_pll0.clkr.hw },
+       { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" },
+};
+
+static const struct parent_map cam_cc_parent_map_4[] = {
+       { P_BI_TCXO, 0 },
+       { P_CAM_CC_PLL3_OUT_MAIN, 5 },
+       { P_CAM_CC_PLL0_OUT_EVEN, 6 },
+       { P_CORE_BI_PLL_TEST_SE, 7 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_4[] = {
+       { .fw_name = "bi_tcxo" },
+       { .hw = &cam_cc_pll3.clkr.hw },
+       { .hw = &cam_cc_pll0.clkr.hw },
+       { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" },
+};
+
+static const struct parent_map cam_cc_parent_map_5[] = {
+       { P_BI_TCXO, 0 },
+       { P_CAM_CC_PLL0_OUT_EVEN, 6 },
+       { P_CORE_BI_PLL_TEST_SE, 7 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_5[] = {
+       { .fw_name = "bi_tcxo" },
+       { .hw = &cam_cc_pll0.clkr.hw },
+       { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" },
+};
+
+static const struct parent_map cam_cc_parent_map_6[] = {
+       { P_BI_TCXO, 0 },
+       { P_CAM_CC_PLL1_OUT_EVEN, 2 },
+       { P_CAM_CC_PLL3_OUT_MAIN, 5 },
+       { P_CAM_CC_PLL0_OUT_EVEN, 6 },
+       { P_CORE_BI_PLL_TEST_SE, 7 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_6[] = {
+       { .fw_name = "bi_tcxo" },
+       { .hw = &cam_cc_pll1.clkr.hw },
+       { .hw = &cam_cc_pll3.clkr.hw },
+       { .hw = &cam_cc_pll0.clkr.hw },
+       { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" },
+};
+
+static const struct freq_tbl ftbl_cam_cc_bps_clk_src[] = {
+       F(200000000, P_CAM_CC_PLL0_OUT_EVEN, 3, 0, 0),
+       F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0),
+       F(432000000, P_CAM_CC_PLL3_OUT_MAIN, 2.5, 0, 0),
+       F(480000000, P_CAM_CC_PLL2_OUT_EARLY, 2, 0, 0),
+       F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cam_cc_bps_clk_src = {
+       .cmd_rcgr = 0x6010,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_2,
+       .freq_tbl = ftbl_cam_cc_bps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_bps_clk_src",
+               .parent_data = cam_cc_parent_data_2,
+               .num_parents = 5,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_cam_cc_cci_0_clk_src[] = {
+       F(37500000, P_CAM_CC_PLL0_OUT_EVEN, 16, 0, 0),
+       F(50000000, P_CAM_CC_PLL0_OUT_EVEN, 12, 0, 0),
+       F(100000000, P_CAM_CC_PLL0_OUT_EVEN, 6, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cam_cc_cci_0_clk_src = {
+       .cmd_rcgr = 0xb0d8,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_5,
+       .freq_tbl = ftbl_cam_cc_cci_0_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_cci_0_clk_src",
+               .parent_data = cam_cc_parent_data_5,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 cam_cc_cci_1_clk_src = {
+       .cmd_rcgr = 0xb14c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_5,
+       .freq_tbl = ftbl_cam_cc_cci_0_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_cci_1_clk_src",
+               .parent_data = cam_cc_parent_data_5,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_cam_cc_cphy_rx_clk_src[] = {
+       F(150000000, P_CAM_CC_PLL0_OUT_EVEN, 4, 0, 0),
+       F(270000000, P_CAM_CC_PLL3_OUT_MAIN, 4, 0, 0),
+       F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cam_cc_cphy_rx_clk_src = {
+       .cmd_rcgr = 0x9064,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_3,
+       .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_cphy_rx_clk_src",
+               .parent_data = cam_cc_parent_data_3,
+               .num_parents = 6,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_cam_cc_csi0phytimer_clk_src[] = {
+       F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = {
+       .cmd_rcgr = 0x5004,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_0,
+       .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_csi0phytimer_clk_src",
+               .parent_data = cam_cc_parent_data_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = {
+       .cmd_rcgr = 0x5028,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_0,
+       .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_csi1phytimer_clk_src",
+               .parent_data = cam_cc_parent_data_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 cam_cc_csi2phytimer_clk_src = {
+       .cmd_rcgr = 0x504c,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_0,
+       .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_csi2phytimer_clk_src",
+               .parent_data = cam_cc_parent_data_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = {
+       .cmd_rcgr = 0x5070,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_0,
+       .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_csi3phytimer_clk_src",
+               .parent_data = cam_cc_parent_data_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_cam_cc_fast_ahb_clk_src[] = {
+       F(100000000, P_CAM_CC_PLL0_OUT_EVEN, 6, 0, 0),
+       F(200000000, P_CAM_CC_PLL0_OUT_EVEN, 3, 0, 0),
+       F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0),
+       F(404000000, P_CAM_CC_PLL1_OUT_EVEN, 2, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cam_cc_fast_ahb_clk_src = {
+       .cmd_rcgr = 0x603c,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_0,
+       .freq_tbl = ftbl_cam_cc_fast_ahb_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_fast_ahb_clk_src",
+               .parent_data = cam_cc_parent_data_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_cam_cc_icp_clk_src[] = {
+       F(240000000, P_CAM_CC_PLL0_OUT_EVEN, 2.5, 0, 0),
+       F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0),
+       F(432000000, P_CAM_CC_PLL3_OUT_MAIN, 2.5, 0, 0),
+       F(480000000, P_CAM_CC_PLL2_OUT_EARLY, 2, 0, 0),
+       F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cam_cc_icp_clk_src = {
+       .cmd_rcgr = 0xb088,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_2,
+       .freq_tbl = ftbl_cam_cc_icp_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_icp_clk_src",
+               .parent_data = cam_cc_parent_data_2,
+               .num_parents = 5,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ife_0_clk_src[] = {
+       F(240000000, P_CAM_CC_PLL0_OUT_EVEN, 2.5, 0, 0),
+       F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0),
+       F(432000000, P_CAM_CC_PLL3_OUT_MAIN, 2.5, 0, 0),
+       F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cam_cc_ife_0_clk_src = {
+       .cmd_rcgr = 0x9010,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_4,
+       .freq_tbl = ftbl_cam_cc_ife_0_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_ife_0_clk_src",
+               .parent_data = cam_cc_parent_data_4,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ife_0_csid_clk_src[] = {
+       F(150000000, P_CAM_CC_PLL0_OUT_EVEN, 4, 0, 0),
+       F(270000000, P_CAM_CC_PLL3_OUT_MAIN, 4, 0, 0),
+       F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0),
+       F(480000000, P_CAM_CC_PLL2_OUT_EARLY, 2, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cam_cc_ife_0_csid_clk_src = {
+       .cmd_rcgr = 0x903c,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_3,
+       .freq_tbl = ftbl_cam_cc_ife_0_csid_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_ife_0_csid_clk_src",
+               .parent_data = cam_cc_parent_data_3,
+               .num_parents = 6,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 cam_cc_ife_1_clk_src = {
+       .cmd_rcgr = 0xa010,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_4,
+       .freq_tbl = ftbl_cam_cc_ife_0_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_ife_1_clk_src",
+               .parent_data = cam_cc_parent_data_4,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 cam_cc_ife_1_csid_clk_src = {
+       .cmd_rcgr = 0xa034,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_3,
+       .freq_tbl = ftbl_cam_cc_ife_0_csid_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_ife_1_csid_clk_src",
+               .parent_data = cam_cc_parent_data_3,
+               .num_parents = 6,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 cam_cc_ife_lite_clk_src = {
+       .cmd_rcgr = 0xb004,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_4,
+       .freq_tbl = ftbl_cam_cc_ife_0_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_ife_lite_clk_src",
+               .parent_data = cam_cc_parent_data_4,
+               .num_parents = 4,
+               .flags = CLK_SET_RATE_PARENT,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = {
+       .cmd_rcgr = 0xb024,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_3,
+       .freq_tbl = ftbl_cam_cc_ife_0_csid_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_ife_lite_csid_clk_src",
+               .parent_data = cam_cc_parent_data_3,
+               .num_parents = 6,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ipe_0_clk_src[] = {
+       F(240000000, P_CAM_CC_PLL0_OUT_EVEN, 2.5, 0, 0),
+       F(360000000, P_CAM_CC_PLL3_OUT_MAIN, 3, 0, 0),
+       F(432000000, P_CAM_CC_PLL3_OUT_MAIN, 2.5, 0, 0),
+       F(540000000, P_CAM_CC_PLL3_OUT_MAIN, 2, 0, 0),
+       F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cam_cc_ipe_0_clk_src = {
+       .cmd_rcgr = 0x7010,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_2,
+       .freq_tbl = ftbl_cam_cc_ipe_0_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_ipe_0_clk_src",
+               .parent_data = cam_cc_parent_data_2,
+               .num_parents = 5,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_cam_cc_jpeg_clk_src[] = {
+       F(66666667, P_CAM_CC_PLL0_OUT_EVEN, 9, 0, 0),
+       F(133333333, P_CAM_CC_PLL0_OUT_EVEN, 4.5, 0, 0),
+       F(216000000, P_CAM_CC_PLL3_OUT_MAIN, 5, 0, 0),
+       F(320000000, P_CAM_CC_PLL2_OUT_EARLY, 3, 0, 0),
+       F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cam_cc_jpeg_clk_src = {
+       .cmd_rcgr = 0xb04c,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_2,
+       .freq_tbl = ftbl_cam_cc_jpeg_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_jpeg_clk_src",
+               .parent_data = cam_cc_parent_data_2,
+               .num_parents = 5,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_cam_cc_lrme_clk_src[] = {
+       F(200000000, P_CAM_CC_PLL0_OUT_EVEN, 3, 0, 0),
+       F(216000000, P_CAM_CC_PLL3_OUT_MAIN, 5, 0, 0),
+       F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0),
+       F(404000000, P_CAM_CC_PLL1_OUT_EVEN, 2, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cam_cc_lrme_clk_src = {
+       .cmd_rcgr = 0xb0f8,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_6,
+       .freq_tbl = ftbl_cam_cc_lrme_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_lrme_clk_src",
+               .parent_data = cam_cc_parent_data_6,
+               .num_parents = 5,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_cam_cc_mclk0_clk_src[] = {
+       F(19200000, P_BI_TCXO, 1, 0, 0),
+       F(24000000, P_CAM_CC_PLL2_OUT_AUX, 10, 1, 2),
+       F(64000000, P_CAM_CC_PLL2_OUT_AUX, 7.5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cam_cc_mclk0_clk_src = {
+       .cmd_rcgr = 0x4004,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_1,
+       .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_mclk0_clk_src",
+               .parent_data = cam_cc_parent_data_1,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 cam_cc_mclk1_clk_src = {
+       .cmd_rcgr = 0x4024,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_1,
+       .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_mclk1_clk_src",
+               .parent_data = cam_cc_parent_data_1,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 cam_cc_mclk2_clk_src = {
+       .cmd_rcgr = 0x4044,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_1,
+       .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_mclk2_clk_src",
+               .parent_data = cam_cc_parent_data_1,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 cam_cc_mclk3_clk_src = {
+       .cmd_rcgr = 0x4064,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_1,
+       .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_mclk3_clk_src",
+               .parent_data = cam_cc_parent_data_1,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 cam_cc_mclk4_clk_src = {
+       .cmd_rcgr = 0x4084,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_1,
+       .freq_tbl = ftbl_cam_cc_mclk0_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_mclk4_clk_src",
+               .parent_data = cam_cc_parent_data_1,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_cam_cc_slow_ahb_clk_src[] = {
+       F(80000000, P_CAM_CC_PLL0_OUT_EVEN, 7.5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cam_cc_slow_ahb_clk_src = {
+       .cmd_rcgr = 0x6058,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = cam_cc_parent_map_0,
+       .freq_tbl = ftbl_cam_cc_slow_ahb_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cam_cc_slow_ahb_clk_src",
+               .parent_data = cam_cc_parent_data_0,
+               .num_parents = 4,
+               .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_branch cam_cc_bps_ahb_clk = {
+       .halt_reg = 0x6070,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x6070,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_bps_ahb_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_slow_ahb_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_bps_areg_clk = {
+       .halt_reg = 0x6054,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x6054,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_bps_areg_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_fast_ahb_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_bps_axi_clk = {
+       .halt_reg = 0x6038,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x6038,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_bps_axi_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_bps_clk = {
+       .halt_reg = 0x6028,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x6028,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_bps_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_bps_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_camnoc_axi_clk = {
+       .halt_reg = 0xb124,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb124,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_camnoc_axi_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_cci_0_clk = {
+       .halt_reg = 0xb0f0,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb0f0,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_cci_0_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_cci_0_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_cci_1_clk = {
+       .halt_reg = 0xb164,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb164,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_cci_1_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_cci_1_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_core_ahb_clk = {
+       .halt_reg = 0xb144,
+       .halt_check = BRANCH_HALT_DELAY,
+       .clkr = {
+               .enable_reg = 0xb144,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_core_ahb_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_slow_ahb_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_cpas_ahb_clk = {
+       .halt_reg = 0xb11c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb11c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_cpas_ahb_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_slow_ahb_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_csi0phytimer_clk = {
+       .halt_reg = 0x501c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x501c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_csi0phytimer_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_csi0phytimer_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_csi1phytimer_clk = {
+       .halt_reg = 0x5040,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x5040,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_csi1phytimer_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_csi1phytimer_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_csi2phytimer_clk = {
+       .halt_reg = 0x5064,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x5064,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_csi2phytimer_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_csi2phytimer_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_csi3phytimer_clk = {
+       .halt_reg = 0x5088,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x5088,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_csi3phytimer_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_csi3phytimer_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_csiphy0_clk = {
+       .halt_reg = 0x5020,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x5020,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_csiphy0_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_cphy_rx_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_csiphy1_clk = {
+       .halt_reg = 0x5044,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x5044,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_csiphy1_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_cphy_rx_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_csiphy2_clk = {
+       .halt_reg = 0x5068,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x5068,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_csiphy2_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_cphy_rx_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_csiphy3_clk = {
+       .halt_reg = 0x508c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x508c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_csiphy3_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_cphy_rx_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_icp_clk = {
+       .halt_reg = 0xb0a0,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb0a0,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_icp_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_icp_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ife_0_axi_clk = {
+       .halt_reg = 0x9080,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x9080,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ife_0_axi_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ife_0_clk = {
+       .halt_reg = 0x9028,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x9028,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ife_0_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_ife_0_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ife_0_cphy_rx_clk = {
+       .halt_reg = 0x907c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x907c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ife_0_cphy_rx_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_cphy_rx_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ife_0_csid_clk = {
+       .halt_reg = 0x9054,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x9054,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ife_0_csid_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_ife_0_csid_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ife_0_dsp_clk = {
+       .halt_reg = 0x9038,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x9038,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ife_0_dsp_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_ife_0_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ife_1_axi_clk = {
+       .halt_reg = 0xa058,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xa058,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ife_1_axi_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ife_1_clk = {
+       .halt_reg = 0xa028,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xa028,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ife_1_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_ife_1_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ife_1_cphy_rx_clk = {
+       .halt_reg = 0xa054,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xa054,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ife_1_cphy_rx_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_cphy_rx_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ife_1_csid_clk = {
+       .halt_reg = 0xa04c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xa04c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ife_1_csid_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_ife_1_csid_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ife_1_dsp_clk = {
+       .halt_reg = 0xa030,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xa030,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ife_1_dsp_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_ife_1_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ife_lite_clk = {
+       .halt_reg = 0xb01c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb01c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ife_lite_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_ife_lite_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ife_lite_cphy_rx_clk = {
+       .halt_reg = 0xb044,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb044,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ife_lite_cphy_rx_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_cphy_rx_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ife_lite_csid_clk = {
+       .halt_reg = 0xb03c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb03c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ife_lite_csid_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_ife_lite_csid_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ipe_0_ahb_clk = {
+       .halt_reg = 0x7040,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x7040,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ipe_0_ahb_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_slow_ahb_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ipe_0_areg_clk = {
+       .halt_reg = 0x703c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x703c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ipe_0_areg_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_fast_ahb_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ipe_0_axi_clk = {
+       .halt_reg = 0x7038,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x7038,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ipe_0_axi_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_ipe_0_clk = {
+       .halt_reg = 0x7028,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x7028,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_ipe_0_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_ipe_0_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_jpeg_clk = {
+       .halt_reg = 0xb064,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb064,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_jpeg_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_jpeg_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_lrme_clk = {
+       .halt_reg = 0xb110,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb110,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_lrme_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_lrme_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_mclk0_clk = {
+       .halt_reg = 0x401c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x401c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_mclk0_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_mclk0_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_mclk1_clk = {
+       .halt_reg = 0x403c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x403c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_mclk1_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_mclk1_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_mclk2_clk = {
+       .halt_reg = 0x405c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x405c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_mclk2_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_mclk2_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_mclk3_clk = {
+       .halt_reg = 0x407c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x407c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_mclk3_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_mclk3_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_mclk4_clk = {
+       .halt_reg = 0x409c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x409c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_mclk4_clk",
+                       .parent_data = &(const struct clk_parent_data){
+                               .hw = &cam_cc_mclk4_clk_src.clkr.hw,
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_soc_ahb_clk = {
+       .halt_reg = 0xb140,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb140,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_soc_ahb_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch cam_cc_sys_tmr_clk = {
+       .halt_reg = 0xb0a8,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb0a8,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "cam_cc_sys_tmr_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct gdsc bps_gdsc = {
+       .gdscr = 0x6004,
+       .pd = {
+               .name = "bps_gdsc",
+       },
+       .pwrsts = PWRSTS_OFF_ON,
+       .flags = HW_CTRL,
+};
+
+static struct gdsc ife_0_gdsc = {
+       .gdscr = 0x9004,
+       .pd = {
+               .name = "ife_0_gdsc",
+       },
+       .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc ife_1_gdsc = {
+       .gdscr = 0xa004,
+       .pd = {
+               .name = "ife_1_gdsc",
+       },
+       .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc ipe_0_gdsc = {
+       .gdscr = 0x7004,
+       .pd = {
+               .name = "ipe_0_gdsc",
+       },
+       .pwrsts = PWRSTS_OFF_ON,
+       .flags = HW_CTRL,
+};
+
+static struct gdsc titan_top_gdsc = {
+       .gdscr = 0xb134,
+       .pd = {
+               .name = "titan_top_gdsc",
+       },
+       .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct clk_hw *cam_cc_sc7180_hws[] = {
+       [CAM_CC_PLL2_OUT_EARLY] = &cam_cc_pll2_out_early.hw,
+};
+
+static struct clk_regmap *cam_cc_sc7180_clocks[] = {
+       [CAM_CC_BPS_AHB_CLK] = &cam_cc_bps_ahb_clk.clkr,
+       [CAM_CC_BPS_AREG_CLK] = &cam_cc_bps_areg_clk.clkr,
+       [CAM_CC_BPS_AXI_CLK] = &cam_cc_bps_axi_clk.clkr,
+       [CAM_CC_BPS_CLK] = &cam_cc_bps_clk.clkr,
+       [CAM_CC_BPS_CLK_SRC] = &cam_cc_bps_clk_src.clkr,
+       [CAM_CC_CAMNOC_AXI_CLK] = &cam_cc_camnoc_axi_clk.clkr,
+       [CAM_CC_CCI_0_CLK] = &cam_cc_cci_0_clk.clkr,
+       [CAM_CC_CCI_0_CLK_SRC] = &cam_cc_cci_0_clk_src.clkr,
+       [CAM_CC_CCI_1_CLK] = &cam_cc_cci_1_clk.clkr,
+       [CAM_CC_CCI_1_CLK_SRC] = &cam_cc_cci_1_clk_src.clkr,
+       [CAM_CC_CORE_AHB_CLK] = &cam_cc_core_ahb_clk.clkr,
+       [CAM_CC_CPAS_AHB_CLK] = &cam_cc_cpas_ahb_clk.clkr,
+       [CAM_CC_CPHY_RX_CLK_SRC] = &cam_cc_cphy_rx_clk_src.clkr,
+       [CAM_CC_CSI0PHYTIMER_CLK] = &cam_cc_csi0phytimer_clk.clkr,
+       [CAM_CC_CSI0PHYTIMER_CLK_SRC] = &cam_cc_csi0phytimer_clk_src.clkr,
+       [CAM_CC_CSI1PHYTIMER_CLK] = &cam_cc_csi1phytimer_clk.clkr,
+       [CAM_CC_CSI1PHYTIMER_CLK_SRC] = &cam_cc_csi1phytimer_clk_src.clkr,
+       [CAM_CC_CSI2PHYTIMER_CLK] = &cam_cc_csi2phytimer_clk.clkr,
+       [CAM_CC_CSI2PHYTIMER_CLK_SRC] = &cam_cc_csi2phytimer_clk_src.clkr,
+       [CAM_CC_CSI3PHYTIMER_CLK] = &cam_cc_csi3phytimer_clk.clkr,
+       [CAM_CC_CSI3PHYTIMER_CLK_SRC] = &cam_cc_csi3phytimer_clk_src.clkr,
+       [CAM_CC_CSIPHY0_CLK] = &cam_cc_csiphy0_clk.clkr,
+       [CAM_CC_CSIPHY1_CLK] = &cam_cc_csiphy1_clk.clkr,
+       [CAM_CC_CSIPHY2_CLK] = &cam_cc_csiphy2_clk.clkr,
+       [CAM_CC_CSIPHY3_CLK] = &cam_cc_csiphy3_clk.clkr,
+       [CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr,
+       [CAM_CC_ICP_CLK] = &cam_cc_icp_clk.clkr,
+       [CAM_CC_ICP_CLK_SRC] = &cam_cc_icp_clk_src.clkr,
+       [CAM_CC_IFE_0_AXI_CLK] = &cam_cc_ife_0_axi_clk.clkr,
+       [CAM_CC_IFE_0_CLK] = &cam_cc_ife_0_clk.clkr,
+       [CAM_CC_IFE_0_CLK_SRC] = &cam_cc_ife_0_clk_src.clkr,
+       [CAM_CC_IFE_0_CPHY_RX_CLK] = &cam_cc_ife_0_cphy_rx_clk.clkr,
+       [CAM_CC_IFE_0_CSID_CLK] = &cam_cc_ife_0_csid_clk.clkr,
+       [CAM_CC_IFE_0_CSID_CLK_SRC] = &cam_cc_ife_0_csid_clk_src.clkr,
+       [CAM_CC_IFE_0_DSP_CLK] = &cam_cc_ife_0_dsp_clk.clkr,
+       [CAM_CC_IFE_1_AXI_CLK] = &cam_cc_ife_1_axi_clk.clkr,
+       [CAM_CC_IFE_1_CLK] = &cam_cc_ife_1_clk.clkr,
+       [CAM_CC_IFE_1_CLK_SRC] = &cam_cc_ife_1_clk_src.clkr,
+       [CAM_CC_IFE_1_CPHY_RX_CLK] = &cam_cc_ife_1_cphy_rx_clk.clkr,
+       [CAM_CC_IFE_1_CSID_CLK] = &cam_cc_ife_1_csid_clk.clkr,
+       [CAM_CC_IFE_1_CSID_CLK_SRC] = &cam_cc_ife_1_csid_clk_src.clkr,
+       [CAM_CC_IFE_1_DSP_CLK] = &cam_cc_ife_1_dsp_clk.clkr,
+       [CAM_CC_IFE_LITE_CLK] = &cam_cc_ife_lite_clk.clkr,
+       [CAM_CC_IFE_LITE_CLK_SRC] = &cam_cc_ife_lite_clk_src.clkr,
+       [CAM_CC_IFE_LITE_CPHY_RX_CLK] = &cam_cc_ife_lite_cphy_rx_clk.clkr,
+       [CAM_CC_IFE_LITE_CSID_CLK] = &cam_cc_ife_lite_csid_clk.clkr,
+       [CAM_CC_IFE_LITE_CSID_CLK_SRC] = &cam_cc_ife_lite_csid_clk_src.clkr,
+       [CAM_CC_IPE_0_AHB_CLK] = &cam_cc_ipe_0_ahb_clk.clkr,
+       [CAM_CC_IPE_0_AREG_CLK] = &cam_cc_ipe_0_areg_clk.clkr,
+       [CAM_CC_IPE_0_AXI_CLK] = &cam_cc_ipe_0_axi_clk.clkr,
+       [CAM_CC_IPE_0_CLK] = &cam_cc_ipe_0_clk.clkr,
+       [CAM_CC_IPE_0_CLK_SRC] = &cam_cc_ipe_0_clk_src.clkr,
+       [CAM_CC_JPEG_CLK] = &cam_cc_jpeg_clk.clkr,
+       [CAM_CC_JPEG_CLK_SRC] = &cam_cc_jpeg_clk_src.clkr,
+       [CAM_CC_LRME_CLK] = &cam_cc_lrme_clk.clkr,
+       [CAM_CC_LRME_CLK_SRC] = &cam_cc_lrme_clk_src.clkr,
+       [CAM_CC_MCLK0_CLK] = &cam_cc_mclk0_clk.clkr,
+       [CAM_CC_MCLK0_CLK_SRC] = &cam_cc_mclk0_clk_src.clkr,
+       [CAM_CC_MCLK1_CLK] = &cam_cc_mclk1_clk.clkr,
+       [CAM_CC_MCLK1_CLK_SRC] = &cam_cc_mclk1_clk_src.clkr,
+       [CAM_CC_MCLK2_CLK] = &cam_cc_mclk2_clk.clkr,
+       [CAM_CC_MCLK2_CLK_SRC] = &cam_cc_mclk2_clk_src.clkr,
+       [CAM_CC_MCLK3_CLK] = &cam_cc_mclk3_clk.clkr,
+       [CAM_CC_MCLK3_CLK_SRC] = &cam_cc_mclk3_clk_src.clkr,
+       [CAM_CC_MCLK4_CLK] = &cam_cc_mclk4_clk.clkr,
+       [CAM_CC_MCLK4_CLK_SRC] = &cam_cc_mclk4_clk_src.clkr,
+       [CAM_CC_PLL0] = &cam_cc_pll0.clkr,
+       [CAM_CC_PLL1] = &cam_cc_pll1.clkr,
+       [CAM_CC_PLL2] = &cam_cc_pll2.clkr,
+       [CAM_CC_PLL2_OUT_AUX] = &cam_cc_pll2_out_aux.clkr,
+       [CAM_CC_PLL3] = &cam_cc_pll3.clkr,
+       [CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr,
+       [CAM_CC_SOC_AHB_CLK] = &cam_cc_soc_ahb_clk.clkr,
+       [CAM_CC_SYS_TMR_CLK] = &cam_cc_sys_tmr_clk.clkr,
+};
+static struct gdsc *cam_cc_sc7180_gdscs[] = {
+       [BPS_GDSC] = &bps_gdsc,
+       [IFE_0_GDSC] = &ife_0_gdsc,
+       [IFE_1_GDSC] = &ife_1_gdsc,
+       [IPE_0_GDSC] = &ipe_0_gdsc,
+       [TITAN_TOP_GDSC] = &titan_top_gdsc,
+};
+
+static const struct regmap_config cam_cc_sc7180_regmap_config = {
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+       .max_register = 0xd028,
+       .fast_io = true,
+};
+
+static const struct qcom_cc_desc cam_cc_sc7180_desc = {
+       .config = &cam_cc_sc7180_regmap_config,
+       .clk_hws = cam_cc_sc7180_hws,
+       .num_clk_hws = ARRAY_SIZE(cam_cc_sc7180_hws),
+       .clks = cam_cc_sc7180_clocks,
+       .num_clks = ARRAY_SIZE(cam_cc_sc7180_clocks),
+       .gdscs = cam_cc_sc7180_gdscs,
+       .num_gdscs = ARRAY_SIZE(cam_cc_sc7180_gdscs),
+};
+
+static const struct of_device_id cam_cc_sc7180_match_table[] = {
+       { .compatible = "qcom,sc7180-camcc" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, cam_cc_sc7180_match_table);
+
+static int cam_cc_sc7180_probe(struct platform_device *pdev)
+{
+       struct regmap *regmap;
+       int ret;
+
+       pm_runtime_enable(&pdev->dev);
+       ret = pm_clk_create(&pdev->dev);
+       if (ret < 0)
+               return ret;
+
+       ret = pm_clk_add(&pdev->dev, "xo");
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to acquire XO clock\n");
+               goto disable_pm_runtime;
+       }
+
+       ret = pm_clk_add(&pdev->dev, "iface");
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to acquire iface clock\n");
+               goto disable_pm_runtime;
+       }
+
+       ret = pm_runtime_get(&pdev->dev);
+       if (ret)
+               goto destroy_pm_clk;
+
+       regmap = qcom_cc_map(pdev, &cam_cc_sc7180_desc);
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               pm_runtime_put(&pdev->dev);
+               goto destroy_pm_clk;
+       }
+
+       clk_fabia_pll_configure(&cam_cc_pll0, regmap, &cam_cc_pll0_config);
+       clk_fabia_pll_configure(&cam_cc_pll1, regmap, &cam_cc_pll1_config);
+       clk_agera_pll_configure(&cam_cc_pll2, regmap, &cam_cc_pll2_config);
+       clk_fabia_pll_configure(&cam_cc_pll3, regmap, &cam_cc_pll3_config);
+
+       ret = qcom_cc_really_probe(pdev, &cam_cc_sc7180_desc, regmap);
+       pm_runtime_put(&pdev->dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to register CAM CC clocks\n");
+               goto destroy_pm_clk;
+       }
+
+       return 0;
+
+destroy_pm_clk:
+       pm_clk_destroy(&pdev->dev);
+
+disable_pm_runtime:
+       pm_runtime_disable(&pdev->dev);
+
+       return ret;
+}
+
+static const struct dev_pm_ops cam_cc_pm_ops = {
+       SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
+};
+
+static struct platform_driver cam_cc_sc7180_driver = {
+       .probe = cam_cc_sc7180_probe,
+       .driver = {
+               .name = "cam_cc-sc7180",
+               .of_match_table = cam_cc_sc7180_match_table,
+               .pm = &cam_cc_pm_ops,
+       },
+};
+
+static int __init cam_cc_sc7180_init(void)
+{
+       return platform_driver_register(&cam_cc_sc7180_driver);
+}
+subsys_initcall(cam_cc_sc7180_init);
+
+static void __exit cam_cc_sc7180_exit(void)
+{
+       platform_driver_unregister(&cam_cc_sc7180_driver);
+}
+module_exit(cam_cc_sc7180_exit);
+
+MODULE_DESCRIPTION("QTI CAM_CC SC7180 Driver");
+MODULE_LICENSE("GPL v2");
index 564431130a760de60ec440cb3285c3908bd0da50..21c357c26ec42a8e98d505d48dc62c4eaa569ef2 100644 (file)
@@ -116,6 +116,16 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
                [PLL_OFF_OPMODE] = 0x38,
                [PLL_OFF_ALPHA_VAL] = 0x40,
        },
+       [CLK_ALPHA_PLL_TYPE_AGERA] =  {
+               [PLL_OFF_L_VAL] = 0x04,
+               [PLL_OFF_ALPHA_VAL] = 0x08,
+               [PLL_OFF_USER_CTL] = 0x0c,
+               [PLL_OFF_CONFIG_CTL] = 0x10,
+               [PLL_OFF_CONFIG_CTL_U] = 0x14,
+               [PLL_OFF_TEST_CTL] = 0x18,
+               [PLL_OFF_TEST_CTL_U] = 0x1c,
+               [PLL_OFF_STATUS] = 0x2c,
+       },
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
 
@@ -207,6 +217,13 @@ static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
 #define wait_for_pll_update_ack_clear(pll) \
        wait_for_pll(pll, ALPHA_PLL_ACK_LATCH, 1, "update_ack_clear")
 
+static void clk_alpha_pll_write_config(struct regmap *regmap, unsigned int reg,
+                                       unsigned int val)
+{
+       if (val)
+               regmap_write(regmap, reg, val);
+}
+
 void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
                             const struct alpha_pll_config *config)
 {
@@ -1004,33 +1021,19 @@ void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
 {
        u32 val, mask;
 
-       if (config->l)
-               regmap_write(regmap, PLL_L_VAL(pll), config->l);
-
-       if (config->alpha)
-               regmap_write(regmap, PLL_FRAC(pll), config->alpha);
-
-       if (config->config_ctl_val)
-               regmap_write(regmap, PLL_CONFIG_CTL(pll),
+       clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);
+       clk_alpha_pll_write_config(regmap, PLL_FRAC(pll), config->alpha);
+       clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll),
                                                config->config_ctl_val);
-
-       if (config->config_ctl_hi_val)
-               regmap_write(regmap, PLL_CONFIG_CTL_U(pll),
+       clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll),
                                                config->config_ctl_hi_val);
-
-       if (config->user_ctl_val)
-               regmap_write(regmap, PLL_USER_CTL(pll), config->user_ctl_val);
-
-       if (config->user_ctl_hi_val)
-               regmap_write(regmap, PLL_USER_CTL_U(pll),
+       clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll),
+                                               config->user_ctl_val);
+       clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll),
                                                config->user_ctl_hi_val);
-
-       if (config->test_ctl_val)
-               regmap_write(regmap, PLL_TEST_CTL(pll),
+       clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll),
                                                config->test_ctl_val);
-
-       if (config->test_ctl_hi_val)
-               regmap_write(regmap, PLL_TEST_CTL_U(pll),
+       clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll),
                                                config->test_ctl_hi_val);
 
        if (config->post_div_mask) {
@@ -1145,25 +1148,38 @@ static unsigned long alpha_pll_fabia_recalc_rate(struct clk_hw *hw,
        return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width);
 }
 
+/*
+ * Due to limited number of bits for fractional rate programming, the
+ * rounded up rate could be marginally higher than the requested rate.
+ */
+static int alpha_pll_check_rate_margin(struct clk_hw *hw,
+                       unsigned long rrate, unsigned long rate)
+{
+       unsigned long rate_margin = rate + PLL_RATE_MARGIN;
+
+       if (rrate > rate_margin || rrate < rate) {
+               pr_err("%s: Rounded rate %lu not within range [%lu, %lu)\n",
+                      clk_hw_get_name(hw), rrate, rate, rate_margin);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int alpha_pll_fabia_set_rate(struct clk_hw *hw, unsigned long rate,
                                                unsigned long prate)
 {
        struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
        u32 l, alpha_width = pll_alpha_width(pll);
+       unsigned long rrate;
+       int ret;
        u64 a;
-       unsigned long rrate, max = rate + PLL_RATE_MARGIN;
 
        rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);
 
-       /*
-        * Due to limited number of bits for fractional rate programming, the
-        * rounded up rate could be marginally higher than the requested rate.
-        */
-       if (rrate > (rate + PLL_RATE_MARGIN) || rrate < rate) {
-               pr_err("%s: Rounded rate %lu not within range [%lu, %lu)\n",
-                      clk_hw_get_name(hw), rrate, rate, max);
-               return -EINVAL;
-       }
+       ret = alpha_pll_check_rate_margin(hw, rrate, rate);
+       if (ret < 0)
+               return ret;
 
        regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
        regmap_write(pll->clkr.regmap, PLL_FRAC(pll), a);
@@ -1206,12 +1222,10 @@ static int alpha_pll_fabia_prepare(struct clk_hw *hw)
 
        rrate = alpha_pll_round_rate(cal_freq, clk_hw_get_rate(parent_hw),
                                        &cal_l, &a, alpha_width);
-       /*
-        * Due to a limited number of bits for fractional rate programming, the
-        * rounded up rate could be marginally higher than the requested rate.
-        */
-       if (rrate > (cal_freq + PLL_RATE_MARGIN) || rrate < cal_freq)
-               return -EINVAL;
+
+       ret = alpha_pll_check_rate_margin(hw, rrate, cal_freq);
+       if (ret < 0)
+               return ret;
 
        /* Setup PLL for calibration frequency */
        regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), cal_l);
@@ -1388,49 +1402,27 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_fabia_ops);
 void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
                             const struct alpha_pll_config *config)
 {
-       if (config->l)
-               regmap_write(regmap, PLL_L_VAL(pll), config->l);
-
+       clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);
        regmap_write(regmap, PLL_CAL_L_VAL(pll), TRION_PLL_CAL_VAL);
-
-       if (config->alpha)
-               regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha);
-
-       if (config->config_ctl_val)
-               regmap_write(regmap, PLL_CONFIG_CTL(pll),
-                            config->config_ctl_val);
-
-       if (config->config_ctl_hi_val)
-               regmap_write(regmap, PLL_CONFIG_CTL_U(pll),
-                            config->config_ctl_hi_val);
-
-       if (config->config_ctl_hi1_val)
-               regmap_write(regmap, PLL_CONFIG_CTL_U1(pll),
-                            config->config_ctl_hi1_val);
-
-       if (config->user_ctl_val)
-               regmap_write(regmap, PLL_USER_CTL(pll),
-                            config->user_ctl_val);
-
-       if (config->user_ctl_hi_val)
-               regmap_write(regmap, PLL_USER_CTL_U(pll),
-                            config->user_ctl_hi_val);
-
-       if (config->user_ctl_hi1_val)
-               regmap_write(regmap, PLL_USER_CTL_U1(pll),
-                            config->user_ctl_hi1_val);
-
-       if (config->test_ctl_val)
-               regmap_write(regmap, PLL_TEST_CTL(pll),
-                            config->test_ctl_val);
-
-       if (config->test_ctl_hi_val)
-               regmap_write(regmap, PLL_TEST_CTL_U(pll),
-                            config->test_ctl_hi_val);
-
-       if (config->test_ctl_hi1_val)
-               regmap_write(regmap, PLL_TEST_CTL_U1(pll),
-                            config->test_ctl_hi1_val);
+       clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);
+       clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll),
+                                    config->config_ctl_val);
+       clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll),
+                                    config->config_ctl_hi_val);
+       clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll),
+                                    config->config_ctl_hi1_val);
+       clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll),
+                                       config->user_ctl_val);
+       clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll),
+                                       config->user_ctl_hi_val);
+       clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U1(pll),
+                                       config->user_ctl_hi1_val);
+       clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll),
+                                       config->test_ctl_val);
+       clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll),
+                                       config->test_ctl_hi_val);
+       clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll),
+                                       config->test_ctl_hi1_val);
 
        regmap_update_bits(regmap, PLL_MODE(pll), PLL_UPDATE_BYPASS,
                           PLL_UPDATE_BYPASS);
@@ -1490,14 +1482,9 @@ static int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate,
 
        rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);
 
-       /*
-        * Due to a limited number of bits for fractional rate programming, the
-        * rounded up rate could be marginally higher than the requested rate.
-        */
-       if (rrate > (rate + PLL_RATE_MARGIN) || rrate < rate) {
-               pr_err("Call set rate on the PLL with rounded rates!\n");
-               return -EINVAL;
-       }
+       ret = alpha_pll_check_rate_margin(hw, rrate, rate);
+       if (ret < 0)
+               return ret;
 
        regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
        regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
@@ -1561,3 +1548,55 @@ const struct clk_ops clk_alpha_pll_postdiv_lucid_ops = {
        .set_rate = clk_alpha_pll_postdiv_fabia_set_rate,
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_lucid_ops);
+
+void clk_agera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+                       const struct alpha_pll_config *config)
+{
+       clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);
+       clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);
+       clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll),
+                                                       config->user_ctl_val);
+       clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll),
+                                               config->config_ctl_val);
+       clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll),
+                                               config->config_ctl_hi_val);
+       clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll),
+                                               config->test_ctl_val);
+       clk_alpha_pll_write_config(regmap,  PLL_TEST_CTL_U(pll),
+                                               config->test_ctl_hi_val);
+}
+EXPORT_SYMBOL_GPL(clk_agera_pll_configure);
+
+static int clk_alpha_pll_agera_set_rate(struct clk_hw *hw, unsigned long rate,
+                                                       unsigned long prate)
+{
+       struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+       u32 l, alpha_width = pll_alpha_width(pll);
+       int ret;
+       unsigned long rrate;
+       u64 a;
+
+       rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);
+       ret = alpha_pll_check_rate_margin(hw, rrate, rate);
+       if (ret < 0)
+               return ret;
+
+       /* change L_VAL without having to go through the power on sequence */
+       regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
+       regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
+
+       if (clk_hw_is_enabled(hw))
+               return wait_for_pll_enable_lock(pll);
+
+       return 0;
+}
+
+const struct clk_ops clk_alpha_pll_agera_ops = {
+       .enable = clk_alpha_pll_enable,
+       .disable = clk_alpha_pll_disable,
+       .is_enabled = clk_alpha_pll_is_enabled,
+       .recalc_rate = alpha_pll_fabia_recalc_rate,
+       .round_rate = clk_alpha_pll_round_rate,
+       .set_rate = clk_alpha_pll_agera_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_alpha_pll_agera_ops);
index d3201b87c0cd4f744c1011a7989342e1b2fc9082..0ea30d2f3da1cb53b3f56182d7522b244aeed783 100644 (file)
@@ -15,6 +15,7 @@ enum {
        CLK_ALPHA_PLL_TYPE_FABIA,
        CLK_ALPHA_PLL_TYPE_TRION,
        CLK_ALPHA_PLL_TYPE_LUCID = CLK_ALPHA_PLL_TYPE_TRION,
+       CLK_ALPHA_PLL_TYPE_AGERA,
        CLK_ALPHA_PLL_TYPE_MAX,
 };
 
@@ -141,6 +142,7 @@ extern const struct clk_ops clk_alpha_pll_postdiv_trion_ops;
 extern const struct clk_ops clk_alpha_pll_lucid_ops;
 #define clk_alpha_pll_fixed_lucid_ops clk_alpha_pll_fixed_trion_ops
 extern const struct clk_ops clk_alpha_pll_postdiv_lucid_ops;
+extern const struct clk_ops clk_alpha_pll_agera_ops;
 
 void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
                             const struct alpha_pll_config *config);
@@ -148,6 +150,8 @@ void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
                                const struct alpha_pll_config *config);
 void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
                             const struct alpha_pll_config *config);
+void clk_agera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+                               const struct alpha_pll_config *config);
 #define clk_lucid_pll_configure(pll, regmap, config) \
        clk_trion_pll_configure(pll, regmap, config)
 
index e2c669b08affcd67b203b5d477c96d26e86abc66..6a2a13c5058e39c269c3f8384dc2ee38502d75f0 100644 (file)
@@ -349,6 +349,7 @@ DEFINE_CLK_RPMH_VRM(sdm845, rf_clk2, rf_clk2_ao, "rfclka2", 1);
 DEFINE_CLK_RPMH_VRM(sdm845, rf_clk3, rf_clk3_ao, "rfclka3", 1);
 DEFINE_CLK_RPMH_VRM(sm8150, rf_clk3, rf_clk3_ao, "rfclka3", 1);
 DEFINE_CLK_RPMH_BCM(sdm845, ipa, "IP0");
+DEFINE_CLK_RPMH_BCM(sdm845, ce, "CE0");
 
 static struct clk_hw *sdm845_rpmh_clocks[] = {
        [RPMH_CXO_CLK]          = &sdm845_bi_tcxo.hw,
@@ -364,6 +365,7 @@ static struct clk_hw *sdm845_rpmh_clocks[] = {
        [RPMH_RF_CLK3]          = &sdm845_rf_clk3.hw,
        [RPMH_RF_CLK3_A]        = &sdm845_rf_clk3_ao.hw,
        [RPMH_IPA_CLK]          = &sdm845_ipa.hw,
+       [RPMH_CE_CLK]           = &sdm845_ce.hw,
 };
 
 static const struct clk_rpmh_desc clk_rpmh_sdm845 = {
@@ -371,6 +373,25 @@ static const struct clk_rpmh_desc clk_rpmh_sdm845 = {
        .num_clks = ARRAY_SIZE(sdm845_rpmh_clocks),
 };
 
+DEFINE_CLK_RPMH_VRM(sdx55, rf_clk1, rf_clk1_ao, "rfclkd1", 1);
+DEFINE_CLK_RPMH_VRM(sdx55, rf_clk2, rf_clk2_ao, "rfclkd2", 1);
+DEFINE_CLK_RPMH_BCM(sdx55, qpic_clk, "QP0");
+
+static struct clk_hw *sdx55_rpmh_clocks[] = {
+       [RPMH_CXO_CLK]          = &sdm845_bi_tcxo.hw,
+       [RPMH_CXO_CLK_A]        = &sdm845_bi_tcxo_ao.hw,
+       [RPMH_RF_CLK1]          = &sdx55_rf_clk1.hw,
+       [RPMH_RF_CLK1_A]        = &sdx55_rf_clk1_ao.hw,
+       [RPMH_RF_CLK2]          = &sdx55_rf_clk2.hw,
+       [RPMH_RF_CLK2_A]        = &sdx55_rf_clk2_ao.hw,
+       [RPMH_QPIC_CLK]         = &sdx55_qpic_clk.hw,
+};
+
+static const struct clk_rpmh_desc clk_rpmh_sdx55 = {
+       .clks = sdx55_rpmh_clocks,
+       .num_clks = ARRAY_SIZE(sdx55_rpmh_clocks),
+};
+
 static struct clk_hw *sm8150_rpmh_clocks[] = {
        [RPMH_CXO_CLK]          = &sdm845_bi_tcxo.hw,
        [RPMH_CXO_CLK_A]        = &sdm845_bi_tcxo_ao.hw,
@@ -432,6 +453,39 @@ static const struct clk_rpmh_desc clk_rpmh_sm8250 = {
        .num_clks = ARRAY_SIZE(sm8250_rpmh_clocks),
 };
 
+DEFINE_CLK_RPMH_VRM(sm8350, div_clk1, div_clk1_ao, "divclka1", 2);
+DEFINE_CLK_RPMH_VRM(sm8350, rf_clk4, rf_clk4_ao, "rfclka4", 1);
+DEFINE_CLK_RPMH_VRM(sm8350, rf_clk5, rf_clk5_ao, "rfclka5", 1);
+DEFINE_CLK_RPMH_BCM(sm8350, pka, "PKA0");
+DEFINE_CLK_RPMH_BCM(sm8350, hwkm, "HK0");
+
+static struct clk_hw *sm8350_rpmh_clocks[] = {
+       [RPMH_CXO_CLK]          = &sdm845_bi_tcxo.hw,
+       [RPMH_CXO_CLK_A]        = &sdm845_bi_tcxo_ao.hw,
+       [RPMH_DIV_CLK1]         = &sm8350_div_clk1.hw,
+       [RPMH_DIV_CLK1_A]       = &sm8350_div_clk1_ao.hw,
+       [RPMH_LN_BB_CLK1]       = &sm8250_ln_bb_clk1.hw,
+       [RPMH_LN_BB_CLK1_A]     = &sm8250_ln_bb_clk1_ao.hw,
+       [RPMH_LN_BB_CLK2]       = &sdm845_ln_bb_clk2.hw,
+       [RPMH_LN_BB_CLK2_A]     = &sdm845_ln_bb_clk2_ao.hw,
+       [RPMH_RF_CLK1]          = &sdm845_rf_clk1.hw,
+       [RPMH_RF_CLK1_A]        = &sdm845_rf_clk1_ao.hw,
+       [RPMH_RF_CLK3]          = &sdm845_rf_clk3.hw,
+       [RPMH_RF_CLK3_A]        = &sdm845_rf_clk3_ao.hw,
+       [RPMH_RF_CLK4]          = &sm8350_rf_clk4.hw,
+       [RPMH_RF_CLK4_A]        = &sm8350_rf_clk4_ao.hw,
+       [RPMH_RF_CLK5]          = &sm8350_rf_clk5.hw,
+       [RPMH_RF_CLK5_A]        = &sm8350_rf_clk5_ao.hw,
+       [RPMH_IPA_CLK]          = &sdm845_ipa.hw,
+       [RPMH_PKA_CLK]          = &sm8350_pka.hw,
+       [RPMH_HWKM_CLK]         = &sm8350_hwkm.hw,
+};
+
+static const struct clk_rpmh_desc clk_rpmh_sm8350 = {
+       .clks = sm8350_rpmh_clocks,
+       .num_clks = ARRAY_SIZE(sm8350_rpmh_clocks),
+};
+
 static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec,
                                         void *data)
 {
@@ -517,8 +571,10 @@ static int clk_rpmh_probe(struct platform_device *pdev)
 static const struct of_device_id clk_rpmh_match_table[] = {
        { .compatible = "qcom,sc7180-rpmh-clk", .data = &clk_rpmh_sc7180},
        { .compatible = "qcom,sdm845-rpmh-clk", .data = &clk_rpmh_sdm845},
+       { .compatible = "qcom,sdx55-rpmh-clk",  .data = &clk_rpmh_sdx55},
        { .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150},
        { .compatible = "qcom,sm8250-rpmh-clk", .data = &clk_rpmh_sm8250},
+       { .compatible = "qcom,sm8350-rpmh-clk", .data = &clk_rpmh_sm8350},
        { }
 };
 MODULE_DEVICE_TABLE(of, clk_rpmh_match_table);
index 07a98d3f882d0c366e99d2f31592802cdf060f79..588575e1169d5e0b8652ebe3814d5134e469f5ae 100644 (file)
@@ -963,6 +963,7 @@ static struct gdsc mdss_gdsc = {
        },
        .pwrsts = PWRSTS_OFF_ON,
        .flags = HW_CTRL,
+       .supply = "mmcx",
 };
 
 static struct clk_regmap *disp_cc_sm8250_clocks[] = {
index 68d8f7aaf64e1f0133400f727fac947ecb24ee30..d82d725ac2319f43e29fa96c37ad9663f1315b3d 100644 (file)
@@ -642,7 +642,7 @@ static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = {
                .name = "gcc_sdcc1_ice_core_clk_src",
                .parent_data = gcc_parent_data_0,
                .num_parents = 4,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
@@ -651,6 +651,7 @@ static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = {
        F(9600000, P_BI_TCXO, 2, 0, 0),
        F(19200000, P_BI_TCXO, 1, 0, 0),
        F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0),
+       F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
        F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0),
        F(202000000, P_GPLL7_OUT_MAIN, 4, 0, 0),
        { }
@@ -666,7 +667,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = {
                .name = "gcc_sdcc2_apps_clk_src",
                .parent_data = gcc_parent_data_5,
                .num_parents = 5,
-               .ops = &clk_rcg2_ops,
+               .ops = &clk_rcg2_floor_ops,
        },
 };
 
diff --git a/drivers/clk/qcom/gcc-sdx55.c b/drivers/clk/qcom/gcc-sdx55.c
new file mode 100644 (file)
index 0000000..e3b9030
--- /dev/null
@@ -0,0 +1,1659 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020, Linaro Ltd.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,gcc-sdx55.h>
+
+#include "common.h"
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+       P_BI_TCXO,
+       P_CORE_BI_PLL_TEST_SE,
+       P_GPLL0_OUT_EVEN,
+       P_GPLL0_OUT_MAIN,
+       P_GPLL4_OUT_EVEN,
+       P_GPLL5_OUT_MAIN,
+       P_SLEEP_CLK,
+};
+
+static const struct pll_vco lucid_vco[] = {
+       { 249600000, 2000000000, 0 },
+};
+
+static struct clk_alpha_pll gpll0 = {
+       .offset = 0x0,
+       .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
+       .vco_table = lucid_vco,
+       .num_vco = ARRAY_SIZE(lucid_vco),
+       .clkr = {
+               .enable_reg = 0x6d000,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gpll0",
+                       .parent_data = &(const struct clk_parent_data){
+                               .fw_name = "bi_tcxo",
+                       },
+                       .num_parents = 1,
+                       .ops = &clk_alpha_pll_fixed_lucid_ops,
+               },
+       },
+};
+
+static const struct clk_div_table post_div_table_lucid_even[] = {
+       { 0x0, 1 },
+       { 0x1, 2 },
+       { 0x3, 4 },
+       { 0x7, 8 },
+       { }
+};
+
+static struct clk_alpha_pll_postdiv gpll0_out_even = {
+       .offset = 0x0,
+       .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
+       .post_div_shift = 8,
+       .post_div_table = post_div_table_lucid_even,
+       .num_post_div = ARRAY_SIZE(post_div_table_lucid_even),
+       .width = 4,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gpll0_out_even",
+               .parent_data = &(const struct clk_parent_data){
+                       .hw = &gpll0.clkr.hw,
+               },
+               .num_parents = 1,
+               .ops = &clk_alpha_pll_postdiv_lucid_ops,
+       },
+};
+
+static struct clk_alpha_pll gpll4 = {
+       .offset = 0x76000,
+       .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
+       .vco_table = lucid_vco,
+       .num_vco = ARRAY_SIZE(lucid_vco),
+       .clkr = {
+               .enable_reg = 0x6d000,
+               .enable_mask = BIT(4),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gpll4",
+                       .parent_data = &(const struct clk_parent_data){
+                               .fw_name = "bi_tcxo",
+                       },
+                       .num_parents = 1,
+                       .ops = &clk_alpha_pll_fixed_lucid_ops,
+               },
+       },
+};
+
+static struct clk_alpha_pll_postdiv gpll4_out_even = {
+       .offset = 0x76000,
+       .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
+       .post_div_shift = 8,
+       .post_div_table = post_div_table_lucid_even,
+       .num_post_div = ARRAY_SIZE(post_div_table_lucid_even),
+       .width = 4,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gpll4_out_even",
+               .parent_data = &(const struct clk_parent_data){
+                       .hw = &gpll4.clkr.hw,
+               },
+               .num_parents = 1,
+               .ops = &clk_alpha_pll_postdiv_lucid_ops,
+       },
+};
+
+static struct clk_alpha_pll gpll5 = {
+       .offset = 0x74000,
+       .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
+       .vco_table = lucid_vco,
+       .num_vco = ARRAY_SIZE(lucid_vco),
+       .clkr = {
+               .enable_reg = 0x6d000,
+               .enable_mask = BIT(5),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gpll5",
+                       .parent_data = &(const struct clk_parent_data){
+                               .fw_name = "bi_tcxo",
+                       },
+                       .num_parents = 1,
+                       .ops = &clk_alpha_pll_fixed_lucid_ops,
+               },
+       },
+};
+
+static const struct parent_map gcc_parent_map_0[] = {
+       { P_BI_TCXO, 0 },
+       { P_GPLL0_OUT_MAIN, 1 },
+       { P_GPLL0_OUT_EVEN, 6 },
+       { P_CORE_BI_PLL_TEST_SE, 7 },
+};
+
+static const struct clk_parent_data gcc_parents_0[] = {
+       { .fw_name = "bi_tcxo" },
+       { .hw = &gpll0.clkr.hw },
+       { .hw = &gpll0_out_even.clkr.hw },
+       { .fw_name = "core_bi_pll_test_se" },
+};
+
+static const struct clk_parent_data gcc_parents_0_ao[] = {
+       { .fw_name = "bi_tcxo_ao" },
+       { .hw = &gpll0.clkr.hw },
+       { .hw = &gpll0_out_even.clkr.hw },
+       { .fw_name = "core_bi_pll_test_se" },
+};
+
+static const struct parent_map gcc_parent_map_2[] = {
+       { P_BI_TCXO, 0 },
+       { P_GPLL0_OUT_MAIN, 1 },
+       { P_GPLL4_OUT_EVEN, 2 },
+       { P_GPLL5_OUT_MAIN, 5 },
+       { P_GPLL0_OUT_EVEN, 6 },
+       { P_CORE_BI_PLL_TEST_SE, 7 },
+};
+
+static const struct clk_parent_data gcc_parents_2[] = {
+       { .fw_name = "bi_tcxo" },
+       { .hw = &gpll0.clkr.hw },
+       { .hw = &gpll4_out_even.clkr.hw },
+       { .hw = &gpll5.clkr.hw },
+       { .hw = &gpll0_out_even.clkr.hw },
+       { .fw_name = "core_bi_pll_test_se" },
+};
+
+static const struct parent_map gcc_parent_map_3[] = {
+       { P_BI_TCXO, 0 },
+       { P_GPLL0_OUT_MAIN, 1 },
+       { P_SLEEP_CLK, 5 },
+       { P_GPLL0_OUT_EVEN, 6 },
+       { P_CORE_BI_PLL_TEST_SE, 7 },
+};
+
+static const struct clk_parent_data gcc_parents_3[] = {
+       { .fw_name = "bi_tcxo" },
+       { .hw = &gpll0.clkr.hw },
+       { .fw_name = "sleep_clk", .name = "sleep_clk" },
+       { .hw = &gpll0_out_even.clkr.hw },
+       { .fw_name = "core_bi_pll_test_se" },
+};
+
+static const struct parent_map gcc_parent_map_4[] = {
+       { P_BI_TCXO, 0 },
+       { P_SLEEP_CLK, 5 },
+       { P_CORE_BI_PLL_TEST_SE, 7 },
+};
+
+static const struct clk_parent_data gcc_parents_4[] = {
+       { .fw_name = "bi_tcxo" },
+       { .fw_name = "sleep_clk", .name = "sleep_clk" },
+       { .fw_name = "core_bi_pll_test_se" },
+};
+
+static const struct parent_map gcc_parent_map_5[] = {
+       { P_BI_TCXO, 0 },
+       { P_GPLL0_OUT_MAIN, 1 },
+       { P_GPLL4_OUT_EVEN, 2 },
+       { P_GPLL0_OUT_EVEN, 6 },
+       { P_CORE_BI_PLL_TEST_SE, 7 },
+};
+
+static const struct clk_parent_data gcc_parents_5[] = {
+       { .fw_name = "bi_tcxo" },
+       { .hw = &gpll0.clkr.hw },
+       { .hw = &gpll4_out_even.clkr.hw },
+       { .hw = &gpll0_out_even.clkr.hw },
+       { .fw_name = "core_bi_pll_test_se" },
+};
+
+static const struct freq_tbl ftbl_gcc_blsp1_qup1_i2c_apps_clk_src[] = {
+       F(9600000, P_BI_TCXO, 2, 0, 0),
+       F(19200000, P_BI_TCXO, 1, 0, 0),
+       F(50000000, P_GPLL0_OUT_MAIN, 12, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gcc_blsp1_qup1_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x11024,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_blsp1_qup1_i2c_apps_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_blsp1_qup1_spi_apps_clk_src[] = {
+       F(960000, P_BI_TCXO, 10, 1, 2),
+       F(4800000, P_BI_TCXO, 4, 0, 0),
+       F(9600000, P_BI_TCXO, 2, 0, 0),
+       F(15000000, P_GPLL0_OUT_EVEN, 5, 1, 4),
+       F(19200000, P_BI_TCXO, 1, 0, 0),
+       F(24000000, P_GPLL0_OUT_MAIN, 12.5, 1, 2),
+       F(25000000, P_GPLL0_OUT_MAIN, 12, 1, 2),
+       F(50000000, P_GPLL0_OUT_MAIN, 12, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gcc_blsp1_qup1_spi_apps_clk_src = {
+       .cmd_rcgr = 0x1100c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_blsp1_qup1_spi_apps_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gcc_blsp1_qup2_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x13024,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_blsp1_qup2_i2c_apps_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gcc_blsp1_qup2_spi_apps_clk_src = {
+       .cmd_rcgr = 0x1300c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_blsp1_qup2_spi_apps_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gcc_blsp1_qup3_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x15024,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_blsp1_qup3_i2c_apps_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gcc_blsp1_qup3_spi_apps_clk_src = {
+       .cmd_rcgr = 0x1500c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_blsp1_qup3_spi_apps_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gcc_blsp1_qup4_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x17024,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_i2c_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_blsp1_qup4_i2c_apps_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gcc_blsp1_qup4_spi_apps_clk_src = {
+       .cmd_rcgr = 0x1700c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_spi_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_blsp1_qup4_spi_apps_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_blsp1_uart1_apps_clk_src[] = {
+       F(3686400, P_GPLL0_OUT_EVEN, 1, 192, 15625),
+       F(7372800, P_GPLL0_OUT_EVEN, 1, 384, 15625),
+       F(9600000, P_BI_TCXO, 2, 0, 0),
+       F(14745600, P_GPLL0_OUT_EVEN, 1, 768, 15625),
+       F(16000000, P_GPLL0_OUT_EVEN, 1, 4, 75),
+       F(19200000, P_BI_TCXO, 1, 0, 0),
+       F(19354839, P_GPLL0_OUT_MAIN, 15.5, 1, 2),
+       F(20000000, P_GPLL0_OUT_MAIN, 15, 1, 2),
+       F(20689655, P_GPLL0_OUT_MAIN, 14.5, 1, 2),
+       F(21428571, P_GPLL0_OUT_MAIN, 14, 1, 2),
+       F(22222222, P_GPLL0_OUT_MAIN, 13.5, 1, 2),
+       F(23076923, P_GPLL0_OUT_MAIN, 13, 1, 2),
+       F(24000000, P_GPLL0_OUT_MAIN, 5, 1, 5),
+       F(25000000, P_GPLL0_OUT_MAIN, 12, 1, 2),
+       F(26086957, P_GPLL0_OUT_MAIN, 11.5, 1, 2),
+       F(27272727, P_GPLL0_OUT_MAIN, 11, 1, 2),
+       F(28571429, P_GPLL0_OUT_MAIN, 10.5, 1, 2),
+       F(32000000, P_GPLL0_OUT_MAIN, 1, 4, 75),
+       F(40000000, P_GPLL0_OUT_MAIN, 15, 0, 0),
+       F(46400000, P_GPLL0_OUT_MAIN, 1, 29, 375),
+       F(48000000, P_GPLL0_OUT_MAIN, 12.5, 0, 0),
+       F(51200000, P_GPLL0_OUT_MAIN, 1, 32, 375),
+       F(56000000, P_GPLL0_OUT_MAIN, 1, 7, 75),
+       F(58982400, P_GPLL0_OUT_MAIN, 1, 1536, 15625),
+       F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0),
+       F(63157895, P_GPLL0_OUT_MAIN, 9.5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gcc_blsp1_uart1_apps_clk_src = {
+       .cmd_rcgr = 0x1200c,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_blsp1_uart1_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_blsp1_uart1_apps_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gcc_blsp1_uart2_apps_clk_src = {
+       .cmd_rcgr = 0x1400c,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_blsp1_uart1_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_blsp1_uart2_apps_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gcc_blsp1_uart3_apps_clk_src = {
+       .cmd_rcgr = 0x1600c,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_blsp1_uart1_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_blsp1_uart3_apps_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gcc_blsp1_uart4_apps_clk_src = {
+       .cmd_rcgr = 0x1800c,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_blsp1_uart1_apps_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_blsp1_uart4_apps_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = {
+       F(19200000, P_BI_TCXO, 1, 0, 0),
+       F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
+       F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
+       F(133333333, P_GPLL0_OUT_MAIN, 4.5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gcc_cpuss_ahb_clk_src = {
+       .cmd_rcgr = 0x24010,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_cpuss_ahb_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_cpuss_ahb_clk_src",
+               .parent_data = gcc_parents_0_ao,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_cpuss_rbcpr_clk_src[] = {
+       F(19200000, P_BI_TCXO, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gcc_cpuss_rbcpr_clk_src = {
+       .cmd_rcgr = 0x2402c,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_cpuss_rbcpr_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_cpuss_rbcpr_clk_src",
+               .parent_data = gcc_parents_0_ao,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_emac_clk_src[] = {
+       F(2500000, P_BI_TCXO, 1, 25, 192),
+       F(5000000, P_BI_TCXO, 1, 25, 96),
+       F(19200000, P_BI_TCXO, 1, 0, 0),
+       F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0),
+       F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
+       F(250000000, P_GPLL4_OUT_EVEN, 2, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gcc_emac_clk_src = {
+       .cmd_rcgr = 0x47020,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_5,
+       .freq_tbl = ftbl_gcc_emac_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_emac_clk_src",
+               .parent_data = gcc_parents_5,
+               .num_parents = 5,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_emac_ptp_clk_src[] = {
+       F(19200000, P_BI_TCXO, 1, 0, 0),
+       F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
+       F(230400000, P_GPLL5_OUT_MAIN, 3.5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gcc_emac_ptp_clk_src = {
+       .cmd_rcgr = 0x47038,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_2,
+       .freq_tbl = ftbl_gcc_emac_ptp_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_emac_ptp_clk_src",
+               .parent_data = gcc_parents_2,
+               .num_parents = 6,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = {
+       F(19200000, P_BI_TCXO, 1, 0, 0),
+       F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0),
+       F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
+       F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
+       F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gcc_gp1_clk_src = {
+       .cmd_rcgr = 0x2b004,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_3,
+       .freq_tbl = ftbl_gcc_gp1_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_gp1_clk_src",
+               .parent_data = gcc_parents_3,
+               .num_parents = 5,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gcc_gp2_clk_src = {
+       .cmd_rcgr = 0x2c004,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_3,
+       .freq_tbl = ftbl_gcc_gp1_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_gp2_clk_src",
+               .parent_data = gcc_parents_3,
+               .num_parents = 5,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gcc_gp3_clk_src = {
+       .cmd_rcgr = 0x2d004,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_3,
+       .freq_tbl = ftbl_gcc_gp1_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_gp3_clk_src",
+               .parent_data = gcc_parents_3,
+               .num_parents = 5,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gcc_pcie_aux_phy_clk_src = {
+       .cmd_rcgr = 0x37034,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_4,
+       .freq_tbl = ftbl_gcc_cpuss_rbcpr_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_pcie_aux_phy_clk_src",
+               .parent_data = gcc_parents_4,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_pcie_rchng_phy_clk_src[] = {
+       F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gcc_pcie_rchng_phy_clk_src = {
+       .cmd_rcgr = 0x37050,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_3,
+       .freq_tbl = ftbl_gcc_pcie_rchng_phy_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_pcie_rchng_phy_clk_src",
+               .parent_data = gcc_parents_3,
+               .num_parents = 5,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = {
+       F(9600000, P_BI_TCXO, 2, 0, 0),
+       F(19200000, P_BI_TCXO, 1, 0, 0),
+       F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gcc_pdm2_clk_src = {
+       .cmd_rcgr = 0x19010,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_pdm2_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_pdm2_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gcc_sdcc1_apps_clk_src = {
+       .cmd_rcgr = 0xf00c,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_gp1_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_sdcc1_apps_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_master_clk_src[] = {
+       F(200000000, P_GPLL0_OUT_EVEN, 1.5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gcc_usb30_master_clk_src = {
+       .cmd_rcgr = 0xb024,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_usb30_master_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_usb30_master_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_mock_utmi_clk_src[] = {
+       F(19200000, P_BI_TCXO, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gcc_usb30_mock_utmi_clk_src = {
+       .cmd_rcgr = 0xb03c,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_0,
+       .freq_tbl = ftbl_gcc_usb30_mock_utmi_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_usb30_mock_utmi_clk_src",
+               .parent_data = gcc_parents_0,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_usb3_phy_aux_clk_src[] = {
+       F(1000000, P_BI_TCXO, 1, 5, 96),
+       F(19200000, P_BI_TCXO, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gcc_usb3_phy_aux_clk_src = {
+       .cmd_rcgr = 0xb064,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_4,
+       .freq_tbl = ftbl_gcc_usb3_phy_aux_clk_src,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gcc_usb3_phy_aux_clk_src",
+               .parent_data = gcc_parents_4,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_branch gcc_ahb_pcie_link_clk = {
+       .halt_reg = 0x22004,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x22004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_ahb_pcie_link_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_ahb_clk = {
+       .halt_reg = 0x10004,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x6d008,
+               .enable_mask = BIT(14),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_ahb_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
+       .halt_reg = 0x11008,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x11008,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup1_i2c_apps_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_blsp1_qup1_i2c_apps_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
+       .halt_reg = 0x11004,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x11004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup1_spi_apps_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_blsp1_qup1_spi_apps_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
+       .halt_reg = 0x13008,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x13008,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup2_i2c_apps_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_blsp1_qup2_i2c_apps_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
+       .halt_reg = 0x13004,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x13004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup2_spi_apps_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_blsp1_qup2_spi_apps_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
+       .halt_reg = 0x15008,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x15008,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup3_i2c_apps_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_blsp1_qup3_i2c_apps_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
+       .halt_reg = 0x15004,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x15004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup3_spi_apps_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_blsp1_qup3_spi_apps_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
+       .halt_reg = 0x17008,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x17008,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup4_i2c_apps_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_blsp1_qup4_i2c_apps_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
+       .halt_reg = 0x17004,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x17004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup4_spi_apps_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_blsp1_qup4_spi_apps_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_uart1_apps_clk = {
+       .halt_reg = 0x12004,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x12004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_uart1_apps_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_blsp1_uart1_apps_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_uart2_apps_clk = {
+       .halt_reg = 0x14004,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x14004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_uart2_apps_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_blsp1_uart2_apps_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_uart3_apps_clk = {
+       .halt_reg = 0x16004,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x16004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_uart3_apps_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_blsp1_uart3_apps_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_uart4_apps_clk = {
+       .halt_reg = 0x18004,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x18004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_uart4_apps_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_blsp1_uart4_apps_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+       .halt_reg = 0x1c004,
+       .halt_check = BRANCH_HALT_VOTED,
+       .hwcg_reg = 0x1c004,
+       .hwcg_bit = 1,
+       .clkr = {
+               .enable_reg = 0x6d008,
+               .enable_mask = BIT(10),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_boot_rom_ahb_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_ce1_ahb_clk = {
+       .halt_reg = 0x2100c,
+       .halt_check = BRANCH_HALT_VOTED,
+       .hwcg_reg = 0x2100c,
+       .hwcg_bit = 1,
+       .clkr = {
+               .enable_reg = 0x6d008,
+               .enable_mask = BIT(3),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_ce1_ahb_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_ce1_axi_clk = {
+       .halt_reg = 0x21008,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x6d008,
+               .enable_mask = BIT(4),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_ce1_axi_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_ce1_clk = {
+       .halt_reg = 0x21004,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x6d008,
+               .enable_mask = BIT(5),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_ce1_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_cpuss_rbcpr_clk = {
+       .halt_reg = 0x24008,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x24008,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_cpuss_rbcpr_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_cpuss_rbcpr_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_eth_axi_clk = {
+       .halt_reg = 0x4701c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x4701c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_eth_axi_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_eth_ptp_clk = {
+       .halt_reg = 0x47018,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x47018,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_eth_ptp_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_emac_ptp_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_eth_rgmii_clk = {
+       .halt_reg = 0x47010,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x47010,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_eth_rgmii_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_emac_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_eth_slave_ahb_clk = {
+       .halt_reg = 0x47014,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x47014,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_eth_slave_ahb_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+       .halt_reg = 0x2b000,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x2b000,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_gp1_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_gp1_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_gp2_clk = {
+       .halt_reg = 0x2c000,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x2c000,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_gp2_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_gp2_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_gp3_clk = {
+       .halt_reg = 0x2d000,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x2d000,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_gp3_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_gp3_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pcie_0_clkref_clk = {
+       .halt_reg = 0x88004,
+       .halt_check = BRANCH_HALT_DELAY,
+       .clkr = {
+               .enable_reg = 0x88004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_pcie_0_clkref_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pcie_aux_clk = {
+       .halt_reg = 0x37024,
+       .halt_check = BRANCH_HALT_DELAY,
+       .clkr = {
+               .enable_reg = 0x6d010,
+               .enable_mask = BIT(3),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_pcie_aux_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pcie_cfg_ahb_clk = {
+       .halt_reg = 0x3701c,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x6d010,
+               .enable_mask = BIT(2),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_pcie_cfg_ahb_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pcie_mstr_axi_clk = {
+       .halt_reg = 0x37018,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x6d010,
+               .enable_mask = BIT(1),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_pcie_mstr_axi_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pcie_pipe_clk = {
+       .halt_reg = 0x3702c,
+       .halt_check = BRANCH_HALT_DELAY,
+       .clkr = {
+               .enable_reg = 0x6d010,
+               .enable_mask = BIT(4),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_pcie_pipe_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pcie_rchng_phy_clk = {
+       .halt_reg = 0x37020,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x6d010,
+               .enable_mask = BIT(7),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_pcie_rchng_phy_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_pcie_rchng_phy_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pcie_sleep_clk = {
+       .halt_reg = 0x37028,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x6d010,
+               .enable_mask = BIT(6),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_pcie_sleep_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_pcie_aux_phy_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pcie_slv_axi_clk = {
+       .halt_reg = 0x37014,
+       .halt_check = BRANCH_HALT_VOTED,
+       .hwcg_reg = 0x37014,
+       .hwcg_bit = 1,
+       .clkr = {
+               .enable_reg = 0x6d010,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_pcie_slv_axi_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pcie_slv_q2a_axi_clk = {
+       .halt_reg = 0x37010,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x6d010,
+               .enable_mask = BIT(5),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_pcie_slv_q2a_axi_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+       .halt_reg = 0x1900c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x1900c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_pdm2_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_pdm2_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+       .halt_reg = 0x19004,
+       .halt_check = BRANCH_HALT,
+       .hwcg_reg = 0x19004,
+       .hwcg_bit = 1,
+       .clkr = {
+               .enable_reg = 0x19004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_pdm_ahb_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pdm_xo4_clk = {
+       .halt_reg = 0x19008,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x19008,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_pdm_xo4_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+       .halt_reg = 0xf008,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xf008,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_sdcc1_ahb_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+       .halt_reg = 0xf004,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xf004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_sdcc1_apps_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_sdcc1_apps_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb30_master_clk = {
+       .halt_reg = 0xb010,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb010,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_usb30_master_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_usb30_master_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb30_mock_utmi_clk = {
+       .halt_reg = 0xb020,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb020,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_usb30_mock_utmi_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_usb30_mock_utmi_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb30_mstr_axi_clk = {
+       .halt_reg = 0xb014,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb014,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_usb30_mstr_axi_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb30_sleep_clk = {
+       .halt_reg = 0xb01c,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb01c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_usb30_sleep_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb30_slv_ahb_clk = {
+       .halt_reg = 0xb018,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb018,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_usb30_slv_ahb_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb3_phy_aux_clk = {
+       .halt_reg = 0xb058,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb058,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_usb3_phy_aux_clk",
+                       .parent_hws = (const struct clk_hw *[]){
+                               &gcc_usb3_phy_aux_clk_src.clkr.hw },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb3_phy_pipe_clk = {
+       .halt_reg = 0xb05c,
+       .halt_check = BRANCH_HALT_DELAY,
+       .clkr = {
+               .enable_reg = 0xb05c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_usb3_phy_pipe_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb3_prim_clkref_clk = {
+       .halt_reg = 0x88000,
+       .halt_check = BRANCH_HALT_DELAY,
+       .clkr = {
+               .enable_reg = 0x88000,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_usb3_prim_clkref_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = {
+       .halt_reg = 0xe004,
+       .halt_check = BRANCH_HALT,
+       .hwcg_reg = 0xe004,
+       .hwcg_bit = 1,
+       .clkr = {
+               .enable_reg = 0xe004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_usb_phy_cfg_ahb2phy_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_xo_pcie_link_clk = {
+       .halt_reg = 0x22008,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x22008,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_xo_pcie_link_clk",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct gdsc usb30_gdsc = {
+       .gdscr = 0x0b004,
+       .pd = {
+               .name = "usb30_gdsc",
+       },
+       .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc pcie_gdsc = {
+       .gdscr = 0x37004,
+       .pd = {
+               .name = "pcie_gdsc",
+       },
+       .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc emac_gdsc = {
+       .gdscr = 0x47004,
+       .pd = {
+               .name = "emac_gdsc",
+       },
+       .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct clk_regmap *gcc_sdx55_clocks[] = {
+       [GCC_AHB_PCIE_LINK_CLK] = &gcc_ahb_pcie_link_clk.clkr,
+       [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
+       [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP1_I2C_APPS_CLK_SRC] =
+               &gcc_blsp1_qup1_i2c_apps_clk_src.clkr,
+       [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
+       [GCC_BLSP1_QUP1_SPI_APPS_CLK_SRC] =
+               &gcc_blsp1_qup1_spi_apps_clk_src.clkr,
+       [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP2_I2C_APPS_CLK_SRC] =
+               &gcc_blsp1_qup2_i2c_apps_clk_src.clkr,
+       [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
+       [GCC_BLSP1_QUP2_SPI_APPS_CLK_SRC] =
+               &gcc_blsp1_qup2_spi_apps_clk_src.clkr,
+       [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP3_I2C_APPS_CLK_SRC] =
+               &gcc_blsp1_qup3_i2c_apps_clk_src.clkr,
+       [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr,
+       [GCC_BLSP1_QUP3_SPI_APPS_CLK_SRC] =
+               &gcc_blsp1_qup3_spi_apps_clk_src.clkr,
+       [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP4_I2C_APPS_CLK_SRC] =
+               &gcc_blsp1_qup4_i2c_apps_clk_src.clkr,
+       [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr,
+       [GCC_BLSP1_QUP4_SPI_APPS_CLK_SRC] =
+               &gcc_blsp1_qup4_spi_apps_clk_src.clkr,
+       [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
+       [GCC_BLSP1_UART1_APPS_CLK_SRC] = &gcc_blsp1_uart1_apps_clk_src.clkr,
+       [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
+       [GCC_BLSP1_UART2_APPS_CLK_SRC] = &gcc_blsp1_uart2_apps_clk_src.clkr,
+       [GCC_BLSP1_UART3_APPS_CLK] = &gcc_blsp1_uart3_apps_clk.clkr,
+       [GCC_BLSP1_UART3_APPS_CLK_SRC] = &gcc_blsp1_uart3_apps_clk_src.clkr,
+       [GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr,
+       [GCC_BLSP1_UART4_APPS_CLK_SRC] = &gcc_blsp1_uart4_apps_clk_src.clkr,
+       [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
+       [GCC_CE1_AHB_CLK] = &gcc_ce1_ahb_clk.clkr,
+       [GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.clkr,
+       [GCC_CE1_CLK] = &gcc_ce1_clk.clkr,
+       [GCC_CPUSS_AHB_CLK_SRC] = &gcc_cpuss_ahb_clk_src.clkr,
+       [GCC_CPUSS_RBCPR_CLK] = &gcc_cpuss_rbcpr_clk.clkr,
+       [GCC_CPUSS_RBCPR_CLK_SRC] = &gcc_cpuss_rbcpr_clk_src.clkr,
+       [GCC_EMAC_CLK_SRC] = &gcc_emac_clk_src.clkr,
+       [GCC_EMAC_PTP_CLK_SRC] = &gcc_emac_ptp_clk_src.clkr,
+       [GCC_ETH_AXI_CLK] = &gcc_eth_axi_clk.clkr,
+       [GCC_ETH_PTP_CLK] = &gcc_eth_ptp_clk.clkr,
+       [GCC_ETH_RGMII_CLK] = &gcc_eth_rgmii_clk.clkr,
+       [GCC_ETH_SLAVE_AHB_CLK] = &gcc_eth_slave_ahb_clk.clkr,
+       [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+       [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr,
+       [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+       [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr,
+       [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+       [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr,
+       [GCC_PCIE_0_CLKREF_CLK] = &gcc_pcie_0_clkref_clk.clkr,
+       [GCC_PCIE_AUX_CLK] = &gcc_pcie_aux_clk.clkr,
+       [GCC_PCIE_AUX_PHY_CLK_SRC] = &gcc_pcie_aux_phy_clk_src.clkr,
+       [GCC_PCIE_CFG_AHB_CLK] = &gcc_pcie_cfg_ahb_clk.clkr,
+       [GCC_PCIE_MSTR_AXI_CLK] = &gcc_pcie_mstr_axi_clk.clkr,
+       [GCC_PCIE_PIPE_CLK] = &gcc_pcie_pipe_clk.clkr,
+       [GCC_PCIE_RCHNG_PHY_CLK] = &gcc_pcie_rchng_phy_clk.clkr,
+       [GCC_PCIE_RCHNG_PHY_CLK_SRC] = &gcc_pcie_rchng_phy_clk_src.clkr,
+       [GCC_PCIE_SLEEP_CLK] = &gcc_pcie_sleep_clk.clkr,
+       [GCC_PCIE_SLV_AXI_CLK] = &gcc_pcie_slv_axi_clk.clkr,
+       [GCC_PCIE_SLV_Q2A_AXI_CLK] = &gcc_pcie_slv_q2a_axi_clk.clkr,
+       [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+       [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr,
+       [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
+       [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr,
+       [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+       [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+       [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr,
+       [GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr,
+       [GCC_USB30_MASTER_CLK_SRC] = &gcc_usb30_master_clk_src.clkr,
+       [GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr,
+       [GCC_USB30_MOCK_UTMI_CLK_SRC] = &gcc_usb30_mock_utmi_clk_src.clkr,
+       [GCC_USB30_MSTR_AXI_CLK] = &gcc_usb30_mstr_axi_clk.clkr,
+       [GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr,
+       [GCC_USB30_SLV_AHB_CLK] = &gcc_usb30_slv_ahb_clk.clkr,
+       [GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr,
+       [GCC_USB3_PHY_AUX_CLK_SRC] = &gcc_usb3_phy_aux_clk_src.clkr,
+       [GCC_USB3_PHY_PIPE_CLK] = &gcc_usb3_phy_pipe_clk.clkr,
+       [GCC_USB3_PRIM_CLKREF_CLK] = &gcc_usb3_prim_clkref_clk.clkr,
+       [GCC_USB_PHY_CFG_AHB2PHY_CLK] = &gcc_usb_phy_cfg_ahb2phy_clk.clkr,
+       [GCC_XO_PCIE_LINK_CLK] = &gcc_xo_pcie_link_clk.clkr,
+       [GPLL0] = &gpll0.clkr,
+       [GPLL0_OUT_EVEN] = &gpll0_out_even.clkr,
+       [GPLL4] = &gpll4.clkr,
+       [GPLL4_OUT_EVEN] = &gpll4_out_even.clkr,
+       [GPLL5] = &gpll5.clkr,
+};
+
+static const struct qcom_reset_map gcc_sdx55_resets[] = {
+       [GCC_EMAC_BCR] = { 0x47000 },
+       [GCC_PCIE_BCR] = { 0x37000 },
+       [GCC_PCIE_LINK_DOWN_BCR] = { 0x77000 },
+       [GCC_PCIE_PHY_BCR] = { 0x39000 },
+       [GCC_PCIE_PHY_COM_BCR] = { 0x78004 },
+       [GCC_QUSB2PHY_BCR] = { 0xd000 },
+       [GCC_USB30_BCR] = { 0xb000 },
+       [GCC_USB3_PHY_BCR] = { 0xc000 },
+       [GCC_USB3PHY_PHY_BCR] = { 0xc004 },
+       [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0xe000 },
+};
+
+static struct gdsc *gcc_sdx55_gdscs[] = {
+       [USB30_GDSC] = &usb30_gdsc,
+       [PCIE_GDSC] = &pcie_gdsc,
+       [EMAC_GDSC] = &emac_gdsc,
+};
+
+static const struct regmap_config gcc_sdx55_regmap_config = {
+       .reg_bits       = 32,
+       .reg_stride     = 4,
+       .val_bits       = 32,
+       .max_register   = 0x9b040,
+       .fast_io        = true,
+};
+
+static const struct qcom_cc_desc gcc_sdx55_desc = {
+       .config = &gcc_sdx55_regmap_config,
+       .clks = gcc_sdx55_clocks,
+       .num_clks = ARRAY_SIZE(gcc_sdx55_clocks),
+       .resets = gcc_sdx55_resets,
+       .num_resets = ARRAY_SIZE(gcc_sdx55_resets),
+       .gdscs = gcc_sdx55_gdscs,
+       .num_gdscs = ARRAY_SIZE(gcc_sdx55_gdscs),
+};
+
+static const struct of_device_id gcc_sdx55_match_table[] = {
+       { .compatible = "qcom,gcc-sdx55" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, gcc_sdx55_match_table);
+
+static int gcc_sdx55_probe(struct platform_device *pdev)
+{
+       struct regmap *regmap;
+
+       regmap = qcom_cc_map(pdev, &gcc_sdx55_desc);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
+       /*
+        * Keep the clocks always-ON as they are critical to the functioning
+        * of the system:
+        * GCC_SYS_NOC_CPUSS_AHB_CLK, GCC_CPUSS_AHB_CLK, GCC_CPUSS_GNOC_CLK
+        */
+       regmap_update_bits(regmap, 0x6d008, BIT(0), BIT(0));
+       regmap_update_bits(regmap, 0x6d008, BIT(21), BIT(21));
+       regmap_update_bits(regmap, 0x6d008, BIT(22), BIT(22));
+
+       return qcom_cc_really_probe(pdev, &gcc_sdx55_desc, regmap);
+}
+
+static struct platform_driver gcc_sdx55_driver = {
+       .probe = gcc_sdx55_probe,
+       .driver = {
+               .name = "gcc-sdx55",
+               .of_match_table = gcc_sdx55_match_table,
+       },
+};
+
+static int __init gcc_sdx55_init(void)
+{
+       return platform_driver_register(&gcc_sdx55_driver);
+}
+subsys_initcall(gcc_sdx55_init);
+
+static void __exit gcc_sdx55_exit(void)
+{
+       platform_driver_unregister(&gcc_sdx55_driver);
+}
+module_exit(gcc_sdx55_exit);
+
+MODULE_DESCRIPTION("QTI GCC SDX55 Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/qcom/lpass-gfm-sm8250.c b/drivers/clk/qcom/lpass-gfm-sm8250.c
new file mode 100644 (file)
index 0000000..d366c7c
--- /dev/null
@@ -0,0 +1,320 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * LPASS Audio CC and Always ON CC Glitch Free Mux clock driver
+ *
+ * Copyright (c) 2020 Linaro Ltd.
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <dt-bindings/clock/qcom,sm8250-lpass-audiocc.h>
+#include <dt-bindings/clock/qcom,sm8250-lpass-aoncc.h>
+
+struct lpass_gfm {
+       struct device *dev;
+       void __iomem *base;
+};
+
+struct clk_gfm {
+       unsigned int mux_reg;
+       unsigned int mux_mask;
+       struct clk_hw   hw;
+       struct lpass_gfm *priv;
+       void __iomem *gfm_mux;
+};
+
+#define GFM_MASK       BIT(1)
+#define to_clk_gfm(_hw) container_of(_hw, struct clk_gfm, hw)
+
+static u8 clk_gfm_get_parent(struct clk_hw *hw)
+{
+       struct clk_gfm *clk = to_clk_gfm(hw);
+
+       return readl(clk->gfm_mux) & GFM_MASK;
+}
+
+static int clk_gfm_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct clk_gfm *clk = to_clk_gfm(hw);
+       unsigned int val;
+
+       val = readl(clk->gfm_mux);
+
+       if (index)
+               val |= GFM_MASK;
+       else
+               val &= ~GFM_MASK;
+
+       writel(val, clk->gfm_mux);
+
+       return 0;
+}
+
+static const struct clk_ops clk_gfm_ops = {
+       .get_parent = clk_gfm_get_parent,
+       .set_parent = clk_gfm_set_parent,
+       .determine_rate = __clk_mux_determine_rate,
+};
+
+static struct clk_gfm lpass_gfm_va_mclk = {
+       .mux_reg = 0x20000,
+       .mux_mask = BIT(0),
+       .hw.init = &(struct clk_init_data) {
+               .name = "VA_MCLK",
+               .ops = &clk_gfm_ops,
+               .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+               .num_parents = 2,
+               .parent_data = (const struct clk_parent_data[]){
+                       {
+                               .index = 0,
+                               .fw_name = "LPASS_CLK_ID_TX_CORE_MCLK",
+                       }, {
+                               .index = 1,
+                               .fw_name = "LPASS_CLK_ID_VA_CORE_MCLK",
+                       },
+               },
+       },
+};
+
+static struct clk_gfm lpass_gfm_tx_npl = {
+       .mux_reg = 0x20000,
+       .mux_mask = BIT(0),
+       .hw.init = &(struct clk_init_data) {
+               .name = "TX_NPL",
+               .ops = &clk_gfm_ops,
+               .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+               .parent_data = (const struct clk_parent_data[]){
+                       {
+                               .index = 0,
+                               .fw_name = "LPASS_CLK_ID_TX_CORE_NPL_MCLK",
+                       }, {
+                               .index = 1,
+                               .fw_name = "LPASS_CLK_ID_VA_CORE_2X_MCLK",
+                       },
+               },
+               .num_parents = 2,
+       },
+};
+
+static struct clk_gfm lpass_gfm_wsa_mclk = {
+       .mux_reg = 0x220d8,
+       .mux_mask = BIT(0),
+       .hw.init = &(struct clk_init_data) {
+               .name = "WSA_MCLK",
+               .ops = &clk_gfm_ops,
+               .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+               .parent_data = (const struct clk_parent_data[]){
+                       {
+                               .index = 0,
+                               .fw_name = "LPASS_CLK_ID_TX_CORE_MCLK",
+                       }, {
+                               .index = 1,
+                               .fw_name = "LPASS_CLK_ID_WSA_CORE_MCLK",
+                       },
+               },
+               .num_parents = 2,
+       },
+};
+
+static struct clk_gfm lpass_gfm_wsa_npl = {
+       .mux_reg = 0x220d8,
+       .mux_mask = BIT(0),
+       .hw.init = &(struct clk_init_data) {
+               .name = "WSA_NPL",
+               .ops = &clk_gfm_ops,
+               .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+               .parent_data = (const struct clk_parent_data[]){
+                       {
+                               .index = 0,
+                               .fw_name = "LPASS_CLK_ID_TX_CORE_NPL_MCLK",
+                       }, {
+                               .index = 1,
+                               .fw_name = "LPASS_CLK_ID_WSA_CORE_NPL_MCLK",
+                       },
+               },
+               .num_parents = 2,
+       },
+};
+
+static struct clk_gfm lpass_gfm_rx_mclk_mclk2 = {
+       .mux_reg = 0x240d8,
+       .mux_mask = BIT(0),
+       .hw.init = &(struct clk_init_data) {
+               .name = "RX_MCLK_MCLK2",
+               .ops = &clk_gfm_ops,
+               .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+               .parent_data = (const struct clk_parent_data[]){
+                       {
+                               .index = 0,
+                               .fw_name = "LPASS_CLK_ID_TX_CORE_MCLK",
+                       }, {
+                               .index = 1,
+                               .fw_name = "LPASS_CLK_ID_RX_CORE_MCLK",
+                       },
+               },
+               .num_parents = 2,
+       },
+};
+
+static struct clk_gfm lpass_gfm_rx_npl = {
+       .mux_reg = 0x240d8,
+       .mux_mask = BIT(0),
+       .hw.init = &(struct clk_init_data) {
+               .name = "RX_NPL",
+               .ops = &clk_gfm_ops,
+               .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+               .parent_data = (const struct clk_parent_data[]){
+                       {
+                               .index = 0,
+                               .fw_name = "LPASS_CLK_ID_TX_CORE_NPL_MCLK",
+                       }, {
+                               .index = 1,
+                               .fw_name = "LPASS_CLK_ID_RX_CORE_NPL_MCLK",
+                       },
+               },
+               .num_parents = 2,
+       },
+};
+
+static struct clk_gfm *aoncc_gfm_clks[] = {
+       [LPASS_CDC_VA_MCLK]             = &lpass_gfm_va_mclk,
+       [LPASS_CDC_TX_NPL]              = &lpass_gfm_tx_npl,
+};
+
+static struct clk_hw_onecell_data aoncc_hw_onecell_data = {
+       .hws = {
+               [LPASS_CDC_VA_MCLK]     = &lpass_gfm_va_mclk.hw,
+               [LPASS_CDC_TX_NPL]      = &lpass_gfm_tx_npl.hw,
+       },
+       .num = ARRAY_SIZE(aoncc_gfm_clks),
+};
+
+static struct clk_gfm *audiocc_gfm_clks[] = {
+       [LPASS_CDC_WSA_NPL]             = &lpass_gfm_wsa_npl,
+       [LPASS_CDC_WSA_MCLK]            = &lpass_gfm_wsa_mclk,
+       [LPASS_CDC_RX_NPL]              = &lpass_gfm_rx_npl,
+       [LPASS_CDC_RX_MCLK_MCLK2]       = &lpass_gfm_rx_mclk_mclk2,
+};
+
+static struct clk_hw_onecell_data audiocc_hw_onecell_data = {
+       .hws = {
+               [LPASS_CDC_WSA_NPL]     = &lpass_gfm_wsa_npl.hw,
+               [LPASS_CDC_WSA_MCLK]    = &lpass_gfm_wsa_mclk.hw,
+               [LPASS_CDC_RX_NPL]      = &lpass_gfm_rx_npl.hw,
+               [LPASS_CDC_RX_MCLK_MCLK2] = &lpass_gfm_rx_mclk_mclk2.hw,
+       },
+       .num = ARRAY_SIZE(audiocc_gfm_clks),
+};
+
+struct lpass_gfm_data {
+       struct clk_hw_onecell_data *onecell_data;
+       struct clk_gfm **gfm_clks;
+};
+
+static struct lpass_gfm_data audiocc_data = {
+       .onecell_data = &audiocc_hw_onecell_data,
+       .gfm_clks = audiocc_gfm_clks,
+};
+
+static struct lpass_gfm_data aoncc_data = {
+       .onecell_data = &aoncc_hw_onecell_data,
+       .gfm_clks = aoncc_gfm_clks,
+};
+
+static int lpass_gfm_clk_driver_probe(struct platform_device *pdev)
+{
+       const struct lpass_gfm_data *data;
+       struct device *dev = &pdev->dev;
+       struct clk_gfm *gfm;
+       struct lpass_gfm *cc;
+       int err, i;
+
+       data = of_device_get_match_data(dev);
+       if (!data)
+               return -EINVAL;
+
+       cc = devm_kzalloc(dev, sizeof(*cc), GFP_KERNEL);
+       if (!cc)
+               return -ENOMEM;
+
+       cc->base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(cc->base))
+               return PTR_ERR(cc->base);
+
+       pm_runtime_enable(dev);
+       err = pm_clk_create(dev);
+       if (err)
+               goto pm_clk_err;
+
+       err = of_pm_clk_add_clks(dev);
+       if (err < 0) {
+               dev_dbg(dev, "Failed to get lpass core voting clocks\n");
+               goto clk_reg_err;
+       }
+
+       for (i = 0; i < data->onecell_data->num; i++) {
+               if (!data->gfm_clks[i])
+                       continue;
+
+               gfm = data->gfm_clks[i];
+               gfm->priv = cc;
+               gfm->gfm_mux = cc->base;
+               gfm->gfm_mux = gfm->gfm_mux + data->gfm_clks[i]->mux_reg;
+
+               err = devm_clk_hw_register(dev, &data->gfm_clks[i]->hw);
+               if (err)
+                       goto clk_reg_err;
+
+       }
+
+       err = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+                                         data->onecell_data);
+       if (err)
+               goto clk_reg_err;
+
+       return 0;
+
+clk_reg_err:
+       pm_clk_destroy(dev);
+pm_clk_err:
+       pm_runtime_disable(dev);
+       return err;
+}
+
+static const struct of_device_id lpass_gfm_clk_match_table[] = {
+       {
+               .compatible = "qcom,sm8250-lpass-aoncc",
+               .data = &aoncc_data,
+       },
+       {
+               .compatible = "qcom,sm8250-lpass-audiocc",
+               .data = &audiocc_data,
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, lpass_gfm_clk_match_table);
+
+static const struct dev_pm_ops lpass_gfm_pm_ops = {
+       SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
+};
+
+static struct platform_driver lpass_gfm_clk_driver = {
+       .probe          = lpass_gfm_clk_driver_probe,
+       .driver         = {
+               .name   = "lpass-gfm-clk",
+               .of_match_table = lpass_gfm_clk_match_table,
+               .pm = &lpass_gfm_pm_ops,
+       },
+};
+module_platform_driver(lpass_gfm_clk_driver);
+MODULE_LICENSE("GPL v2");
index 228d08f5d26fa12b4aecfe0f649123c7f08ff86c..2e0ecc38efdd1963be7477435890c0ed38accde3 100644 (file)
@@ -356,12 +356,52 @@ static const struct qcom_cc_desc lpass_audio_hm_sc7180_desc = {
        .num_gdscs = ARRAY_SIZE(lpass_audio_hm_sc7180_gdscs),
 };
 
+static void lpass_pm_runtime_disable(void *data)
+{
+       pm_runtime_disable(data);
+}
+
+static void lpass_pm_clk_destroy(void *data)
+{
+       pm_clk_destroy(data);
+}
+
+static int lpass_create_pm_clks(struct platform_device *pdev)
+{
+       int ret;
+
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
+       pm_runtime_enable(&pdev->dev);
+
+       ret = devm_add_action_or_reset(&pdev->dev, lpass_pm_runtime_disable, &pdev->dev);
+       if (ret)
+               return ret;
+
+       ret = pm_clk_create(&pdev->dev);
+       if (ret)
+               return ret;
+       ret = devm_add_action_or_reset(&pdev->dev, lpass_pm_clk_destroy, &pdev->dev);
+       if (ret)
+               return ret;
+
+       ret = pm_clk_add(&pdev->dev, "iface");
+       if (ret < 0)
+               dev_err(&pdev->dev, "failed to acquire iface clock\n");
+
+       return ret;
+}
+
 static int lpass_core_cc_sc7180_probe(struct platform_device *pdev)
 {
        const struct qcom_cc_desc *desc;
        struct regmap *regmap;
        int ret;
 
+       ret = lpass_create_pm_clks(pdev);
+       if (ret)
+               return ret;
+
        lpass_core_cc_sc7180_regmap_config.name = "lpass_audio_cc";
        desc = &lpass_audio_hm_sc7180_desc;
        ret = qcom_cc_probe_by_index(pdev, 1, desc);
@@ -386,12 +426,22 @@ static int lpass_core_cc_sc7180_probe(struct platform_device *pdev)
        clk_fabia_pll_configure(&lpass_lpaaudio_dig_pll, regmap,
                                &lpass_lpaaudio_dig_pll_config);
 
-       return qcom_cc_really_probe(pdev, &lpass_core_cc_sc7180_desc, regmap);
+       ret = qcom_cc_really_probe(pdev, &lpass_core_cc_sc7180_desc, regmap);
+
+       pm_runtime_mark_last_busy(&pdev->dev);
+       pm_runtime_put_autosuspend(&pdev->dev);
+
+       return ret;
 }
 
 static int lpass_hm_core_probe(struct platform_device *pdev)
 {
        const struct qcom_cc_desc *desc;
+       int ret;
+
+       ret = lpass_create_pm_clks(pdev);
+       if (ret)
+               return ret;
 
        lpass_core_cc_sc7180_regmap_config.name = "lpass_hm_core";
        desc = &lpass_core_hm_sc7180_desc;
@@ -399,61 +449,28 @@ static int lpass_hm_core_probe(struct platform_device *pdev)
        return qcom_cc_probe_by_index(pdev, 0, desc);
 }
 
-static const struct of_device_id lpass_core_cc_sc7180_match_table[] = {
+static const struct of_device_id lpass_hm_sc7180_match_table[] = {
        {
                .compatible = "qcom,sc7180-lpasshm",
-               .data = lpass_hm_core_probe,
        },
+       { }
+};
+MODULE_DEVICE_TABLE(of, lpass_hm_sc7180_match_table);
+
+static const struct of_device_id lpass_core_cc_sc7180_match_table[] = {
        {
                .compatible = "qcom,sc7180-lpasscorecc",
-               .data = lpass_core_cc_sc7180_probe,
        },
        { }
 };
 MODULE_DEVICE_TABLE(of, lpass_core_cc_sc7180_match_table);
 
-static int lpass_core_sc7180_probe(struct platform_device *pdev)
-{
-       int (*clk_probe)(struct platform_device *p);
-       int ret;
-
-       pm_runtime_enable(&pdev->dev);
-       ret = pm_clk_create(&pdev->dev);
-       if (ret)
-               goto disable_pm_runtime;
-
-       ret = pm_clk_add(&pdev->dev, "iface");
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to acquire iface clock\n");
-               goto destroy_pm_clk;
-       }
-
-       ret = -EINVAL;
-       clk_probe = of_device_get_match_data(&pdev->dev);
-       if (!clk_probe)
-               goto destroy_pm_clk;
-
-       ret = clk_probe(pdev);
-       if (ret)
-               goto destroy_pm_clk;
-
-       return 0;
-
-destroy_pm_clk:
-       pm_clk_destroy(&pdev->dev);
-
-disable_pm_runtime:
-       pm_runtime_disable(&pdev->dev);
-
-       return ret;
-}
-
 static const struct dev_pm_ops lpass_core_cc_pm_ops = {
        SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
 };
 
 static struct platform_driver lpass_core_cc_sc7180_driver = {
-       .probe = lpass_core_sc7180_probe,
+       .probe = lpass_core_cc_sc7180_probe,
        .driver = {
                .name = "lpass_core_cc-sc7180",
                .of_match_table = lpass_core_cc_sc7180_match_table,
@@ -461,17 +478,43 @@ static struct platform_driver lpass_core_cc_sc7180_driver = {
        },
 };
 
-static int __init lpass_core_cc_sc7180_init(void)
+static const struct dev_pm_ops lpass_hm_pm_ops = {
+       SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
+};
+
+static struct platform_driver lpass_hm_sc7180_driver = {
+       .probe = lpass_hm_core_probe,
+       .driver = {
+               .name = "lpass_hm-sc7180",
+               .of_match_table = lpass_hm_sc7180_match_table,
+               .pm = &lpass_hm_pm_ops,
+       },
+};
+
+static int __init lpass_sc7180_init(void)
 {
-       return platform_driver_register(&lpass_core_cc_sc7180_driver);
+       int ret;
+
+       ret = platform_driver_register(&lpass_core_cc_sc7180_driver);
+       if (ret)
+               return ret;
+
+       ret = platform_driver_register(&lpass_hm_sc7180_driver);
+       if (ret) {
+               platform_driver_unregister(&lpass_core_cc_sc7180_driver);
+               return ret;
+       }
+
+       return 0;
 }
-subsys_initcall(lpass_core_cc_sc7180_init);
+subsys_initcall(lpass_sc7180_init);
 
-static void __exit lpass_core_cc_sc7180_exit(void)
+static void __exit lpass_sc7180_exit(void)
 {
+       platform_driver_unregister(&lpass_hm_sc7180_driver);
        platform_driver_unregister(&lpass_core_cc_sc7180_driver);
 }
-module_exit(lpass_core_cc_sc7180_exit);
+module_exit(lpass_sc7180_exit);
 
 MODULE_DESCRIPTION("QTI LPASS_CORE_CC SC7180 Driver");
 MODULE_LICENSE("GPL v2");
index 5f25a70bc61c40464971e44c108dda123d6d8365..4146c1d717b96f9398526b9ef8643d35120ce711 100644 (file)
@@ -121,7 +121,7 @@ sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg,
                        (phy_no ? CPG_DSI1PHYCR : CPG_DSI0PHYCR);
 
                parent_name = phy_no ? "dsi1pck" : "dsi0pck";
-               mult = __raw_readl(dsi_reg);
+               mult = readl(dsi_reg);
                if (!(mult & 0x8000))
                        mult = 1;
                else
index fd54b9f625dadde6b4837260be33c7d6ddb78ac0..4a43ebec7d5e297eb064c995fe79a5981820d393 100644 (file)
@@ -41,6 +41,7 @@ enum clk_ids {
        CLK_S2,
        CLK_S3,
        CLK_SDSRC,
+       CLK_RPCSRC,
        CLK_RINT,
 
        /* Module Clocks */
@@ -67,6 +68,12 @@ static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = {
        DEF_FIXED(".s2",        CLK_S2,            CLK_PLL1_DIV2,  4, 1),
        DEF_FIXED(".s3",        CLK_S3,            CLK_PLL1_DIV2,  6, 1),
        DEF_FIXED(".sdsrc",     CLK_SDSRC,         CLK_PLL1_DIV2,  2, 1),
+       DEF_BASE(".rpcsrc",     CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1),
+
+       DEF_BASE("rpc",         R8A774A1_CLK_RPC, CLK_TYPE_GEN3_RPC,
+                CLK_RPCSRC),
+       DEF_BASE("rpcd2",       R8A774A1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2,
+                R8A774A1_CLK_RPC),
 
        DEF_GEN3_OSC(".r",      CLK_RINT,          CLK_EXTAL,      32),
 
@@ -200,6 +207,7 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = {
        DEF_MOD("can-fd",                914,   R8A774A1_CLK_S3D2),
        DEF_MOD("can-if1",               915,   R8A774A1_CLK_S3D4),
        DEF_MOD("can-if0",               916,   R8A774A1_CLK_S3D4),
+       DEF_MOD("rpc-if",                917,   R8A774A1_CLK_RPCD2),
        DEF_MOD("i2c6",                  918,   R8A774A1_CLK_S0D6),
        DEF_MOD("i2c5",                  919,   R8A774A1_CLK_S0D6),
        DEF_MOD("i2c-dvfs",              926,   R8A774A1_CLK_CP),
index f436691271ece627bd77318e487eda27506e827a..6f04c40fe237a25576eebed7338a5ff4e618fb85 100644 (file)
@@ -40,6 +40,7 @@ enum clk_ids {
        CLK_S2,
        CLK_S3,
        CLK_SDSRC,
+       CLK_RPCSRC,
        CLK_RINT,
 
        /* Module Clocks */
@@ -65,6 +66,12 @@ static const struct cpg_core_clk r8a774b1_core_clks[] __initconst = {
        DEF_FIXED(".s2",        CLK_S2,            CLK_PLL1_DIV2,  4, 1),
        DEF_FIXED(".s3",        CLK_S3,            CLK_PLL1_DIV2,  6, 1),
        DEF_FIXED(".sdsrc",     CLK_SDSRC,         CLK_PLL1_DIV2,  2, 1),
+       DEF_BASE(".rpcsrc",     CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1),
+
+       DEF_BASE("rpc",         R8A774B1_CLK_RPC, CLK_TYPE_GEN3_RPC,
+                CLK_RPCSRC),
+       DEF_BASE("rpcd2",       R8A774B1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2,
+                R8A774B1_CLK_RPC),
 
        DEF_GEN3_OSC(".r",      CLK_RINT,          CLK_EXTAL,      32),
 
@@ -196,6 +203,7 @@ static const struct mssr_mod_clk r8a774b1_mod_clks[] __initconst = {
        DEF_MOD("can-fd",                914,   R8A774B1_CLK_S3D2),
        DEF_MOD("can-if1",               915,   R8A774B1_CLK_S3D4),
        DEF_MOD("can-if0",               916,   R8A774B1_CLK_S3D4),
+       DEF_MOD("rpc-if",                917,   R8A774B1_CLK_RPCD2),
        DEF_MOD("i2c6",                  918,   R8A774B1_CLK_S0D6),
        DEF_MOD("i2c5",                  919,   R8A774B1_CLK_S0D6),
        DEF_MOD("i2c-dvfs",              926,   R8A774B1_CLK_CP),
index 9fc9fa9e531ab42e955d6a69be6a4ec78071071e..ed3a2cf0e0bb26d25f009507bfb297d270b0a4a7 100644 (file)
@@ -44,6 +44,7 @@ enum clk_ids {
        CLK_S2,
        CLK_S3,
        CLK_SDSRC,
+       CLK_RPCSRC,
        CLK_RINT,
        CLK_OCO,
 
@@ -74,6 +75,13 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = {
        DEF_FIXED(".s3",       CLK_S3,             CLK_PLL1,       6, 1),
        DEF_FIXED(".sdsrc",    CLK_SDSRC,          CLK_PLL1,       2, 1),
 
+       DEF_FIXED_RPCSRC_E3(".rpcsrc", CLK_RPCSRC, CLK_PLL0, CLK_PLL1),
+
+       DEF_BASE("rpc",         R8A774C0_CLK_RPC, CLK_TYPE_GEN3_RPC,
+                CLK_RPCSRC),
+       DEF_BASE("rpcd2",       R8A774C0_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2,
+                R8A774C0_CLK_RPC),
+
        DEF_DIV6_RO(".r",      CLK_RINT,           CLK_EXTAL, CPG_RCKCR, 32),
 
        DEF_RATE(".oco",       CLK_OCO,            8 * 1000 * 1000),
@@ -199,6 +207,7 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = {
        DEF_MOD("can-fd",                914,   R8A774C0_CLK_S3D2),
        DEF_MOD("can-if1",               915,   R8A774C0_CLK_S3D4),
        DEF_MOD("can-if0",               916,   R8A774C0_CLK_S3D4),
+       DEF_MOD("rpc-if",                917,   R8A774C0_CLK_RPCD2),
        DEF_MOD("i2c6",                  918,   R8A774C0_CLK_S3D2),
        DEF_MOD("i2c5",                  919,   R8A774C0_CLK_S3D2),
        DEF_MOD("i2c-dvfs",              926,   R8A774C0_CLK_CP),
index 17ebbac7ddfb49255acbf3b89200f397b228e88e..aa5389b04d74204b1f8b196963fc2392b375ff1f 100644 (file)
@@ -26,7 +26,6 @@
 #include <dt-bindings/clock/r8a779a0-cpg-mssr.h>
 
 #include "renesas-cpg-mssr.h"
-#include "rcar-gen3-cpg.h"
 
 enum rcar_r8a779a0_clk_types {
        CLK_TYPE_R8A779A0_MAIN = CLK_TYPE_CUSTOM,
@@ -84,6 +83,14 @@ enum clk_ids {
        DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_PLL2X_3X, CLK_MAIN, \
                 .offset = _offset)
 
+#define DEF_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \
+       DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_MDSEL,   \
+                (_parent0) << 16 | (_parent1),         \
+                .div = (_div0) << 16 | (_div1), .offset = _md)
+
+#define DEF_OSC(_name, _id, _parent, _div)             \
+       DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_OSC, _parent, .div = _div)
+
 static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
        /* External Clock Inputs */
        DEF_INPUT("extal",  CLK_EXTAL),
@@ -136,15 +143,51 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
        DEF_DIV6P1("canfd",     R8A779A0_CLK_CANFD,     CLK_PLL5_DIV4,  0x878),
        DEF_DIV6P1("csi0",      R8A779A0_CLK_CSI0,      CLK_PLL5_DIV4,  0x880),
 
-       DEF_GEN3_OSC("osc",     R8A779A0_CLK_OSC,       CLK_EXTAL,      8),
-       DEF_GEN3_MDSEL("r",     R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
+       DEF_OSC("osc",          R8A779A0_CLK_OSC,       CLK_EXTAL,      8),
+       DEF_MDSEL("r",          R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1),
 };
 
 static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
+       DEF_MOD("csi40",        331,    R8A779A0_CLK_CSI0),
+       DEF_MOD("csi41",        400,    R8A779A0_CLK_CSI0),
+       DEF_MOD("csi42",        401,    R8A779A0_CLK_CSI0),
+       DEF_MOD("csi43",        402,    R8A779A0_CLK_CSI0),
        DEF_MOD("scif0",        702,    R8A779A0_CLK_S1D8),
        DEF_MOD("scif1",        703,    R8A779A0_CLK_S1D8),
        DEF_MOD("scif3",        704,    R8A779A0_CLK_S1D8),
        DEF_MOD("scif4",        705,    R8A779A0_CLK_S1D8),
+       DEF_MOD("vin00",        730,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin01",        731,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin02",        800,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin03",        801,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin04",        802,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin05",        803,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin06",        804,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin07",        805,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin10",        806,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin11",        807,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin12",        808,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin13",        809,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin14",        810,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin15",        811,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin16",        812,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin17",        813,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin20",        814,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin21",        815,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin22",        816,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin23",        817,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin24",        818,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin25",        819,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin26",        820,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin27",        821,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin30",        822,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin31",        823,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin32",        824,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin33",        825,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin34",        826,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin35",        827,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin36",        828,    R8A779A0_CLK_S1D1),
+       DEF_MOD("vin37",        829,    R8A779A0_CLK_S1D1),
 };
 
 static spinlock_t cpg_lock;
@@ -153,7 +196,7 @@ static const struct rcar_r8a779a0_cpg_pll_config *cpg_pll_config __initdata;
 static unsigned int cpg_clk_extalr __initdata;
 static u32 cpg_mode __initdata;
 
-struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev,
+static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev,
        const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
        struct clk **clks, void __iomem *base,
        struct raw_notifier_head *notifiers)
index 488f8b3980c55072009b1f4642efc6e31186b560..063b6115148869aa014216343cfa06407a30b77b 100644 (file)
@@ -224,10 +224,9 @@ static struct clk * __init cpg_z_clk_register(const char *name,
 #define CPG_SD_STP_MASK                (CPG_SD_STP_HCK | CPG_SD_STP_CK)
 #define CPG_SD_FC_MASK         (0x7 << 2 | 0x3 << 0)
 
-#define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \
+#define CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) \
 { \
        .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
-              ((stp_ck) ? CPG_SD_STP_CK : 0) | \
               ((sd_srcfc) << 2) | \
               ((sd_fc) << 0), \
        .div = (sd_div), \
@@ -247,36 +246,36 @@ struct sd_clock {
 };
 
 /* SDn divider
- *                     sd_srcfc   sd_fc   div
- * stp_hck   stp_ck    (div)      (div)     = sd_srcfc x sd_fc
- *-------------------------------------------------------------------
- *  0         0         0 (1)      1 (4)      4 : SDR104 / HS200 / HS400 (8 TAP)
- *  0         0         1 (2)      1 (4)      8 : SDR50
- *  1         0         2 (4)      1 (4)     16 : HS / SDR25
- *  1         0         3 (8)      1 (4)     32 : NS / SDR12
- *  1         0         4 (16)     1 (4)     64
- *  0         0         0 (1)      0 (2)      2
- *  0         0         1 (2)      0 (2)      4 : SDR104 / HS200 / HS400 (4 TAP)
- *  1         0         2 (4)      0 (2)      8
- *  1         0         3 (8)      0 (2)     16
- *  1         0         4 (16)     0 (2)     32
+ *           sd_srcfc   sd_fc   div
+ * stp_hck   (div)      (div)     = sd_srcfc x sd_fc
+ *---------------------------------------------------------
+ *  0         0 (1)      1 (4)      4 : SDR104 / HS200 / HS400 (8 TAP)
+ *  0         1 (2)      1 (4)      8 : SDR50
+ *  1         2 (4)      1 (4)     16 : HS / SDR25
+ *  1         3 (8)      1 (4)     32 : NS / SDR12
+ *  1         4 (16)     1 (4)     64
+ *  0         0 (1)      0 (2)      2
+ *  0         1 (2)      0 (2)      4 : SDR104 / HS200 / HS400 (4 TAP)
+ *  1         2 (4)      0 (2)      8
+ *  1         3 (8)      0 (2)     16
+ *  1         4 (16)     0 (2)     32
  *
  *  NOTE: There is a quirk option to ignore the first row of the dividers
  *  table when searching for suitable settings. This is because HS400 on
  *  early ES versions of H3 and M3-W requires a specific setting to work.
  */
 static const struct sd_div_table cpg_sd_div_table[] = {
-/*     CPG_SD_DIV_TABLE_DATA(stp_hck,  stp_ck,   sd_srcfc,   sd_fc,  sd_div) */
-       CPG_SD_DIV_TABLE_DATA(0,        0,        0,          1,        4),
-       CPG_SD_DIV_TABLE_DATA(0,        0,        1,          1,        8),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        2,          1,       16),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        3,          1,       32),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        4,          1,       64),
-       CPG_SD_DIV_TABLE_DATA(0,        0,        0,          0,        2),
-       CPG_SD_DIV_TABLE_DATA(0,        0,        1,          0,        4),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        2,          0,        8),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        3,          0,       16),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        4,          0,       32),
+/*     CPG_SD_DIV_TABLE_DATA(stp_hck,  sd_srcfc,   sd_fc,  sd_div) */
+       CPG_SD_DIV_TABLE_DATA(0,        0,          1,        4),
+       CPG_SD_DIV_TABLE_DATA(0,        1,          1,        8),
+       CPG_SD_DIV_TABLE_DATA(1,        2,          1,       16),
+       CPG_SD_DIV_TABLE_DATA(1,        3,          1,       32),
+       CPG_SD_DIV_TABLE_DATA(1,        4,          1,       64),
+       CPG_SD_DIV_TABLE_DATA(0,        0,          0,        2),
+       CPG_SD_DIV_TABLE_DATA(0,        1,          0,        4),
+       CPG_SD_DIV_TABLE_DATA(1,        2,          0,        8),
+       CPG_SD_DIV_TABLE_DATA(1,        3,          0,       16),
+       CPG_SD_DIV_TABLE_DATA(1,        4,          0,       32),
 };
 
 #define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw)
@@ -696,6 +695,34 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
                                                  cpg_rpcsrc_div_table,
                                                  &cpg_lock);
 
+       case CLK_TYPE_GEN3_E3_RPCSRC:
+               /*
+                * Register RPCSRC as fixed factor clock based on the
+                * MD[4:1] pins and CPG_RPCCKCR[4:3] register value for
+                * which has been set prior to booting the kernel.
+                */
+               value = (readl(base + CPG_RPCCKCR) & GENMASK(4, 3)) >> 3;
+
+               switch (value) {
+               case 0:
+                       div = 5;
+                       break;
+               case 1:
+                       div = 3;
+                       break;
+               case 2:
+                       parent = clks[core->parent >> 16];
+                       if (IS_ERR(parent))
+                               return ERR_CAST(parent);
+                       div = core->div;
+                       break;
+               case 3:
+               default:
+                       div = 2;
+                       break;
+               }
+               break;
+
        case CLK_TYPE_GEN3_RPC:
                return cpg_rpc_clk_register(core->name, base,
                                            __clk_get_name(parent), notifiers);
index c4ac80cac6a0a2c42135859db8a459f0749924bc..3d949c4a3244cef1bcdfb4215a3e57fdb111ea0b 100644 (file)
@@ -24,6 +24,7 @@ enum rcar_gen3_clk_types {
        CLK_TYPE_GEN3_OSC,      /* OSC EXTAL predivider and fixed divider */
        CLK_TYPE_GEN3_RCKSEL,   /* Select parent/divider using RCKCR.CKSEL */
        CLK_TYPE_GEN3_RPCSRC,
+       CLK_TYPE_GEN3_E3_RPCSRC,
        CLK_TYPE_GEN3_RPC,
        CLK_TYPE_GEN3_RPCD2,
 
@@ -54,6 +55,10 @@ enum rcar_gen3_clk_types {
 #define DEF_GEN3_Z(_name, _id, _type, _parent, _div, _offset)  \
        DEF_BASE(_name, _id, _type, _parent, .div = _div, .offset = _offset)
 
+#define DEF_FIXED_RPCSRC_E3(_name, _id, _parent0, _parent1)    \
+       DEF_BASE(_name, _id, CLK_TYPE_GEN3_E3_RPCSRC,   \
+                (_parent0) << 16 | (_parent1), .div = 8)
+
 struct rcar_gen3_cpg_pll_config {
        u8 extal_div;
        u8 pll1_mult;
index d4c02986c34e9347d1317b318453028206055320..3abafd78f7c8a5701a8093f7cb67d38d42d85ef9 100644 (file)
@@ -160,7 +160,7 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev)
        if (ret < 0)
                return ret;
 
-       priv->rsts = devm_reset_control_array_get(dev, true, false);
+       priv->rsts = devm_reset_control_array_get_shared(dev);
        if (IS_ERR(priv->rsts))
                return PTR_ERR(priv->rsts);
 
index 94db8837033771a76fa63e3cfed7604062723713..1c3215dc4877c8b6cf31d544f07cadaefca9f7b7 100644 (file)
@@ -119,7 +119,8 @@ static const u16 srstclr_for_v3u[] = {
 };
 
 /**
- * Clock Pulse Generator / Module Standby and Software Reset Private Data
+ * struct cpg_mssr_priv - Clock Pulse Generator / Module Standby
+ *                        and Software Reset Private Data
  *
  * @rcdev: Optional reset controller entity
  * @dev: CPG/MSSR device
index 47cd6c5de8372b592a5e431ef8ad7c20af98096c..effd05032e85c477c8cee496262b87333f669197 100644 (file)
@@ -11,67 +11,77 @@ config COMMON_CLK_ROCKCHIP
 if COMMON_CLK_ROCKCHIP
 config CLK_PX30
        bool "Rockchip PX30 clock controller support"
+       depends on (ARM64 || COMPILE_TEST)
        default y
        help
          Build the driver for PX30 Clock Driver.
 
 config CLK_RV110X
        bool "Rockchip RV110x clock controller support"
+       depends on (ARM || COMPILE_TEST)
        default y
        help
          Build the driver for RV110x Clock Driver.
 
 config CLK_RK3036
        bool "Rockchip RK3036 clock controller support"
+       depends on (ARM || COMPILE_TEST)
        default y
        help
          Build the driver for RK3036 Clock Driver.
 
 config CLK_RK312X
        bool "Rockchip RK312x clock controller support"
+       depends on (ARM || COMPILE_TEST)
        default y
        help
          Build the driver for RK312x Clock Driver.
 
 config CLK_RK3188
        bool "Rockchip RK3188 clock controller support"
+       depends on (ARM || COMPILE_TEST)
        default y
        help
          Build the driver for RK3188 Clock Driver.
 
 config CLK_RK322X
        bool "Rockchip RK322x clock controller support"
+       depends on (ARM || COMPILE_TEST)
        default y
        help
          Build the driver for RK322x Clock Driver.
 
 config CLK_RK3288
        bool "Rockchip RK3288 clock controller support"
-       depends on ARM
+       depends on (ARM || COMPILE_TEST)
        default y
        help
          Build the driver for RK3288 Clock Driver.
 
 config CLK_RK3308
        bool "Rockchip RK3308 clock controller support"
+       depends on (ARM64 || COMPILE_TEST)
        default y
        help
          Build the driver for RK3308 Clock Driver.
 
 config CLK_RK3328
        bool "Rockchip RK3328 clock controller support"
+       depends on (ARM64 || COMPILE_TEST)
        default y
        help
          Build the driver for RK3328 Clock Driver.
 
 config CLK_RK3368
        bool "Rockchip RK3368 clock controller support"
+       depends on (ARM64 || COMPILE_TEST)
        default y
        help
          Build the driver for RK3368 Clock Driver.
 
 config CLK_RK3399
        tristate "Rockchip RK3399 clock controller support"
+       depends on (ARM64 || COMPILE_TEST)
        default y
        help
          Build the driver for RK3399 Clock Driver.
index 730020fcc7fed5ea65d61a1ff7fe27e202498d06..0b76ad34de00082a0a280b9d7e6ef51132aa29cb 100644 (file)
@@ -255,19 +255,19 @@ static struct rockchip_clk_branch common_spdif_fracmux __initdata =
                        RK2928_CLKSEL_CON(5), 8, 2, MFLAGS);
 
 static struct rockchip_clk_branch common_uart0_fracmux __initdata =
-       MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
+       MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(13), 8, 2, MFLAGS);
 
 static struct rockchip_clk_branch common_uart1_fracmux __initdata =
-       MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
+       MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(14), 8, 2, MFLAGS);
 
 static struct rockchip_clk_branch common_uart2_fracmux __initdata =
-       MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
+       MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(15), 8, 2, MFLAGS);
 
 static struct rockchip_clk_branch common_uart3_fracmux __initdata =
-       MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
+       MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(16), 8, 2, MFLAGS);
 
 static struct rockchip_clk_branch common_clk_branches[] __initdata = {
@@ -408,28 +408,28 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
        COMPOSITE_NOMUX(0, "uart0_pre", "uart_src", 0,
                        RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
                        RK2928_CLKGATE_CON(1), 8, GFLAGS),
-       COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_pre", 0,
+       COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_pre", CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(17), 0,
                        RK2928_CLKGATE_CON(1), 9, GFLAGS,
                        &common_uart0_fracmux),
        COMPOSITE_NOMUX(0, "uart1_pre", "uart_src", 0,
                        RK2928_CLKSEL_CON(14), 0, 7, DFLAGS,
                        RK2928_CLKGATE_CON(1), 10, GFLAGS),
-       COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_pre", 0,
+       COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_pre", CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(18), 0,
                        RK2928_CLKGATE_CON(1), 11, GFLAGS,
                        &common_uart1_fracmux),
        COMPOSITE_NOMUX(0, "uart2_pre", "uart_src", 0,
                        RK2928_CLKSEL_CON(15), 0, 7, DFLAGS,
                        RK2928_CLKGATE_CON(1), 12, GFLAGS),
-       COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_pre", 0,
+       COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_pre", CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(19), 0,
                        RK2928_CLKGATE_CON(1), 13, GFLAGS,
                        &common_uart2_fracmux),
        COMPOSITE_NOMUX(0, "uart3_pre", "uart_src", 0,
                        RK2928_CLKSEL_CON(16), 0, 7, DFLAGS,
                        RK2928_CLKGATE_CON(1), 14, GFLAGS),
-       COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_pre", 0,
+       COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_pre", CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(20), 0,
                        RK2928_CLKGATE_CON(1), 15, GFLAGS,
                        &common_uart3_fracmux),
@@ -449,7 +449,6 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 
        /* hclk_cpu gates */
        GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(5), 6, GFLAGS),
-       GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
        GATE(HCLK_SPDIF, "hclk_spdif", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 1, GFLAGS),
        GATE(0, "hclk_cpubus", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 8, GFLAGS),
        /* hclk_ahb2apb is part of a clk branch */
@@ -543,15 +542,15 @@ static struct clk_div_table div_aclk_cpu_t[] = {
 };
 
 static struct rockchip_clk_branch rk3066a_i2s0_fracmux __initdata =
-       MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
+       MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(2), 8, 2, MFLAGS);
 
 static struct rockchip_clk_branch rk3066a_i2s1_fracmux __initdata =
-       MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
+       MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(3), 8, 2, MFLAGS);
 
 static struct rockchip_clk_branch rk3066a_i2s2_fracmux __initdata =
-       MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
+       MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(4), 8, 2, MFLAGS);
 
 static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
@@ -615,27 +614,28 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
        COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
                        RK2928_CLKSEL_CON(2), 0, 7, DFLAGS,
                        RK2928_CLKGATE_CON(0), 7, GFLAGS),
-       COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0,
+       COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(6), 0,
                        RK2928_CLKGATE_CON(0), 8, GFLAGS,
                        &rk3066a_i2s0_fracmux),
        COMPOSITE_NOMUX(0, "i2s1_pre", "i2s_src", 0,
                        RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
                        RK2928_CLKGATE_CON(0), 9, GFLAGS),
-       COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_pre", 0,
+       COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_pre", CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(7), 0,
                        RK2928_CLKGATE_CON(0), 10, GFLAGS,
                        &rk3066a_i2s1_fracmux),
        COMPOSITE_NOMUX(0, "i2s2_pre", "i2s_src", 0,
                        RK2928_CLKSEL_CON(4), 0, 7, DFLAGS,
                        RK2928_CLKGATE_CON(0), 11, GFLAGS),
-       COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_pre", 0,
+       COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_pre", CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(8), 0,
                        RK2928_CLKGATE_CON(0), 12, GFLAGS,
                        &rk3066a_i2s2_fracmux),
 
-       GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
-       GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
+       GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
+       GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
+       GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
        GATE(HCLK_CIF1, "hclk_cif1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 6, GFLAGS),
        GATE(HCLK_HDMI, "hclk_hdmi", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
 
@@ -728,6 +728,7 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
                        RK2928_CLKGATE_CON(0), 10, GFLAGS,
                        &rk3188_i2s0_fracmux),
 
+       GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
        GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
        GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS),
 
index b443169dd408dd233e8d368280be53d4cd695f8f..336481bc6cc726d182ef21543c158b1658138d37 100644 (file)
@@ -603,8 +603,7 @@ void rockchip_clk_protect_critical(const char *const clocks[],
        for (i = 0; i < nclocks; i++) {
                struct clk *clk = __clk_lookup(clocks[i]);
 
-               if (clk)
-                       clk_prepare_enable(clk);
+               clk_prepare_enable(clk);
        }
 }
 EXPORT_SYMBOL_GPL(rockchip_clk_protect_critical);
index 57d4b3f20417fd994ecf5173b90d6eceb9567673..9323fcfac6cc8f3629f3b990091b7c86d77d0881 100644 (file)
@@ -2,10 +2,73 @@
 # Recent Exynos platforms should just select COMMON_CLK_SAMSUNG:
 config COMMON_CLK_SAMSUNG
        bool "Samsung Exynos clock controller support" if COMPILE_TEST
-       # Clocks on ARM64 SoCs (e.g. Exynos5433, Exynos7) are chosen by
-       # EXYNOS_ARM64_COMMON_CLK to avoid building them on ARMv7:
+       select S3C64XX_COMMON_CLK if ARM && ARCH_S3C64XX
+       select S5PV210_COMMON_CLK if ARM && ARCH_S5PV210
+       select EXYNOS_3250_COMMON_CLK if ARM && SOC_EXYNOS3250
+       select EXYNOS_4_COMMON_CLK if ARM && ARCH_EXYNOS4
+       select EXYNOS_5250_COMMON_CLK if ARM && SOC_EXYNOS5250
+       select EXYNOS_5260_COMMON_CLK if ARM && SOC_EXYNOS5260
+       select EXYNOS_5410_COMMON_CLK if ARM && SOC_EXYNOS5410
+       select EXYNOS_5420_COMMON_CLK if ARM && SOC_EXYNOS5420
        select EXYNOS_ARM64_COMMON_CLK if ARM64 && ARCH_EXYNOS
 
+config S3C64XX_COMMON_CLK
+       bool "Samsung S3C64xx clock controller support" if COMPILE_TEST
+       depends on COMMON_CLK_SAMSUNG
+       help
+         Support for the clock controller present on the Samsung S3C64xx SoCs.
+         Choose Y here only if you build for this SoC.
+
+config S5PV210_COMMON_CLK
+       bool "Samsung S5Pv210 clock controller support" if COMPILE_TEST
+       depends on COMMON_CLK_SAMSUNG
+       help
+         Support for the clock controller present on the Samsung S5Pv210 SoCs.
+         Choose Y here only if you build for this SoC.
+
+config EXYNOS_3250_COMMON_CLK
+       bool "Samsung Exynos3250 clock controller support" if COMPILE_TEST
+       depends on COMMON_CLK_SAMSUNG
+       help
+         Support for the clock controller present on the Samsung
+         Exynos3250 SoCs. Choose Y here only if you build for this SoC.
+
+config EXYNOS_4_COMMON_CLK
+       bool "Samsung Exynos4 clock controller support" if COMPILE_TEST
+       depends on COMMON_CLK_SAMSUNG
+       help
+         Support for the clock controller present on the Samsung
+         Exynos4212 and Exynos4412 SoCs. Choose Y here only if you build for
+         this SoC.
+
+config EXYNOS_5250_COMMON_CLK
+       bool "Samsung Exynos5250 clock controller support" if COMPILE_TEST
+       depends on COMMON_CLK_SAMSUNG
+       help
+         Support for the clock controller present on the Samsung
+         Exynos5250 SoCs. Choose Y here only if you build for this SoC.
+
+config EXYNOS_5260_COMMON_CLK
+       bool "Samsung Exynos5260 clock controller support" if COMPILE_TEST
+       depends on COMMON_CLK_SAMSUNG
+       help
+         Support for the clock controller present on the Samsung
+         Exynos5260 SoCs. Choose Y here only if you build for this SoC.
+
+config EXYNOS_5410_COMMON_CLK
+       bool "Samsung Exynos5410 clock controller support" if COMPILE_TEST
+       depends on COMMON_CLK_SAMSUNG
+       help
+         Support for the clock controller present on the Samsung
+         Exynos5410 SoCs. Choose Y here only if you build for this SoC.
+
+config EXYNOS_5420_COMMON_CLK
+       bool "Samsung Exynos5420 clock controller support" if COMPILE_TEST
+       depends on COMMON_CLK_SAMSUNG
+       help
+         Support for the clock controller present on the Samsung
+         Exynos5420 SoCs. Choose Y here only if you build for this SoC.
+
 config EXYNOS_ARM64_COMMON_CLK
        bool "Samsung Exynos ARMv8-family clock controller support" if COMPILE_TEST
        depends on COMMON_CLK_SAMSUNG
index 1a4e6b787978383ba44252a9e70cb587dea659fa..bb1433f11c8803d3ff42c2acf53a94c6307d9744 100644 (file)
@@ -4,15 +4,15 @@
 #
 
 obj-$(CONFIG_COMMON_CLK)       += clk.o clk-pll.o clk-cpu.o
-obj-$(CONFIG_SOC_EXYNOS3250)   += clk-exynos3250.o
-obj-$(CONFIG_ARCH_EXYNOS4)     += clk-exynos4.o
-obj-$(CONFIG_ARCH_EXYNOS4)     += clk-exynos4412-isp.o
-obj-$(CONFIG_SOC_EXYNOS5250)   += clk-exynos5250.o
-obj-$(CONFIG_SOC_EXYNOS5250)   += clk-exynos5-subcmu.o
-obj-$(CONFIG_SOC_EXYNOS5260)   += clk-exynos5260.o
-obj-$(CONFIG_SOC_EXYNOS5410)   += clk-exynos5410.o
-obj-$(CONFIG_SOC_EXYNOS5420)   += clk-exynos5420.o
-obj-$(CONFIG_SOC_EXYNOS5420)   += clk-exynos5-subcmu.o
+obj-$(CONFIG_EXYNOS_3250_COMMON_CLK)   += clk-exynos3250.o
+obj-$(CONFIG_EXYNOS_4_COMMON_CLK)      += clk-exynos4.o
+obj-$(CONFIG_EXYNOS_4_COMMON_CLK)      += clk-exynos4412-isp.o
+obj-$(CONFIG_EXYNOS_5250_COMMON_CLK)   += clk-exynos5250.o
+obj-$(CONFIG_EXYNOS_5250_COMMON_CLK)   += clk-exynos5-subcmu.o
+obj-$(CONFIG_EXYNOS_5260_COMMON_CLK)   += clk-exynos5260.o
+obj-$(CONFIG_EXYNOS_5410_COMMON_CLK)   += clk-exynos5410.o
+obj-$(CONFIG_EXYNOS_5420_COMMON_CLK)   += clk-exynos5420.o
+obj-$(CONFIG_EXYNOS_5420_COMMON_CLK)   += clk-exynos5-subcmu.o
 obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK)  += clk-exynos5433.o
 obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o
 obj-$(CONFIG_ARCH_EXYNOS)      += clk-exynos-clkout.o
@@ -21,5 +21,5 @@ obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
 obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
 obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
 obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o
-obj-$(CONFIG_ARCH_S3C64XX)     += clk-s3c64xx.o
-obj-$(CONFIG_ARCH_S5PV210)     += clk-s5pv210.o clk-s5pv210-audss.o
+obj-$(CONFIG_S3C64XX_COMMON_CLK)       += clk-s3c64xx.o
+obj-$(CONFIG_S5PV210_COMMON_CLK)       += clk-s5pv210.o clk-s5pv210-audss.o
index ac70ad785d8edde1ac0bb381815a1ed3ed7aaa19..5873a9354b50739f9c019b2d97a8b54015949047 100644 (file)
@@ -8,14 +8,17 @@
 
 #include <linux/errno.h>
 #include <linux/hrtimer.h>
+#include <linux/iopoll.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/timekeeping.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include "clk.h"
 #include "clk-pll.h"
 
-#define PLL_TIMEOUT_MS         10
+#define PLL_TIMEOUT_US         20000U
+#define PLL_TIMEOUT_LOOPS      1000000U
 
 struct samsung_clk_pll {
        struct clk_hw           hw;
@@ -63,6 +66,53 @@ static long samsung_pll_round_rate(struct clk_hw *hw,
        return rate_table[i - 1].rate;
 }
 
+static bool pll_early_timeout = true;
+
+static int __init samsung_pll_disable_early_timeout(void)
+{
+       pll_early_timeout = false;
+       return 0;
+}
+arch_initcall(samsung_pll_disable_early_timeout);
+
+/* Wait until the PLL is locked */
+static int samsung_pll_lock_wait(struct samsung_clk_pll *pll,
+                                unsigned int reg_mask)
+{
+       int i, ret;
+       u32 val;
+
+       /*
+        * This function might be called when the timekeeping API can't be used
+        * to detect timeouts. One situation is when the clocksource is not yet
+        * initialized, another when the timekeeping is suspended. udelay() also
+        * cannot be used when the clocksource is not running on arm64, since
+        * the current timer is used as cycle counter. So a simple busy loop
+        * is used here in that special cases. The limit of iterations has been
+        * derived from experimental measurements of various PLLs on multiple
+        * Exynos SoC variants. Single register read time was usually in range
+        * 0.4...1.5 us, never less than 0.4 us.
+        */
+       if (pll_early_timeout || timekeeping_suspended) {
+               i = PLL_TIMEOUT_LOOPS;
+               while (i-- > 0) {
+                       if (readl_relaxed(pll->con_reg) & reg_mask)
+                               return 0;
+
+                       cpu_relax();
+               }
+               ret = -ETIMEDOUT;
+       } else {
+               ret = readl_relaxed_poll_timeout_atomic(pll->con_reg, val,
+                                       val & reg_mask, 0, PLL_TIMEOUT_US);
+       }
+
+       if (ret < 0)
+               pr_err("Could not lock PLL %s\n", clk_hw_get_name(&pll->hw));
+
+       return ret;
+}
+
 static int samsung_pll3xxx_enable(struct clk_hw *hw)
 {
        struct samsung_clk_pll *pll = to_clk_pll(hw);
@@ -72,13 +122,7 @@ static int samsung_pll3xxx_enable(struct clk_hw *hw)
        tmp |= BIT(pll->enable_offs);
        writel_relaxed(tmp, pll->con_reg);
 
-       /* wait lock time */
-       do {
-               cpu_relax();
-               tmp = readl_relaxed(pll->con_reg);
-       } while (!(tmp & BIT(pll->lock_offs)));
-
-       return 0;
+       return samsung_pll_lock_wait(pll, BIT(pll->lock_offs));
 }
 
 static void samsung_pll3xxx_disable(struct clk_hw *hw)
@@ -240,13 +284,10 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
                        (rate->sdiv << PLL35XX_SDIV_SHIFT);
        writel_relaxed(tmp, pll->con_reg);
 
-       /* Wait until the PLL is locked if it is enabled. */
-       if (tmp & BIT(pll->enable_offs)) {
-               do {
-                       cpu_relax();
-                       tmp = readl_relaxed(pll->con_reg);
-               } while (!(tmp & BIT(pll->lock_offs)));
-       }
+       /* Wait for PLL lock if the PLL is enabled */
+       if (tmp & BIT(pll->enable_offs))
+               return samsung_pll_lock_wait(pll, BIT(pll->lock_offs));
+
        return 0;
 }
 
@@ -318,7 +359,7 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
                                        unsigned long parent_rate)
 {
        struct samsung_clk_pll *pll = to_clk_pll(hw);
-       u32 tmp, pll_con0, pll_con1;
+       u32 pll_con0, pll_con1;
        const struct samsung_pll_rate_table *rate;
 
        rate = samsung_get_pll_settings(pll, drate);
@@ -356,13 +397,8 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
        pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT;
        writel_relaxed(pll_con1, pll->con_reg + 4);
 
-       /* wait_lock_time */
-       if (pll_con0 & BIT(pll->enable_offs)) {
-               do {
-                       cpu_relax();
-                       tmp = readl_relaxed(pll->con_reg);
-               } while (!(tmp & BIT(pll->lock_offs)));
-       }
+       if (pll_con0 & BIT(pll->enable_offs))
+               return samsung_pll_lock_wait(pll, BIT(pll->lock_offs));
 
        return 0;
 }
@@ -437,7 +473,6 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
        struct samsung_clk_pll *pll = to_clk_pll(hw);
        const struct samsung_pll_rate_table *rate;
        u32 con0, con1;
-       ktime_t start;
 
        /* Get required rate settings from table */
        rate = samsung_get_pll_settings(pll, drate);
@@ -488,21 +523,8 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
        writel_relaxed(con1, pll->con_reg + 0x4);
        writel_relaxed(con0, pll->con_reg);
 
-       /* Wait for locking. */
-       start = ktime_get();
-       while (!(readl_relaxed(pll->con_reg) & PLL45XX_LOCKED)) {
-               ktime_t delta = ktime_sub(ktime_get(), start);
-
-               if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
-                       pr_err("%s: could not lock PLL %s\n",
-                                       __func__, clk_hw_get_name(hw));
-                       return -EFAULT;
-               }
-
-               cpu_relax();
-       }
-
-       return 0;
+       /* Wait for PLL lock */
+       return samsung_pll_lock_wait(pll, PLL45XX_LOCKED);
 }
 
 static const struct clk_ops samsung_pll45xx_clk_ops = {
@@ -588,7 +610,6 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
        struct samsung_clk_pll *pll = to_clk_pll(hw);
        const struct samsung_pll_rate_table *rate;
        u32 con0, con1, lock;
-       ktime_t start;
 
        /* Get required rate settings from table */
        rate = samsung_get_pll_settings(pll, drate);
@@ -647,21 +668,8 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
        writel_relaxed(con0, pll->con_reg);
        writel_relaxed(con1, pll->con_reg + 0x4);
 
-       /* Wait for locking. */
-       start = ktime_get();
-       while (!(readl_relaxed(pll->con_reg) & PLL46XX_LOCKED)) {
-               ktime_t delta = ktime_sub(ktime_get(), start);
-
-               if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
-                       pr_err("%s: could not lock PLL %s\n",
-                                       __func__, clk_hw_get_name(hw));
-                       return -EFAULT;
-               }
-
-               cpu_relax();
-       }
-
-       return 0;
+       /* Wait for PLL lock */
+       return samsung_pll_lock_wait(pll, PLL46XX_LOCKED);
 }
 
 static const struct clk_ops samsung_pll46xx_clk_ops = {
@@ -1035,14 +1043,9 @@ static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate,
                        (rate->sdiv << PLL2550XX_S_SHIFT);
        writel_relaxed(tmp, pll->con_reg);
 
-       /* wait_lock_time */
-       do {
-               cpu_relax();
-               tmp = readl_relaxed(pll->con_reg);
-       } while (!(tmp & (PLL2550XX_LOCK_STAT_MASK
-                       << PLL2550XX_LOCK_STAT_SHIFT)));
-
-       return 0;
+       /* Wait for PLL lock */
+       return samsung_pll_lock_wait(pll,
+                       PLL2550XX_LOCK_STAT_MASK << PLL2550XX_LOCK_STAT_SHIFT);
 }
 
 static const struct clk_ops samsung_pll2550xx_clk_ops = {
@@ -1132,13 +1135,9 @@ static int samsung_pll2650x_set_rate(struct clk_hw *hw, unsigned long drate,
        con1 |= ((rate->kdiv & PLL2650X_K_MASK) << PLL2650X_K_SHIFT);
        writel_relaxed(con1, pll->con_reg + 4);
 
-       do {
-               cpu_relax();
-               con0 = readl_relaxed(pll->con_reg);
-       } while (!(con0 & (PLL2650X_LOCK_STAT_MASK
-                       << PLL2650X_LOCK_STAT_SHIFT)));
-
-       return 0;
+       /* Wait for PLL lock */
+       return samsung_pll_lock_wait(pll,
+                       PLL2650X_LOCK_STAT_MASK << PLL2650X_LOCK_STAT_SHIFT);
 }
 
 static const struct clk_ops samsung_pll2650x_clk_ops = {
@@ -1196,7 +1195,7 @@ static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate,
                                        unsigned long parent_rate)
 {
        struct samsung_clk_pll *pll = to_clk_pll(hw);
-       u32 tmp, pll_con0, pll_con2;
+       u32 pll_con0, pll_con2;
        const struct samsung_pll_rate_table *rate;
 
        rate = samsung_get_pll_settings(pll, drate);
@@ -1229,11 +1228,7 @@ static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate,
        writel_relaxed(pll_con0, pll->con_reg);
        writel_relaxed(pll_con2, pll->con_reg + 8);
 
-       do {
-               tmp = readl_relaxed(pll->con_reg);
-       } while (!(tmp & (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT)));
-
-       return 0;
+       return samsung_pll_lock_wait(pll, 0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT);
 }
 
 static const struct clk_ops samsung_pll2650xx_clk_ops = {
index f3b4eb9cb0f5547ff1f81741e6fc6eab8c838823..1c14eb20c06684291f0ce6317307e22db22a7df7 100644 (file)
@@ -8,12 +8,12 @@ menuconfig CLK_SIFIVE
 
 if CLK_SIFIVE
 
-config CLK_SIFIVE_FU540_PRCI
-       bool "PRCI driver for SiFive FU540 SoCs"
+config CLK_SIFIVE_PRCI
+       bool "PRCI driver for SiFive SoCs"
        select CLK_ANALOGBITS_WRPLL_CLN28HPC
        help
          Supports the Power Reset Clock interface (PRCI) IP block found in
-         FU540 SoCs.  If this kernel is meant to run on a SiFive FU540 SoC,
-         enable this driver.
+         FU540/FU740 SoCs. If this kernel is meant to run on a SiFive FU540/
+         FU740 SoCs, enable this driver.
 
 endif
index 0797f14fef6b6bb3728b5a2fe3cf2e59fcb4ae54..7b06fc04e6b3e763fc287a842e3e17a447da4ab4 100644 (file)
@@ -1,2 +1,2 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_CLK_SIFIVE_FU540_PRCI)    += fu540-prci.o
+obj-$(CONFIG_CLK_SIFIVE_PRCI)  += sifive-prci.o fu540-prci.o fu740-prci.o
index a8901f90a61ac08f6dba531cbc8f3760deff39f2..29bab915003cb7ea3bf143f8273a72a745b8fa04 100644 (file)
@@ -1,17 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2018-2019 SiFive, Inc.
- * Wesley Terpstra
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * Copyright (C) 2018-2019 Wesley Terpstra
+ * Copyright (C) 2018-2019 Paul Walmsley
+ * Copyright (C) 2020 Zong Li
  *
  * The FU540 PRCI implements clock and reset control for the SiFive
  * FU540-C000 chip.  This driver assumes that it has sole control
  * - SiFive FU540-C000 manual v1p0, Chapter 7 "Clocking and Reset"
  */
 
-#include <dt-bindings/clock/sifive-fu540-prci.h>
-#include <linux/clkdev.h>
-#include <linux/clk-provider.h>
-#include <linux/clk/analogbits-wrpll-cln28hpc.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
 #include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_clk.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-/*
- * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
- *     hfclk and rtcclk
- */
-#define EXPECTED_CLK_PARENT_COUNT              2
-
-/*
- * Register offsets and bitmasks
- */
-
-/* COREPLLCFG0 */
-#define PRCI_COREPLLCFG0_OFFSET                        0x4
-# define PRCI_COREPLLCFG0_DIVR_SHIFT           0
-# define PRCI_COREPLLCFG0_DIVR_MASK            (0x3f << PRCI_COREPLLCFG0_DIVR_SHIFT)
-# define PRCI_COREPLLCFG0_DIVF_SHIFT           6
-# define PRCI_COREPLLCFG0_DIVF_MASK            (0x1ff << PRCI_COREPLLCFG0_DIVF_SHIFT)
-# define PRCI_COREPLLCFG0_DIVQ_SHIFT           15
-# define PRCI_COREPLLCFG0_DIVQ_MASK            (0x7 << PRCI_COREPLLCFG0_DIVQ_SHIFT)
-# define PRCI_COREPLLCFG0_RANGE_SHIFT          18
-# define PRCI_COREPLLCFG0_RANGE_MASK           (0x7 << PRCI_COREPLLCFG0_RANGE_SHIFT)
-# define PRCI_COREPLLCFG0_BYPASS_SHIFT         24
-# define PRCI_COREPLLCFG0_BYPASS_MASK          (0x1 << PRCI_COREPLLCFG0_BYPASS_SHIFT)
-# define PRCI_COREPLLCFG0_FSE_SHIFT            25
-# define PRCI_COREPLLCFG0_FSE_MASK             (0x1 << PRCI_COREPLLCFG0_FSE_SHIFT)
-# define PRCI_COREPLLCFG0_LOCK_SHIFT           31
-# define PRCI_COREPLLCFG0_LOCK_MASK            (0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)
 
-/* DDRPLLCFG0 */
-#define PRCI_DDRPLLCFG0_OFFSET                 0xc
-# define PRCI_DDRPLLCFG0_DIVR_SHIFT            0
-# define PRCI_DDRPLLCFG0_DIVR_MASK             (0x3f << PRCI_DDRPLLCFG0_DIVR_SHIFT)
-# define PRCI_DDRPLLCFG0_DIVF_SHIFT            6
-# define PRCI_DDRPLLCFG0_DIVF_MASK             (0x1ff << PRCI_DDRPLLCFG0_DIVF_SHIFT)
-# define PRCI_DDRPLLCFG0_DIVQ_SHIFT            15
-# define PRCI_DDRPLLCFG0_DIVQ_MASK             (0x7 << PRCI_DDRPLLCFG0_DIVQ_SHIFT)
-# define PRCI_DDRPLLCFG0_RANGE_SHIFT           18
-# define PRCI_DDRPLLCFG0_RANGE_MASK            (0x7 << PRCI_DDRPLLCFG0_RANGE_SHIFT)
-# define PRCI_DDRPLLCFG0_BYPASS_SHIFT          24
-# define PRCI_DDRPLLCFG0_BYPASS_MASK           (0x1 << PRCI_DDRPLLCFG0_BYPASS_SHIFT)
-# define PRCI_DDRPLLCFG0_FSE_SHIFT             25
-# define PRCI_DDRPLLCFG0_FSE_MASK              (0x1 << PRCI_DDRPLLCFG0_FSE_SHIFT)
-# define PRCI_DDRPLLCFG0_LOCK_SHIFT            31
-# define PRCI_DDRPLLCFG0_LOCK_MASK             (0x1 << PRCI_DDRPLLCFG0_LOCK_SHIFT)
-
-/* DDRPLLCFG1 */
-#define PRCI_DDRPLLCFG1_OFFSET                 0x10
-# define PRCI_DDRPLLCFG1_CKE_SHIFT             24
-# define PRCI_DDRPLLCFG1_CKE_MASK              (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
-
-/* GEMGXLPLLCFG0 */
-#define PRCI_GEMGXLPLLCFG0_OFFSET              0x1c
-# define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT         0
-# define PRCI_GEMGXLPLLCFG0_DIVR_MASK          (0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT)
-# define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT         6
-# define PRCI_GEMGXLPLLCFG0_DIVF_MASK          (0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT)
-# define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT         15
-# define PRCI_GEMGXLPLLCFG0_DIVQ_MASK          (0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT)
-# define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT                18
-# define PRCI_GEMGXLPLLCFG0_RANGE_MASK         (0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT)
-# define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT       24
-# define PRCI_GEMGXLPLLCFG0_BYPASS_MASK                (0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT)
-# define PRCI_GEMGXLPLLCFG0_FSE_SHIFT          25
-# define PRCI_GEMGXLPLLCFG0_FSE_MASK           (0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT)
-# define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT         31
-# define PRCI_GEMGXLPLLCFG0_LOCK_MASK          (0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT)
-
-/* GEMGXLPLLCFG1 */
-#define PRCI_GEMGXLPLLCFG1_OFFSET              0x20
-# define PRCI_GEMGXLPLLCFG1_CKE_SHIFT          24
-# define PRCI_GEMGXLPLLCFG1_CKE_MASK           (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
-
-/* CORECLKSEL */
-#define PRCI_CORECLKSEL_OFFSET                 0x24
-# define PRCI_CORECLKSEL_CORECLKSEL_SHIFT      0
-# define PRCI_CORECLKSEL_CORECLKSEL_MASK       (0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT)
-
-/* DEVICESRESETREG */
-#define PRCI_DEVICESRESETREG_OFFSET                    0x28
-# define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT     0
-# define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK      (0x1 << PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT)
-# define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT      1
-# define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK       (0x1 << PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT)
-# define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT      2
-# define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK       (0x1 << PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT)
-# define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT      3
-# define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK       (0x1 << PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT)
-# define PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT       5
-# define PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK                (0x1 << PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT)
+#include <dt-bindings/clock/sifive-fu540-prci.h>
 
-/* CLKMUXSTATUSREG */
-#define PRCI_CLKMUXSTATUSREG_OFFSET                    0x2c
-# define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT    1
-# define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK     (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
+#include "fu540-prci.h"
+#include "sifive-prci.h"
 
-/*
- * Private structures
- */
+/* PRCI integration data for each WRPLL instance */
 
-/**
- * struct __prci_data - per-device-instance data
- * @va: base virtual address of the PRCI IP block
- * @hw_clks: encapsulates struct clk_hw records
- *
- * PRCI per-device instance data
- */
-struct __prci_data {
-       void __iomem *va;
-       struct clk_hw_onecell_data hw_clks;
+static struct __prci_wrpll_data __prci_corepll_data = {
+       .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
+       .cfg1_offs = PRCI_COREPLLCFG1_OFFSET,
+       .enable_bypass = sifive_prci_coreclksel_use_hfclk,
+       .disable_bypass = sifive_prci_coreclksel_use_corepll,
 };
 
-/**
- * struct __prci_wrpll_data - WRPLL configuration and integration data
- * @c: WRPLL current configuration record
- * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
- * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
- * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
- *
- * @enable_bypass and @disable_bypass are used for WRPLL instances
- * that contain a separate external glitchless clock mux downstream
- * from the PLL.  The WRPLL internal bypass mux is not glitchless.
- */
-struct __prci_wrpll_data {
-       struct wrpll_cfg c;
-       void (*enable_bypass)(struct __prci_data *pd);
-       void (*disable_bypass)(struct __prci_data *pd);
-       u8 cfg0_offs;
+static struct __prci_wrpll_data __prci_ddrpll_data = {
+       .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
+       .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
 };
 
-/**
- * struct __prci_clock - describes a clock device managed by PRCI
- * @name: user-readable clock name string - should match the manual
- * @parent_name: parent name for this clock
- * @ops: struct clk_ops for the Linux clock framework to use for control
- * @hw: Linux-private clock data
- * @pwd: WRPLL-specific data, associated with this clock (if not NULL)
- * @pd: PRCI-specific data associated with this clock (if not NULL)
- *
- * PRCI clock data.  Used by the PRCI driver to register PRCI-provided
- * clocks to the Linux clock infrastructure.
- */
-struct __prci_clock {
-       const char *name;
-       const char *parent_name;
-       const struct clk_ops *ops;
-       struct clk_hw hw;
-       struct __prci_wrpll_data *pwd;
-       struct __prci_data *pd;
+static struct __prci_wrpll_data __prci_gemgxlpll_data = {
+       .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
+       .cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET,
 };
 
-#define clk_hw_to_prci_clock(pwd) container_of(pwd, struct __prci_clock, hw)
-
-/*
- * Private functions
- */
-
-/**
- * __prci_readl() - read from a PRCI register
- * @pd: PRCI context
- * @offs: register offset to read from (in bytes, from PRCI base address)
- *
- * Read the register located at offset @offs from the base virtual
- * address of the PRCI register target described by @pd, and return
- * the value to the caller.
- *
- * Context: Any context.
- *
- * Return: the contents of the register described by @pd and @offs.
- */
-static u32 __prci_readl(struct __prci_data *pd, u32 offs)
-{
-       return readl_relaxed(pd->va + offs);
-}
-
-static void __prci_writel(u32 v, u32 offs, struct __prci_data *pd)
-{
-       writel_relaxed(v, pd->va + offs);
-}
-
-/* WRPLL-related private functions */
-
-/**
- * __prci_wrpll_unpack() - unpack WRPLL configuration registers into parameters
- * @c: ptr to a struct wrpll_cfg record to write config into
- * @r: value read from the PRCI PLL configuration register
- *
- * Given a value @r read from an FU540 PRCI PLL configuration register,
- * split it into fields and populate it into the WRPLL configuration record
- * pointed to by @c.
- *
- * The COREPLLCFG0 macros are used below, but the other *PLLCFG0 macros
- * have the same register layout.
- *
- * Context: Any context.
- */
-static void __prci_wrpll_unpack(struct wrpll_cfg *c, u32 r)
-{
-       u32 v;
-
-       v = r & PRCI_COREPLLCFG0_DIVR_MASK;
-       v >>= PRCI_COREPLLCFG0_DIVR_SHIFT;
-       c->divr = v;
-
-       v = r & PRCI_COREPLLCFG0_DIVF_MASK;
-       v >>= PRCI_COREPLLCFG0_DIVF_SHIFT;
-       c->divf = v;
-
-       v = r & PRCI_COREPLLCFG0_DIVQ_MASK;
-       v >>= PRCI_COREPLLCFG0_DIVQ_SHIFT;
-       c->divq = v;
-
-       v = r & PRCI_COREPLLCFG0_RANGE_MASK;
-       v >>= PRCI_COREPLLCFG0_RANGE_SHIFT;
-       c->range = v;
-
-       c->flags &= (WRPLL_FLAGS_INT_FEEDBACK_MASK |
-                    WRPLL_FLAGS_EXT_FEEDBACK_MASK);
-
-       /* external feedback mode not supported */
-       c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
-}
-
-/**
- * __prci_wrpll_pack() - pack PLL configuration parameters into a register value
- * @c: pointer to a struct wrpll_cfg record containing the PLL's cfg
- *
- * Using a set of WRPLL configuration values pointed to by @c,
- * assemble a PRCI PLL configuration register value, and return it to
- * the caller.
- *
- * Context: Any context.  Caller must ensure that the contents of the
- *          record pointed to by @c do not change during the execution
- *          of this function.
- *
- * Returns: a value suitable for writing into a PRCI PLL configuration
- *          register
- */
-static u32 __prci_wrpll_pack(const struct wrpll_cfg *c)
-{
-       u32 r = 0;
-
-       r |= c->divr << PRCI_COREPLLCFG0_DIVR_SHIFT;
-       r |= c->divf << PRCI_COREPLLCFG0_DIVF_SHIFT;
-       r |= c->divq << PRCI_COREPLLCFG0_DIVQ_SHIFT;
-       r |= c->range << PRCI_COREPLLCFG0_RANGE_SHIFT;
-
-       /* external feedback mode not supported */
-       r |= PRCI_COREPLLCFG0_FSE_MASK;
-
-       return r;
-}
-
-/**
- * __prci_wrpll_read_cfg() - read the WRPLL configuration from the PRCI
- * @pd: PRCI context
- * @pwd: PRCI WRPLL metadata
- *
- * Read the current configuration of the PLL identified by @pwd from
- * the PRCI identified by @pd, and store it into the local configuration
- * cache in @pwd.
- *
- * Context: Any context.  Caller must prevent the records pointed to by
- *          @pd and @pwd from changing during execution.
- */
-static void __prci_wrpll_read_cfg(struct __prci_data *pd,
-                                 struct __prci_wrpll_data *pwd)
-{
-       __prci_wrpll_unpack(&pwd->c, __prci_readl(pd, pwd->cfg0_offs));
-}
-
-/**
- * __prci_wrpll_write_cfg() - write WRPLL configuration into the PRCI
- * @pd: PRCI context
- * @pwd: PRCI WRPLL metadata
- * @c: WRPLL configuration record to write
- *
- * Write the WRPLL configuration described by @c into the WRPLL
- * configuration register identified by @pwd in the PRCI instance
- * described by @c.  Make a cached copy of the WRPLL's current
- * configuration so it can be used by other code.
- *
- * Context: Any context.  Caller must prevent the records pointed to by
- *          @pd and @pwd from changing during execution.
- */
-static void __prci_wrpll_write_cfg(struct __prci_data *pd,
-                                  struct __prci_wrpll_data *pwd,
-                                  struct wrpll_cfg *c)
-{
-       __prci_writel(__prci_wrpll_pack(c), pwd->cfg0_offs, pd);
-
-       memcpy(&pwd->c, c, sizeof(*c));
-}
-
-/* Core clock mux control */
-
-/**
- * __prci_coreclksel_use_hfclk() - switch the CORECLK mux to output HFCLK
- * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
- *
- * Switch the CORECLK mux to the HFCLK input source; return once complete.
- *
- * Context: Any context.  Caller must prevent concurrent changes to the
- *          PRCI_CORECLKSEL_OFFSET register.
- */
-static void __prci_coreclksel_use_hfclk(struct __prci_data *pd)
-{
-       u32 r;
-
-       r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
-       r |= PRCI_CORECLKSEL_CORECLKSEL_MASK;
-       __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
-
-       r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
-}
-
-/**
- * __prci_coreclksel_use_corepll() - switch the CORECLK mux to output COREPLL
- * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
- *
- * Switch the CORECLK mux to the PLL output clock; return once complete.
- *
- * Context: Any context.  Caller must prevent concurrent changes to the
- *          PRCI_CORECLKSEL_OFFSET register.
- */
-static void __prci_coreclksel_use_corepll(struct __prci_data *pd)
-{
-       u32 r;
-
-       r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
-       r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK;
-       __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
-
-       r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
-}
-
-/*
- * Linux clock framework integration
- *
- * See the Linux clock framework documentation for more information on
- * these functions.
- */
-
-static unsigned long sifive_fu540_prci_wrpll_recalc_rate(struct clk_hw *hw,
-                                                        unsigned long parent_rate)
-{
-       struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
-       struct __prci_wrpll_data *pwd = pc->pwd;
-
-       return wrpll_calc_output_rate(&pwd->c, parent_rate);
-}
-
-static long sifive_fu540_prci_wrpll_round_rate(struct clk_hw *hw,
-                                              unsigned long rate,
-                                              unsigned long *parent_rate)
-{
-       struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
-       struct __prci_wrpll_data *pwd = pc->pwd;
-       struct wrpll_cfg c;
-
-       memcpy(&c, &pwd->c, sizeof(c));
-
-       wrpll_configure_for_rate(&c, rate, *parent_rate);
-
-       return wrpll_calc_output_rate(&c, *parent_rate);
-}
-
-static int sifive_fu540_prci_wrpll_set_rate(struct clk_hw *hw,
-                                           unsigned long rate,
-                                           unsigned long parent_rate)
-{
-       struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
-       struct __prci_wrpll_data *pwd = pc->pwd;
-       struct __prci_data *pd = pc->pd;
-       int r;
-
-       r = wrpll_configure_for_rate(&pwd->c, rate, parent_rate);
-       if (r)
-               return r;
-
-       if (pwd->enable_bypass)
-               pwd->enable_bypass(pd);
-
-       __prci_wrpll_write_cfg(pd, pwd, &pwd->c);
-
-       udelay(wrpll_calc_max_lock_us(&pwd->c));
-
-       if (pwd->disable_bypass)
-               pwd->disable_bypass(pd);
-
-       return 0;
-}
+/* Linux clock framework integration */
 
 static const struct clk_ops sifive_fu540_prci_wrpll_clk_ops = {
-       .set_rate = sifive_fu540_prci_wrpll_set_rate,
-       .round_rate = sifive_fu540_prci_wrpll_round_rate,
-       .recalc_rate = sifive_fu540_prci_wrpll_recalc_rate,
+       .set_rate = sifive_prci_wrpll_set_rate,
+       .round_rate = sifive_prci_wrpll_round_rate,
+       .recalc_rate = sifive_prci_wrpll_recalc_rate,
+       .enable = sifive_prci_clock_enable,
+       .disable = sifive_prci_clock_disable,
+       .is_enabled = sifive_clk_is_enabled,
 };
 
 static const struct clk_ops sifive_fu540_prci_wrpll_ro_clk_ops = {
-       .recalc_rate = sifive_fu540_prci_wrpll_recalc_rate,
+       .recalc_rate = sifive_prci_wrpll_recalc_rate,
 };
 
-/* TLCLKSEL clock integration */
-
-static unsigned long sifive_fu540_prci_tlclksel_recalc_rate(struct clk_hw *hw,
-                                                           unsigned long parent_rate)
-{
-       struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
-       struct __prci_data *pd = pc->pd;
-       u32 v;
-       u8 div;
-
-       v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
-       v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
-       div = v ? 1 : 2;
-
-       return div_u64(parent_rate, div);
-}
-
 static const struct clk_ops sifive_fu540_prci_tlclksel_clk_ops = {
-       .recalc_rate = sifive_fu540_prci_tlclksel_recalc_rate,
-};
-
-/*
- * PRCI integration data for each WRPLL instance
- */
-
-static struct __prci_wrpll_data __prci_corepll_data = {
-       .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
-       .enable_bypass = __prci_coreclksel_use_hfclk,
-       .disable_bypass = __prci_coreclksel_use_corepll,
-};
-
-static struct __prci_wrpll_data __prci_ddrpll_data = {
-       .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
+       .recalc_rate = sifive_prci_tlclksel_recalc_rate,
 };
 
-static struct __prci_wrpll_data __prci_gemgxlpll_data = {
-       .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
-};
-
-/*
- * List of clock controls provided by the PRCI
- */
-
-static struct __prci_clock __prci_init_clocks[] = {
+/* List of clock controls provided by the PRCI */
+struct __prci_clock __prci_init_clocks_fu540[] = {
        [PRCI_CLK_COREPLL] = {
                .name = "corepll",
                .parent_name = "hfclk",
@@ -506,125 +87,3 @@ static struct __prci_clock __prci_init_clocks[] = {
                .ops = &sifive_fu540_prci_tlclksel_clk_ops,
        },
 };
-
-/**
- * __prci_register_clocks() - register clock controls in the PRCI with Linux
- * @dev: Linux struct device *
- *
- * Register the list of clock controls described in __prci_init_plls[] with
- * the Linux clock framework.
- *
- * Return: 0 upon success or a negative error code upon failure.
- */
-static int __prci_register_clocks(struct device *dev, struct __prci_data *pd)
-{
-       struct clk_init_data init = { };
-       struct __prci_clock *pic;
-       int parent_count, i, r;
-
-       parent_count = of_clk_get_parent_count(dev->of_node);
-       if (parent_count != EXPECTED_CLK_PARENT_COUNT) {
-               dev_err(dev, "expected only two parent clocks, found %d\n",
-                       parent_count);
-               return -EINVAL;
-       }
-
-       /* Register PLLs */
-       for (i = 0; i < ARRAY_SIZE(__prci_init_clocks); ++i) {
-               pic = &__prci_init_clocks[i];
-
-               init.name = pic->name;
-               init.parent_names = &pic->parent_name;
-               init.num_parents = 1;
-               init.ops = pic->ops;
-               pic->hw.init = &init;
-
-               pic->pd = pd;
-
-               if (pic->pwd)
-                       __prci_wrpll_read_cfg(pd, pic->pwd);
-
-               r = devm_clk_hw_register(dev, &pic->hw);
-               if (r) {
-                       dev_warn(dev, "Failed to register clock %s: %d\n",
-                                init.name, r);
-                       return r;
-               }
-
-               r = clk_hw_register_clkdev(&pic->hw, pic->name, dev_name(dev));
-               if (r) {
-                       dev_warn(dev, "Failed to register clkdev for %s: %d\n",
-                                init.name, r);
-                       return r;
-               }
-
-               pd->hw_clks.hws[i] = &pic->hw;
-       }
-
-       pd->hw_clks.num = i;
-
-       r = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
-                                       &pd->hw_clks);
-       if (r) {
-               dev_err(dev, "could not add hw_provider: %d\n", r);
-               return r;
-       }
-
-       return 0;
-}
-
-/*
- * Linux device model integration
- *
- * See the Linux device model documentation for more information about
- * these functions.
- */
-static int sifive_fu540_prci_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct resource *res;
-       struct __prci_data *pd;
-       int r;
-
-       pd = devm_kzalloc(dev,
-                         struct_size(pd, hw_clks.hws,
-                                     ARRAY_SIZE(__prci_init_clocks)),
-                         GFP_KERNEL);
-       if (!pd)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       pd->va = devm_ioremap_resource(dev, res);
-       if (IS_ERR(pd->va))
-               return PTR_ERR(pd->va);
-
-       r = __prci_register_clocks(dev, pd);
-       if (r) {
-               dev_err(dev, "could not register clocks: %d\n", r);
-               return r;
-       }
-
-       dev_dbg(dev, "SiFive FU540 PRCI probed\n");
-
-       return 0;
-}
-
-static const struct of_device_id sifive_fu540_prci_of_match[] = {
-       { .compatible = "sifive,fu540-c000-prci", },
-       {}
-};
-MODULE_DEVICE_TABLE(of, sifive_fu540_prci_of_match);
-
-static struct platform_driver sifive_fu540_prci_driver = {
-       .driver = {
-               .name = "sifive-fu540-prci",
-               .of_match_table = sifive_fu540_prci_of_match,
-       },
-       .probe = sifive_fu540_prci_probe,
-};
-
-static int __init sifive_fu540_prci_init(void)
-{
-       return platform_driver_register(&sifive_fu540_prci_driver);
-}
-core_initcall(sifive_fu540_prci_init);
diff --git a/drivers/clk/sifive/fu540-prci.h b/drivers/clk/sifive/fu540-prci.h
new file mode 100644 (file)
index 0000000..c8271ef
--- /dev/null
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 SiFive, Inc.
+ * Zong Li
+ */
+
+#ifndef __SIFIVE_CLK_FU540_PRCI_H
+#define __SIFIVE_CLK_FU540_PRCI_H
+
+#include "sifive-prci.h"
+
+#define NUM_CLOCK_FU540        4
+
+extern struct __prci_clock __prci_init_clocks_fu540[NUM_CLOCK_FU540];
+
+static const struct prci_clk_desc prci_clk_fu540 = {
+       .clks = __prci_init_clocks_fu540,
+       .num_clks = ARRAY_SIZE(__prci_init_clocks_fu540),
+};
+
+#endif /* __SIFIVE_CLK_FU540_PRCI_H */
diff --git a/drivers/clk/sifive/fu740-prci.c b/drivers/clk/sifive/fu740-prci.c
new file mode 100644 (file)
index 0000000..764d109
--- /dev/null
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 SiFive, Inc.
+ * Copyright (C) 2020 Zong Li
+ */
+
+#include <linux/module.h>
+
+#include <dt-bindings/clock/sifive-fu740-prci.h>
+
+#include "fu540-prci.h"
+#include "sifive-prci.h"
+
+/* PRCI integration data for each WRPLL instance */
+
+static struct __prci_wrpll_data __prci_corepll_data = {
+       .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
+       .cfg1_offs = PRCI_COREPLLCFG1_OFFSET,
+       .enable_bypass = sifive_prci_coreclksel_use_hfclk,
+       .disable_bypass = sifive_prci_coreclksel_use_final_corepll,
+};
+
+static struct __prci_wrpll_data __prci_ddrpll_data = {
+       .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
+       .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
+};
+
+static struct __prci_wrpll_data __prci_gemgxlpll_data = {
+       .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
+       .cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET,
+};
+
+static struct __prci_wrpll_data __prci_dvfscorepll_data = {
+       .cfg0_offs = PRCI_DVFSCOREPLLCFG0_OFFSET,
+       .cfg1_offs = PRCI_DVFSCOREPLLCFG1_OFFSET,
+       .enable_bypass = sifive_prci_corepllsel_use_corepll,
+       .disable_bypass = sifive_prci_corepllsel_use_dvfscorepll,
+};
+
+static struct __prci_wrpll_data __prci_hfpclkpll_data = {
+       .cfg0_offs = PRCI_HFPCLKPLLCFG0_OFFSET,
+       .cfg1_offs = PRCI_HFPCLKPLLCFG1_OFFSET,
+       .enable_bypass = sifive_prci_hfpclkpllsel_use_hfclk,
+       .disable_bypass = sifive_prci_hfpclkpllsel_use_hfpclkpll,
+};
+
+static struct __prci_wrpll_data __prci_cltxpll_data = {
+       .cfg0_offs = PRCI_CLTXPLLCFG0_OFFSET,
+       .cfg1_offs = PRCI_CLTXPLLCFG1_OFFSET,
+};
+
+/* Linux clock framework integration */
+
+static const struct clk_ops sifive_fu740_prci_wrpll_clk_ops = {
+       .set_rate = sifive_prci_wrpll_set_rate,
+       .round_rate = sifive_prci_wrpll_round_rate,
+       .recalc_rate = sifive_prci_wrpll_recalc_rate,
+       .enable = sifive_prci_clock_enable,
+       .disable = sifive_prci_clock_disable,
+       .is_enabled = sifive_clk_is_enabled,
+};
+
+static const struct clk_ops sifive_fu740_prci_wrpll_ro_clk_ops = {
+       .recalc_rate = sifive_prci_wrpll_recalc_rate,
+};
+
+static const struct clk_ops sifive_fu740_prci_tlclksel_clk_ops = {
+       .recalc_rate = sifive_prci_tlclksel_recalc_rate,
+};
+
+static const struct clk_ops sifive_fu740_prci_hfpclkplldiv_clk_ops = {
+       .recalc_rate = sifive_prci_hfpclkplldiv_recalc_rate,
+};
+
+/* List of clock controls provided by the PRCI */
+struct __prci_clock __prci_init_clocks_fu740[] = {
+       [PRCI_CLK_COREPLL] = {
+               .name = "corepll",
+               .parent_name = "hfclk",
+               .ops = &sifive_fu740_prci_wrpll_clk_ops,
+               .pwd = &__prci_corepll_data,
+       },
+       [PRCI_CLK_DDRPLL] = {
+               .name = "ddrpll",
+               .parent_name = "hfclk",
+               .ops = &sifive_fu740_prci_wrpll_ro_clk_ops,
+               .pwd = &__prci_ddrpll_data,
+       },
+       [PRCI_CLK_GEMGXLPLL] = {
+               .name = "gemgxlpll",
+               .parent_name = "hfclk",
+               .ops = &sifive_fu740_prci_wrpll_clk_ops,
+               .pwd = &__prci_gemgxlpll_data,
+       },
+       [PRCI_CLK_DVFSCOREPLL] = {
+               .name = "dvfscorepll",
+               .parent_name = "hfclk",
+               .ops = &sifive_fu740_prci_wrpll_clk_ops,
+               .pwd = &__prci_dvfscorepll_data,
+       },
+       [PRCI_CLK_HFPCLKPLL] = {
+               .name = "hfpclkpll",
+               .parent_name = "hfclk",
+               .ops = &sifive_fu740_prci_wrpll_clk_ops,
+               .pwd = &__prci_hfpclkpll_data,
+       },
+       [PRCI_CLK_CLTXPLL] = {
+               .name = "cltxpll",
+               .parent_name = "hfclk",
+               .ops = &sifive_fu740_prci_wrpll_clk_ops,
+               .pwd = &__prci_cltxpll_data,
+       },
+       [PRCI_CLK_TLCLK] = {
+               .name = "tlclk",
+               .parent_name = "corepll",
+               .ops = &sifive_fu740_prci_tlclksel_clk_ops,
+       },
+       [PRCI_CLK_PCLK] = {
+               .name = "pclk",
+               .parent_name = "hfpclkpll",
+               .ops = &sifive_fu740_prci_hfpclkplldiv_clk_ops,
+       },
+};
diff --git a/drivers/clk/sifive/fu740-prci.h b/drivers/clk/sifive/fu740-prci.h
new file mode 100644 (file)
index 0000000..13ef971
--- /dev/null
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 SiFive, Inc.
+ * Zong Li
+ */
+
+#ifndef __SIFIVE_CLK_FU740_PRCI_H
+#define __SIFIVE_CLK_FU740_PRCI_H
+
+#include "sifive-prci.h"
+
+#define NUM_CLOCK_FU740        8
+
+extern struct __prci_clock __prci_init_clocks_fu740[NUM_CLOCK_FU740];
+
+static const struct prci_clk_desc prci_clk_fu740 = {
+       .clks = __prci_init_clocks_fu740,
+       .num_clks = ARRAY_SIZE(__prci_init_clocks_fu740),
+};
+
+#endif /* __SIFIVE_CLK_FU740_PRCI_H */
diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c
new file mode 100644 (file)
index 0000000..c78b042
--- /dev/null
@@ -0,0 +1,574 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 SiFive, Inc.
+ * Copyright (C) 2020 Zong Li
+ */
+
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include "sifive-prci.h"
+#include "fu540-prci.h"
+#include "fu740-prci.h"
+
+/*
+ * Private functions
+ */
+
+/**
+ * __prci_readl() - read from a PRCI register
+ * @pd: PRCI context
+ * @offs: register offset to read from (in bytes, from PRCI base address)
+ *
+ * Read the register located at offset @offs from the base virtual
+ * address of the PRCI register target described by @pd, and return
+ * the value to the caller.
+ *
+ * Context: Any context.
+ *
+ * Return: the contents of the register described by @pd and @offs.
+ */
+static u32 __prci_readl(struct __prci_data *pd, u32 offs)
+{
+       return readl_relaxed(pd->va + offs);
+}
+
+static void __prci_writel(u32 v, u32 offs, struct __prci_data *pd)
+{
+       writel_relaxed(v, pd->va + offs);
+}
+
+/* WRPLL-related private functions */
+
+/**
+ * __prci_wrpll_unpack() - unpack WRPLL configuration registers into parameters
+ * @c: ptr to a struct wrpll_cfg record to write config into
+ * @r: value read from the PRCI PLL configuration register
+ *
+ * Given a value @r read from an FU740 PRCI PLL configuration register,
+ * split it into fields and populate it into the WRPLL configuration record
+ * pointed to by @c.
+ *
+ * The COREPLLCFG0 macros are used below, but the other *PLLCFG0 macros
+ * have the same register layout.
+ *
+ * Context: Any context.
+ */
+static void __prci_wrpll_unpack(struct wrpll_cfg *c, u32 r)
+{
+       u32 v;
+
+       v = r & PRCI_COREPLLCFG0_DIVR_MASK;
+       v >>= PRCI_COREPLLCFG0_DIVR_SHIFT;
+       c->divr = v;
+
+       v = r & PRCI_COREPLLCFG0_DIVF_MASK;
+       v >>= PRCI_COREPLLCFG0_DIVF_SHIFT;
+       c->divf = v;
+
+       v = r & PRCI_COREPLLCFG0_DIVQ_MASK;
+       v >>= PRCI_COREPLLCFG0_DIVQ_SHIFT;
+       c->divq = v;
+
+       v = r & PRCI_COREPLLCFG0_RANGE_MASK;
+       v >>= PRCI_COREPLLCFG0_RANGE_SHIFT;
+       c->range = v;
+
+       c->flags &=
+           (WRPLL_FLAGS_INT_FEEDBACK_MASK | WRPLL_FLAGS_EXT_FEEDBACK_MASK);
+
+       /* external feedback mode not supported */
+       c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
+}
+
+/**
+ * __prci_wrpll_pack() - pack PLL configuration parameters into a register value
+ * @c: pointer to a struct wrpll_cfg record containing the PLL's cfg
+ *
+ * Using a set of WRPLL configuration values pointed to by @c,
+ * assemble a PRCI PLL configuration register value, and return it to
+ * the caller.
+ *
+ * Context: Any context.  Caller must ensure that the contents of the
+ *          record pointed to by @c do not change during the execution
+ *          of this function.
+ *
+ * Returns: a value suitable for writing into a PRCI PLL configuration
+ *          register
+ */
+static u32 __prci_wrpll_pack(const struct wrpll_cfg *c)
+{
+       u32 r = 0;
+
+       r |= c->divr << PRCI_COREPLLCFG0_DIVR_SHIFT;
+       r |= c->divf << PRCI_COREPLLCFG0_DIVF_SHIFT;
+       r |= c->divq << PRCI_COREPLLCFG0_DIVQ_SHIFT;
+       r |= c->range << PRCI_COREPLLCFG0_RANGE_SHIFT;
+
+       /* external feedback mode not supported */
+       r |= PRCI_COREPLLCFG0_FSE_MASK;
+
+       return r;
+}
+
+/**
+ * __prci_wrpll_read_cfg0() - read the WRPLL configuration from the PRCI
+ * @pd: PRCI context
+ * @pwd: PRCI WRPLL metadata
+ *
+ * Read the current configuration of the PLL identified by @pwd from
+ * the PRCI identified by @pd, and store it into the local configuration
+ * cache in @pwd.
+ *
+ * Context: Any context.  Caller must prevent the records pointed to by
+ *          @pd and @pwd from changing during execution.
+ */
+static void __prci_wrpll_read_cfg0(struct __prci_data *pd,
+                                  struct __prci_wrpll_data *pwd)
+{
+       __prci_wrpll_unpack(&pwd->c, __prci_readl(pd, pwd->cfg0_offs));
+}
+
+/**
+ * __prci_wrpll_write_cfg0() - write WRPLL configuration into the PRCI
+ * @pd: PRCI context
+ * @pwd: PRCI WRPLL metadata
+ * @c: WRPLL configuration record to write
+ *
+ * Write the WRPLL configuration described by @c into the WRPLL
+ * configuration register identified by @pwd in the PRCI instance
+ * described by @c.  Make a cached copy of the WRPLL's current
+ * configuration so it can be used by other code.
+ *
+ * Context: Any context.  Caller must prevent the records pointed to by
+ *          @pd and @pwd from changing during execution.
+ */
+static void __prci_wrpll_write_cfg0(struct __prci_data *pd,
+                                   struct __prci_wrpll_data *pwd,
+                                   struct wrpll_cfg *c)
+{
+       __prci_writel(__prci_wrpll_pack(c), pwd->cfg0_offs, pd);
+
+       memcpy(&pwd->c, c, sizeof(*c));
+}
+
+/**
+ * __prci_wrpll_write_cfg1() - write Clock enable/disable configuration
+ * into the PRCI
+ * @pd: PRCI context
+ * @pwd: PRCI WRPLL metadata
+ * @enable: Clock enable or disable value
+ */
+static void __prci_wrpll_write_cfg1(struct __prci_data *pd,
+                                   struct __prci_wrpll_data *pwd,
+                                   u32 enable)
+{
+       __prci_writel(enable, pwd->cfg1_offs, pd);
+}
+
+/*
+ * Linux clock framework integration
+ *
+ * See the Linux clock framework documentation for more information on
+ * these functions.
+ */
+
+unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw,
+                                           unsigned long parent_rate)
+{
+       struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+       struct __prci_wrpll_data *pwd = pc->pwd;
+
+       return wrpll_calc_output_rate(&pwd->c, parent_rate);
+}
+
+long sifive_prci_wrpll_round_rate(struct clk_hw *hw,
+                                 unsigned long rate,
+                                 unsigned long *parent_rate)
+{
+       struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+       struct __prci_wrpll_data *pwd = pc->pwd;
+       struct wrpll_cfg c;
+
+       memcpy(&c, &pwd->c, sizeof(c));
+
+       wrpll_configure_for_rate(&c, rate, *parent_rate);
+
+       return wrpll_calc_output_rate(&c, *parent_rate);
+}
+
+int sifive_prci_wrpll_set_rate(struct clk_hw *hw,
+                              unsigned long rate, unsigned long parent_rate)
+{
+       struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+       struct __prci_wrpll_data *pwd = pc->pwd;
+       struct __prci_data *pd = pc->pd;
+       int r;
+
+       r = wrpll_configure_for_rate(&pwd->c, rate, parent_rate);
+       if (r)
+               return r;
+
+       if (pwd->enable_bypass)
+               pwd->enable_bypass(pd);
+
+       __prci_wrpll_write_cfg0(pd, pwd, &pwd->c);
+
+       udelay(wrpll_calc_max_lock_us(&pwd->c));
+
+       return 0;
+}
+
+int sifive_clk_is_enabled(struct clk_hw *hw)
+{
+       struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+       struct __prci_wrpll_data *pwd = pc->pwd;
+       struct __prci_data *pd = pc->pd;
+       u32 r;
+
+       r = __prci_readl(pd, pwd->cfg1_offs);
+
+       if (r & PRCI_COREPLLCFG1_CKE_MASK)
+               return 1;
+       else
+               return 0;
+}
+
+int sifive_prci_clock_enable(struct clk_hw *hw)
+{
+       struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+       struct __prci_wrpll_data *pwd = pc->pwd;
+       struct __prci_data *pd = pc->pd;
+
+       if (sifive_clk_is_enabled(hw))
+               return 0;
+
+       __prci_wrpll_write_cfg1(pd, pwd, PRCI_COREPLLCFG1_CKE_MASK);
+
+       if (pwd->disable_bypass)
+               pwd->disable_bypass(pd);
+
+       return 0;
+}
+
+void sifive_prci_clock_disable(struct clk_hw *hw)
+{
+       struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+       struct __prci_wrpll_data *pwd = pc->pwd;
+       struct __prci_data *pd = pc->pd;
+       u32 r;
+
+       if (pwd->enable_bypass)
+               pwd->enable_bypass(pd);
+
+       r = __prci_readl(pd, pwd->cfg1_offs);
+       r &= ~PRCI_COREPLLCFG1_CKE_MASK;
+
+       __prci_wrpll_write_cfg1(pd, pwd, r);
+}
+
+/* TLCLKSEL clock integration */
+
+unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw,
+                                              unsigned long parent_rate)
+{
+       struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+       struct __prci_data *pd = pc->pd;
+       u32 v;
+       u8 div;
+
+       v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
+       v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
+       div = v ? 1 : 2;
+
+       return div_u64(parent_rate, div);
+}
+
+/* HFPCLK clock integration */
+
+unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk_hw *hw,
+                                                  unsigned long parent_rate)
+{
+       struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+       struct __prci_data *pd = pc->pd;
+       u32 div = __prci_readl(pd, PRCI_HFPCLKPLLDIV_OFFSET);
+
+       return div_u64(parent_rate, div + 2);
+}
+
+/*
+ * Core clock mux control
+ */
+
+/**
+ * sifive_prci_coreclksel_use_hfclk() - switch the CORECLK mux to output HFCLK
+ * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
+ *
+ * Switch the CORECLK mux to the HFCLK input source; return once complete.
+ *
+ * Context: Any context.  Caller must prevent concurrent changes to the
+ *          PRCI_CORECLKSEL_OFFSET register.
+ */
+void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd)
+{
+       u32 r;
+
+       r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
+       r |= PRCI_CORECLKSEL_CORECLKSEL_MASK;
+       __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
+
+       r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);   /* barrier */
+}
+
+/**
+ * sifive_prci_coreclksel_use_corepll() - switch the CORECLK mux to output
+ * COREPLL
+ * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
+ *
+ * Switch the CORECLK mux to the COREPLL output clock; return once complete.
+ *
+ * Context: Any context.  Caller must prevent concurrent changes to the
+ *          PRCI_CORECLKSEL_OFFSET register.
+ */
+void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd)
+{
+       u32 r;
+
+       r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
+       r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK;
+       __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
+
+       r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);   /* barrier */
+}
+
+/**
+ * sifive_prci_coreclksel_use_final_corepll() - switch the CORECLK mux to output
+ * FINAL_COREPLL
+ * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
+ *
+ * Switch the CORECLK mux to the final COREPLL output clock; return once
+ * complete.
+ *
+ * Context: Any context.  Caller must prevent concurrent changes to the
+ *          PRCI_CORECLKSEL_OFFSET register.
+ */
+void sifive_prci_coreclksel_use_final_corepll(struct __prci_data *pd)
+{
+       u32 r;
+
+       r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
+       r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK;
+       __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
+
+       r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);   /* barrier */
+}
+
+/**
+ * sifive_prci_corepllsel_use_dvfscorepll() - switch the COREPLL mux to
+ * output DVFS_COREPLL
+ * @pd: struct __prci_data * for the PRCI containing the COREPLL mux reg
+ *
+ * Switch the COREPLL mux to the DVFSCOREPLL output clock; return once complete.
+ *
+ * Context: Any context.  Caller must prevent concurrent changes to the
+ *          PRCI_COREPLLSEL_OFFSET register.
+ */
+void sifive_prci_corepllsel_use_dvfscorepll(struct __prci_data *pd)
+{
+       u32 r;
+
+       r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET);
+       r |= PRCI_COREPLLSEL_COREPLLSEL_MASK;
+       __prci_writel(r, PRCI_COREPLLSEL_OFFSET, pd);
+
+       r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET);   /* barrier */
+}
+
+/**
+ * sifive_prci_corepllsel_use_corepll() - switch the COREPLL mux to
+ * output COREPLL
+ * @pd: struct __prci_data * for the PRCI containing the COREPLL mux reg
+ *
+ * Switch the COREPLL mux to the COREPLL output clock; return once complete.
+ *
+ * Context: Any context.  Caller must prevent concurrent changes to the
+ *          PRCI_COREPLLSEL_OFFSET register.
+ */
+void sifive_prci_corepllsel_use_corepll(struct __prci_data *pd)
+{
+       u32 r;
+
+       r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET);
+       r &= ~PRCI_COREPLLSEL_COREPLLSEL_MASK;
+       __prci_writel(r, PRCI_COREPLLSEL_OFFSET, pd);
+
+       r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET);   /* barrier */
+}
+
+/**
+ * sifive_prci_hfpclkpllsel_use_hfclk() - switch the HFPCLKPLL mux to
+ * output HFCLK
+ * @pd: struct __prci_data * for the PRCI containing the HFPCLKPLL mux reg
+ *
+ * Switch the HFPCLKPLL mux to the HFCLK input source; return once complete.
+ *
+ * Context: Any context.  Caller must prevent concurrent changes to the
+ *          PRCI_HFPCLKPLLSEL_OFFSET register.
+ */
+void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd)
+{
+       u32 r;
+
+       r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET);
+       r |= PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK;
+       __prci_writel(r, PRCI_HFPCLKPLLSEL_OFFSET, pd);
+
+       r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET); /* barrier */
+}
+
+/**
+ * sifive_prci_hfpclkpllsel_use_hfpclkpll() - switch the HFPCLKPLL mux to
+ * output HFPCLKPLL
+ * @pd: struct __prci_data * for the PRCI containing the HFPCLKPLL mux reg
+ *
+ * Switch the HFPCLKPLL mux to the HFPCLKPLL output clock; return once complete.
+ *
+ * Context: Any context.  Caller must prevent concurrent changes to the
+ *          PRCI_HFPCLKPLLSEL_OFFSET register.
+ */
+void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd)
+{
+       u32 r;
+
+       r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET);
+       r &= ~PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK;
+       __prci_writel(r, PRCI_HFPCLKPLLSEL_OFFSET, pd);
+
+       r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET); /* barrier */
+}
+
+/**
+ * __prci_register_clocks() - register clock controls in the PRCI
+ * @dev: Linux struct device
+ * @pd: The pointer for PRCI per-device instance data
+ * @desc: The pointer for the information of clocks of each SoCs
+ *
+ * Register the list of clock controls described in __prci_init_clocks[] with
+ * the Linux clock framework.
+ *
+ * Return: 0 upon success or a negative error code upon failure.
+ */
+static int __prci_register_clocks(struct device *dev, struct __prci_data *pd,
+                                 const struct prci_clk_desc *desc)
+{
+       struct clk_init_data init = { };
+       struct __prci_clock *pic;
+       int parent_count, i, r;
+
+       parent_count = of_clk_get_parent_count(dev->of_node);
+       if (parent_count != EXPECTED_CLK_PARENT_COUNT) {
+               dev_err(dev, "expected only two parent clocks, found %d\n",
+                       parent_count);
+               return -EINVAL;
+       }
+
+       /* Register PLLs */
+       for (i = 0; i < desc->num_clks; ++i) {
+               pic = &(desc->clks[i]);
+
+               init.name = pic->name;
+               init.parent_names = &pic->parent_name;
+               init.num_parents = 1;
+               init.ops = pic->ops;
+               pic->hw.init = &init;
+
+               pic->pd = pd;
+
+               if (pic->pwd)
+                       __prci_wrpll_read_cfg0(pd, pic->pwd);
+
+               r = devm_clk_hw_register(dev, &pic->hw);
+               if (r) {
+                       dev_warn(dev, "Failed to register clock %s: %d\n",
+                                init.name, r);
+                       return r;
+               }
+
+               r = clk_hw_register_clkdev(&pic->hw, pic->name, dev_name(dev));
+               if (r) {
+                       dev_warn(dev, "Failed to register clkdev for %s: %d\n",
+                                init.name, r);
+                       return r;
+               }
+
+               pd->hw_clks.hws[i] = &pic->hw;
+       }
+
+       pd->hw_clks.num = i;
+
+       r = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+                                       &pd->hw_clks);
+       if (r) {
+               dev_err(dev, "could not add hw_provider: %d\n", r);
+               return r;
+       }
+
+       return 0;
+}
+
+/**
+ * sifive_prci_init() - initialize prci data and check parent count
+ * @pdev: platform device pointer for the prci
+ *
+ * Return: 0 upon success or a negative error code upon failure.
+ */
+static int sifive_prci_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       struct __prci_data *pd;
+       const struct prci_clk_desc *desc;
+       int r;
+
+       desc = of_device_get_match_data(&pdev->dev);
+
+       pd = devm_kzalloc(dev, struct_size(pd, hw_clks.hws, desc->num_clks), GFP_KERNEL);
+       if (!pd)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       pd->va = devm_ioremap_resource(dev, res);
+       if (IS_ERR(pd->va))
+               return PTR_ERR(pd->va);
+
+       r = __prci_register_clocks(dev, pd, desc);
+       if (r) {
+               dev_err(dev, "could not register clocks: %d\n", r);
+               return r;
+       }
+
+       dev_dbg(dev, "SiFive PRCI probed\n");
+
+       return 0;
+}
+
+static const struct of_device_id sifive_prci_of_match[] = {
+       {.compatible = "sifive,fu540-c000-prci", .data = &prci_clk_fu540},
+       {.compatible = "sifive,fu740-c000-prci", .data = &prci_clk_fu740},
+       {}
+};
+
+static struct platform_driver sifive_prci_driver = {
+       .driver = {
+               .name = "sifive-clk-prci",
+               .of_match_table = sifive_prci_of_match,
+       },
+       .probe = sifive_prci_probe,
+};
+
+static int __init sifive_prci_init(void)
+{
+       return platform_driver_register(&sifive_prci_driver);
+}
+core_initcall(sifive_prci_init);
diff --git a/drivers/clk/sifive/sifive-prci.h b/drivers/clk/sifive/sifive-prci.h
new file mode 100644 (file)
index 0000000..dbdbd17
--- /dev/null
@@ -0,0 +1,299 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018-2019 SiFive, Inc.
+ * Wesley Terpstra
+ * Paul Walmsley
+ * Zong Li
+ */
+
+#ifndef __SIFIVE_CLK_SIFIVE_PRCI_H
+#define __SIFIVE_CLK_SIFIVE_PRCI_H
+
+#include <linux/clk/analogbits-wrpll-cln28hpc.h>
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+/*
+ * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
+ *     hfclk and rtcclk
+ */
+#define EXPECTED_CLK_PARENT_COUNT 2
+
+/*
+ * Register offsets and bitmasks
+ */
+
+/* COREPLLCFG0 */
+#define PRCI_COREPLLCFG0_OFFSET                0x4
+#define PRCI_COREPLLCFG0_DIVR_SHIFT    0
+#define PRCI_COREPLLCFG0_DIVR_MASK     (0x3f << PRCI_COREPLLCFG0_DIVR_SHIFT)
+#define PRCI_COREPLLCFG0_DIVF_SHIFT    6
+#define PRCI_COREPLLCFG0_DIVF_MASK     (0x1ff << PRCI_COREPLLCFG0_DIVF_SHIFT)
+#define PRCI_COREPLLCFG0_DIVQ_SHIFT    15
+#define PRCI_COREPLLCFG0_DIVQ_MASK     (0x7 << PRCI_COREPLLCFG0_DIVQ_SHIFT)
+#define PRCI_COREPLLCFG0_RANGE_SHIFT   18
+#define PRCI_COREPLLCFG0_RANGE_MASK    (0x7 << PRCI_COREPLLCFG0_RANGE_SHIFT)
+#define PRCI_COREPLLCFG0_BYPASS_SHIFT  24
+#define PRCI_COREPLLCFG0_BYPASS_MASK   (0x1 << PRCI_COREPLLCFG0_BYPASS_SHIFT)
+#define PRCI_COREPLLCFG0_FSE_SHIFT     25
+#define PRCI_COREPLLCFG0_FSE_MASK      (0x1 << PRCI_COREPLLCFG0_FSE_SHIFT)
+#define PRCI_COREPLLCFG0_LOCK_SHIFT    31
+#define PRCI_COREPLLCFG0_LOCK_MASK     (0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)
+
+/* COREPLLCFG1 */
+#define PRCI_COREPLLCFG1_OFFSET                0x8
+#define PRCI_COREPLLCFG1_CKE_SHIFT     31
+#define PRCI_COREPLLCFG1_CKE_MASK      (0x1 << PRCI_COREPLLCFG1_CKE_SHIFT)
+
+/* DDRPLLCFG0 */
+#define PRCI_DDRPLLCFG0_OFFSET         0xc
+#define PRCI_DDRPLLCFG0_DIVR_SHIFT     0
+#define PRCI_DDRPLLCFG0_DIVR_MASK      (0x3f << PRCI_DDRPLLCFG0_DIVR_SHIFT)
+#define PRCI_DDRPLLCFG0_DIVF_SHIFT     6
+#define PRCI_DDRPLLCFG0_DIVF_MASK      (0x1ff << PRCI_DDRPLLCFG0_DIVF_SHIFT)
+#define PRCI_DDRPLLCFG0_DIVQ_SHIFT     15
+#define PRCI_DDRPLLCFG0_DIVQ_MASK      (0x7 << PRCI_DDRPLLCFG0_DIVQ_SHIFT)
+#define PRCI_DDRPLLCFG0_RANGE_SHIFT    18
+#define PRCI_DDRPLLCFG0_RANGE_MASK     (0x7 << PRCI_DDRPLLCFG0_RANGE_SHIFT)
+#define PRCI_DDRPLLCFG0_BYPASS_SHIFT   24
+#define PRCI_DDRPLLCFG0_BYPASS_MASK    (0x1 << PRCI_DDRPLLCFG0_BYPASS_SHIFT)
+#define PRCI_DDRPLLCFG0_FSE_SHIFT      25
+#define PRCI_DDRPLLCFG0_FSE_MASK       (0x1 << PRCI_DDRPLLCFG0_FSE_SHIFT)
+#define PRCI_DDRPLLCFG0_LOCK_SHIFT     31
+#define PRCI_DDRPLLCFG0_LOCK_MASK      (0x1 << PRCI_DDRPLLCFG0_LOCK_SHIFT)
+
+/* DDRPLLCFG1 */
+#define PRCI_DDRPLLCFG1_OFFSET         0x10
+#define PRCI_DDRPLLCFG1_CKE_SHIFT      31
+#define PRCI_DDRPLLCFG1_CKE_MASK       (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
+
+/* GEMGXLPLLCFG0 */
+#define PRCI_GEMGXLPLLCFG0_OFFSET      0x1c
+#define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT  0
+#define PRCI_GEMGXLPLLCFG0_DIVR_MASK   (0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT)
+#define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT  6
+#define PRCI_GEMGXLPLLCFG0_DIVF_MASK   (0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT)
+#define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT  15
+#define PRCI_GEMGXLPLLCFG0_DIVQ_MASK   (0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT)
+#define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT 18
+#define PRCI_GEMGXLPLLCFG0_RANGE_MASK  (0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT)
+#define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT        24
+#define PRCI_GEMGXLPLLCFG0_BYPASS_MASK (0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT)
+#define PRCI_GEMGXLPLLCFG0_FSE_SHIFT   25
+#define PRCI_GEMGXLPLLCFG0_FSE_MASK    (0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT)
+#define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT  31
+#define PRCI_GEMGXLPLLCFG0_LOCK_MASK   (0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT)
+
+/* GEMGXLPLLCFG1 */
+#define PRCI_GEMGXLPLLCFG1_OFFSET      0x20
+#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT   31
+#define PRCI_GEMGXLPLLCFG1_CKE_MASK    (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
+
+/* CORECLKSEL */
+#define PRCI_CORECLKSEL_OFFSET                 0x24
+#define PRCI_CORECLKSEL_CORECLKSEL_SHIFT       0
+#define PRCI_CORECLKSEL_CORECLKSEL_MASK                                        \
+               (0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT)
+
+/* DEVICESRESETREG */
+#define PRCI_DEVICESRESETREG_OFFSET                            0x28
+#define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT              0
+#define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK                       \
+               (0x1 << PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT)
+#define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT               1
+#define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK                                \
+               (0x1 << PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT)
+#define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT               2
+#define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK                                \
+               (0x1 << PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT)
+#define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT               3
+#define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK                                \
+               (0x1 << PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT)
+#define PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT                        5
+#define PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK                         \
+               (0x1 << PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT)
+#define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT              6
+#define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_MASK                       \
+               (0x1 << PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT)
+
+/* CLKMUXSTATUSREG */
+#define PRCI_CLKMUXSTATUSREG_OFFSET                            0x2c
+#define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT             1
+#define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK                      \
+               (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
+
+/* CLTXPLLCFG0 */
+#define PRCI_CLTXPLLCFG0_OFFSET                0x30
+#define PRCI_CLTXPLLCFG0_DIVR_SHIFT    0
+#define PRCI_CLTXPLLCFG0_DIVR_MASK     (0x3f << PRCI_CLTXPLLCFG0_DIVR_SHIFT)
+#define PRCI_CLTXPLLCFG0_DIVF_SHIFT    6
+#define PRCI_CLTXPLLCFG0_DIVF_MASK     (0x1ff << PRCI_CLTXPLLCFG0_DIVF_SHIFT)
+#define PRCI_CLTXPLLCFG0_DIVQ_SHIFT    15
+#define PRCI_CLTXPLLCFG0_DIVQ_MASK     (0x7 << PRCI_CLTXPLLCFG0_DIVQ_SHIFT)
+#define PRCI_CLTXPLLCFG0_RANGE_SHIFT   18
+#define PRCI_CLTXPLLCFG0_RANGE_MASK    (0x7 << PRCI_CLTXPLLCFG0_RANGE_SHIFT)
+#define PRCI_CLTXPLLCFG0_BYPASS_SHIFT  24
+#define PRCI_CLTXPLLCFG0_BYPASS_MASK   (0x1 << PRCI_CLTXPLLCFG0_BYPASS_SHIFT)
+#define PRCI_CLTXPLLCFG0_FSE_SHIFT     25
+#define PRCI_CLTXPLLCFG0_FSE_MASK      (0x1 << PRCI_CLTXPLLCFG0_FSE_SHIFT)
+#define PRCI_CLTXPLLCFG0_LOCK_SHIFT    31
+#define PRCI_CLTXPLLCFG0_LOCK_MASK     (0x1 << PRCI_CLTXPLLCFG0_LOCK_SHIFT)
+
+/* CLTXPLLCFG1 */
+#define PRCI_CLTXPLLCFG1_OFFSET                0x34
+#define PRCI_CLTXPLLCFG1_CKE_SHIFT     31
+#define PRCI_CLTXPLLCFG1_CKE_MASK      (0x1 << PRCI_CLTXPLLCFG1_CKE_SHIFT)
+
+/* DVFSCOREPLLCFG0 */
+#define PRCI_DVFSCOREPLLCFG0_OFFSET    0x38
+
+/* DVFSCOREPLLCFG1 */
+#define PRCI_DVFSCOREPLLCFG1_OFFSET    0x3c
+#define PRCI_DVFSCOREPLLCFG1_CKE_SHIFT 31
+#define PRCI_DVFSCOREPLLCFG1_CKE_MASK  (0x1 << PRCI_DVFSCOREPLLCFG1_CKE_SHIFT)
+
+/* COREPLLSEL */
+#define PRCI_COREPLLSEL_OFFSET                 0x40
+#define PRCI_COREPLLSEL_COREPLLSEL_SHIFT       0
+#define PRCI_COREPLLSEL_COREPLLSEL_MASK                                        \
+               (0x1 << PRCI_COREPLLSEL_COREPLLSEL_SHIFT)
+
+/* HFPCLKPLLCFG0 */
+#define PRCI_HFPCLKPLLCFG0_OFFSET              0x50
+#define PRCI_HFPCLKPLL_CFG0_DIVR_SHIFT         0
+#define PRCI_HFPCLKPLL_CFG0_DIVR_MASK                                  \
+               (0x3f << PRCI_HFPCLKPLLCFG0_DIVR_SHIFT)
+#define PRCI_HFPCLKPLL_CFG0_DIVF_SHIFT         6
+#define PRCI_HFPCLKPLL_CFG0_DIVF_MASK                                  \
+               (0x1ff << PRCI_HFPCLKPLLCFG0_DIVF_SHIFT)
+#define PRCI_HFPCLKPLL_CFG0_DIVQ_SHIFT         15
+#define PRCI_HFPCLKPLL_CFG0_DIVQ_MASK                                  \
+               (0x7 << PRCI_HFPCLKPLLCFG0_DIVQ_SHIFT)
+#define PRCI_HFPCLKPLL_CFG0_RANGE_SHIFT                18
+#define PRCI_HFPCLKPLL_CFG0_RANGE_MASK                                 \
+               (0x7 << PRCI_HFPCLKPLLCFG0_RANGE_SHIFT)
+#define PRCI_HFPCLKPLL_CFG0_BYPASS_SHIFT       24
+#define PRCI_HFPCLKPLL_CFG0_BYPASS_MASK                                        \
+               (0x1 << PRCI_HFPCLKPLLCFG0_BYPASS_SHIFT)
+#define PRCI_HFPCLKPLL_CFG0_FSE_SHIFT          25
+#define PRCI_HFPCLKPLL_CFG0_FSE_MASK                                   \
+               (0x1 << PRCI_HFPCLKPLLCFG0_FSE_SHIFT)
+#define PRCI_HFPCLKPLL_CFG0_LOCK_SHIFT         31
+#define PRCI_HFPCLKPLL_CFG0_LOCK_MASK                                  \
+               (0x1 << PRCI_HFPCLKPLLCFG0_LOCK_SHIFT)
+
+/* HFPCLKPLLCFG1 */
+#define PRCI_HFPCLKPLLCFG1_OFFSET              0x54
+#define PRCI_HFPCLKPLLCFG1_CKE_SHIFT           31
+#define PRCI_HFPCLKPLLCFG1_CKE_MASK                                    \
+               (0x1 << PRCI_HFPCLKPLLCFG1_CKE_SHIFT)
+
+/* HFPCLKPLLSEL */
+#define PRCI_HFPCLKPLLSEL_OFFSET               0x58
+#define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT   0
+#define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK                            \
+               (0x1 << PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT)
+
+/* HFPCLKPLLDIV */
+#define PRCI_HFPCLKPLLDIV_OFFSET               0x5c
+
+/* PRCIPLL */
+#define PRCI_PRCIPLL_OFFSET                    0xe0
+
+/* PROCMONCFG */
+#define PRCI_PROCMONCFG_OFFSET                 0xf0
+
+/*
+ * Private structures
+ */
+
+/**
+ * struct __prci_data - per-device-instance data
+ * @va: base virtual address of the PRCI IP block
+ * @hw_clks: encapsulates struct clk_hw records
+ *
+ * PRCI per-device instance data
+ */
+struct __prci_data {
+       void __iomem *va;
+       struct clk_hw_onecell_data hw_clks;
+};
+
+/**
+ * struct __prci_wrpll_data - WRPLL configuration and integration data
+ * @c: WRPLL current configuration record
+ * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
+ * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
+ * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
+ * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address
+ *
+ * @enable_bypass and @disable_bypass are used for WRPLL instances
+ * that contain a separate external glitchless clock mux downstream
+ * from the PLL.  The WRPLL internal bypass mux is not glitchless.
+ */
+struct __prci_wrpll_data {
+       struct wrpll_cfg c;
+       void (*enable_bypass)(struct __prci_data *pd);
+       void (*disable_bypass)(struct __prci_data *pd);
+       u8 cfg0_offs;
+       u8 cfg1_offs;
+};
+
+/**
+ * struct __prci_clock - describes a clock device managed by PRCI
+ * @name: user-readable clock name string - should match the manual
+ * @parent_name: parent name for this clock
+ * @ops: struct clk_ops for the Linux clock framework to use for control
+ * @hw: Linux-private clock data
+ * @pwd: WRPLL-specific data, associated with this clock (if not NULL)
+ * @pd: PRCI-specific data associated with this clock (if not NULL)
+ *
+ * PRCI clock data.  Used by the PRCI driver to register PRCI-provided
+ * clocks to the Linux clock infrastructure.
+ */
+struct __prci_clock {
+       const char *name;
+       const char *parent_name;
+       const struct clk_ops *ops;
+       struct clk_hw hw;
+       struct __prci_wrpll_data *pwd;
+       struct __prci_data *pd;
+};
+
+#define clk_hw_to_prci_clock(pwd) container_of(pwd, struct __prci_clock, hw)
+
+/*
+ * struct prci_clk_desc - describes the information of clocks of each SoCs
+ * @clks: point to a array of __prci_clock
+ * @num_clks: the number of element of clks
+ */
+struct prci_clk_desc {
+       struct __prci_clock *clks;
+       size_t num_clks;
+};
+
+/* Core clock mux control */
+void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd);
+void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd);
+void sifive_prci_coreclksel_use_final_corepll(struct __prci_data *pd);
+void sifive_prci_corepllsel_use_dvfscorepll(struct __prci_data *pd);
+void sifive_prci_corepllsel_use_corepll(struct __prci_data *pd);
+void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd);
+void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd);
+
+/* Linux clock framework integration */
+long sifive_prci_wrpll_round_rate(struct clk_hw *hw, unsigned long rate,
+                                 unsigned long *parent_rate);
+int sifive_prci_wrpll_set_rate(struct clk_hw *hw, unsigned long rate,
+                              unsigned long parent_rate);
+int sifive_clk_is_enabled(struct clk_hw *hw);
+int sifive_prci_clock_enable(struct clk_hw *hw);
+void sifive_prci_clock_disable(struct clk_hw *hw);
+unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw,
+                                           unsigned long parent_rate);
+unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw,
+                                              unsigned long parent_rate);
+unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk_hw *hw,
+                                                  unsigned long parent_rate);
+
+#endif /* __SIFIVE_CLK_SIFIVE_PRCI_H */
index a66263b6490d39dcb77fd4e220c14c71cccf81e5..6ecf18f71c329fa24608d103d07d7fde7a59db06 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (C) 2016 NVIDIA Corporation
+ * Copyright (C) 2016-2020 NVIDIA Corporation
  */
 
 #include <linux/clk-provider.h>
@@ -174,7 +174,7 @@ static long tegra_bpmp_clk_round_rate(struct clk_hw *hw, unsigned long rate,
        int err;
 
        memset(&request, 0, sizeof(request));
-       request.rate = rate;
+       request.rate = min_t(u64, rate, S64_MAX);
 
        memset(&msg, 0, sizeof(msg));
        msg.cmd = CMD_CLK_ROUND_RATE;
@@ -256,7 +256,7 @@ static int tegra_bpmp_clk_set_rate(struct clk_hw *hw, unsigned long rate,
        struct tegra_bpmp_clk_message msg;
 
        memset(&request, 0, sizeof(request));
-       request.rate = rate;
+       request.rate = min_t(u64, rate, S64_MAX);
 
        memset(&msg, 0, sizeof(msg));
        msg.cmd = CMD_CLK_SET_RATE;
index cfbaa90c7adbf61533cab4a531205aea8f53bafd..a5f526bb0483e1bc77c2ff87d313afc5bca9af34 100644 (file)
@@ -1856,13 +1856,13 @@ static int dfll_fetch_pwm_params(struct tegra_dfll *td)
                            &td->reg_init_uV);
        if (!ret) {
                dev_err(td->dev, "couldn't get initialized voltage\n");
-               return ret;
+               return -EINVAL;
        }
 
        ret = read_dt_param(td, "nvidia,pwm-period-nanoseconds", &pwm_period);
        if (!ret) {
                dev_err(td->dev, "couldn't get PWM period\n");
-               return ret;
+               return -EINVAL;
        }
        td->pwm_rate = (NSEC_PER_SEC / pwm_period) * (MAX_DFLL_VOLTAGES - 1);
 
index ff7da2d3e94d853b8d25c3b323d8ff645dbed360..24413812ec5b6b26dfb680c2af1daa14038be8e1 100644 (file)
@@ -227,6 +227,7 @@ enum clk_id {
        tegra_clk_sdmmc4,
        tegra_clk_sdmmc4_8,
        tegra_clk_se,
+       tegra_clk_se_10,
        tegra_clk_soc_therm,
        tegra_clk_soc_therm_8,
        tegra_clk_sor0,
index 2b2a3b81c16bab38e08a6d408547bbcfac1e3179..60cc34f90cb9b4943de20c8c5f12683dcc551c2e 100644 (file)
@@ -630,7 +630,7 @@ static struct tegra_periph_init_data periph_clks[] = {
        INT8("host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_8),
        INT8("host1x", mux_pllc4_out1_pllc_pllc4_out2_pllp_clkm_plla_pllc4_out0, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_9),
        INT8("se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se),
-       INT8("se", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se),
+       INT8("se", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se_10),
        INT8("2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d_8),
        INT8("3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d_8),
        INT8("vic03", mux_pllm_pllc_pllp_plla_pllc2_c3_clkm, CLK_SOURCE_VIC03, 178, 0, tegra_clk_vic03),
index fd1f938c38d191b9c56fcc9004a981936a69c476..e2749dbc74b897f66eaea70db6f459239fa2efec 100644 (file)
 #define CLKID_PCIE_CML_EN1                     80
 #define CLKID_MIPI_ENABLE                      81
 #define CLKID_GEN_CLK                          84
+#define CLKID_VPU_0_SEL                                92
+#define CLKID_VPU_0                            93
+#define CLKID_VPU_1_SEL                                95
+#define CLKID_VPU_1                            96
+#define CLKID_VPU                              97
+#define CLKID_VAPB_0_SEL                       99
+#define CLKID_VAPB_0                           100
+#define CLKID_VAPB_1_SEL                       102
+#define CLKID_VAPB_1                           103
+#define CLKID_VAPB_SEL                         104
+#define CLKID_VAPB                             105
+#define CLKID_VCLK                             106
+#define CLKID_VCLK2                            107
+#define CLKID_VCLK_DIV1                                122
+#define CLKID_VCLK_DIV2                                123
+#define CLKID_VCLK_DIV4                                124
+#define CLKID_VCLK_DIV6                                125
+#define CLKID_VCLK_DIV12                       126
+#define CLKID_VCLK2_DIV1                       127
+#define CLKID_VCLK2_DIV2                       128
+#define CLKID_VCLK2_DIV4                       129
+#define CLKID_VCLK2_DIV6                       130
+#define CLKID_VCLK2_DIV12                      131
+#define CLKID_CTS_ENCL                         133
+#define CLKID_VDIN_MEAS                                136
 
 #endif /* __AXG_CLKC_H */
diff --git a/include/dt-bindings/clock/fsl,qoriq-clockgen.h b/include/dt-bindings/clock/fsl,qoriq-clockgen.h
new file mode 100644 (file)
index 0000000..ddec7d0
--- /dev/null
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef DT_CLOCK_FSL_QORIQ_CLOCKGEN_H
+#define DT_CLOCK_FSL_QORIQ_CLOCKGEN_H
+
+#define QORIQ_CLK_SYSCLK       0
+#define QORIQ_CLK_CMUX         1
+#define QORIQ_CLK_HWACCEL      2
+#define QORIQ_CLK_FMAN         3
+#define QORIQ_CLK_PLATFORM_PLL 4
+#define QORIQ_CLK_CORECLK      5
+
+#define QORIQ_CLK_PLL_DIV(x)   ((x) - 1)
+
+#endif /* DT_CLOCK_FSL_QORIQ_CLOCKGEN_H */
index 40d49940d8a8dfb1b55aa9a56b8d674ac16d1a30..a93b58c5e18ecdb86a0098cf37485fa62df7933a 100644 (file)
 #define CLKID_SPICC1_SCLK                      261
 #define CLKID_NNA_AXI_CLK                      264
 #define CLKID_NNA_CORE_CLK                     267
+#define CLKID_MIPI_DSI_PXCLK_SEL               269
+#define CLKID_MIPI_DSI_PXCLK                   270
 
 #endif /* __G12A_CLKC_H */
diff --git a/include/dt-bindings/clock/qcom,camcc-sc7180.h b/include/dt-bindings/clock/qcom,camcc-sc7180.h
new file mode 100644 (file)
index 0000000..ef7d3a0
--- /dev/null
@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_CAM_CC_SC7180_H
+#define _DT_BINDINGS_CLK_QCOM_CAM_CC_SC7180_H
+
+/* CAM_CC clocks */
+#define CAM_CC_PLL2_OUT_EARLY                                  0
+#define CAM_CC_PLL0                                            1
+#define CAM_CC_PLL1                                            2
+#define CAM_CC_PLL2                                            3
+#define CAM_CC_PLL2_OUT_AUX                                    4
+#define CAM_CC_PLL3                                            5
+#define CAM_CC_CAMNOC_AXI_CLK                                  6
+#define CAM_CC_CCI_0_CLK                                       7
+#define CAM_CC_CCI_0_CLK_SRC                                   8
+#define CAM_CC_CCI_1_CLK                                       9
+#define CAM_CC_CCI_1_CLK_SRC                                   10
+#define CAM_CC_CORE_AHB_CLK                                    11
+#define CAM_CC_CPAS_AHB_CLK                                    12
+#define CAM_CC_CPHY_RX_CLK_SRC                                 13
+#define CAM_CC_CSI0PHYTIMER_CLK                                        14
+#define CAM_CC_CSI0PHYTIMER_CLK_SRC                            15
+#define CAM_CC_CSI1PHYTIMER_CLK                                        16
+#define CAM_CC_CSI1PHYTIMER_CLK_SRC                            17
+#define CAM_CC_CSI2PHYTIMER_CLK                                        18
+#define CAM_CC_CSI2PHYTIMER_CLK_SRC                            19
+#define CAM_CC_CSI3PHYTIMER_CLK                                        20
+#define CAM_CC_CSI3PHYTIMER_CLK_SRC                            21
+#define CAM_CC_CSIPHY0_CLK                                     22
+#define CAM_CC_CSIPHY1_CLK                                     23
+#define CAM_CC_CSIPHY2_CLK                                     24
+#define CAM_CC_CSIPHY3_CLK                                     25
+#define CAM_CC_FAST_AHB_CLK_SRC                                        26
+#define CAM_CC_ICP_APB_CLK                                     27
+#define CAM_CC_ICP_ATB_CLK                                     28
+#define CAM_CC_ICP_CLK                                         29
+#define CAM_CC_ICP_CLK_SRC                                     30
+#define CAM_CC_ICP_CTI_CLK                                     31
+#define CAM_CC_ICP_TS_CLK                                      32
+#define CAM_CC_IFE_0_AXI_CLK                                   33
+#define CAM_CC_IFE_0_CLK                                       34
+#define CAM_CC_IFE_0_CLK_SRC                                   35
+#define CAM_CC_IFE_0_CPHY_RX_CLK                               36
+#define CAM_CC_IFE_0_CSID_CLK                                  37
+#define CAM_CC_IFE_0_CSID_CLK_SRC                              38
+#define CAM_CC_IFE_0_DSP_CLK                                   39
+#define CAM_CC_IFE_1_AXI_CLK                                   40
+#define CAM_CC_IFE_1_CLK                                       41
+#define CAM_CC_IFE_1_CLK_SRC                                   42
+#define CAM_CC_IFE_1_CPHY_RX_CLK                               43
+#define CAM_CC_IFE_1_CSID_CLK                                  44
+#define CAM_CC_IFE_1_CSID_CLK_SRC                              45
+#define CAM_CC_IFE_1_DSP_CLK                                   46
+#define CAM_CC_IFE_LITE_CLK                                    47
+#define CAM_CC_IFE_LITE_CLK_SRC                                        48
+#define CAM_CC_IFE_LITE_CPHY_RX_CLK                            49
+#define CAM_CC_IFE_LITE_CSID_CLK                               50
+#define CAM_CC_IFE_LITE_CSID_CLK_SRC                           51
+#define CAM_CC_IPE_0_AHB_CLK                                   52
+#define CAM_CC_IPE_0_AREG_CLK                                  53
+#define CAM_CC_IPE_0_AXI_CLK                                   54
+#define CAM_CC_IPE_0_CLK                                       55
+#define CAM_CC_IPE_0_CLK_SRC                                   56
+#define CAM_CC_JPEG_CLK                                                57
+#define CAM_CC_JPEG_CLK_SRC                                    58
+#define CAM_CC_LRME_CLK                                                59
+#define CAM_CC_LRME_CLK_SRC                                    60
+#define CAM_CC_MCLK0_CLK                                       61
+#define CAM_CC_MCLK0_CLK_SRC                                   62
+#define CAM_CC_MCLK1_CLK                                       63
+#define CAM_CC_MCLK1_CLK_SRC                                   64
+#define CAM_CC_MCLK2_CLK                                       65
+#define CAM_CC_MCLK2_CLK_SRC                                   66
+#define CAM_CC_MCLK3_CLK                                       67
+#define CAM_CC_MCLK3_CLK_SRC                                   68
+#define CAM_CC_MCLK4_CLK                                       69
+#define CAM_CC_MCLK4_CLK_SRC                                   70
+#define CAM_CC_BPS_AHB_CLK                                     71
+#define CAM_CC_BPS_AREG_CLK                                    72
+#define CAM_CC_BPS_AXI_CLK                                     73
+#define CAM_CC_BPS_CLK                                         74
+#define CAM_CC_BPS_CLK_SRC                                     75
+#define CAM_CC_SLOW_AHB_CLK_SRC                                        76
+#define CAM_CC_SOC_AHB_CLK                                     77
+#define CAM_CC_SYS_TMR_CLK                                     78
+
+/* CAM_CC power domains */
+#define BPS_GDSC                                               0
+#define IFE_0_GDSC                                             1
+#define IFE_1_GDSC                                             2
+#define IPE_0_GDSC                                             3
+#define TITAN_TOP_GDSC                                         4
+
+/* CAM_CC resets */
+#define CAM_CC_BPS_BCR                                         0
+#define CAM_CC_CAMNOC_BCR                                      1
+#define CAM_CC_CCI_0_BCR                                       2
+#define CAM_CC_CCI_1_BCR                                       3
+#define CAM_CC_CPAS_BCR                                                4
+#define CAM_CC_CSI0PHY_BCR                                     5
+#define CAM_CC_CSI1PHY_BCR                                     6
+#define CAM_CC_CSI2PHY_BCR                                     7
+#define CAM_CC_CSI3PHY_BCR                                     8
+#define CAM_CC_ICP_BCR                                         9
+#define CAM_CC_IFE_0_BCR                                       10
+#define CAM_CC_IFE_1_BCR                                       11
+#define CAM_CC_IFE_LITE_BCR                                    12
+#define CAM_CC_IPE_0_BCR                                       13
+#define CAM_CC_JPEG_BCR                                                14
+#define CAM_CC_LRME_BCR                                                15
+#define CAM_CC_MCLK0_BCR                                       16
+#define CAM_CC_MCLK1_BCR                                       17
+#define CAM_CC_MCLK2_BCR                                       18
+#define CAM_CC_MCLK3_BCR                                       19
+#define CAM_CC_MCLK4_BCR                                       20
+#define CAM_CC_TITAN_TOP_BCR                                   21
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,gcc-sdx55.h b/include/dt-bindings/clock/qcom,gcc-sdx55.h
new file mode 100644 (file)
index 0000000..fb9a594
--- /dev/null
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020, Linaro Ltd.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_GCC_SDX55_H
+#define _DT_BINDINGS_CLK_QCOM_GCC_SDX55_H
+
+#define GPLL0                                                  3
+#define GPLL0_OUT_EVEN                                         4
+#define GPLL4                                                  5
+#define GPLL4_OUT_EVEN                                         6
+#define GPLL5                                                  7
+#define GCC_AHB_PCIE_LINK_CLK                                  8
+#define GCC_BLSP1_AHB_CLK                                      9
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK                            10
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK_SRC                                11
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK                            12
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK_SRC                                13
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK                            14
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK_SRC                                15
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK                            16
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK_SRC                                17
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK                            18
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK_SRC                                19
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK                            20
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK_SRC                                21
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK                            22
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK_SRC                                23
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK                            24
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK_SRC                                25
+#define GCC_BLSP1_UART1_APPS_CLK                               26
+#define GCC_BLSP1_UART1_APPS_CLK_SRC                           27
+#define GCC_BLSP1_UART2_APPS_CLK                               28
+#define GCC_BLSP1_UART2_APPS_CLK_SRC                           29
+#define GCC_BLSP1_UART3_APPS_CLK                               30
+#define GCC_BLSP1_UART3_APPS_CLK_SRC                           31
+#define GCC_BLSP1_UART4_APPS_CLK                               32
+#define GCC_BLSP1_UART4_APPS_CLK_SRC                           33
+#define GCC_BOOT_ROM_AHB_CLK                                   34
+#define GCC_CE1_AHB_CLK                                                35
+#define GCC_CE1_AXI_CLK                                                36
+#define GCC_CE1_CLK                                            37
+#define GCC_CPUSS_AHB_CLK                                      38
+#define GCC_CPUSS_AHB_CLK_SRC                                  39
+#define GCC_CPUSS_GNOC_CLK                                     40
+#define GCC_CPUSS_RBCPR_CLK                                    41
+#define GCC_CPUSS_RBCPR_CLK_SRC                                        42
+#define GCC_EMAC_CLK_SRC                                       43
+#define GCC_EMAC_PTP_CLK_SRC                                   44
+#define GCC_ETH_AXI_CLK                                                45
+#define GCC_ETH_PTP_CLK                                                46
+#define GCC_ETH_RGMII_CLK                                      47
+#define GCC_ETH_SLAVE_AHB_CLK                                  48
+#define GCC_GP1_CLK                                            49
+#define GCC_GP1_CLK_SRC                                                50
+#define GCC_GP2_CLK                                            51
+#define GCC_GP2_CLK_SRC                                                52
+#define GCC_GP3_CLK                                            53
+#define GCC_GP3_CLK_SRC                                                54
+#define GCC_PCIE_0_CLKREF_CLK                                  55
+#define GCC_PCIE_AUX_CLK                                       56
+#define GCC_PCIE_AUX_PHY_CLK_SRC                               57
+#define GCC_PCIE_CFG_AHB_CLK                                   58
+#define GCC_PCIE_MSTR_AXI_CLK                                  59
+#define GCC_PCIE_PIPE_CLK                                      60
+#define GCC_PCIE_RCHNG_PHY_CLK                                 61
+#define GCC_PCIE_RCHNG_PHY_CLK_SRC                             62
+#define GCC_PCIE_SLEEP_CLK                                     63
+#define GCC_PCIE_SLV_AXI_CLK                                   64
+#define GCC_PCIE_SLV_Q2A_AXI_CLK                               65
+#define GCC_PDM2_CLK                                           66
+#define GCC_PDM2_CLK_SRC                                       67
+#define GCC_PDM_AHB_CLK                                                68
+#define GCC_PDM_XO4_CLK                                                69
+#define GCC_SDCC1_AHB_CLK                                      70
+#define GCC_SDCC1_APPS_CLK                                     71
+#define GCC_SDCC1_APPS_CLK_SRC                                 72
+#define GCC_SYS_NOC_CPUSS_AHB_CLK                              73
+#define GCC_USB30_MASTER_CLK                                   74
+#define GCC_USB30_MASTER_CLK_SRC                               75
+#define GCC_USB30_MOCK_UTMI_CLK                                        76
+#define GCC_USB30_MOCK_UTMI_CLK_SRC                            77
+#define GCC_USB30_MSTR_AXI_CLK                                 78
+#define GCC_USB30_SLEEP_CLK                                    79
+#define GCC_USB30_SLV_AHB_CLK                                  80
+#define GCC_USB3_PHY_AUX_CLK                                   81
+#define GCC_USB3_PHY_AUX_CLK_SRC                               82
+#define GCC_USB3_PHY_PIPE_CLK                                  83
+#define GCC_USB3_PRIM_CLKREF_CLK                               84
+#define GCC_USB_PHY_CFG_AHB2PHY_CLK                            85
+#define GCC_XO_DIV4_CLK                                                86
+#define GCC_XO_PCIE_LINK_CLK                                   87
+
+#define GCC_EMAC_BCR                                           0
+#define GCC_PCIE_BCR                                           1
+#define GCC_PCIE_LINK_DOWN_BCR                                 2
+#define GCC_PCIE_NOCSR_COM_PHY_BCR                             3
+#define GCC_PCIE_PHY_BCR                                       4
+#define GCC_PCIE_PHY_CFG_AHB_BCR                               5
+#define GCC_PCIE_PHY_COM_BCR                                   6
+#define GCC_PCIE_PHY_NOCSR_COM_PHY_BCR                         7
+#define GCC_PDM_BCR                                            8
+#define GCC_QUSB2PHY_BCR                                       9
+#define GCC_TCSR_PCIE_BCR                                      10
+#define GCC_USB30_BCR                                          11
+#define GCC_USB3_PHY_BCR                                       12
+#define GCC_USB3PHY_PHY_BCR                                    13
+#define GCC_USB_PHY_CFG_AHB2PHY_BCR                            14
+
+/* GCC power domains */
+#define USB30_GDSC                                             0
+#define PCIE_GDSC                                              1
+#define EMAC_GDSC                                              2
+
+#endif
index 2e6c54e65455c1e927303a17133140ebeba6b5f7..583a99161aaab9f6f79a339e448f3d8ba95bdee6 100644 (file)
 #define RPMH_IPA_CLK                           12
 #define RPMH_LN_BB_CLK1                                13
 #define RPMH_LN_BB_CLK1_A                      14
+#define RPMH_CE_CLK                            15
+#define RPMH_QPIC_CLK                          16
+#define RPMH_DIV_CLK1                          17
+#define RPMH_DIV_CLK1_A                                18
+#define RPMH_RF_CLK4                           19
+#define RPMH_RF_CLK4_A                         20
+#define RPMH_RF_CLK5                           21
+#define RPMH_RF_CLK5_A                         22
+#define RPMH_PKA_CLK                           23
+#define RPMH_HWKM_CLK                          24
 
 #endif
diff --git a/include/dt-bindings/clock/qcom,sm8250-lpass-aoncc.h b/include/dt-bindings/clock/qcom,sm8250-lpass-aoncc.h
new file mode 100644 (file)
index 0000000..f5a1cfa
--- /dev/null
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _DT_BINDINGS_CLK_LPASS_AONCC_SM8250_H
+#define _DT_BINDINGS_CLK_LPASS_AONCC_SM8250_H
+
+/* from AOCC */
+#define LPASS_CDC_VA_MCLK                              0
+#define LPASS_CDC_TX_NPL                               1
+#define LPASS_CDC_TX_MCLK                              2
+
+#endif /* _DT_BINDINGS_CLK_LPASS_AONCC_SM8250_H */
diff --git a/include/dt-bindings/clock/qcom,sm8250-lpass-audiocc.h b/include/dt-bindings/clock/qcom,sm8250-lpass-audiocc.h
new file mode 100644 (file)
index 0000000..a1aa6cb
--- /dev/null
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _DT_BINDINGS_CLK_LPASS_AUDIOCC_SM8250_H
+#define _DT_BINDINGS_CLK_LPASS_AUDIOCC_SM8250_H
+
+/* From AudioCC */
+#define LPASS_CDC_WSA_NPL                              0
+#define LPASS_CDC_WSA_MCLK                             1
+#define LPASS_CDC_RX_MCLK                              2
+#define LPASS_CDC_RX_NPL                               3
+#define LPASS_CDC_RX_MCLK_MCLK2                                4
+
+#endif /* _DT_BINDINGS_CLK_LPASS_AUDIOCC_SM8250_H */
diff --git a/include/dt-bindings/clock/sifive-fu740-prci.h b/include/dt-bindings/clock/sifive-fu740-prci.h
new file mode 100644 (file)
index 0000000..cd7706e
--- /dev/null
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright (C) 2019 SiFive, Inc.
+ * Wesley Terpstra
+ * Paul Walmsley
+ * Zong Li
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_SIFIVE_FU740_PRCI_H
+#define __DT_BINDINGS_CLOCK_SIFIVE_FU740_PRCI_H
+
+/* Clock indexes for use by Device Tree data and the PRCI driver */
+
+#define PRCI_CLK_COREPLL              0
+#define PRCI_CLK_DDRPLL                       1
+#define PRCI_CLK_GEMGXLPLL            2
+#define PRCI_CLK_DVFSCOREPLL          3
+#define PRCI_CLK_HFPCLKPLL            4
+#define PRCI_CLK_CLTXPLL              5
+#define PRCI_CLK_TLCLK                6
+#define PRCI_CLK_PCLK                 7
+
+#endif /* __DT_BINDINGS_CLOCK_SIFIVE_FU740_PRCI_H */
index 03a5de5f99f4a3f5bae8dac7a0f3218ee256f027..e4316890661afcb9ca5d1aff5eb66f0a6438ccb7 100644 (file)
@@ -639,6 +639,12 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev,
                const struct clk_parent_data *parent_data, unsigned long flags,
                void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
                const struct clk_div_table *table, spinlock_t *lock);
+struct clk_hw *__devm_clk_hw_register_divider(struct device *dev,
+               struct device_node *np, const char *name,
+               const char *parent_name, const struct clk_hw *parent_hw,
+               const struct clk_parent_data *parent_data, unsigned long flags,
+               void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
+               const struct clk_div_table *table, spinlock_t *lock);
 struct clk *clk_register_divider_table(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
                void __iomem *reg, u8 shift, u8 width,
@@ -779,6 +785,27 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
                                  (parent_data), (flags), (reg), (shift),     \
                                  (width), (clk_divider_flags), (table),      \
                                  (lock))
+/**
+ * devm_clk_hw_register_divider_table - register a table based divider clock
+ * with the clock framework (devres variant)
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @shift: number of bits to shift the bitfield
+ * @width: width of the bitfield
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @table: array of divider/value pairs ending with a div set to 0
+ * @lock: shared register lock for this clock
+ */
+#define devm_clk_hw_register_divider_table(dev, name, parent_name, flags,     \
+                                          reg, shift, width,                 \
+                                          clk_divider_flags, table, lock)    \
+       __devm_clk_hw_register_divider((dev), NULL, (name), (parent_name),    \
+                                      NULL, NULL, (flags), (reg), (shift),   \
+                                      (width), (clk_divider_flags), (table), \
+                                      (lock))
 
 void clk_unregister_divider(struct clk *clk);
 void clk_hw_unregister_divider(struct clk_hw *hw);
@@ -1062,6 +1089,13 @@ struct clk_hw *clk_hw_register_composite_pdata(struct device *dev,
                struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
                struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
                unsigned long flags);
+struct clk_hw *devm_clk_hw_register_composite_pdata(struct device *dev,
+               const char *name, const struct clk_parent_data *parent_data,
+               int num_parents,
+               struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
+               struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
+               struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+               unsigned long flags);
 void clk_hw_unregister_composite(struct clk_hw *hw);
 
 struct clk *clk_register(struct device *dev, struct clk_hw *hw);
@@ -1088,6 +1122,11 @@ static inline struct clk_hw *__clk_get_hw(struct clk *clk)
        return (struct clk_hw *)clk;
 }
 #endif
+
+struct clk *clk_hw_get_clk(struct clk_hw *hw, const char *con_id);
+struct clk *devm_clk_hw_get_clk(struct device *dev, struct clk_hw *hw,
+                               const char *con_id);
+
 unsigned int clk_hw_get_num_parents(const struct clk_hw *hw);
 struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw);
 struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw,
index 7fd6a1febcf4f400dd0aaa5b7f128c3a36035793..31ff1bf1b79f5a8a120f2c2c91f2de96f627d61a 100644 (file)
@@ -109,6 +109,17 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb);
  */
 int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb);
 
+/**
+ * devm_clk_notifier_register - register a managed rate-change notifier callback
+ * @dev: device for clock "consumer"
+ * @clk: clock whose rate we are interested in
+ * @nb: notifier block with callback function pointer
+ *
+ * Returns 0 on success, -EERROR otherwise
+ */
+int devm_clk_notifier_register(struct device *dev, struct clk *clk,
+                              struct notifier_block *nb);
+
 /**
  * clk_get_accuracy - obtain the clock accuracy in ppb (parts per billion)
  *                   for a clock source.
@@ -150,7 +161,7 @@ int clk_get_phase(struct clk *clk);
 int clk_set_duty_cycle(struct clk *clk, unsigned int num, unsigned int den);
 
 /**
- * clk_get_duty_cycle - return the duty cycle ratio of a clock signal
+ * clk_get_scaled_duty_cycle - return the duty cycle ratio of a clock signal
  * @clk: clock signal source
  * @scale: scaling factor to be applied to represent the ratio as an integer
  *
@@ -186,6 +197,13 @@ static inline int clk_notifier_unregister(struct clk *clk,
        return -ENOTSUPP;
 }
 
+static inline int devm_clk_notifier_register(struct device *dev,
+                                            struct clk *clk,
+                                            struct notifier_block *nb)
+{
+       return -ENOTSUPP;
+}
+
 static inline long clk_get_accuracy(struct clk *clk)
 {
        return -ENOTSUPP;
index 79097e365f7f21f68e472de4eabb380bb3dace21..38b7740017123ca3f08f6b6d556fa42f312cc1dd 100644 (file)
@@ -10,7 +10,7 @@
 
 struct device_node;
 
-#ifdef CONFIG_ARCH_S3C64XX
+#ifdef CONFIG_S3C64XX_COMMON_CLK
 void s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
                      unsigned long xusbxti_f, bool s3c6400,
                      void __iomem *base);
@@ -19,7 +19,7 @@ static inline void s3c64xx_clk_init(struct device_node *np,
                                    unsigned long xtal_f,
                                    unsigned long xusbxti_f,
                                    bool s3c6400, void __iomem *base) { }
-#endif /* CONFIG_ARCH_S3C64XX */
+#endif /* CONFIG_S3C64XX_COMMON_CLK */
 
 #ifdef CONFIG_S3C2410_COMMON_CLK
 void s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,