Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 9 May 2019 21:50:09 +0000 (14:50 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 9 May 2019 21:50:09 +0000 (14:50 -0700)
Pull clk framework updates from Stephen Boyd:
 "We have a couple new features and changes in the core clk framework
  this time around because we've finally gotten around to fixing some
  long standing issues. There's still work to do though, so this pull
  request is largely laying down the foundation for all the driver
  changes to come in the next merge window.

  The first problem we're alleviating is how parents of clks are
  specified. With the new method, we should see lots of drivers migrate
  away from the current design of string comparisons on the entire clk
  tree to a more direct method where they can use clk_hw pointers or
  more localized names specified in DT or via clkdev. This should reduce
  our reliance on string comparisons for all the topology description
  logic that we've been using for years and hopefully speed some things
  up while avoiding problems we have with generating clk names.

  Beyond that we also got rid of the CLK_IS_BASIC flag because it wasn't
  really helping anyone and we introduced big-endian versions of the
  basic clk types so that we can get rid of clk_{readl,writel}(). Both
  of these are things that driver developers have tried to use over the
  years that I typically bat away during code reviews because they're
  not useful. It's great to see these two things go away so maintainers
  can save time not worrying about these things.

  On the driver side we got the usual collection of new SoC support and
  non-critical fixes and updates to existing code. The big topics that
  stand out are the new driver support for Mediatek MT8183 and MT8516
  SoCs, Amlogic Meson8b and G12a SoCs, and the SiFive FU540 SoC. The
  other patches in the driver pile are mostly fixes for things that are
  being used for the first time or additions for clks that couldn't be
  tested before because there wasn't a consumer driver that exercised
  them. Details are below and also in the sub-maintainer tags.

  Core:
   - Remove clk_readl() and introduce BE versions of basic clk types
   - Rewrite how clk parents can be specified to allow DT/clkdev lookups
   - Removal of the CLK_IS_BASIC clk flag
   - Framework documentation updates and fixes

  New Drivers:
   - Support for STM32F769
   - AT91 sam9x60 PMC support
   - SiFive FU540 PRCI and PLL support
   - Qualcomm QCS404 CDSP clk support
   - Qualcomm QCS404 Turing clk support
   - Mediatek MT8183 clock support
   - Mediatek MT8516 clock support
   - Milbeaut M10V clk controller support
   - Support for Cirrus Logic Lochnagar clks

  Updates:
   - Rework AT91 sckc DT bindings
   - Fix slow RC oscillator issue on sama5d3
   - Mark UFS clk as critical on Hi-Silicon hi3660 SoCs
   - Various static analysis fixes/finds and const markings
   - Video Engine (ECLK) support on Aspeed SoCs
   - Xilinx ZynqMP Versal platform support
   - Convert Xilinx ZynqMP driver to be struct oriented
   - Fixes for Rockchip rk3328 and rk3288 SoCs
   - Sub-type for Rockchip SoCs where mux and divider aren't a single register
   - Remove SNVS clock from i.MX7UPL clock driver and bindings
   - Improve i.MX5 clock driver for i.MX50 support
   - Addition of ADC clock definition for Exynos 5410 SoC (Odroid XU)
   - Export a new clock for the MBUS controller on the A13
   - Allwinner H6 fixes to support a finer clocking of the video and VPU engines
   - Add g12a support in the Amlogic axg audio clock controller
   - Add missing PCI USB clock on Rensas RZ/N1
   - Add Z2 (Cortex-A53) clocks on Rensas R-Car E3 and RZ/G2E
   - A new helper DIV64_U64_ROUND_CLOSEST() in <linux/math64.h>
   - VPU and Video Decoder clocks on Amlogic Meson8b
   - Finally remove the wrong ABP Meson8b clock id
   - Add Video Decoder, PCIe PLL, and CPU Clocks on Amlogic G12A
   - Re-expose SAR_ADC_SEL and CTS_OSCIN on Amlogic G12A AO clock controller
   - Un-expose some Amlogic AXG-Audio input clocks IDs"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (172 commits)
  clk: Cache core in clk_fetch_parent_index() without names
  clk: imx: correct pfdv2 gate_bit/vld_bit operations
  clk: sifive: add a driver for the SiFive FU540 PRCI IP block
  clk: analogbits: add Wide-Range PLL library
  clk: imx: clk-pllv3: mark expected switch fall-throughs
  clk: imx8mq: Add dsi_ipg_div
  clk: imx: pllv4: add fractional-N pll support
  clk: sunxi-ng: Use the correct style for SPDX License Identifier
  clk: sprd: Use the correct style for SPDX License Identifier
  clk: renesas: Use the correct style for SPDX License Identifier
  clk: qcom: Use the correct style for SPDX License Identifier
  clk: davinci: Use the correct style for SPDX License Identifier
  clk: actions: Use the correct style for SPDX License Identifier
  clk: imx: keep uart clock on during system boot
  clk: imx: correct i.MX7D AV PLL num/denom offset
  dt-bindings: clk: add documentation for the SiFive PRCI driver
  clk: stm32mp1: Add ddrperfm clock
  clk: Remove CLK_IS_BASIC clk flag
  clock: milbeaut: Add Milbeaut M10V clock controller
  dt-bindings: clock: milbeaut: add Milbeaut clock description
  ...

214 files changed:
Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,ipu.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/mediatek/mediatek,mcucfg.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt
Documentation/devicetree/bindings/clock/amlogic,axg-audio-clkc.txt
Documentation/devicetree/bindings/clock/at91-clock.txt
Documentation/devicetree/bindings/clock/cirrus,lochnagar.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/milbeaut-clock.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/clock/qcom,turingcc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/qoriq-clock.txt
Documentation/devicetree/bindings/clock/sifive/fu540-prci.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
MAINTAINERS
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/omap_hwmod.c
arch/mips/alchemy/common/clock.c
arch/powerpc/platforms/512x/clock-commonclk.c
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/actions/owl-common.h
drivers/clk/actions/owl-composite.h
drivers/clk/actions/owl-divider.h
drivers/clk/actions/owl-factor.h
drivers/clk/actions/owl-fixed-factor.h
drivers/clk/actions/owl-gate.h
drivers/clk/actions/owl-mux.h
drivers/clk/actions/owl-pll.h
drivers/clk/actions/owl-reset.h
drivers/clk/analogbits/Kconfig [new file with mode: 0644]
drivers/clk/analogbits/Makefile [new file with mode: 0644]
drivers/clk/analogbits/wrpll-cln28hpc.c [new file with mode: 0644]
drivers/clk/at91/Makefile
drivers/clk/at91/at91sam9260.c
drivers/clk/at91/at91sam9rl.c
drivers/clk/at91/at91sam9x5.c
drivers/clk/at91/clk-generated.c
drivers/clk/at91/clk-master.c
drivers/clk/at91/clk-peripheral.c
drivers/clk/at91/clk-sam9x60-pll.c [new file with mode: 0644]
drivers/clk/at91/clk-usb.c
drivers/clk/at91/dt-compat.c
drivers/clk/at91/pmc.h
drivers/clk/at91/sam9x60.c [new file with mode: 0644]
drivers/clk/at91/sama5d2.c
drivers/clk/at91/sama5d4.c
drivers/clk/at91/sckc.c
drivers/clk/clk-aspeed.c
drivers/clk/clk-composite.c
drivers/clk/clk-divider.c
drivers/clk/clk-fixed-factor.c
drivers/clk/clk-fixed-rate.c
drivers/clk/clk-fractional-divider.c
drivers/clk/clk-gate.c
drivers/clk/clk-gpio.c
drivers/clk/clk-highbank.c
drivers/clk/clk-lochnagar.c [new file with mode: 0644]
drivers/clk/clk-milbeaut.c [new file with mode: 0644]
drivers/clk/clk-multiplier.c
drivers/clk/clk-mux.c
drivers/clk/clk-pwm.c
drivers/clk/clk-qoriq.c
drivers/clk/clk-stm32f4.c
drivers/clk/clk-stm32mp1.c
drivers/clk/clk-xgene.c
drivers/clk/clk.c
drivers/clk/clk.h
drivers/clk/clkdev.c
drivers/clk/davinci/da8xx-cfgchip.c
drivers/clk/davinci/pll.h
drivers/clk/davinci/psc.h
drivers/clk/hisilicon/clk-hi3660.c
drivers/clk/hisilicon/clk-hisi-phase.c
drivers/clk/imx/Makefile
drivers/clk/imx/clk-divider-gate.c
drivers/clk/imx/clk-imx5.c [moved from drivers/clk/imx/clk-imx51-imx53.c with 94% similarity]
drivers/clk/imx/clk-imx6sll.c
drivers/clk/imx/clk-imx7d.c
drivers/clk/imx/clk-imx7ulp.c
drivers/clk/imx/clk-imx8mq.c
drivers/clk/imx/clk-pfdv2.c
drivers/clk/imx/clk-pll14xx.c
drivers/clk/imx/clk-pllv3.c
drivers/clk/imx/clk-pllv4.c
drivers/clk/imx/clk-sccg-pll.c
drivers/clk/imx/clk.h
drivers/clk/ingenic/jz4725b-cgu.c
drivers/clk/mediatek/Kconfig
drivers/clk/mediatek/Makefile
drivers/clk/mediatek/clk-gate.h
drivers/clk/mediatek/clk-mt8183-audio.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt8183-cam.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt8183-img.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt8183-ipu0.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt8183-ipu1.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt8183-ipu_adl.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt8183-ipu_conn.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt8183-mfgcfg.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt8183-mm.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt8183-vdec.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt8183-venc.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt8183.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt8516.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mtk.h
drivers/clk/mediatek/clk-mux.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mux.h [new file with mode: 0644]
drivers/clk/mediatek/clk-pll.c
drivers/clk/meson/axg-audio.c
drivers/clk/meson/axg-audio.h
drivers/clk/meson/clk-pll.c
drivers/clk/meson/clk-pll.h
drivers/clk/meson/g12a-aoclk.h
drivers/clk/meson/g12a.c
drivers/clk/meson/g12a.h
drivers/clk/meson/meson8b.c
drivers/clk/meson/meson8b.h
drivers/clk/mmp/clk-gate.c
drivers/clk/mvebu/common.c
drivers/clk/mvebu/cp110-system-controller.c
drivers/clk/nxp/clk-lpc18xx-ccu.c
drivers/clk/nxp/clk-lpc18xx-cgu.c
drivers/clk/nxp/clk-lpc32xx.c
drivers/clk/qcom/Kconfig
drivers/clk/qcom/Makefile
drivers/clk/qcom/clk-branch.c
drivers/clk/qcom/clk-branch.h
drivers/clk/qcom/clk-regmap-mux-div.h
drivers/clk/qcom/gcc-msm8998.c
drivers/clk/qcom/gcc-qcs404.c
drivers/clk/qcom/turingcc-qcs404.c [new file with mode: 0644]
drivers/clk/renesas/r7s9210-cpg-mssr.c
drivers/clk/renesas/r8a774a1-cpg-mssr.c
drivers/clk/renesas/r8a774c0-cpg-mssr.c
drivers/clk/renesas/r8a7795-cpg-mssr.c
drivers/clk/renesas/r8a7796-cpg-mssr.c
drivers/clk/renesas/r8a77965-cpg-mssr.c
drivers/clk/renesas/r8a77980-cpg-mssr.c
drivers/clk/renesas/r8a77990-cpg-mssr.c
drivers/clk/renesas/r8a77995-cpg-mssr.c
drivers/clk/renesas/r9a06g032-clocks.c
drivers/clk/renesas/rcar-gen2-cpg.h
drivers/clk/renesas/rcar-gen3-cpg.c
drivers/clk/renesas/rcar-gen3-cpg.h
drivers/clk/renesas/renesas-cpg-mssr.h
drivers/clk/rockchip/clk-ddr.c
drivers/clk/rockchip/clk-half-divider.c
drivers/clk/rockchip/clk-rk3288.c
drivers/clk/rockchip/clk-rk3328.c
drivers/clk/rockchip/clk.c
drivers/clk/rockchip/clk.h
drivers/clk/samsung/clk-exynos5410.c
drivers/clk/sifive/Kconfig [new file with mode: 0644]
drivers/clk/sifive/Makefile [new file with mode: 0644]
drivers/clk/sifive/fu540-prci.c [new file with mode: 0644]
drivers/clk/sprd/common.h
drivers/clk/sprd/composite.h
drivers/clk/sprd/div.h
drivers/clk/sprd/gate.h
drivers/clk/sprd/mux.h
drivers/clk/sprd/pll.h
drivers/clk/sunxi-ng/ccu-sun50i-a64.c
drivers/clk/sunxi-ng/ccu-sun50i-h6.c
drivers/clk/sunxi-ng/ccu-sun50i-h6.h
drivers/clk/sunxi-ng/ccu-sun5i.h
drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
drivers/clk/sunxi-ng/ccu-suniv-f1c100s.h
drivers/clk/sunxi/Kconfig [new file with mode: 0644]
drivers/clk/sunxi/Makefile
drivers/clk/tegra/clk-divider.c
drivers/clk/tegra/clk-emc.c
drivers/clk/tegra/clk-pll.c
drivers/clk/tegra/clk-super.c
drivers/clk/tegra/clk-tegra124.c
drivers/clk/tegra/clk-tegra210.c
drivers/clk/ti/clk-7xx-compat.c
drivers/clk/ti/clk-7xx.c
drivers/clk/ti/clkctrl.c
drivers/clk/ti/clock.h
drivers/clk/ux500/clk-sysctrl.c
drivers/clk/zynq/clkc.c
drivers/clk/zynq/pll.c
drivers/clk/zynqmp/clk-mux-zynqmp.c
drivers/clk/zynqmp/clk-zynqmp.h
drivers/clk/zynqmp/clkc.c
drivers/clk/zynqmp/divider.c
drivers/pwm/pwm-meson.c
include/dt-bindings/clock/axg-audio-clkc.h
include/dt-bindings/clock/exynos5410.h
include/dt-bindings/clock/g12a-aoclkc.h
include/dt-bindings/clock/g12a-clkc.h
include/dt-bindings/clock/imx7ulp-clock.h
include/dt-bindings/clock/jz4725b-cgu.h
include/dt-bindings/clock/meson8b-clkc.h
include/dt-bindings/clock/mt8183-clk.h [new file with mode: 0644]
include/dt-bindings/clock/mt8516-clk.h [new file with mode: 0644]
include/dt-bindings/clock/qcom,gcc-qcs404.h
include/dt-bindings/clock/qcom,turingcc-qcs404.h [new file with mode: 0644]
include/dt-bindings/clock/stm32fx-clock.h
include/dt-bindings/clock/sun5i-ccu.h
include/linux/clk-provider.h
include/linux/clk/analogbits-wrpll-cln28hpc.h [new file with mode: 0644]
include/linux/clk/at91_pmc.h
include/linux/clk/ti.h
include/linux/device.h
include/linux/math64.h

index de4075413d9196a85663f4ab8559ab43a4adee55..161e63a6c254d036350a9b41d1e455feaf3baf48 100644 (file)
@@ -14,6 +14,8 @@ Required Properties:
        - "mediatek,mt7629-apmixedsys"
        - "mediatek,mt8135-apmixedsys"
        - "mediatek,mt8173-apmixedsys"
+       - "mediatek,mt8183-apmixedsys", "syscon"
+       - "mediatek,mt8516-apmixedsys"
 - #clock-cells: Must be 1
 
 The apmixedsys controller uses the common clk binding from
index d1606b2c3e63b82f613516992340522d30f83632..f3cef1a6d95c7452ba534d6ab4851bbe080ab2e4 100644 (file)
@@ -9,6 +9,7 @@ Required Properties:
        - "mediatek,mt2701-audsys", "syscon"
        - "mediatek,mt7622-audsys", "syscon"
        - "mediatek,mt7623-audsys", "mediatek,mt2701-audsys", "syscon"
+       - "mediatek,mt8183-audiosys", "syscon"
 - #clock-cells: Must be 1
 
 The AUDSYS controller uses the common clk binding from
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,camsys.txt
new file mode 100644 (file)
index 0000000..d8930f6
--- /dev/null
@@ -0,0 +1,22 @@
+MediaTek CAMSYS controller
+============================
+
+The MediaTek camsys controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be one of:
+       - "mediatek,mt8183-camsys", "syscon"
+- #clock-cells: Must be 1
+
+The camsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+camsys: camsys@1a000000  {
+       compatible = "mediatek,mt8183-camsys", "syscon";
+       reg = <0 0x1a000000  0 0x1000>;
+       #clock-cells = <1>;
+};
index 3f99672163e37dac2e556d3c9f02534fa0ee01cc..e3bc4a1e7a6e46b419b3aa68e989c3d104813a17 100644 (file)
@@ -11,6 +11,7 @@ Required Properties:
        - "mediatek,mt6797-imgsys", "syscon"
        - "mediatek,mt7623-imgsys", "mediatek,mt2701-imgsys", "syscon"
        - "mediatek,mt8173-imgsys", "syscon"
+       - "mediatek,mt8183-imgsys", "syscon"
 - #clock-cells: Must be 1
 
 The imgsys controller uses the common clk binding from
index 417bd83d13789ff045b2f4951f6b09450b8f3178..a90913988d7ea789c576a1cae08d98d382259c98 100644 (file)
@@ -15,6 +15,8 @@ Required Properties:
        - "mediatek,mt7629-infracfg", "syscon"
        - "mediatek,mt8135-infracfg", "syscon"
        - "mediatek,mt8173-infracfg", "syscon"
+       - "mediatek,mt8183-infracfg", "syscon"
+       - "mediatek,mt8516-infracfg", "syscon"
 - #clock-cells: Must be 1
 - #reset-cells: Must be 1
 
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ipu.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ipu.txt
new file mode 100644 (file)
index 0000000..aabc8c5
--- /dev/null
@@ -0,0 +1,43 @@
+Mediatek IPU controller
+============================
+
+The Mediatek ipu controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be one of:
+       - "mediatek,mt8183-ipu_conn", "syscon"
+       - "mediatek,mt8183-ipu_adl", "syscon"
+       - "mediatek,mt8183-ipu_core0", "syscon"
+       - "mediatek,mt8183-ipu_core1", "syscon"
+- #clock-cells: Must be 1
+
+The ipu controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+ipu_conn: syscon@19000000 {
+       compatible = "mediatek,mt8183-ipu_conn", "syscon";
+       reg = <0 0x19000000 0 0x1000>;
+       #clock-cells = <1>;
+};
+
+ipu_adl: syscon@19010000 {
+       compatible = "mediatek,mt8183-ipu_adl", "syscon";
+       reg = <0 0x19010000 0 0x1000>;
+       #clock-cells = <1>;
+};
+
+ipu_core0: syscon@19180000 {
+       compatible = "mediatek,mt8183-ipu_core0", "syscon";
+       reg = <0 0x19180000 0 0x1000>;
+       #clock-cells = <1>;
+};
+
+ipu_core1: syscon@19280000 {
+       compatible = "mediatek,mt8183-ipu_core1", "syscon";
+       reg = <0 0x19280000 0 0x1000>;
+       #clock-cells = <1>;
+};
index b8fb03f3613e39123a1b94270850c4b481b7d172..2b882b7ca72ed292cd234bc7a656260f89a72bc1 100644 (file)
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: Should be one of:
        - "mediatek,mt2712-mcucfg", "syscon"
+       - "mediatek,mt8183-mcucfg", "syscon"
 - #clock-cells: Must be 1
 
 The mcucfg controller uses the common clk binding from
index 859e67b416d5006ae2851b80352e32493f9c4c7b..72787e7dd2274cd620e4f70bf112d2726a87a75d 100644 (file)
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: Should be one of:
        - "mediatek,mt2712-mfgcfg", "syscon"
+       - "mediatek,mt8183-mfgcfg", "syscon"
 - #clock-cells: Must be 1
 
 The mfgcfg controller uses the common clk binding from
index 15d977afad3130e0849e3f9139ded0ccd4ddf9a7..545eab717c967459c25188f61286503be603907e 100644 (file)
@@ -11,6 +11,7 @@ Required Properties:
        - "mediatek,mt6797-mmsys", "syscon"
        - "mediatek,mt7623-mmsys", "mediatek,mt2701-mmsys", "syscon"
        - "mediatek,mt8173-mmsys", "syscon"
+       - "mediatek,mt8183-mmsys", "syscon"
 - #clock-cells: Must be 1
 
 The mmsys controller uses the common clk binding from
index d160c2b4b6fe5cec7156825fefcb86bb9ba6662e..a023b8338960f28f8ab8b55afbe53ba43ce5be94 100644 (file)
@@ -14,6 +14,8 @@ Required Properties:
        - "mediatek,mt7629-topckgen"
        - "mediatek,mt8135-topckgen"
        - "mediatek,mt8173-topckgen"
+       - "mediatek,mt8183-topckgen", "syscon"
+       - "mediatek,mt8516-topckgen"
 - #clock-cells: Must be 1
 
 The topckgen controller uses the common clk binding from
index 3212afc753c8d1f8e03c8d8c999c010bb98d4092..57176bb8dbb508087df62791c4eb3873b65242f2 100644 (file)
@@ -11,6 +11,7 @@ Required Properties:
        - "mediatek,mt6797-vdecsys", "syscon"
        - "mediatek,mt7623-vdecsys", "mediatek,mt2701-vdecsys", "syscon"
        - "mediatek,mt8173-vdecsys", "syscon"
+       - "mediatek,mt8183-vdecsys", "syscon"
 - #clock-cells: Must be 1
 
 The vdecsys controller uses the common clk binding from
index 851545357e94af7f3ec4a96ac882cded0d166d7e..c9faa626908769e54fe68c2f93f0c4ad8ccc5746 100644 (file)
@@ -9,6 +9,7 @@ Required Properties:
        - "mediatek,mt2712-vencsys", "syscon"
        - "mediatek,mt6797-vencsys", "syscon"
        - "mediatek,mt8173-vencsys", "syscon"
+       - "mediatek,mt8183-vencsys", "syscon"
 - #clock-cells: Must be 1
 
 The vencsys controller uses the common clk binding from
index 61777ad24f61c0657ce812151f910c24fa12b38a..0f777749f4f1e3b82fceed4788e48bc738adbe3f 100644 (file)
@@ -6,7 +6,8 @@ devices.
 
 Required Properties:
 
-- compatible   : should be "amlogic,axg-audio-clkc" for the A113X and A113D
+- compatible   : should be "amlogic,axg-audio-clkc" for the A113X and A113D,
+                 "amlogic,g12a-audio-clkc" for G12A.
 - reg          : physical base address of the clock controller and length of
                  memory mapped region.
 - clocks       : a list of phandle + clock-specifier pairs for the clocks listed
index e9f70fcdfe804bd6d85dffb9627e0d7eef41be7d..b520280e33ff0095287f445b4bfa83c484da5d0c 100644 (file)
@@ -8,35 +8,30 @@ Slow Clock controller:
 
 Required properties:
 - compatible : shall be one of the following:
-       "atmel,at91sam9x5-sckc" or
+       "atmel,at91sam9x5-sckc",
+       "atmel,sama5d3-sckc" or
        "atmel,sama5d4-sckc":
                at91 SCKC (Slow Clock Controller)
-               This node contains the slow clock definitions.
-
-       "atmel,at91sam9x5-clk-slow-osc":
-               at91 slow oscillator
-
-       "atmel,at91sam9x5-clk-slow-rc-osc":
-               at91 internal slow RC oscillator
-- reg : defines the IO memory reserved for the SCKC.
-- #size-cells : shall be 0 (reg is used to encode clk id).
-- #address-cells : shall be 1 (reg is used to encode clk id).
+- #clock-cells : shall be 0.
+- clocks : shall be the input parent clock phandle for the clock.
 
+Optional properties:
+- atmel,osc-bypass : boolean property. Set this when a clock signal is directly
+  provided on XIN.
 
 For example:
-       sckc: sckc@fffffe50 {
-               compatible = "atmel,sama5d3-pmc";
-               reg = <0xfffffe50 0x4>
-               #size-cells = <0>;
-               #address-cells = <1>;
-
-               /* put at91 slow clocks here */
+       sckc@fffffe50 {
+               compatible = "atmel,at91sam9x5-sckc";
+               reg = <0xfffffe50 0x4>;
+               clocks = <&slow_xtal>;
+               #clock-cells = <0>;
        };
 
 Power Management Controller (PMC):
 
 Required properties:
-- compatible : shall be "atmel,<chip>-pmc", "syscon":
+- compatible : shall be "atmel,<chip>-pmc", "syscon" or
+       "microchip,sam9x60-pmc"
        <chip> can be: at91rm9200, at91sam9260, at91sam9261,
        at91sam9263, at91sam9g45, at91sam9n12, at91sam9rl, at91sam9g15,
        at91sam9g25, at91sam9g35, at91sam9x25, at91sam9x35, at91sam9x5,
diff --git a/Documentation/devicetree/bindings/clock/cirrus,lochnagar.txt b/Documentation/devicetree/bindings/clock/cirrus,lochnagar.txt
new file mode 100644 (file)
index 0000000..b8d8ef3
--- /dev/null
@@ -0,0 +1,93 @@
+Cirrus Logic Lochnagar Audio Development Board
+
+Lochnagar is an evaluation and development board for Cirrus Logic
+Smart CODEC and Amp devices. It allows the connection of most Cirrus
+Logic devices on mini-cards, as well as allowing connection of
+various application processor systems to provide a full evaluation
+platform.  Audio system topology, clocking and power can all be
+controlled through the Lochnagar, allowing the device under test
+to be used in a variety of possible use cases.
+
+This binding document describes the binding for the clock portion of
+the driver.
+
+Also see these documents for generic binding information:
+  [1] Clock : ../clock/clock-bindings.txt
+
+And these for relevant defines:
+  [2] include/dt-bindings/clock/lochnagar.h
+
+This binding must be part of the Lochnagar MFD binding:
+  [3] ../mfd/cirrus,lochnagar.txt
+
+Required properties:
+
+  - compatible : One of the following strings:
+                 "cirrus,lochnagar1-clk"
+                 "cirrus,lochnagar2-clk"
+
+  - #clock-cells : Must be 1. The first cell indicates the clock
+    number, see [2] for available clocks and [1].
+
+Optional properties:
+
+  - clocks : Must contain an entry for each clock in clock-names.
+  - clock-names : May contain entries for each of the following
+    clocks:
+     - ln-cdc-clkout : Output clock from CODEC card.
+     - ln-dsp-clkout : Output clock from DSP card.
+     - ln-gf-mclk1,ln-gf-mclk2,ln-gf-mclk3,ln-gf-mclk4 : Optional
+       input audio clocks from host system.
+     - ln-psia1-mclk, ln-psia2-mclk : Optional input audio clocks from
+       external connector.
+     - ln-spdif-clkout : Optional input audio clock from SPDIF.
+     - ln-adat-mclk : Optional input audio clock from ADAT.
+     - ln-pmic-32k : On board fixed clock.
+     - ln-clk-12m : On board fixed clock.
+     - ln-clk-11m : On board fixed clock.
+     - ln-clk-24m : On board fixed clock.
+     - ln-clk-22m : On board fixed clock.
+     - ln-clk-8m : On board fixed clock.
+     - ln-usb-clk-24m : On board fixed clock.
+     - ln-usb-clk-12m : On board fixed clock.
+
+  - assigned-clocks : A list of Lochnagar clocks to be reparented, see
+    [2] for available clocks.
+  - assigned-clock-parents : Parents to be assigned to the clocks
+    listed in "assigned-clocks".
+
+Optional nodes:
+
+  - fixed-clock nodes may be registered for the following on board clocks:
+     - ln-pmic-32k : 32768 Hz
+     - ln-clk-12m : 12288000 Hz
+     - ln-clk-11m : 11298600 Hz
+     - ln-clk-24m : 24576000 Hz
+     - ln-clk-22m : 22579200 Hz
+     - ln-clk-8m : 8192000 Hz
+     - ln-usb-clk-24m : 24576000 Hz
+     - ln-usb-clk-12m : 12288000 Hz
+
+Example:
+
+lochnagar {
+       lochnagar-clk {
+               compatible = "cirrus,lochnagar2-clk";
+
+               #clock-cells = <1>;
+
+               clocks = <&clk-audio>, <&clk_pmic>;
+               clock-names = "ln-gf-mclk2", "ln-pmic-32k";
+
+               assigned-clocks = <&lochnagar-clk LOCHNAGAR_CDC_MCLK1>,
+                                 <&lochnagar-clk LOCHNAGAR_CDC_MCLK2>;
+               assigned-clock-parents = <&clk-audio>,
+                                        <&clk-pmic>;
+       };
+
+       clk-pmic: clk-pmic {
+               compatible = "fixed-clock";
+               clock-cells = <0>;
+               clock-frequency = <32768>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/clock/milbeaut-clock.yaml b/Documentation/devicetree/bindings/clock/milbeaut-clock.yaml
new file mode 100644 (file)
index 0000000..5cf0b81
--- /dev/null
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/bindings/clock/milbeaut-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Milbeaut SoCs Clock Controller Binding
+
+maintainers:
+  - Taichi Sugaya <sugaya.taichi@socionext.com>
+
+description: |
+  Milbeaut SoCs Clock controller is an integrated clock controller, which
+  generates and supplies to all modules.
+
+  This binding uses common clock bindings
+  [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+properties:
+  compatible:
+    oneOf:
+      - items:
+          - enum:
+              - socionext,milbeaut-m10v-ccu
+  clocks:
+    maxItems: 1
+    description: external clock
+
+  '#clock-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - '#clock-cells'
+
+examples:
+  # Clock controller node:
+  - |
+    m10v-clk-ctrl@1d021000 {
+        compatible = "socionext,milbeaut-m10v-clk-ccu";
+        reg = <0x1d021000 0x4000>;
+        #clock-cells = <1>;
+        clocks = <&clki40mhz>;
+    };
+
+  # Required an external clock for Clock controller node:
+  - |
+    clocks {
+        clki40mhz: clki40mhz {
+            compatible = "fixed-clock";
+            #clock-cells = <0>;
+            clock-frequency = <40000000>;
+        };
+        /* other clocks */
+    };
+
+  # The clock consumer shall specify the desired clock-output of the clock
+  # controller as below by specifying output-id in its "clk" phandle cell.
+  # 2: uart
+  # 4: 32-bit timer
+  # 7: UHS-I/II
+  - |
+    serial@1e700010 {
+        compatible = "socionext,milbeaut-usio-uart";
+        reg = <0x1e700010 0x10>;
+        interrupts = <0 141 0x4>, <0 149 0x4>;
+        interrupt-names = "rx", "tx";
+        clocks = <&clk 2>;
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,turingcc.txt b/Documentation/devicetree/bindings/clock/qcom,turingcc.txt
new file mode 100644 (file)
index 0000000..126517d
--- /dev/null
@@ -0,0 +1,19 @@
+Qualcomm Turing Clock & Reset Controller Binding
+------------------------------------------------
+
+Required properties :
+- compatible: shall contain "qcom,qcs404-turingcc".
+- reg: shall contain base register location and length.
+- clocks: ahb clock for the TuringCC
+- #clock-cells: from common clock binding, shall contain 1.
+- #reset-cells: from common reset binding, shall contain 1.
+
+Example:
+       turingcc: clock-controller@800000 {
+               compatible = "qcom,qcs404-turingcc";
+               reg = <0x00800000 0x30000>;
+               clocks = <&gcc GCC_CDSP_CFG_AHB_CLK>;
+
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+       };
index c655f28d59187f7947ca17d91a8e470e6505ea91..f7d48f23da444796eb5766129fcc8b4cb3ffb7a0 100644 (file)
@@ -39,6 +39,7 @@ Required properties:
        * "fsl,b4860-clockgen"
        * "fsl,ls1012a-clockgen"
        * "fsl,ls1021a-clockgen"
+       * "fsl,ls1028a-clockgen"
        * "fsl,ls1043a-clockgen"
        * "fsl,ls1046a-clockgen"
        * "fsl,ls1088a-clockgen"
@@ -83,8 +84,8 @@ second cell is the clock index for the specified type.
        1       cmux            index (n in CLKCnCSR)
        2       hwaccel         index (n in CLKCGnHWACSR)
        3       fman            0 for fm1, 1 for fm2
-       4       platform pll    0=pll, 1=pll/2, 2=pll/3, 3=pll/4
-                               4=pll/5, 5=pll/6, 6=pll/7, 7=pll/8
+       4       platform pll    n=pll/(n+1). For example, when n=1,
+                               that means output_freq=PLL_freq/2.
        5       coreclk         must be 0
 
 3. Example
diff --git a/Documentation/devicetree/bindings/clock/sifive/fu540-prci.txt b/Documentation/devicetree/bindings/clock/sifive/fu540-prci.txt
new file mode 100644 (file)
index 0000000..349808f
--- /dev/null
@@ -0,0 +1,46 @@
+SiFive FU540 PRCI bindings
+
+On the FU540 family of SoCs, most system-wide clock and reset integration
+is via the PRCI IP block.
+
+Required properties:
+- compatible: Should be "sifive,<chip>-prci".  Only one value is
+       supported: "sifive,fu540-c000-prci"
+- reg: Should describe the PRCI's register target physical address region
+- clocks: Should point to the hfclk device tree node and the rtcclk
+          device tree node.  The RTC clock here is not a time-of-day clock,
+         but is instead a high-stability clock source for system timers
+         and cycle counters.
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock via the clock ID
+macros defined in include/dt-bindings/clock/sifive-fu540-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.
+
+Examples:
+
+/* under /, in PCB-specific DT data */
+hfclk: hfclk {
+       #clock-cells = <0>;
+       compatible = "fixed-clock";
+       clock-frequency = <33333333>;
+       clock-output-names = "hfclk";
+};
+rtcclk: rtcclk {
+       #clock-cells = <0>;
+       compatible = "fixed-clock";
+       clock-frequency = <1000000>;
+       clock-output-names = "rtcclk";
+};
+
+/* under /soc, in SoC-specific DT data */
+prci: clock-controller@10000000 {
+       compatible = "sifive,fu540-c000-prci";
+       reg = <0x0 0x10000000 0x0 0x1000>;
+       clocks = <&hfclk>, <&rtcclk>;
+       #clock-cells = <1>;
+};
index b240121d2ac940e4eef678b3769f1262a1d3cb1d..cfa04b614d8aadff693e6566dbf2d475b0818c75 100644 (file)
@@ -11,6 +11,8 @@ Required properties:
   "st,stm32f42xx-rcc"
   "st,stm32f469-rcc"
   "st,stm32f746-rcc"
+  "st,stm32f769-rcc"
+
 - reg: should be register base and length as documented in the
   datasheet
 - #reset-cells: 1, see below
@@ -102,6 +104,10 @@ The secondary index is bound with the following magic numbers:
        28      CLK_I2C3
        29      CLK_I2C4
        30      CLK_LPTIMER     (LPTimer1 clock)
+       31      CLK_PLL_SRC
+       32      CLK_DFSDM1
+       33      CLK_ADFSDM1
+       34      CLK_F769_DSI
 )
 
 Example:
index a3143515e134502b1c7972d31d40498a00c1a45b..960070e36bd9d0ed1bec79a63644d1b9c0e432f0 100644 (file)
@@ -979,6 +979,12 @@ F: drivers/iio/adc/ltc2497*
 X:     drivers/iio/*/adjd*
 F:     drivers/staging/iio/*/ad*
 
+ANALOGBITS PLL LIBRARIES
+M:     Paul Walmsley <paul.walmsley@sifive.com>
+S:     Supported
+F:     drivers/clk/analogbits/*
+F:     include/linux/clk/analogbits*
+
 ANDES ARCHITECTURE
 M:     Greentime Hu <green.hu@gmail.com>
 M:     Vincent Chen <deanbo422@gmail.com>
index 42881f21cede1659fbe3518ad0da1df2d42f96d9..3e0f09cc00289035032da0418dd7665a6a0481ca 100644 (file)
@@ -119,6 +119,9 @@ void __init ti_clk_init_features(void)
        if (cpu_is_omap343x())
                features.flags |= TI_CLK_DPLL_HAS_FREQSEL;
 
+       if (omap_type() == OMAP2_DEVICE_TYPE_GP)
+               features.flags |= TI_CLK_DEVICE_TYPE_GP;
+
        /* Idlest value for interface clocks.
         * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
         * 34xx reverses this, just to keep us on our toes
index 3a04c73ac03c372c6b2dff678ed90bdb369aaa62..baadddf9aad49eb44d9d0974e6b6e11c28fd661c 100644 (file)
@@ -648,10 +648,10 @@ static struct clockdomain *_get_clkdm(struct omap_hwmod *oh)
        if (oh->clkdm) {
                return oh->clkdm;
        } else if (oh->_clk) {
-               if (__clk_get_flags(oh->_clk) & CLK_IS_BASIC)
+               if (!omap2_clk_is_hw_omap(__clk_get_hw(oh->_clk)))
                        return NULL;
                clk = to_clk_hw_omap(__clk_get_hw(oh->_clk));
-               return  clk->clkdm;
+               return clk->clkdm;
        }
        return NULL;
 }
index d129475fd40dee71e759d4679c3b9eac48c24e91..a95a894aceaf1237852d5b18bb61a145099bc20f 100644 (file)
@@ -160,7 +160,7 @@ static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name,
        id.name = ALCHEMY_CPU_CLK;
        id.parent_names = &parent_name;
        id.num_parents = 1;
-       id.flags = CLK_IS_BASIC;
+       id.flags = 0;
        id.ops = &alchemy_clkops_cpu;
        h->init = &id;
 
index b3097fe6441b9571095a696b7ee357c995b88dbb..af265ae40a6125f9445b706e09dc4089e5d7d42f 100644 (file)
@@ -239,6 +239,7 @@ static inline struct clk *mpc512x_clk_divider(
        const char *name, const char *parent_name, u8 clkflags,
        u32 __iomem *reg, u8 pos, u8 len, int divflags)
 {
+       divflags |= CLK_DIVIDER_BIG_ENDIAN;
        return clk_register_divider(NULL, name, parent_name, clkflags,
                                    reg, pos, len, divflags, &clklock);
 }
@@ -250,7 +251,7 @@ static inline struct clk *mpc512x_clk_divtable(
 {
        u8 divflags;
 
-       divflags = 0;
+       divflags = CLK_DIVIDER_BIG_ENDIAN;
        return clk_register_divider_table(NULL, name, parent_name, 0,
                                          reg, pos, len, divflags,
                                          divtab, &clklock);
@@ -261,10 +262,12 @@ static inline struct clk *mpc512x_clk_gated(
        u32 __iomem *reg, u8 pos)
 {
        int clkflags;
+       u8 gateflags;
 
        clkflags = CLK_SET_RATE_PARENT;
+       gateflags = CLK_GATE_BIG_ENDIAN;
        return clk_register_gate(NULL, name, parent_name, clkflags,
-                                reg, pos, 0, &clklock);
+                                reg, pos, gateflags, &clklock);
 }
 
 static inline struct clk *mpc512x_clk_muxed(const char *name,
@@ -275,7 +278,7 @@ static inline struct clk *mpc512x_clk_muxed(const char *name,
        u8 muxflags;
 
        clkflags = CLK_SET_RATE_PARENT;
-       muxflags = 0;
+       muxflags = CLK_MUX_BIG_ENDIAN;
        return clk_register_mux(NULL, name,
                                parent_names, parent_count, clkflags,
                                reg, pos, len, muxflags, &clklock);
index e705aab9e38ba8f6b82fc74ba74bbee5e3ec9843..fc1e0cf44995d55284f11e2d9430b37ffc6f3df3 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 
 config CLKDEV_LOOKUP
        bool
@@ -219,6 +220,13 @@ config COMMON_CLK_XGENE
        ---help---
          Sypport for the APM X-Gene SoC reference, PLL, and device clocks.
 
+config COMMON_CLK_LOCHNAGAR
+       tristate "Cirrus Logic Lochnagar clock driver"
+       depends on MFD_LOCHNAGAR
+       help
+         This driver supports the clocking features of the Cirrus Logic
+         Lochnagar audio development board.
+
 config COMMON_CLK_NXP
        def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
        select REGMAP_MMIO if ARCH_LPC32XX
@@ -297,6 +305,7 @@ config COMMON_CLK_FIXED_MMIO
          Support for Memory Mapped IO Fixed clocks
 
 source "drivers/clk/actions/Kconfig"
+source "drivers/clk/analogbits/Kconfig"
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
 source "drivers/clk/imgtec/Kconfig"
@@ -309,7 +318,9 @@ source "drivers/clk/mvebu/Kconfig"
 source "drivers/clk/qcom/Kconfig"
 source "drivers/clk/renesas/Kconfig"
 source "drivers/clk/samsung/Kconfig"
+source "drivers/clk/sifive/Kconfig"
 source "drivers/clk/sprd/Kconfig"
+source "drivers/clk/sunxi/Kconfig"
 source "drivers/clk/sunxi-ng/Kconfig"
 source "drivers/clk/tegra/Kconfig"
 source "drivers/clk/ti/Kconfig"
index 1db133652f0c3889a5f4d716ac32a32d403afd72..9ef4305d55e0f6bf87b2123c12958b74dc0db10f 100644 (file)
@@ -32,8 +32,10 @@ obj-$(CONFIG_COMMON_CLK_GEMINI)              += clk-gemini.o
 obj-$(CONFIG_COMMON_CLK_ASPEED)                += clk-aspeed.o
 obj-$(CONFIG_ARCH_HIGHBANK)            += clk-highbank.o
 obj-$(CONFIG_CLK_HSDK)                 += clk-hsdk-pll.o
+obj-$(CONFIG_COMMON_CLK_LOCHNAGAR)     += clk-lochnagar.o
 obj-$(CONFIG_COMMON_CLK_MAX77686)      += clk-max77686.o
 obj-$(CONFIG_COMMON_CLK_MAX9485)       += clk-max9485.o
+obj-$(CONFIG_ARCH_MILBEAUT_M10V)       += clk-milbeaut.o
 obj-$(CONFIG_ARCH_MOXART)              += clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)             += clk-nomadik.o
 obj-$(CONFIG_ARCH_NPCM7XX)             += clk-npcm7xx.o
@@ -64,6 +66,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE)                += clk-xgene.o
 
 # please keep this section sorted lexicographically by directory path name
 obj-y                                  += actions/
+obj-y                                  += analogbits/
 obj-$(CONFIG_COMMON_CLK_AT91)          += at91/
 obj-$(CONFIG_ARCH_ARTPEC)              += axis/
 obj-$(CONFIG_ARC_PLAT_AXS10X)          += axs10x/
@@ -93,6 +96,7 @@ obj-$(CONFIG_COMMON_CLK_QCOM)         += qcom/
 obj-y                                  += renesas/
 obj-$(CONFIG_ARCH_ROCKCHIP)            += rockchip/
 obj-$(CONFIG_COMMON_CLK_SAMSUNG)       += samsung/
+obj-$(CONFIG_CLK_SIFIVE)               += sifive/
 obj-$(CONFIG_ARCH_SIRF)                        += sirf/
 obj-$(CONFIG_ARCH_SOCFPGA)             += socfpga/
 obj-$(CONFIG_PLAT_SPEAR)               += spear/
index 5a866a8b913dbca3b6f07389ecb540fa039ecdfc..c000a431471ef1e9e973aa19e3f001814af0b7aa 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 //
 // OWL common clock driver
 //
index b410ed5bf308fa583e71fb0dc25e6f149715bae4..bca38bf8f218c73785e06c467d0a3c39d9172873 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 //
 // OWL composite clock driver
 //
index 92d3e3d23967c7468b838fbfb86cd6ef9bb2ceee..083be6d80954d78fbbb39fce8aceab28f1e31a5d 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 //
 // OWL divider clock driver
 //
index f1a7ffe896e118b925b3b2c08335f883fc38e7c0..04b89cbfdccbb0ded9ceb5abc4df9607e3613c0a 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 //
 // OWL factor clock driver
 //
index cc9fe36c0964fe265baa2315467237aca48a70dd..3dfd7fd7d292a456c45bae87d8e7d179f35ea044 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 //
 // OWL fixed factor clock driver
 //
index c2d61ceebce2adac51804db60caf6b37bcbd53ed..c2f161c93fda5acc7b9641a88f45086c18252ba0 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 //
 // OWL gate clock driver
 //
index 834284c8c3ae56154cfd2e340d73604577e95189..53b9ab665294ca873b8b0288f2a2c1814210802a 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 //
 // OWL mux clock driver
 //
index 6fb0d45bb0882b2ae06a1095939cca49ea08cbb0..78e5fc360b03b59cf86e34dc6704f762548094d3 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 //
 // OWL pll clock driver
 //
index 10f5774979a6f1054cef041671b5029496d1382d..a947ffcb5a0269f92f66ff5acc19697d0a3c67f9 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 //
 // Actions Semi Owl SoCs Reset Management Unit driver
 //
diff --git a/drivers/clk/analogbits/Kconfig b/drivers/clk/analogbits/Kconfig
new file mode 100644 (file)
index 0000000..b5fd60c
--- /dev/null
@@ -0,0 +1,2 @@
+config CLK_ANALOGBITS_WRPLL_CLN28HPC
+       bool
diff --git a/drivers/clk/analogbits/Makefile b/drivers/clk/analogbits/Makefile
new file mode 100644 (file)
index 0000000..bf01744
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_CLK_ANALOGBITS_WRPLL_CLN28HPC)    += wrpll-cln28hpc.o
diff --git a/drivers/clk/analogbits/wrpll-cln28hpc.c b/drivers/clk/analogbits/wrpll-cln28hpc.c
new file mode 100644 (file)
index 0000000..776ead3
--- /dev/null
@@ -0,0 +1,364 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018-2019 SiFive, Inc.
+ * Wesley Terpstra
+ * Paul Walmsley
+ *
+ * This library supports configuration parsing and reprogramming of
+ * the CLN28HPC variant of the Analog Bits Wide Range PLL.  The
+ * intention is for this library to be reusable for any device that
+ * integrates this PLL; thus the register structure and programming
+ * details are expected to be provided by a separate IP block driver.
+ *
+ * The bulk of this code is primarily useful for clock configurations
+ * that must operate at arbitrary rates, as opposed to clock configurations
+ * that are restricted by software or manufacturer guidance to a small,
+ * pre-determined set of performance points.
+ *
+ * References:
+ * - Analog Bits "Wide Range PLL Datasheet", version 2015.10.01
+ * - SiFive FU540-C000 Manual v1p0, Chapter 7 "Clocking and Reset"
+ *   https://static.dev.sifive.com/FU540-C000-v1.0.pdf
+ */
+
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/log2.h>
+#include <linux/math64.h>
+#include <linux/clk/analogbits-wrpll-cln28hpc.h>
+
+/* MIN_INPUT_FREQ: minimum input clock frequency, in Hz (Fref_min) */
+#define MIN_INPUT_FREQ                 7000000
+
+/* MAX_INPUT_FREQ: maximum input clock frequency, in Hz (Fref_max) */
+#define MAX_INPUT_FREQ                 600000000
+
+/* MIN_POST_DIVIDE_REF_FREQ: minimum post-divider reference frequency, in Hz */
+#define MIN_POST_DIVR_FREQ             7000000
+
+/* MAX_POST_DIVIDE_REF_FREQ: maximum post-divider reference frequency, in Hz */
+#define MAX_POST_DIVR_FREQ             200000000
+
+/* MIN_VCO_FREQ: minimum VCO frequency, in Hz (Fvco_min) */
+#define MIN_VCO_FREQ                   2400000000UL
+
+/* MAX_VCO_FREQ: maximum VCO frequency, in Hz (Fvco_max) */
+#define MAX_VCO_FREQ                   4800000000ULL
+
+/* MAX_DIVQ_DIVISOR: maximum output divisor.  Selected by DIVQ = 6 */
+#define MAX_DIVQ_DIVISOR               64
+
+/* MAX_DIVR_DIVISOR: maximum reference divisor.  Selected by DIVR = 63 */
+#define MAX_DIVR_DIVISOR               64
+
+/* MAX_LOCK_US: maximum PLL lock time, in microseconds (tLOCK_max) */
+#define MAX_LOCK_US                    70
+
+/*
+ * ROUND_SHIFT: number of bits to shift to avoid precision loss in the rounding
+ *              algorithm
+ */
+#define ROUND_SHIFT                    20
+
+/*
+ * Private functions
+ */
+
+/**
+ * __wrpll_calc_filter_range() - determine PLL loop filter bandwidth
+ * @post_divr_freq: input clock rate after the R divider
+ *
+ * Select the value to be presented to the PLL RANGE input signals, based
+ * on the input clock frequency after the post-R-divider @post_divr_freq.
+ * This code follows the recommendations in the PLL datasheet for filter
+ * range selection.
+ *
+ * Return: The RANGE value to be presented to the PLL configuration inputs,
+ *         or a negative return code upon error.
+ */
+static int __wrpll_calc_filter_range(unsigned long post_divr_freq)
+{
+       if (post_divr_freq < MIN_POST_DIVR_FREQ ||
+           post_divr_freq > MAX_POST_DIVR_FREQ) {
+               WARN(1, "%s: post-divider reference freq out of range: %lu",
+                    __func__, post_divr_freq);
+               return -ERANGE;
+       }
+
+       switch (post_divr_freq) {
+       case 0 ... 10999999:
+               return 1;
+       case 11000000 ... 17999999:
+               return 2;
+       case 18000000 ... 29999999:
+               return 3;
+       case 30000000 ... 49999999:
+               return 4;
+       case 50000000 ... 79999999:
+               return 5;
+       case 80000000 ... 129999999:
+               return 6;
+       }
+
+       return 7;
+}
+
+/**
+ * __wrpll_calc_fbdiv() - return feedback fixed divide value
+ * @c: ptr to a struct wrpll_cfg record to read from
+ *
+ * The internal feedback path includes a fixed by-two divider; the
+ * external feedback path does not.  Return the appropriate divider
+ * value (2 or 1) depending on whether internal or external feedback
+ * is enabled.  This code doesn't test for invalid configurations
+ * (e.g. both or neither of WRPLL_FLAGS_*_FEEDBACK are set); it relies
+ * on the caller to do so.
+ *
+ * Context: Any context.  Caller must protect the memory pointed to by
+ *          @c from simultaneous modification.
+ *
+ * Return: 2 if internal feedback is enabled or 1 if external feedback
+ *         is enabled.
+ */
+static u8 __wrpll_calc_fbdiv(const struct wrpll_cfg *c)
+{
+       return (c->flags & WRPLL_FLAGS_INT_FEEDBACK_MASK) ? 2 : 1;
+}
+
+/**
+ * __wrpll_calc_divq() - determine DIVQ based on target PLL output clock rate
+ * @target_rate: target PLL output clock rate
+ * @vco_rate: pointer to a u64 to store the computed VCO rate into
+ *
+ * Determine a reasonable value for the PLL Q post-divider, based on the
+ * target output rate @target_rate for the PLL.  Along with returning the
+ * computed Q divider value as the return value, this function stores the
+ * desired target VCO rate into the variable pointed to by @vco_rate.
+ *
+ * Context: Any context.  Caller must protect the memory pointed to by
+ *          @vco_rate from simultaneous access or modification.
+ *
+ * Return: a positive integer DIVQ value to be programmed into the hardware
+ *         upon success, or 0 upon error (since 0 is an invalid DIVQ value)
+ */
+static u8 __wrpll_calc_divq(u32 target_rate, u64 *vco_rate)
+{
+       u64 s;
+       u8 divq = 0;
+
+       if (!vco_rate) {
+               WARN_ON(1);
+               goto wcd_out;
+       }
+
+       s = div_u64(MAX_VCO_FREQ, target_rate);
+       if (s <= 1) {
+               divq = 1;
+               *vco_rate = MAX_VCO_FREQ;
+       } else if (s > MAX_DIVQ_DIVISOR) {
+               divq = ilog2(MAX_DIVQ_DIVISOR);
+               *vco_rate = MIN_VCO_FREQ;
+       } else {
+               divq = ilog2(s);
+               *vco_rate = (u64)target_rate << divq;
+       }
+
+wcd_out:
+       return divq;
+}
+
+/**
+ * __wrpll_update_parent_rate() - update PLL data when parent rate changes
+ * @c: ptr to a struct wrpll_cfg record to write PLL data to
+ * @parent_rate: PLL input refclk rate (pre-R-divider)
+ *
+ * Pre-compute some data used by the PLL configuration algorithm when
+ * the PLL's reference clock rate changes.  The intention is to avoid
+ * computation when the parent rate remains constant - expected to be
+ * the common case.
+ *
+ * Returns: 0 upon success or -ERANGE if the reference clock rate is
+ * out of range.
+ */
+static int __wrpll_update_parent_rate(struct wrpll_cfg *c,
+                                     unsigned long parent_rate)
+{
+       u8 max_r_for_parent;
+
+       if (parent_rate > MAX_INPUT_FREQ || parent_rate < MIN_POST_DIVR_FREQ)
+               return -ERANGE;
+
+       c->parent_rate = parent_rate;
+       max_r_for_parent = div_u64(parent_rate, MIN_POST_DIVR_FREQ);
+       c->max_r = min_t(u8, MAX_DIVR_DIVISOR, max_r_for_parent);
+
+       c->init_r = DIV_ROUND_UP_ULL(parent_rate, MAX_POST_DIVR_FREQ);
+
+       return 0;
+}
+
+/**
+ * wrpll_configure() - compute PLL configuration for a target rate
+ * @c: ptr to a struct wrpll_cfg record to write into
+ * @target_rate: target PLL output clock rate (post-Q-divider)
+ * @parent_rate: PLL input refclk rate (pre-R-divider)
+ *
+ * Compute the appropriate PLL signal configuration values and store
+ * in PLL context @c.  PLL reprogramming is not glitchless, so the
+ * caller should switch any downstream logic to a different clock
+ * source or clock-gate it before presenting these values to the PLL
+ * configuration signals.
+ *
+ * The caller must pass this function a pre-initialized struct
+ * wrpll_cfg record: either initialized to zero (with the
+ * exception of the .name and .flags fields) or read from the PLL.
+ *
+ * Context: Any context.  Caller must protect the memory pointed to by @c
+ *          from simultaneous access or modification.
+ *
+ * Return: 0 upon success; anything else upon failure.
+ */
+int wrpll_configure_for_rate(struct wrpll_cfg *c, u32 target_rate,
+                            unsigned long parent_rate)
+{
+       unsigned long ratio;
+       u64 target_vco_rate, delta, best_delta, f_pre_div, vco, vco_pre;
+       u32 best_f, f, post_divr_freq;
+       u8 fbdiv, divq, best_r, r;
+       int range;
+
+       if (c->flags == 0) {
+               WARN(1, "%s called with uninitialized PLL config", __func__);
+               return -EINVAL;
+       }
+
+       /* Initialize rounding data if it hasn't been initialized already */
+       if (parent_rate != c->parent_rate) {
+               if (__wrpll_update_parent_rate(c, parent_rate)) {
+                       pr_err("%s: PLL input rate is out of range\n",
+                              __func__);
+                       return -ERANGE;
+               }
+       }
+
+       c->flags &= ~WRPLL_FLAGS_RESET_MASK;
+
+       /* Put the PLL into bypass if the user requests the parent clock rate */
+       if (target_rate == parent_rate) {
+               c->flags |= WRPLL_FLAGS_BYPASS_MASK;
+               return 0;
+       }
+
+       c->flags &= ~WRPLL_FLAGS_BYPASS_MASK;
+
+       /* Calculate the Q shift and target VCO rate */
+       divq = __wrpll_calc_divq(target_rate, &target_vco_rate);
+       if (!divq)
+               return -1;
+       c->divq = divq;
+
+       /* Precalculate the pre-Q divider target ratio */
+       ratio = div64_u64((target_vco_rate << ROUND_SHIFT), parent_rate);
+
+       fbdiv = __wrpll_calc_fbdiv(c);
+       best_r = 0;
+       best_f = 0;
+       best_delta = MAX_VCO_FREQ;
+
+       /*
+        * Consider all values for R which land within
+        * [MIN_POST_DIVR_FREQ, MAX_POST_DIVR_FREQ]; prefer smaller R
+        */
+       for (r = c->init_r; r <= c->max_r; ++r) {
+               f_pre_div = ratio * r;
+               f = (f_pre_div + (1 << ROUND_SHIFT)) >> ROUND_SHIFT;
+               f >>= (fbdiv - 1);
+
+               post_divr_freq = div_u64(parent_rate, r);
+               vco_pre = fbdiv * post_divr_freq;
+               vco = vco_pre * f;
+
+               /* Ensure rounding didn't take us out of range */
+               if (vco > target_vco_rate) {
+                       --f;
+                       vco = vco_pre * f;
+               } else if (vco < MIN_VCO_FREQ) {
+                       ++f;
+                       vco = vco_pre * f;
+               }
+
+               delta = abs(target_rate - vco);
+               if (delta < best_delta) {
+                       best_delta = delta;
+                       best_r = r;
+                       best_f = f;
+               }
+       }
+
+       c->divr = best_r - 1;
+       c->divf = best_f - 1;
+
+       post_divr_freq = div_u64(parent_rate, best_r);
+
+       /* Pick the best PLL jitter filter */
+       range = __wrpll_calc_filter_range(post_divr_freq);
+       if (range < 0)
+               return range;
+       c->range = range;
+
+       return 0;
+}
+
+/**
+ * wrpll_calc_output_rate() - calculate the PLL's target output rate
+ * @c: ptr to a struct wrpll_cfg record to read from
+ * @parent_rate: PLL refclk rate
+ *
+ * Given a pointer to the PLL's current input configuration @c and the
+ * PLL's input reference clock rate @parent_rate (before the R
+ * pre-divider), calculate the PLL's output clock rate (after the Q
+ * post-divider).
+ *
+ * Context: Any context.  Caller must protect the memory pointed to by @c
+ *          from simultaneous modification.
+ *
+ * Return: the PLL's output clock rate, in Hz.  The return value from
+ *         this function is intended to be convenient to pass directly
+ *         to the Linux clock framework; thus there is no explicit
+ *         error return value.
+ */
+unsigned long wrpll_calc_output_rate(const struct wrpll_cfg *c,
+                                    unsigned long parent_rate)
+{
+       u8 fbdiv;
+       u64 n;
+
+       if (c->flags & WRPLL_FLAGS_EXT_FEEDBACK_MASK) {
+               WARN(1, "external feedback mode not yet supported");
+               return ULONG_MAX;
+       }
+
+       fbdiv = __wrpll_calc_fbdiv(c);
+       n = parent_rate * fbdiv * (c->divf + 1);
+       n = div_u64(n, c->divr + 1);
+       n >>= c->divq;
+
+       return n;
+}
+
+/**
+ * wrpll_calc_max_lock_us() - return the time for the PLL to lock
+ * @c: ptr to a struct wrpll_cfg record to read from
+ *
+ * Return the minimum amount of time (in microseconds) that the caller
+ * must wait after reprogramming the PLL to ensure that it is locked
+ * to the input frequency and stable.  This is likely to depend on the DIVR
+ * value; this is under discussion with the manufacturer.
+ *
+ * Return: the minimum amount of time the caller must wait for the PLL
+ *         to lock (in microseconds)
+ */
+unsigned int wrpll_calc_max_lock_us(const struct wrpll_cfg *c)
+{
+       return MAX_LOCK_US;
+}
index c75df1cad60e646294a1f5e44871a8c82b2ff6e3..3732241352cea202c7ce94602638b7938074791f 100644 (file)
@@ -14,6 +14,8 @@ obj-$(CONFIG_HAVE_AT91_SMD)           += clk-smd.o
 obj-$(CONFIG_HAVE_AT91_H32MX)          += clk-h32mx.o
 obj-$(CONFIG_HAVE_AT91_GENERATED_CLK)  += clk-generated.o
 obj-$(CONFIG_HAVE_AT91_I2S_MUX_CLK)    += clk-i2s-mux.o
+obj-$(CONFIG_HAVE_AT91_SAM9X60_PLL)    += clk-sam9x60-pll.o
 obj-$(CONFIG_SOC_AT91SAM9) += at91sam9260.o at91sam9rl.o at91sam9x5.o
+obj-$(CONFIG_SOC_SAM9X60) += sam9x60.o
 obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o
 obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o
index b1af5a39542387101c5bd1931cb60f7c0e2979d4..0aabe49aed09449b153de865adc739dc8e22eacf 100644 (file)
@@ -41,7 +41,7 @@ static u8 sam9260_plla_out[] = { 0, 2 };
 
 static u16 sam9260_plla_icpll[] = { 1, 1 };
 
-static struct clk_range sam9260_plla_outputs[] = {
+static const struct clk_range sam9260_plla_outputs[] = {
        { .min = 80000000, .max = 160000000 },
        { .min = 150000000, .max = 240000000 },
 };
@@ -58,7 +58,7 @@ static u8 sam9260_pllb_out[] = { 1 };
 
 static u16 sam9260_pllb_icpll[] = { 1 };
 
-static struct clk_range sam9260_pllb_outputs[] = {
+static const struct clk_range sam9260_pllb_outputs[] = {
        { .min = 70000000, .max = 130000000 },
 };
 
@@ -128,7 +128,7 @@ static u8 sam9g20_plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
 
 static u16 sam9g20_plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
 
-static struct clk_range sam9g20_plla_outputs[] = {
+static const struct clk_range sam9g20_plla_outputs[] = {
        { .min = 745000000, .max = 800000000 },
        { .min = 695000000, .max = 750000000 },
        { .min = 645000000, .max = 700000000 },
@@ -151,7 +151,7 @@ static u8 sam9g20_pllb_out[] = { 0 };
 
 static u16 sam9g20_pllb_icpll[] = { 0 };
 
-static struct clk_range sam9g20_pllb_outputs[] = {
+static const struct clk_range sam9g20_pllb_outputs[] = {
        { .min = 30000000, .max = 100000000 },
 };
 
@@ -182,7 +182,7 @@ static const struct clk_master_characteristics sam9261_mck_characteristics = {
        .divisors = { 1, 2, 4, 0 },
 };
 
-static struct clk_range sam9261_plla_outputs[] = {
+static const struct clk_range sam9261_plla_outputs[] = {
        { .min = 80000000, .max = 200000000 },
        { .min = 190000000, .max = 240000000 },
 };
@@ -199,7 +199,7 @@ static u8 sam9261_pllb_out[] = { 1 };
 
 static u16 sam9261_pllb_icpll[] = { 1 };
 
-static struct clk_range sam9261_pllb_outputs[] = {
+static const struct clk_range sam9261_pllb_outputs[] = {
        { .min = 70000000, .max = 130000000 },
 };
 
@@ -262,7 +262,7 @@ static const struct clk_master_characteristics sam9263_mck_characteristics = {
        .divisors = { 1, 2, 4, 0 },
 };
 
-static struct clk_range sam9263_pll_outputs[] = {
+static const struct clk_range sam9263_pll_outputs[] = {
        { .min = 80000000, .max = 200000000 },
        { .min = 190000000, .max = 240000000 },
 };
index 5aeef68b4bddbb9ef7f86ee49e94af67f434bdc9..0ac34cdaa106932fb797c534dae04273d26b8aad 100644 (file)
@@ -14,7 +14,7 @@ static const struct clk_master_characteristics sam9rl_mck_characteristics = {
 
 static u8 sam9rl_plla_out[] = { 0, 2 };
 
-static struct clk_range sam9rl_plla_outputs[] = {
+static const struct clk_range sam9rl_plla_outputs[] = {
        { .min = 80000000, .max = 200000000 },
        { .min = 190000000, .max = 240000000 },
 };
index 3487e03d4bc61c277fe8f44faeececa326e21876..0855f3a80cc79ea8ea6933192964e02c0a2ef079 100644 (file)
@@ -17,7 +17,7 @@ static u8 plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
 
 static u16 plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
 
-static struct clk_range plla_outputs[] = {
+static const struct clk_range plla_outputs[] = {
        { .min = 745000000, .max = 800000000 },
        { .min = 695000000, .max = 750000000 },
        { .min = 645000000, .max = 700000000 },
@@ -49,6 +49,13 @@ static const struct {
        { .n = "pck1",  .p = "prog1",    .id = 9 },
 };
 
+static const struct clk_pcr_layout at91sam9x5_pcr_layout = {
+       .offset = 0x10c,
+       .cmd = BIT(12),
+       .pid_mask = GENMASK(5, 0),
+       .div_mask = GENMASK(17, 16),
+};
+
 struct pck {
        char *n;
        u8 id;
@@ -242,6 +249,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
 
        for (i = 0; i < ARRAY_SIZE(at91sam9x5_periphck); i++) {
                hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+                                                        &at91sam9x5_pcr_layout,
                                                         at91sam9x5_periphck[i].n,
                                                         "masterck",
                                                         at91sam9x5_periphck[i].id,
@@ -254,6 +262,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
 
        for (i = 0; extra_pcks[i].id; i++) {
                hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+                                                        &at91sam9x5_pcr_layout,
                                                         extra_pcks[i].n,
                                                         "masterck",
                                                         extra_pcks[i].id,
index 66e7f7baf9580fe6b6ac7ec837581fb3c0b60d27..5f18847965c16bcb89c858ac22958a65761382bb 100644 (file)
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/clk/at91_pmc.h>
@@ -31,6 +32,7 @@ struct clk_generated {
        spinlock_t *lock;
        u32 id;
        u32 gckdiv;
+       const struct clk_pcr_layout *layout;
        u8 parent_id;
        bool audio_pll_allowed;
 };
@@ -47,14 +49,14 @@ static int clk_generated_enable(struct clk_hw *hw)
                 __func__, gck->gckdiv, gck->parent_id);
 
        spin_lock_irqsave(gck->lock, flags);
-       regmap_write(gck->regmap, AT91_PMC_PCR,
-                    (gck->id & AT91_PMC_PCR_PID_MASK));
-       regmap_update_bits(gck->regmap, AT91_PMC_PCR,
-                          AT91_PMC_PCR_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK |
-                          AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN,
-                          AT91_PMC_PCR_GCKCSS(gck->parent_id) |
-                          AT91_PMC_PCR_CMD |
-                          AT91_PMC_PCR_GCKDIV(gck->gckdiv) |
+       regmap_write(gck->regmap, gck->layout->offset,
+                    (gck->id & gck->layout->pid_mask));
+       regmap_update_bits(gck->regmap, gck->layout->offset,
+                          AT91_PMC_PCR_GCKDIV_MASK | gck->layout->gckcss_mask |
+                          gck->layout->cmd | AT91_PMC_PCR_GCKEN,
+                          field_prep(gck->layout->gckcss_mask, gck->parent_id) |
+                          gck->layout->cmd |
+                          FIELD_PREP(AT91_PMC_PCR_GCKDIV_MASK, gck->gckdiv) |
                           AT91_PMC_PCR_GCKEN);
        spin_unlock_irqrestore(gck->lock, flags);
        return 0;
@@ -66,11 +68,11 @@ static void clk_generated_disable(struct clk_hw *hw)
        unsigned long flags;
 
        spin_lock_irqsave(gck->lock, flags);
-       regmap_write(gck->regmap, AT91_PMC_PCR,
-                    (gck->id & AT91_PMC_PCR_PID_MASK));
-       regmap_update_bits(gck->regmap, AT91_PMC_PCR,
-                          AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN,
-                          AT91_PMC_PCR_CMD);
+       regmap_write(gck->regmap, gck->layout->offset,
+                    (gck->id & gck->layout->pid_mask));
+       regmap_update_bits(gck->regmap, gck->layout->offset,
+                          gck->layout->cmd | AT91_PMC_PCR_GCKEN,
+                          gck->layout->cmd);
        spin_unlock_irqrestore(gck->lock, flags);
 }
 
@@ -81,9 +83,9 @@ static int clk_generated_is_enabled(struct clk_hw *hw)
        unsigned int status;
 
        spin_lock_irqsave(gck->lock, flags);
-       regmap_write(gck->regmap, AT91_PMC_PCR,
-                    (gck->id & AT91_PMC_PCR_PID_MASK));
-       regmap_read(gck->regmap, AT91_PMC_PCR, &status);
+       regmap_write(gck->regmap, gck->layout->offset,
+                    (gck->id & gck->layout->pid_mask));
+       regmap_read(gck->regmap, gck->layout->offset, &status);
        spin_unlock_irqrestore(gck->lock, flags);
 
        return status & AT91_PMC_PCR_GCKEN ? 1 : 0;
@@ -259,19 +261,18 @@ static void clk_generated_startup(struct clk_generated *gck)
        unsigned long flags;
 
        spin_lock_irqsave(gck->lock, flags);
-       regmap_write(gck->regmap, AT91_PMC_PCR,
-                    (gck->id & AT91_PMC_PCR_PID_MASK));
-       regmap_read(gck->regmap, AT91_PMC_PCR, &tmp);
+       regmap_write(gck->regmap, gck->layout->offset,
+                    (gck->id & gck->layout->pid_mask));
+       regmap_read(gck->regmap, gck->layout->offset, &tmp);
        spin_unlock_irqrestore(gck->lock, flags);
 
-       gck->parent_id = (tmp & AT91_PMC_PCR_GCKCSS_MASK)
-                                       >> AT91_PMC_PCR_GCKCSS_OFFSET;
-       gck->gckdiv = (tmp & AT91_PMC_PCR_GCKDIV_MASK)
-                                       >> AT91_PMC_PCR_GCKDIV_OFFSET;
+       gck->parent_id = field_get(gck->layout->gckcss_mask, tmp);
+       gck->gckdiv = FIELD_GET(AT91_PMC_PCR_GCKDIV_MASK, tmp);
 }
 
 struct clk_hw * __init
 at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
+                           const struct clk_pcr_layout *layout,
                            const char *name, const char **parent_names,
                            u8 num_parents, u8 id, bool pll_audio,
                            const struct clk_range *range)
@@ -298,6 +299,7 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
        gck->lock = lock;
        gck->range = *range;
        gck->audio_pll_allowed = pll_audio;
+       gck->layout = layout;
 
        clk_generated_startup(gck);
        hw = &gck->hw;
index eb53b4a8fab635476d6f84449ca7696d006a464a..12b5bf4cc7bb56175e6fa7f5e7f0560cffc23e0b 100644 (file)
@@ -29,6 +29,7 @@ struct clk_master {
        struct regmap *regmap;
        const struct clk_master_layout *layout;
        const struct clk_master_characteristics *characteristics;
+       u32 mckr;
 };
 
 static inline bool clk_master_ready(struct regmap *regmap)
@@ -69,7 +70,7 @@ static unsigned long clk_master_recalc_rate(struct clk_hw *hw,
                                                master->characteristics;
        unsigned int mckr;
 
-       regmap_read(master->regmap, AT91_PMC_MCKR, &mckr);
+       regmap_read(master->regmap, master->layout->offset, &mckr);
        mckr &= layout->mask;
 
        pres = (mckr >> layout->pres_shift) & MASTER_PRES_MASK;
@@ -95,7 +96,7 @@ static u8 clk_master_get_parent(struct clk_hw *hw)
        struct clk_master *master = to_clk_master(hw);
        unsigned int mckr;
 
-       regmap_read(master->regmap, AT91_PMC_MCKR, &mckr);
+       regmap_read(master->regmap, master->layout->offset, &mckr);
 
        return mckr & AT91_PMC_CSS;
 }
@@ -147,13 +148,14 @@ at91_clk_register_master(struct regmap *regmap,
        return hw;
 }
 
-
 const struct clk_master_layout at91rm9200_master_layout = {
        .mask = 0x31F,
        .pres_shift = 2,
+       .offset = AT91_PMC_MCKR,
 };
 
 const struct clk_master_layout at91sam9x5_master_layout = {
        .mask = 0x373,
        .pres_shift = 4,
+       .offset = AT91_PMC_MCKR,
 };
index 65c1defa78e4a136c1ddcd0f04d8e2c5882b6811..6b7748b9588a444cc5d0f003bf117b9cb60d06ed 100644 (file)
@@ -8,6 +8,7 @@
  *
  */
 
+#include <linux/bitops.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/clk/at91_pmc.h>
@@ -23,9 +24,6 @@ DEFINE_SPINLOCK(pmc_pcr_lock);
 #define PERIPHERAL_ID_MAX      31
 #define PERIPHERAL_MASK(id)    (1 << ((id) & PERIPHERAL_ID_MAX))
 
-#define PERIPHERAL_RSHIFT_MASK 0x3
-#define PERIPHERAL_RSHIFT(val) (((val) >> 16) & PERIPHERAL_RSHIFT_MASK)
-
 #define PERIPHERAL_MAX_SHIFT   3
 
 struct clk_peripheral {
@@ -43,6 +41,7 @@ struct clk_sam9x5_peripheral {
        spinlock_t *lock;
        u32 id;
        u32 div;
+       const struct clk_pcr_layout *layout;
        bool auto_div;
 };
 
@@ -169,13 +168,13 @@ static int clk_sam9x5_peripheral_enable(struct clk_hw *hw)
                return 0;
 
        spin_lock_irqsave(periph->lock, flags);
-       regmap_write(periph->regmap, AT91_PMC_PCR,
-                    (periph->id & AT91_PMC_PCR_PID_MASK));
-       regmap_update_bits(periph->regmap, AT91_PMC_PCR,
-                          AT91_PMC_PCR_DIV_MASK | AT91_PMC_PCR_CMD |
+       regmap_write(periph->regmap, periph->layout->offset,
+                    (periph->id & periph->layout->pid_mask));
+       regmap_update_bits(periph->regmap, periph->layout->offset,
+                          periph->layout->div_mask | periph->layout->cmd |
                           AT91_PMC_PCR_EN,
-                          AT91_PMC_PCR_DIV(periph->div) |
-                          AT91_PMC_PCR_CMD |
+                          field_prep(periph->layout->div_mask, periph->div) |
+                          periph->layout->cmd |
                           AT91_PMC_PCR_EN);
        spin_unlock_irqrestore(periph->lock, flags);
 
@@ -191,11 +190,11 @@ static void clk_sam9x5_peripheral_disable(struct clk_hw *hw)
                return;
 
        spin_lock_irqsave(periph->lock, flags);
-       regmap_write(periph->regmap, AT91_PMC_PCR,
-                    (periph->id & AT91_PMC_PCR_PID_MASK));
-       regmap_update_bits(periph->regmap, AT91_PMC_PCR,
-                          AT91_PMC_PCR_EN | AT91_PMC_PCR_CMD,
-                          AT91_PMC_PCR_CMD);
+       regmap_write(periph->regmap, periph->layout->offset,
+                    (periph->id & periph->layout->pid_mask));
+       regmap_update_bits(periph->regmap, periph->layout->offset,
+                          AT91_PMC_PCR_EN | periph->layout->cmd,
+                          periph->layout->cmd);
        spin_unlock_irqrestore(periph->lock, flags);
 }
 
@@ -209,9 +208,9 @@ static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw)
                return 1;
 
        spin_lock_irqsave(periph->lock, flags);
-       regmap_write(periph->regmap, AT91_PMC_PCR,
-                    (periph->id & AT91_PMC_PCR_PID_MASK));
-       regmap_read(periph->regmap, AT91_PMC_PCR, &status);
+       regmap_write(periph->regmap, periph->layout->offset,
+                    (periph->id & periph->layout->pid_mask));
+       regmap_read(periph->regmap, periph->layout->offset, &status);
        spin_unlock_irqrestore(periph->lock, flags);
 
        return status & AT91_PMC_PCR_EN ? 1 : 0;
@@ -229,13 +228,13 @@ clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw,
                return parent_rate;
 
        spin_lock_irqsave(periph->lock, flags);
-       regmap_write(periph->regmap, AT91_PMC_PCR,
-                    (periph->id & AT91_PMC_PCR_PID_MASK));
-       regmap_read(periph->regmap, AT91_PMC_PCR, &status);
+       regmap_write(periph->regmap, periph->layout->offset,
+                    (periph->id & periph->layout->pid_mask));
+       regmap_read(periph->regmap, periph->layout->offset, &status);
        spin_unlock_irqrestore(periph->lock, flags);
 
        if (status & AT91_PMC_PCR_EN) {
-               periph->div = PERIPHERAL_RSHIFT(status);
+               periph->div = field_get(periph->layout->div_mask, status);
                periph->auto_div = false;
        } else {
                clk_sam9x5_peripheral_autodiv(periph);
@@ -328,6 +327,7 @@ static const struct clk_ops sam9x5_peripheral_ops = {
 
 struct clk_hw * __init
 at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
+                                   const struct clk_pcr_layout *layout,
                                    const char *name, const char *parent_name,
                                    u32 id, const struct clk_range *range)
 {
@@ -354,7 +354,9 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
        periph->div = 0;
        periph->regmap = regmap;
        periph->lock = lock;
-       periph->auto_div = true;
+       if (layout->div_mask)
+               periph->auto_div = true;
+       periph->layout = layout;
        periph->range = *range;
 
        hw = &periph->hw;
diff --git a/drivers/clk/at91/clk-sam9x60-pll.c b/drivers/clk/at91/clk-sam9x60-pll.c
new file mode 100644 (file)
index 0000000..34b8178
--- /dev/null
@@ -0,0 +1,330 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  Copyright (C) 2019 Microchip Technology Inc.
+ *
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include "pmc.h"
+
+#define PMC_PLL_CTRL0  0xc
+#define                PMC_PLL_CTRL0_DIV_MSK           GENMASK(7, 0)
+#define                PMC_PLL_CTRL0_ENPLL             BIT(28)
+#define                PMC_PLL_CTRL0_ENPLLCK           BIT(29)
+#define                PMC_PLL_CTRL0_ENLOCK            BIT(31)
+
+#define PMC_PLL_CTRL1  0x10
+#define                PMC_PLL_CTRL1_FRACR_MSK         GENMASK(21, 0)
+#define                PMC_PLL_CTRL1_MUL_MSK           GENMASK(30, 24)
+
+#define PMC_PLL_ACR    0x18
+#define                PMC_PLL_ACR_DEFAULT             0x1b040010UL
+#define                PMC_PLL_ACR_UTMIVR              BIT(12)
+#define                PMC_PLL_ACR_UTMIBG              BIT(13)
+#define                PMC_PLL_ACR_LOOP_FILTER_MSK     GENMASK(31, 24)
+
+#define PMC_PLL_UPDT   0x1c
+#define                PMC_PLL_UPDT_UPDATE             BIT(8)
+
+#define PMC_PLL_ISR0   0xec
+
+#define PLL_DIV_MAX            (FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, UINT_MAX) + 1)
+#define UPLL_DIV               2
+#define PLL_MUL_MAX            (FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, UINT_MAX) + 1)
+
+#define PLL_MAX_ID             1
+
+struct sam9x60_pll {
+       struct clk_hw hw;
+       struct regmap *regmap;
+       spinlock_t *lock;
+       const struct clk_pll_characteristics *characteristics;
+       u32 frac;
+       u8 id;
+       u8 div;
+       u16 mul;
+};
+
+#define to_sam9x60_pll(hw) container_of(hw, struct sam9x60_pll, hw)
+
+static inline bool sam9x60_pll_ready(struct regmap *regmap, int id)
+{
+       unsigned int status;
+
+       regmap_read(regmap, PMC_PLL_ISR0, &status);
+
+       return !!(status & BIT(id));
+}
+
+static int sam9x60_pll_prepare(struct clk_hw *hw)
+{
+       struct sam9x60_pll *pll = to_sam9x60_pll(hw);
+       struct regmap *regmap = pll->regmap;
+       unsigned long flags;
+       u8 div;
+       u16 mul;
+       u32 val;
+
+       spin_lock_irqsave(pll->lock, flags);
+       regmap_write(regmap, PMC_PLL_UPDT, pll->id);
+
+       regmap_read(regmap, PMC_PLL_CTRL0, &val);
+       div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, val);
+
+       regmap_read(regmap, PMC_PLL_CTRL1, &val);
+       mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, val);
+
+       if (sam9x60_pll_ready(regmap, pll->id) &&
+           (div == pll->div && mul == pll->mul)) {
+               spin_unlock_irqrestore(pll->lock, flags);
+               return 0;
+       }
+
+       /* Recommended value for PMC_PLL_ACR */
+       val = PMC_PLL_ACR_DEFAULT;
+       regmap_write(regmap, PMC_PLL_ACR, val);
+
+       regmap_write(regmap, PMC_PLL_CTRL1,
+                    FIELD_PREP(PMC_PLL_CTRL1_MUL_MSK, pll->mul));
+
+       if (pll->characteristics->upll) {
+               /* Enable the UTMI internal bandgap */
+               val |= PMC_PLL_ACR_UTMIBG;
+               regmap_write(regmap, PMC_PLL_ACR, val);
+
+               udelay(10);
+
+               /* Enable the UTMI internal regulator */
+               val |= PMC_PLL_ACR_UTMIVR;
+               regmap_write(regmap, PMC_PLL_ACR, val);
+
+               udelay(10);
+       }
+
+       regmap_update_bits(regmap, PMC_PLL_UPDT,
+                          PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
+
+       regmap_write(regmap, PMC_PLL_CTRL0,
+                    PMC_PLL_CTRL0_ENLOCK | PMC_PLL_CTRL0_ENPLL |
+                    PMC_PLL_CTRL0_ENPLLCK | pll->div);
+
+       regmap_update_bits(regmap, PMC_PLL_UPDT,
+                          PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
+
+       while (!sam9x60_pll_ready(regmap, pll->id))
+               cpu_relax();
+
+       spin_unlock_irqrestore(pll->lock, flags);
+
+       return 0;
+}
+
+static int sam9x60_pll_is_prepared(struct clk_hw *hw)
+{
+       struct sam9x60_pll *pll = to_sam9x60_pll(hw);
+
+       return sam9x60_pll_ready(pll->regmap, pll->id);
+}
+
+static void sam9x60_pll_unprepare(struct clk_hw *hw)
+{
+       struct sam9x60_pll *pll = to_sam9x60_pll(hw);
+       unsigned long flags;
+
+       spin_lock_irqsave(pll->lock, flags);
+
+       regmap_write(pll->regmap, PMC_PLL_UPDT, pll->id);
+
+       regmap_update_bits(pll->regmap, PMC_PLL_CTRL0,
+                          PMC_PLL_CTRL0_ENPLLCK, 0);
+
+       regmap_update_bits(pll->regmap, PMC_PLL_UPDT,
+                          PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
+
+       regmap_update_bits(pll->regmap, PMC_PLL_CTRL0, PMC_PLL_CTRL0_ENPLL, 0);
+
+       if (pll->characteristics->upll)
+               regmap_update_bits(pll->regmap, PMC_PLL_ACR,
+                                  PMC_PLL_ACR_UTMIBG | PMC_PLL_ACR_UTMIVR, 0);
+
+       regmap_update_bits(pll->regmap, PMC_PLL_UPDT,
+                          PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
+
+       spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static unsigned long sam9x60_pll_recalc_rate(struct clk_hw *hw,
+                                            unsigned long parent_rate)
+{
+       struct sam9x60_pll *pll = to_sam9x60_pll(hw);
+
+       return (parent_rate * (pll->mul + 1)) / (pll->div + 1);
+}
+
+static long sam9x60_pll_get_best_div_mul(struct sam9x60_pll *pll,
+                                        unsigned long rate,
+                                        unsigned long parent_rate,
+                                        bool update)
+{
+       const struct clk_pll_characteristics *characteristics =
+                                                       pll->characteristics;
+       unsigned long bestremainder = ULONG_MAX;
+       unsigned long maxdiv, mindiv, tmpdiv;
+       long bestrate = -ERANGE;
+       unsigned long bestdiv = 0;
+       unsigned long bestmul = 0;
+       unsigned long bestfrac = 0;
+
+       if (rate < characteristics->output[0].min ||
+           rate > characteristics->output[0].max)
+               return -ERANGE;
+
+       if (!pll->characteristics->upll) {
+               mindiv = parent_rate / rate;
+               if (mindiv < 2)
+                       mindiv = 2;
+
+               maxdiv = DIV_ROUND_UP(parent_rate * PLL_MUL_MAX, rate);
+               if (maxdiv > PLL_DIV_MAX)
+                       maxdiv = PLL_DIV_MAX;
+       } else {
+               mindiv = maxdiv = UPLL_DIV;
+       }
+
+       for (tmpdiv = mindiv; tmpdiv <= maxdiv; tmpdiv++) {
+               unsigned long remainder;
+               unsigned long tmprate;
+               unsigned long tmpmul;
+               unsigned long tmpfrac = 0;
+
+               /*
+                * Calculate the multiplier associated with the current
+                * divider that provide the closest rate to the requested one.
+                */
+               tmpmul = mult_frac(rate, tmpdiv, parent_rate);
+               tmprate = mult_frac(parent_rate, tmpmul, tmpdiv);
+               remainder = rate - tmprate;
+
+               if (remainder) {
+                       tmpfrac = DIV_ROUND_CLOSEST_ULL((u64)remainder * tmpdiv * (1 << 22),
+                                                       parent_rate);
+
+                       tmprate += DIV_ROUND_CLOSEST_ULL((u64)tmpfrac * parent_rate,
+                                                        tmpdiv * (1 << 22));
+
+                       if (tmprate > rate)
+                               remainder = tmprate - rate;
+                       else
+                               remainder = rate - tmprate;
+               }
+
+               /*
+                * Compare the remainder with the best remainder found until
+                * now and elect a new best multiplier/divider pair if the
+                * current remainder is smaller than the best one.
+                */
+               if (remainder < bestremainder) {
+                       bestremainder = remainder;
+                       bestdiv = tmpdiv;
+                       bestmul = tmpmul;
+                       bestrate = tmprate;
+                       bestfrac = tmpfrac;
+               }
+
+               /* We've found a perfect match!  */
+               if (!remainder)
+                       break;
+       }
+
+       /* Check if bestrate is a valid output rate  */
+       if (bestrate < characteristics->output[0].min &&
+           bestrate > characteristics->output[0].max)
+               return -ERANGE;
+
+       if (update) {
+               pll->div = bestdiv - 1;
+               pll->mul = bestmul - 1;
+               pll->frac = bestfrac;
+       }
+
+       return bestrate;
+}
+
+static long sam9x60_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+                                  unsigned long *parent_rate)
+{
+       struct sam9x60_pll *pll = to_sam9x60_pll(hw);
+
+       return sam9x60_pll_get_best_div_mul(pll, rate, *parent_rate, false);
+}
+
+static int sam9x60_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct sam9x60_pll *pll = to_sam9x60_pll(hw);
+
+       return sam9x60_pll_get_best_div_mul(pll, rate, parent_rate, true);
+}
+
+static const struct clk_ops pll_ops = {
+       .prepare = sam9x60_pll_prepare,
+       .unprepare = sam9x60_pll_unprepare,
+       .is_prepared = sam9x60_pll_is_prepared,
+       .recalc_rate = sam9x60_pll_recalc_rate,
+       .round_rate = sam9x60_pll_round_rate,
+       .set_rate = sam9x60_pll_set_rate,
+};
+
+struct clk_hw * __init
+sam9x60_clk_register_pll(struct regmap *regmap, spinlock_t *lock,
+                        const char *name, const char *parent_name, u8 id,
+                        const struct clk_pll_characteristics *characteristics)
+{
+       struct sam9x60_pll *pll;
+       struct clk_hw *hw;
+       struct clk_init_data init;
+       unsigned int pllr;
+       int ret;
+
+       if (id > PLL_MAX_ID)
+               return ERR_PTR(-EINVAL);
+
+       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+       if (!pll)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &pll_ops;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+       init.flags = CLK_SET_RATE_GATE;
+
+       pll->id = id;
+       pll->hw.init = &init;
+       pll->characteristics = characteristics;
+       pll->regmap = regmap;
+       pll->lock = lock;
+
+       regmap_write(regmap, PMC_PLL_UPDT, id);
+       regmap_read(regmap, PMC_PLL_CTRL0, &pllr);
+       pll->div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, pllr);
+       regmap_read(regmap, PMC_PLL_CTRL1, &pllr);
+       pll->mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, pllr);
+
+       hw = &pll->hw;
+       ret = clk_hw_register(NULL, hw);
+       if (ret) {
+               kfree(pll);
+               hw = ERR_PTR(ret);
+       }
+
+       return hw;
+}
+
index 79ee1c760f2a5ba41a7cfaf3a7d748b30ef11f8c..ebc37ee335185849ac3a7b7e68649c15cf224739 100644 (file)
 #define RM9200_USB_DIV_SHIFT   28
 #define RM9200_USB_DIV_TAB_SIZE        4
 
+#define SAM9X5_USBS_MASK       GENMASK(0, 0)
+#define SAM9X60_USBS_MASK      GENMASK(1, 0)
+
 struct at91sam9x5_clk_usb {
        struct clk_hw hw;
        struct regmap *regmap;
+       u32 usbs_mask;
 };
 
 #define to_at91sam9x5_clk_usb(hw) \
@@ -111,8 +115,7 @@ static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
        if (index > 1)
                return -EINVAL;
 
-       regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS,
-                          index ? AT91_PMC_USBS : 0);
+       regmap_update_bits(usb->regmap, AT91_PMC_USB, usb->usbs_mask, index);
 
        return 0;
 }
@@ -124,7 +127,7 @@ static u8 at91sam9x5_clk_usb_get_parent(struct clk_hw *hw)
 
        regmap_read(usb->regmap, AT91_PMC_USB, &usbr);
 
-       return usbr & AT91_PMC_USBS;
+       return usbr & usb->usbs_mask;
 }
 
 static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -190,9 +193,10 @@ static const struct clk_ops at91sam9n12_usb_ops = {
        .set_rate = at91sam9x5_clk_usb_set_rate,
 };
 
-struct clk_hw * __init
-at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
-                           const char **parent_names, u8 num_parents)
+static struct clk_hw * __init
+_at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
+                            const char **parent_names, u8 num_parents,
+                            u32 usbs_mask)
 {
        struct at91sam9x5_clk_usb *usb;
        struct clk_hw *hw;
@@ -212,6 +216,7 @@ at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
 
        usb->hw.init = &init;
        usb->regmap = regmap;
+       usb->usbs_mask = SAM9X5_USBS_MASK;
 
        hw = &usb->hw;
        ret = clk_hw_register(NULL, &usb->hw);
@@ -223,6 +228,22 @@ at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
        return hw;
 }
 
+struct clk_hw * __init
+at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
+                           const char **parent_names, u8 num_parents)
+{
+       return _at91sam9x5_clk_register_usb(regmap, name, parent_names,
+                                           num_parents, SAM9X5_USBS_MASK);
+}
+
+struct clk_hw * __init
+sam9x60_clk_register_usb(struct regmap *regmap, const char *name,
+                        const char **parent_names, u8 num_parents)
+{
+       return _at91sam9x5_clk_register_usb(regmap, name, parent_names,
+                                           num_parents, SAM9X60_USBS_MASK);
+}
+
 struct clk_hw * __init
 at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
                             const char *parent_name)
index b95bb4e2a9270c1d759735d6ca086092b73da934..aa1754eac59fff6d3a09f7d4f03dbad4b77446cc 100644 (file)
@@ -93,6 +93,14 @@ CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup,
               of_sama5d2_clk_audio_pll_pmc_setup);
 #endif /* CONFIG_HAVE_AT91_AUDIO_PLL */
 
+static const struct clk_pcr_layout dt_pcr_layout = {
+       .offset = 0x10c,
+       .cmd = BIT(12),
+       .pid_mask = GENMASK(5, 0),
+       .div_mask = GENMASK(17, 16),
+       .gckcss_mask = GENMASK(10, 8),
+};
+
 #ifdef CONFIG_HAVE_AT91_GENERATED_CLK
 #define GENERATED_SOURCE_MAX   6
 
@@ -146,7 +154,8 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
                     id == GCK_ID_CLASSD))
                        pll_audio = true;
 
-               hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name,
+               hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
+                                                &dt_pcr_layout, name,
                                                 parent_names, num_parents,
                                                 id, pll_audio, &range);
                if (IS_ERR(hw))
@@ -448,6 +457,7 @@ of_at91_clk_periph_setup(struct device_node *np, u8 type)
 
                        hw = at91_clk_register_sam9x5_peripheral(regmap,
                                                                 &pmc_pcr_lock,
+                                                                &dt_pcr_layout,
                                                                 name,
                                                                 parent_name,
                                                                 id, &range);
index a0e5ce9c9b9ea6981948ed102be4f8a870e6a99c..2311204948be77480b8000241cf9f953115601b7 100644 (file)
@@ -38,6 +38,7 @@ struct clk_range {
 #define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,}
 
 struct clk_master_layout {
+       u32 offset;
        u32 mask;
        u8 pres_shift;
 };
@@ -65,9 +66,10 @@ extern const struct clk_pll_layout sama5d3_pll_layout;
 struct clk_pll_characteristics {
        struct clk_range input;
        int num_output;
-       struct clk_range *output;
+       const struct clk_range *output;
        u16 *icpll;
        u8 *out;
+       u8 upll : 1;
 };
 
 struct clk_programmable_layout {
@@ -82,6 +84,17 @@ extern const struct clk_programmable_layout at91rm9200_programmable_layout;
 extern const struct clk_programmable_layout at91sam9g45_programmable_layout;
 extern const struct clk_programmable_layout at91sam9x5_programmable_layout;
 
+struct clk_pcr_layout {
+       u32 offset;
+       u32 cmd;
+       u32 div_mask;
+       u32 gckcss_mask;
+       u32 pid_mask;
+};
+
+#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
+#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
+
 #define ndck(a, s) (a[s - 1].id + 1)
 #define nck(a) (a[ARRAY_SIZE(a) - 1].id + 1)
 struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
@@ -107,6 +120,7 @@ at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
 
 struct clk_hw * __init
 at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
+                           const struct clk_pcr_layout *layout,
                            const char *name, const char **parent_names,
                            u8 num_parents, u8 id, bool pll_audio,
                            const struct clk_range *range);
@@ -145,6 +159,7 @@ at91_clk_register_peripheral(struct regmap *regmap, const char *name,
                             const char *parent_name, u32 id);
 struct clk_hw * __init
 at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
+                                   const struct clk_pcr_layout *layout,
                                    const char *name, const char *parent_name,
                                    u32 id, const struct clk_range *range);
 
@@ -157,6 +172,11 @@ struct clk_hw * __init
 at91_clk_register_plldiv(struct regmap *regmap, const char *name,
                         const char *parent_name);
 
+struct clk_hw * __init
+sam9x60_clk_register_pll(struct regmap *regmap, spinlock_t *lock,
+                        const char *name, const char *parent_name, u8 id,
+                        const struct clk_pll_characteristics *characteristics);
+
 struct clk_hw * __init
 at91_clk_register_programmable(struct regmap *regmap, const char *name,
                               const char **parent_names, u8 num_parents, u8 id,
@@ -183,6 +203,9 @@ struct clk_hw * __init
 at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
                             const char *parent_name);
 struct clk_hw * __init
+sam9x60_clk_register_usb(struct regmap *regmap, const char *name,
+                        const char **parent_names, u8 num_parents);
+struct clk_hw * __init
 at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
                            const char *parent_name, const u32 *divisors);
 
diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c
new file mode 100644 (file)
index 0000000..9790ddf
--- /dev/null
@@ -0,0 +1,307 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/at91.h>
+
+#include "pmc.h"
+
+static DEFINE_SPINLOCK(pmc_pll_lock);
+
+static const struct clk_master_characteristics mck_characteristics = {
+       .output = { .min = 140000000, .max = 200000000 },
+       .divisors = { 1, 2, 4, 3 },
+       .have_div3_pres = 1,
+};
+
+static const struct clk_master_layout sam9x60_master_layout = {
+       .mask = 0x373,
+       .pres_shift = 4,
+       .offset = 0x28,
+};
+
+static const struct clk_range plla_outputs[] = {
+       { .min = 300000000, .max = 600000000 },
+};
+
+static const struct clk_pll_characteristics plla_characteristics = {
+       .input = { .min = 12000000, .max = 48000000 },
+       .num_output = ARRAY_SIZE(plla_outputs),
+       .output = plla_outputs,
+};
+
+static const struct clk_range upll_outputs[] = {
+       { .min = 300000000, .max = 500000000 },
+};
+
+static const struct clk_pll_characteristics upll_characteristics = {
+       .input = { .min = 12000000, .max = 48000000 },
+       .num_output = ARRAY_SIZE(upll_outputs),
+       .output = upll_outputs,
+       .upll = true,
+};
+
+static const struct clk_programmable_layout sam9x60_programmable_layout = {
+       .pres_shift = 8,
+       .css_mask = 0x1f,
+       .have_slck_mck = 0,
+};
+
+static const struct clk_pcr_layout sam9x60_pcr_layout = {
+       .offset = 0x88,
+       .cmd = BIT(31),
+       .gckcss_mask = GENMASK(12, 8),
+       .pid_mask = GENMASK(6, 0),
+};
+
+static const struct {
+       char *n;
+       char *p;
+       u8 id;
+} sam9x60_systemck[] = {
+       { .n = "ddrck",  .p = "masterck", .id = 2 },
+       { .n = "uhpck",  .p = "usbck",    .id = 6 },
+       { .n = "pck0",   .p = "prog0",    .id = 8 },
+       { .n = "pck1",   .p = "prog1",    .id = 9 },
+       { .n = "qspick", .p = "masterck", .id = 19 },
+};
+
+static const struct {
+       char *n;
+       u8 id;
+} sam9x60_periphck[] = {
+       { .n = "pioA_clk",   .id = 2, },
+       { .n = "pioB_clk",   .id = 3, },
+       { .n = "pioC_clk",   .id = 4, },
+       { .n = "flex0_clk",  .id = 5, },
+       { .n = "flex1_clk",  .id = 6, },
+       { .n = "flex2_clk",  .id = 7, },
+       { .n = "flex3_clk",  .id = 8, },
+       { .n = "flex6_clk",  .id = 9, },
+       { .n = "flex7_clk",  .id = 10, },
+       { .n = "flex8_clk",  .id = 11, },
+       { .n = "sdmmc0_clk", .id = 12, },
+       { .n = "flex4_clk",  .id = 13, },
+       { .n = "flex5_clk",  .id = 14, },
+       { .n = "flex9_clk",  .id = 15, },
+       { .n = "flex10_clk", .id = 16, },
+       { .n = "tcb0_clk",   .id = 17, },
+       { .n = "pwm_clk",    .id = 18, },
+       { .n = "adc_clk",    .id = 19, },
+       { .n = "dma0_clk",   .id = 20, },
+       { .n = "matrix_clk", .id = 21, },
+       { .n = "uhphs_clk",  .id = 22, },
+       { .n = "udphs_clk",  .id = 23, },
+       { .n = "macb0_clk",  .id = 24, },
+       { .n = "lcd_clk",    .id = 25, },
+       { .n = "sdmmc1_clk", .id = 26, },
+       { .n = "macb1_clk",  .id = 27, },
+       { .n = "ssc_clk",    .id = 28, },
+       { .n = "can0_clk",   .id = 29, },
+       { .n = "can1_clk",   .id = 30, },
+       { .n = "flex11_clk", .id = 32, },
+       { .n = "flex12_clk", .id = 33, },
+       { .n = "i2s_clk",    .id = 34, },
+       { .n = "qspi_clk",   .id = 35, },
+       { .n = "gfx2d_clk",  .id = 36, },
+       { .n = "pit64b_clk", .id = 37, },
+       { .n = "trng_clk",   .id = 38, },
+       { .n = "aes_clk",    .id = 39, },
+       { .n = "tdes_clk",   .id = 40, },
+       { .n = "sha_clk",    .id = 41, },
+       { .n = "classd_clk", .id = 42, },
+       { .n = "isi_clk",    .id = 43, },
+       { .n = "pioD_clk",   .id = 44, },
+       { .n = "tcb1_clk",   .id = 45, },
+       { .n = "dbgu_clk",   .id = 47, },
+       { .n = "mpddr_clk",  .id = 49, },
+};
+
+static const struct {
+       char *n;
+       u8 id;
+       struct clk_range r;
+       bool pll;
+} sam9x60_gck[] = {
+       { .n = "flex0_gclk",  .id = 5, },
+       { .n = "flex1_gclk",  .id = 6, },
+       { .n = "flex2_gclk",  .id = 7, },
+       { .n = "flex3_gclk",  .id = 8, },
+       { .n = "flex6_gclk",  .id = 9, },
+       { .n = "flex7_gclk",  .id = 10, },
+       { .n = "flex8_gclk",  .id = 11, },
+       { .n = "sdmmc0_gclk", .id = 12, .r = { .min = 0, .max = 105000000 }, },
+       { .n = "flex4_gclk",  .id = 13, },
+       { .n = "flex5_gclk",  .id = 14, },
+       { .n = "flex9_gclk",  .id = 15, },
+       { .n = "flex10_gclk", .id = 16, },
+       { .n = "tcb0_gclk",   .id = 17, },
+       { .n = "adc_gclk",    .id = 19, },
+       { .n = "lcd_gclk",    .id = 25, .r = { .min = 0, .max = 140000000 }, },
+       { .n = "sdmmc1_gclk", .id = 26, .r = { .min = 0, .max = 105000000 }, },
+       { .n = "flex11_gclk", .id = 32, },
+       { .n = "flex12_gclk", .id = 33, },
+       { .n = "i2s_gclk",    .id = 34, .r = { .min = 0, .max = 105000000 },
+               .pll = true, },
+       { .n = "pit64b_gclk", .id = 37, },
+       { .n = "classd_gclk", .id = 42, .r = { .min = 0, .max = 100000000 },
+               .pll = true, },
+       { .n = "tcb1_gclk",   .id = 45, },
+       { .n = "dbgu_gclk",   .id = 47, },
+};
+
+static void __init sam9x60_pmc_setup(struct device_node *np)
+{
+       struct clk_range range = CLK_RANGE(0, 0);
+       const char *td_slck_name, *md_slck_name, *mainxtal_name;
+       struct pmc_data *sam9x60_pmc;
+       const char *parent_names[6];
+       struct regmap *regmap;
+       struct clk_hw *hw;
+       int i;
+       bool bypass;
+
+       i = of_property_match_string(np, "clock-names", "td_slck");
+       if (i < 0)
+               return;
+
+       td_slck_name = of_clk_get_parent_name(np, i);
+
+       i = of_property_match_string(np, "clock-names", "md_slck");
+       if (i < 0)
+               return;
+
+       md_slck_name = of_clk_get_parent_name(np, i);
+
+       i = of_property_match_string(np, "clock-names", "main_xtal");
+       if (i < 0)
+               return;
+       mainxtal_name = of_clk_get_parent_name(np, i);
+
+       regmap = syscon_node_to_regmap(np);
+       if (IS_ERR(regmap))
+               return;
+
+       sam9x60_pmc = pmc_data_allocate(PMC_MAIN + 1,
+                                       nck(sam9x60_systemck),
+                                       nck(sam9x60_periphck),
+                                       nck(sam9x60_gck));
+       if (!sam9x60_pmc)
+               return;
+
+       hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 24000000,
+                                          50000000);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       bypass = of_property_read_bool(np, "atmel,osc-bypass");
+
+       hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+                                       bypass);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       parent_names[0] = "main_rc_osc";
+       parent_names[1] = "main_osc";
+       hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       sam9x60_pmc->chws[PMC_MAIN] = hw;
+
+       hw = sam9x60_clk_register_pll(regmap, &pmc_pll_lock, "pllack",
+                                     "mainck", 0, &plla_characteristics);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       hw = sam9x60_clk_register_pll(regmap, &pmc_pll_lock, "upllck",
+                                     "main_osc", 1, &upll_characteristics);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       sam9x60_pmc->chws[PMC_UTMI] = hw;
+
+       parent_names[0] = md_slck_name;
+       parent_names[1] = "mainck";
+       parent_names[2] = "pllack";
+       hw = at91_clk_register_master(regmap, "masterck", 3, parent_names,
+                                     &sam9x60_master_layout,
+                                     &mck_characteristics);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       sam9x60_pmc->chws[PMC_MCK] = hw;
+
+       parent_names[0] = "pllack";
+       parent_names[1] = "upllck";
+       parent_names[2] = "mainck";
+       parent_names[3] = "mainck";
+       hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 4);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       parent_names[0] = md_slck_name;
+       parent_names[1] = td_slck_name;
+       parent_names[2] = "mainck";
+       parent_names[3] = "masterck";
+       parent_names[4] = "pllack";
+       parent_names[5] = "upllck";
+       for (i = 0; i < 8; i++) {
+               char name[6];
+
+               snprintf(name, sizeof(name), "prog%d", i);
+
+               hw = at91_clk_register_programmable(regmap, name,
+                                                   parent_names, 6, i,
+                                                   &sam9x60_programmable_layout);
+               if (IS_ERR(hw))
+                       goto err_free;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(sam9x60_systemck); i++) {
+               hw = at91_clk_register_system(regmap, sam9x60_systemck[i].n,
+                                             sam9x60_systemck[i].p,
+                                             sam9x60_systemck[i].id);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               sam9x60_pmc->shws[sam9x60_systemck[i].id] = hw;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(sam9x60_periphck); i++) {
+               hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+                                                        &sam9x60_pcr_layout,
+                                                        sam9x60_periphck[i].n,
+                                                        "masterck",
+                                                        sam9x60_periphck[i].id,
+                                                        &range);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               sam9x60_pmc->phws[sam9x60_periphck[i].id] = hw;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(sam9x60_gck); i++) {
+               hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
+                                                &sam9x60_pcr_layout,
+                                                sam9x60_gck[i].n,
+                                                parent_names, 6,
+                                                sam9x60_gck[i].id,
+                                                sam9x60_gck[i].pll,
+                                                &sam9x60_gck[i].r);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               sam9x60_pmc->ghws[sam9x60_gck[i].id] = hw;
+       }
+
+       of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sam9x60_pmc);
+
+       return;
+
+err_free:
+       pmc_data_free(sam9x60_pmc);
+}
+/* Some clks are used for a clocksource */
+CLK_OF_DECLARE(sam9x60_pmc, "microchip,sam9x60-pmc", sam9x60_pmc_setup);
index 81943fac4537ef3c8e8d0f611a897b2dd6b8171f..6509d09348048f101f65b339b8521543a65447be 100644 (file)
@@ -16,7 +16,7 @@ static u8 plla_out[] = { 0 };
 
 static u16 plla_icpll[] = { 0 };
 
-static struct clk_range plla_outputs[] = {
+static const struct clk_range plla_outputs[] = {
        { .min = 600000000, .max = 1200000000 },
 };
 
@@ -28,6 +28,13 @@ static const struct clk_pll_characteristics plla_characteristics = {
        .out = plla_out,
 };
 
+static const struct clk_pcr_layout sama5d2_pcr_layout = {
+       .offset = 0x10c,
+       .cmd = BIT(12),
+       .gckcss_mask = GENMASK(10, 8),
+       .pid_mask = GENMASK(6, 0),
+};
+
 static const struct {
        char *n;
        char *p;
@@ -274,6 +281,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
 
        for (i = 0; i < ARRAY_SIZE(sama5d2_periphck); i++) {
                hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+                                                        &sama5d2_pcr_layout,
                                                         sama5d2_periphck[i].n,
                                                         "masterck",
                                                         sama5d2_periphck[i].id,
@@ -286,6 +294,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
 
        for (i = 0; i < ARRAY_SIZE(sama5d2_periph32ck); i++) {
                hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+                                                        &sama5d2_pcr_layout,
                                                         sama5d2_periph32ck[i].n,
                                                         "h32mxck",
                                                         sama5d2_periph32ck[i].id,
@@ -304,6 +313,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
        parent_names[5] = "audiopll_pmcck";
        for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) {
                hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
+                                                &sama5d2_pcr_layout,
                                                 sama5d2_gck[i].n,
                                                 parent_names, 6,
                                                 sama5d2_gck[i].id,
index b645a9d59cdbd61aa6358072ba5783265f873da7..25b156d4e645f6daf4edea37f16cede5ac3ce4b9 100644 (file)
@@ -16,7 +16,7 @@ static u8 plla_out[] = { 0 };
 
 static u16 plla_icpll[] = { 0 };
 
-static struct clk_range plla_outputs[] = {
+static const struct clk_range plla_outputs[] = {
        { .min = 600000000, .max = 1200000000 },
 };
 
@@ -28,6 +28,12 @@ static const struct clk_pll_characteristics plla_characteristics = {
        .out = plla_out,
 };
 
+static const struct clk_pcr_layout sama5d4_pcr_layout = {
+       .offset = 0x10c,
+       .cmd = BIT(12),
+       .pid_mask = GENMASK(6, 0),
+};
+
 static const struct {
        char *n;
        char *p;
@@ -232,6 +238,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
 
        for (i = 0; i < ARRAY_SIZE(sama5d4_periphck); i++) {
                hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+                                                        &sama5d4_pcr_layout,
                                                         sama5d4_periphck[i].n,
                                                         "masterck",
                                                         sama5d4_periphck[i].id,
@@ -244,6 +251,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
 
        for (i = 0; i < ARRAY_SIZE(sama5d4_periph32ck); i++) {
                hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+                                                        &sama5d4_pcr_layout,
                                                         sama5d4_periph32ck[i].n,
                                                         "h32mxck",
                                                         sama5d4_periph32ck[i].id,
index ab6ecefc49ad85424a02dda7b3d3342d76598884..e76b1d64e905c878c5f961e3fb075e4850eea9f8 100644 (file)
@@ -152,28 +152,6 @@ at91_clk_register_slow_osc(void __iomem *sckcr,
        return hw;
 }
 
-static void __init
-of_at91sam9x5_clk_slow_osc_setup(struct device_node *np, void __iomem *sckcr)
-{
-       struct clk_hw *hw;
-       const char *parent_name;
-       const char *name = np->name;
-       u32 startup;
-       bool bypass;
-
-       parent_name = of_clk_get_parent_name(np, 0);
-       of_property_read_string(np, "clock-output-names", &name);
-       of_property_read_u32(np, "atmel,startup-time-usec", &startup);
-       bypass = of_property_read_bool(np, "atmel,osc-bypass");
-
-       hw = at91_clk_register_slow_osc(sckcr, name, parent_name, startup,
-                                        bypass);
-       if (IS_ERR(hw))
-               return;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-}
-
 static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw,
                                                 unsigned long parent_rate)
 {
@@ -266,28 +244,6 @@ at91_clk_register_slow_rc_osc(void __iomem *sckcr,
        return hw;
 }
 
-static void __init
-of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np, void __iomem *sckcr)
-{
-       struct clk_hw *hw;
-       u32 frequency = 0;
-       u32 accuracy = 0;
-       u32 startup = 0;
-       const char *name = np->name;
-
-       of_property_read_string(np, "clock-output-names", &name);
-       of_property_read_u32(np, "clock-frequency", &frequency);
-       of_property_read_u32(np, "clock-accuracy", &accuracy);
-       of_property_read_u32(np, "atmel,startup-time-usec", &startup);
-
-       hw = at91_clk_register_slow_rc_osc(sckcr, name, frequency, accuracy,
-                                           startup);
-       if (IS_ERR(hw))
-               return;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-}
-
 static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index)
 {
        struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
@@ -365,68 +321,72 @@ at91_clk_register_sam9x5_slow(void __iomem *sckcr,
        return hw;
 }
 
-static void __init
-of_at91sam9x5_clk_slow_setup(struct device_node *np, void __iomem *sckcr)
+static void __init at91sam9x5_sckc_register(struct device_node *np,
+                                           unsigned int rc_osc_startup_us)
 {
+       const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
+       void __iomem *regbase = of_iomap(np, 0);
+       struct device_node *child = NULL;
+       const char *xtal_name;
        struct clk_hw *hw;
-       const char *parent_names[2];
-       unsigned int num_parents;
-       const char *name = np->name;
+       bool bypass;
 
-       num_parents = of_clk_get_parent_count(np);
-       if (num_parents == 0 || num_parents > 2)
+       if (!regbase)
+               return;
+
+       hw = at91_clk_register_slow_rc_osc(regbase, parent_names[0], 32768,
+                                          50000000, rc_osc_startup_us);
+       if (IS_ERR(hw))
                return;
 
-       of_clk_parent_fill(np, parent_names, num_parents);
+       xtal_name = of_clk_get_parent_name(np, 0);
+       if (!xtal_name) {
+               /* DT backward compatibility */
+               child = of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow-osc");
+               if (!child)
+                       return;
+
+               xtal_name = of_clk_get_parent_name(child, 0);
+               bypass = of_property_read_bool(child, "atmel,osc-bypass");
+
+               child =  of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow");
+       } else {
+               bypass = of_property_read_bool(np, "atmel,osc-bypass");
+       }
+
+       if (!xtal_name)
+               return;
 
-       of_property_read_string(np, "clock-output-names", &name);
+       hw = at91_clk_register_slow_osc(regbase, parent_names[1], xtal_name,
+                                       1200000, bypass);
+       if (IS_ERR(hw))
+               return;
 
-       hw = at91_clk_register_sam9x5_slow(sckcr, name, parent_names,
-                                           num_parents);
+       hw = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_names, 2);
        if (IS_ERR(hw))
                return;
 
        of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-}
 
-static const struct of_device_id sckc_clk_ids[] __initconst = {
-       /* Slow clock */
-       {
-               .compatible = "atmel,at91sam9x5-clk-slow-osc",
-               .data = of_at91sam9x5_clk_slow_osc_setup,
-       },
-       {
-               .compatible = "atmel,at91sam9x5-clk-slow-rc-osc",
-               .data = of_at91sam9x5_clk_slow_rc_osc_setup,
-       },
-       {
-               .compatible = "atmel,at91sam9x5-clk-slow",
-               .data = of_at91sam9x5_clk_slow_setup,
-       },
-       { /*sentinel*/ }
-};
+       /* DT backward compatibility */
+       if (child)
+               of_clk_add_hw_provider(child, of_clk_hw_simple_get, hw);
+}
 
 static void __init of_at91sam9x5_sckc_setup(struct device_node *np)
 {
-       struct device_node *childnp;
-       void (*clk_setup)(struct device_node *, void __iomem *);
-       const struct of_device_id *clk_id;
-       void __iomem *regbase = of_iomap(np, 0);
-
-       if (!regbase)
-               return;
-
-       for_each_child_of_node(np, childnp) {
-               clk_id = of_match_node(sckc_clk_ids, childnp);
-               if (!clk_id)
-                       continue;
-               clk_setup = clk_id->data;
-               clk_setup(childnp, regbase);
-       }
+       at91sam9x5_sckc_register(np, 75);
 }
 CLK_OF_DECLARE(at91sam9x5_clk_sckc, "atmel,at91sam9x5-sckc",
               of_at91sam9x5_sckc_setup);
 
+static void __init of_sama5d3_sckc_setup(struct device_node *np)
+{
+       at91sam9x5_sckc_register(np, 500);
+}
+CLK_OF_DECLARE(sama5d3_clk_sckc, "atmel,sama5d3-sckc",
+              of_sama5d3_sckc_setup);
+
 static int clk_sama5d4_slow_osc_prepare(struct clk_hw *hw)
 {
        struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw);
index 596136793fc470f12c685b7e74ad98dd270e8d63..42b4df6ba249f2ec3b7382cfb2a732358473affb 100644 (file)
@@ -87,10 +87,10 @@ struct aspeed_clk_gate {
 /* TODO: ask Aspeed about the actual parent data */
 static const struct aspeed_gate_data aspeed_gates[] = {
        /*                               clk rst   name                 parent  flags */
-       [ASPEED_CLK_GATE_ECLK] =        {  0, -1, "eclk-gate",          "eclk", 0 }, /* Video Engine */
+       [ASPEED_CLK_GATE_ECLK] =        {  0,  6, "eclk-gate",          "eclk", 0 }, /* Video Engine */
        [ASPEED_CLK_GATE_GCLK] =        {  1,  7, "gclk-gate",          NULL,   0 }, /* 2D engine */
        [ASPEED_CLK_GATE_MCLK] =        {  2, -1, "mclk-gate",          "mpll", CLK_IS_CRITICAL }, /* SDRAM */
-       [ASPEED_CLK_GATE_VCLK] =        {  3,  6, "vclk-gate",          NULL,   0 }, /* Video Capture */
+       [ASPEED_CLK_GATE_VCLK] =        {  3, -1, "vclk-gate",          NULL,   0 }, /* Video Capture */
        [ASPEED_CLK_GATE_BCLK] =        {  4,  8, "bclk-gate",          "bclk", CLK_IS_CRITICAL }, /* PCIe/PCI */
        [ASPEED_CLK_GATE_DCLK] =        {  5, -1, "dclk-gate",          NULL,   CLK_IS_CRITICAL }, /* DAC */
        [ASPEED_CLK_GATE_REFCLK] =      {  6, -1, "refclk-gate",        "clkin", CLK_IS_CRITICAL },
@@ -113,6 +113,24 @@ static const struct aspeed_gate_data aspeed_gates[] = {
        [ASPEED_CLK_GATE_LHCCLK] =      { 28, -1, "lhclk-gate",         "lhclk", 0 }, /* LPC master/LPC+ */
 };
 
+static const char * const eclk_parent_names[] = {
+       "mpll",
+       "hpll",
+       "dpll",
+};
+
+static const struct clk_div_table ast2500_eclk_div_table[] = {
+       { 0x0, 2 },
+       { 0x1, 2 },
+       { 0x2, 3 },
+       { 0x3, 4 },
+       { 0x4, 5 },
+       { 0x5, 6 },
+       { 0x6, 7 },
+       { 0x7, 8 },
+       { 0 }
+};
+
 static const struct clk_div_table ast2500_mac_div_table[] = {
        { 0x0, 4 }, /* Yep, really. Aspeed confirmed this is correct */
        { 0x1, 4 },
@@ -192,18 +210,21 @@ static struct clk_hw *aspeed_ast2500_calc_pll(const char *name, u32 val)
 
 struct aspeed_clk_soc_data {
        const struct clk_div_table *div_table;
+       const struct clk_div_table *eclk_div_table;
        const struct clk_div_table *mac_div_table;
        struct clk_hw *(*calc_pll)(const char *name, u32 val);
 };
 
 static const struct aspeed_clk_soc_data ast2500_data = {
        .div_table = ast2500_div_table,
+       .eclk_div_table = ast2500_eclk_div_table,
        .mac_div_table = ast2500_mac_div_table,
        .calc_pll = aspeed_ast2500_calc_pll,
 };
 
 static const struct aspeed_clk_soc_data ast2400_data = {
        .div_table = ast2400_div_table,
+       .eclk_div_table = ast2400_div_table,
        .mac_div_table = ast2400_div_table,
        .calc_pll = aspeed_ast2400_calc_pll,
 };
@@ -522,6 +543,22 @@ static int aspeed_clk_probe(struct platform_device *pdev)
                return PTR_ERR(hw);
        aspeed_clk_data->hws[ASPEED_CLK_24M] = hw;
 
+       hw = clk_hw_register_mux(dev, "eclk-mux", eclk_parent_names,
+                                ARRAY_SIZE(eclk_parent_names), 0,
+                                scu_base + ASPEED_CLK_SELECTION, 2, 0x3, 0,
+                                &aspeed_clk_lock);
+       if (IS_ERR(hw))
+               return PTR_ERR(hw);
+       aspeed_clk_data->hws[ASPEED_CLK_ECLK_MUX] = hw;
+
+       hw = clk_hw_register_divider_table(dev, "eclk", "eclk-mux", 0,
+                                          scu_base + ASPEED_CLK_SELECTION, 28,
+                                          3, 0, soc_data->eclk_div_table,
+                                          &aspeed_clk_lock);
+       if (IS_ERR(hw))
+               return PTR_ERR(hw);
+       aspeed_clk_data->hws[ASPEED_CLK_ECLK] = hw;
+
        /*
         * TODO: There are a number of clocks that not included in this driver
         * as more information is required:
@@ -531,7 +568,6 @@ static int aspeed_clk_probe(struct platform_device *pdev)
         *   RGMII
         *   RMII
         *   UART[1..5] clock source mux
-        *   Video Engine (ECLK) mux and clock divider
         */
 
        for (i = 0; i < ARRAY_SIZE(aspeed_gates); i++) {
index 46604214bba03e2581153e59fc08aa7c8fea7820..b06038b8f6586034df7385fd478a4a6b8b2d4fc2 100644 (file)
@@ -218,7 +218,7 @@ struct clk_hw *clk_hw_register_composite(struct device *dev, const char *name,
                return ERR_PTR(-ENOMEM);
 
        init.name = name;
-       init.flags = flags | CLK_IS_BASIC;
+       init.flags = flags;
        init.parent_names = parent_names;
        init.num_parents = num_parents;
        hw = &composite->hw;
index e5a17265cfaf390fa1c2a77990917240e85a2edc..3f9ff78c4a2a9fe941fcdf8fd87ae113e52921d5 100644 (file)
  * parent - fixed parent.  No clk_set_parent support
  */
 
+static inline u32 clk_div_readl(struct clk_divider *divider)
+{
+       if (divider->flags & CLK_DIVIDER_BIG_ENDIAN)
+               return ioread32be(divider->reg);
+
+       return readl(divider->reg);
+}
+
+static inline void clk_div_writel(struct clk_divider *divider, u32 val)
+{
+       if (divider->flags & CLK_DIVIDER_BIG_ENDIAN)
+               iowrite32be(val, divider->reg);
+       else
+               writel(val, divider->reg);
+}
+
 static unsigned int _get_table_maxdiv(const struct clk_div_table *table,
                                      u8 width)
 {
@@ -135,7 +151,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
        struct clk_divider *divider = to_clk_divider(hw);
        unsigned int val;
 
-       val = clk_readl(divider->reg) >> divider->shift;
+       val = clk_div_readl(divider) >> divider->shift;
        val &= clk_div_mask(divider->width);
 
        return divider_recalc_rate(hw, parent_rate, val, divider->table,
@@ -370,7 +386,7 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
        if (divider->flags & CLK_DIVIDER_READ_ONLY) {
                u32 val;
 
-               val = clk_readl(divider->reg) >> divider->shift;
+               val = clk_div_readl(divider) >> divider->shift;
                val &= clk_div_mask(divider->width);
 
                return divider_ro_round_rate(hw, rate, prate, divider->table,
@@ -420,11 +436,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
        if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
                val = clk_div_mask(divider->width) << (divider->shift + 16);
        } else {
-               val = clk_readl(divider->reg);
+               val = clk_div_readl(divider);
                val &= ~(clk_div_mask(divider->width) << divider->shift);
        }
        val |= (u32)value << divider->shift;
-       clk_writel(val, divider->reg);
+       clk_div_writel(divider, val);
 
        if (divider->lock)
                spin_unlock_irqrestore(divider->lock, flags);
@@ -475,7 +491,7 @@ static struct clk_hw *_register_divider(struct device *dev, const char *name,
                init.ops = &clk_divider_ro_ops;
        else
                init.ops = &clk_divider_ops;
-       init.flags = flags | CLK_IS_BASIC;
+       init.flags = flags;
        init.parent_names = (parent_name ? &parent_name: NULL);
        init.num_parents = (parent_name ? 1 : 0);
 
index 241b3f8c61a93d7f25a51ebe74d6038aae61dc30..8b343e59dc616e959a78463941868500c7b9da53 100644 (file)
@@ -64,12 +64,14 @@ const struct clk_ops clk_fixed_factor_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_fixed_factor_ops);
 
-struct clk_hw *clk_hw_register_fixed_factor(struct device *dev,
-               const char *name, const char *parent_name, unsigned long flags,
-               unsigned int mult, unsigned int div)
+static struct clk_hw *
+__clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
+               const char *name, const char *parent_name, int index,
+               unsigned long flags, unsigned int mult, unsigned int div)
 {
        struct clk_fixed_factor *fix;
-       struct clk_init_data init;
+       struct clk_init_data init = { };
+       struct clk_parent_data pdata = { .index = index };
        struct clk_hw *hw;
        int ret;
 
@@ -84,12 +86,18 @@ struct clk_hw *clk_hw_register_fixed_factor(struct device *dev,
 
        init.name = name;
        init.ops = &clk_fixed_factor_ops;
-       init.flags = flags | CLK_IS_BASIC;
-       init.parent_names = &parent_name;
+       init.flags = flags;
+       if (parent_name)
+               init.parent_names = &parent_name;
+       else
+               init.parent_data = &pdata;
        init.num_parents = 1;
 
        hw = &fix->hw;
-       ret = clk_hw_register(dev, hw);
+       if (dev)
+               ret = clk_hw_register(dev, hw);
+       else
+               ret = of_clk_hw_register(np, hw);
        if (ret) {
                kfree(fix);
                hw = ERR_PTR(ret);
@@ -97,6 +105,14 @@ struct clk_hw *clk_hw_register_fixed_factor(struct device *dev,
 
        return hw;
 }
+
+struct clk_hw *clk_hw_register_fixed_factor(struct device *dev,
+               const char *name, const char *parent_name, unsigned long flags,
+               unsigned int mult, unsigned int div)
+{
+       return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, -1,
+                                             flags, mult, div);
+}
 EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor);
 
 struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
@@ -143,11 +159,10 @@ static const struct of_device_id set_rate_parent_matches[] = {
        { /* Sentinel */ },
 };
 
-static struct clk *_of_fixed_factor_clk_setup(struct device_node *node)
+static struct clk_hw *_of_fixed_factor_clk_setup(struct device_node *node)
 {
-       struct clk *clk;
+       struct clk_hw *hw;
        const char *clk_name = node->name;
-       const char *parent_name;
        unsigned long flags = 0;
        u32 div, mult;
        int ret;
@@ -165,30 +180,28 @@ static struct clk *_of_fixed_factor_clk_setup(struct device_node *node)
        }
 
        of_property_read_string(node, "clock-output-names", &clk_name);
-       parent_name = of_clk_get_parent_name(node, 0);
 
        if (of_match_node(set_rate_parent_matches, node))
                flags |= CLK_SET_RATE_PARENT;
 
-       clk = clk_register_fixed_factor(NULL, clk_name, parent_name, flags,
-                                       mult, div);
-       if (IS_ERR(clk)) {
+       hw = __clk_hw_register_fixed_factor(NULL, node, clk_name, NULL, 0,
+                                           flags, mult, div);
+       if (IS_ERR(hw)) {
                /*
-                * If parent clock is not registered, registration would fail.
                 * Clear OF_POPULATED flag so that clock registration can be
                 * attempted again from probe function.
                 */
                of_node_clear_flag(node, OF_POPULATED);
-               return clk;
+               return ERR_CAST(hw);
        }
 
-       ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+       ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw);
        if (ret) {
-               clk_unregister(clk);
+               clk_hw_unregister_fixed_factor(hw);
                return ERR_PTR(ret);
        }
 
-       return clk;
+       return hw;
 }
 
 /**
@@ -203,17 +216,17 @@ CLK_OF_DECLARE(fixed_factor_clk, "fixed-factor-clock",
 
 static int of_fixed_factor_clk_remove(struct platform_device *pdev)
 {
-       struct clk *clk = platform_get_drvdata(pdev);
+       struct clk_hw *clk = platform_get_drvdata(pdev);
 
        of_clk_del_provider(pdev->dev.of_node);
-       clk_unregister_fixed_factor(clk);
+       clk_hw_unregister_fixed_factor(clk);
 
        return 0;
 }
 
 static int of_fixed_factor_clk_probe(struct platform_device *pdev)
 {
-       struct clk *clk;
+       struct clk_hw *clk;
 
        /*
         * This function is not executed when of_fixed_factor_clk_setup
index 00ef4f5e53fe247d946100efcfe5ee93d12fa642..a7e4aef7a37624a2ce2b4829bf15e4aa7deafead 100644 (file)
@@ -68,7 +68,7 @@ struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev,
 
        init.name = name;
        init.ops = &clk_fixed_rate_ops;
-       init.flags = flags | CLK_IS_BASIC;
+       init.flags = flags;
        init.parent_names = (parent_name ? &parent_name: NULL);
        init.num_parents = (parent_name ? 1 : 0);
 
index fdfe2e423d1506e96a059cdb054796dd9c955bd6..d81f1d2e9129887595168be8b36faa9f3f7fde41 100644 (file)
 #include <linux/slab.h>
 #include <linux/rational.h>
 
+static inline u32 clk_fd_readl(struct clk_fractional_divider *fd)
+{
+       if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
+               return ioread32be(fd->reg);
+
+       return readl(fd->reg);
+}
+
+static inline void clk_fd_writel(struct clk_fractional_divider *fd, u32 val)
+{
+       if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
+               iowrite32be(val, fd->reg);
+       else
+               writel(val, fd->reg);
+}
+
 static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
                                        unsigned long parent_rate)
 {
@@ -27,7 +43,7 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
        else
                __acquire(fd->lock);
 
-       val = clk_readl(fd->reg);
+       val = clk_fd_readl(fd);
 
        if (fd->lock)
                spin_unlock_irqrestore(fd->lock, flags);
@@ -115,10 +131,10 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
        else
                __acquire(fd->lock);
 
-       val = clk_readl(fd->reg);
+       val = clk_fd_readl(fd);
        val &= ~(fd->mmask | fd->nmask);
        val |= (m << fd->mshift) | (n << fd->nshift);
-       clk_writel(val, fd->reg);
+       clk_fd_writel(fd, val);
 
        if (fd->lock)
                spin_unlock_irqrestore(fd->lock, flags);
@@ -151,7 +167,7 @@ struct clk_hw *clk_hw_register_fractional_divider(struct device *dev,
 
        init.name = name;
        init.ops = &clk_fractional_divider_ops;
-       init.flags = flags | CLK_IS_BASIC;
+       init.flags = flags;
        init.parent_names = parent_name ? &parent_name : NULL;
        init.num_parents = parent_name ? 1 : 0;
 
index f05823cd9b21117a0dd04f3d86a6a6f658cc983d..1b99fc96274517b61fb0fca61978551e50e837dc 100644 (file)
  * parent - fixed parent.  No clk_set_parent support
  */
 
+static inline u32 clk_gate_readl(struct clk_gate *gate)
+{
+       if (gate->flags & CLK_GATE_BIG_ENDIAN)
+               return ioread32be(gate->reg);
+
+       return readl(gate->reg);
+}
+
+static inline void clk_gate_writel(struct clk_gate *gate, u32 val)
+{
+       if (gate->flags & CLK_GATE_BIG_ENDIAN)
+               iowrite32be(val, gate->reg);
+       else
+               writel(val, gate->reg);
+}
+
 /*
  * It works on following logic:
  *
@@ -55,7 +71,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
                if (set)
                        reg |= BIT(gate->bit_idx);
        } else {
-               reg = clk_readl(gate->reg);
+               reg = clk_gate_readl(gate);
 
                if (set)
                        reg |= BIT(gate->bit_idx);
@@ -63,7 +79,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
                        reg &= ~BIT(gate->bit_idx);
        }
 
-       clk_writel(reg, gate->reg);
+       clk_gate_writel(gate, reg);
 
        if (gate->lock)
                spin_unlock_irqrestore(gate->lock, flags);
@@ -88,7 +104,7 @@ int clk_gate_is_enabled(struct clk_hw *hw)
        u32 reg;
        struct clk_gate *gate = to_clk_gate(hw);
 
-       reg = clk_readl(gate->reg);
+       reg = clk_gate_readl(gate);
 
        /* if a set bit disables this clk, flip it before masking */
        if (gate->flags & CLK_GATE_SET_TO_DISABLE)
@@ -142,7 +158,7 @@ struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name,
 
        init.name = name;
        init.ops = &clk_gate_ops;
-       init.flags = flags | CLK_IS_BASIC;
+       init.flags = flags;
        init.parent_names = parent_name ? &parent_name : NULL;
        init.num_parents = parent_name ? 1 : 0;
 
index c2f07f0d077c7659727cdbe39d0c970821db5c9b..9d930edd651626ac0997dca0d6d78d1fad107aad 100644 (file)
@@ -137,7 +137,7 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name,
 
        init.name = name;
        init.ops = clk_gpio_ops;
-       init.flags = flags | CLK_IS_BASIC;
+       init.flags = flags;
        init.parent_names = parent_names;
        init.num_parents = num_parents;
 
index 8e4581004695c44f11ea66250773c60720f4bbb8..bd328b0eb243e5a0208059533d6aba8527785093 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/err.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -272,7 +271,7 @@ static const struct clk_ops periclk_ops = {
        .set_rate = clk_periclk_set_rate,
 };
 
-static __init struct clk *hb_clk_init(struct device_node *node, const struct clk_ops *ops)
+static void __init hb_clk_init(struct device_node *node, const struct clk_ops *ops, unsigned long clkflags)
 {
        u32 reg;
        struct hb_clk *hb_clk;
@@ -284,11 +283,11 @@ static __init struct clk *hb_clk_init(struct device_node *node, const struct clk
 
        rc = of_property_read_u32(node, "reg", &reg);
        if (WARN_ON(rc))
-               return NULL;
+               return;
 
        hb_clk = kzalloc(sizeof(*hb_clk), GFP_KERNEL);
        if (WARN_ON(!hb_clk))
-               return NULL;
+               return;
 
        /* Map system registers */
        srnp = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
@@ -301,7 +300,7 @@ static __init struct clk *hb_clk_init(struct device_node *node, const struct clk
 
        init.name = clk_name;
        init.ops = ops;
-       init.flags = 0;
+       init.flags = clkflags;
        parent_name = of_clk_get_parent_name(node, 0);
        init.parent_names = &parent_name;
        init.num_parents = 1;
@@ -311,33 +310,31 @@ static __init struct clk *hb_clk_init(struct device_node *node, const struct clk
        rc = clk_hw_register(NULL, &hb_clk->hw);
        if (WARN_ON(rc)) {
                kfree(hb_clk);
-               return NULL;
+               return;
        }
-       rc = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &hb_clk->hw);
-       return hb_clk->hw.clk;
+       of_clk_add_hw_provider(node, of_clk_hw_simple_get, &hb_clk->hw);
 }
 
 static void __init hb_pll_init(struct device_node *node)
 {
-       hb_clk_init(node, &clk_pll_ops);
+       hb_clk_init(node, &clk_pll_ops, 0);
 }
 CLK_OF_DECLARE(hb_pll, "calxeda,hb-pll-clock", hb_pll_init);
 
 static void __init hb_a9periph_init(struct device_node *node)
 {
-       hb_clk_init(node, &a9periphclk_ops);
+       hb_clk_init(node, &a9periphclk_ops, 0);
 }
 CLK_OF_DECLARE(hb_a9periph, "calxeda,hb-a9periph-clock", hb_a9periph_init);
 
 static void __init hb_a9bus_init(struct device_node *node)
 {
-       struct clk *clk = hb_clk_init(node, &a9bclk_ops);
-       clk_prepare_enable(clk);
+       hb_clk_init(node, &a9bclk_ops, CLK_IS_CRITICAL);
 }
 CLK_OF_DECLARE(hb_a9bus, "calxeda,hb-a9bus-clock", hb_a9bus_init);
 
 static void __init hb_emmc_init(struct device_node *node)
 {
-       hb_clk_init(node, &periclk_ops);
+       hb_clk_init(node, &periclk_ops, 0);
 }
 CLK_OF_DECLARE(hb_emmc, "calxeda,hb-emmc-clock", hb_emmc_init);
diff --git a/drivers/clk/clk-lochnagar.c b/drivers/clk/clk-lochnagar.c
new file mode 100644 (file)
index 0000000..a2f31e5
--- /dev/null
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Lochnagar clock control
+ *
+ * Copyright (c) 2017-2018 Cirrus Logic, Inc. and
+ *                         Cirrus Logic International Semiconductor Ltd.
+ *
+ * Author: Charles Keepax <ckeepax@opensource.cirrus.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/lochnagar.h>
+#include <linux/mfd/lochnagar1_regs.h>
+#include <linux/mfd/lochnagar2_regs.h>
+
+#include <dt-bindings/clk/lochnagar.h>
+
+#define LOCHNAGAR_NUM_CLOCKS   (LOCHNAGAR_SPDIF_CLKOUT + 1)
+
+struct lochnagar_clk {
+       const char * const name;
+       struct clk_hw hw;
+
+       struct lochnagar_clk_priv *priv;
+
+       u16 cfg_reg;
+       u16 ena_mask;
+
+       u16 src_reg;
+       u16 src_mask;
+};
+
+struct lochnagar_clk_priv {
+       struct device *dev;
+       struct regmap *regmap;
+       enum lochnagar_type type;
+
+       const char **parents;
+       unsigned int nparents;
+
+       struct lochnagar_clk lclks[LOCHNAGAR_NUM_CLOCKS];
+};
+
+static const char * const lochnagar1_clk_parents[] = {
+       "ln-none",
+       "ln-spdif-mclk",
+       "ln-psia1-mclk",
+       "ln-psia2-mclk",
+       "ln-cdc-clkout",
+       "ln-dsp-clkout",
+       "ln-pmic-32k",
+       "ln-gf-mclk1",
+       "ln-gf-mclk3",
+       "ln-gf-mclk2",
+       "ln-gf-mclk4",
+};
+
+static const char * const lochnagar2_clk_parents[] = {
+       "ln-none",
+       "ln-cdc-clkout",
+       "ln-dsp-clkout",
+       "ln-pmic-32k",
+       "ln-spdif-mclk",
+       "ln-clk-12m",
+       "ln-clk-11m",
+       "ln-clk-24m",
+       "ln-clk-22m",
+       "ln-clk-8m",
+       "ln-usb-clk-24m",
+       "ln-gf-mclk1",
+       "ln-gf-mclk3",
+       "ln-gf-mclk2",
+       "ln-psia1-mclk",
+       "ln-psia2-mclk",
+       "ln-spdif-clkout",
+       "ln-adat-mclk",
+       "ln-usb-clk-12m",
+};
+
+#define LN1_CLK(ID, NAME, REG) \
+       [LOCHNAGAR_##ID] = { \
+               .name = NAME, \
+               .cfg_reg = LOCHNAGAR1_##REG, \
+               .ena_mask = LOCHNAGAR1_##ID##_ENA_MASK, \
+               .src_reg = LOCHNAGAR1_##ID##_SEL, \
+               .src_mask = LOCHNAGAR1_SRC_MASK, \
+       }
+
+#define LN2_CLK(ID, NAME) \
+       [LOCHNAGAR_##ID] = { \
+               .name = NAME, \
+               .cfg_reg = LOCHNAGAR2_##ID##_CTRL, \
+               .src_reg = LOCHNAGAR2_##ID##_CTRL, \
+               .ena_mask = LOCHNAGAR2_CLK_ENA_MASK, \
+               .src_mask = LOCHNAGAR2_CLK_SRC_MASK, \
+       }
+
+static const struct lochnagar_clk lochnagar1_clks[LOCHNAGAR_NUM_CLOCKS] = {
+       LN1_CLK(CDC_MCLK1,      "ln-cdc-mclk1",  CDC_AIF_CTRL2),
+       LN1_CLK(CDC_MCLK2,      "ln-cdc-mclk2",  CDC_AIF_CTRL2),
+       LN1_CLK(DSP_CLKIN,      "ln-dsp-clkin",  DSP_AIF),
+       LN1_CLK(GF_CLKOUT1,     "ln-gf-clkout1", GF_AIF1),
+};
+
+static const struct lochnagar_clk lochnagar2_clks[LOCHNAGAR_NUM_CLOCKS] = {
+       LN2_CLK(CDC_MCLK1,      "ln-cdc-mclk1"),
+       LN2_CLK(CDC_MCLK2,      "ln-cdc-mclk2"),
+       LN2_CLK(DSP_CLKIN,      "ln-dsp-clkin"),
+       LN2_CLK(GF_CLKOUT1,     "ln-gf-clkout1"),
+       LN2_CLK(GF_CLKOUT2,     "ln-gf-clkout2"),
+       LN2_CLK(PSIA1_MCLK,     "ln-psia1-mclk"),
+       LN2_CLK(PSIA2_MCLK,     "ln-psia2-mclk"),
+       LN2_CLK(SPDIF_MCLK,     "ln-spdif-mclk"),
+       LN2_CLK(ADAT_MCLK,      "ln-adat-mclk"),
+       LN2_CLK(SOUNDCARD_MCLK, "ln-soundcard-mclk"),
+};
+
+static inline struct lochnagar_clk *lochnagar_hw_to_lclk(struct clk_hw *hw)
+{
+       return container_of(hw, struct lochnagar_clk, hw);
+}
+
+static int lochnagar_clk_prepare(struct clk_hw *hw)
+{
+       struct lochnagar_clk *lclk = lochnagar_hw_to_lclk(hw);
+       struct lochnagar_clk_priv *priv = lclk->priv;
+       struct regmap *regmap = priv->regmap;
+       int ret;
+
+       ret = regmap_update_bits(regmap, lclk->cfg_reg,
+                                lclk->ena_mask, lclk->ena_mask);
+       if (ret < 0)
+               dev_dbg(priv->dev, "Failed to prepare %s: %d\n",
+                       lclk->name, ret);
+
+       return ret;
+}
+
+static void lochnagar_clk_unprepare(struct clk_hw *hw)
+{
+       struct lochnagar_clk *lclk = lochnagar_hw_to_lclk(hw);
+       struct lochnagar_clk_priv *priv = lclk->priv;
+       struct regmap *regmap = priv->regmap;
+       int ret;
+
+       ret = regmap_update_bits(regmap, lclk->cfg_reg, lclk->ena_mask, 0);
+       if (ret < 0)
+               dev_dbg(priv->dev, "Failed to unprepare %s: %d\n",
+                       lclk->name, ret);
+}
+
+static int lochnagar_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct lochnagar_clk *lclk = lochnagar_hw_to_lclk(hw);
+       struct lochnagar_clk_priv *priv = lclk->priv;
+       struct regmap *regmap = priv->regmap;
+       int ret;
+
+       ret = regmap_update_bits(regmap, lclk->src_reg, lclk->src_mask, index);
+       if (ret < 0)
+               dev_dbg(priv->dev, "Failed to reparent %s: %d\n",
+                       lclk->name, ret);
+
+       return ret;
+}
+
+static u8 lochnagar_clk_get_parent(struct clk_hw *hw)
+{
+       struct lochnagar_clk *lclk = lochnagar_hw_to_lclk(hw);
+       struct lochnagar_clk_priv *priv = lclk->priv;
+       struct regmap *regmap = priv->regmap;
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(regmap, lclk->src_reg, &val);
+       if (ret < 0) {
+               dev_dbg(priv->dev, "Failed to read parent of %s: %d\n",
+                       lclk->name, ret);
+               return priv->nparents;
+       }
+
+       val &= lclk->src_mask;
+
+       return val;
+}
+
+static const struct clk_ops lochnagar_clk_ops = {
+       .prepare = lochnagar_clk_prepare,
+       .unprepare = lochnagar_clk_unprepare,
+       .set_parent = lochnagar_clk_set_parent,
+       .get_parent = lochnagar_clk_get_parent,
+};
+
+static int lochnagar_init_parents(struct lochnagar_clk_priv *priv)
+{
+       struct device_node *np = priv->dev->of_node;
+       int i, j;
+
+       switch (priv->type) {
+       case LOCHNAGAR1:
+               memcpy(priv->lclks, lochnagar1_clks, sizeof(lochnagar1_clks));
+
+               priv->nparents = ARRAY_SIZE(lochnagar1_clk_parents);
+               priv->parents = devm_kmemdup(priv->dev, lochnagar1_clk_parents,
+                                            sizeof(lochnagar1_clk_parents),
+                                            GFP_KERNEL);
+               break;
+       case LOCHNAGAR2:
+               memcpy(priv->lclks, lochnagar2_clks, sizeof(lochnagar2_clks));
+
+               priv->nparents = ARRAY_SIZE(lochnagar2_clk_parents);
+               priv->parents = devm_kmemdup(priv->dev, lochnagar2_clk_parents,
+                                            sizeof(lochnagar2_clk_parents),
+                                            GFP_KERNEL);
+               break;
+       default:
+               dev_err(priv->dev, "Unknown Lochnagar type: %d\n", priv->type);
+               return -EINVAL;
+       }
+
+       if (!priv->parents)
+               return -ENOMEM;
+
+       for (i = 0; i < priv->nparents; i++) {
+               j = of_property_match_string(np, "clock-names",
+                                            priv->parents[i]);
+               if (j >= 0)
+                       priv->parents[i] = of_clk_get_parent_name(np, j);
+       }
+
+       return 0;
+}
+
+static struct clk_hw *
+lochnagar_of_clk_hw_get(struct of_phandle_args *clkspec, void *data)
+{
+       struct lochnagar_clk_priv *priv = data;
+       unsigned int idx = clkspec->args[0];
+
+       if (idx >= ARRAY_SIZE(priv->lclks)) {
+               dev_err(priv->dev, "Invalid index %u\n", idx);
+               return ERR_PTR(-EINVAL);
+       }
+
+       return &priv->lclks[idx].hw;
+}
+
+static int lochnagar_init_clks(struct lochnagar_clk_priv *priv)
+{
+       struct clk_init_data clk_init = {
+               .ops = &lochnagar_clk_ops,
+               .parent_names = priv->parents,
+               .num_parents = priv->nparents,
+       };
+       struct lochnagar_clk *lclk;
+       int ret, i;
+
+       for (i = 0; i < ARRAY_SIZE(priv->lclks); i++) {
+               lclk = &priv->lclks[i];
+
+               if (!lclk->name)
+                       continue;
+
+               clk_init.name = lclk->name;
+
+               lclk->priv = priv;
+               lclk->hw.init = &clk_init;
+
+               ret = devm_clk_hw_register(priv->dev, &lclk->hw);
+               if (ret) {
+                       dev_err(priv->dev, "Failed to register %s: %d\n",
+                               lclk->name, ret);
+                       return ret;
+               }
+       }
+
+       ret = devm_of_clk_add_hw_provider(priv->dev, lochnagar_of_clk_hw_get,
+                                         priv);
+       if (ret < 0)
+               dev_err(priv->dev, "Failed to register provider: %d\n", ret);
+
+       return ret;
+}
+
+static const struct of_device_id lochnagar_of_match[] = {
+       { .compatible = "cirrus,lochnagar1-clk", .data = (void *)LOCHNAGAR1 },
+       { .compatible = "cirrus,lochnagar2-clk", .data = (void *)LOCHNAGAR2 },
+       {}
+};
+MODULE_DEVICE_TABLE(of, lochnagar_of_match);
+
+static int lochnagar_clk_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct lochnagar_clk_priv *priv;
+       const struct of_device_id *of_id;
+       int ret;
+
+       of_id = of_match_device(lochnagar_of_match, dev);
+       if (!of_id)
+               return -EINVAL;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->dev = dev;
+       priv->regmap = dev_get_regmap(dev->parent, NULL);
+       priv->type = (enum lochnagar_type)of_id->data;
+
+       ret = lochnagar_init_parents(priv);
+       if (ret)
+               return ret;
+
+       return lochnagar_init_clks(priv);
+}
+
+static struct platform_driver lochnagar_clk_driver = {
+       .driver = {
+               .name = "lochnagar-clk",
+               .of_match_table = lochnagar_of_match,
+       },
+       .probe = lochnagar_clk_probe,
+};
+module_platform_driver(lochnagar_clk_driver);
+
+MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");
+MODULE_DESCRIPTION("Clock driver for Cirrus Logic Lochnagar Board");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/clk-milbeaut.c b/drivers/clk/clk-milbeaut.c
new file mode 100644 (file)
index 0000000..5fc78fa
--- /dev/null
@@ -0,0 +1,663 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Socionext Inc.
+ * Copyright (C) 2016 Linaro Ltd.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#define M10V_CLKSEL1           0x0
+#define CLKSEL(n)      (((n) - 1) * 4 + M10V_CLKSEL1)
+
+#define M10V_PLL1              "pll1"
+#define M10V_PLL1DIV2          "pll1-2"
+#define M10V_PLL2              "pll2"
+#define M10V_PLL2DIV2          "pll2-2"
+#define M10V_PLL6              "pll6"
+#define M10V_PLL6DIV2          "pll6-2"
+#define M10V_PLL6DIV3          "pll6-3"
+#define M10V_PLL7              "pll7"
+#define M10V_PLL7DIV2          "pll7-2"
+#define M10V_PLL7DIV5          "pll7-5"
+#define M10V_PLL9              "pll9"
+#define M10V_PLL10             "pll10"
+#define M10V_PLL10DIV2         "pll10-2"
+#define M10V_PLL11             "pll11"
+
+#define M10V_SPI_PARENT0       "spi-parent0"
+#define M10V_SPI_PARENT1       "spi-parent1"
+#define M10V_SPI_PARENT2       "spi-parent2"
+#define M10V_UHS1CLK2_PARENT0  "uhs1clk2-parent0"
+#define M10V_UHS1CLK2_PARENT1  "uhs1clk2-parent1"
+#define M10V_UHS1CLK2_PARENT2  "uhs1clk2-parent2"
+#define M10V_UHS1CLK1_PARENT0  "uhs1clk1-parent0"
+#define M10V_UHS1CLK1_PARENT1  "uhs1clk1-parent1"
+#define M10V_NFCLK_PARENT0     "nfclk-parent0"
+#define M10V_NFCLK_PARENT1     "nfclk-parent1"
+#define M10V_NFCLK_PARENT2     "nfclk-parent2"
+#define M10V_NFCLK_PARENT3     "nfclk-parent3"
+#define M10V_NFCLK_PARENT4     "nfclk-parent4"
+#define M10V_NFCLK_PARENT5     "nfclk-parent5"
+
+#define M10V_DCHREQ            1
+#define M10V_UPOLL_RATE                1
+#define M10V_UTIMEOUT          250
+
+#define M10V_EMMCCLK_ID                0
+#define M10V_ACLK_ID           1
+#define M10V_HCLK_ID           2
+#define M10V_PCLK_ID           3
+#define M10V_RCLK_ID           4
+#define M10V_SPICLK_ID         5
+#define M10V_NFCLK_ID          6
+#define M10V_UHS1CLK2_ID       7
+#define M10V_NUM_CLKS          8
+
+#define to_m10v_div(_hw)        container_of(_hw, struct m10v_clk_divider, hw)
+
+static struct clk_hw_onecell_data *m10v_clk_data;
+
+static DEFINE_SPINLOCK(m10v_crglock);
+
+struct m10v_clk_div_factors {
+       const char                      *name;
+       const char                      *parent_name;
+       u32                             offset;
+       u8                              shift;
+       u8                              width;
+       const struct clk_div_table      *table;
+       unsigned long                   div_flags;
+       int                             onecell_idx;
+};
+
+struct m10v_clk_div_fixed_data {
+       const char      *name;
+       const char      *parent_name;
+       u8              div;
+       u8              mult;
+       int             onecell_idx;
+};
+
+struct m10v_clk_mux_factors {
+       const char              *name;
+       const char * const      *parent_names;
+       u8                      num_parents;
+       u32                     offset;
+       u8                      shift;
+       u8                      mask;
+       u32                     *table;
+       unsigned long           mux_flags;
+       int                     onecell_idx;
+};
+
+static const struct clk_div_table emmcclk_table[] = {
+       { .val = 0, .div = 8 },
+       { .val = 1, .div = 9 },
+       { .val = 2, .div = 10 },
+       { .val = 3, .div = 15 },
+       { .div = 0 },
+};
+
+static const struct clk_div_table mclk400_table[] = {
+       { .val = 1, .div = 2 },
+       { .val = 3, .div = 4 },
+       { .div = 0 },
+};
+
+static const struct clk_div_table mclk200_table[] = {
+       { .val = 3, .div = 4 },
+       { .val = 7, .div = 8 },
+       { .div = 0 },
+};
+
+static const struct clk_div_table aclk400_table[] = {
+       { .val = 1, .div = 2 },
+       { .val = 3, .div = 4 },
+       { .div = 0 },
+};
+
+static const struct clk_div_table aclk300_table[] = {
+       { .val = 0, .div = 2 },
+       { .val = 1, .div = 3 },
+       { .div = 0 },
+};
+
+static const struct clk_div_table aclk_table[] = {
+       { .val = 3, .div = 4 },
+       { .val = 7, .div = 8 },
+       { .div = 0 },
+};
+
+static const struct clk_div_table aclkexs_table[] = {
+       { .val = 3, .div = 4 },
+       { .val = 4, .div = 5 },
+       { .val = 5, .div = 6 },
+       { .val = 7, .div = 8 },
+       { .div = 0 },
+};
+
+static const struct clk_div_table hclk_table[] = {
+       { .val = 7, .div = 8 },
+       { .val = 15, .div = 16 },
+       { .div = 0 },
+};
+
+static const struct clk_div_table hclkbmh_table[] = {
+       { .val = 3, .div = 4 },
+       { .val = 7, .div = 8 },
+       { .div = 0 },
+};
+
+static const struct clk_div_table pclk_table[] = {
+       { .val = 15, .div = 16 },
+       { .val = 31, .div = 32 },
+       { .div = 0 },
+};
+
+static const struct clk_div_table rclk_table[] = {
+       { .val = 0, .div = 8 },
+       { .val = 1, .div = 16 },
+       { .val = 2, .div = 24 },
+       { .val = 3, .div = 32 },
+       { .div = 0 },
+};
+
+static const struct clk_div_table uhs1clk0_table[] = {
+       { .val = 0, .div = 2 },
+       { .val = 1, .div = 3 },
+       { .val = 2, .div = 4 },
+       { .val = 3, .div = 8 },
+       { .val = 4, .div = 16 },
+       { .div = 0 },
+};
+
+static const struct clk_div_table uhs2clk_table[] = {
+       { .val = 0, .div = 9 },
+       { .val = 1, .div = 10 },
+       { .val = 2, .div = 11 },
+       { .val = 3, .div = 12 },
+       { .val = 4, .div = 13 },
+       { .val = 5, .div = 14 },
+       { .val = 6, .div = 16 },
+       { .val = 7, .div = 18 },
+       { .div = 0 },
+};
+
+static u32 spi_mux_table[] = {0, 1, 2};
+static const char * const spi_mux_names[] = {
+       M10V_SPI_PARENT0, M10V_SPI_PARENT1, M10V_SPI_PARENT2
+};
+
+static u32 uhs1clk2_mux_table[] = {2, 3, 4, 8};
+static const char * const uhs1clk2_mux_names[] = {
+       M10V_UHS1CLK2_PARENT0, M10V_UHS1CLK2_PARENT1,
+       M10V_UHS1CLK2_PARENT2, M10V_PLL6DIV2
+};
+
+static u32 uhs1clk1_mux_table[] = {3, 4, 8};
+static const char * const uhs1clk1_mux_names[] = {
+       M10V_UHS1CLK1_PARENT0, M10V_UHS1CLK1_PARENT1, M10V_PLL6DIV2
+};
+
+static u32 nfclk_mux_table[] = {0, 1, 2, 3, 4, 8};
+static const char * const nfclk_mux_names[] = {
+       M10V_NFCLK_PARENT0, M10V_NFCLK_PARENT1, M10V_NFCLK_PARENT2,
+       M10V_NFCLK_PARENT3, M10V_NFCLK_PARENT4, M10V_NFCLK_PARENT5
+};
+
+static const struct m10v_clk_div_fixed_data m10v_pll_fixed_data[] = {
+       {M10V_PLL1, NULL, 1, 40, -1},
+       {M10V_PLL2, NULL, 1, 30, -1},
+       {M10V_PLL6, NULL, 1, 35, -1},
+       {M10V_PLL7, NULL, 1, 40, -1},
+       {M10V_PLL9, NULL, 1, 33, -1},
+       {M10V_PLL10, NULL, 5, 108, -1},
+       {M10V_PLL10DIV2, M10V_PLL10, 2, 1, -1},
+       {M10V_PLL11, NULL, 2, 75, -1},
+};
+
+static const struct m10v_clk_div_fixed_data m10v_div_fixed_data[] = {
+       {"usb2", NULL, 2, 1, -1},
+       {"pcisuppclk", NULL, 20, 1, -1},
+       {M10V_PLL1DIV2, M10V_PLL1, 2, 1, -1},
+       {M10V_PLL2DIV2, M10V_PLL2, 2, 1, -1},
+       {M10V_PLL6DIV2, M10V_PLL6, 2, 1, -1},
+       {M10V_PLL6DIV3, M10V_PLL6, 3, 1, -1},
+       {M10V_PLL7DIV2, M10V_PLL7, 2, 1, -1},
+       {M10V_PLL7DIV5, M10V_PLL7, 5, 1, -1},
+       {"ca7wd", M10V_PLL2DIV2, 12, 1, -1},
+       {"pclkca7wd", M10V_PLL1DIV2, 16, 1, -1},
+       {M10V_SPI_PARENT0, M10V_PLL10DIV2, 2, 1, -1},
+       {M10V_SPI_PARENT1, M10V_PLL10DIV2, 4, 1, -1},
+       {M10V_SPI_PARENT2, M10V_PLL7DIV2, 8, 1, -1},
+       {M10V_UHS1CLK2_PARENT0, M10V_PLL7, 4, 1, -1},
+       {M10V_UHS1CLK2_PARENT1, M10V_PLL7, 8, 1, -1},
+       {M10V_UHS1CLK2_PARENT2, M10V_PLL7, 16, 1, -1},
+       {M10V_UHS1CLK1_PARENT0, M10V_PLL7, 8, 1, -1},
+       {M10V_UHS1CLK1_PARENT1, M10V_PLL7, 16, 1, -1},
+       {M10V_NFCLK_PARENT0, M10V_PLL7DIV2, 8, 1, -1},
+       {M10V_NFCLK_PARENT1, M10V_PLL7DIV2, 10, 1, -1},
+       {M10V_NFCLK_PARENT2, M10V_PLL7DIV2, 13, 1, -1},
+       {M10V_NFCLK_PARENT3, M10V_PLL7DIV2, 16, 1, -1},
+       {M10V_NFCLK_PARENT4, M10V_PLL7DIV2, 40, 1, -1},
+       {M10V_NFCLK_PARENT5, M10V_PLL7DIV5, 10, 1, -1},
+};
+
+static const struct m10v_clk_div_factors m10v_div_factor_data[] = {
+       {"emmc", M10V_PLL11, CLKSEL(1), 28, 3, emmcclk_table, 0,
+               M10V_EMMCCLK_ID},
+       {"mclk400", M10V_PLL1DIV2, CLKSEL(10), 7, 3, mclk400_table, 0, -1},
+       {"mclk200", M10V_PLL1DIV2, CLKSEL(10), 3, 4, mclk200_table, 0, -1},
+       {"aclk400", M10V_PLL1DIV2, CLKSEL(10), 0, 3, aclk400_table, 0, -1},
+       {"aclk300", M10V_PLL2DIV2, CLKSEL(12), 0, 2, aclk300_table, 0, -1},
+       {"aclk", M10V_PLL1DIV2, CLKSEL(9), 20, 4, aclk_table, 0, M10V_ACLK_ID},
+       {"aclkexs", M10V_PLL1DIV2, CLKSEL(9), 16, 4, aclkexs_table, 0, -1},
+       {"hclk", M10V_PLL1DIV2, CLKSEL(9), 7, 5, hclk_table, 0, M10V_HCLK_ID},
+       {"hclkbmh", M10V_PLL1DIV2, CLKSEL(9), 12, 4, hclkbmh_table, 0, -1},
+       {"pclk", M10V_PLL1DIV2, CLKSEL(9), 0, 7, pclk_table, 0, M10V_PCLK_ID},
+       {"uhs1clk0", M10V_PLL7, CLKSEL(1), 3, 5, uhs1clk0_table, 0, -1},
+       {"uhs2clk", M10V_PLL6DIV3, CLKSEL(1), 18, 4, uhs2clk_table, 0, -1},
+};
+
+static const struct m10v_clk_mux_factors m10v_mux_factor_data[] = {
+       {"spi", spi_mux_names, ARRAY_SIZE(spi_mux_names),
+               CLKSEL(8), 3, 7, spi_mux_table, 0, M10V_SPICLK_ID},
+       {"uhs1clk2", uhs1clk2_mux_names, ARRAY_SIZE(uhs1clk2_mux_names),
+               CLKSEL(1), 13, 31, uhs1clk2_mux_table, 0, M10V_UHS1CLK2_ID},
+       {"uhs1clk1", uhs1clk1_mux_names, ARRAY_SIZE(uhs1clk1_mux_names),
+               CLKSEL(1), 8, 31, uhs1clk1_mux_table, 0, -1},
+       {"nfclk", nfclk_mux_names, ARRAY_SIZE(nfclk_mux_names),
+               CLKSEL(1), 22, 127, nfclk_mux_table, 0, M10V_NFCLK_ID},
+};
+
+static u8 m10v_mux_get_parent(struct clk_hw *hw)
+{
+       struct clk_mux *mux = to_clk_mux(hw);
+       u32 val;
+
+       val = readl(mux->reg) >> mux->shift;
+       val &= mux->mask;
+
+       return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
+}
+
+static int m10v_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct clk_mux *mux = to_clk_mux(hw);
+       u32 val = clk_mux_index_to_val(mux->table, mux->flags, index);
+       unsigned long flags = 0;
+       u32 reg;
+       u32 write_en = BIT(fls(mux->mask) - 1);
+
+       if (mux->lock)
+               spin_lock_irqsave(mux->lock, flags);
+       else
+               __acquire(mux->lock);
+
+       reg = readl(mux->reg);
+       reg &= ~(mux->mask << mux->shift);
+
+       val = (val | write_en) << mux->shift;
+       reg |= val;
+       writel(reg, mux->reg);
+
+       if (mux->lock)
+               spin_unlock_irqrestore(mux->lock, flags);
+       else
+               __release(mux->lock);
+
+       return 0;
+}
+
+static const struct clk_ops m10v_mux_ops = {
+       .get_parent = m10v_mux_get_parent,
+       .set_parent = m10v_mux_set_parent,
+       .determine_rate = __clk_mux_determine_rate,
+};
+
+static struct clk_hw *m10v_clk_hw_register_mux(struct device *dev,
+                       const char *name, const char * const *parent_names,
+                       u8 num_parents, unsigned long flags, void __iomem *reg,
+                       u8 shift, u32 mask, u8 clk_mux_flags, u32 *table,
+                       spinlock_t *lock)
+{
+       struct clk_mux *mux;
+       struct clk_hw *hw;
+       struct clk_init_data init;
+       int ret;
+
+       mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+       if (!mux)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &m10v_mux_ops;
+       init.flags = flags;
+       init.parent_names = parent_names;
+       init.num_parents = num_parents;
+
+       mux->reg = reg;
+       mux->shift = shift;
+       mux->mask = mask;
+       mux->flags = clk_mux_flags;
+       mux->lock = lock;
+       mux->table = table;
+       mux->hw.init = &init;
+
+       hw = &mux->hw;
+       ret = clk_hw_register(dev, hw);
+       if (ret) {
+               kfree(mux);
+               hw = ERR_PTR(ret);
+       }
+
+       return hw;
+
+}
+
+struct m10v_clk_divider {
+       struct clk_hw   hw;
+       void __iomem    *reg;
+       u8              shift;
+       u8              width;
+       u8              flags;
+       const struct clk_div_table      *table;
+       spinlock_t      *lock;
+       void __iomem    *write_valid_reg;
+};
+
+static unsigned long m10v_clk_divider_recalc_rate(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       struct m10v_clk_divider *divider = to_m10v_div(hw);
+       unsigned int val;
+
+       val = readl(divider->reg) >> divider->shift;
+       val &= clk_div_mask(divider->width);
+
+       return divider_recalc_rate(hw, parent_rate, val, divider->table,
+                                  divider->flags, divider->width);
+}
+
+static long m10v_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long *prate)
+{
+       struct m10v_clk_divider *divider = to_m10v_div(hw);
+
+       /* if read only, just return current value */
+       if (divider->flags & CLK_DIVIDER_READ_ONLY) {
+               u32 val;
+
+               val = readl(divider->reg) >> divider->shift;
+               val &= clk_div_mask(divider->width);
+
+               return divider_ro_round_rate(hw, rate, prate, divider->table,
+                                            divider->width, divider->flags,
+                                            val);
+       }
+
+       return divider_round_rate(hw, rate, prate, divider->table,
+                                 divider->width, divider->flags);
+}
+
+static int m10v_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct m10v_clk_divider *divider = to_m10v_div(hw);
+       int value;
+       unsigned long flags = 0;
+       u32 val;
+       u32 write_en = BIT(divider->width - 1);
+
+       value = divider_get_val(rate, parent_rate, divider->table,
+                               divider->width, divider->flags);
+       if (value < 0)
+               return value;
+
+       if (divider->lock)
+               spin_lock_irqsave(divider->lock, flags);
+       else
+               __acquire(divider->lock);
+
+       val = readl(divider->reg);
+       val &= ~(clk_div_mask(divider->width) << divider->shift);
+
+       val |= ((u32)value | write_en) << divider->shift;
+       writel(val, divider->reg);
+
+       if (divider->write_valid_reg) {
+               writel(M10V_DCHREQ, divider->write_valid_reg);
+               if (readl_poll_timeout(divider->write_valid_reg, val,
+                       !val, M10V_UPOLL_RATE, M10V_UTIMEOUT))
+                       pr_err("%s:%s couldn't stabilize\n",
+                               __func__, divider->hw.init->name);
+       }
+
+       if (divider->lock)
+               spin_unlock_irqrestore(divider->lock, flags);
+       else
+               __release(divider->lock);
+
+       return 0;
+}
+
+static const struct clk_ops m10v_clk_divider_ops = {
+       .recalc_rate = m10v_clk_divider_recalc_rate,
+       .round_rate = m10v_clk_divider_round_rate,
+       .set_rate = m10v_clk_divider_set_rate,
+};
+
+static struct clk_hw *m10v_clk_hw_register_divider(struct device *dev,
+               const char *name, const char *parent_name, unsigned long flags,
+               void __iomem *reg, u8 shift, u8 width,
+               u8 clk_divider_flags, const struct clk_div_table *table,
+               spinlock_t *lock, void __iomem *write_valid_reg)
+{
+       struct m10v_clk_divider *div;
+       struct clk_hw *hw;
+       struct clk_init_data init;
+       int ret;
+
+       div = kzalloc(sizeof(*div), GFP_KERNEL);
+       if (!div)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &m10v_clk_divider_ops;
+       init.flags = flags;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       div->reg = reg;
+       div->shift = shift;
+       div->width = width;
+       div->flags = clk_divider_flags;
+       div->lock = lock;
+       div->hw.init = &init;
+       div->table = table;
+       div->write_valid_reg = write_valid_reg;
+
+       /* register the clock */
+       hw = &div->hw;
+       ret = clk_hw_register(dev, hw);
+       if (ret) {
+               kfree(div);
+               hw = ERR_PTR(ret);
+       }
+
+       return hw;
+}
+
+static void m10v_reg_div_pre(const struct m10v_clk_div_factors *factors,
+                            struct clk_hw_onecell_data *clk_data,
+                            void __iomem *base)
+{
+       struct clk_hw *hw;
+       void __iomem *write_valid_reg;
+
+       /*
+        * The registers on CLKSEL(9) or CLKSEL(10) need additional
+        * writing to become valid.
+        */
+       if ((factors->offset == CLKSEL(9)) || (factors->offset == CLKSEL(10)))
+               write_valid_reg = base + CLKSEL(11);
+       else
+               write_valid_reg = NULL;
+
+       hw = m10v_clk_hw_register_divider(NULL, factors->name,
+                                         factors->parent_name,
+                                         CLK_SET_RATE_PARENT,
+                                         base + factors->offset,
+                                         factors->shift,
+                                         factors->width, factors->div_flags,
+                                         factors->table,
+                                         &m10v_crglock, write_valid_reg);
+
+       if (factors->onecell_idx >= 0)
+               clk_data->hws[factors->onecell_idx] = hw;
+}
+
+static void m10v_reg_fixed_pre(const struct m10v_clk_div_fixed_data *factors,
+                              struct clk_hw_onecell_data *clk_data,
+                              const char *parent_name)
+{
+       struct clk_hw *hw;
+       const char *pn = factors->parent_name ?
+                               factors->parent_name : parent_name;
+
+       hw = clk_hw_register_fixed_factor(NULL, factors->name, pn, 0,
+                                         factors->mult, factors->div);
+
+       if (factors->onecell_idx >= 0)
+               clk_data->hws[factors->onecell_idx] = hw;
+}
+
+static void m10v_reg_mux_pre(const struct m10v_clk_mux_factors *factors,
+                              struct clk_hw_onecell_data *clk_data,
+                              void __iomem *base)
+{
+       struct clk_hw *hw;
+
+       hw = m10v_clk_hw_register_mux(NULL, factors->name,
+                                     factors->parent_names,
+                                     factors->num_parents,
+                                     CLK_SET_RATE_PARENT,
+                                     base + factors->offset, factors->shift,
+                                     factors->mask, factors->mux_flags,
+                                     factors->table, &m10v_crglock);
+
+       if (factors->onecell_idx >= 0)
+               clk_data->hws[factors->onecell_idx] = hw;
+}
+
+static int m10v_clk_probe(struct platform_device *pdev)
+{
+       int id;
+       struct resource *res;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       void __iomem *base;
+       const char *parent_name;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       parent_name = of_clk_get_parent_name(np, 0);
+
+       for (id = 0; id < ARRAY_SIZE(m10v_div_factor_data); ++id)
+               m10v_reg_div_pre(&m10v_div_factor_data[id],
+                                m10v_clk_data, base);
+
+       for (id = 0; id < ARRAY_SIZE(m10v_div_fixed_data); ++id)
+               m10v_reg_fixed_pre(&m10v_div_fixed_data[id],
+                                  m10v_clk_data, parent_name);
+
+       for (id = 0; id < ARRAY_SIZE(m10v_mux_factor_data); ++id)
+               m10v_reg_mux_pre(&m10v_mux_factor_data[id],
+                                m10v_clk_data, base);
+
+       for (id = 0; id < M10V_NUM_CLKS; id++) {
+               if (IS_ERR(m10v_clk_data->hws[id]))
+                       return PTR_ERR(m10v_clk_data->hws[id]);
+       }
+
+       return 0;
+}
+
+static const struct of_device_id m10v_clk_dt_ids[] = {
+       { .compatible = "socionext,milbeaut-m10v-ccu", },
+       { }
+};
+
+static struct platform_driver m10v_clk_driver = {
+       .probe  = m10v_clk_probe,
+       .driver = {
+               .name = "m10v-ccu",
+               .of_match_table = m10v_clk_dt_ids,
+       },
+};
+builtin_platform_driver(m10v_clk_driver);
+
+static void __init m10v_cc_init(struct device_node *np)
+{
+       int id;
+       void __iomem *base;
+       const char *parent_name;
+       struct clk_hw *hw;
+
+       m10v_clk_data = kzalloc(struct_size(m10v_clk_data, hws,
+                                       M10V_NUM_CLKS),
+                                       GFP_KERNEL);
+
+       if (!m10v_clk_data)
+               return;
+
+       base = of_iomap(np, 0);
+       if (!base) {
+               kfree(m10v_clk_data);
+               return;
+       }
+
+       parent_name = of_clk_get_parent_name(np, 0);
+       if (!parent_name) {
+               kfree(m10v_clk_data);
+               iounmap(base);
+               return;
+       }
+
+       /*
+        * This way all clocks fetched before the platform device probes,
+        * except those we assign here for early use, will be deferred.
+        */
+       for (id = 0; id < M10V_NUM_CLKS; id++)
+               m10v_clk_data->hws[id] = ERR_PTR(-EPROBE_DEFER);
+
+       /*
+        * PLLs are set by bootloader so this driver registers them as the
+        * fixed factor.
+        */
+       for (id = 0; id < ARRAY_SIZE(m10v_pll_fixed_data); ++id)
+               m10v_reg_fixed_pre(&m10v_pll_fixed_data[id],
+                                  m10v_clk_data, parent_name);
+
+       /*
+        * timer consumes "rclk" so it needs to register here.
+        */
+       hw = m10v_clk_hw_register_divider(NULL, "rclk", M10V_PLL10DIV2, 0,
+                                       base + CLKSEL(1), 0, 3, 0, rclk_table,
+                                       &m10v_crglock, NULL);
+       m10v_clk_data->hws[M10V_RCLK_ID] = hw;
+
+       m10v_clk_data->num = M10V_NUM_CLKS;
+       of_clk_add_hw_provider(np, of_clk_hw_onecell_get, m10v_clk_data);
+}
+CLK_OF_DECLARE_DRIVER(m10v_cc, "socionext,milbeaut-m10v-ccu", m10v_cc_init);
index 3c86f859c199f4f19b43d6fadaa483bffab5797e..94470b4eadf41e94f4ea95cf0c337dbc66c079e7 100644 (file)
 #include <linux/of.h>
 #include <linux/slab.h>
 
+static inline u32 clk_mult_readl(struct clk_multiplier *mult)
+{
+       if (mult->flags & CLK_MULTIPLIER_BIG_ENDIAN)
+               return ioread32be(mult->reg);
+
+       return readl(mult->reg);
+}
+
+static inline void clk_mult_writel(struct clk_multiplier *mult, u32 val)
+{
+       if (mult->flags & CLK_MULTIPLIER_BIG_ENDIAN)
+               iowrite32be(val, mult->reg);
+       else
+               writel(val, mult->reg);
+}
+
 static unsigned long __get_mult(struct clk_multiplier *mult,
                                unsigned long rate,
                                unsigned long parent_rate)
@@ -27,7 +43,7 @@ static unsigned long clk_multiplier_recalc_rate(struct clk_hw *hw,
        struct clk_multiplier *mult = to_clk_multiplier(hw);
        unsigned long val;
 
-       val = clk_readl(mult->reg) >> mult->shift;
+       val = clk_mult_readl(mult) >> mult->shift;
        val &= GENMASK(mult->width - 1, 0);
 
        if (!val && mult->flags & CLK_MULTIPLIER_ZERO_BYPASS)
@@ -118,10 +134,10 @@ static int clk_multiplier_set_rate(struct clk_hw *hw, unsigned long rate,
        else
                __acquire(mult->lock);
 
-       val = clk_readl(mult->reg);
+       val = clk_mult_readl(mult);
        val &= ~GENMASK(mult->width + mult->shift - 1, mult->shift);
        val |= factor << mult->shift;
-       clk_writel(val, mult->reg);
+       clk_mult_writel(mult, val);
 
        if (mult->lock)
                spin_unlock_irqrestore(mult->lock, flags);
index 2ad2df2e890933ac11483eac7673a9e7da6b19dd..66e91f740508bd3ba996ffe0e67d2c40d55cb869 100644 (file)
  * parent - parent is adjustable through clk_set_parent
  */
 
+static inline u32 clk_mux_readl(struct clk_mux *mux)
+{
+       if (mux->flags & CLK_MUX_BIG_ENDIAN)
+               return ioread32be(mux->reg);
+
+       return readl(mux->reg);
+}
+
+static inline void clk_mux_writel(struct clk_mux *mux, u32 val)
+{
+       if (mux->flags & CLK_MUX_BIG_ENDIAN)
+               iowrite32be(val, mux->reg);
+       else
+               writel(val, mux->reg);
+}
+
 int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
                         unsigned int val)
 {
@@ -73,7 +89,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
        struct clk_mux *mux = to_clk_mux(hw);
        u32 val;
 
-       val = clk_readl(mux->reg) >> mux->shift;
+       val = clk_mux_readl(mux) >> mux->shift;
        val &= mux->mask;
 
        return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
@@ -94,12 +110,12 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
        if (mux->flags & CLK_MUX_HIWORD_MASK) {
                reg = mux->mask << (mux->shift + 16);
        } else {
-               reg = clk_readl(mux->reg);
+               reg = clk_mux_readl(mux);
                reg &= ~(mux->mask << mux->shift);
        }
        val = val << mux->shift;
        reg |= val;
-       clk_writel(reg, mux->reg);
+       clk_mux_writel(mux, reg);
 
        if (mux->lock)
                spin_unlock_irqrestore(mux->lock, flags);
@@ -159,7 +175,7 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
                init.ops = &clk_mux_ro_ops;
        else
                init.ops = &clk_mux_ops;
-       init.flags = flags | CLK_IS_BASIC;
+       init.flags = flags;
        init.parent_names = parent_names;
        init.num_parents = num_parents;
 
index 8cb9d117fdbf91dfd6625edeac4b42020413542c..02b472a1f9b0145b0b7ed70171ccbcc5d9b4bde1 100644 (file)
@@ -101,7 +101,7 @@ static int clk_pwm_probe(struct platform_device *pdev)
 
        init.name = clk_name;
        init.ops = &clk_pwm_ops;
-       init.flags = CLK_IS_BASIC;
+       init.flags = 0;
        init.num_parents = 0;
 
        clk_pwm->pwm = pwm;
index 1212a9be7e80f0d389b00670b1b345f409b63448..4739a47ec8bd5b4f5a581ab49702f8bb8642e86e 100644 (file)
@@ -34,6 +34,7 @@
 #define CGA_PLL4       4       /* only on clockgen-1.0, which lacks CGB */
 #define CGB_PLL1       4
 #define CGB_PLL2       5
+#define MAX_PLL_DIV    16
 
 struct clockgen_pll_div {
        struct clk *clk;
@@ -41,7 +42,7 @@ struct clockgen_pll_div {
 };
 
 struct clockgen_pll {
-       struct clockgen_pll_div div[8];
+       struct clockgen_pll_div div[MAX_PLL_DIV];
 };
 
 #define CLKSEL_VALID   1
@@ -79,7 +80,7 @@ struct clockgen_chipinfo {
        const struct clockgen_muxinfo *cmux_groups[2];
        const struct clockgen_muxinfo *hwaccel[NUM_HWACCEL];
        void (*init_periph)(struct clockgen *cg);
-       int cmux_to_group[NUM_CMUX]; /* -1 terminates if fewer than NUM_CMUX */
+       int cmux_to_group[NUM_CMUX + 1]; /* array should be -1 terminated */
        u32 pll_mask;   /* 1 << n bit set if PLL n is valid */
        u32 flags;      /* CG_xxx */
 };
@@ -245,6 +246,58 @@ static const struct clockgen_muxinfo clockgen2_cmux_cgb = {
        },
 };
 
+static const struct clockgen_muxinfo ls1028a_hwa1 = {
+       {
+               { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+               {},
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+       },
+};
+
+static const struct clockgen_muxinfo ls1028a_hwa2 = {
+       {
+               { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+               {},
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+       },
+};
+
+static const struct clockgen_muxinfo ls1028a_hwa3 = {
+       {
+               { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+               {},
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+       },
+};
+
+static const struct clockgen_muxinfo ls1028a_hwa4 = {
+       {
+               { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+               { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+               {},
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+               { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+       },
+};
+
 static const struct clockgen_muxinfo ls1043a_hwa1 = {
        {
                {},
@@ -507,6 +560,21 @@ static const struct clockgen_chipinfo chipinfo[] = {
                },
                .pll_mask = 0x03,
        },
+       {
+               .compat = "fsl,ls1028a-clockgen",
+               .cmux_groups = {
+                       &clockgen2_cmux_cga12
+               },
+               .hwaccel = {
+                       &ls1028a_hwa1, &ls1028a_hwa2,
+                       &ls1028a_hwa3, &ls1028a_hwa4
+               },
+               .cmux_to_group = {
+                       0, 0, 0, 0, -1
+               },
+               .pll_mask = 0x07,
+               .flags = CG_VER3 | CG_LITTLE_ENDIAN,
+       },
        {
                .compat = "fsl,ls1043a-clockgen",
                .init_periph = t2080_init_periph,
@@ -601,7 +669,7 @@ static const struct clockgen_chipinfo chipinfo[] = {
                        &p4080_cmux_grp1, &p4080_cmux_grp2
                },
                .cmux_to_group = {
-                       0, 0, 0, 0, 1, 1, 1, 1
+                       0, 0, 0, 0, 1, 1, 1, 1, -1
                },
                .pll_mask = 0x1f,
        },
@@ -1128,7 +1196,7 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
                int ret;
 
                /*
-                * For platform PLL, there are 8 divider clocks.
+                * For platform PLL, there are MAX_PLL_DIV divider clocks.
                 * For core PLL, there are 4 divider clocks at most.
                 */
                if (idx != PLATFORM_PLL && i >= 4)
@@ -1423,6 +1491,7 @@ CLK_OF_DECLARE(qoriq_clockgen_b4420, "fsl,b4420-clockgen", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_b4860, "fsl,b4860-clockgen", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_ls1012a, "fsl,ls1012a-clockgen", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls1028a, "fsl,ls1028a-clockgen", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_ls1046a, "fsl,ls1046a-clockgen", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_ls1088a, "fsl,ls1088a-clockgen", clockgen_init);
index cdaa567c8042eea0e5ee29ec7775bdc97e295a3d..fdac33a9be2f67bd5f458b86d427813386ed08e7 100644 (file)
@@ -300,6 +300,85 @@ static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
        { STM32F4_RCC_APB2ENR, 26,      "ltdc",         "apb2_div" },
 };
 
+static const struct stm32f4_gate_data stm32f769_gates[] __initconst = {
+       { STM32F4_RCC_AHB1ENR,  0,      "gpioa",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  1,      "gpiob",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  2,      "gpioc",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  3,      "gpiod",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  4,      "gpioe",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  5,      "gpiof",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  6,      "gpiog",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  7,      "gpioh",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  8,      "gpioi",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR,  9,      "gpioj",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 10,      "gpiok",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 12,      "crc",          "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 18,      "bkpsra",       "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 20,      "dtcmram",      "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 21,      "dma1",         "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 22,      "dma2",         "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 23,      "dma2d",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 25,      "ethmac",       "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 26,      "ethmactx",     "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 27,      "ethmacrx",     "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 28,      "ethmacptp",    "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 29,      "otghs",        "ahb_div" },
+       { STM32F4_RCC_AHB1ENR, 30,      "otghsulpi",    "ahb_div" },
+
+       { STM32F4_RCC_AHB2ENR,  0,      "dcmi",         "ahb_div" },
+       { STM32F4_RCC_AHB2ENR,  1,      "jpeg",         "ahb_div" },
+       { STM32F4_RCC_AHB2ENR,  4,      "cryp",         "ahb_div" },
+       { STM32F4_RCC_AHB2ENR,  5,      "hash",         "ahb_div" },
+       { STM32F4_RCC_AHB2ENR,  6,      "rng",          "pll48"   },
+       { STM32F4_RCC_AHB2ENR,  7,      "otgfs",        "pll48"   },
+
+       { STM32F4_RCC_AHB3ENR,  0,      "fmc",          "ahb_div",
+               CLK_IGNORE_UNUSED },
+       { STM32F4_RCC_AHB3ENR,  1,      "qspi",         "ahb_div",
+               CLK_IGNORE_UNUSED },
+
+       { STM32F4_RCC_APB1ENR,  0,      "tim2",         "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  1,      "tim3",         "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  2,      "tim4",         "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  3,      "tim5",         "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  4,      "tim6",         "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  5,      "tim7",         "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  6,      "tim12",        "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  7,      "tim13",        "apb1_mul" },
+       { STM32F4_RCC_APB1ENR,  8,      "tim14",        "apb1_mul" },
+       { STM32F4_RCC_APB1ENR, 10,      "rtcapb",       "apb1_mul" },
+       { STM32F4_RCC_APB1ENR, 11,      "wwdg",         "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 13,      "can3",         "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 14,      "spi2",         "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 15,      "spi3",         "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 16,      "spdifrx",      "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 25,      "can1",         "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 26,      "can2",         "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 27,      "cec",          "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 28,      "pwr",          "apb1_div" },
+       { STM32F4_RCC_APB1ENR, 29,      "dac",          "apb1_div" },
+
+       { STM32F4_RCC_APB2ENR,  0,      "tim1",         "apb2_mul" },
+       { STM32F4_RCC_APB2ENR,  1,      "tim8",         "apb2_mul" },
+       { STM32F4_RCC_APB2ENR,  7,      "sdmmc2",       "sdmux2" },
+       { STM32F4_RCC_APB2ENR,  8,      "adc1",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR,  9,      "adc2",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 10,      "adc3",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 11,      "sdmmc1",       "sdmux1" },
+       { STM32F4_RCC_APB2ENR, 12,      "spi1",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 13,      "spi4",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 14,      "syscfg",       "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 16,      "tim9",         "apb2_mul" },
+       { STM32F4_RCC_APB2ENR, 17,      "tim10",        "apb2_mul" },
+       { STM32F4_RCC_APB2ENR, 18,      "tim11",        "apb2_mul" },
+       { STM32F4_RCC_APB2ENR, 20,      "spi5",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 21,      "spi6",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 22,      "sai1",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 23,      "sai2",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 26,      "ltdc",         "apb2_div" },
+       { STM32F4_RCC_APB2ENR, 30,      "mdio",         "apb2_div" },
+};
+
 /*
  * This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx
  * have gate bits associated with them. Its combined hweight is 71.
@@ -318,6 +397,10 @@ static const u64 stm32f746_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
                                                      0x0000000000000003ull,
                                                      0x04f77f833e01c9ffull };
 
+static const u64 stm32f769_gate_map[MAX_GATE_MAP] = { 0x000000f37ef417ffull,
+                                                     0x0000000000000003ull,
+                                                     0x44F77F833E01EDFFull };
+
 static const u64 *stm32f4_gate_map;
 
 static struct clk_hw **clks;
@@ -1048,6 +1131,10 @@ static const char *rtc_parents[4] = {
        "no-clock", "lse", "lsi", "hse-rtc"
 };
 
+static const char *pll_src = "pll-src";
+
+static const char *pllsrc_parent[2] = { "hsi", NULL };
+
 static const char *dsi_parent[2] = { NULL, "pll-r" };
 
 static const char *lcd_parent[1] = { "pllsai-r-div" };
@@ -1072,6 +1159,9 @@ static const char *uart_parents2[4] = { "apb1_div", "sys", "hsi", "lse" };
 
 static const char *i2c_parents[4] = { "apb1_div", "sys", "hsi", "no-clock" };
 
+static const char * const dfsdm1_src[] = { "apb2_div", "sys" };
+static const char * const adsfdm1_parent[] = { "sai1_clk", "sai2_clk" };
+
 struct stm32_aux_clk {
        int idx;
        const char *name;
@@ -1313,6 +1403,177 @@ static const struct stm32_aux_clk stm32f746_aux_clk[] = {
        },
 };
 
+static const struct stm32_aux_clk stm32f769_aux_clk[] = {
+       {
+               CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
+               NO_MUX, 0, 0,
+               STM32F4_RCC_APB2ENR, 26,
+               CLK_SET_RATE_PARENT
+       },
+       {
+               CLK_I2S, "i2s", i2s_parents, ARRAY_SIZE(i2s_parents),
+               STM32F4_RCC_CFGR, 23, 1,
+               NO_GATE, 0,
+               CLK_SET_RATE_PARENT
+       },
+       {
+               CLK_SAI1, "sai1_clk", sai_parents, ARRAY_SIZE(sai_parents),
+               STM32F4_RCC_DCKCFGR, 20, 3,
+               STM32F4_RCC_APB2ENR, 22,
+               CLK_SET_RATE_PARENT
+       },
+       {
+               CLK_SAI2, "sai2_clk", sai_parents, ARRAY_SIZE(sai_parents),
+               STM32F4_RCC_DCKCFGR, 22, 3,
+               STM32F4_RCC_APB2ENR, 23,
+               CLK_SET_RATE_PARENT
+       },
+       {
+               NO_IDX, "pll48", pll48_parents, ARRAY_SIZE(pll48_parents),
+               STM32F7_RCC_DCKCFGR2, 27, 1,
+               NO_GATE, 0,
+               0
+       },
+       {
+               NO_IDX, "sdmux1", sdmux_parents, ARRAY_SIZE(sdmux_parents),
+               STM32F7_RCC_DCKCFGR2, 28, 1,
+               NO_GATE, 0,
+               0
+       },
+       {
+               NO_IDX, "sdmux2", sdmux_parents, ARRAY_SIZE(sdmux_parents),
+               STM32F7_RCC_DCKCFGR2, 29, 1,
+               NO_GATE, 0,
+               0
+       },
+       {
+               CLK_HDMI_CEC, "hdmi-cec",
+               hdmi_parents, ARRAY_SIZE(hdmi_parents),
+               STM32F7_RCC_DCKCFGR2, 26, 1,
+               NO_GATE, 0,
+               0
+       },
+       {
+               CLK_SPDIF, "spdif-rx",
+               spdif_parent, ARRAY_SIZE(spdif_parent),
+               STM32F7_RCC_DCKCFGR2, 22, 3,
+               STM32F4_RCC_APB2ENR, 23,
+               CLK_SET_RATE_PARENT
+       },
+       {
+               CLK_USART1, "usart1",
+               uart_parents1, ARRAY_SIZE(uart_parents1),
+               STM32F7_RCC_DCKCFGR2, 0, 3,
+               STM32F4_RCC_APB2ENR, 4,
+               CLK_SET_RATE_PARENT,
+       },
+       {
+               CLK_USART2, "usart2",
+               uart_parents2, ARRAY_SIZE(uart_parents1),
+               STM32F7_RCC_DCKCFGR2, 2, 3,
+               STM32F4_RCC_APB1ENR, 17,
+               CLK_SET_RATE_PARENT,
+       },
+       {
+               CLK_USART3, "usart3",
+               uart_parents2, ARRAY_SIZE(uart_parents1),
+               STM32F7_RCC_DCKCFGR2, 4, 3,
+               STM32F4_RCC_APB1ENR, 18,
+               CLK_SET_RATE_PARENT,
+       },
+       {
+               CLK_UART4, "uart4",
+               uart_parents2, ARRAY_SIZE(uart_parents1),
+               STM32F7_RCC_DCKCFGR2, 6, 3,
+               STM32F4_RCC_APB1ENR, 19,
+               CLK_SET_RATE_PARENT,
+       },
+       {
+               CLK_UART5, "uart5",
+               uart_parents2, ARRAY_SIZE(uart_parents1),
+               STM32F7_RCC_DCKCFGR2, 8, 3,
+               STM32F4_RCC_APB1ENR, 20,
+               CLK_SET_RATE_PARENT,
+       },
+       {
+               CLK_USART6, "usart6",
+               uart_parents1, ARRAY_SIZE(uart_parents1),
+               STM32F7_RCC_DCKCFGR2, 10, 3,
+               STM32F4_RCC_APB2ENR, 5,
+               CLK_SET_RATE_PARENT,
+       },
+       {
+               CLK_UART7, "uart7",
+               uart_parents2, ARRAY_SIZE(uart_parents1),
+               STM32F7_RCC_DCKCFGR2, 12, 3,
+               STM32F4_RCC_APB1ENR, 30,
+               CLK_SET_RATE_PARENT,
+       },
+       {
+               CLK_UART8, "uart8",
+               uart_parents2, ARRAY_SIZE(uart_parents1),
+               STM32F7_RCC_DCKCFGR2, 14, 3,
+               STM32F4_RCC_APB1ENR, 31,
+               CLK_SET_RATE_PARENT,
+       },
+       {
+               CLK_I2C1, "i2c1",
+               i2c_parents, ARRAY_SIZE(i2c_parents),
+               STM32F7_RCC_DCKCFGR2, 16, 3,
+               STM32F4_RCC_APB1ENR, 21,
+               CLK_SET_RATE_PARENT,
+       },
+       {
+               CLK_I2C2, "i2c2",
+               i2c_parents, ARRAY_SIZE(i2c_parents),
+               STM32F7_RCC_DCKCFGR2, 18, 3,
+               STM32F4_RCC_APB1ENR, 22,
+               CLK_SET_RATE_PARENT,
+       },
+       {
+               CLK_I2C3, "i2c3",
+               i2c_parents, ARRAY_SIZE(i2c_parents),
+               STM32F7_RCC_DCKCFGR2, 20, 3,
+               STM32F4_RCC_APB1ENR, 23,
+               CLK_SET_RATE_PARENT,
+       },
+       {
+               CLK_I2C4, "i2c4",
+               i2c_parents, ARRAY_SIZE(i2c_parents),
+               STM32F7_RCC_DCKCFGR2, 22, 3,
+               STM32F4_RCC_APB1ENR, 24,
+               CLK_SET_RATE_PARENT,
+       },
+       {
+               CLK_LPTIMER, "lptim1",
+               lptim_parent, ARRAY_SIZE(lptim_parent),
+               STM32F7_RCC_DCKCFGR2, 24, 3,
+               STM32F4_RCC_APB1ENR, 9,
+               CLK_SET_RATE_PARENT
+       },
+       {
+               CLK_F769_DSI, "dsi",
+               dsi_parent, ARRAY_SIZE(dsi_parent),
+               STM32F7_RCC_DCKCFGR2, 0, 1,
+               STM32F4_RCC_APB2ENR, 27,
+               CLK_SET_RATE_PARENT
+       },
+       {
+               CLK_DFSDM1, "dfsdm1",
+               dfsdm1_src, ARRAY_SIZE(dfsdm1_src),
+               STM32F4_RCC_DCKCFGR, 25, 1,
+               STM32F4_RCC_APB2ENR, 29,
+               CLK_SET_RATE_PARENT
+       },
+       {
+               CLK_ADFSDM1, "adfsdm1",
+               adsfdm1_parent, ARRAY_SIZE(adsfdm1_parent),
+               STM32F4_RCC_DCKCFGR, 26, 1,
+               STM32F4_RCC_APB2ENR, 29,
+               CLK_SET_RATE_PARENT
+       },
+};
+
 static const struct stm32f4_clk_data stm32f429_clk_data = {
        .end_primary    = END_PRIMARY_CLK,
        .gates_data     = stm32f429_gates,
@@ -1343,6 +1604,16 @@ static const struct stm32f4_clk_data stm32f746_clk_data = {
        .aux_clk_num    = ARRAY_SIZE(stm32f746_aux_clk),
 };
 
+static const struct stm32f4_clk_data stm32f769_clk_data = {
+       .end_primary    = END_PRIMARY_CLK_F7,
+       .gates_data     = stm32f769_gates,
+       .gates_map      = stm32f769_gate_map,
+       .gates_num      = ARRAY_SIZE(stm32f769_gates),
+       .pll_data       = stm32f469_pll,
+       .aux_clk        = stm32f769_aux_clk,
+       .aux_clk_num    = ARRAY_SIZE(stm32f769_aux_clk),
+};
+
 static const struct of_device_id stm32f4_of_match[] = {
        {
                .compatible = "st,stm32f42xx-rcc",
@@ -1356,6 +1627,10 @@ static const struct of_device_id stm32f4_of_match[] = {
                .compatible = "st,stm32f746-rcc",
                .data = &stm32f746_clk_data
        },
+       {
+               .compatible = "st,stm32f769-rcc",
+               .data = &stm32f769_clk_data
+       },
        {}
 };
 
@@ -1427,9 +1702,8 @@ static void __init stm32f4_rcc_init(struct device_node *np)
        int n;
        const struct of_device_id *match;
        const struct stm32f4_clk_data *data;
-       unsigned long pllcfgr;
-       const char *pllsrc;
        unsigned long pllm;
+       struct clk_hw *pll_src_hw;
 
        base = of_iomap(np, 0);
        if (!base) {
@@ -1460,21 +1734,33 @@ static void __init stm32f4_rcc_init(struct device_node *np)
 
        hse_clk = of_clk_get_parent_name(np, 0);
        dsi_parent[0] = hse_clk;
+       pllsrc_parent[1] = hse_clk;
 
        i2s_in_clk = of_clk_get_parent_name(np, 1);
 
        i2s_parents[1] = i2s_in_clk;
        sai_parents[2] = i2s_in_clk;
 
+       if (of_device_is_compatible(np, "st,stm32f769-rcc")) {
+               clk_hw_register_gate(NULL, "dfsdm1_apb", "apb2_div", 0,
+                                    base + STM32F4_RCC_APB2ENR, 29,
+                                    CLK_IGNORE_UNUSED, &stm32f4_clk_lock);
+               dsi_parent[0] = pll_src;
+               sai_parents[3] = pll_src;
+       }
+
        clks[CLK_HSI] = clk_hw_register_fixed_rate_with_accuracy(NULL, "hsi",
                        NULL, 0, 16000000, 160000);
 
-       pllcfgr = readl(base + STM32F4_RCC_PLLCFGR);
-       pllsrc = pllcfgr & BIT(22) ? hse_clk : "hsi";
-       pllm = pllcfgr & 0x3f;
+       pll_src_hw = clk_hw_register_mux(NULL, pll_src, pllsrc_parent,
+                                        ARRAY_SIZE(pllsrc_parent), 0,
+                                        base + STM32F4_RCC_PLLCFGR, 22, 1, 0,
+                                        &stm32f4_clk_lock);
+
+       pllm = readl(base + STM32F4_RCC_PLLCFGR) & 0x3f;
 
-       clk_hw_register_fixed_factor(NULL, "vco_in", pllsrc,
-                                              0, 1, pllm);
+       clk_hw_register_fixed_factor(NULL, "vco_in", pll_src,
+                                    0, 1, pllm);
 
        stm32f4_rcc_register_pll("vco_in", &data->pll_data[0],
                        &stm32f4_clk_lock);
@@ -1612,12 +1898,16 @@ static void __init stm32f4_rcc_init(struct device_node *np)
                        clks[aux_clk->idx] = hw;
        }
 
-       if (of_device_is_compatible(np, "st,stm32f746-rcc"))
+       if (of_device_is_compatible(np, "st,stm32f746-rcc")) {
 
                clk_hw_register_fixed_factor(NULL, "hsi_div488", "hsi", 0,
                                1, 488);
 
+               clks[CLK_PLL_SRC] = pll_src_hw;
+       }
+
        of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL);
+
        return;
 fail:
        kfree(clks);
@@ -1626,3 +1916,4 @@ fail:
 CLK_OF_DECLARE_DRIVER(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
 CLK_OF_DECLARE_DRIVER(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init);
 CLK_OF_DECLARE_DRIVER(stm32f746_rcc, "st,stm32f746-rcc", stm32f4_rcc_init);
+CLK_OF_DECLARE_DRIVER(stm32f769_rcc, "st,stm32f769-rcc", stm32f4_rcc_init);
index a0ae8dc1690905f2960b3ba42f2bb3185b156a36..a875649df8b8f1d6e02d2edfa20e6f4ee2d36768 100644 (file)
@@ -1402,6 +1402,7 @@ enum {
        G_CRYP1,
        G_HASH1,
        G_BKPSRAM,
+       G_DDRPERFM,
 
        G_LAST
 };
@@ -1488,6 +1489,7 @@ static struct stm32_gate_cfg per_gate_cfg[G_LAST] = {
        K_GATE(G_STGENRO,       RCC_APB4ENSETR, 20, 0),
        K_MGATE(G_USBPHY,       RCC_APB4ENSETR, 16, 0),
        K_GATE(G_IWDG2,         RCC_APB4ENSETR, 15, 0),
+       K_GATE(G_DDRPERFM,      RCC_APB4ENSETR, 8, 0),
        K_MGATE(G_DSI,          RCC_APB4ENSETR, 4, 0),
        K_MGATE(G_LTDC,         RCC_APB4ENSETR, 0, 0),
 
@@ -1899,6 +1901,7 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
        PCLK(CRC1, "crc1", "ck_axi", 0, G_CRC1),
        PCLK(USBH, "usbh", "ck_axi", 0, G_USBH),
        PCLK(ETHSTP, "ethstp", "ck_axi", 0, G_ETHSTP),
+       PCLK(DDRPERFM, "ddrperfm", "pclk4", 0, G_DDRPERFM),
 
        /* Kernel clocks */
        KCLK(SDMMC1_K, "sdmmc1_k", sdmmc12_src, 0, G_SDMMC1, M_SDMMC12),
index 531b030d4d4e7392cd827b9c9f40f5293d59b1f2..d975465fe2a8a1a0f4595c3d7be5c77790121d2c 100644 (file)
@@ -262,7 +262,7 @@ static unsigned long xgene_clk_pmd_recalc_rate(struct clk_hw *hw,
        else
                __acquire(fd->lock);
 
-       val = clk_readl(fd->reg);
+       val = readl(fd->reg);
 
        if (fd->lock)
                spin_unlock_irqrestore(fd->lock, flags);
@@ -333,10 +333,10 @@ static int xgene_clk_pmd_set_rate(struct clk_hw *hw, unsigned long rate,
        else
                __acquire(fd->lock);
 
-       val = clk_readl(fd->reg);
+       val = readl(fd->reg);
        val &= ~fd->mask;
        val |= (scale << fd->shift);
-       clk_writel(val, fd->reg);
+       writel(val, fd->reg);
 
        if (fd->lock)
                spin_unlock_irqrestore(fd->lock, flags);
index 96053a96fe2fc4878250aabf92601de729838cd3..aa51756fd4d695b359ee5c6117e7c9d00fddf183 100644 (file)
@@ -39,15 +39,23 @@ static LIST_HEAD(clk_notifier_list);
 
 /***    private data structures    ***/
 
+struct clk_parent_map {
+       const struct clk_hw     *hw;
+       struct clk_core         *core;
+       const char              *fw_name;
+       const char              *name;
+       int                     index;
+};
+
 struct clk_core {
        const char              *name;
        const struct clk_ops    *ops;
        struct clk_hw           *hw;
        struct module           *owner;
        struct device           *dev;
+       struct device_node      *of_node;
        struct clk_core         *parent;
-       const char              **parent_names;
-       struct clk_core         **parents;
+       struct clk_parent_map   *parents;
        u8                      num_parents;
        u8                      new_parent_index;
        unsigned long           rate;
@@ -316,17 +324,102 @@ static struct clk_core *clk_core_lookup(const char *name)
        return NULL;
 }
 
+/**
+ * clk_core_get - Find the clk_core parent of a clk
+ * @core: clk to find parent of
+ * @p_index: parent index to search for
+ *
+ * This is the preferred method for clk providers to find the parent of a
+ * clk when that parent is external to the clk controller. The parent_names
+ * array is indexed and treated as a local name matching a string in the device
+ * node's 'clock-names' property or as the 'con_id' matching the device's
+ * dev_name() in a clk_lookup. This allows clk providers to use their own
+ * namespace instead of looking for a globally unique parent string.
+ *
+ * For example the following DT snippet would allow a clock registered by the
+ * clock-controller@c001 that has a clk_init_data::parent_data array
+ * with 'xtal' in the 'name' member to find the clock provided by the
+ * clock-controller@f00abcd without needing to get the globally unique name of
+ * the xtal clk.
+ *
+ *      parent: clock-controller@f00abcd {
+ *              reg = <0xf00abcd 0xabcd>;
+ *              #clock-cells = <0>;
+ *      };
+ *
+ *      clock-controller@c001 {
+ *              reg = <0xc001 0xf00d>;
+ *              clocks = <&parent>;
+ *              clock-names = "xtal";
+ *              #clock-cells = <1>;
+ *      };
+ *
+ * Returns: -ENOENT when the provider can't be found or the clk doesn't
+ * exist in the provider. -EINVAL when the name can't be found. NULL when the
+ * provider knows about the clk but it isn't provided on this system.
+ * A valid clk_core pointer when the clk can be found in the provider.
+ */
+static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
+{
+       const char *name = core->parents[p_index].fw_name;
+       int index = core->parents[p_index].index;
+       struct clk_hw *hw = ERR_PTR(-ENOENT);
+       struct device *dev = core->dev;
+       const char *dev_id = dev ? dev_name(dev) : NULL;
+       struct device_node *np = core->of_node;
+
+       if (np && index >= 0)
+               hw = of_clk_get_hw(np, index, name);
+
+       /*
+        * If the DT search above couldn't find the provider or the provider
+        * didn't know about this clk, fallback to looking up via clkdev based
+        * clk_lookups
+        */
+       if (PTR_ERR(hw) == -ENOENT && name)
+               hw = clk_find_hw(dev_id, name);
+
+       if (IS_ERR(hw))
+               return ERR_CAST(hw);
+
+       return hw->core;
+}
+
+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);
+
+       if (entry->hw) {
+               parent = entry->hw->core;
+               /*
+                * We have a direct reference but it isn't registered yet?
+                * Orphan it and let clk_reparent() update the orphan status
+                * when the parent is registered.
+                */
+               if (!parent)
+                       parent = ERR_PTR(-EPROBE_DEFER);
+       } else {
+               parent = clk_core_get(core, index);
+               if (IS_ERR(parent) && PTR_ERR(parent) == -ENOENT)
+                       parent = clk_core_lookup(entry->name);
+       }
+
+       /* Only cache it if it's not an error */
+       if (!IS_ERR(parent))
+               entry->core = parent;
+}
+
 static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core,
                                                         u8 index)
 {
-       if (!core || index >= core->num_parents)
+       if (!core || index >= core->num_parents || !core->parents)
                return NULL;
 
-       if (!core->parents[index])
-               core->parents[index] =
-                               clk_core_lookup(core->parent_names[index]);
+       if (!core->parents[index].core)
+               clk_core_fill_parent_index(core, index);
 
-       return core->parents[index];
+       return core->parents[index].core;
 }
 
 struct clk_hw *
@@ -347,23 +440,18 @@ unsigned int __clk_get_enable_count(struct clk *clk)
 
 static unsigned long clk_core_get_rate_nolock(struct clk_core *core)
 {
-       unsigned long ret;
-
-       if (!core) {
-               ret = 0;
-               goto out;
-       }
-
-       ret = core->rate;
-
-       if (!core->num_parents)
-               goto out;
+       if (!core)
+               return 0;
 
-       if (!core->parent)
-               ret = 0;
+       if (!core->num_parents || core->parent)
+               return core->rate;
 
-out:
-       return ret;
+       /*
+        * Clk must have a parent because num_parents > 0 but the parent isn't
+        * known yet. Best to return 0 as the rate of this clk until we can
+        * properly recalc the rate based on the parent's rate.
+        */
+       return 0;
 }
 
 unsigned long clk_hw_get_rate(const struct clk_hw *hw)
@@ -524,9 +612,15 @@ void clk_hw_set_rate_range(struct clk_hw *hw, unsigned long min_rate,
 EXPORT_SYMBOL_GPL(clk_hw_set_rate_range);
 
 /*
+ * __clk_mux_determine_rate - clk_ops::determine_rate implementation for a mux type clk
+ * @hw: mux type clk to determine rate on
+ * @req: rate request, also used to return preferred parent and frequencies
+ *
  * Helper for finding best parent to provide a given frequency. This can be used
  * directly as a determine_rate callback (e.g. for a mux), or from a more
  * complex clock that may combine a mux with other operations.
+ *
+ * Returns: 0 on success, -EERROR value on error
  */
 int __clk_mux_determine_rate(struct clk_hw *hw,
                             struct clk_rate_request *req)
@@ -1519,20 +1613,37 @@ static int clk_fetch_parent_index(struct clk_core *core,
                return -EINVAL;
 
        for (i = 0; i < core->num_parents; i++) {
-               if (core->parents[i] == parent)
+               /* Found it first try! */
+               if (core->parents[i].core == parent)
                        return i;
 
-               if (core->parents[i])
+               /* Something else is here, so keep looking */
+               if (core->parents[i].core)
                        continue;
 
-               /* Fallback to comparing globally unique names */
-               if (!strcmp(parent->name, core->parent_names[i])) {
-                       core->parents[i] = parent;
-                       return i;
+               /* Maybe core hasn't been cached but the hw is all we know? */
+               if (core->parents[i].hw) {
+                       if (core->parents[i].hw == parent->hw)
+                               break;
+
+                       /* Didn't match, but we're expecting a clk_hw */
+                       continue;
                }
+
+               /* Maybe it hasn't been cached (clk_set_parent() path) */
+               if (parent == clk_core_get(core, i))
+                       break;
+
+               /* Fallback to comparing globally unique names */
+               if (!strcmp(parent->name, core->parents[i].name))
+                       break;
        }
 
-       return -EINVAL;
+       if (i == core->num_parents)
+               return -EINVAL;
+
+       core->parents[i].core = parent;
+       return i;
 }
 
 /*
@@ -2293,6 +2404,7 @@ void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent)
 bool clk_has_parent(struct clk *clk, struct clk *parent)
 {
        struct clk_core *core, *parent_core;
+       int i;
 
        /* NULL clocks should be nops, so return success if either is NULL. */
        if (!clk || !parent)
@@ -2305,8 +2417,11 @@ bool clk_has_parent(struct clk *clk, struct clk *parent)
        if (core->parent == parent_core)
                return true;
 
-       return match_string(core->parent_names, core->num_parents,
-                           parent_core->name) >= 0;
+       for (i = 0; i < core->num_parents; i++)
+               if (!strcmp(core->parents[i].name, parent_core->name))
+                       return true;
+
+       return false;
 }
 EXPORT_SYMBOL_GPL(clk_has_parent);
 
@@ -2850,7 +2965,6 @@ static const struct {
        ENTRY(CLK_SET_PARENT_GATE),
        ENTRY(CLK_SET_RATE_PARENT),
        ENTRY(CLK_IGNORE_UNUSED),
-       ENTRY(CLK_IS_BASIC),
        ENTRY(CLK_GET_RATE_NOCACHE),
        ENTRY(CLK_SET_RATE_NO_REPARENT),
        ENTRY(CLK_GET_ACCURACY_NOCACHE),
@@ -2889,9 +3003,9 @@ static int possible_parents_show(struct seq_file *s, void *data)
        int i;
 
        for (i = 0; i < core->num_parents - 1; i++)
-               seq_printf(s, "%s ", core->parent_names[i]);
+               seq_printf(s, "%s ", core->parents[i].name);
 
-       seq_printf(s, "%s\n", core->parent_names[i]);
+       seq_printf(s, "%s\n", core->parents[i].name);
 
        return 0;
 }
@@ -3025,7 +3139,7 @@ static inline void clk_debug_unregister(struct clk_core *core)
  */
 static int __clk_core_init(struct clk_core *core)
 {
-       int i, ret;
+       int ret;
        struct clk_core *orphan;
        struct hlist_node *tmp2;
        unsigned long rate;
@@ -3079,12 +3193,6 @@ static int __clk_core_init(struct clk_core *core)
                goto out;
        }
 
-       /* throw a WARN if any entries in parent_names are NULL */
-       for (i = 0; i < core->num_parents; i++)
-               WARN(!core->parent_names[i],
-                               "%s: invalid NULL in %s's .parent_names\n",
-                               __func__, core->name);
-
        core->parent = __clk_init_parent(core);
 
        /*
@@ -3313,20 +3421,104 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
        return clk;
 }
 
-/**
- * clk_register - allocate a new clock, register it and return an opaque cookie
- * @dev: device that is registering this clock
- * @hw: link to hardware-specific clock data
- *
- * clk_register is the primary interface for populating the clock tree with new
- * clock nodes.  It returns a pointer to the newly allocated struct clk which
- * cannot be dereferenced by driver code but may be used in conjunction with the
- * rest of the clock API.  In the event of an error clk_register will return an
- * error code; drivers must test for an error code after calling clk_register.
- */
-struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+static int clk_cpy_name(const char **dst_p, const char *src, bool must_exist)
+{
+       const char *dst;
+
+       if (!src) {
+               if (must_exist)
+                       return -EINVAL;
+               return 0;
+       }
+
+       *dst_p = dst = kstrdup_const(src, GFP_KERNEL);
+       if (!dst)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static int clk_core_populate_parent_map(struct clk_core *core)
+{
+       const struct clk_init_data *init = core->hw->init;
+       u8 num_parents = init->num_parents;
+       const char * const *parent_names = init->parent_names;
+       const struct clk_hw **parent_hws = init->parent_hws;
+       const struct clk_parent_data *parent_data = init->parent_data;
+       int i, ret = 0;
+       struct clk_parent_map *parents, *parent;
+
+       if (!num_parents)
+               return 0;
+
+       /*
+        * Avoid unnecessary string look-ups of clk_core's possible parents by
+        * having a cache of names/clk_hw pointers to clk_core pointers.
+        */
+       parents = kcalloc(num_parents, sizeof(*parents), GFP_KERNEL);
+       core->parents = parents;
+       if (!parents)
+               return -ENOMEM;
+
+       /* Copy everything over because it might be __initdata */
+       for (i = 0, parent = parents; i < num_parents; i++, parent++) {
+               parent->index = -1;
+               if (parent_names) {
+                       /* throw a WARN if any entries are NULL */
+                       WARN(!parent_names[i],
+                               "%s: invalid NULL in %s's .parent_names\n",
+                               __func__, core->name);
+                       ret = clk_cpy_name(&parent->name, parent_names[i],
+                                          true);
+               } else if (parent_data) {
+                       parent->hw = parent_data[i].hw;
+                       parent->index = parent_data[i].index;
+                       ret = clk_cpy_name(&parent->fw_name,
+                                          parent_data[i].fw_name, false);
+                       if (!ret)
+                               ret = clk_cpy_name(&parent->name,
+                                                  parent_data[i].name,
+                                                  false);
+               } else if (parent_hws) {
+                       parent->hw = parent_hws[i];
+               } else {
+                       ret = -EINVAL;
+                       WARN(1, "Must specify parents if num_parents > 0\n");
+               }
+
+               if (ret) {
+                       do {
+                               kfree_const(parents[i].name);
+                               kfree_const(parents[i].fw_name);
+                       } while (--i >= 0);
+                       kfree(parents);
+
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static void clk_core_free_parent_map(struct clk_core *core)
+{
+       int i = core->num_parents;
+
+       if (!core->num_parents)
+               return;
+
+       while (--i >= 0) {
+               kfree_const(core->parents[i].name);
+               kfree_const(core->parents[i].fw_name);
+       }
+
+       kfree(core->parents);
+}
+
+static struct clk *
+__clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
 {
-       int i, ret;
+       int ret;
        struct clk_core *core;
 
        core = kzalloc(sizeof(*core), GFP_KERNEL);
@@ -3350,6 +3542,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
        if (dev && pm_runtime_enabled(dev))
                core->rpm_enabled = true;
        core->dev = dev;
+       core->of_node = np;
        if (dev && dev->driver)
                core->owner = dev->driver->owner;
        core->hw = hw;
@@ -3359,33 +3552,9 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
        core->max_rate = ULONG_MAX;
        hw->core = core;
 
-       /* allocate local copy in case parent_names is __initdata */
-       core->parent_names = kcalloc(core->num_parents, sizeof(char *),
-                                       GFP_KERNEL);
-
-       if (!core->parent_names) {
-               ret = -ENOMEM;
-               goto fail_parent_names;
-       }
-
-
-       /* copy each string name in case parent_names is __initdata */
-       for (i = 0; i < core->num_parents; i++) {
-               core->parent_names[i] = kstrdup_const(hw->init->parent_names[i],
-                                               GFP_KERNEL);
-               if (!core->parent_names[i]) {
-                       ret = -ENOMEM;
-                       goto fail_parent_names_copy;
-               }
-       }
-
-       /* avoid unnecessary string look-ups of clk_core's possible parents. */
-       core->parents = kcalloc(core->num_parents, sizeof(*core->parents),
-                               GFP_KERNEL);
-       if (!core->parents) {
-               ret = -ENOMEM;
+       ret = clk_core_populate_parent_map(core);
+       if (ret)
                goto fail_parents;
-       };
 
        INIT_HLIST_HEAD(&core->clks);
 
@@ -3396,7 +3565,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
        hw->clk = alloc_clk(core, NULL, NULL);
        if (IS_ERR(hw->clk)) {
                ret = PTR_ERR(hw->clk);
-               goto fail_parents;
+               goto fail_create_clk;
        }
 
        clk_core_link_consumer(hw->core, hw->clk);
@@ -3412,13 +3581,9 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
        free_clk(hw->clk);
        hw->clk = NULL;
 
+fail_create_clk:
+       clk_core_free_parent_map(core);
 fail_parents:
-       kfree(core->parents);
-fail_parent_names_copy:
-       while (--i >= 0)
-               kfree_const(core->parent_names[i]);
-       kfree(core->parent_names);
-fail_parent_names:
 fail_ops:
        kfree_const(core->name);
 fail_name:
@@ -3426,6 +3591,24 @@ fail_name:
 fail_out:
        return ERR_PTR(ret);
 }
+
+/**
+ * clk_register - allocate a new clock, register it and return an opaque cookie
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * clk_register is the *deprecated* interface for populating the clock tree with
+ * new clock nodes. Use clk_hw_register() instead.
+ *
+ * Returns: a pointer to the newly allocated struct clk which
+ * cannot be dereferenced by driver code but may be used in conjunction with the
+ * rest of the clock API.  In the event of an error clk_register will return an
+ * error code; drivers must test for an error code after calling clk_register.
+ */
+struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+{
+       return __clk_register(dev, dev_of_node(dev), hw);
+}
 EXPORT_SYMBOL_GPL(clk_register);
 
 /**
@@ -3440,23 +3623,35 @@ EXPORT_SYMBOL_GPL(clk_register);
  */
 int clk_hw_register(struct device *dev, struct clk_hw *hw)
 {
-       return PTR_ERR_OR_ZERO(clk_register(dev, hw));
+       return PTR_ERR_OR_ZERO(__clk_register(dev, dev_of_node(dev), hw));
 }
 EXPORT_SYMBOL_GPL(clk_hw_register);
 
+/*
+ * of_clk_hw_register - register a clk_hw and return an error code
+ * @node: device_node of device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * of_clk_hw_register() is the primary interface for populating the clock tree
+ * with new clock nodes when a struct device is not available, but a struct
+ * device_node is. It returns an integer equal to zero indicating success or
+ * less than zero indicating failure. Drivers must test for an error code after
+ * calling of_clk_hw_register().
+ */
+int of_clk_hw_register(struct device_node *node, struct clk_hw *hw)
+{
+       return PTR_ERR_OR_ZERO(__clk_register(NULL, node, hw));
+}
+EXPORT_SYMBOL_GPL(of_clk_hw_register);
+
 /* Free memory allocated for a clock. */
 static void __clk_release(struct kref *ref)
 {
        struct clk_core *core = container_of(ref, struct clk_core, ref);
-       int i = core->num_parents;
 
        lockdep_assert_held(&prepare_lock);
 
-       kfree(core->parents);
-       while (--i >= 0)
-               kfree_const(core->parent_names[i]);
-
-       kfree(core->parent_names);
+       clk_core_free_parent_map(core);
        kfree_const(core->name);
        kfree(core);
 }
@@ -3575,9 +3770,10 @@ static void devm_clk_hw_release(struct device *dev, void *res)
  * @dev: device that is registering this clock
  * @hw: link to hardware-specific clock data
  *
- * Managed clk_register(). Clocks returned from this function are
- * automatically clk_unregister()ed on driver detach. See clk_register() for
- * more information.
+ * Managed clk_register(). This function is *deprecated*, use devm_clk_hw_register() instead.
+ *
+ * Clocks returned from this function are automatically clk_unregister()ed on
+ * driver detach. See clk_register() for more information.
  */
 struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
 {
@@ -3895,6 +4091,8 @@ EXPORT_SYMBOL_GPL(of_clk_hw_onecell_get);
  * @np: Device node pointer associated with clock provider
  * @clk_src_get: callback for decoding clock
  * @data: context pointer for @clk_src_get callback.
+ *
+ * This function is *deprecated*. Use of_clk_add_hw_provider() instead.
  */
 int of_clk_add_provider(struct device_node *np,
                        struct clk *(*clk_src_get)(struct of_phandle_args *clkspec,
index 553f531cc232e5531c25f7278a3a080df5d5bf25..d8400d623b34b73bfe6bcabac2d7a00f3732a9eb 100644 (file)
@@ -19,6 +19,8 @@ static inline struct clk_hw *of_clk_get_hw(struct device_node *np,
 }
 #endif
 
+struct clk_hw *clk_find_hw(const char *dev_id, const char *con_id);
+
 #ifdef CONFIG_COMMON_CLK
 struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
                              const char *dev_id, const char *con_id);
index 6e787cc9e5b90ded5c9fd9f613301c6c735133b3..2afc8df8acffe5996dae4ba3c58056f879bc1298 100644 (file)
@@ -72,25 +72,26 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
        return cl;
 }
 
-static struct clk *__clk_get_sys(struct device *dev, const char *dev_id,
-                                const char *con_id)
+struct clk_hw *clk_find_hw(const char *dev_id, const char *con_id)
 {
        struct clk_lookup *cl;
-       struct clk *clk = NULL;
+       struct clk_hw *hw = ERR_PTR(-ENOENT);
 
        mutex_lock(&clocks_mutex);
-
        cl = clk_find(dev_id, con_id);
-       if (!cl)
-               goto out;
-
-       clk = clk_hw_create_clk(dev, cl->clk_hw, dev_id, con_id);
-       if (IS_ERR(clk))
-               cl = NULL;
-out:
+       if (cl)
+               hw = cl->clk_hw;
        mutex_unlock(&clocks_mutex);
 
-       return cl ? clk : ERR_PTR(-ENOENT);
+       return hw;
+}
+
+static struct clk *__clk_get_sys(struct device *dev, const char *dev_id,
+                                const char *con_id)
+{
+       struct clk_hw *hw = clk_find_hw(dev_id, con_id);
+
+       return clk_hw_create_clk(dev, hw, dev_id, con_id);
 }
 
 struct clk *clk_get_sys(const char *dev_id, const char *con_id)
index d1bbee19ed0fcf74edfb2019fc4907ba00533a66..bdc52364b4216503062da8c8e9222abf04f6b97e 100644 (file)
@@ -160,10 +160,8 @@ static int __init da8xx_cfgchip_register_div4p5(struct device *dev,
        struct da8xx_cfgchip_gate_clk *gate;
 
        gate = da8xx_cfgchip_gate_clk_register(dev, &da8xx_div4p5ena_info, regmap);
-       if (IS_ERR(gate))
-               return PTR_ERR(gate);
 
-       return 0;
+       return PTR_ERR_OR_ZERO(gate);
 }
 
 static int __init
index 7cc354dd29e223b3f3f2f88b8466762e1d71b107..c2a453caa131112a0a56ab8fdb9da5023790c5dd 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Clock driver for TI Davinci PSC controllers
  *
index cc5614567a70d61cf76aa6777caf9c2f39479c5d..69070f834391a34fcdb650110bf8e5cb80b8d6e0 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Clock driver for TI Davinci PSC controllers
  *
index f404199596563e34f7b62eead4fc539f084ca79b..794eeff0d5d2d548eb7fa91be8131e48d7299ca4 100644 (file)
@@ -163,8 +163,12 @@ static const struct hisi_gate_clock hi3660_crgctrl_gate_sep_clks[] = {
          "clk_isp_snclk_mux", CLK_SET_RATE_PARENT, 0x50, 17, 0, },
        { HI3660_CLK_GATE_ISP_SNCLK2, "clk_gate_isp_snclk2",
          "clk_isp_snclk_mux", CLK_SET_RATE_PARENT, 0x50, 18, 0, },
+       /*
+        * clk_gate_ufs_subsys is a system bus clock, mark it as critical
+        * clock and keep it on for system suspend and resume.
+        */
        { HI3660_CLK_GATE_UFS_SUBSYS, "clk_gate_ufs_subsys", "clk_div_sysbus",
-         CLK_SET_RATE_PARENT, 0x50, 21, 0, },
+         CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0x50, 21, 0, },
        { HI3660_PCLK_GATE_DSI0, "pclk_gate_dsi0", "clk_div_cfgbus",
          CLK_SET_RATE_PARENT, 0x50, 28, 0, },
        { HI3660_PCLK_GATE_DSI1, "pclk_gate_dsi1", "clk_div_cfgbus",
index 5fdc267bb2da6b9a4107566ba8d69dc5141a11a8..ba6afad66a2b0c257b306ebe503a823a02b03752 100644 (file)
@@ -75,10 +75,10 @@ static int hisi_clk_set_phase(struct clk_hw *hw, int degrees)
 
        spin_lock_irqsave(phase->lock, flags);
 
-       val = clk_readl(phase->reg);
+       val = readl(phase->reg);
        val &= ~phase->mask;
        val |= regval << phase->shift;
-       clk_writel(val, phase->reg);
+       writel(val, phase->reg);
 
        spin_unlock_irqrestore(phase->lock, flags);
 
index 0d5180fbe9883b1b94eebc0498039d75f4b0f6bf..05641c64b31740566621a9b0ef7d858430d2b6ee 100644 (file)
@@ -35,7 +35,7 @@ obj-$(CONFIG_SOC_IMX25)  += clk-imx25.o
 obj-$(CONFIG_SOC_IMX27)  += clk-imx27.o
 obj-$(CONFIG_SOC_IMX31)  += clk-imx31.o
 obj-$(CONFIG_SOC_IMX35)  += clk-imx35.o
-obj-$(CONFIG_SOC_IMX5)   += clk-imx51-imx53.o
+obj-$(CONFIG_SOC_IMX5)   += clk-imx5.o
 obj-$(CONFIG_SOC_IMX6Q)  += clk-imx6q.o
 obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o
 obj-$(CONFIG_SOC_IMX6SLL) += clk-imx6sll.o
index df1f8429fe169e62ca4b9c1c76548965aa007a81..2a8352a316c7062778ae9abecb8b2c96ee40ce96 100644 (file)
@@ -29,7 +29,7 @@ static unsigned long clk_divider_gate_recalc_rate_ro(struct clk_hw *hw,
        struct clk_divider *div = to_clk_divider(hw);
        unsigned int val;
 
-       val = clk_readl(div->reg) >> div->shift;
+       val = readl(div->reg) >> div->shift;
        val &= clk_div_mask(div->width);
        if (!val)
                return 0;
@@ -51,7 +51,7 @@ static unsigned long clk_divider_gate_recalc_rate(struct clk_hw *hw,
        if (!clk_hw_is_enabled(hw)) {
                val = div_gate->cached_val;
        } else {
-               val = clk_readl(div->reg) >> div->shift;
+               val = readl(div->reg) >> div->shift;
                val &= clk_div_mask(div->width);
        }
 
@@ -87,10 +87,10 @@ static int clk_divider_gate_set_rate(struct clk_hw *hw, unsigned long rate,
        spin_lock_irqsave(div->lock, flags);
 
        if (clk_hw_is_enabled(hw)) {
-               val = clk_readl(div->reg);
+               val = readl(div->reg);
                val &= ~(clk_div_mask(div->width) << div->shift);
                val |= (u32)value << div->shift;
-               clk_writel(val, div->reg);
+               writel(val, div->reg);
        } else {
                div_gate->cached_val = value;
        }
@@ -114,9 +114,9 @@ static int clk_divider_enable(struct clk_hw *hw)
 
        spin_lock_irqsave(div->lock, flags);
        /* restore div val */
-       val = clk_readl(div->reg);
+       val = readl(div->reg);
        val |= div_gate->cached_val << div->shift;
-       clk_writel(val, div->reg);
+       writel(val, div->reg);
 
        spin_unlock_irqrestore(div->lock, flags);
 
@@ -133,10 +133,10 @@ static void clk_divider_disable(struct clk_hw *hw)
        spin_lock_irqsave(div->lock, flags);
 
        /* store the current div val */
-       val = clk_readl(div->reg) >> div->shift;
+       val = readl(div->reg) >> div->shift;
        val &= clk_div_mask(div->width);
        div_gate->cached_val = val;
-       clk_writel(0, div->reg);
+       writel(0, div->reg);
 
        spin_unlock_irqrestore(div->lock, flags);
 }
@@ -146,7 +146,7 @@ static int clk_divider_is_enabled(struct clk_hw *hw)
        struct clk_divider *div = to_clk_divider(hw);
        u32 val;
 
-       val = clk_readl(div->reg) >> div->shift;
+       val = readl(div->reg) >> div->shift;
        val &= clk_div_mask(div->width);
 
        return val ? 1 : 0;
@@ -206,7 +206,7 @@ struct clk_hw *imx_clk_divider_gate(const char *name, const char *parent_name,
        div_gate->divider.hw.init = &init;
        div_gate->divider.flags = CLK_DIVIDER_ONE_BASED | clk_divider_flags;
        /* cache gate status */
-       val = clk_readl(reg) >> shift;
+       val = readl(reg) >> shift;
        val &= clk_div_mask(width);
        div_gate->cached_val = val;
 
similarity index 94%
rename from drivers/clk/imx/clk-imx51-imx53.c
rename to drivers/clk/imx/clk-imx5.c
index e91c826bce7072b537f6e8b24cd905be4fa09f46..c85ebd74a8a53d565d33678a528f0fc12dd0784d 100644 (file)
@@ -164,10 +164,6 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base)
        clk[IMX5_CLK_CKIH1]             = imx_obtain_fixed_clock("ckih1", 0);
        clk[IMX5_CLK_CKIH2]             = imx_obtain_fixed_clock("ckih2", 0);
 
-       clk[IMX5_CLK_PERIPH_APM]        = imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2,
-                                               periph_apm_sel, ARRAY_SIZE(periph_apm_sel));
-       clk[IMX5_CLK_MAIN_BUS]          = imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 1,
-                                               main_bus_sel, ARRAY_SIZE(main_bus_sel));
        clk[IMX5_CLK_PER_LP_APM]        = imx_clk_mux("per_lp_apm", MXC_CCM_CBCMR, 1, 1,
                                                per_lp_apm_sel, ARRAY_SIZE(per_lp_apm_sel));
        clk[IMX5_CLK_PER_PRED1]         = imx_clk_divider("per_pred1", "per_lp_apm", MXC_CCM_CBCDR, 6, 2);
@@ -191,16 +187,10 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base)
        clk[IMX5_CLK_UART_PRED]         = imx_clk_divider("uart_pred", "uart_sel", MXC_CCM_CSCDR1, 3, 3);
        clk[IMX5_CLK_UART_ROOT]         = imx_clk_divider("uart_root", "uart_pred", MXC_CCM_CSCDR1, 0, 3);
 
-       clk[IMX5_CLK_ESDHC_A_SEL]       = imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 20, 2,
-                                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
-       clk[IMX5_CLK_ESDHC_B_SEL]       = imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2,
-                                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
        clk[IMX5_CLK_ESDHC_A_PRED]      = imx_clk_divider("esdhc_a_pred", "esdhc_a_sel", MXC_CCM_CSCDR1, 16, 3);
        clk[IMX5_CLK_ESDHC_A_PODF]      = imx_clk_divider("esdhc_a_podf", "esdhc_a_pred", MXC_CCM_CSCDR1, 11, 3);
        clk[IMX5_CLK_ESDHC_B_PRED]      = imx_clk_divider("esdhc_b_pred", "esdhc_b_sel", MXC_CCM_CSCDR1, 22, 3);
        clk[IMX5_CLK_ESDHC_B_PODF]      = imx_clk_divider("esdhc_b_podf", "esdhc_b_pred", MXC_CCM_CSCDR1, 19, 3);
-       clk[IMX5_CLK_ESDHC_C_SEL]       = imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel));
-       clk[IMX5_CLK_ESDHC_D_SEL]       = imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 18, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel));
 
        clk[IMX5_CLK_EMI_SEL]           = imx_clk_mux("emi_sel", MXC_CCM_CBCDR, 26, 1,
                                                emi_slow_sel, ARRAY_SIZE(emi_slow_sel));
@@ -311,10 +301,6 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base)
        clk_register_clkdev(clk[IMX5_CLK_CPU_PODF], NULL, "cpu0");
        clk_register_clkdev(clk[IMX5_CLK_GPC_DVFS], "gpc_dvfs", NULL);
 
-       /* Set SDHC parents to be PLL2 */
-       clk_set_parent(clk[IMX5_CLK_ESDHC_A_SEL], clk[IMX5_CLK_PLL2_SW]);
-       clk_set_parent(clk[IMX5_CLK_ESDHC_B_SEL], clk[IMX5_CLK_PLL2_SW]);
-
        /* move usb phy clk to 24MHz */
        clk_set_parent(clk[IMX5_CLK_USB_PHY_SEL], clk[IMX5_CLK_OSC]);
 }
@@ -342,8 +328,21 @@ static void __init mx50_clocks_init(struct device_node *np)
 
        mx5_clocks_common_init(ccm_base);
 
+       /*
+        * This clock is called periph_clk in the i.MX50 Reference Manual, but
+        * it comes closest in scope to the main_bus_clk of i.MX51 and i.MX53
+        */
+       clk[IMX5_CLK_MAIN_BUS]          = imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 2,
+                                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+
        clk[IMX5_CLK_LP_APM]            = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1,
                                                lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
+       clk[IMX5_CLK_ESDHC_A_SEL]       = imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 21, 2,
+                                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+       clk[IMX5_CLK_ESDHC_B_SEL]       = imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2,
+                                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+       clk[IMX5_CLK_ESDHC_C_SEL]       = imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 20, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel));
+       clk[IMX5_CLK_ESDHC_D_SEL]       = imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel));
        clk[IMX5_CLK_ESDHC1_PER_GATE]   = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
        clk[IMX5_CLK_ESDHC2_PER_GATE]   = imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6);
        clk[IMX5_CLK_ESDHC3_PER_GATE]   = imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10);
@@ -372,6 +371,10 @@ static void __init mx50_clocks_init(struct device_node *np)
        clk_data.clk_num = ARRAY_SIZE(clk);
        of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
+       /* Set SDHC parents to be PLL2 */
+       clk_set_parent(clk[IMX5_CLK_ESDHC_A_SEL], clk[IMX5_CLK_PLL2_SW]);
+       clk_set_parent(clk[IMX5_CLK_ESDHC_B_SEL], clk[IMX5_CLK_PLL2_SW]);
+
        /* set SDHC root clock to 200MHZ*/
        clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000);
        clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000);
@@ -410,6 +413,10 @@ static void __init mx51_clocks_init(struct device_node *np)
 
        mx5_clocks_common_init(ccm_base);
 
+       clk[IMX5_CLK_PERIPH_APM]        = imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2,
+                                               periph_apm_sel, ARRAY_SIZE(periph_apm_sel));
+       clk[IMX5_CLK_MAIN_BUS]          = imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 1,
+                                               main_bus_sel, ARRAY_SIZE(main_bus_sel));
        clk[IMX5_CLK_LP_APM]            = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1,
                                                lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
        clk[IMX5_CLK_IPU_DI0_SEL]       = imx_clk_mux_flags("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
@@ -422,6 +429,12 @@ static void __init mx51_clocks_init(struct device_node *np)
                                                mx51_tve_sel, ARRAY_SIZE(mx51_tve_sel));
        clk[IMX5_CLK_TVE_GATE]          = imx_clk_gate2("tve_gate", "tve_sel", MXC_CCM_CCGR2, 30);
        clk[IMX5_CLK_TVE_PRED]          = imx_clk_divider("tve_pred", "pll3_sw", MXC_CCM_CDCDR, 28, 3);
+       clk[IMX5_CLK_ESDHC_A_SEL]       = imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 20, 2,
+                                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+       clk[IMX5_CLK_ESDHC_B_SEL]       = imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2,
+                                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+       clk[IMX5_CLK_ESDHC_C_SEL]       = imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel));
+       clk[IMX5_CLK_ESDHC_D_SEL]       = imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 18, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel));
        clk[IMX5_CLK_ESDHC1_PER_GATE]   = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
        clk[IMX5_CLK_ESDHC2_PER_GATE]   = imx_clk_gate2("esdhc2_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 6);
        clk[IMX5_CLK_ESDHC3_PER_GATE]   = imx_clk_gate2("esdhc3_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 10);
@@ -452,6 +465,10 @@ static void __init mx51_clocks_init(struct device_node *np)
        /* set the usboh3 parent to pll2_sw */
        clk_set_parent(clk[IMX5_CLK_USBOH3_SEL], clk[IMX5_CLK_PLL2_SW]);
 
+       /* Set SDHC parents to be PLL2 */
+       clk_set_parent(clk[IMX5_CLK_ESDHC_A_SEL], clk[IMX5_CLK_PLL2_SW]);
+       clk_set_parent(clk[IMX5_CLK_ESDHC_B_SEL], clk[IMX5_CLK_PLL2_SW]);
+
        /* set SDHC root clock to 166.25MHZ*/
        clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 166250000);
        clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 166250000);
@@ -506,6 +523,10 @@ static void __init mx53_clocks_init(struct device_node *np)
 
        mx5_clocks_common_init(ccm_base);
 
+       clk[IMX5_CLK_PERIPH_APM]        = imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2,
+                                               periph_apm_sel, ARRAY_SIZE(periph_apm_sel));
+       clk[IMX5_CLK_MAIN_BUS]          = imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 1,
+                                               main_bus_sel, ARRAY_SIZE(main_bus_sel));
        clk[IMX5_CLK_LP_APM]            = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1,
                                                lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
        clk[IMX5_CLK_LDB_DI1_DIV_3_5]   = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
@@ -527,6 +548,12 @@ static void __init mx53_clocks_init(struct device_node *np)
                                                mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel), CLK_SET_RATE_PARENT);
        clk[IMX5_CLK_TVE_GATE]          = imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30);
        clk[IMX5_CLK_TVE_PRED]          = imx_clk_divider("tve_pred", "tve_ext_sel", MXC_CCM_CDCDR, 28, 3);
+       clk[IMX5_CLK_ESDHC_A_SEL]       = imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 20, 2,
+                                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+       clk[IMX5_CLK_ESDHC_B_SEL]       = imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2,
+                                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+       clk[IMX5_CLK_ESDHC_C_SEL]       = imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel));
+       clk[IMX5_CLK_ESDHC_D_SEL]       = imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 18, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel));
        clk[IMX5_CLK_ESDHC1_PER_GATE]   = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
        clk[IMX5_CLK_ESDHC2_PER_GATE]   = imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6);
        clk[IMX5_CLK_ESDHC3_PER_GATE]   = imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10);
@@ -589,6 +616,10 @@ static void __init mx53_clocks_init(struct device_node *np)
        clk_data.clk_num = ARRAY_SIZE(clk);
        of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
+       /* Set SDHC parents to be PLL2 */
+       clk_set_parent(clk[IMX5_CLK_ESDHC_A_SEL], clk[IMX5_CLK_PLL2_SW]);
+       clk_set_parent(clk[IMX5_CLK_ESDHC_B_SEL], clk[IMX5_CLK_PLL2_SW]);
+
        /* set SDHC root clock to 200MHZ*/
        clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000);
        clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000);
index 3bd2044cf25c2618869f50d0aa17faa63ac1213e..7eea448cb9a98627c457a96221a26214989c5385 100644 (file)
@@ -76,6 +76,20 @@ static u32 share_count_ssi1;
 static u32 share_count_ssi2;
 static u32 share_count_ssi3;
 
+static struct clk ** const uart_clks[] __initconst = {
+       &clks[IMX6SLL_CLK_UART1_IPG],
+       &clks[IMX6SLL_CLK_UART1_SERIAL],
+       &clks[IMX6SLL_CLK_UART2_IPG],
+       &clks[IMX6SLL_CLK_UART2_SERIAL],
+       &clks[IMX6SLL_CLK_UART3_IPG],
+       &clks[IMX6SLL_CLK_UART3_SERIAL],
+       &clks[IMX6SLL_CLK_UART4_IPG],
+       &clks[IMX6SLL_CLK_UART4_SERIAL],
+       &clks[IMX6SLL_CLK_UART5_IPG],
+       &clks[IMX6SLL_CLK_UART5_SERIAL],
+       NULL
+};
+
 static void __init imx6sll_clocks_init(struct device_node *ccm_node)
 {
        struct device_node *np;
@@ -268,7 +282,7 @@ static void __init imx6sll_clocks_init(struct device_node *ccm_node)
        clks[IMX6SLL_CLK_GPT_BUS]       = imx_clk_gate2("gpt1_bus",     "perclk", base + 0x6c, 20);
        clks[IMX6SLL_CLK_GPT_SERIAL]    = imx_clk_gate2("gpt1_serial",  "perclk", base + 0x6c, 22);
        clks[IMX6SLL_CLK_UART4_IPG]     = imx_clk_gate2("uart4_ipg",    "ipg", base + 0x6c, 24);
-       clks[IMX6SLL_CLK_UART4_SERIAL]  = imx_clk_gate2("uart4_serail", "uart_podf", base + 0x6c, 24);
+       clks[IMX6SLL_CLK_UART4_SERIAL]  = imx_clk_gate2("uart4_serial", "uart_podf", base + 0x6c, 24);
        clks[IMX6SLL_CLK_GPIO1]         = imx_clk_gate2("gpio1",        "ipg", base + 0x6c, 26);
        clks[IMX6SLL_CLK_GPIO5]         = imx_clk_gate2("gpio5",        "ipg", base + 0x6c, 30);
 
@@ -334,6 +348,8 @@ static void __init imx6sll_clocks_init(struct device_node *ccm_node)
        clk_data.clk_num = ARRAY_SIZE(clks);
        of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
+       imx_register_uart_clocks(uart_clks);
+
        /* Lower the AHB clock rate before changing the clock source. */
        clk_set_rate(clks[IMX6SLL_CLK_AHB], 99000000);
 
index cfbd8d4edb8599b9cddbaec02f1a2832faa02bf7..5b8a0c729f90298ed90bf3d4360da83f56d60663 100644 (file)
@@ -417,8 +417,8 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
        clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_DDR_IMX7, "pll_dram_main", "osc", base + 0x70, 0x7f);
        clks[IMX7D_PLL_SYS_MAIN]  = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll_sys_main", "osc", base + 0xb0, 0x1);
        clks[IMX7D_PLL_ENET_MAIN] = imx_clk_pllv3(IMX_PLLV3_ENET_IMX7, "pll_enet_main", "osc", base + 0xe0, 0x0);
-       clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_audio_main", "osc", base + 0xf0, 0x7f);
-       clks[IMX7D_PLL_VIDEO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_video_main", "osc", base + 0x130, 0x7f);
+       clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV_IMX7, "pll_audio_main", "osc", base + 0xf0, 0x7f);
+       clks[IMX7D_PLL_VIDEO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV_IMX7, "pll_video_main", "osc", base + 0x130, 0x7f);
 
        clks[IMX7D_PLL_ARM_MAIN_BYPASS]  = imx_clk_mux_flags("pll_arm_main_bypass", base + 0x60, 16, 1, pll_arm_bypass_sel, ARRAY_SIZE(pll_arm_bypass_sel), CLK_SET_RATE_PARENT);
        clks[IMX7D_PLL_DRAM_MAIN_BYPASS] = imx_clk_mux_flags("pll_dram_main_bypass", base + 0x70, 16, 1, pll_dram_bypass_sel, ARRAY_SIZE(pll_dram_bypass_sel), CLK_SET_RATE_PARENT);
index ce306631e84410d007afea1543a1c85df32fd0b7..66682100f14c950ed31db5fd68f1fc4ad6274630 100644 (file)
@@ -151,7 +151,6 @@ static void __init imx7ulp_clk_pcc2_init(struct device_node *np)
        clks[IMX7ULP_CLK_DMA1]          = imx_clk_hw_gate("dma1", "nic1_clk", base + 0x20, 30);
        clks[IMX7ULP_CLK_RGPIO2P1]      = imx_clk_hw_gate("rgpio2p1", "nic1_bus_clk", base + 0x3c, 30);
        clks[IMX7ULP_CLK_DMA_MUX1]      = imx_clk_hw_gate("dma_mux1", "nic1_bus_clk", base + 0x84, 30);
-       clks[IMX7ULP_CLK_SNVS]          = imx_clk_hw_gate("snvs", "nic1_bus_clk", base + 0x8c, 30);
        clks[IMX7ULP_CLK_CAAM]          = imx_clk_hw_gate("caam", "nic1_clk", base + 0x90, 30);
        clks[IMX7ULP_CLK_LPTPM4]        = imx7ulp_clk_composite("lptpm4",  periph_bus_sels, ARRAY_SIZE(periph_bus_sels), true, false, true, base + 0x94);
        clks[IMX7ULP_CLK_LPTPM5]        = imx7ulp_clk_composite("lptpm5",  periph_bus_sels, ARRAY_SIZE(periph_bus_sels), true, false, true, base + 0x98);
index a9b3888aef0c207bb97ffa4191131bda3425565f..daf1841b2adb0ef3fe9821444d96534623d3516f 100644 (file)
@@ -458,6 +458,7 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
        clks[IMX8MQ_CLK_DSI_DBI] = imx8m_clk_composite("dsi_dbi", imx8mq_dsi_dbi_sels, base + 0xbc00);
        clks[IMX8MQ_CLK_DSI_ESC] = imx8m_clk_composite("dsi_esc", imx8mq_dsi_esc_sels, base + 0xbc80);
        clks[IMX8MQ_CLK_DSI_AHB] = imx8m_clk_composite("dsi_ahb", imx8mq_dsi_ahb_sels, base + 0x9200);
+       clks[IMX8MQ_CLK_DSI_IPG_DIV] = imx_clk_divider2("dsi_ipg_div", "dsi_ahb", base + 0x9280, 0, 6);
        clks[IMX8MQ_CLK_CSI1_CORE] = imx8m_clk_composite("csi1_core", imx8mq_csi1_core_sels, base + 0xbd00);
        clks[IMX8MQ_CLK_CSI1_PHY_REF] = imx8m_clk_composite("csi1_phy_ref", imx8mq_csi1_phy_sels, base + 0xbd80);
        clks[IMX8MQ_CLK_CSI1_ESC] = imx8m_clk_composite("csi1_esc", imx8mq_csi1_esc_sels, base + 0xbe00);
index 7e9134b205abc41a1ef89d243502875ab56e5762..fb567dcc21185bb714982d5f3999d6d6065e944f 100644 (file)
@@ -43,7 +43,7 @@ static int clk_pfdv2_wait(struct clk_pfdv2 *pfd)
 {
        u32 val;
 
-       return readl_poll_timeout(pfd->reg, val, val & pfd->vld_bit,
+       return readl_poll_timeout(pfd->reg, val, val & (1 << pfd->vld_bit),
                                  0, LOCK_TIMEOUT_US);
 }
 
@@ -55,7 +55,7 @@ static int clk_pfdv2_enable(struct clk_hw *hw)
 
        spin_lock_irqsave(&pfd_lock, flags);
        val = readl_relaxed(pfd->reg);
-       val &= ~pfd->gate_bit;
+       val &= ~(1 << pfd->gate_bit);
        writel_relaxed(val, pfd->reg);
        spin_unlock_irqrestore(&pfd_lock, flags);
 
@@ -70,7 +70,7 @@ static void clk_pfdv2_disable(struct clk_hw *hw)
 
        spin_lock_irqsave(&pfd_lock, flags);
        val = readl_relaxed(pfd->reg);
-       val |= pfd->gate_bit;
+       val |= (1 << pfd->gate_bit);
        writel_relaxed(val, pfd->reg);
        spin_unlock_irqrestore(&pfd_lock, flags);
 }
@@ -123,7 +123,7 @@ static int clk_pfdv2_is_enabled(struct clk_hw *hw)
 {
        struct clk_pfdv2 *pfd = to_clk_pfdv2(hw);
 
-       if (readl_relaxed(pfd->reg) & pfd->gate_bit)
+       if (readl_relaxed(pfd->reg) & (1 << pfd->gate_bit))
                return 0;
 
        return 1;
@@ -180,7 +180,7 @@ struct clk_hw *imx_clk_pfdv2(const char *name, const char *parent_name,
                return ERR_PTR(-ENOMEM);
 
        pfd->reg = reg;
-       pfd->gate_bit = 1 << ((idx + 1) * 8 - 1);
+       pfd->gate_bit = (idx + 1) * 8 - 1;
        pfd->vld_bit = pfd->gate_bit - 1;
        pfd->frac_off = idx * 8;
 
index 113d71042199b3d3599da84df07e932b1c7902a9..b7213023b238fdeadbf0548b17790432956483c4 100644 (file)
@@ -74,10 +74,9 @@ static unsigned long clk_pll1416x_recalc_rate(struct clk_hw *hw,
                                                  unsigned long parent_rate)
 {
        struct clk_pll14xx *pll = to_clk_pll14xx(hw);
-       u32 mdiv, pdiv, sdiv, pll_gnrl, pll_div;
+       u32 mdiv, pdiv, sdiv, pll_div;
        u64 fvco = parent_rate;
 
-       pll_gnrl = readl_relaxed(pll->base);
        pll_div = readl_relaxed(pll->base + 4);
        mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
        pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
@@ -93,11 +92,10 @@ static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw,
                                                  unsigned long parent_rate)
 {
        struct clk_pll14xx *pll = to_clk_pll14xx(hw);
-       u32 mdiv, pdiv, sdiv, pll_gnrl, pll_div_ctl0, pll_div_ctl1;
+       u32 mdiv, pdiv, sdiv, pll_div_ctl0, pll_div_ctl1;
        short int kdiv;
        u64 fvco = parent_rate;
 
-       pll_gnrl = readl_relaxed(pll->base);
        pll_div_ctl0 = readl_relaxed(pll->base + 4);
        pll_div_ctl1 = readl_relaxed(pll->base + 8);
        mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
index 9af62ee8f347af29bfd474c0475957aa2da85c8a..4110e713d25945b1f48ab70aeffefb279d0d0a68 100644 (file)
@@ -20,6 +20,8 @@
 
 #define PLL_NUM_OFFSET         0x10
 #define PLL_DENOM_OFFSET       0x20
+#define PLL_IMX7_NUM_OFFSET    0x20
+#define PLL_IMX7_DENOM_OFFSET  0x30
 
 #define PLL_VF610_NUM_OFFSET   0x20
 #define PLL_VF610_DENOM_OFFSET 0x30
@@ -49,6 +51,8 @@ struct clk_pllv3 {
        u32             div_mask;
        u32             div_shift;
        unsigned long   ref_clock;
+       u32             num_offset;
+       u32             denom_offset;
 };
 
 #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw)
@@ -219,8 +223,8 @@ static unsigned long clk_pllv3_av_recalc_rate(struct clk_hw *hw,
                                              unsigned long parent_rate)
 {
        struct clk_pllv3 *pll = to_clk_pllv3(hw);
-       u32 mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET);
-       u32 mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET);
+       u32 mfn = readl_relaxed(pll->base + pll->num_offset);
+       u32 mfd = readl_relaxed(pll->base + pll->denom_offset);
        u32 div = readl_relaxed(pll->base) & pll->div_mask;
        u64 temp64 = (u64)parent_rate;
 
@@ -289,8 +293,8 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
        val &= ~pll->div_mask;
        val |= div;
        writel_relaxed(val, pll->base);
-       writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET);
-       writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET);
+       writel_relaxed(mfn, pll->base + pll->num_offset);
+       writel_relaxed(mfd, pll->base + pll->denom_offset);
 
        return clk_pllv3_wait_lock(pll);
 }
@@ -352,8 +356,8 @@ static unsigned long clk_pllv3_vf610_recalc_rate(struct clk_hw *hw,
        struct clk_pllv3 *pll = to_clk_pllv3(hw);
        struct clk_pllv3_vf610_mf mf;
 
-       mf.mfn = readl_relaxed(pll->base + PLL_VF610_NUM_OFFSET);
-       mf.mfd = readl_relaxed(pll->base + PLL_VF610_DENOM_OFFSET);
+       mf.mfn = readl_relaxed(pll->base + pll->num_offset);
+       mf.mfd = readl_relaxed(pll->base + pll->denom_offset);
        mf.mfi = (readl_relaxed(pll->base) & pll->div_mask) ? 22 : 20;
 
        return clk_pllv3_vf610_mf_to_rate(parent_rate, mf);
@@ -382,8 +386,8 @@ static int clk_pllv3_vf610_set_rate(struct clk_hw *hw, unsigned long rate,
                val |= pll->div_mask;   /* set bit for mfi=22 */
        writel_relaxed(val, pll->base);
 
-       writel_relaxed(mf.mfn, pll->base + PLL_VF610_NUM_OFFSET);
-       writel_relaxed(mf.mfd, pll->base + PLL_VF610_DENOM_OFFSET);
+       writel_relaxed(mf.mfn, pll->base + pll->num_offset);
+       writel_relaxed(mf.mfd, pll->base + pll->denom_offset);
 
        return clk_pllv3_wait_lock(pll);
 }
@@ -426,6 +430,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
                return ERR_PTR(-ENOMEM);
 
        pll->power_bit = BM_PLL_POWER;
+       pll->num_offset = PLL_NUM_OFFSET;
+       pll->denom_offset = PLL_DENOM_OFFSET;
 
        switch (type) {
        case IMX_PLLV3_SYS:
@@ -433,13 +439,20 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
                break;
        case IMX_PLLV3_SYS_VF610:
                ops = &clk_pllv3_vf610_ops;
+               pll->num_offset = PLL_VF610_NUM_OFFSET;
+               pll->denom_offset = PLL_VF610_DENOM_OFFSET;
                break;
        case IMX_PLLV3_USB_VF610:
                pll->div_shift = 1;
+               /* fall through */
        case IMX_PLLV3_USB:
                ops = &clk_pllv3_ops;
                pll->powerup_set = true;
                break;
+       case IMX_PLLV3_AV_IMX7:
+               pll->num_offset = PLL_IMX7_NUM_OFFSET;
+               pll->denom_offset = PLL_IMX7_DENOM_OFFSET;
+               /* fall through */
        case IMX_PLLV3_AV:
                ops = &clk_pllv3_av_ops;
                break;
@@ -454,6 +467,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
                break;
        case IMX_PLLV3_DDR_IMX7:
                pll->power_bit = IMX7_DDR_PLL_POWER;
+               pll->num_offset = PLL_IMX7_NUM_OFFSET;
+               pll->denom_offset = PLL_IMX7_DENOM_OFFSET;
                ops = &clk_pllv3_av_ops;
                break;
        default:
index d38bc9f87c1d4ece536663e4dc9b4db6fc9f070e..d7e62c3620d36941f498e3519bc2f03e203a26a3 100644 (file)
@@ -30,6 +30,9 @@
 /* PLL Denominator Register (xPLLDENOM) */
 #define PLL_DENOM_OFFSET       0x14
 
+#define MAX_MFD                        0x3fffffff
+#define DEFAULT_MFD            1000000
+
 struct clk_pllv4 {
        struct clk_hw   hw;
        void __iomem    *base;
@@ -64,13 +67,20 @@ static unsigned long clk_pllv4_recalc_rate(struct clk_hw *hw,
                                           unsigned long parent_rate)
 {
        struct clk_pllv4 *pll = to_clk_pllv4(hw);
-       u32 div;
+       u32 mult, mfn, mfd;
+       u64 temp64;
+
+       mult = readl_relaxed(pll->base + PLL_CFG_OFFSET);
+       mult &= BM_PLL_MULT;
+       mult >>= BP_PLL_MULT;
 
-       div = readl_relaxed(pll->base + PLL_CFG_OFFSET);
-       div &= BM_PLL_MULT;
-       div >>= BP_PLL_MULT;
+       mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET);
+       mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET);
+       temp64 = parent_rate;
+       temp64 *= mfn;
+       do_div(temp64, mfd);
 
-       return parent_rate * div;
+       return (parent_rate * mult) + (u32)temp64;
 }
 
 static long clk_pllv4_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -78,14 +88,46 @@ static long clk_pllv4_round_rate(struct clk_hw *hw, unsigned long rate,
 {
        unsigned long parent_rate = *prate;
        unsigned long round_rate, i;
+       u32 mfn, mfd = DEFAULT_MFD;
+       bool found = false;
+       u64 temp64;
 
        for (i = 0; i < ARRAY_SIZE(pllv4_mult_table); i++) {
                round_rate = parent_rate * pllv4_mult_table[i];
-               if (rate >= round_rate)
-                       return round_rate;
+               if (rate >= round_rate) {
+                       found = true;
+                       break;
+               }
+       }
+
+       if (!found) {
+               pr_warn("%s: unable to round rate %lu, parent rate %lu\n",
+                       clk_hw_get_name(hw), rate, parent_rate);
+               return 0;
        }
 
-       return round_rate;
+       if (parent_rate <= MAX_MFD)
+               mfd = parent_rate;
+
+       temp64 = (u64)(rate - round_rate);
+       temp64 *= mfd;
+       do_div(temp64, parent_rate);
+       mfn = temp64;
+
+       /*
+        * NOTE: The value of numerator must always be configured to be
+        * less than the value of the denominator. If we can't get a proper
+        * pair of mfn/mfd, we simply return the round_rate without using
+        * the frac part.
+        */
+       if (mfn >= mfd)
+               return round_rate;
+
+       temp64 = (u64)parent_rate;
+       temp64 *= mfn;
+       do_div(temp64, mfd);
+
+       return round_rate + (u32)temp64;
 }
 
 static bool clk_pllv4_is_valid_mult(unsigned int mult)
@@ -105,18 +147,30 @@ static int clk_pllv4_set_rate(struct clk_hw *hw, unsigned long rate,
                              unsigned long parent_rate)
 {
        struct clk_pllv4 *pll = to_clk_pllv4(hw);
-       u32 val, mult;
+       u32 val, mult, mfn, mfd = DEFAULT_MFD;
+       u64 temp64;
 
        mult = rate / parent_rate;
 
        if (!clk_pllv4_is_valid_mult(mult))
                return -EINVAL;
 
+       if (parent_rate <= MAX_MFD)
+               mfd = parent_rate;
+
+       temp64 = (u64)(rate - mult * parent_rate);
+       temp64 *= mfd;
+       do_div(temp64, parent_rate);
+       mfn = temp64;
+
        val = readl_relaxed(pll->base + PLL_CFG_OFFSET);
        val &= ~BM_PLL_MULT;
        val |= mult << BP_PLL_MULT;
        writel_relaxed(val, pll->base + PLL_CFG_OFFSET);
 
+       writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET);
+       writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET);
+
        return 0;
 }
 
index 9dfd03a955574e6a07e554ab7d041c122011bb7f..991bbe63f15633e35767ef96bddede264f8584ff 100644 (file)
@@ -348,7 +348,7 @@ static unsigned long clk_sccg_pll_recalc_rate(struct clk_hw *hw,
 
        temp64 = parent_rate;
 
-       val = clk_readl(pll->base + PLL_CFG0);
+       val = readl(pll->base + PLL_CFG0);
        if (val & SSCG_PLL_BYPASS2_MASK) {
                temp64 = parent_rate;
        } else if (val & SSCG_PLL_BYPASS1_MASK) {
@@ -371,10 +371,10 @@ static int clk_sccg_pll_set_rate(struct clk_hw *hw, unsigned long rate,
        u32 val;
 
        /* set bypass here too since the parent might be the same */
-       val = clk_readl(pll->base + PLL_CFG0);
+       val = readl(pll->base + PLL_CFG0);
        val &= ~SSCG_PLL_BYPASS_MASK;
        val |= FIELD_PREP(SSCG_PLL_BYPASS_MASK, setup->bypass);
-       clk_writel(val, pll->base + PLL_CFG0);
+       writel(val, pll->base + PLL_CFG0);
 
        val = readl_relaxed(pll->base + PLL_CFG2);
        val &= ~(PLL_DIVF1_MASK | PLL_DIVF2_MASK);
@@ -395,7 +395,7 @@ static u8 clk_sccg_pll_get_parent(struct clk_hw *hw)
        u32 val;
        u8 ret = pll->parent;
 
-       val = clk_readl(pll->base + PLL_CFG0);
+       val = readl(pll->base + PLL_CFG0);
        if (val & SSCG_PLL_BYPASS2_MASK)
                ret = pll->bypass2;
        else if (val & SSCG_PLL_BYPASS1_MASK)
@@ -408,10 +408,10 @@ static int clk_sccg_pll_set_parent(struct clk_hw *hw, u8 index)
        struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
        u32 val;
 
-       val = clk_readl(pll->base + PLL_CFG0);
+       val = readl(pll->base + PLL_CFG0);
        val &= ~SSCG_PLL_BYPASS_MASK;
        val |= FIELD_PREP(SSCG_PLL_BYPASS_MASK, pll->setup.bypass);
-       clk_writel(val, pll->base + PLL_CFG0);
+       writel(val, pll->base + PLL_CFG0);
 
        return clk_sccg_pll_wait_lock(pll);
 }
index 5748ec8673e45da2bf40a63f2b77d7d1b4c4331b..8639a8f2153e4b0b3a344b93b9ef36213f76e59e 100644 (file)
@@ -77,6 +77,7 @@ enum imx_pllv3_type {
        IMX_PLLV3_ENET_IMX7,
        IMX_PLLV3_SYS_VF610,
        IMX_PLLV3_DDR_IMX7,
+       IMX_PLLV3_AV_IMX7,
 };
 
 struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
@@ -138,11 +139,6 @@ static inline struct clk_hw *imx_clk_hw_fixed(const char *name, int rate)
        return clk_hw_register_fixed_rate(NULL, name, NULL, 0, rate);
 }
 
-static inline struct clk_hw *imx_get_clk_hw_fixed(const char *name, int rate)
-{
-       return clk_hw_register_fixed_rate(NULL, name, NULL, 0, rate);
-}
-
 static inline struct clk *imx_clk_mux_ldb(const char *name, void __iomem *reg,
                        u8 shift, u8 width, const char * const *parents,
                        int num_parents)
index 584ff4ff81c721b2c9a5d781c4062a3921998cb5..8901ea0295b7d2474edafaf2e6b1f769840e8af2 100644 (file)
@@ -205,6 +205,12 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
                .parents = { JZ4725B_CLK_EXT512, JZ4725B_CLK_OSC32K, -1, -1 },
                .mux = { CGU_REG_OPCR, 2, 1},
        },
+
+       [JZ4725B_CLK_UDC_PHY] = {
+               "udc_phy", CGU_CLK_GATE,
+               .parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
+               .gate = { CGU_REG_OPCR, 6, true },
+       },
 };
 
 static void __init jz4725b_cgu_init(struct device_node *np)
index 53edade25a1d98eb7e6ee3a566a9d295bc5616fd..4d8a9aef95f6dfe5d6e12c1790ab6ba8a27c7b4a 100644 (file)
@@ -216,4 +216,87 @@ config COMMON_CLK_MT8173
        default ARCH_MEDIATEK
        ---help---
          This driver supports MediaTek MT8173 clocks.
+
+config COMMON_CLK_MT8183
+       bool "Clock driver for MediaTek MT8183"
+       depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
+       select COMMON_CLK_MEDIATEK
+       default ARCH_MEDIATEK && ARM64
+       help
+         This driver supports MediaTek MT8183 basic clocks.
+
+config COMMON_CLK_MT8183_AUDIOSYS
+       bool "Clock driver for MediaTek MT8183 audiosys"
+       depends on COMMON_CLK_MT8183
+       help
+         This driver supports MediaTek MT8183 audiosys clocks.
+
+config COMMON_CLK_MT8183_CAMSYS
+       bool "Clock driver for MediaTek MT8183 camsys"
+       depends on COMMON_CLK_MT8183
+       help
+         This driver supports MediaTek MT8183 camsys clocks.
+
+config COMMON_CLK_MT8183_IMGSYS
+       bool "Clock driver for MediaTek MT8183 imgsys"
+       depends on COMMON_CLK_MT8183
+       help
+         This driver supports MediaTek MT8183 imgsys clocks.
+
+config COMMON_CLK_MT8183_IPU_CORE0
+       bool "Clock driver for MediaTek MT8183 ipu_core0"
+       depends on COMMON_CLK_MT8183
+       help
+         This driver supports MediaTek MT8183 ipu_core0 clocks.
+
+config COMMON_CLK_MT8183_IPU_CORE1
+       bool "Clock driver for MediaTek MT8183 ipu_core1"
+       depends on COMMON_CLK_MT8183
+       help
+         This driver supports MediaTek MT8183 ipu_core1 clocks.
+
+config COMMON_CLK_MT8183_IPU_ADL
+       bool "Clock driver for MediaTek MT8183 ipu_adl"
+       depends on COMMON_CLK_MT8183
+       help
+         This driver supports MediaTek MT8183 ipu_adl clocks.
+
+config COMMON_CLK_MT8183_IPU_CONN
+       bool "Clock driver for MediaTek MT8183 ipu_conn"
+       depends on COMMON_CLK_MT8183
+       help
+         This driver supports MediaTek MT8183 ipu_conn clocks.
+
+config COMMON_CLK_MT8183_MFGCFG
+       bool "Clock driver for MediaTek MT8183 mfgcfg"
+       depends on COMMON_CLK_MT8183
+       help
+         This driver supports MediaTek MT8183 mfgcfg clocks.
+
+config COMMON_CLK_MT8183_MMSYS
+       bool "Clock driver for MediaTek MT8183 mmsys"
+       depends on COMMON_CLK_MT8183
+       help
+         This driver supports MediaTek MT8183 mmsys clocks.
+
+config COMMON_CLK_MT8183_VDECSYS
+       bool "Clock driver for MediaTek MT8183 vdecsys"
+       depends on COMMON_CLK_MT8183
+       help
+         This driver supports MediaTek MT8183 vdecsys clocks.
+
+config COMMON_CLK_MT8183_VENCSYS
+       bool "Clock driver for MediaTek MT8183 vencsys"
+       depends on COMMON_CLK_MT8183
+       help
+         This driver supports MediaTek MT8183 vencsys clocks.
+
+config COMMON_CLK_MT8516
+       bool "Clock driver for MediaTek MT8516"
+       depends on ARCH_MEDIATEK || COMPILE_TEST
+       select COMMON_CLK_MEDIATEK
+       default ARCH_MEDIATEK
+       help
+         This driver supports MediaTek MT8516 clocks.
+
 endmenu
index ee4410ff43abca6123f98a4ba28588a680639dd6..f74937b35f683b405b1ecf2caa427eef5ca1a126 100644 (file)
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o
+obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o clk-mux.o
+
 obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
 obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o
 obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o
@@ -31,3 +32,16 @@ obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o
 obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o
 obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
 obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
+obj-$(CONFIG_COMMON_CLK_MT8183) += clk-mt8183.o
+obj-$(CONFIG_COMMON_CLK_MT8183_AUDIOSYS) += clk-mt8183-audio.o
+obj-$(CONFIG_COMMON_CLK_MT8183_CAMSYS) += clk-mt8183-cam.o
+obj-$(CONFIG_COMMON_CLK_MT8183_IMGSYS) += clk-mt8183-img.o
+obj-$(CONFIG_COMMON_CLK_MT8183_IPU_CORE0) += clk-mt8183-ipu0.o
+obj-$(CONFIG_COMMON_CLK_MT8183_IPU_CORE1) += clk-mt8183-ipu1.o
+obj-$(CONFIG_COMMON_CLK_MT8183_IPU_ADL) += clk-mt8183-ipu_adl.o
+obj-$(CONFIG_COMMON_CLK_MT8183_IPU_CONN) += clk-mt8183-ipu_conn.o
+obj-$(CONFIG_COMMON_CLK_MT8183_MFGCFG) += clk-mt8183-mfgcfg.o
+obj-$(CONFIG_COMMON_CLK_MT8183_MMSYS) += clk-mt8183-mm.o
+obj-$(CONFIG_COMMON_CLK_MT8183_VDECSYS) += clk-mt8183-vdec.o
+obj-$(CONFIG_COMMON_CLK_MT8183_VENCSYS) += clk-mt8183-venc.o
+obj-$(CONFIG_COMMON_CLK_MT8516) += clk-mt8516.o
index 9f766dfe1d57341a815148cc1e9afb0906b60910..ab240163f9f815dbf0293e2fe551d4af88394698 100644 (file)
@@ -50,4 +50,18 @@ struct clk *mtk_clk_register_gate(
                const struct clk_ops *ops,
                unsigned long flags);
 
+#define GATE_MTK_FLAGS(_id, _name, _parent, _regs, _shift,     \
+                       _ops, _flags) {                         \
+               .id = _id,                                      \
+               .name = _name,                                  \
+               .parent_name = _parent,                         \
+               .regs = _regs,                                  \
+               .shift = _shift,                                \
+               .ops = _ops,                                    \
+               .flags = _flags,                                \
+       }
+
+#define GATE_MTK(_id, _name, _parent, _regs, _shift, _ops)             \
+       GATE_MTK_FLAGS(_id, _name, _parent, _regs, _shift, _ops, 0)
+
 #endif /* __DRV_CLK_GATE_H */
diff --git a/drivers/clk/mediatek/clk-mt8183-audio.c b/drivers/clk/mediatek/clk-mt8183-audio.c
new file mode 100644 (file)
index 0000000..c874501
--- /dev/null
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 MediaTek Inc.
+// Author: Weiyi Lu <weiyi.lu@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8183-clk.h>
+
+static const struct mtk_gate_regs audio0_cg_regs = {
+       .set_ofs = 0x0,
+       .clr_ofs = 0x0,
+       .sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs audio1_cg_regs = {
+       .set_ofs = 0x4,
+       .clr_ofs = 0x4,
+       .sta_ofs = 0x4,
+};
+
+#define GATE_AUDIO0(_id, _name, _parent, _shift)               \
+       GATE_MTK(_id, _name, _parent, &audio0_cg_regs, _shift,  \
+               &mtk_clk_gate_ops_no_setclr)
+
+#define GATE_AUDIO1(_id, _name, _parent, _shift)               \
+       GATE_MTK(_id, _name, _parent, &audio1_cg_regs, _shift,  \
+               &mtk_clk_gate_ops_no_setclr)
+
+static const struct mtk_gate audio_clks[] = {
+       /* AUDIO0 */
+       GATE_AUDIO0(CLK_AUDIO_AFE, "aud_afe", "audio_sel",
+               2),
+       GATE_AUDIO0(CLK_AUDIO_22M, "aud_22m", "aud_eng1_sel",
+               8),
+       GATE_AUDIO0(CLK_AUDIO_24M, "aud_24m", "aud_eng2_sel",
+               9),
+       GATE_AUDIO0(CLK_AUDIO_APLL2_TUNER, "aud_apll2_tuner", "aud_eng2_sel",
+               18),
+       GATE_AUDIO0(CLK_AUDIO_APLL_TUNER, "aud_apll_tuner", "aud_eng1_sel",
+               19),
+       GATE_AUDIO0(CLK_AUDIO_TDM, "aud_tdm", "apll12_divb",
+               20),
+       GATE_AUDIO0(CLK_AUDIO_ADC, "aud_adc", "audio_sel",
+               24),
+       GATE_AUDIO0(CLK_AUDIO_DAC, "aud_dac", "audio_sel",
+               25),
+       GATE_AUDIO0(CLK_AUDIO_DAC_PREDIS, "aud_dac_predis", "audio_sel",
+               26),
+       GATE_AUDIO0(CLK_AUDIO_TML, "aud_tml", "audio_sel",
+               27),
+       /* AUDIO1 */
+       GATE_AUDIO1(CLK_AUDIO_I2S1, "aud_i2s1", "audio_sel",
+               4),
+       GATE_AUDIO1(CLK_AUDIO_I2S2, "aud_i2s2", "audio_sel",
+               5),
+       GATE_AUDIO1(CLK_AUDIO_I2S3, "aud_i2s3", "audio_sel",
+               6),
+       GATE_AUDIO1(CLK_AUDIO_I2S4, "aud_i2s4", "audio_sel",
+               7),
+       GATE_AUDIO1(CLK_AUDIO_PDN_ADDA6_ADC, "aud_pdn_adda6_adc", "audio_sel",
+               20),
+};
+
+static int clk_mt8183_audio_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       int r;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK);
+
+       mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks),
+                       clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               return r;
+
+       r = devm_of_platform_populate(&pdev->dev);
+       if (r)
+               of_clk_del_provider(node);
+
+       return r;
+}
+
+static const struct of_device_id of_match_clk_mt8183_audio[] = {
+       { .compatible = "mediatek,mt8183-audiosys", },
+       {}
+};
+
+static struct platform_driver clk_mt8183_audio_drv = {
+       .probe = clk_mt8183_audio_probe,
+       .driver = {
+               .name = "clk-mt8183-audio",
+               .of_match_table = of_match_clk_mt8183_audio,
+       },
+};
+
+builtin_platform_driver(clk_mt8183_audio_drv);
diff --git a/drivers/clk/mediatek/clk-mt8183-cam.c b/drivers/clk/mediatek/clk-mt8183-cam.c
new file mode 100644 (file)
index 0000000..8643802
--- /dev/null
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 MediaTek Inc.
+// Author: Weiyi Lu <weiyi.lu@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8183-clk.h>
+
+static const struct mtk_gate_regs cam_cg_regs = {
+       .set_ofs = 0x4,
+       .clr_ofs = 0x8,
+       .sta_ofs = 0x0,
+};
+
+#define GATE_CAM(_id, _name, _parent, _shift)                  \
+       GATE_MTK(_id, _name, _parent, &cam_cg_regs, _shift,     \
+               &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate cam_clks[] = {
+       GATE_CAM(CLK_CAM_LARB6, "cam_larb6", "cam_sel", 0),
+       GATE_CAM(CLK_CAM_DFP_VAD, "cam_dfp_vad", "cam_sel", 1),
+       GATE_CAM(CLK_CAM_LARB3, "cam_larb3", "cam_sel", 2),
+       GATE_CAM(CLK_CAM_CAM, "cam_cam", "cam_sel", 6),
+       GATE_CAM(CLK_CAM_CAMTG, "cam_camtg", "cam_sel", 7),
+       GATE_CAM(CLK_CAM_SENINF, "cam_seninf", "cam_sel", 8),
+       GATE_CAM(CLK_CAM_CAMSV0, "cam_camsv0", "cam_sel", 9),
+       GATE_CAM(CLK_CAM_CAMSV1, "cam_camsv1", "cam_sel", 10),
+       GATE_CAM(CLK_CAM_CAMSV2, "cam_camsv2", "cam_sel", 11),
+       GATE_CAM(CLK_CAM_CCU, "cam_ccu", "cam_sel", 12),
+};
+
+static int clk_mt8183_cam_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_CAM_NR_CLK);
+
+       mtk_clk_register_gates(node, cam_clks, ARRAY_SIZE(cam_clks),
+                       clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8183_cam[] = {
+       { .compatible = "mediatek,mt8183-camsys", },
+       {}
+};
+
+static struct platform_driver clk_mt8183_cam_drv = {
+       .probe = clk_mt8183_cam_probe,
+       .driver = {
+               .name = "clk-mt8183-cam",
+               .of_match_table = of_match_clk_mt8183_cam,
+       },
+};
+
+builtin_platform_driver(clk_mt8183_cam_drv);
diff --git a/drivers/clk/mediatek/clk-mt8183-img.c b/drivers/clk/mediatek/clk-mt8183-img.c
new file mode 100644 (file)
index 0000000..470d676
--- /dev/null
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 MediaTek Inc.
+// Author: Weiyi Lu <weiyi.lu@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8183-clk.h>
+
+static const struct mtk_gate_regs img_cg_regs = {
+       .set_ofs = 0x4,
+       .clr_ofs = 0x8,
+       .sta_ofs = 0x0,
+};
+
+#define GATE_IMG(_id, _name, _parent, _shift)                  \
+       GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift,     \
+               &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate img_clks[] = {
+       GATE_IMG(CLK_IMG_LARB5, "img_larb5", "img_sel", 0),
+       GATE_IMG(CLK_IMG_LARB2, "img_larb2", "img_sel", 1),
+       GATE_IMG(CLK_IMG_DIP, "img_dip", "img_sel", 2),
+       GATE_IMG(CLK_IMG_FDVT, "img_fdvt", "img_sel", 3),
+       GATE_IMG(CLK_IMG_DPE, "img_dpe", "img_sel", 4),
+       GATE_IMG(CLK_IMG_RSC, "img_rsc", "img_sel", 5),
+       GATE_IMG(CLK_IMG_MFB, "img_mfb", "img_sel", 6),
+       GATE_IMG(CLK_IMG_WPE_A, "img_wpe_a", "img_sel", 7),
+       GATE_IMG(CLK_IMG_WPE_B, "img_wpe_b", "img_sel", 8),
+       GATE_IMG(CLK_IMG_OWE, "img_owe", "img_sel", 9),
+};
+
+static int clk_mt8183_img_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK);
+
+       mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
+                       clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8183_img[] = {
+       { .compatible = "mediatek,mt8183-imgsys", },
+       {}
+};
+
+static struct platform_driver clk_mt8183_img_drv = {
+       .probe = clk_mt8183_img_probe,
+       .driver = {
+               .name = "clk-mt8183-img",
+               .of_match_table = of_match_clk_mt8183_img,
+       },
+};
+
+builtin_platform_driver(clk_mt8183_img_drv);
diff --git a/drivers/clk/mediatek/clk-mt8183-ipu0.c b/drivers/clk/mediatek/clk-mt8183-ipu0.c
new file mode 100644 (file)
index 0000000..c5cb76f
--- /dev/null
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 MediaTek Inc.
+// Author: Weiyi Lu <weiyi.lu@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8183-clk.h>
+
+static const struct mtk_gate_regs ipu_core0_cg_regs = {
+       .set_ofs = 0x4,
+       .clr_ofs = 0x8,
+       .sta_ofs = 0x0,
+};
+
+#define GATE_IPU_CORE0(_id, _name, _parent, _shift)                    \
+       GATE_MTK(_id, _name, _parent, &ipu_core0_cg_regs, _shift,       \
+               &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate ipu_core0_clks[] = {
+       GATE_IPU_CORE0(CLK_IPU_CORE0_JTAG, "ipu_core0_jtag", "dsp_sel", 0),
+       GATE_IPU_CORE0(CLK_IPU_CORE0_AXI, "ipu_core0_axi", "dsp_sel", 1),
+       GATE_IPU_CORE0(CLK_IPU_CORE0_IPU, "ipu_core0_ipu", "dsp_sel", 2),
+};
+
+static int clk_mt8183_ipu_core0_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_IPU_CORE0_NR_CLK);
+
+       mtk_clk_register_gates(node, ipu_core0_clks, ARRAY_SIZE(ipu_core0_clks),
+                       clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8183_ipu_core0[] = {
+       { .compatible = "mediatek,mt8183-ipu_core0", },
+       {}
+};
+
+static struct platform_driver clk_mt8183_ipu_core0_drv = {
+       .probe = clk_mt8183_ipu_core0_probe,
+       .driver = {
+               .name = "clk-mt8183-ipu_core0",
+               .of_match_table = of_match_clk_mt8183_ipu_core0,
+       },
+};
+
+builtin_platform_driver(clk_mt8183_ipu_core0_drv);
diff --git a/drivers/clk/mediatek/clk-mt8183-ipu1.c b/drivers/clk/mediatek/clk-mt8183-ipu1.c
new file mode 100644 (file)
index 0000000..8fd5fe0
--- /dev/null
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 MediaTek Inc.
+// Author: Weiyi Lu <weiyi.lu@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8183-clk.h>
+
+static const struct mtk_gate_regs ipu_core1_cg_regs = {
+       .set_ofs = 0x4,
+       .clr_ofs = 0x8,
+       .sta_ofs = 0x0,
+};
+
+#define GATE_IPU_CORE1(_id, _name, _parent, _shift)                    \
+       GATE_MTK(_id, _name, _parent, &ipu_core1_cg_regs, _shift,       \
+               &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate ipu_core1_clks[] = {
+       GATE_IPU_CORE1(CLK_IPU_CORE1_JTAG, "ipu_core1_jtag", "dsp_sel", 0),
+       GATE_IPU_CORE1(CLK_IPU_CORE1_AXI, "ipu_core1_axi", "dsp_sel", 1),
+       GATE_IPU_CORE1(CLK_IPU_CORE1_IPU, "ipu_core1_ipu", "dsp_sel", 2),
+};
+
+static int clk_mt8183_ipu_core1_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_IPU_CORE1_NR_CLK);
+
+       mtk_clk_register_gates(node, ipu_core1_clks, ARRAY_SIZE(ipu_core1_clks),
+                       clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8183_ipu_core1[] = {
+       { .compatible = "mediatek,mt8183-ipu_core1", },
+       {}
+};
+
+static struct platform_driver clk_mt8183_ipu_core1_drv = {
+       .probe = clk_mt8183_ipu_core1_probe,
+       .driver = {
+               .name = "clk-mt8183-ipu_core1",
+               .of_match_table = of_match_clk_mt8183_ipu_core1,
+       },
+};
+
+builtin_platform_driver(clk_mt8183_ipu_core1_drv);
diff --git a/drivers/clk/mediatek/clk-mt8183-ipu_adl.c b/drivers/clk/mediatek/clk-mt8183-ipu_adl.c
new file mode 100644 (file)
index 0000000..3f37d0e
--- /dev/null
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 MediaTek Inc.
+// Author: Weiyi Lu <weiyi.lu@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8183-clk.h>
+
+static const struct mtk_gate_regs ipu_adl_cg_regs = {
+       .set_ofs = 0x204,
+       .clr_ofs = 0x204,
+       .sta_ofs = 0x204,
+};
+
+#define GATE_IPU_ADL_I(_id, _name, _parent, _shift)            \
+       GATE_MTK(_id, _name, _parent, &ipu_adl_cg_regs, _shift, \
+               &mtk_clk_gate_ops_no_setclr_inv)
+
+static const struct mtk_gate ipu_adl_clks[] = {
+       GATE_IPU_ADL_I(CLK_IPU_ADL_CABGEN, "ipu_adl_cabgen", "dsp_sel", 24),
+};
+
+static int clk_mt8183_ipu_adl_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_IPU_ADL_NR_CLK);
+
+       mtk_clk_register_gates(node, ipu_adl_clks, ARRAY_SIZE(ipu_adl_clks),
+                       clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8183_ipu_adl[] = {
+       { .compatible = "mediatek,mt8183-ipu_adl", },
+       {}
+};
+
+static struct platform_driver clk_mt8183_ipu_adl_drv = {
+       .probe = clk_mt8183_ipu_adl_probe,
+       .driver = {
+               .name = "clk-mt8183-ipu_adl",
+               .of_match_table = of_match_clk_mt8183_ipu_adl,
+       },
+};
+
+builtin_platform_driver(clk_mt8183_ipu_adl_drv);
diff --git a/drivers/clk/mediatek/clk-mt8183-ipu_conn.c b/drivers/clk/mediatek/clk-mt8183-ipu_conn.c
new file mode 100644 (file)
index 0000000..7e0eef7
--- /dev/null
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 MediaTek Inc.
+// Author: Weiyi Lu <weiyi.lu@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8183-clk.h>
+
+static const struct mtk_gate_regs ipu_conn_cg_regs = {
+       .set_ofs = 0x4,
+       .clr_ofs = 0x8,
+       .sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs ipu_conn_apb_cg_regs = {
+       .set_ofs = 0x10,
+       .clr_ofs = 0x10,
+       .sta_ofs = 0x10,
+};
+
+static const struct mtk_gate_regs ipu_conn_axi_cg_regs = {
+       .set_ofs = 0x18,
+       .clr_ofs = 0x18,
+       .sta_ofs = 0x18,
+};
+
+static const struct mtk_gate_regs ipu_conn_axi1_cg_regs = {
+       .set_ofs = 0x1c,
+       .clr_ofs = 0x1c,
+       .sta_ofs = 0x1c,
+};
+
+static const struct mtk_gate_regs ipu_conn_axi2_cg_regs = {
+       .set_ofs = 0x20,
+       .clr_ofs = 0x20,
+       .sta_ofs = 0x20,
+};
+
+#define GATE_IPU_CONN(_id, _name, _parent, _shift)                     \
+       GATE_MTK(_id, _name, _parent, &ipu_conn_cg_regs, _shift,        \
+               &mtk_clk_gate_ops_setclr)
+
+#define GATE_IPU_CONN_APB(_id, _name, _parent, _shift)                 \
+       GATE_MTK(_id, _name, _parent, &ipu_conn_apb_cg_regs, _shift,    \
+               &mtk_clk_gate_ops_no_setclr)
+
+#define GATE_IPU_CONN_AXI_I(_id, _name, _parent, _shift)               \
+       GATE_MTK(_id, _name, _parent, &ipu_conn_axi_cg_regs, _shift,    \
+               &mtk_clk_gate_ops_no_setclr_inv)
+
+#define GATE_IPU_CONN_AXI1_I(_id, _name, _parent, _shift)              \
+       GATE_MTK(_id, _name, _parent, &ipu_conn_axi1_cg_regs, _shift,   \
+               &mtk_clk_gate_ops_no_setclr_inv)
+
+#define GATE_IPU_CONN_AXI2_I(_id, _name, _parent, _shift)              \
+       GATE_MTK(_id, _name, _parent, &ipu_conn_axi2_cg_regs, _shift,   \
+               &mtk_clk_gate_ops_no_setclr_inv)
+
+static const struct mtk_gate ipu_conn_clks[] = {
+       GATE_IPU_CONN(CLK_IPU_CONN_IPU,
+               "ipu_conn_ipu", "dsp_sel", 0),
+       GATE_IPU_CONN(CLK_IPU_CONN_AHB,
+               "ipu_conn_ahb", "dsp_sel", 1),
+       GATE_IPU_CONN(CLK_IPU_CONN_AXI,
+               "ipu_conn_axi", "dsp_sel", 2),
+       GATE_IPU_CONN(CLK_IPU_CONN_ISP,
+               "ipu_conn_isp", "dsp_sel", 3),
+       GATE_IPU_CONN(CLK_IPU_CONN_CAM_ADL,
+               "ipu_conn_cam_adl", "dsp_sel", 4),
+       GATE_IPU_CONN(CLK_IPU_CONN_IMG_ADL,
+               "ipu_conn_img_adl", "dsp_sel", 5),
+       GATE_IPU_CONN_APB(CLK_IPU_CONN_DAP_RX,
+               "ipu_conn_dap_rx", "dsp1_sel", 0),
+       GATE_IPU_CONN_APB(CLK_IPU_CONN_APB2AXI,
+               "ipu_conn_apb2axi", "dsp1_sel", 3),
+       GATE_IPU_CONN_APB(CLK_IPU_CONN_APB2AHB,
+               "ipu_conn_apb2ahb", "dsp1_sel", 20),
+       GATE_IPU_CONN_AXI_I(CLK_IPU_CONN_IPU_CAB1TO2,
+               "ipu_conn_ipu_cab1to2", "dsp1_sel", 6),
+       GATE_IPU_CONN_AXI_I(CLK_IPU_CONN_IPU1_CAB1TO2,
+               "ipu_conn_ipu1_cab1to2", "dsp1_sel", 13),
+       GATE_IPU_CONN_AXI_I(CLK_IPU_CONN_IPU2_CAB1TO2,
+               "ipu_conn_ipu2_cab1to2", "dsp1_sel", 20),
+       GATE_IPU_CONN_AXI1_I(CLK_IPU_CONN_CAB3TO3,
+               "ipu_conn_cab3to3", "dsp1_sel", 0),
+       GATE_IPU_CONN_AXI2_I(CLK_IPU_CONN_CAB2TO1,
+               "ipu_conn_cab2to1", "dsp1_sel", 14),
+       GATE_IPU_CONN_AXI2_I(CLK_IPU_CONN_CAB3TO1_SLICE,
+               "ipu_conn_cab3to1_slice", "dsp1_sel", 17),
+};
+
+static int clk_mt8183_ipu_conn_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_IPU_CONN_NR_CLK);
+
+       mtk_clk_register_gates(node, ipu_conn_clks, ARRAY_SIZE(ipu_conn_clks),
+                       clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8183_ipu_conn[] = {
+       { .compatible = "mediatek,mt8183-ipu_conn", },
+       {}
+};
+
+static struct platform_driver clk_mt8183_ipu_conn_drv = {
+       .probe = clk_mt8183_ipu_conn_probe,
+       .driver = {
+               .name = "clk-mt8183-ipu_conn",
+               .of_match_table = of_match_clk_mt8183_ipu_conn,
+       },
+};
+
+builtin_platform_driver(clk_mt8183_ipu_conn_drv);
diff --git a/drivers/clk/mediatek/clk-mt8183-mfgcfg.c b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c
new file mode 100644 (file)
index 0000000..99a6b02
--- /dev/null
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 MediaTek Inc.
+// Author: Weiyi Lu <weiyi.lu@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8183-clk.h>
+
+static const struct mtk_gate_regs mfg_cg_regs = {
+       .set_ofs = 0x4,
+       .clr_ofs = 0x8,
+       .sta_ofs = 0x0,
+};
+
+#define GATE_MFG(_id, _name, _parent, _shift)                  \
+       GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift,     \
+               &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate mfg_clks[] = {
+       GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_sel", 0)
+};
+
+static int clk_mt8183_mfg_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_MFG_NR_CLK);
+
+       mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks),
+                       clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8183_mfg[] = {
+       { .compatible = "mediatek,mt8183-mfgcfg", },
+       {}
+};
+
+static struct platform_driver clk_mt8183_mfg_drv = {
+       .probe = clk_mt8183_mfg_probe,
+       .driver = {
+               .name = "clk-mt8183-mfg",
+               .of_match_table = of_match_clk_mt8183_mfg,
+       },
+};
+
+builtin_platform_driver(clk_mt8183_mfg_drv);
diff --git a/drivers/clk/mediatek/clk-mt8183-mm.c b/drivers/clk/mediatek/clk-mt8183-mm.c
new file mode 100644 (file)
index 0000000..720c696
--- /dev/null
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 MediaTek Inc.
+// Author: Weiyi Lu <weiyi.lu@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8183-clk.h>
+
+static const struct mtk_gate_regs mm0_cg_regs = {
+       .set_ofs = 0x104,
+       .clr_ofs = 0x108,
+       .sta_ofs = 0x100,
+};
+
+static const struct mtk_gate_regs mm1_cg_regs = {
+       .set_ofs = 0x114,
+       .clr_ofs = 0x118,
+       .sta_ofs = 0x110,
+};
+
+#define GATE_MM0(_id, _name, _parent, _shift)                  \
+       GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift,     \
+               &mtk_clk_gate_ops_setclr)
+
+#define GATE_MM1(_id, _name, _parent, _shift)                  \
+       GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift,     \
+               &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate mm_clks[] = {
+       /* MM0 */
+       GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0),
+       GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
+       GATE_MM0(CLK_MM_SMI_LARB1, "mm_smi_larb1", "mm_sel", 2),
+       GATE_MM0(CLK_MM_GALS_COMM0, "mm_gals_comm0", "mm_sel", 3),
+       GATE_MM0(CLK_MM_GALS_COMM1, "mm_gals_comm1", "mm_sel", 4),
+       GATE_MM0(CLK_MM_GALS_CCU2MM, "mm_gals_ccu2mm", "mm_sel", 5),
+       GATE_MM0(CLK_MM_GALS_IPU12MM, "mm_gals_ipu12mm", "mm_sel", 6),
+       GATE_MM0(CLK_MM_GALS_IMG2MM, "mm_gals_img2mm", "mm_sel", 7),
+       GATE_MM0(CLK_MM_GALS_CAM2MM, "mm_gals_cam2mm", "mm_sel", 8),
+       GATE_MM0(CLK_MM_GALS_IPU2MM, "mm_gals_ipu2mm", "mm_sel", 9),
+       GATE_MM0(CLK_MM_MDP_DL_TXCK, "mm_mdp_dl_txck", "mm_sel", 10),
+       GATE_MM0(CLK_MM_IPU_DL_TXCK, "mm_ipu_dl_txck", "mm_sel", 11),
+       GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 12),
+       GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 13),
+       GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 14),
+       GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 15),
+       GATE_MM0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 16),
+       GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 17),
+       GATE_MM0(CLK_MM_MDP_WDMA0, "mm_mdp_wdma0", "mm_sel", 18),
+       GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 19),
+       GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 20),
+       GATE_MM0(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "mm_sel", 21),
+       GATE_MM0(CLK_MM_DISP_OVL1_2L, "mm_disp_ovl1_2l", "mm_sel", 22),
+       GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 23),
+       GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 24),
+       GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 25),
+       GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 26),
+       GATE_MM0(CLK_MM_DISP_CCORR0, "mm_disp_ccorr0", "mm_sel", 27),
+       GATE_MM0(CLK_MM_DISP_AAL0, "mm_disp_aal0", "mm_sel", 28),
+       GATE_MM0(CLK_MM_DISP_GAMMA0, "mm_disp_gamma0", "mm_sel", 29),
+       GATE_MM0(CLK_MM_DISP_DITHER0, "mm_disp_dither0", "mm_sel", 30),
+       GATE_MM0(CLK_MM_DISP_SPLIT, "mm_disp_split", "mm_sel", 31),
+       /* MM1 */
+       GATE_MM1(CLK_MM_DSI0_MM, "mm_dsi0_mm", "mm_sel", 0),
+       GATE_MM1(CLK_MM_DSI0_IF, "mm_dsi0_if", "mm_sel", 1),
+       GATE_MM1(CLK_MM_DPI_MM, "mm_dpi_mm", "mm_sel", 2),
+       GATE_MM1(CLK_MM_DPI_IF, "mm_dpi_if", "dpi0_sel", 3),
+       GATE_MM1(CLK_MM_FAKE_ENG2, "mm_fake_eng2", "mm_sel", 4),
+       GATE_MM1(CLK_MM_MDP_DL_RX, "mm_mdp_dl_rx", "mm_sel", 5),
+       GATE_MM1(CLK_MM_IPU_DL_RX, "mm_ipu_dl_rx", "mm_sel", 6),
+       GATE_MM1(CLK_MM_26M, "mm_26m", "f_f26m_ck", 7),
+       GATE_MM1(CLK_MM_MMSYS_R2Y, "mm_mmsys_r2y", "mm_sel", 8),
+       GATE_MM1(CLK_MM_DISP_RSZ, "mm_disp_rsz", "mm_sel", 9),
+       GATE_MM1(CLK_MM_MDP_AAL, "mm_mdp_aal", "mm_sel", 10),
+       GATE_MM1(CLK_MM_MDP_CCORR, "mm_mdp_ccorr", "mm_sel", 11),
+       GATE_MM1(CLK_MM_DBI_MM, "mm_dbi_mm", "mm_sel", 12),
+       GATE_MM1(CLK_MM_DBI_IF, "mm_dbi_if", "dpi0_sel", 13),
+};
+
+static int clk_mt8183_mm_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
+
+       mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
+                       clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8183_mm[] = {
+       { .compatible = "mediatek,mt8183-mmsys", },
+       {}
+};
+
+static struct platform_driver clk_mt8183_mm_drv = {
+       .probe = clk_mt8183_mm_probe,
+       .driver = {
+               .name = "clk-mt8183-mm",
+               .of_match_table = of_match_clk_mt8183_mm,
+       },
+};
+
+builtin_platform_driver(clk_mt8183_mm_drv);
diff --git a/drivers/clk/mediatek/clk-mt8183-vdec.c b/drivers/clk/mediatek/clk-mt8183-vdec.c
new file mode 100644 (file)
index 0000000..6250fd1
--- /dev/null
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 MediaTek Inc.
+// Author: Weiyi Lu <weiyi.lu@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8183-clk.h>
+
+static const struct mtk_gate_regs vdec0_cg_regs = {
+       .set_ofs = 0x0,
+       .clr_ofs = 0x4,
+       .sta_ofs = 0x0,
+};
+
+static const struct mtk_gate_regs vdec1_cg_regs = {
+       .set_ofs = 0x8,
+       .clr_ofs = 0xc,
+       .sta_ofs = 0x8,
+};
+
+#define GATE_VDEC0_I(_id, _name, _parent, _shift)              \
+       GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift,   \
+               &mtk_clk_gate_ops_setclr_inv)
+
+#define GATE_VDEC1_I(_id, _name, _parent, _shift)              \
+       GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift,   \
+               &mtk_clk_gate_ops_setclr_inv)
+
+static const struct mtk_gate vdec_clks[] = {
+       /* VDEC0 */
+       GATE_VDEC0_I(CLK_VDEC_VDEC, "vdec_vdec", "mm_sel", 0),
+       /* VDEC1 */
+       GATE_VDEC1_I(CLK_VDEC_LARB1, "vdec_larb1", "mm_sel", 0),
+};
+
+static int clk_mt8183_vdec_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK);
+
+       mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
+                       clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8183_vdec[] = {
+       { .compatible = "mediatek,mt8183-vdecsys", },
+       {}
+};
+
+static struct platform_driver clk_mt8183_vdec_drv = {
+       .probe = clk_mt8183_vdec_probe,
+       .driver = {
+               .name = "clk-mt8183-vdec",
+               .of_match_table = of_match_clk_mt8183_vdec,
+       },
+};
+
+builtin_platform_driver(clk_mt8183_vdec_drv);
diff --git a/drivers/clk/mediatek/clk-mt8183-venc.c b/drivers/clk/mediatek/clk-mt8183-venc.c
new file mode 100644 (file)
index 0000000..6678ef0
--- /dev/null
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 MediaTek Inc.
+// Author: Weiyi Lu <weiyi.lu@mediatek.com>
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8183-clk.h>
+
+static const struct mtk_gate_regs venc_cg_regs = {
+       .set_ofs = 0x4,
+       .clr_ofs = 0x8,
+       .sta_ofs = 0x0,
+};
+
+#define GATE_VENC_I(_id, _name, _parent, _shift)               \
+       GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift,    \
+               &mtk_clk_gate_ops_setclr_inv)
+
+static const struct mtk_gate venc_clks[] = {
+       GATE_VENC_I(CLK_VENC_LARB, "venc_larb",
+               "mm_sel", 0),
+       GATE_VENC_I(CLK_VENC_VENC, "venc_venc",
+               "mm_sel", 4),
+       GATE_VENC_I(CLK_VENC_JPGENC, "venc_jpgenc",
+               "mm_sel", 8),
+};
+
+static int clk_mt8183_venc_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK);
+
+       mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
+                       clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8183_venc[] = {
+       { .compatible = "mediatek,mt8183-vencsys", },
+       {}
+};
+
+static struct platform_driver clk_mt8183_venc_drv = {
+       .probe = clk_mt8183_venc_probe,
+       .driver = {
+               .name = "clk-mt8183-venc",
+               .of_match_table = of_match_clk_mt8183_venc,
+       },
+};
+
+builtin_platform_driver(clk_mt8183_venc_drv);
diff --git a/drivers/clk/mediatek/clk-mt8183.c b/drivers/clk/mediatek/clk-mt8183.c
new file mode 100644 (file)
index 0000000..9d86510
--- /dev/null
@@ -0,0 +1,1284 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 MediaTek Inc.
+// Author: Weiyi Lu <weiyi.lu@mediatek.com>
+
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+#include "clk-mux.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8183-clk.h>
+
+static DEFINE_SPINLOCK(mt8183_clk_lock);
+
+static const struct mtk_fixed_clk top_fixed_clks[] = {
+       FIXED_CLK(CLK_TOP_CLK26M, "f_f26m_ck", "clk26m", 26000000),
+       FIXED_CLK(CLK_TOP_ULPOSC, "osc", NULL, 250000),
+       FIXED_CLK(CLK_TOP_UNIVP_192M, "univpll_192m", "univpll", 192000000),
+};
+
+static const struct mtk_fixed_factor top_divs[] = {
+       FACTOR(CLK_TOP_CLK13M, "clk13m", "clk26m", 1,
+               2),
+       FACTOR(CLK_TOP_F26M_CK_D2, "csw_f26m_ck_d2", "clk26m", 1,
+               2),
+       FACTOR(CLK_TOP_SYSPLL_CK, "syspll_ck", "mainpll", 1,
+               1),
+       FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "syspll_ck", 1,
+               2),
+       FACTOR(CLK_TOP_SYSPLL_D2_D2, "syspll_d2_d2", "syspll_d2", 1,
+               2),
+       FACTOR(CLK_TOP_SYSPLL_D2_D4, "syspll_d2_d4", "syspll_d2", 1,
+               4),
+       FACTOR(CLK_TOP_SYSPLL_D2_D8, "syspll_d2_d8", "syspll_d2", 1,
+               8),
+       FACTOR(CLK_TOP_SYSPLL_D2_D16, "syspll_d2_d16", "syspll_d2", 1,
+               16),
+       FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1,
+               3),
+       FACTOR(CLK_TOP_SYSPLL_D3_D2, "syspll_d3_d2", "syspll_d3", 1,
+               2),
+       FACTOR(CLK_TOP_SYSPLL_D3_D4, "syspll_d3_d4", "syspll_d3", 1,
+               4),
+       FACTOR(CLK_TOP_SYSPLL_D3_D8, "syspll_d3_d8", "syspll_d3", 1,
+               8),
+       FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1,
+               5),
+       FACTOR(CLK_TOP_SYSPLL_D5_D2, "syspll_d5_d2", "syspll_d5", 1,
+               2),
+       FACTOR(CLK_TOP_SYSPLL_D5_D4, "syspll_d5_d4", "syspll_d5", 1,
+               4),
+       FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1,
+               7),
+       FACTOR(CLK_TOP_SYSPLL_D7_D2, "syspll_d7_d2", "syspll_d7", 1,
+               2),
+       FACTOR(CLK_TOP_SYSPLL_D7_D4, "syspll_d7_d4", "syspll_d7", 1,
+               4),
+       FACTOR(CLK_TOP_UNIVPLL_CK, "univpll_ck", "univpll", 1,
+               1),
+       FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll_ck", 1,
+               2),
+       FACTOR(CLK_TOP_UNIVPLL_D2_D2, "univpll_d2_d2", "univpll_d2", 1,
+               2),
+       FACTOR(CLK_TOP_UNIVPLL_D2_D4, "univpll_d2_d4", "univpll_d2", 1,
+               4),
+       FACTOR(CLK_TOP_UNIVPLL_D2_D8, "univpll_d2_d8", "univpll_d2", 1,
+               8),
+       FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1,
+               3),
+       FACTOR(CLK_TOP_UNIVPLL_D3_D2, "univpll_d3_d2", "univpll_d3", 1,
+               2),
+       FACTOR(CLK_TOP_UNIVPLL_D3_D4, "univpll_d3_d4", "univpll_d3", 1,
+               4),
+       FACTOR(CLK_TOP_UNIVPLL_D3_D8, "univpll_d3_d8", "univpll_d3", 1,
+               8),
+       FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1,
+               5),
+       FACTOR(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1,
+               2),
+       FACTOR(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1,
+               4),
+       FACTOR(CLK_TOP_UNIVPLL_D5_D8, "univpll_d5_d8", "univpll_d5", 1,
+               8),
+       FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1,
+               7),
+       FACTOR(CLK_TOP_UNIVP_192M_CK, "univ_192m_ck", "univpll_192m", 1,
+               1),
+       FACTOR(CLK_TOP_UNIVP_192M_D2, "univ_192m_d2", "univ_192m_ck", 1,
+               2),
+       FACTOR(CLK_TOP_UNIVP_192M_D4, "univ_192m_d4", "univ_192m_ck", 1,
+               4),
+       FACTOR(CLK_TOP_UNIVP_192M_D8, "univ_192m_d8", "univ_192m_ck", 1,
+               8),
+       FACTOR(CLK_TOP_UNIVP_192M_D16, "univ_192m_d16", "univ_192m_ck", 1,
+               16),
+       FACTOR(CLK_TOP_UNIVP_192M_D32, "univ_192m_d32", "univ_192m_ck", 1,
+               32),
+       FACTOR(CLK_TOP_APLL1_CK, "apll1_ck", "apll1", 1,
+               1),
+       FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1", 1,
+               2),
+       FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1,
+               4),
+       FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1", 1,
+               8),
+       FACTOR(CLK_TOP_APLL2_CK, "apll2_ck", "apll2", 1,
+               1),
+       FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1,
+               2),
+       FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1,
+               4),
+       FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2", 1,
+               8),
+       FACTOR(CLK_TOP_TVDPLL_CK, "tvdpll_ck", "tvdpll", 1,
+               1),
+       FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1,
+               2),
+       FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1,
+               4),
+       FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll", 1,
+               8),
+       FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll", 1,
+               16),
+       FACTOR(CLK_TOP_MMPLL_CK, "mmpll_ck", "mmpll", 1,
+               1),
+       FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll", 1,
+               4),
+       FACTOR(CLK_TOP_MMPLL_D4_D2, "mmpll_d4_d2", "mmpll_d4", 1,
+               2),
+       FACTOR(CLK_TOP_MMPLL_D4_D4, "mmpll_d4_d4", "mmpll_d4", 1,
+               4),
+       FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1,
+               5),
+       FACTOR(CLK_TOP_MMPLL_D5_D2, "mmpll_d5_d2", "mmpll_d5", 1,
+               2),
+       FACTOR(CLK_TOP_MMPLL_D5_D4, "mmpll_d5_d4", "mmpll_d5", 1,
+               4),
+       FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll", 1,
+               6),
+       FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1,
+               7),
+       FACTOR(CLK_TOP_MFGPLL_CK, "mfgpll_ck", "mfgpll", 1,
+               1),
+       FACTOR(CLK_TOP_MSDCPLL_CK, "msdcpll_ck", "msdcpll", 1,
+               1),
+       FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1,
+               2),
+       FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1,
+               4),
+       FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1,
+               8),
+       FACTOR(CLK_TOP_MSDCPLL_D16, "msdcpll_d16", "msdcpll", 1,
+               16),
+       FACTOR(CLK_TOP_AD_OSC_CK, "ad_osc_ck", "osc", 1,
+               1),
+       FACTOR(CLK_TOP_OSC_D2, "osc_d2", "osc", 1,
+               2),
+       FACTOR(CLK_TOP_OSC_D4, "osc_d4", "osc", 1,
+               4),
+       FACTOR(CLK_TOP_OSC_D8, "osc_d8", "osc", 1,
+               8),
+       FACTOR(CLK_TOP_OSC_D16, "osc_d16", "osc", 1,
+               16),
+       FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1,
+               2),
+       FACTOR(CLK_TOP_UNIVPLL_D3_D16, "univpll_d3_d16", "univpll_d3", 1,
+               16),
+};
+
+static const char * const axi_parents[] = {
+       "clk26m",
+       "syspll_d2_d4",
+       "syspll_d7",
+       "osc_d4"
+};
+
+static const char * const mm_parents[] = {
+       "clk26m",
+       "mmpll_d7",
+       "syspll_d3",
+       "univpll_d2_d2",
+       "syspll_d2_d2",
+       "syspll_d3_d2"
+};
+
+static const char * const img_parents[] = {
+       "clk26m",
+       "mmpll_d6",
+       "univpll_d3",
+       "syspll_d3",
+       "univpll_d2_d2",
+       "syspll_d2_d2",
+       "univpll_d3_d2",
+       "syspll_d3_d2"
+};
+
+static const char * const cam_parents[] = {
+       "clk26m",
+       "syspll_d2",
+       "mmpll_d6",
+       "syspll_d3",
+       "mmpll_d7",
+       "univpll_d3",
+       "univpll_d2_d2",
+       "syspll_d2_d2",
+       "syspll_d3_d2",
+       "univpll_d3_d2"
+};
+
+static const char * const dsp_parents[] = {
+       "clk26m",
+       "mmpll_d6",
+       "mmpll_d7",
+       "univpll_d3",
+       "syspll_d3",
+       "univpll_d2_d2",
+       "syspll_d2_d2",
+       "univpll_d3_d2",
+       "syspll_d3_d2"
+};
+
+static const char * const dsp1_parents[] = {
+       "clk26m",
+       "mmpll_d6",
+       "mmpll_d7",
+       "univpll_d3",
+       "syspll_d3",
+       "univpll_d2_d2",
+       "syspll_d2_d2",
+       "univpll_d3_d2",
+       "syspll_d3_d2"
+};
+
+static const char * const dsp2_parents[] = {
+       "clk26m",
+       "mmpll_d6",
+       "mmpll_d7",
+       "univpll_d3",
+       "syspll_d3",
+       "univpll_d2_d2",
+       "syspll_d2_d2",
+       "univpll_d3_d2",
+       "syspll_d3_d2"
+};
+
+static const char * const ipu_if_parents[] = {
+       "clk26m",
+       "mmpll_d6",
+       "mmpll_d7",
+       "univpll_d3",
+       "syspll_d3",
+       "univpll_d2_d2",
+       "syspll_d2_d2",
+       "univpll_d3_d2",
+       "syspll_d3_d2"
+};
+
+static const char * const mfg_parents[] = {
+       "clk26m",
+       "mfgpll_ck",
+       "univpll_d3",
+       "syspll_d3"
+};
+
+static const char * const f52m_mfg_parents[] = {
+       "clk26m",
+       "univpll_d3_d2",
+       "univpll_d3_d4",
+       "univpll_d3_d8"
+};
+
+static const char * const camtg_parents[] = {
+       "clk26m",
+       "univ_192m_d8",
+       "univpll_d3_d8",
+       "univ_192m_d4",
+       "univpll_d3_d16",
+       "csw_f26m_ck_d2",
+       "univ_192m_d16",
+       "univ_192m_d32"
+};
+
+static const char * const camtg2_parents[] = {
+       "clk26m",
+       "univ_192m_d8",
+       "univpll_d3_d8",
+       "univ_192m_d4",
+       "univpll_d3_d16",
+       "csw_f26m_ck_d2",
+       "univ_192m_d16",
+       "univ_192m_d32"
+};
+
+static const char * const camtg3_parents[] = {
+       "clk26m",
+       "univ_192m_d8",
+       "univpll_d3_d8",
+       "univ_192m_d4",
+       "univpll_d3_d16",
+       "csw_f26m_ck_d2",
+       "univ_192m_d16",
+       "univ_192m_d32"
+};
+
+static const char * const camtg4_parents[] = {
+       "clk26m",
+       "univ_192m_d8",
+       "univpll_d3_d8",
+       "univ_192m_d4",
+       "univpll_d3_d16",
+       "csw_f26m_ck_d2",
+       "univ_192m_d16",
+       "univ_192m_d32"
+};
+
+static const char * const uart_parents[] = {
+       "clk26m",
+       "univpll_d3_d8"
+};
+
+static const char * const spi_parents[] = {
+       "clk26m",
+       "syspll_d5_d2",
+       "syspll_d3_d4",
+       "msdcpll_d4"
+};
+
+static const char * const msdc50_hclk_parents[] = {
+       "clk26m",
+       "syspll_d2_d2",
+       "syspll_d3_d2"
+};
+
+static const char * const msdc50_0_parents[] = {
+       "clk26m",
+       "msdcpll_ck",
+       "msdcpll_d2",
+       "univpll_d2_d4",
+       "syspll_d3_d2",
+       "univpll_d2_d2"
+};
+
+static const char * const msdc30_1_parents[] = {
+       "clk26m",
+       "univpll_d3_d2",
+       "syspll_d3_d2",
+       "syspll_d7",
+       "msdcpll_d2"
+};
+
+static const char * const msdc30_2_parents[] = {
+       "clk26m",
+       "univpll_d3_d2",
+       "syspll_d3_d2",
+       "syspll_d7",
+       "msdcpll_d2"
+};
+
+static const char * const audio_parents[] = {
+       "clk26m",
+       "syspll_d5_d4",
+       "syspll_d7_d4",
+       "syspll_d2_d16"
+};
+
+static const char * const aud_intbus_parents[] = {
+       "clk26m",
+       "syspll_d2_d4",
+       "syspll_d7_d2"
+};
+
+static const char * const pmicspi_parents[] = {
+       "clk26m",
+       "syspll_d2_d8",
+       "osc_d8"
+};
+
+static const char * const fpwrap_ulposc_parents[] = {
+       "clk26m",
+       "osc_d16",
+       "osc_d4",
+       "osc_d8"
+};
+
+static const char * const atb_parents[] = {
+       "clk26m",
+       "syspll_d2_d2",
+       "syspll_d5"
+};
+
+static const char * const sspm_parents[] = {
+       "clk26m",
+       "univpll_d2_d4",
+       "syspll_d2_d2",
+       "univpll_d2_d2",
+       "syspll_d3"
+};
+
+static const char * const dpi0_parents[] = {
+       "clk26m",
+       "tvdpll_d2",
+       "tvdpll_d4",
+       "tvdpll_d8",
+       "tvdpll_d16",
+       "univpll_d5_d2",
+       "univpll_d3_d4",
+       "syspll_d3_d4",
+       "univpll_d3_d8"
+};
+
+static const char * const scam_parents[] = {
+       "clk26m",
+       "syspll_d5_d2"
+};
+
+static const char * const disppwm_parents[] = {
+       "clk26m",
+       "univpll_d3_d4",
+       "osc_d2",
+       "osc_d4",
+       "osc_d16"
+};
+
+static const char * const usb_top_parents[] = {
+       "clk26m",
+       "univpll_d5_d4",
+       "univpll_d3_d4",
+       "univpll_d5_d2"
+};
+
+
+static const char * const ssusb_top_xhci_parents[] = {
+       "clk26m",
+       "univpll_d5_d4",
+       "univpll_d3_d4",
+       "univpll_d5_d2"
+};
+
+static const char * const spm_parents[] = {
+       "clk26m",
+       "syspll_d2_d8"
+};
+
+static const char * const i2c_parents[] = {
+       "clk26m",
+       "syspll_d2_d8",
+       "univpll_d5_d2"
+};
+
+static const char * const scp_parents[] = {
+       "clk26m",
+       "univpll_d2_d8",
+       "syspll_d5",
+       "syspll_d2_d2",
+       "univpll_d2_d2",
+       "syspll_d3",
+       "univpll_d3"
+};
+
+static const char * const seninf_parents[] = {
+       "clk26m",
+       "univpll_d2_d2",
+       "univpll_d3_d2",
+       "univpll_d2_d4"
+};
+
+static const char * const dxcc_parents[] = {
+       "clk26m",
+       "syspll_d2_d2",
+       "syspll_d2_d4",
+       "syspll_d2_d8"
+};
+
+static const char * const aud_engen1_parents[] = {
+       "clk26m",
+       "apll1_d2",
+       "apll1_d4",
+       "apll1_d8"
+};
+
+static const char * const aud_engen2_parents[] = {
+       "clk26m",
+       "apll2_d2",
+       "apll2_d4",
+       "apll2_d8"
+};
+
+static const char * const faes_ufsfde_parents[] = {
+       "clk26m",
+       "syspll_d2",
+       "syspll_d2_d2",
+       "syspll_d3",
+       "syspll_d2_d4",
+       "univpll_d3"
+};
+
+static const char * const fufs_parents[] = {
+       "clk26m",
+       "syspll_d2_d4",
+       "syspll_d2_d8",
+       "syspll_d2_d16"
+};
+
+static const char * const aud_1_parents[] = {
+       "clk26m",
+       "apll1_ck"
+};
+
+static const char * const aud_2_parents[] = {
+       "clk26m",
+       "apll2_ck"
+};
+
+/*
+ * CRITICAL CLOCK:
+ * axi_sel is the main bus clock of whole SOC.
+ * spm_sel is the clock of the always-on co-processor.
+ */
+static const struct mtk_mux top_muxes[] = {
+       /* CLK_CFG_0 */
+       MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_AXI, "axi_sel",
+               axi_parents, 0x40,
+               0x44, 0x48, 0, 2, 7, 0x004, 0, CLK_IS_CRITICAL),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MM, "mm_sel",
+               mm_parents, 0x40,
+               0x44, 0x48, 8, 3, 15, 0x004, 1),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_IMG, "img_sel",
+               img_parents, 0x40,
+               0x44, 0x48, 16, 3, 23, 0x004, 2),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_CAM, "cam_sel",
+               cam_parents, 0x40,
+               0x44, 0x48, 24, 4, 31, 0x004, 3),
+       /* CLK_CFG_1 */
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DSP, "dsp_sel",
+               dsp_parents, 0x50,
+               0x54, 0x58, 0, 4, 7, 0x004, 4),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DSP1, "dsp1_sel",
+               dsp1_parents, 0x50,
+               0x54, 0x58, 8, 4, 15, 0x004, 5),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DSP2, "dsp2_sel",
+               dsp2_parents, 0x50,
+               0x54, 0x58, 16, 4, 23, 0x004, 6),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_IPU_IF, "ipu_if_sel",
+               ipu_if_parents, 0x50,
+               0x54, 0x58, 24, 4, 31, 0x004, 7),
+       /* CLK_CFG_2 */
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MFG, "mfg_sel",
+               mfg_parents, 0x60,
+               0x64, 0x68, 0, 2, 7, 0x004, 8),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_F52M_MFG, "f52m_mfg_sel",
+               f52m_mfg_parents, 0x60,
+               0x64, 0x68, 8, 2, 15, 0x004, 9),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_CAMTG, "camtg_sel",
+               camtg_parents, 0x60,
+               0x64, 0x68, 16, 3, 23, 0x004, 10),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_CAMTG2, "camtg2_sel",
+               camtg2_parents, 0x60,
+               0x64, 0x68, 24, 3, 31, 0x004, 11),
+       /* CLK_CFG_3 */
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_CAMTG3, "camtg3_sel",
+               camtg3_parents, 0x70,
+               0x74, 0x78, 0, 3, 7, 0x004, 12),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_CAMTG4, "camtg4_sel",
+               camtg4_parents, 0x70,
+               0x74, 0x78, 8, 3, 15, 0x004, 13),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_UART, "uart_sel",
+               uart_parents, 0x70,
+               0x74, 0x78, 16, 1, 23, 0x004, 14),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SPI, "spi_sel",
+               spi_parents, 0x70,
+               0x74, 0x78, 24, 2, 31, 0x004, 15),
+       /* CLK_CFG_4 */
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC50_0_HCLK, "msdc50_hclk_sel",
+               msdc50_hclk_parents, 0x80,
+               0x84, 0x88, 0, 2, 7, 0x004, 16),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC50_0, "msdc50_0_sel",
+               msdc50_0_parents, 0x80,
+               0x84, 0x88, 8, 3, 15, 0x004, 17),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC30_1, "msdc30_1_sel",
+               msdc30_1_parents, 0x80,
+               0x84, 0x88, 16, 3, 23, 0x004, 18),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC30_2, "msdc30_2_sel",
+               msdc30_2_parents, 0x80,
+               0x84, 0x88, 24, 3, 31, 0x004, 19),
+       /* CLK_CFG_5 */
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_AUDIO, "audio_sel",
+               audio_parents, 0x90,
+               0x94, 0x98, 0, 2, 7, 0x004, 20),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_AUD_INTBUS, "aud_intbus_sel",
+               aud_intbus_parents, 0x90,
+               0x94, 0x98, 8, 2, 15, 0x004, 21),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_PMICSPI, "pmicspi_sel",
+               pmicspi_parents, 0x90,
+               0x94, 0x98, 16, 2, 23, 0x004, 22),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_FPWRAP_ULPOSC, "fpwrap_ulposc_sel",
+               fpwrap_ulposc_parents, 0x90,
+               0x94, 0x98, 24, 2, 31, 0x004, 23),
+       /* CLK_CFG_6 */
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_ATB, "atb_sel",
+               atb_parents, 0xa0,
+               0xa4, 0xa8, 0, 2, 7, 0x004, 24),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SSPM, "sspm_sel",
+               sspm_parents, 0xa0,
+               0xa4, 0xa8, 8, 3, 15, 0x004, 25),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DPI0, "dpi0_sel",
+               dpi0_parents, 0xa0,
+               0xa4, 0xa8, 16, 4, 23, 0x004, 26),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SCAM, "scam_sel",
+               scam_parents, 0xa0,
+               0xa4, 0xa8, 24, 1, 31, 0x004, 27),
+       /* CLK_CFG_7 */
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DISP_PWM, "disppwm_sel",
+               disppwm_parents, 0xb0,
+               0xb4, 0xb8, 0, 3, 7, 0x004, 28),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_USB_TOP, "usb_top_sel",
+               usb_top_parents, 0xb0,
+               0xb4, 0xb8, 8, 2, 15, 0x004, 29),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SSUSB_TOP_XHCI, "ssusb_top_xhci_sel",
+               ssusb_top_xhci_parents, 0xb0,
+               0xb4, 0xb8, 16, 2, 23, 0x004, 30),
+       MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_SPM, "spm_sel",
+               spm_parents, 0xb0,
+               0xb4, 0xb8, 24, 1, 31, 0x008, 0, CLK_IS_CRITICAL),
+       /* CLK_CFG_8 */
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_I2C, "i2c_sel",
+               i2c_parents, 0xc0,
+               0xc4, 0xc8, 0, 2, 7, 0x008, 1),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SCP, "scp_sel",
+               scp_parents, 0xc0,
+               0xc4, 0xc8, 8, 3, 15, 0x008, 2),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SENINF, "seninf_sel",
+               seninf_parents, 0xc0,
+               0xc4, 0xc8, 16, 2, 23, 0x008, 3),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DXCC, "dxcc_sel",
+               dxcc_parents, 0xc0,
+               0xc4, 0xc8, 24, 2, 31, 0x008, 4),
+       /* CLK_CFG_9 */
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_AUD_ENG1, "aud_eng1_sel",
+               aud_engen1_parents, 0xd0,
+               0xd4, 0xd8, 0, 2, 7, 0x008, 5),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_AUD_ENG2, "aud_eng2_sel",
+               aud_engen2_parents, 0xd0,
+               0xd4, 0xd8, 8, 2, 15, 0x008, 6),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_FAES_UFSFDE, "faes_ufsfde_sel",
+               faes_ufsfde_parents, 0xd0,
+               0xd4, 0xd8, 16, 3, 23, 0x008, 7),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_FUFS, "fufs_sel",
+               fufs_parents, 0xd0,
+               0xd4, 0xd8, 24, 2, 31, 0x008, 8),
+       /* CLK_CFG_10 */
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_AUD_1, "aud_1_sel",
+               aud_1_parents, 0xe0,
+               0xe4, 0xe8, 0, 1, 7, 0x008, 9),
+       MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_AUD_2, "aud_2_sel",
+               aud_2_parents, 0xe0,
+               0xe4, 0xe8, 8, 1, 15, 0x008, 10),
+};
+
+static const char * const apll_i2s0_parents[] = {
+       "aud_1_sel",
+       "aud_2_sel"
+};
+
+static const char * const apll_i2s1_parents[] = {
+       "aud_1_sel",
+       "aud_2_sel"
+};
+
+static const char * const apll_i2s2_parents[] = {
+       "aud_1_sel",
+       "aud_2_sel"
+};
+
+static const char * const apll_i2s3_parents[] = {
+       "aud_1_sel",
+       "aud_2_sel"
+};
+
+static const char * const apll_i2s4_parents[] = {
+       "aud_1_sel",
+       "aud_2_sel"
+};
+
+static const char * const apll_i2s5_parents[] = {
+       "aud_1_sel",
+       "aud_2_sel"
+};
+
+static struct mtk_composite top_aud_muxes[] = {
+       MUX(CLK_TOP_MUX_APLL_I2S0, "apll_i2s0_sel", apll_i2s0_parents,
+               0x320, 8, 1),
+       MUX(CLK_TOP_MUX_APLL_I2S1, "apll_i2s1_sel", apll_i2s1_parents,
+               0x320, 9, 1),
+       MUX(CLK_TOP_MUX_APLL_I2S2, "apll_i2s2_sel", apll_i2s2_parents,
+               0x320, 10, 1),
+       MUX(CLK_TOP_MUX_APLL_I2S3, "apll_i2s3_sel", apll_i2s3_parents,
+               0x320, 11, 1),
+       MUX(CLK_TOP_MUX_APLL_I2S4, "apll_i2s4_sel", apll_i2s4_parents,
+               0x320, 12, 1),
+       MUX(CLK_TOP_MUX_APLL_I2S5, "apll_i2s5_sel", apll_i2s5_parents,
+               0x328, 20, 1),
+};
+
+static const char * const mcu_mp0_parents[] = {
+       "clk26m",
+       "armpll_ll",
+       "armpll_div_pll1",
+       "armpll_div_pll2"
+};
+
+static const char * const mcu_mp2_parents[] = {
+       "clk26m",
+       "armpll_l",
+       "armpll_div_pll1",
+       "armpll_div_pll2"
+};
+
+static const char * const mcu_bus_parents[] = {
+       "clk26m",
+       "ccipll",
+       "armpll_div_pll1",
+       "armpll_div_pll2"
+};
+
+static struct mtk_composite mcu_muxes[] = {
+       /* mp0_pll_divider_cfg */
+       MUX(CLK_MCU_MP0_SEL, "mcu_mp0_sel", mcu_mp0_parents, 0x7A0, 9, 2),
+       /* mp2_pll_divider_cfg */
+       MUX(CLK_MCU_MP2_SEL, "mcu_mp2_sel", mcu_mp2_parents, 0x7A8, 9, 2),
+       /* bus_pll_divider_cfg */
+       MUX(CLK_MCU_BUS_SEL, "mcu_bus_sel", mcu_bus_parents, 0x7C0, 9, 2),
+};
+
+static struct mtk_composite top_aud_divs[] = {
+       DIV_GATE(CLK_TOP_APLL12_DIV0, "apll12_div0", "apll_i2s0_sel",
+               0x320, 2, 0x324, 8, 0),
+       DIV_GATE(CLK_TOP_APLL12_DIV1, "apll12_div1", "apll_i2s1_sel",
+               0x320, 3, 0x324, 8, 8),
+       DIV_GATE(CLK_TOP_APLL12_DIV2, "apll12_div2", "apll_i2s2_sel",
+               0x320, 4, 0x324, 8, 16),
+       DIV_GATE(CLK_TOP_APLL12_DIV3, "apll12_div3", "apll_i2s3_sel",
+               0x320, 5, 0x324, 8, 24),
+       DIV_GATE(CLK_TOP_APLL12_DIV4, "apll12_div4", "apll_i2s4_sel",
+               0x320, 6, 0x328, 8, 0),
+       DIV_GATE(CLK_TOP_APLL12_DIVB, "apll12_divb", "apll12_div4",
+               0x320, 7, 0x328, 8, 8),
+};
+
+static const struct mtk_gate_regs top_cg_regs = {
+       .set_ofs = 0x104,
+       .clr_ofs = 0x104,
+       .sta_ofs = 0x104,
+};
+
+#define GATE_TOP(_id, _name, _parent, _shift)                  \
+       GATE_MTK(_id, _name, _parent, &top_cg_regs, _shift,     \
+               &mtk_clk_gate_ops_no_setclr_inv)
+
+static const struct mtk_gate top_clks[] = {
+       /* TOP */
+       GATE_TOP(CLK_TOP_ARMPLL_DIV_PLL1, "armpll_div_pll1", "mainpll", 4),
+       GATE_TOP(CLK_TOP_ARMPLL_DIV_PLL2, "armpll_div_pll2", "univpll", 5),
+};
+
+static const struct mtk_gate_regs infra0_cg_regs = {
+       .set_ofs = 0x80,
+       .clr_ofs = 0x84,
+       .sta_ofs = 0x90,
+};
+
+static const struct mtk_gate_regs infra1_cg_regs = {
+       .set_ofs = 0x88,
+       .clr_ofs = 0x8c,
+       .sta_ofs = 0x94,
+};
+
+static const struct mtk_gate_regs infra2_cg_regs = {
+       .set_ofs = 0xa4,
+       .clr_ofs = 0xa8,
+       .sta_ofs = 0xac,
+};
+
+static const struct mtk_gate_regs infra3_cg_regs = {
+       .set_ofs = 0xc0,
+       .clr_ofs = 0xc4,
+       .sta_ofs = 0xc8,
+};
+
+#define GATE_INFRA0(_id, _name, _parent, _shift)               \
+       GATE_MTK(_id, _name, _parent, &infra0_cg_regs, _shift,  \
+               &mtk_clk_gate_ops_setclr)
+
+#define GATE_INFRA1(_id, _name, _parent, _shift)               \
+       GATE_MTK(_id, _name, _parent, &infra1_cg_regs, _shift,  \
+               &mtk_clk_gate_ops_setclr)
+
+#define GATE_INFRA2(_id, _name, _parent, _shift)               \
+       GATE_MTK(_id, _name, _parent, &infra2_cg_regs, _shift,  \
+               &mtk_clk_gate_ops_setclr)
+
+#define GATE_INFRA3(_id, _name, _parent, _shift)               \
+       GATE_MTK(_id, _name, _parent, &infra3_cg_regs, _shift,  \
+               &mtk_clk_gate_ops_setclr)
+
+static const struct mtk_gate infra_clks[] = {
+       /* INFRA0 */
+       GATE_INFRA0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr",
+               "axi_sel", 0),
+       GATE_INFRA0(CLK_INFRA_PMIC_AP, "infra_pmic_ap",
+               "axi_sel", 1),
+       GATE_INFRA0(CLK_INFRA_PMIC_MD, "infra_pmic_md",
+               "axi_sel", 2),
+       GATE_INFRA0(CLK_INFRA_PMIC_CONN, "infra_pmic_conn",
+               "axi_sel", 3),
+       GATE_INFRA0(CLK_INFRA_SCPSYS, "infra_scp",
+               "scp_sel", 4),
+       GATE_INFRA0(CLK_INFRA_SEJ, "infra_sej",
+               "f_f26m_ck", 5),
+       GATE_INFRA0(CLK_INFRA_APXGPT, "infra_apxgpt",
+               "axi_sel", 6),
+       GATE_INFRA0(CLK_INFRA_ICUSB, "infra_icusb",
+               "axi_sel", 8),
+       GATE_INFRA0(CLK_INFRA_GCE, "infra_gce",
+               "axi_sel", 9),
+       GATE_INFRA0(CLK_INFRA_THERM, "infra_therm",
+               "axi_sel", 10),
+       GATE_INFRA0(CLK_INFRA_I2C0, "infra_i2c0",
+               "i2c_sel", 11),
+       GATE_INFRA0(CLK_INFRA_I2C1, "infra_i2c1",
+               "i2c_sel", 12),
+       GATE_INFRA0(CLK_INFRA_I2C2, "infra_i2c2",
+               "i2c_sel", 13),
+       GATE_INFRA0(CLK_INFRA_I2C3, "infra_i2c3",
+               "i2c_sel", 14),
+       GATE_INFRA0(CLK_INFRA_PWM_HCLK, "infra_pwm_hclk",
+               "axi_sel", 15),
+       GATE_INFRA0(CLK_INFRA_PWM1, "infra_pwm1",
+               "i2c_sel", 16),
+       GATE_INFRA0(CLK_INFRA_PWM2, "infra_pwm2",
+               "i2c_sel", 17),
+       GATE_INFRA0(CLK_INFRA_PWM3, "infra_pwm3",
+               "i2c_sel", 18),
+       GATE_INFRA0(CLK_INFRA_PWM4, "infra_pwm4",
+               "i2c_sel", 19),
+       GATE_INFRA0(CLK_INFRA_PWM, "infra_pwm",
+               "i2c_sel", 21),
+       GATE_INFRA0(CLK_INFRA_UART0, "infra_uart0",
+               "uart_sel", 22),
+       GATE_INFRA0(CLK_INFRA_UART1, "infra_uart1",
+               "uart_sel", 23),
+       GATE_INFRA0(CLK_INFRA_UART2, "infra_uart2",
+               "uart_sel", 24),
+       GATE_INFRA0(CLK_INFRA_UART3, "infra_uart3",
+               "uart_sel", 25),
+       GATE_INFRA0(CLK_INFRA_GCE_26M, "infra_gce_26m",
+               "axi_sel", 27),
+       GATE_INFRA0(CLK_INFRA_CQ_DMA_FPC, "infra_cqdma_fpc",
+               "axi_sel", 28),
+       GATE_INFRA0(CLK_INFRA_BTIF, "infra_btif",
+               "axi_sel", 31),
+       /* INFRA1 */
+       GATE_INFRA1(CLK_INFRA_SPI0, "infra_spi0",
+               "spi_sel", 1),
+       GATE_INFRA1(CLK_INFRA_MSDC0, "infra_msdc0",
+               "msdc50_hclk_sel", 2),
+       GATE_INFRA1(CLK_INFRA_MSDC1, "infra_msdc1",
+               "axi_sel", 4),
+       GATE_INFRA1(CLK_INFRA_MSDC2, "infra_msdc2",
+               "axi_sel", 5),
+       GATE_INFRA1(CLK_INFRA_MSDC0_SCK, "infra_msdc0_sck",
+               "msdc50_0_sel", 6),
+       GATE_INFRA1(CLK_INFRA_DVFSRC, "infra_dvfsrc",
+               "f_f26m_ck", 7),
+       GATE_INFRA1(CLK_INFRA_GCPU, "infra_gcpu",
+               "axi_sel", 8),
+       GATE_INFRA1(CLK_INFRA_TRNG, "infra_trng",
+               "axi_sel", 9),
+       GATE_INFRA1(CLK_INFRA_AUXADC, "infra_auxadc",
+               "f_f26m_ck", 10),
+       GATE_INFRA1(CLK_INFRA_CPUM, "infra_cpum",
+               "axi_sel", 11),
+       GATE_INFRA1(CLK_INFRA_CCIF1_AP, "infra_ccif1_ap",
+               "axi_sel", 12),
+       GATE_INFRA1(CLK_INFRA_CCIF1_MD, "infra_ccif1_md",
+               "axi_sel", 13),
+       GATE_INFRA1(CLK_INFRA_AUXADC_MD, "infra_auxadc_md",
+               "f_f26m_ck", 14),
+       GATE_INFRA1(CLK_INFRA_MSDC1_SCK, "infra_msdc1_sck",
+               "msdc30_1_sel", 16),
+       GATE_INFRA1(CLK_INFRA_MSDC2_SCK, "infra_msdc2_sck",
+               "msdc30_2_sel", 17),
+       GATE_INFRA1(CLK_INFRA_AP_DMA, "infra_apdma",
+               "axi_sel", 18),
+       GATE_INFRA1(CLK_INFRA_XIU, "infra_xiu",
+               "axi_sel", 19),
+       GATE_INFRA1(CLK_INFRA_DEVICE_APC, "infra_device_apc",
+               "axi_sel", 20),
+       GATE_INFRA1(CLK_INFRA_CCIF_AP, "infra_ccif_ap",
+               "axi_sel", 23),
+       GATE_INFRA1(CLK_INFRA_DEBUGSYS, "infra_debugsys",
+               "axi_sel", 24),
+       GATE_INFRA1(CLK_INFRA_AUDIO, "infra_audio",
+               "axi_sel", 25),
+       GATE_INFRA1(CLK_INFRA_CCIF_MD, "infra_ccif_md",
+               "axi_sel", 26),
+       GATE_INFRA1(CLK_INFRA_DXCC_SEC_CORE, "infra_dxcc_sec_core",
+               "dxcc_sel", 27),
+       GATE_INFRA1(CLK_INFRA_DXCC_AO, "infra_dxcc_ao",
+               "dxcc_sel", 28),
+       GATE_INFRA1(CLK_INFRA_DEVMPU_BCLK, "infra_devmpu_bclk",
+               "axi_sel", 30),
+       GATE_INFRA1(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m",
+               "f_f26m_ck", 31),
+       /* INFRA2 */
+       GATE_INFRA2(CLK_INFRA_IRTX, "infra_irtx",
+               "f_f26m_ck", 0),
+       GATE_INFRA2(CLK_INFRA_USB, "infra_usb",
+               "usb_top_sel", 1),
+       GATE_INFRA2(CLK_INFRA_DISP_PWM, "infra_disppwm",
+               "axi_sel", 2),
+       GATE_INFRA2(CLK_INFRA_CLDMA_BCLK, "infra_cldma_bclk",
+               "axi_sel", 3),
+       GATE_INFRA2(CLK_INFRA_AUDIO_26M_BCLK, "infra_audio_26m_bclk",
+               "f_f26m_ck", 4),
+       GATE_INFRA2(CLK_INFRA_SPI1, "infra_spi1",
+               "spi_sel", 6),
+       GATE_INFRA2(CLK_INFRA_I2C4, "infra_i2c4",
+               "i2c_sel", 7),
+       GATE_INFRA2(CLK_INFRA_MODEM_TEMP_SHARE, "infra_md_tmp_share",
+               "f_f26m_ck", 8),
+       GATE_INFRA2(CLK_INFRA_SPI2, "infra_spi2",
+               "spi_sel", 9),
+       GATE_INFRA2(CLK_INFRA_SPI3, "infra_spi3",
+               "spi_sel", 10),
+       GATE_INFRA2(CLK_INFRA_UNIPRO_SCK, "infra_unipro_sck",
+               "ssusb_top_xhci_sel", 11),
+       GATE_INFRA2(CLK_INFRA_UNIPRO_TICK, "infra_unipro_tick",
+               "fufs_sel", 12),
+       GATE_INFRA2(CLK_INFRA_UFS_MP_SAP_BCLK, "infra_ufs_mp_sap_bck",
+               "fufs_sel", 13),
+       GATE_INFRA2(CLK_INFRA_MD32_BCLK, "infra_md32_bclk",
+               "axi_sel", 14),
+       GATE_INFRA2(CLK_INFRA_SSPM, "infra_sspm",
+               "sspm_sel", 15),
+       GATE_INFRA2(CLK_INFRA_UNIPRO_MBIST, "infra_unipro_mbist",
+               "axi_sel", 16),
+       GATE_INFRA2(CLK_INFRA_SSPM_BUS_HCLK, "infra_sspm_bus_hclk",
+               "axi_sel", 17),
+       GATE_INFRA2(CLK_INFRA_I2C5, "infra_i2c5",
+               "i2c_sel", 18),
+       GATE_INFRA2(CLK_INFRA_I2C5_ARBITER, "infra_i2c5_arbiter",
+               "i2c_sel", 19),
+       GATE_INFRA2(CLK_INFRA_I2C5_IMM, "infra_i2c5_imm",
+               "i2c_sel", 20),
+       GATE_INFRA2(CLK_INFRA_I2C1_ARBITER, "infra_i2c1_arbiter",
+               "i2c_sel", 21),
+       GATE_INFRA2(CLK_INFRA_I2C1_IMM, "infra_i2c1_imm",
+               "i2c_sel", 22),
+       GATE_INFRA2(CLK_INFRA_I2C2_ARBITER, "infra_i2c2_arbiter",
+               "i2c_sel", 23),
+       GATE_INFRA2(CLK_INFRA_I2C2_IMM, "infra_i2c2_imm",
+               "i2c_sel", 24),
+       GATE_INFRA2(CLK_INFRA_SPI4, "infra_spi4",
+               "spi_sel", 25),
+       GATE_INFRA2(CLK_INFRA_SPI5, "infra_spi5",
+               "spi_sel", 26),
+       GATE_INFRA2(CLK_INFRA_CQ_DMA, "infra_cqdma",
+               "axi_sel", 27),
+       GATE_INFRA2(CLK_INFRA_UFS, "infra_ufs",
+               "fufs_sel", 28),
+       GATE_INFRA2(CLK_INFRA_AES_UFSFDE, "infra_aes_ufsfde",
+               "faes_ufsfde_sel", 29),
+       GATE_INFRA2(CLK_INFRA_UFS_TICK, "infra_ufs_tick",
+               "fufs_sel", 30),
+       /* INFRA3 */
+       GATE_INFRA3(CLK_INFRA_MSDC0_SELF, "infra_msdc0_self",
+               "msdc50_0_sel", 0),
+       GATE_INFRA3(CLK_INFRA_MSDC1_SELF, "infra_msdc1_self",
+               "msdc50_0_sel", 1),
+       GATE_INFRA3(CLK_INFRA_MSDC2_SELF, "infra_msdc2_self",
+               "msdc50_0_sel", 2),
+       GATE_INFRA3(CLK_INFRA_SSPM_26M_SELF, "infra_sspm_26m_self",
+               "f_f26m_ck", 3),
+       GATE_INFRA3(CLK_INFRA_SSPM_32K_SELF, "infra_sspm_32k_self",
+               "f_f26m_ck", 4),
+       GATE_INFRA3(CLK_INFRA_UFS_AXI, "infra_ufs_axi",
+               "axi_sel", 5),
+       GATE_INFRA3(CLK_INFRA_I2C6, "infra_i2c6",
+               "i2c_sel", 6),
+       GATE_INFRA3(CLK_INFRA_AP_MSDC0, "infra_ap_msdc0",
+               "msdc50_hclk_sel", 7),
+       GATE_INFRA3(CLK_INFRA_MD_MSDC0, "infra_md_msdc0",
+               "msdc50_hclk_sel", 8),
+       GATE_INFRA3(CLK_INFRA_CCIF2_AP, "infra_ccif2_ap",
+               "axi_sel", 16),
+       GATE_INFRA3(CLK_INFRA_CCIF2_MD, "infra_ccif2_md",
+               "axi_sel", 17),
+       GATE_INFRA3(CLK_INFRA_CCIF3_AP, "infra_ccif3_ap",
+               "axi_sel", 18),
+       GATE_INFRA3(CLK_INFRA_CCIF3_MD, "infra_ccif3_md",
+               "axi_sel", 19),
+       GATE_INFRA3(CLK_INFRA_SEJ_F13M, "infra_sej_f13m",
+               "f_f26m_ck", 20),
+       GATE_INFRA3(CLK_INFRA_AES_BCLK, "infra_aes_bclk",
+               "axi_sel", 21),
+       GATE_INFRA3(CLK_INFRA_I2C7, "infra_i2c7",
+               "i2c_sel", 22),
+       GATE_INFRA3(CLK_INFRA_I2C8, "infra_i2c8",
+               "i2c_sel", 23),
+       GATE_INFRA3(CLK_INFRA_FBIST2FPC, "infra_fbist2fpc",
+               "msdc50_0_sel", 24),
+};
+
+static const struct mtk_gate_regs apmixed_cg_regs = {
+       .set_ofs = 0x20,
+       .clr_ofs = 0x20,
+       .sta_ofs = 0x20,
+};
+
+#define GATE_APMIXED_FLAGS(_id, _name, _parent, _shift, _flags)        \
+       GATE_MTK_FLAGS(_id, _name, _parent, &apmixed_cg_regs,           \
+               _shift, &mtk_clk_gate_ops_no_setclr_inv, _flags)
+
+#define GATE_APMIXED(_id, _name, _parent, _shift)      \
+       GATE_APMIXED_FLAGS(_id, _name, _parent, _shift, 0)
+
+/*
+ * CRITICAL CLOCK:
+ * apmixed_appll26m is the toppest clock gate of all PLLs.
+ */
+static const struct mtk_gate apmixed_clks[] = {
+       /* AUDIO0 */
+       GATE_APMIXED(CLK_APMIXED_SSUSB_26M, "apmixed_ssusb26m",
+               "f_f26m_ck", 4),
+       GATE_APMIXED_FLAGS(CLK_APMIXED_APPLL_26M, "apmixed_appll26m",
+               "f_f26m_ck", 5, CLK_IS_CRITICAL),
+       GATE_APMIXED(CLK_APMIXED_MIPIC0_26M, "apmixed_mipic026m",
+               "f_f26m_ck", 6),
+       GATE_APMIXED(CLK_APMIXED_MDPLLGP_26M, "apmixed_mdpll26m",
+               "f_f26m_ck", 7),
+       GATE_APMIXED(CLK_APMIXED_MMSYS_26M, "apmixed_mmsys26m",
+               "f_f26m_ck", 8),
+       GATE_APMIXED(CLK_APMIXED_UFS_26M, "apmixed_ufs26m",
+               "f_f26m_ck", 9),
+       GATE_APMIXED(CLK_APMIXED_MIPIC1_26M, "apmixed_mipic126m",
+               "f_f26m_ck", 11),
+       GATE_APMIXED(CLK_APMIXED_MEMPLL_26M, "apmixed_mempll26m",
+               "f_f26m_ck", 13),
+       GATE_APMIXED(CLK_APMIXED_CLKSQ_LVPLL_26M, "apmixed_lvpll26m",
+               "f_f26m_ck", 14),
+       GATE_APMIXED(CLK_APMIXED_MIPID0_26M, "apmixed_mipid026m",
+               "f_f26m_ck", 16),
+       GATE_APMIXED(CLK_APMIXED_MIPID1_26M, "apmixed_mipid126m",
+               "f_f26m_ck", 17),
+};
+
+#define MT8183_PLL_FMAX                (3800UL * MHZ)
+#define MT8183_PLL_FMIN                (1500UL * MHZ)
+
+#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags,            \
+                       _rst_bar_mask, _pcwbits, _pcwibits, _pd_reg,    \
+                       _pd_shift, _tuner_reg,  _tuner_en_reg,          \
+                       _tuner_en_bit, _pcw_reg, _pcw_shift,            \
+                       _pcw_chg_reg, _div_table) {                     \
+               .id = _id,                                              \
+               .name = _name,                                          \
+               .reg = _reg,                                            \
+               .pwr_reg = _pwr_reg,                                    \
+               .en_mask = _en_mask,                                    \
+               .flags = _flags,                                        \
+               .rst_bar_mask = _rst_bar_mask,                          \
+               .fmax = MT8183_PLL_FMAX,                                \
+               .fmin = MT8183_PLL_FMIN,                                \
+               .pcwbits = _pcwbits,                                    \
+               .pcwibits = _pcwibits,                                  \
+               .pd_reg = _pd_reg,                                      \
+               .pd_shift = _pd_shift,                                  \
+               .tuner_reg = _tuner_reg,                                \
+               .tuner_en_reg = _tuner_en_reg,                          \
+               .tuner_en_bit = _tuner_en_bit,                          \
+               .pcw_reg = _pcw_reg,                                    \
+               .pcw_shift = _pcw_shift,                                \
+               .pcw_chg_reg = _pcw_chg_reg,                            \
+               .div_table = _div_table,                                \
+       }
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags,              \
+                       _rst_bar_mask, _pcwbits, _pcwibits, _pd_reg,    \
+                       _pd_shift, _tuner_reg, _tuner_en_reg,           \
+                       _tuner_en_bit, _pcw_reg, _pcw_shift,            \
+                       _pcw_chg_reg)                                   \
+               PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags,     \
+                       _rst_bar_mask, _pcwbits, _pcwibits, _pd_reg,    \
+                       _pd_shift, _tuner_reg, _tuner_en_reg,           \
+                       _tuner_en_bit, _pcw_reg, _pcw_shift,            \
+                       _pcw_chg_reg, NULL)
+
+static const struct mtk_pll_div_table armpll_div_table[] = {
+       { .div = 0, .freq = MT8183_PLL_FMAX },
+       { .div = 1, .freq = 1500 * MHZ },
+       { .div = 2, .freq = 750 * MHZ },
+       { .div = 3, .freq = 375 * MHZ },
+       { .div = 4, .freq = 187500000 },
+       { } /* sentinel */
+};
+
+static const struct mtk_pll_div_table mfgpll_div_table[] = {
+       { .div = 0, .freq = MT8183_PLL_FMAX },
+       { .div = 1, .freq = 1600 * MHZ },
+       { .div = 2, .freq = 800 * MHZ },
+       { .div = 3, .freq = 400 * MHZ },
+       { .div = 4, .freq = 200 * MHZ },
+       { } /* sentinel */
+};
+
+static const struct mtk_pll_data plls[] = {
+       PLL_B(CLK_APMIXED_ARMPLL_LL, "armpll_ll", 0x0200, 0x020C, 0x00000001,
+               HAVE_RST_BAR | PLL_AO, BIT(24), 22, 8, 0x0204, 24, 0x0, 0x0, 0,
+               0x0204, 0, 0, armpll_div_table),
+       PLL_B(CLK_APMIXED_ARMPLL_L, "armpll_l", 0x0210, 0x021C, 0x00000001,
+               HAVE_RST_BAR | PLL_AO, BIT(24), 22, 8, 0x0214, 24, 0x0, 0x0, 0,
+               0x0214, 0, 0, armpll_div_table),
+       PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x0290, 0x029C, 0x00000001,
+               HAVE_RST_BAR | PLL_AO, BIT(24), 22, 8, 0x0294, 24, 0x0, 0x0, 0,
+               0x0294, 0, 0),
+       PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0220, 0x022C, 0x00000001,
+               HAVE_RST_BAR, BIT(24), 22, 8, 0x0224, 24, 0x0, 0x0, 0,
+               0x0224, 0, 0),
+       PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0230, 0x023C, 0x00000001,
+               HAVE_RST_BAR, BIT(24), 22, 8, 0x0234, 24, 0x0, 0x0, 0,
+               0x0234, 0, 0),
+       PLL_B(CLK_APMIXED_MFGPLL, "mfgpll", 0x0240, 0x024C, 0x00000001,
+               0, 0, 22, 8, 0x0244, 24, 0x0, 0x0, 0, 0x0244, 0, 0,
+               mfgpll_div_table),
+       PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0250, 0x025C, 0x00000001,
+               0, 0, 22, 8, 0x0254, 24, 0x0, 0x0, 0, 0x0254, 0, 0),
+       PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0260, 0x026C, 0x00000001,
+               0, 0, 22, 8, 0x0264, 24, 0x0, 0x0, 0, 0x0264, 0, 0),
+       PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0270, 0x027C, 0x00000001,
+               HAVE_RST_BAR, BIT(23), 22, 8, 0x0274, 24, 0x0, 0x0, 0,
+               0x0274, 0, 0),
+       PLL(CLK_APMIXED_APLL1, "apll1", 0x02A0, 0x02B0, 0x00000001,
+               0, 0, 32, 8, 0x02A0, 1, 0x02A8, 0x0014, 0, 0x02A4, 0, 0x02A0),
+       PLL(CLK_APMIXED_APLL2, "apll2", 0x02b4, 0x02c4, 0x00000001,
+               0, 0, 32, 8, 0x02B4, 1, 0x02BC, 0x0014, 1, 0x02B8, 0, 0x02B4),
+};
+
+static int clk_mt8183_apmixed_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+
+       mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+
+       mtk_clk_register_gates(node, apmixed_clks, ARRAY_SIZE(apmixed_clks),
+               clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static int clk_mt8183_top_probe(struct platform_device *pdev)
+{
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       void __iomem *base;
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+       mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
+               clk_data);
+
+       mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+
+       mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes),
+               node, &mt8183_clk_lock, clk_data);
+
+       mtk_clk_register_composites(top_aud_muxes, ARRAY_SIZE(top_aud_muxes),
+               base, &mt8183_clk_lock, clk_data);
+
+       mtk_clk_register_composites(top_aud_divs, ARRAY_SIZE(top_aud_divs),
+               base, &mt8183_clk_lock, clk_data);
+
+       mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks),
+               clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static int clk_mt8183_infra_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+
+       mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+               clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static int clk_mt8183_mcu_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+       void __iomem *base;
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK);
+
+       mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base,
+                       &mt8183_clk_lock, clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt8183[] = {
+       {
+               .compatible = "mediatek,mt8183-apmixedsys",
+               .data = clk_mt8183_apmixed_probe,
+       }, {
+               .compatible = "mediatek,mt8183-topckgen",
+               .data = clk_mt8183_top_probe,
+       }, {
+               .compatible = "mediatek,mt8183-infracfg",
+               .data = clk_mt8183_infra_probe,
+       }, {
+               .compatible = "mediatek,mt8183-mcucfg",
+               .data = clk_mt8183_mcu_probe,
+       }, {
+               /* sentinel */
+       }
+};
+
+static int clk_mt8183_probe(struct platform_device *pdev)
+{
+       int (*clk_probe)(struct platform_device *pdev);
+       int r;
+
+       clk_probe = of_device_get_match_data(&pdev->dev);
+       if (!clk_probe)
+               return -EINVAL;
+
+       r = clk_probe(pdev);
+       if (r)
+               dev_err(&pdev->dev,
+                       "could not register clock provider: %s: %d\n",
+                       pdev->name, r);
+
+       return r;
+}
+
+static struct platform_driver clk_mt8183_drv = {
+       .probe = clk_mt8183_probe,
+       .driver = {
+               .name = "clk-mt8183",
+               .of_match_table = of_match_clk_mt8183,
+       },
+};
+
+static int __init clk_mt8183_init(void)
+{
+       return platform_driver_register(&clk_mt8183_drv);
+}
+
+arch_initcall(clk_mt8183_init);
diff --git a/drivers/clk/mediatek/clk-mt8516.c b/drivers/clk/mediatek/clk-mt8516.c
new file mode 100644 (file)
index 0000000..26fe43c
--- /dev/null
@@ -0,0 +1,815 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *         Fabien Parent <fparent@baylibre.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8516-clk.h>
+
+static DEFINE_SPINLOCK(mt8516_clk_lock);
+
+static const struct mtk_fixed_clk fixed_clks[] __initconst = {
+       FIXED_CLK(CLK_TOP_CLK_NULL, "clk_null", NULL, 0),
+       FIXED_CLK(CLK_TOP_I2S_INFRA_BCK, "i2s_infra_bck", "clk_null", 26000000),
+       FIXED_CLK(CLK_TOP_MEMPLL, "mempll", "clk26m", 800000000),
+};
+
+static const struct mtk_fixed_factor top_divs[] __initconst = {
+       FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "mempll", 1, 1),
+       FACTOR(CLK_TOP_MAINPLL_D2, "mainpll_d2", "mainpll", 1, 2),
+       FACTOR(CLK_TOP_MAINPLL_D4, "mainpll_d4", "mainpll", 1, 4),
+       FACTOR(CLK_TOP_MAINPLL_D8, "mainpll_d8", "mainpll", 1, 8),
+       FACTOR(CLK_TOP_MAINPLL_D16, "mainpll_d16", "mainpll", 1, 16),
+       FACTOR(CLK_TOP_MAINPLL_D11, "mainpll_d11", "mainpll", 1, 11),
+       FACTOR(CLK_TOP_MAINPLL_D22, "mainpll_d22", "mainpll", 1, 22),
+       FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3),
+       FACTOR(CLK_TOP_MAINPLL_D6, "mainpll_d6", "mainpll", 1, 6),
+       FACTOR(CLK_TOP_MAINPLL_D12, "mainpll_d12", "mainpll", 1, 12),
+       FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5),
+       FACTOR(CLK_TOP_MAINPLL_D10, "mainpll_d10", "mainpll", 1, 10),
+       FACTOR(CLK_TOP_MAINPLL_D20, "mainpll_d20", "mainpll", 1, 20),
+       FACTOR(CLK_TOP_MAINPLL_D40, "mainpll_d40", "mainpll", 1, 40),
+       FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7),
+       FACTOR(CLK_TOP_MAINPLL_D14, "mainpll_d14", "mainpll", 1, 14),
+       FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
+       FACTOR(CLK_TOP_UNIVPLL_D4, "univpll_d4", "univpll", 1, 4),
+       FACTOR(CLK_TOP_UNIVPLL_D8, "univpll_d8", "univpll", 1, 8),
+       FACTOR(CLK_TOP_UNIVPLL_D16, "univpll_d16", "univpll", 1, 16),
+       FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
+       FACTOR(CLK_TOP_UNIVPLL_D6, "univpll_d6", "univpll", 1, 6),
+       FACTOR(CLK_TOP_UNIVPLL_D12, "univpll_d12", "univpll", 1, 12),
+       FACTOR(CLK_TOP_UNIVPLL_D24, "univpll_d24", "univpll", 1, 24),
+       FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+       FACTOR(CLK_TOP_UNIVPLL_D20, "univpll_d20", "univpll", 1, 20),
+       FACTOR(CLK_TOP_MMPLL380M, "mmpll380m", "mmpll", 1, 1),
+       FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+       FACTOR(CLK_TOP_MMPLL_200M, "mmpll_200m", "mmpll", 1, 3),
+       FACTOR(CLK_TOP_USB_PHY48M, "usb_phy48m_ck", "univpll", 1, 26),
+       FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1),
+       FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1_ck", 1, 2),
+       FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "rg_apll1_d2_en", 1, 2),
+       FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "rg_apll1_d4_en", 1, 2),
+       FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1),
+       FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2_ck", 1, 2),
+       FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "rg_apll2_d2_en", 1, 2),
+       FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "rg_apll2_d4_en", 1, 2),
+       FACTOR(CLK_TOP_CLK26M, "clk26m_ck", "clk26m", 1, 1),
+       FACTOR(CLK_TOP_CLK26M_D2, "clk26m_d2", "clk26m", 1, 2),
+       FACTOR(CLK_TOP_AHB_INFRA_D2, "ahb_infra_d2", "ahb_infra_sel", 1, 2),
+       FACTOR(CLK_TOP_NFI1X, "nfi1x_ck", "nfi2x_pad_sel", 1, 2),
+       FACTOR(CLK_TOP_ETH_D2, "eth_d2_ck", "eth_sel", 1, 2),
+};
+
+static const char * const uart0_parents[] __initconst = {
+       "clk26m_ck",
+       "univpll_d24"
+};
+
+static const char * const ahb_infra_parents[] __initconst = {
+       "clk_null",
+       "clk26m_ck",
+       "mainpll_d11",
+       "clk_null",
+       "mainpll_d12",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "mainpll_d10"
+};
+
+static const char * const msdc0_parents[] __initconst = {
+       "clk26m_ck",
+       "univpll_d6",
+       "mainpll_d8",
+       "univpll_d8",
+       "mainpll_d16",
+       "mmpll_200m",
+       "mainpll_d12",
+       "mmpll_d2"
+};
+
+static const char * const uart1_parents[] __initconst = {
+       "clk26m_ck",
+       "univpll_d24"
+};
+
+static const char * const msdc1_parents[] __initconst = {
+       "clk26m_ck",
+       "univpll_d6",
+       "mainpll_d8",
+       "univpll_d8",
+       "mainpll_d16",
+       "mmpll_200m",
+       "mainpll_d12",
+       "mmpll_d2"
+};
+
+static const char * const pmicspi_parents[] __initconst = {
+       "univpll_d20",
+       "usb_phy48m_ck",
+       "univpll_d16",
+       "clk26m_ck"
+};
+
+static const char * const qaxi_aud26m_parents[] __initconst = {
+       "clk26m_ck",
+       "ahb_infra_sel"
+};
+
+static const char * const aud_intbus_parents[] __initconst = {
+       "clk_null",
+       "clk26m_ck",
+       "mainpll_d22",
+       "clk_null",
+       "mainpll_d11"
+};
+
+static const char * const nfi2x_pad_parents[] __initconst = {
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk26m_ck",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "mainpll_d12",
+       "mainpll_d8",
+       "clk_null",
+       "mainpll_d6",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "mainpll_d4",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "clk_null",
+       "mainpll_d10",
+       "mainpll_d7",
+       "clk_null",
+       "mainpll_d5"
+};
+
+static const char * const nfi1x_pad_parents[] __initconst = {
+       "ahb_infra_sel",
+       "nfi1x_ck"
+};
+
+static const char * const ddrphycfg_parents[] __initconst = {
+       "clk26m_ck",
+       "mainpll_d16"
+};
+
+static const char * const usb_78m_parents[] __initconst = {
+       "clk_null",
+       "clk26m_ck",
+       "univpll_d16",
+       "clk_null",
+       "mainpll_d20"
+};
+
+static const char * const spinor_parents[] __initconst = {
+       "clk26m_d2",
+       "clk26m_ck",
+       "mainpll_d40",
+       "univpll_d24",
+       "univpll_d20",
+       "mainpll_d20",
+       "mainpll_d16",
+       "univpll_d12"
+};
+
+static const char * const msdc2_parents[] __initconst = {
+       "clk26m_ck",
+       "univpll_d6",
+       "mainpll_d8",
+       "univpll_d8",
+       "mainpll_d16",
+       "mmpll_200m",
+       "mainpll_d12",
+       "mmpll_d2"
+};
+
+static const char * const eth_parents[] __initconst = {
+       "clk26m_ck",
+       "mainpll_d40",
+       "univpll_d24",
+       "univpll_d20",
+       "mainpll_d20"
+};
+
+static const char * const aud1_parents[] __initconst = {
+       "clk26m_ck",
+       "apll1_ck"
+};
+
+static const char * const aud2_parents[] __initconst = {
+       "clk26m_ck",
+       "apll2_ck"
+};
+
+static const char * const aud_engen1_parents[] __initconst = {
+       "clk26m_ck",
+       "rg_apll1_d2_en",
+       "rg_apll1_d4_en",
+       "rg_apll1_d8_en"
+};
+
+static const char * const aud_engen2_parents[] __initconst = {
+       "clk26m_ck",
+       "rg_apll2_d2_en",
+       "rg_apll2_d4_en",
+       "rg_apll2_d8_en"
+};
+
+static const char * const i2c_parents[] __initconst = {
+       "clk26m_ck",
+       "univpll_d20",
+       "univpll_d16",
+       "univpll_d12"
+};
+
+static const char * const aud_i2s0_m_parents[] __initconst = {
+       "rg_aud1",
+       "rg_aud2"
+};
+
+static const char * const pwm_parents[] __initconst = {
+       "clk26m_ck",
+       "univpll_d12"
+};
+
+static const char * const spi_parents[] __initconst = {
+       "clk26m_ck",
+       "univpll_d12",
+       "univpll_d8",
+       "univpll_d6"
+};
+
+static const char * const aud_spdifin_parents[] __initconst = {
+       "clk26m_ck",
+       "univpll_d2"
+};
+
+static const char * const uart2_parents[] __initconst = {
+       "clk26m_ck",
+       "univpll_d24"
+};
+
+static const char * const bsi_parents[] __initconst = {
+       "clk26m_ck",
+       "mainpll_d10",
+       "mainpll_d12",
+       "mainpll_d20"
+};
+
+static const char * const dbg_atclk_parents[] __initconst = {
+       "clk_null",
+       "clk26m_ck",
+       "mainpll_d5",
+       "clk_null",
+       "univpll_d5"
+};
+
+static const char * const csw_nfiecc_parents[] __initconst = {
+       "clk_null",
+       "mainpll_d7",
+       "mainpll_d6",
+       "clk_null",
+       "mainpll_d5"
+};
+
+static const char * const nfiecc_parents[] __initconst = {
+       "clk_null",
+       "nfi2x_pad_sel",
+       "mainpll_d4",
+       "clk_null",
+       "csw_nfiecc_sel"
+};
+
+static struct mtk_composite top_muxes[] __initdata = {
+       /* CLK_MUX_SEL0 */
+       MUX(CLK_TOP_UART0_SEL, "uart0_sel", uart0_parents,
+               0x000, 0, 1),
+       MUX(CLK_TOP_AHB_INFRA_SEL, "ahb_infra_sel", ahb_infra_parents,
+               0x000, 4, 4),
+       MUX(CLK_TOP_MSDC0_SEL, "msdc0_sel", msdc0_parents,
+               0x000, 11, 3),
+       MUX(CLK_TOP_UART1_SEL, "uart1_sel", uart1_parents,
+               0x000, 19, 1),
+       MUX(CLK_TOP_MSDC1_SEL, "msdc1_sel", msdc1_parents,
+               0x000, 20, 3),
+       MUX(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents,
+               0x000, 24, 2),
+       MUX(CLK_TOP_QAXI_AUD26M_SEL, "qaxi_aud26m_sel", qaxi_aud26m_parents,
+               0x000, 26, 1),
+       MUX(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
+               0x000, 27, 3),
+       /* CLK_MUX_SEL1 */
+       MUX(CLK_TOP_NFI2X_PAD_SEL, "nfi2x_pad_sel", nfi2x_pad_parents,
+               0x004, 0, 7),
+       MUX(CLK_TOP_NFI1X_PAD_SEL, "nfi1x_pad_sel", nfi1x_pad_parents,
+               0x004, 7, 1),
+       MUX(CLK_TOP_USB_78M_SEL, "usb_78m_sel", usb_78m_parents,
+               0x004, 20, 3),
+       /* CLK_MUX_SEL8 */
+       MUX(CLK_TOP_SPINOR_SEL, "spinor_sel", spinor_parents,
+               0x040, 0, 3),
+       MUX(CLK_TOP_MSDC2_SEL, "msdc2_sel", msdc2_parents,
+               0x040, 3, 3),
+       MUX(CLK_TOP_ETH_SEL, "eth_sel", eth_parents,
+               0x040, 6, 3),
+       MUX(CLK_TOP_AUD1_SEL, "aud1_sel", aud1_parents,
+               0x040, 22, 1),
+       MUX(CLK_TOP_AUD2_SEL, "aud2_sel", aud2_parents,
+               0x040, 23, 1),
+       MUX(CLK_TOP_AUD_ENGEN1_SEL, "aud_engen1_sel", aud_engen1_parents,
+               0x040, 24, 2),
+       MUX(CLK_TOP_AUD_ENGEN2_SEL, "aud_engen2_sel", aud_engen2_parents,
+               0x040, 26, 2),
+       MUX(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents,
+               0x040, 28, 2),
+       /* CLK_SEL_9 */
+       MUX(CLK_TOP_AUD_I2S0_M_SEL, "aud_i2s0_m_sel", aud_i2s0_m_parents,
+               0x044, 12, 1),
+       MUX(CLK_TOP_AUD_I2S1_M_SEL, "aud_i2s1_m_sel", aud_i2s0_m_parents,
+               0x044, 13, 1),
+       MUX(CLK_TOP_AUD_I2S2_M_SEL, "aud_i2s2_m_sel", aud_i2s0_m_parents,
+               0x044, 14, 1),
+       MUX(CLK_TOP_AUD_I2S3_M_SEL, "aud_i2s3_m_sel", aud_i2s0_m_parents,
+               0x044, 15, 1),
+       MUX(CLK_TOP_AUD_I2S4_M_SEL, "aud_i2s4_m_sel", aud_i2s0_m_parents,
+               0x044, 16, 1),
+       MUX(CLK_TOP_AUD_I2S5_M_SEL, "aud_i2s5_m_sel", aud_i2s0_m_parents,
+               0x044, 17, 1),
+       MUX(CLK_TOP_AUD_SPDIF_B_SEL, "aud_spdif_b_sel", aud_i2s0_m_parents,
+               0x044, 18, 1),
+       /* CLK_MUX_SEL13 */
+       MUX(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents,
+               0x07c, 0, 1),
+       MUX(CLK_TOP_SPI_SEL, "spi_sel", spi_parents,
+               0x07c, 1, 2),
+       MUX(CLK_TOP_AUD_SPDIFIN_SEL, "aud_spdifin_sel", aud_spdifin_parents,
+               0x07c, 3, 1),
+       MUX(CLK_TOP_UART2_SEL, "uart2_sel", uart2_parents,
+               0x07c, 4, 1),
+       MUX(CLK_TOP_BSI_SEL, "bsi_sel", bsi_parents,
+               0x07c, 5, 2),
+       MUX(CLK_TOP_DBG_ATCLK_SEL, "dbg_atclk_sel", dbg_atclk_parents,
+               0x07c, 7, 3),
+       MUX(CLK_TOP_CSW_NFIECC_SEL, "csw_nfiecc_sel", csw_nfiecc_parents,
+               0x07c, 10, 3),
+       MUX(CLK_TOP_NFIECC_SEL, "nfiecc_sel", nfiecc_parents,
+               0x07c, 13, 3),
+};
+
+static const char * const ifr_mux1_parents[] __initconst = {
+       "clk26m_ck",
+       "armpll",
+       "univpll",
+       "mainpll_d2"
+};
+
+static const char * const ifr_eth_25m_parents[] __initconst = {
+       "eth_d2_ck",
+       "rg_eth"
+};
+
+static const char * const ifr_i2c0_parents[] __initconst = {
+       "ahb_infra_d2",
+       "rg_i2c"
+};
+
+static const struct mtk_composite ifr_muxes[] __initconst = {
+       MUX(CLK_IFR_MUX1_SEL, "ifr_mux1_sel", ifr_mux1_parents, 0x000,
+               2, 2),
+       MUX(CLK_IFR_ETH_25M_SEL, "ifr_eth_25m_sel", ifr_eth_25m_parents, 0x080,
+               0, 1),
+       MUX(CLK_IFR_I2C0_SEL, "ifr_i2c0_sel", ifr_i2c0_parents, 0x080,
+               1, 1),
+       MUX(CLK_IFR_I2C1_SEL, "ifr_i2c1_sel", ifr_i2c0_parents, 0x080,
+               2, 1),
+       MUX(CLK_IFR_I2C2_SEL, "ifr_i2c2_sel", ifr_i2c0_parents, 0x080,
+               3, 1),
+};
+
+#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) {   \
+               .id = _id,                                      \
+               .name = _name,                                  \
+               .parent_name = _parent,                         \
+               .div_reg = _reg,                                \
+               .div_shift = _shift,                            \
+               .div_width = _width,                            \
+}
+
+static const struct mtk_clk_divider top_adj_divs[] = {
+       DIV_ADJ(CLK_TOP_APLL12_CK_DIV0, "apll12_ck_div0", "aud_i2s0_m_sel",
+               0x0048, 0, 8),
+       DIV_ADJ(CLK_TOP_APLL12_CK_DIV1, "apll12_ck_div1", "aud_i2s1_m_sel",
+               0x0048, 8, 8),
+       DIV_ADJ(CLK_TOP_APLL12_CK_DIV2, "apll12_ck_div2", "aud_i2s2_m_sel",
+               0x0048, 16, 8),
+       DIV_ADJ(CLK_TOP_APLL12_CK_DIV3, "apll12_ck_div3", "aud_i2s3_m_sel",
+               0x0048, 24, 8),
+       DIV_ADJ(CLK_TOP_APLL12_CK_DIV4, "apll12_ck_div4", "aud_i2s4_m_sel",
+               0x004c, 0, 8),
+       DIV_ADJ(CLK_TOP_APLL12_CK_DIV4B, "apll12_ck_div4b", "apll12_div4",
+               0x004c, 8, 8),
+       DIV_ADJ(CLK_TOP_APLL12_CK_DIV5, "apll12_ck_div5", "aud_i2s5_m_sel",
+               0x004c, 16, 8),
+       DIV_ADJ(CLK_TOP_APLL12_CK_DIV5B, "apll12_ck_div5b", "apll12_div5",
+               0x004c, 24, 8),
+       DIV_ADJ(CLK_TOP_APLL12_CK_DIV6, "apll12_ck_div6", "aud_spdif_b_sel",
+               0x0078, 0, 8),
+};
+
+static const struct mtk_gate_regs top1_cg_regs = {
+       .set_ofs = 0x54,
+       .clr_ofs = 0x84,
+       .sta_ofs = 0x24,
+};
+
+static const struct mtk_gate_regs top2_cg_regs = {
+       .set_ofs = 0x6c,
+       .clr_ofs = 0x9c,
+       .sta_ofs = 0x3c,
+};
+
+static const struct mtk_gate_regs top3_cg_regs = {
+       .set_ofs = 0xa0,
+       .clr_ofs = 0xb0,
+       .sta_ofs = 0x70,
+};
+
+static const struct mtk_gate_regs top4_cg_regs = {
+       .set_ofs = 0xa4,
+       .clr_ofs = 0xb4,
+       .sta_ofs = 0x74,
+};
+
+static const struct mtk_gate_regs top5_cg_regs = {
+       .set_ofs = 0x44,
+       .clr_ofs = 0x44,
+       .sta_ofs = 0x44,
+};
+
+#define GATE_TOP1(_id, _name, _parent, _shift) {       \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &top1_cg_regs,                  \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr,        \
+       }
+
+#define GATE_TOP2(_id, _name, _parent, _shift) {       \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &top2_cg_regs,                  \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr,        \
+       }
+
+#define GATE_TOP2_I(_id, _name, _parent, _shift) {     \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &top2_cg_regs,                  \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr_inv,    \
+       }
+
+#define GATE_TOP3(_id, _name, _parent, _shift) {       \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &top3_cg_regs,                  \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr,        \
+       }
+
+#define GATE_TOP4_I(_id, _name, _parent, _shift) {     \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &top4_cg_regs,                  \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr_inv,    \
+       }
+
+#define GATE_TOP5(_id, _name, _parent, _shift) {       \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &top5_cg_regs,                  \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_no_setclr,     \
+       }
+
+static const struct mtk_gate top_clks[] __initconst = {
+       /* TOP1 */
+       GATE_TOP1(CLK_TOP_THEM, "them", "ahb_infra_sel", 1),
+       GATE_TOP1(CLK_TOP_APDMA, "apdma", "ahb_infra_sel", 2),
+       GATE_TOP1(CLK_TOP_I2C0, "i2c0", "ifr_i2c0_sel", 3),
+       GATE_TOP1(CLK_TOP_I2C1, "i2c1", "ifr_i2c1_sel", 4),
+       GATE_TOP1(CLK_TOP_AUXADC1, "auxadc1", "ahb_infra_sel", 5),
+       GATE_TOP1(CLK_TOP_NFI, "nfi", "nfi1x_pad_sel", 6),
+       GATE_TOP1(CLK_TOP_NFIECC, "nfiecc", "rg_nfiecc", 7),
+       GATE_TOP1(CLK_TOP_DEBUGSYS, "debugsys", "rg_dbg_atclk", 8),
+       GATE_TOP1(CLK_TOP_PWM, "pwm", "ahb_infra_sel", 9),
+       GATE_TOP1(CLK_TOP_UART0, "uart0", "uart0_sel", 10),
+       GATE_TOP1(CLK_TOP_UART1, "uart1", "uart1_sel", 11),
+       GATE_TOP1(CLK_TOP_BTIF, "btif", "ahb_infra_sel", 12),
+       GATE_TOP1(CLK_TOP_USB, "usb", "usb_78m", 13),
+       GATE_TOP1(CLK_TOP_FLASHIF_26M, "flashif_26m", "clk26m_ck", 14),
+       GATE_TOP1(CLK_TOP_AUXADC2, "auxadc2", "ahb_infra_sel", 15),
+       GATE_TOP1(CLK_TOP_I2C2, "i2c2", "ifr_i2c2_sel", 16),
+       GATE_TOP1(CLK_TOP_MSDC0, "msdc0", "msdc0_sel", 17),
+       GATE_TOP1(CLK_TOP_MSDC1, "msdc1", "msdc1_sel", 18),
+       GATE_TOP1(CLK_TOP_NFI2X, "nfi2x", "nfi2x_pad_sel", 19),
+       GATE_TOP1(CLK_TOP_PMICWRAP_AP, "pwrap_ap", "clk26m_ck", 20),
+       GATE_TOP1(CLK_TOP_SEJ, "sej", "ahb_infra_sel", 21),
+       GATE_TOP1(CLK_TOP_MEMSLP_DLYER, "memslp_dlyer", "clk26m_ck", 22),
+       GATE_TOP1(CLK_TOP_SPI, "spi", "spi_sel", 23),
+       GATE_TOP1(CLK_TOP_APXGPT, "apxgpt", "clk26m_ck", 24),
+       GATE_TOP1(CLK_TOP_AUDIO, "audio", "clk26m_ck", 25),
+       GATE_TOP1(CLK_TOP_PMICWRAP_MD, "pwrap_md", "clk26m_ck", 27),
+       GATE_TOP1(CLK_TOP_PMICWRAP_CONN, "pwrap_conn", "clk26m_ck", 28),
+       GATE_TOP1(CLK_TOP_PMICWRAP_26M, "pwrap_26m", "clk26m_ck", 29),
+       GATE_TOP1(CLK_TOP_AUX_ADC, "aux_adc", "clk26m_ck", 30),
+       GATE_TOP1(CLK_TOP_AUX_TP, "aux_tp", "clk26m_ck", 31),
+       /* TOP2 */
+       GATE_TOP2(CLK_TOP_MSDC2, "msdc2", "ahb_infra_sel", 0),
+       GATE_TOP2(CLK_TOP_RBIST, "rbist", "univpll_d12", 1),
+       GATE_TOP2(CLK_TOP_NFI_BUS, "nfi_bus", "ahb_infra_sel", 2),
+       GATE_TOP2(CLK_TOP_GCE, "gce", "ahb_infra_sel", 4),
+       GATE_TOP2(CLK_TOP_TRNG, "trng", "ahb_infra_sel", 5),
+       GATE_TOP2(CLK_TOP_SEJ_13M, "sej_13m", "clk26m_ck", 6),
+       GATE_TOP2(CLK_TOP_AES, "aes", "ahb_infra_sel", 7),
+       GATE_TOP2(CLK_TOP_PWM_B, "pwm_b", "rg_pwm_infra", 8),
+       GATE_TOP2(CLK_TOP_PWM1_FB, "pwm1_fb", "rg_pwm_infra", 9),
+       GATE_TOP2(CLK_TOP_PWM2_FB, "pwm2_fb", "rg_pwm_infra", 10),
+       GATE_TOP2(CLK_TOP_PWM3_FB, "pwm3_fb", "rg_pwm_infra", 11),
+       GATE_TOP2(CLK_TOP_PWM4_FB, "pwm4_fb", "rg_pwm_infra", 12),
+       GATE_TOP2(CLK_TOP_PWM5_FB, "pwm5_fb", "rg_pwm_infra", 13),
+       GATE_TOP2(CLK_TOP_USB_1P, "usb_1p", "usb_78m", 14),
+       GATE_TOP2(CLK_TOP_FLASHIF_FREERUN, "flashif_freerun", "ahb_infra_sel",
+               15),
+       GATE_TOP2(CLK_TOP_66M_ETH, "eth_66m", "ahb_infra_d2", 19),
+       GATE_TOP2(CLK_TOP_133M_ETH, "eth_133m", "ahb_infra_sel", 20),
+       GATE_TOP2(CLK_TOP_FETH_25M, "feth_25m", "ifr_eth_25m_sel", 21),
+       GATE_TOP2(CLK_TOP_FETH_50M, "feth_50m", "rg_eth", 22),
+       GATE_TOP2(CLK_TOP_FLASHIF_AXI, "flashif_axi", "ahb_infra_sel", 23),
+       GATE_TOP2(CLK_TOP_USBIF, "usbif", "ahb_infra_sel", 24),
+       GATE_TOP2(CLK_TOP_UART2, "uart2", "rg_uart2", 25),
+       GATE_TOP2(CLK_TOP_BSI, "bsi", "ahb_infra_sel", 26),
+       GATE_TOP2_I(CLK_TOP_MSDC0_INFRA, "msdc0_infra", "msdc0", 28),
+       GATE_TOP2_I(CLK_TOP_MSDC1_INFRA, "msdc1_infra", "msdc1", 29),
+       GATE_TOP2_I(CLK_TOP_MSDC2_INFRA, "msdc2_infra", "rg_msdc2", 30),
+       GATE_TOP2(CLK_TOP_USB_78M, "usb_78m", "usb_78m_sel", 31),
+       /* TOP3 */
+       GATE_TOP3(CLK_TOP_RG_SPINOR, "rg_spinor", "spinor_sel", 0),
+       GATE_TOP3(CLK_TOP_RG_MSDC2, "rg_msdc2", "msdc2_sel", 1),
+       GATE_TOP3(CLK_TOP_RG_ETH, "rg_eth", "eth_sel", 2),
+       GATE_TOP3(CLK_TOP_RG_AUD1, "rg_aud1", "aud1_sel", 8),
+       GATE_TOP3(CLK_TOP_RG_AUD2, "rg_aud2", "aud2_sel", 9),
+       GATE_TOP3(CLK_TOP_RG_AUD_ENGEN1, "rg_aud_engen1", "aud_engen1_sel", 10),
+       GATE_TOP3(CLK_TOP_RG_AUD_ENGEN2, "rg_aud_engen2", "aud_engen2_sel", 11),
+       GATE_TOP3(CLK_TOP_RG_I2C, "rg_i2c", "i2c_sel", 12),
+       GATE_TOP3(CLK_TOP_RG_PWM_INFRA, "rg_pwm_infra", "pwm_sel", 13),
+       GATE_TOP3(CLK_TOP_RG_AUD_SPDIF_IN, "rg_aud_spdif_in", "aud_spdifin_sel",
+               14),
+       GATE_TOP3(CLK_TOP_RG_UART2, "rg_uart2", "uart2_sel", 15),
+       GATE_TOP3(CLK_TOP_RG_BSI, "rg_bsi", "bsi_sel", 16),
+       GATE_TOP3(CLK_TOP_RG_DBG_ATCLK, "rg_dbg_atclk", "dbg_atclk_sel", 17),
+       GATE_TOP3(CLK_TOP_RG_NFIECC, "rg_nfiecc", "nfiecc_sel", 18),
+       /* TOP4 */
+       GATE_TOP4_I(CLK_TOP_RG_APLL1_D2_EN, "rg_apll1_d2_en", "apll1_d2", 8),
+       GATE_TOP4_I(CLK_TOP_RG_APLL1_D4_EN, "rg_apll1_d4_en", "apll1_d4", 9),
+       GATE_TOP4_I(CLK_TOP_RG_APLL1_D8_EN, "rg_apll1_d8_en", "apll1_d8", 10),
+       GATE_TOP4_I(CLK_TOP_RG_APLL2_D2_EN, "rg_apll2_d2_en", "apll2_d2", 11),
+       GATE_TOP4_I(CLK_TOP_RG_APLL2_D4_EN, "rg_apll2_d4_en", "apll2_d4", 12),
+       GATE_TOP4_I(CLK_TOP_RG_APLL2_D8_EN, "rg_apll2_d8_en", "apll2_d8", 13),
+       /* TOP5 */
+       GATE_TOP5(CLK_TOP_APLL12_DIV0, "apll12_div0", "apll12_ck_div0", 0),
+       GATE_TOP5(CLK_TOP_APLL12_DIV1, "apll12_div1", "apll12_ck_div1", 1),
+       GATE_TOP5(CLK_TOP_APLL12_DIV2, "apll12_div2", "apll12_ck_div2", 2),
+       GATE_TOP5(CLK_TOP_APLL12_DIV3, "apll12_div3", "apll12_ck_div3", 3),
+       GATE_TOP5(CLK_TOP_APLL12_DIV4, "apll12_div4", "apll12_ck_div4", 4),
+       GATE_TOP5(CLK_TOP_APLL12_DIV4B, "apll12_div4b", "apll12_ck_div4b", 5),
+       GATE_TOP5(CLK_TOP_APLL12_DIV5, "apll12_div5", "apll12_ck_div5", 6),
+       GATE_TOP5(CLK_TOP_APLL12_DIV5B, "apll12_div5b", "apll12_ck_div5b", 7),
+       GATE_TOP5(CLK_TOP_APLL12_DIV6, "apll12_div6", "apll12_ck_div6", 8),
+};
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+       struct clk_onecell_data *clk_data;
+       int r;
+       void __iomem *base;
+
+       base = of_iomap(node, 0);
+       if (!base) {
+               pr_err("%s(): ioremap failed\n", __func__);
+               return;
+       }
+
+       clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+       mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks),
+                                   clk_data);
+       mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), clk_data);
+
+       mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+       mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
+               &mt8516_clk_lock, clk_data);
+       mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs),
+                               base, &mt8516_clk_lock, clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               pr_err("%s(): could not register clock provider: %d\n",
+                       __func__, r);
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8516-topckgen", mtk_topckgen_init);
+
+static void __init mtk_infracfg_init(struct device_node *node)
+{
+       struct clk_onecell_data *clk_data;
+       int r;
+       void __iomem *base;
+
+       base = of_iomap(node, 0);
+       if (!base) {
+               pr_err("%s(): ioremap failed\n", __func__);
+               return;
+       }
+
+       clk_data = mtk_alloc_clk_data(CLK_IFR_NR_CLK);
+
+       mtk_clk_register_composites(ifr_muxes, ARRAY_SIZE(ifr_muxes), base,
+               &mt8516_clk_lock, clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               pr_err("%s(): could not register clock provider: %d\n",
+                       __func__, r);
+}
+CLK_OF_DECLARE(mtk_infracfg, "mediatek,mt8516-infracfg", mtk_infracfg_init);
+
+#define MT8516_PLL_FMAX                (1502UL * MHZ)
+
+#define CON0_MT8516_RST_BAR    BIT(27)
+
+#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,  \
+                       _pd_reg, _pd_shift, _tuner_reg, _pcw_reg,       \
+                       _pcw_shift, _div_table) {                       \
+               .id = _id,                                              \
+               .name = _name,                                          \
+               .reg = _reg,                                            \
+               .pwr_reg = _pwr_reg,                                    \
+               .en_mask = _en_mask,                                    \
+               .flags = _flags,                                        \
+               .rst_bar_mask = CON0_MT8516_RST_BAR,                    \
+               .fmax = MT8516_PLL_FMAX,                                \
+               .pcwbits = _pcwbits,                                    \
+               .pd_reg = _pd_reg,                                      \
+               .pd_shift = _pd_shift,                                  \
+               .tuner_reg = _tuner_reg,                                \
+               .pcw_reg = _pcw_reg,                                    \
+               .pcw_shift = _pcw_shift,                                \
+               .div_table = _div_table,                                \
+       }
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,    \
+                       _pd_reg, _pd_shift, _tuner_reg, _pcw_reg,       \
+                       _pcw_shift)                                     \
+               PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
+                       _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \
+                       NULL)
+
+static const struct mtk_pll_div_table mmpll_div_table[] = {
+       { .div = 0, .freq = MT8516_PLL_FMAX },
+       { .div = 1, .freq = 1000000000 },
+       { .div = 2, .freq = 604500000 },
+       { .div = 3, .freq = 253500000 },
+       { .div = 4, .freq = 126750000 },
+       { } /* sentinel */
+};
+
+static const struct mtk_pll_data plls[] = {
+       PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0100, 0x0110, 0x00000001, 0,
+               21, 0x0104, 24, 0, 0x0104, 0),
+       PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0120, 0x0130, 0x00000001,
+               HAVE_RST_BAR, 21, 0x0124, 24, 0, 0x0124, 0),
+       PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0140, 0x0150, 0x30000001,
+               HAVE_RST_BAR, 7, 0x0144, 24, 0, 0x0144, 0),
+       PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0160, 0x0170, 0x00000001, 0,
+               21, 0x0164, 24, 0, 0x0164, 0, mmpll_div_table),
+       PLL(CLK_APMIXED_APLL1, "apll1", 0x0180, 0x0190, 0x00000001, 0,
+               31, 0x0180, 1, 0x0194, 0x0184, 0),
+       PLL(CLK_APMIXED_APLL2, "apll2", 0x01A0, 0x01B0, 0x00000001, 0,
+               31, 0x01A0, 1, 0x01B4, 0x01A4, 0),
+};
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+       struct clk_onecell_data *clk_data;
+       void __iomem *base;
+       int r;
+
+       base = of_iomap(node, 0);
+       if (!base) {
+               pr_err("%s(): ioremap failed\n", __func__);
+               return;
+       }
+
+       clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+
+       mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               pr_err("%s(): could not register clock provider: %d\n",
+                       __func__, r);
+
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8516-apmixedsys",
+               mtk_apmixedsys_init);
index fb27b5bf30d95e737ffabdaf43a4ddd4d86328a0..33ab1731482f3f9939e3230e43f7b7d3df76a0f8 100644 (file)
@@ -227,10 +227,13 @@ struct mtk_pll_data {
        unsigned int flags;
        const struct clk_ops *ops;
        u32 rst_bar_mask;
+       unsigned long fmin;
        unsigned long fmax;
        int pcwbits;
+       int pcwibits;
        uint32_t pcw_reg;
        int pcw_shift;
+       uint32_t pcw_chg_reg;
        const struct mtk_pll_div_table *div_table;
        const char *parent_name;
 };
diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c
new file mode 100644 (file)
index 0000000..76f9cd0
--- /dev/null
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Owen Chen <owen.chen@mediatek.com>
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-mux.h"
+
+static inline struct mtk_clk_mux *to_mtk_clk_mux(struct clk_hw *hw)
+{
+       return container_of(hw, struct mtk_clk_mux, hw);
+}
+
+static int mtk_clk_mux_enable(struct clk_hw *hw)
+{
+       struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+       u32 mask = BIT(mux->data->gate_shift);
+
+       return regmap_update_bits(mux->regmap, mux->data->mux_ofs,
+                       mask, ~mask);
+}
+
+static void mtk_clk_mux_disable(struct clk_hw *hw)
+{
+       struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+       u32 mask = BIT(mux->data->gate_shift);
+
+       regmap_update_bits(mux->regmap, mux->data->mux_ofs, mask, mask);
+}
+
+static int mtk_clk_mux_enable_setclr(struct clk_hw *hw)
+{
+       struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+
+       return regmap_write(mux->regmap, mux->data->clr_ofs,
+                       BIT(mux->data->gate_shift));
+}
+
+static void mtk_clk_mux_disable_setclr(struct clk_hw *hw)
+{
+       struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+
+       regmap_write(mux->regmap, mux->data->set_ofs,
+                       BIT(mux->data->gate_shift));
+}
+
+static int mtk_clk_mux_is_enabled(struct clk_hw *hw)
+{
+       struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+       u32 val;
+
+       regmap_read(mux->regmap, mux->data->mux_ofs, &val);
+
+       return (val & BIT(mux->data->gate_shift)) == 0;
+}
+
+static u8 mtk_clk_mux_get_parent(struct clk_hw *hw)
+{
+       struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+       u32 mask = GENMASK(mux->data->mux_width - 1, 0);
+       u32 val;
+
+       regmap_read(mux->regmap, mux->data->mux_ofs, &val);
+       val = (val >> mux->data->mux_shift) & mask;
+
+       return val;
+}
+
+static int mtk_clk_mux_set_parent_lock(struct clk_hw *hw, u8 index)
+{
+       struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+       u32 mask = GENMASK(mux->data->mux_width - 1, 0);
+       unsigned long flags = 0;
+
+       if (mux->lock)
+               spin_lock_irqsave(mux->lock, flags);
+       else
+               __acquire(mux->lock);
+
+       regmap_update_bits(mux->regmap, mux->data->mux_ofs, mask,
+               index << mux->data->mux_shift);
+
+       if (mux->lock)
+               spin_unlock_irqrestore(mux->lock, flags);
+       else
+               __release(mux->lock);
+
+       return 0;
+}
+
+static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index)
+{
+       struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+       u32 mask = GENMASK(mux->data->mux_width - 1, 0);
+       u32 val, orig;
+       unsigned long flags = 0;
+
+       if (mux->lock)
+               spin_lock_irqsave(mux->lock, flags);
+       else
+               __acquire(mux->lock);
+
+       regmap_read(mux->regmap, mux->data->mux_ofs, &orig);
+       val = (orig & ~(mask << mux->data->mux_shift))
+                       | (index << mux->data->mux_shift);
+
+       if (val != orig) {
+               regmap_write(mux->regmap, mux->data->clr_ofs,
+                               mask << mux->data->mux_shift);
+               regmap_write(mux->regmap, mux->data->set_ofs,
+                               index << mux->data->mux_shift);
+
+               if (mux->data->upd_shift >= 0)
+                       regmap_write(mux->regmap, mux->data->upd_ofs,
+                                       BIT(mux->data->upd_shift));
+       }
+
+       if (mux->lock)
+               spin_unlock_irqrestore(mux->lock, flags);
+       else
+               __release(mux->lock);
+
+       return 0;
+}
+
+const struct clk_ops mtk_mux_ops = {
+       .get_parent = mtk_clk_mux_get_parent,
+       .set_parent = mtk_clk_mux_set_parent_lock,
+};
+
+const struct clk_ops mtk_mux_clr_set_upd_ops = {
+       .get_parent = mtk_clk_mux_get_parent,
+       .set_parent = mtk_clk_mux_set_parent_setclr_lock,
+};
+
+const struct clk_ops mtk_mux_gate_ops = {
+       .enable = mtk_clk_mux_enable,
+       .disable = mtk_clk_mux_disable,
+       .is_enabled = mtk_clk_mux_is_enabled,
+       .get_parent = mtk_clk_mux_get_parent,
+       .set_parent = mtk_clk_mux_set_parent_lock,
+};
+
+const struct clk_ops mtk_mux_gate_clr_set_upd_ops = {
+       .enable = mtk_clk_mux_enable_setclr,
+       .disable = mtk_clk_mux_disable_setclr,
+       .is_enabled = mtk_clk_mux_is_enabled,
+       .get_parent = mtk_clk_mux_get_parent,
+       .set_parent = mtk_clk_mux_set_parent_setclr_lock,
+};
+
+struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
+                                struct regmap *regmap,
+                                spinlock_t *lock)
+{
+       struct mtk_clk_mux *clk_mux;
+       struct clk_init_data init;
+       struct clk *clk;
+
+       clk_mux = kzalloc(sizeof(*clk_mux), GFP_KERNEL);
+       if (!clk_mux)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = mux->name;
+       init.flags = mux->flags | CLK_SET_RATE_PARENT;
+       init.parent_names = mux->parent_names;
+       init.num_parents = mux->num_parents;
+       init.ops = mux->ops;
+
+       clk_mux->regmap = regmap;
+       clk_mux->data = mux;
+       clk_mux->lock = lock;
+       clk_mux->hw.init = &init;
+
+       clk = clk_register(NULL, &clk_mux->hw);
+       if (IS_ERR(clk)) {
+               kfree(clk_mux);
+               return clk;
+       }
+
+       return clk;
+}
+
+int mtk_clk_register_muxes(const struct mtk_mux *muxes,
+                          int num, struct device_node *node,
+                          spinlock_t *lock,
+                          struct clk_onecell_data *clk_data)
+{
+       struct regmap *regmap;
+       struct clk *clk;
+       int i;
+
+       regmap = syscon_node_to_regmap(node);
+       if (IS_ERR(regmap)) {
+               pr_err("Cannot find regmap for %pOF: %ld\n", node,
+                      PTR_ERR(regmap));
+               return PTR_ERR(regmap);
+       }
+
+       for (i = 0; i < num; i++) {
+               const struct mtk_mux *mux = &muxes[i];
+
+               if (IS_ERR_OR_NULL(clk_data->clks[mux->id])) {
+                       clk = mtk_clk_register_mux(mux, regmap, lock);
+
+                       if (IS_ERR(clk)) {
+                               pr_err("Failed to register clk %s: %ld\n",
+                                      mux->name, PTR_ERR(clk));
+                               continue;
+                       }
+
+                       clk_data->clks[mux->id] = clk;
+               }
+       }
+
+       return 0;
+}
diff --git a/drivers/clk/mediatek/clk-mux.h b/drivers/clk/mediatek/clk-mux.h
new file mode 100644 (file)
index 0000000..f5625f4
--- /dev/null
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Owen Chen <owen.chen@mediatek.com>
+ */
+
+#ifndef __DRV_CLK_MTK_MUX_H
+#define __DRV_CLK_MTK_MUX_H
+
+#include <linux/clk-provider.h>
+
+struct mtk_clk_mux {
+       struct clk_hw hw;
+       struct regmap *regmap;
+       const struct mtk_mux *data;
+       spinlock_t *lock;
+};
+
+struct mtk_mux {
+       int id;
+       const char *name;
+       const char * const *parent_names;
+       unsigned int flags;
+
+       u32 mux_ofs;
+       u32 set_ofs;
+       u32 clr_ofs;
+       u32 upd_ofs;
+
+       u8 mux_shift;
+       u8 mux_width;
+       u8 gate_shift;
+       s8 upd_shift;
+
+       const struct clk_ops *ops;
+
+       signed char num_parents;
+};
+
+extern const struct clk_ops mtk_mux_ops;
+extern const struct clk_ops mtk_mux_clr_set_upd_ops;
+extern const struct clk_ops mtk_mux_gate_ops;
+extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops;
+
+#define GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs,         \
+                       _mux_set_ofs, _mux_clr_ofs, _shift, _width,     \
+                       _gate, _upd_ofs, _upd, _flags, _ops) {          \
+               .id = _id,                                              \
+               .name = _name,                                          \
+               .mux_ofs = _mux_ofs,                                    \
+               .set_ofs = _mux_set_ofs,                                \
+               .clr_ofs = _mux_clr_ofs,                                \
+               .upd_ofs = _upd_ofs,                                    \
+               .mux_shift = _shift,                                    \
+               .mux_width = _width,                                    \
+               .gate_shift = _gate,                                    \
+               .upd_shift = _upd,                                      \
+               .parent_names = _parents,                               \
+               .num_parents = ARRAY_SIZE(_parents),                    \
+               .flags = _flags,                                        \
+               .ops = &_ops,                                           \
+       }
+
+#define MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs,     \
+                       _mux_set_ofs, _mux_clr_ofs, _shift, _width,     \
+                       _gate, _upd_ofs, _upd, _flags)                  \
+               GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs,  \
+                       _mux_set_ofs, _mux_clr_ofs, _shift, _width,     \
+                       _gate, _upd_ofs, _upd, _flags,                  \
+                       mtk_mux_gate_clr_set_upd_ops)
+
+#define MUX_GATE_CLR_SET_UPD(_id, _name, _parents, _mux_ofs,           \
+                       _mux_set_ofs, _mux_clr_ofs, _shift, _width,     \
+                       _gate, _upd_ofs, _upd)                          \
+               MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents,        \
+                       _mux_ofs, _mux_set_ofs, _mux_clr_ofs, _shift,   \
+                       _width, _gate, _upd_ofs, _upd,                  \
+                       CLK_SET_RATE_PARENT)
+
+struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
+                                struct regmap *regmap,
+                                spinlock_t *lock);
+
+int mtk_clk_register_muxes(const struct mtk_mux *muxes,
+                          int num, struct device_node *node,
+                          spinlock_t *lock,
+                          struct clk_onecell_data *clk_data);
+
+#endif /* __DRV_CLK_MTK_MUX_H */
index f54e4015b0b1f3c005e7d82b5fdffa6dc826a8ad..8d556fc99fed170f6c8a2508d6bfc3eca86069f1 100644 (file)
 #define CON0_BASE_EN           BIT(0)
 #define CON0_PWR_ON            BIT(0)
 #define CON0_ISO_EN            BIT(1)
-#define CON0_PCW_CHG           BIT(31)
+#define PCW_CHG_MASK           BIT(31)
 
 #define AUDPLL_TUNER_EN                BIT(31)
 
 #define POSTDIV_MASK           0x7
+
+/* default 7 bits integer, can be overridden with pcwibits. */
 #define INTEGER_BITS           7
 
 /*
@@ -49,6 +51,7 @@ struct mtk_clk_pll {
        void __iomem    *tuner_addr;
        void __iomem    *tuner_en_addr;
        void __iomem    *pcw_addr;
+       void __iomem    *pcw_chg_addr;
        const struct mtk_pll_data *data;
 };
 
@@ -68,12 +71,15 @@ static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
                u32 pcw, int postdiv)
 {
        int pcwbits = pll->data->pcwbits;
-       int pcwfbits;
+       int pcwfbits = 0;
+       int ibits;
        u64 vco;
        u8 c = 0;
 
        /* The fractional part of the PLL divider. */
-       pcwfbits = pcwbits > INTEGER_BITS ? pcwbits - INTEGER_BITS : 0;
+       ibits = pll->data->pcwibits ? pll->data->pcwibits : INTEGER_BITS;
+       if (pcwbits > ibits)
+               pcwfbits = pcwbits - ibits;
 
        vco = (u64)fin * pcw;
 
@@ -88,13 +94,39 @@ static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
        return ((unsigned long)vco + postdiv - 1) / postdiv;
 }
 
+static void __mtk_pll_tuner_enable(struct mtk_clk_pll *pll)
+{
+       u32 r;
+
+       if (pll->tuner_en_addr) {
+               r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit);
+               writel(r, pll->tuner_en_addr);
+       } else if (pll->tuner_addr) {
+               r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
+               writel(r, pll->tuner_addr);
+       }
+}
+
+static void __mtk_pll_tuner_disable(struct mtk_clk_pll *pll)
+{
+       u32 r;
+
+       if (pll->tuner_en_addr) {
+               r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit);
+               writel(r, pll->tuner_en_addr);
+       } else if (pll->tuner_addr) {
+               r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
+               writel(r, pll->tuner_addr);
+       }
+}
+
 static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
                int postdiv)
 {
-       u32 con1, val;
-       int pll_en;
+       u32 chg, val;
 
-       pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN;
+       /* disable tuner */
+       __mtk_pll_tuner_disable(pll);
 
        /* set postdiv */
        val = readl(pll->pd_addr);
@@ -112,18 +144,15 @@ static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
                        pll->data->pcw_shift);
        val |= pcw << pll->data->pcw_shift;
        writel(val, pll->pcw_addr);
-
-       con1 = readl(pll->base_addr + REG_CON1);
-
-       if (pll_en)
-               con1 |= CON0_PCW_CHG;
-
-       writel(con1, pll->base_addr + REG_CON1);
+       chg = readl(pll->pcw_chg_addr) | PCW_CHG_MASK;
+       writel(chg, pll->pcw_chg_addr);
        if (pll->tuner_addr)
-               writel(con1 + 1, pll->tuner_addr);
+               writel(val + 1, pll->tuner_addr);
+
+       /* restore tuner_en */
+       __mtk_pll_tuner_enable(pll);
 
-       if (pll_en)
-               udelay(20);
+       udelay(20);
 }
 
 /*
@@ -138,9 +167,10 @@ static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
 static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
                u32 freq, u32 fin)
 {
-       unsigned long fmin = 1000 * MHZ;
+       unsigned long fmin = pll->data->fmin ? pll->data->fmin : (1000 * MHZ);
        const struct mtk_pll_div_table *div_table = pll->data->div_table;
        u64 _pcw;
+       int ibits;
        u32 val;
 
        if (freq > pll->data->fmax)
@@ -164,7 +194,8 @@ static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
        }
 
        /* _pcw = freq * postdiv / fin * 2^pcwfbits */
-       _pcw = ((u64)freq << val) << (pll->data->pcwbits - INTEGER_BITS);
+       ibits = pll->data->pcwibits ? pll->data->pcwibits : INTEGER_BITS;
+       _pcw = ((u64)freq << val) << (pll->data->pcwbits - ibits);
        do_div(_pcw, fin);
 
        *pcw = (u32)_pcw;
@@ -228,13 +259,7 @@ static int mtk_pll_prepare(struct clk_hw *hw)
        r |= pll->data->en_mask;
        writel(r, pll->base_addr + REG_CON0);
 
-       if (pll->tuner_en_addr) {
-               r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit);
-               writel(r, pll->tuner_en_addr);
-       } else if (pll->tuner_addr) {
-               r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
-               writel(r, pll->tuner_addr);
-       }
+       __mtk_pll_tuner_enable(pll);
 
        udelay(20);
 
@@ -258,13 +283,7 @@ static void mtk_pll_unprepare(struct clk_hw *hw)
                writel(r, pll->base_addr + REG_CON0);
        }
 
-       if (pll->tuner_en_addr) {
-               r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit);
-               writel(r, pll->tuner_en_addr);
-       } else if (pll->tuner_addr) {
-               r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
-               writel(r, pll->tuner_addr);
-       }
+       __mtk_pll_tuner_disable(pll);
 
        r = readl(pll->base_addr + REG_CON0);
        r &= ~CON0_BASE_EN;
@@ -302,6 +321,10 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
        pll->pwr_addr = base + data->pwr_reg;
        pll->pd_addr = base + data->pd_reg;
        pll->pcw_addr = base + data->pcw_reg;
+       if (data->pcw_chg_reg)
+               pll->pcw_chg_addr = base + data->pcw_chg_reg;
+       else
+               pll->pcw_chg_addr = pll->base_addr + REG_CON1;
        if (data->tuner_reg)
                pll->tuner_addr = base + data->tuner_reg;
        if (data->tuner_en_reg)
index 7ab200b6c3bff5a18080368550eb850d37ce5d6d..8028ff6f661075168f6e41afde073f0082d1d932 100644 (file)
 #include "clk-phase.h"
 #include "sclk-div.h"
 
-#define AXG_MST_IN_COUNT       8
-#define AXG_SLV_SCLK_COUNT     10
-#define AXG_SLV_LRCLK_COUNT    10
+#define AUD_MST_IN_COUNT       8
+#define AUD_SLV_SCLK_COUNT     10
+#define AUD_SLV_LRCLK_COUNT    10
 
-#define AXG_AUD_GATE(_name, _reg, _bit, _pname, _iflags)               \
-struct clk_regmap axg_##_name = {                                      \
+#define AUD_GATE(_name, _reg, _bit, _pname, _iflags)                   \
+struct clk_regmap aud_##_name = {                                      \
        .data = &(struct clk_regmap_gate_data){                         \
                .offset = (_reg),                                       \
                .bit_idx = (_bit),                                      \
        },                                                              \
        .hw.init = &(struct clk_init_data) {                            \
-               .name = "axg_"#_name,                                   \
+               .name = "aud_"#_name,                                   \
                .ops = &clk_regmap_gate_ops,                            \
                .parent_names = (const char *[]){ _pname },             \
                .num_parents = 1,                                       \
@@ -39,8 +39,8 @@ struct clk_regmap axg_##_name = {                                     \
        },                                                              \
 }
 
-#define AXG_AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pnames, _iflags) \
-struct clk_regmap axg_##_name = {                                      \
+#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pnames, _iflags) \
+struct clk_regmap aud_##_name = {                                      \
        .data = &(struct clk_regmap_mux_data){                          \
                .offset = (_reg),                                       \
                .mask = (_mask),                                        \
@@ -48,7 +48,7 @@ struct clk_regmap axg_##_name = {                                     \
                .flags = (_dflags),                                     \
        },                                                              \
        .hw.init = &(struct clk_init_data){                             \
-               .name = "axg_"#_name,                                   \
+               .name = "aud_"#_name,                                   \
                .ops = &clk_regmap_mux_ops,                             \
                .parent_names = (_pnames),                              \
                .num_parents = ARRAY_SIZE(_pnames),                     \
@@ -56,8 +56,8 @@ struct clk_regmap axg_##_name = {                                     \
        },                                                              \
 }
 
-#define AXG_AUD_DIV(_name, _reg, _shift, _width, _dflags, _pname, _iflags) \
-struct clk_regmap axg_##_name = {                                      \
+#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _pname, _iflags) \
+struct clk_regmap aud_##_name = {                                      \
        .data = &(struct clk_regmap_div_data){                          \
                .offset = (_reg),                                       \
                .shift = (_shift),                                      \
@@ -65,7 +65,7 @@ struct clk_regmap axg_##_name = {                                     \
                .flags = (_dflags),                                     \
        },                                                              \
        .hw.init = &(struct clk_init_data){                             \
-               .name = "axg_"#_name,                                   \
+               .name = "aud_"#_name,                                   \
                .ops = &clk_regmap_divider_ops,                         \
                .parent_names = (const char *[]) { _pname },            \
                .num_parents = 1,                                       \
@@ -73,109 +73,113 @@ struct clk_regmap axg_##_name = {                                 \
        },                                                              \
 }
 
-#define AXG_PCLK_GATE(_name, _bit)                             \
-       AXG_AUD_GATE(_name, AUDIO_CLK_GATE_EN, _bit, "axg_audio_pclk", 0)
+#define AUD_PCLK_GATE(_name, _bit)                             \
+       AUD_GATE(_name, AUDIO_CLK_GATE_EN, _bit, "audio_pclk", 0)
 
 /* Audio peripheral clocks */
-static AXG_PCLK_GATE(ddr_arb,     0);
-static AXG_PCLK_GATE(pdm,         1);
-static AXG_PCLK_GATE(tdmin_a,     2);
-static AXG_PCLK_GATE(tdmin_b,     3);
-static AXG_PCLK_GATE(tdmin_c,     4);
-static AXG_PCLK_GATE(tdmin_lb,    5);
-static AXG_PCLK_GATE(tdmout_a,    6);
-static AXG_PCLK_GATE(tdmout_b,    7);
-static AXG_PCLK_GATE(tdmout_c,    8);
-static AXG_PCLK_GATE(frddr_a,     9);
-static AXG_PCLK_GATE(frddr_b,     10);
-static AXG_PCLK_GATE(frddr_c,     11);
-static AXG_PCLK_GATE(toddr_a,     12);
-static AXG_PCLK_GATE(toddr_b,     13);
-static AXG_PCLK_GATE(toddr_c,     14);
-static AXG_PCLK_GATE(loopback,    15);
-static AXG_PCLK_GATE(spdifin,     16);
-static AXG_PCLK_GATE(spdifout,    17);
-static AXG_PCLK_GATE(resample,    18);
-static AXG_PCLK_GATE(power_detect, 19);
+static AUD_PCLK_GATE(ddr_arb,     0);
+static AUD_PCLK_GATE(pdm,         1);
+static AUD_PCLK_GATE(tdmin_a,     2);
+static AUD_PCLK_GATE(tdmin_b,     3);
+static AUD_PCLK_GATE(tdmin_c,     4);
+static AUD_PCLK_GATE(tdmin_lb,    5);
+static AUD_PCLK_GATE(tdmout_a,    6);
+static AUD_PCLK_GATE(tdmout_b,    7);
+static AUD_PCLK_GATE(tdmout_c,    8);
+static AUD_PCLK_GATE(frddr_a,     9);
+static AUD_PCLK_GATE(frddr_b,     10);
+static AUD_PCLK_GATE(frddr_c,     11);
+static AUD_PCLK_GATE(toddr_a,     12);
+static AUD_PCLK_GATE(toddr_b,     13);
+static AUD_PCLK_GATE(toddr_c,     14);
+static AUD_PCLK_GATE(loopback,    15);
+static AUD_PCLK_GATE(spdifin,     16);
+static AUD_PCLK_GATE(spdifout,    17);
+static AUD_PCLK_GATE(resample,    18);
+static AUD_PCLK_GATE(power_detect, 19);
+static AUD_PCLK_GATE(spdifout_b,   21);
 
 /* Audio Master Clocks */
 static const char * const mst_mux_parent_names[] = {
-       "axg_mst_in0", "axg_mst_in1", "axg_mst_in2", "axg_mst_in3",
-       "axg_mst_in4", "axg_mst_in5", "axg_mst_in6", "axg_mst_in7",
+       "aud_mst_in0", "aud_mst_in1", "aud_mst_in2", "aud_mst_in3",
+       "aud_mst_in4", "aud_mst_in5", "aud_mst_in6", "aud_mst_in7",
 };
 
-#define AXG_MST_MUX(_name, _reg, _flag)                                \
-       AXG_AUD_MUX(_name##_sel, _reg, 0x7, 24, _flag,          \
-                   mst_mux_parent_names, CLK_SET_RATE_PARENT)
-
-#define AXG_MST_MCLK_MUX(_name, _reg)                          \
-       AXG_MST_MUX(_name, _reg, CLK_MUX_ROUND_CLOSEST)
-
-#define AXG_MST_SYS_MUX(_name, _reg)                           \
-       AXG_MST_MUX(_name, _reg, 0)
-
-static AXG_MST_MCLK_MUX(mst_a_mclk,   AUDIO_MCLK_A_CTRL);
-static AXG_MST_MCLK_MUX(mst_b_mclk,   AUDIO_MCLK_B_CTRL);
-static AXG_MST_MCLK_MUX(mst_c_mclk,   AUDIO_MCLK_C_CTRL);
-static AXG_MST_MCLK_MUX(mst_d_mclk,   AUDIO_MCLK_D_CTRL);
-static AXG_MST_MCLK_MUX(mst_e_mclk,   AUDIO_MCLK_E_CTRL);
-static AXG_MST_MCLK_MUX(mst_f_mclk,   AUDIO_MCLK_F_CTRL);
-static AXG_MST_MCLK_MUX(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
-static AXG_MST_MCLK_MUX(pdm_dclk,     AUDIO_CLK_PDMIN_CTRL0);
-static AXG_MST_SYS_MUX(spdifin_clk,   AUDIO_CLK_SPDIFIN_CTRL);
-static AXG_MST_SYS_MUX(pdm_sysclk,    AUDIO_CLK_PDMIN_CTRL1);
-
-#define AXG_MST_DIV(_name, _reg, _flag)                                \
-       AXG_AUD_DIV(_name##_div, _reg, 0, 16, _flag,            \
-                   "axg_"#_name"_sel", CLK_SET_RATE_PARENT)    \
-
-#define AXG_MST_MCLK_DIV(_name, _reg)                          \
-       AXG_MST_DIV(_name, _reg, CLK_DIVIDER_ROUND_CLOSEST)
-
-#define AXG_MST_SYS_DIV(_name, _reg)                           \
-       AXG_MST_DIV(_name, _reg, 0)
-
-static AXG_MST_MCLK_DIV(mst_a_mclk,   AUDIO_MCLK_A_CTRL);
-static AXG_MST_MCLK_DIV(mst_b_mclk,   AUDIO_MCLK_B_CTRL);
-static AXG_MST_MCLK_DIV(mst_c_mclk,   AUDIO_MCLK_C_CTRL);
-static AXG_MST_MCLK_DIV(mst_d_mclk,   AUDIO_MCLK_D_CTRL);
-static AXG_MST_MCLK_DIV(mst_e_mclk,   AUDIO_MCLK_E_CTRL);
-static AXG_MST_MCLK_DIV(mst_f_mclk,   AUDIO_MCLK_F_CTRL);
-static AXG_MST_MCLK_DIV(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
-static AXG_MST_MCLK_DIV(pdm_dclk,     AUDIO_CLK_PDMIN_CTRL0);
-static AXG_MST_SYS_DIV(spdifin_clk,   AUDIO_CLK_SPDIFIN_CTRL);
-static AXG_MST_SYS_DIV(pdm_sysclk,    AUDIO_CLK_PDMIN_CTRL1);
-
-#define AXG_MST_MCLK_GATE(_name, _reg)                         \
-       AXG_AUD_GATE(_name, _reg, 31,  "axg_"#_name"_div",      \
-                    CLK_SET_RATE_PARENT)
-
-static AXG_MST_MCLK_GATE(mst_a_mclk,   AUDIO_MCLK_A_CTRL);
-static AXG_MST_MCLK_GATE(mst_b_mclk,   AUDIO_MCLK_B_CTRL);
-static AXG_MST_MCLK_GATE(mst_c_mclk,   AUDIO_MCLK_C_CTRL);
-static AXG_MST_MCLK_GATE(mst_d_mclk,   AUDIO_MCLK_D_CTRL);
-static AXG_MST_MCLK_GATE(mst_e_mclk,   AUDIO_MCLK_E_CTRL);
-static AXG_MST_MCLK_GATE(mst_f_mclk,   AUDIO_MCLK_F_CTRL);
-static AXG_MST_MCLK_GATE(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
-static AXG_MST_MCLK_GATE(spdifin_clk,  AUDIO_CLK_SPDIFIN_CTRL);
-static AXG_MST_MCLK_GATE(pdm_dclk,     AUDIO_CLK_PDMIN_CTRL0);
-static AXG_MST_MCLK_GATE(pdm_sysclk,   AUDIO_CLK_PDMIN_CTRL1);
+#define AUD_MST_MUX(_name, _reg, _flag)                                \
+       AUD_MUX(_name##_sel, _reg, 0x7, 24, _flag,              \
+               mst_mux_parent_names, CLK_SET_RATE_PARENT)
+
+#define AUD_MST_MCLK_MUX(_name, _reg)                          \
+       AUD_MST_MUX(_name, _reg, CLK_MUX_ROUND_CLOSEST)
+
+#define AUD_MST_SYS_MUX(_name, _reg)                           \
+       AUD_MST_MUX(_name, _reg, 0)
+
+static AUD_MST_MCLK_MUX(mst_a_mclk,   AUDIO_MCLK_A_CTRL);
+static AUD_MST_MCLK_MUX(mst_b_mclk,   AUDIO_MCLK_B_CTRL);
+static AUD_MST_MCLK_MUX(mst_c_mclk,   AUDIO_MCLK_C_CTRL);
+static AUD_MST_MCLK_MUX(mst_d_mclk,   AUDIO_MCLK_D_CTRL);
+static AUD_MST_MCLK_MUX(mst_e_mclk,   AUDIO_MCLK_E_CTRL);
+static AUD_MST_MCLK_MUX(mst_f_mclk,   AUDIO_MCLK_F_CTRL);
+static AUD_MST_MCLK_MUX(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
+static AUD_MST_MCLK_MUX(pdm_dclk,     AUDIO_CLK_PDMIN_CTRL0);
+static AUD_MST_SYS_MUX(spdifin_clk,   AUDIO_CLK_SPDIFIN_CTRL);
+static AUD_MST_SYS_MUX(pdm_sysclk,    AUDIO_CLK_PDMIN_CTRL1);
+static AUD_MST_MCLK_MUX(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL);
+
+#define AUD_MST_DIV(_name, _reg, _flag)                                \
+       AUD_DIV(_name##_div, _reg, 0, 16, _flag,                \
+                   "aud_"#_name"_sel", CLK_SET_RATE_PARENT)    \
+
+#define AUD_MST_MCLK_DIV(_name, _reg)                          \
+       AUD_MST_DIV(_name, _reg, CLK_DIVIDER_ROUND_CLOSEST)
+
+#define AUD_MST_SYS_DIV(_name, _reg)                           \
+       AUD_MST_DIV(_name, _reg, 0)
+
+static AUD_MST_MCLK_DIV(mst_a_mclk,   AUDIO_MCLK_A_CTRL);
+static AUD_MST_MCLK_DIV(mst_b_mclk,   AUDIO_MCLK_B_CTRL);
+static AUD_MST_MCLK_DIV(mst_c_mclk,   AUDIO_MCLK_C_CTRL);
+static AUD_MST_MCLK_DIV(mst_d_mclk,   AUDIO_MCLK_D_CTRL);
+static AUD_MST_MCLK_DIV(mst_e_mclk,   AUDIO_MCLK_E_CTRL);
+static AUD_MST_MCLK_DIV(mst_f_mclk,   AUDIO_MCLK_F_CTRL);
+static AUD_MST_MCLK_DIV(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
+static AUD_MST_MCLK_DIV(pdm_dclk,     AUDIO_CLK_PDMIN_CTRL0);
+static AUD_MST_SYS_DIV(spdifin_clk,   AUDIO_CLK_SPDIFIN_CTRL);
+static AUD_MST_SYS_DIV(pdm_sysclk,    AUDIO_CLK_PDMIN_CTRL1);
+static AUD_MST_MCLK_DIV(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL);
+
+#define AUD_MST_MCLK_GATE(_name, _reg)                         \
+       AUD_GATE(_name, _reg, 31,  "aud_"#_name"_div",  \
+                CLK_SET_RATE_PARENT)
+
+static AUD_MST_MCLK_GATE(mst_a_mclk,   AUDIO_MCLK_A_CTRL);
+static AUD_MST_MCLK_GATE(mst_b_mclk,   AUDIO_MCLK_B_CTRL);
+static AUD_MST_MCLK_GATE(mst_c_mclk,   AUDIO_MCLK_C_CTRL);
+static AUD_MST_MCLK_GATE(mst_d_mclk,   AUDIO_MCLK_D_CTRL);
+static AUD_MST_MCLK_GATE(mst_e_mclk,   AUDIO_MCLK_E_CTRL);
+static AUD_MST_MCLK_GATE(mst_f_mclk,   AUDIO_MCLK_F_CTRL);
+static AUD_MST_MCLK_GATE(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
+static AUD_MST_MCLK_GATE(spdifin_clk,  AUDIO_CLK_SPDIFIN_CTRL);
+static AUD_MST_MCLK_GATE(pdm_dclk,     AUDIO_CLK_PDMIN_CTRL0);
+static AUD_MST_MCLK_GATE(pdm_sysclk,   AUDIO_CLK_PDMIN_CTRL1);
+static AUD_MST_MCLK_GATE(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL);
 
 /* Sample Clocks */
-#define AXG_MST_SCLK_PRE_EN(_name, _reg)                       \
-       AXG_AUD_GATE(mst_##_name##_sclk_pre_en, _reg, 31,       \
-                    "axg_mst_"#_name"_mclk", 0)
-
-static AXG_MST_SCLK_PRE_EN(a, AUDIO_MST_A_SCLK_CTRL0);
-static AXG_MST_SCLK_PRE_EN(b, AUDIO_MST_B_SCLK_CTRL0);
-static AXG_MST_SCLK_PRE_EN(c, AUDIO_MST_C_SCLK_CTRL0);
-static AXG_MST_SCLK_PRE_EN(d, AUDIO_MST_D_SCLK_CTRL0);
-static AXG_MST_SCLK_PRE_EN(e, AUDIO_MST_E_SCLK_CTRL0);
-static AXG_MST_SCLK_PRE_EN(f, AUDIO_MST_F_SCLK_CTRL0);
-
-#define AXG_AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width,          \
+#define AUD_MST_SCLK_PRE_EN(_name, _reg)                       \
+       AUD_GATE(mst_##_name##_sclk_pre_en, _reg, 31,           \
+                "aud_mst_"#_name"_mclk", 0)
+
+static AUD_MST_SCLK_PRE_EN(a, AUDIO_MST_A_SCLK_CTRL0);
+static AUD_MST_SCLK_PRE_EN(b, AUDIO_MST_B_SCLK_CTRL0);
+static AUD_MST_SCLK_PRE_EN(c, AUDIO_MST_C_SCLK_CTRL0);
+static AUD_MST_SCLK_PRE_EN(d, AUDIO_MST_D_SCLK_CTRL0);
+static AUD_MST_SCLK_PRE_EN(e, AUDIO_MST_E_SCLK_CTRL0);
+static AUD_MST_SCLK_PRE_EN(f, AUDIO_MST_F_SCLK_CTRL0);
+
+#define AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width,              \
                         _hi_shift, _hi_width, _pname, _iflags)         \
-struct clk_regmap axg_##_name = {                                      \
+struct clk_regmap aud_##_name = {                                      \
        .data = &(struct meson_sclk_div_data) {                         \
                .div = {                                                \
                        .reg_off = (_reg),                              \
@@ -189,7 +193,7 @@ struct clk_regmap axg_##_name = {                                   \
                },                                                      \
        },                                                              \
        .hw.init = &(struct clk_init_data) {                            \
-               .name = "axg_"#_name,                                   \
+               .name = "aud_"#_name,                                   \
                .ops = &meson_sclk_div_ops,                             \
                .parent_names = (const char *[]) { _pname },            \
                .num_parents = 1,                                       \
@@ -197,32 +201,32 @@ struct clk_regmap axg_##_name = {                                 \
        },                                                              \
 }
 
-#define AXG_MST_SCLK_DIV(_name, _reg)                                  \
-       AXG_AUD_SCLK_DIV(mst_##_name##_sclk_div, _reg, 20, 10, 0, 0,    \
-                        "axg_mst_"#_name"_sclk_pre_en",                \
-                        CLK_SET_RATE_PARENT)
-
-static AXG_MST_SCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0);
-static AXG_MST_SCLK_DIV(b, AUDIO_MST_B_SCLK_CTRL0);
-static AXG_MST_SCLK_DIV(c, AUDIO_MST_C_SCLK_CTRL0);
-static AXG_MST_SCLK_DIV(d, AUDIO_MST_D_SCLK_CTRL0);
-static AXG_MST_SCLK_DIV(e, AUDIO_MST_E_SCLK_CTRL0);
-static AXG_MST_SCLK_DIV(f, AUDIO_MST_F_SCLK_CTRL0);
-
-#define AXG_MST_SCLK_POST_EN(_name, _reg)                              \
-       AXG_AUD_GATE(mst_##_name##_sclk_post_en, _reg, 30,              \
-                    "axg_mst_"#_name"_sclk_div", CLK_SET_RATE_PARENT)
-
-static AXG_MST_SCLK_POST_EN(a, AUDIO_MST_A_SCLK_CTRL0);
-static AXG_MST_SCLK_POST_EN(b, AUDIO_MST_B_SCLK_CTRL0);
-static AXG_MST_SCLK_POST_EN(c, AUDIO_MST_C_SCLK_CTRL0);
-static AXG_MST_SCLK_POST_EN(d, AUDIO_MST_D_SCLK_CTRL0);
-static AXG_MST_SCLK_POST_EN(e, AUDIO_MST_E_SCLK_CTRL0);
-static AXG_MST_SCLK_POST_EN(f, AUDIO_MST_F_SCLK_CTRL0);
-
-#define AXG_AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2, \
+#define AUD_MST_SCLK_DIV(_name, _reg)                                  \
+       AUD_SCLK_DIV(mst_##_name##_sclk_div, _reg, 20, 10, 0, 0,        \
+                    "aud_mst_"#_name"_sclk_pre_en",                    \
+                    CLK_SET_RATE_PARENT)
+
+static AUD_MST_SCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0);
+static AUD_MST_SCLK_DIV(b, AUDIO_MST_B_SCLK_CTRL0);
+static AUD_MST_SCLK_DIV(c, AUDIO_MST_C_SCLK_CTRL0);
+static AUD_MST_SCLK_DIV(d, AUDIO_MST_D_SCLK_CTRL0);
+static AUD_MST_SCLK_DIV(e, AUDIO_MST_E_SCLK_CTRL0);
+static AUD_MST_SCLK_DIV(f, AUDIO_MST_F_SCLK_CTRL0);
+
+#define AUD_MST_SCLK_POST_EN(_name, _reg)                              \
+       AUD_GATE(mst_##_name##_sclk_post_en, _reg, 30,          \
+                "aud_mst_"#_name"_sclk_div", CLK_SET_RATE_PARENT)
+
+static AUD_MST_SCLK_POST_EN(a, AUDIO_MST_A_SCLK_CTRL0);
+static AUD_MST_SCLK_POST_EN(b, AUDIO_MST_B_SCLK_CTRL0);
+static AUD_MST_SCLK_POST_EN(c, AUDIO_MST_C_SCLK_CTRL0);
+static AUD_MST_SCLK_POST_EN(d, AUDIO_MST_D_SCLK_CTRL0);
+static AUD_MST_SCLK_POST_EN(e, AUDIO_MST_E_SCLK_CTRL0);
+static AUD_MST_SCLK_POST_EN(f, AUDIO_MST_F_SCLK_CTRL0);
+
+#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2, \
                         _pname, _iflags)                               \
-struct clk_regmap axg_##_name = {                                      \
+struct clk_regmap aud_##_name = {                                      \
        .data = &(struct meson_clk_triphase_data) {                     \
                .ph0 = {                                                \
                        .reg_off = (_reg),                              \
@@ -241,7 +245,7 @@ struct clk_regmap axg_##_name = {                                   \
                },                                                      \
        },                                                              \
        .hw.init = &(struct clk_init_data) {                            \
-               .name = "axg_"#_name,                                   \
+               .name = "aud_"#_name,                                   \
                .ops = &meson_clk_triphase_ops,                         \
                .parent_names = (const char *[]) { _pname },            \
                .num_parents = 1,                                       \
@@ -249,87 +253,87 @@ struct clk_regmap axg_##_name = {                                 \
        },                                                              \
 }
 
-#define AXG_MST_SCLK(_name, _reg)                                      \
-       AXG_AUD_TRIPHASE(mst_##_name##_sclk, _reg, 1, 0, 2, 4,          \
-                        "axg_mst_"#_name"_sclk_post_en", CLK_SET_RATE_PARENT)
-
-static AXG_MST_SCLK(a, AUDIO_MST_A_SCLK_CTRL1);
-static AXG_MST_SCLK(b, AUDIO_MST_B_SCLK_CTRL1);
-static AXG_MST_SCLK(c, AUDIO_MST_C_SCLK_CTRL1);
-static AXG_MST_SCLK(d, AUDIO_MST_D_SCLK_CTRL1);
-static AXG_MST_SCLK(e, AUDIO_MST_E_SCLK_CTRL1);
-static AXG_MST_SCLK(f, AUDIO_MST_F_SCLK_CTRL1);
-
-#define AXG_MST_LRCLK_DIV(_name, _reg)                                 \
-       AXG_AUD_SCLK_DIV(mst_##_name##_lrclk_div, _reg, 0, 10, 10, 10,  \
-                   "axg_mst_"#_name"_sclk_post_en", 0)                 \
-
-static AXG_MST_LRCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0);
-static AXG_MST_LRCLK_DIV(b, AUDIO_MST_B_SCLK_CTRL0);
-static AXG_MST_LRCLK_DIV(c, AUDIO_MST_C_SCLK_CTRL0);
-static AXG_MST_LRCLK_DIV(d, AUDIO_MST_D_SCLK_CTRL0);
-static AXG_MST_LRCLK_DIV(e, AUDIO_MST_E_SCLK_CTRL0);
-static AXG_MST_LRCLK_DIV(f, AUDIO_MST_F_SCLK_CTRL0);
-
-#define AXG_MST_LRCLK(_name, _reg)                                     \
-       AXG_AUD_TRIPHASE(mst_##_name##_lrclk, _reg, 1, 1, 3, 5,         \
-                        "axg_mst_"#_name"_lrclk_div", CLK_SET_RATE_PARENT)
-
-static AXG_MST_LRCLK(a, AUDIO_MST_A_SCLK_CTRL1);
-static AXG_MST_LRCLK(b, AUDIO_MST_B_SCLK_CTRL1);
-static AXG_MST_LRCLK(c, AUDIO_MST_C_SCLK_CTRL1);
-static AXG_MST_LRCLK(d, AUDIO_MST_D_SCLK_CTRL1);
-static AXG_MST_LRCLK(e, AUDIO_MST_E_SCLK_CTRL1);
-static AXG_MST_LRCLK(f, AUDIO_MST_F_SCLK_CTRL1);
+#define AUD_MST_SCLK(_name, _reg)                                      \
+       AUD_TRIPHASE(mst_##_name##_sclk, _reg, 1, 0, 2, 4,              \
+                    "aud_mst_"#_name"_sclk_post_en", CLK_SET_RATE_PARENT)
+
+static AUD_MST_SCLK(a, AUDIO_MST_A_SCLK_CTRL1);
+static AUD_MST_SCLK(b, AUDIO_MST_B_SCLK_CTRL1);
+static AUD_MST_SCLK(c, AUDIO_MST_C_SCLK_CTRL1);
+static AUD_MST_SCLK(d, AUDIO_MST_D_SCLK_CTRL1);
+static AUD_MST_SCLK(e, AUDIO_MST_E_SCLK_CTRL1);
+static AUD_MST_SCLK(f, AUDIO_MST_F_SCLK_CTRL1);
+
+#define AUD_MST_LRCLK_DIV(_name, _reg)                                 \
+       AUD_SCLK_DIV(mst_##_name##_lrclk_div, _reg, 0, 10, 10, 10,      \
+                    "aud_mst_"#_name"_sclk_post_en", 0)                \
+
+static AUD_MST_LRCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0);
+static AUD_MST_LRCLK_DIV(b, AUDIO_MST_B_SCLK_CTRL0);
+static AUD_MST_LRCLK_DIV(c, AUDIO_MST_C_SCLK_CTRL0);
+static AUD_MST_LRCLK_DIV(d, AUDIO_MST_D_SCLK_CTRL0);
+static AUD_MST_LRCLK_DIV(e, AUDIO_MST_E_SCLK_CTRL0);
+static AUD_MST_LRCLK_DIV(f, AUDIO_MST_F_SCLK_CTRL0);
+
+#define AUD_MST_LRCLK(_name, _reg)                                     \
+       AUD_TRIPHASE(mst_##_name##_lrclk, _reg, 1, 1, 3, 5,             \
+                    "aud_mst_"#_name"_lrclk_div", CLK_SET_RATE_PARENT)
+
+static AUD_MST_LRCLK(a, AUDIO_MST_A_SCLK_CTRL1);
+static AUD_MST_LRCLK(b, AUDIO_MST_B_SCLK_CTRL1);
+static AUD_MST_LRCLK(c, AUDIO_MST_C_SCLK_CTRL1);
+static AUD_MST_LRCLK(d, AUDIO_MST_D_SCLK_CTRL1);
+static AUD_MST_LRCLK(e, AUDIO_MST_E_SCLK_CTRL1);
+static AUD_MST_LRCLK(f, AUDIO_MST_F_SCLK_CTRL1);
 
 static const char * const tdm_sclk_parent_names[] = {
-       "axg_mst_a_sclk", "axg_mst_b_sclk", "axg_mst_c_sclk",
-       "axg_mst_d_sclk", "axg_mst_e_sclk", "axg_mst_f_sclk",
-       "axg_slv_sclk0", "axg_slv_sclk1", "axg_slv_sclk2",
-       "axg_slv_sclk3", "axg_slv_sclk4", "axg_slv_sclk5",
-       "axg_slv_sclk6", "axg_slv_sclk7", "axg_slv_sclk8",
-       "axg_slv_sclk9"
+       "aud_mst_a_sclk", "aud_mst_b_sclk", "aud_mst_c_sclk",
+       "aud_mst_d_sclk", "aud_mst_e_sclk", "aud_mst_f_sclk",
+       "aud_slv_sclk0", "aud_slv_sclk1", "aud_slv_sclk2",
+       "aud_slv_sclk3", "aud_slv_sclk4", "aud_slv_sclk5",
+       "aud_slv_sclk6", "aud_slv_sclk7", "aud_slv_sclk8",
+       "aud_slv_sclk9"
 };
 
-#define AXG_TDM_SCLK_MUX(_name, _reg)                          \
-       AXG_AUD_MUX(tdm##_name##_sclk_sel, _reg, 0xf, 24,       \
+#define AUD_TDM_SCLK_MUX(_name, _reg)                          \
+       AUD_MUX(tdm##_name##_sclk_sel, _reg, 0xf, 24,           \
                    CLK_MUX_ROUND_CLOSEST,                      \
                    tdm_sclk_parent_names, 0)
 
-static AXG_TDM_SCLK_MUX(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
-static AXG_TDM_SCLK_MUX(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
-static AXG_TDM_SCLK_MUX(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
-static AXG_TDM_SCLK_MUX(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
-static AXG_TDM_SCLK_MUX(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
-static AXG_TDM_SCLK_MUX(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
-static AXG_TDM_SCLK_MUX(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
-
-#define AXG_TDM_SCLK_PRE_EN(_name, _reg)                               \
-       AXG_AUD_GATE(tdm##_name##_sclk_pre_en, _reg, 31,                \
-                    "axg_tdm"#_name"_sclk_sel", CLK_SET_RATE_PARENT)
-
-static AXG_TDM_SCLK_PRE_EN(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
-static AXG_TDM_SCLK_PRE_EN(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
-static AXG_TDM_SCLK_PRE_EN(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
-static AXG_TDM_SCLK_PRE_EN(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
-static AXG_TDM_SCLK_PRE_EN(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
-static AXG_TDM_SCLK_PRE_EN(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
-static AXG_TDM_SCLK_PRE_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
-
-#define AXG_TDM_SCLK_POST_EN(_name, _reg)                              \
-       AXG_AUD_GATE(tdm##_name##_sclk_post_en, _reg, 30,               \
-                    "axg_tdm"#_name"_sclk_pre_en", CLK_SET_RATE_PARENT)
-
-static AXG_TDM_SCLK_POST_EN(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
-static AXG_TDM_SCLK_POST_EN(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
-static AXG_TDM_SCLK_POST_EN(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
-static AXG_TDM_SCLK_POST_EN(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
-static AXG_TDM_SCLK_POST_EN(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
-static AXG_TDM_SCLK_POST_EN(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
-static AXG_TDM_SCLK_POST_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
-
-#define AXG_TDM_SCLK(_name, _reg)                                      \
-       struct clk_regmap axg_tdm##_name##_sclk = {                     \
+static AUD_TDM_SCLK_MUX(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
+static AUD_TDM_SCLK_MUX(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
+static AUD_TDM_SCLK_MUX(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
+static AUD_TDM_SCLK_MUX(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
+static AUD_TDM_SCLK_MUX(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
+static AUD_TDM_SCLK_MUX(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
+static AUD_TDM_SCLK_MUX(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
+
+#define AUD_TDM_SCLK_PRE_EN(_name, _reg)                               \
+       AUD_GATE(tdm##_name##_sclk_pre_en, _reg, 31,                    \
+                "aud_tdm"#_name"_sclk_sel", CLK_SET_RATE_PARENT)
+
+static AUD_TDM_SCLK_PRE_EN(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
+static AUD_TDM_SCLK_PRE_EN(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
+static AUD_TDM_SCLK_PRE_EN(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
+static AUD_TDM_SCLK_PRE_EN(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
+static AUD_TDM_SCLK_PRE_EN(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
+static AUD_TDM_SCLK_PRE_EN(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
+static AUD_TDM_SCLK_PRE_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
+
+#define AUD_TDM_SCLK_POST_EN(_name, _reg)                              \
+       AUD_GATE(tdm##_name##_sclk_post_en, _reg, 30,                   \
+                "aud_tdm"#_name"_sclk_pre_en", CLK_SET_RATE_PARENT)
+
+static AUD_TDM_SCLK_POST_EN(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
+static AUD_TDM_SCLK_POST_EN(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
+static AUD_TDM_SCLK_POST_EN(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
+static AUD_TDM_SCLK_POST_EN(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
+static AUD_TDM_SCLK_POST_EN(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
+static AUD_TDM_SCLK_POST_EN(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
+static AUD_TDM_SCLK_POST_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
+
+#define AUD_TDM_SCLK(_name, _reg)                                      \
+       struct clk_regmap aud_tdm##_name##_sclk = {                     \
        .data = &(struct meson_clk_phase_data) {                        \
                .ph = {                                                 \
                        .reg_off = (_reg),                              \
@@ -338,44 +342,83 @@ static AXG_TDM_SCLK_POST_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
                },                                                      \
        },                                                              \
        .hw.init = &(struct clk_init_data) {                            \
-               .name = "axg_tdm"#_name"_sclk",                         \
+               .name = "aud_tdm"#_name"_sclk",                         \
                .ops = &meson_clk_phase_ops,                            \
                .parent_names = (const char *[])                        \
-               { "axg_tdm"#_name"_sclk_post_en" },                     \
+               { "aud_tdm"#_name"_sclk_post_en" },                     \
                .num_parents = 1,                                       \
                .flags = CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT,   \
        },                                                              \
 }
 
-static AXG_TDM_SCLK(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
-static AXG_TDM_SCLK(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
-static AXG_TDM_SCLK(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
-static AXG_TDM_SCLK(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
-static AXG_TDM_SCLK(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
-static AXG_TDM_SCLK(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
-static AXG_TDM_SCLK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
+static AUD_TDM_SCLK(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
+static AUD_TDM_SCLK(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
+static AUD_TDM_SCLK(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
+static AUD_TDM_SCLK(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
+static AUD_TDM_SCLK(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
+static AUD_TDM_SCLK(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
+static AUD_TDM_SCLK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
 
 static const char * const tdm_lrclk_parent_names[] = {
-       "axg_mst_a_lrclk", "axg_mst_b_lrclk", "axg_mst_c_lrclk",
-       "axg_mst_d_lrclk", "axg_mst_e_lrclk", "axg_mst_f_lrclk",
-       "axg_slv_lrclk0", "axg_slv_lrclk1", "axg_slv_lrclk2",
-       "axg_slv_lrclk3", "axg_slv_lrclk4", "axg_slv_lrclk5",
-       "axg_slv_lrclk6", "axg_slv_lrclk7", "axg_slv_lrclk8",
-       "axg_slv_lrclk9"
+       "aud_mst_a_lrclk", "aud_mst_b_lrclk", "aud_mst_c_lrclk",
+       "aud_mst_d_lrclk", "aud_mst_e_lrclk", "aud_mst_f_lrclk",
+       "aud_slv_lrclk0", "aud_slv_lrclk1", "aud_slv_lrclk2",
+       "aud_slv_lrclk3", "aud_slv_lrclk4", "aud_slv_lrclk5",
+       "aud_slv_lrclk6", "aud_slv_lrclk7", "aud_slv_lrclk8",
+       "aud_slv_lrclk9"
 };
 
-#define AXG_TDM_LRLCK(_name, _reg)                    \
-       AXG_AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20, \
-                   CLK_MUX_ROUND_CLOSEST,             \
-                   tdm_lrclk_parent_names, 0)
+#define AUD_TDM_LRLCK(_name, _reg)                    \
+       AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20,     \
+               CLK_MUX_ROUND_CLOSEST,                 \
+               tdm_lrclk_parent_names, 0)
+
+static AUD_TDM_LRLCK(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
+static AUD_TDM_LRLCK(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
+static AUD_TDM_LRLCK(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
+static AUD_TDM_LRLCK(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
+static AUD_TDM_LRLCK(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
+static AUD_TDM_LRLCK(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
+static AUD_TDM_LRLCK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
+
+/* G12a Pad control */
+#define AUD_TDM_PAD_CTRL(_name, _reg, _shift, _parents)                \
+       AUD_MUX(tdm_##_name, _reg, 0x7, _shift, 0, _parents,    \
+               CLK_SET_RATE_NO_REPARENT)
+
+static const char * const mclk_pad_ctrl_parent_names[] = {
+       "aud_mst_a_mclk", "aud_mst_b_mclk", "aud_mst_c_mclk",
+       "aud_mst_d_mclk", "aud_mst_e_mclk", "aud_mst_f_mclk",
+};
+
+static AUD_TDM_PAD_CTRL(mclk_pad_0, AUDIO_MST_PAD_CTRL0, 0,
+                       mclk_pad_ctrl_parent_names);
+static AUD_TDM_PAD_CTRL(mclk_pad_1, AUDIO_MST_PAD_CTRL0, 4,
+                       mclk_pad_ctrl_parent_names);
+
+static const char * const lrclk_pad_ctrl_parent_names[] = {
+       "aud_mst_a_lrclk", "aud_mst_b_lrclk", "aud_mst_c_lrclk",
+       "aud_mst_d_lrclk", "aud_mst_e_lrclk", "aud_mst_f_lrclk",
+};
 
-static AXG_TDM_LRLCK(in_a,  AUDIO_CLK_TDMIN_A_CTRL);
-static AXG_TDM_LRLCK(in_b,  AUDIO_CLK_TDMIN_B_CTRL);
-static AXG_TDM_LRLCK(in_c,  AUDIO_CLK_TDMIN_C_CTRL);
-static AXG_TDM_LRLCK(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
-static AXG_TDM_LRLCK(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
-static AXG_TDM_LRLCK(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
-static AXG_TDM_LRLCK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
+static AUD_TDM_PAD_CTRL(lrclk_pad_0, AUDIO_MST_PAD_CTRL1, 16,
+                       lrclk_pad_ctrl_parent_names);
+static AUD_TDM_PAD_CTRL(lrclk_pad_1, AUDIO_MST_PAD_CTRL1, 20,
+                       lrclk_pad_ctrl_parent_names);
+static AUD_TDM_PAD_CTRL(lrclk_pad_2, AUDIO_MST_PAD_CTRL1, 24,
+                       lrclk_pad_ctrl_parent_names);
+
+static const char * const sclk_pad_ctrl_parent_names[] = {
+       "aud_mst_a_sclk", "aud_mst_b_sclk", "aud_mst_c_sclk",
+       "aud_mst_d_sclk", "aud_mst_e_sclk", "aud_mst_f_sclk",
+};
+
+static AUD_TDM_PAD_CTRL(sclk_pad_0, AUDIO_MST_PAD_CTRL1, 0,
+                       sclk_pad_ctrl_parent_names);
+static AUD_TDM_PAD_CTRL(sclk_pad_1, AUDIO_MST_PAD_CTRL1, 4,
+                       sclk_pad_ctrl_parent_names);
+static AUD_TDM_PAD_CTRL(sclk_pad_2, AUDIO_MST_PAD_CTRL1, 8,
+                       sclk_pad_ctrl_parent_names);
 
 /*
  * Array of all clocks provided by this provider
@@ -383,255 +426,416 @@ static AXG_TDM_LRLCK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
  */
 static struct clk_hw_onecell_data axg_audio_hw_onecell_data = {
        .hws = {
-               [AUD_CLKID_DDR_ARB]             = &axg_ddr_arb.hw,
-               [AUD_CLKID_PDM]                 = &axg_pdm.hw,
-               [AUD_CLKID_TDMIN_A]             = &axg_tdmin_a.hw,
-               [AUD_CLKID_TDMIN_B]             = &axg_tdmin_b.hw,
-               [AUD_CLKID_TDMIN_C]             = &axg_tdmin_c.hw,
-               [AUD_CLKID_TDMIN_LB]            = &axg_tdmin_lb.hw,
-               [AUD_CLKID_TDMOUT_A]            = &axg_tdmout_a.hw,
-               [AUD_CLKID_TDMOUT_B]            = &axg_tdmout_b.hw,
-               [AUD_CLKID_TDMOUT_C]            = &axg_tdmout_c.hw,
-               [AUD_CLKID_FRDDR_A]             = &axg_frddr_a.hw,
-               [AUD_CLKID_FRDDR_B]             = &axg_frddr_b.hw,
-               [AUD_CLKID_FRDDR_C]             = &axg_frddr_c.hw,
-               [AUD_CLKID_TODDR_A]             = &axg_toddr_a.hw,
-               [AUD_CLKID_TODDR_B]             = &axg_toddr_b.hw,
-               [AUD_CLKID_TODDR_C]             = &axg_toddr_c.hw,
-               [AUD_CLKID_LOOPBACK]            = &axg_loopback.hw,
-               [AUD_CLKID_SPDIFIN]             = &axg_spdifin.hw,
-               [AUD_CLKID_SPDIFOUT]            = &axg_spdifout.hw,
-               [AUD_CLKID_RESAMPLE]            = &axg_resample.hw,
-               [AUD_CLKID_POWER_DETECT]        = &axg_power_detect.hw,
-               [AUD_CLKID_MST_A_MCLK_SEL]      = &axg_mst_a_mclk_sel.hw,
-               [AUD_CLKID_MST_B_MCLK_SEL]      = &axg_mst_b_mclk_sel.hw,
-               [AUD_CLKID_MST_C_MCLK_SEL]      = &axg_mst_c_mclk_sel.hw,
-               [AUD_CLKID_MST_D_MCLK_SEL]      = &axg_mst_d_mclk_sel.hw,
-               [AUD_CLKID_MST_E_MCLK_SEL]      = &axg_mst_e_mclk_sel.hw,
-               [AUD_CLKID_MST_F_MCLK_SEL]      = &axg_mst_f_mclk_sel.hw,
-               [AUD_CLKID_MST_A_MCLK_DIV]      = &axg_mst_a_mclk_div.hw,
-               [AUD_CLKID_MST_B_MCLK_DIV]      = &axg_mst_b_mclk_div.hw,
-               [AUD_CLKID_MST_C_MCLK_DIV]      = &axg_mst_c_mclk_div.hw,
-               [AUD_CLKID_MST_D_MCLK_DIV]      = &axg_mst_d_mclk_div.hw,
-               [AUD_CLKID_MST_E_MCLK_DIV]      = &axg_mst_e_mclk_div.hw,
-               [AUD_CLKID_MST_F_MCLK_DIV]      = &axg_mst_f_mclk_div.hw,
-               [AUD_CLKID_MST_A_MCLK]          = &axg_mst_a_mclk.hw,
-               [AUD_CLKID_MST_B_MCLK]          = &axg_mst_b_mclk.hw,
-               [AUD_CLKID_MST_C_MCLK]          = &axg_mst_c_mclk.hw,
-               [AUD_CLKID_MST_D_MCLK]          = &axg_mst_d_mclk.hw,
-               [AUD_CLKID_MST_E_MCLK]          = &axg_mst_e_mclk.hw,
-               [AUD_CLKID_MST_F_MCLK]          = &axg_mst_f_mclk.hw,
-               [AUD_CLKID_SPDIFOUT_CLK_SEL]    = &axg_spdifout_clk_sel.hw,
-               [AUD_CLKID_SPDIFOUT_CLK_DIV]    = &axg_spdifout_clk_div.hw,
-               [AUD_CLKID_SPDIFOUT_CLK]        = &axg_spdifout_clk.hw,
-               [AUD_CLKID_SPDIFIN_CLK_SEL]     = &axg_spdifin_clk_sel.hw,
-               [AUD_CLKID_SPDIFIN_CLK_DIV]     = &axg_spdifin_clk_div.hw,
-               [AUD_CLKID_SPDIFIN_CLK]         = &axg_spdifin_clk.hw,
-               [AUD_CLKID_PDM_DCLK_SEL]        = &axg_pdm_dclk_sel.hw,
-               [AUD_CLKID_PDM_DCLK_DIV]        = &axg_pdm_dclk_div.hw,
-               [AUD_CLKID_PDM_DCLK]            = &axg_pdm_dclk.hw,
-               [AUD_CLKID_PDM_SYSCLK_SEL]      = &axg_pdm_sysclk_sel.hw,
-               [AUD_CLKID_PDM_SYSCLK_DIV]      = &axg_pdm_sysclk_div.hw,
-               [AUD_CLKID_PDM_SYSCLK]          = &axg_pdm_sysclk.hw,
-               [AUD_CLKID_MST_A_SCLK_PRE_EN]   = &axg_mst_a_sclk_pre_en.hw,
-               [AUD_CLKID_MST_B_SCLK_PRE_EN]   = &axg_mst_b_sclk_pre_en.hw,
-               [AUD_CLKID_MST_C_SCLK_PRE_EN]   = &axg_mst_c_sclk_pre_en.hw,
-               [AUD_CLKID_MST_D_SCLK_PRE_EN]   = &axg_mst_d_sclk_pre_en.hw,
-               [AUD_CLKID_MST_E_SCLK_PRE_EN]   = &axg_mst_e_sclk_pre_en.hw,
-               [AUD_CLKID_MST_F_SCLK_PRE_EN]   = &axg_mst_f_sclk_pre_en.hw,
-               [AUD_CLKID_MST_A_SCLK_DIV]      = &axg_mst_a_sclk_div.hw,
-               [AUD_CLKID_MST_B_SCLK_DIV]      = &axg_mst_b_sclk_div.hw,
-               [AUD_CLKID_MST_C_SCLK_DIV]      = &axg_mst_c_sclk_div.hw,
-               [AUD_CLKID_MST_D_SCLK_DIV]      = &axg_mst_d_sclk_div.hw,
-               [AUD_CLKID_MST_E_SCLK_DIV]      = &axg_mst_e_sclk_div.hw,
-               [AUD_CLKID_MST_F_SCLK_DIV]      = &axg_mst_f_sclk_div.hw,
-               [AUD_CLKID_MST_A_SCLK_POST_EN]  = &axg_mst_a_sclk_post_en.hw,
-               [AUD_CLKID_MST_B_SCLK_POST_EN]  = &axg_mst_b_sclk_post_en.hw,
-               [AUD_CLKID_MST_C_SCLK_POST_EN]  = &axg_mst_c_sclk_post_en.hw,
-               [AUD_CLKID_MST_D_SCLK_POST_EN]  = &axg_mst_d_sclk_post_en.hw,
-               [AUD_CLKID_MST_E_SCLK_POST_EN]  = &axg_mst_e_sclk_post_en.hw,
-               [AUD_CLKID_MST_F_SCLK_POST_EN]  = &axg_mst_f_sclk_post_en.hw,
-               [AUD_CLKID_MST_A_SCLK]          = &axg_mst_a_sclk.hw,
-               [AUD_CLKID_MST_B_SCLK]          = &axg_mst_b_sclk.hw,
-               [AUD_CLKID_MST_C_SCLK]          = &axg_mst_c_sclk.hw,
-               [AUD_CLKID_MST_D_SCLK]          = &axg_mst_d_sclk.hw,
-               [AUD_CLKID_MST_E_SCLK]          = &axg_mst_e_sclk.hw,
-               [AUD_CLKID_MST_F_SCLK]          = &axg_mst_f_sclk.hw,
-               [AUD_CLKID_MST_A_LRCLK_DIV]     = &axg_mst_a_lrclk_div.hw,
-               [AUD_CLKID_MST_B_LRCLK_DIV]     = &axg_mst_b_lrclk_div.hw,
-               [AUD_CLKID_MST_C_LRCLK_DIV]     = &axg_mst_c_lrclk_div.hw,
-               [AUD_CLKID_MST_D_LRCLK_DIV]     = &axg_mst_d_lrclk_div.hw,
-               [AUD_CLKID_MST_E_LRCLK_DIV]     = &axg_mst_e_lrclk_div.hw,
-               [AUD_CLKID_MST_F_LRCLK_DIV]     = &axg_mst_f_lrclk_div.hw,
-               [AUD_CLKID_MST_A_LRCLK]         = &axg_mst_a_lrclk.hw,
-               [AUD_CLKID_MST_B_LRCLK]         = &axg_mst_b_lrclk.hw,
-               [AUD_CLKID_MST_C_LRCLK]         = &axg_mst_c_lrclk.hw,
-               [AUD_CLKID_MST_D_LRCLK]         = &axg_mst_d_lrclk.hw,
-               [AUD_CLKID_MST_E_LRCLK]         = &axg_mst_e_lrclk.hw,
-               [AUD_CLKID_MST_F_LRCLK]         = &axg_mst_f_lrclk.hw,
-               [AUD_CLKID_TDMIN_A_SCLK_SEL]    = &axg_tdmin_a_sclk_sel.hw,
-               [AUD_CLKID_TDMIN_B_SCLK_SEL]    = &axg_tdmin_b_sclk_sel.hw,
-               [AUD_CLKID_TDMIN_C_SCLK_SEL]    = &axg_tdmin_c_sclk_sel.hw,
-               [AUD_CLKID_TDMIN_LB_SCLK_SEL]   = &axg_tdmin_lb_sclk_sel.hw,
-               [AUD_CLKID_TDMOUT_A_SCLK_SEL]   = &axg_tdmout_a_sclk_sel.hw,
-               [AUD_CLKID_TDMOUT_B_SCLK_SEL]   = &axg_tdmout_b_sclk_sel.hw,
-               [AUD_CLKID_TDMOUT_C_SCLK_SEL]   = &axg_tdmout_c_sclk_sel.hw,
-               [AUD_CLKID_TDMIN_A_SCLK_PRE_EN] = &axg_tdmin_a_sclk_pre_en.hw,
-               [AUD_CLKID_TDMIN_B_SCLK_PRE_EN] = &axg_tdmin_b_sclk_pre_en.hw,
-               [AUD_CLKID_TDMIN_C_SCLK_PRE_EN] = &axg_tdmin_c_sclk_pre_en.hw,
-               [AUD_CLKID_TDMIN_LB_SCLK_PRE_EN] = &axg_tdmin_lb_sclk_pre_en.hw,
-               [AUD_CLKID_TDMOUT_A_SCLK_PRE_EN] = &axg_tdmout_a_sclk_pre_en.hw,
-               [AUD_CLKID_TDMOUT_B_SCLK_PRE_EN] = &axg_tdmout_b_sclk_pre_en.hw,
-               [AUD_CLKID_TDMOUT_C_SCLK_PRE_EN] = &axg_tdmout_c_sclk_pre_en.hw,
-               [AUD_CLKID_TDMIN_A_SCLK_POST_EN] = &axg_tdmin_a_sclk_post_en.hw,
-               [AUD_CLKID_TDMIN_B_SCLK_POST_EN] = &axg_tdmin_b_sclk_post_en.hw,
-               [AUD_CLKID_TDMIN_C_SCLK_POST_EN] = &axg_tdmin_c_sclk_post_en.hw,
-               [AUD_CLKID_TDMIN_LB_SCLK_POST_EN] = &axg_tdmin_lb_sclk_post_en.hw,
-               [AUD_CLKID_TDMOUT_A_SCLK_POST_EN] = &axg_tdmout_a_sclk_post_en.hw,
-               [AUD_CLKID_TDMOUT_B_SCLK_POST_EN] = &axg_tdmout_b_sclk_post_en.hw,
-               [AUD_CLKID_TDMOUT_C_SCLK_POST_EN] = &axg_tdmout_c_sclk_post_en.hw,
-               [AUD_CLKID_TDMIN_A_SCLK]        = &axg_tdmin_a_sclk.hw,
-               [AUD_CLKID_TDMIN_B_SCLK]        = &axg_tdmin_b_sclk.hw,
-               [AUD_CLKID_TDMIN_C_SCLK]        = &axg_tdmin_c_sclk.hw,
-               [AUD_CLKID_TDMIN_LB_SCLK]       = &axg_tdmin_lb_sclk.hw,
-               [AUD_CLKID_TDMOUT_A_SCLK]       = &axg_tdmout_a_sclk.hw,
-               [AUD_CLKID_TDMOUT_B_SCLK]       = &axg_tdmout_b_sclk.hw,
-               [AUD_CLKID_TDMOUT_C_SCLK]       = &axg_tdmout_c_sclk.hw,
-               [AUD_CLKID_TDMIN_A_LRCLK]       = &axg_tdmin_a_lrclk.hw,
-               [AUD_CLKID_TDMIN_B_LRCLK]       = &axg_tdmin_b_lrclk.hw,
-               [AUD_CLKID_TDMIN_C_LRCLK]       = &axg_tdmin_c_lrclk.hw,
-               [AUD_CLKID_TDMIN_LB_LRCLK]      = &axg_tdmin_lb_lrclk.hw,
-               [AUD_CLKID_TDMOUT_A_LRCLK]      = &axg_tdmout_a_lrclk.hw,
-               [AUD_CLKID_TDMOUT_B_LRCLK]      = &axg_tdmout_b_lrclk.hw,
-               [AUD_CLKID_TDMOUT_C_LRCLK]      = &axg_tdmout_c_lrclk.hw,
+               [AUD_CLKID_DDR_ARB]             = &aud_ddr_arb.hw,
+               [AUD_CLKID_PDM]                 = &aud_pdm.hw,
+               [AUD_CLKID_TDMIN_A]             = &aud_tdmin_a.hw,
+               [AUD_CLKID_TDMIN_B]             = &aud_tdmin_b.hw,
+               [AUD_CLKID_TDMIN_C]             = &aud_tdmin_c.hw,
+               [AUD_CLKID_TDMIN_LB]            = &aud_tdmin_lb.hw,
+               [AUD_CLKID_TDMOUT_A]            = &aud_tdmout_a.hw,
+               [AUD_CLKID_TDMOUT_B]            = &aud_tdmout_b.hw,
+               [AUD_CLKID_TDMOUT_C]            = &aud_tdmout_c.hw,
+               [AUD_CLKID_FRDDR_A]             = &aud_frddr_a.hw,
+               [AUD_CLKID_FRDDR_B]             = &aud_frddr_b.hw,
+               [AUD_CLKID_FRDDR_C]             = &aud_frddr_c.hw,
+               [AUD_CLKID_TODDR_A]             = &aud_toddr_a.hw,
+               [AUD_CLKID_TODDR_B]             = &aud_toddr_b.hw,
+               [AUD_CLKID_TODDR_C]             = &aud_toddr_c.hw,
+               [AUD_CLKID_LOOPBACK]            = &aud_loopback.hw,
+               [AUD_CLKID_SPDIFIN]             = &aud_spdifin.hw,
+               [AUD_CLKID_SPDIFOUT]            = &aud_spdifout.hw,
+               [AUD_CLKID_RESAMPLE]            = &aud_resample.hw,
+               [AUD_CLKID_POWER_DETECT]        = &aud_power_detect.hw,
+               [AUD_CLKID_MST_A_MCLK_SEL]      = &aud_mst_a_mclk_sel.hw,
+               [AUD_CLKID_MST_B_MCLK_SEL]      = &aud_mst_b_mclk_sel.hw,
+               [AUD_CLKID_MST_C_MCLK_SEL]      = &aud_mst_c_mclk_sel.hw,
+               [AUD_CLKID_MST_D_MCLK_SEL]      = &aud_mst_d_mclk_sel.hw,
+               [AUD_CLKID_MST_E_MCLK_SEL]      = &aud_mst_e_mclk_sel.hw,
+               [AUD_CLKID_MST_F_MCLK_SEL]      = &aud_mst_f_mclk_sel.hw,
+               [AUD_CLKID_MST_A_MCLK_DIV]      = &aud_mst_a_mclk_div.hw,
+               [AUD_CLKID_MST_B_MCLK_DIV]      = &aud_mst_b_mclk_div.hw,
+               [AUD_CLKID_MST_C_MCLK_DIV]      = &aud_mst_c_mclk_div.hw,
+               [AUD_CLKID_MST_D_MCLK_DIV]      = &aud_mst_d_mclk_div.hw,
+               [AUD_CLKID_MST_E_MCLK_DIV]      = &aud_mst_e_mclk_div.hw,
+               [AUD_CLKID_MST_F_MCLK_DIV]      = &aud_mst_f_mclk_div.hw,
+               [AUD_CLKID_MST_A_MCLK]          = &aud_mst_a_mclk.hw,
+               [AUD_CLKID_MST_B_MCLK]          = &aud_mst_b_mclk.hw,
+               [AUD_CLKID_MST_C_MCLK]          = &aud_mst_c_mclk.hw,
+               [AUD_CLKID_MST_D_MCLK]          = &aud_mst_d_mclk.hw,
+               [AUD_CLKID_MST_E_MCLK]          = &aud_mst_e_mclk.hw,
+               [AUD_CLKID_MST_F_MCLK]          = &aud_mst_f_mclk.hw,
+               [AUD_CLKID_SPDIFOUT_CLK_SEL]    = &aud_spdifout_clk_sel.hw,
+               [AUD_CLKID_SPDIFOUT_CLK_DIV]    = &aud_spdifout_clk_div.hw,
+               [AUD_CLKID_SPDIFOUT_CLK]        = &aud_spdifout_clk.hw,
+               [AUD_CLKID_SPDIFIN_CLK_SEL]     = &aud_spdifin_clk_sel.hw,
+               [AUD_CLKID_SPDIFIN_CLK_DIV]     = &aud_spdifin_clk_div.hw,
+               [AUD_CLKID_SPDIFIN_CLK]         = &aud_spdifin_clk.hw,
+               [AUD_CLKID_PDM_DCLK_SEL]        = &aud_pdm_dclk_sel.hw,
+               [AUD_CLKID_PDM_DCLK_DIV]        = &aud_pdm_dclk_div.hw,
+               [AUD_CLKID_PDM_DCLK]            = &aud_pdm_dclk.hw,
+               [AUD_CLKID_PDM_SYSCLK_SEL]      = &aud_pdm_sysclk_sel.hw,
+               [AUD_CLKID_PDM_SYSCLK_DIV]      = &aud_pdm_sysclk_div.hw,
+               [AUD_CLKID_PDM_SYSCLK]          = &aud_pdm_sysclk.hw,
+               [AUD_CLKID_MST_A_SCLK_PRE_EN]   = &aud_mst_a_sclk_pre_en.hw,
+               [AUD_CLKID_MST_B_SCLK_PRE_EN]   = &aud_mst_b_sclk_pre_en.hw,
+               [AUD_CLKID_MST_C_SCLK_PRE_EN]   = &aud_mst_c_sclk_pre_en.hw,
+               [AUD_CLKID_MST_D_SCLK_PRE_EN]   = &aud_mst_d_sclk_pre_en.hw,
+               [AUD_CLKID_MST_E_SCLK_PRE_EN]   = &aud_mst_e_sclk_pre_en.hw,
+               [AUD_CLKID_MST_F_SCLK_PRE_EN]   = &aud_mst_f_sclk_pre_en.hw,
+               [AUD_CLKID_MST_A_SCLK_DIV]      = &aud_mst_a_sclk_div.hw,
+               [AUD_CLKID_MST_B_SCLK_DIV]      = &aud_mst_b_sclk_div.hw,
+               [AUD_CLKID_MST_C_SCLK_DIV]      = &aud_mst_c_sclk_div.hw,
+               [AUD_CLKID_MST_D_SCLK_DIV]      = &aud_mst_d_sclk_div.hw,
+               [AUD_CLKID_MST_E_SCLK_DIV]      = &aud_mst_e_sclk_div.hw,
+               [AUD_CLKID_MST_F_SCLK_DIV]      = &aud_mst_f_sclk_div.hw,
+               [AUD_CLKID_MST_A_SCLK_POST_EN]  = &aud_mst_a_sclk_post_en.hw,
+               [AUD_CLKID_MST_B_SCLK_POST_EN]  = &aud_mst_b_sclk_post_en.hw,
+               [AUD_CLKID_MST_C_SCLK_POST_EN]  = &aud_mst_c_sclk_post_en.hw,
+               [AUD_CLKID_MST_D_SCLK_POST_EN]  = &aud_mst_d_sclk_post_en.hw,
+               [AUD_CLKID_MST_E_SCLK_POST_EN]  = &aud_mst_e_sclk_post_en.hw,
+               [AUD_CLKID_MST_F_SCLK_POST_EN]  = &aud_mst_f_sclk_post_en.hw,
+               [AUD_CLKID_MST_A_SCLK]          = &aud_mst_a_sclk.hw,
+               [AUD_CLKID_MST_B_SCLK]          = &aud_mst_b_sclk.hw,
+               [AUD_CLKID_MST_C_SCLK]          = &aud_mst_c_sclk.hw,
+               [AUD_CLKID_MST_D_SCLK]          = &aud_mst_d_sclk.hw,
+               [AUD_CLKID_MST_E_SCLK]          = &aud_mst_e_sclk.hw,
+               [AUD_CLKID_MST_F_SCLK]          = &aud_mst_f_sclk.hw,
+               [AUD_CLKID_MST_A_LRCLK_DIV]     = &aud_mst_a_lrclk_div.hw,
+               [AUD_CLKID_MST_B_LRCLK_DIV]     = &aud_mst_b_lrclk_div.hw,
+               [AUD_CLKID_MST_C_LRCLK_DIV]     = &aud_mst_c_lrclk_div.hw,
+               [AUD_CLKID_MST_D_LRCLK_DIV]     = &aud_mst_d_lrclk_div.hw,
+               [AUD_CLKID_MST_E_LRCLK_DIV]     = &aud_mst_e_lrclk_div.hw,
+               [AUD_CLKID_MST_F_LRCLK_DIV]     = &aud_mst_f_lrclk_div.hw,
+               [AUD_CLKID_MST_A_LRCLK]         = &aud_mst_a_lrclk.hw,
+               [AUD_CLKID_MST_B_LRCLK]         = &aud_mst_b_lrclk.hw,
+               [AUD_CLKID_MST_C_LRCLK]         = &aud_mst_c_lrclk.hw,
+               [AUD_CLKID_MST_D_LRCLK]         = &aud_mst_d_lrclk.hw,
+               [AUD_CLKID_MST_E_LRCLK]         = &aud_mst_e_lrclk.hw,
+               [AUD_CLKID_MST_F_LRCLK]         = &aud_mst_f_lrclk.hw,
+               [AUD_CLKID_TDMIN_A_SCLK_SEL]    = &aud_tdmin_a_sclk_sel.hw,
+               [AUD_CLKID_TDMIN_B_SCLK_SEL]    = &aud_tdmin_b_sclk_sel.hw,
+               [AUD_CLKID_TDMIN_C_SCLK_SEL]    = &aud_tdmin_c_sclk_sel.hw,
+               [AUD_CLKID_TDMIN_LB_SCLK_SEL]   = &aud_tdmin_lb_sclk_sel.hw,
+               [AUD_CLKID_TDMOUT_A_SCLK_SEL]   = &aud_tdmout_a_sclk_sel.hw,
+               [AUD_CLKID_TDMOUT_B_SCLK_SEL]   = &aud_tdmout_b_sclk_sel.hw,
+               [AUD_CLKID_TDMOUT_C_SCLK_SEL]   = &aud_tdmout_c_sclk_sel.hw,
+               [AUD_CLKID_TDMIN_A_SCLK_PRE_EN] = &aud_tdmin_a_sclk_pre_en.hw,
+               [AUD_CLKID_TDMIN_B_SCLK_PRE_EN] = &aud_tdmin_b_sclk_pre_en.hw,
+               [AUD_CLKID_TDMIN_C_SCLK_PRE_EN] = &aud_tdmin_c_sclk_pre_en.hw,
+               [AUD_CLKID_TDMIN_LB_SCLK_PRE_EN] = &aud_tdmin_lb_sclk_pre_en.hw,
+               [AUD_CLKID_TDMOUT_A_SCLK_PRE_EN] = &aud_tdmout_a_sclk_pre_en.hw,
+               [AUD_CLKID_TDMOUT_B_SCLK_PRE_EN] = &aud_tdmout_b_sclk_pre_en.hw,
+               [AUD_CLKID_TDMOUT_C_SCLK_PRE_EN] = &aud_tdmout_c_sclk_pre_en.hw,
+               [AUD_CLKID_TDMIN_A_SCLK_POST_EN] = &aud_tdmin_a_sclk_post_en.hw,
+               [AUD_CLKID_TDMIN_B_SCLK_POST_EN] = &aud_tdmin_b_sclk_post_en.hw,
+               [AUD_CLKID_TDMIN_C_SCLK_POST_EN] = &aud_tdmin_c_sclk_post_en.hw,
+               [AUD_CLKID_TDMIN_LB_SCLK_POST_EN] = &aud_tdmin_lb_sclk_post_en.hw,
+               [AUD_CLKID_TDMOUT_A_SCLK_POST_EN] = &aud_tdmout_a_sclk_post_en.hw,
+               [AUD_CLKID_TDMOUT_B_SCLK_POST_EN] = &aud_tdmout_b_sclk_post_en.hw,
+               [AUD_CLKID_TDMOUT_C_SCLK_POST_EN] = &aud_tdmout_c_sclk_post_en.hw,
+               [AUD_CLKID_TDMIN_A_SCLK]        = &aud_tdmin_a_sclk.hw,
+               [AUD_CLKID_TDMIN_B_SCLK]        = &aud_tdmin_b_sclk.hw,
+               [AUD_CLKID_TDMIN_C_SCLK]        = &aud_tdmin_c_sclk.hw,
+               [AUD_CLKID_TDMIN_LB_SCLK]       = &aud_tdmin_lb_sclk.hw,
+               [AUD_CLKID_TDMOUT_A_SCLK]       = &aud_tdmout_a_sclk.hw,
+               [AUD_CLKID_TDMOUT_B_SCLK]       = &aud_tdmout_b_sclk.hw,
+               [AUD_CLKID_TDMOUT_C_SCLK]       = &aud_tdmout_c_sclk.hw,
+               [AUD_CLKID_TDMIN_A_LRCLK]       = &aud_tdmin_a_lrclk.hw,
+               [AUD_CLKID_TDMIN_B_LRCLK]       = &aud_tdmin_b_lrclk.hw,
+               [AUD_CLKID_TDMIN_C_LRCLK]       = &aud_tdmin_c_lrclk.hw,
+               [AUD_CLKID_TDMIN_LB_LRCLK]      = &aud_tdmin_lb_lrclk.hw,
+               [AUD_CLKID_TDMOUT_A_LRCLK]      = &aud_tdmout_a_lrclk.hw,
+               [AUD_CLKID_TDMOUT_B_LRCLK]      = &aud_tdmout_b_lrclk.hw,
+               [AUD_CLKID_TDMOUT_C_LRCLK]      = &aud_tdmout_c_lrclk.hw,
                [NR_CLKS] = NULL,
        },
        .num = NR_CLKS,
 };
 
-/* Convenience table to populate regmap in .probe() */
-static struct clk_regmap *const axg_audio_clk_regmaps[] = {
-       &axg_ddr_arb,
-       &axg_pdm,
-       &axg_tdmin_a,
-       &axg_tdmin_b,
-       &axg_tdmin_c,
-       &axg_tdmin_lb,
-       &axg_tdmout_a,
-       &axg_tdmout_b,
-       &axg_tdmout_c,
-       &axg_frddr_a,
-       &axg_frddr_b,
-       &axg_frddr_c,
-       &axg_toddr_a,
-       &axg_toddr_b,
-       &axg_toddr_c,
-       &axg_loopback,
-       &axg_spdifin,
-       &axg_spdifout,
-       &axg_resample,
-       &axg_power_detect,
-       &axg_mst_a_mclk_sel,
-       &axg_mst_b_mclk_sel,
-       &axg_mst_c_mclk_sel,
-       &axg_mst_d_mclk_sel,
-       &axg_mst_e_mclk_sel,
-       &axg_mst_f_mclk_sel,
-       &axg_mst_a_mclk_div,
-       &axg_mst_b_mclk_div,
-       &axg_mst_c_mclk_div,
-       &axg_mst_d_mclk_div,
-       &axg_mst_e_mclk_div,
-       &axg_mst_f_mclk_div,
-       &axg_mst_a_mclk,
-       &axg_mst_b_mclk,
-       &axg_mst_c_mclk,
-       &axg_mst_d_mclk,
-       &axg_mst_e_mclk,
-       &axg_mst_f_mclk,
-       &axg_spdifout_clk_sel,
-       &axg_spdifout_clk_div,
-       &axg_spdifout_clk,
-       &axg_spdifin_clk_sel,
-       &axg_spdifin_clk_div,
-       &axg_spdifin_clk,
-       &axg_pdm_dclk_sel,
-       &axg_pdm_dclk_div,
-       &axg_pdm_dclk,
-       &axg_pdm_sysclk_sel,
-       &axg_pdm_sysclk_div,
-       &axg_pdm_sysclk,
-       &axg_mst_a_sclk_pre_en,
-       &axg_mst_b_sclk_pre_en,
-       &axg_mst_c_sclk_pre_en,
-       &axg_mst_d_sclk_pre_en,
-       &axg_mst_e_sclk_pre_en,
-       &axg_mst_f_sclk_pre_en,
-       &axg_mst_a_sclk_div,
-       &axg_mst_b_sclk_div,
-       &axg_mst_c_sclk_div,
-       &axg_mst_d_sclk_div,
-       &axg_mst_e_sclk_div,
-       &axg_mst_f_sclk_div,
-       &axg_mst_a_sclk_post_en,
-       &axg_mst_b_sclk_post_en,
-       &axg_mst_c_sclk_post_en,
-       &axg_mst_d_sclk_post_en,
-       &axg_mst_e_sclk_post_en,
-       &axg_mst_f_sclk_post_en,
-       &axg_mst_a_sclk,
-       &axg_mst_b_sclk,
-       &axg_mst_c_sclk,
-       &axg_mst_d_sclk,
-       &axg_mst_e_sclk,
-       &axg_mst_f_sclk,
-       &axg_mst_a_lrclk_div,
-       &axg_mst_b_lrclk_div,
-       &axg_mst_c_lrclk_div,
-       &axg_mst_d_lrclk_div,
-       &axg_mst_e_lrclk_div,
-       &axg_mst_f_lrclk_div,
-       &axg_mst_a_lrclk,
-       &axg_mst_b_lrclk,
-       &axg_mst_c_lrclk,
-       &axg_mst_d_lrclk,
-       &axg_mst_e_lrclk,
-       &axg_mst_f_lrclk,
-       &axg_tdmin_a_sclk_sel,
-       &axg_tdmin_b_sclk_sel,
-       &axg_tdmin_c_sclk_sel,
-       &axg_tdmin_lb_sclk_sel,
-       &axg_tdmout_a_sclk_sel,
-       &axg_tdmout_b_sclk_sel,
-       &axg_tdmout_c_sclk_sel,
-       &axg_tdmin_a_sclk_pre_en,
-       &axg_tdmin_b_sclk_pre_en,
-       &axg_tdmin_c_sclk_pre_en,
-       &axg_tdmin_lb_sclk_pre_en,
-       &axg_tdmout_a_sclk_pre_en,
-       &axg_tdmout_b_sclk_pre_en,
-       &axg_tdmout_c_sclk_pre_en,
-       &axg_tdmin_a_sclk_post_en,
-       &axg_tdmin_b_sclk_post_en,
-       &axg_tdmin_c_sclk_post_en,
-       &axg_tdmin_lb_sclk_post_en,
-       &axg_tdmout_a_sclk_post_en,
-       &axg_tdmout_b_sclk_post_en,
-       &axg_tdmout_c_sclk_post_en,
-       &axg_tdmin_a_sclk,
-       &axg_tdmin_b_sclk,
-       &axg_tdmin_c_sclk,
-       &axg_tdmin_lb_sclk,
-       &axg_tdmout_a_sclk,
-       &axg_tdmout_b_sclk,
-       &axg_tdmout_c_sclk,
-       &axg_tdmin_a_lrclk,
-       &axg_tdmin_b_lrclk,
-       &axg_tdmin_c_lrclk,
-       &axg_tdmin_lb_lrclk,
-       &axg_tdmout_a_lrclk,
-       &axg_tdmout_b_lrclk,
-       &axg_tdmout_c_lrclk,
+/*
+ * Array of all G12A clocks provided by this provider
+ * The input clocks of the controller will be populated at runtime
+ */
+static struct clk_hw_onecell_data g12a_audio_hw_onecell_data = {
+       .hws = {
+               [AUD_CLKID_DDR_ARB]             = &aud_ddr_arb.hw,
+               [AUD_CLKID_PDM]                 = &aud_pdm.hw,
+               [AUD_CLKID_TDMIN_A]             = &aud_tdmin_a.hw,
+               [AUD_CLKID_TDMIN_B]             = &aud_tdmin_b.hw,
+               [AUD_CLKID_TDMIN_C]             = &aud_tdmin_c.hw,
+               [AUD_CLKID_TDMIN_LB]            = &aud_tdmin_lb.hw,
+               [AUD_CLKID_TDMOUT_A]            = &aud_tdmout_a.hw,
+               [AUD_CLKID_TDMOUT_B]            = &aud_tdmout_b.hw,
+               [AUD_CLKID_TDMOUT_C]            = &aud_tdmout_c.hw,
+               [AUD_CLKID_FRDDR_A]             = &aud_frddr_a.hw,
+               [AUD_CLKID_FRDDR_B]             = &aud_frddr_b.hw,
+               [AUD_CLKID_FRDDR_C]             = &aud_frddr_c.hw,
+               [AUD_CLKID_TODDR_A]             = &aud_toddr_a.hw,
+               [AUD_CLKID_TODDR_B]             = &aud_toddr_b.hw,
+               [AUD_CLKID_TODDR_C]             = &aud_toddr_c.hw,
+               [AUD_CLKID_LOOPBACK]            = &aud_loopback.hw,
+               [AUD_CLKID_SPDIFIN]             = &aud_spdifin.hw,
+               [AUD_CLKID_SPDIFOUT]            = &aud_spdifout.hw,
+               [AUD_CLKID_RESAMPLE]            = &aud_resample.hw,
+               [AUD_CLKID_POWER_DETECT]        = &aud_power_detect.hw,
+               [AUD_CLKID_SPDIFOUT_B]          = &aud_spdifout_b.hw,
+               [AUD_CLKID_MST_A_MCLK_SEL]      = &aud_mst_a_mclk_sel.hw,
+               [AUD_CLKID_MST_B_MCLK_SEL]      = &aud_mst_b_mclk_sel.hw,
+               [AUD_CLKID_MST_C_MCLK_SEL]      = &aud_mst_c_mclk_sel.hw,
+               [AUD_CLKID_MST_D_MCLK_SEL]      = &aud_mst_d_mclk_sel.hw,
+               [AUD_CLKID_MST_E_MCLK_SEL]      = &aud_mst_e_mclk_sel.hw,
+               [AUD_CLKID_MST_F_MCLK_SEL]      = &aud_mst_f_mclk_sel.hw,
+               [AUD_CLKID_MST_A_MCLK_DIV]      = &aud_mst_a_mclk_div.hw,
+               [AUD_CLKID_MST_B_MCLK_DIV]      = &aud_mst_b_mclk_div.hw,
+               [AUD_CLKID_MST_C_MCLK_DIV]      = &aud_mst_c_mclk_div.hw,
+               [AUD_CLKID_MST_D_MCLK_DIV]      = &aud_mst_d_mclk_div.hw,
+               [AUD_CLKID_MST_E_MCLK_DIV]      = &aud_mst_e_mclk_div.hw,
+               [AUD_CLKID_MST_F_MCLK_DIV]      = &aud_mst_f_mclk_div.hw,
+               [AUD_CLKID_MST_A_MCLK]          = &aud_mst_a_mclk.hw,
+               [AUD_CLKID_MST_B_MCLK]          = &aud_mst_b_mclk.hw,
+               [AUD_CLKID_MST_C_MCLK]          = &aud_mst_c_mclk.hw,
+               [AUD_CLKID_MST_D_MCLK]          = &aud_mst_d_mclk.hw,
+               [AUD_CLKID_MST_E_MCLK]          = &aud_mst_e_mclk.hw,
+               [AUD_CLKID_MST_F_MCLK]          = &aud_mst_f_mclk.hw,
+               [AUD_CLKID_SPDIFOUT_CLK_SEL]    = &aud_spdifout_clk_sel.hw,
+               [AUD_CLKID_SPDIFOUT_CLK_DIV]    = &aud_spdifout_clk_div.hw,
+               [AUD_CLKID_SPDIFOUT_CLK]        = &aud_spdifout_clk.hw,
+               [AUD_CLKID_SPDIFOUT_B_CLK_SEL]  = &aud_spdifout_b_clk_sel.hw,
+               [AUD_CLKID_SPDIFOUT_B_CLK_DIV]  = &aud_spdifout_b_clk_div.hw,
+               [AUD_CLKID_SPDIFOUT_B_CLK]      = &aud_spdifout_b_clk.hw,
+               [AUD_CLKID_SPDIFIN_CLK_SEL]     = &aud_spdifin_clk_sel.hw,
+               [AUD_CLKID_SPDIFIN_CLK_DIV]     = &aud_spdifin_clk_div.hw,
+               [AUD_CLKID_SPDIFIN_CLK]         = &aud_spdifin_clk.hw,
+               [AUD_CLKID_PDM_DCLK_SEL]        = &aud_pdm_dclk_sel.hw,
+               [AUD_CLKID_PDM_DCLK_DIV]        = &aud_pdm_dclk_div.hw,
+               [AUD_CLKID_PDM_DCLK]            = &aud_pdm_dclk.hw,
+               [AUD_CLKID_PDM_SYSCLK_SEL]      = &aud_pdm_sysclk_sel.hw,
+               [AUD_CLKID_PDM_SYSCLK_DIV]      = &aud_pdm_sysclk_div.hw,
+               [AUD_CLKID_PDM_SYSCLK]          = &aud_pdm_sysclk.hw,
+               [AUD_CLKID_MST_A_SCLK_PRE_EN]   = &aud_mst_a_sclk_pre_en.hw,
+               [AUD_CLKID_MST_B_SCLK_PRE_EN]   = &aud_mst_b_sclk_pre_en.hw,
+               [AUD_CLKID_MST_C_SCLK_PRE_EN]   = &aud_mst_c_sclk_pre_en.hw,
+               [AUD_CLKID_MST_D_SCLK_PRE_EN]   = &aud_mst_d_sclk_pre_en.hw,
+               [AUD_CLKID_MST_E_SCLK_PRE_EN]   = &aud_mst_e_sclk_pre_en.hw,
+               [AUD_CLKID_MST_F_SCLK_PRE_EN]   = &aud_mst_f_sclk_pre_en.hw,
+               [AUD_CLKID_MST_A_SCLK_DIV]      = &aud_mst_a_sclk_div.hw,
+               [AUD_CLKID_MST_B_SCLK_DIV]      = &aud_mst_b_sclk_div.hw,
+               [AUD_CLKID_MST_C_SCLK_DIV]      = &aud_mst_c_sclk_div.hw,
+               [AUD_CLKID_MST_D_SCLK_DIV]      = &aud_mst_d_sclk_div.hw,
+               [AUD_CLKID_MST_E_SCLK_DIV]      = &aud_mst_e_sclk_div.hw,
+               [AUD_CLKID_MST_F_SCLK_DIV]      = &aud_mst_f_sclk_div.hw,
+               [AUD_CLKID_MST_A_SCLK_POST_EN]  = &aud_mst_a_sclk_post_en.hw,
+               [AUD_CLKID_MST_B_SCLK_POST_EN]  = &aud_mst_b_sclk_post_en.hw,
+               [AUD_CLKID_MST_C_SCLK_POST_EN]  = &aud_mst_c_sclk_post_en.hw,
+               [AUD_CLKID_MST_D_SCLK_POST_EN]  = &aud_mst_d_sclk_post_en.hw,
+               [AUD_CLKID_MST_E_SCLK_POST_EN]  = &aud_mst_e_sclk_post_en.hw,
+               [AUD_CLKID_MST_F_SCLK_POST_EN]  = &aud_mst_f_sclk_post_en.hw,
+               [AUD_CLKID_MST_A_SCLK]          = &aud_mst_a_sclk.hw,
+               [AUD_CLKID_MST_B_SCLK]          = &aud_mst_b_sclk.hw,
+               [AUD_CLKID_MST_C_SCLK]          = &aud_mst_c_sclk.hw,
+               [AUD_CLKID_MST_D_SCLK]          = &aud_mst_d_sclk.hw,
+               [AUD_CLKID_MST_E_SCLK]          = &aud_mst_e_sclk.hw,
+               [AUD_CLKID_MST_F_SCLK]          = &aud_mst_f_sclk.hw,
+               [AUD_CLKID_MST_A_LRCLK_DIV]     = &aud_mst_a_lrclk_div.hw,
+               [AUD_CLKID_MST_B_LRCLK_DIV]     = &aud_mst_b_lrclk_div.hw,
+               [AUD_CLKID_MST_C_LRCLK_DIV]     = &aud_mst_c_lrclk_div.hw,
+               [AUD_CLKID_MST_D_LRCLK_DIV]     = &aud_mst_d_lrclk_div.hw,
+               [AUD_CLKID_MST_E_LRCLK_DIV]     = &aud_mst_e_lrclk_div.hw,
+               [AUD_CLKID_MST_F_LRCLK_DIV]     = &aud_mst_f_lrclk_div.hw,
+               [AUD_CLKID_MST_A_LRCLK]         = &aud_mst_a_lrclk.hw,
+               [AUD_CLKID_MST_B_LRCLK]         = &aud_mst_b_lrclk.hw,
+               [AUD_CLKID_MST_C_LRCLK]         = &aud_mst_c_lrclk.hw,
+               [AUD_CLKID_MST_D_LRCLK]         = &aud_mst_d_lrclk.hw,
+               [AUD_CLKID_MST_E_LRCLK]         = &aud_mst_e_lrclk.hw,
+               [AUD_CLKID_MST_F_LRCLK]         = &aud_mst_f_lrclk.hw,
+               [AUD_CLKID_TDMIN_A_SCLK_SEL]    = &aud_tdmin_a_sclk_sel.hw,
+               [AUD_CLKID_TDMIN_B_SCLK_SEL]    = &aud_tdmin_b_sclk_sel.hw,
+               [AUD_CLKID_TDMIN_C_SCLK_SEL]    = &aud_tdmin_c_sclk_sel.hw,
+               [AUD_CLKID_TDMIN_LB_SCLK_SEL]   = &aud_tdmin_lb_sclk_sel.hw,
+               [AUD_CLKID_TDMOUT_A_SCLK_SEL]   = &aud_tdmout_a_sclk_sel.hw,
+               [AUD_CLKID_TDMOUT_B_SCLK_SEL]   = &aud_tdmout_b_sclk_sel.hw,
+               [AUD_CLKID_TDMOUT_C_SCLK_SEL]   = &aud_tdmout_c_sclk_sel.hw,
+               [AUD_CLKID_TDMIN_A_SCLK_PRE_EN] = &aud_tdmin_a_sclk_pre_en.hw,
+               [AUD_CLKID_TDMIN_B_SCLK_PRE_EN] = &aud_tdmin_b_sclk_pre_en.hw,
+               [AUD_CLKID_TDMIN_C_SCLK_PRE_EN] = &aud_tdmin_c_sclk_pre_en.hw,
+               [AUD_CLKID_TDMIN_LB_SCLK_PRE_EN] = &aud_tdmin_lb_sclk_pre_en.hw,
+               [AUD_CLKID_TDMOUT_A_SCLK_PRE_EN] = &aud_tdmout_a_sclk_pre_en.hw,
+               [AUD_CLKID_TDMOUT_B_SCLK_PRE_EN] = &aud_tdmout_b_sclk_pre_en.hw,
+               [AUD_CLKID_TDMOUT_C_SCLK_PRE_EN] = &aud_tdmout_c_sclk_pre_en.hw,
+               [AUD_CLKID_TDMIN_A_SCLK_POST_EN] = &aud_tdmin_a_sclk_post_en.hw,
+               [AUD_CLKID_TDMIN_B_SCLK_POST_EN] = &aud_tdmin_b_sclk_post_en.hw,
+               [AUD_CLKID_TDMIN_C_SCLK_POST_EN] = &aud_tdmin_c_sclk_post_en.hw,
+               [AUD_CLKID_TDMIN_LB_SCLK_POST_EN] = &aud_tdmin_lb_sclk_post_en.hw,
+               [AUD_CLKID_TDMOUT_A_SCLK_POST_EN] = &aud_tdmout_a_sclk_post_en.hw,
+               [AUD_CLKID_TDMOUT_B_SCLK_POST_EN] = &aud_tdmout_b_sclk_post_en.hw,
+               [AUD_CLKID_TDMOUT_C_SCLK_POST_EN] = &aud_tdmout_c_sclk_post_en.hw,
+               [AUD_CLKID_TDMIN_A_SCLK]        = &aud_tdmin_a_sclk.hw,
+               [AUD_CLKID_TDMIN_B_SCLK]        = &aud_tdmin_b_sclk.hw,
+               [AUD_CLKID_TDMIN_C_SCLK]        = &aud_tdmin_c_sclk.hw,
+               [AUD_CLKID_TDMIN_LB_SCLK]       = &aud_tdmin_lb_sclk.hw,
+               [AUD_CLKID_TDMOUT_A_SCLK]       = &aud_tdmout_a_sclk.hw,
+               [AUD_CLKID_TDMOUT_B_SCLK]       = &aud_tdmout_b_sclk.hw,
+               [AUD_CLKID_TDMOUT_C_SCLK]       = &aud_tdmout_c_sclk.hw,
+               [AUD_CLKID_TDMIN_A_LRCLK]       = &aud_tdmin_a_lrclk.hw,
+               [AUD_CLKID_TDMIN_B_LRCLK]       = &aud_tdmin_b_lrclk.hw,
+               [AUD_CLKID_TDMIN_C_LRCLK]       = &aud_tdmin_c_lrclk.hw,
+               [AUD_CLKID_TDMIN_LB_LRCLK]      = &aud_tdmin_lb_lrclk.hw,
+               [AUD_CLKID_TDMOUT_A_LRCLK]      = &aud_tdmout_a_lrclk.hw,
+               [AUD_CLKID_TDMOUT_B_LRCLK]      = &aud_tdmout_b_lrclk.hw,
+               [AUD_CLKID_TDMOUT_C_LRCLK]      = &aud_tdmout_c_lrclk.hw,
+               [AUD_CLKID_TDM_MCLK_PAD0]       = &aud_tdm_mclk_pad_0.hw,
+               [AUD_CLKID_TDM_MCLK_PAD1]       = &aud_tdm_mclk_pad_1.hw,
+               [AUD_CLKID_TDM_LRCLK_PAD0]      = &aud_tdm_lrclk_pad_0.hw,
+               [AUD_CLKID_TDM_LRCLK_PAD1]      = &aud_tdm_lrclk_pad_1.hw,
+               [AUD_CLKID_TDM_LRCLK_PAD2]      = &aud_tdm_lrclk_pad_2.hw,
+               [AUD_CLKID_TDM_SCLK_PAD0]       = &aud_tdm_sclk_pad_0.hw,
+               [AUD_CLKID_TDM_SCLK_PAD1]       = &aud_tdm_sclk_pad_1.hw,
+               [AUD_CLKID_TDM_SCLK_PAD2]       = &aud_tdm_sclk_pad_2.hw,
+               [NR_CLKS] = NULL,
+       },
+       .num = NR_CLKS,
+};
+
+/* Convenience table to populate regmap in .probe()
+ * Note that this table is shared between both AXG and G12A,
+ * with spdifout_b clocks being exclusive to G12A. Since those
+ * clocks are not declared within the AXG onecell table, we do not
+ * feel the need to have separate AXG/G12A regmap tables.
+ */
+static struct clk_regmap *const aud_clk_regmaps[] = {
+       &aud_ddr_arb,
+       &aud_pdm,
+       &aud_tdmin_a,
+       &aud_tdmin_b,
+       &aud_tdmin_c,
+       &aud_tdmin_lb,
+       &aud_tdmout_a,
+       &aud_tdmout_b,
+       &aud_tdmout_c,
+       &aud_frddr_a,
+       &aud_frddr_b,
+       &aud_frddr_c,
+       &aud_toddr_a,
+       &aud_toddr_b,
+       &aud_toddr_c,
+       &aud_loopback,
+       &aud_spdifin,
+       &aud_spdifout,
+       &aud_resample,
+       &aud_power_detect,
+       &aud_spdifout_b,
+       &aud_mst_a_mclk_sel,
+       &aud_mst_b_mclk_sel,
+       &aud_mst_c_mclk_sel,
+       &aud_mst_d_mclk_sel,
+       &aud_mst_e_mclk_sel,
+       &aud_mst_f_mclk_sel,
+       &aud_mst_a_mclk_div,
+       &aud_mst_b_mclk_div,
+       &aud_mst_c_mclk_div,
+       &aud_mst_d_mclk_div,
+       &aud_mst_e_mclk_div,
+       &aud_mst_f_mclk_div,
+       &aud_mst_a_mclk,
+       &aud_mst_b_mclk,
+       &aud_mst_c_mclk,
+       &aud_mst_d_mclk,
+       &aud_mst_e_mclk,
+       &aud_mst_f_mclk,
+       &aud_spdifout_clk_sel,
+       &aud_spdifout_clk_div,
+       &aud_spdifout_clk,
+       &aud_spdifin_clk_sel,
+       &aud_spdifin_clk_div,
+       &aud_spdifin_clk,
+       &aud_pdm_dclk_sel,
+       &aud_pdm_dclk_div,
+       &aud_pdm_dclk,
+       &aud_pdm_sysclk_sel,
+       &aud_pdm_sysclk_div,
+       &aud_pdm_sysclk,
+       &aud_mst_a_sclk_pre_en,
+       &aud_mst_b_sclk_pre_en,
+       &aud_mst_c_sclk_pre_en,
+       &aud_mst_d_sclk_pre_en,
+       &aud_mst_e_sclk_pre_en,
+       &aud_mst_f_sclk_pre_en,
+       &aud_mst_a_sclk_div,
+       &aud_mst_b_sclk_div,
+       &aud_mst_c_sclk_div,
+       &aud_mst_d_sclk_div,
+       &aud_mst_e_sclk_div,
+       &aud_mst_f_sclk_div,
+       &aud_mst_a_sclk_post_en,
+       &aud_mst_b_sclk_post_en,
+       &aud_mst_c_sclk_post_en,
+       &aud_mst_d_sclk_post_en,
+       &aud_mst_e_sclk_post_en,
+       &aud_mst_f_sclk_post_en,
+       &aud_mst_a_sclk,
+       &aud_mst_b_sclk,
+       &aud_mst_c_sclk,
+       &aud_mst_d_sclk,
+       &aud_mst_e_sclk,
+       &aud_mst_f_sclk,
+       &aud_mst_a_lrclk_div,
+       &aud_mst_b_lrclk_div,
+       &aud_mst_c_lrclk_div,
+       &aud_mst_d_lrclk_div,
+       &aud_mst_e_lrclk_div,
+       &aud_mst_f_lrclk_div,
+       &aud_mst_a_lrclk,
+       &aud_mst_b_lrclk,
+       &aud_mst_c_lrclk,
+       &aud_mst_d_lrclk,
+       &aud_mst_e_lrclk,
+       &aud_mst_f_lrclk,
+       &aud_tdmin_a_sclk_sel,
+       &aud_tdmin_b_sclk_sel,
+       &aud_tdmin_c_sclk_sel,
+       &aud_tdmin_lb_sclk_sel,
+       &aud_tdmout_a_sclk_sel,
+       &aud_tdmout_b_sclk_sel,
+       &aud_tdmout_c_sclk_sel,
+       &aud_tdmin_a_sclk_pre_en,
+       &aud_tdmin_b_sclk_pre_en,
+       &aud_tdmin_c_sclk_pre_en,
+       &aud_tdmin_lb_sclk_pre_en,
+       &aud_tdmout_a_sclk_pre_en,
+       &aud_tdmout_b_sclk_pre_en,
+       &aud_tdmout_c_sclk_pre_en,
+       &aud_tdmin_a_sclk_post_en,
+       &aud_tdmin_b_sclk_post_en,
+       &aud_tdmin_c_sclk_post_en,
+       &aud_tdmin_lb_sclk_post_en,
+       &aud_tdmout_a_sclk_post_en,
+       &aud_tdmout_b_sclk_post_en,
+       &aud_tdmout_c_sclk_post_en,
+       &aud_tdmin_a_sclk,
+       &aud_tdmin_b_sclk,
+       &aud_tdmin_c_sclk,
+       &aud_tdmin_lb_sclk,
+       &aud_tdmout_a_sclk,
+       &aud_tdmout_b_sclk,
+       &aud_tdmout_c_sclk,
+       &aud_tdmin_a_lrclk,
+       &aud_tdmin_b_lrclk,
+       &aud_tdmin_c_lrclk,
+       &aud_tdmin_lb_lrclk,
+       &aud_tdmout_a_lrclk,
+       &aud_tdmout_b_lrclk,
+       &aud_tdmout_c_lrclk,
+       &aud_spdifout_b_clk_sel,
+       &aud_spdifout_b_clk_div,
+       &aud_spdifout_b_clk,
+       &aud_tdm_mclk_pad_0,
+       &aud_tdm_mclk_pad_1,
+       &aud_tdm_lrclk_pad_0,
+       &aud_tdm_lrclk_pad_1,
+       &aud_tdm_lrclk_pad_2,
+       &aud_tdm_sclk_pad_0,
+       &aud_tdm_sclk_pad_1,
+       &aud_tdm_sclk_pad_2,
 };
 
 static int devm_clk_get_enable(struct device *dev, char *id)
@@ -665,14 +869,13 @@ static int devm_clk_get_enable(struct device *dev, char *id)
 }
 
 static int axg_register_clk_hw_input(struct device *dev,
-                                    const char *name,
-                                    unsigned int clkid)
+                                    const char *name)
 {
        char *clk_name;
        struct clk_hw *hw;
        int err = 0;
 
-       clk_name = kasprintf(GFP_KERNEL, "axg_%s", name);
+       clk_name = kasprintf(GFP_KERNEL, "aud_%s", name);
        if (!clk_name)
                return -ENOMEM;
 
@@ -686,8 +889,6 @@ static int axg_register_clk_hw_input(struct device *dev,
                        if (err != -EPROBE_DEFER)
                                dev_err(dev, "failed to get %s clock", name);
                }
-       } else {
-               axg_audio_hw_onecell_data.hws[clkid] = hw;
        }
 
        kfree(clk_name);
@@ -696,8 +897,7 @@ static int axg_register_clk_hw_input(struct device *dev,
 
 static int axg_register_clk_hw_inputs(struct device *dev,
                                      const char *basename,
-                                     unsigned int count,
-                                     unsigned int clkid)
+                                     unsigned int count)
 {
        char *name;
        int i, ret;
@@ -707,7 +907,7 @@ static int axg_register_clk_hw_inputs(struct device *dev,
                if (!name)
                        return -ENOMEM;
 
-               ret = axg_register_clk_hw_input(dev, name, clkid + i);
+               ret = axg_register_clk_hw_input(dev, name);
                kfree(name);
                if (ret)
                        return ret;
@@ -723,15 +923,24 @@ static const struct regmap_config axg_audio_regmap_cfg = {
        .max_register   = AUDIO_CLK_PDMIN_CTRL1,
 };
 
+struct audioclk_data {
+       struct clk_hw_onecell_data *hw_onecell_data;
+};
+
 static int axg_audio_clkc_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
+       const struct audioclk_data *data;
        struct regmap *map;
        struct resource *res;
        void __iomem *regs;
        struct clk_hw *hw;
        int ret, i;
 
+       data = of_device_get_match_data(dev);
+       if (!data)
+               return -EINVAL;
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        regs = devm_ioremap_resource(dev, res);
        if (IS_ERR(regs))
@@ -755,40 +964,35 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
        }
 
        /* Register the peripheral input clock */
-       hw = meson_clk_hw_register_input(dev, "pclk", "axg_audio_pclk", 0);
+       hw = meson_clk_hw_register_input(dev, "pclk", "audio_pclk", 0);
        if (IS_ERR(hw))
                return PTR_ERR(hw);
 
-       axg_audio_hw_onecell_data.hws[AUD_CLKID_PCLK] = hw;
-
        /* Register optional input master clocks */
        ret = axg_register_clk_hw_inputs(dev, "mst_in",
-                                        AXG_MST_IN_COUNT,
-                                        AUD_CLKID_MST0);
+                                        AUD_MST_IN_COUNT);
        if (ret)
                return ret;
 
        /* Register optional input slave sclks */
        ret = axg_register_clk_hw_inputs(dev, "slv_sclk",
-                                        AXG_SLV_SCLK_COUNT,
-                                        AUD_CLKID_SLV_SCLK0);
+                                        AUD_SLV_SCLK_COUNT);
        if (ret)
                return ret;
 
        /* Register optional input slave lrclks */
        ret = axg_register_clk_hw_inputs(dev, "slv_lrclk",
-                                        AXG_SLV_LRCLK_COUNT,
-                                        AUD_CLKID_SLV_LRCLK0);
+                                        AUD_SLV_LRCLK_COUNT);
        if (ret)
                return ret;
 
        /* Populate regmap for the regmap backed clocks */
-       for (i = 0; i < ARRAY_SIZE(axg_audio_clk_regmaps); i++)
-               axg_audio_clk_regmaps[i]->map = map;
+       for (i = 0; i < ARRAY_SIZE(aud_clk_regmaps); i++)
+               aud_clk_regmaps[i]->map = map;
 
        /* Take care to skip the registered input clocks */
-       for (i = AUD_CLKID_DDR_ARB; i < axg_audio_hw_onecell_data.num; i++) {
-               hw = axg_audio_hw_onecell_data.hws[i];
+       for (i = AUD_CLKID_DDR_ARB; i < data->hw_onecell_data->num; i++) {
+               hw = data->hw_onecell_data->hws[i];
                /* array might be sparse */
                if (!hw)
                        continue;
@@ -802,12 +1006,25 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
        }
 
        return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
-                                          &axg_audio_hw_onecell_data);
+                                          data->hw_onecell_data);
 }
 
+static const struct audioclk_data axg_audioclk_data = {
+       .hw_onecell_data = &axg_audio_hw_onecell_data,
+};
+
+static const struct audioclk_data g12a_audioclk_data = {
+       .hw_onecell_data = &g12a_audio_hw_onecell_data,
+};
+
 static const struct of_device_id clkc_match_table[] = {
-       { .compatible = "amlogic,axg-audio-clkc" },
-       {}
+       {
+               .compatible = "amlogic,axg-audio-clkc",
+               .data = &axg_audioclk_data
+       }, {
+               .compatible = "amlogic,g12a-audio-clkc",
+               .data = &g12a_audioclk_data
+       }, {}
 };
 MODULE_DEVICE_TABLE(of, clkc_match_table);
 
@@ -820,6 +1037,6 @@ static struct platform_driver axg_audio_driver = {
 };
 module_platform_driver(axg_audio_driver);
 
-MODULE_DESCRIPTION("Amlogic A113x Audio Clock driver");
+MODULE_DESCRIPTION("Amlogic AXG/G12A Audio Clock driver");
 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
 MODULE_LICENSE("GPL v2");
index 7191b39c9d6509688ae48bd9411a24a6addf49b2..5d972d55d6c741ef8ee80fd0c3012ba6b558f0c9 100644 (file)
@@ -20,6 +20,8 @@
 #define AUDIO_MCLK_D_CTRL      0x010
 #define AUDIO_MCLK_E_CTRL      0x014
 #define AUDIO_MCLK_F_CTRL      0x018
+#define AUDIO_MST_PAD_CTRL0    0x01c
+#define AUDIO_MST_PAD_CTRL1    0x020
 #define AUDIO_MST_A_SCLK_CTRL0 0x040
 #define AUDIO_MST_A_SCLK_CTRL1 0x044
 #define AUDIO_MST_B_SCLK_CTRL0 0x048
 #define AUDIO_CLK_LOCKER_CTRL  0x0A8
 #define AUDIO_CLK_PDMIN_CTRL0  0x0AC
 #define AUDIO_CLK_PDMIN_CTRL1  0x0B0
+#define AUDIO_CLK_SPDIFOUT_B_CTRL 0x0B4
 
 /*
  * CLKID index values
  * These indices are entirely contrived and do not map onto the hardware.
  */
 
-#define AUD_CLKID_PCLK                 0
-#define AUD_CLKID_MST0                 1
-#define AUD_CLKID_MST1                 2
-#define AUD_CLKID_MST2                 3
-#define AUD_CLKID_MST3                 4
-#define AUD_CLKID_MST4                 5
-#define AUD_CLKID_MST5                 6
-#define AUD_CLKID_MST6                 7
-#define AUD_CLKID_MST7                 8
 #define AUD_CLKID_MST_A_MCLK_SEL       59
 #define AUD_CLKID_MST_B_MCLK_SEL       60
 #define AUD_CLKID_MST_C_MCLK_SEL       61
 #define AUD_CLKID_TDMOUT_A_SCLK_POST_EN        148
 #define AUD_CLKID_TDMOUT_B_SCLK_POST_EN        149
 #define AUD_CLKID_TDMOUT_C_SCLK_POST_EN        150
+#define AUD_CLKID_SPDIFOUT_B_CLK_SEL   153
+#define AUD_CLKID_SPDIFOUT_B_CLK_DIV   154
 
 /* include the CLKIDs which are part of the DT bindings */
 #include <dt-bindings/clock/axg-audio-clkc.h>
 
-#define NR_CLKS        151
+#define NR_CLKS        163
 
 #endif /*__AXG_AUDIO_CLKC_H */
index 7a14ac9b2fecfece592807d72c38043bb84c12e4..ddb1e563473953007288b5585359fe991e9fbffe 100644 (file)
@@ -303,6 +303,16 @@ static int meson_clk_pll_is_enabled(struct clk_hw *hw)
        return 1;
 }
 
+static int meson_clk_pcie_pll_enable(struct clk_hw *hw)
+{
+       meson_clk_pll_init(hw);
+
+       if (meson_clk_pll_wait_lock(hw))
+               return -EIO;
+
+       return 0;
+}
+
 static int meson_clk_pll_enable(struct clk_hw *hw)
 {
        struct clk_regmap *clk = to_clk_regmap(hw);
@@ -387,6 +397,22 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
        return 0;
 }
 
+/*
+ * The Meson G12A PCIE PLL is fined tuned to deliver a very precise
+ * 100MHz reference clock for the PCIe Analog PHY, and thus requires
+ * a strict register sequence to enable the PLL.
+ * To simplify, re-use the _init() op to enable the PLL and keep
+ * the other ops except set_rate since the rate is fixed.
+ */
+const struct clk_ops meson_clk_pcie_pll_ops = {
+       .recalc_rate    = meson_clk_pll_recalc_rate,
+       .round_rate     = meson_clk_pll_round_rate,
+       .is_enabled     = meson_clk_pll_is_enabled,
+       .enable         = meson_clk_pcie_pll_enable,
+       .disable        = meson_clk_pll_disable
+};
+EXPORT_SYMBOL_GPL(meson_clk_pcie_pll_ops);
+
 const struct clk_ops meson_clk_pll_ops = {
        .init           = meson_clk_pll_init,
        .recalc_rate    = meson_clk_pll_recalc_rate,
index 55af2e285b1b0b75bb2f3b3b4608eb6425f0d2ee..367efd0f6410cf68906a9decf59fb153c935ea4b 100644 (file)
@@ -45,5 +45,6 @@ struct meson_clk_pll_data {
 
 extern const struct clk_ops meson_clk_pll_ro_ops;
 extern const struct clk_ops meson_clk_pll_ops;
+extern const struct clk_ops meson_clk_pcie_pll_ops;
 
 #endif /* __MESON_CLK_PLL_H */
index 04b0d55066412d0a4c5fb06cd6e0a24cdb104854..a67c8a7cd7c471cba8ded30e325f8b4fef002341 100644 (file)
@@ -16,9 +16,7 @@
  * to expose, such as the internal muxes and dividers of composite clocks,
  * will remain defined here.
  */
-#define CLKID_AO_SAR_ADC_SEL   16
 #define CLKID_AO_SAR_ADC_DIV   17
-#define CLKID_AO_CTS_OSCIN     19
 #define CLKID_AO_32K_PRE       20
 #define CLKID_AO_32K_DIV       21
 #define CLKID_AO_32K_SEL       22
index f7b11e1eeebe894c26425067fb5cf14cab09a029..739f64fdf1e3bb04a096653b7ac052170dc6699c 100644 (file)
@@ -150,6 +150,318 @@ static struct clk_regmap g12a_sys_pll = {
        },
 };
 
+static struct clk_regmap g12a_sys_pll_div16_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .bit_idx = 24,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "sys_pll_div16_en",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ "sys_pll" },
+               .num_parents = 1,
+               /*
+                * This clock is used to debug the sys_pll range
+                * Linux should not change it at runtime
+                */
+       },
+};
+
+static struct clk_fixed_factor g12a_sys_pll_div16 = {
+       .mult = 1,
+       .div = 16,
+       .hw.init = &(struct clk_init_data){
+               .name = "sys_pll_div16",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "sys_pll_div16_en" },
+               .num_parents = 1,
+       },
+};
+
+/* Datasheet names this field as "premux0" */
+static struct clk_regmap g12a_cpu_clk_premux0 = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x3,
+               .shift = 0,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_dyn0_sel",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal",
+                                                 "fclk_div2",
+                                                 "fclk_div3" },
+               .num_parents = 3,
+       },
+};
+
+/* Datasheet names this field as "mux0_divn_tcnt" */
+static struct clk_regmap g12a_cpu_clk_mux0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .shift = 4,
+               .width = 6,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_dyn0_div",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_dyn0_sel" },
+               .num_parents = 1,
+       },
+};
+
+/* Datasheet names this field as "postmux0" */
+static struct clk_regmap g12a_cpu_clk_postmux0 = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x1,
+               .shift = 2,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_dyn0",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_dyn0_sel",
+                                                 "cpu_clk_dyn0_div" },
+               .num_parents = 2,
+       },
+};
+
+/* Datasheet names this field as "premux1" */
+static struct clk_regmap g12a_cpu_clk_premux1 = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x3,
+               .shift = 16,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_dyn1_sel",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal",
+                                                 "fclk_div2",
+                                                 "fclk_div3" },
+               .num_parents = 3,
+       },
+};
+
+/* Datasheet names this field as "Mux1_divn_tcnt" */
+static struct clk_regmap g12a_cpu_clk_mux1_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .shift = 20,
+               .width = 6,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_dyn1_div",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_dyn1_sel" },
+               .num_parents = 1,
+       },
+};
+
+/* Datasheet names this field as "postmux1" */
+static struct clk_regmap g12a_cpu_clk_postmux1 = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x1,
+               .shift = 18,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_dyn1",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_dyn1_sel",
+                                                 "cpu_clk_dyn1_div" },
+               .num_parents = 2,
+       },
+};
+
+/* Datasheet names this field as "Final_dyn_mux_sel" */
+static struct clk_regmap g12a_cpu_clk_dyn = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x1,
+               .shift = 10,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_dyn",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_dyn0",
+                                                 "cpu_clk_dyn1" },
+               .num_parents = 2,
+       },
+};
+
+/* Datasheet names this field as "Final_mux_sel" */
+static struct clk_regmap g12a_cpu_clk = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x1,
+               .shift = 11,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_dyn",
+                                                 "sys_pll" },
+               .num_parents = 2,
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_div16_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .bit_idx = 1,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "cpu_clk_div16_en",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk" },
+               .num_parents = 1,
+               /*
+                * This clock is used to debug the cpu_clk range
+                * Linux should not change it at runtime
+                */
+       },
+};
+
+static struct clk_fixed_factor g12a_cpu_clk_div16 = {
+       .mult = 1,
+       .div = 16,
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_div16",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "cpu_clk_div16_en" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_apb_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .shift = 3,
+               .width = 3,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_apb_div",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_apb = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .bit_idx = 1,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "cpu_clk_apb",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_apb_div" },
+               .num_parents = 1,
+               /*
+                * This clock is set by the ROM monitor code,
+                * Linux should not change it at runtime
+                */
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_atb_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .shift = 6,
+               .width = 3,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_atb_div",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_atb = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .bit_idx = 17,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "cpu_clk_atb",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_atb_div" },
+               .num_parents = 1,
+               /*
+                * This clock is set by the ROM monitor code,
+                * Linux should not change it at runtime
+                */
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_axi_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .shift = 9,
+               .width = 3,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_axi_div",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_axi = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .bit_idx = 18,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "cpu_clk_axi",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_axi_div" },
+               .num_parents = 1,
+               /*
+                * This clock is set by the ROM monitor code,
+                * Linux should not change it at runtime
+                */
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_trace_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .shift = 20,
+               .width = 3,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_trace_div",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_trace = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .bit_idx = 23,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "cpu_clk_trace",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_trace_div" },
+               .num_parents = 1,
+               /*
+                * This clock is set by the ROM monitor code,
+                * Linux should not change it at runtime
+                */
+       },
+};
+
 static const struct pll_mult_range g12a_gp0_pll_mult_range = {
        .min = 55,
        .max = 255,
@@ -302,6 +614,118 @@ static struct clk_regmap g12a_hifi_pll = {
        },
 };
 
+/*
+ * The Meson G12A PCIE PLL is fined tuned to deliver a very precise
+ * 100MHz reference clock for the PCIe Analog PHY, and thus requires
+ * a strict register sequence to enable the PLL.
+ */
+static const struct reg_sequence g12a_pcie_pll_init_regs[] = {
+       { .reg = HHI_PCIE_PLL_CNTL0,    .def = 0x20090496 },
+       { .reg = HHI_PCIE_PLL_CNTL0,    .def = 0x30090496 },
+       { .reg = HHI_PCIE_PLL_CNTL1,    .def = 0x00000000 },
+       { .reg = HHI_PCIE_PLL_CNTL2,    .def = 0x00001100 },
+       { .reg = HHI_PCIE_PLL_CNTL3,    .def = 0x10058e00 },
+       { .reg = HHI_PCIE_PLL_CNTL4,    .def = 0x000100c0 },
+       { .reg = HHI_PCIE_PLL_CNTL5,    .def = 0x68000048 },
+       { .reg = HHI_PCIE_PLL_CNTL5,    .def = 0x68000068, .delay_us = 20 },
+       { .reg = HHI_PCIE_PLL_CNTL4,    .def = 0x008100c0, .delay_us = 10 },
+       { .reg = HHI_PCIE_PLL_CNTL0,    .def = 0x34090496 },
+       { .reg = HHI_PCIE_PLL_CNTL0,    .def = 0x14090496, .delay_us = 10 },
+       { .reg = HHI_PCIE_PLL_CNTL2,    .def = 0x00001000 },
+};
+
+/* Keep a single entry table for recalc/round_rate() ops */
+static const struct pll_params_table g12a_pcie_pll_table[] = {
+       PLL_PARAMS(150, 1),
+       {0, 0},
+};
+
+static struct clk_regmap g12a_pcie_pll_dco = {
+       .data = &(struct meson_clk_pll_data){
+               .en = {
+                       .reg_off = HHI_PCIE_PLL_CNTL0,
+                       .shift   = 28,
+                       .width   = 1,
+               },
+               .m = {
+                       .reg_off = HHI_PCIE_PLL_CNTL0,
+                       .shift   = 0,
+                       .width   = 8,
+               },
+               .n = {
+                       .reg_off = HHI_PCIE_PLL_CNTL0,
+                       .shift   = 10,
+                       .width   = 5,
+               },
+               .frac = {
+                       .reg_off = HHI_PCIE_PLL_CNTL1,
+                       .shift   = 0,
+                       .width   = 12,
+               },
+               .l = {
+                       .reg_off = HHI_PCIE_PLL_CNTL0,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_PCIE_PLL_CNTL0,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+               .table = g12a_pcie_pll_table,
+               .init_regs = g12a_pcie_pll_init_regs,
+               .init_count = ARRAY_SIZE(g12a_pcie_pll_init_regs),
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "pcie_pll_dco",
+               .ops = &meson_clk_pcie_pll_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor g12a_pcie_pll_dco_div2 = {
+       .mult = 1,
+       .div = 2,
+       .hw.init = &(struct clk_init_data){
+               .name = "pcie_pll_dco_div2",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "pcie_pll_dco" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_pcie_pll_od = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_PCIE_PLL_CNTL0,
+               .shift = 16,
+               .width = 5,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST |
+                        CLK_DIVIDER_ONE_BASED |
+                        CLK_DIVIDER_ALLOW_ZERO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "pcie_pll_od",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "pcie_pll_dco_div2" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_fixed_factor g12a_pcie_pll = {
+       .mult = 1,
+       .div = 2,
+       .hw.init = &(struct clk_init_data){
+               .name = "pcie_pll_pll",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "pcie_pll_od" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
 static struct clk_regmap g12a_hdmi_pll_dco = {
        .data = &(struct meson_clk_pll_data){
                .en = {
@@ -1071,6 +1495,151 @@ static struct clk_regmap g12a_vpu = {
        },
 };
 
+/* VDEC clocks */
+
+static const char * const g12a_vdec_parent_names[] = {
+       "fclk_div2p5", "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7",
+       "hifi_pll", "gp0_pll",
+};
+
+static struct clk_regmap g12a_vdec_1_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VDEC_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 9,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_1_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_vdec_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_vdec_parent_names),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_vdec_1_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VDEC_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_1_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "vdec_1_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_vdec_1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VDEC_CLK_CNTL,
+               .bit_idx = 8,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vdec_1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vdec_1_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_vdec_hevcf_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VDEC2_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 9,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_hevcf_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_vdec_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_vdec_parent_names),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_vdec_hevcf_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VDEC2_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_hevcf_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "vdec_hevcf_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_vdec_hevcf = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VDEC2_CLK_CNTL,
+               .bit_idx = 8,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vdec_hevcf",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vdec_hevcf_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_vdec_hevc_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VDEC2_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 25,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_hevc_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_vdec_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_vdec_parent_names),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_vdec_hevc_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VDEC2_CLK_CNTL,
+               .shift = 16,
+               .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_hevc_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "vdec_hevc_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_vdec_hevc = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VDEC2_CLK_CNTL,
+               .bit_idx = 24,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vdec_hevc",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vdec_hevc_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
 /* VAPB Clock */
 
 static const char * const g12a_vapb_parent_names[] = {
@@ -2167,6 +2736,39 @@ static struct clk_hw_onecell_data g12a_hw_onecell_data = {
                [CLKID_MALI]                    = &g12a_mali.hw,
                [CLKID_MPLL_5OM_DIV]            = &g12a_mpll_50m_div.hw,
                [CLKID_MPLL_5OM]                = &g12a_mpll_50m.hw,
+               [CLKID_SYS_PLL_DIV16_EN]        = &g12a_sys_pll_div16_en.hw,
+               [CLKID_SYS_PLL_DIV16]           = &g12a_sys_pll_div16.hw,
+               [CLKID_CPU_CLK_DYN0_SEL]        = &g12a_cpu_clk_premux0.hw,
+               [CLKID_CPU_CLK_DYN0_DIV]        = &g12a_cpu_clk_mux0_div.hw,
+               [CLKID_CPU_CLK_DYN0]            = &g12a_cpu_clk_postmux0.hw,
+               [CLKID_CPU_CLK_DYN1_SEL]        = &g12a_cpu_clk_premux1.hw,
+               [CLKID_CPU_CLK_DYN1_DIV]        = &g12a_cpu_clk_mux1_div.hw,
+               [CLKID_CPU_CLK_DYN1]            = &g12a_cpu_clk_postmux1.hw,
+               [CLKID_CPU_CLK_DYN]             = &g12a_cpu_clk_dyn.hw,
+               [CLKID_CPU_CLK]                 = &g12a_cpu_clk.hw,
+               [CLKID_CPU_CLK_DIV16_EN]        = &g12a_cpu_clk_div16_en.hw,
+               [CLKID_CPU_CLK_DIV16]           = &g12a_cpu_clk_div16.hw,
+               [CLKID_CPU_CLK_APB_DIV]         = &g12a_cpu_clk_apb_div.hw,
+               [CLKID_CPU_CLK_APB]             = &g12a_cpu_clk_apb.hw,
+               [CLKID_CPU_CLK_ATB_DIV]         = &g12a_cpu_clk_atb_div.hw,
+               [CLKID_CPU_CLK_ATB]             = &g12a_cpu_clk_atb.hw,
+               [CLKID_CPU_CLK_AXI_DIV]         = &g12a_cpu_clk_axi_div.hw,
+               [CLKID_CPU_CLK_AXI]             = &g12a_cpu_clk_axi.hw,
+               [CLKID_CPU_CLK_TRACE_DIV]       = &g12a_cpu_clk_trace_div.hw,
+               [CLKID_CPU_CLK_TRACE]           = &g12a_cpu_clk_trace.hw,
+               [CLKID_PCIE_PLL_DCO]            = &g12a_pcie_pll_dco.hw,
+               [CLKID_PCIE_PLL_DCO_DIV2]       = &g12a_pcie_pll_dco_div2.hw,
+               [CLKID_PCIE_PLL_OD]             = &g12a_pcie_pll_od.hw,
+               [CLKID_PCIE_PLL]                = &g12a_pcie_pll.hw,
+               [CLKID_VDEC_1_SEL]              = &g12a_vdec_1_sel.hw,
+               [CLKID_VDEC_1_DIV]              = &g12a_vdec_1_div.hw,
+               [CLKID_VDEC_1]                  = &g12a_vdec_1.hw,
+               [CLKID_VDEC_HEVC_SEL]           = &g12a_vdec_hevc_sel.hw,
+               [CLKID_VDEC_HEVC_DIV]           = &g12a_vdec_hevc_div.hw,
+               [CLKID_VDEC_HEVC]               = &g12a_vdec_hevc.hw,
+               [CLKID_VDEC_HEVCF_SEL]          = &g12a_vdec_hevcf_sel.hw,
+               [CLKID_VDEC_HEVCF_DIV]          = &g12a_vdec_hevcf_div.hw,
+               [CLKID_VDEC_HEVCF]              = &g12a_vdec_hevcf.hw,
                [NR_CLKS]                       = NULL,
        },
        .num = NR_CLKS,
@@ -2335,6 +2937,35 @@ static struct clk_regmap *const g12a_clk_regmaps[] = {
        &g12a_mali_1,
        &g12a_mali,
        &g12a_mpll_50m,
+       &g12a_sys_pll_div16_en,
+       &g12a_cpu_clk_premux0,
+       &g12a_cpu_clk_mux0_div,
+       &g12a_cpu_clk_postmux0,
+       &g12a_cpu_clk_premux1,
+       &g12a_cpu_clk_mux1_div,
+       &g12a_cpu_clk_postmux1,
+       &g12a_cpu_clk_dyn,
+       &g12a_cpu_clk,
+       &g12a_cpu_clk_div16_en,
+       &g12a_cpu_clk_apb_div,
+       &g12a_cpu_clk_apb,
+       &g12a_cpu_clk_atb_div,
+       &g12a_cpu_clk_atb,
+       &g12a_cpu_clk_axi_div,
+       &g12a_cpu_clk_axi,
+       &g12a_cpu_clk_trace_div,
+       &g12a_cpu_clk_trace,
+       &g12a_pcie_pll_od,
+       &g12a_pcie_pll_dco,
+       &g12a_vdec_1_sel,
+       &g12a_vdec_1_div,
+       &g12a_vdec_1,
+       &g12a_vdec_hevc_sel,
+       &g12a_vdec_hevc_div,
+       &g12a_vdec_hevc,
+       &g12a_vdec_hevcf_sel,
+       &g12a_vdec_hevcf_div,
+       &g12a_vdec_hevcf,
 };
 
 static const struct meson_eeclkc_data g12a_clkc_data = {
index f399dfe1401cd6e9c25aa7039a975121bb29f6e2..39c41af7080446a42302c43e6315493f21f0a29f 100644 (file)
@@ -50,6 +50,7 @@
 #define HHI_GCLK_MPEG2                 0x148
 #define HHI_GCLK_OTHER                 0x150
 #define HHI_GCLK_OTHER2                        0x154
+#define HHI_SYS_CPU_CLK_CNTL1          0x15c
 #define HHI_VID_CLK_DIV                        0x164
 #define HHI_MPEG_CLK_CNTL              0x174
 #define HHI_AUD_CLK_CNTL               0x178
 #define CLKID_MALI_0_DIV                       170
 #define CLKID_MALI_1_DIV                       173
 #define CLKID_MPLL_5OM_DIV                     176
+#define CLKID_SYS_PLL_DIV16_EN                 178
+#define CLKID_SYS_PLL_DIV16                    179
+#define CLKID_CPU_CLK_DYN0_SEL                 180
+#define CLKID_CPU_CLK_DYN0_DIV                 181
+#define CLKID_CPU_CLK_DYN0                     182
+#define CLKID_CPU_CLK_DYN1_SEL                 183
+#define CLKID_CPU_CLK_DYN1_DIV                 184
+#define CLKID_CPU_CLK_DYN1                     185
+#define CLKID_CPU_CLK_DYN                      186
+#define CLKID_CPU_CLK_DIV16_EN                 188
+#define CLKID_CPU_CLK_DIV16                    189
+#define CLKID_CPU_CLK_APB_DIV                  190
+#define CLKID_CPU_CLK_APB                      191
+#define CLKID_CPU_CLK_ATB_DIV                  192
+#define CLKID_CPU_CLK_ATB                      193
+#define CLKID_CPU_CLK_AXI_DIV                  194
+#define CLKID_CPU_CLK_AXI                      195
+#define CLKID_CPU_CLK_TRACE_DIV                        196
+#define CLKID_CPU_CLK_TRACE                    197
+#define CLKID_PCIE_PLL_DCO                     198
+#define CLKID_PCIE_PLL_DCO_DIV2                        199
+#define CLKID_PCIE_PLL_OD                      200
+#define CLKID_VDEC_1_SEL                       202
+#define CLKID_VDEC_1_DIV                       203
+#define CLKID_VDEC_HEVC_SEL                    205
+#define CLKID_VDEC_HEVC_DIV                    206
+#define CLKID_VDEC_HEVCF_SEL                   208
+#define CLKID_VDEC_HEVCF_DIV                   209
 
-#define NR_CLKS                                        178
+#define NR_CLKS                                        211
 
 /* include the CLKIDs that have been made part of the DT binding */
 #include <dt-bindings/clock/g12a-clkc.h>
index 576ad42252d04ec524e093d6e4b3ba686761c112..37cf0f01bb5d952394991d1aa2474f48cdbcb334 100644 (file)
@@ -1703,6 +1703,456 @@ static struct clk_regmap meson8b_mali = {
        },
 };
 
+static const struct pll_params_table meson8m2_gp_pll_params_table[] = {
+       PLL_PARAMS(182, 3),
+       { /* sentinel */ },
+};
+
+static struct clk_regmap meson8m2_gp_pll_dco = {
+       .data = &(struct meson_clk_pll_data){
+               .en = {
+                       .reg_off = HHI_GP_PLL_CNTL,
+                       .shift   = 30,
+                       .width   = 1,
+               },
+               .m = {
+                       .reg_off = HHI_GP_PLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = HHI_GP_PLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .l = {
+                       .reg_off = HHI_GP_PLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_GP_PLL_CNTL,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+               .table = meson8m2_gp_pll_params_table,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "gp_pll_dco",
+               .ops = &meson_clk_pll_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap meson8m2_gp_pll = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_GP_PLL_CNTL,
+               .shift = 16,
+               .width = 2,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "gp_pll",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "gp_pll_dco" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static const char * const mmeson8b_vpu_0_1_parent_names[] = {
+       "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
+};
+
+static const char * const mmeson8m2_vpu_0_1_parent_names[] = {
+       "fclk_div4", "fclk_div3", "fclk_div5", "gp_pll"
+};
+
+static struct clk_regmap meson8b_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_names = mmeson8b_vpu_0_1_parent_names,
+               .num_parents = ARRAY_SIZE(mmeson8b_vpu_0_1_parent_names),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8m2_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_names = mmeson8m2_vpu_0_1_parent_names,
+               .num_parents = ARRAY_SIZE(mmeson8m2_vpu_0_1_parent_names),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_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_names = (const char *[]){ "vpu_0_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_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_names = (const char *[]){ "vpu_0_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_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_names = mmeson8b_vpu_0_1_parent_names,
+               .num_parents = ARRAY_SIZE(mmeson8b_vpu_0_1_parent_names),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8m2_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_names = mmeson8m2_vpu_0_1_parent_names,
+               .num_parents = ARRAY_SIZE(mmeson8m2_vpu_0_1_parent_names),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_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_names = (const char *[]){ "vpu_1_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_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_names = (const char *[]){ "vpu_1_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_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_names = (const char *[]){ "vpu_0", "vpu_1" },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static const char * const meson8b_vdec_parent_names[] = {
+       "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "mpll2", "mpll1"
+};
+
+static struct clk_regmap meson8b_vdec_1_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VDEC_CLK_CNTL,
+               .mask = 0x3,
+               .shift = 9,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_1_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = meson8b_vdec_parent_names,
+               .num_parents = ARRAY_SIZE(meson8b_vdec_parent_names),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_1_1_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VDEC_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_1_1_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "vdec_1_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_1_1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VDEC_CLK_CNTL,
+               .bit_idx = 8,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vdec_1_1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vdec_1_1_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_1_2_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VDEC3_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_1_2_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "vdec_1_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_1_2 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VDEC3_CLK_CNTL,
+               .bit_idx = 8,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vdec_1_2",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vdec_1_2_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_1 = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VDEC3_CLK_CNTL,
+               .mask = 0x1,
+               .shift = 15,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_1",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = (const char *[]){ "vdec_1_1", "vdec_1_2" },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_hcodec_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VDEC_CLK_CNTL,
+               .mask = 0x3,
+               .shift = 25,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_hcodec_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = meson8b_vdec_parent_names,
+               .num_parents = ARRAY_SIZE(meson8b_vdec_parent_names),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_hcodec_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VDEC_CLK_CNTL,
+               .shift = 16,
+               .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_hcodec_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "vdec_hcodec_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_hcodec = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VDEC_CLK_CNTL,
+               .bit_idx = 24,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vdec_hcodec",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vdec_hcodec_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_2_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VDEC2_CLK_CNTL,
+               .mask = 0x3,
+               .shift = 9,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_2_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = meson8b_vdec_parent_names,
+               .num_parents = ARRAY_SIZE(meson8b_vdec_parent_names),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_2_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VDEC2_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_2_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "vdec_2_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_2 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VDEC2_CLK_CNTL,
+               .bit_idx = 8,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vdec_2",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vdec_2_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_hevc_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VDEC2_CLK_CNTL,
+               .mask = 0x3,
+               .shift = 25,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_hevc_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = meson8b_vdec_parent_names,
+               .num_parents = ARRAY_SIZE(meson8b_vdec_parent_names),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_hevc_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VDEC2_CLK_CNTL,
+               .shift = 16,
+               .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_hevc_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "vdec_hevc_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_hevc_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VDEC2_CLK_CNTL,
+               .bit_idx = 24,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vdec_hevc_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vdec_hevc_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_vdec_hevc = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VDEC2_CLK_CNTL,
+               .mask = 0x1,
+               .shift = 31,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vdec_hevc",
+               .ops = &clk_regmap_mux_ops,
+               /* TODO: The second parent is currently unknown */
+               .parent_names = (const char *[]){ "vdec_hevc_en" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
 /* Everything Else (EE) domain gates */
 
 static MESON_GATE(meson8b_ddr, HHI_GCLK_MPEG0, 0);
@@ -1966,6 +2416,22 @@ static struct clk_hw_onecell_data meson8_hw_onecell_data = {
                [CLKID_MALI_0_SEL]          = &meson8b_mali_0_sel.hw,
                [CLKID_MALI_0_DIV]          = &meson8b_mali_0_div.hw,
                [CLKID_MALI]                = &meson8b_mali_0.hw,
+               [CLKID_VPU_0_SEL]           = &meson8b_vpu_0_sel.hw,
+               [CLKID_VPU_0_DIV]           = &meson8b_vpu_0_div.hw,
+               [CLKID_VPU]                 = &meson8b_vpu_0.hw,
+               [CLKID_VDEC_1_SEL]          = &meson8b_vdec_1_sel.hw,
+               [CLKID_VDEC_1_1_DIV]        = &meson8b_vdec_1_1_div.hw,
+               [CLKID_VDEC_1]              = &meson8b_vdec_1_1.hw,
+               [CLKID_VDEC_HCODEC_SEL]     = &meson8b_vdec_hcodec_sel.hw,
+               [CLKID_VDEC_HCODEC_DIV]     = &meson8b_vdec_hcodec_div.hw,
+               [CLKID_VDEC_HCODEC]         = &meson8b_vdec_hcodec.hw,
+               [CLKID_VDEC_2_SEL]          = &meson8b_vdec_2_sel.hw,
+               [CLKID_VDEC_2_DIV]          = &meson8b_vdec_2_div.hw,
+               [CLKID_VDEC_2]              = &meson8b_vdec_2.hw,
+               [CLKID_VDEC_HEVC_SEL]       = &meson8b_vdec_hevc_sel.hw,
+               [CLKID_VDEC_HEVC_DIV]       = &meson8b_vdec_hevc_div.hw,
+               [CLKID_VDEC_HEVC_EN]        = &meson8b_vdec_hevc_en.hw,
+               [CLKID_VDEC_HEVC]           = &meson8b_vdec_hevc.hw,
                [CLK_NR_CLKS]               = NULL,
        },
        .num = CLK_NR_CLKS,
@@ -2152,6 +2618,240 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
                [CLKID_MALI_1_DIV]          = &meson8b_mali_1_div.hw,
                [CLKID_MALI_1]              = &meson8b_mali_1.hw,
                [CLKID_MALI]                = &meson8b_mali.hw,
+               [CLKID_VPU_0_SEL]           = &meson8b_vpu_0_sel.hw,
+               [CLKID_VPU_0_DIV]           = &meson8b_vpu_0_div.hw,
+               [CLKID_VPU_0]               = &meson8b_vpu_0.hw,
+               [CLKID_VPU_1_SEL]           = &meson8b_vpu_1_sel.hw,
+               [CLKID_VPU_1_DIV]           = &meson8b_vpu_1_div.hw,
+               [CLKID_VPU_1]               = &meson8b_vpu_1.hw,
+               [CLKID_VPU]                 = &meson8b_vpu.hw,
+               [CLKID_VDEC_1_SEL]          = &meson8b_vdec_1_sel.hw,
+               [CLKID_VDEC_1_1_DIV]        = &meson8b_vdec_1_1_div.hw,
+               [CLKID_VDEC_1_1]            = &meson8b_vdec_1_1.hw,
+               [CLKID_VDEC_1_2_DIV]        = &meson8b_vdec_1_2_div.hw,
+               [CLKID_VDEC_1_2]            = &meson8b_vdec_1_2.hw,
+               [CLKID_VDEC_1]              = &meson8b_vdec_1.hw,
+               [CLKID_VDEC_HCODEC_SEL]     = &meson8b_vdec_hcodec_sel.hw,
+               [CLKID_VDEC_HCODEC_DIV]     = &meson8b_vdec_hcodec_div.hw,
+               [CLKID_VDEC_HCODEC]         = &meson8b_vdec_hcodec.hw,
+               [CLKID_VDEC_2_SEL]          = &meson8b_vdec_2_sel.hw,
+               [CLKID_VDEC_2_DIV]          = &meson8b_vdec_2_div.hw,
+               [CLKID_VDEC_2]              = &meson8b_vdec_2.hw,
+               [CLKID_VDEC_HEVC_SEL]       = &meson8b_vdec_hevc_sel.hw,
+               [CLKID_VDEC_HEVC_DIV]       = &meson8b_vdec_hevc_div.hw,
+               [CLKID_VDEC_HEVC_EN]        = &meson8b_vdec_hevc_en.hw,
+               [CLKID_VDEC_HEVC]           = &meson8b_vdec_hevc.hw,
+               [CLK_NR_CLKS]               = NULL,
+       },
+       .num = CLK_NR_CLKS,
+};
+
+static struct clk_hw_onecell_data meson8m2_hw_onecell_data = {
+       .hws = {
+               [CLKID_XTAL] = &meson8b_xtal.hw,
+               [CLKID_PLL_FIXED] = &meson8b_fixed_pll.hw,
+               [CLKID_PLL_VID] = &meson8b_vid_pll.hw,
+               [CLKID_PLL_SYS] = &meson8b_sys_pll.hw,
+               [CLKID_FCLK_DIV2] = &meson8b_fclk_div2.hw,
+               [CLKID_FCLK_DIV3] = &meson8b_fclk_div3.hw,
+               [CLKID_FCLK_DIV4] = &meson8b_fclk_div4.hw,
+               [CLKID_FCLK_DIV5] = &meson8b_fclk_div5.hw,
+               [CLKID_FCLK_DIV7] = &meson8b_fclk_div7.hw,
+               [CLKID_CPUCLK] = &meson8b_cpu_clk.hw,
+               [CLKID_MPEG_SEL] = &meson8b_mpeg_clk_sel.hw,
+               [CLKID_MPEG_DIV] = &meson8b_mpeg_clk_div.hw,
+               [CLKID_CLK81] = &meson8b_clk81.hw,
+               [CLKID_DDR]                 = &meson8b_ddr.hw,
+               [CLKID_DOS]                 = &meson8b_dos.hw,
+               [CLKID_ISA]                 = &meson8b_isa.hw,
+               [CLKID_PL301]               = &meson8b_pl301.hw,
+               [CLKID_PERIPHS]             = &meson8b_periphs.hw,
+               [CLKID_SPICC]               = &meson8b_spicc.hw,
+               [CLKID_I2C]                 = &meson8b_i2c.hw,
+               [CLKID_SAR_ADC]             = &meson8b_sar_adc.hw,
+               [CLKID_SMART_CARD]          = &meson8b_smart_card.hw,
+               [CLKID_RNG0]                = &meson8b_rng0.hw,
+               [CLKID_UART0]               = &meson8b_uart0.hw,
+               [CLKID_SDHC]                = &meson8b_sdhc.hw,
+               [CLKID_STREAM]              = &meson8b_stream.hw,
+               [CLKID_ASYNC_FIFO]          = &meson8b_async_fifo.hw,
+               [CLKID_SDIO]                = &meson8b_sdio.hw,
+               [CLKID_ABUF]                = &meson8b_abuf.hw,
+               [CLKID_HIU_IFACE]           = &meson8b_hiu_iface.hw,
+               [CLKID_ASSIST_MISC]         = &meson8b_assist_misc.hw,
+               [CLKID_SPI]                 = &meson8b_spi.hw,
+               [CLKID_I2S_SPDIF]           = &meson8b_i2s_spdif.hw,
+               [CLKID_ETH]                 = &meson8b_eth.hw,
+               [CLKID_DEMUX]               = &meson8b_demux.hw,
+               [CLKID_AIU_GLUE]            = &meson8b_aiu_glue.hw,
+               [CLKID_IEC958]              = &meson8b_iec958.hw,
+               [CLKID_I2S_OUT]             = &meson8b_i2s_out.hw,
+               [CLKID_AMCLK]               = &meson8b_amclk.hw,
+               [CLKID_AIFIFO2]             = &meson8b_aififo2.hw,
+               [CLKID_MIXER]               = &meson8b_mixer.hw,
+               [CLKID_MIXER_IFACE]         = &meson8b_mixer_iface.hw,
+               [CLKID_ADC]                 = &meson8b_adc.hw,
+               [CLKID_BLKMV]               = &meson8b_blkmv.hw,
+               [CLKID_AIU]                 = &meson8b_aiu.hw,
+               [CLKID_UART1]               = &meson8b_uart1.hw,
+               [CLKID_G2D]                 = &meson8b_g2d.hw,
+               [CLKID_USB0]                = &meson8b_usb0.hw,
+               [CLKID_USB1]                = &meson8b_usb1.hw,
+               [CLKID_RESET]               = &meson8b_reset.hw,
+               [CLKID_NAND]                = &meson8b_nand.hw,
+               [CLKID_DOS_PARSER]          = &meson8b_dos_parser.hw,
+               [CLKID_USB]                 = &meson8b_usb.hw,
+               [CLKID_VDIN1]               = &meson8b_vdin1.hw,
+               [CLKID_AHB_ARB0]            = &meson8b_ahb_arb0.hw,
+               [CLKID_EFUSE]               = &meson8b_efuse.hw,
+               [CLKID_BOOT_ROM]            = &meson8b_boot_rom.hw,
+               [CLKID_AHB_DATA_BUS]        = &meson8b_ahb_data_bus.hw,
+               [CLKID_AHB_CTRL_BUS]        = &meson8b_ahb_ctrl_bus.hw,
+               [CLKID_HDMI_INTR_SYNC]      = &meson8b_hdmi_intr_sync.hw,
+               [CLKID_HDMI_PCLK]           = &meson8b_hdmi_pclk.hw,
+               [CLKID_USB1_DDR_BRIDGE]     = &meson8b_usb1_ddr_bridge.hw,
+               [CLKID_USB0_DDR_BRIDGE]     = &meson8b_usb0_ddr_bridge.hw,
+               [CLKID_MMC_PCLK]            = &meson8b_mmc_pclk.hw,
+               [CLKID_DVIN]                = &meson8b_dvin.hw,
+               [CLKID_UART2]               = &meson8b_uart2.hw,
+               [CLKID_SANA]                = &meson8b_sana.hw,
+               [CLKID_VPU_INTR]            = &meson8b_vpu_intr.hw,
+               [CLKID_SEC_AHB_AHB3_BRIDGE] = &meson8b_sec_ahb_ahb3_bridge.hw,
+               [CLKID_CLK81_A9]            = &meson8b_clk81_a9.hw,
+               [CLKID_VCLK2_VENCI0]        = &meson8b_vclk2_venci0.hw,
+               [CLKID_VCLK2_VENCI1]        = &meson8b_vclk2_venci1.hw,
+               [CLKID_VCLK2_VENCP0]        = &meson8b_vclk2_vencp0.hw,
+               [CLKID_VCLK2_VENCP1]        = &meson8b_vclk2_vencp1.hw,
+               [CLKID_GCLK_VENCI_INT]      = &meson8b_gclk_venci_int.hw,
+               [CLKID_GCLK_VENCP_INT]      = &meson8b_gclk_vencp_int.hw,
+               [CLKID_DAC_CLK]             = &meson8b_dac_clk.hw,
+               [CLKID_AOCLK_GATE]          = &meson8b_aoclk_gate.hw,
+               [CLKID_IEC958_GATE]         = &meson8b_iec958_gate.hw,
+               [CLKID_ENC480P]             = &meson8b_enc480p.hw,
+               [CLKID_RNG1]                = &meson8b_rng1.hw,
+               [CLKID_GCLK_VENCL_INT]      = &meson8b_gclk_vencl_int.hw,
+               [CLKID_VCLK2_VENCLMCC]      = &meson8b_vclk2_venclmcc.hw,
+               [CLKID_VCLK2_VENCL]         = &meson8b_vclk2_vencl.hw,
+               [CLKID_VCLK2_OTHER]         = &meson8b_vclk2_other.hw,
+               [CLKID_EDP]                 = &meson8b_edp.hw,
+               [CLKID_AO_MEDIA_CPU]        = &meson8b_ao_media_cpu.hw,
+               [CLKID_AO_AHB_SRAM]         = &meson8b_ao_ahb_sram.hw,
+               [CLKID_AO_AHB_BUS]          = &meson8b_ao_ahb_bus.hw,
+               [CLKID_AO_IFACE]            = &meson8b_ao_iface.hw,
+               [CLKID_MPLL0]               = &meson8b_mpll0.hw,
+               [CLKID_MPLL1]               = &meson8b_mpll1.hw,
+               [CLKID_MPLL2]               = &meson8b_mpll2.hw,
+               [CLKID_MPLL0_DIV]           = &meson8b_mpll0_div.hw,
+               [CLKID_MPLL1_DIV]           = &meson8b_mpll1_div.hw,
+               [CLKID_MPLL2_DIV]           = &meson8b_mpll2_div.hw,
+               [CLKID_CPU_IN_SEL]          = &meson8b_cpu_in_sel.hw,
+               [CLKID_CPU_IN_DIV2]         = &meson8b_cpu_in_div2.hw,
+               [CLKID_CPU_IN_DIV3]         = &meson8b_cpu_in_div3.hw,
+               [CLKID_CPU_SCALE_DIV]       = &meson8b_cpu_scale_div.hw,
+               [CLKID_CPU_SCALE_OUT_SEL]   = &meson8b_cpu_scale_out_sel.hw,
+               [CLKID_MPLL_PREDIV]         = &meson8b_mpll_prediv.hw,
+               [CLKID_FCLK_DIV2_DIV]       = &meson8b_fclk_div2_div.hw,
+               [CLKID_FCLK_DIV3_DIV]       = &meson8b_fclk_div3_div.hw,
+               [CLKID_FCLK_DIV4_DIV]       = &meson8b_fclk_div4_div.hw,
+               [CLKID_FCLK_DIV5_DIV]       = &meson8b_fclk_div5_div.hw,
+               [CLKID_FCLK_DIV7_DIV]       = &meson8b_fclk_div7_div.hw,
+               [CLKID_NAND_SEL]            = &meson8b_nand_clk_sel.hw,
+               [CLKID_NAND_DIV]            = &meson8b_nand_clk_div.hw,
+               [CLKID_NAND_CLK]            = &meson8b_nand_clk_gate.hw,
+               [CLKID_PLL_FIXED_DCO]       = &meson8b_fixed_pll_dco.hw,
+               [CLKID_HDMI_PLL_DCO]        = &meson8b_hdmi_pll_dco.hw,
+               [CLKID_PLL_SYS_DCO]         = &meson8b_sys_pll_dco.hw,
+               [CLKID_CPU_CLK_DIV2]        = &meson8b_cpu_clk_div2.hw,
+               [CLKID_CPU_CLK_DIV3]        = &meson8b_cpu_clk_div3.hw,
+               [CLKID_CPU_CLK_DIV4]        = &meson8b_cpu_clk_div4.hw,
+               [CLKID_CPU_CLK_DIV5]        = &meson8b_cpu_clk_div5.hw,
+               [CLKID_CPU_CLK_DIV6]        = &meson8b_cpu_clk_div6.hw,
+               [CLKID_CPU_CLK_DIV7]        = &meson8b_cpu_clk_div7.hw,
+               [CLKID_CPU_CLK_DIV8]        = &meson8b_cpu_clk_div8.hw,
+               [CLKID_APB_SEL]             = &meson8b_apb_clk_sel.hw,
+               [CLKID_APB]                 = &meson8b_apb_clk_gate.hw,
+               [CLKID_PERIPH_SEL]          = &meson8b_periph_clk_sel.hw,
+               [CLKID_PERIPH]              = &meson8b_periph_clk_gate.hw,
+               [CLKID_AXI_SEL]             = &meson8b_axi_clk_sel.hw,
+               [CLKID_AXI]                 = &meson8b_axi_clk_gate.hw,
+               [CLKID_L2_DRAM_SEL]         = &meson8b_l2_dram_clk_sel.hw,
+               [CLKID_L2_DRAM]             = &meson8b_l2_dram_clk_gate.hw,
+               [CLKID_HDMI_PLL_LVDS_OUT]   = &meson8b_hdmi_pll_lvds_out.hw,
+               [CLKID_HDMI_PLL_HDMI_OUT]   = &meson8b_hdmi_pll_hdmi_out.hw,
+               [CLKID_VID_PLL_IN_SEL]      = &meson8b_vid_pll_in_sel.hw,
+               [CLKID_VID_PLL_IN_EN]       = &meson8b_vid_pll_in_en.hw,
+               [CLKID_VID_PLL_PRE_DIV]     = &meson8b_vid_pll_pre_div.hw,
+               [CLKID_VID_PLL_POST_DIV]    = &meson8b_vid_pll_post_div.hw,
+               [CLKID_VID_PLL_FINAL_DIV]   = &meson8b_vid_pll_final_div.hw,
+               [CLKID_VCLK_IN_SEL]         = &meson8b_vclk_in_sel.hw,
+               [CLKID_VCLK_IN_EN]          = &meson8b_vclk_in_en.hw,
+               [CLKID_VCLK_DIV1]           = &meson8b_vclk_div1_gate.hw,
+               [CLKID_VCLK_DIV2_DIV]       = &meson8b_vclk_div2_div.hw,
+               [CLKID_VCLK_DIV2]           = &meson8b_vclk_div2_div_gate.hw,
+               [CLKID_VCLK_DIV4_DIV]       = &meson8b_vclk_div4_div.hw,
+               [CLKID_VCLK_DIV4]           = &meson8b_vclk_div4_div_gate.hw,
+               [CLKID_VCLK_DIV6_DIV]       = &meson8b_vclk_div6_div.hw,
+               [CLKID_VCLK_DIV6]           = &meson8b_vclk_div6_div_gate.hw,
+               [CLKID_VCLK_DIV12_DIV]      = &meson8b_vclk_div12_div.hw,
+               [CLKID_VCLK_DIV12]          = &meson8b_vclk_div12_div_gate.hw,
+               [CLKID_VCLK2_IN_SEL]        = &meson8b_vclk2_in_sel.hw,
+               [CLKID_VCLK2_IN_EN]         = &meson8b_vclk2_clk_in_en.hw,
+               [CLKID_VCLK2_DIV1]          = &meson8b_vclk2_div1_gate.hw,
+               [CLKID_VCLK2_DIV2_DIV]      = &meson8b_vclk2_div2_div.hw,
+               [CLKID_VCLK2_DIV2]          = &meson8b_vclk2_div2_div_gate.hw,
+               [CLKID_VCLK2_DIV4_DIV]      = &meson8b_vclk2_div4_div.hw,
+               [CLKID_VCLK2_DIV4]          = &meson8b_vclk2_div4_div_gate.hw,
+               [CLKID_VCLK2_DIV6_DIV]      = &meson8b_vclk2_div6_div.hw,
+               [CLKID_VCLK2_DIV6]          = &meson8b_vclk2_div6_div_gate.hw,
+               [CLKID_VCLK2_DIV12_DIV]     = &meson8b_vclk2_div12_div.hw,
+               [CLKID_VCLK2_DIV12]         = &meson8b_vclk2_div12_div_gate.hw,
+               [CLKID_CTS_ENCT_SEL]        = &meson8b_cts_enct_sel.hw,
+               [CLKID_CTS_ENCT]            = &meson8b_cts_enct.hw,
+               [CLKID_CTS_ENCP_SEL]        = &meson8b_cts_encp_sel.hw,
+               [CLKID_CTS_ENCP]            = &meson8b_cts_encp.hw,
+               [CLKID_CTS_ENCI_SEL]        = &meson8b_cts_enci_sel.hw,
+               [CLKID_CTS_ENCI]            = &meson8b_cts_enci.hw,
+               [CLKID_HDMI_TX_PIXEL_SEL]   = &meson8b_hdmi_tx_pixel_sel.hw,
+               [CLKID_HDMI_TX_PIXEL]       = &meson8b_hdmi_tx_pixel.hw,
+               [CLKID_CTS_ENCL_SEL]        = &meson8b_cts_encl_sel.hw,
+               [CLKID_CTS_ENCL]            = &meson8b_cts_encl.hw,
+               [CLKID_CTS_VDAC0_SEL]       = &meson8b_cts_vdac0_sel.hw,
+               [CLKID_CTS_VDAC0]           = &meson8b_cts_vdac0.hw,
+               [CLKID_HDMI_SYS_SEL]        = &meson8b_hdmi_sys_sel.hw,
+               [CLKID_HDMI_SYS_DIV]        = &meson8b_hdmi_sys_div.hw,
+               [CLKID_HDMI_SYS]            = &meson8b_hdmi_sys.hw,
+               [CLKID_MALI_0_SEL]          = &meson8b_mali_0_sel.hw,
+               [CLKID_MALI_0_DIV]          = &meson8b_mali_0_div.hw,
+               [CLKID_MALI_0]              = &meson8b_mali_0.hw,
+               [CLKID_MALI_1_SEL]          = &meson8b_mali_1_sel.hw,
+               [CLKID_MALI_1_DIV]          = &meson8b_mali_1_div.hw,
+               [CLKID_MALI_1]              = &meson8b_mali_1.hw,
+               [CLKID_MALI]                = &meson8b_mali.hw,
+               [CLKID_GP_PLL_DCO]          = &meson8m2_gp_pll_dco.hw,
+               [CLKID_GP_PLL]              = &meson8m2_gp_pll.hw,
+               [CLKID_VPU_0_SEL]           = &meson8m2_vpu_0_sel.hw,
+               [CLKID_VPU_0_DIV]           = &meson8b_vpu_0_div.hw,
+               [CLKID_VPU_0]               = &meson8b_vpu_0.hw,
+               [CLKID_VPU_1_SEL]           = &meson8m2_vpu_1_sel.hw,
+               [CLKID_VPU_1_DIV]           = &meson8b_vpu_1_div.hw,
+               [CLKID_VPU_1]               = &meson8b_vpu_1.hw,
+               [CLKID_VPU]                 = &meson8b_vpu.hw,
+               [CLKID_VDEC_1_SEL]          = &meson8b_vdec_1_sel.hw,
+               [CLKID_VDEC_1_1_DIV]        = &meson8b_vdec_1_1_div.hw,
+               [CLKID_VDEC_1_1]            = &meson8b_vdec_1_1.hw,
+               [CLKID_VDEC_1_2_DIV]        = &meson8b_vdec_1_2_div.hw,
+               [CLKID_VDEC_1_2]            = &meson8b_vdec_1_2.hw,
+               [CLKID_VDEC_1]              = &meson8b_vdec_1.hw,
+               [CLKID_VDEC_HCODEC_SEL]     = &meson8b_vdec_hcodec_sel.hw,
+               [CLKID_VDEC_HCODEC_DIV]     = &meson8b_vdec_hcodec_div.hw,
+               [CLKID_VDEC_HCODEC]         = &meson8b_vdec_hcodec.hw,
+               [CLKID_VDEC_2_SEL]          = &meson8b_vdec_2_sel.hw,
+               [CLKID_VDEC_2_DIV]          = &meson8b_vdec_2_div.hw,
+               [CLKID_VDEC_2]              = &meson8b_vdec_2.hw,
+               [CLKID_VDEC_HEVC_SEL]       = &meson8b_vdec_hevc_sel.hw,
+               [CLKID_VDEC_HEVC_DIV]       = &meson8b_vdec_hevc_div.hw,
+               [CLKID_VDEC_HEVC_EN]        = &meson8b_vdec_hevc_en.hw,
+               [CLKID_VDEC_HEVC]           = &meson8b_vdec_hevc.hw,
                [CLK_NR_CLKS]               = NULL,
        },
        .num = CLK_NR_CLKS,
@@ -2314,6 +3014,33 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
        &meson8b_mali_1_div,
        &meson8b_mali_1,
        &meson8b_mali,
+       &meson8m2_gp_pll_dco,
+       &meson8m2_gp_pll,
+       &meson8b_vpu_0_sel,
+       &meson8m2_vpu_0_sel,
+       &meson8b_vpu_0_div,
+       &meson8b_vpu_0,
+       &meson8b_vpu_1_sel,
+       &meson8m2_vpu_1_sel,
+       &meson8b_vpu_1_div,
+       &meson8b_vpu_1,
+       &meson8b_vpu,
+       &meson8b_vdec_1_sel,
+       &meson8b_vdec_1_1_div,
+       &meson8b_vdec_1_1,
+       &meson8b_vdec_1_2_div,
+       &meson8b_vdec_1_2,
+       &meson8b_vdec_1,
+       &meson8b_vdec_hcodec_sel,
+       &meson8b_vdec_hcodec_div,
+       &meson8b_vdec_hcodec,
+       &meson8b_vdec_2_sel,
+       &meson8b_vdec_2_div,
+       &meson8b_vdec_2,
+       &meson8b_vdec_hevc_sel,
+       &meson8b_vdec_hevc_div,
+       &meson8b_vdec_hevc_en,
+       &meson8b_vdec_hevc,
 };
 
 static const struct meson8b_clk_reset_line {
@@ -2558,9 +3285,14 @@ static void __init meson8b_clkc_init(struct device_node *np)
        return meson8b_clkc_init_common(np, &meson8b_hw_onecell_data);
 }
 
+static void __init meson8m2_clkc_init(struct device_node *np)
+{
+       return meson8b_clkc_init_common(np, &meson8m2_hw_onecell_data);
+}
+
 CLK_OF_DECLARE_DRIVER(meson8_clkc, "amlogic,meson8-clkc",
                      meson8_clkc_init);
 CLK_OF_DECLARE_DRIVER(meson8b_clkc, "amlogic,meson8b-clkc",
                      meson8b_clkc_init);
 CLK_OF_DECLARE_DRIVER(meson8m2_clkc, "amlogic,meson8m2-clkc",
-                     meson8b_clkc_init);
+                     meson8m2_clkc_init);
index b8c58faeae525cf588f36a10f6836a792c2a163f..ed37196187e69e7ad3f181fd911f3565b533cc8a 100644 (file)
@@ -19,6 +19,7 @@
  *
  * [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
  */
+#define HHI_GP_PLL_CNTL                        0x40  /* 0x10 offset in data sheet */
 #define HHI_VIID_CLK_DIV               0x128 /* 0x4a offset in data sheet */
 #define HHI_VIID_CLK_CNTL              0x12c /* 0x4b offset in data sheet */
 #define HHI_GCLK_MPEG0                 0x140 /* 0x50 offset in data sheet */
 #define HHI_VID_DIVIDER_CNTL           0x198 /* 0x66 offset in data sheet */
 #define HHI_SYS_CPU_CLK_CNTL0          0x19c /* 0x67 offset in data sheet */
 #define HHI_MALI_CLK_CNTL              0x1b0 /* 0x6c offset in data sheet */
+#define HHI_VPU_CLK_CNTL               0x1bc /* 0x6f offset in data sheet */
 #define HHI_HDMI_CLK_CNTL              0x1cc /* 0x73 offset in data sheet */
+#define HHI_VDEC_CLK_CNTL              0x1e0 /* 0x78 offset in data sheet */
+#define HHI_VDEC2_CLK_CNTL             0x1e4 /* 0x79 offset in data sheet */
+#define HHI_VDEC3_CLK_CNTL             0x1e8 /* 0x7a offset in data sheet */
 #define HHI_NAND_CLK_CNTL              0x25c /* 0x97 offset in data sheet */
 #define HHI_MPLL_CNTL                  0x280 /* 0xa0 offset in data sheet */
 #define HHI_SYS_PLL_CNTL               0x300 /* 0xc0 offset in data sheet */
 #define CLKID_MALI_1_SEL       178
 #define CLKID_MALI_1_DIV       179
 #define CLKID_MALI_1           180
+#define CLKID_GP_PLL_DCO       181
+#define CLKID_GP_PLL           182
+#define CLKID_VPU_0_SEL                183
+#define CLKID_VPU_0_DIV                184
+#define CLKID_VPU_0            185
+#define CLKID_VPU_1_SEL                186
+#define CLKID_VPU_1_DIV                187
+#define CLKID_VPU_1            189
+#define CLKID_VDEC_1_SEL       191
+#define CLKID_VDEC_1_1_DIV     192
+#define CLKID_VDEC_1_1         193
+#define CLKID_VDEC_1_2_DIV     194
+#define CLKID_VDEC_1_2         195
+#define CLKID_VDEC_HCODEC_SEL  197
+#define CLKID_VDEC_HCODEC_DIV  198
+#define CLKID_VDEC_2_SEL       200
+#define CLKID_VDEC_2_DIV       201
+#define CLKID_VDEC_HEVC_SEL    203
+#define CLKID_VDEC_HEVC_DIV    204
+#define CLKID_VDEC_HEVC_EN     205
 
-#define CLK_NR_CLKS            181
+#define CLK_NR_CLKS            207
 
 /*
  * include the CLKID and RESETID that have
index 7355595c42e21e4249590b40292cc2a814e7002b..1755916ddef2df7cd9e3e0595fcee74ffc3e0802 100644 (file)
@@ -108,7 +108,7 @@ struct clk *mmp_clk_register_gate(struct device *dev, const char *name,
 
        init.name = name;
        init.ops = &mmp_clk_gate_ops;
-       init.flags = flags | CLK_IS_BASIC;
+       init.flags = flags;
        init.parent_names = (parent_name ? &parent_name : NULL);
        init.num_parents = (parent_name ? 1 : 0);
 
index 6ab3c2e627c715fa99a219b19c178e264bd1f8e7..785dbede483543ba9f67a0ba7dcce77ef9a28fdb 100644 (file)
@@ -240,7 +240,7 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
        int n;
 
        if (ctrl) {
-               pr_err("mvebu-clk-gating: cannot instantiate more than one gatable clock device\n");
+               pr_err("mvebu-clk-gating: cannot instantiate more than one gateable clock device\n");
                return;
        }
 
index 9235a331b588068ac717ed66eb0c3db5b89f6f9f..b6de283f45e3739744b293785062cb4670a2f479 100644 (file)
@@ -21,7 +21,7 @@
  *    - Equal to SDIO clock
  *    - 2/5 PLL0
  *
- * CP110 has 32 gatable clocks, for the various peripherals in the IP.
+ * CP110 has 32 gateable clocks, for the various peripherals in the IP.
  */
 
 #define pr_fmt(fmt) "cp110-system-controller: " fmt
@@ -57,7 +57,7 @@ enum {
 #define CP110_CORE_NAND                        4
 #define CP110_CORE_SDIO                        5
 
-/* A number of gatable clocks need special handling */
+/* A number of gateable clocks need special handling */
 #define CP110_GATE_AUDIO               0
 #define CP110_GATE_COMM_UNIT           1
 #define CP110_GATE_NAND                        2
index 27781b49eb8218f8c960d6999176467a545b4ae9..5969f620607a7a1f3c61e741e39966621ef30b93 100644 (file)
@@ -142,7 +142,7 @@ static int lpc18xx_ccu_gate_endisable(struct clk_hw *hw, bool enable)
         * Divider field is write only, so divider stat field must
         * be read so divider field can be set accordingly.
         */
-       val = clk_readl(gate->reg);
+       val = readl(gate->reg);
        if (val & LPC18XX_CCU_DIVSTAT)
                val |= LPC18XX_CCU_DIV;
 
@@ -155,12 +155,12 @@ static int lpc18xx_ccu_gate_endisable(struct clk_hw *hw, bool enable)
                 * and the next write should clear the RUN bit.
                 */
                val |= LPC18XX_CCU_AUTO;
-               clk_writel(val, gate->reg);
+               writel(val, gate->reg);
 
                val &= ~LPC18XX_CCU_RUN;
        }
 
-       clk_writel(val, gate->reg);
+       writel(val, gate->reg);
 
        return 0;
 }
index 2531174b399ea28b4f5dd86f08853f65e2b20dc9..f5bc8bd192b7eb49777266463aee6656fd1c3514 100644 (file)
@@ -352,9 +352,9 @@ static unsigned long lpc18xx_pll0_recalc_rate(struct clk_hw *hw,
        struct lpc18xx_pll *pll = to_lpc_pll(hw);
        u32 ctrl, mdiv, msel, npdiv;
 
-       ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
-       mdiv = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_MDIV);
-       npdiv = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_NP_DIV);
+       ctrl = readl(pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+       mdiv = readl(pll->reg + LPC18XX_CGU_PLL0USB_MDIV);
+       npdiv = readl(pll->reg + LPC18XX_CGU_PLL0USB_NP_DIV);
 
        if (ctrl & LPC18XX_PLL0_CTRL_BYPASS)
                return parent_rate;
@@ -415,25 +415,25 @@ static int lpc18xx_pll0_set_rate(struct clk_hw *hw, unsigned long rate,
        m |= lpc18xx_pll0_msel2seli(m) << LPC18XX_PLL0_MDIV_SELI_SHIFT;
 
        /* Power down PLL, disable clk output and dividers */
-       ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+       ctrl = readl(pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
        ctrl |= LPC18XX_PLL0_CTRL_PD;
        ctrl &= ~(LPC18XX_PLL0_CTRL_BYPASS | LPC18XX_PLL0_CTRL_DIRECTI |
                  LPC18XX_PLL0_CTRL_DIRECTO | LPC18XX_PLL0_CTRL_CLKEN);
-       clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+       writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
 
        /* Configure new PLL settings */
-       clk_writel(m, pll->reg + LPC18XX_CGU_PLL0USB_MDIV);
-       clk_writel(LPC18XX_PLL0_NP_DIVS_1, pll->reg + LPC18XX_CGU_PLL0USB_NP_DIV);
+       writel(m, pll->reg + LPC18XX_CGU_PLL0USB_MDIV);
+       writel(LPC18XX_PLL0_NP_DIVS_1, pll->reg + LPC18XX_CGU_PLL0USB_NP_DIV);
 
        /* Power up PLL and wait for lock */
        ctrl &= ~LPC18XX_PLL0_CTRL_PD;
-       clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+       writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
        do {
                udelay(10);
-               stat = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_STAT);
+               stat = readl(pll->reg + LPC18XX_CGU_PLL0USB_STAT);
                if (stat & LPC18XX_PLL0_STAT_LOCK) {
                        ctrl |= LPC18XX_PLL0_CTRL_CLKEN;
-                       clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+                       writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
 
                        return 0;
                }
@@ -458,8 +458,8 @@ static unsigned long lpc18xx_pll1_recalc_rate(struct clk_hw *hw,
        bool direct, fbsel;
        u32 stat, ctrl;
 
-       stat = clk_readl(pll->reg + LPC18XX_CGU_PLL1_STAT);
-       ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL1_CTRL);
+       stat = readl(pll->reg + LPC18XX_CGU_PLL1_STAT);
+       ctrl = readl(pll->reg + LPC18XX_CGU_PLL1_CTRL);
 
        direct = (ctrl & LPC18XX_PLL1_CTRL_DIRECT) ? true : false;
        fbsel = (ctrl & LPC18XX_PLL1_CTRL_FBSEL) ? true : false;
index 5eeecee17b695c8de0c4c134e3ec03dfea8e6e5b..7524d19fe60b13eedd548fb4401d00304a7c09aa 100644 (file)
@@ -1085,13 +1085,12 @@ struct clk_hw_proto {
        };
 };
 
-#define LPC32XX_DEFINE_FIXED(_idx, _rate, _flags)                      \
+#define LPC32XX_DEFINE_FIXED(_idx, _rate)                      \
 [CLK_PREFIX(_idx)] = {                                                 \
        .type = CLK_FIXED,                                              \
        {                                                               \
                .f = {                                                  \
                        .fixed_rate = (_rate),                          \
-                       .flags = (_flags),                              \
                },                                                      \
        },                                                              \
 }
@@ -1225,7 +1224,7 @@ struct clk_hw_proto {
 }
 
 static struct clk_hw_proto clk_hw_proto[LPC32XX_CLK_HW_MAX] = {
-       LPC32XX_DEFINE_FIXED(RTC, 32768, 0),
+       LPC32XX_DEFINE_FIXED(RTC, 32768),
        LPC32XX_DEFINE_PLL(PLL397X, pll_397x, HCLKPLL_CTRL, BIT(1)),
        LPC32XX_DEFINE_PLL(HCLK_PLL, hclk_pll, HCLKPLL_CTRL, PLL_CTRL_ENABLE),
        LPC32XX_DEFINE_PLL(USB_PLL, usb_pll, USB_CTRL, PLL_CTRL_ENABLE),
@@ -1468,7 +1467,7 @@ static struct clk * __init lpc32xx_clk_register(u32 id)
                struct clk_fixed_rate *fixed = &clk_hw->f;
 
                clk = clk_register_fixed_rate(NULL, lpc32xx_clk->name,
-                       parents[0], fixed->flags, fixed->fixed_rate);
+                       parents[0], 0, fixed->fixed_rate);
                break;
        }
        default:
index 1c04575c118f722c5d94ad28c281bdb1a76ec611..18bdf34d5e647eb276e41a8b57dbfe728f95cfd9 100644 (file)
@@ -243,6 +243,12 @@ config SDM_GCC_660
          Say Y if you want to use peripheral devices such as UART, SPI,
          i2C, USB, UFS, SDDC, PCIe, etc.
 
+config QCS_TURING_404
+       tristate "QCS404 Turing Clock Controller"
+       help
+         Support for the Turing Clock Controller on QCS404, provides clocks
+         and resets for the Turing subsystem.
+
 config SDM_GCC_845
        tristate "SDM845 Global Clock Controller"
        select QCOM_GDSC
index ee8d0698e3707fc539a91b2ab22bad7e1a8ed0ce..f0768fb1f037e1efb683ddbf0412ad24eb364187 100644 (file)
@@ -42,6 +42,7 @@ obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
 obj-$(CONFIG_QCOM_CLK_RPMH) += clk-rpmh.o
 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
 obj-$(CONFIG_QCS_GCC_404) += gcc-qcs404.o
+obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o
 obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o
 obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o
 obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o
index 99446bf630aaad4282669c25c73cf85fcd4f549a..f869fc6aaed64e79e6bd8af7a7d13d18de5a44f2 100644 (file)
@@ -146,6 +146,12 @@ const struct clk_ops clk_branch2_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_branch2_ops);
 
+const struct clk_ops clk_branch2_aon_ops = {
+       .enable = clk_branch2_enable,
+       .is_enabled = clk_is_enabled_regmap,
+};
+EXPORT_SYMBOL_GPL(clk_branch2_aon_ops);
+
 const struct clk_ops clk_branch_simple_ops = {
        .enable = clk_enable_regmap,
        .disable = clk_disable_regmap,
index b3561e0a39842fa2dd71dcc540f6f113206a5346..17a58119165e89018c248a20ddf61da626185120 100644 (file)
@@ -40,6 +40,7 @@ struct clk_branch {
 extern const struct clk_ops clk_branch_ops;
 extern const struct clk_ops clk_branch2_ops;
 extern const struct clk_ops clk_branch_simple_ops;
+extern const struct clk_ops clk_branch2_aon_ops;
 
 #define to_clk_branch(_hw) \
        container_of(to_clk_regmap(_hw), struct clk_branch, clkr)
index 6cd6261be7ac3ba785c53d0c723c9aad9e8bd17b..4df6c8d24c248cc053d3a9cb604da0d5c3af40d2 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2017, Linaro Limited
  * Author: Georgi Djakov <georgi.djakov@linaro.org>
index c240fba794c7a25b882caa3e33fbd3ff386c797a..033688264c7b74503fedeadd9229e98e89866a3f 100644 (file)
@@ -2161,7 +2161,7 @@ static struct clk_branch gcc_pcie_0_mstr_axi_clk = {
 
 static struct clk_branch gcc_pcie_0_pipe_clk = {
        .halt_reg = 0x6b018,
-       .halt_check = BRANCH_HALT,
+       .halt_check = BRANCH_HALT_SKIP,
        .clkr = {
                .enable_reg = 0x6b018,
                .enable_mask = BIT(0),
index 5a62f64ada9305f358e479d08f939a084536729c..a54807eb3b28cab96522032ab03502919dd1372e 100644 (file)
@@ -260,6 +260,20 @@ static const char * const gcc_parent_names_15[] = {
        "core_bi_pll_test_se",
 };
 
+static const struct parent_map gcc_parent_map_16[] = {
+       { P_XO, 0 },
+       { P_GPLL0_OUT_MAIN, 1 },
+       { P_GPLL0_OUT_AUX, 2 },
+       { P_CORE_BI_PLL_TEST_SE, 7 },
+};
+
+static const char * const gcc_parent_names_16[] = {
+       "cxo",
+       "gpll0_out_main",
+       "gpll0_out_aux",
+       "core_bi_pll_test_se",
+};
+
 static struct clk_fixed_factor cxo = {
        .mult = 1,
        .div = 1,
@@ -1194,6 +1208,28 @@ static struct clk_rcg2 vsync_clk_src = {
        },
 };
 
+static const struct freq_tbl ftbl_cdsp_bimc_clk_src[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       F(133333333, P_GPLL0_OUT_MAIN, 6, 0, 0),
+       F(266666667, P_GPLL0_OUT_MAIN, 3, 0, 0),
+       F(320000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cdsp_bimc_clk_src = {
+       .cmd_rcgr = 0x5e010,
+       .mnd_width = 0,
+       .hid_width = 5,
+       .parent_map = gcc_parent_map_16,
+       .freq_tbl = ftbl_cdsp_bimc_clk_src,
+       .clkr.hw.init = &(struct clk_init_data) {
+               .name = "cdsp_bimc_clk_src",
+               .parent_names = gcc_parent_names_16,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
 static struct clk_branch gcc_apss_ahb_clk = {
        .halt_reg = 0x4601c,
        .halt_check = BRANCH_HALT_VOTED,
@@ -1255,6 +1291,24 @@ static struct clk_branch gcc_bimc_gpu_clk = {
        },
 };
 
+static struct clk_branch gcc_bimc_cdsp_clk = {
+       .halt_reg = 0x31030,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x31030,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data) {
+                       .name = "gcc_bimc_cdsp_clk",
+                       .parent_names = (const char *[]) {
+                               "cdsp_bimc_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
 static struct clk_branch gcc_bimc_mdss_clk = {
        .halt_reg = 0x31038,
        .halt_check = BRANCH_HALT,
@@ -1792,6 +1846,24 @@ static struct clk_branch gcc_gfx_tbu_clk = {
        },
 };
 
+static struct clk_branch gcc_cdsp_tbu_clk = {
+       .halt_reg = 0x1203c,
+       .halt_check = BRANCH_VOTED,
+       .clkr = {
+               .enable_reg = 0x13020,
+               .enable_mask = BIT(9),
+               .hw.init = &(struct clk_init_data) {
+                       .name = "gcc_cdsp_tbu_clk",
+                       .parent_names = (const char *[]) {
+                               "cdsp_bimc_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
 static struct clk_branch gcc_gp1_clk = {
        .halt_reg = 0x8000,
        .halt_check = BRANCH_HALT,
@@ -2304,6 +2376,19 @@ static struct clk_branch gcc_sdcc1_ice_core_clk = {
        },
 };
 
+static struct clk_branch gcc_cdsp_cfg_ahb_clk = {
+       .halt_reg = 0x5e004,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x5e004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data) {
+                       .name = "gcc_cdsp_cfg_ahb_cbcr",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
 static struct clk_branch gcc_sdcc2_ahb_clk = {
        .halt_reg = 0x4301c,
        .halt_check = BRANCH_HALT,
@@ -2548,6 +2633,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = {
        [GCC_ESC0_CLK_SRC] = &esc0_clk_src.clkr,
        [GCC_APSS_AHB_CLK] = &gcc_apss_ahb_clk.clkr,
        [GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr,
+       [GCC_BIMC_CDSP_CLK] = &gcc_bimc_cdsp_clk.clkr,
        [GCC_BIMC_MDSS_CLK] = &gcc_bimc_mdss_clk.clkr,
        [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
        [GCC_BLSP1_QUP0_I2C_APPS_CLK] = &gcc_blsp1_qup0_i2c_apps_clk.clkr,
@@ -2605,6 +2691,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = {
        [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
        [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
        [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr,
+       [GCC_CDSP_CFG_AHB_CLK] = &gcc_cdsp_cfg_ahb_clk.clkr,
        [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
        [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
        [GCC_SYS_NOC_USB3_CLK] = &gcc_sys_noc_usb3_clk.clkr,
@@ -2645,6 +2732,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = {
        [GCC_USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr,
        [GCC_USB_HS_SYSTEM_CLK_SRC] = &usb_hs_system_clk_src.clkr,
        [GCC_VSYNC_CLK_SRC] = &vsync_clk_src.clkr,
+       [GCC_CDSP_BIMC_CLK_SRC] = &cdsp_bimc_clk_src.clkr,
        [GCC_USB_HS_INACTIVITY_TIMERS_CLK] =
                        &gcc_usb_hs_inactivity_timers_clk.clkr,
        [GCC_BIMC_GPU_CLK] = &gcc_bimc_gpu_clk.clkr,
@@ -2653,6 +2741,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = {
        [GCC_GFX_TBU_CLK] = &gcc_gfx_tbu_clk.clkr,
        [GCC_SMMU_CFG_CLK] = &gcc_smmu_cfg_clk.clkr,
        [GCC_APSS_TCU_CLK] = &gcc_apss_tcu_clk.clkr,
+       [GCC_CDSP_TBU_CLK] = &gcc_cdsp_tbu_clk.clkr,
        [GCC_CRYPTO_AHB_CLK] = &gcc_crypto_ahb_clk.clkr,
        [GCC_CRYPTO_AXI_CLK] = &gcc_crypto_axi_clk.clkr,
        [GCC_CRYPTO_CLK] = &gcc_crypto_clk.clkr,
@@ -2664,6 +2753,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = {
 
 static const struct qcom_reset_map gcc_qcs404_resets[] = {
        [GCC_GENI_IR_BCR] = { 0x0F000 },
+       [GCC_CDSP_RESTART] = { 0x18000 },
        [GCC_USB_HS_BCR] = { 0x41000 },
        [GCC_USB2_HS_PHY_ONLY_BCR] = { 0x41034 },
        [GCC_QUSB2_PHY_BCR] = { 0x4103c },
diff --git a/drivers/clk/qcom/turingcc-qcs404.c b/drivers/clk/qcom/turingcc-qcs404.c
new file mode 100644 (file)
index 0000000..aa859e6
--- /dev/null
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019, Linaro Ltd.
+ */
+
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,turingcc-qcs404.h>
+
+#include "clk-regmap.h"
+#include "clk-branch.h"
+#include "common.h"
+#include "reset.h"
+
+static struct clk_branch turing_wrapper_aon_cbcr = {
+       .halt_reg = 0x5098,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x5098,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data) {
+                       .name = "turing_wrapper_aon_clk",
+                       .ops = &clk_branch2_aon_ops,
+               },
+       },
+};
+
+static struct clk_branch turing_q6ss_ahbm_aon_cbcr = {
+       .halt_reg = 0x9000,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x9000,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data) {
+                       .name = "turing_q6ss_ahbm_aon_cbcr",
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch turing_q6ss_q6_axim_clk = {
+       .halt_reg = 0xb000,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0xb000,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data) {
+                       .name = "turing_q6ss_q6_axim_clk",
+                       .ops = &clk_branch2_aon_ops,
+               },
+       },
+};
+
+static struct clk_branch turing_q6ss_ahbs_aon_cbcr = {
+       .halt_reg = 0x10000,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x10000,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data) {
+                       .name = "turing_q6ss_ahbs_aon_clk",
+                       .ops = &clk_branch2_aon_ops,
+               },
+       },
+};
+
+static struct clk_branch turing_wrapper_qos_ahbs_aon_cbcr = {
+       .halt_reg = 0x11014,
+       .halt_check = BRANCH_HALT,
+       .clkr = {
+               .enable_reg = 0x11014,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data) {
+                       .name = "turing_wrapper_qos_ahbs_aon_clk",
+                       .ops = &clk_branch2_aon_ops,
+               },
+       },
+};
+
+static struct clk_regmap *turingcc_clocks[] = {
+       [TURING_WRAPPER_AON_CLK] = &turing_wrapper_aon_cbcr.clkr,
+       [TURING_Q6SS_AHBM_AON_CLK] = &turing_q6ss_ahbm_aon_cbcr.clkr,
+       [TURING_Q6SS_Q6_AXIM_CLK] = &turing_q6ss_q6_axim_clk.clkr,
+       [TURING_Q6SS_AHBS_AON_CLK] = &turing_q6ss_ahbs_aon_cbcr.clkr,
+       [TURING_WRAPPER_QOS_AHBS_AON_CLK] = &turing_wrapper_qos_ahbs_aon_cbcr.clkr,
+};
+
+static const struct regmap_config turingcc_regmap_config = {
+       .reg_bits       = 32,
+       .reg_stride     = 4,
+       .val_bits       = 32,
+       .max_register   = 0x30000,
+       .fast_io        = true,
+};
+
+static const struct qcom_cc_desc turingcc_desc = {
+       .config = &turingcc_regmap_config,
+       .clks = turingcc_clocks,
+       .num_clks = ARRAY_SIZE(turingcc_clocks),
+};
+
+static int turingcc_probe(struct platform_device *pdev)
+{
+       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, NULL);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to acquire iface clock\n");
+               goto destroy_pm_clk;
+       }
+
+       ret = qcom_cc_probe(pdev, &turingcc_desc);
+       if (ret < 0)
+               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 int turingcc_remove(struct platform_device *pdev)
+{
+       pm_clk_destroy(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+
+       return 0;
+}
+
+static const struct dev_pm_ops turingcc_pm_ops = {
+       SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
+};
+
+static const struct of_device_id turingcc_match_table[] = {
+       { .compatible = "qcom,qcs404-turingcc" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, turingcc_match_table);
+
+static struct platform_driver turingcc_driver = {
+       .probe          = turingcc_probe,
+       .remove         = turingcc_remove,
+       .driver         = {
+               .name   = "qcs404-turingcc",
+               .of_match_table = turingcc_match_table,
+               .pm = &turingcc_pm_ops,
+       },
+};
+
+module_platform_driver(turingcc_driver);
+
+MODULE_DESCRIPTION("Qualcomm QCS404 Turing Clock Controller");
+MODULE_LICENSE("GPL v2");
index 57c49fe8829567e1909dfa10cc63c63cacfacb1e..cf65d4e0e116664760ba415205126bc58b2ec4c0 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 #include <dt-bindings/clock/r7s9210-cpg-mssr.h>
 #include "renesas-cpg-mssr.h"
 
@@ -119,7 +120,7 @@ static void __init r7s9210_update_clk_table(struct clk *extal_clk,
        if (clk_get_rate(extal_clk) > 12000000)
                cpg_mode = 1;
 
-       frqcr = clk_readl(base + CPG_FRQCR) & 0xFFF;
+       frqcr = readl(base + CPG_FRQCR) & 0xFFF;
        if (frqcr == 0x012)
                index = 0;
        else if (frqcr == 0x112)
index 4d92b27a61538347cabd13e49fa50f8fcbeec958..76ed7d1bae368adc6870aefb88be5acbcef95b69 100644 (file)
@@ -71,8 +71,8 @@ static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = {
        DEF_GEN3_OSC(".r",      CLK_RINT,          CLK_EXTAL,      32),
 
        /* Core Clock Outputs */
-       DEF_BASE("z",           R8A774A1_CLK_Z,     CLK_TYPE_GEN3_Z, CLK_PLL0),
-       DEF_BASE("z2",          R8A774A1_CLK_Z2,    CLK_TYPE_GEN3_Z2, CLK_PLL2),
+       DEF_GEN3_Z("z",         R8A774A1_CLK_Z,     CLK_TYPE_GEN3_Z,  CLK_PLL0, 2, 8),
+       DEF_GEN3_Z("z2",        R8A774A1_CLK_Z2,    CLK_TYPE_GEN3_Z,  CLK_PLL2, 2, 0),
        DEF_FIXED("ztr",        R8A774A1_CLK_ZTR,   CLK_PLL1_DIV2,  6, 1),
        DEF_FIXED("ztrd2",      R8A774A1_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
        DEF_FIXED("zt",         R8A774A1_CLK_ZT,    CLK_PLL1_DIV2,  4, 1),
@@ -123,8 +123,8 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = {
        DEF_MOD("msiof2",                209,   R8A774A1_CLK_MSO),
        DEF_MOD("msiof1",                210,   R8A774A1_CLK_MSO),
        DEF_MOD("msiof0",                211,   R8A774A1_CLK_MSO),
-       DEF_MOD("sys-dmac2",             217,   R8A774A1_CLK_S0D3),
-       DEF_MOD("sys-dmac1",             218,   R8A774A1_CLK_S0D3),
+       DEF_MOD("sys-dmac2",             217,   R8A774A1_CLK_S3D1),
+       DEF_MOD("sys-dmac1",             218,   R8A774A1_CLK_S3D1),
        DEF_MOD("sys-dmac0",             219,   R8A774A1_CLK_S0D3),
        DEF_MOD("cmt3",                  300,   R8A774A1_CLK_R),
        DEF_MOD("cmt2",                  301,   R8A774A1_CLK_R),
@@ -143,8 +143,8 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = {
        DEF_MOD("rwdt",                  402,   R8A774A1_CLK_R),
        DEF_MOD("intc-ex",               407,   R8A774A1_CLK_CP),
        DEF_MOD("intc-ap",               408,   R8A774A1_CLK_S0D3),
-       DEF_MOD("audmac1",               501,   R8A774A1_CLK_S0D3),
-       DEF_MOD("audmac0",               502,   R8A774A1_CLK_S0D3),
+       DEF_MOD("audmac1",               501,   R8A774A1_CLK_S1D2),
+       DEF_MOD("audmac0",               502,   R8A774A1_CLK_S1D2),
        DEF_MOD("hscif4",                516,   R8A774A1_CLK_S3D1),
        DEF_MOD("hscif3",                517,   R8A774A1_CLK_S3D1),
        DEF_MOD("hscif2",                518,   R8A774A1_CLK_S3D1),
@@ -165,9 +165,9 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = {
        DEF_MOD("vspd0",                 623,   R8A774A1_CLK_S0D2),
        DEF_MOD("vspb",                  626,   R8A774A1_CLK_S0D1),
        DEF_MOD("vspi0",                 631,   R8A774A1_CLK_S0D1),
-       DEF_MOD("ehci1",                 702,   R8A774A1_CLK_S3D4),
-       DEF_MOD("ehci0",                 703,   R8A774A1_CLK_S3D4),
-       DEF_MOD("hsusb",                 704,   R8A774A1_CLK_S3D4),
+       DEF_MOD("ehci1",                 702,   R8A774A1_CLK_S3D2),
+       DEF_MOD("ehci0",                 703,   R8A774A1_CLK_S3D2),
+       DEF_MOD("hsusb",                 704,   R8A774A1_CLK_S3D2),
        DEF_MOD("csi20",                 714,   R8A774A1_CLK_CSI0),
        DEF_MOD("csi40",                 716,   R8A774A1_CLK_CSI0),
        DEF_MOD("du2",                   722,   R8A774A1_CLK_S2D1),
index 34e274f2a273a314cf76f764db7bfbaf0b554b7d..f91e7a4847537926e0816efbc79ee62cfbc395e8 100644 (file)
@@ -81,6 +81,7 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = {
        /* Core Clock Outputs */
        DEF_FIXED("za2",       R8A774C0_CLK_ZA2,   CLK_PLL0D24,    1, 1),
        DEF_FIXED("za8",       R8A774C0_CLK_ZA8,   CLK_PLL0D8,     1, 1),
+       DEF_GEN3_Z("z2",       R8A774C0_CLK_Z2,    CLK_TYPE_GEN3_Z, CLK_PLL0, 4, 8),
        DEF_FIXED("ztr",       R8A774C0_CLK_ZTR,   CLK_PLL1,       6, 1),
        DEF_FIXED("zt",        R8A774C0_CLK_ZT,    CLK_PLL1,       4, 1),
        DEF_FIXED("zx",        R8A774C0_CLK_ZX,    CLK_PLL1,       3, 1),
@@ -157,7 +158,7 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = {
        DEF_MOD("intc-ex",               407,   R8A774C0_CLK_CP),
        DEF_MOD("intc-ap",               408,   R8A774C0_CLK_S0D3),
 
-       DEF_MOD("audmac0",               502,   R8A774C0_CLK_S3D4),
+       DEF_MOD("audmac0",               502,   R8A774C0_CLK_S1D2),
        DEF_MOD("hscif4",                516,   R8A774C0_CLK_S3D1C),
        DEF_MOD("hscif3",                517,   R8A774C0_CLK_S3D1C),
        DEF_MOD("hscif2",                518,   R8A774C0_CLK_S3D1C),
@@ -177,8 +178,8 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = {
        DEF_MOD("vspb",                  626,   R8A774C0_CLK_S0D1),
        DEF_MOD("vspi0",                 631,   R8A774C0_CLK_S0D1),
 
-       DEF_MOD("ehci0",                 703,   R8A774C0_CLK_S3D4),
-       DEF_MOD("hsusb",                 704,   R8A774C0_CLK_S3D4),
+       DEF_MOD("ehci0",                 703,   R8A774C0_CLK_S3D2),
+       DEF_MOD("hsusb",                 704,   R8A774C0_CLK_S3D2),
        DEF_MOD("csi40",                 716,   R8A774C0_CLK_CSI0),
        DEF_MOD("du1",                   723,   R8A774C0_CLK_S1D1),
        DEF_MOD("du0",                   724,   R8A774C0_CLK_S1D1),
index 86842c9fd314e9241da9cabc1edf8461d9e05550..9e9a6f2c31e808eb25cfeb800bc5772978deb2bb 100644 (file)
@@ -3,6 +3,7 @@
  * r8a7795 Clock Pulse Generator / Module Standby and Software Reset
  *
  * Copyright (C) 2015 Glider bvba
+ * Copyright (C) 2018-2019 Renesas Electronics Corp.
  *
  * Based on clk-rcar-gen3.c
  *
@@ -73,8 +74,8 @@ static struct cpg_core_clk r8a7795_core_clks[] __initdata = {
        DEF_GEN3_OSC(".r",      CLK_RINT,          CLK_EXTAL,      32),
 
        /* Core Clock Outputs */
-       DEF_BASE("z",           R8A7795_CLK_Z,     CLK_TYPE_GEN3_Z, CLK_PLL0),
-       DEF_BASE("z2",          R8A7795_CLK_Z2,    CLK_TYPE_GEN3_Z2, CLK_PLL2),
+       DEF_GEN3_Z("z",         R8A7795_CLK_Z,     CLK_TYPE_GEN3_Z,  CLK_PLL0, 2, 8),
+       DEF_GEN3_Z("z2",        R8A7795_CLK_Z2,    CLK_TYPE_GEN3_Z,  CLK_PLL2, 2, 0),
        DEF_FIXED("ztr",        R8A7795_CLK_ZTR,   CLK_PLL1_DIV2,  6, 1),
        DEF_FIXED("ztrd2",      R8A7795_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
        DEF_FIXED("zt",         R8A7795_CLK_ZT,    CLK_PLL1_DIV2,  4, 1),
@@ -129,8 +130,8 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
        DEF_MOD("msiof2",                209,   R8A7795_CLK_MSO),
        DEF_MOD("msiof1",                210,   R8A7795_CLK_MSO),
        DEF_MOD("msiof0",                211,   R8A7795_CLK_MSO),
-       DEF_MOD("sys-dmac2",             217,   R8A7795_CLK_S0D3),
-       DEF_MOD("sys-dmac1",             218,   R8A7795_CLK_S0D3),
+       DEF_MOD("sys-dmac2",             217,   R8A7795_CLK_S3D1),
+       DEF_MOD("sys-dmac1",             218,   R8A7795_CLK_S3D1),
        DEF_MOD("sys-dmac0",             219,   R8A7795_CLK_S0D3),
        DEF_MOD("sceg-pub",              229,   R8A7795_CLK_CR),
        DEF_MOD("cmt3",                  300,   R8A7795_CLK_R),
@@ -153,16 +154,16 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
        DEF_MOD("rwdt",                  402,   R8A7795_CLK_R),
        DEF_MOD("intc-ex",               407,   R8A7795_CLK_CP),
        DEF_MOD("intc-ap",               408,   R8A7795_CLK_S0D3),
-       DEF_MOD("audmac1",               501,   R8A7795_CLK_S0D3),
-       DEF_MOD("audmac0",               502,   R8A7795_CLK_S0D3),
-       DEF_MOD("drif7",                 508,   R8A7795_CLK_S3D2),
-       DEF_MOD("drif6",                 509,   R8A7795_CLK_S3D2),
-       DEF_MOD("drif5",                 510,   R8A7795_CLK_S3D2),
-       DEF_MOD("drif4",                 511,   R8A7795_CLK_S3D2),
-       DEF_MOD("drif3",                 512,   R8A7795_CLK_S3D2),
-       DEF_MOD("drif2",                 513,   R8A7795_CLK_S3D2),
-       DEF_MOD("drif1",                 514,   R8A7795_CLK_S3D2),
-       DEF_MOD("drif0",                 515,   R8A7795_CLK_S3D2),
+       DEF_MOD("audmac1",               501,   R8A7795_CLK_S1D2),
+       DEF_MOD("audmac0",               502,   R8A7795_CLK_S1D2),
+       DEF_MOD("drif31",                508,   R8A7795_CLK_S3D2),
+       DEF_MOD("drif30",                509,   R8A7795_CLK_S3D2),
+       DEF_MOD("drif21",                510,   R8A7795_CLK_S3D2),
+       DEF_MOD("drif20",                511,   R8A7795_CLK_S3D2),
+       DEF_MOD("drif11",                512,   R8A7795_CLK_S3D2),
+       DEF_MOD("drif10",                513,   R8A7795_CLK_S3D2),
+       DEF_MOD("drif01",                514,   R8A7795_CLK_S3D2),
+       DEF_MOD("drif00",                515,   R8A7795_CLK_S3D2),
        DEF_MOD("hscif4",                516,   R8A7795_CLK_S3D1),
        DEF_MOD("hscif3",                517,   R8A7795_CLK_S3D1),
        DEF_MOD("hscif2",                518,   R8A7795_CLK_S3D1),
@@ -194,12 +195,12 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
        DEF_MOD("vspi2",                 629,   R8A7795_CLK_S2D1), /* ES1.x */
        DEF_MOD("vspi1",                 630,   R8A7795_CLK_S0D1),
        DEF_MOD("vspi0",                 631,   R8A7795_CLK_S0D1),
-       DEF_MOD("ehci3",                 700,   R8A7795_CLK_S3D4),
-       DEF_MOD("ehci2",                 701,   R8A7795_CLK_S3D4),
-       DEF_MOD("ehci1",                 702,   R8A7795_CLK_S3D4),
-       DEF_MOD("ehci0",                 703,   R8A7795_CLK_S3D4),
-       DEF_MOD("hsusb",                 704,   R8A7795_CLK_S3D4),
-       DEF_MOD("hsusb3",                705,   R8A7795_CLK_S3D4),
+       DEF_MOD("ehci3",                 700,   R8A7795_CLK_S3D2),
+       DEF_MOD("ehci2",                 701,   R8A7795_CLK_S3D2),
+       DEF_MOD("ehci1",                 702,   R8A7795_CLK_S3D2),
+       DEF_MOD("ehci0",                 703,   R8A7795_CLK_S3D2),
+       DEF_MOD("hsusb",                 704,   R8A7795_CLK_S3D2),
+       DEF_MOD("hsusb3",                705,   R8A7795_CLK_S3D2),
        DEF_MOD("csi21",                 713,   R8A7795_CLK_CSI0), /* ES1.x */
        DEF_MOD("csi20",                 714,   R8A7795_CLK_CSI0),
        DEF_MOD("csi41",                 715,   R8A7795_CLK_CSI0),
index 12c455859f2c28f2d97fc149d39304897b445913..d8e9af5d9ae9cf6e12b282eb9a10f3f169b4d07e 100644 (file)
@@ -3,6 +3,7 @@
  * r8a7796 Clock Pulse Generator / Module Standby and Software Reset
  *
  * Copyright (C) 2016 Glider bvba
+ * Copyright (C) 2018 Renesas Electronics Corp.
  *
  * Based on r8a7795-cpg-mssr.c
  *
@@ -73,8 +74,8 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
        DEF_GEN3_OSC(".r",      CLK_RINT,          CLK_EXTAL,      32),
 
        /* Core Clock Outputs */
-       DEF_BASE("z",           R8A7796_CLK_Z,     CLK_TYPE_GEN3_Z, CLK_PLL0),
-       DEF_BASE("z2",          R8A7796_CLK_Z2,    CLK_TYPE_GEN3_Z2, CLK_PLL2),
+       DEF_GEN3_Z("z",         R8A7796_CLK_Z,     CLK_TYPE_GEN3_Z,  CLK_PLL0, 2, 8),
+       DEF_GEN3_Z("z2",        R8A7796_CLK_Z2,    CLK_TYPE_GEN3_Z,  CLK_PLL2, 2, 0),
        DEF_FIXED("ztr",        R8A7796_CLK_ZTR,   CLK_PLL1_DIV2,  6, 1),
        DEF_FIXED("ztrd2",      R8A7796_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
        DEF_FIXED("zt",         R8A7796_CLK_ZT,    CLK_PLL1_DIV2,  4, 1),
@@ -126,8 +127,8 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
        DEF_MOD("msiof2",                209,   R8A7796_CLK_MSO),
        DEF_MOD("msiof1",                210,   R8A7796_CLK_MSO),
        DEF_MOD("msiof0",                211,   R8A7796_CLK_MSO),
-       DEF_MOD("sys-dmac2",             217,   R8A7796_CLK_S0D3),
-       DEF_MOD("sys-dmac1",             218,   R8A7796_CLK_S0D3),
+       DEF_MOD("sys-dmac2",             217,   R8A7796_CLK_S3D1),
+       DEF_MOD("sys-dmac1",             218,   R8A7796_CLK_S3D1),
        DEF_MOD("sys-dmac0",             219,   R8A7796_CLK_S0D3),
        DEF_MOD("cmt3",                  300,   R8A7796_CLK_R),
        DEF_MOD("cmt2",                  301,   R8A7796_CLK_R),
@@ -146,16 +147,16 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
        DEF_MOD("rwdt",                  402,   R8A7796_CLK_R),
        DEF_MOD("intc-ex",               407,   R8A7796_CLK_CP),
        DEF_MOD("intc-ap",               408,   R8A7796_CLK_S0D3),
-       DEF_MOD("audmac1",               501,   R8A7796_CLK_S0D3),
-       DEF_MOD("audmac0",               502,   R8A7796_CLK_S0D3),
-       DEF_MOD("drif7",                 508,   R8A7796_CLK_S3D2),
-       DEF_MOD("drif6",                 509,   R8A7796_CLK_S3D2),
-       DEF_MOD("drif5",                 510,   R8A7796_CLK_S3D2),
-       DEF_MOD("drif4",                 511,   R8A7796_CLK_S3D2),
-       DEF_MOD("drif3",                 512,   R8A7796_CLK_S3D2),
-       DEF_MOD("drif2",                 513,   R8A7796_CLK_S3D2),
-       DEF_MOD("drif1",                 514,   R8A7796_CLK_S3D2),
-       DEF_MOD("drif0",                 515,   R8A7796_CLK_S3D2),
+       DEF_MOD("audmac1",               501,   R8A7796_CLK_S1D2),
+       DEF_MOD("audmac0",               502,   R8A7796_CLK_S1D2),
+       DEF_MOD("drif31",                508,   R8A7796_CLK_S3D2),
+       DEF_MOD("drif30",                509,   R8A7796_CLK_S3D2),
+       DEF_MOD("drif21",                510,   R8A7796_CLK_S3D2),
+       DEF_MOD("drif20",                511,   R8A7796_CLK_S3D2),
+       DEF_MOD("drif11",                512,   R8A7796_CLK_S3D2),
+       DEF_MOD("drif10",                513,   R8A7796_CLK_S3D2),
+       DEF_MOD("drif01",                514,   R8A7796_CLK_S3D2),
+       DEF_MOD("drif00",                515,   R8A7796_CLK_S3D2),
        DEF_MOD("hscif4",                516,   R8A7796_CLK_S3D1),
        DEF_MOD("hscif3",                517,   R8A7796_CLK_S3D1),
        DEF_MOD("hscif2",                518,   R8A7796_CLK_S3D1),
@@ -176,9 +177,9 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
        DEF_MOD("vspd0",                 623,   R8A7796_CLK_S0D2),
        DEF_MOD("vspb",                  626,   R8A7796_CLK_S0D1),
        DEF_MOD("vspi0",                 631,   R8A7796_CLK_S0D1),
-       DEF_MOD("ehci1",                 702,   R8A7796_CLK_S3D4),
-       DEF_MOD("ehci0",                 703,   R8A7796_CLK_S3D4),
-       DEF_MOD("hsusb",                 704,   R8A7796_CLK_S3D4),
+       DEF_MOD("ehci1",                 702,   R8A7796_CLK_S3D2),
+       DEF_MOD("ehci0",                 703,   R8A7796_CLK_S3D2),
+       DEF_MOD("hsusb",                 704,   R8A7796_CLK_S3D2),
        DEF_MOD("csi20",                 714,   R8A7796_CLK_CSI0),
        DEF_MOD("csi40",                 716,   R8A7796_CLK_CSI0),
        DEF_MOD("du2",                   722,   R8A7796_CLK_S2D1),
index eb1cca58a1e1ff079d7a37d6ada2350689144b56..8f87e314d94904986baf1234413786c82ff81c3f 100644 (file)
@@ -3,6 +3,7 @@
  * r8a77965 Clock Pulse Generator / Module Standby and Software Reset
  *
  * Copyright (C) 2018 Jacopo Mondi <jacopo+renesas@jmondi.org>
+ * Copyright (C) 2019 Renesas Electronics Corp.
  *
  * Based on r8a7795-cpg-mssr.c
  *
@@ -71,7 +72,7 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = {
        DEF_GEN3_OSC(".r",      CLK_RINT,               CLK_EXTAL,      32),
 
        /* Core Clock Outputs */
-       DEF_BASE("z",           R8A77965_CLK_Z,         CLK_TYPE_GEN3_Z, CLK_PLL0),
+       DEF_GEN3_Z("z",         R8A77965_CLK_Z,         CLK_TYPE_GEN3_Z,  CLK_PLL0, 2, 8),
        DEF_FIXED("ztr",        R8A77965_CLK_ZTR,       CLK_PLL1_DIV2,  6, 1),
        DEF_FIXED("ztrd2",      R8A77965_CLK_ZTRD2,     CLK_PLL1_DIV2,  12, 1),
        DEF_FIXED("zt",         R8A77965_CLK_ZT,        CLK_PLL1_DIV2,  4, 1),
@@ -123,8 +124,8 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = {
        DEF_MOD("msiof2",               209,    R8A77965_CLK_MSO),
        DEF_MOD("msiof1",               210,    R8A77965_CLK_MSO),
        DEF_MOD("msiof0",               211,    R8A77965_CLK_MSO),
-       DEF_MOD("sys-dmac2",            217,    R8A77965_CLK_S0D3),
-       DEF_MOD("sys-dmac1",            218,    R8A77965_CLK_S0D3),
+       DEF_MOD("sys-dmac2",            217,    R8A77965_CLK_S3D1),
+       DEF_MOD("sys-dmac1",            218,    R8A77965_CLK_S3D1),
        DEF_MOD("sys-dmac0",            219,    R8A77965_CLK_S0D3),
 
        DEF_MOD("cmt3",                 300,    R8A77965_CLK_R),
@@ -146,16 +147,16 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = {
        DEF_MOD("intc-ex",              407,    R8A77965_CLK_CP),
        DEF_MOD("intc-ap",              408,    R8A77965_CLK_S0D3),
 
-       DEF_MOD("audmac1",              501,    R8A77965_CLK_S0D3),
-       DEF_MOD("audmac0",              502,    R8A77965_CLK_S0D3),
-       DEF_MOD("drif7",                508,    R8A77965_CLK_S3D2),
-       DEF_MOD("drif6",                509,    R8A77965_CLK_S3D2),
-       DEF_MOD("drif5",                510,    R8A77965_CLK_S3D2),
-       DEF_MOD("drif4",                511,    R8A77965_CLK_S3D2),
-       DEF_MOD("drif3",                512,    R8A77965_CLK_S3D2),
-       DEF_MOD("drif2",                513,    R8A77965_CLK_S3D2),
-       DEF_MOD("drif1",                514,    R8A77965_CLK_S3D2),
-       DEF_MOD("drif0",                515,    R8A77965_CLK_S3D2),
+       DEF_MOD("audmac1",              501,    R8A77965_CLK_S1D2),
+       DEF_MOD("audmac0",              502,    R8A77965_CLK_S1D2),
+       DEF_MOD("drif31",               508,    R8A77965_CLK_S3D2),
+       DEF_MOD("drif30",               509,    R8A77965_CLK_S3D2),
+       DEF_MOD("drif21",               510,    R8A77965_CLK_S3D2),
+       DEF_MOD("drif20",               511,    R8A77965_CLK_S3D2),
+       DEF_MOD("drif11",               512,    R8A77965_CLK_S3D2),
+       DEF_MOD("drif10",               513,    R8A77965_CLK_S3D2),
+       DEF_MOD("drif01",               514,    R8A77965_CLK_S3D2),
+       DEF_MOD("drif00",               515,    R8A77965_CLK_S3D2),
        DEF_MOD("hscif4",               516,    R8A77965_CLK_S3D1),
        DEF_MOD("hscif3",               517,    R8A77965_CLK_S3D1),
        DEF_MOD("hscif2",               518,    R8A77965_CLK_S3D1),
@@ -175,9 +176,9 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = {
        DEF_MOD("vspb",                 626,    R8A77965_CLK_S0D1),
        DEF_MOD("vspi0",                631,    R8A77965_CLK_S0D1),
 
-       DEF_MOD("ehci1",                702,    R8A77965_CLK_S3D4),
-       DEF_MOD("ehci0",                703,    R8A77965_CLK_S3D4),
-       DEF_MOD("hsusb",                704,    R8A77965_CLK_S3D4),
+       DEF_MOD("ehci1",                702,    R8A77965_CLK_S3D2),
+       DEF_MOD("ehci0",                703,    R8A77965_CLK_S3D2),
+       DEF_MOD("hsusb",                704,    R8A77965_CLK_S3D2),
        DEF_MOD("csi20",                714,    R8A77965_CLK_CSI0),
        DEF_MOD("csi40",                716,    R8A77965_CLK_CSI0),
        DEF_MOD("du3",                  721,    R8A77965_CLK_S2D1),
index f9e07fcc0d96f6ed9826bb2daee1c005984dd429..7227f675e61ffdb1cdd084f59b532745f9c674f1 100644 (file)
@@ -171,7 +171,7 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = {
        DEF_MOD("gpio1",                 911,   R8A77980_CLK_CP),
        DEF_MOD("gpio0",                 912,   R8A77980_CLK_CP),
        DEF_MOD("can-fd",                914,   R8A77980_CLK_S3D2),
-       DEF_MOD("rpc-if",                917,   R8A77980_CLK_RPC),
+       DEF_MOD("rpc-if",                917,   R8A77980_CLK_RPCD2),
        DEF_MOD("i2c4",                  927,   R8A77980_CLK_S0D6),
        DEF_MOD("i2c3",                  928,   R8A77980_CLK_S0D6),
        DEF_MOD("i2c2",                  929,   R8A77980_CLK_S3D2),
index 9a278c75c918cfa8cc095163510b407883b919d0..9570404baa583a8f501ec3a9d47dad733cf60114 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * r8a77990 Clock Pulse Generator / Module Standby and Software Reset
  *
- * Copyright (C) 2018 Renesas Electronics Corp.
+ * Copyright (C) 2018-2019 Renesas Electronics Corp.
  *
  * Based on r8a7795-cpg-mssr.c
  *
@@ -81,6 +81,7 @@ static const struct cpg_core_clk r8a77990_core_clks[] __initconst = {
        /* Core Clock Outputs */
        DEF_FIXED("za2",       R8A77990_CLK_ZA2,   CLK_PLL0D24,    1, 1),
        DEF_FIXED("za8",       R8A77990_CLK_ZA8,   CLK_PLL0D8,     1, 1),
+       DEF_GEN3_Z("z2",       R8A77990_CLK_Z2,    CLK_TYPE_GEN3_Z, CLK_PLL0, 4, 8),
        DEF_FIXED("ztr",       R8A77990_CLK_ZTR,   CLK_PLL1,       6, 1),
        DEF_FIXED("zt",        R8A77990_CLK_ZT,    CLK_PLL1,       4, 1),
        DEF_FIXED("zx",        R8A77990_CLK_ZX,    CLK_PLL1,       3, 1),
@@ -152,15 +153,15 @@ static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = {
        DEF_MOD("intc-ex",               407,   R8A77990_CLK_CP),
        DEF_MOD("intc-ap",               408,   R8A77990_CLK_S0D3),
 
-       DEF_MOD("audmac0",               502,   R8A77990_CLK_S3D4),
-       DEF_MOD("drif7",                 508,   R8A77990_CLK_S3D2),
-       DEF_MOD("drif6",                 509,   R8A77990_CLK_S3D2),
-       DEF_MOD("drif5",                 510,   R8A77990_CLK_S3D2),
-       DEF_MOD("drif4",                 511,   R8A77990_CLK_S3D2),
-       DEF_MOD("drif3",                 512,   R8A77990_CLK_S3D2),
-       DEF_MOD("drif2",                 513,   R8A77990_CLK_S3D2),
-       DEF_MOD("drif1",                 514,   R8A77990_CLK_S3D2),
-       DEF_MOD("drif0",                 515,   R8A77990_CLK_S3D2),
+       DEF_MOD("audmac0",               502,   R8A77990_CLK_S1D2),
+       DEF_MOD("drif31",                508,   R8A77990_CLK_S3D2),
+       DEF_MOD("drif30",                509,   R8A77990_CLK_S3D2),
+       DEF_MOD("drif21",                510,   R8A77990_CLK_S3D2),
+       DEF_MOD("drif20",                511,   R8A77990_CLK_S3D2),
+       DEF_MOD("drif11",                512,   R8A77990_CLK_S3D2),
+       DEF_MOD("drif10",                513,   R8A77990_CLK_S3D2),
+       DEF_MOD("drif01",                514,   R8A77990_CLK_S3D2),
+       DEF_MOD("drif00",                515,   R8A77990_CLK_S3D2),
        DEF_MOD("hscif4",                516,   R8A77990_CLK_S3D1C),
        DEF_MOD("hscif3",                517,   R8A77990_CLK_S3D1C),
        DEF_MOD("hscif2",                518,   R8A77990_CLK_S3D1C),
@@ -180,8 +181,8 @@ static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = {
        DEF_MOD("vspb",                  626,   R8A77990_CLK_S0D1),
        DEF_MOD("vspi0",                 631,   R8A77990_CLK_S0D1),
 
-       DEF_MOD("ehci0",                 703,   R8A77990_CLK_S3D4),
-       DEF_MOD("hsusb",                 704,   R8A77990_CLK_S3D4),
+       DEF_MOD("ehci0",                 703,   R8A77990_CLK_S3D2),
+       DEF_MOD("hsusb",                 704,   R8A77990_CLK_S3D2),
        DEF_MOD("csi40",                 716,   R8A77990_CLK_CSI0),
        DEF_MOD("du1",                   723,   R8A77990_CLK_S1D1),
        DEF_MOD("du0",                   724,   R8A77990_CLK_S1D1),
index eee3874865a95b1a2007a6c1ccb7244a5e030c0f..68707277b17b42c4267ff893ede58dd00b0021fd 100644 (file)
@@ -133,7 +133,7 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = {
        DEF_MOD("rwdt",                  402,   R8A77995_CLK_R),
        DEF_MOD("intc-ex",               407,   R8A77995_CLK_CP),
        DEF_MOD("intc-ap",               408,   R8A77995_CLK_S1D2),
-       DEF_MOD("audmac0",               502,   R8A77995_CLK_S3D1),
+       DEF_MOD("audmac0",               502,   R8A77995_CLK_S1D2),
        DEF_MOD("hscif3",                517,   R8A77995_CLK_S3D1C),
        DEF_MOD("hscif0",                520,   R8A77995_CLK_S3D1C),
        DEF_MOD("thermal",               522,   R8A77995_CLK_CP),
index 658cb11b6f55cd0701a4c2d3dab1b3adea943804..97c72477cd54aba0ca92a4f37b12e82354cb41ea 100644 (file)
@@ -170,6 +170,7 @@ static const struct r9a06g032_clkdesc r9a06g032_clocks[] __initconst = {
        D_GATE(CLK_P6_PG2, "clk_p6_pg2", DIV_P6_PG, 0x8a3, 0x8a4, 0x8a5, 0, 0xb61, 0, 0),
        D_GATE(CLK_P6_PG3, "clk_p6_pg3", DIV_P6_PG, 0x8a6, 0x8a7, 0x8a8, 0, 0xb62, 0, 0),
        D_GATE(CLK_P6_PG4, "clk_p6_pg4", DIV_P6_PG, 0x8a9, 0x8aa, 0x8ab, 0, 0xb63, 0, 0),
+       D_GATE(CLK_PCI_USB, "clk_pci_usb", CLKOUT_D40, 0xe6, 0, 0, 0, 0, 0, 0),
        D_GATE(CLK_QSPI0, "clk_qspi0", DIV_QSPI0, 0x2a4, 0x2a5, 0, 0, 0, 0, 0),
        D_GATE(CLK_QSPI1, "clk_qspi1", DIV_QSPI1, 0x484, 0x485, 0, 0, 0, 0, 0),
        D_GATE(CLK_RGMII_REF, "clk_rgmii_ref", CLKOUT_D8, 0x340, 0, 0, 0, 0, 0, 0),
index bff9551c7a38a01e90506cc8f424a9b267cb981a..db2f57ef2f9984e4a5ff55a6a42906890f285361 100644 (file)
@@ -1,5 +1,5 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
  * R-Car Gen2 Clock Pulse Generator
  *
  * Copyright (C) 2016 Cogent Embedded Inc.
index 9a8071a8114daec9b456f50a6a2966ed16d89887..d25c8ba00a65684185a6a6b0f44de1f425709b58 100644 (file)
@@ -3,6 +3,7 @@
  * R-Car Gen3 Clock Pulse Generator
  *
  * Copyright (C) 2015-2018 Glider bvba
+ * Copyright (C) 2019 Renesas Electronics Corp.
  *
  * Based on clk-rcar-gen3.c
  *
@@ -88,14 +89,13 @@ static void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
 #define CPG_FRQCRB                     0x00000004
 #define CPG_FRQCRB_KICK                        BIT(31)
 #define CPG_FRQCRC                     0x000000e0
-#define CPG_FRQCRC_ZFC_MASK            GENMASK(12, 8)
-#define CPG_FRQCRC_Z2FC_MASK           GENMASK(4, 0)
 
 struct cpg_z_clk {
        struct clk_hw hw;
        void __iomem *reg;
        void __iomem *kick_reg;
        unsigned long mask;
+       unsigned int fixed_div;
 };
 
 #define to_z_clk(_hw)  container_of(_hw, struct cpg_z_clk, hw)
@@ -110,17 +110,18 @@ static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
        val = readl(zclk->reg) & zclk->mask;
        mult = 32 - (val >> __ffs(zclk->mask));
 
-       /* Factor of 2 is for fixed divider */
-       return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult, 32 * 2);
+       return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult,
+                                    32 * zclk->fixed_div);
 }
 
 static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
                                 unsigned long *parent_rate)
 {
-       /* Factor of 2 is for fixed divider */
-       unsigned long prate = *parent_rate / 2;
+       struct cpg_z_clk *zclk = to_z_clk(hw);
+       unsigned long prate;
        unsigned int mult;
 
+       prate = *parent_rate / zclk->fixed_div;
        mult = div_u64(rate * 32ULL, prate);
        mult = clamp(mult, 1U, 32U);
 
@@ -134,8 +135,8 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
        unsigned int mult;
        unsigned int i;
 
-       /* Factor of 2 is for fixed divider */
-       mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL * 2, parent_rate);
+       mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div,
+                                      parent_rate);
        mult = clamp(mult, 1U, 32U);
 
        if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
@@ -178,7 +179,8 @@ static const struct clk_ops cpg_z_clk_ops = {
 static struct clk * __init cpg_z_clk_register(const char *name,
                                              const char *parent_name,
                                              void __iomem *reg,
-                                             unsigned long mask)
+                                             unsigned int div,
+                                             unsigned int offset)
 {
        struct clk_init_data init;
        struct cpg_z_clk *zclk;
@@ -197,7 +199,8 @@ static struct clk * __init cpg_z_clk_register(const char *name,
        zclk->reg = reg + CPG_FRQCRC;
        zclk->kick_reg = reg + CPG_FRQCRB;
        zclk->hw.init = &init;
-       zclk->mask = mask;
+       zclk->mask = GENMASK(offset + 4, offset);
+       zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */
 
        clk = clk_register(NULL, &zclk->hw);
        if (IS_ERR(clk))
@@ -234,8 +237,6 @@ struct sd_clock {
        const struct sd_div_table *div_table;
        struct cpg_simple_notifier csn;
        unsigned int div_num;
-       unsigned int div_min;
-       unsigned int div_max;
        unsigned int cur_div_idx;
 };
 
@@ -312,14 +313,20 @@ static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock,
                                          unsigned long rate,
                                          unsigned long parent_rate)
 {
-       unsigned int div;
-
-       if (!rate)
-               rate = 1;
-
-       div = DIV_ROUND_CLOSEST(parent_rate, rate);
+       unsigned long calc_rate, diff, diff_min = ULONG_MAX;
+       unsigned int i, best_div = 0;
+
+       for (i = 0; i < clock->div_num; i++) {
+               calc_rate = DIV_ROUND_CLOSEST(parent_rate,
+                                             clock->div_table[i].div);
+               diff = calc_rate > rate ? calc_rate - rate : rate - calc_rate;
+               if (diff < diff_min) {
+                       best_div = clock->div_table[i].div;
+                       diff_min = diff;
+               }
+       }
 
-       return clamp_t(unsigned int, div, clock->div_min, clock->div_max);
+       return best_div;
 }
 
 static long cpg_sd_clock_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -369,27 +376,26 @@ static u32 cpg_quirks __initdata;
 #define RCKCR_CKSEL    BIT(1)          /* Manual RCLK parent selection */
 #define SD_SKIP_FIRST  BIT(2)          /* Skip first clock in SD table */
 
-static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
-       void __iomem *base, const char *parent_name,
+static struct clk * __init cpg_sd_clk_register(const char *name,
+       void __iomem *base, unsigned int offset, const char *parent_name,
        struct raw_notifier_head *notifiers)
 {
        struct clk_init_data init;
        struct sd_clock *clock;
        struct clk *clk;
-       unsigned int i;
        u32 val;
 
        clock = kzalloc(sizeof(*clock), GFP_KERNEL);
        if (!clock)
                return ERR_PTR(-ENOMEM);
 
-       init.name = core->name;
+       init.name = name;
        init.ops = &cpg_sd_clock_ops;
        init.flags = CLK_SET_RATE_PARENT;
        init.parent_names = &parent_name;
        init.num_parents = 1;
 
-       clock->csn.reg = base + core->offset;
+       clock->csn.reg = base + offset;
        clock->hw.init = &init;
        clock->div_table = cpg_sd_div_table;
        clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
@@ -403,13 +409,6 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
        val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK);
        writel(val, clock->csn.reg);
 
-       clock->div_max = clock->div_table[0].div;
-       clock->div_min = clock->div_max;
-       for (i = 1; i < clock->div_num; i++) {
-               clock->div_max = max(clock->div_max, clock->div_table[i].div);
-               clock->div_min = min(clock->div_min, clock->div_table[i].div);
-       }
-
        clk = clk_register(NULL, &clock->hw);
        if (IS_ERR(clk))
                goto free_clock;
@@ -606,8 +605,8 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
                break;
 
        case CLK_TYPE_GEN3_SD:
-               return cpg_sd_clk_register(core, base, __clk_get_name(parent),
-                                          notifiers);
+               return cpg_sd_clk_register(core->name, base, core->offset,
+                                          __clk_get_name(parent), notifiers);
 
        case CLK_TYPE_GEN3_R:
                if (cpg_quirks & RCKCR_CKSEL) {
@@ -658,11 +657,7 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
 
        case CLK_TYPE_GEN3_Z:
                return cpg_z_clk_register(core->name, __clk_get_name(parent),
-                                         base, CPG_FRQCRC_ZFC_MASK);
-
-       case CLK_TYPE_GEN3_Z2:
-               return cpg_z_clk_register(core->name, __clk_get_name(parent),
-                                         base, CPG_FRQCRC_Z2FC_MASK);
+                                         base, core->div, core->offset);
 
        case CLK_TYPE_GEN3_OSC:
                /*
index eac1b057455a96df789d1c90aa4059ea5542c37e..c4ac80cac6a0a2c42135859db8a459f0749924bc 100644 (file)
@@ -1,8 +1,9 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
  * R-Car Gen3 Clock Pulse Generator
  *
  * Copyright (C) 2015-2018 Glider bvba
+ * Copyright (C) 2018 Renesas Electronics Corp.
  *
  */
 
@@ -20,7 +21,6 @@ enum rcar_gen3_clk_types {
        CLK_TYPE_GEN3_R,
        CLK_TYPE_GEN3_MDSEL,    /* Select parent/divider using mode pin */
        CLK_TYPE_GEN3_Z,
-       CLK_TYPE_GEN3_Z2,
        CLK_TYPE_GEN3_OSC,      /* OSC EXTAL predivider and fixed divider */
        CLK_TYPE_GEN3_RCKSEL,   /* Select parent/divider using RCKCR.CKSEL */
        CLK_TYPE_GEN3_RPCSRC,
@@ -51,6 +51,9 @@ enum rcar_gen3_clk_types {
        DEF_BASE(_name, _id, CLK_TYPE_GEN3_RCKSEL,      \
                 (_parent0) << 16 | (_parent1), .div = (_div0) << 16 | (_div1))
 
+#define DEF_GEN3_Z(_name, _id, _type, _parent, _div, _offset)  \
+       DEF_BASE(_name, _id, _type, _parent, .div = _div, .offset = _offset)
+
 struct rcar_gen3_cpg_pll_config {
        u8 extal_div;
        u8 pll1_mult;
index c4ec9df146fd990e90bb3b93b78e93c1d14e811c..4ddcdf3bfb95f47dc86c863d93310b30aba60535 100644 (file)
@@ -1,5 +1,5 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
  * Renesas Clock Pulse Generator / Module Standby and Software Reset
  *
  * Copyright (C) 2015 Glider bvba
index ebce5260068b72a9e2013e3aeaddc61f7cf252d8..09ede69205932e3aed826a8ad721c32fbac9d1b0 100644 (file)
@@ -82,7 +82,7 @@ static u8 rockchip_ddrclk_get_parent(struct clk_hw *hw)
        struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
        u32 val;
 
-       val = clk_readl(ddrclk->reg_base +
+       val = readl(ddrclk->reg_base +
                        ddrclk->mux_offset) >> ddrclk->mux_shift;
        val &= GENMASK(ddrclk->mux_width - 1, 0);
 
index b8da6e799423ace8bd446e9be70d96a89a92a13d..784b81e1ea7c656a30f24d6db834b13eecaee1c2 100644 (file)
@@ -24,7 +24,7 @@ static unsigned long clk_half_divider_recalc_rate(struct clk_hw *hw,
        struct clk_divider *divider = to_clk_divider(hw);
        unsigned int val;
 
-       val = clk_readl(divider->reg) >> divider->shift;
+       val = readl(divider->reg) >> divider->shift;
        val &= div_mask(divider->width);
        val = val * 2 + 3;
 
@@ -124,11 +124,11 @@ static int clk_half_divider_set_rate(struct clk_hw *hw, unsigned long rate,
        if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
                val = div_mask(divider->width) << (divider->shift + 16);
        } else {
-               val = clk_readl(divider->reg);
+               val = readl(divider->reg);
                val &= ~(div_mask(divider->width) << divider->shift);
        }
        val |= value << divider->shift;
-       clk_writel(val, divider->reg);
+       writel(val, divider->reg);
 
        if (divider->lock)
                spin_unlock_irqrestore(divider->lock, flags);
index 5a67b7869960e6c87ded5fee5508fa70088841a6..24baeb56a1b3df53ac7a71ef5214c7a641df78fc 100644 (file)
@@ -200,8 +200,8 @@ PNAME(mux_aclk_cpu_src_p)   = { "cpll_aclk_cpu", "gpll_aclk_cpu" };
 PNAME(mux_pll_src_cpll_gpll_p)         = { "cpll", "gpll" };
 PNAME(mux_pll_src_npll_cpll_gpll_p)    = { "npll", "cpll", "gpll" };
 PNAME(mux_pll_src_cpll_gpll_npll_p)    = { "cpll", "gpll", "npll" };
-PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "usbphy480m_src" };
-PNAME(mux_pll_src_cpll_gll_usb_npll_p) = { "cpll", "gpll", "usbphy480m_src", "npll" };
+PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "unstable:usbphy480m_src" };
+PNAME(mux_pll_src_cpll_gll_usb_npll_p) = { "cpll", "gpll", "unstable:usbphy480m_src", "npll" };
 
 PNAME(mux_mmc_src_p)   = { "cpll", "gpll", "xin24m", "xin24m" };
 PNAME(mux_i2s_pre_p)   = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" };
@@ -219,7 +219,7 @@ PNAME(mux_hsadcout_p)       = { "hsadc_src", "ext_hsadc" };
 PNAME(mux_edp_24m_p)   = { "ext_edp_24m", "xin24m" };
 PNAME(mux_tspout_p)    = { "cpll", "gpll", "npll", "xin27m" };
 
-PNAME(mux_aclk_vcodec_pre_p)   = { "aclk_vepu", "aclk_vdpu" };
+PNAME(mux_aclk_vcodec_pre_p)   = { "aclk_vdpu", "aclk_vepu" };
 PNAME(mux_usbphy480m_p)                = { "sclk_otgphy1_480m", "sclk_otgphy2_480m",
                                    "sclk_otgphy0_480m" };
 PNAME(mux_hsicphy480m_p)       = { "cpll", "gpll", "usbphy480m_src" };
@@ -313,13 +313,13 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
        COMPOSITE_NOMUX(0, "aclk_core_mp", "armclk", CLK_IGNORE_UNUSED,
                        RK3288_CLKSEL_CON(0), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
                        RK3288_CLKGATE_CON(12), 6, GFLAGS),
-       COMPOSITE_NOMUX(0, "atclk", "armclk", CLK_IGNORE_UNUSED,
+       COMPOSITE_NOMUX(0, "atclk", "armclk", 0,
                        RK3288_CLKSEL_CON(37), 4, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
                        RK3288_CLKGATE_CON(12), 7, GFLAGS),
        COMPOSITE_NOMUX(0, "pclk_dbg_pre", "armclk", CLK_IGNORE_UNUSED,
                        RK3288_CLKSEL_CON(37), 9, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
                        RK3288_CLKGATE_CON(12), 8, GFLAGS),
-       GATE(0, "pclk_dbg", "pclk_dbg_pre", CLK_IGNORE_UNUSED,
+       GATE(0, "pclk_dbg", "pclk_dbg_pre", 0,
                        RK3288_CLKGATE_CON(12), 9, GFLAGS),
        GATE(0, "cs_dbg", "pclk_dbg_pre", CLK_IGNORE_UNUSED,
                        RK3288_CLKGATE_CON(12), 10, GFLAGS),
@@ -420,7 +420,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
        COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb480m_p, 0,
                        RK3288_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
                        RK3288_CLKGATE_CON(3), 11, GFLAGS),
-       MUXGRF(0, "aclk_vcodec_pre", mux_aclk_vcodec_pre_p, 0,
+       MUXGRF(0, "aclk_vcodec_pre", mux_aclk_vcodec_pre_p, CLK_SET_RATE_PARENT,
                        RK3288_GRF_SOC_CON(0), 7, 1, MFLAGS),
        GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vcodec_pre", 0,
                RK3288_CLKGATE_CON(9), 0, GFLAGS),
@@ -647,7 +647,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
        INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
                        RK3288_CLKSEL_CON(22), 7, IFLAGS),
 
-       GATE(0, "jtag", "ext_jtag", CLK_IGNORE_UNUSED,
+       GATE(0, "jtag", "ext_jtag", 0,
                        RK3288_CLKGATE_CON(4), 14, GFLAGS),
 
        COMPOSITE_NODIV(SCLK_USBPHY480M_SRC, "usbphy480m_src", mux_usbphy480m_p, 0,
@@ -656,7 +656,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
        COMPOSITE_NODIV(SCLK_HSICPHY480M, "sclk_hsicphy480m", mux_hsicphy480m_p, 0,
                        RK3288_CLKSEL_CON(29), 0, 2, MFLAGS,
                        RK3288_CLKGATE_CON(3), 6, GFLAGS),
-       GATE(0, "hsicphy12m_xin12m", "xin12m", CLK_IGNORE_UNUSED,
+       GATE(0, "hsicphy12m_xin12m", "xin12m", 0,
                        RK3288_CLKGATE_CON(13), 9, GFLAGS),
        DIV(0, "hsicphy12m_usbphy", "sclk_hsicphy480m", 0,
                        RK3288_CLKSEL_CON(11), 8, 6, DFLAGS),
@@ -697,7 +697,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
        GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 3, GFLAGS),
        GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 9, GFLAGS),
        GATE(PCLK_EFUSE256, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS),
-       GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(11), 11, GFLAGS),
+       GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 11, GFLAGS),
 
        /* ddrctrl [DDR Controller PHY clock] gates */
        GATE(0, "nclk_ddrupctl0", "ddrphy", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(11), 4, GFLAGS),
@@ -837,12 +837,9 @@ static const char *const rk3288_critical_clocks[] __initconst = {
        "pclk_alive_niu",
        "pclk_pd_pmu",
        "pclk_pmu_niu",
-       "pclk_core_niu",
-       "pclk_ddrupctl0",
-       "pclk_publ0",
-       "pclk_ddrupctl1",
-       "pclk_publ1",
        "pmu_hclk_otg0",
+       /* pwm-regulators on some boards, so handoff-critical later */
+       "pclk_rkpwm",
 };
 
 static void __iomem *rk3288_cru_base;
@@ -859,6 +856,9 @@ static const int rk3288_saved_cru_reg_ids[] = {
        RK3288_CLKSEL_CON(10),
        RK3288_CLKSEL_CON(33),
        RK3288_CLKSEL_CON(37),
+
+       /* We turn aclk_dmac1 on for suspend; this will restore it */
+       RK3288_CLKGATE_CON(10),
 };
 
 static u32 rk3288_saved_cru_regs[ARRAY_SIZE(rk3288_saved_cru_reg_ids)];
@@ -874,6 +874,14 @@ static int rk3288_clk_suspend(void)
                                readl_relaxed(rk3288_cru_base + reg_id);
        }
 
+       /*
+        * Going into deep sleep (specifically setting PMU_CLR_DMA in
+        * RK3288_PMU_PWRMODE_CON1) appears to fail unless
+        * "aclk_dmac1" is on.
+        */
+       writel_relaxed(1 << (12 + 16),
+                      rk3288_cru_base + RK3288_CLKGATE_CON(10));
+
        /*
         * Switch PLLs other than DPLL (for SDRAM) to slow mode to
         * avoid crashes on resume. The Mask ROM on the system will
index 65ab5c2f48b0de9f86f56f25a60ea0aa60e934e4..f12142d9cea2a0c68101c083993238a0f15fd5d3 100644 (file)
@@ -458,7 +458,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
                        RK3328_CLKSEL_CON(35), 15, 1, MFLAGS, 8, 7, DFLAGS,
                        RK3328_CLKGATE_CON(2), 12, GFLAGS),
        COMPOSITE(SCLK_CRYPTO, "clk_crypto", mux_2plls_p, 0,
-                       RK3328_CLKSEL_CON(20), 7, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK3328_CLKSEL_CON(20), 7, 1, MFLAGS, 0, 5, DFLAGS,
                        RK3328_CLKGATE_CON(2), 4, GFLAGS),
        COMPOSITE_NOMUX(SCLK_TSADC, "clk_tsadc", "clk_24m", 0,
                        RK3328_CLKSEL_CON(22), 0, 10, DFLAGS,
@@ -550,15 +550,15 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
        GATE(0, "hclk_rkvenc_niu", "hclk_rkvenc", 0,
                        RK3328_CLKGATE_CON(25), 1, GFLAGS),
        GATE(ACLK_H265, "aclk_h265", "aclk_rkvenc", 0,
-                       RK3328_CLKGATE_CON(25), 0, GFLAGS),
+                       RK3328_CLKGATE_CON(25), 2, GFLAGS),
        GATE(PCLK_H265, "pclk_h265", "hclk_rkvenc", 0,
-                       RK3328_CLKGATE_CON(25), 1, GFLAGS),
+                       RK3328_CLKGATE_CON(25), 3, GFLAGS),
        GATE(ACLK_H264, "aclk_h264", "aclk_rkvenc", 0,
-                       RK3328_CLKGATE_CON(25), 0, GFLAGS),
+                       RK3328_CLKGATE_CON(25), 4, GFLAGS),
        GATE(HCLK_H264, "hclk_h264", "hclk_rkvenc", 0,
-                       RK3328_CLKGATE_CON(25), 1, GFLAGS),
+                       RK3328_CLKGATE_CON(25), 5, GFLAGS),
        GATE(ACLK_AXISRAM, "aclk_axisram", "aclk_rkvenc", CLK_IGNORE_UNUSED,
-                       RK3328_CLKGATE_CON(25), 0, GFLAGS),
+                       RK3328_CLKGATE_CON(25), 6, GFLAGS),
 
        COMPOSITE(SCLK_VENC_CORE, "sclk_venc_core", mux_4plls_p, 0,
                        RK3328_CLKSEL_CON(51), 14, 2, MFLAGS, 8, 5, DFLAGS,
@@ -663,7 +663,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
 
        /* PD_GMAC */
        COMPOSITE(ACLK_GMAC, "aclk_gmac", mux_2plls_hdmiphy_p, 0,
-                       RK3328_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3328_CLKSEL_CON(25), 6, 2, MFLAGS, 0, 5, DFLAGS,
                        RK3328_CLKGATE_CON(3), 2, GFLAGS),
        COMPOSITE_NOMUX(PCLK_GMAC, "pclk_gmac", "aclk_gmac", 0,
                        RK3328_CLKSEL_CON(25), 8, 3, DFLAGS,
@@ -733,7 +733,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
 
        /* PD_PERI */
        GATE(0, "aclk_peri_noc", "aclk_peri", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(19), 11, GFLAGS),
-       GATE(ACLK_USB3OTG, "aclk_usb3otg", "aclk_peri", 0, RK3328_CLKGATE_CON(19), 4, GFLAGS),
+       GATE(ACLK_USB3OTG, "aclk_usb3otg", "aclk_peri", 0, RK3328_CLKGATE_CON(19), 14, GFLAGS),
 
        GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK3328_CLKGATE_CON(19), 0, GFLAGS),
        GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK3328_CLKGATE_CON(19), 1, GFLAGS),
@@ -913,7 +913,7 @@ static void __init rk3328_clk_init(struct device_node *np)
                                     &rk3328_cpuclk_data, rk3328_cpuclk_rates,
                                     ARRAY_SIZE(rk3328_cpuclk_rates));
 
-       rockchip_register_softrst(np, 11, reg_base + RK3328_SOFTRST_CON(0),
+       rockchip_register_softrst(np, 12, reg_base + RK3328_SOFTRST_CON(0),
                                  ROCKCHIP_SOFTRST_HIWORD_MASK);
 
        rockchip_register_restart_notifier(ctx, RK3328_GLB_SRST_FST, NULL);
index c3ad92965823967740d2283615e009dfefaa959a..0ea8e8080d1a663ca0e09f6da3746afa2e925ee8 100644 (file)
@@ -46,7 +46,7 @@ static struct clk *rockchip_clk_register_branch(const char *name,
                const char *const *parent_names, u8 num_parents,
                void __iomem *base,
                int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
-               u8 div_shift, u8 div_width, u8 div_flags,
+               int div_offset, u8 div_shift, u8 div_width, u8 div_flags,
                struct clk_div_table *div_table, int gate_offset,
                u8 gate_shift, u8 gate_flags, unsigned long flags,
                spinlock_t *lock)
@@ -95,7 +95,10 @@ static struct clk *rockchip_clk_register_branch(const char *name,
                }
 
                div->flags = div_flags;
-               div->reg = base + muxdiv_offset;
+               if (div_offset)
+                       div->reg = base + div_offset;
+               else
+                       div->reg = base + muxdiv_offset;
                div->shift = div_shift;
                div->width = div_width;
                div->lock = lock;
@@ -516,7 +519,7 @@ void __init rockchip_clk_register_branches(
                                ctx->reg_base, list->muxdiv_offset,
                                list->mux_shift,
                                list->mux_width, list->mux_flags,
-                               list->div_shift, list->div_width,
+                               list->div_offset, list->div_shift, list->div_width,
                                list->div_flags, list->div_table,
                                list->gate_offset, list->gate_shift,
                                list->gate_flags, flags, &ctx->lock);
index 6b53fff4cc96b6d2b875c5e4e94e32c7ca3d632b..1b527075543108256c4bca2d0aa960c482ae12f5 100644 (file)
@@ -407,6 +407,7 @@ struct rockchip_clk_branch {
        u8                              mux_shift;
        u8                              mux_width;
        u8                              mux_flags;
+       int                             div_offset;
        u8                              div_shift;
        u8                              div_width;
        u8                              div_flags;
@@ -438,6 +439,28 @@ struct rockchip_clk_branch {
                .gate_flags     = gf,                           \
        }
 
+#define COMPOSITE_DIV_OFFSET(_id, cname, pnames, f, mo, ms, mw,        \
+                            mf, do, ds, dw, df, go, gs, gf)    \
+       {                                                       \
+               .id             = _id,                          \
+               .branch_type    = branch_composite,             \
+               .name           = cname,                        \
+               .parent_names   = pnames,                       \
+               .num_parents    = ARRAY_SIZE(pnames),           \
+               .flags          = f,                            \
+               .muxdiv_offset  = mo,                           \
+               .mux_shift      = ms,                           \
+               .mux_width      = mw,                           \
+               .mux_flags      = mf,                           \
+               .div_offset     = do,                           \
+               .div_shift      = ds,                           \
+               .div_width      = dw,                           \
+               .div_flags      = df,                           \
+               .gate_offset    = go,                           \
+               .gate_shift     = gs,                           \
+               .gate_flags     = gf,                           \
+       }
+
 #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df,  \
                        go, gs, gf)                             \
        {                                                       \
index 0a0b09591e6fd8493242e05df2943e1cfa0666ab..b2da2c8fa0c78a5a3abf842e0cdccd3be5337b3f 100644 (file)
@@ -209,6 +209,7 @@ static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = {
        GATE(CLK_USI1, "usi1", "aclk66", GATE_IP_PERIC, 11, 0, 0),
        GATE(CLK_USI2, "usi2", "aclk66", GATE_IP_PERIC, 12, 0, 0),
        GATE(CLK_USI3, "usi3", "aclk66", GATE_IP_PERIC, 13, 0, 0),
+       GATE(CLK_TSADC, "tsadc", "aclk66", GATE_IP_PERIC, 15, 0, 0),
        GATE(CLK_PWM, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0),
 
        GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
diff --git a/drivers/clk/sifive/Kconfig b/drivers/clk/sifive/Kconfig
new file mode 100644 (file)
index 0000000..8db4a3e
--- /dev/null
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0
+
+menuconfig CLK_SIFIVE
+       bool "SiFive SoC driver support"
+       help
+         SoC drivers for SiFive Linux-capable SoCs.
+
+if CLK_SIFIVE
+
+config CLK_SIFIVE_FU540_PRCI
+       bool "PRCI driver for SiFive FU540 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.
+
+endif
diff --git a/drivers/clk/sifive/Makefile b/drivers/clk/sifive/Makefile
new file mode 100644 (file)
index 0000000..74d58a4
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_CLK_SIFIVE_FU540_PRCI)    += fu540-prci.o
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c
new file mode 100644 (file)
index 0000000..0ec8bf7
--- /dev/null
@@ -0,0 +1,626 @@
+// 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.
+ *
+ * The FU540 PRCI implements clock and reset control for the SiFive
+ * FU540-C000 chip.  This driver assumes that it has sole control
+ * over all PRCI resources.
+ *
+ * This driver is based on the PRCI driver written by Wesley Terpstra:
+ * https://github.com/riscv/riscv-linux/commit/999529edf517ed75b56659d456d221b2ee56bb60
+ *
+ * References:
+ * - 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/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)
+
+/* 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)
+
+/*
+ * 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
+ *
+ * @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;
+};
+
+/**
+ * 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)
+
+/*
+ * 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;
+}
+
+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,
+};
+
+static const struct clk_ops sifive_fu540_prci_wrpll_ro_clk_ops = {
+       .recalc_rate = sifive_fu540_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,
+};
+
+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[] = {
+       [PRCI_CLK_COREPLL] = {
+               .name = "corepll",
+               .parent_name = "hfclk",
+               .ops = &sifive_fu540_prci_wrpll_clk_ops,
+               .pwd = &__prci_corepll_data,
+       },
+       [PRCI_CLK_DDRPLL] = {
+               .name = "ddrpll",
+               .parent_name = "hfclk",
+               .ops = &sifive_fu540_prci_wrpll_ro_clk_ops,
+               .pwd = &__prci_ddrpll_data,
+       },
+       [PRCI_CLK_GEMGXLPLL] = {
+               .name = "gemgxlpll",
+               .parent_name = "hfclk",
+               .ops = &sifive_fu540_prci_wrpll_clk_ops,
+               .pwd = &__prci_gemgxlpll_data,
+       },
+       [PRCI_CLK_TLCLK] = {
+               .name = "tlclk",
+               .parent_name = "corepll",
+               .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, sizeof(*pd), 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);
index abd9ff5ef44861046d2f435cb5daf91bed667343..1d077b39cef6b1dffc86840b489eedbf9f130624 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 //
 // Spreadtrum clock infrastructure
 //
index 0984e9e252dc574c336f985642d7fb369735fa25..04ab3f587ee2b906fc6e43db6aa5ac152b91f208 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 //
 // Spreadtrum composite clock driver
 //
index b3033d24d431017acfb9f1853e3b16733fa414de..87510e3d0e14ab7c29349017fac3b5c1396d8f96 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 //
 // Spreadtrum divider clock driver
 //
index 2e582c68a08b3c3f1aa5696e24d4237d27d556d1..dc352ea55e1fa464b52e76d93f862b0b821550de 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 //
 // Spreadtrum gate clock driver
 //
index 548cfa0f145c87fbebba8657aee655d1d600a852..892e4191cc7f12f364ada9f95ecfc5cb97a5d406 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 //
 // Spreadtrum multiplexer clock driver
 //
index 51417562109936bfea59658ce99a7b1a7fee1ead..e95f11e91ffe15f3bddecf5428880d406e2c077e 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 //
 // Spreadtrum pll clock driver
 //
index 932836d26e2bf40e5e3d1e7ce056f9658f1b87f0..be0deee7018252dec1a56e4acdf862d0ae0f3a79 100644 (file)
@@ -531,7 +531,8 @@ static SUNXI_CCU_GATE(dram_ts_clk,  "dram-ts",      "dram",
 
 static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
 static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
-                                0x104, 0, 4, 24, 3, BIT(31), 0);
+                                0x104, 0, 4, 24, 3, BIT(31),
+                                CLK_SET_RATE_PARENT);
 
 static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" };
 static const u8 tcon0_table[] = { 0, 2, };
index 139e8389615c74dab720fdfd0e72a24423d7e7ad..3c32d7798f27b2ff05c912ede945201074adfc64 100644 (file)
@@ -266,7 +266,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
                                       0, 4,    /* M */
                                       24, 1,   /* mux */
                                       BIT(31), /* gate */
-                                      0);
+                                      CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2",
                      0x60c, BIT(0), 0);
@@ -311,7 +311,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
                                       0, 3,    /* M */
                                       24, 1,   /* mux */
                                       BIT(31), /* gate */
-                                      0);
+                                      CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2",
                      0x69c, BIT(0), 0);
@@ -656,6 +656,8 @@ static const char * const hdmi_cec_parents[] = { "osc32k", "pll-periph0-2x" };
 static const struct ccu_mux_fixed_prediv hdmi_cec_predivs[] = {
        { .index = 1, .div = 36621 },
 };
+
+#define SUN50I_H6_HDMI_CEC_CLK_REG             0xb10
 static struct ccu_mux hdmi_cec_clk = {
        .enable         = BIT(31),
 
@@ -689,7 +691,7 @@ static SUNXI_CCU_MUX_WITH_GATE(tcon_lcd0_clk, "tcon-lcd0",
                               tcon_lcd0_parents, 0xb60,
                               24, 3,   /* mux */
                               BIT(31), /* gate */
-                              0);
+                              CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_GATE(bus_tcon_lcd0_clk, "bus-tcon-lcd0", "ahb3",
                      0xb7c, BIT(0), 0);
@@ -704,7 +706,7 @@ static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
                                  8, 2,         /* P */
                                  24, 3,        /* mux */
                                  BIT(31),      /* gate */
-                                 0);
+                                 CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb3",
                      0xb9c, BIT(0), 0);
@@ -1200,6 +1202,15 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
        val &= ~(GENMASK(21, 16) | BIT(0));
        writel(val | (7 << 16), reg + SUN50I_H6_PLL_AUDIO_REG);
 
+       /*
+        * First clock parent (osc32K) is unusable for CEC. But since there
+        * is no good way to force parent switch (both run with same frequency),
+        * just set second clock parent here.
+        */
+       val = readl(reg + SUN50I_H6_HDMI_CEC_CLK_REG);
+       val |= BIT(24);
+       writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG);
+
        return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc);
 }
 
index 2ccfe4428260d165848d81495769c207f9192497..9406f9a6a8aa492f067504d897afde94b87f2b9d 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright 2016 Icenowy Zheng <icenowy@aosc.io>
  */
index 93a275fbd9a907277c5ce49353dad95d73b61adf..b66abd4fd0bf1c7c1c0323f6f7b271025a5be47c 100644 (file)
 
 /* The rest of the module clocks are exported */
 
-#define CLK_MBUS               99
-
-/* And finally the IEP clock */
-
 #define CLK_NUMBER             (CLK_IEP + 1)
 
 #endif /* _CCU_SUN5I_H_ */
index 2d6555d7317058c1b892bc91dbd75dfe0fe1df6e..5f714b4d8ee42c1119f8ffb9dc7986798bf2ec1e 100644 (file)
@@ -513,8 +513,9 @@ static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M", 0x130, BIT(16), 0);
 
 static SUNXI_CCU_GATE(mipi_csi_clk, "mipi-csi", "osc24M", 0x130, BIT(31), 0);
 
-static const char * const csi_mclk_parents[] = { "pll-de", "osc24M" };
-static const u8 csi_mclk_table[] = { 3, 5 };
+static const char * const csi_mclk_parents[] = { "pll-video0", "pll-de",
+                                                "osc24M" };
+static const u8 csi_mclk_table[] = { 0, 3, 5 };
 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_mclk_clk, "csi-mclk",
                                       csi_mclk_parents, csi_mclk_table,
                                       0x134,
index ac12f261f8caa3f76d0b8407be287506ed7ff7cc..eada0e2918591c0cbb589d79587c67651f141891 100644 (file)
@@ -325,7 +325,8 @@ static SUNXI_CCU_GATE(dram_ohci_clk,        "dram-ohci",    "dram",
 
 static const char * const de_parents[] = { "pll-video", "pll-periph0" };
 static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
-                                0x104, 0, 4, 24, 2, BIT(31), 0);
+                                0x104, 0, 4, 24, 2, BIT(31),
+                                CLK_SET_RATE_PARENT);
 
 static const char * const tcon_parents[] = { "pll-video" };
 static SUNXI_CCU_M_WITH_MUX_GATE(tcon_clk, "tcon", tcon_parents,
index a09dfbe364023f774f83f3cd01e48c8102ba5ab8..dc9f0a365664ee1db6e17a0be0d8a637dd8802da 100644 (file)
@@ -240,7 +240,7 @@ static SUNXI_CCU_MUX_WITH_GATE(spdif_clk, "spdif", i2s_spdif_parents,
 /* The BSP header file has a CIR_CFG, but no mod clock uses this definition */
 
 static SUNXI_CCU_GATE(usb_phy0_clk,    "usb-phy0",     "osc24M",
-                     0x0cc, BIT(8), 0);
+                     0x0cc, BIT(1), 0);
 
 static SUNXI_CCU_GATE(dram_ve_clk,     "dram-ve",      "pll-ddr",
                      0x100, BIT(0), 0);
index 39d06fed55b2d4c45ab112e4c11ab7a331eaf58f..b22484f1bb9a5dd2dda63daf19f3387b98939f6f 100644 (file)
@@ -1,5 +1,5 @@
-/* SPDX-License-Identifier: GPL-2.0+
- *
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
  * Copyright 2017 Icenowy Zheng <icenowy@aosc.io>
  *
  */
diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
new file mode 100644 (file)
index 0000000..2b6207c
--- /dev/null
@@ -0,0 +1,43 @@
+menuconfig CLK_SUNXI
+       bool "Legacy clock support for Allwinner SoCs"
+       depends on ARCH_SUNXI || COMPILE_TEST
+       default y
+
+if CLK_SUNXI
+
+config CLK_SUNXI_CLOCKS
+       bool "Legacy clock drivers"
+       default y
+       help
+         Legacy clock drivers being used on older (A10, A13, A20,
+         A23, A31, A80) SoCs. These drivers are kept around for
+         Device Tree backward compatibility issues, in case one would
+         still use a Device Tree with one clock provider by
+         node. Newer Device Trees and newer SoCs use the drivers
+         controlled by CONFIG_SUNXI_CCU.
+
+config CLK_SUNXI_PRCM_SUN6I
+       bool "Legacy A31 PRCM driver"
+       select MFD_SUN6I_PRCM
+       default y
+       help
+         Legacy clock driver for the A31 PRCM clocks. Those are
+         usually needed for the PMIC communication, mostly.
+
+config CLK_SUNXI_PRCM_SUN8I
+       bool "Legacy sun8i PRCM driver"
+       select MFD_SUN6I_PRCM
+       default y
+       help
+         Legacy clock driver for the sun8i family PRCM clocks.
+         Those are usually needed for the PMIC communication,
+         mostly.
+
+config CLK_SUNXI_PRCM_SUN9I
+       bool "Legacy A80 PRCM driver"
+       default y
+       help
+         Legacy clock driver for the A80 PRCM clocks. Those are
+         usually needed for the PMIC communication, mostly.
+
+endif
index be88368b48a1c1046ee82b3a343eed9c059244ac..e10824c76ae92319e225ea0ff0e67e75dfcc62c2 100644 (file)
@@ -3,27 +3,32 @@
 # Makefile for sunxi specific clk
 #
 
-obj-y += clk-sunxi.o clk-factors.o
-obj-y += clk-a10-codec.o
-obj-y += clk-a10-hosc.o
-obj-y += clk-a10-mod1.o
-obj-y += clk-a10-pll2.o
-obj-y += clk-a10-ve.o
-obj-y += clk-a20-gmac.o
-obj-y += clk-mod0.o
-obj-y += clk-simple-gates.o
-obj-y += clk-sun4i-display.o
-obj-y += clk-sun4i-pll3.o
-obj-y += clk-sun4i-tcon-ch1.o
-obj-y += clk-sun8i-bus-gates.o
-obj-y += clk-sun8i-mbus.o
-obj-y += clk-sun9i-core.o
-obj-y += clk-sun9i-mmc.o
-obj-y += clk-usb.o
+obj-$(CONFIG_CLK_SUNXI) += clk-factors.o
 
-obj-$(CONFIG_MACH_SUN9I) += clk-sun8i-apb0.o
-obj-$(CONFIG_MACH_SUN9I) += clk-sun9i-cpus.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sunxi.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-a10-codec.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-a10-hosc.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-a10-mod1.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-a10-pll2.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-a10-ve.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-a20-gmac.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-mod0.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-simple-gates.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun4i-display.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun4i-pll3.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun4i-tcon-ch1.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun8i-bus-gates.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun8i-mbus.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun9i-core.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun9i-mmc.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-usb.o
 
-obj-$(CONFIG_MFD_SUN6I_PRCM) += \
-       clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
-       clk-sun8i-apb0.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun8i-apb0.o
+obj-$(CONFIG_CLK_SUNXI_CLOCKS) += clk-sun9i-cpus.o
+
+obj-$(CONFIG_CLK_SUNXI_PRCM_SUN6I)     += clk-sun6i-apb0.o
+obj-$(CONFIG_CLK_SUNXI_PRCM_SUN6I)     += clk-sun6i-apb0-gates.o
+obj-$(CONFIG_CLK_SUNXI_PRCM_SUN6I)     += clk-sun6i-ar100.o
+
+obj-$(CONFIG_CLK_SUNXI_PRCM_SUN8I)     += clk-sun8i-apb0.o
+obj-$(CONFIG_CLK_SUNXI_PRCM_SUN8I)     += clk-sun6i-apb0-gates.o
index 205fe8ff63f03b44ece507a81c68ae11a2d7bb0c..2a1822a227407440b8aa42666acb02918731c8bc 100644 (file)
@@ -175,6 +175,7 @@ struct clk *tegra_clk_register_mc(const char *name, const char *parent_name,
                                  void __iomem *reg, spinlock_t *lock)
 {
        return clk_register_divider_table(NULL, name, parent_name,
-                                         CLK_IS_CRITICAL, reg, 16, 1, 0,
+                                         CLK_IS_CRITICAL,
+                                         reg, 16, 1, CLK_DIVIDER_READ_ONLY,
                                          mc_div_table, lock);
 }
index 0621a3a82ea6c801de2d0c2a055cc29769a2f554..93ecb538e59bbf272db3facad5c68f410ec10072 100644 (file)
@@ -121,18 +121,28 @@ static int emc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
        struct tegra_clk_emc *tegra;
        u8 ram_code = tegra_read_ram_code();
        struct emc_timing *timing = NULL;
-       int i;
+       int i, k, t;
 
        tegra = container_of(hw, struct tegra_clk_emc, hw);
 
-       for (i = 0; i < tegra->num_timings; i++) {
-               if (tegra->timings[i].ram_code != ram_code)
-                       continue;
+       for (k = 0; k < tegra->num_timings; k++) {
+               if (tegra->timings[k].ram_code == ram_code)
+                       break;
+       }
+
+       for (t = k; t < tegra->num_timings; t++) {
+               if (tegra->timings[t].ram_code != ram_code)
+                       break;
+       }
 
+       for (i = k; i < t; i++) {
                timing = tegra->timings + i;
 
+               if (timing->rate < req->rate && i != t - 1)
+                       continue;
+
                if (timing->rate > req->max_rate) {
-                       i = max(i, 1);
+                       i = max(i, k + 1);
                        req->rate = tegra->timings[i - 1].rate;
                        return 0;
                }
@@ -140,10 +150,8 @@ static int emc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
                if (timing->rate < req->min_rate)
                        continue;
 
-               if (timing->rate >= req->rate) {
-                       req->rate = timing->rate;
-                       return 0;
-               }
+               req->rate = timing->rate;
+               return 0;
        }
 
        if (timing) {
@@ -214,7 +222,10 @@ static int emc_set_timing(struct tegra_clk_emc *tegra,
 
        if (emc_get_parent(&tegra->hw) == timing->parent_index &&
            clk_get_rate(timing->parent) != timing->parent_rate) {
-               BUG();
+               WARN_ONCE(1, "parent %s rate mismatch %lu %lu\n",
+                         __clk_get_name(timing->parent),
+                         clk_get_rate(timing->parent),
+                         timing->parent_rate);
                return -EINVAL;
        }
 
@@ -282,7 +293,7 @@ static struct emc_timing *get_backup_timing(struct tegra_clk_emc *tegra,
        for (i = timing_index+1; i < tegra->num_timings; i++) {
                timing = tegra->timings + i;
                if (timing->ram_code != ram_code)
-                       continue;
+                       break;
 
                if (emc_parent_clk_sources[timing->parent_index] !=
                    emc_parent_clk_sources[
@@ -293,7 +304,7 @@ static struct emc_timing *get_backup_timing(struct tegra_clk_emc *tegra,
        for (i = timing_index-1; i >= 0; --i) {
                timing = tegra->timings + i;
                if (timing->ram_code != ram_code)
-                       continue;
+                       break;
 
                if (emc_parent_clk_sources[timing->parent_index] !=
                    emc_parent_clk_sources[
@@ -433,19 +444,23 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra,
                                struct device_node *node,
                                u32 ram_code)
 {
+       struct emc_timing *timings_ptr;
        struct device_node *child;
        int child_count = of_get_child_count(node);
        int i = 0, err;
+       size_t size;
 
-       tegra->timings = kcalloc(child_count, sizeof(struct emc_timing),
-                                GFP_KERNEL);
+       size = (tegra->num_timings + child_count) * sizeof(struct emc_timing);
+
+       tegra->timings = krealloc(tegra->timings, size, GFP_KERNEL);
        if (!tegra->timings)
                return -ENOMEM;
 
-       tegra->num_timings = child_count;
+       timings_ptr = tegra->timings + tegra->num_timings;
+       tegra->num_timings += child_count;
 
        for_each_child_of_node(node, child) {
-               struct emc_timing *timing = tegra->timings + (i++);
+               struct emc_timing *timing = timings_ptr + (i++);
 
                err = load_one_timing_from_dt(tegra, timing, child);
                if (err) {
@@ -456,7 +471,7 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra,
                timing->ram_code = ram_code;
        }
 
-       sort(tegra->timings, tegra->num_timings, sizeof(struct emc_timing),
+       sort(timings_ptr, child_count, sizeof(struct emc_timing),
             cmp_timings, NULL);
 
        return 0;
@@ -499,10 +514,10 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
                 * fuses until the apbmisc driver is loaded.
                 */
                err = load_timings_from_dt(tegra, node, node_ram_code);
-               of_node_put(node);
-               if (err)
+               if (err) {
+                       of_node_put(node);
                        return ERR_PTR(err);
-               break;
+               }
        }
 
        if (tegra->num_timings == 0)
@@ -532,7 +547,5 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
        /* Allow debugging tools to see the EMC clock */
        clk_register_clkdev(clk, "emc", "tegra-clk-debug");
 
-       clk_prepare_enable(clk);
-
        return clk;
 };
index b50b7460014bcd8452622907cf9c64c35f0a155c..6b976b2514f77bdb422ccd96f2517086f6d25977 100644 (file)
@@ -444,6 +444,9 @@ static int clk_pll_enable(struct clk_hw *hw)
        unsigned long flags = 0;
        int ret;
 
+       if (clk_pll_is_enabled(hw))
+               return 0;
+
        if (pll->lock)
                spin_lock_irqsave(pll->lock, flags);
 
@@ -663,8 +666,8 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll,
                pll_override_writel(val, params->pmc_divp_reg, pll);
 
                val = pll_override_readl(params->pmc_divnm_reg, pll);
-               val &= ~(divm_mask(pll) << div_nmp->override_divm_shift) |
-                       ~(divn_mask(pll) << div_nmp->override_divn_shift);
+               val &= ~((divm_mask(pll) << div_nmp->override_divm_shift) |
+                       (divn_mask(pll) << div_nmp->override_divn_shift));
                val |= (cfg->m << div_nmp->override_divm_shift) |
                        (cfg->n << div_nmp->override_divn_shift);
                pll_override_writel(val, params->pmc_divnm_reg, pll);
@@ -940,11 +943,16 @@ static int clk_plle_training(struct tegra_clk_pll *pll)
 static int clk_plle_enable(struct clk_hw *hw)
 {
        struct tegra_clk_pll *pll = to_clk_pll(hw);
-       unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
        struct tegra_clk_pll_freq_table sel;
+       unsigned long input_rate;
        u32 val;
        int err;
 
+       if (clk_pll_is_enabled(hw))
+               return 0;
+
+       input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
+
        if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
                return -EINVAL;
 
@@ -1355,6 +1363,9 @@ static int clk_pllc_enable(struct clk_hw *hw)
        int ret;
        unsigned long flags = 0;
 
+       if (clk_pll_is_enabled(hw))
+               return 0;
+
        if (pll->lock)
                spin_lock_irqsave(pll->lock, flags);
 
@@ -1567,7 +1578,12 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
        u32 val;
        int ret;
        unsigned long flags = 0;
-       unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
+       unsigned long input_rate;
+
+       if (clk_pll_is_enabled(hw))
+               return 0;
+
+       input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
 
        if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
                return -EINVAL;
@@ -1704,6 +1720,9 @@ static int clk_pllu_tegra114_enable(struct clk_hw *hw)
                return -EINVAL;
        }
 
+       if (clk_pll_is_enabled(hw))
+               return 0;
+
        input_rate = clk_hw_get_rate(__clk_get_hw(osc));
 
        if (pll->lock)
@@ -2379,6 +2398,16 @@ struct clk *tegra_clk_register_pllre_tegra210(const char *name,
        return clk;
 }
 
+static int clk_plle_tegra210_is_enabled(struct clk_hw *hw)
+{
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       u32 val;
+
+       val = pll_readl_base(pll);
+
+       return val & PLLE_BASE_ENABLE ? 1 : 0;
+}
+
 static int clk_plle_tegra210_enable(struct clk_hw *hw)
 {
        struct tegra_clk_pll *pll = to_clk_pll(hw);
@@ -2386,7 +2415,12 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw)
        u32 val;
        int ret = 0;
        unsigned long flags = 0;
-       unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
+       unsigned long input_rate;
+
+       if (clk_plle_tegra210_is_enabled(hw))
+               return 0;
+
+       input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
 
        if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
                return -EINVAL;
@@ -2497,16 +2531,6 @@ out:
                spin_unlock_irqrestore(pll->lock, flags);
 }
 
-static int clk_plle_tegra210_is_enabled(struct clk_hw *hw)
-{
-       struct tegra_clk_pll *pll = to_clk_pll(hw);
-       u32 val;
-
-       val = pll_readl_base(pll);
-
-       return val & PLLE_BASE_ENABLE ? 1 : 0;
-}
-
 static const struct clk_ops tegra_clk_plle_tegra210_ops = {
        .is_enabled =  clk_plle_tegra210_is_enabled,
        .enable = clk_plle_tegra210_enable,
index 84267cfc44332e556d79b8dd8d889bd3235fabd6..b5ff76c663f8776eabdeedcc1d70696db69a3717 100644 (file)
@@ -121,7 +121,7 @@ out:
        return err;
 }
 
-const struct clk_ops tegra_clk_super_mux_ops = {
+static const struct clk_ops tegra_clk_super_mux_ops = {
        .get_parent = clk_super_get_parent,
        .set_parent = clk_super_set_parent,
 };
index df0018f7bf7ed8668d04a6ab5ef47994b4ef3ac3..d7bee144f4b7c40dc604f4022b6a74f0b48338ec 100644 (file)
@@ -413,7 +413,6 @@ static struct tegra_clk_pll_params pll_m_params = {
        .base_reg = PLLM_BASE,
        .misc_reg = PLLM_MISC,
        .lock_mask = PLL_BASE_LOCK,
-       .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
        .max_p = 5,
        .pdiv_tohw = pllm_p,
@@ -421,7 +420,7 @@ static struct tegra_clk_pll_params pll_m_params = {
        .pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE,
        .pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2,
        .freq_table = pll_m_freq_table,
-       .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
+       .flags = TEGRA_PLL_USE_LOCK,
 };
 
 static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
@@ -1466,9 +1465,9 @@ static void __init tegra124_132_clock_init_pre(struct device_node *np)
        tegra_pmc_clk_init(pmc_base, tegra124_clks);
 
        /* For Tegra124 & Tegra132, PLLD is the only source for DSIA & DSIB */
-       plld_base = clk_readl(clk_base + PLLD_BASE);
+       plld_base = readl(clk_base + PLLD_BASE);
        plld_base &= ~BIT(25);
-       clk_writel(plld_base, clk_base + PLLD_BASE);
+       writel(plld_base, clk_base + PLLD_BASE);
 }
 
 /**
index 7545af763d7a927872862e99a55d671e45b17740..ed3c7df75d1eed70c4ccdf1fed97169ac990a424 100644 (file)
@@ -3557,7 +3557,7 @@ static void __init tegra210_clock_init(struct device_node *np)
        if (!clks)
                return;
 
-       value = clk_readl(clk_base + SPARE_REG0) >> CLK_M_DIVISOR_SHIFT;
+       value = readl(clk_base + SPARE_REG0) >> CLK_M_DIVISOR_SHIFT;
        clk_m_div = (value & CLK_M_DIVISOR_MASK) + 1;
 
        if (tegra_osc_clk_init(clk_base, tegra210_clks, tegra210_input_freq,
@@ -3574,9 +3574,9 @@ static void __init tegra210_clock_init(struct device_node *np)
        tegra_pmc_clk_init(pmc_base, tegra210_clks);
 
        /* For Tegra210, PLLD is the only source for DSIA & DSIB */
-       value = clk_readl(clk_base + PLLD_BASE);
+       value = readl(clk_base + PLLD_BASE);
        value &= ~BIT(25);
-       clk_writel(value, clk_base + PLLD_BASE);
+       writel(value, clk_base + PLLD_BASE);
 
        tegra_clk_apply_init_table = tegra210_clock_apply_init_table;
 
index e3cb7f0b03aeda7803ba6812aef45e8200d80952..b3cd2296f84bd261cc0394d53e3d85e859f21e5b 100644 (file)
@@ -362,7 +362,7 @@ static const struct omap_clkctrl_reg_data dra7_l3init_clkctrl_regs[] __initconst
        { DRA7_MMC2_CLKCTRL, dra7_mmc2_bit_data, CLKF_SW_SUP, "l3init_cm:clk:0010:25" },
        { DRA7_USB_OTG_SS2_CLKCTRL, dra7_usb_otg_ss2_bit_data, CLKF_HW_SUP, "dpll_core_h13x2_ck" },
        { DRA7_USB_OTG_SS3_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_core_h13x2_ck" },
-       { DRA7_USB_OTG_SS4_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_core_h13x2_ck" },
+       { DRA7_USB_OTG_SS4_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_DRA74 | CLKF_SOC_DRA76, "dpll_core_h13x2_ck" },
        { DRA7_SATA_CLKCTRL, dra7_sata_bit_data, CLKF_SW_SUP, "func_48m_fclk" },
        { DRA7_PCIE1_CLKCTRL, dra7_pcie1_bit_data, CLKF_SW_SUP, "l4_root_clk_div", "pcie_clkdm" },
        { DRA7_PCIE2_CLKCTRL, dra7_pcie2_bit_data, CLKF_SW_SUP, "l4_root_clk_div", "pcie_clkdm" },
@@ -662,7 +662,7 @@ static const struct omap_clkctrl_reg_data dra7_l4per_clkctrl_regs[] __initconst
        { DRA7_AES1_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div", "l4sec_clkdm" },
        { DRA7_AES2_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div", "l4sec_clkdm" },
        { DRA7_DES_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div", "l4sec_clkdm" },
-       { DRA7_RNG_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div", "l4sec_clkdm" },
+       { DRA7_RNG_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_NONSEC, "l3_iclk_div", "l4sec_clkdm" },
        { DRA7_SHAM_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div", "l4sec_clkdm" },
        { DRA7_UART7_CLKCTRL, dra7_uart7_bit_data, CLKF_SW_SUP, "l4per_cm:clk:01d0:24", "l4per2_clkdm" },
        { DRA7_UART8_CLKCTRL, dra7_uart8_bit_data, CLKF_SW_SUP, "l4per_cm:clk:01e0:24", "l4per2_clkdm" },
@@ -704,7 +704,7 @@ static const struct omap_clkctrl_reg_data dra7_wkupaon_clkctrl_regs[] __initcons
        { DRA7_WD_TIMER2_CLKCTRL, NULL, CLKF_SW_SUP, "sys_32k_ck" },
        { DRA7_GPIO1_CLKCTRL, dra7_gpio1_bit_data, CLKF_HW_SUP, "wkupaon_iclk_mux" },
        { DRA7_TIMER1_CLKCTRL, dra7_timer1_bit_data, CLKF_SW_SUP, "wkupaon_cm:clk:0020:24" },
-       { DRA7_TIMER12_CLKCTRL, NULL, 0, "secure_32k_clk_src_ck" },
+       { DRA7_TIMER12_CLKCTRL, NULL, CLKF_SOC_NONSEC, "secure_32k_clk_src_ck" },
        { DRA7_COUNTER_32K_CLKCTRL, NULL, 0, "wkupaon_iclk_mux" },
        { DRA7_UART10_CLKCTRL, dra7_uart10_bit_data, CLKF_SW_SUP, "wkupaon_cm:clk:0060:24" },
        { DRA7_DCAN1_CLKCTRL, dra7_dcan1_bit_data, CLKF_SW_SUP, "wkupaon_cm:clk:0068:24" },
index 597fb4a593180e087a24e80b6c5a512266dadc90..79186b918d8725fdfc4b66c74028b3d03e7ad632 100644 (file)
@@ -348,7 +348,7 @@ static const struct omap_clkctrl_reg_data dra7_l3init_clkctrl_regs[] __initconst
        { DRA7_L3INIT_MMC2_CLKCTRL, dra7_mmc2_bit_data, CLKF_SW_SUP, "l3init-clkctrl:0010:25" },
        { DRA7_L3INIT_USB_OTG_SS2_CLKCTRL, dra7_usb_otg_ss2_bit_data, CLKF_HW_SUP, "dpll_core_h13x2_ck" },
        { DRA7_L3INIT_USB_OTG_SS3_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_core_h13x2_ck" },
-       { DRA7_L3INIT_USB_OTG_SS4_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_core_h13x2_ck" },
+       { DRA7_L3INIT_USB_OTG_SS4_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_DRA74 | CLKF_SOC_DRA76, "dpll_core_h13x2_ck" },
        { DRA7_L3INIT_SATA_CLKCTRL, dra7_sata_bit_data, CLKF_SW_SUP, "func_48m_fclk" },
        { DRA7_L3INIT_OCP2SCP1_CLKCTRL, NULL, CLKF_HW_SUP, "l4_root_clk_div" },
        { DRA7_L3INIT_OCP2SCP3_CLKCTRL, NULL, CLKF_HW_SUP, "l4_root_clk_div" },
@@ -590,7 +590,7 @@ static const struct omap_clkctrl_reg_data dra7_l4sec_clkctrl_regs[] __initconst
        { DRA7_L4SEC_AES1_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" },
        { DRA7_L4SEC_AES2_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" },
        { DRA7_L4SEC_DES_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" },
-       { DRA7_L4SEC_RNG_CLKCTRL, NULL, CLKF_HW_SUP, "" },
+       { DRA7_L4SEC_RNG_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_NONSEC, "" },
        { DRA7_L4SEC_SHAM_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" },
        { 0 },
 };
@@ -757,7 +757,7 @@ static const struct omap_clkctrl_reg_data dra7_wkupaon_clkctrl_regs[] __initcons
        { DRA7_WKUPAON_WD_TIMER2_CLKCTRL, NULL, CLKF_SW_SUP, "sys_32k_ck" },
        { DRA7_WKUPAON_GPIO1_CLKCTRL, dra7_gpio1_bit_data, CLKF_HW_SUP, "wkupaon_iclk_mux" },
        { DRA7_WKUPAON_TIMER1_CLKCTRL, dra7_timer1_bit_data, CLKF_SW_SUP, "wkupaon-clkctrl:0020:24" },
-       { DRA7_WKUPAON_TIMER12_CLKCTRL, NULL, 0, "secure_32k_clk_src_ck" },
+       { DRA7_WKUPAON_TIMER12_CLKCTRL, NULL, CLKF_SOC_NONSEC, "secure_32k_clk_src_ck" },
        { DRA7_WKUPAON_COUNTER_32K_CLKCTRL, NULL, 0, "wkupaon_iclk_mux" },
        { DRA7_WKUPAON_UART10_CLKCTRL, dra7_uart10_bit_data, CLKF_SW_SUP, "wkupaon-clkctrl:0060:24" },
        { DRA7_WKUPAON_DCAN1_CLKCTRL, dra7_dcan1_bit_data, CLKF_SW_SUP, "wkupaon-clkctrl:0068:24" },
index 639f515e08f0917e5f0c790f44ed7342336c9238..96d65a1cf7be15bbee8ac91e48562c27623c013d 100644 (file)
@@ -446,6 +446,7 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node)
        u32 addr;
        int ret;
        char *c;
+       u16 soc_mask = 0;
 
        if (!(ti_clk_get_features()->flags & TI_CLK_CLKCTRL_COMPAT) &&
            of_node_name_eq(node, "clk"))
@@ -469,6 +470,13 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node)
                else
                        data = dra7_clkctrl_data;
        }
+
+       if (of_machine_is_compatible("ti,dra72"))
+               soc_mask = CLKF_SOC_DRA72;
+       if (of_machine_is_compatible("ti,dra74"))
+               soc_mask = CLKF_SOC_DRA74;
+       if (of_machine_is_compatible("ti,dra76"))
+               soc_mask = CLKF_SOC_DRA76;
 #endif
 #ifdef CONFIG_SOC_AM33XX
        if (of_machine_is_compatible("ti,am33xx")) {
@@ -501,6 +509,9 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node)
                data = dm816_clkctrl_data;
 #endif
 
+       if (ti_clk_get_features()->flags & TI_CLK_DEVICE_TYPE_GP)
+               soc_mask |= CLKF_SOC_NONSEC;
+
        while (data->addr) {
                if (addr == data->addr)
                        break;
@@ -562,6 +573,12 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node)
        reg_data = data->regs;
 
        while (reg_data->parent) {
+               if ((reg_data->flags & CLKF_SOC_MASK) &&
+                   (reg_data->flags & soc_mask) == 0) {
+                       reg_data++;
+                       continue;
+               }
+
                hw = kzalloc(sizeof(*hw), GFP_KERNEL);
                if (!hw)
                        return;
index 1c0fac59d8090fdf175a8d3baf0a1ef6e809cc49..e4b8392ff63c05d654413a0ec3bf2954a853480c 100644 (file)
@@ -83,6 +83,13 @@ enum {
 #define CLKF_HW_SUP                    BIT(6)
 #define CLKF_NO_IDLEST                 BIT(7)
 
+#define CLKF_SOC_MASK                  GENMASK(11, 8)
+
+#define CLKF_SOC_NONSEC                        BIT(8)
+#define CLKF_SOC_DRA72                 BIT(9)
+#define CLKF_SOC_DRA74                 BIT(10)
+#define CLKF_SOC_DRA76                 BIT(11)
+
 #define CLK(dev, con, ck)              \
        {                               \
                .lk = {                 \
@@ -303,7 +310,6 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
 int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
                                       struct clk_rate_request *req);
 int omap2_clk_for_each(int (*fn)(struct clk_hw_omap *hw));
-bool omap2_clk_is_hw_omap(struct clk_hw *hw);
 
 extern struct ti_clk_ll_ops *ti_clk_ll_ops;
 
index 7c0403b733ae4c5b236b58f3ea440cf0a2204a1c..698306f4801fc52cc400461c7414cc5f80db2701 100644 (file)
@@ -42,7 +42,8 @@ static int clk_sysctrl_prepare(struct clk_hw *hw)
                                clk->reg_bits[0]);
 
        if (!ret && clk->enable_delay_us)
-               usleep_range(clk->enable_delay_us, clk->enable_delay_us);
+               usleep_range(clk->enable_delay_us, clk->enable_delay_us +
+                            (clk->enable_delay_us >> 2));
 
        return ret;
 }
index d7b53ac8ad11520101c11823fd44c0b9eaec178f..4b9d5c14c400cfb7199ae0595145ae8a11c451d9 100644 (file)
@@ -158,7 +158,7 @@ static void __init zynq_clk_register_fclk(enum zynq_clk fclk,
        clks[fclk] = clk_register_gate(NULL, clk_name,
                        div1_name, CLK_SET_RATE_PARENT, fclk_gate_reg,
                        0, CLK_GATE_SET_TO_DISABLE, fclk_gate_lock);
-       enable_reg = clk_readl(fclk_gate_reg) & 1;
+       enable_reg = readl(fclk_gate_reg) & 1;
        if (enable && !enable_reg) {
                if (clk_prepare_enable(clks[fclk]))
                        pr_warn("%s: FCLK%u enable failed\n", __func__,
@@ -287,7 +287,7 @@ static void __init zynq_clk_setup(struct device_node *np)
                        SLCR_IOPLL_CTRL, 4, 1, 0, &iopll_lock);
 
        /* CPU clocks */
-       tmp = clk_readl(SLCR_621_TRUE) & 1;
+       tmp = readl(SLCR_621_TRUE) & 1;
        clk = clk_register_mux(NULL, "cpu_mux", cpu_parents, 4,
                        CLK_SET_RATE_NO_REPARENT, SLCR_ARM_CLK_CTRL, 4, 2, 0,
                        &armclk_lock);
@@ -510,7 +510,7 @@ static void __init zynq_clk_setup(struct device_node *np)
                        &dbgclk_lock);
 
        /* leave debug clocks in the state the bootloader set them up to */
-       tmp = clk_readl(SLCR_DBG_CLK_CTRL);
+       tmp = readl(SLCR_DBG_CLK_CTRL);
        if (tmp & DBG_CLK_CTRL_CLKACT_TRC)
                if (clk_prepare_enable(clks[dbg_trc]))
                        pr_warn("%s: trace clk enable failed\n", __func__);
index 00d72fb5c0361e675c3930746588c19d860165da..800b70ee19b39e7d10b89634b0477ed6343422fd 100644 (file)
@@ -90,7 +90,7 @@ static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
         * makes probably sense to redundantly save fbdiv in the struct
         * zynq_pll to save the IO access.
         */
-       fbdiv = (clk_readl(clk->pll_ctrl) & PLLCTRL_FBDIV_MASK) >>
+       fbdiv = (readl(clk->pll_ctrl) & PLLCTRL_FBDIV_MASK) >>
                        PLLCTRL_FBDIV_SHIFT;
 
        return parent_rate * fbdiv;
@@ -112,7 +112,7 @@ static int zynq_pll_is_enabled(struct clk_hw *hw)
 
        spin_lock_irqsave(clk->lock, flags);
 
-       reg = clk_readl(clk->pll_ctrl);
+       reg = readl(clk->pll_ctrl);
 
        spin_unlock_irqrestore(clk->lock, flags);
 
@@ -138,10 +138,10 @@ static int zynq_pll_enable(struct clk_hw *hw)
        /* Power up PLL and wait for lock */
        spin_lock_irqsave(clk->lock, flags);
 
-       reg = clk_readl(clk->pll_ctrl);
+       reg = readl(clk->pll_ctrl);
        reg &= ~(PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK);
-       clk_writel(reg, clk->pll_ctrl);
-       while (!(clk_readl(clk->pll_status) & (1 << clk->lockbit)))
+       writel(reg, clk->pll_ctrl);
+       while (!(readl(clk->pll_status) & (1 << clk->lockbit)))
                ;
 
        spin_unlock_irqrestore(clk->lock, flags);
@@ -168,9 +168,9 @@ static void zynq_pll_disable(struct clk_hw *hw)
        /* shut down PLL */
        spin_lock_irqsave(clk->lock, flags);
 
-       reg = clk_readl(clk->pll_ctrl);
+       reg = readl(clk->pll_ctrl);
        reg |= PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK;
-       clk_writel(reg, clk->pll_ctrl);
+       writel(reg, clk->pll_ctrl);
 
        spin_unlock_irqrestore(clk->lock, flags);
 }
@@ -223,9 +223,9 @@ struct clk *clk_register_zynq_pll(const char *name, const char *parent,
 
        spin_lock_irqsave(pll->lock, flags);
 
-       reg = clk_readl(pll->pll_ctrl);
+       reg = readl(pll->pll_ctrl);
        reg &= ~PLLCTRL_BPQUAL_MASK;
-       clk_writel(reg, pll->pll_ctrl);
+       writel(reg, pll->pll_ctrl);
 
        spin_unlock_irqrestore(pll->lock, flags);
 
index 4143f560c28d67d3cd7b2799c99f74099aded436..0af8f74c5fa5424028b63bf8c4db45fc93db0aee 100644 (file)
@@ -138,4 +138,3 @@ struct clk_hw *zynqmp_clk_register_mux(const char *name, u32 clk_id,
 
        return hw;
 }
-EXPORT_SYMBOL_GPL(zynqmp_clk_register_mux);
index 7ab163b67249f277144c3283a4f34d01e5351213..fec9a15c878620db88ea8d9d8389aeac3e9bc0b5 100644 (file)
 
 #include <linux/firmware/xlnx-zynqmp.h>
 
-/* Clock APIs payload parameters */
-#define CLK_GET_NAME_RESP_LEN                          16
-#define CLK_GET_TOPOLOGY_RESP_WORDS                    3
-#define CLK_GET_PARENTS_RESP_WORDS                     3
-#define CLK_GET_ATTR_RESP_WORDS                                1
-
 enum topology_type {
        TYPE_INVALID,
        TYPE_MUX,
index b0908ec62f73b057828ec0965a80bd9582f8acb7..8febd2431545c90ac51b2479c60a5ef54baff8a1 100644 (file)
 #define MAX_NODES                      6
 #define MAX_NAME_LEN                   50
 
-#define CLK_TYPE_SHIFT                 2
-
-#define PM_API_PAYLOAD_LEN             3
-
-#define NA_PARENT                      0xFFFFFFFF
-#define DUMMY_PARENT                   0xFFFFFFFE
-
-#define CLK_TYPE_FIELD_LEN             4
-#define CLK_TOPOLOGY_NODE_OFFSET       16
-#define NODES_PER_RESP                 3
-
-#define CLK_TYPE_FIELD_MASK            0xF
-#define CLK_FLAG_FIELD_MASK            GENMASK(21, 8)
-#define CLK_TYPE_FLAG_FIELD_MASK       GENMASK(31, 24)
-
-#define CLK_PARENTS_ID_LEN             16
-#define CLK_PARENTS_ID_MASK            0xFFFF
-
 /* Flags for parents */
 #define PARENT_CLK_SELF                        0
 #define PARENT_CLK_NODE1               1
 #define END_OF_PARENTS                 1
 #define RESERVED_CLK_NAME              ""
 
-#define CLK_VALID_MASK                 0x1
+#define CLK_GET_NAME_RESP_LEN          16
+#define CLK_GET_TOPOLOGY_RESP_WORDS    3
+#define CLK_GET_PARENTS_RESP_WORDS     3
+#define CLK_GET_ATTR_RESP_WORDS                1
 
 enum clk_type {
        CLK_TYPE_OUTPUT,
@@ -80,6 +65,7 @@ struct clock_parent {
  * @num_nodes:         Number of nodes present in topology
  * @parent:            Parent of clock
  * @num_parents:       Number of parents of clock
+ * @clk_id:            Clock id
  */
 struct zynqmp_clock {
        char clk_name[MAX_NAME_LEN];
@@ -89,6 +75,36 @@ struct zynqmp_clock {
        u32 num_nodes;
        struct clock_parent parent[MAX_PARENT];
        u32 num_parents;
+       u32 clk_id;
+};
+
+struct name_resp {
+       char name[CLK_GET_NAME_RESP_LEN];
+};
+
+struct topology_resp {
+#define CLK_TOPOLOGY_TYPE              GENMASK(3, 0)
+#define CLK_TOPOLOGY_FLAGS             GENMASK(23, 8)
+#define CLK_TOPOLOGY_TYPE_FLAGS                GENMASK(31, 24)
+       u32 topology[CLK_GET_TOPOLOGY_RESP_WORDS];
+};
+
+struct parents_resp {
+#define NA_PARENT                      0xFFFFFFFF
+#define DUMMY_PARENT                   0xFFFFFFFE
+#define CLK_PARENTS_ID                 GENMASK(15, 0)
+#define CLK_PARENTS_FLAGS              GENMASK(31, 16)
+       u32 parents[CLK_GET_PARENTS_RESP_WORDS];
+};
+
+struct attr_resp {
+#define CLK_ATTR_VALID                 BIT(0)
+#define CLK_ATTR_TYPE                  BIT(2)
+#define CLK_ATTR_NODE_INDEX            GENMASK(13, 0)
+#define CLK_ATTR_NODE_TYPE             GENMASK(19, 14)
+#define CLK_ATTR_NODE_SUBCLASS         GENMASK(25, 20)
+#define CLK_ATTR_NODE_CLASS            GENMASK(31, 26)
+       u32 attr[CLK_GET_ATTR_RESP_WORDS];
 };
 
 static const char clk_type_postfix[][10] = {
@@ -199,14 +215,15 @@ static int zynqmp_pm_clock_get_num_clocks(u32 *nclocks)
 /**
  * zynqmp_pm_clock_get_name() - Get the name of clock for given id
  * @clock_id:  ID of the clock to be queried
- * @name:      Name of given clock
+ * @response:  Name of the clock with the given id
  *
  * This function is used to get name of clock specified by given
  * clock ID.
  *
- * Return: Returns 0, in case of error name would be 0
+ * Return: Returns 0
  */
-static int zynqmp_pm_clock_get_name(u32 clock_id, char *name)
+static int zynqmp_pm_clock_get_name(u32 clock_id,
+                                   struct name_resp *response)
 {
        struct zynqmp_pm_query_data qdata = {0};
        u32 ret_payload[PAYLOAD_ARG_CNT];
@@ -215,7 +232,7 @@ static int zynqmp_pm_clock_get_name(u32 clock_id, char *name)
        qdata.arg1 = clock_id;
 
        eemi_ops->query_data(qdata, ret_payload);
-       memcpy(name, ret_payload, CLK_GET_NAME_RESP_LEN);
+       memcpy(response, ret_payload, sizeof(*response));
 
        return 0;
 }
@@ -224,7 +241,7 @@ static int zynqmp_pm_clock_get_name(u32 clock_id, char *name)
  * zynqmp_pm_clock_get_topology() - Get the topology of clock for given id
  * @clock_id:  ID of the clock to be queried
  * @index:     Node index of clock topology
- * @topology:  Buffer to store nodes in topology and flags
+ * @response:  Buffer used for the topology response
  *
  * This function is used to get topology information for the clock
  * specified by given clock ID.
@@ -237,7 +254,8 @@ static int zynqmp_pm_clock_get_name(u32 clock_id, char *name)
  *
  * Return: 0 on success else error+reason
  */
-static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index, u32 *topology)
+static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index,
+                                       struct topology_resp *response)
 {
        struct zynqmp_pm_query_data qdata = {0};
        u32 ret_payload[PAYLOAD_ARG_CNT];
@@ -248,7 +266,7 @@ static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index, u32 *topology)
        qdata.arg2 = index;
 
        ret = eemi_ops->query_data(qdata, ret_payload);
-       memcpy(topology, &ret_payload[1], CLK_GET_TOPOLOGY_RESP_WORDS * 4);
+       memcpy(response, &ret_payload[1], sizeof(*response));
 
        return ret;
 }
@@ -297,7 +315,7 @@ struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id,
  * zynqmp_pm_clock_get_parents() - Get the first 3 parents of clock for given id
  * @clock_id:  Clock ID
  * @index:     Parent index
- * @parents:   3 parents of the given clock
+ * @response:  Parents of the given clock
  *
  * This function is used to get 3 parents for the clock specified by
  * given clock ID.
@@ -310,7 +328,8 @@ struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id,
  *
  * Return: 0 on success else error+reason
  */
-static int zynqmp_pm_clock_get_parents(u32 clock_id, u32 index, u32 *parents)
+static int zynqmp_pm_clock_get_parents(u32 clock_id, u32 index,
+                                      struct parents_resp *response)
 {
        struct zynqmp_pm_query_data qdata = {0};
        u32 ret_payload[PAYLOAD_ARG_CNT];
@@ -321,7 +340,7 @@ static int zynqmp_pm_clock_get_parents(u32 clock_id, u32 index, u32 *parents)
        qdata.arg2 = index;
 
        ret = eemi_ops->query_data(qdata, ret_payload);
-       memcpy(parents, &ret_payload[1], CLK_GET_PARENTS_RESP_WORDS * 4);
+       memcpy(response, &ret_payload[1], sizeof(*response));
 
        return ret;
 }
@@ -329,13 +348,14 @@ static int zynqmp_pm_clock_get_parents(u32 clock_id, u32 index, u32 *parents)
 /**
  * zynqmp_pm_clock_get_attributes() - Get the attributes of clock for given id
  * @clock_id:  Clock ID
- * @attr:      Clock attributes
+ * @response:  Clock attributes response
  *
  * This function is used to get clock's attributes(e.g. valid, clock type, etc).
  *
  * Return: 0 on success else error+reason
  */
-static int zynqmp_pm_clock_get_attributes(u32 clock_id, u32 *attr)
+static int zynqmp_pm_clock_get_attributes(u32 clock_id,
+                                         struct attr_resp *response)
 {
        struct zynqmp_pm_query_data qdata = {0};
        u32 ret_payload[PAYLOAD_ARG_CNT];
@@ -345,7 +365,7 @@ static int zynqmp_pm_clock_get_attributes(u32 clock_id, u32 *attr)
        qdata.arg1 = clock_id;
 
        ret = eemi_ops->query_data(qdata, ret_payload);
-       memcpy(attr, &ret_payload[1], CLK_GET_ATTR_RESP_WORDS * 4);
+       memcpy(response, &ret_payload[1], sizeof(*response));
 
        return ret;
 }
@@ -354,24 +374,28 @@ static int zynqmp_pm_clock_get_attributes(u32 clock_id, u32 *attr)
  * __zynqmp_clock_get_topology() - Get topology data of clock from firmware
  *                                response data
  * @topology:          Clock topology
- * @data:              Clock topology data received from firmware
+ * @response:          Clock topology data received from firmware
  * @nnodes:            Number of nodes
  *
  * Return: 0 on success else error+reason
  */
 static int __zynqmp_clock_get_topology(struct clock_topology *topology,
-                                      u32 *data, u32 *nnodes)
+                                      struct topology_resp *response,
+                                      u32 *nnodes)
 {
        int i;
+       u32 type;
 
-       for (i = 0; i < PM_API_PAYLOAD_LEN; i++) {
-               if (!(data[i] & CLK_TYPE_FIELD_MASK))
+       for (i = 0; i < ARRAY_SIZE(response->topology); i++) {
+               type = FIELD_GET(CLK_TOPOLOGY_TYPE, response->topology[i]);
+               if (type == TYPE_INVALID)
                        return END_OF_TOPOLOGY_NODE;
-               topology[*nnodes].type = data[i] & CLK_TYPE_FIELD_MASK;
-               topology[*nnodes].flag = FIELD_GET(CLK_FLAG_FIELD_MASK,
-                                                  data[i]);
+               topology[*nnodes].type = type;
+               topology[*nnodes].flag = FIELD_GET(CLK_TOPOLOGY_FLAGS,
+                                                  response->topology[i]);
                topology[*nnodes].type_flag =
-                               FIELD_GET(CLK_TYPE_FLAG_FIELD_MASK, data[i]);
+                               FIELD_GET(CLK_TOPOLOGY_TYPE_FLAGS,
+                                         response->topology[i]);
                (*nnodes)++;
        }
 
@@ -392,14 +416,16 @@ static int zynqmp_clock_get_topology(u32 clk_id,
                                     u32 *num_nodes)
 {
        int j, ret;
-       u32 pm_resp[PM_API_PAYLOAD_LEN] = {0};
+       struct topology_resp response = { };
 
        *num_nodes = 0;
-       for (j = 0; j <= MAX_NODES; j += 3) {
-               ret = zynqmp_pm_clock_get_topology(clk_id, j, pm_resp);
+       for (j = 0; j <= MAX_NODES; j += ARRAY_SIZE(response.topology)) {
+               ret = zynqmp_pm_clock_get_topology(clock[clk_id].clk_id, j,
+                                                  &response);
                if (ret)
                        return ret;
-               ret = __zynqmp_clock_get_topology(topology, pm_resp, num_nodes);
+               ret = __zynqmp_clock_get_topology(topology, &response,
+                                                 num_nodes);
                if (ret == END_OF_TOPOLOGY_NODE)
                        return 0;
        }
@@ -408,31 +434,33 @@ static int zynqmp_clock_get_topology(u32 clk_id,
 }
 
 /**
- * __zynqmp_clock_get_topology() - Get parents info of clock from firmware
+ * __zynqmp_clock_get_parents() - Get parents info of clock from firmware
  *                                response data
  * @parents:           Clock parents
- * @data:              Clock parents data received from firmware
+ * @response:          Clock parents data received from firmware
  * @nparent:           Number of parent
  *
  * Return: 0 on success else error+reason
  */
-static int __zynqmp_clock_get_parents(struct clock_parent *parents, u32 *data,
+static int __zynqmp_clock_get_parents(struct clock_parent *parents,
+                                     struct parents_resp *response,
                                      u32 *nparent)
 {
        int i;
        struct clock_parent *parent;
 
-       for (i = 0; i < PM_API_PAYLOAD_LEN; i++) {
-               if (data[i] == NA_PARENT)
+       for (i = 0; i < ARRAY_SIZE(response->parents); i++) {
+               if (response->parents[i] == NA_PARENT)
                        return END_OF_PARENTS;
 
                parent = &parents[i];
-               parent->id = data[i] & CLK_PARENTS_ID_MASK;
-               if (data[i] == DUMMY_PARENT) {
+               parent->id = FIELD_GET(CLK_PARENTS_ID, response->parents[i]);
+               if (response->parents[i] == DUMMY_PARENT) {
                        strcpy(parent->name, "dummy_name");
                        parent->flag = 0;
                } else {
-                       parent->flag = data[i] >> CLK_PARENTS_ID_LEN;
+                       parent->flag = FIELD_GET(CLK_PARENTS_FLAGS,
+                                                response->parents[i]);
                        if (zynqmp_get_clock_name(parent->id, parent->name))
                                continue;
                }
@@ -454,20 +482,21 @@ static int zynqmp_clock_get_parents(u32 clk_id, struct clock_parent *parents,
                                    u32 *num_parents)
 {
        int j = 0, ret;
-       u32 pm_resp[PM_API_PAYLOAD_LEN] = {0};
+       struct parents_resp response = { };
 
        *num_parents = 0;
        do {
                /* Get parents from firmware */
-               ret = zynqmp_pm_clock_get_parents(clk_id, j, pm_resp);
+               ret = zynqmp_pm_clock_get_parents(clock[clk_id].clk_id, j,
+                                                 &response);
                if (ret)
                        return ret;
 
-               ret = __zynqmp_clock_get_parents(&parents[j], pm_resp,
+               ret = __zynqmp_clock_get_parents(&parents[j], &response,
                                                 num_parents);
                if (ret == END_OF_PARENTS)
                        return 0;
-               j += PM_API_PAYLOAD_LEN;
+               j += ARRAY_SIZE(response.parents);
        } while (*num_parents <= MAX_PARENT);
 
        return 0;
@@ -528,13 +557,14 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name,
                                                   const char **parent_names)
 {
        int j;
-       u32 num_nodes;
+       u32 num_nodes, clk_dev_id;
        char *clk_out = NULL;
        struct clock_topology *nodes;
        struct clk_hw *hw = NULL;
 
        nodes = clock[clk_id].node;
        num_nodes = clock[clk_id].num_nodes;
+       clk_dev_id = clock[clk_id].clk_id;
 
        for (j = 0; j < num_nodes; j++) {
                /*
@@ -551,13 +581,14 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name,
                if (!clk_topology[nodes[j].type])
                        continue;
 
-               hw = (*clk_topology[nodes[j].type])(clk_out, clk_id,
+               hw = (*clk_topology[nodes[j].type])(clk_out, clk_dev_id,
                                                    parent_names,
                                                    num_parents,
                                                    &nodes[j]);
                if (IS_ERR(hw))
-                       pr_warn_once("%s() %s register fail with %ld\n",
-                                    __func__, clk_name, PTR_ERR(hw));
+                       pr_warn_once("%s() 0x%x: %s register fail with %ld\n",
+                                    __func__,  clk_dev_id, clk_name,
+                                    PTR_ERR(hw));
 
                parent_names[0] = clk_out;
        }
@@ -621,20 +652,33 @@ static int zynqmp_register_clocks(struct device_node *np)
 static void zynqmp_get_clock_info(void)
 {
        int i, ret;
-       u32 attr, type = 0;
+       u32 type = 0;
+       u32 nodetype, subclass, class;
+       struct attr_resp attr;
+       struct name_resp name;
 
        for (i = 0; i < clock_max_idx; i++) {
-               zynqmp_pm_clock_get_name(i, clock[i].clk_name);
-               if (!strcmp(clock[i].clk_name, RESERVED_CLK_NAME))
-                       continue;
-
                ret = zynqmp_pm_clock_get_attributes(i, &attr);
                if (ret)
                        continue;
 
-               clock[i].valid = attr & CLK_VALID_MASK;
-               clock[i].type = attr >> CLK_TYPE_SHIFT ? CLK_TYPE_EXTERNAL :
-                                                       CLK_TYPE_OUTPUT;
+               clock[i].valid = FIELD_GET(CLK_ATTR_VALID, attr.attr[0]);
+               clock[i].type = FIELD_GET(CLK_ATTR_TYPE, attr.attr[0]) ?
+                       CLK_TYPE_EXTERNAL : CLK_TYPE_OUTPUT;
+
+               nodetype = FIELD_GET(CLK_ATTR_NODE_TYPE, attr.attr[0]);
+               subclass = FIELD_GET(CLK_ATTR_NODE_SUBCLASS, attr.attr[0]);
+               class = FIELD_GET(CLK_ATTR_NODE_CLASS, attr.attr[0]);
+
+               clock[i].clk_id = FIELD_PREP(CLK_ATTR_NODE_CLASS, class) |
+                                 FIELD_PREP(CLK_ATTR_NODE_SUBCLASS, subclass) |
+                                 FIELD_PREP(CLK_ATTR_NODE_TYPE, nodetype) |
+                                 FIELD_PREP(CLK_ATTR_NODE_INDEX, i);
+
+               zynqmp_pm_clock_get_name(clock[i].clk_id, &name);
+               if (!strcmp(name.name, RESERVED_CLK_NAME))
+                       continue;
+               strncpy(clock[i].clk_name, name.name, MAX_NAME_LEN);
        }
 
        /* Get topology of all clock */
index a371c66e72ef682d04655e2eaa0e288475380727..d8f5b70d27092cbe5816318d481fab783db062c2 100644 (file)
  * struct zynqmp_clk_divider - adjustable divider clock
  * @hw:                handle between common and hardware-specific interfaces
  * @flags:     Hardware specific flags
+ * @is_frac:   The divider is a fractional divider
  * @clk_id:    Id of clock
  * @div_type:  divisor type (TYPE_DIV1 or TYPE_DIV2)
  */
 struct zynqmp_clk_divider {
        struct clk_hw hw;
        u8 flags;
+       bool is_frac;
        u32 clk_id;
        u32 div_type;
 };
@@ -76,6 +78,13 @@ static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw,
        else
                value = div >> 16;
 
+       if (!value) {
+               WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO),
+                    "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
+                    clk_name);
+               return parent_rate;
+       }
+
        return DIV_ROUND_UP_ULL(parent_rate, value);
 }
 
@@ -116,8 +125,7 @@ static long zynqmp_clk_divider_round_rate(struct clk_hw *hw,
 
        bestdiv = zynqmp_divider_get_val(*prate, rate);
 
-       if ((clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) &&
-           (divider->flags & CLK_FRAC))
+       if ((clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) && divider->is_frac)
                bestdiv = rate % *prate ? 1 : bestdiv;
        *prate = rate * bestdiv;
 
@@ -195,11 +203,13 @@ struct clk_hw *zynqmp_clk_register_divider(const char *name,
 
        init.name = name;
        init.ops = &zynqmp_clk_divider_ops;
-       init.flags = nodes->flag;
+       /* CLK_FRAC is not defined in the common clk framework */
+       init.flags = nodes->flag & ~CLK_FRAC;
        init.parent_names = parents;
        init.num_parents = 1;
 
        /* struct clk_divider assignments */
+       div->is_frac = !!(nodes->flag & CLK_FRAC);
        div->flags = nodes->type_flag;
        div->hw.init = &init;
        div->clk_id = clk_id;
@@ -214,4 +224,3 @@ struct clk_hw *zynqmp_clk_register_divider(const char *name,
 
        return hw;
 }
-EXPORT_SYMBOL_GPL(zynqmp_clk_register_divider);
index c1ed641b3e26622041c0fead2931a13bface7454..4ae5d774443ec09eb6f31f4fd2a290ed268493a2 100644 (file)
@@ -470,7 +470,7 @@ static int meson_pwm_init_channels(struct meson_pwm *meson,
 
                init.name = name;
                init.ops = &clk_mux_ops;
-               init.flags = CLK_IS_BASIC;
+               init.flags = 0;
                init.parent_names = meson->data->parent_names;
                init.num_parents = meson->data->num_parents;
 
index fd9c362099d9bea3d3132ad203aa785f7a4314de..75901c636893c7ddb67c3777be1f97f0b042ebd0 100644 (file)
@@ -7,26 +7,6 @@
 #ifndef __AXG_AUDIO_CLKC_BINDINGS_H
 #define __AXG_AUDIO_CLKC_BINDINGS_H
 
-#define AUD_CLKID_SLV_SCLK0            9
-#define AUD_CLKID_SLV_SCLK1            10
-#define AUD_CLKID_SLV_SCLK2            11
-#define AUD_CLKID_SLV_SCLK3            12
-#define AUD_CLKID_SLV_SCLK4            13
-#define AUD_CLKID_SLV_SCLK5            14
-#define AUD_CLKID_SLV_SCLK6            15
-#define AUD_CLKID_SLV_SCLK7            16
-#define AUD_CLKID_SLV_SCLK8            17
-#define AUD_CLKID_SLV_SCLK9            18
-#define AUD_CLKID_SLV_LRCLK0           19
-#define AUD_CLKID_SLV_LRCLK1           20
-#define AUD_CLKID_SLV_LRCLK2           21
-#define AUD_CLKID_SLV_LRCLK3           22
-#define AUD_CLKID_SLV_LRCLK4           23
-#define AUD_CLKID_SLV_LRCLK5           24
-#define AUD_CLKID_SLV_LRCLK6           25
-#define AUD_CLKID_SLV_LRCLK7           26
-#define AUD_CLKID_SLV_LRCLK8           27
-#define AUD_CLKID_SLV_LRCLK9           28
 #define AUD_CLKID_DDR_ARB              29
 #define AUD_CLKID_PDM                  30
 #define AUD_CLKID_TDMIN_A              31
 #define AUD_CLKID_TDMOUT_A_LRCLK       134
 #define AUD_CLKID_TDMOUT_B_LRCLK       135
 #define AUD_CLKID_TDMOUT_C_LRCLK       136
+#define AUD_CLKID_SPDIFOUT_B           151
+#define AUD_CLKID_SPDIFOUT_B_CLK       152
+#define AUD_CLKID_TDM_MCLK_PAD0                155
+#define AUD_CLKID_TDM_MCLK_PAD1                156
+#define AUD_CLKID_TDM_LRCLK_PAD0       157
+#define AUD_CLKID_TDM_LRCLK_PAD1       158
+#define AUD_CLKID_TDM_LRCLK_PAD2       159
+#define AUD_CLKID_TDM_SCLK_PAD0                160
+#define AUD_CLKID_TDM_SCLK_PAD1                161
+#define AUD_CLKID_TDM_SCLK_PAD2                162
 
 #endif /* __AXG_AUDIO_CLKC_BINDINGS_H */
index f179eabbcdb70382dc99062d097f6e45dcb14351..86c2ad56c5ef6af1c6421d09686640627d8d1d08 100644 (file)
@@ -36,6 +36,7 @@
 #define CLK_UART0              257
 #define CLK_UART1              258
 #define CLK_UART2              259
+#define CLK_UART3              260
 #define CLK_I2C0               261
 #define CLK_I2C1               262
 #define CLK_I2C2               263
@@ -44,7 +45,7 @@
 #define CLK_USI1               266
 #define CLK_USI2               267
 #define CLK_USI3               268
-#define CLK_UART3              260
+#define CLK_TSADC              270
 #define CLK_PWM                        279
 #define CLK_MCT                        315
 #define CLK_WDT                        316
index 8db01ffbeb0635a25e3871eedd8b2bc1477ed2ba..e916e49ff28846f378c81195e5652427f307db59 100644 (file)
@@ -26,7 +26,9 @@
 #define CLKID_AO_M4_FCLK       13
 #define CLKID_AO_M4_HCLK       14
 #define CLKID_AO_CLK81         15
+#define CLKID_AO_SAR_ADC_SEL   16
 #define CLKID_AO_SAR_ADC_CLK   18
+#define CLKID_AO_CTS_OSCIN     19
 #define CLKID_AO_32K           23
 #define CLKID_AO_CEC           27
 #define CLKID_AO_CTS_RTC_OSCIN 28
index 83b657038d1ea0541c10c6a7fb0347c1bc219a8a..82c9e0c020b21fd4a463840674a606342072ebcf 100644 (file)
 #define CLKID_MALI_1                           174
 #define CLKID_MALI                             175
 #define CLKID_MPLL_5OM                         177
+#define CLKID_CPU_CLK                          187
+#define CLKID_PCIE_PLL                         201
+#define CLKID_VDEC_1                           204
+#define CLKID_VDEC_HEVC                                207
+#define CLKID_VDEC_HEVCF                       210
 
 #endif /* __G12A_CLKC_H */
index 21d872e69cb1951daea477da8ecc5ef2dbbf3bfc..6f66f9005c814bf3a6db2c66d845b373df9d0cc2 100644 (file)
@@ -65,7 +65,6 @@
 #define IMX7ULP_CLK_FLEXBUS            2
 #define IMX7ULP_CLK_SEMA42_1           3
 #define IMX7ULP_CLK_DMA_MUX1           4
-#define IMX7ULP_CLK_SNVS               5
 #define IMX7ULP_CLK_CAAM               6
 #define IMX7ULP_CLK_LPTPM4             7
 #define IMX7ULP_CLK_LPTPM5             8
index 460bbeff6ab84006a96b1ac7ba05a4562dbf93fc..31f1ab0fe42cfffcfc88591d0a3177501f7f23f5 100644 (file)
@@ -31,5 +31,6 @@
 #define JZ4725B_CLK_TCU                22
 #define JZ4725B_CLK_EXT512     23
 #define JZ4725B_CLK_RTC                24
+#define JZ4725B_CLK_UDC_PHY    25
 
 #endif /* __DT_BINDINGS_CLOCK_JZ4725B_CGU_H__ */
index 8067077a62ca9ccf82d688d22b83898db52be4b2..47556539f0ee44d4a011acf5de5a78a331bef2ba 100644 (file)
 #define CLKID_MPLL1            94
 #define CLKID_MPLL2            95
 #define CLKID_NAND_CLK         112
-#define CLKID_ABP              124
 #define CLKID_APB              124
 #define CLKID_PERIPH           126
 #define CLKID_AXI              128
 #define CLKID_L2_DRAM          130
+#define CLKID_VPU              190
+#define CLKID_VDEC_1           196
+#define CLKID_VDEC_HCODEC      199
+#define CLKID_VDEC_2           202
+#define CLKID_VDEC_HEVC                206
 
 #endif /* __MESON8B_CLKC_H */
diff --git a/include/dt-bindings/clock/mt8183-clk.h b/include/dt-bindings/clock/mt8183-clk.h
new file mode 100644 (file)
index 0000000..0046506
--- /dev/null
@@ -0,0 +1,422 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Weiyi Lu <weiyi.lu@mediatek.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT8183_H
+#define _DT_BINDINGS_CLK_MT8183_H
+
+/* APMIXED */
+#define CLK_APMIXED_ARMPLL_LL          0
+#define CLK_APMIXED_ARMPLL_L           1
+#define CLK_APMIXED_CCIPLL             2
+#define CLK_APMIXED_MAINPLL            3
+#define CLK_APMIXED_UNIV2PLL           4
+#define CLK_APMIXED_MSDCPLL            5
+#define CLK_APMIXED_MMPLL              6
+#define CLK_APMIXED_MFGPLL             7
+#define CLK_APMIXED_TVDPLL             8
+#define CLK_APMIXED_APLL1              9
+#define CLK_APMIXED_APLL2              10
+#define CLK_APMIXED_SSUSB_26M          11
+#define CLK_APMIXED_APPLL_26M          12
+#define CLK_APMIXED_MIPIC0_26M         13
+#define CLK_APMIXED_MDPLLGP_26M                14
+#define CLK_APMIXED_MMSYS_26M          15
+#define CLK_APMIXED_UFS_26M            16
+#define CLK_APMIXED_MIPIC1_26M         17
+#define CLK_APMIXED_MEMPLL_26M         18
+#define CLK_APMIXED_CLKSQ_LVPLL_26M    19
+#define CLK_APMIXED_MIPID0_26M         20
+#define CLK_APMIXED_MIPID1_26M         21
+#define CLK_APMIXED_NR_CLK             22
+
+/* TOPCKGEN */
+#define CLK_TOP_MUX_AXI                        0
+#define CLK_TOP_MUX_MM                 1
+#define CLK_TOP_MUX_CAM                        2
+#define CLK_TOP_MUX_MFG                        3
+#define CLK_TOP_MUX_CAMTG              4
+#define CLK_TOP_MUX_UART               5
+#define CLK_TOP_MUX_SPI                        6
+#define CLK_TOP_MUX_MSDC50_0_HCLK      7
+#define CLK_TOP_MUX_MSDC50_0           8
+#define CLK_TOP_MUX_MSDC30_1           9
+#define CLK_TOP_MUX_MSDC30_2           10
+#define CLK_TOP_MUX_AUDIO              11
+#define CLK_TOP_MUX_AUD_INTBUS         12
+#define CLK_TOP_MUX_FPWRAP_ULPOSC      13
+#define CLK_TOP_MUX_SCP                        14
+#define CLK_TOP_MUX_ATB                        15
+#define CLK_TOP_MUX_SSPM               16
+#define CLK_TOP_MUX_DPI0               17
+#define CLK_TOP_MUX_SCAM               18
+#define CLK_TOP_MUX_AUD_1              19
+#define CLK_TOP_MUX_AUD_2              20
+#define CLK_TOP_MUX_DISP_PWM           21
+#define CLK_TOP_MUX_SSUSB_TOP_XHCI     22
+#define CLK_TOP_MUX_USB_TOP            23
+#define CLK_TOP_MUX_SPM                        24
+#define CLK_TOP_MUX_I2C                        25
+#define CLK_TOP_MUX_F52M_MFG           26
+#define CLK_TOP_MUX_SENINF             27
+#define CLK_TOP_MUX_DXCC               28
+#define CLK_TOP_MUX_CAMTG2             29
+#define CLK_TOP_MUX_AUD_ENG1           30
+#define CLK_TOP_MUX_AUD_ENG2           31
+#define CLK_TOP_MUX_FAES_UFSFDE                32
+#define CLK_TOP_MUX_FUFS               33
+#define CLK_TOP_MUX_IMG                        34
+#define CLK_TOP_MUX_DSP                        35
+#define CLK_TOP_MUX_DSP1               36
+#define CLK_TOP_MUX_DSP2               37
+#define CLK_TOP_MUX_IPU_IF             38
+#define CLK_TOP_MUX_CAMTG3             39
+#define CLK_TOP_MUX_CAMTG4             40
+#define CLK_TOP_MUX_PMICSPI            41
+#define CLK_TOP_SYSPLL_CK              42
+#define CLK_TOP_SYSPLL_D2              43
+#define CLK_TOP_SYSPLL_D3              44
+#define CLK_TOP_SYSPLL_D5              45
+#define CLK_TOP_SYSPLL_D7              46
+#define CLK_TOP_SYSPLL_D2_D2           47
+#define CLK_TOP_SYSPLL_D2_D4           48
+#define CLK_TOP_SYSPLL_D2_D8           49
+#define CLK_TOP_SYSPLL_D2_D16          50
+#define CLK_TOP_SYSPLL_D3_D2           51
+#define CLK_TOP_SYSPLL_D3_D4           52
+#define CLK_TOP_SYSPLL_D3_D8           53
+#define CLK_TOP_SYSPLL_D5_D2           54
+#define CLK_TOP_SYSPLL_D5_D4           55
+#define CLK_TOP_SYSPLL_D7_D2           56
+#define CLK_TOP_SYSPLL_D7_D4           57
+#define CLK_TOP_UNIVPLL_CK             58
+#define CLK_TOP_UNIVPLL_D2             59
+#define CLK_TOP_UNIVPLL_D3             60
+#define CLK_TOP_UNIVPLL_D5             61
+#define CLK_TOP_UNIVPLL_D7             62
+#define CLK_TOP_UNIVPLL_D2_D2          63
+#define CLK_TOP_UNIVPLL_D2_D4          64
+#define CLK_TOP_UNIVPLL_D2_D8          65
+#define CLK_TOP_UNIVPLL_D3_D2          66
+#define CLK_TOP_UNIVPLL_D3_D4          67
+#define CLK_TOP_UNIVPLL_D3_D8          68
+#define CLK_TOP_UNIVPLL_D5_D2          69
+#define CLK_TOP_UNIVPLL_D5_D4          70
+#define CLK_TOP_UNIVPLL_D5_D8          71
+#define CLK_TOP_APLL1_CK               72
+#define CLK_TOP_APLL1_D2               73
+#define CLK_TOP_APLL1_D4               74
+#define CLK_TOP_APLL1_D8               75
+#define CLK_TOP_APLL2_CK               76
+#define CLK_TOP_APLL2_D2               77
+#define CLK_TOP_APLL2_D4               78
+#define CLK_TOP_APLL2_D8               79
+#define CLK_TOP_TVDPLL_CK              80
+#define CLK_TOP_TVDPLL_D2              81
+#define CLK_TOP_TVDPLL_D4              82
+#define CLK_TOP_TVDPLL_D8              83
+#define CLK_TOP_TVDPLL_D16             84
+#define CLK_TOP_MSDCPLL_CK             85
+#define CLK_TOP_MSDCPLL_D2             86
+#define CLK_TOP_MSDCPLL_D4             87
+#define CLK_TOP_MSDCPLL_D8             88
+#define CLK_TOP_MSDCPLL_D16            89
+#define CLK_TOP_AD_OSC_CK              90
+#define CLK_TOP_OSC_D2                 91
+#define CLK_TOP_OSC_D4                 92
+#define CLK_TOP_OSC_D8                 93
+#define CLK_TOP_OSC_D16                        94
+#define CLK_TOP_F26M_CK_D2             95
+#define CLK_TOP_MFGPLL_CK              96
+#define CLK_TOP_UNIVP_192M_CK          97
+#define CLK_TOP_UNIVP_192M_D2          98
+#define CLK_TOP_UNIVP_192M_D4          99
+#define CLK_TOP_UNIVP_192M_D8          100
+#define CLK_TOP_UNIVP_192M_D16         101
+#define CLK_TOP_UNIVP_192M_D32         102
+#define CLK_TOP_MMPLL_CK               103
+#define CLK_TOP_MMPLL_D4               104
+#define CLK_TOP_MMPLL_D4_D2            105
+#define CLK_TOP_MMPLL_D4_D4            106
+#define CLK_TOP_MMPLL_D5               107
+#define CLK_TOP_MMPLL_D5_D2            108
+#define CLK_TOP_MMPLL_D5_D4            109
+#define CLK_TOP_MMPLL_D6               110
+#define CLK_TOP_MMPLL_D7               111
+#define CLK_TOP_CLK26M                 112
+#define CLK_TOP_CLK13M                 113
+#define CLK_TOP_ULPOSC                 114
+#define CLK_TOP_UNIVP_192M             115
+#define CLK_TOP_MUX_APLL_I2S0          116
+#define CLK_TOP_MUX_APLL_I2S1          117
+#define CLK_TOP_MUX_APLL_I2S2          118
+#define CLK_TOP_MUX_APLL_I2S3          119
+#define CLK_TOP_MUX_APLL_I2S4          120
+#define CLK_TOP_MUX_APLL_I2S5          121
+#define CLK_TOP_APLL12_DIV0            122
+#define CLK_TOP_APLL12_DIV1            123
+#define CLK_TOP_APLL12_DIV2            124
+#define CLK_TOP_APLL12_DIV3            125
+#define CLK_TOP_APLL12_DIV4            126
+#define CLK_TOP_APLL12_DIVB            127
+#define CLK_TOP_UNIVPLL                        128
+#define CLK_TOP_ARMPLL_DIV_PLL1                129
+#define CLK_TOP_ARMPLL_DIV_PLL2                130
+#define CLK_TOP_UNIVPLL_D3_D16         131
+#define CLK_TOP_NR_CLK                 132
+
+/* CAMSYS */
+#define CLK_CAM_LARB6                  0
+#define CLK_CAM_DFP_VAD                        1
+#define CLK_CAM_CAM                    2
+#define CLK_CAM_CAMTG                  3
+#define CLK_CAM_SENINF                 4
+#define CLK_CAM_CAMSV0                 5
+#define CLK_CAM_CAMSV1                 6
+#define CLK_CAM_CAMSV2                 7
+#define CLK_CAM_CCU                    8
+#define CLK_CAM_LARB3                  9
+#define CLK_CAM_NR_CLK                 10
+
+/* INFRACFG_AO */
+#define CLK_INFRA_PMIC_TMR             0
+#define CLK_INFRA_PMIC_AP              1
+#define CLK_INFRA_PMIC_MD              2
+#define CLK_INFRA_PMIC_CONN            3
+#define CLK_INFRA_SCPSYS               4
+#define CLK_INFRA_SEJ                  5
+#define CLK_INFRA_APXGPT               6
+#define CLK_INFRA_ICUSB                        7
+#define CLK_INFRA_GCE                  8
+#define CLK_INFRA_THERM                        9
+#define CLK_INFRA_I2C0                 10
+#define CLK_INFRA_I2C1                 11
+#define CLK_INFRA_I2C2                 12
+#define CLK_INFRA_I2C3                 13
+#define CLK_INFRA_PWM_HCLK             14
+#define CLK_INFRA_PWM1                 15
+#define CLK_INFRA_PWM2                 16
+#define CLK_INFRA_PWM3                 17
+#define CLK_INFRA_PWM4                 18
+#define CLK_INFRA_PWM                  19
+#define CLK_INFRA_UART0                        20
+#define CLK_INFRA_UART1                        21
+#define CLK_INFRA_UART2                        22
+#define CLK_INFRA_UART3                        23
+#define CLK_INFRA_GCE_26M              24
+#define CLK_INFRA_CQ_DMA_FPC           25
+#define CLK_INFRA_BTIF                 26
+#define CLK_INFRA_SPI0                 27
+#define CLK_INFRA_MSDC0                        28
+#define CLK_INFRA_MSDC1                        29
+#define CLK_INFRA_MSDC2                        30
+#define CLK_INFRA_MSDC0_SCK            31
+#define CLK_INFRA_DVFSRC               32
+#define CLK_INFRA_GCPU                 33
+#define CLK_INFRA_TRNG                 34
+#define CLK_INFRA_AUXADC               35
+#define CLK_INFRA_CPUM                 36
+#define CLK_INFRA_CCIF1_AP             37
+#define CLK_INFRA_CCIF1_MD             38
+#define CLK_INFRA_AUXADC_MD            39
+#define CLK_INFRA_MSDC1_SCK            40
+#define CLK_INFRA_MSDC2_SCK            41
+#define CLK_INFRA_AP_DMA               42
+#define CLK_INFRA_XIU                  43
+#define CLK_INFRA_DEVICE_APC           44
+#define CLK_INFRA_CCIF_AP              45
+#define CLK_INFRA_DEBUGSYS             46
+#define CLK_INFRA_AUDIO                        47
+#define CLK_INFRA_CCIF_MD              48
+#define CLK_INFRA_DXCC_SEC_CORE                49
+#define CLK_INFRA_DXCC_AO              50
+#define CLK_INFRA_DRAMC_F26M           51
+#define CLK_INFRA_IRTX                 52
+#define CLK_INFRA_DISP_PWM             53
+#define CLK_INFRA_CLDMA_BCLK           54
+#define CLK_INFRA_AUDIO_26M_BCLK       55
+#define CLK_INFRA_SPI1                 56
+#define CLK_INFRA_I2C4                 57
+#define CLK_INFRA_MODEM_TEMP_SHARE     58
+#define CLK_INFRA_SPI2                 59
+#define CLK_INFRA_SPI3                 60
+#define CLK_INFRA_UNIPRO_SCK           61
+#define CLK_INFRA_UNIPRO_TICK          62
+#define CLK_INFRA_UFS_MP_SAP_BCLK      63
+#define CLK_INFRA_MD32_BCLK            64
+#define CLK_INFRA_SSPM                 65
+#define CLK_INFRA_UNIPRO_MBIST         66
+#define CLK_INFRA_SSPM_BUS_HCLK                67
+#define CLK_INFRA_I2C5                 68
+#define CLK_INFRA_I2C5_ARBITER         69
+#define CLK_INFRA_I2C5_IMM             70
+#define CLK_INFRA_I2C1_ARBITER         71
+#define CLK_INFRA_I2C1_IMM             72
+#define CLK_INFRA_I2C2_ARBITER         73
+#define CLK_INFRA_I2C2_IMM             74
+#define CLK_INFRA_SPI4                 75
+#define CLK_INFRA_SPI5                 76
+#define CLK_INFRA_CQ_DMA               77
+#define CLK_INFRA_UFS                  78
+#define CLK_INFRA_AES_UFSFDE           79
+#define CLK_INFRA_UFS_TICK             80
+#define CLK_INFRA_MSDC0_SELF           81
+#define CLK_INFRA_MSDC1_SELF           82
+#define CLK_INFRA_MSDC2_SELF           83
+#define CLK_INFRA_SSPM_26M_SELF                84
+#define CLK_INFRA_SSPM_32K_SELF                85
+#define CLK_INFRA_UFS_AXI              86
+#define CLK_INFRA_I2C6                 87
+#define CLK_INFRA_AP_MSDC0             88
+#define CLK_INFRA_MD_MSDC0             89
+#define CLK_INFRA_USB                  90
+#define CLK_INFRA_DEVMPU_BCLK          91
+#define CLK_INFRA_CCIF2_AP             92
+#define CLK_INFRA_CCIF2_MD             93
+#define CLK_INFRA_CCIF3_AP             94
+#define CLK_INFRA_CCIF3_MD             95
+#define CLK_INFRA_SEJ_F13M             96
+#define CLK_INFRA_AES_BCLK             97
+#define CLK_INFRA_I2C7                 98
+#define CLK_INFRA_I2C8                 99
+#define CLK_INFRA_FBIST2FPC            100
+#define CLK_INFRA_NR_CLK               101
+
+/* MFGCFG */
+#define CLK_MFG_BG3D                   0
+#define CLK_MFG_NR_CLK                 1
+
+/* IMG */
+#define CLK_IMG_OWE                    0
+#define CLK_IMG_WPE_B                  1
+#define CLK_IMG_WPE_A                  2
+#define CLK_IMG_MFB                    3
+#define CLK_IMG_RSC                    4
+#define CLK_IMG_DPE                    5
+#define CLK_IMG_FDVT                   6
+#define CLK_IMG_DIP                    7
+#define CLK_IMG_LARB2                  8
+#define CLK_IMG_LARB5                  9
+#define CLK_IMG_NR_CLK                 10
+
+/* MMSYS_CONFIG */
+#define CLK_MM_SMI_COMMON              0
+#define CLK_MM_SMI_LARB0               1
+#define CLK_MM_SMI_LARB1               2
+#define CLK_MM_GALS_COMM0              3
+#define CLK_MM_GALS_COMM1              4
+#define CLK_MM_GALS_CCU2MM             5
+#define CLK_MM_GALS_IPU12MM            6
+#define CLK_MM_GALS_IMG2MM             7
+#define CLK_MM_GALS_CAM2MM             8
+#define CLK_MM_GALS_IPU2MM             9
+#define CLK_MM_MDP_DL_TXCK             10
+#define CLK_MM_IPU_DL_TXCK             11
+#define CLK_MM_MDP_RDMA0               12
+#define CLK_MM_MDP_RDMA1               13
+#define CLK_MM_MDP_RSZ0                        14
+#define CLK_MM_MDP_RSZ1                        15
+#define CLK_MM_MDP_TDSHP               16
+#define CLK_MM_MDP_WROT0               17
+#define CLK_MM_FAKE_ENG                        18
+#define CLK_MM_DISP_OVL0               19
+#define CLK_MM_DISP_OVL0_2L            20
+#define CLK_MM_DISP_OVL1_2L            21
+#define CLK_MM_DISP_RDMA0              22
+#define CLK_MM_DISP_RDMA1              23
+#define CLK_MM_DISP_WDMA0              24
+#define CLK_MM_DISP_COLOR0             25
+#define CLK_MM_DISP_CCORR0             26
+#define CLK_MM_DISP_AAL0               27
+#define CLK_MM_DISP_GAMMA0             28
+#define CLK_MM_DISP_DITHER0            29
+#define CLK_MM_DISP_SPLIT              30
+#define CLK_MM_DSI0_MM                 31
+#define CLK_MM_DSI0_IF                 32
+#define CLK_MM_DPI_MM                  33
+#define CLK_MM_DPI_IF                  34
+#define CLK_MM_FAKE_ENG2               35
+#define CLK_MM_MDP_DL_RX               36
+#define CLK_MM_IPU_DL_RX               37
+#define CLK_MM_26M                     38
+#define CLK_MM_MMSYS_R2Y               39
+#define CLK_MM_DISP_RSZ                        40
+#define CLK_MM_MDP_WDMA0               41
+#define CLK_MM_MDP_AAL                 42
+#define CLK_MM_MDP_CCORR               43
+#define CLK_MM_DBI_MM                  44
+#define CLK_MM_DBI_IF                  45
+#define CLK_MM_NR_CLK                  46
+
+/* VDEC_GCON */
+#define CLK_VDEC_VDEC                  0
+#define CLK_VDEC_LARB1                 1
+#define CLK_VDEC_NR_CLK                        2
+
+/* VENC_GCON */
+#define CLK_VENC_LARB                  0
+#define CLK_VENC_VENC                  1
+#define CLK_VENC_JPGENC                        2
+#define CLK_VENC_NR_CLK                        3
+
+/* AUDIO */
+#define CLK_AUDIO_TML                  0
+#define CLK_AUDIO_DAC_PREDIS           1
+#define CLK_AUDIO_DAC                  2
+#define CLK_AUDIO_ADC                  3
+#define CLK_AUDIO_APLL_TUNER           4
+#define CLK_AUDIO_APLL2_TUNER          5
+#define CLK_AUDIO_24M                  6
+#define CLK_AUDIO_22M                  7
+#define CLK_AUDIO_AFE                  8
+#define CLK_AUDIO_I2S4                 9
+#define CLK_AUDIO_I2S3                 10
+#define CLK_AUDIO_I2S2                 11
+#define CLK_AUDIO_I2S1                 12
+#define CLK_AUDIO_PDN_ADDA6_ADC                13
+#define CLK_AUDIO_TDM                  14
+#define CLK_AUDIO_NR_CLK               15
+
+/* IPU_CONN */
+#define CLK_IPU_CONN_IPU               0
+#define CLK_IPU_CONN_AHB               1
+#define CLK_IPU_CONN_AXI               2
+#define CLK_IPU_CONN_ISP               3
+#define CLK_IPU_CONN_CAM_ADL           4
+#define CLK_IPU_CONN_IMG_ADL           5
+#define CLK_IPU_CONN_DAP_RX            6
+#define CLK_IPU_CONN_APB2AXI           7
+#define CLK_IPU_CONN_APB2AHB           8
+#define CLK_IPU_CONN_IPU_CAB1TO2       9
+#define CLK_IPU_CONN_IPU1_CAB1TO2      10
+#define CLK_IPU_CONN_IPU2_CAB1TO2      11
+#define CLK_IPU_CONN_CAB3TO3           12
+#define CLK_IPU_CONN_CAB2TO1           13
+#define CLK_IPU_CONN_CAB3TO1_SLICE     14
+#define CLK_IPU_CONN_NR_CLK            15
+
+/* IPU_ADL */
+#define CLK_IPU_ADL_CABGEN             0
+#define CLK_IPU_ADL_NR_CLK             1
+
+/* IPU_CORE0 */
+#define CLK_IPU_CORE0_JTAG             0
+#define CLK_IPU_CORE0_AXI              1
+#define CLK_IPU_CORE0_IPU              2
+#define CLK_IPU_CORE0_NR_CLK           3
+
+/* IPU_CORE1 */
+#define CLK_IPU_CORE1_JTAG             0
+#define CLK_IPU_CORE1_AXI              1
+#define CLK_IPU_CORE1_IPU              2
+#define CLK_IPU_CORE1_NR_CLK           3
+
+/* MCUCFG */
+#define CLK_MCU_MP0_SEL                        0
+#define CLK_MCU_MP2_SEL                        1
+#define CLK_MCU_BUS_SEL                        2
+#define CLK_MCU_NR_CLK                 3
+
+#endif /* _DT_BINDINGS_CLK_MT8183_H */
diff --git a/include/dt-bindings/clock/mt8516-clk.h b/include/dt-bindings/clock/mt8516-clk.h
new file mode 100644 (file)
index 0000000..9cfca53
--- /dev/null
@@ -0,0 +1,211 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT8516_H
+#define _DT_BINDINGS_CLK_MT8516_H
+
+/* APMIXEDSYS */
+
+#define CLK_APMIXED_ARMPLL             0
+#define CLK_APMIXED_MAINPLL            1
+#define CLK_APMIXED_UNIVPLL            2
+#define CLK_APMIXED_MMPLL              3
+#define CLK_APMIXED_APLL1              4
+#define CLK_APMIXED_APLL2              5
+#define CLK_APMIXED_NR_CLK             6
+
+/* INFRACFG */
+
+#define CLK_IFR_MUX1_SEL               0
+#define CLK_IFR_ETH_25M_SEL            1
+#define CLK_IFR_I2C0_SEL               2
+#define CLK_IFR_I2C1_SEL               3
+#define CLK_IFR_I2C2_SEL               4
+#define CLK_IFR_NR_CLK                 5
+
+/* TOPCKGEN */
+
+#define CLK_TOP_CLK_NULL               0
+#define CLK_TOP_I2S_INFRA_BCK          1
+#define CLK_TOP_MEMPLL                 2
+#define CLK_TOP_DMPLL                  3
+#define CLK_TOP_MAINPLL_D2             4
+#define CLK_TOP_MAINPLL_D4             5
+#define CLK_TOP_MAINPLL_D8             6
+#define CLK_TOP_MAINPLL_D16            7
+#define CLK_TOP_MAINPLL_D11            8
+#define CLK_TOP_MAINPLL_D22            9
+#define CLK_TOP_MAINPLL_D3             10
+#define CLK_TOP_MAINPLL_D6             11
+#define CLK_TOP_MAINPLL_D12            12
+#define CLK_TOP_MAINPLL_D5             13
+#define CLK_TOP_MAINPLL_D10            14
+#define CLK_TOP_MAINPLL_D20            15
+#define CLK_TOP_MAINPLL_D40            16
+#define CLK_TOP_MAINPLL_D7             17
+#define CLK_TOP_MAINPLL_D14            18
+#define CLK_TOP_UNIVPLL_D2             19
+#define CLK_TOP_UNIVPLL_D4             20
+#define CLK_TOP_UNIVPLL_D8             21
+#define CLK_TOP_UNIVPLL_D16            22
+#define CLK_TOP_UNIVPLL_D3             23
+#define CLK_TOP_UNIVPLL_D6             24
+#define CLK_TOP_UNIVPLL_D12            25
+#define CLK_TOP_UNIVPLL_D24            26
+#define CLK_TOP_UNIVPLL_D5             27
+#define CLK_TOP_UNIVPLL_D20            28
+#define CLK_TOP_MMPLL380M              29
+#define CLK_TOP_MMPLL_D2               30
+#define CLK_TOP_MMPLL_200M             31
+#define CLK_TOP_USB_PHY48M             32
+#define CLK_TOP_APLL1                  33
+#define CLK_TOP_APLL1_D2               34
+#define CLK_TOP_APLL1_D4               35
+#define CLK_TOP_APLL1_D8               36
+#define CLK_TOP_APLL2                  37
+#define CLK_TOP_APLL2_D2               38
+#define CLK_TOP_APLL2_D4               39
+#define CLK_TOP_APLL2_D8               40
+#define CLK_TOP_CLK26M                 41
+#define CLK_TOP_CLK26M_D2              42
+#define CLK_TOP_AHB_INFRA_D2           43
+#define CLK_TOP_NFI1X                  44
+#define CLK_TOP_ETH_D2                 45
+#define CLK_TOP_THEM                   46
+#define CLK_TOP_APDMA                  47
+#define CLK_TOP_I2C0                   48
+#define CLK_TOP_I2C1                   49
+#define CLK_TOP_AUXADC1                        50
+#define CLK_TOP_NFI                    51
+#define CLK_TOP_NFIECC                 52
+#define CLK_TOP_DEBUGSYS               53
+#define CLK_TOP_PWM                    54
+#define CLK_TOP_UART0                  55
+#define CLK_TOP_UART1                  56
+#define CLK_TOP_BTIF                   57
+#define CLK_TOP_USB                    58
+#define CLK_TOP_FLASHIF_26M            59
+#define CLK_TOP_AUXADC2                        60
+#define CLK_TOP_I2C2                   61
+#define CLK_TOP_MSDC0                  62
+#define CLK_TOP_MSDC1                  63
+#define CLK_TOP_NFI2X                  64
+#define CLK_TOP_PMICWRAP_AP            65
+#define CLK_TOP_SEJ                    66
+#define CLK_TOP_MEMSLP_DLYER           67
+#define CLK_TOP_SPI                    68
+#define CLK_TOP_APXGPT                 69
+#define CLK_TOP_AUDIO                  70
+#define CLK_TOP_PMICWRAP_MD            71
+#define CLK_TOP_PMICWRAP_CONN          72
+#define CLK_TOP_PMICWRAP_26M           73
+#define CLK_TOP_AUX_ADC                        74
+#define CLK_TOP_AUX_TP                 75
+#define CLK_TOP_MSDC2                  76
+#define CLK_TOP_RBIST                  77
+#define CLK_TOP_NFI_BUS                        78
+#define CLK_TOP_GCE                    79
+#define CLK_TOP_TRNG                   80
+#define CLK_TOP_SEJ_13M                        81
+#define CLK_TOP_AES                    82
+#define CLK_TOP_PWM_B                  83
+#define CLK_TOP_PWM1_FB                        84
+#define CLK_TOP_PWM2_FB                        85
+#define CLK_TOP_PWM3_FB                        86
+#define CLK_TOP_PWM4_FB                        87
+#define CLK_TOP_PWM5_FB                        88
+#define CLK_TOP_USB_1P                 89
+#define CLK_TOP_FLASHIF_FREERUN                90
+#define CLK_TOP_66M_ETH                        91
+#define CLK_TOP_133M_ETH               92
+#define CLK_TOP_FETH_25M               93
+#define CLK_TOP_FETH_50M               94
+#define CLK_TOP_FLASHIF_AXI            95
+#define CLK_TOP_USBIF                  96
+#define CLK_TOP_UART2                  97
+#define CLK_TOP_BSI                    98
+#define CLK_TOP_RG_SPINOR              99
+#define CLK_TOP_RG_MSDC2               100
+#define CLK_TOP_RG_ETH                 101
+#define CLK_TOP_RG_AUD1                        102
+#define CLK_TOP_RG_AUD2                        103
+#define CLK_TOP_RG_AUD_ENGEN1          104
+#define CLK_TOP_RG_AUD_ENGEN2          105
+#define CLK_TOP_RG_I2C                 106
+#define CLK_TOP_RG_PWM_INFRA           107
+#define CLK_TOP_RG_AUD_SPDIF_IN                108
+#define CLK_TOP_RG_UART2               109
+#define CLK_TOP_RG_BSI                 110
+#define CLK_TOP_RG_DBG_ATCLK           111
+#define CLK_TOP_RG_NFIECC              112
+#define CLK_TOP_RG_APLL1_D2_EN         113
+#define CLK_TOP_RG_APLL1_D4_EN         114
+#define CLK_TOP_RG_APLL1_D8_EN         115
+#define CLK_TOP_RG_APLL2_D2_EN         116
+#define CLK_TOP_RG_APLL2_D4_EN         117
+#define CLK_TOP_RG_APLL2_D8_EN         118
+#define CLK_TOP_APLL12_DIV0            119
+#define CLK_TOP_APLL12_DIV1            120
+#define CLK_TOP_APLL12_DIV2            121
+#define CLK_TOP_APLL12_DIV3            122
+#define CLK_TOP_APLL12_DIV4            123
+#define CLK_TOP_APLL12_DIV4B           124
+#define CLK_TOP_APLL12_DIV5            125
+#define CLK_TOP_APLL12_DIV5B           126
+#define CLK_TOP_APLL12_DIV6            127
+#define CLK_TOP_UART0_SEL              128
+#define CLK_TOP_EMI_DDRPHY_SEL         129
+#define CLK_TOP_AHB_INFRA_SEL          130
+#define CLK_TOP_MSDC0_SEL              131
+#define CLK_TOP_UART1_SEL              132
+#define CLK_TOP_MSDC1_SEL              133
+#define CLK_TOP_PMICSPI_SEL            134
+#define CLK_TOP_QAXI_AUD26M_SEL                135
+#define CLK_TOP_AUD_INTBUS_SEL         136
+#define CLK_TOP_NFI2X_PAD_SEL          137
+#define CLK_TOP_NFI1X_PAD_SEL          138
+#define CLK_TOP_DDRPHYCFG_SEL          139
+#define CLK_TOP_USB_78M_SEL            140
+#define CLK_TOP_SPINOR_SEL             141
+#define CLK_TOP_MSDC2_SEL              142
+#define CLK_TOP_ETH_SEL                        143
+#define CLK_TOP_AUD1_SEL               144
+#define CLK_TOP_AUD2_SEL               145
+#define CLK_TOP_AUD_ENGEN1_SEL         146
+#define CLK_TOP_AUD_ENGEN2_SEL         147
+#define CLK_TOP_I2C_SEL                        148
+#define CLK_TOP_AUD_I2S0_M_SEL         149
+#define CLK_TOP_AUD_I2S1_M_SEL         150
+#define CLK_TOP_AUD_I2S2_M_SEL         151
+#define CLK_TOP_AUD_I2S3_M_SEL         152
+#define CLK_TOP_AUD_I2S4_M_SEL         153
+#define CLK_TOP_AUD_I2S5_M_SEL         154
+#define CLK_TOP_AUD_SPDIF_B_SEL                155
+#define CLK_TOP_PWM_SEL                        156
+#define CLK_TOP_SPI_SEL                        157
+#define CLK_TOP_AUD_SPDIFIN_SEL                158
+#define CLK_TOP_UART2_SEL              159
+#define CLK_TOP_BSI_SEL                        160
+#define CLK_TOP_DBG_ATCLK_SEL          161
+#define CLK_TOP_CSW_NFIECC_SEL         162
+#define CLK_TOP_NFIECC_SEL             163
+#define CLK_TOP_APLL12_CK_DIV0         164
+#define CLK_TOP_APLL12_CK_DIV1         165
+#define CLK_TOP_APLL12_CK_DIV2         166
+#define CLK_TOP_APLL12_CK_DIV3         167
+#define CLK_TOP_APLL12_CK_DIV4         168
+#define CLK_TOP_APLL12_CK_DIV4B                169
+#define CLK_TOP_APLL12_CK_DIV5         170
+#define CLK_TOP_APLL12_CK_DIV5B                171
+#define CLK_TOP_APLL12_CK_DIV6         172
+#define CLK_TOP_USB_78M                        173
+#define CLK_TOP_MSDC0_INFRA            174
+#define CLK_TOP_MSDC1_INFRA            175
+#define CLK_TOP_MSDC2_INFRA            176
+#define CLK_TOP_NR_CLK                 177
+
+#endif /* _DT_BINDINGS_CLK_MT8516_H */
index 6ceb55ed72c6f78dfc659755ead7d671f435bf14..454b3f43f53856874c8c6828767422fa590b844b 100644 (file)
 #define GCC_MDP_TBU_CLK                                        138
 #define GCC_QDSS_DAP_CLK                               139
 #define GCC_DCC_XO_CLK                                 140
+#define GCC_CDSP_CFG_AHB_CLK                           143
+#define GCC_BIMC_CDSP_CLK                              144
+#define GCC_CDSP_TBU_CLK                               145
+#define GCC_CDSP_BIMC_CLK_SRC                          146
 
 #define GCC_GENI_IR_BCR                                        0
 #define GCC_USB_HS_BCR                                 1
 #define GCC_PCIE_0_LINK_DOWN_BCR                       11
 #define GCC_PCIEPHY_0_PHY_BCR                          12
 #define GCC_EMAC_BCR                                   13
+#define GCC_CDSP_RESTART                               14
 
 #endif
diff --git a/include/dt-bindings/clock/qcom,turingcc-qcs404.h b/include/dt-bindings/clock/qcom,turingcc-qcs404.h
new file mode 100644 (file)
index 0000000..838faef
--- /dev/null
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019, Linaro Ltd
+ */
+
+#ifndef _DT_BINDINGS_CLK_TURING_QCS404_H
+#define _DT_BINDINGS_CLK_TURING_QCS404_H
+
+#define TURING_Q6SS_Q6_AXIM_CLK                0
+#define TURING_Q6SS_AHBM_AON_CLK       1
+#define TURING_WRAPPER_AON_CLK         2
+#define TURING_Q6SS_AHBS_AON_CLK       3
+#define TURING_WRAPPER_QOS_AHBS_AON_CLK        4
+
+#endif
index 58d8b515be55f4a2a44aaf3b10b41191747cb994..7d34e297049caa4c40f6190002ff8a8a4b6ece91 100644 (file)
 #define CLK_I2C3               28
 #define CLK_I2C4               29
 #define CLK_LPTIMER            30
-
-#define END_PRIMARY_CLK_F7     31
+#define CLK_PLL_SRC            31
+#define CLK_DFSDM1             32
+#define CLK_ADFSDM1            33
+#define CLK_F769_DSI           34
+#define END_PRIMARY_CLK_F7     35
 
 #endif
index 81f34d477aeba7ef4e7baa2512d21dfed2db569b..2e6b9ddcc24e50f67f882b649f344aa40ac0e9fb 100644 (file)
 #define CLK_AVS                        96
 #define CLK_HDMI               97
 #define CLK_GPU                        98
-
+#define CLK_MBUS               99
 #define CLK_IEP                        100
 
 #endif /* _DT_BINDINGS_CLK_SUN5I_H_ */
index b7cf80a712939a1818fd1045133faafcda755271..491d992d045d4fded2cf11397de471efcbb51cc9 100644 (file)
@@ -24,7 +24,7 @@
 #define CLK_SET_RATE_PARENT    BIT(2) /* propagate rate change up one level */
 #define CLK_IGNORE_UNUSED      BIT(3) /* do not gate even if unused */
                                /* unused */
-#define CLK_IS_BASIC           BIT(5) /* Basic clk, can't do a to_clk_foo() */
+                               /* unused */
 #define CLK_GET_RATE_NOCACHE   BIT(6) /* do not use the cached clk rate */
 #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
 #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
@@ -250,6 +250,20 @@ struct clk_ops {
        void            (*debug_init)(struct clk_hw *hw, struct dentry *dentry);
 };
 
+/**
+ * struct clk_parent_data - clk parent information
+ * @hw: parent clk_hw pointer (used for clk providers with internal clks)
+ * @fw_name: parent name local to provider registering clk
+ * @name: globally unique parent name (used as a fallback)
+ * @index: parent index local to provider registering clk (if @fw_name absent)
+ */
+struct clk_parent_data {
+       const struct clk_hw     *hw;
+       const char              *fw_name;
+       const char              *name;
+       int                     index;
+};
+
 /**
  * struct clk_init_data - holds init data that's common to all clocks and is
  * shared between the clock provider and the common clock framework.
@@ -257,13 +271,20 @@ struct clk_ops {
  * @name: clock name
  * @ops: operations this clock supports
  * @parent_names: array of string names for all possible parents
+ * @parent_data: array of parent data for all possible parents (when some
+ *               parents are external to the clk controller)
+ * @parent_hws: array of pointers to all possible parents (when all parents
+ *              are internal to the clk controller)
  * @num_parents: number of possible parents
  * @flags: framework-level hints and quirks
  */
 struct clk_init_data {
        const char              *name;
        const struct clk_ops    *ops;
+       /* Only one of the following three should be assigned */
        const char              * const *parent_names;
+       const struct clk_parent_data    *parent_data;
+       const struct clk_hw             **parent_hws;
        u8                      num_parents;
        unsigned long           flags;
 };
@@ -307,7 +328,6 @@ struct clk_fixed_rate {
        struct          clk_hw hw;
        unsigned long   fixed_rate;
        unsigned long   fixed_accuracy;
-       u8              flags;
 };
 
 #define to_clk_fixed_rate(_hw) container_of(_hw, struct clk_fixed_rate, hw)
@@ -349,6 +369,9 @@ void of_fixed_clk_setup(struct device_node *np);
  *     of this register, and mask of gate bits are in higher 16-bit of this
  *     register.  While setting the gate bits, higher 16-bit should also be
  *     updated to indicate changing gate bits.
+ * CLK_GATE_BIG_ENDIAN - by default little endian register accesses are used for
+ *     the gate register.  Setting this flag makes the register accesses big
+ *     endian.
  */
 struct clk_gate {
        struct clk_hw hw;
@@ -362,6 +385,7 @@ struct clk_gate {
 
 #define CLK_GATE_SET_TO_DISABLE                BIT(0)
 #define CLK_GATE_HIWORD_MASK           BIT(1)
+#define CLK_GATE_BIG_ENDIAN            BIT(2)
 
 extern const struct clk_ops clk_gate_ops;
 struct clk *clk_register_gate(struct device *dev, const char *name,
@@ -417,6 +441,9 @@ struct clk_div_table {
  * CLK_DIVIDER_MAX_AT_ZERO - For dividers which are like CLK_DIVIDER_ONE_BASED
  *     except when the value read from the register is zero, the divisor is
  *     2^width of the field.
+ * CLK_DIVIDER_BIG_ENDIAN - By default little endian register accesses are used
+ *     for the divider register.  Setting this flag makes the register accesses
+ *     big endian.
  */
 struct clk_divider {
        struct clk_hw   hw;
@@ -438,6 +465,7 @@ struct clk_divider {
 #define CLK_DIVIDER_ROUND_CLOSEST      BIT(4)
 #define CLK_DIVIDER_READ_ONLY          BIT(5)
 #define CLK_DIVIDER_MAX_AT_ZERO                BIT(6)
+#define CLK_DIVIDER_BIG_ENDIAN         BIT(7)
 
 extern const struct clk_ops clk_divider_ops;
 extern const struct clk_ops clk_divider_ro_ops;
@@ -499,8 +527,13 @@ void clk_hw_unregister_divider(struct clk_hw *hw);
  *     register, and mask of mux bits are in higher 16-bit of this register.
  *     While setting the mux bits, higher 16-bit should also be updated to
  *     indicate changing mux bits.
+ * CLK_MUX_READ_ONLY - The mux registers can't be written, only read in the
+ *     .get_parent clk_op.
  * CLK_MUX_ROUND_CLOSEST - Use the parent rate that is closest to the desired
  *     frequency.
+ * CLK_MUX_BIG_ENDIAN - By default little endian register accesses are used for
+ *     the mux register.  Setting this flag makes the register accesses big
+ *     endian.
  */
 struct clk_mux {
        struct clk_hw   hw;
@@ -519,6 +552,7 @@ struct clk_mux {
 #define CLK_MUX_HIWORD_MASK            BIT(2)
 #define CLK_MUX_READ_ONLY              BIT(3) /* mux can't be changed */
 #define CLK_MUX_ROUND_CLOSEST          BIT(4)
+#define CLK_MUX_BIG_ENDIAN             BIT(5)
 
 extern const struct clk_ops clk_mux_ops;
 extern const struct clk_ops clk_mux_ro_ops;
@@ -602,6 +636,9 @@ void clk_hw_unregister_fixed_factor(struct clk_hw *hw);
  *     is the value read from the register. If CLK_FRAC_DIVIDER_ZERO_BASED
  *     is set then the numerator and denominator are both the value read
  *     plus one.
+ * CLK_FRAC_DIVIDER_BIG_ENDIAN - By default little endian register accesses are
+ *     used for the divider register.  Setting this flag makes the register
+ *     accesses big endian.
  */
 struct clk_fractional_divider {
        struct clk_hw   hw;
@@ -622,6 +659,7 @@ struct clk_fractional_divider {
 #define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, hw)
 
 #define CLK_FRAC_DIVIDER_ZERO_BASED            BIT(0)
+#define CLK_FRAC_DIVIDER_BIG_ENDIAN            BIT(1)
 
 extern const struct clk_ops clk_fractional_divider_ops;
 struct clk *clk_register_fractional_divider(struct device *dev,
@@ -654,6 +692,9 @@ void clk_hw_unregister_fractional_divider(struct clk_hw *hw);
  *     leaving the parent rate unmodified.
  * CLK_MULTIPLIER_ROUND_CLOSEST - Makes the best calculated divider to be
  *     rounded to the closest integer instead of the down one.
+ * CLK_MULTIPLIER_BIG_ENDIAN - By default little endian register accesses are
+ *     used for the multiplier register.  Setting this flag makes the register
+ *     accesses big endian.
  */
 struct clk_multiplier {
        struct clk_hw   hw;
@@ -668,6 +709,7 @@ struct clk_multiplier {
 
 #define CLK_MULTIPLIER_ZERO_BYPASS             BIT(0)
 #define CLK_MULTIPLIER_ROUND_CLOSEST   BIT(1)
+#define CLK_MULTIPLIER_BIG_ENDIAN              BIT(2)
 
 extern const struct clk_ops clk_multiplier_ops;
 
@@ -712,16 +754,19 @@ struct clk_hw *clk_hw_register_composite(struct device *dev, const char *name,
                unsigned long flags);
 void clk_hw_unregister_composite(struct clk_hw *hw);
 
-/***
- * struct clk_gpio_gate - gpio gated clock
+/**
+ * struct clk_gpio - gpio gated clock
  *
  * @hw:                handle between common and hardware-specific interfaces
  * @gpiod:     gpio descriptor
  *
- * Clock with a gpio control for enabling and disabling the parent clock.
- * Implements .enable, .disable and .is_enabled
+ * Clock with a gpio control for enabling and disabling the parent clock
+ * or switching between two parents by asserting or deasserting the gpio.
+ *
+ * Implements .enable, .disable and .is_enabled or
+ * .get_parent, .set_parent and .determine_rate depending on which clk_ops
+ * is used.
  */
-
 struct clk_gpio {
        struct clk_hw   hw;
        struct gpio_desc *gpiod;
@@ -738,16 +783,6 @@ struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name,
                unsigned long flags);
 void clk_hw_unregister_gpio_gate(struct clk_hw *hw);
 
-/**
- * struct clk_gpio_mux - gpio controlled clock multiplexer
- *
- * @hw:                see struct clk_gpio
- * @gpiod:     gpio descriptor to select the parent of this clock multiplexer
- *
- * Clock with a gpio control for selecting the parent clock.
- * Implements .get_parent, .set_parent and .determine_rate
- */
-
 extern const struct clk_ops clk_gpio_mux_ops;
 struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
                const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod,
@@ -757,22 +792,12 @@ struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name,
                unsigned long flags);
 void clk_hw_unregister_gpio_mux(struct clk_hw *hw);
 
-/**
- * clk_register - allocate a new clock, register it and return an opaque cookie
- * @dev: device that is registering this clock
- * @hw: link to hardware-specific clock data
- *
- * clk_register is the primary interface for populating the clock tree with new
- * clock nodes.  It returns a pointer to the newly allocated struct clk which
- * cannot be dereferenced by driver code but may be used in conjuction with the
- * rest of the clock API.  In the event of an error clk_register will return an
- * error code; drivers must test for an error code after calling clk_register.
- */
 struct clk *clk_register(struct device *dev, struct clk_hw *hw);
 struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
 
 int __must_check clk_hw_register(struct device *dev, struct clk_hw *hw);
 int __must_check devm_clk_hw_register(struct device *dev, struct clk_hw *hw);
+int __must_check of_clk_hw_register(struct device_node *node, struct clk_hw *hw);
 
 void clk_unregister(struct clk *clk);
 void devm_clk_unregister(struct device *dev, struct clk *clk);
@@ -993,37 +1018,6 @@ static inline int of_clk_detect_critical(struct device_node *np, int index,
 }
 #endif /* CONFIG_OF */
 
-/*
- * wrap access to peripherals in accessor routines
- * for improved portability across platforms
- */
-
-#if IS_ENABLED(CONFIG_PPC)
-
-static inline u32 clk_readl(u32 __iomem *reg)
-{
-       return ioread32be(reg);
-}
-
-static inline void clk_writel(u32 val, u32 __iomem *reg)
-{
-       iowrite32be(val, reg);
-}
-
-#else  /* platform dependent I/O accessors */
-
-static inline u32 clk_readl(u32 __iomem *reg)
-{
-       return readl(reg);
-}
-
-static inline void clk_writel(u32 val, u32 __iomem *reg)
-{
-       writel(val, reg);
-}
-
-#endif /* platform dependent I/O accessors */
-
 void clk_gate_restore_context(struct clk_hw *hw);
 
 #endif /* CONFIG_COMMON_CLK */
diff --git a/include/linux/clk/analogbits-wrpll-cln28hpc.h b/include/linux/clk/analogbits-wrpll-cln28hpc.h
new file mode 100644 (file)
index 0000000..0327909
--- /dev/null
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018-2019 SiFive, Inc.
+ * Wesley Terpstra
+ * Paul Walmsley
+ */
+
+#ifndef __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H
+#define __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H
+
+#include <linux/types.h>
+
+/* DIVQ_VALUES: number of valid DIVQ values */
+#define DIVQ_VALUES                            6
+
+/*
+ * Bit definitions for struct wrpll_cfg.flags
+ *
+ * WRPLL_FLAGS_BYPASS_FLAG: if set, the PLL is either in bypass, or should be
+ *     programmed to enter bypass
+ * WRPLL_FLAGS_RESET_FLAG: if set, the PLL is in reset
+ * WRPLL_FLAGS_INT_FEEDBACK_FLAG: if set, the PLL is configured for internal
+ *     feedback mode
+ * WRPLL_FLAGS_EXT_FEEDBACK_FLAG: if set, the PLL is configured for external
+ *     feedback mode (not yet supported by this driver)
+ */
+#define WRPLL_FLAGS_BYPASS_SHIFT               0
+#define WRPLL_FLAGS_BYPASS_MASK                BIT(WRPLL_FLAGS_BYPASS_SHIFT)
+#define WRPLL_FLAGS_RESET_SHIFT                1
+#define WRPLL_FLAGS_RESET_MASK         BIT(WRPLL_FLAGS_RESET_SHIFT)
+#define WRPLL_FLAGS_INT_FEEDBACK_SHIFT 2
+#define WRPLL_FLAGS_INT_FEEDBACK_MASK  BIT(WRPLL_FLAGS_INT_FEEDBACK_SHIFT)
+#define WRPLL_FLAGS_EXT_FEEDBACK_SHIFT 3
+#define WRPLL_FLAGS_EXT_FEEDBACK_MASK  BIT(WRPLL_FLAGS_EXT_FEEDBACK_SHIFT)
+
+/**
+ * struct wrpll_cfg - WRPLL configuration values
+ * @divr: reference divider value (6 bits), as presented to the PLL signals
+ * @divf: feedback divider value (9 bits), as presented to the PLL signals
+ * @divq: output divider value (3 bits), as presented to the PLL signals
+ * @flags: PLL configuration flags.  See above for more information
+ * @range: PLL loop filter range.  See below for more information
+ * @output_rate_cache: cached output rates, swept across DIVQ
+ * @parent_rate: PLL refclk rate for which values are valid
+ * @max_r: maximum possible R divider value, given @parent_rate
+ * @init_r: initial R divider value to start the search from
+ *
+ * @divr, @divq, @divq, @range represent what the PLL expects to see
+ * on its input signals.  Thus @divr and @divf are the actual divisors
+ * minus one.  @divq is a power-of-two divider; for example, 1 =
+ * divide-by-2 and 6 = divide-by-64.  0 is an invalid @divq value.
+ *
+ * When initially passing a struct wrpll_cfg record, the
+ * record should be zero-initialized with the exception of the @flags
+ * field.  The only flag bits that need to be set are either
+ * WRPLL_FLAGS_INT_FEEDBACK or WRPLL_FLAGS_EXT_FEEDBACK.
+ */
+struct wrpll_cfg {
+       u8 divr;
+       u8 divq;
+       u8 range;
+       u8 flags;
+       u16 divf;
+/* private: */
+       u32 output_rate_cache[DIVQ_VALUES];
+       unsigned long parent_rate;
+       u8 max_r;
+       u8 init_r;
+};
+
+int wrpll_configure_for_rate(struct wrpll_cfg *c, u32 target_rate,
+                            unsigned long parent_rate);
+
+unsigned int wrpll_calc_max_lock_us(const struct wrpll_cfg *c);
+
+unsigned long wrpll_calc_output_rate(const struct wrpll_cfg *c,
+                                    unsigned long parent_rate);
+
+#endif /* __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H */
index 931ab05f771d66046fcd566f713bbeaf25139b50..0c53f26ae3d32378a92348e43920a861e638a7d6 100644 (file)
@@ -74,6 +74,8 @@
 #define                        AT91_PMC_USBDIV_4               (2 << 28)
 #define                AT91_PMC_USB96M         (1     << 28)           /* Divider by 2 Enable (PLLB only) */
 
+#define AT91_PMC_CPU_CKR       0x28                    /* CPU Clock Register */
+
 #define        AT91_PMC_MCKR           0x30                    /* Master Clock Register */
 #define                AT91_PMC_CSS            (3 <<  0)               /* Master Clock Selection */
 #define                        AT91_PMC_CSS_SLOW               (0 << 0)
 
 #define AT91_PMC_PCR           0x10c                   /* Peripheral Control Register [some SAM9 and SAMA5] */
 #define                AT91_PMC_PCR_PID_MASK           0x3f
-#define                AT91_PMC_PCR_GCKCSS_OFFSET      8
-#define                AT91_PMC_PCR_GCKCSS_MASK        (0x7  << AT91_PMC_PCR_GCKCSS_OFFSET)
-#define                AT91_PMC_PCR_GCKCSS(n)          ((n)  << AT91_PMC_PCR_GCKCSS_OFFSET)    /* GCK Clock Source Selection */
 #define                AT91_PMC_PCR_CMD                (0x1  <<  12)                           /* Command (read=0, write=1) */
-#define                AT91_PMC_PCR_DIV_OFFSET         16
-#define                AT91_PMC_PCR_DIV_MASK           (0x3  << AT91_PMC_PCR_DIV_OFFSET)
-#define                AT91_PMC_PCR_DIV(n)             ((n)  << AT91_PMC_PCR_DIV_OFFSET)       /* Divisor Value */
-#define                AT91_PMC_PCR_GCKDIV_OFFSET      20
-#define                AT91_PMC_PCR_GCKDIV_MASK        (0xff  << AT91_PMC_PCR_GCKDIV_OFFSET)
-#define                AT91_PMC_PCR_GCKDIV(n)          ((n)  << AT91_PMC_PCR_GCKDIV_OFFSET)    /* Generated Clock Divisor Value */
+#define                AT91_PMC_PCR_GCKDIV_MASK        GENMASK(27, 20)
 #define                AT91_PMC_PCR_EN                 (0x1  <<  28)                           /* Enable */
 #define                AT91_PMC_PCR_GCKEN              (0x1  <<  29)                           /* GCK Enable */
 
index 78872efc7be09fa9cd16e090ef17ae998cac06e1..1e8ef96555ce4c260e68063103e054beefac7b6d 100644 (file)
@@ -243,6 +243,7 @@ struct ti_clk_ll_ops {
 
 #define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw)
 
+bool omap2_clk_is_hw_omap(struct clk_hw *hw);
 int omap2_clk_disable_autoidle_all(void);
 int omap2_clk_enable_autoidle_all(void);
 int omap2_clk_allow_idle(struct clk *clk);
@@ -293,6 +294,7 @@ struct ti_clk_features {
 #define TI_CLK_DISABLE_CLKDM_CONTROL           BIT(2)
 #define TI_CLK_ERRATA_I810                     BIT(3)
 #define TI_CLK_CLKCTRL_COMPAT                  BIT(4)
+#define TI_CLK_DEVICE_TYPE_GP                  BIT(5)
 
 void ti_clk_setup_features(struct ti_clk_features *features);
 const struct ti_clk_features *ti_clk_get_features(void);
index 4457e560bc2b09cf3f10e943aa1fcfe40a0ebd49..e85264fb66161408aee2815001d8d5159ab04ac1 100644 (file)
@@ -1229,7 +1229,7 @@ static inline void device_lock_assert(struct device *dev)
 
 static inline struct device_node *dev_of_node(struct device *dev)
 {
-       if (!IS_ENABLED(CONFIG_OF))
+       if (!IS_ENABLED(CONFIG_OF) || !dev)
                return NULL;
        return dev->of_node;
 }
index bb2c84afb80c6c2246d233f7acab29c33bdb372e..65bef21cdddbd7584a01b7435327cdb994009b36 100644 (file)
@@ -284,4 +284,17 @@ static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
 #define DIV64_U64_ROUND_UP(ll, d)      \
        ({ u64 _tmp = (d); div64_u64((ll) + _tmp - 1, _tmp); })
 
+/**
+ * DIV64_U64_ROUND_CLOSEST - unsigned 64bit divide with 64bit divisor rounded to nearest integer
+ * @dividend: unsigned 64bit dividend
+ * @divisor: unsigned 64bit divisor
+ *
+ * Divide unsigned 64bit dividend by unsigned 64bit divisor
+ * and round to closest integer.
+ *
+ * Return: dividend / divisor rounded to nearest integer
+ */
+#define DIV64_U64_ROUND_CLOSEST(dividend, divisor)     \
+       ({ u64 _tmp = (divisor); div64_u64((dividend) + _tmp / 2, _tmp); })
+
 #endif /* _LINUX_MATH64_H */