Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 13 Apr 2018 22:51:06 +0000 (15:51 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 13 Apr 2018 22:51:06 +0000 (15:51 -0700)
Pull clk updates from Stephen Boyd:
 "The large diff this time around is from the addition of a new clk
  driver for the TI Davinci family of SoCs. So far those clks have been
  supported with a custom implementation of the clk API in the arch port
  instead of in the CCF. With this driver merged we're one step closer
  to having a single clk API implementation.

  The other large diff is from the Amlogic clk driver that underwent
  some major surgery to use regmap. Beyond that, the biggest hitter is
  Samsung which needed some reworks to properly handle clk provider
  power domains and a bunch of PLL rate updates.

  The core framework was fairly quiet this round, just getting some
  cleanups and small fixes for some of the more esoteric features. And
  the usual set of driver non-critical fixes, cleanups, and minor
  additions are here as well.

  Core:
   - Rejig clk_ops::init() to be a little earlier for phase/accuracy ops
   - debugfs ops macroized to shave some lines of boilerplate code
   - Always calculate the phase instead of caching it in clk_get_phase()
   - More __must_check on bulk clk APIs

  New Drivers:
   - TI's Davinci family of SoCs
   - Intel's Stratix10 SoC
   - stm32mp157 SoC
   - Allwinner H6 CCU
   - Silicon Labs SI544 clock generator chip
   - Renesas R-Car M3-N and V3H SoCs
   - i.MX6SLL SoCs

  Removed Drivers:
   - ST-Ericsson AB8540/9540

  Updates:
   - Mediatek MT2701 and MT7622 audsys support and MT2712 updates
   - STM32F469 DSI and STM32F769 sdmmc2 support
   - GPIO clks can sleep now
   - Spreadtrum SC9860 RTC clks
   - Nvidia Tegra MBIST workarounds and various minor fixes
   - Rockchip phase handling fixes and a memory leak plugged
   - Renesas drivers switch to readl/writel from clk_readl/clk_writel
   - Renesas gained CPU (Z/Z2) and watchdog support
   - Rockchip rk3328 display clks and rk3399 1.6GHz PLL support
   - Qualcomm PM8921 PMIC XO buffers
   - Amlogic migrates to regmap APIs
   - TI Keystone clk latching support
   - Allwinner H3 and H5 video clk fixes
   - Broadcom BCM2835 PLLs needed another bit to enable
   - i.MX6SX CKO mux fix and i.MX7D Video PLL divider fix
   - i.MX6UL/ULL epdc_podf support
   - Hi3798CV200 COMBPHY0 and USB2_OTG_UTMI and phase support for eMMC"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (233 commits)
  clk: davinci: add a reset lookup table for psc0
  clk: imx: add clock driver for imx6sll
  dt-bindings: imx: update clock doc for imx6sll
  clk: imx: add new gate/gate2 wrapper funtion
  clk: imx: Add CLK_IS_CRITICAL flag for busy divider and busy mux
  clk: cs2000: set pm_ops in hibernate-compatible way
  clk: bcm2835: De-assert/assert PLL reset signal when appropriate
  clk: imx7d: Move clks_init_on before any clock operations
  clk: imx7d: Correct ahb clk parent select
  clk: imx7d: Correct dram pll type
  clk: imx7d: Add USB clock information
  clk: socfpga: stratix10: add clock driver for Stratix10 platform
  dt-bindings: documentation: add clock bindings information for Stratix10
  clk: ti: fix flag space conflict with clkctrl clocks
  clk: uniphier: add additional ethernet clock lines for Pro4
  clk: uniphier: add SATA clock control support
  clk: uniphier: add PCIe clock control support
  clk: Add driver for the si544 clock generator chip
  clk: davinci: Remove redundant dev_err calls
  clk: uniphier: add ethernet clock control support for PXs3
  ...

198 files changed:
Documentation/clk.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt
Documentation/devicetree/bindings/clock/imx6sll-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/intc_stratix10.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
Documentation/devicetree/bindings/clock/rockchip,rk3328-cru.txt
Documentation/devicetree/bindings/clock/silabs,si544.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/sunxi-ccu.txt
Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ti/davinci/pll.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ti/davinci/psc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ti/divider.txt
Documentation/devicetree/bindings/clock/ti/mux.txt
MAINTAINERS
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/bcm/clk-bcm2835.c
drivers/clk/clk-cs2000-cp.c
drivers/clk/clk-divider.c
drivers/clk/clk-gpio.c
drivers/clk/clk-mux.c
drivers/clk/clk-si544.c [new file with mode: 0644]
drivers/clk/clk-stm32f4.c
drivers/clk/clk-stm32mp1.c [new file with mode: 0644]
drivers/clk/clk.c
drivers/clk/davinci/Makefile [new file with mode: 0644]
drivers/clk/davinci/da8xx-cfgchip.c [new file with mode: 0644]
drivers/clk/davinci/pll-da830.c [new file with mode: 0644]
drivers/clk/davinci/pll-da850.c [new file with mode: 0644]
drivers/clk/davinci/pll-dm355.c [new file with mode: 0644]
drivers/clk/davinci/pll-dm365.c [new file with mode: 0644]
drivers/clk/davinci/pll-dm644x.c [new file with mode: 0644]
drivers/clk/davinci/pll-dm646x.c [new file with mode: 0644]
drivers/clk/davinci/pll.c [new file with mode: 0644]
drivers/clk/davinci/pll.h [new file with mode: 0644]
drivers/clk/davinci/psc-da830.c [new file with mode: 0644]
drivers/clk/davinci/psc-da850.c [new file with mode: 0644]
drivers/clk/davinci/psc-dm355.c [new file with mode: 0644]
drivers/clk/davinci/psc-dm365.c [new file with mode: 0644]
drivers/clk/davinci/psc-dm644x.c [new file with mode: 0644]
drivers/clk/davinci/psc-dm646x.c [new file with mode: 0644]
drivers/clk/davinci/psc.c [new file with mode: 0644]
drivers/clk/davinci/psc.h [new file with mode: 0644]
drivers/clk/hisilicon/Makefile
drivers/clk/hisilicon/clk-hisi-phase.c [new file with mode: 0644]
drivers/clk/hisilicon/clk.c
drivers/clk/hisilicon/clk.h
drivers/clk/hisilicon/crg-hi3516cv300.c
drivers/clk/hisilicon/crg-hi3798cv200.c
drivers/clk/imx/Makefile
drivers/clk/imx/clk-busy.c
drivers/clk/imx/clk-imx6sll.c [new file with mode: 0644]
drivers/clk/imx/clk-imx6sx.c
drivers/clk/imx/clk-imx6ul.c
drivers/clk/imx/clk-imx7d.c
drivers/clk/imx/clk-pllv2.c
drivers/clk/imx/clk.h
drivers/clk/keystone/sci-clk.c
drivers/clk/mediatek/Kconfig
drivers/clk/mediatek/Makefile
drivers/clk/mediatek/clk-mt2701-aud.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt2701.c
drivers/clk/mediatek/clk-mt2712.c
drivers/clk/mediatek/clk-mt7622-aud.c
drivers/clk/meson/Kconfig
drivers/clk/meson/Makefile
drivers/clk/meson/axg.c
drivers/clk/meson/axg.h
drivers/clk/meson/clk-audio-divider.c
drivers/clk/meson/clk-cpu.c [deleted file]
drivers/clk/meson/clk-mpll.c
drivers/clk/meson/clk-pll.c
drivers/clk/meson/clk-regmap.c [new file with mode: 0644]
drivers/clk/meson/clk-regmap.h [new file with mode: 0644]
drivers/clk/meson/clkc.h
drivers/clk/meson/gxbb-aoclk-regmap.c [deleted file]
drivers/clk/meson/gxbb-aoclk.c
drivers/clk/meson/gxbb-aoclk.h
drivers/clk/meson/gxbb.c
drivers/clk/meson/gxbb.h
drivers/clk/meson/meson8b.c
drivers/clk/meson/meson8b.h
drivers/clk/mvebu/armada-38x.c
drivers/clk/mvebu/cp110-system-controller.c
drivers/clk/nxp/clk-lpc32xx.c
drivers/clk/qcom/clk-regmap-divider.c
drivers/clk/qcom/clk-rpm.c
drivers/clk/qcom/clk-smd-rpm.c
drivers/clk/qcom/gcc-msm8996.c
drivers/clk/renesas/Kconfig
drivers/clk/renesas/Makefile
drivers/clk/renesas/clk-div6.c
drivers/clk/renesas/clk-mstp.c
drivers/clk/renesas/clk-r8a73a4.c
drivers/clk/renesas/clk-r8a7740.c
drivers/clk/renesas/clk-rcar-gen2.c
drivers/clk/renesas/clk-rz.c
drivers/clk/renesas/clk-sh73a0.c
drivers/clk/renesas/r8a7743-cpg-mssr.c
drivers/clk/renesas/r8a7745-cpg-mssr.c
drivers/clk/renesas/r8a7790-cpg-mssr.c
drivers/clk/renesas/r8a7791-cpg-mssr.c
drivers/clk/renesas/r8a7792-cpg-mssr.c
drivers/clk/renesas/r8a7794-cpg-mssr.c
drivers/clk/renesas/r8a7795-cpg-mssr.c
drivers/clk/renesas/r8a7796-cpg-mssr.c
drivers/clk/renesas/r8a77965-cpg-mssr.c [new file with mode: 0644]
drivers/clk/renesas/r8a77980-cpg-mssr.c [new file with mode: 0644]
drivers/clk/renesas/rcar-gen3-cpg.c
drivers/clk/renesas/rcar-gen3-cpg.h
drivers/clk/renesas/renesas-cpg-mssr.c
drivers/clk/renesas/renesas-cpg-mssr.h
drivers/clk/rockchip/clk-mmc-phase.c
drivers/clk/rockchip/clk-rk3228.c
drivers/clk/rockchip/clk-rk3328.c
drivers/clk/rockchip/clk-rk3399.c
drivers/clk/rockchip/clk.c
drivers/clk/samsung/Makefile
drivers/clk/samsung/clk-exynos-audss.c
drivers/clk/samsung/clk-exynos3250.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos5-subcmu.c [new file with mode: 0644]
drivers/clk/samsung/clk-exynos5-subcmu.h [new file with mode: 0644]
drivers/clk/samsung/clk-exynos5250.c
drivers/clk/samsung/clk-exynos5260.c
drivers/clk/samsung/clk-exynos5410.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/samsung/clk-exynos5433.c
drivers/clk/samsung/clk-exynos7.c
drivers/clk/samsung/clk-pll.h
drivers/clk/samsung/clk-s3c2410.c
drivers/clk/samsung/clk-s3c2412.c
drivers/clk/samsung/clk-s3c2443.c
drivers/clk/samsung/clk-s3c64xx.c
drivers/clk/socfpga/Makefile
drivers/clk/socfpga/clk-gate-s10.c [new file with mode: 0644]
drivers/clk/socfpga/clk-periph-s10.c [new file with mode: 0644]
drivers/clk/socfpga/clk-pll-s10.c [new file with mode: 0644]
drivers/clk/socfpga/clk-s10.c [new file with mode: 0644]
drivers/clk/socfpga/clk.h
drivers/clk/socfpga/stratix10-clk.h [new file with mode: 0644]
drivers/clk/sprd/sc9860-clk.c
drivers/clk/sunxi-ng/Kconfig
drivers/clk/sunxi-ng/Makefile
drivers/clk/sunxi-ng/ccu-sun50i-h6.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu-sun50i-h6.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu-sun8i-h3.c
drivers/clk/sunxi-ng/ccu-sun8i-h3.h
drivers/clk/sunxi-ng/ccu_nkmp.c
drivers/clk/sunxi-ng/ccu_nkmp.h
drivers/clk/sunxi-ng/ccu_nm.c
drivers/clk/sunxi-ng/ccu_nm.h
drivers/clk/tegra/clk-emc.c
drivers/clk/tegra/clk-pll.c
drivers/clk/tegra/clk-tegra-periph.c
drivers/clk/tegra/clk-tegra-super-gen4.c
drivers/clk/tegra/clk-tegra114.c
drivers/clk/tegra/clk-tegra124.c
drivers/clk/tegra/clk-tegra20.c
drivers/clk/tegra/clk-tegra210.c
drivers/clk/tegra/clk-tegra30.c
drivers/clk/tegra/clk.h
drivers/clk/ti/clk.c
drivers/clk/ti/clock.h
drivers/clk/ti/divider.c
drivers/clk/ti/mux.c
drivers/clk/uniphier/clk-uniphier-sys.c
drivers/clk/ux500/Makefile
drivers/clk/ux500/abx500-clk.c
drivers/clk/ux500/u8540_clk.c [deleted file]
drivers/clk/ux500/u9540_clk.c [deleted file]
drivers/clk/versatile/clk-vexpress-osc.c
drivers/soc/samsung/pm_domains.c
include/dt-bindings/clock/axg-clkc.h
include/dt-bindings/clock/histb-clock.h
include/dt-bindings/clock/imx6sll-clock.h [new file with mode: 0644]
include/dt-bindings/clock/mt2701-clk.h
include/dt-bindings/clock/mt2712-clk.h
include/dt-bindings/clock/mt7622-clk.h
include/dt-bindings/clock/qcom,rpmcc.h
include/dt-bindings/clock/r8a77965-cpg-mssr.h [new file with mode: 0644]
include/dt-bindings/clock/r8a77980-cpg-mssr.h [new file with mode: 0644]
include/dt-bindings/clock/rk3328-cru.h
include/dt-bindings/clock/sprd,sc9860-clk.h
include/dt-bindings/clock/stm32fx-clock.h
include/dt-bindings/clock/stm32mp1-clks.h [new file with mode: 0644]
include/dt-bindings/clock/stratix10-clock.h [new file with mode: 0644]
include/dt-bindings/clock/sun50i-h6-ccu.h [new file with mode: 0644]
include/dt-bindings/clock/sun8i-h3-ccu.h
include/dt-bindings/clock/tegra210-car.h
include/dt-bindings/reset/sun50i-h6-ccu.h [new file with mode: 0644]
include/linux/clk-provider.h
include/linux/clk.h
include/linux/clk/tegra.h
include/linux/clk/ti.h
include/linux/platform_data/clk-da8xx-cfgchip.h [new file with mode: 0644]
include/linux/platform_data/clk-davinci-pll.h [new file with mode: 0644]

index be909ed45970b24305c58e1ac2dca92c11ffbd73..511628bb3d3a25fcc6ffb3a8d07d2696622d47ab 100644 (file)
@@ -268,9 +268,19 @@ The common clock framework uses two global locks, the prepare lock and the
 enable lock.
 
 The enable lock is a spinlock and is held across calls to the .enable,
-.disable and .is_enabled operations. Those operations are thus not allowed to
-sleep, and calls to the clk_enable(), clk_disable() and clk_is_enabled() API
-functions are allowed in atomic context.
+.disable operations. Those operations are thus not allowed to sleep,
+and calls to the clk_enable(), clk_disable() API functions are allowed in
+atomic context.
+
+For clk_is_enabled() API, it is also designed to be allowed to be used in
+atomic context. However, it doesn't really make any sense to hold the enable
+lock in core, unless you want to do something else with the information of
+the enable state with that lock held. Otherwise, seeing if a clk is enabled is
+a one-shot read of the enabled state, which could just as easily change after
+the function returns because the lock is released. Thus the user of this API
+needs to handle synchronizing the read of the state with whatever they're
+using it for to make sure that the enable state doesn't change during that
+time.
 
 The prepare lock is a mutex and is held across calls to all other operations.
 All those operations are allowed to sleep, and calls to the corresponding API
index 9b8f578d5e197847c949c5d1afd86fde54d871a2..34a69ba67f13f0f90fabb67de3d1ab3de1c4b6be 100644 (file)
@@ -6,6 +6,7 @@ The MediaTek AUDSYS controller provides various clocks to the system.
 Required Properties:
 
 - compatible: Should be one of:
+       - "mediatek,mt2701-audsys", "syscon"
        - "mediatek,mt7622-audsys", "syscon"
 - #clock-cells: Must be 1
 
@@ -13,10 +14,19 @@ The AUDSYS 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.
 
+Required sub-nodes:
+-------
+For common binding part and usage, refer to
+../sonud/mt2701-afe-pcm.txt.
+
 Example:
 
-audsys: audsys@11220000 {
-       compatible = "mediatek,mt7622-audsys", "syscon";
-       reg = <0 0x11220000 0 0x1000>;
-       #clock-cells = <1>;
-};
+       audsys: clock-controller@11220000 {
+               compatible = "mediatek,mt7622-audsys", "syscon";
+               reg = <0 0x11220000 0 0x2000>;
+               #clock-cells = <1>;
+
+               afe: audio-controller {
+                       ...
+               };
+       };
diff --git a/Documentation/devicetree/bindings/clock/imx6sll-clock.txt b/Documentation/devicetree/bindings/clock/imx6sll-clock.txt
new file mode 100644 (file)
index 0000000..fee849d
--- /dev/null
@@ -0,0 +1,36 @@
+* Clock bindings for Freescale i.MX6 SLL
+
+Required properties:
+- compatible: Should be "fsl,imx6sll-ccm"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- clocks: list of clock specifiers, must contain an entry for each required
+  entry in clock-names
+- clock-names: should include entries "ckil", "osc", "ipp_di0" and "ipp_di1"
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  See include/dt-bindings/clock/imx6sll-clock.h
+for the full list of i.MX6 SLL clock IDs.
+
+Examples:
+
+#include <dt-bindings/clock/imx6sll-clock.h>
+
+clks: clock-controller@20c4000 {
+               compatible = "fsl,imx6sll-ccm";
+               reg = <0x020c4000 0x4000>;
+               interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+               #clock-cells = <1>;
+               clocks = <&ckil>, <&osc>, <&ipp_di0>, <&ipp_di1>;
+               clock-names = "ckil", "osc", "ipp_di0", "ipp_di1";
+};
+
+uart1: serial@2020000 {
+               compatible = "fsl,imx6sl-uart", "fsl,imx6q-uart", "fsl,imx21-uart";
+               reg = <0x02020000 0x4000>;
+               interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&clks IMX6SLL_CLK_UART1_IPG>,
+                        <&clks IMX6SLL_CLK_UART1_SERIAL>;
+               clock-names = "ipg", "per";
+};
diff --git a/Documentation/devicetree/bindings/clock/intc_stratix10.txt b/Documentation/devicetree/bindings/clock/intc_stratix10.txt
new file mode 100644 (file)
index 0000000..9f4ec5c
--- /dev/null
@@ -0,0 +1,20 @@
+Device Tree Clock bindings for Intel's SoCFPGA Stratix10 platform
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be
+       "intel,stratix10-clkmgr"
+
+- reg : shall be the control register offset from CLOCK_MANAGER's base for the clock.
+
+- #clock-cells : from common clock binding, shall be set to 1.
+
+Example:
+       clkmgr: clock-controller@ffd10000 {
+               compatible = "intel,stratix10-clkmgr";
+               reg = <0xffd10000 0x1000>;
+               #clock-cells = <1>;
+       };
index f1890d0777a6cc25462d308311b5722a19c21c4d..773a5226342fc1d2945ea79bd32abb1d0f8e7c8d 100644 (file)
@@ -22,7 +22,9 @@ Required Properties:
       - "renesas,r8a7794-cpg-mssr" for the r8a7794 SoC (R-Car E2)
       - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3)
       - "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W)
+      - "renesas,r8a77965-cpg-mssr" for the r8a77965 SoC (R-Car M3-N)
       - "renesas,r8a77970-cpg-mssr" for the r8a77970 SoC (R-Car V3M)
+      - "renesas,r8a77980-cpg-mssr" for the r8a77980 SoC (R-Car V3H)
       - "renesas,r8a77995-cpg-mssr" for the r8a77995 SoC (R-Car D3)
 
   - reg: Base address and length of the memory resource used by the CPG/MSSR
@@ -32,8 +34,8 @@ Required Properties:
     clock-names
   - clock-names: List of external parent clock names. Valid names are:
       - "extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794,
-                r8a7795, r8a7796, r8a77970, r8a77995)
-      - "extalr" (r8a7795, r8a7796, r8a77970)
+                r8a7795, r8a7796, r8a77965, r8a77970, r8a77980, r8a77995)
+      - "extalr" (r8a7795, r8a7796, r8a77965, r8a77970, r8a77980)
       - "usb_extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7793, r8a7794)
 
   - #clock-cells: Must be 2
index e71c675ba5dad112c50a25ca99df9d87c8ff35d8..904ae682ea90216ad9c6f07d2f4d7666635693eb 100644 (file)
@@ -32,6 +32,7 @@ clock-output-names:
  - "clkin_i2s" - external I2S clock - optional,
  - "gmac_clkin" - external GMAC clock - optional
  - "phy_50m_out" - output clock of the pll in the mac phy
+ - "hdmi_phy" - output clock of the hdmi phy pll - optional
 
 Example: Clock controller node:
 
diff --git a/Documentation/devicetree/bindings/clock/silabs,si544.txt b/Documentation/devicetree/bindings/clock/silabs,si544.txt
new file mode 100644 (file)
index 0000000..b86535b
--- /dev/null
@@ -0,0 +1,25 @@
+Binding for Silicon Labs 544 programmable I2C clock generator.
+
+Reference
+This binding uses the common clock binding[1]. Details about the device can be
+found in the datasheet[2].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Si544 datasheet
+    https://www.silabs.com/documents/public/data-sheets/si544-datasheet.pdf
+
+Required properties:
+ - compatible: One of "silabs,si514a", "silabs,si514b" "silabs,si514c" according
+               to the speed grade of the chip.
+ - reg: I2C device address.
+ - #clock-cells: From common clock bindings: Shall be 0.
+
+Optional properties:
+ - clock-output-names: From common clock bindings. Recommended to be "si544".
+
+Example:
+       si544: clock-controller@55 {
+               reg = <0x55>;
+               #clock-cells = <0>;
+               compatible = "silabs,si544b";
+       };
diff --git a/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt
new file mode 100644 (file)
index 0000000..fb9495e
--- /dev/null
@@ -0,0 +1,60 @@
+STMicroelectronics STM32 Peripheral Reset Clock Controller
+==========================================================
+
+The RCC IP is both a reset and a clock controller.
+
+RCC makes also power management (resume/supend and wakeup interrupt).
+
+Please also refer to reset.txt for common reset controller binding usage.
+
+Please also refer to clock-bindings.txt for common clock controller
+binding usage.
+
+
+Required properties:
+- compatible: "st,stm32mp1-rcc", "syscon"
+- reg: should be register base and length as documented in the datasheet
+- #clock-cells: 1, device nodes should specify the clock in their
+  "clocks" property, containing a phandle to the clock device node,
+  an index specifying the clock to use.
+- #reset-cells: Shall be 1
+- interrupts: Should contain a general interrupt line and a interrupt line
+  to the wake-up of processor (CSTOP).
+
+Example:
+       rcc: rcc@50000000 {
+               compatible = "st,stm32mp1-rcc", "syscon";
+               reg = <0x50000000 0x1000>;
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+               interrupts = <GIC_SPI 5 IRQ_TYPE_NONE>,
+                            <GIC_SPI 145 IRQ_TYPE_NONE>;
+       };
+
+Specifying clocks
+=================
+
+All available clocks are defined as preprocessor macros in
+dt-bindings/clock/stm32mp1-clks.h header and can be used in device
+tree sources.
+
+Specifying softreset control of devices
+=======================================
+
+Device nodes should specify the reset channel required in their "resets"
+property, containing a phandle to the reset device node and an index specifying
+which channel to use.
+The index is the bit number within the RCC registers bank, starting from RCC
+base address.
+It is calculated as: index = register_offset / 4 * 32 + bit_offset.
+Where bit_offset is the bit offset within the register.
+
+For example on STM32MP1, for LTDC reset:
+ ltdc = APB4_RSTSETR_offset / 4 * 32 + LTDC_bit_offset
+      = 0x180 / 4 * 32 + 0 = 3072
+
+The list of valid indices for STM32MP1 is available in:
+include/dt-bindings/reset-controller/stm32mp1-resets.h
+
+This file implements defines like:
+#define LTDC_R 3072
index 4ca21c3a6fc926d602460421264023670ffe1e52..460ef27b1008453dd879cbcdabc83cc9189d846f 100644 (file)
@@ -20,6 +20,7 @@ Required properties :
                - "allwinner,sun50i-a64-ccu"
                - "allwinner,sun50i-a64-r-ccu"
                - "allwinner,sun50i-h5-ccu"
+               - "allwinner,sun50i-h6-ccu"
                - "nextthing,gr8-ccu"
 
 - reg: Must contain the registers base address and length
@@ -31,6 +32,9 @@ Required properties :
 - #clock-cells : must contain 1
 - #reset-cells : must contain 1
 
+For the main CCU on H6, one more clock is needed:
+- "iosc": the SoC's internal frequency oscillator
+
 For the PRCM CCUs on A83T/H3/A64, two more clocks are needed:
 - "pll-periph": the SoC's peripheral PLL from the main CCU
 - "iosc": the SoC's internal frequency oscillator
diff --git a/Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip.txt b/Documentation/devicetree/bindings/clock/ti/davinci/da8xx-cfgchip.txt
new file mode 100644 (file)
index 0000000..1e03dce
--- /dev/null
@@ -0,0 +1,93 @@
+Binding for TI DA8XX/OMAP-L13X/AM17XX/AM18XX CFGCHIP clocks
+
+TI DA8XX/OMAP-L13X/AM17XX/AM18XX SoCs contain a general purpose set of
+registers call CFGCHIPn. Some of these registers function as clock
+gates. This document describes the bindings for those clocks.
+
+All of the clock nodes described below must be child nodes of a CFGCHIP node
+(compatible = "ti,da830-cfgchip").
+
+USB PHY clocks
+--------------
+Required properties:
+- compatible: shall be "ti,da830-usb-phy-clocks".
+- #clock-cells: from common clock binding; shall be set to 1.
+- clocks: phandles to the parent clocks corresponding to clock-names
+- clock-names: shall be "fck", "usb_refclkin", "auxclk"
+
+This node provides two clocks. The clock at index 0 is the USB 2.0 PHY 48MHz
+clock and the clock at index 1 is the USB 1.1 PHY 48MHz clock.
+
+eHRPWM Time Base Clock (TBCLK)
+------------------------------
+Required properties:
+- compatible: shall be "ti,da830-tbclksync".
+- #clock-cells: from common clock binding; shall be set to 0.
+- clocks: phandle to the parent clock
+- clock-names: shall be "fck"
+
+PLL DIV4.5 divider
+------------------
+Required properties:
+- compatible: shall be "ti,da830-div4p5ena".
+- #clock-cells: from common clock binding; shall be set to 0.
+- clocks: phandle to the parent clock
+- clock-names: shall be "pll0_pllout"
+
+EMIFA clock source (ASYNC1)
+---------------------------
+Required properties:
+- compatible: shall be "ti,da850-async1-clksrc".
+- #clock-cells: from common clock binding; shall be set to 0.
+- clocks: phandles to the parent clocks corresponding to clock-names
+- clock-names: shall be "pll0_sysclk3", "div4.5"
+
+ASYNC3 clock source
+-------------------
+Required properties:
+- compatible: shall be "ti,da850-async3-clksrc".
+- #clock-cells: from common clock binding; shall be set to 0.
+- clocks: phandles to the parent clocks corresponding to clock-names
+- clock-names: shall be "pll0_sysclk2", "pll1_sysclk2"
+
+Examples:
+
+       cfgchip: syscon@1417c {
+               compatible = "ti,da830-cfgchip", "syscon", "simple-mfd";
+               reg = <0x1417c 0x14>;
+
+               usb_phy_clk: usb-phy-clocks {
+                       compatible = "ti,da830-usb-phy-clocks";
+                       #clock-cells = <1>;
+                       clocks = <&psc1 1>, <&usb_refclkin>, <&pll0_auxclk>;
+                       clock-names = "fck", "usb_refclkin", "auxclk";
+               };
+               ehrpwm_tbclk: ehrpwm_tbclk {
+                       compatible = "ti,da830-tbclksync";
+                       #clock-cells = <0>;
+                       clocks = <&psc1 17>;
+                       clock-names = "fck";
+               };
+               div4p5_clk: div4.5 {
+                       compatible = "ti,da830-div4p5ena";
+                       #clock-cells = <0>;
+                       clocks = <&pll0_pllout>;
+                       clock-names = "pll0_pllout";
+               };
+               async1_clk: async1 {
+                       compatible = "ti,da850-async1-clksrc";
+                       #clock-cells = <0>;
+                       clocks = <&pll0_sysclk 3>, <&div4p5_clk>;
+                       clock-names = "pll0_sysclk3", "div4.5";
+               };
+               async3_clk: async3 {
+                       compatible = "ti,da850-async3-clksrc";
+                       #clock-cells = <0>;
+                       clocks = <&pll0_sysclk 2>, <&pll1_sysclk 2>;
+                       clock-names = "pll0_sysclk2", "pll1_sysclk2";
+               };
+       };
+
+Also see:
+- Documentation/devicetree/bindings/clock/clock-bindings.txt
+
diff --git a/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
new file mode 100644 (file)
index 0000000..36998e1
--- /dev/null
@@ -0,0 +1,96 @@
+Binding for TI DaVinci PLL Controllers
+
+The PLL provides clocks to most of the components on the SoC. In addition
+to the PLL itself, this controller also contains bypasses, gates, dividers,
+an multiplexers for various clock signals.
+
+Required properties:
+- compatible: shall be one of:
+       - "ti,da850-pll0" for PLL0 on DA850/OMAP-L138/AM18XX
+       - "ti,da850-pll1" for PLL1 on DA850/OMAP-L138/AM18XX
+- reg: physical base address and size of the controller's register area.
+- clocks: phandles corresponding to the clock names
+- clock-names: names of the clock sources - depends on compatible string
+       - for "ti,da850-pll0", shall be "clksrc", "extclksrc"
+       - for "ti,da850-pll1", shall be "clksrc"
+
+Optional properties:
+- ti,clkmode-square-wave: Indicates that the the board is supplying a square
+       wave input on the OSCIN pin instead of using a crystal oscillator.
+       This property is only valid when compatible = "ti,da850-pll0".
+
+
+Optional child nodes:
+
+pllout
+       Describes the main PLL clock output (before POSTDIV). The node name must
+       be "pllout".
+
+       Required properties:
+       - #clock-cells: shall be 0
+
+sysclk
+       Describes the PLLDIVn divider clocks that provide the SYSCLKn clock
+       domains. The node name must be "sysclk". Consumers of this node should
+       use "n" in "SYSCLKn" as the index parameter for the clock cell.
+
+       Required properties:
+       - #clock-cells: shall be 1
+
+auxclk
+       Describes the AUXCLK output of the PLL. The node name must be "auxclk".
+       This child node is only valid when compatible = "ti,da850-pll0".
+
+       Required properties:
+       - #clock-cells: shall be 0
+
+obsclk
+       Describes the OBSCLK output of the PLL. The node name must be "obsclk".
+
+       Required properties:
+       - #clock-cells: shall be 0
+
+
+Examples:
+
+       pll0: clock-controller@11000 {
+               compatible = "ti,da850-pll0";
+               reg = <0x11000 0x1000>;
+               clocks = <&ref_clk>, <&pll1_sysclk 3>;
+               clock-names = "clksrc", "extclksrc";
+               ti,clkmode-square-wave;
+
+               pll0_pllout: pllout {
+                       #clock-cells = <0>;
+               };
+
+               pll0_sysclk: sysclk {
+                       #clock-cells = <1>;
+               };
+
+               pll0_auxclk: auxclk {
+                       #clock-cells = <0>;
+               };
+
+               pll0_obsclk: obsclk {
+                       #clock-cells = <0>;
+               };
+       };
+
+       pll1: clock-controller@21a000 {
+               compatible = "ti,da850-pll1";
+               reg = <0x21a000 0x1000>;
+               clocks = <&ref_clk>;
+               clock-names = "clksrc";
+
+               pll0_sysclk: sysclk {
+                       #clock-cells = <1>;
+               };
+
+               pll0_obsclk: obsclk {
+                       #clock-cells = <0>;
+               };
+       };
+
+Also see:
+- Documentation/devicetree/bindings/clock/clock-bindings.txt
diff --git a/Documentation/devicetree/bindings/clock/ti/davinci/psc.txt b/Documentation/devicetree/bindings/clock/ti/davinci/psc.txt
new file mode 100644 (file)
index 0000000..dae4ad8
--- /dev/null
@@ -0,0 +1,71 @@
+Binding for TI DaVinci Power Sleep Controller (PSC)
+
+The PSC provides power management, clock gating and reset functionality. It is
+primarily used for clocking.
+
+Required properties:
+- compatible: shall be one of:
+       - "ti,da850-psc0" for PSC0 on DA850/OMAP-L138/AM18XX
+       - "ti,da850-psc1" for PSC1 on DA850/OMAP-L138/AM18XX
+- reg: physical base address and size of the controller's register area
+- #clock-cells: from common clock binding; shall be set to 1
+- #power-domain-cells: from generic power domain binding; shall be set to 1.
+- clocks: phandles to clocks corresponding to the clock-names property
+- clock-names: list of parent clock names - depends on compatible value
+       - for "ti,da850-psc0", shall be "pll0_sysclk1", "pll0_sysclk2",
+         "pll0_sysclk4", "pll0_sysclk6", "async1"
+       - for "ti,da850-psc1", shall be "pll0_sysclk2", "pll0_sysclk4", "async3"
+
+Optional properties:
+- #reset-cells: from reset binding; shall be set to 1 - only applicable when
+  at least one local domain provides a local reset.
+
+Consumers:
+
+       Clock, power domain and reset consumers shall use the local power domain
+       module ID (LPSC) as the index corresponding to the clock cell. Refer to
+       the device-specific datasheet to find these numbers. NB: Most local
+       domains only provide a clock/power domain and not a reset.
+
+Examples:
+
+       psc0: clock-controller@10000 {
+               compatible = "ti,da850-psc0";
+               reg = <0x10000 0x1000>;
+               #clock-cells = <1>;
+               #power-domain-cells = <1>;
+               #reset-cells = <1>;
+               clocks = <&pll0_sysclk 1>, <&pll0_sysclk 2>,
+                        <&pll0_sysclk 4>, <&pll0_sysclk 6>, <&async1_clk>;
+               clock_names = "pll0_sysclk1", "pll0_sysclk2",
+                             "pll0_sysclk4", "pll0_sysclk6", "async1";
+       };
+       psc1: clock-controller@227000 {
+               compatible = "ti,da850-psc1";
+               reg = <0x227000 0x1000>;
+               #clock-cells = <1>;
+               #power-domain-cells = <1>;
+               clocks = <&pll0_sysclk 2>, <&pll0_sysclk 4>, <&async3_clk>;
+               clock_names = "pll0_sysclk2", "pll0_sysclk4", "async3";
+       };
+
+       /* consumer */
+       dsp: dsp@11800000 {
+               compatible = "ti,da850-dsp";
+               reg = <0x11800000 0x40000>,
+                     <0x11e00000 0x8000>,
+                     <0x11f00000 0x8000>,
+                     <0x01c14044 0x4>,
+                     <0x01c14174 0x8>;
+               reg-names = "l2sram", "l1pram", "l1dram", "host1cfg", "chipsig";
+               interrupt-parent = <&intc>;
+               interrupts = <28>;
+               clocks = <&psc0 15>;
+               power-domains = <&psc0 15>;
+               resets = <&psc0 15>;
+       };
+
+Also see:
+- Documentation/devicetree/bindings/clock/clock-bindings.txt
+- Documentation/devicetree/bindings/power/power_domain.txt
+- Documentation/devicetree/bindings/reset/reset.txt
index 35a6f5c7e5c26fd7ccf0bff9c7ab2f2f55667082..9b13b32974f9926874d1a893fa00be961c5aef4d 100644 (file)
@@ -75,6 +75,9 @@ Optional properties:
 - ti,invert-autoidle-bit : autoidle is enabled by setting the bit to 0,
   see [2]
 - ti,set-rate-parent : clk_set_rate is propagated to parent
+- ti,latch-bit : latch the divider value to HW, only needed if the register
+  access requires this. As an example dra76x DPLL_GMAC H14 divider implements
+  such behavior.
 
 Examples:
 dpll_usb_m2_ck: dpll_usb_m2_ck@4a008190 {
index 2d0d170f80013d4e57390461c1392ac7e699d9a6..eec8994b9be876752795bc4a37dc526329b9e453 100644 (file)
@@ -48,6 +48,9 @@ Optional properties:
   zero
 - ti,set-rate-parent : clk_set_rate is propagated to parent clock,
   not supported by the composite-mux-clock subtype
+- ti,latch-bit : latch the mux value to HW, only needed if the register
+  access requires this. As an example, dra7x DPLL_GMAC H14 muxing
+  implements such behavior.
 
 Examples:
 
index 9b091ef6579b0f8592e35cac37a4b7889570a347..87b3da2c404e9980afb78fc1ad5b28360b3d7056 100644 (file)
@@ -12365,6 +12365,7 @@ M:      Tomasz Figa <tomasz.figa@gmail.com>
 M:     Chanwoo Choi <cw00.choi@samsung.com>
 S:     Supported
 L:     linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/snawrocki/clk.git
 F:     drivers/clk/samsung/
 F:     include/dt-bindings/clock/exynos*.h
 F:     Documentation/devicetree/bindings/clock/exynos*.txt
@@ -14001,6 +14002,13 @@ F:     arch/arm/mach-davinci/
 F:     drivers/i2c/busses/i2c-davinci.c
 F:     arch/arm/boot/dts/da850*
 
+TI DAVINCI SERIES CLOCK DRIVER
+M:     David Lechner <david@lechnology.com>
+R:     Sekhar Nori <nsekhar@ti.com>
+S:     Maintained
+F:     Documentation/devicetree/bindings/clock/ti/davinci/
+F:     drivers/clk/davinci/
+
 TI DAVINCI SERIES GPIO DRIVER
 M:     Keerthy <j-keerthy@ti.com>
 L:     linux-gpio@vger.kernel.org
index 7ae23b25b406cb891c61478b50ea12c6ae7c2431..41492e980ef4c0deb4fd6f62020d76137c912b42 100644 (file)
@@ -55,8 +55,10 @@ config COMMON_CLK_RK808
          by control register.
 
 config COMMON_CLK_HI655X
-       tristate "Clock driver for Hi655x"
-       depends on MFD_HI655X_PMIC || COMPILE_TEST
+       tristate "Clock driver for Hi655x" if EXPERT
+       depends on (MFD_HI655X_PMIC || COMPILE_TEST)
+       depends on REGMAP
+       default MFD_HI655X_PMIC
        ---help---
          This driver supports the hi655x PMIC clock. This
          multi-function device has one fixed-rate oscillator, clocked
@@ -101,6 +103,15 @@ config COMMON_CLK_SI514
          This driver supports the Silicon Labs 514 programmable clock
          generator.
 
+config COMMON_CLK_SI544
+       tristate "Clock driver for SiLabs 544 devices"
+       depends on I2C
+       select REGMAP_I2C
+       help
+       ---help---
+         This driver supports the Silicon Labs 544 programmable clock
+         generator.
+
 config COMMON_CLK_SI570
        tristate "Clock driver for SiLabs 570 and compatible devices"
        depends on I2C
@@ -248,6 +259,26 @@ config COMMON_CLK_VC5
          This driver supports the IDT VersaClock 5 and VersaClock 6
          programmable clock generators.
 
+config COMMON_CLK_STM32MP157
+       def_bool COMMON_CLK && MACH_STM32MP157
+       help
+       ---help---
+         Support for stm32mp157 SoC family clocks
+
+config COMMON_CLK_STM32F
+       bool "Clock driver for stm32f4 and stm32f7 SoC families"
+       depends on MACH_STM32F429 || MACH_STM32F469 || MACH_STM32F746
+       help
+       ---help---
+         Support for stm32f4 and stm32f7 SoC families clocks
+
+config COMMON_CLK_STM32H7
+       bool "Clock driver for stm32h7 SoC family"
+       depends on MACH_STM32H743
+       help
+       ---help---
+         Support for stm32h7 SoC family clocks
+
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
 source "drivers/clk/imgtec/Kconfig"
index 6605513eaa946883df06f17a0ba95ec75db76409..de6d06ac790b63eb90b6d2b04077750fd985d64c 100644 (file)
@@ -45,9 +45,11 @@ obj-$(CONFIG_COMMON_CLK_SCMI)           += clk-scmi.o
 obj-$(CONFIG_COMMON_CLK_SCPI)           += clk-scpi.o
 obj-$(CONFIG_COMMON_CLK_SI5351)                += clk-si5351.o
 obj-$(CONFIG_COMMON_CLK_SI514)         += clk-si514.o
+obj-$(CONFIG_COMMON_CLK_SI544)         += clk-si544.o
 obj-$(CONFIG_COMMON_CLK_SI570)         += clk-si570.o
-obj-$(CONFIG_ARCH_STM32)               += clk-stm32f4.o
-obj-$(CONFIG_ARCH_STM32)               += clk-stm32h7.o
+obj-$(CONFIG_COMMON_CLK_STM32F)                += clk-stm32f4.o
+obj-$(CONFIG_COMMON_CLK_STM32H7)       += clk-stm32h7.o
+obj-$(CONFIG_COMMON_CLK_STM32MP157)    += clk-stm32mp1.o
 obj-$(CONFIG_ARCH_TANGO)               += clk-tango4.o
 obj-$(CONFIG_CLK_TWL6040)              += clk-twl6040.o
 obj-$(CONFIG_ARCH_U300)                        += clk-u300.o
@@ -62,6 +64,7 @@ obj-$(CONFIG_ARCH_ARTPEC)             += axis/
 obj-$(CONFIG_ARC_PLAT_AXS10X)          += axs10x/
 obj-y                                  += bcm/
 obj-$(CONFIG_ARCH_BERLIN)              += berlin/
+obj-$(CONFIG_ARCH_DAVINCI)             += davinci/
 obj-$(CONFIG_H8300)                    += h8300/
 obj-$(CONFIG_ARCH_HISI)                        += hisilicon/
 obj-y                                  += imgtec/
@@ -89,6 +92,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)            += socfpga/
 obj-$(CONFIG_PLAT_SPEAR)               += spear/
 obj-$(CONFIG_ARCH_SPRD)                        += sprd/
 obj-$(CONFIG_ARCH_STI)                 += st/
+obj-$(CONFIG_ARCH_STRATIX10)           += socfpga/
 obj-$(CONFIG_ARCH_SUNXI)               += sunxi/
 obj-$(CONFIG_ARCH_SUNXI)               += sunxi-ng/
 obj-$(CONFIG_ARCH_TEGRA)               += tegra/
index a07f6451694ae3ff25b65fa02ddd5f78e1caec05..fa0d5c8611a0dc0440464ae8d71a44d5b37a7712 100644 (file)
@@ -602,9 +602,7 @@ static void bcm2835_pll_off(struct clk_hw *hw)
        const struct bcm2835_pll_data *data = pll->data;
 
        spin_lock(&cprman->regs_lock);
-       cprman_write(cprman, data->cm_ctrl_reg,
-                    cprman_read(cprman, data->cm_ctrl_reg) |
-                    CM_PLL_ANARST);
+       cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST);
        cprman_write(cprman, data->a2w_ctrl_reg,
                     cprman_read(cprman, data->a2w_ctrl_reg) |
                     A2W_PLL_CTRL_PWRDN);
@@ -640,6 +638,10 @@ static int bcm2835_pll_on(struct clk_hw *hw)
                cpu_relax();
        }
 
+       cprman_write(cprman, data->a2w_ctrl_reg,
+                    cprman_read(cprman, data->a2w_ctrl_reg) |
+                    A2W_PLL_CTRL_PRST_DISABLE);
+
        return 0;
 }
 
index e8ea81c30f0ccd290ea9fa7b66750b889c23a8df..c58019750b7e186da9d503b486d2fd6510de749f 100644 (file)
@@ -549,7 +549,7 @@ static int cs2000_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops cs2000_pm_ops = {
-       .resume_early   = cs2000_resume,
+       SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, cs2000_resume)
 };
 
 static struct i2c_driver cs2000_driver = {
index b49942b9fe50f69cb4ed4f549e4d0f0dbd87f6ce..b6234a5da12d19e4b88b55796b71304526b59bde 100644 (file)
  * parent - fixed parent.  No clk_set_parent support
  */
 
-#define div_mask(width)        ((1 << (width)) - 1)
-
 static unsigned int _get_table_maxdiv(const struct clk_div_table *table,
                                      u8 width)
 {
-       unsigned int maxdiv = 0, mask = div_mask(width);
+       unsigned int maxdiv = 0, mask = clk_div_mask(width);
        const struct clk_div_table *clkt;
 
        for (clkt = table; clkt->div; clkt++)
@@ -57,12 +55,12 @@ static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width,
                                unsigned long flags)
 {
        if (flags & CLK_DIVIDER_ONE_BASED)
-               return div_mask(width);
+               return clk_div_mask(width);
        if (flags & CLK_DIVIDER_POWER_OF_TWO)
-               return 1 << div_mask(width);
+               return 1 << clk_div_mask(width);
        if (table)
                return _get_table_maxdiv(table, width);
-       return div_mask(width) + 1;
+       return clk_div_mask(width) + 1;
 }
 
 static unsigned int _get_table_div(const struct clk_div_table *table,
@@ -84,7 +82,7 @@ static unsigned int _get_div(const struct clk_div_table *table,
        if (flags & CLK_DIVIDER_POWER_OF_TWO)
                return 1 << val;
        if (flags & CLK_DIVIDER_MAX_AT_ZERO)
-               return val ? val : div_mask(width) + 1;
+               return val ? val : clk_div_mask(width) + 1;
        if (table)
                return _get_table_div(table, val);
        return val + 1;
@@ -109,7 +107,7 @@ static unsigned int _get_val(const struct clk_div_table *table,
        if (flags & CLK_DIVIDER_POWER_OF_TWO)
                return __ffs(div);
        if (flags & CLK_DIVIDER_MAX_AT_ZERO)
-               return (div == div_mask(width) + 1) ? 0 : div;
+               return (div == clk_div_mask(width) + 1) ? 0 : div;
        if (table)
                return  _get_table_val(table, div);
        return div - 1;
@@ -141,7 +139,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
        unsigned int val;
 
        val = clk_readl(divider->reg) >> divider->shift;
-       val &= div_mask(divider->width);
+       val &= clk_div_mask(divider->width);
 
        return divider_recalc_rate(hw, parent_rate, val, divider->table,
                                   divider->flags, divider->width);
@@ -344,19 +342,43 @@ long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
 }
 EXPORT_SYMBOL_GPL(divider_round_rate_parent);
 
+long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
+                                 unsigned long rate, unsigned long *prate,
+                                 const struct clk_div_table *table, u8 width,
+                                 unsigned long flags, unsigned int val)
+{
+       int div;
+
+       div = _get_div(table, val, flags, width);
+
+       /* Even a read-only clock can propagate a rate change */
+       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
+               if (!parent)
+                       return -EINVAL;
+
+               *prate = clk_hw_round_rate(parent, rate * div);
+       }
+
+       return DIV_ROUND_UP_ULL((u64)*prate, div);
+}
+EXPORT_SYMBOL_GPL(divider_ro_round_rate_parent);
+
+
 static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
                                unsigned long *prate)
 {
        struct clk_divider *divider = to_clk_divider(hw);
-       int bestdiv;
 
        /* if read only, just return current value */
        if (divider->flags & CLK_DIVIDER_READ_ONLY) {
-               bestdiv = clk_readl(divider->reg) >> divider->shift;
-               bestdiv &= div_mask(divider->width);
-               bestdiv = _get_div(divider->table, bestdiv, divider->flags,
-                       divider->width);
-               return DIV_ROUND_UP_ULL((u64)*prate, bestdiv);
+               u32 val;
+
+               val = clk_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,
@@ -376,7 +398,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate,
 
        value = _get_val(table, div, flags, width);
 
-       return min_t(unsigned int, value, div_mask(width));
+       return min_t(unsigned int, value, clk_div_mask(width));
 }
 EXPORT_SYMBOL_GPL(divider_get_val);
 
@@ -399,10 +421,10 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
                __acquire(divider->lock);
 
        if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
-               val = div_mask(divider->width) << (divider->shift + 16);
+               val = clk_div_mask(divider->width) << (divider->shift + 16);
        } else {
                val = clk_readl(divider->reg);
-               val &= ~(div_mask(divider->width) << divider->shift);
+               val &= ~(clk_div_mask(divider->width) << divider->shift);
        }
        val |= (u32)value << divider->shift;
        clk_writel(val, divider->reg);
index 151513c655c3c24becbded77921ff3b290630671..40af4fbab4d23f24acda1ab07fe1df887131c243 100644 (file)
@@ -73,14 +73,14 @@ static u8 clk_gpio_mux_get_parent(struct clk_hw *hw)
 {
        struct clk_gpio *clk = to_clk_gpio(hw);
 
-       return gpiod_get_value(clk->gpiod);
+       return gpiod_get_value_cansleep(clk->gpiod);
 }
 
 static int clk_gpio_mux_set_parent(struct clk_hw *hw, u8 index)
 {
        struct clk_gpio *clk = to_clk_gpio(hw);
 
-       gpiod_set_value(clk->gpiod, index);
+       gpiod_set_value_cansleep(clk->gpiod, index);
 
        return 0;
 }
index 39cabe157163b9b0dd3498c65a242fe1614253ee..ac4a042f8658258dbcbfdbc058e8b87c8412a51b 100644 (file)
  * parent - parent is adjustable through clk_set_parent
  */
 
-static u8 clk_mux_get_parent(struct clk_hw *hw)
+int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
+                        unsigned int val)
 {
-       struct clk_mux *mux = to_clk_mux(hw);
        int num_parents = clk_hw_get_num_parents(hw);
-       u32 val;
 
-       /*
-        * FIXME need a mux-specific flag to determine if val is bitwise or numeric
-        * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
-        * to 0x7 (index starts at one)
-        * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
-        * val = 0x4 really means "bit 2, index starts at bit 0"
-        */
-       val = clk_readl(mux->reg) >> mux->shift;
-       val &= mux->mask;
-
-       if (mux->table) {
+       if (table) {
                int i;
 
                for (i = 0; i < num_parents; i++)
-                       if (mux->table[i] == val)
+                       if (table[i] == val)
                                return i;
                return -EINVAL;
        }
 
-       if (val && (mux->flags & CLK_MUX_INDEX_BIT))
+       if (val && (flags & CLK_MUX_INDEX_BIT))
                val = ffs(val) - 1;
 
-       if (val && (mux->flags & CLK_MUX_INDEX_ONE))
+       if (val && (flags & CLK_MUX_INDEX_ONE))
                val--;
 
        if (val >= num_parents)
@@ -62,36 +51,58 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
 
        return val;
 }
+EXPORT_SYMBOL_GPL(clk_mux_val_to_index);
 
-static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
+unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index)
 {
-       struct clk_mux *mux = to_clk_mux(hw);
-       u32 val;
-       unsigned long flags = 0;
+       unsigned int val = index;
 
-       if (mux->table) {
-               index = mux->table[index];
+       if (table) {
+               val = table[index];
        } else {
-               if (mux->flags & CLK_MUX_INDEX_BIT)
-                       index = 1 << index;
+               if (flags & CLK_MUX_INDEX_BIT)
+                       val = 1 << index;
 
-               if (mux->flags & CLK_MUX_INDEX_ONE)
-                       index++;
+               if (flags & CLK_MUX_INDEX_ONE)
+                       val++;
        }
 
+       return val;
+}
+EXPORT_SYMBOL_GPL(clk_mux_index_to_val);
+
+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 &= mux->mask;
+
+       return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
+}
+
+static int clk_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;
+
        if (mux->lock)
                spin_lock_irqsave(mux->lock, flags);
        else
                __acquire(mux->lock);
 
        if (mux->flags & CLK_MUX_HIWORD_MASK) {
-               val = mux->mask << (mux->shift + 16);
+               reg = mux->mask << (mux->shift + 16);
        } else {
-               val = clk_readl(mux->reg);
-               val &= ~(mux->mask << mux->shift);
+               reg = clk_readl(mux->reg);
+               reg &= ~(mux->mask << mux->shift);
        }
-       val |= index << mux->shift;
-       clk_writel(val, mux->reg);
+       val = val << mux->shift;
+       reg |= val;
+       clk_writel(reg, mux->reg);
 
        if (mux->lock)
                spin_unlock_irqrestore(mux->lock, flags);
diff --git a/drivers/clk/clk-si544.c b/drivers/clk/clk-si544.c
new file mode 100644 (file)
index 0000000..1c96a9f
--- /dev/null
@@ -0,0 +1,411 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for Silicon Labs Si544 Programmable Oscillator
+ * Copyright (C) 2018 Topic Embedded Products
+ * Author: Mike Looijmans <mike.looijmans@topic.nl>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+/* I2C registers (decimal as in datasheet) */
+#define SI544_REG_CONTROL      7
+#define SI544_REG_OE_STATE     17
+#define SI544_REG_HS_DIV       23
+#define SI544_REG_LS_HS_DIV    24
+#define SI544_REG_FBDIV0       26
+#define SI544_REG_FBDIV8       27
+#define SI544_REG_FBDIV16      28
+#define SI544_REG_FBDIV24      29
+#define SI544_REG_FBDIV32      30
+#define SI544_REG_FBDIV40      31
+#define SI544_REG_FCAL_OVR     69
+#define SI544_REG_ADPLL_DELTA_M0       231
+#define SI544_REG_ADPLL_DELTA_M8       232
+#define SI544_REG_ADPLL_DELTA_M16      233
+#define SI544_REG_PAGE_SELECT  255
+
+/* Register values */
+#define SI544_CONTROL_RESET    BIT(7)
+#define SI544_CONTROL_MS_ICAL2 BIT(3)
+
+#define SI544_OE_STATE_ODC_OE  BIT(0)
+
+/* Max freq depends on speed grade */
+#define SI544_MIN_FREQ     200000U
+
+/* Si544 Internal oscilator runs at 55.05 MHz */
+#define FXO              55050000U
+
+/* VCO range is 10.8 .. 12.1 GHz, max depends on speed grade */
+#define FVCO_MIN       10800000000ULL
+
+#define HS_DIV_MAX     2046
+#define HS_DIV_MAX_ODD 33
+
+/* Lowest frequency synthesizeable using only the HS divider */
+#define MIN_HSDIV_FREQ (FVCO_MIN / HS_DIV_MAX)
+
+enum si544_speed_grade {
+       si544a,
+       si544b,
+       si544c,
+};
+
+struct clk_si544 {
+       struct clk_hw hw;
+       struct regmap *regmap;
+       struct i2c_client *i2c_client;
+       enum si544_speed_grade speed_grade;
+};
+#define to_clk_si544(_hw)      container_of(_hw, struct clk_si544, hw)
+
+/**
+ * struct clk_si544_muldiv - Multiplier/divider settings
+ * @fb_div_frac:       integer part of feedback divider (32 bits)
+ * @fb_div_int:                fractional part of feedback divider (11 bits)
+ * @hs_div:            1st divider, 5..2046, must be even when >33
+ * @ls_div_bits:       2nd divider, as 2^x, range 0..5
+ *                      If ls_div_bits is non-zero, hs_div must be even
+ */
+struct clk_si544_muldiv {
+       u32 fb_div_frac;
+       u16 fb_div_int;
+       u16 hs_div;
+       u8 ls_div_bits;
+};
+
+/* Enables or disables the output driver */
+static int si544_enable_output(struct clk_si544 *data, bool enable)
+{
+       return regmap_update_bits(data->regmap, SI544_REG_OE_STATE,
+               SI544_OE_STATE_ODC_OE, enable ? SI544_OE_STATE_ODC_OE : 0);
+}
+
+/* Retrieve clock multiplier and dividers from hardware */
+static int si544_get_muldiv(struct clk_si544 *data,
+       struct clk_si544_muldiv *settings)
+{
+       int err;
+       u8 reg[6];
+
+       err = regmap_bulk_read(data->regmap, SI544_REG_HS_DIV, reg, 2);
+       if (err)
+               return err;
+
+       settings->ls_div_bits = (reg[1] >> 4) & 0x07;
+       settings->hs_div = (reg[1] & 0x07) << 8 | reg[0];
+
+       err = regmap_bulk_read(data->regmap, SI544_REG_FBDIV0, reg, 6);
+       if (err)
+               return err;
+
+       settings->fb_div_int = reg[4] | (reg[5] & 0x07) << 8;
+       settings->fb_div_frac = reg[0] | reg[1] << 8 | reg[2] << 16 |
+                               reg[3] << 24;
+       return 0;
+}
+
+static int si544_set_muldiv(struct clk_si544 *data,
+       struct clk_si544_muldiv *settings)
+{
+       int err;
+       u8 reg[6];
+
+       reg[0] = settings->hs_div;
+       reg[1] = settings->hs_div >> 8 | settings->ls_div_bits << 4;
+
+       err = regmap_bulk_write(data->regmap, SI544_REG_HS_DIV, reg, 2);
+       if (err < 0)
+               return err;
+
+       reg[0] = settings->fb_div_frac;
+       reg[1] = settings->fb_div_frac >> 8;
+       reg[2] = settings->fb_div_frac >> 16;
+       reg[3] = settings->fb_div_frac >> 24;
+       reg[4] = settings->fb_div_int;
+       reg[5] = settings->fb_div_int >> 8;
+
+       /*
+        * Writing to SI544_REG_FBDIV40 triggers the clock change, so that
+        * must be written last
+        */
+       return regmap_bulk_write(data->regmap, SI544_REG_FBDIV0, reg, 6);
+}
+
+static bool is_valid_frequency(const struct clk_si544 *data,
+       unsigned long frequency)
+{
+       unsigned long max_freq = 0;
+
+       if (frequency < SI544_MIN_FREQ)
+               return false;
+
+       switch (data->speed_grade) {
+       case si544a:
+               max_freq = 1500000000;
+               break;
+       case si544b:
+               max_freq = 800000000;
+               break;
+       case si544c:
+               max_freq = 350000000;
+               break;
+       }
+
+       return frequency <= max_freq;
+}
+
+/* Calculate divider settings for a given frequency */
+static int si544_calc_muldiv(struct clk_si544_muldiv *settings,
+       unsigned long frequency)
+{
+       u64 vco;
+       u32 ls_freq;
+       u32 tmp;
+       u8 res;
+
+       /* Determine the minimum value of LS_DIV and resulting target freq. */
+       ls_freq = frequency;
+       settings->ls_div_bits = 0;
+
+       if (frequency >= MIN_HSDIV_FREQ) {
+               settings->ls_div_bits = 0;
+       } else {
+               res = 1;
+               tmp = 2 * HS_DIV_MAX;
+               while (tmp <= (HS_DIV_MAX * 32)) {
+                       if (((u64)frequency * tmp) >= FVCO_MIN)
+                               break;
+                       ++res;
+                       tmp <<= 1;
+               }
+               settings->ls_div_bits = res;
+               ls_freq = frequency << res;
+       }
+
+       /* Determine minimum HS_DIV by rounding up */
+       vco = FVCO_MIN + ls_freq - 1;
+       do_div(vco, ls_freq);
+       settings->hs_div = vco;
+
+       /* round up to even number when required */
+       if ((settings->hs_div & 1) &&
+           (settings->hs_div > HS_DIV_MAX_ODD || settings->ls_div_bits))
+               ++settings->hs_div;
+
+       /* Calculate VCO frequency (in 10..12GHz range) */
+       vco = (u64)ls_freq * settings->hs_div;
+
+       /* Calculate the integer part of the feedback divider */
+       tmp = do_div(vco, FXO);
+       settings->fb_div_int = vco;
+
+       /* And the fractional bits using the remainder */
+       vco = (u64)tmp << 32;
+       do_div(vco, FXO);
+       settings->fb_div_frac = vco;
+
+       return 0;
+}
+
+/* Calculate resulting frequency given the register settings */
+static unsigned long si544_calc_rate(struct clk_si544_muldiv *settings)
+{
+       u32 d = settings->hs_div * BIT(settings->ls_div_bits);
+       u64 vco;
+
+       /* Calculate VCO from the fractional part */
+       vco = (u64)settings->fb_div_frac * FXO;
+       vco += (FXO / 2);
+       vco >>= 32;
+
+       /* Add the integer part of the VCO frequency */
+       vco += (u64)settings->fb_div_int * FXO;
+
+       /* Apply divider to obtain the generated frequency */
+       do_div(vco, d);
+
+       return vco;
+}
+
+static unsigned long si544_recalc_rate(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       struct clk_si544 *data = to_clk_si544(hw);
+       struct clk_si544_muldiv settings;
+       int err;
+
+       err = si544_get_muldiv(data, &settings);
+       if (err)
+               return 0;
+
+       return si544_calc_rate(&settings);
+}
+
+static long si544_round_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long *parent_rate)
+{
+       struct clk_si544 *data = to_clk_si544(hw);
+       struct clk_si544_muldiv settings;
+       int err;
+
+       if (!is_valid_frequency(data, rate))
+               return -EINVAL;
+
+       err = si544_calc_muldiv(&settings, rate);
+       if (err)
+               return err;
+
+       return si544_calc_rate(&settings);
+}
+
+/*
+ * Update output frequency for "big" frequency changes
+ */
+static int si544_set_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long parent_rate)
+{
+       struct clk_si544 *data = to_clk_si544(hw);
+       struct clk_si544_muldiv settings;
+       int err;
+
+       if (!is_valid_frequency(data, rate))
+               return -EINVAL;
+
+       err = si544_calc_muldiv(&settings, rate);
+       if (err)
+               return err;
+
+       si544_enable_output(data, false);
+
+       /* Allow FCAL for this frequency update */
+       err = regmap_write(data->regmap, SI544_REG_FCAL_OVR, 0);
+       if (err < 0)
+               return err;
+
+
+       err = si544_set_muldiv(data, &settings);
+       if (err < 0)
+               return err; /* Undefined state now, best to leave disabled */
+
+       /* Trigger calibration */
+       err = regmap_write(data->regmap, SI544_REG_CONTROL,
+                          SI544_CONTROL_MS_ICAL2);
+       if (err < 0)
+               return err;
+
+       /* Applying a new frequency can take up to 10ms */
+       usleep_range(10000, 12000);
+
+       si544_enable_output(data, true);
+
+       return err;
+}
+
+static const struct clk_ops si544_clk_ops = {
+       .recalc_rate = si544_recalc_rate,
+       .round_rate = si544_round_rate,
+       .set_rate = si544_set_rate,
+};
+
+static bool si544_regmap_is_volatile(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case SI544_REG_CONTROL:
+       case SI544_REG_FCAL_OVR:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static const struct regmap_config si544_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .cache_type = REGCACHE_RBTREE,
+       .max_register = SI544_REG_PAGE_SELECT,
+       .volatile_reg = si544_regmap_is_volatile,
+};
+
+static int si544_probe(struct i2c_client *client,
+               const struct i2c_device_id *id)
+{
+       struct clk_si544 *data;
+       struct clk_init_data init;
+       int err;
+
+       data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       init.ops = &si544_clk_ops;
+       init.flags = 0;
+       init.num_parents = 0;
+       data->hw.init = &init;
+       data->i2c_client = client;
+       data->speed_grade = id->driver_data;
+
+       if (of_property_read_string(client->dev.of_node, "clock-output-names",
+                       &init.name))
+               init.name = client->dev.of_node->name;
+
+       data->regmap = devm_regmap_init_i2c(client, &si544_regmap_config);
+       if (IS_ERR(data->regmap))
+               return PTR_ERR(data->regmap);
+
+       i2c_set_clientdata(client, data);
+
+       /* Select page 0, just to be sure, there appear to be no more */
+       err = regmap_write(data->regmap, SI544_REG_PAGE_SELECT, 0);
+       if (err < 0)
+               return err;
+
+       err = devm_clk_hw_register(&client->dev, &data->hw);
+       if (err) {
+               dev_err(&client->dev, "clock registration failed\n");
+               return err;
+       }
+       err = devm_of_clk_add_hw_provider(&client->dev, of_clk_hw_simple_get,
+                                         &data->hw);
+       if (err) {
+               dev_err(&client->dev, "unable to add clk provider\n");
+               return err;
+       }
+
+       return 0;
+}
+
+static const struct i2c_device_id si544_id[] = {
+       { "si544a", si544a },
+       { "si544b", si544b },
+       { "si544c", si544c },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, si544_id);
+
+static const struct of_device_id clk_si544_of_match[] = {
+       { .compatible = "silabs,si544a" },
+       { .compatible = "silabs,si544b" },
+       { .compatible = "silabs,si544c" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, clk_si544_of_match);
+
+static struct i2c_driver si544_driver = {
+       .driver = {
+               .name = "si544",
+               .of_match_table = clk_si544_of_match,
+       },
+       .probe          = si544_probe,
+       .id_table       = si544_id,
+};
+module_i2c_driver(si544_driver);
+
+MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
+MODULE_DESCRIPTION("Si544 driver");
+MODULE_LICENSE("GPL");
index da44f8dc1d292bd3b145177d00b021e0cc7c7f6b..294850bdc195d7923f684dd5d5f17eb7f883ed68 100644 (file)
@@ -282,6 +282,7 @@ static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
 
        { STM32F4_RCC_APB2ENR,  0,      "tim1",         "apb2_mul" },
        { STM32F4_RCC_APB2ENR,  1,      "tim8",         "apb2_mul" },
+       { STM32F4_RCC_APB2ENR,  7,      "sdmmc2",       "sdmux"    },
        { STM32F4_RCC_APB2ENR,  8,      "adc1",         "apb2_div" },
        { STM32F4_RCC_APB2ENR,  9,      "adc2",         "apb2_div" },
        { STM32F4_RCC_APB2ENR, 10,      "adc3",         "apb2_div" },
@@ -315,7 +316,7 @@ static const u64 stm32f46xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
 
 static const u64 stm32f746_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
                                                      0x0000000000000003ull,
-                                                     0x04f77f033e01c9ffull };
+                                                     0x04f77f833e01c9ffull };
 
 static const u64 *stm32f4_gate_map;
 
@@ -521,7 +522,7 @@ static const struct stm32f4_pll_data stm32f429_pll[MAX_PLL_DIV] = {
 };
 
 static const struct stm32f4_pll_data stm32f469_pll[MAX_PLL_DIV] = {
-       { PLL,     50, { "pll",      "pll-q",    NULL       } },
+       { PLL,     50, { "pll",      "pll-q",    "pll-r"    } },
        { PLL_I2S, 50, { "plli2s-p", "plli2s-q", "plli2s-r" } },
        { PLL_SAI, 50, { "pllsai-p", "pllsai-q", "pllsai-r" } },
 };
@@ -1047,6 +1048,8 @@ static const char *rtc_parents[4] = {
        "no-clock", "lse", "lsi", "hse-rtc"
 };
 
+static const char *dsi_parent[2] = { NULL, "pll-r" };
+
 static const char *lcd_parent[1] = { "pllsai-r-div" };
 
 static const char *i2s_parents[2] = { "plli2s-r", NULL };
@@ -1156,6 +1159,12 @@ static const struct stm32_aux_clk stm32f469_aux_clk[] = {
                NO_GATE, 0,
                0
        },
+       {
+               CLK_F469_DSI, "dsi", dsi_parent, ARRAY_SIZE(dsi_parent),
+               STM32F4_RCC_DCKCFGR, 29, 1,
+               STM32F4_RCC_APB2ENR, 27,
+               CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
+       },
 };
 
 static const struct stm32_aux_clk stm32f746_aux_clk[] = {
@@ -1450,6 +1459,7 @@ static void __init stm32f4_rcc_init(struct device_node *np)
        stm32f4_gate_map = data->gates_map;
 
        hse_clk = of_clk_get_parent_name(np, 0);
+       dsi_parent[0] = hse_clk;
 
        i2s_in_clk = of_clk_get_parent_name(np, 1);
 
diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c
new file mode 100644 (file)
index 0000000..f1d5967
--- /dev/null
@@ -0,0 +1,2117 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Olivier Bideau <olivier.bideau@st.com> for STMicroelectronics.
+ * Author: Gabriel Fernandez <gabriel.fernandez@st.com> for STMicroelectronics.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/clock/stm32mp1-clks.h>
+
+static DEFINE_SPINLOCK(rlock);
+
+#define RCC_OCENSETR           0x0C
+#define RCC_HSICFGR            0x18
+#define RCC_RDLSICR            0x144
+#define RCC_PLL1CR             0x80
+#define RCC_PLL1CFGR1          0x84
+#define RCC_PLL1CFGR2          0x88
+#define RCC_PLL2CR             0x94
+#define RCC_PLL2CFGR1          0x98
+#define RCC_PLL2CFGR2          0x9C
+#define RCC_PLL3CR             0x880
+#define RCC_PLL3CFGR1          0x884
+#define RCC_PLL3CFGR2          0x888
+#define RCC_PLL4CR             0x894
+#define RCC_PLL4CFGR1          0x898
+#define RCC_PLL4CFGR2          0x89C
+#define RCC_APB1ENSETR         0xA00
+#define RCC_APB2ENSETR         0xA08
+#define RCC_APB3ENSETR         0xA10
+#define RCC_APB4ENSETR         0x200
+#define RCC_APB5ENSETR         0x208
+#define RCC_AHB2ENSETR         0xA18
+#define RCC_AHB3ENSETR         0xA20
+#define RCC_AHB4ENSETR         0xA28
+#define RCC_AHB5ENSETR         0x210
+#define RCC_AHB6ENSETR         0x218
+#define RCC_AHB6LPENSETR       0x318
+#define RCC_RCK12SELR          0x28
+#define RCC_RCK3SELR           0x820
+#define RCC_RCK4SELR           0x824
+#define RCC_MPCKSELR           0x20
+#define RCC_ASSCKSELR          0x24
+#define RCC_MSSCKSELR          0x48
+#define RCC_SPI6CKSELR         0xC4
+#define RCC_SDMMC12CKSELR      0x8F4
+#define RCC_SDMMC3CKSELR       0x8F8
+#define RCC_FMCCKSELR          0x904
+#define RCC_I2C46CKSELR                0xC0
+#define RCC_I2C12CKSELR                0x8C0
+#define RCC_I2C35CKSELR                0x8C4
+#define RCC_UART1CKSELR                0xC8
+#define RCC_QSPICKSELR         0x900
+#define RCC_ETHCKSELR          0x8FC
+#define RCC_RNG1CKSELR         0xCC
+#define RCC_RNG2CKSELR         0x920
+#define RCC_GPUCKSELR          0x938
+#define RCC_USBCKSELR          0x91C
+#define RCC_STGENCKSELR                0xD4
+#define RCC_SPDIFCKSELR                0x914
+#define RCC_SPI2S1CKSELR       0x8D8
+#define RCC_SPI2S23CKSELR      0x8DC
+#define RCC_SPI2S45CKSELR      0x8E0
+#define RCC_CECCKSELR          0x918
+#define RCC_LPTIM1CKSELR       0x934
+#define RCC_LPTIM23CKSELR      0x930
+#define RCC_LPTIM45CKSELR      0x92C
+#define RCC_UART24CKSELR       0x8E8
+#define RCC_UART35CKSELR       0x8EC
+#define RCC_UART6CKSELR                0x8E4
+#define RCC_UART78CKSELR       0x8F0
+#define RCC_FDCANCKSELR                0x90C
+#define RCC_SAI1CKSELR         0x8C8
+#define RCC_SAI2CKSELR         0x8CC
+#define RCC_SAI3CKSELR         0x8D0
+#define RCC_SAI4CKSELR         0x8D4
+#define RCC_ADCCKSELR          0x928
+#define RCC_MPCKDIVR           0x2C
+#define RCC_DSICKSELR          0x924
+#define RCC_CPERCKSELR         0xD0
+#define RCC_MCO1CFGR           0x800
+#define RCC_MCO2CFGR           0x804
+#define RCC_BDCR               0x140
+#define RCC_AXIDIVR            0x30
+#define RCC_MCUDIVR            0x830
+#define RCC_APB1DIVR           0x834
+#define RCC_APB2DIVR           0x838
+#define RCC_APB3DIVR           0x83C
+#define RCC_APB4DIVR           0x3C
+#define RCC_APB5DIVR           0x40
+#define RCC_TIMG1PRER          0x828
+#define RCC_TIMG2PRER          0x82C
+#define RCC_RTCDIVR            0x44
+#define RCC_DBGCFGR            0x80C
+
+#define RCC_CLR        0x4
+
+static const char * const ref12_parents[] = {
+       "ck_hsi", "ck_hse"
+};
+
+static const char * const ref3_parents[] = {
+       "ck_hsi", "ck_hse", "ck_csi"
+};
+
+static const char * const ref4_parents[] = {
+       "ck_hsi", "ck_hse", "ck_csi"
+};
+
+static const char * const cpu_src[] = {
+       "ck_hsi", "ck_hse", "pll1_p"
+};
+
+static const char * const axi_src[] = {
+       "ck_hsi", "ck_hse", "pll2_p", "pll3_p"
+};
+
+static const char * const per_src[] = {
+       "ck_hsi", "ck_csi", "ck_hse"
+};
+
+static const char * const mcu_src[] = {
+       "ck_hsi", "ck_hse", "ck_csi", "pll3_p"
+};
+
+static const char * const sdmmc12_src[] = {
+       "ck_axi", "pll3_r", "pll4_p", "ck_hsi"
+};
+
+static const char * const sdmmc3_src[] = {
+       "ck_mcu", "pll3_r", "pll4_p", "ck_hsi"
+};
+
+static const char * const fmc_src[] = {
+       "ck_axi", "pll3_r", "pll4_p", "ck_per"
+};
+
+static const char * const qspi_src[] = {
+       "ck_axi", "pll3_r", "pll4_p", "ck_per"
+};
+
+static const char * const eth_src[] = {
+       "pll4_p", "pll3_q"
+};
+
+static const char * const rng_src[] = {
+       "ck_csi", "pll4_r", "ck_lse", "ck_lsi"
+};
+
+static const char * const usbphy_src[] = {
+       "ck_hse", "pll4_r", "clk-hse-div2"
+};
+
+static const char * const usbo_src[] = {
+       "pll4_r", "ck_usbo_48m"
+};
+
+static const char * const stgen_src[] = {
+       "ck_hsi", "ck_hse"
+};
+
+static const char * const spdif_src[] = {
+       "pll4_p", "pll3_q", "ck_hsi"
+};
+
+static const char * const spi123_src[] = {
+       "pll4_p", "pll3_q", "i2s_ckin", "ck_per", "pll3_r"
+};
+
+static const char * const spi45_src[] = {
+       "pclk2", "pll4_q", "ck_hsi", "ck_csi", "ck_hse"
+};
+
+static const char * const spi6_src[] = {
+       "pclk5", "pll4_q", "ck_hsi", "ck_csi", "ck_hse", "pll3_q"
+};
+
+static const char * const cec_src[] = {
+       "ck_lse", "ck_lsi", "ck_csi"
+};
+
+static const char * const i2c12_src[] = {
+       "pclk1", "pll4_r", "ck_hsi", "ck_csi"
+};
+
+static const char * const i2c35_src[] = {
+       "pclk1", "pll4_r", "ck_hsi", "ck_csi"
+};
+
+static const char * const i2c46_src[] = {
+       "pclk5", "pll3_q", "ck_hsi", "ck_csi"
+};
+
+static const char * const lptim1_src[] = {
+       "pclk1", "pll4_p", "pll3_q", "ck_lse", "ck_lsi", "ck_per"
+};
+
+static const char * const lptim23_src[] = {
+       "pclk3", "pll4_q", "ck_per", "ck_lse", "ck_lsi"
+};
+
+static const char * const lptim45_src[] = {
+       "pclk3", "pll4_p", "pll3_q", "ck_lse", "ck_lsi", "ck_per"
+};
+
+static const char * const usart1_src[] = {
+       "pclk5", "pll3_q", "ck_hsi", "ck_csi", "pll4_q", "ck_hse"
+};
+
+const char * const usart234578_src[] = {
+       "pclk1", "pll4_q", "ck_hsi", "ck_csi", "ck_hse"
+};
+
+static const char * const usart6_src[] = {
+       "pclk2", "pll4_q", "ck_hsi", "ck_csi", "ck_hse"
+};
+
+static const char * const dfsdm_src[] = {
+       "pclk2", "ck_mcu"
+};
+
+static const char * const fdcan_src[] = {
+       "ck_hse", "pll3_q", "pll4_q"
+};
+
+static const char * const sai_src[] = {
+       "pll4_q", "pll3_q", "i2s_ckin", "ck_per"
+};
+
+static const char * const sai2_src[] = {
+       "pll4_q", "pll3_q", "i2s_ckin", "ck_per", "spdif_ck_symb"
+};
+
+static const char * const adc12_src[] = {
+       "pll4_q", "ck_per"
+};
+
+static const char * const dsi_src[] = {
+       "ck_dsi_phy", "pll4_p"
+};
+
+static const char * const rtc_src[] = {
+       "off", "ck_lse", "ck_lsi", "ck_hse_rtc"
+};
+
+static const char * const mco1_src[] = {
+       "ck_hsi", "ck_hse", "ck_csi", "ck_lsi", "ck_lse"
+};
+
+static const char * const mco2_src[] = {
+       "ck_mpu", "ck_axi", "ck_mcu", "pll4_p", "ck_hse", "ck_hsi"
+};
+
+static const char * const ck_trace_src[] = {
+       "ck_axi"
+};
+
+static const struct clk_div_table axi_div_table[] = {
+       { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },
+       { 4, 4 }, { 5, 4 }, { 6, 4 }, { 7, 4 },
+       { 0 },
+};
+
+static const struct clk_div_table mcu_div_table[] = {
+       { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 },
+       { 4, 16 }, { 5, 32 }, { 6, 64 }, { 7, 128 },
+       { 8, 512 }, { 9, 512 }, { 10, 512}, { 11, 512 },
+       { 12, 512 }, { 13, 512 }, { 14, 512}, { 15, 512 },
+       { 0 },
+};
+
+static const struct clk_div_table apb_div_table[] = {
+       { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 },
+       { 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 },
+       { 0 },
+};
+
+static const struct clk_div_table ck_trace_div_table[] = {
+       { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 },
+       { 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 },
+       { 0 },
+};
+
+#define MAX_MUX_CLK 2
+
+struct stm32_mmux {
+       u8 nbr_clk;
+       struct clk_hw *hws[MAX_MUX_CLK];
+};
+
+struct stm32_clk_mmux {
+       struct clk_mux mux;
+       struct stm32_mmux *mmux;
+};
+
+struct stm32_mgate {
+       u8 nbr_clk;
+       u32 flag;
+};
+
+struct stm32_clk_mgate {
+       struct clk_gate gate;
+       struct stm32_mgate *mgate;
+       u32 mask;
+};
+
+struct clock_config {
+       u32 id;
+       const char *name;
+       union {
+               const char *parent_name;
+               const char * const *parent_names;
+       };
+       int num_parents;
+       unsigned long flags;
+       void *cfg;
+       struct clk_hw * (*func)(struct device *dev,
+                               struct clk_hw_onecell_data *clk_data,
+                               void __iomem *base, spinlock_t *lock,
+                               const struct clock_config *cfg);
+};
+
+#define NO_ID ~0
+
+struct gate_cfg {
+       u32 reg_off;
+       u8 bit_idx;
+       u8 gate_flags;
+};
+
+struct fixed_factor_cfg {
+       unsigned int mult;
+       unsigned int div;
+};
+
+struct div_cfg {
+       u32 reg_off;
+       u8 shift;
+       u8 width;
+       u8 div_flags;
+       const struct clk_div_table *table;
+};
+
+struct mux_cfg {
+       u32 reg_off;
+       u8 shift;
+       u8 width;
+       u8 mux_flags;
+       u32 *table;
+};
+
+struct stm32_gate_cfg {
+       struct gate_cfg         *gate;
+       struct stm32_mgate      *mgate;
+       const struct clk_ops    *ops;
+};
+
+struct stm32_div_cfg {
+       struct div_cfg          *div;
+       const struct clk_ops    *ops;
+};
+
+struct stm32_mux_cfg {
+       struct mux_cfg          *mux;
+       struct stm32_mmux       *mmux;
+       const struct clk_ops    *ops;
+};
+
+/* STM32 Composite clock */
+struct stm32_composite_cfg {
+       const struct stm32_gate_cfg     *gate;
+       const struct stm32_div_cfg      *div;
+       const struct stm32_mux_cfg      *mux;
+};
+
+static struct clk_hw *
+_clk_hw_register_gate(struct device *dev,
+                     struct clk_hw_onecell_data *clk_data,
+                     void __iomem *base, spinlock_t *lock,
+                     const struct clock_config *cfg)
+{
+       struct gate_cfg *gate_cfg = cfg->cfg;
+
+       return clk_hw_register_gate(dev,
+                                   cfg->name,
+                                   cfg->parent_name,
+                                   cfg->flags,
+                                   gate_cfg->reg_off + base,
+                                   gate_cfg->bit_idx,
+                                   gate_cfg->gate_flags,
+                                   lock);
+}
+
+static struct clk_hw *
+_clk_hw_register_fixed_factor(struct device *dev,
+                             struct clk_hw_onecell_data *clk_data,
+                             void __iomem *base, spinlock_t *lock,
+                             const struct clock_config *cfg)
+{
+       struct fixed_factor_cfg *ff_cfg = cfg->cfg;
+
+       return clk_hw_register_fixed_factor(dev, cfg->name, cfg->parent_name,
+                                           cfg->flags, ff_cfg->mult,
+                                           ff_cfg->div);
+}
+
+static struct clk_hw *
+_clk_hw_register_divider_table(struct device *dev,
+                              struct clk_hw_onecell_data *clk_data,
+                              void __iomem *base, spinlock_t *lock,
+                              const struct clock_config *cfg)
+{
+       struct div_cfg *div_cfg = cfg->cfg;
+
+       return clk_hw_register_divider_table(dev,
+                                            cfg->name,
+                                            cfg->parent_name,
+                                            cfg->flags,
+                                            div_cfg->reg_off + base,
+                                            div_cfg->shift,
+                                            div_cfg->width,
+                                            div_cfg->div_flags,
+                                            div_cfg->table,
+                                            lock);
+}
+
+static struct clk_hw *
+_clk_hw_register_mux(struct device *dev,
+                    struct clk_hw_onecell_data *clk_data,
+                    void __iomem *base, spinlock_t *lock,
+                    const struct clock_config *cfg)
+{
+       struct mux_cfg *mux_cfg = cfg->cfg;
+
+       return clk_hw_register_mux(dev, cfg->name, cfg->parent_names,
+                                  cfg->num_parents, cfg->flags,
+                                  mux_cfg->reg_off + base, mux_cfg->shift,
+                                  mux_cfg->width, mux_cfg->mux_flags, lock);
+}
+
+/* MP1 Gate clock with set & clear registers */
+
+static int mp1_gate_clk_enable(struct clk_hw *hw)
+{
+       if (!clk_gate_ops.is_enabled(hw))
+               clk_gate_ops.enable(hw);
+
+       return 0;
+}
+
+static void mp1_gate_clk_disable(struct clk_hw *hw)
+{
+       struct clk_gate *gate = to_clk_gate(hw);
+       unsigned long flags = 0;
+
+       if (clk_gate_ops.is_enabled(hw)) {
+               spin_lock_irqsave(gate->lock, flags);
+               writel_relaxed(BIT(gate->bit_idx), gate->reg + RCC_CLR);
+               spin_unlock_irqrestore(gate->lock, flags);
+       }
+}
+
+const struct clk_ops mp1_gate_clk_ops = {
+       .enable         = mp1_gate_clk_enable,
+       .disable        = mp1_gate_clk_disable,
+       .is_enabled     = clk_gate_is_enabled,
+};
+
+static struct clk_hw *_get_stm32_mux(void __iomem *base,
+                                    const struct stm32_mux_cfg *cfg,
+                                    spinlock_t *lock)
+{
+       struct stm32_clk_mmux *mmux;
+       struct clk_mux *mux;
+       struct clk_hw *mux_hw;
+
+       if (cfg->mmux) {
+               mmux = kzalloc(sizeof(*mmux), GFP_KERNEL);
+               if (!mmux)
+                       return ERR_PTR(-ENOMEM);
+
+               mmux->mux.reg = cfg->mux->reg_off + base;
+               mmux->mux.shift = cfg->mux->shift;
+               mmux->mux.mask = (1 << cfg->mux->width) - 1;
+               mmux->mux.flags = cfg->mux->mux_flags;
+               mmux->mux.table = cfg->mux->table;
+               mmux->mux.lock = lock;
+               mmux->mmux = cfg->mmux;
+               mux_hw = &mmux->mux.hw;
+               cfg->mmux->hws[cfg->mmux->nbr_clk++] = mux_hw;
+
+       } else {
+               mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+               if (!mux)
+                       return ERR_PTR(-ENOMEM);
+
+               mux->reg = cfg->mux->reg_off + base;
+               mux->shift = cfg->mux->shift;
+               mux->mask = (1 << cfg->mux->width) - 1;
+               mux->flags = cfg->mux->mux_flags;
+               mux->table = cfg->mux->table;
+               mux->lock = lock;
+               mux_hw = &mux->hw;
+       }
+
+       return mux_hw;
+}
+
+static struct clk_hw *_get_stm32_div(void __iomem *base,
+                                    const struct stm32_div_cfg *cfg,
+                                    spinlock_t *lock)
+{
+       struct clk_divider *div;
+
+       div = kzalloc(sizeof(*div), GFP_KERNEL);
+
+       if (!div)
+               return ERR_PTR(-ENOMEM);
+
+       div->reg = cfg->div->reg_off + base;
+       div->shift = cfg->div->shift;
+       div->width = cfg->div->width;
+       div->flags = cfg->div->div_flags;
+       div->table = cfg->div->table;
+       div->lock = lock;
+
+       return &div->hw;
+}
+
+static struct clk_hw *
+_get_stm32_gate(void __iomem *base,
+               const struct stm32_gate_cfg *cfg, spinlock_t *lock)
+{
+       struct stm32_clk_mgate *mgate;
+       struct clk_gate *gate;
+       struct clk_hw *gate_hw;
+
+       if (cfg->mgate) {
+               mgate = kzalloc(sizeof(*mgate), GFP_KERNEL);
+               if (!mgate)
+                       return ERR_PTR(-ENOMEM);
+
+               mgate->gate.reg = cfg->gate->reg_off + base;
+               mgate->gate.bit_idx = cfg->gate->bit_idx;
+               mgate->gate.flags = cfg->gate->gate_flags;
+               mgate->gate.lock = lock;
+               mgate->mask = BIT(cfg->mgate->nbr_clk++);
+
+               mgate->mgate = cfg->mgate;
+
+               gate_hw = &mgate->gate.hw;
+
+       } else {
+               gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+               if (!gate)
+                       return ERR_PTR(-ENOMEM);
+
+               gate->reg = cfg->gate->reg_off + base;
+               gate->bit_idx = cfg->gate->bit_idx;
+               gate->flags = cfg->gate->gate_flags;
+               gate->lock = lock;
+
+               gate_hw = &gate->hw;
+       }
+
+       return gate_hw;
+}
+
+static struct clk_hw *
+clk_stm32_register_gate_ops(struct device *dev,
+                           const char *name,
+                           const char *parent_name,
+                           unsigned long flags,
+                           void __iomem *base,
+                           const struct stm32_gate_cfg *cfg,
+                           spinlock_t *lock)
+{
+       struct clk_init_data init = { NULL };
+       struct clk_gate *gate;
+       struct clk_hw *hw;
+       int ret;
+
+       gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+       if (!gate)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+       init.flags = flags;
+
+       init.ops = &clk_gate_ops;
+
+       if (cfg->ops)
+               init.ops = cfg->ops;
+
+       hw = _get_stm32_gate(base, cfg, lock);
+       if (IS_ERR(hw))
+               return ERR_PTR(-ENOMEM);
+
+       hw->init = &init;
+
+       ret = clk_hw_register(dev, hw);
+       if (ret) {
+               kfree(gate);
+               hw = ERR_PTR(ret);
+       }
+
+       return hw;
+}
+
+static struct clk_hw *
+clk_stm32_register_composite(struct device *dev,
+                            const char *name, const char * const *parent_names,
+                            int num_parents, void __iomem *base,
+                            const struct stm32_composite_cfg *cfg,
+                            unsigned long flags, spinlock_t *lock)
+{
+       const struct clk_ops *mux_ops, *div_ops, *gate_ops;
+       struct clk_hw *mux_hw, *div_hw, *gate_hw;
+
+       mux_hw = NULL;
+       div_hw = NULL;
+       gate_hw = NULL;
+       mux_ops = NULL;
+       div_ops = NULL;
+       gate_ops = NULL;
+
+       if (cfg->mux) {
+               mux_hw = _get_stm32_mux(base, cfg->mux, lock);
+
+               if (!IS_ERR(mux_hw)) {
+                       mux_ops = &clk_mux_ops;
+
+                       if (cfg->mux->ops)
+                               mux_ops = cfg->mux->ops;
+               }
+       }
+
+       if (cfg->div) {
+               div_hw = _get_stm32_div(base, cfg->div, lock);
+
+               if (!IS_ERR(div_hw)) {
+                       div_ops = &clk_divider_ops;
+
+                       if (cfg->div->ops)
+                               div_ops = cfg->div->ops;
+               }
+       }
+
+       if (cfg->gate) {
+               gate_hw = _get_stm32_gate(base, cfg->gate, lock);
+
+               if (!IS_ERR(gate_hw)) {
+                       gate_ops = &clk_gate_ops;
+
+                       if (cfg->gate->ops)
+                               gate_ops = cfg->gate->ops;
+               }
+       }
+
+       return clk_hw_register_composite(dev, name, parent_names, num_parents,
+                                      mux_hw, mux_ops, div_hw, div_ops,
+                                      gate_hw, gate_ops, flags);
+}
+
+#define to_clk_mgate(_gate) container_of(_gate, struct stm32_clk_mgate, gate)
+
+static int mp1_mgate_clk_enable(struct clk_hw *hw)
+{
+       struct clk_gate *gate = to_clk_gate(hw);
+       struct stm32_clk_mgate *clk_mgate = to_clk_mgate(gate);
+
+       clk_mgate->mgate->flag |= clk_mgate->mask;
+
+       mp1_gate_clk_enable(hw);
+
+       return  0;
+}
+
+static void mp1_mgate_clk_disable(struct clk_hw *hw)
+{
+       struct clk_gate *gate = to_clk_gate(hw);
+       struct stm32_clk_mgate *clk_mgate = to_clk_mgate(gate);
+
+       clk_mgate->mgate->flag &= ~clk_mgate->mask;
+
+       if (clk_mgate->mgate->flag == 0)
+               mp1_gate_clk_disable(hw);
+}
+
+const struct clk_ops mp1_mgate_clk_ops = {
+       .enable         = mp1_mgate_clk_enable,
+       .disable        = mp1_mgate_clk_disable,
+       .is_enabled     = clk_gate_is_enabled,
+
+};
+
+#define to_clk_mmux(_mux) container_of(_mux, struct stm32_clk_mmux, mux)
+
+static u8 clk_mmux_get_parent(struct clk_hw *hw)
+{
+       return clk_mux_ops.get_parent(hw);
+}
+
+static int clk_mmux_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct clk_mux *mux = to_clk_mux(hw);
+       struct stm32_clk_mmux *clk_mmux = to_clk_mmux(mux);
+       struct clk_hw *hwp;
+       int ret, n;
+
+       ret = clk_mux_ops.set_parent(hw, index);
+       if (ret)
+               return ret;
+
+       hwp = clk_hw_get_parent(hw);
+
+       for (n = 0; n < clk_mmux->mmux->nbr_clk; n++)
+               if (clk_mmux->mmux->hws[n] != hw)
+                       clk_hw_reparent(clk_mmux->mmux->hws[n], hwp);
+
+       return 0;
+}
+
+const struct clk_ops clk_mmux_ops = {
+       .get_parent     = clk_mmux_get_parent,
+       .set_parent     = clk_mmux_set_parent,
+       .determine_rate = __clk_mux_determine_rate,
+};
+
+/* STM32 PLL */
+struct stm32_pll_obj {
+       /* lock pll enable/disable registers */
+       spinlock_t *lock;
+       void __iomem *reg;
+       struct clk_hw hw;
+};
+
+#define to_pll(_hw) container_of(_hw, struct stm32_pll_obj, hw)
+
+#define PLL_ON         BIT(0)
+#define PLL_RDY                BIT(1)
+#define DIVN_MASK      0x1FF
+#define DIVM_MASK      0x3F
+#define DIVM_SHIFT     16
+#define DIVN_SHIFT     0
+#define FRAC_OFFSET    0xC
+#define FRAC_MASK      0x1FFF
+#define FRAC_SHIFT     3
+#define FRACLE         BIT(16)
+
+static int __pll_is_enabled(struct clk_hw *hw)
+{
+       struct stm32_pll_obj *clk_elem = to_pll(hw);
+
+       return readl_relaxed(clk_elem->reg) & PLL_ON;
+}
+
+#define TIMEOUT 5
+
+static int pll_enable(struct clk_hw *hw)
+{
+       struct stm32_pll_obj *clk_elem = to_pll(hw);
+       u32 reg;
+       unsigned long flags = 0;
+       unsigned int timeout = TIMEOUT;
+       int bit_status = 0;
+
+       spin_lock_irqsave(clk_elem->lock, flags);
+
+       if (__pll_is_enabled(hw))
+               goto unlock;
+
+       reg = readl_relaxed(clk_elem->reg);
+       reg |= PLL_ON;
+       writel_relaxed(reg, clk_elem->reg);
+
+       /* We can't use readl_poll_timeout() because we can be blocked if
+        * someone enables this clock before clocksource changes.
+        * Only jiffies counter is available. Jiffies are incremented by
+        * interruptions and enable op does not allow to be interrupted.
+        */
+       do {
+               bit_status = !(readl_relaxed(clk_elem->reg) & PLL_RDY);
+
+               if (bit_status)
+                       udelay(120);
+
+       } while (bit_status && --timeout);
+
+unlock:
+       spin_unlock_irqrestore(clk_elem->lock, flags);
+
+       return bit_status;
+}
+
+static void pll_disable(struct clk_hw *hw)
+{
+       struct stm32_pll_obj *clk_elem = to_pll(hw);
+       u32 reg;
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(clk_elem->lock, flags);
+
+       reg = readl_relaxed(clk_elem->reg);
+       reg &= ~PLL_ON;
+       writel_relaxed(reg, clk_elem->reg);
+
+       spin_unlock_irqrestore(clk_elem->lock, flags);
+}
+
+static u32 pll_frac_val(struct clk_hw *hw)
+{
+       struct stm32_pll_obj *clk_elem = to_pll(hw);
+       u32 reg, frac = 0;
+
+       reg = readl_relaxed(clk_elem->reg + FRAC_OFFSET);
+       if (reg & FRACLE)
+               frac = (reg >> FRAC_SHIFT) & FRAC_MASK;
+
+       return frac;
+}
+
+static unsigned long pll_recalc_rate(struct clk_hw *hw,
+                                    unsigned long parent_rate)
+{
+       struct stm32_pll_obj *clk_elem = to_pll(hw);
+       u32 reg;
+       u32 frac, divm, divn;
+       u64 rate, rate_frac = 0;
+
+       reg = readl_relaxed(clk_elem->reg + 4);
+
+       divm = ((reg >> DIVM_SHIFT) & DIVM_MASK) + 1;
+       divn = ((reg >> DIVN_SHIFT) & DIVN_MASK) + 1;
+       rate = (u64)parent_rate * divn;
+
+       do_div(rate, divm);
+
+       frac = pll_frac_val(hw);
+       if (frac) {
+               rate_frac = (u64)parent_rate * (u64)frac;
+               do_div(rate_frac, (divm * 8192));
+       }
+
+       return rate + rate_frac;
+}
+
+static int pll_is_enabled(struct clk_hw *hw)
+{
+       struct stm32_pll_obj *clk_elem = to_pll(hw);
+       unsigned long flags = 0;
+       int ret;
+
+       spin_lock_irqsave(clk_elem->lock, flags);
+       ret = __pll_is_enabled(hw);
+       spin_unlock_irqrestore(clk_elem->lock, flags);
+
+       return ret;
+}
+
+static const struct clk_ops pll_ops = {
+       .enable         = pll_enable,
+       .disable        = pll_disable,
+       .recalc_rate    = pll_recalc_rate,
+       .is_enabled     = pll_is_enabled,
+};
+
+static struct clk_hw *clk_register_pll(struct device *dev, const char *name,
+                                      const char *parent_name,
+                                      void __iomem *reg,
+                                      unsigned long flags,
+                                      spinlock_t *lock)
+{
+       struct stm32_pll_obj *element;
+       struct clk_init_data init;
+       struct clk_hw *hw;
+       int err;
+
+       element = kzalloc(sizeof(*element), GFP_KERNEL);
+       if (!element)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &pll_ops;
+       init.flags = flags;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       element->hw.init = &init;
+       element->reg = reg;
+       element->lock = lock;
+
+       hw = &element->hw;
+       err = clk_hw_register(dev, hw);
+
+       if (err) {
+               kfree(element);
+               return ERR_PTR(err);
+       }
+
+       return hw;
+}
+
+/* Kernel Timer */
+struct timer_cker {
+       /* lock the kernel output divider register */
+       spinlock_t *lock;
+       void __iomem *apbdiv;
+       void __iomem *timpre;
+       struct clk_hw hw;
+};
+
+#define to_timer_cker(_hw) container_of(_hw, struct timer_cker, hw)
+
+#define APB_DIV_MASK 0x07
+#define TIM_PRE_MASK 0x01
+
+static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct timer_cker *tim_ker = to_timer_cker(hw);
+       u32 prescaler;
+       unsigned int mult = 0;
+
+       prescaler = readl_relaxed(tim_ker->apbdiv) & APB_DIV_MASK;
+       if (prescaler < 2)
+               return 1;
+
+       mult = 2;
+
+       if (rate / parent_rate >= 4)
+               mult = 4;
+
+       return mult;
+}
+
+static long timer_ker_round_rate(struct clk_hw *hw, unsigned long rate,
+                                unsigned long *parent_rate)
+{
+       unsigned long factor = __bestmult(hw, rate, *parent_rate);
+
+       return *parent_rate * factor;
+}
+
+static int timer_ker_set_rate(struct clk_hw *hw, unsigned long rate,
+                             unsigned long parent_rate)
+{
+       struct timer_cker *tim_ker = to_timer_cker(hw);
+       unsigned long flags = 0;
+       unsigned long factor = __bestmult(hw, rate, parent_rate);
+       int ret = 0;
+
+       spin_lock_irqsave(tim_ker->lock, flags);
+
+       switch (factor) {
+       case 1:
+               break;
+       case 2:
+               writel_relaxed(0, tim_ker->timpre);
+               break;
+       case 4:
+               writel_relaxed(1, tim_ker->timpre);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       spin_unlock_irqrestore(tim_ker->lock, flags);
+
+       return ret;
+}
+
+static unsigned long timer_ker_recalc_rate(struct clk_hw *hw,
+                                          unsigned long parent_rate)
+{
+       struct timer_cker *tim_ker = to_timer_cker(hw);
+       u32 prescaler, timpre;
+       u32 mul;
+
+       prescaler = readl_relaxed(tim_ker->apbdiv) & APB_DIV_MASK;
+
+       timpre = readl_relaxed(tim_ker->timpre) & TIM_PRE_MASK;
+
+       if (!prescaler)
+               return parent_rate;
+
+       mul = (timpre + 1) * 2;
+
+       return parent_rate * mul;
+}
+
+static const struct clk_ops timer_ker_ops = {
+       .recalc_rate    = timer_ker_recalc_rate,
+       .round_rate     = timer_ker_round_rate,
+       .set_rate       = timer_ker_set_rate,
+
+};
+
+static struct clk_hw *clk_register_cktim(struct device *dev, const char *name,
+                                        const char *parent_name,
+                                        unsigned long flags,
+                                        void __iomem *apbdiv,
+                                        void __iomem *timpre,
+                                        spinlock_t *lock)
+{
+       struct timer_cker *tim_ker;
+       struct clk_init_data init;
+       struct clk_hw *hw;
+       int err;
+
+       tim_ker = kzalloc(sizeof(*tim_ker), GFP_KERNEL);
+       if (!tim_ker)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &timer_ker_ops;
+       init.flags = flags;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       tim_ker->hw.init = &init;
+       tim_ker->lock = lock;
+       tim_ker->apbdiv = apbdiv;
+       tim_ker->timpre = timpre;
+
+       hw = &tim_ker->hw;
+       err = clk_hw_register(dev, hw);
+
+       if (err) {
+               kfree(tim_ker);
+               return ERR_PTR(err);
+       }
+
+       return hw;
+}
+
+struct stm32_pll_cfg {
+       u32 offset;
+};
+
+struct clk_hw *_clk_register_pll(struct device *dev,
+                                struct clk_hw_onecell_data *clk_data,
+                                void __iomem *base, spinlock_t *lock,
+                                const struct clock_config *cfg)
+{
+       struct stm32_pll_cfg *stm_pll_cfg = cfg->cfg;
+
+       return clk_register_pll(dev, cfg->name, cfg->parent_name,
+                               base + stm_pll_cfg->offset, cfg->flags, lock);
+}
+
+struct stm32_cktim_cfg {
+       u32 offset_apbdiv;
+       u32 offset_timpre;
+};
+
+static struct clk_hw *_clk_register_cktim(struct device *dev,
+                                         struct clk_hw_onecell_data *clk_data,
+                                         void __iomem *base, spinlock_t *lock,
+                                         const struct clock_config *cfg)
+{
+       struct stm32_cktim_cfg *cktim_cfg = cfg->cfg;
+
+       return clk_register_cktim(dev, cfg->name, cfg->parent_name, cfg->flags,
+                                 cktim_cfg->offset_apbdiv + base,
+                                 cktim_cfg->offset_timpre + base, lock);
+}
+
+static struct clk_hw *
+_clk_stm32_register_gate(struct device *dev,
+                        struct clk_hw_onecell_data *clk_data,
+                        void __iomem *base, spinlock_t *lock,
+                        const struct clock_config *cfg)
+{
+       return clk_stm32_register_gate_ops(dev,
+                                   cfg->name,
+                                   cfg->parent_name,
+                                   cfg->flags,
+                                   base,
+                                   cfg->cfg,
+                                   lock);
+}
+
+static struct clk_hw *
+_clk_stm32_register_composite(struct device *dev,
+                             struct clk_hw_onecell_data *clk_data,
+                             void __iomem *base, spinlock_t *lock,
+                             const struct clock_config *cfg)
+{
+       return clk_stm32_register_composite(dev, cfg->name, cfg->parent_names,
+                                           cfg->num_parents, base, cfg->cfg,
+                                           cfg->flags, lock);
+}
+
+#define GATE(_id, _name, _parent, _flags, _offset, _bit_idx, _gate_flags)\
+{\
+       .id             = _id,\
+       .name           = _name,\
+       .parent_name    = _parent,\
+       .flags          = _flags,\
+       .cfg            =  &(struct gate_cfg) {\
+               .reg_off        = _offset,\
+               .bit_idx        = _bit_idx,\
+               .gate_flags     = _gate_flags,\
+       },\
+       .func           = _clk_hw_register_gate,\
+}
+
+#define FIXED_FACTOR(_id, _name, _parent, _flags, _mult, _div)\
+{\
+       .id             = _id,\
+       .name           = _name,\
+       .parent_name    = _parent,\
+       .flags          = _flags,\
+       .cfg            =  &(struct fixed_factor_cfg) {\
+               .mult = _mult,\
+               .div = _div,\
+       },\
+       .func           = _clk_hw_register_fixed_factor,\
+}
+
+#define DIV_TABLE(_id, _name, _parent, _flags, _offset, _shift, _width,\
+                 _div_flags, _div_table)\
+{\
+       .id             = _id,\
+       .name           = _name,\
+       .parent_name    = _parent,\
+       .flags          = _flags,\
+       .cfg            =  &(struct div_cfg) {\
+               .reg_off        = _offset,\
+               .shift          = _shift,\
+               .width          = _width,\
+               .div_flags      = _div_flags,\
+               .table          = _div_table,\
+       },\
+       .func           = _clk_hw_register_divider_table,\
+}
+
+#define DIV(_id, _name, _parent, _flags, _offset, _shift, _width, _div_flags)\
+       DIV_TABLE(_id, _name, _parent, _flags, _offset, _shift, _width,\
+                 _div_flags, NULL)
+
+#define MUX(_id, _name, _parents, _flags, _offset, _shift, _width, _mux_flags)\
+{\
+       .id             = _id,\
+       .name           = _name,\
+       .parent_names   = _parents,\
+       .num_parents    = ARRAY_SIZE(_parents),\
+       .flags          = _flags,\
+       .cfg            =  &(struct mux_cfg) {\
+               .reg_off        = _offset,\
+               .shift          = _shift,\
+               .width          = _width,\
+               .mux_flags      = _mux_flags,\
+       },\
+       .func           = _clk_hw_register_mux,\
+}
+
+#define PLL(_id, _name, _parent, _flags, _offset)\
+{\
+       .id             = _id,\
+       .name           = _name,\
+       .parent_name    = _parent,\
+       .flags          = _flags,\
+       .cfg            =  &(struct stm32_pll_cfg) {\
+               .offset = _offset,\
+       },\
+       .func           = _clk_register_pll,\
+}
+
+#define STM32_CKTIM(_name, _parent, _flags, _offset_apbdiv, _offset_timpre)\
+{\
+       .id             = NO_ID,\
+       .name           = _name,\
+       .parent_name    = _parent,\
+       .flags          = _flags,\
+       .cfg            =  &(struct stm32_cktim_cfg) {\
+               .offset_apbdiv = _offset_apbdiv,\
+               .offset_timpre = _offset_timpre,\
+       },\
+       .func           = _clk_register_cktim,\
+}
+
+#define STM32_TIM(_id, _name, _parent, _offset_set, _bit_idx)\
+                 GATE_MP1(_id, _name, _parent, CLK_SET_RATE_PARENT,\
+                          _offset_set, _bit_idx, 0)
+
+/* STM32 GATE */
+#define STM32_GATE(_id, _name, _parent, _flags, _gate)\
+{\
+       .id             = _id,\
+       .name           = _name,\
+       .parent_name    = _parent,\
+       .flags          = _flags,\
+       .cfg            = (struct stm32_gate_cfg *) {_gate},\
+       .func           = _clk_stm32_register_gate,\
+}
+
+#define _STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags, _mgate, _ops)\
+       (&(struct stm32_gate_cfg) {\
+               &(struct gate_cfg) {\
+                       .reg_off        = _gate_offset,\
+                       .bit_idx        = _gate_bit_idx,\
+                       .gate_flags     = _gate_flags,\
+               },\
+               .mgate          = _mgate,\
+               .ops            = _ops,\
+       })
+
+#define _STM32_MGATE(_mgate)\
+       (&per_gate_cfg[_mgate])
+
+#define _GATE(_gate_offset, _gate_bit_idx, _gate_flags)\
+       _STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags,\
+                   NULL, NULL)\
+
+#define _GATE_MP1(_gate_offset, _gate_bit_idx, _gate_flags)\
+       _STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags,\
+                   NULL, &mp1_gate_clk_ops)\
+
+#define _MGATE_MP1(_mgate)\
+       .gate = &per_gate_cfg[_mgate]
+
+#define GATE_MP1(_id, _name, _parent, _flags, _offset, _bit_idx, _gate_flags)\
+       STM32_GATE(_id, _name, _parent, _flags,\
+                  _GATE_MP1(_offset, _bit_idx, _gate_flags))
+
+#define MGATE_MP1(_id, _name, _parent, _flags, _mgate)\
+       STM32_GATE(_id, _name, _parent, _flags,\
+                  _STM32_MGATE(_mgate))
+
+#define _STM32_DIV(_div_offset, _div_shift, _div_width,\
+                  _div_flags, _div_table, _ops)\
+       .div = &(struct stm32_div_cfg) {\
+               &(struct div_cfg) {\
+                       .reg_off        = _div_offset,\
+                       .shift          = _div_shift,\
+                       .width          = _div_width,\
+                       .div_flags      = _div_flags,\
+                       .table          = _div_table,\
+               },\
+               .ops            = _ops,\
+       }
+
+#define _DIV(_div_offset, _div_shift, _div_width, _div_flags, _div_table)\
+       _STM32_DIV(_div_offset, _div_shift, _div_width,\
+                  _div_flags, _div_table, NULL)\
+
+#define _STM32_MUX(_offset, _shift, _width, _mux_flags, _mmux, _ops)\
+       .mux = &(struct stm32_mux_cfg) {\
+               &(struct mux_cfg) {\
+                       .reg_off        = _offset,\
+                       .shift          = _shift,\
+                       .width          = _width,\
+                       .mux_flags      = _mux_flags,\
+                       .table          = NULL,\
+               },\
+               .mmux           = _mmux,\
+               .ops            = _ops,\
+       }
+
+#define _MUX(_offset, _shift, _width, _mux_flags)\
+       _STM32_MUX(_offset, _shift, _width, _mux_flags, NULL, NULL)\
+
+#define _MMUX(_mmux) .mux = &ker_mux_cfg[_mmux]
+
+#define PARENT(_parent) ((const char *[]) { _parent})
+
+#define _NO_MUX .mux = NULL
+#define _NO_DIV .div = NULL
+#define _NO_GATE .gate = NULL
+
+#define COMPOSITE(_id, _name, _parents, _flags, _gate, _mux, _div)\
+{\
+       .id             = _id,\
+       .name           = _name,\
+       .parent_names   = _parents,\
+       .num_parents    = ARRAY_SIZE(_parents),\
+       .flags          = _flags,\
+       .cfg            = &(struct stm32_composite_cfg) {\
+               _gate,\
+               _mux,\
+               _div,\
+       },\
+       .func           = _clk_stm32_register_composite,\
+}
+
+#define PCLK(_id, _name, _parent, _flags, _mgate)\
+       MGATE_MP1(_id, _name, _parent, _flags, _mgate)
+
+#define KCLK(_id, _name, _parents, _flags, _mgate, _mmux)\
+            COMPOSITE(_id, _name, _parents, CLK_OPS_PARENT_ENABLE | _flags,\
+                 _MGATE_MP1(_mgate),\
+                 _MMUX(_mmux),\
+                 _NO_DIV)
+
+enum {
+       G_SAI1,
+       G_SAI2,
+       G_SAI3,
+       G_SAI4,
+       G_SPI1,
+       G_SPI2,
+       G_SPI3,
+       G_SPI4,
+       G_SPI5,
+       G_SPI6,
+       G_SPDIF,
+       G_I2C1,
+       G_I2C2,
+       G_I2C3,
+       G_I2C4,
+       G_I2C5,
+       G_I2C6,
+       G_USART2,
+       G_UART4,
+       G_USART3,
+       G_UART5,
+       G_USART1,
+       G_USART6,
+       G_UART7,
+       G_UART8,
+       G_LPTIM1,
+       G_LPTIM2,
+       G_LPTIM3,
+       G_LPTIM4,
+       G_LPTIM5,
+       G_LTDC,
+       G_DSI,
+       G_QSPI,
+       G_FMC,
+       G_SDMMC1,
+       G_SDMMC2,
+       G_SDMMC3,
+       G_USBO,
+       G_USBPHY,
+       G_RNG1,
+       G_RNG2,
+       G_FDCAN,
+       G_DAC12,
+       G_CEC,
+       G_ADC12,
+       G_GPU,
+       G_STGEN,
+       G_DFSDM,
+       G_ADFSDM,
+       G_TIM2,
+       G_TIM3,
+       G_TIM4,
+       G_TIM5,
+       G_TIM6,
+       G_TIM7,
+       G_TIM12,
+       G_TIM13,
+       G_TIM14,
+       G_MDIO,
+       G_TIM1,
+       G_TIM8,
+       G_TIM15,
+       G_TIM16,
+       G_TIM17,
+       G_SYSCFG,
+       G_VREF,
+       G_TMPSENS,
+       G_PMBCTRL,
+       G_HDP,
+       G_IWDG2,
+       G_STGENRO,
+       G_DMA1,
+       G_DMA2,
+       G_DMAMUX,
+       G_DCMI,
+       G_CRYP2,
+       G_HASH2,
+       G_CRC2,
+       G_HSEM,
+       G_IPCC,
+       G_GPIOA,
+       G_GPIOB,
+       G_GPIOC,
+       G_GPIOD,
+       G_GPIOE,
+       G_GPIOF,
+       G_GPIOG,
+       G_GPIOH,
+       G_GPIOI,
+       G_GPIOJ,
+       G_GPIOK,
+       G_MDMA,
+       G_ETHCK,
+       G_ETHTX,
+       G_ETHRX,
+       G_ETHMAC,
+       G_CRC1,
+       G_USBH,
+       G_ETHSTP,
+       G_RTCAPB,
+       G_TZC,
+       G_TZPC,
+       G_IWDG1,
+       G_BSEC,
+       G_GPIOZ,
+       G_CRYP1,
+       G_HASH1,
+       G_BKPSRAM,
+
+       G_LAST
+};
+
+struct stm32_mgate mp1_mgate[G_LAST];
+
+#define _K_GATE(_id, _gate_offset, _gate_bit_idx, _gate_flags,\
+              _mgate, _ops)\
+       [_id] = {\
+               &(struct gate_cfg) {\
+                       .reg_off        = _gate_offset,\
+                       .bit_idx        = _gate_bit_idx,\
+                       .gate_flags     = _gate_flags,\
+               },\
+               .mgate          = _mgate,\
+               .ops            = _ops,\
+       }
+
+#define K_GATE(_id, _gate_offset, _gate_bit_idx, _gate_flags)\
+       _K_GATE(_id, _gate_offset, _gate_bit_idx, _gate_flags,\
+              NULL, &mp1_gate_clk_ops)
+
+#define K_MGATE(_id, _gate_offset, _gate_bit_idx, _gate_flags)\
+       _K_GATE(_id, _gate_offset, _gate_bit_idx, _gate_flags,\
+              &mp1_mgate[_id], &mp1_mgate_clk_ops)
+
+/* Peripheral gates */
+struct stm32_gate_cfg per_gate_cfg[G_LAST] = {
+       /* Multi gates */
+       K_GATE(G_MDIO,          RCC_APB1ENSETR, 31, 0),
+       K_MGATE(G_DAC12,        RCC_APB1ENSETR, 29, 0),
+       K_MGATE(G_CEC,          RCC_APB1ENSETR, 27, 0),
+       K_MGATE(G_SPDIF,        RCC_APB1ENSETR, 26, 0),
+       K_MGATE(G_I2C5,         RCC_APB1ENSETR, 24, 0),
+       K_MGATE(G_I2C3,         RCC_APB1ENSETR, 23, 0),
+       K_MGATE(G_I2C2,         RCC_APB1ENSETR, 22, 0),
+       K_MGATE(G_I2C1,         RCC_APB1ENSETR, 21, 0),
+       K_MGATE(G_UART8,        RCC_APB1ENSETR, 19, 0),
+       K_MGATE(G_UART7,        RCC_APB1ENSETR, 18, 0),
+       K_MGATE(G_UART5,        RCC_APB1ENSETR, 17, 0),
+       K_MGATE(G_UART4,        RCC_APB1ENSETR, 16, 0),
+       K_MGATE(G_USART3,       RCC_APB1ENSETR, 15, 0),
+       K_MGATE(G_USART2,       RCC_APB1ENSETR, 14, 0),
+       K_MGATE(G_SPI3,         RCC_APB1ENSETR, 12, 0),
+       K_MGATE(G_SPI2,         RCC_APB1ENSETR, 11, 0),
+       K_MGATE(G_LPTIM1,       RCC_APB1ENSETR, 9, 0),
+       K_GATE(G_TIM14,         RCC_APB1ENSETR, 8, 0),
+       K_GATE(G_TIM13,         RCC_APB1ENSETR, 7, 0),
+       K_GATE(G_TIM12,         RCC_APB1ENSETR, 6, 0),
+       K_GATE(G_TIM7,          RCC_APB1ENSETR, 5, 0),
+       K_GATE(G_TIM6,          RCC_APB1ENSETR, 4, 0),
+       K_GATE(G_TIM5,          RCC_APB1ENSETR, 3, 0),
+       K_GATE(G_TIM4,          RCC_APB1ENSETR, 2, 0),
+       K_GATE(G_TIM3,          RCC_APB1ENSETR, 1, 0),
+       K_GATE(G_TIM2,          RCC_APB1ENSETR, 0, 0),
+
+       K_MGATE(G_FDCAN,        RCC_APB2ENSETR, 24, 0),
+       K_GATE(G_ADFSDM,        RCC_APB2ENSETR, 21, 0),
+       K_GATE(G_DFSDM,         RCC_APB2ENSETR, 20, 0),
+       K_MGATE(G_SAI3,         RCC_APB2ENSETR, 18, 0),
+       K_MGATE(G_SAI2,         RCC_APB2ENSETR, 17, 0),
+       K_MGATE(G_SAI1,         RCC_APB2ENSETR, 16, 0),
+       K_MGATE(G_USART6,       RCC_APB2ENSETR, 13, 0),
+       K_MGATE(G_SPI5,         RCC_APB2ENSETR, 10, 0),
+       K_MGATE(G_SPI4,         RCC_APB2ENSETR, 9, 0),
+       K_MGATE(G_SPI1,         RCC_APB2ENSETR, 8, 0),
+       K_GATE(G_TIM17,         RCC_APB2ENSETR, 4, 0),
+       K_GATE(G_TIM16,         RCC_APB2ENSETR, 3, 0),
+       K_GATE(G_TIM15,         RCC_APB2ENSETR, 2, 0),
+       K_GATE(G_TIM8,          RCC_APB2ENSETR, 1, 0),
+       K_GATE(G_TIM1,          RCC_APB2ENSETR, 0, 0),
+
+       K_GATE(G_HDP,           RCC_APB3ENSETR, 20, 0),
+       K_GATE(G_PMBCTRL,       RCC_APB3ENSETR, 17, 0),
+       K_GATE(G_TMPSENS,       RCC_APB3ENSETR, 16, 0),
+       K_GATE(G_VREF,          RCC_APB3ENSETR, 13, 0),
+       K_GATE(G_SYSCFG,        RCC_APB3ENSETR, 11, 0),
+       K_MGATE(G_SAI4,         RCC_APB3ENSETR, 8, 0),
+       K_MGATE(G_LPTIM5,       RCC_APB3ENSETR, 3, 0),
+       K_MGATE(G_LPTIM4,       RCC_APB3ENSETR, 2, 0),
+       K_MGATE(G_LPTIM3,       RCC_APB3ENSETR, 1, 0),
+       K_MGATE(G_LPTIM2,       RCC_APB3ENSETR, 0, 0),
+
+       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_MGATE(G_DSI,          RCC_APB4ENSETR, 4, 0),
+       K_MGATE(G_LTDC,         RCC_APB4ENSETR, 0, 0),
+
+       K_GATE(G_STGEN,         RCC_APB5ENSETR, 20, 0),
+       K_GATE(G_BSEC,          RCC_APB5ENSETR, 16, 0),
+       K_GATE(G_IWDG1,         RCC_APB5ENSETR, 15, 0),
+       K_GATE(G_TZPC,          RCC_APB5ENSETR, 13, 0),
+       K_GATE(G_TZC,           RCC_APB5ENSETR, 12, 0),
+       K_GATE(G_RTCAPB,        RCC_APB5ENSETR, 8, 0),
+       K_MGATE(G_USART1,       RCC_APB5ENSETR, 4, 0),
+       K_MGATE(G_I2C6,         RCC_APB5ENSETR, 3, 0),
+       K_MGATE(G_I2C4,         RCC_APB5ENSETR, 2, 0),
+       K_MGATE(G_SPI6,         RCC_APB5ENSETR, 0, 0),
+
+       K_MGATE(G_SDMMC3,       RCC_AHB2ENSETR, 16, 0),
+       K_MGATE(G_USBO,         RCC_AHB2ENSETR, 8, 0),
+       K_MGATE(G_ADC12,        RCC_AHB2ENSETR, 5, 0),
+       K_GATE(G_DMAMUX,        RCC_AHB2ENSETR, 2, 0),
+       K_GATE(G_DMA2,          RCC_AHB2ENSETR, 1, 0),
+       K_GATE(G_DMA1,          RCC_AHB2ENSETR, 0, 0),
+
+       K_GATE(G_IPCC,          RCC_AHB3ENSETR, 12, 0),
+       K_GATE(G_HSEM,          RCC_AHB3ENSETR, 11, 0),
+       K_GATE(G_CRC2,          RCC_AHB3ENSETR, 7, 0),
+       K_MGATE(G_RNG2,         RCC_AHB3ENSETR, 6, 0),
+       K_GATE(G_HASH2,         RCC_AHB3ENSETR, 5, 0),
+       K_GATE(G_CRYP2,         RCC_AHB3ENSETR, 4, 0),
+       K_GATE(G_DCMI,          RCC_AHB3ENSETR, 0, 0),
+
+       K_GATE(G_GPIOK,         RCC_AHB4ENSETR, 10, 0),
+       K_GATE(G_GPIOJ,         RCC_AHB4ENSETR, 9, 0),
+       K_GATE(G_GPIOI,         RCC_AHB4ENSETR, 8, 0),
+       K_GATE(G_GPIOH,         RCC_AHB4ENSETR, 7, 0),
+       K_GATE(G_GPIOG,         RCC_AHB4ENSETR, 6, 0),
+       K_GATE(G_GPIOF,         RCC_AHB4ENSETR, 5, 0),
+       K_GATE(G_GPIOE,         RCC_AHB4ENSETR, 4, 0),
+       K_GATE(G_GPIOD,         RCC_AHB4ENSETR, 3, 0),
+       K_GATE(G_GPIOC,         RCC_AHB4ENSETR, 2, 0),
+       K_GATE(G_GPIOB,         RCC_AHB4ENSETR, 1, 0),
+       K_GATE(G_GPIOA,         RCC_AHB4ENSETR, 0, 0),
+
+       K_GATE(G_BKPSRAM,       RCC_AHB5ENSETR, 8, 0),
+       K_MGATE(G_RNG1,         RCC_AHB5ENSETR, 6, 0),
+       K_GATE(G_HASH1,         RCC_AHB5ENSETR, 5, 0),
+       K_GATE(G_CRYP1,         RCC_AHB5ENSETR, 4, 0),
+       K_GATE(G_GPIOZ,         RCC_AHB5ENSETR, 0, 0),
+
+       K_GATE(G_USBH,          RCC_AHB6ENSETR, 24, 0),
+       K_GATE(G_CRC1,          RCC_AHB6ENSETR, 20, 0),
+       K_MGATE(G_SDMMC2,       RCC_AHB6ENSETR, 17, 0),
+       K_MGATE(G_SDMMC1,       RCC_AHB6ENSETR, 16, 0),
+       K_MGATE(G_QSPI,         RCC_AHB6ENSETR, 14, 0),
+       K_MGATE(G_FMC,          RCC_AHB6ENSETR, 12, 0),
+       K_GATE(G_ETHMAC,        RCC_AHB6ENSETR, 10, 0),
+       K_GATE(G_ETHRX,         RCC_AHB6ENSETR, 9, 0),
+       K_GATE(G_ETHTX,         RCC_AHB6ENSETR, 8, 0),
+       K_GATE(G_ETHCK,         RCC_AHB6ENSETR, 7, 0),
+       K_MGATE(G_GPU,          RCC_AHB6ENSETR, 5, 0),
+       K_GATE(G_MDMA,          RCC_AHB6ENSETR, 0, 0),
+       K_GATE(G_ETHSTP,        RCC_AHB6LPENSETR, 11, 0),
+};
+
+enum {
+       M_SDMMC12,
+       M_SDMMC3,
+       M_FMC,
+       M_QSPI,
+       M_RNG1,
+       M_RNG2,
+       M_USBPHY,
+       M_USBO,
+       M_STGEN,
+       M_SPDIF,
+       M_SPI1,
+       M_SPI23,
+       M_SPI45,
+       M_SPI6,
+       M_CEC,
+       M_I2C12,
+       M_I2C35,
+       M_I2C46,
+       M_LPTIM1,
+       M_LPTIM23,
+       M_LPTIM45,
+       M_USART1,
+       M_UART24,
+       M_UART35,
+       M_USART6,
+       M_UART78,
+       M_SAI1,
+       M_SAI2,
+       M_SAI3,
+       M_SAI4,
+       M_DSI,
+       M_FDCAN,
+       M_ADC12,
+       M_ETHCK,
+       M_CKPER,
+       M_LAST
+};
+
+struct stm32_mmux ker_mux[M_LAST];
+
+#define _K_MUX(_id, _offset, _shift, _width, _mux_flags, _mmux, _ops)\
+       [_id] = {\
+               &(struct mux_cfg) {\
+                       .reg_off        = _offset,\
+                       .shift          = _shift,\
+                       .width          = _width,\
+                       .mux_flags      = _mux_flags,\
+                       .table          = NULL,\
+               },\
+               .mmux           = _mmux,\
+               .ops            = _ops,\
+       }
+
+#define K_MUX(_id, _offset, _shift, _width, _mux_flags)\
+       _K_MUX(_id, _offset, _shift, _width, _mux_flags,\
+                       NULL, NULL)
+
+#define K_MMUX(_id, _offset, _shift, _width, _mux_flags)\
+       _K_MUX(_id, _offset, _shift, _width, _mux_flags,\
+                       &ker_mux[_id], &clk_mmux_ops)
+
+const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = {
+       /* Kernel multi mux */
+       K_MMUX(M_SDMMC12, RCC_SDMMC12CKSELR, 0, 3, 0),
+       K_MMUX(M_SPI23, RCC_SPI2S23CKSELR, 0, 3, 0),
+       K_MMUX(M_SPI45, RCC_SPI2S45CKSELR, 0, 3, 0),
+       K_MMUX(M_I2C12, RCC_I2C12CKSELR, 0, 3, 0),
+       K_MMUX(M_I2C35, RCC_I2C35CKSELR, 0, 3, 0),
+       K_MMUX(M_LPTIM23, RCC_LPTIM23CKSELR, 0, 3, 0),
+       K_MMUX(M_LPTIM45, RCC_LPTIM45CKSELR, 0, 3, 0),
+       K_MMUX(M_UART24, RCC_UART24CKSELR, 0, 3, 0),
+       K_MMUX(M_UART35, RCC_UART35CKSELR, 0, 3, 0),
+       K_MMUX(M_UART78, RCC_UART78CKSELR, 0, 3, 0),
+       K_MMUX(M_SAI1, RCC_SAI1CKSELR, 0, 3, 0),
+       K_MMUX(M_ETHCK, RCC_ETHCKSELR, 0, 2, 0),
+       K_MMUX(M_I2C46, RCC_I2C46CKSELR, 0, 3, 0),
+
+       /*  Kernel simple mux */
+       K_MUX(M_RNG2, RCC_RNG2CKSELR, 0, 2, 0),
+       K_MUX(M_SDMMC3, RCC_SDMMC3CKSELR, 0, 3, 0),
+       K_MUX(M_FMC, RCC_FMCCKSELR, 0, 2, 0),
+       K_MUX(M_QSPI, RCC_QSPICKSELR, 0, 2, 0),
+       K_MUX(M_USBPHY, RCC_USBCKSELR, 0, 2, 0),
+       K_MUX(M_USBO, RCC_USBCKSELR, 4, 1, 0),
+       K_MUX(M_SPDIF, RCC_SPDIFCKSELR, 0, 2, 0),
+       K_MUX(M_SPI1, RCC_SPI2S1CKSELR, 0, 3, 0),
+       K_MUX(M_CEC, RCC_CECCKSELR, 0, 2, 0),
+       K_MUX(M_LPTIM1, RCC_LPTIM1CKSELR, 0, 3, 0),
+       K_MUX(M_USART6, RCC_UART6CKSELR, 0, 3, 0),
+       K_MUX(M_FDCAN, RCC_FDCANCKSELR, 0, 2, 0),
+       K_MUX(M_SAI2, RCC_SAI2CKSELR, 0, 3, 0),
+       K_MUX(M_SAI3, RCC_SAI3CKSELR, 0, 3, 0),
+       K_MUX(M_SAI4, RCC_SAI4CKSELR, 0, 3, 0),
+       K_MUX(M_ADC12, RCC_ADCCKSELR, 0, 2, 0),
+       K_MUX(M_DSI, RCC_DSICKSELR, 0, 1, 0),
+       K_MUX(M_CKPER, RCC_CPERCKSELR, 0, 2, 0),
+       K_MUX(M_RNG1, RCC_RNG1CKSELR, 0, 2, 0),
+       K_MUX(M_STGEN, RCC_STGENCKSELR, 0, 2, 0),
+       K_MUX(M_USART1, RCC_UART1CKSELR, 0, 3, 0),
+       K_MUX(M_SPI6, RCC_SPI6CKSELR, 0, 3, 0),
+};
+
+static const struct clock_config stm32mp1_clock_cfg[] = {
+       /* Oscillator divider */
+       DIV(NO_ID, "clk-hsi-div", "clk-hsi", 0, RCC_HSICFGR, 0, 2,
+           CLK_DIVIDER_READ_ONLY),
+
+       /*  External / Internal Oscillators */
+       GATE_MP1(CK_HSE, "ck_hse", "clk-hse", 0, RCC_OCENSETR, 8, 0),
+       GATE_MP1(CK_CSI, "ck_csi", "clk-csi", 0, RCC_OCENSETR, 4, 0),
+       GATE_MP1(CK_HSI, "ck_hsi", "clk-hsi-div", 0, RCC_OCENSETR, 0, 0),
+       GATE(CK_LSI, "ck_lsi", "clk-lsi", 0, RCC_RDLSICR, 0, 0),
+       GATE(CK_LSE, "ck_lse", "clk-lse", 0, RCC_BDCR, 0, 0),
+
+       FIXED_FACTOR(CK_HSE_DIV2, "clk-hse-div2", "ck_hse", 0, 1, 2),
+
+       /* ref clock pll */
+       MUX(NO_ID, "ref1", ref12_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK12SELR,
+           0, 2, CLK_MUX_READ_ONLY),
+
+       MUX(NO_ID, "ref3", ref3_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK3SELR,
+           0, 2, CLK_MUX_READ_ONLY),
+
+       MUX(NO_ID, "ref4", ref4_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK4SELR,
+           0, 2, CLK_MUX_READ_ONLY),
+
+       /* PLLs */
+       PLL(PLL1, "pll1", "ref1", CLK_IGNORE_UNUSED, RCC_PLL1CR),
+       PLL(PLL2, "pll2", "ref1", CLK_IGNORE_UNUSED, RCC_PLL2CR),
+       PLL(PLL3, "pll3", "ref3", CLK_IGNORE_UNUSED, RCC_PLL3CR),
+       PLL(PLL4, "pll4", "ref4", CLK_IGNORE_UNUSED, RCC_PLL4CR),
+
+       /* ODF */
+       COMPOSITE(PLL1_P, "pll1_p", PARENT("pll1"), 0,
+                 _GATE(RCC_PLL1CR, 4, 0),
+                 _NO_MUX,
+                 _DIV(RCC_PLL1CFGR2, 0, 7, 0, NULL)),
+
+       COMPOSITE(PLL2_P, "pll2_p", PARENT("pll2"), 0,
+                 _GATE(RCC_PLL2CR, 4, 0),
+                 _NO_MUX,
+                 _DIV(RCC_PLL2CFGR2, 0, 7, 0, NULL)),
+
+       COMPOSITE(PLL2_Q, "pll2_q", PARENT("pll2"), 0,
+                 _GATE(RCC_PLL2CR, 5, 0),
+                 _NO_MUX,
+                 _DIV(RCC_PLL2CFGR2, 8, 7, 0, NULL)),
+
+       COMPOSITE(PLL2_R, "pll2_r", PARENT("pll2"), CLK_IS_CRITICAL,
+                 _GATE(RCC_PLL2CR, 6, 0),
+                 _NO_MUX,
+                 _DIV(RCC_PLL2CFGR2, 16, 7, 0, NULL)),
+
+       COMPOSITE(PLL3_P, "pll3_p", PARENT("pll3"), 0,
+                 _GATE(RCC_PLL3CR, 4, 0),
+                 _NO_MUX,
+                 _DIV(RCC_PLL3CFGR2, 0, 7, 0, NULL)),
+
+       COMPOSITE(PLL3_Q, "pll3_q", PARENT("pll3"), 0,
+                 _GATE(RCC_PLL3CR, 5, 0),
+                 _NO_MUX,
+                 _DIV(RCC_PLL3CFGR2, 8, 7, 0, NULL)),
+
+       COMPOSITE(PLL3_R, "pll3_r", PARENT("pll3"), 0,
+                 _GATE(RCC_PLL3CR, 6, 0),
+                 _NO_MUX,
+                 _DIV(RCC_PLL3CFGR2, 16, 7, 0, NULL)),
+
+       COMPOSITE(PLL4_P, "pll4_p", PARENT("pll4"), 0,
+                 _GATE(RCC_PLL4CR, 4, 0),
+                 _NO_MUX,
+                 _DIV(RCC_PLL4CFGR2, 0, 7, 0, NULL)),
+
+       COMPOSITE(PLL4_Q, "pll4_q", PARENT("pll4"), 0,
+                 _GATE(RCC_PLL4CR, 5, 0),
+                 _NO_MUX,
+                 _DIV(RCC_PLL4CFGR2, 8, 7, 0, NULL)),
+
+       COMPOSITE(PLL4_R, "pll4_r", PARENT("pll4"), 0,
+                 _GATE(RCC_PLL4CR, 6, 0),
+                 _NO_MUX,
+                 _DIV(RCC_PLL4CFGR2, 16, 7, 0, NULL)),
+
+       /* MUX system clocks */
+       MUX(CK_PER, "ck_per", per_src, CLK_OPS_PARENT_ENABLE,
+           RCC_CPERCKSELR, 0, 2, 0),
+
+       MUX(CK_MPU, "ck_mpu", cpu_src, CLK_OPS_PARENT_ENABLE |
+            CLK_IS_CRITICAL, RCC_MPCKSELR, 0, 2, 0),
+
+       COMPOSITE(CK_AXI, "ck_axi", axi_src, CLK_IS_CRITICAL |
+                  CLK_OPS_PARENT_ENABLE,
+                  _NO_GATE,
+                  _MUX(RCC_ASSCKSELR, 0, 2, 0),
+                  _DIV(RCC_AXIDIVR, 0, 3, 0, axi_div_table)),
+
+       COMPOSITE(CK_MCU, "ck_mcu", mcu_src, CLK_IS_CRITICAL |
+                  CLK_OPS_PARENT_ENABLE,
+                  _NO_GATE,
+                  _MUX(RCC_MSSCKSELR, 0, 2, 0),
+                  _DIV(RCC_MCUDIVR, 0, 4, 0, mcu_div_table)),
+
+       DIV_TABLE(NO_ID, "pclk1", "ck_mcu", CLK_IGNORE_UNUSED, RCC_APB1DIVR, 0,
+                 3, CLK_DIVIDER_READ_ONLY, apb_div_table),
+
+       DIV_TABLE(NO_ID, "pclk2", "ck_mcu", CLK_IGNORE_UNUSED, RCC_APB2DIVR, 0,
+                 3, CLK_DIVIDER_READ_ONLY, apb_div_table),
+
+       DIV_TABLE(NO_ID, "pclk3", "ck_mcu", CLK_IGNORE_UNUSED, RCC_APB3DIVR, 0,
+                 3, CLK_DIVIDER_READ_ONLY, apb_div_table),
+
+       DIV_TABLE(NO_ID, "pclk4", "ck_axi", CLK_IGNORE_UNUSED, RCC_APB4DIVR, 0,
+                 3, CLK_DIVIDER_READ_ONLY, apb_div_table),
+
+       DIV_TABLE(NO_ID, "pclk5", "ck_axi", CLK_IGNORE_UNUSED, RCC_APB5DIVR, 0,
+                 3, CLK_DIVIDER_READ_ONLY, apb_div_table),
+
+       /* Kernel Timers */
+       STM32_CKTIM("ck1_tim", "pclk1", 0, RCC_APB1DIVR, RCC_TIMG1PRER),
+       STM32_CKTIM("ck2_tim", "pclk2", 0, RCC_APB2DIVR, RCC_TIMG2PRER),
+
+       STM32_TIM(TIM2_K, "tim2_k", "ck1_tim", RCC_APB1ENSETR, 0),
+       STM32_TIM(TIM3_K, "tim3_k", "ck1_tim", RCC_APB1ENSETR, 1),
+       STM32_TIM(TIM4_K, "tim4_k", "ck1_tim", RCC_APB1ENSETR, 2),
+       STM32_TIM(TIM5_K, "tim5_k", "ck1_tim", RCC_APB1ENSETR, 3),
+       STM32_TIM(TIM6_K, "tim6_k", "ck1_tim", RCC_APB1ENSETR, 4),
+       STM32_TIM(TIM7_K, "tim7_k", "ck1_tim", RCC_APB1ENSETR, 5),
+       STM32_TIM(TIM12_K, "tim12_k", "ck1_tim", RCC_APB1ENSETR, 6),
+       STM32_TIM(TIM13_K, "tim13_k", "ck1_tim", RCC_APB1ENSETR, 7),
+       STM32_TIM(TIM14_K, "tim14_k", "ck1_tim", RCC_APB1ENSETR, 8),
+       STM32_TIM(TIM1_K, "tim1_k", "ck2_tim", RCC_APB2ENSETR, 0),
+       STM32_TIM(TIM8_K, "tim8_k", "ck2_tim", RCC_APB2ENSETR, 1),
+       STM32_TIM(TIM15_K, "tim15_k", "ck2_tim", RCC_APB2ENSETR, 2),
+       STM32_TIM(TIM16_K, "tim16_k", "ck2_tim", RCC_APB2ENSETR, 3),
+       STM32_TIM(TIM17_K, "tim17_k", "ck2_tim", RCC_APB2ENSETR, 4),
+
+       /* Peripheral clocks */
+       PCLK(TIM2, "tim2", "pclk1", CLK_IGNORE_UNUSED, G_TIM2),
+       PCLK(TIM3, "tim3", "pclk1", CLK_IGNORE_UNUSED, G_TIM3),
+       PCLK(TIM4, "tim4", "pclk1", CLK_IGNORE_UNUSED, G_TIM4),
+       PCLK(TIM5, "tim5", "pclk1", CLK_IGNORE_UNUSED, G_TIM5),
+       PCLK(TIM6, "tim6", "pclk1", CLK_IGNORE_UNUSED, G_TIM6),
+       PCLK(TIM7, "tim7", "pclk1", CLK_IGNORE_UNUSED, G_TIM7),
+       PCLK(TIM12, "tim12", "pclk1", CLK_IGNORE_UNUSED, G_TIM12),
+       PCLK(TIM13, "tim13", "pclk1", CLK_IGNORE_UNUSED, G_TIM13),
+       PCLK(TIM14, "tim14", "pclk1", CLK_IGNORE_UNUSED, G_TIM14),
+       PCLK(LPTIM1, "lptim1", "pclk1", 0, G_LPTIM1),
+       PCLK(SPI2, "spi2", "pclk1", 0, G_SPI2),
+       PCLK(SPI3, "spi3", "pclk1", 0, G_SPI3),
+       PCLK(USART2, "usart2", "pclk1", 0, G_USART2),
+       PCLK(USART3, "usart3", "pclk1", 0, G_USART3),
+       PCLK(UART4, "uart4", "pclk1", 0, G_UART4),
+       PCLK(UART5, "uart5", "pclk1", 0, G_UART5),
+       PCLK(UART7, "uart7", "pclk1", 0, G_UART7),
+       PCLK(UART8, "uart8", "pclk1", 0, G_UART8),
+       PCLK(I2C1, "i2c1", "pclk1", 0, G_I2C1),
+       PCLK(I2C2, "i2c2", "pclk1", 0, G_I2C2),
+       PCLK(I2C3, "i2c3", "pclk1", 0, G_I2C3),
+       PCLK(I2C5, "i2c5", "pclk1", 0, G_I2C5),
+       PCLK(SPDIF, "spdif", "pclk1", 0, G_SPDIF),
+       PCLK(CEC, "cec", "pclk1", 0, G_CEC),
+       PCLK(DAC12, "dac12", "pclk1", 0, G_DAC12),
+       PCLK(MDIO, "mdio", "pclk1", 0, G_MDIO),
+       PCLK(TIM1, "tim1", "pclk2", CLK_IGNORE_UNUSED, G_TIM1),
+       PCLK(TIM8, "tim8", "pclk2", CLK_IGNORE_UNUSED, G_TIM8),
+       PCLK(TIM15, "tim15", "pclk2", CLK_IGNORE_UNUSED, G_TIM15),
+       PCLK(TIM16, "tim16", "pclk2", CLK_IGNORE_UNUSED, G_TIM16),
+       PCLK(TIM17, "tim17", "pclk2", CLK_IGNORE_UNUSED, G_TIM17),
+       PCLK(SPI1, "spi1", "pclk2", 0, G_SPI1),
+       PCLK(SPI4, "spi4", "pclk2", 0, G_SPI4),
+       PCLK(SPI5, "spi5", "pclk2", 0, G_SPI5),
+       PCLK(USART6, "usart6", "pclk2", 0, G_USART6),
+       PCLK(SAI1, "sai1", "pclk2", 0, G_SAI1),
+       PCLK(SAI2, "sai2", "pclk2", 0, G_SAI2),
+       PCLK(SAI3, "sai3", "pclk2", 0, G_SAI3),
+       PCLK(DFSDM, "dfsdm", "pclk2", 0, G_DFSDM),
+       PCLK(FDCAN, "fdcan", "pclk2", 0, G_FDCAN),
+       PCLK(LPTIM2, "lptim2", "pclk3", 0, G_LPTIM2),
+       PCLK(LPTIM3, "lptim3", "pclk3", 0, G_LPTIM3),
+       PCLK(LPTIM4, "lptim4", "pclk3", 0, G_LPTIM4),
+       PCLK(LPTIM5, "lptim5", "pclk3", 0, G_LPTIM5),
+       PCLK(SAI4, "sai4", "pclk3", 0, G_SAI4),
+       PCLK(SYSCFG, "syscfg", "pclk3", 0, G_SYSCFG),
+       PCLK(VREF, "vref", "pclk3", 13, G_VREF),
+       PCLK(TMPSENS, "tmpsens", "pclk3", 0, G_TMPSENS),
+       PCLK(PMBCTRL, "pmbctrl", "pclk3", 0, G_PMBCTRL),
+       PCLK(HDP, "hdp", "pclk3", 0, G_HDP),
+       PCLK(LTDC, "ltdc", "pclk4", 0, G_LTDC),
+       PCLK(DSI, "dsi", "pclk4", 0, G_DSI),
+       PCLK(IWDG2, "iwdg2", "pclk4", 0, G_IWDG2),
+       PCLK(USBPHY, "usbphy", "pclk4", 0, G_USBPHY),
+       PCLK(STGENRO, "stgenro", "pclk4", 0, G_STGENRO),
+       PCLK(SPI6, "spi6", "pclk5", 0, G_SPI6),
+       PCLK(I2C4, "i2c4", "pclk5", 0, G_I2C4),
+       PCLK(I2C6, "i2c6", "pclk5", 0, G_I2C6),
+       PCLK(USART1, "usart1", "pclk5", 0, G_USART1),
+       PCLK(RTCAPB, "rtcapb", "pclk5", CLK_IGNORE_UNUSED |
+            CLK_IS_CRITICAL, G_RTCAPB),
+       PCLK(TZC, "tzc", "pclk5", CLK_IGNORE_UNUSED, G_TZC),
+       PCLK(TZPC, "tzpc", "pclk5", CLK_IGNORE_UNUSED, G_TZPC),
+       PCLK(IWDG1, "iwdg1", "pclk5", 0, G_IWDG1),
+       PCLK(BSEC, "bsec", "pclk5", CLK_IGNORE_UNUSED, G_BSEC),
+       PCLK(STGEN, "stgen", "pclk5", CLK_IGNORE_UNUSED, G_STGEN),
+       PCLK(DMA1, "dma1", "ck_mcu", 0, G_DMA1),
+       PCLK(DMA2, "dma2", "ck_mcu",  0, G_DMA2),
+       PCLK(DMAMUX, "dmamux", "ck_mcu", 0, G_DMAMUX),
+       PCLK(ADC12, "adc12", "ck_mcu", 0, G_ADC12),
+       PCLK(USBO, "usbo", "ck_mcu", 0, G_USBO),
+       PCLK(SDMMC3, "sdmmc3", "ck_mcu", 0, G_SDMMC3),
+       PCLK(DCMI, "dcmi", "ck_mcu", 0, G_DCMI),
+       PCLK(CRYP2, "cryp2", "ck_mcu", 0, G_CRYP2),
+       PCLK(HASH2, "hash2", "ck_mcu", 0, G_HASH2),
+       PCLK(RNG2, "rng2", "ck_mcu", 0, G_RNG2),
+       PCLK(CRC2, "crc2", "ck_mcu", 0, G_CRC2),
+       PCLK(HSEM, "hsem", "ck_mcu", 0, G_HSEM),
+       PCLK(IPCC, "ipcc", "ck_mcu", 0, G_IPCC),
+       PCLK(GPIOA, "gpioa", "ck_mcu", 0, G_GPIOA),
+       PCLK(GPIOB, "gpiob", "ck_mcu", 0, G_GPIOB),
+       PCLK(GPIOC, "gpioc", "ck_mcu", 0, G_GPIOC),
+       PCLK(GPIOD, "gpiod", "ck_mcu", 0, G_GPIOD),
+       PCLK(GPIOE, "gpioe", "ck_mcu", 0, G_GPIOE),
+       PCLK(GPIOF, "gpiof", "ck_mcu", 0, G_GPIOF),
+       PCLK(GPIOG, "gpiog", "ck_mcu", 0, G_GPIOG),
+       PCLK(GPIOH, "gpioh", "ck_mcu", 0, G_GPIOH),
+       PCLK(GPIOI, "gpioi", "ck_mcu", 0, G_GPIOI),
+       PCLK(GPIOJ, "gpioj", "ck_mcu", 0, G_GPIOJ),
+       PCLK(GPIOK, "gpiok", "ck_mcu", 0, G_GPIOK),
+       PCLK(GPIOZ, "gpioz", "ck_axi", CLK_IGNORE_UNUSED, G_GPIOZ),
+       PCLK(CRYP1, "cryp1", "ck_axi", CLK_IGNORE_UNUSED, G_CRYP1),
+       PCLK(HASH1, "hash1", "ck_axi", CLK_IGNORE_UNUSED, G_HASH1),
+       PCLK(RNG1, "rng1", "ck_axi", 0, G_RNG1),
+       PCLK(BKPSRAM, "bkpsram", "ck_axi", CLK_IGNORE_UNUSED, G_BKPSRAM),
+       PCLK(MDMA, "mdma", "ck_axi", 0, G_MDMA),
+       PCLK(GPU, "gpu", "ck_axi", 0, G_GPU),
+       PCLK(ETHTX, "ethtx", "ck_axi", 0, G_ETHTX),
+       PCLK(ETHRX, "ethrx", "ck_axi", 0, G_ETHRX),
+       PCLK(ETHMAC, "ethmac", "ck_axi", 0, G_ETHMAC),
+       PCLK(FMC, "fmc", "ck_axi", CLK_IGNORE_UNUSED, G_FMC),
+       PCLK(QSPI, "qspi", "ck_axi", CLK_IGNORE_UNUSED, G_QSPI),
+       PCLK(SDMMC1, "sdmmc1", "ck_axi", 0, G_SDMMC1),
+       PCLK(SDMMC2, "sdmmc2", "ck_axi", 0, G_SDMMC2),
+       PCLK(CRC1, "crc1", "ck_axi", 0, G_CRC1),
+       PCLK(USBH, "usbh", "ck_axi", 0, G_USBH),
+       PCLK(ETHSTP, "ethstp", "ck_axi", 0, G_ETHSTP),
+
+       /* Kernel clocks */
+       KCLK(SDMMC1_K, "sdmmc1_k", sdmmc12_src, 0, G_SDMMC1, M_SDMMC12),
+       KCLK(SDMMC2_K, "sdmmc2_k", sdmmc12_src, 0, G_SDMMC2, M_SDMMC12),
+       KCLK(SDMMC3_K, "sdmmc3_k", sdmmc3_src, 0, G_SDMMC3, M_SDMMC3),
+       KCLK(FMC_K, "fmc_k", fmc_src, 0, G_FMC, M_FMC),
+       KCLK(QSPI_K, "qspi_k", qspi_src, 0, G_QSPI, M_QSPI),
+       KCLK(RNG1_K, "rng1_k", rng_src, 0, G_RNG1, M_RNG1),
+       KCLK(RNG2_K, "rng2_k", rng_src, 0, G_RNG2, M_RNG2),
+       KCLK(USBPHY_K, "usbphy_k", usbphy_src, 0, G_USBPHY, M_USBPHY),
+       KCLK(STGEN_K, "stgen_k",  stgen_src, CLK_IGNORE_UNUSED,
+            G_STGEN, M_STGEN),
+       KCLK(SPDIF_K, "spdif_k", spdif_src, 0, G_SPDIF, M_SPDIF),
+       KCLK(SPI1_K, "spi1_k", spi123_src, 0, G_SPI1, M_SPI1),
+       KCLK(SPI2_K, "spi2_k", spi123_src, 0, G_SPI2, M_SPI23),
+       KCLK(SPI3_K, "spi3_k", spi123_src, 0, G_SPI3, M_SPI23),
+       KCLK(SPI4_K, "spi4_k", spi45_src, 0, G_SPI4, M_SPI45),
+       KCLK(SPI5_K, "spi5_k", spi45_src, 0, G_SPI5, M_SPI45),
+       KCLK(SPI6_K, "spi6_k", spi6_src, 0, G_SPI6, M_SPI6),
+       KCLK(CEC_K, "cec_k", cec_src, 0, G_CEC, M_CEC),
+       KCLK(I2C1_K, "i2c1_k", i2c12_src, 0, G_I2C1, M_I2C12),
+       KCLK(I2C2_K, "i2c2_k", i2c12_src, 0, G_I2C2, M_I2C12),
+       KCLK(I2C3_K, "i2c3_k", i2c35_src, 0, G_I2C3, M_I2C35),
+       KCLK(I2C5_K, "i2c5_k", i2c35_src, 0, G_I2C5, M_I2C35),
+       KCLK(I2C4_K, "i2c4_k", i2c46_src, 0, G_I2C4, M_I2C46),
+       KCLK(I2C6_K, "i2c6_k", i2c46_src, 0, G_I2C6, M_I2C46),
+       KCLK(LPTIM1_K, "lptim1_k", lptim1_src, 0, G_LPTIM1, M_LPTIM1),
+       KCLK(LPTIM2_K, "lptim2_k", lptim23_src, 0, G_LPTIM2, M_LPTIM23),
+       KCLK(LPTIM3_K, "lptim3_k", lptim23_src, 0, G_LPTIM3, M_LPTIM23),
+       KCLK(LPTIM4_K, "lptim4_k", lptim45_src, 0, G_LPTIM4, M_LPTIM45),
+       KCLK(LPTIM5_K, "lptim5_k", lptim45_src, 0, G_LPTIM5, M_LPTIM45),
+       KCLK(USART1_K, "usart1_k", usart1_src, 0, G_USART1, M_USART1),
+       KCLK(USART2_K, "usart2_k", usart234578_src, 0, G_USART2, M_UART24),
+       KCLK(USART3_K, "usart3_k", usart234578_src, 0, G_USART3, M_UART35),
+       KCLK(UART4_K, "uart4_k", usart234578_src, 0, G_UART4, M_UART24),
+       KCLK(UART5_K, "uart5_k", usart234578_src, 0, G_UART5, M_UART35),
+       KCLK(USART6_K, "uart6_k", usart6_src, 0, G_USART6, M_USART6),
+       KCLK(UART7_K, "uart7_k", usart234578_src, 0, G_UART7, M_UART78),
+       KCLK(UART8_K, "uart8_k", usart234578_src, 0, G_UART8, M_UART78),
+       KCLK(FDCAN_K, "fdcan_k", fdcan_src, 0, G_FDCAN, M_FDCAN),
+       KCLK(SAI1_K, "sai1_k", sai_src, 0, G_SAI1, M_SAI1),
+       KCLK(SAI2_K, "sai2_k", sai2_src, 0, G_SAI2, M_SAI2),
+       KCLK(SAI3_K, "sai3_k", sai_src, 0, G_SAI2, M_SAI3),
+       KCLK(SAI4_K, "sai4_k", sai_src, 0, G_SAI2, M_SAI4),
+       KCLK(ADC12_K, "adc12_k", adc12_src, 0, G_ADC12, M_ADC12),
+       KCLK(DSI_K, "dsi_k", dsi_src, 0, G_DSI, M_DSI),
+       KCLK(ADFSDM_K, "adfsdm_k", sai_src, 0, G_ADFSDM, M_SAI1),
+       KCLK(USBO_K, "usbo_k", usbo_src, 0, G_USBO, M_USBO),
+       KCLK(ETHCK_K, "ethck_k", eth_src, 0, G_ETHCK, M_ETHCK),
+
+       /* Particulary Kernel Clocks (no mux or no gate) */
+       MGATE_MP1(DFSDM_K, "dfsdm_k", "ck_mcu", 0, G_DFSDM),
+       MGATE_MP1(DSI_PX, "dsi_px", "pll4_q", CLK_SET_RATE_PARENT, G_DSI),
+       MGATE_MP1(LTDC_PX, "ltdc_px", "pll4_q", CLK_SET_RATE_PARENT, G_LTDC),
+       MGATE_MP1(GPU_K, "gpu_k", "pll2_q", 0, G_GPU),
+       MGATE_MP1(DAC12_K, "dac12_k", "ck_lsi", 0, G_DAC12),
+
+       COMPOSITE(ETHPTP_K, "ethptp_k", eth_src, CLK_OPS_PARENT_ENABLE,
+                 _NO_GATE,
+                 _MMUX(M_ETHCK),
+                 _DIV(RCC_ETHCKSELR, 4, 4, CLK_DIVIDER_ALLOW_ZERO, NULL)),
+
+       /* RTC clock */
+       DIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 7,
+           CLK_DIVIDER_ALLOW_ZERO),
+
+       COMPOSITE(RTC, "ck_rtc", rtc_src, CLK_OPS_PARENT_ENABLE |
+                  CLK_SET_RATE_PARENT,
+                 _GATE(RCC_BDCR, 20, 0),
+                 _MUX(RCC_BDCR, 16, 2, 0),
+                 _NO_DIV),
+
+       /* MCO clocks */
+       COMPOSITE(CK_MCO1, "ck_mco1", mco1_src, CLK_OPS_PARENT_ENABLE |
+                 CLK_SET_RATE_NO_REPARENT,
+                 _GATE(RCC_MCO1CFGR, 12, 0),
+                 _MUX(RCC_MCO1CFGR, 0, 3, 0),
+                 _DIV(RCC_MCO1CFGR, 4, 4, 0, NULL)),
+
+       COMPOSITE(CK_MCO2, "ck_mco2", mco2_src, CLK_OPS_PARENT_ENABLE |
+                 CLK_SET_RATE_NO_REPARENT,
+                 _GATE(RCC_MCO2CFGR, 12, 0),
+                 _MUX(RCC_MCO2CFGR, 0, 3, 0),
+                 _DIV(RCC_MCO2CFGR, 4, 4, 0, NULL)),
+
+       /* Debug clocks */
+       FIXED_FACTOR(NO_ID, "ck_axi_div2", "ck_axi", 0, 1, 2),
+
+       GATE(DBG, "ck_apb_dbg", "ck_axi_div2", 0, RCC_DBGCFGR, 8, 0),
+
+       GATE(CK_DBG, "ck_sys_dbg", "ck_axi", 0, RCC_DBGCFGR, 8, 0),
+
+       COMPOSITE(CK_TRACE, "ck_trace", ck_trace_src, CLK_OPS_PARENT_ENABLE,
+                 _GATE(RCC_DBGCFGR, 9, 0),
+                 _NO_MUX,
+                 _DIV(RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table)),
+};
+
+struct stm32_clock_match_data {
+       const struct clock_config *cfg;
+       unsigned int num;
+       unsigned int maxbinding;
+};
+
+static struct stm32_clock_match_data stm32mp1_data = {
+       .cfg            = stm32mp1_clock_cfg,
+       .num            = ARRAY_SIZE(stm32mp1_clock_cfg),
+       .maxbinding     = STM32MP1_LAST_CLK,
+};
+
+static const struct of_device_id stm32mp1_match_data[] = {
+       {
+               .compatible = "st,stm32mp1-rcc",
+               .data = &stm32mp1_data,
+       },
+       { }
+};
+
+static int stm32_register_hw_clk(struct device *dev,
+                                struct clk_hw_onecell_data *clk_data,
+                                void __iomem *base, spinlock_t *lock,
+                                const struct clock_config *cfg)
+{
+       static struct clk_hw **hws;
+       struct clk_hw *hw = ERR_PTR(-ENOENT);
+
+       hws = clk_data->hws;
+
+       if (cfg->func)
+               hw = (*cfg->func)(dev, clk_data, base, lock, cfg);
+
+       if (IS_ERR(hw)) {
+               pr_err("Unable to register %s\n", cfg->name);
+               return  PTR_ERR(hw);
+       }
+
+       if (cfg->id != NO_ID)
+               hws[cfg->id] = hw;
+
+       return 0;
+}
+
+static int stm32_rcc_init(struct device_node *np,
+                         void __iomem *base,
+                         const struct of_device_id *match_data)
+{
+       struct clk_hw_onecell_data *clk_data;
+       struct clk_hw **hws;
+       const struct of_device_id *match;
+       const struct stm32_clock_match_data *data;
+       int err, n, max_binding;
+
+       match = of_match_node(match_data, np);
+       if (!match) {
+               pr_err("%s: match data not found\n", __func__);
+               return -ENODEV;
+       }
+
+       data = match->data;
+
+       max_binding =  data->maxbinding;
+
+       clk_data = kzalloc(sizeof(*clk_data) +
+                                 sizeof(*clk_data->hws) * max_binding,
+                                 GFP_KERNEL);
+       if (!clk_data)
+               return -ENOMEM;
+
+       clk_data->num = max_binding;
+
+       hws = clk_data->hws;
+
+       for (n = 0; n < max_binding; n++)
+               hws[n] = ERR_PTR(-ENOENT);
+
+       for (n = 0; n < data->num; n++) {
+               err = stm32_register_hw_clk(NULL, clk_data, base, &rlock,
+                                           &data->cfg[n]);
+               if (err) {
+                       pr_err("%s: can't register  %s\n", __func__,
+                              data->cfg[n].name);
+
+                       kfree(clk_data);
+
+                       return err;
+               }
+       }
+
+       return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
+}
+
+static void stm32mp1_rcc_init(struct device_node *np)
+{
+       void __iomem *base;
+
+       base = of_iomap(np, 0);
+       if (!base) {
+               pr_err("%s: unable to map resource", np->name);
+               of_node_put(np);
+               return;
+       }
+
+       if (stm32_rcc_init(np, base, stm32mp1_match_data)) {
+               iounmap(base);
+               of_node_put(np);
+       }
+}
+
+CLK_OF_DECLARE_DRIVER(stm32mp1_rcc, "st,stm32mp1-rcc", stm32mp1_rcc_init);
index 076d4244d6725228a12ed0c0daa5ee1c3b7e3c43..ea67ac81c6f97db113cef4977936776d1673ae3f 100644 (file)
@@ -2375,6 +2375,9 @@ static int clk_core_get_phase(struct clk_core *core)
        int ret;
 
        clk_prepare_lock();
+       /* Always try to update cached phase if possible */
+       if (core->ops->get_phase)
+               core->phase = core->ops->get_phase(core->hw);
        ret = core->phase;
        clk_prepare_unlock();
 
@@ -2491,19 +2494,7 @@ static int clk_summary_show(struct seq_file *s, void *data)
 
        return 0;
 }
-
-
-static int clk_summary_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, clk_summary_show, inode->i_private);
-}
-
-static const struct file_operations clk_summary_fops = {
-       .open           = clk_summary_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(clk_summary);
 
 static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
 {
@@ -2537,7 +2528,7 @@ static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
        seq_putc(s, '}');
 }
 
-static int clk_dump(struct seq_file *s, void *data)
+static int clk_dump_show(struct seq_file *s, void *data)
 {
        struct clk_core *c;
        bool first_node = true;
@@ -2560,19 +2551,7 @@ static int clk_dump(struct seq_file *s, void *data)
        seq_puts(s, "}\n");
        return 0;
 }
-
-
-static int clk_dump_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, clk_dump, inode->i_private);
-}
-
-static const struct file_operations clk_dump_fops = {
-       .open           = clk_dump_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(clk_dump);
 
 static const struct {
        unsigned long flag;
@@ -2594,7 +2573,7 @@ static const struct {
 #undef ENTRY
 };
 
-static int clk_flags_dump(struct seq_file *s, void *data)
+static int clk_flags_show(struct seq_file *s, void *data)
 {
        struct clk_core *core = s->private;
        unsigned long flags = core->flags;
@@ -2613,20 +2592,9 @@ static int clk_flags_dump(struct seq_file *s, void *data)
 
        return 0;
 }
+DEFINE_SHOW_ATTRIBUTE(clk_flags);
 
-static int clk_flags_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, clk_flags_dump, inode->i_private);
-}
-
-static const struct file_operations clk_flags_fops = {
-       .open           = clk_flags_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static int possible_parents_dump(struct seq_file *s, void *data)
+static int possible_parents_show(struct seq_file *s, void *data)
 {
        struct clk_core *core = s->private;
        int i;
@@ -2638,18 +2606,7 @@ static int possible_parents_dump(struct seq_file *s, void *data)
 
        return 0;
 }
-
-static int possible_parents_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, possible_parents_dump, inode->i_private);
-}
-
-static const struct file_operations possible_parents_fops = {
-       .open           = possible_parents_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(possible_parents);
 
 static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
 {
@@ -2932,6 +2889,17 @@ static int __clk_core_init(struct clk_core *core)
                core->orphan = true;
        }
 
+       /*
+        * optional platform-specific magic
+        *
+        * The .init callback is not used by any of the basic clock types, but
+        * exists for weird hardware that must perform initialization magic.
+        * Please consider other ways of solving initialization problems before
+        * using this callback, as its use is discouraged.
+        */
+       if (core->ops->init)
+               core->ops->init(core->hw);
+
        /*
         * Set clk's accuracy.  The preferred method is to use
         * .recalc_accuracy. For simple clocks and lazy developers the default
@@ -3009,17 +2977,6 @@ static int __clk_core_init(struct clk_core *core)
                }
        }
 
-       /*
-        * optional platform-specific magic
-        *
-        * The .init callback is not used by any of the basic clock types, but
-        * exists for weird hardware that must perform initialization magic.
-        * Please consider other ways of solving initialization problems before
-        * using this callback, as its use is discouraged.
-        */
-       if (core->ops->init)
-               core->ops->init(core->hw);
-
        kref_init(&core->ref);
 out:
        clk_pm_runtime_put(core);
diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile
new file mode 100644 (file)
index 0000000..11178b7
--- /dev/null
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0
+
+ifeq ($(CONFIG_COMMON_CLK), y)
+obj-$(CONFIG_ARCH_DAVINCI_DA8XX)       += da8xx-cfgchip.o
+
+obj-y += pll.o
+obj-$(CONFIG_ARCH_DAVINCI_DA830)       += pll-da830.o
+obj-$(CONFIG_ARCH_DAVINCI_DA850)       += pll-da850.o
+obj-$(CONFIG_ARCH_DAVINCI_DM355)       += pll-dm355.o
+obj-$(CONFIG_ARCH_DAVINCI_DM365)       += pll-dm365.o
+obj-$(CONFIG_ARCH_DAVINCI_DM644x)      += pll-dm644x.o
+obj-$(CONFIG_ARCH_DAVINCI_DM646x)      += pll-dm646x.o
+
+obj-y += psc.o
+obj-$(CONFIG_ARCH_DAVINCI_DA830)       += psc-da830.o
+obj-$(CONFIG_ARCH_DAVINCI_DA850)       += psc-da850.o
+obj-$(CONFIG_ARCH_DAVINCI_DM355)       += psc-dm355.o
+obj-$(CONFIG_ARCH_DAVINCI_DM365)       += psc-dm365.o
+obj-$(CONFIG_ARCH_DAVINCI_DM644x)      += psc-dm644x.o
+obj-$(CONFIG_ARCH_DAVINCI_DM646x)      += psc-dm646x.o
+endif
diff --git a/drivers/clk/davinci/da8xx-cfgchip.c b/drivers/clk/davinci/da8xx-cfgchip.c
new file mode 100644 (file)
index 0000000..c971111
--- /dev/null
@@ -0,0 +1,790 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Clock driver for DA8xx/AM17xx/AM18xx/OMAP-L13x CFGCHIP
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/init.h>
+#include <linux/mfd/da8xx-cfgchip.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_data/clk-da8xx-cfgchip.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+/* --- Gate clocks --- */
+
+#define DA8XX_GATE_CLOCK_IS_DIV4P5     BIT(1)
+
+struct da8xx_cfgchip_gate_clk_info {
+       const char *name;
+       u32 cfgchip;
+       u32 bit;
+       u32 flags;
+};
+
+struct da8xx_cfgchip_gate_clk {
+       struct clk_hw hw;
+       struct regmap *regmap;
+       u32 reg;
+       u32 mask;
+};
+
+#define to_da8xx_cfgchip_gate_clk(_hw) \
+       container_of((_hw), struct da8xx_cfgchip_gate_clk, hw)
+
+static int da8xx_cfgchip_gate_clk_enable(struct clk_hw *hw)
+{
+       struct da8xx_cfgchip_gate_clk *clk = to_da8xx_cfgchip_gate_clk(hw);
+
+       return regmap_write_bits(clk->regmap, clk->reg, clk->mask, clk->mask);
+}
+
+static void da8xx_cfgchip_gate_clk_disable(struct clk_hw *hw)
+{
+       struct da8xx_cfgchip_gate_clk *clk = to_da8xx_cfgchip_gate_clk(hw);
+
+       regmap_write_bits(clk->regmap, clk->reg, clk->mask, 0);
+}
+
+static int da8xx_cfgchip_gate_clk_is_enabled(struct clk_hw *hw)
+{
+       struct da8xx_cfgchip_gate_clk *clk = to_da8xx_cfgchip_gate_clk(hw);
+       unsigned int val;
+
+       regmap_read(clk->regmap, clk->reg, &val);
+
+       return !!(val & clk->mask);
+}
+
+static unsigned long da8xx_cfgchip_div4p5_recalc_rate(struct clk_hw *hw,
+                                                     unsigned long parent_rate)
+{
+       /* this clock divides by 4.5 */
+       return parent_rate * 2 / 9;
+}
+
+static const struct clk_ops da8xx_cfgchip_gate_clk_ops = {
+       .enable         = da8xx_cfgchip_gate_clk_enable,
+       .disable        = da8xx_cfgchip_gate_clk_disable,
+       .is_enabled     = da8xx_cfgchip_gate_clk_is_enabled,
+};
+
+static const struct clk_ops da8xx_cfgchip_div4p5_clk_ops = {
+       .enable         = da8xx_cfgchip_gate_clk_enable,
+       .disable        = da8xx_cfgchip_gate_clk_disable,
+       .is_enabled     = da8xx_cfgchip_gate_clk_is_enabled,
+       .recalc_rate    = da8xx_cfgchip_div4p5_recalc_rate,
+};
+
+static struct da8xx_cfgchip_gate_clk * __init
+da8xx_cfgchip_gate_clk_register(struct device *dev,
+                               const struct da8xx_cfgchip_gate_clk_info *info,
+                               struct regmap *regmap)
+{
+       struct clk *parent;
+       const char *parent_name;
+       struct da8xx_cfgchip_gate_clk *gate;
+       struct clk_init_data init;
+       int ret;
+
+       parent = devm_clk_get(dev, NULL);
+       if (IS_ERR(parent))
+               return ERR_CAST(parent);
+
+       parent_name = __clk_get_name(parent);
+
+       gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
+       if (!gate)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = info->name;
+       if (info->flags & DA8XX_GATE_CLOCK_IS_DIV4P5)
+               init.ops = &da8xx_cfgchip_div4p5_clk_ops;
+       else
+               init.ops = &da8xx_cfgchip_gate_clk_ops;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+       init.flags = 0;
+
+       gate->hw.init = &init;
+       gate->regmap = regmap;
+       gate->reg = info->cfgchip;
+       gate->mask = info->bit;
+
+       ret = devm_clk_hw_register(dev, &gate->hw);
+       if (ret < 0)
+               return ERR_PTR(ret);
+
+       return gate;
+}
+
+static const struct da8xx_cfgchip_gate_clk_info da8xx_tbclksync_info __initconst = {
+       .name = "ehrpwm_tbclk",
+       .cfgchip = CFGCHIP(1),
+       .bit = CFGCHIP1_TBCLKSYNC,
+};
+
+static int __init da8xx_cfgchip_register_tbclk(struct device *dev,
+                                              struct regmap *regmap)
+{
+       struct da8xx_cfgchip_gate_clk *gate;
+
+       gate = da8xx_cfgchip_gate_clk_register(dev, &da8xx_tbclksync_info,
+                                              regmap);
+       if (IS_ERR(gate))
+               return PTR_ERR(gate);
+
+       clk_hw_register_clkdev(&gate->hw, "tbclk", "ehrpwm.0");
+       clk_hw_register_clkdev(&gate->hw, "tbclk", "ehrpwm.1");
+
+       return 0;
+}
+
+static const struct da8xx_cfgchip_gate_clk_info da8xx_div4p5ena_info __initconst = {
+       .name = "div4.5",
+       .cfgchip = CFGCHIP(3),
+       .bit = CFGCHIP3_DIV45PENA,
+       .flags = DA8XX_GATE_CLOCK_IS_DIV4P5,
+};
+
+static int __init da8xx_cfgchip_register_div4p5(struct device *dev,
+                                               struct regmap *regmap)
+{
+       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;
+}
+
+static int __init
+of_da8xx_cfgchip_gate_clk_init(struct device *dev,
+                              const struct da8xx_cfgchip_gate_clk_info *info,
+                              struct regmap *regmap)
+{
+       struct da8xx_cfgchip_gate_clk *gate;
+
+       gate = da8xx_cfgchip_gate_clk_register(dev, info, regmap);
+       if (IS_ERR(gate))
+               return PTR_ERR(gate);
+
+       return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, gate);
+}
+
+static int __init of_da8xx_tbclksync_init(struct device *dev,
+                                         struct regmap *regmap)
+{
+       return of_da8xx_cfgchip_gate_clk_init(dev, &da8xx_tbclksync_info, regmap);
+}
+
+static int __init of_da8xx_div4p5ena_init(struct device *dev,
+                                         struct regmap *regmap)
+{
+       return of_da8xx_cfgchip_gate_clk_init(dev, &da8xx_div4p5ena_info, regmap);
+}
+
+/* --- MUX clocks --- */
+
+struct da8xx_cfgchip_mux_clk_info {
+       const char *name;
+       const char *parent0;
+       const char *parent1;
+       u32 cfgchip;
+       u32 bit;
+};
+
+struct da8xx_cfgchip_mux_clk {
+       struct clk_hw hw;
+       struct regmap *regmap;
+       u32 reg;
+       u32 mask;
+};
+
+#define to_da8xx_cfgchip_mux_clk(_hw) \
+       container_of((_hw), struct da8xx_cfgchip_mux_clk, hw)
+
+static int da8xx_cfgchip_mux_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct da8xx_cfgchip_mux_clk *clk = to_da8xx_cfgchip_mux_clk(hw);
+       unsigned int val = index ? clk->mask : 0;
+
+       return regmap_write_bits(clk->regmap, clk->reg, clk->mask, val);
+}
+
+static u8 da8xx_cfgchip_mux_clk_get_parent(struct clk_hw *hw)
+{
+       struct da8xx_cfgchip_mux_clk *clk = to_da8xx_cfgchip_mux_clk(hw);
+       unsigned int val;
+
+       regmap_read(clk->regmap, clk->reg, &val);
+
+       return (val & clk->mask) ? 1 : 0;
+}
+
+static const struct clk_ops da8xx_cfgchip_mux_clk_ops = {
+       .set_parent     = da8xx_cfgchip_mux_clk_set_parent,
+       .get_parent     = da8xx_cfgchip_mux_clk_get_parent,
+};
+
+static struct da8xx_cfgchip_mux_clk * __init
+da8xx_cfgchip_mux_clk_register(struct device *dev,
+                              const struct da8xx_cfgchip_mux_clk_info *info,
+                              struct regmap *regmap)
+{
+       const char * const parent_names[] = { info->parent0, info->parent1 };
+       struct da8xx_cfgchip_mux_clk *mux;
+       struct clk_init_data init;
+       int ret;
+
+       mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+       if (!mux)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = info->name;
+       init.ops = &da8xx_cfgchip_mux_clk_ops;
+       init.parent_names = parent_names;
+       init.num_parents = 2;
+       init.flags = 0;
+
+       mux->hw.init = &init;
+       mux->regmap = regmap;
+       mux->reg = info->cfgchip;
+       mux->mask = info->bit;
+
+       ret = devm_clk_hw_register(dev, &mux->hw);
+       if (ret < 0)
+               return ERR_PTR(ret);
+
+       return mux;
+}
+
+static const struct da8xx_cfgchip_mux_clk_info da850_async1_info __initconst = {
+       .name = "async1",
+       .parent0 = "pll0_sysclk3",
+       .parent1 = "div4.5",
+       .cfgchip = CFGCHIP(3),
+       .bit = CFGCHIP3_EMA_CLKSRC,
+};
+
+static int __init da8xx_cfgchip_register_async1(struct device *dev,
+                                               struct regmap *regmap)
+{
+       struct da8xx_cfgchip_mux_clk *mux;
+
+       mux = da8xx_cfgchip_mux_clk_register(dev, &da850_async1_info, regmap);
+       if (IS_ERR(mux))
+               return PTR_ERR(mux);
+
+       clk_hw_register_clkdev(&mux->hw, "async1", "da850-psc0");
+
+       return 0;
+}
+
+static const struct da8xx_cfgchip_mux_clk_info da850_async3_info __initconst = {
+       .name = "async3",
+       .parent0 = "pll0_sysclk2",
+       .parent1 = "pll1_sysclk2",
+       .cfgchip = CFGCHIP(3),
+       .bit = CFGCHIP3_ASYNC3_CLKSRC,
+};
+
+static int __init da850_cfgchip_register_async3(struct device *dev,
+                                               struct regmap *regmap)
+{
+       struct da8xx_cfgchip_mux_clk *mux;
+       struct clk_hw *parent;
+
+       mux = da8xx_cfgchip_mux_clk_register(dev, &da850_async3_info, regmap);
+       if (IS_ERR(mux))
+               return PTR_ERR(mux);
+
+       clk_hw_register_clkdev(&mux->hw, "async3", "da850-psc1");
+
+       /* pll1_sysclk2 is not affected by CPU scaling, so use it for async3 */
+       parent = clk_hw_get_parent_by_index(&mux->hw, 1);
+       if (parent)
+               clk_set_parent(mux->hw.clk, parent->clk);
+       else
+               dev_warn(dev, "Failed to find async3 parent clock\n");
+
+       return 0;
+}
+
+static int __init
+of_da8xx_cfgchip_init_mux_clock(struct device *dev,
+                               const struct da8xx_cfgchip_mux_clk_info *info,
+                               struct regmap *regmap)
+{
+       struct da8xx_cfgchip_mux_clk *mux;
+
+       mux = da8xx_cfgchip_mux_clk_register(dev, info, regmap);
+       if (IS_ERR(mux))
+               return PTR_ERR(mux);
+
+       return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &mux->hw);
+}
+
+static int __init of_da850_async1_init(struct device *dev, struct regmap *regmap)
+{
+       return of_da8xx_cfgchip_init_mux_clock(dev, &da850_async1_info, regmap);
+}
+
+static int __init of_da850_async3_init(struct device *dev, struct regmap *regmap)
+{
+       return of_da8xx_cfgchip_init_mux_clock(dev, &da850_async3_info, regmap);
+}
+
+/* --- USB 2.0 PHY clock --- */
+
+struct da8xx_usb0_clk48 {
+       struct clk_hw hw;
+       struct clk *fck;
+       struct regmap *regmap;
+};
+
+#define to_da8xx_usb0_clk48(_hw) \
+       container_of((_hw), struct da8xx_usb0_clk48, hw)
+
+static int da8xx_usb0_clk48_prepare(struct clk_hw *hw)
+{
+       struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
+
+       /* The USB 2.0 PSC clock is only needed temporarily during the USB 2.0
+        * PHY clock enable, but since clk_prepare() can't be called in an
+        * atomic context (i.e. in clk_enable()), we have to prepare it here.
+        */
+       return clk_prepare(usb0->fck);
+}
+
+static void da8xx_usb0_clk48_unprepare(struct clk_hw *hw)
+{
+       struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
+
+       clk_unprepare(usb0->fck);
+}
+
+static int da8xx_usb0_clk48_enable(struct clk_hw *hw)
+{
+       struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
+       unsigned int mask, val;
+       int ret;
+
+       /* Locking the USB 2.O PLL requires that the USB 2.O PSC is enabled
+        * temporaily. It can be turned back off once the PLL is locked.
+        */
+       clk_enable(usb0->fck);
+
+       /* Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
+        * PHY may use the USB 2.0 PLL clock without USB 2.0 OTG being used.
+        */
+       mask = CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_PHY_PLLON;
+       val = CFGCHIP2_PHY_PLLON;
+
+       regmap_write_bits(usb0->regmap, CFGCHIP(2), mask, val);
+       ret = regmap_read_poll_timeout(usb0->regmap, CFGCHIP(2), val,
+                                      val & CFGCHIP2_PHYCLKGD, 0, 500000);
+
+       clk_disable(usb0->fck);
+
+       return ret;
+}
+
+static void da8xx_usb0_clk48_disable(struct clk_hw *hw)
+{
+       struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
+       unsigned int val;
+
+       val = CFGCHIP2_PHYPWRDN;
+       regmap_write_bits(usb0->regmap, CFGCHIP(2), val, val);
+}
+
+static int da8xx_usb0_clk48_is_enabled(struct clk_hw *hw)
+{
+       struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
+       unsigned int val;
+
+       regmap_read(usb0->regmap, CFGCHIP(2), &val);
+
+       return !!(val & CFGCHIP2_PHYCLKGD);
+}
+
+static unsigned long da8xx_usb0_clk48_recalc_rate(struct clk_hw *hw,
+                                                 unsigned long parent_rate)
+{
+       struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
+       unsigned int mask, val;
+
+       /* The parent clock rate must be one of the following */
+       mask = CFGCHIP2_REFFREQ_MASK;
+       switch (parent_rate) {
+       case 12000000:
+               val = CFGCHIP2_REFFREQ_12MHZ;
+               break;
+       case 13000000:
+               val = CFGCHIP2_REFFREQ_13MHZ;
+               break;
+       case 19200000:
+               val = CFGCHIP2_REFFREQ_19_2MHZ;
+               break;
+       case 20000000:
+               val = CFGCHIP2_REFFREQ_20MHZ;
+               break;
+       case 24000000:
+               val = CFGCHIP2_REFFREQ_24MHZ;
+               break;
+       case 26000000:
+               val = CFGCHIP2_REFFREQ_26MHZ;
+               break;
+       case 38400000:
+               val = CFGCHIP2_REFFREQ_38_4MHZ;
+               break;
+       case 40000000:
+               val = CFGCHIP2_REFFREQ_40MHZ;
+               break;
+       case 48000000:
+               val = CFGCHIP2_REFFREQ_48MHZ;
+               break;
+       default:
+               return 0;
+       }
+
+       regmap_write_bits(usb0->regmap, CFGCHIP(2), mask, val);
+
+       /* USB 2.0 PLL always supplies 48MHz */
+       return 48000000;
+}
+
+static long da8xx_usb0_clk48_round_rate(struct clk_hw *hw, unsigned long rate,
+                                       unsigned long *parent_rate)
+{
+       return 48000000;
+}
+
+static int da8xx_usb0_clk48_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
+
+       return regmap_write_bits(usb0->regmap, CFGCHIP(2),
+                                CFGCHIP2_USB2PHYCLKMUX,
+                                index ? CFGCHIP2_USB2PHYCLKMUX : 0);
+}
+
+static u8 da8xx_usb0_clk48_get_parent(struct clk_hw *hw)
+{
+       struct da8xx_usb0_clk48 *usb0 = to_da8xx_usb0_clk48(hw);
+       unsigned int val;
+
+       regmap_read(usb0->regmap, CFGCHIP(2), &val);
+
+       return (val & CFGCHIP2_USB2PHYCLKMUX) ? 1 : 0;
+}
+
+static const struct clk_ops da8xx_usb0_clk48_ops = {
+       .prepare        = da8xx_usb0_clk48_prepare,
+       .unprepare      = da8xx_usb0_clk48_unprepare,
+       .enable         = da8xx_usb0_clk48_enable,
+       .disable        = da8xx_usb0_clk48_disable,
+       .is_enabled     = da8xx_usb0_clk48_is_enabled,
+       .recalc_rate    = da8xx_usb0_clk48_recalc_rate,
+       .round_rate     = da8xx_usb0_clk48_round_rate,
+       .set_parent     = da8xx_usb0_clk48_set_parent,
+       .get_parent     = da8xx_usb0_clk48_get_parent,
+};
+
+static struct da8xx_usb0_clk48 *
+da8xx_cfgchip_register_usb0_clk48(struct device *dev,
+                                 struct regmap *regmap)
+{
+       const char * const parent_names[] = { "usb_refclkin", "pll0_auxclk" };
+       struct clk *fck_clk;
+       struct da8xx_usb0_clk48 *usb0;
+       struct clk_init_data init;
+       int ret;
+
+       fck_clk = devm_clk_get(dev, "fck");
+       if (IS_ERR(fck_clk)) {
+               if (PTR_ERR(fck_clk) != -EPROBE_DEFER)
+                       dev_err(dev, "Missing fck clock\n");
+               return ERR_CAST(fck_clk);
+       }
+
+       usb0 = devm_kzalloc(dev, sizeof(*usb0), GFP_KERNEL);
+       if (!usb0)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = "usb0_clk48";
+       init.ops = &da8xx_usb0_clk48_ops;
+       init.parent_names = parent_names;
+       init.num_parents = 2;
+
+       usb0->hw.init = &init;
+       usb0->fck = fck_clk;
+       usb0->regmap = regmap;
+
+       ret = devm_clk_hw_register(dev, &usb0->hw);
+       if (ret < 0)
+               return ERR_PTR(ret);
+
+       return usb0;
+}
+
+/* --- USB 1.1 PHY clock --- */
+
+struct da8xx_usb1_clk48 {
+       struct clk_hw hw;
+       struct regmap *regmap;
+};
+
+#define to_da8xx_usb1_clk48(_hw) \
+       container_of((_hw), struct da8xx_usb1_clk48, hw)
+
+static int da8xx_usb1_clk48_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct da8xx_usb1_clk48 *usb1 = to_da8xx_usb1_clk48(hw);
+
+       return regmap_write_bits(usb1->regmap, CFGCHIP(2),
+                                CFGCHIP2_USB1PHYCLKMUX,
+                                index ? CFGCHIP2_USB1PHYCLKMUX : 0);
+}
+
+static u8 da8xx_usb1_clk48_get_parent(struct clk_hw *hw)
+{
+       struct da8xx_usb1_clk48 *usb1 = to_da8xx_usb1_clk48(hw);
+       unsigned int val;
+
+       regmap_read(usb1->regmap, CFGCHIP(2), &val);
+
+       return (val & CFGCHIP2_USB1PHYCLKMUX) ? 1 : 0;
+}
+
+static const struct clk_ops da8xx_usb1_clk48_ops = {
+       .set_parent     = da8xx_usb1_clk48_set_parent,
+       .get_parent     = da8xx_usb1_clk48_get_parent,
+};
+
+/**
+ * da8xx_cfgchip_register_usb1_clk48 - Register a new USB 1.1 PHY clock
+ * @regmap: The CFGCHIP regmap
+ */
+static struct da8xx_usb1_clk48 *
+da8xx_cfgchip_register_usb1_clk48(struct device *dev,
+                                 struct regmap *regmap)
+{
+       const char * const parent_names[] = { "usb0_clk48", "usb_refclkin" };
+       struct da8xx_usb1_clk48 *usb1;
+       struct clk_init_data init;
+       int ret;
+
+       usb1 = devm_kzalloc(dev, sizeof(*usb1), GFP_KERNEL);
+       if (!usb1)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = "usb1_clk48";
+       init.ops = &da8xx_usb1_clk48_ops;
+       init.parent_names = parent_names;
+       init.num_parents = 2;
+
+       usb1->hw.init = &init;
+       usb1->regmap = regmap;
+
+       ret = devm_clk_hw_register(dev, &usb1->hw);
+       if (ret < 0)
+               return ERR_PTR(ret);
+
+       return usb1;
+}
+
+static int da8xx_cfgchip_register_usb_phy_clk(struct device *dev,
+                                             struct regmap *regmap)
+{
+       struct da8xx_usb0_clk48 *usb0;
+       struct da8xx_usb1_clk48 *usb1;
+       struct clk_hw *parent;
+
+       usb0 = da8xx_cfgchip_register_usb0_clk48(dev, regmap);
+       if (IS_ERR(usb0))
+               return PTR_ERR(usb0);
+
+       /*
+        * All existing boards use pll0_auxclk as the parent and new boards
+        * should use device tree, so hard-coding the value (1) here.
+        */
+       parent = clk_hw_get_parent_by_index(&usb0->hw, 1);
+       if (parent)
+               clk_set_parent(usb0->hw.clk, parent->clk);
+       else
+               dev_warn(dev, "Failed to find usb0 parent clock\n");
+
+       usb1 = da8xx_cfgchip_register_usb1_clk48(dev, regmap);
+       if (IS_ERR(usb1))
+               return PTR_ERR(usb1);
+
+       /*
+        * All existing boards use usb0_clk48 as the parent and new boards
+        * should use device tree, so hard-coding the value (0) here.
+        */
+       parent = clk_hw_get_parent_by_index(&usb1->hw, 0);
+       if (parent)
+               clk_set_parent(usb1->hw.clk, parent->clk);
+       else
+               dev_warn(dev, "Failed to find usb1 parent clock\n");
+
+       clk_hw_register_clkdev(&usb0->hw, "usb0_clk48", "da8xx-usb-phy");
+       clk_hw_register_clkdev(&usb1->hw, "usb1_clk48", "da8xx-usb-phy");
+
+       return 0;
+}
+
+static int of_da8xx_usb_phy_clk_init(struct device *dev, struct regmap *regmap)
+{
+       struct clk_hw_onecell_data *clk_data;
+       struct da8xx_usb0_clk48 *usb0;
+       struct da8xx_usb1_clk48 *usb1;
+
+       clk_data = devm_kzalloc(dev, sizeof(*clk_data) + 2 *
+                               sizeof(*clk_data->hws), GFP_KERNEL);
+       if (!clk_data)
+               return -ENOMEM;
+
+       clk_data->num = 2;
+
+       usb0 = da8xx_cfgchip_register_usb0_clk48(dev, regmap);
+       if (IS_ERR(usb0)) {
+               if (PTR_ERR(usb0) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+
+               dev_warn(dev, "Failed to register usb0_clk48 (%ld)\n",
+                        PTR_ERR(usb0));
+
+               clk_data->hws[0] = ERR_PTR(-ENOENT);
+       } else {
+               clk_data->hws[0] = &usb0->hw;
+       }
+
+       usb1 = da8xx_cfgchip_register_usb1_clk48(dev, regmap);
+       if (IS_ERR(usb1)) {
+               if (PTR_ERR(usb0) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+
+               dev_warn(dev, "Failed to register usb1_clk48 (%ld)\n",
+                        PTR_ERR(usb1));
+
+               clk_data->hws[1] = ERR_PTR(-ENOENT);
+       } else {
+               clk_data->hws[1] = &usb1->hw;
+       }
+
+       return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
+}
+
+/* --- platform device --- */
+
+static const struct of_device_id da8xx_cfgchip_of_match[] = {
+       {
+               .compatible = "ti,da830-tbclksync",
+               .data = of_da8xx_tbclksync_init,
+       },
+       {
+               .compatible = "ti,da830-div4p5ena",
+               .data = of_da8xx_div4p5ena_init,
+       },
+       {
+               .compatible = "ti,da850-async1-clksrc",
+               .data = of_da850_async1_init,
+       },
+       {
+               .compatible = "ti,da850-async3-clksrc",
+               .data = of_da850_async3_init,
+       },
+       {
+               .compatible = "ti,da830-usb-phy-clocks",
+               .data = of_da8xx_usb_phy_clk_init,
+       },
+       { }
+};
+
+static const struct platform_device_id da8xx_cfgchip_id_table[] = {
+       {
+               .name = "da830-tbclksync",
+               .driver_data = (kernel_ulong_t)da8xx_cfgchip_register_tbclk,
+       },
+       {
+               .name = "da830-div4p5ena",
+               .driver_data = (kernel_ulong_t)da8xx_cfgchip_register_div4p5,
+       },
+       {
+               .name = "da850-async1-clksrc",
+               .driver_data = (kernel_ulong_t)da8xx_cfgchip_register_async1,
+       },
+       {
+               .name = "da850-async3-clksrc",
+               .driver_data = (kernel_ulong_t)da850_cfgchip_register_async3,
+       },
+       {
+               .name = "da830-usb-phy-clks",
+               .driver_data = (kernel_ulong_t)da8xx_cfgchip_register_usb_phy_clk,
+       },
+       { }
+};
+
+typedef int (*da8xx_cfgchip_init)(struct device *dev, struct regmap *regmap);
+
+static int da8xx_cfgchip_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct da8xx_cfgchip_clk_platform_data *pdata = dev->platform_data;
+       const struct of_device_id *of_id;
+       da8xx_cfgchip_init clk_init = NULL;
+       struct regmap *regmap = NULL;
+
+       of_id = of_match_device(da8xx_cfgchip_of_match, dev);
+       if (of_id) {
+               struct device_node *parent;
+
+               clk_init = of_id->data;
+               parent = of_get_parent(dev->of_node);
+               regmap = syscon_node_to_regmap(parent);
+               of_node_put(parent);
+       } else if (pdev->id_entry && pdata) {
+               clk_init = (void *)pdev->id_entry->driver_data;
+               regmap = pdata->cfgchip;
+       }
+
+       if (!clk_init) {
+               dev_err(dev, "unable to find driver data\n");
+               return -EINVAL;
+       }
+
+       if (IS_ERR_OR_NULL(regmap)) {
+               dev_err(dev, "no regmap for CFGCHIP syscon\n");
+               return regmap ? PTR_ERR(regmap) : -ENOENT;
+       }
+
+       return clk_init(dev, regmap);
+}
+
+static struct platform_driver da8xx_cfgchip_driver = {
+       .probe          = da8xx_cfgchip_probe,
+       .driver         = {
+               .name           = "da8xx-cfgchip-clk",
+               .of_match_table = da8xx_cfgchip_of_match,
+       },
+       .id_table       = da8xx_cfgchip_id_table,
+};
+
+static int __init da8xx_cfgchip_driver_init(void)
+{
+       return platform_driver_register(&da8xx_cfgchip_driver);
+}
+
+/* has to be postcore_initcall because PSC devices depend on the async3 clock */
+postcore_initcall(da8xx_cfgchip_driver_init);
diff --git a/drivers/clk/davinci/pll-da830.c b/drivers/clk/davinci/pll-da830.c
new file mode 100644 (file)
index 0000000..929a3d3
--- /dev/null
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLL clock descriptions for TI DA830/OMAP-L137/AM17XX
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/clkdev.h>
+#include <linux/bitops.h>
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include "pll.h"
+
+static const struct davinci_pll_clk_info da830_pll_info = {
+       .name = "pll0",
+       .pllm_mask = GENMASK(4, 0),
+       .pllm_min = 4,
+       .pllm_max = 32,
+       .pllout_min_rate = 300000000,
+       .pllout_max_rate = 600000000,
+       .flags = PLL_HAS_CLKMODE | PLL_HAS_PREDIV | PLL_HAS_POSTDIV,
+};
+
+/*
+ * NB: Technically, the clocks flagged as SYSCLK_FIXED_DIV are "fixed ratio",
+ * meaning that we could change the divider as long as we keep the correct
+ * ratio between all of the clocks, but we don't support that because there is
+ * currently not a need for it.
+ */
+
+SYSCLK(2, pll0_sysclk2, pll0_pllen, 5, SYSCLK_FIXED_DIV);
+SYSCLK(3, pll0_sysclk3, pll0_pllen, 5, 0);
+SYSCLK(4, pll0_sysclk4, pll0_pllen, 5, SYSCLK_FIXED_DIV);
+SYSCLK(5, pll0_sysclk5, pll0_pllen, 5, 0);
+SYSCLK(6, pll0_sysclk6, pll0_pllen, 5, SYSCLK_FIXED_DIV);
+SYSCLK(7, pll0_sysclk7, pll0_pllen, 5, 0);
+
+int da830_pll_init(struct device *dev, void __iomem *base)
+{
+       struct clk *clk;
+
+       davinci_pll_clk_register(dev, &da830_pll_info, "ref_clk", base);
+
+       clk = davinci_pll_sysclk_register(dev, &pll0_sysclk2, base);
+       clk_register_clkdev(clk, "pll0_sysclk2", "da830-psc0");
+       clk_register_clkdev(clk, "pll0_sysclk2", "da830-psc1");
+
+       clk = davinci_pll_sysclk_register(dev, &pll0_sysclk3, base);
+       clk_register_clkdev(clk, "pll0_sysclk3", "da830-psc0");
+
+       clk = davinci_pll_sysclk_register(dev, &pll0_sysclk4, base);
+       clk_register_clkdev(clk, "pll0_sysclk4", "da830-psc0");
+       clk_register_clkdev(clk, "pll0_sysclk4", "da830-psc1");
+
+       clk = davinci_pll_sysclk_register(dev, &pll0_sysclk5, base);
+       clk_register_clkdev(clk, "pll0_sysclk5", "da830-psc1");
+
+       clk = davinci_pll_sysclk_register(dev, &pll0_sysclk6, base);
+       clk_register_clkdev(clk, "pll0_sysclk6", "da830-psc0");
+
+       clk = davinci_pll_sysclk_register(dev, &pll0_sysclk7, base);
+
+       clk = davinci_pll_auxclk_register(dev, "pll0_auxclk", base);
+       clk_register_clkdev(clk, NULL, "i2c_davinci.1");
+       clk_register_clkdev(clk, "timer0", NULL);
+       clk_register_clkdev(clk, NULL, "davinci-wdt");
+
+       return 0;
+}
diff --git a/drivers/clk/davinci/pll-da850.c b/drivers/clk/davinci/pll-da850.c
new file mode 100644 (file)
index 0000000..2a038b7
--- /dev/null
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLL clock descriptions for TI DA850/OMAP-L138/AM18XX
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mfd/da8xx-cfgchip.h>
+#include <linux/of.h>
+#include <linux/types.h>
+
+#include "pll.h"
+
+#define OCSEL_OCSRC_OSCIN              0x14
+#define OCSEL_OCSRC_PLL0_SYSCLK(n)     (0x16 + (n))
+#define OCSEL_OCSRC_PLL1_OBSCLK                0x1e
+#define OCSEL_OCSRC_PLL1_SYSCLK(n)     (0x16 + (n))
+
+static const struct davinci_pll_clk_info da850_pll0_info = {
+       .name = "pll0",
+       .unlock_reg = CFGCHIP(0),
+       .unlock_mask = CFGCHIP0_PLL_MASTER_LOCK,
+       .pllm_mask = GENMASK(4, 0),
+       .pllm_min = 4,
+       .pllm_max = 32,
+       .pllout_min_rate = 300000000,
+       .pllout_max_rate = 600000000,
+       .flags = PLL_HAS_CLKMODE | PLL_HAS_PREDIV | PLL_HAS_POSTDIV |
+                PLL_HAS_EXTCLKSRC,
+};
+
+/*
+ * NB: Technically, the clocks flagged as SYSCLK_FIXED_DIV are "fixed ratio",
+ * meaning that we could change the divider as long as we keep the correct
+ * ratio between all of the clocks, but we don't support that because there is
+ * currently not a need for it.
+ */
+
+SYSCLK(1, pll0_sysclk1, pll0_pllen, 5, SYSCLK_FIXED_DIV);
+SYSCLK(2, pll0_sysclk2, pll0_pllen, 5, SYSCLK_FIXED_DIV);
+SYSCLK(3, pll0_sysclk3, pll0_pllen, 5, 0);
+SYSCLK(4, pll0_sysclk4, pll0_pllen, 5, SYSCLK_FIXED_DIV);
+SYSCLK(5, pll0_sysclk5, pll0_pllen, 5, 0);
+SYSCLK(6, pll0_sysclk6, pll0_pllen, 5, SYSCLK_ARM_RATE | SYSCLK_FIXED_DIV);
+SYSCLK(7, pll0_sysclk7, pll0_pllen, 5, 0);
+
+static const char * const da850_pll0_obsclk_parent_names[] = {
+       "oscin",
+       "pll0_sysclk1",
+       "pll0_sysclk2",
+       "pll0_sysclk3",
+       "pll0_sysclk4",
+       "pll0_sysclk5",
+       "pll0_sysclk6",
+       "pll0_sysclk7",
+       "pll1_obsclk",
+};
+
+static u32 da850_pll0_obsclk_table[] = {
+       OCSEL_OCSRC_OSCIN,
+       OCSEL_OCSRC_PLL0_SYSCLK(1),
+       OCSEL_OCSRC_PLL0_SYSCLK(2),
+       OCSEL_OCSRC_PLL0_SYSCLK(3),
+       OCSEL_OCSRC_PLL0_SYSCLK(4),
+       OCSEL_OCSRC_PLL0_SYSCLK(5),
+       OCSEL_OCSRC_PLL0_SYSCLK(6),
+       OCSEL_OCSRC_PLL0_SYSCLK(7),
+       OCSEL_OCSRC_PLL1_OBSCLK,
+};
+
+static const struct davinci_pll_obsclk_info da850_pll0_obsclk_info = {
+       .name = "pll0_obsclk",
+       .parent_names = da850_pll0_obsclk_parent_names,
+       .num_parents = ARRAY_SIZE(da850_pll0_obsclk_parent_names),
+       .table = da850_pll0_obsclk_table,
+       .ocsrc_mask = GENMASK(4, 0),
+};
+
+int da850_pll0_init(struct device *dev, void __iomem *base)
+{
+       struct clk *clk;
+
+       davinci_pll_clk_register(dev, &da850_pll0_info, "ref_clk", base);
+
+       clk = davinci_pll_sysclk_register(dev, &pll0_sysclk1, base);
+       clk_register_clkdev(clk, "pll0_sysclk1", "da850-psc0");
+
+       clk = davinci_pll_sysclk_register(dev, &pll0_sysclk2, base);
+       clk_register_clkdev(clk, "pll0_sysclk2", "da850-psc0");
+       clk_register_clkdev(clk, "pll0_sysclk2", "da850-psc1");
+       clk_register_clkdev(clk, "pll0_sysclk2", "da850-async3-clksrc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll0_sysclk3, base);
+       clk_register_clkdev(clk, "pll0_sysclk3", "da850-async1-clksrc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll0_sysclk4, base);
+       clk_register_clkdev(clk, "pll0_sysclk4", "da850-psc0");
+       clk_register_clkdev(clk, "pll0_sysclk4", "da850-psc1");
+
+       davinci_pll_sysclk_register(dev, &pll0_sysclk5, base);
+
+       clk = davinci_pll_sysclk_register(dev, &pll0_sysclk6, base);
+       clk_register_clkdev(clk, "pll0_sysclk6", "da850-psc0");
+
+       davinci_pll_sysclk_register(dev, &pll0_sysclk7, base);
+
+       davinci_pll_auxclk_register(dev, "pll0_auxclk", base);
+
+       clk = clk_register_fixed_factor(dev, "async2", "pll0_auxclk",
+                                       CLK_IS_CRITICAL, 1, 1);
+
+       clk_register_clkdev(clk, NULL, "i2c_davinci.1");
+       clk_register_clkdev(clk, "timer0", NULL);
+       clk_register_clkdev(clk, NULL, "davinci-wdt");
+
+       davinci_pll_obsclk_register(dev, &da850_pll0_obsclk_info, base);
+
+       return 0;
+}
+
+static const struct davinci_pll_sysclk_info *da850_pll0_sysclk_info[] = {
+       &pll0_sysclk1,
+       &pll0_sysclk2,
+       &pll0_sysclk3,
+       &pll0_sysclk4,
+       &pll0_sysclk5,
+       &pll0_sysclk6,
+       &pll0_sysclk7,
+       NULL
+};
+
+int of_da850_pll0_init(struct device *dev, void __iomem *base)
+{
+       return of_davinci_pll_init(dev, &da850_pll0_info,
+                                  &da850_pll0_obsclk_info,
+                                  da850_pll0_sysclk_info, 7, base);
+}
+
+static const struct davinci_pll_clk_info da850_pll1_info = {
+       .name = "pll1",
+       .unlock_reg = CFGCHIP(3),
+       .unlock_mask = CFGCHIP3_PLL1_MASTER_LOCK,
+       .pllm_mask = GENMASK(4, 0),
+       .pllm_min = 4,
+       .pllm_max = 32,
+       .pllout_min_rate = 300000000,
+       .pllout_max_rate = 600000000,
+       .flags = PLL_HAS_POSTDIV,
+};
+
+SYSCLK(1, pll1_sysclk1, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+SYSCLK(2, pll1_sysclk2, pll1_pllen, 5, 0);
+SYSCLK(3, pll1_sysclk3, pll1_pllen, 5, 0);
+
+static const char * const da850_pll1_obsclk_parent_names[] = {
+       "oscin",
+       "pll1_sysclk1",
+       "pll1_sysclk2",
+       "pll1_sysclk3",
+};
+
+static u32 da850_pll1_obsclk_table[] = {
+       OCSEL_OCSRC_OSCIN,
+       OCSEL_OCSRC_PLL1_SYSCLK(1),
+       OCSEL_OCSRC_PLL1_SYSCLK(2),
+       OCSEL_OCSRC_PLL1_SYSCLK(3),
+};
+
+static const struct davinci_pll_obsclk_info da850_pll1_obsclk_info = {
+       .name = "pll1_obsclk",
+       .parent_names = da850_pll1_obsclk_parent_names,
+       .num_parents = ARRAY_SIZE(da850_pll1_obsclk_parent_names),
+       .table = da850_pll1_obsclk_table,
+       .ocsrc_mask = GENMASK(4, 0),
+};
+
+int da850_pll1_init(struct device *dev, void __iomem *base)
+{
+       struct clk *clk;
+
+       davinci_pll_clk_register(dev, &da850_pll1_info, "oscin", base);
+
+       davinci_pll_sysclk_register(dev, &pll1_sysclk1, base);
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk2, base);
+       clk_register_clkdev(clk, "pll1_sysclk2", "da850-async3-clksrc");
+
+       davinci_pll_sysclk_register(dev, &pll1_sysclk3, base);
+
+       davinci_pll_obsclk_register(dev, &da850_pll1_obsclk_info, base);
+
+       return 0;
+}
+
+static const struct davinci_pll_sysclk_info *da850_pll1_sysclk_info[] = {
+       &pll1_sysclk1,
+       &pll1_sysclk2,
+       &pll1_sysclk3,
+       NULL
+};
+
+int of_da850_pll1_init(struct device *dev, void __iomem *base)
+{
+       return of_davinci_pll_init(dev, &da850_pll1_info,
+                                  &da850_pll1_obsclk_info,
+                                  da850_pll1_sysclk_info, 3, base);
+}
diff --git a/drivers/clk/davinci/pll-dm355.c b/drivers/clk/davinci/pll-dm355.c
new file mode 100644 (file)
index 0000000..5345f82
--- /dev/null
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLL clock descriptions for TI DM355
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/clkdev.h>
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include "pll.h"
+
+static const struct davinci_pll_clk_info dm355_pll1_info = {
+       .name = "pll1",
+       .pllm_mask = GENMASK(7, 0),
+       .pllm_min = 92,
+       .pllm_max = 184,
+       .flags = PLL_HAS_CLKMODE | PLL_HAS_PREDIV | PLL_PREDIV_ALWAYS_ENABLED |
+                PLL_PREDIV_FIXED8 | PLL_HAS_POSTDIV |
+                PLL_POSTDIV_ALWAYS_ENABLED | PLL_POSTDIV_FIXED_DIV,
+};
+
+SYSCLK(1, pll1_sysclk1, pll1, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED);
+SYSCLK(2, pll1_sysclk2, pll1, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED);
+SYSCLK(3, pll1_sysclk3, pll1, 5, SYSCLK_ALWAYS_ENABLED);
+SYSCLK(4, pll1_sysclk4, pll1, 5, SYSCLK_ALWAYS_ENABLED);
+
+int dm355_pll1_init(struct device *dev, void __iomem *base)
+{
+       struct clk *clk;
+
+       davinci_pll_clk_register(dev, &dm355_pll1_info, "ref_clk", base);
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base);
+       clk_register_clkdev(clk, "pll1_sysclk1", "dm355-psc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk2, base);
+       clk_register_clkdev(clk, "pll1_sysclk2", "dm355-psc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk3, base);
+       clk_register_clkdev(clk, "pll1_sysclk3", "dm355-psc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk4, base);
+       clk_register_clkdev(clk, "pll1_sysclk4", "dm355-psc");
+
+       clk = davinci_pll_auxclk_register(dev, "pll1_auxclk", base);
+       clk_register_clkdev(clk, "pll1_auxclk", "dm355-psc");
+
+       davinci_pll_sysclkbp_clk_register(dev, "pll1_sysclkbp", base);
+
+       return 0;
+}
+
+static const struct davinci_pll_clk_info dm355_pll2_info = {
+       .name = "pll2",
+       .pllm_mask = GENMASK(7, 0),
+       .pllm_min = 92,
+       .pllm_max = 184,
+       .flags = PLL_HAS_PREDIV | PLL_PREDIV_ALWAYS_ENABLED | PLL_HAS_POSTDIV |
+                PLL_POSTDIV_ALWAYS_ENABLED | PLL_POSTDIV_FIXED_DIV,
+};
+
+SYSCLK(1, pll2_sysclk1, pll2, 5, SYSCLK_FIXED_DIV);
+SYSCLK(2, pll2_sysclk2, pll2, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED);
+
+int dm355_pll2_init(struct device *dev, void __iomem *base)
+{
+       davinci_pll_clk_register(dev, &dm355_pll2_info, "oscin", base);
+
+       davinci_pll_sysclk_register(dev, &pll2_sysclk1, base);
+
+       davinci_pll_sysclk_register(dev, &pll2_sysclk2, base);
+
+       davinci_pll_sysclkbp_clk_register(dev, "pll2_sysclkbp", base);
+
+       return 0;
+}
diff --git a/drivers/clk/davinci/pll-dm365.c b/drivers/clk/davinci/pll-dm365.c
new file mode 100644 (file)
index 0000000..5f8d9f4
--- /dev/null
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLL clock descriptions for TI DM365
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/clkdev.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include "pll.h"
+
+#define OCSEL_OCSRC_ENABLE     0
+
+static const struct davinci_pll_clk_info dm365_pll1_info = {
+       .name = "pll1",
+       .pllm_mask = GENMASK(9, 0),
+       .pllm_min = 1,
+       .pllm_max = 1023,
+       .flags = PLL_HAS_CLKMODE | PLL_HAS_PREDIV | PLL_HAS_POSTDIV |
+                PLL_POSTDIV_ALWAYS_ENABLED | PLL_PLLM_2X,
+};
+
+SYSCLK(1, pll1_sysclk1, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+SYSCLK(2, pll1_sysclk2, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+SYSCLK(3, pll1_sysclk3, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+SYSCLK(4, pll1_sysclk4, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+SYSCLK(5, pll1_sysclk5, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+SYSCLK(6, pll1_sysclk6, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+SYSCLK(7, pll1_sysclk7, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+SYSCLK(8, pll1_sysclk8, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+SYSCLK(9, pll1_sysclk9, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+
+/*
+ * This is a bit of a hack to make OCSEL[OCSRC] on DM365 look like OCSEL[OCSRC]
+ * on DA850. On DM365, OCSEL[OCSRC] is just an enable/disable bit instead of a
+ * multiplexer. By modeling it as a single parent mux clock, the clock code will
+ * still do the right thing in this case.
+ */
+static const char * const dm365_pll_obsclk_parent_names[] = {
+       "oscin",
+};
+
+static u32 dm365_pll_obsclk_table[] = {
+       OCSEL_OCSRC_ENABLE,
+};
+
+static const struct davinci_pll_obsclk_info dm365_pll1_obsclk_info = {
+       .name = "pll1_obsclk",
+       .parent_names = dm365_pll_obsclk_parent_names,
+       .num_parents = ARRAY_SIZE(dm365_pll_obsclk_parent_names),
+       .table = dm365_pll_obsclk_table,
+       .ocsrc_mask = BIT(4),
+};
+
+int dm365_pll1_init(struct device *dev, void __iomem *base)
+{
+       struct clk *clk;
+
+       davinci_pll_clk_register(dev, &dm365_pll1_info, "ref_clk", base);
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base);
+       clk_register_clkdev(clk, "pll1_sysclk1", "dm365-psc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk2, base);
+       clk_register_clkdev(clk, "pll1_sysclk2", "dm365-psc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk3, base);
+       clk_register_clkdev(clk, "pll1_sysclk3", "dm365-psc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk4, base);
+       clk_register_clkdev(clk, "pll1_sysclk4", "dm365-psc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk5, base);
+       clk_register_clkdev(clk, "pll1_sysclk5", "dm365-psc");
+
+       davinci_pll_sysclk_register(dev, &pll1_sysclk6, base);
+
+       davinci_pll_sysclk_register(dev, &pll1_sysclk7, base);
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk8, base);
+       clk_register_clkdev(clk, "pll1_sysclk8", "dm365-psc");
+
+       davinci_pll_sysclk_register(dev, &pll1_sysclk9, base);
+
+       clk = davinci_pll_auxclk_register(dev, "pll1_auxclk", base);
+       clk_register_clkdev(clk, "pll1_auxclk", "dm355-psc");
+
+       davinci_pll_sysclkbp_clk_register(dev, "pll1_sysclkbp", base);
+
+       davinci_pll_obsclk_register(dev, &dm365_pll1_obsclk_info, base);
+
+       return 0;
+}
+
+static const struct davinci_pll_clk_info dm365_pll2_info = {
+       .name = "pll2",
+       .pllm_mask = GENMASK(9, 0),
+       .pllm_min = 1,
+       .pllm_max = 1023,
+       .flags = PLL_HAS_PREDIV | PLL_HAS_POSTDIV | PLL_POSTDIV_ALWAYS_ENABLED |
+                PLL_PLLM_2X,
+};
+
+SYSCLK(1, pll2_sysclk1, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+SYSCLK(2, pll2_sysclk2, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+SYSCLK(3, pll2_sysclk3, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+SYSCLK(4, pll2_sysclk4, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+SYSCLK(5, pll2_sysclk5, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);
+
+static const struct davinci_pll_obsclk_info dm365_pll2_obsclk_info = {
+       .name = "pll2_obsclk",
+       .parent_names = dm365_pll_obsclk_parent_names,
+       .num_parents = ARRAY_SIZE(dm365_pll_obsclk_parent_names),
+       .table = dm365_pll_obsclk_table,
+       .ocsrc_mask = BIT(4),
+};
+
+int dm365_pll2_init(struct device *dev, void __iomem *base)
+{
+       struct clk *clk;
+
+       davinci_pll_clk_register(dev, &dm365_pll2_info, "oscin", base);
+
+       davinci_pll_sysclk_register(dev, &pll2_sysclk1, base);
+
+       clk = davinci_pll_sysclk_register(dev, &pll2_sysclk2, base);
+       clk_register_clkdev(clk, "pll1_sysclk2", "dm365-psc");
+
+       davinci_pll_sysclk_register(dev, &pll2_sysclk3, base);
+
+       clk = davinci_pll_sysclk_register(dev, &pll2_sysclk4, base);
+       clk_register_clkdev(clk, "pll1_sysclk4", "dm365-psc");
+
+       davinci_pll_sysclk_register(dev, &pll2_sysclk5, base);
+
+       davinci_pll_auxclk_register(dev, "pll2_auxclk", base);
+
+       davinci_pll_obsclk_register(dev, &dm365_pll2_obsclk_info, base);
+
+       return 0;
+}
diff --git a/drivers/clk/davinci/pll-dm644x.c b/drivers/clk/davinci/pll-dm644x.c
new file mode 100644 (file)
index 0000000..69bf785
--- /dev/null
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLL clock descriptions for TI DM644X
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/clkdev.h>
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include "pll.h"
+
+static const struct davinci_pll_clk_info dm644x_pll1_info = {
+       .name = "pll1",
+       .pllm_mask = GENMASK(4, 0),
+       .pllm_min = 1,
+       .pllm_max = 32,
+       .pllout_min_rate = 400000000,
+       .pllout_max_rate = 600000000, /* 810MHz @ 1.3V, -810 only */
+       .flags = PLL_HAS_CLKMODE | PLL_HAS_POSTDIV,
+};
+
+SYSCLK(1, pll1_sysclk1, pll1_pllen, 4, SYSCLK_FIXED_DIV);
+SYSCLK(2, pll1_sysclk2, pll1_pllen, 4, SYSCLK_FIXED_DIV);
+SYSCLK(3, pll1_sysclk3, pll1_pllen, 4, SYSCLK_FIXED_DIV);
+SYSCLK(5, pll1_sysclk5, pll1_pllen, 4, SYSCLK_FIXED_DIV);
+
+int dm644x_pll1_init(struct device *dev, void __iomem *base)
+{
+       struct clk *clk;
+
+       davinci_pll_clk_register(dev, &dm644x_pll1_info, "ref_clk", base);
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base);
+       clk_register_clkdev(clk, "pll1_sysclk1", "dm644x-psc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk2, base);
+       clk_register_clkdev(clk, "pll1_sysclk2", "dm644x-psc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk3, base);
+       clk_register_clkdev(clk, "pll1_sysclk3", "dm644x-psc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk5, base);
+       clk_register_clkdev(clk, "pll1_sysclk5", "dm644x-psc");
+
+       clk = davinci_pll_auxclk_register(dev, "pll1_auxclk", base);
+       clk_register_clkdev(clk, "pll1_auxclk", "dm644x-psc");
+
+       davinci_pll_sysclkbp_clk_register(dev, "pll1_sysclkbp", base);
+
+       return 0;
+}
+
+static const struct davinci_pll_clk_info dm644x_pll2_info = {
+       .name = "pll2",
+       .pllm_mask = GENMASK(4, 0),
+       .pllm_min = 1,
+       .pllm_max = 32,
+       .pllout_min_rate = 400000000,
+       .pllout_max_rate = 900000000,
+       .flags = PLL_HAS_POSTDIV | PLL_POSTDIV_FIXED_DIV,
+};
+
+SYSCLK(1, pll2_sysclk1, pll2_pllen, 4, 0);
+SYSCLK(2, pll2_sysclk2, pll2_pllen, 4, 0);
+
+int dm644x_pll2_init(struct device *dev, void __iomem *base)
+{
+       davinci_pll_clk_register(dev, &dm644x_pll2_info, "oscin", base);
+
+       davinci_pll_sysclk_register(dev, &pll2_sysclk1, base);
+
+       davinci_pll_sysclk_register(dev, &pll2_sysclk2, base);
+
+       davinci_pll_sysclkbp_clk_register(dev, "pll2_sysclkbp", base);
+
+       return 0;
+}
diff --git a/drivers/clk/davinci/pll-dm646x.c b/drivers/clk/davinci/pll-dm646x.c
new file mode 100644 (file)
index 0000000..a61cc32
--- /dev/null
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLL clock descriptions for TI DM646X
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include "pll.h"
+
+static const struct davinci_pll_clk_info dm646x_pll1_info = {
+       .name = "pll1",
+       .pllm_mask = GENMASK(4, 0),
+       .pllm_min = 14,
+       .pllm_max = 32,
+       .flags = PLL_HAS_CLKMODE,
+};
+
+SYSCLK(1, pll1_sysclk1, pll1_pllen, 4, SYSCLK_FIXED_DIV);
+SYSCLK(2, pll1_sysclk2, pll1_pllen, 4, SYSCLK_FIXED_DIV);
+SYSCLK(3, pll1_sysclk3, pll1_pllen, 4, SYSCLK_FIXED_DIV);
+SYSCLK(4, pll1_sysclk4, pll1_pllen, 4, 0);
+SYSCLK(5, pll1_sysclk5, pll1_pllen, 4, 0);
+SYSCLK(6, pll1_sysclk6, pll1_pllen, 4, 0);
+SYSCLK(8, pll1_sysclk8, pll1_pllen, 4, 0);
+SYSCLK(9, pll1_sysclk9, pll1_pllen, 4, 0);
+
+int dm646x_pll1_init(struct device *dev, void __iomem *base)
+{
+       struct clk *clk;
+
+       davinci_pll_clk_register(dev, &dm646x_pll1_info, "ref_clk", base);
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base);
+       clk_register_clkdev(clk, "pll1_sysclk1", "dm646x-psc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk2, base);
+       clk_register_clkdev(clk, "pll1_sysclk2", "dm646x-psc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk3, base);
+       clk_register_clkdev(clk, "pll1_sysclk3", "dm646x-psc");
+       clk_register_clkdev(clk, NULL, "davinci-wdt");
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk4, base);
+       clk_register_clkdev(clk, "pll1_sysclk4", "dm646x-psc");
+
+       clk = davinci_pll_sysclk_register(dev, &pll1_sysclk5, base);
+       clk_register_clkdev(clk, "pll1_sysclk5", "dm646x-psc");
+
+       davinci_pll_sysclk_register(dev, &pll1_sysclk6, base);
+
+       davinci_pll_sysclk_register(dev, &pll1_sysclk8, base);
+
+       davinci_pll_sysclk_register(dev, &pll1_sysclk9, base);
+
+       davinci_pll_sysclkbp_clk_register(dev, "pll1_sysclkbp", base);
+
+       davinci_pll_auxclk_register(dev, "pll1_auxclk", base);
+
+       return 0;
+}
+
+static const struct davinci_pll_clk_info dm646x_pll2_info = {
+       .name = "pll2",
+       .pllm_mask = GENMASK(4, 0),
+       .pllm_min = 14,
+       .pllm_max = 32,
+       .flags = 0,
+};
+
+SYSCLK(1, pll2_sysclk1, pll2_pllen, 4, 0);
+
+int dm646x_pll2_init(struct device *dev, void __iomem *base)
+{
+       davinci_pll_clk_register(dev, &dm646x_pll2_info, "oscin", base);
+
+       davinci_pll_sysclk_register(dev, &pll2_sysclk1, base);
+
+       return 0;
+}
diff --git a/drivers/clk/davinci/pll.c b/drivers/clk/davinci/pll.c
new file mode 100644 (file)
index 0000000..23a24c9
--- /dev/null
@@ -0,0 +1,899 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLL clock driver for TI Davinci SoCs
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ *
+ * Based on arch/arm/mach-davinci/clock.c
+ * Copyright (C) 2006-2007 Texas Instruments.
+ * Copyright (C) 2008-2009 Deep Root Systems, LLC
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/notifier.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_data/clk-davinci-pll.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "pll.h"
+
+#define MAX_NAME_SIZE  20
+#define OSCIN_CLK_NAME "oscin"
+
+#define REVID          0x000
+#define PLLCTL         0x100
+#define OCSEL          0x104
+#define PLLSECCTL      0x108
+#define PLLM           0x110
+#define PREDIV         0x114
+#define PLLDIV1                0x118
+#define PLLDIV2                0x11c
+#define PLLDIV3                0x120
+#define OSCDIV         0x124
+#define POSTDIV                0x128
+#define BPDIV          0x12c
+#define PLLCMD         0x138
+#define PLLSTAT                0x13c
+#define ALNCTL         0x140
+#define DCHANGE                0x144
+#define CKEN           0x148
+#define CKSTAT         0x14c
+#define SYSTAT         0x150
+#define PLLDIV4                0x160
+#define PLLDIV5                0x164
+#define PLLDIV6                0x168
+#define PLLDIV7                0x16c
+#define PLLDIV8                0x170
+#define PLLDIV9                0x174
+
+#define PLLCTL_PLLEN           BIT(0)
+#define PLLCTL_PLLPWRDN                BIT(1)
+#define PLLCTL_PLLRST          BIT(3)
+#define PLLCTL_PLLDIS          BIT(4)
+#define PLLCTL_PLLENSRC                BIT(5)
+#define PLLCTL_CLKMODE         BIT(8)
+
+/* shared by most *DIV registers */
+#define DIV_RATIO_SHIFT                0
+#define DIV_RATIO_WIDTH                5
+#define DIV_ENABLE_SHIFT       15
+
+#define PLLCMD_GOSET           BIT(0)
+#define PLLSTAT_GOSTAT         BIT(0)
+
+#define CKEN_OBSCLK_SHIFT      1
+#define CKEN_AUXEN_SHIFT       0
+
+/*
+ * OMAP-L138 system reference guide recommends a wait for 4 OSCIN/CLKIN
+ * cycles to ensure that the PLLC has switched to bypass mode. Delay of 1us
+ * ensures we are good for all > 4MHz OSCIN/CLKIN inputs. Typically the input
+ * is ~25MHz. Units are micro seconds.
+ */
+#define PLL_BYPASS_TIME                1
+
+/* From OMAP-L138 datasheet table 6-4. Units are micro seconds */
+#define PLL_RESET_TIME         1
+
+/*
+ * From OMAP-L138 datasheet table 6-4; assuming prediv = 1, sqrt(pllm) = 4
+ * Units are micro seconds.
+ */
+#define PLL_LOCK_TIME          20
+
+/**
+ * struct davinci_pll_clk - Main PLL clock (aka PLLOUT)
+ * @hw: clk_hw for the pll
+ * @base: Base memory address
+ * @pllm_min: The minimum allowable PLLM[PLLM] value
+ * @pllm_max: The maxiumum allowable PLLM[PLLM] value
+ * @pllm_mask: Bitmask for PLLM[PLLM] value
+ */
+struct davinci_pll_clk {
+       struct clk_hw hw;
+       void __iomem *base;
+       u32 pllm_min;
+       u32 pllm_max;
+       u32 pllm_mask;
+};
+
+#define to_davinci_pll_clk(_hw) \
+       container_of((_hw), struct davinci_pll_clk, hw)
+
+static unsigned long davinci_pll_recalc_rate(struct clk_hw *hw,
+                                            unsigned long parent_rate)
+{
+       struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
+       unsigned long rate = parent_rate;
+       u32 mult;
+
+       mult = readl(pll->base + PLLM) & pll->pllm_mask;
+       rate *= mult + 1;
+
+       return rate;
+}
+
+static int davinci_pll_determine_rate(struct clk_hw *hw,
+                                     struct clk_rate_request *req)
+{
+       struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
+       struct clk_hw *parent = req->best_parent_hw;
+       unsigned long parent_rate = req->best_parent_rate;
+       unsigned long rate = req->rate;
+       unsigned long best_rate, r;
+       u32 mult;
+
+       /* there is a limited range of valid outputs (see datasheet) */
+       if (rate < req->min_rate)
+               return -EINVAL;
+
+       rate = min(rate, req->max_rate);
+       mult = rate / parent_rate;
+       best_rate = parent_rate * mult;
+
+       /* easy case when there is no PREDIV */
+       if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
+               if (best_rate < req->min_rate)
+                       return -EINVAL;
+
+               if (mult < pll->pllm_min || mult > pll->pllm_max)
+                       return -EINVAL;
+
+               req->rate = best_rate;
+
+               return 0;
+       }
+
+       /* see if the PREDIV clock can help us */
+       best_rate = 0;
+
+       for (mult = pll->pllm_min; mult <= pll->pllm_max; mult++) {
+               parent_rate = clk_hw_round_rate(parent, rate / mult);
+               r = parent_rate * mult;
+               if (r < req->min_rate)
+                       continue;
+               if (r > rate || r > req->max_rate)
+                       break;
+               if (r > best_rate) {
+                       best_rate = r;
+                       req->rate = best_rate;
+                       req->best_parent_rate = parent_rate;
+                       if (best_rate == rate)
+                               break;
+               }
+       }
+
+       return 0;
+}
+
+static int davinci_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
+       u32 mult;
+
+       mult = rate / parent_rate;
+       writel(mult - 1, pll->base + PLLM);
+
+       return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int davinci_pll_debug_init(struct clk_hw *hw, struct dentry *dentry);
+#else
+#define davinci_pll_debug_init NULL
+#endif
+
+static const struct clk_ops davinci_pll_ops = {
+       .recalc_rate    = davinci_pll_recalc_rate,
+       .determine_rate = davinci_pll_determine_rate,
+       .set_rate       = davinci_pll_set_rate,
+       .debug_init     = davinci_pll_debug_init,
+};
+
+/* PLLM works differently on DM365 */
+static unsigned long dm365_pll_recalc_rate(struct clk_hw *hw,
+                                          unsigned long parent_rate)
+{
+       struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
+       unsigned long rate = parent_rate;
+       u32 mult;
+
+       mult = readl(pll->base + PLLM) & pll->pllm_mask;
+       rate *= mult * 2;
+
+       return rate;
+}
+
+static const struct clk_ops dm365_pll_ops = {
+       .recalc_rate    = dm365_pll_recalc_rate,
+       .debug_init     = davinci_pll_debug_init,
+};
+
+/**
+ * davinci_pll_div_register - common *DIV clock implementation
+ * @name: the clock name
+ * @parent_name: the parent clock name
+ * @reg: the *DIV register
+ * @fixed: if true, the divider is a fixed value
+ * @flags: bitmap of CLK_* flags from clock-provider.h
+ */
+static struct clk *davinci_pll_div_register(struct device *dev,
+                                           const char *name,
+                                           const char *parent_name,
+                                           void __iomem *reg,
+                                           bool fixed, u32 flags)
+{
+       const char * const *parent_names = parent_name ? &parent_name : NULL;
+       int num_parents = parent_name ? 1 : 0;
+       const struct clk_ops *divider_ops = &clk_divider_ops;
+       struct clk_gate *gate;
+       struct clk_divider *divider;
+
+       gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
+       if (!gate)
+               return ERR_PTR(-ENOMEM);
+
+       gate->reg = reg;
+       gate->bit_idx = DIV_ENABLE_SHIFT;
+
+       divider = devm_kzalloc(dev, sizeof(*divider), GFP_KERNEL);
+       if (!divider)
+               return ERR_PTR(-ENOMEM);
+
+       divider->reg = reg;
+       divider->shift = DIV_RATIO_SHIFT;
+       divider->width = DIV_RATIO_WIDTH;
+
+       if (fixed) {
+               divider->flags |= CLK_DIVIDER_READ_ONLY;
+               divider_ops = &clk_divider_ro_ops;
+       }
+
+       return clk_register_composite(dev, name, parent_names, num_parents,
+                                     NULL, NULL, &divider->hw, divider_ops,
+                                     &gate->hw, &clk_gate_ops, flags);
+}
+
+struct davinci_pllen_clk {
+       struct clk_hw hw;
+       void __iomem *base;
+};
+
+#define to_davinci_pllen_clk(_hw) \
+       container_of((_hw), struct davinci_pllen_clk, hw)
+
+static const struct clk_ops davinci_pllen_ops = {
+       /* this clocks just uses the clock notification feature */
+};
+
+/*
+ * The PLL has to be switched into bypass mode while we are chaning the rate,
+ * so we do that on the PLLEN clock since it is the end of the line. This will
+ * switch to bypass before any of the parent clocks (PREDIV, PLL, POSTDIV) are
+ * changed and will switch back to the PLL after the changes have been made.
+ */
+static int davinci_pllen_rate_change(struct notifier_block *nb,
+                                    unsigned long flags, void *data)
+{
+       struct clk_notifier_data *cnd = data;
+       struct clk_hw *hw = __clk_get_hw(cnd->clk);
+       struct davinci_pllen_clk *pll = to_davinci_pllen_clk(hw);
+       u32 ctrl;
+
+       ctrl = readl(pll->base + PLLCTL);
+
+       if (flags == PRE_RATE_CHANGE) {
+               /* Switch the PLL to bypass mode */
+               ctrl &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN);
+               writel(ctrl, pll->base + PLLCTL);
+
+               udelay(PLL_BYPASS_TIME);
+
+               /* Reset and enable PLL */
+               ctrl &= ~(PLLCTL_PLLRST | PLLCTL_PLLDIS);
+               writel(ctrl, pll->base + PLLCTL);
+       } else {
+               udelay(PLL_RESET_TIME);
+
+               /* Bring PLL out of reset */
+               ctrl |= PLLCTL_PLLRST;
+               writel(ctrl, pll->base + PLLCTL);
+
+               udelay(PLL_LOCK_TIME);
+
+               /* Remove PLL from bypass mode */
+               ctrl |= PLLCTL_PLLEN;
+               writel(ctrl, pll->base + PLLCTL);
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct davinci_pll_platform_data *davinci_pll_get_pdata(struct device *dev)
+{
+       struct davinci_pll_platform_data *pdata = dev_get_platdata(dev);
+
+       /*
+        * Platform data is optional, so allocate a new struct if one was not
+        * provided. For device tree, this will always be the case.
+        */
+       if (!pdata)
+               pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return NULL;
+
+       /* for device tree, we need to fill in the struct */
+       if (dev->of_node)
+               pdata->cfgchip =
+                       syscon_regmap_lookup_by_compatible("ti,da830-cfgchip");
+
+       return pdata;
+}
+
+static struct notifier_block davinci_pllen_notifier = {
+       .notifier_call = davinci_pllen_rate_change,
+};
+
+/**
+ * davinci_pll_clk_register - Register a PLL clock
+ * @info: The device-specific clock info
+ * @parent_name: The parent clock name
+ * @base: The PLL's memory region
+ *
+ * This creates a series of clocks that represent the PLL.
+ *
+ *     OSCIN > [PREDIV >] PLL > [POSTDIV >] PLLEN
+ *
+ * - OSCIN is the parent clock (on secondary PLL, may come from primary PLL)
+ * - PREDIV and POSTDIV are optional (depends on the PLL controller)
+ * - PLL is the PLL output (aka PLLOUT)
+ * - PLLEN is the bypass multiplexer
+ *
+ * Returns: The PLLOUT clock or a negative error code.
+ */
+struct clk *davinci_pll_clk_register(struct device *dev,
+                                    const struct davinci_pll_clk_info *info,
+                                    const char *parent_name,
+                                    void __iomem *base)
+{
+       struct davinci_pll_platform_data *pdata;
+       char prediv_name[MAX_NAME_SIZE];
+       char pllout_name[MAX_NAME_SIZE];
+       char postdiv_name[MAX_NAME_SIZE];
+       char pllen_name[MAX_NAME_SIZE];
+       struct clk_init_data init;
+       struct davinci_pll_clk *pllout;
+       struct davinci_pllen_clk *pllen;
+       struct clk *pllout_clk, *clk;
+
+       pdata = davinci_pll_get_pdata(dev);
+       if (!pdata)
+               return ERR_PTR(-ENOMEM);
+
+       if (info->flags & PLL_HAS_CLKMODE) {
+               /*
+                * If a PLL has PLLCTL[CLKMODE], then it is the primary PLL.
+                * We register a clock named "oscin" that serves as the internal
+                * "input clock" domain shared by both PLLs (if there are 2)
+                * and will be the parent clock to the AUXCLK, SYSCLKBP and
+                * OBSCLK domains. NB: The various TRMs use "OSCIN" to mean
+                * a number of different things. In this driver we use it to
+                * mean the signal after the PLLCTL[CLKMODE] switch.
+                */
+               clk = clk_register_fixed_factor(dev, OSCIN_CLK_NAME,
+                                               parent_name, 0, 1, 1);
+               if (IS_ERR(clk))
+                       return clk;
+
+               parent_name = OSCIN_CLK_NAME;
+       }
+
+       if (info->flags & PLL_HAS_PREDIV) {
+               bool fixed = info->flags & PLL_PREDIV_FIXED_DIV;
+               u32 flags = 0;
+
+               snprintf(prediv_name, MAX_NAME_SIZE, "%s_prediv", info->name);
+
+               if (info->flags & PLL_PREDIV_ALWAYS_ENABLED)
+                       flags |= CLK_IS_CRITICAL;
+
+               /* Some? DM355 chips don't correctly report the PREDIV value */
+               if (info->flags & PLL_PREDIV_FIXED8)
+                       clk = clk_register_fixed_factor(dev, prediv_name,
+                                               parent_name, flags, 1, 8);
+               else
+                       clk = davinci_pll_div_register(dev, prediv_name,
+                               parent_name, base + PREDIV, fixed, flags);
+               if (IS_ERR(clk))
+                       return clk;
+
+               parent_name = prediv_name;
+       }
+
+       /* Unlock writing to PLL registers */
+       if (info->unlock_reg) {
+               if (IS_ERR_OR_NULL(pdata->cfgchip))
+                       dev_warn(dev, "Failed to get CFGCHIP (%ld)\n",
+                                PTR_ERR(pdata->cfgchip));
+               else
+                       regmap_write_bits(pdata->cfgchip, info->unlock_reg,
+                                         info->unlock_mask, 0);
+       }
+
+       pllout = devm_kzalloc(dev, sizeof(*pllout), GFP_KERNEL);
+       if (!pllout)
+               return ERR_PTR(-ENOMEM);
+
+       snprintf(pllout_name, MAX_NAME_SIZE, "%s_pllout", info->name);
+
+       init.name = pllout_name;
+       if (info->flags & PLL_PLLM_2X)
+               init.ops = &dm365_pll_ops;
+       else
+               init.ops = &davinci_pll_ops;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+       init.flags = 0;
+
+       if (info->flags & PLL_HAS_PREDIV)
+               init.flags |= CLK_SET_RATE_PARENT;
+
+       pllout->hw.init = &init;
+       pllout->base = base;
+       pllout->pllm_mask = info->pllm_mask;
+       pllout->pllm_min = info->pllm_min;
+       pllout->pllm_max = info->pllm_max;
+
+       pllout_clk = devm_clk_register(dev, &pllout->hw);
+       if (IS_ERR(pllout_clk))
+               return pllout_clk;
+
+       clk_hw_set_rate_range(&pllout->hw, info->pllout_min_rate,
+                             info->pllout_max_rate);
+
+       parent_name = pllout_name;
+
+       if (info->flags & PLL_HAS_POSTDIV) {
+               bool fixed = info->flags & PLL_POSTDIV_FIXED_DIV;
+               u32 flags = CLK_SET_RATE_PARENT;
+
+               snprintf(postdiv_name, MAX_NAME_SIZE, "%s_postdiv", info->name);
+
+               if (info->flags & PLL_POSTDIV_ALWAYS_ENABLED)
+                       flags |= CLK_IS_CRITICAL;
+
+               clk = davinci_pll_div_register(dev, postdiv_name, parent_name,
+                                              base + POSTDIV, fixed, flags);
+               if (IS_ERR(clk))
+                       return clk;
+
+               parent_name = postdiv_name;
+       }
+
+       pllen = devm_kzalloc(dev, sizeof(*pllout), GFP_KERNEL);
+       if (!pllen)
+               return ERR_PTR(-ENOMEM);
+
+       snprintf(pllen_name, MAX_NAME_SIZE, "%s_pllen", info->name);
+
+       init.name = pllen_name;
+       init.ops = &davinci_pllen_ops;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+       init.flags = CLK_SET_RATE_PARENT;
+
+       pllen->hw.init = &init;
+       pllen->base = base;
+
+       clk = devm_clk_register(dev, &pllen->hw);
+       if (IS_ERR(clk))
+               return clk;
+
+       clk_notifier_register(clk, &davinci_pllen_notifier);
+
+       return pllout_clk;
+}
+
+/**
+ * davinci_pll_auxclk_register - Register bypass clock (AUXCLK)
+ * @name: The clock name
+ * @base: The PLL memory region
+ */
+struct clk *davinci_pll_auxclk_register(struct device *dev,
+                                       const char *name,
+                                       void __iomem *base)
+{
+       return clk_register_gate(dev, name, OSCIN_CLK_NAME, 0, base + CKEN,
+                                CKEN_AUXEN_SHIFT, 0, NULL);
+}
+
+/**
+ * davinci_pll_sysclkbp_clk_register - Register bypass divider clock (SYSCLKBP)
+ * @name: The clock name
+ * @base: The PLL memory region
+ */
+struct clk *davinci_pll_sysclkbp_clk_register(struct device *dev,
+                                             const char *name,
+                                             void __iomem *base)
+{
+       return clk_register_divider(dev, name, OSCIN_CLK_NAME, 0, base + BPDIV,
+                                   DIV_RATIO_SHIFT, DIV_RATIO_WIDTH,
+                                   CLK_DIVIDER_READ_ONLY, NULL);
+}
+
+/**
+ * davinci_pll_obsclk_register - Register oscillator divider clock (OBSCLK)
+ * @info: The clock info
+ * @base: The PLL memory region
+ */
+struct clk *
+davinci_pll_obsclk_register(struct device *dev,
+                           const struct davinci_pll_obsclk_info *info,
+                           void __iomem *base)
+{
+       struct clk_mux *mux;
+       struct clk_gate *gate;
+       struct clk_divider *divider;
+       u32 oscdiv;
+
+       mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+       if (!mux)
+               return ERR_PTR(-ENOMEM);
+
+       mux->reg = base + OCSEL;
+       mux->table = info->table;
+       mux->mask = info->ocsrc_mask;
+
+       gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
+       if (!gate)
+               return ERR_PTR(-ENOMEM);
+
+       gate->reg = base + CKEN;
+       gate->bit_idx = CKEN_OBSCLK_SHIFT;
+
+       divider = devm_kzalloc(dev, sizeof(*divider), GFP_KERNEL);
+       if (!divider)
+               return ERR_PTR(-ENOMEM);
+
+       divider->reg = base + OSCDIV;
+       divider->shift = DIV_RATIO_SHIFT;
+       divider->width = DIV_RATIO_WIDTH;
+
+       /* make sure divider is enabled just in case bootloader disabled it */
+       oscdiv = readl(base + OSCDIV);
+       oscdiv |= BIT(DIV_ENABLE_SHIFT);
+       writel(oscdiv, base + OSCDIV);
+
+       return clk_register_composite(dev, info->name, info->parent_names,
+                                     info->num_parents,
+                                     &mux->hw, &clk_mux_ops,
+                                     &divider->hw, &clk_divider_ops,
+                                     &gate->hw, &clk_gate_ops, 0);
+}
+
+/* The PLL SYSCLKn clocks have a mechanism for synchronizing rate changes. */
+static int davinci_pll_sysclk_rate_change(struct notifier_block *nb,
+                                         unsigned long flags, void *data)
+{
+       struct clk_notifier_data *cnd = data;
+       struct clk_hw *hw = __clk_get_hw(clk_get_parent(cnd->clk));
+       struct davinci_pllen_clk *pll = to_davinci_pllen_clk(hw);
+       u32 pllcmd, pllstat;
+
+       switch (flags) {
+       case POST_RATE_CHANGE:
+               /* apply the changes */
+               pllcmd = readl(pll->base + PLLCMD);
+               pllcmd |= PLLCMD_GOSET;
+               writel(pllcmd, pll->base + PLLCMD);
+               /* fallthrough */
+       case PRE_RATE_CHANGE:
+               /* Wait until for outstanding changes to take effect */
+               do {
+                       pllstat = readl(pll->base + PLLSTAT);
+               } while (pllstat & PLLSTAT_GOSTAT);
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block davinci_pll_sysclk_notifier = {
+       .notifier_call = davinci_pll_sysclk_rate_change,
+};
+
+/**
+ * davinci_pll_sysclk_register - Register divider clocks (SYSCLKn)
+ * @info: The clock info
+ * @base: The PLL memory region
+ */
+struct clk *
+davinci_pll_sysclk_register(struct device *dev,
+                           const struct davinci_pll_sysclk_info *info,
+                           void __iomem *base)
+{
+       const struct clk_ops *divider_ops = &clk_divider_ops;
+       struct clk_gate *gate;
+       struct clk_divider *divider;
+       struct clk *clk;
+       u32 reg;
+       u32 flags = 0;
+
+       /* PLLDIVn registers are not entirely consecutive */
+       if (info->id < 4)
+               reg = PLLDIV1 + 4 * (info->id - 1);
+       else
+               reg = PLLDIV4 + 4 * (info->id - 4);
+
+       gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
+       if (!gate)
+               return ERR_PTR(-ENOMEM);
+
+       gate->reg = base + reg;
+       gate->bit_idx = DIV_ENABLE_SHIFT;
+
+       divider = devm_kzalloc(dev, sizeof(*divider), GFP_KERNEL);
+       if (!divider)
+               return ERR_PTR(-ENOMEM);
+
+       divider->reg = base + reg;
+       divider->shift = DIV_RATIO_SHIFT;
+       divider->width = info->ratio_width;
+       divider->flags = 0;
+
+       if (info->flags & SYSCLK_FIXED_DIV) {
+               divider->flags |= CLK_DIVIDER_READ_ONLY;
+               divider_ops = &clk_divider_ro_ops;
+       }
+
+       /* Only the ARM clock can change the parent PLL rate */
+       if (info->flags & SYSCLK_ARM_RATE)
+               flags |= CLK_SET_RATE_PARENT;
+
+       if (info->flags & SYSCLK_ALWAYS_ENABLED)
+               flags |= CLK_IS_CRITICAL;
+
+       clk = clk_register_composite(dev, info->name, &info->parent_name, 1,
+                                    NULL, NULL, &divider->hw, divider_ops,
+                                    &gate->hw, &clk_gate_ops, flags);
+       if (IS_ERR(clk))
+               return clk;
+
+       clk_notifier_register(clk, &davinci_pll_sysclk_notifier);
+
+       return clk;
+}
+
+int of_davinci_pll_init(struct device *dev,
+                       const struct davinci_pll_clk_info *info,
+                       const struct davinci_pll_obsclk_info *obsclk_info,
+                       const struct davinci_pll_sysclk_info **div_info,
+                       u8 max_sysclk_id,
+                       void __iomem *base)
+{
+       struct device_node *node = dev->of_node;
+       struct device_node *child;
+       const char *parent_name;
+       struct clk *clk;
+
+       if (info->flags & PLL_HAS_CLKMODE)
+               parent_name = of_clk_get_parent_name(node, 0);
+       else
+               parent_name = OSCIN_CLK_NAME;
+
+       clk = davinci_pll_clk_register(dev, info, parent_name, base);
+       if (IS_ERR(clk)) {
+               dev_err(dev, "failed to register %s\n", info->name);
+               return PTR_ERR(clk);
+       }
+
+       child = of_get_child_by_name(node, "pllout");
+       if (of_device_is_available(child))
+               of_clk_add_provider(child, of_clk_src_simple_get, clk);
+       of_node_put(child);
+
+       child = of_get_child_by_name(node, "sysclk");
+       if (of_device_is_available(child)) {
+               struct clk_onecell_data *clk_data;
+               struct clk **clks;
+               int n_clks =  max_sysclk_id + 1;
+               int i;
+
+               clk_data = devm_kzalloc(dev, sizeof(*clk_data), GFP_KERNEL);
+               if (!clk_data)
+                       return -ENOMEM;
+
+               clks = devm_kmalloc_array(dev, n_clks, sizeof(*clks), GFP_KERNEL);
+               if (!clks)
+                       return -ENOMEM;
+
+               clk_data->clks = clks;
+               clk_data->clk_num = n_clks;
+
+               for (i = 0; i < n_clks; i++)
+                       clks[i] = ERR_PTR(-ENOENT);
+
+               for (; *div_info; div_info++) {
+                       clk = davinci_pll_sysclk_register(dev, *div_info, base);
+                       if (IS_ERR(clk))
+                               dev_warn(dev, "failed to register %s (%ld)\n",
+                                        (*div_info)->name, PTR_ERR(clk));
+                       else
+                               clks[(*div_info)->id] = clk;
+               }
+               of_clk_add_provider(child, of_clk_src_onecell_get, clk_data);
+       }
+       of_node_put(child);
+
+       child = of_get_child_by_name(node, "auxclk");
+       if (of_device_is_available(child)) {
+               char child_name[MAX_NAME_SIZE];
+
+               snprintf(child_name, MAX_NAME_SIZE, "%s_auxclk", info->name);
+
+               clk = davinci_pll_auxclk_register(dev, child_name, base);
+               if (IS_ERR(clk))
+                       dev_warn(dev, "failed to register %s (%ld)\n",
+                                child_name, PTR_ERR(clk));
+               else
+                       of_clk_add_provider(child, of_clk_src_simple_get, clk);
+       }
+       of_node_put(child);
+
+       child = of_get_child_by_name(node, "obsclk");
+       if (of_device_is_available(child)) {
+               if (obsclk_info)
+                       clk = davinci_pll_obsclk_register(dev, obsclk_info, base);
+               else
+                       clk = ERR_PTR(-EINVAL);
+
+               if (IS_ERR(clk))
+                       dev_warn(dev, "failed to register obsclk (%ld)\n",
+                                PTR_ERR(clk));
+               else
+                       of_clk_add_provider(child, of_clk_src_simple_get, clk);
+       }
+       of_node_put(child);
+
+       return 0;
+}
+
+static const struct of_device_id davinci_pll_of_match[] = {
+       { .compatible = "ti,da850-pll0", .data = of_da850_pll0_init },
+       { .compatible = "ti,da850-pll1", .data = of_da850_pll1_init },
+       { }
+};
+
+static const struct platform_device_id davinci_pll_id_table[] = {
+       { .name = "da830-pll",   .driver_data = (kernel_ulong_t)da830_pll_init   },
+       { .name = "da850-pll0",  .driver_data = (kernel_ulong_t)da850_pll0_init  },
+       { .name = "da850-pll1",  .driver_data = (kernel_ulong_t)da850_pll1_init  },
+       { .name = "dm355-pll1",  .driver_data = (kernel_ulong_t)dm355_pll1_init  },
+       { .name = "dm355-pll2",  .driver_data = (kernel_ulong_t)dm355_pll2_init  },
+       { .name = "dm365-pll1",  .driver_data = (kernel_ulong_t)dm365_pll1_init  },
+       { .name = "dm365-pll2",  .driver_data = (kernel_ulong_t)dm365_pll2_init  },
+       { .name = "dm644x-pll1", .driver_data = (kernel_ulong_t)dm644x_pll1_init },
+       { .name = "dm644x-pll2", .driver_data = (kernel_ulong_t)dm644x_pll2_init },
+       { .name = "dm646x-pll1", .driver_data = (kernel_ulong_t)dm646x_pll1_init },
+       { .name = "dm646x-pll2", .driver_data = (kernel_ulong_t)dm646x_pll2_init },
+       { }
+};
+
+typedef int (*davinci_pll_init)(struct device *dev, void __iomem *base);
+
+static int davinci_pll_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       const struct of_device_id *of_id;
+       davinci_pll_init pll_init = NULL;
+       struct resource *res;
+       void __iomem *base;
+
+       of_id = of_match_device(davinci_pll_of_match, dev);
+       if (of_id)
+               pll_init = of_id->data;
+       else if (pdev->id_entry)
+               pll_init = (void *)pdev->id_entry->driver_data;
+
+       if (!pll_init) {
+               dev_err(dev, "unable to find driver data\n");
+               return -EINVAL;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       return pll_init(dev, base);
+}
+
+static struct platform_driver davinci_pll_driver = {
+       .probe          = davinci_pll_probe,
+       .driver         = {
+               .name           = "davinci-pll-clk",
+               .of_match_table = davinci_pll_of_match,
+       },
+       .id_table       = davinci_pll_id_table,
+};
+
+static int __init davinci_pll_driver_init(void)
+{
+       return platform_driver_register(&davinci_pll_driver);
+}
+
+/* has to be postcore_initcall because PSC devices depend on PLL parent clocks */
+postcore_initcall(davinci_pll_driver_init);
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+
+#define DEBUG_REG(n)   \
+{                      \
+       .name   = #n,   \
+       .offset = n,    \
+}
+
+static const struct debugfs_reg32 davinci_pll_regs[] = {
+       DEBUG_REG(REVID),
+       DEBUG_REG(PLLCTL),
+       DEBUG_REG(OCSEL),
+       DEBUG_REG(PLLSECCTL),
+       DEBUG_REG(PLLM),
+       DEBUG_REG(PREDIV),
+       DEBUG_REG(PLLDIV1),
+       DEBUG_REG(PLLDIV2),
+       DEBUG_REG(PLLDIV3),
+       DEBUG_REG(OSCDIV),
+       DEBUG_REG(POSTDIV),
+       DEBUG_REG(BPDIV),
+       DEBUG_REG(PLLCMD),
+       DEBUG_REG(PLLSTAT),
+       DEBUG_REG(ALNCTL),
+       DEBUG_REG(DCHANGE),
+       DEBUG_REG(CKEN),
+       DEBUG_REG(CKSTAT),
+       DEBUG_REG(SYSTAT),
+       DEBUG_REG(PLLDIV4),
+       DEBUG_REG(PLLDIV5),
+       DEBUG_REG(PLLDIV6),
+       DEBUG_REG(PLLDIV7),
+       DEBUG_REG(PLLDIV8),
+       DEBUG_REG(PLLDIV9),
+};
+
+static int davinci_pll_debug_init(struct clk_hw *hw, struct dentry *dentry)
+{
+       struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
+       struct debugfs_regset32 *regset;
+       struct dentry *d;
+
+       regset = kzalloc(sizeof(*regset), GFP_KERNEL);
+       if (!regset)
+               return -ENOMEM;
+
+       regset->regs = davinci_pll_regs;
+       regset->nregs = ARRAY_SIZE(davinci_pll_regs);
+       regset->base = pll->base;
+
+       d = debugfs_create_regset32("registers", 0400, dentry, regset);
+       if (IS_ERR(d)) {
+               kfree(regset);
+               return PTR_ERR(d);
+       }
+
+       return 0;
+}
+#endif
diff --git a/drivers/clk/davinci/pll.h b/drivers/clk/davinci/pll.h
new file mode 100644 (file)
index 0000000..b1b6fb2
--- /dev/null
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Clock driver for TI Davinci PSC controllers
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#ifndef __CLK_DAVINCI_PLL_H___
+#define __CLK_DAVINCI_PLL_H___
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/types.h>
+
+#define PLL_HAS_CLKMODE                        BIT(0) /* PLL has PLLCTL[CLKMODE] */
+#define PLL_HAS_PREDIV                 BIT(1) /* has prediv before PLL */
+#define PLL_PREDIV_ALWAYS_ENABLED      BIT(2) /* don't clear DEN bit */
+#define PLL_PREDIV_FIXED_DIV           BIT(3) /* fixed divider value */
+#define PLL_HAS_POSTDIV                        BIT(4) /* has postdiv after PLL */
+#define PLL_POSTDIV_ALWAYS_ENABLED     BIT(5) /* don't clear DEN bit */
+#define PLL_POSTDIV_FIXED_DIV          BIT(6) /* fixed divider value */
+#define PLL_HAS_EXTCLKSRC              BIT(7) /* has selectable bypass */
+#define PLL_PLLM_2X                    BIT(8) /* PLLM value is 2x (DM365) */
+#define PLL_PREDIV_FIXED8              BIT(9) /* DM355 quirk */
+
+/** davinci_pll_clk_info - controller-specific PLL info
+ * @name: The name of the PLL
+ * @unlock_reg: Option CFGCHIP register for unlocking PLL
+ * @unlock_mask: Bitmask used with @unlock_reg
+ * @pllm_mask: Bitmask for PLLM[PLLM] value
+ * @pllm_min: Minimum allowable value for PLLM[PLLM]
+ * @pllm_max: Maximum allowable value for PLLM[PLLM]
+ * @pllout_min_rate: Minimum allowable rate for PLLOUT
+ * @pllout_max_rate: Maximum allowable rate for PLLOUT
+ * @flags: Bitmap of PLL_* flags.
+ */
+struct davinci_pll_clk_info {
+       const char *name;
+       u32 unlock_reg;
+       u32 unlock_mask;
+       u32 pllm_mask;
+       u32 pllm_min;
+       u32 pllm_max;
+       unsigned long pllout_min_rate;
+       unsigned long pllout_max_rate;
+       u32 flags;
+};
+
+#define SYSCLK_ARM_RATE                BIT(0) /* Controls ARM rate */
+#define SYSCLK_ALWAYS_ENABLED  BIT(1) /* Or bad things happen */
+#define SYSCLK_FIXED_DIV       BIT(2) /* Fixed divider */
+
+/** davinci_pll_sysclk_info - SYSCLKn-specific info
+ * @name: The name of the clock
+ * @parent_name: The name of the parent clock
+ * @id: "n" in "SYSCLKn"
+ * @ratio_width: Width (in bits) of RATIO in PLLDIVn register
+ * @flags: Bitmap of SYSCLK_* flags.
+ */
+struct davinci_pll_sysclk_info {
+       const char *name;
+       const char *parent_name;
+       u32 id;
+       u32 ratio_width;
+       u32 flags;
+};
+
+#define SYSCLK(i, n, p, w, f)                          \
+static const struct davinci_pll_sysclk_info n = {      \
+       .name           = #n,                           \
+       .parent_name    = #p,                           \
+       .id             = (i),                          \
+       .ratio_width    = (w),                          \
+       .flags          = (f),                          \
+}
+
+/** davinci_pll_obsclk_info - OBSCLK-specific info
+ * @name: The name of the clock
+ * @parent_names: Array of names of the parent clocks
+ * @num_parents: Length of @parent_names
+ * @table: Array of values to write to OCSEL[OCSRC] cooresponding to
+ *         @parent_names
+ * @ocsrc_mask: Bitmask for OCSEL[OCSRC]
+ */
+struct davinci_pll_obsclk_info {
+       const char *name;
+       const char * const *parent_names;
+       u8 num_parents;
+       u32 *table;
+       u32 ocsrc_mask;
+};
+
+struct clk *davinci_pll_clk_register(struct device *dev,
+                                    const struct davinci_pll_clk_info *info,
+                                    const char *parent_name,
+                                    void __iomem *base);
+struct clk *davinci_pll_auxclk_register(struct device *dev,
+                                       const char *name,
+                                       void __iomem *base);
+struct clk *davinci_pll_sysclkbp_clk_register(struct device *dev,
+                                             const char *name,
+                                             void __iomem *base);
+struct clk *
+davinci_pll_obsclk_register(struct device *dev,
+                           const struct davinci_pll_obsclk_info *info,
+                           void __iomem *base);
+struct clk *
+davinci_pll_sysclk_register(struct device *dev,
+                           const struct davinci_pll_sysclk_info *info,
+                           void __iomem *base);
+
+int of_davinci_pll_init(struct device *dev,
+                       const struct davinci_pll_clk_info *info,
+                       const struct davinci_pll_obsclk_info *obsclk_info,
+                       const struct davinci_pll_sysclk_info **div_info,
+                       u8 max_sysclk_id,
+                       void __iomem *base);
+
+/* Platform-specific callbacks */
+
+int da830_pll_init(struct device *dev, void __iomem *base);
+
+int da850_pll0_init(struct device *dev, void __iomem *base);
+int da850_pll1_init(struct device *dev, void __iomem *base);
+int of_da850_pll0_init(struct device *dev, void __iomem *base);
+int of_da850_pll1_init(struct device *dev, void __iomem *base);
+
+int dm355_pll1_init(struct device *dev, void __iomem *base);
+int dm355_pll2_init(struct device *dev, void __iomem *base);
+
+int dm365_pll1_init(struct device *dev, void __iomem *base);
+int dm365_pll2_init(struct device *dev, void __iomem *base);
+
+int dm644x_pll1_init(struct device *dev, void __iomem *base);
+int dm644x_pll2_init(struct device *dev, void __iomem *base);
+
+int dm646x_pll1_init(struct device *dev, void __iomem *base);
+int dm646x_pll2_init(struct device *dev, void __iomem *base);
+
+#endif /* __CLK_DAVINCI_PLL_H___ */
diff --git a/drivers/clk/davinci/psc-da830.c b/drivers/clk/davinci/psc-da830.c
new file mode 100644 (file)
index 0000000..f61abf5
--- /dev/null
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PSC clock descriptions for TI DA830/OMAP-L137/AM17XX
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include "psc.h"
+
+LPSC_CLKDEV1(spi0_clkdev,      NULL,   "spi_davinci.0");
+LPSC_CLKDEV1(mmcsd_clkdev,     NULL,   "da830-mmc.0");
+LPSC_CLKDEV1(uart0_clkdev,     NULL,   "serial8250.0");
+
+static const struct davinci_lpsc_clk_info da830_psc0_info[] = {
+       LPSC(0,  0, tpcc,     pll0_sysclk2, NULL,         LPSC_ALWAYS_ENABLED),
+       LPSC(1,  0, tptc0,    pll0_sysclk2, NULL,         LPSC_ALWAYS_ENABLED),
+       LPSC(2,  0, tptc1,    pll0_sysclk2, NULL,         LPSC_ALWAYS_ENABLED),
+       LPSC(3,  0, aemif,    pll0_sysclk3, NULL,         LPSC_ALWAYS_ENABLED),
+       LPSC(4,  0, spi0,     pll0_sysclk2, spi0_clkdev,  0),
+       LPSC(5,  0, mmcsd,    pll0_sysclk2, mmcsd_clkdev, 0),
+       LPSC(6,  0, aintc,    pll0_sysclk4, NULL,         LPSC_ALWAYS_ENABLED),
+       LPSC(7,  0, arm_rom,  pll0_sysclk2, NULL,         LPSC_ALWAYS_ENABLED),
+       LPSC(8,  0, secu_mgr, pll0_sysclk4, NULL,         LPSC_ALWAYS_ENABLED),
+       LPSC(9,  0, uart0,    pll0_sysclk2, uart0_clkdev, 0),
+       LPSC(10, 0, scr0_ss,  pll0_sysclk2, NULL,         LPSC_ALWAYS_ENABLED),
+       LPSC(11, 0, scr1_ss,  pll0_sysclk2, NULL,         LPSC_ALWAYS_ENABLED),
+       LPSC(12, 0, scr2_ss,  pll0_sysclk2, NULL,         LPSC_ALWAYS_ENABLED),
+       LPSC(13, 0, pruss,    pll0_sysclk2, NULL,         LPSC_ALWAYS_ENABLED),
+       LPSC(14, 0, arm,      pll0_sysclk6, NULL,         LPSC_ALWAYS_ENABLED),
+       { }
+};
+
+static int da830_psc0_init(struct device *dev, void __iomem *base)
+{
+       return davinci_psc_register_clocks(dev, da830_psc0_info, 16, base);
+}
+
+static struct clk_bulk_data da830_psc0_parent_clks[] = {
+       { .id = "pll0_sysclk2" },
+       { .id = "pll0_sysclk3" },
+       { .id = "pll0_sysclk4" },
+       { .id = "pll0_sysclk6" },
+};
+
+const struct davinci_psc_init_data da830_psc0_init_data = {
+       .parent_clks            = da830_psc0_parent_clks,
+       .num_parent_clks        = ARRAY_SIZE(da830_psc0_parent_clks),
+       .psc_init               = &da830_psc0_init,
+};
+
+LPSC_CLKDEV2(usb0_clkdev,      NULL,   "musb-da8xx",
+                               NULL,   "cppi41-dmaengine");
+LPSC_CLKDEV1(usb1_clkdev,      NULL,   "ohci-da8xx");
+/* REVISIT: gpio-davinci.c should be modified to drop con_id */
+LPSC_CLKDEV1(gpio_clkdev,      "gpio", NULL);
+LPSC_CLKDEV2(emac_clkdev,      NULL,   "davinci_emac.1",
+                               "fck",  "davinci_mdio.0");
+LPSC_CLKDEV1(mcasp0_clkdev,    NULL,   "davinci-mcasp.0");
+LPSC_CLKDEV1(mcasp1_clkdev,    NULL,   "davinci-mcasp.1");
+LPSC_CLKDEV1(mcasp2_clkdev,    NULL,   "davinci-mcasp.2");
+LPSC_CLKDEV1(spi1_clkdev,      NULL,   "spi_davinci.1");
+LPSC_CLKDEV1(i2c1_clkdev,      NULL,   "i2c_davinci.2");
+LPSC_CLKDEV1(uart1_clkdev,     NULL,   "serial8250.1");
+LPSC_CLKDEV1(uart2_clkdev,     NULL,   "serial8250.2");
+LPSC_CLKDEV1(lcdc_clkdev,      "fck",  "da8xx_lcdc.0");
+LPSC_CLKDEV2(pwm_clkdev,       "fck",  "ehrpwm.0",
+                               "fck",  "ehrpwm.1");
+LPSC_CLKDEV3(ecap_clkdev,      "fck",  "ecap.0",
+                               "fck",  "ecap.1",
+                               "fck",  "ecap.2");
+LPSC_CLKDEV2(eqep_clkdev,      NULL,   "eqep.0",
+                               NULL,   "eqep.1");
+
+static const struct davinci_lpsc_clk_info da830_psc1_info[] = {
+       LPSC(1,  0, usb0,   pll0_sysclk2, usb0_clkdev,   0),
+       LPSC(2,  0, usb1,   pll0_sysclk4, usb1_clkdev,   0),
+       LPSC(3,  0, gpio,   pll0_sysclk4, gpio_clkdev,   0),
+       LPSC(5,  0, emac,   pll0_sysclk4, emac_clkdev,   0),
+       LPSC(6,  0, emif3,  pll0_sysclk5, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(7,  0, mcasp0, pll0_sysclk2, mcasp0_clkdev, 0),
+       LPSC(8,  0, mcasp1, pll0_sysclk2, mcasp1_clkdev, 0),
+       LPSC(9,  0, mcasp2, pll0_sysclk2, mcasp2_clkdev, 0),
+       LPSC(10, 0, spi1,   pll0_sysclk2, spi1_clkdev,   0),
+       LPSC(11, 0, i2c1,   pll0_sysclk4, i2c1_clkdev,   0),
+       LPSC(12, 0, uart1,  pll0_sysclk2, uart1_clkdev,  0),
+       LPSC(13, 0, uart2,  pll0_sysclk2, uart2_clkdev,  0),
+       LPSC(16, 0, lcdc,   pll0_sysclk2, lcdc_clkdev,   0),
+       LPSC(17, 0, pwm,    pll0_sysclk2, pwm_clkdev,    0),
+       LPSC(20, 0, ecap,   pll0_sysclk2, ecap_clkdev,   0),
+       LPSC(21, 0, eqep,   pll0_sysclk2, eqep_clkdev,   0),
+       { }
+};
+
+static int da830_psc1_init(struct device *dev, void __iomem *base)
+{
+       return davinci_psc_register_clocks(dev, da830_psc1_info, 32, base);
+}
+
+static struct clk_bulk_data da830_psc1_parent_clks[] = {
+       { .id = "pll0_sysclk2" },
+       { .id = "pll0_sysclk4" },
+       { .id = "pll0_sysclk5" },
+};
+
+const struct davinci_psc_init_data da830_psc1_init_data = {
+       .parent_clks            = da830_psc1_parent_clks,
+       .num_parent_clks        = ARRAY_SIZE(da830_psc1_parent_clks),
+       .psc_init               = &da830_psc1_init,
+};
diff --git a/drivers/clk/davinci/psc-da850.c b/drivers/clk/davinci/psc-da850.c
new file mode 100644 (file)
index 0000000..d196dcb
--- /dev/null
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PSC clock descriptions for TI DA850/OMAP-L138/AM18XX
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/reset-controller.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/types.h>
+
+#include "psc.h"
+
+LPSC_CLKDEV2(emifa_clkdev,     NULL,           "ti-aemif",
+                               "aemif",        "davinci_nand.0");
+LPSC_CLKDEV1(spi0_clkdev,      NULL,           "spi_davinci.0");
+LPSC_CLKDEV1(mmcsd0_clkdev,    NULL,           "da830-mmc.0");
+LPSC_CLKDEV1(uart0_clkdev,     NULL,           "serial8250.0");
+/* REVISIT: used dev_id instead of con_id */
+LPSC_CLKDEV1(arm_clkdev,       "arm",          NULL);
+LPSC_CLKDEV1(dsp_clkdev,       NULL,           "davinci-rproc.0");
+
+static const struct davinci_lpsc_clk_info da850_psc0_info[] = {
+       LPSC(0,  0, tpcc0,   pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(1,  0, tptc0,   pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(2,  0, tptc1,   pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(3,  0, emifa,   async1,       emifa_clkdev,  0),
+       LPSC(4,  0, spi0,    pll0_sysclk2, spi0_clkdev,   0),
+       LPSC(5,  0, mmcsd0,  pll0_sysclk2, mmcsd0_clkdev, 0),
+       LPSC(6,  0, aintc,   pll0_sysclk4, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(7,  0, arm_rom, pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(9,  0, uart0,   pll0_sysclk2, uart0_clkdev,  0),
+       LPSC(13, 0, pruss,   pll0_sysclk2, NULL,          0),
+       LPSC(14, 0, arm,     pll0_sysclk6, arm_clkdev,    LPSC_ALWAYS_ENABLED | LPSC_SET_RATE_PARENT),
+       LPSC(15, 1, dsp,     pll0_sysclk1, dsp_clkdev,    LPSC_FORCE | LPSC_LOCAL_RESET),
+       { }
+};
+
+LPSC_CLKDEV3(usb0_clkdev,      "fck",  "da830-usb-phy-clks",
+                               NULL,   "musb-da8xx",
+                               NULL,   "cppi41-dmaengine");
+LPSC_CLKDEV1(usb1_clkdev,      NULL,   "ohci-da8xx");
+/* REVISIT: gpio-davinci.c should be modified to drop con_id */
+LPSC_CLKDEV1(gpio_clkdev,      "gpio", NULL);
+LPSC_CLKDEV2(emac_clkdev,      NULL,   "davinci_emac.1",
+                               "fck",  "davinci_mdio.0");
+LPSC_CLKDEV1(mcasp0_clkdev,    NULL,   "davinci-mcasp.0");
+LPSC_CLKDEV1(sata_clkdev,      "fck",  "ahci_da850");
+LPSC_CLKDEV1(vpif_clkdev,      NULL,   "vpif");
+LPSC_CLKDEV1(spi1_clkdev,      NULL,   "spi_davinci.1");
+LPSC_CLKDEV1(i2c1_clkdev,      NULL,   "i2c_davinci.2");
+LPSC_CLKDEV1(uart1_clkdev,     NULL,   "serial8250.1");
+LPSC_CLKDEV1(uart2_clkdev,     NULL,   "serial8250.2");
+LPSC_CLKDEV1(mcbsp0_clkdev,    NULL,   "davinci-mcbsp.0");
+LPSC_CLKDEV1(mcbsp1_clkdev,    NULL,   "davinci-mcbsp.1");
+LPSC_CLKDEV1(lcdc_clkdev,      "fck",  "da8xx_lcdc.0");
+LPSC_CLKDEV3(ehrpwm_clkdev,    "fck",  "ehrpwm.0",
+                               "fck",  "ehrpwm.1",
+                               NULL,   "da830-tbclksync");
+LPSC_CLKDEV1(mmcsd1_clkdev,    NULL,   "da830-mmc.1");
+LPSC_CLKDEV3(ecap_clkdev,      "fck",  "ecap.0",
+                               "fck",  "ecap.1",
+                               "fck",  "ecap.2");
+
+static struct reset_control_lookup da850_psc0_reset_lookup_table[] = {
+       RESET_LOOKUP("da850-psc0", 15, "davinci-rproc.0", NULL),
+};
+
+static int da850_psc0_init(struct device *dev, void __iomem *base)
+{
+       reset_controller_add_lookup(da850_psc0_reset_lookup_table,
+                                   ARRAY_SIZE(da850_psc0_reset_lookup_table));
+       return davinci_psc_register_clocks(dev, da850_psc0_info, 16, base);
+}
+
+static int of_da850_psc0_init(struct device *dev, void __iomem *base)
+{
+       return of_davinci_psc_clk_init(dev, da850_psc0_info, 16, base);
+}
+
+static struct clk_bulk_data da850_psc0_parent_clks[] = {
+       { .id = "pll0_sysclk1" },
+       { .id = "pll0_sysclk2" },
+       { .id = "pll0_sysclk4" },
+       { .id = "pll0_sysclk6" },
+       { .id = "async1"       },
+};
+
+const struct davinci_psc_init_data da850_psc0_init_data = {
+       .parent_clks            = da850_psc0_parent_clks,
+       .num_parent_clks        = ARRAY_SIZE(da850_psc0_parent_clks),
+       .psc_init               = &da850_psc0_init,
+};
+
+const struct davinci_psc_init_data of_da850_psc0_init_data = {
+       .parent_clks            = da850_psc0_parent_clks,
+       .num_parent_clks        = ARRAY_SIZE(da850_psc0_parent_clks),
+       .psc_init               = &of_da850_psc0_init,
+};
+
+static const struct davinci_lpsc_clk_info da850_psc1_info[] = {
+       LPSC(0,  0, tpcc1,  pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(1,  0, usb0,   pll0_sysclk2, usb0_clkdev,   0),
+       LPSC(2,  0, usb1,   pll0_sysclk4, usb1_clkdev,   0),
+       LPSC(3,  0, gpio,   pll0_sysclk4, gpio_clkdev,   0),
+       LPSC(5,  0, emac,   pll0_sysclk4, emac_clkdev,   0),
+       LPSC(6,  0, ddr,    pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(7,  0, mcasp0, async3,       mcasp0_clkdev, 0),
+       LPSC(8,  0, sata,   pll0_sysclk2, sata_clkdev,   LPSC_FORCE),
+       LPSC(9,  0, vpif,   pll0_sysclk2, vpif_clkdev,   0),
+       LPSC(10, 0, spi1,   async3,       spi1_clkdev,   0),
+       LPSC(11, 0, i2c1,   pll0_sysclk4, i2c1_clkdev,   0),
+       LPSC(12, 0, uart1,  async3,       uart1_clkdev,  0),
+       LPSC(13, 0, uart2,  async3,       uart2_clkdev,  0),
+       LPSC(14, 0, mcbsp0, async3,       mcbsp0_clkdev, 0),
+       LPSC(15, 0, mcbsp1, async3,       mcbsp1_clkdev, 0),
+       LPSC(16, 0, lcdc,   pll0_sysclk2, lcdc_clkdev,   0),
+       LPSC(17, 0, ehrpwm, async3,       ehrpwm_clkdev, 0),
+       LPSC(18, 0, mmcsd1, pll0_sysclk2, mmcsd1_clkdev, 0),
+       LPSC(20, 0, ecap,   async3,       ecap_clkdev,   0),
+       LPSC(21, 0, tptc2,  pll0_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
+       { }
+};
+
+static int da850_psc1_init(struct device *dev, void __iomem *base)
+{
+       return davinci_psc_register_clocks(dev, da850_psc1_info, 32, base);
+}
+
+static int of_da850_psc1_init(struct device *dev, void __iomem *base)
+{
+       return of_davinci_psc_clk_init(dev, da850_psc1_info, 32, base);
+}
+
+static struct clk_bulk_data da850_psc1_parent_clks[] = {
+       { .id = "pll0_sysclk2" },
+       { .id = "pll0_sysclk4" },
+       { .id = "async3"       },
+};
+
+const struct davinci_psc_init_data da850_psc1_init_data = {
+       .parent_clks            = da850_psc1_parent_clks,
+       .num_parent_clks        = ARRAY_SIZE(da850_psc1_parent_clks),
+       .psc_init               = &da850_psc1_init,
+};
+
+const struct davinci_psc_init_data of_da850_psc1_init_data = {
+       .parent_clks            = da850_psc1_parent_clks,
+       .num_parent_clks        = ARRAY_SIZE(da850_psc1_parent_clks),
+       .psc_init               = &of_da850_psc1_init,
+};
diff --git a/drivers/clk/davinci/psc-dm355.c b/drivers/clk/davinci/psc-dm355.c
new file mode 100644 (file)
index 0000000..6995ece
--- /dev/null
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PSC clock descriptions for TI DaVinci DM355
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include "psc.h"
+
+LPSC_CLKDEV1(vpss_master_clkdev,       "master",       "vpss");
+LPSC_CLKDEV1(vpss_slave_clkdev,                "slave",        "vpss");
+LPSC_CLKDEV1(spi1_clkdev,              NULL,           "spi_davinci.1");
+LPSC_CLKDEV1(mmcsd1_clkdev,            NULL,           "dm6441-mmc.1");
+LPSC_CLKDEV1(mcbsp1_clkdev,            NULL,           "davinci-mcbsp.1");
+LPSC_CLKDEV1(usb_clkdev,               "usb",          NULL);
+LPSC_CLKDEV1(spi2_clkdev,              NULL,           "spi_davinci.2");
+LPSC_CLKDEV1(aemif_clkdev,             "aemif",        NULL);
+LPSC_CLKDEV1(mmcsd0_clkdev,            NULL,           "dm6441-mmc.0");
+LPSC_CLKDEV1(mcbsp0_clkdev,            NULL,           "davinci-mcbsp.0");
+LPSC_CLKDEV1(i2c_clkdev,               NULL,           "i2c_davinci.1");
+LPSC_CLKDEV1(uart0_clkdev,             NULL,           "serial8250.0");
+LPSC_CLKDEV1(uart1_clkdev,             NULL,           "serial8250.1");
+LPSC_CLKDEV1(uart2_clkdev,             NULL,           "serial8250.2");
+LPSC_CLKDEV1(spi0_clkdev,              NULL,           "spi_davinci.0");
+/* REVISIT: gpio-davinci.c should be modified to drop con_id */
+LPSC_CLKDEV1(gpio_clkdev,              "gpio",         NULL);
+LPSC_CLKDEV1(timer0_clkdev,            "timer0",       NULL);
+LPSC_CLKDEV1(timer2_clkdev,            NULL,           "davinci-wdt");
+LPSC_CLKDEV1(vpss_dac_clkdev,          "vpss_dac",     NULL);
+
+static const struct davinci_lpsc_clk_info dm355_psc_info[] = {
+       LPSC(0,  0, vpss_master, pll1_sysclk4, vpss_master_clkdev, 0),
+       LPSC(1,  0, vpss_slave,  pll1_sysclk4, vpss_slave_clkdev,  0),
+       LPSC(5,  0, timer3,      pll1_auxclk,  NULL,               0),
+       LPSC(6,  0, spi1,        pll1_sysclk2, spi1_clkdev,        0),
+       LPSC(7,  0, mmcsd1,      pll1_sysclk2, mmcsd1_clkdev,      0),
+       LPSC(8,  0, asp1,        pll1_sysclk2, NULL,               0),
+       LPSC(9,  0, usb,         pll1_sysclk2, usb_clkdev,         0),
+       LPSC(10, 0, pwm3,        pll1_auxclk,  NULL,               0),
+       LPSC(11, 0, spi2,        pll1_sysclk2, spi2_clkdev,        0),
+       LPSC(12, 0, rto,         pll1_auxclk,  NULL,               0),
+       LPSC(14, 0, aemif,       pll1_sysclk2, aemif_clkdev,       0),
+       LPSC(15, 0, mmcsd0,      pll1_sysclk2, mmcsd0_clkdev,      0),
+       LPSC(17, 0, asp0,        pll1_sysclk2, NULL,               0),
+       LPSC(18, 0, i2c,         pll1_auxclk,  i2c_clkdev,         0),
+       LPSC(19, 0, uart0,       pll1_auxclk,  uart0_clkdev,       0),
+       LPSC(20, 0, uart1,       pll1_auxclk,  uart1_clkdev,       0),
+       LPSC(21, 0, uart2,       pll1_sysclk2, uart2_clkdev,       0),
+       LPSC(22, 0, spi0,        pll1_sysclk2, spi0_clkdev,        0),
+       LPSC(23, 0, pwm0,        pll1_auxclk,  NULL,               0),
+       LPSC(24, 0, pwm1,        pll1_auxclk,  NULL,               0),
+       LPSC(25, 0, pwm2,        pll1_auxclk,  NULL,               0),
+       LPSC(26, 0, gpio,        pll1_sysclk2, gpio_clkdev,        0),
+       LPSC(27, 0, timer0,      pll1_auxclk,  timer0_clkdev,      LPSC_ALWAYS_ENABLED),
+       LPSC(28, 0, timer1,      pll1_auxclk,  NULL,               0),
+       /* REVISIT: why can't this be disabled? */
+       LPSC(29, 0, timer2,      pll1_auxclk,  timer2_clkdev,      LPSC_ALWAYS_ENABLED),
+       LPSC(31, 0, arm,         pll1_sysclk1, NULL,               LPSC_ALWAYS_ENABLED),
+       LPSC(40, 0, mjcp,        pll1_sysclk1, NULL,               0),
+       LPSC(41, 0, vpss_dac,    pll1_sysclk3, vpss_dac_clkdev,    0),
+       { }
+};
+
+static int dm355_psc_init(struct device *dev, void __iomem *base)
+{
+       return davinci_psc_register_clocks(dev, dm355_psc_info, 42, base);
+}
+
+static struct clk_bulk_data dm355_psc_parent_clks[] = {
+       { .id = "pll1_sysclk1" },
+       { .id = "pll1_sysclk2" },
+       { .id = "pll1_sysclk3" },
+       { .id = "pll1_sysclk4" },
+       { .id = "pll1_auxclk"  },
+};
+
+const struct davinci_psc_init_data dm355_psc_init_data = {
+       .parent_clks            = dm355_psc_parent_clks,
+       .num_parent_clks        = ARRAY_SIZE(dm355_psc_parent_clks),
+       .psc_init               = &dm355_psc_init,
+};
diff --git a/drivers/clk/davinci/psc-dm365.c b/drivers/clk/davinci/psc-dm365.c
new file mode 100644 (file)
index 0000000..3ad915f
--- /dev/null
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PSC clock descriptions for TI DaVinci DM365
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include "psc.h"
+
+LPSC_CLKDEV1(vpss_slave_clkdev,                "slave",        "vpss");
+LPSC_CLKDEV1(spi1_clkdev,              NULL,           "spi_davinci.1");
+LPSC_CLKDEV1(mmcsd1_clkdev,            NULL,           "da830-mmc.1");
+LPSC_CLKDEV1(asp0_clkdev,              NULL,           "davinci-mcbsp");
+LPSC_CLKDEV1(usb_clkdev,               "usb",          NULL);
+LPSC_CLKDEV1(spi2_clkdev,              NULL,           "spi_davinci.2");
+LPSC_CLKDEV1(aemif_clkdev,             "aemif",        NULL);
+LPSC_CLKDEV1(mmcsd0_clkdev,            NULL,           "da830-mmc.0");
+LPSC_CLKDEV1(i2c_clkdev,               NULL,           "i2c_davinci.1");
+LPSC_CLKDEV1(uart0_clkdev,             NULL,           "serial8250.0");
+LPSC_CLKDEV1(uart1_clkdev,             NULL,           "serial8250.1");
+LPSC_CLKDEV1(spi0_clkdev,              NULL,           "spi_davinci.0");
+/* REVISIT: gpio-davinci.c should be modified to drop con_id */
+LPSC_CLKDEV1(gpio_clkdev,              "gpio",         NULL);
+LPSC_CLKDEV1(timer0_clkdev,            "timer0",       NULL);
+LPSC_CLKDEV1(timer2_clkdev,            NULL,           "davinci-wdt");
+LPSC_CLKDEV1(spi3_clkdev,              NULL,           "spi_davinci.3");
+LPSC_CLKDEV1(spi4_clkdev,              NULL,           "spi_davinci.4");
+LPSC_CLKDEV2(emac_clkdev,              NULL,           "davinci_emac.1",
+                                       "fck",          "davinci_mdio.0");
+LPSC_CLKDEV1(voice_codec_clkdev,       NULL,           "davinci_voicecodec");
+LPSC_CLKDEV1(vpss_dac_clkdev,          "vpss_dac",     NULL);
+LPSC_CLKDEV1(vpss_master_clkdev,       "master",       "vpss");
+
+static const struct davinci_lpsc_clk_info dm365_psc_info[] = {
+       LPSC(1,  0, vpss_slave,  pll1_sysclk5, vpss_slave_clkdev,  0),
+       LPSC(5,  0, timer3,      pll1_auxclk,  NULL,               0),
+       LPSC(6,  0, spi1,        pll1_sysclk4, spi1_clkdev,        0),
+       LPSC(7,  0, mmcsd1,      pll1_sysclk4, mmcsd1_clkdev,      0),
+       LPSC(8,  0, asp0,        pll1_sysclk4, asp0_clkdev,        0),
+       LPSC(9,  0, usb,         pll1_auxclk,  usb_clkdev,         0),
+       LPSC(10, 0, pwm3,        pll1_auxclk,  NULL,               0),
+       LPSC(11, 0, spi2,        pll1_sysclk4, spi2_clkdev,        0),
+       LPSC(12, 0, rto,         pll1_sysclk4, NULL,               0),
+       LPSC(14, 0, aemif,       pll1_sysclk4, aemif_clkdev,       0),
+       LPSC(15, 0, mmcsd0,      pll1_sysclk8, mmcsd0_clkdev,      0),
+       LPSC(18, 0, i2c,         pll1_auxclk,  i2c_clkdev,         0),
+       LPSC(19, 0, uart0,       pll1_auxclk,  uart0_clkdev,       0),
+       LPSC(20, 0, uart1,       pll1_sysclk4, uart1_clkdev,       0),
+       LPSC(22, 0, spi0,        pll1_sysclk4, spi0_clkdev,        0),
+       LPSC(23, 0, pwm0,        pll1_auxclk,  NULL,               0),
+       LPSC(24, 0, pwm1,        pll1_auxclk,  NULL,               0),
+       LPSC(25, 0, pwm2,        pll1_auxclk,  NULL,               0),
+       LPSC(26, 0, gpio,        pll1_sysclk4, gpio_clkdev,        0),
+       LPSC(27, 0, timer0,      pll1_auxclk,  timer0_clkdev,      LPSC_ALWAYS_ENABLED),
+       LPSC(28, 0, timer1,      pll1_auxclk,  NULL,               0),
+       /* REVISIT: why can't this be disabled? */
+       LPSC(29, 0, timer2,      pll1_auxclk,  timer2_clkdev,      LPSC_ALWAYS_ENABLED),
+       LPSC(31, 0, arm,         pll2_sysclk2, NULL,               LPSC_ALWAYS_ENABLED),
+       LPSC(38, 0, spi3,        pll1_sysclk4, spi3_clkdev,        0),
+       LPSC(39, 0, spi4,        pll1_auxclk,  spi4_clkdev,        0),
+       LPSC(40, 0, emac,        pll2_sysclk4, emac_clkdev,        0),
+       LPSC(44, 1, voice_codec, pll1_sysclk3, voice_codec_clkdev, 0),
+       LPSC(46, 1, vpss_dac,    pll1_sysclk3, vpss_dac_clkdev,    0),
+       LPSC(47, 0, vpss_master, pll1_sysclk5, vpss_master_clkdev, 0),
+       LPSC(50, 0, mjcp,        pll1_sysclk3, NULL,               0),
+       { }
+};
+
+static int dm365_psc_init(struct device *dev, void __iomem *base)
+{
+       return davinci_psc_register_clocks(dev, dm365_psc_info, 52, base);
+}
+
+static struct clk_bulk_data dm365_psc_parent_clks[] = {
+       { .id = "pll1_sysclk1" },
+       { .id = "pll1_sysclk3" },
+       { .id = "pll1_sysclk4" },
+       { .id = "pll1_sysclk5" },
+       { .id = "pll1_sysclk8" },
+       { .id = "pll2_sysclk2" },
+       { .id = "pll2_sysclk4" },
+       { .id = "pll1_auxclk"  },
+};
+
+const struct davinci_psc_init_data dm365_psc_init_data = {
+       .parent_clks            = dm365_psc_parent_clks,
+       .num_parent_clks        = ARRAY_SIZE(dm365_psc_parent_clks),
+       .psc_init               = &dm365_psc_init,
+};
diff --git a/drivers/clk/davinci/psc-dm644x.c b/drivers/clk/davinci/psc-dm644x.c
new file mode 100644 (file)
index 0000000..c22367b
--- /dev/null
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PSC clock descriptions for TI DaVinci DM644x
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include "psc.h"
+
+LPSC_CLKDEV1(vpss_master_clkdev,       "master",       "vpss");
+LPSC_CLKDEV1(vpss_slave_clkdev,                "slave",        "vpss");
+LPSC_CLKDEV2(emac_clkdev,              NULL,           "davinci_emac.1",
+                                       "fck",          "davinci_mdio.0");
+LPSC_CLKDEV1(usb_clkdev,               "usb",          NULL);
+LPSC_CLKDEV1(ide_clkdev,               NULL,           "palm_bk3710");
+LPSC_CLKDEV1(aemif_clkdev,             "aemif",        NULL);
+LPSC_CLKDEV1(mmcsd_clkdev,             NULL,           "dm6441-mmc.0");
+LPSC_CLKDEV1(asp0_clkdev,              NULL,           "davinci-mcbsp");
+LPSC_CLKDEV1(i2c_clkdev,               NULL,           "i2c_davinci.1");
+LPSC_CLKDEV1(uart0_clkdev,             NULL,           "serial8250.0");
+LPSC_CLKDEV1(uart1_clkdev,             NULL,           "serial8250.1");
+LPSC_CLKDEV1(uart2_clkdev,             NULL,           "serial8250.2");
+/* REVISIT: gpio-davinci.c should be modified to drop con_id */
+LPSC_CLKDEV1(gpio_clkdev,              "gpio",         NULL);
+LPSC_CLKDEV1(timer0_clkdev,            "timer0",       NULL);
+LPSC_CLKDEV1(timer2_clkdev,            NULL,           "davinci-wdt");
+
+static const struct davinci_lpsc_clk_info dm644x_psc_info[] = {
+       LPSC(0,  0, vpss_master, pll1_sysclk3, vpss_master_clkdev, 0),
+       LPSC(1,  0, vpss_slave,  pll1_sysclk3, vpss_slave_clkdev,  0),
+       LPSC(6,  0, emac,        pll1_sysclk5, emac_clkdev,        0),
+       LPSC(9,  0, usb,         pll1_sysclk5, usb_clkdev,         0),
+       LPSC(10, 0, ide,         pll1_sysclk5, ide_clkdev,         0),
+       LPSC(11, 0, vlynq,       pll1_sysclk5, NULL,               0),
+       LPSC(14, 0, aemif,       pll1_sysclk5, aemif_clkdev,       0),
+       LPSC(15, 0, mmcsd,       pll1_sysclk5, mmcsd_clkdev,       0),
+       LPSC(17, 0, asp0,        pll1_sysclk5, asp0_clkdev,        0),
+       LPSC(18, 0, i2c,         pll1_auxclk,  i2c_clkdev,         0),
+       LPSC(19, 0, uart0,       pll1_auxclk,  uart0_clkdev,       0),
+       LPSC(20, 0, uart1,       pll1_auxclk,  uart1_clkdev,       0),
+       LPSC(21, 0, uart2,       pll1_auxclk,  uart2_clkdev,       0),
+       LPSC(22, 0, spi,         pll1_sysclk5, NULL,               0),
+       LPSC(23, 0, pwm0,        pll1_auxclk,  NULL,               0),
+       LPSC(24, 0, pwm1,        pll1_auxclk,  NULL,               0),
+       LPSC(25, 0, pwm2,        pll1_auxclk,  NULL,               0),
+       LPSC(26, 0, gpio,        pll1_sysclk5, gpio_clkdev,        0),
+       LPSC(27, 0, timer0,      pll1_auxclk,  timer0_clkdev,      LPSC_ALWAYS_ENABLED),
+       LPSC(28, 0, timer1,      pll1_auxclk,  NULL,               0),
+       /* REVISIT: why can't this be disabled? */
+       LPSC(29, 0, timer2,      pll1_auxclk,  timer2_clkdev,      LPSC_ALWAYS_ENABLED),
+       LPSC(31, 0, arm,         pll1_sysclk2, NULL,               LPSC_ALWAYS_ENABLED),
+       /* REVISIT how to disable? */
+       LPSC(39, 1, dsp,         pll1_sysclk1, NULL,               LPSC_ALWAYS_ENABLED),
+       /* REVISIT how to disable? */
+       LPSC(40, 1, vicp,        pll1_sysclk2, NULL,               LPSC_ALWAYS_ENABLED),
+       { }
+};
+
+static int dm644x_psc_init(struct device *dev, void __iomem *base)
+{
+       return davinci_psc_register_clocks(dev, dm644x_psc_info, 41, base);
+}
+
+static struct clk_bulk_data dm644x_psc_parent_clks[] = {
+       { .id = "pll1_sysclk1" },
+       { .id = "pll1_sysclk2" },
+       { .id = "pll1_sysclk3" },
+       { .id = "pll1_sysclk5" },
+       { .id = "pll1_auxclk"  },
+};
+
+const struct davinci_psc_init_data dm644x_psc_init_data = {
+       .parent_clks            = dm644x_psc_parent_clks,
+       .num_parent_clks        = ARRAY_SIZE(dm644x_psc_parent_clks),
+       .psc_init               = &dm644x_psc_init,
+};
diff --git a/drivers/clk/davinci/psc-dm646x.c b/drivers/clk/davinci/psc-dm646x.c
new file mode 100644 (file)
index 0000000..468ef86
--- /dev/null
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PSC clock descriptions for TI DaVinci DM646x
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include "psc.h"
+
+LPSC_CLKDEV1(ide_clkdev,       NULL,           "palm_bk3710");
+LPSC_CLKDEV2(emac_clkdev,      NULL,           "davinci_emac.1",
+                               "fck",          "davinci_mdio.0");
+LPSC_CLKDEV1(aemif_clkdev,     "aemif",        NULL);
+LPSC_CLKDEV1(mcasp0_clkdev,    NULL,           "davinci-mcasp.0");
+LPSC_CLKDEV1(mcasp1_clkdev,    NULL,           "davinci-mcasp.1");
+LPSC_CLKDEV1(uart0_clkdev,     NULL,           "serial8250.0");
+LPSC_CLKDEV1(uart1_clkdev,     NULL,           "serial8250.1");
+LPSC_CLKDEV1(uart2_clkdev,     NULL,           "serial8250.2");
+LPSC_CLKDEV1(i2c_clkdev,       NULL,           "i2c_davinci.1");
+/* REVISIT: gpio-davinci.c should be modified to drop con_id */
+LPSC_CLKDEV1(gpio_clkdev,      "gpio",         NULL);
+LPSC_CLKDEV1(timer0_clkdev,    "timer0",        NULL);
+
+static const struct davinci_lpsc_clk_info dm646x_psc_info[] = {
+       LPSC(0,  0, arm,      pll1_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
+       /* REVISIT how to disable? */
+       LPSC(1,  0, dsp,      pll1_sysclk1, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(4,  0, edma_cc,  pll1_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(5,  0, edma_tc0, pll1_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(6,  0, edma_tc1, pll1_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(7,  0, edma_tc2, pll1_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(8,  0, edma_tc3, pll1_sysclk2, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(10, 0, ide,      pll1_sysclk4, ide_clkdev,    0),
+       LPSC(14, 0, emac,     pll1_sysclk3, emac_clkdev,   0),
+       LPSC(16, 0, vpif0,    ref_clk,      NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(17, 0, vpif1,    ref_clk,      NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(21, 0, aemif,    pll1_sysclk3, aemif_clkdev,  LPSC_ALWAYS_ENABLED),
+       LPSC(22, 0, mcasp0,   pll1_sysclk3, mcasp0_clkdev, 0),
+       LPSC(23, 0, mcasp1,   pll1_sysclk3, mcasp1_clkdev, 0),
+       LPSC(26, 0, uart0,    aux_clkin,    uart0_clkdev,  0),
+       LPSC(27, 0, uart1,    aux_clkin,    uart1_clkdev,  0),
+       LPSC(28, 0, uart2,    aux_clkin,    uart2_clkdev,  0),
+       /* REVIST: disabling hangs system */
+       LPSC(29, 0, pwm0,     pll1_sysclk3, NULL,          LPSC_ALWAYS_ENABLED),
+       /* REVIST: disabling hangs system */
+       LPSC(30, 0, pwm1,     pll1_sysclk3, NULL,          LPSC_ALWAYS_ENABLED),
+       LPSC(31, 0, i2c,      pll1_sysclk3, i2c_clkdev,    0),
+       LPSC(33, 0, gpio,     pll1_sysclk3, gpio_clkdev,   0),
+       LPSC(34, 0, timer0,   pll1_sysclk3, timer0_clkdev, LPSC_ALWAYS_ENABLED),
+       LPSC(35, 0, timer1,   pll1_sysclk3, NULL,          0),
+       { }
+};
+
+static int dm646x_psc_init(struct device *dev, void __iomem *base)
+{
+       return davinci_psc_register_clocks(dev, dm646x_psc_info, 46, base);
+}
+
+static struct clk_bulk_data dm646x_psc_parent_clks[] = {
+       { .id = "ref_clk"      },
+       { .id = "aux_clkin"    },
+       { .id = "pll1_sysclk1" },
+       { .id = "pll1_sysclk2" },
+       { .id = "pll1_sysclk3" },
+       { .id = "pll1_sysclk4" },
+       { .id = "pll1_sysclk5" },
+};
+
+const struct davinci_psc_init_data dm646x_psc_init_data = {
+       .parent_clks            = dm646x_psc_parent_clks,
+       .num_parent_clks        = ARRAY_SIZE(dm646x_psc_parent_clks),
+       .psc_init               = &dm646x_psc_init,
+};
diff --git a/drivers/clk/davinci/psc.c b/drivers/clk/davinci/psc.c
new file mode 100644 (file)
index 0000000..ce170e6
--- /dev/null
@@ -0,0 +1,551 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Clock driver for TI Davinci PSC controllers
+ *
+ * Copyright (C) 2017 David Lechner <david@lechnology.com>
+ *
+ * Based on: drivers/clk/keystone/gate.c
+ * Copyright (C) 2013 Texas Instruments.
+ *     Murali Karicheri <m-karicheri2@ti.com>
+ *     Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * And: arch/arm/mach-davinci/psc.c
+ * Copyright (C) 2006 Texas Instruments.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "psc.h"
+
+/* PSC register offsets */
+#define EPCPR                  0x070
+#define PTCMD                  0x120
+#define PTSTAT                 0x128
+#define PDSTAT(n)              (0x200 + 4 * (n))
+#define PDCTL(n)               (0x300 + 4 * (n))
+#define MDSTAT(n)              (0x800 + 4 * (n))
+#define MDCTL(n)               (0xa00 + 4 * (n))
+
+/* PSC module states */
+enum davinci_lpsc_state {
+       LPSC_STATE_SWRSTDISABLE = 0,
+       LPSC_STATE_SYNCRST      = 1,
+       LPSC_STATE_DISABLE      = 2,
+       LPSC_STATE_ENABLE       = 3,
+};
+
+#define MDSTAT_STATE_MASK      GENMASK(5, 0)
+#define MDSTAT_MCKOUT          BIT(12)
+#define PDSTAT_STATE_MASK      GENMASK(4, 0)
+#define MDCTL_FORCE            BIT(31)
+#define MDCTL_LRESET           BIT(8)
+#define PDCTL_EPCGOOD          BIT(8)
+#define PDCTL_NEXT             BIT(0)
+
+struct davinci_psc_data {
+       struct clk_onecell_data clk_data;
+       struct genpd_onecell_data pm_data;
+       struct reset_controller_dev rcdev;
+};
+
+/**
+ * struct davinci_lpsc_clk - LPSC clock structure
+ * @dev: the device that provides this LPSC
+ * @hw: clk_hw for the LPSC
+ * @pm_domain: power domain for the LPSC
+ * @genpd_clk: clock reference owned by @pm_domain
+ * @regmap: PSC MMIO region
+ * @md: Module domain (LPSC module id)
+ * @pd: Power domain
+ * @flags: LPSC_* quirk flags
+ */
+struct davinci_lpsc_clk {
+       struct device *dev;
+       struct clk_hw hw;
+       struct generic_pm_domain pm_domain;
+       struct clk *genpd_clk;
+       struct regmap *regmap;
+       u32 md;
+       u32 pd;
+       u32 flags;
+};
+
+#define to_davinci_psc_data(x) container_of(x, struct davinci_psc_data, x)
+#define to_davinci_lpsc_clk(x) container_of(x, struct davinci_lpsc_clk, x)
+
+/**
+ * best_dev_name - get the "best" device name.
+ * @dev: the device
+ *
+ * Returns the device tree compatible name if the device has a DT node,
+ * otherwise return the device name. This is mainly needed because clkdev
+ * lookups are limited to 20 chars for dev_id and when using device tree,
+ * dev_name(dev) is much longer than that.
+ */
+static inline const char *best_dev_name(struct device *dev)
+{
+       const char *compatible;
+
+       if (!of_property_read_string(dev->of_node, "compatible", &compatible))
+               return compatible;
+
+       return dev_name(dev);
+}
+
+static void davinci_lpsc_config(struct davinci_lpsc_clk *lpsc,
+                               enum davinci_lpsc_state next_state)
+{
+       u32 epcpr, pdstat, mdstat, ptstat;
+
+       regmap_write_bits(lpsc->regmap, MDCTL(lpsc->md), MDSTAT_STATE_MASK,
+                         next_state);
+
+       if (lpsc->flags & LPSC_FORCE)
+               regmap_write_bits(lpsc->regmap, MDCTL(lpsc->md), MDCTL_FORCE,
+                                 MDCTL_FORCE);
+
+       regmap_read(lpsc->regmap, PDSTAT(lpsc->pd), &pdstat);
+       if ((pdstat & PDSTAT_STATE_MASK) == 0) {
+               regmap_write_bits(lpsc->regmap, PDCTL(lpsc->pd), PDCTL_NEXT,
+                                 PDCTL_NEXT);
+
+               regmap_write(lpsc->regmap, PTCMD, BIT(lpsc->pd));
+
+               regmap_read_poll_timeout(lpsc->regmap, EPCPR, epcpr,
+                                        epcpr & BIT(lpsc->pd), 0, 0);
+
+               regmap_write_bits(lpsc->regmap, PDCTL(lpsc->pd), PDCTL_EPCGOOD,
+                                 PDCTL_EPCGOOD);
+       } else {
+               regmap_write(lpsc->regmap, PTCMD, BIT(lpsc->pd));
+       }
+
+       regmap_read_poll_timeout(lpsc->regmap, PTSTAT, ptstat,
+                                !(ptstat & BIT(lpsc->pd)), 0, 0);
+
+       regmap_read_poll_timeout(lpsc->regmap, MDSTAT(lpsc->md), mdstat,
+                                (mdstat & MDSTAT_STATE_MASK) == next_state,
+                                0, 0);
+}
+
+static int davinci_lpsc_clk_enable(struct clk_hw *hw)
+{
+       struct davinci_lpsc_clk *lpsc = to_davinci_lpsc_clk(hw);
+
+       davinci_lpsc_config(lpsc, LPSC_STATE_ENABLE);
+
+       return 0;
+}
+
+static void davinci_lpsc_clk_disable(struct clk_hw *hw)
+{
+       struct davinci_lpsc_clk *lpsc = to_davinci_lpsc_clk(hw);
+
+       davinci_lpsc_config(lpsc, LPSC_STATE_DISABLE);
+}
+
+static int davinci_lpsc_clk_is_enabled(struct clk_hw *hw)
+{
+       struct davinci_lpsc_clk *lpsc = to_davinci_lpsc_clk(hw);
+       u32 mdstat;
+
+       regmap_read(lpsc->regmap, MDSTAT(lpsc->md), &mdstat);
+
+       return (mdstat & MDSTAT_MCKOUT) ? 1 : 0;
+}
+
+static const struct clk_ops davinci_lpsc_clk_ops = {
+       .enable         = davinci_lpsc_clk_enable,
+       .disable        = davinci_lpsc_clk_disable,
+       .is_enabled     = davinci_lpsc_clk_is_enabled,
+};
+
+static int davinci_psc_genpd_attach_dev(struct generic_pm_domain *pm_domain,
+                                       struct device *dev)
+{
+       struct davinci_lpsc_clk *lpsc = to_davinci_lpsc_clk(pm_domain);
+       struct clk *clk;
+       int ret;
+
+       /*
+        * pm_clk_remove_clk() will call clk_put(), so we have to use clk_get()
+        * to get the clock instead of using lpsc->hw.clk directly.
+        */
+       clk = clk_get_sys(best_dev_name(lpsc->dev), clk_hw_get_name(&lpsc->hw));
+       if (IS_ERR(clk))
+               return (PTR_ERR(clk));
+
+       ret = pm_clk_create(dev);
+       if (ret < 0)
+               goto fail_clk_put;
+
+       ret = pm_clk_add_clk(dev, clk);
+       if (ret < 0)
+               goto fail_pm_clk_destroy;
+
+       lpsc->genpd_clk = clk;
+
+       return 0;
+
+fail_pm_clk_destroy:
+       pm_clk_destroy(dev);
+fail_clk_put:
+       clk_put(clk);
+
+       return ret;
+}
+
+static void davinci_psc_genpd_detach_dev(struct generic_pm_domain *pm_domain,
+                                        struct device *dev)
+{
+       struct davinci_lpsc_clk *lpsc = to_davinci_lpsc_clk(pm_domain);
+
+       pm_clk_remove_clk(dev, lpsc->genpd_clk);
+       pm_clk_destroy(dev);
+
+       lpsc->genpd_clk = NULL;
+}
+
+/**
+ * davinci_lpsc_clk_register - register LPSC clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @regmap: PSC MMIO region
+ * @md: local PSC number
+ * @pd: power domain
+ * @flags: LPSC_* flags
+ */
+static struct davinci_lpsc_clk *
+davinci_lpsc_clk_register(struct device *dev, const char *name,
+                         const char *parent_name, struct regmap *regmap,
+                         u32 md, u32 pd, u32 flags)
+{
+       struct clk_init_data init;
+       struct davinci_lpsc_clk *lpsc;
+       int ret;
+       bool is_on;
+
+       lpsc = devm_kzalloc(dev, sizeof(*lpsc), GFP_KERNEL);
+       if (!lpsc)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &davinci_lpsc_clk_ops;
+       init.parent_names = (parent_name ? &parent_name : NULL);
+       init.num_parents = (parent_name ? 1 : 0);
+       init.flags = 0;
+
+       if (flags & LPSC_ALWAYS_ENABLED)
+               init.flags |= CLK_IS_CRITICAL;
+
+       if (flags & LPSC_SET_RATE_PARENT)
+               init.flags |= CLK_SET_RATE_PARENT;
+
+       lpsc->dev = dev;
+       lpsc->regmap = regmap;
+       lpsc->hw.init = &init;
+       lpsc->md = md;
+       lpsc->pd = pd;
+       lpsc->flags = flags;
+
+       ret = devm_clk_hw_register(dev, &lpsc->hw);
+       if (ret < 0)
+               return ERR_PTR(ret);
+
+       /* genpd attach needs a way to look up this clock */
+       ret = clk_hw_register_clkdev(&lpsc->hw, name, best_dev_name(dev));
+
+       lpsc->pm_domain.name = devm_kasprintf(dev, GFP_KERNEL, "%s: %s",
+                                             best_dev_name(dev), name);
+       lpsc->pm_domain.attach_dev = davinci_psc_genpd_attach_dev;
+       lpsc->pm_domain.detach_dev = davinci_psc_genpd_detach_dev;
+       lpsc->pm_domain.flags = GENPD_FLAG_PM_CLK;
+
+       is_on = davinci_lpsc_clk_is_enabled(&lpsc->hw);
+       pm_genpd_init(&lpsc->pm_domain, NULL, is_on);
+
+       return lpsc;
+}
+
+static int davinci_lpsc_clk_reset(struct clk *clk, bool reset)
+{
+       struct clk_hw *hw = __clk_get_hw(clk);
+       struct davinci_lpsc_clk *lpsc = to_davinci_lpsc_clk(hw);
+       u32 mdctl;
+
+       if (IS_ERR_OR_NULL(lpsc))
+               return -EINVAL;
+
+       mdctl = reset ? 0 : MDCTL_LRESET;
+       regmap_write_bits(lpsc->regmap, MDCTL(lpsc->md), MDCTL_LRESET, mdctl);
+
+       return 0;
+}
+
+/*
+ * REVISIT: These exported functions can be removed after a non-DT lookup is
+ * added to the reset controller framework and the davinci-rproc driver is
+ * updated to use the generic reset controller framework.
+ */
+
+int davinci_clk_reset_assert(struct clk *clk)
+{
+       return davinci_lpsc_clk_reset(clk, true);
+}
+EXPORT_SYMBOL(davinci_clk_reset_assert);
+
+int davinci_clk_reset_deassert(struct clk *clk)
+{
+       return davinci_lpsc_clk_reset(clk, false);
+}
+EXPORT_SYMBOL(davinci_clk_reset_deassert);
+
+static int davinci_psc_reset_assert(struct reset_controller_dev *rcdev,
+                                   unsigned long id)
+{
+       struct davinci_psc_data *psc = to_davinci_psc_data(rcdev);
+       struct clk *clk = psc->clk_data.clks[id];
+
+       return davinci_lpsc_clk_reset(clk, true);
+}
+
+static int davinci_psc_reset_deassert(struct reset_controller_dev *rcdev,
+                                     unsigned long id)
+{
+       struct davinci_psc_data *psc = to_davinci_psc_data(rcdev);
+       struct clk *clk = psc->clk_data.clks[id];
+
+       return davinci_lpsc_clk_reset(clk, false);
+}
+
+static const struct reset_control_ops davinci_psc_reset_ops = {
+       .assert         = davinci_psc_reset_assert,
+       .deassert       = davinci_psc_reset_deassert,
+};
+
+static int davinci_psc_reset_of_xlate(struct reset_controller_dev *rcdev,
+                                     const struct of_phandle_args *reset_spec)
+{
+       struct of_phandle_args clkspec = *reset_spec; /* discard const qualifier */
+       struct clk *clk;
+       struct clk_hw *hw;
+       struct davinci_lpsc_clk *lpsc;
+
+       /* the clock node is the same as the reset node */
+       clk = of_clk_get_from_provider(&clkspec);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       hw = __clk_get_hw(clk);
+       lpsc = to_davinci_lpsc_clk(hw);
+       clk_put(clk);
+
+       /* not all modules support local reset */
+       if (!(lpsc->flags & LPSC_LOCAL_RESET))
+               return -EINVAL;
+
+       return lpsc->md;
+}
+
+static const struct regmap_config davinci_psc_regmap_config = {
+       .reg_bits       = 32,
+       .reg_stride     = 4,
+       .val_bits       = 32,
+};
+
+static struct davinci_psc_data *
+__davinci_psc_register_clocks(struct device *dev,
+                             const struct davinci_lpsc_clk_info *info,
+                             int num_clks,
+                             void __iomem *base)
+{
+       struct davinci_psc_data *psc;
+       struct clk **clks;
+       struct generic_pm_domain **pm_domains;
+       struct regmap *regmap;
+       int i, ret;
+
+       psc = devm_kzalloc(dev, sizeof(*psc), GFP_KERNEL);
+       if (!psc)
+               return ERR_PTR(-ENOMEM);
+
+       clks = devm_kmalloc_array(dev, num_clks, sizeof(*clks), GFP_KERNEL);
+       if (!clks)
+               return ERR_PTR(-ENOMEM);
+
+       psc->clk_data.clks = clks;
+       psc->clk_data.clk_num = num_clks;
+
+       /*
+        * init array with error so that of_clk_src_onecell_get() doesn't
+        * return NULL for gaps in the sparse array
+        */
+       for (i = 0; i < num_clks; i++)
+               clks[i] = ERR_PTR(-ENOENT);
+
+       pm_domains = devm_kcalloc(dev, num_clks, sizeof(*pm_domains), GFP_KERNEL);
+       if (!pm_domains)
+               return ERR_PTR(-ENOMEM);
+
+       psc->pm_data.domains = pm_domains;
+       psc->pm_data.num_domains = num_clks;
+
+       regmap = devm_regmap_init_mmio(dev, base, &davinci_psc_regmap_config);
+       if (IS_ERR(regmap))
+               return ERR_CAST(regmap);
+
+       for (; info->name; info++) {
+               struct davinci_lpsc_clk *lpsc;
+
+               lpsc = davinci_lpsc_clk_register(dev, info->name, info->parent,
+                                                regmap, info->md, info->pd,
+                                                info->flags);
+               if (IS_ERR(lpsc)) {
+                       dev_warn(dev, "Failed to register %s (%ld)\n",
+                                info->name, PTR_ERR(lpsc));
+                       continue;
+               }
+
+               clks[info->md] = lpsc->hw.clk;
+               pm_domains[info->md] = &lpsc->pm_domain;
+       }
+
+       psc->rcdev.ops = &davinci_psc_reset_ops;
+       psc->rcdev.owner = THIS_MODULE;
+       psc->rcdev.dev = dev;
+       psc->rcdev.of_node = dev->of_node;
+       psc->rcdev.of_reset_n_cells = 1;
+       psc->rcdev.of_xlate = davinci_psc_reset_of_xlate;
+       psc->rcdev.nr_resets = num_clks;
+
+       ret = devm_reset_controller_register(dev, &psc->rcdev);
+       if (ret < 0)
+               dev_warn(dev, "Failed to register reset controller (%d)\n", ret);
+
+       return psc;
+}
+
+int davinci_psc_register_clocks(struct device *dev,
+                               const struct davinci_lpsc_clk_info *info,
+                               u8 num_clks,
+                               void __iomem *base)
+{
+       struct davinci_psc_data *psc;
+
+       psc = __davinci_psc_register_clocks(dev, info, num_clks, base);
+       if (IS_ERR(psc))
+               return PTR_ERR(psc);
+
+       for (; info->name; info++) {
+               const struct davinci_lpsc_clkdev_info *cdevs = info->cdevs;
+               struct clk *clk = psc->clk_data.clks[info->md];
+
+               if (!cdevs || IS_ERR_OR_NULL(clk))
+                       continue;
+
+               for (; cdevs->con_id || cdevs->dev_id; cdevs++)
+                       clk_register_clkdev(clk, cdevs->con_id, cdevs->dev_id);
+       }
+
+       return 0;
+}
+
+int of_davinci_psc_clk_init(struct device *dev,
+                           const struct davinci_lpsc_clk_info *info,
+                           u8 num_clks,
+                           void __iomem *base)
+{
+       struct device_node *node = dev->of_node;
+       struct davinci_psc_data *psc;
+
+       psc = __davinci_psc_register_clocks(dev, info, num_clks, base);
+       if (IS_ERR(psc))
+               return PTR_ERR(psc);
+
+       of_genpd_add_provider_onecell(node, &psc->pm_data);
+
+       of_clk_add_provider(node, of_clk_src_onecell_get, &psc->clk_data);
+
+       return 0;
+}
+
+static const struct of_device_id davinci_psc_of_match[] = {
+       { .compatible = "ti,da850-psc0", .data = &of_da850_psc0_init_data },
+       { .compatible = "ti,da850-psc1", .data = &of_da850_psc1_init_data },
+       { }
+};
+
+static const struct platform_device_id davinci_psc_id_table[] = {
+       { .name = "da830-psc0", .driver_data = (kernel_ulong_t)&da830_psc0_init_data },
+       { .name = "da830-psc1", .driver_data = (kernel_ulong_t)&da830_psc1_init_data },
+       { .name = "da850-psc0", .driver_data = (kernel_ulong_t)&da850_psc0_init_data },
+       { .name = "da850-psc1", .driver_data = (kernel_ulong_t)&da850_psc1_init_data },
+       { .name = "dm355-psc",  .driver_data = (kernel_ulong_t)&dm355_psc_init_data  },
+       { .name = "dm365-psc",  .driver_data = (kernel_ulong_t)&dm365_psc_init_data  },
+       { .name = "dm644x-psc", .driver_data = (kernel_ulong_t)&dm644x_psc_init_data },
+       { .name = "dm646x-psc", .driver_data = (kernel_ulong_t)&dm646x_psc_init_data },
+       { }
+};
+
+static int davinci_psc_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       const struct of_device_id *of_id;
+       const struct davinci_psc_init_data *init_data = NULL;
+       struct resource *res;
+       void __iomem *base;
+       int ret;
+
+       of_id = of_match_device(davinci_psc_of_match, dev);
+       if (of_id)
+               init_data = of_id->data;
+       else if (pdev->id_entry)
+               init_data = (void *)pdev->id_entry->driver_data;
+
+       if (!init_data) {
+               dev_err(dev, "unable to find driver init data\n");
+               return -EINVAL;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       ret = devm_clk_bulk_get(dev, init_data->num_parent_clks,
+                               init_data->parent_clks);
+       if (ret < 0)
+               return ret;
+
+       return init_data->psc_init(dev, base);
+}
+
+static struct platform_driver davinci_psc_driver = {
+       .probe          = davinci_psc_probe,
+       .driver         = {
+               .name           = "davinci-psc-clk",
+               .of_match_table = davinci_psc_of_match,
+       },
+       .id_table       = davinci_psc_id_table,
+};
+
+static int __init davinci_psc_driver_init(void)
+{
+       return platform_driver_register(&davinci_psc_driver);
+}
+
+/* has to be postcore_initcall because davinci_gpio depend on PSC clocks */
+postcore_initcall(davinci_psc_driver_init);
diff --git a/drivers/clk/davinci/psc.h b/drivers/clk/davinci/psc.h
new file mode 100644 (file)
index 0000000..c2a7df6
--- /dev/null
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Clock driver for TI Davinci PSC controllers
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#ifndef __CLK_DAVINCI_PSC_H__
+#define __CLK_DAVINCI_PSC_H__
+
+#include <linux/clk-provider.h>
+#include <linux/types.h>
+
+/* PSC quirk flags */
+#define LPSC_ALWAYS_ENABLED    BIT(0) /* never disable this clock */
+#define LPSC_SET_RATE_PARENT   BIT(1) /* propagate set_rate to parent clock */
+#define LPSC_FORCE             BIT(2) /* requires MDCTL FORCE bit */
+#define LPSC_LOCAL_RESET       BIT(3) /* acts as reset provider */
+
+struct davinci_lpsc_clkdev_info {
+       const char *con_id;
+       const char *dev_id;
+};
+
+#define LPSC_CLKDEV(c, d) {    \
+       .con_id = (c),          \
+       .dev_id = (d)           \
+}
+
+#define LPSC_CLKDEV1(n, c, d) \
+static const struct davinci_lpsc_clkdev_info n[] __initconst = {       \
+       LPSC_CLKDEV((c), (d)),                                          \
+       { }                                                             \
+}
+
+#define LPSC_CLKDEV2(n, c1, d1, c2, d2) \
+static const struct davinci_lpsc_clkdev_info n[] __initconst = {       \
+       LPSC_CLKDEV((c1), (d1)),                                        \
+       LPSC_CLKDEV((c2), (d2)),                                        \
+       { }                                                             \
+}
+
+#define LPSC_CLKDEV3(n, c1, d1, c2, d2, c3, d3) \
+static const struct davinci_lpsc_clkdev_info n[] __initconst = {       \
+       LPSC_CLKDEV((c1), (d1)),                                        \
+       LPSC_CLKDEV((c2), (d2)),                                        \
+       LPSC_CLKDEV((c3), (d3)),                                        \
+       { }                                                             \
+}
+
+/**
+ * davinci_lpsc_clk_info - LPSC module-specific clock information
+ * @name: the clock name
+ * @parent: the parent clock name
+ * @cdevs: optional array of clkdev lookup table info
+ * @md: the local module domain (LPSC id)
+ * @pd: the power domain id
+ * @flags: bitmask of LPSC_* flags
+ */
+struct davinci_lpsc_clk_info {
+       const char *name;
+       const char *parent;
+       const struct davinci_lpsc_clkdev_info *cdevs;
+       u32 md;
+       u32 pd;
+       unsigned long flags;
+};
+
+#define LPSC(m, d, n, p, c, f) \
+{                              \
+       .name   = #n,           \
+       .parent = #p,           \
+       .cdevs  = (c),          \
+       .md     = (m),          \
+       .pd     = (d),          \
+       .flags  = (f),          \
+}
+
+int davinci_psc_register_clocks(struct device *dev,
+                               const struct davinci_lpsc_clk_info *info,
+                               u8 num_clks,
+                               void __iomem *base);
+
+int of_davinci_psc_clk_init(struct device *dev,
+                           const struct davinci_lpsc_clk_info *info,
+                           u8 num_clks,
+                           void __iomem *base);
+
+/* Device-specific data */
+
+struct davinci_psc_init_data {
+       struct clk_bulk_data *parent_clks;
+       int num_parent_clks;
+       int (*psc_init)(struct device *dev, void __iomem *base);
+};
+
+extern const struct davinci_psc_init_data da830_psc0_init_data;
+extern const struct davinci_psc_init_data da830_psc1_init_data;
+extern const struct davinci_psc_init_data da850_psc0_init_data;
+extern const struct davinci_psc_init_data da850_psc1_init_data;
+extern const struct davinci_psc_init_data of_da850_psc0_init_data;
+extern const struct davinci_psc_init_data of_da850_psc1_init_data;
+extern const struct davinci_psc_init_data dm355_psc_init_data;
+extern const struct davinci_psc_init_data dm365_psc_init_data;
+extern const struct davinci_psc_init_data dm644x_psc_init_data;
+extern const struct davinci_psc_init_data dm646x_psc_init_data;
+
+#endif /* __CLK_DAVINCI_PSC_H__ */
index 4806fc2cb4ac4bc9b976a13dd5c4d20f933c83cf..2a714c0f965786f74bd1f3e671cb9d1d8fec4e1a 100644 (file)
@@ -3,7 +3,7 @@
 # Hisilicon Clock specific Makefile
 #
 
-obj-y  += clk.o clkgate-separated.o clkdivider-hi6220.o
+obj-y  += clk.o clkgate-separated.o clkdivider-hi6220.o clk-hisi-phase.o
 
 obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
diff --git a/drivers/clk/hisilicon/clk-hisi-phase.c b/drivers/clk/hisilicon/clk-hisi-phase.c
new file mode 100644 (file)
index 0000000..5bce929
--- /dev/null
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017 HiSilicon Technologies Co., Ltd.
+ *
+ * Simple HiSilicon phase clock implementation.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+struct clk_hisi_phase {
+       struct clk_hw   hw;
+       void __iomem    *reg;
+       u32             *phase_degrees;
+       u32             *phase_regvals;
+       u8              phase_num;
+       u32             mask;
+       u8              shift;
+       u8              flags;
+       spinlock_t      *lock;
+};
+
+#define to_clk_hisi_phase(_hw) container_of(_hw, struct clk_hisi_phase, hw)
+
+static int hisi_phase_regval_to_degrees(struct clk_hisi_phase *phase,
+                                       u32 regval)
+{
+       int i;
+
+       for (i = 0; i < phase->phase_num; i++)
+               if (phase->phase_regvals[i] == regval)
+                       return phase->phase_degrees[i];
+
+       return -EINVAL;
+}
+
+static int hisi_clk_get_phase(struct clk_hw *hw)
+{
+       struct clk_hisi_phase *phase = to_clk_hisi_phase(hw);
+       u32 regval;
+
+       regval = readl(phase->reg);
+       regval = (regval & phase->mask) >> phase->shift;
+
+       return hisi_phase_regval_to_degrees(phase, regval);
+}
+
+static int hisi_phase_degrees_to_regval(struct clk_hisi_phase *phase,
+                                       int degrees)
+{
+       int i;
+
+       for (i = 0; i < phase->phase_num; i++)
+               if (phase->phase_degrees[i] == degrees)
+                       return phase->phase_regvals[i];
+
+       return -EINVAL;
+}
+
+static int hisi_clk_set_phase(struct clk_hw *hw, int degrees)
+{
+       struct clk_hisi_phase *phase = to_clk_hisi_phase(hw);
+       unsigned long flags = 0;
+       int regval;
+       u32 val;
+
+       regval = hisi_phase_degrees_to_regval(phase, degrees);
+       if (regval < 0)
+               return regval;
+
+       spin_lock_irqsave(phase->lock, flags);
+
+       val = clk_readl(phase->reg);
+       val &= ~phase->mask;
+       val |= regval << phase->shift;
+       clk_writel(val, phase->reg);
+
+       spin_unlock_irqrestore(phase->lock, flags);
+
+       return 0;
+}
+
+static const struct clk_ops clk_phase_ops = {
+       .get_phase = hisi_clk_get_phase,
+       .set_phase = hisi_clk_set_phase,
+};
+
+struct clk *clk_register_hisi_phase(struct device *dev,
+               const struct hisi_phase_clock *clks,
+               void __iomem *base, spinlock_t *lock)
+{
+       struct clk_hisi_phase *phase;
+       struct clk_init_data init;
+
+       phase = devm_kzalloc(dev, sizeof(struct clk_hisi_phase), GFP_KERNEL);
+       if (!phase)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = clks->name;
+       init.ops = &clk_phase_ops;
+       init.flags = clks->flags | CLK_IS_BASIC;
+       init.parent_names = clks->parent_names ? &clks->parent_names : NULL;
+       init.num_parents = clks->parent_names ? 1 : 0;
+
+       phase->reg = base + clks->offset;
+       phase->shift = clks->shift;
+       phase->mask = (BIT(clks->width) - 1) << clks->shift;
+       phase->lock = lock;
+       phase->phase_degrees = clks->phase_degrees;
+       phase->phase_regvals = clks->phase_regvals;
+       phase->phase_num = clks->phase_num;
+       phase->hw.init = &init;
+
+       return devm_clk_register(dev, &phase->hw);
+}
+EXPORT_SYMBOL_GPL(clk_register_hisi_phase);
index b73c1dfae7f1ea0787ea7a23e64d895569458d2c..953c8dacef8b095b89e94db1553ac18e54b559ac 100644 (file)
@@ -49,6 +49,8 @@ struct hisi_clock_data *hisi_clk_alloc(struct platform_device *pdev,
                return NULL;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return NULL;
        clk_data->base = devm_ioremap(&pdev->dev,
                                res->start, resource_size(res));
        if (!clk_data->base)
@@ -197,6 +199,30 @@ err:
 }
 EXPORT_SYMBOL_GPL(hisi_clk_register_mux);
 
+int hisi_clk_register_phase(struct device *dev,
+                           const struct hisi_phase_clock *clks,
+                           int nums, struct hisi_clock_data *data)
+{
+       void __iomem *base = data->base;
+       struct clk *clk;
+       int i;
+
+       for (i = 0; i < nums; i++) {
+               clk = clk_register_hisi_phase(dev, &clks[i], base,
+                                             &hisi_clk_lock);
+               if (IS_ERR(clk)) {
+                       pr_err("%s: failed to register clock %s\n", __func__,
+                              clks[i].name);
+                       return PTR_ERR(clk);
+               }
+
+               data->clk_data.clks[clks[i].id] = clk;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(hisi_clk_register_phase);
+
 int hisi_clk_register_divider(const struct hisi_divider_clock *clks,
                                      int nums, struct hisi_clock_data *data)
 {
index 4e1d1affc6f548ea11d9d6d9ae610659310479b3..8d7ee5c3231bd7e76279b5fa878428a69b51681e 100644 (file)
@@ -68,6 +68,19 @@ struct hisi_mux_clock {
        const char              *alias;
 };
 
+struct hisi_phase_clock {
+       unsigned int            id;
+       const char              *name;
+       const char              *parent_names;
+       unsigned long           flags;
+       unsigned long           offset;
+       u8                      shift;
+       u8                      width;
+       u32                     *phase_degrees;
+       u32                     *phase_regvals;
+       u8                      phase_num;
+};
+
 struct hisi_divider_clock {
        unsigned int            id;
        const char              *name;
@@ -120,6 +133,12 @@ int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *,
                                int, struct hisi_clock_data *);
 int hisi_clk_register_mux(const struct hisi_mux_clock *, int,
                                struct hisi_clock_data *);
+struct clk *clk_register_hisi_phase(struct device *dev,
+                               const struct hisi_phase_clock *clks,
+                               void __iomem *base, spinlock_t *lock);
+int hisi_clk_register_phase(struct device *dev,
+                               const struct hisi_phase_clock *clks,
+                               int nums, struct hisi_clock_data *data);
 int hisi_clk_register_divider(const struct hisi_divider_clock *,
                                int, struct hisi_clock_data *);
 int hisi_clk_register_gate(const struct hisi_gate_clock *,
index 2007123832bb3ffce59e2740f572026a304eb8ef..53450b651e4c709b64324dcd7ee0273124cb0e9f 100644 (file)
@@ -204,7 +204,7 @@ static const struct hisi_crg_funcs hi3516cv300_crg_funcs = {
 /* hi3516CV300 sysctrl CRG */
 #define HI3516CV300_SYSCTRL_NR_CLKS 16
 
-static const char *wdt_mux_p[] __initconst = { "3m", "apb" };
+static const char *const wdt_mux_p[] __initconst = { "3m", "apb" };
 static u32 wdt_mux_table[] = {0, 1};
 
 static const struct hisi_mux_clock hi3516cv300_sysctrl_mux_clks[] = {
index 8478948e858e396b3797d99d926c0dfe754cd8fa..743eec1315280eb97a7c246a1bb3eec22a42d8e4 100644 (file)
 #include "reset.h"
 
 /* hi3798CV200 core CRG */
-#define HI3798CV200_INNER_CLK_OFFSET   64
-#define HI3798CV200_FIXED_24M  65
-#define HI3798CV200_FIXED_25M  66
-#define HI3798CV200_FIXED_50M  67
-#define HI3798CV200_FIXED_75M  68
-#define HI3798CV200_FIXED_100M 69
-#define HI3798CV200_FIXED_150M 70
-#define HI3798CV200_FIXED_200M 71
-#define HI3798CV200_FIXED_250M 72
-#define HI3798CV200_FIXED_300M 73
-#define HI3798CV200_FIXED_400M 74
-#define HI3798CV200_MMC_MUX    75
-#define HI3798CV200_ETH_PUB_CLK        76
-#define HI3798CV200_ETH_BUS_CLK        77
-#define HI3798CV200_ETH_BUS0_CLK       78
-#define HI3798CV200_ETH_BUS1_CLK       79
-#define HI3798CV200_COMBPHY1_MUX       80
-#define HI3798CV200_FIXED_12M  81
-#define HI3798CV200_FIXED_48M  82
-#define HI3798CV200_FIXED_60M  83
-#define HI3798CV200_FIXED_166P5M       84
-#define HI3798CV200_SDIO0_MUX  85
-
-#define HI3798CV200_CRG_NR_CLKS                128
+#define HI3798CV200_INNER_CLK_OFFSET           64
+#define HI3798CV200_FIXED_24M                  65
+#define HI3798CV200_FIXED_25M                  66
+#define HI3798CV200_FIXED_50M                  67
+#define HI3798CV200_FIXED_75M                  68
+#define HI3798CV200_FIXED_100M                 69
+#define HI3798CV200_FIXED_150M                 70
+#define HI3798CV200_FIXED_200M                 71
+#define HI3798CV200_FIXED_250M                 72
+#define HI3798CV200_FIXED_300M                 73
+#define HI3798CV200_FIXED_400M                 74
+#define HI3798CV200_MMC_MUX                    75
+#define HI3798CV200_ETH_PUB_CLK                        76
+#define HI3798CV200_ETH_BUS_CLK                        77
+#define HI3798CV200_ETH_BUS0_CLK               78
+#define HI3798CV200_ETH_BUS1_CLK               79
+#define HI3798CV200_COMBPHY1_MUX               80
+#define HI3798CV200_FIXED_12M                  81
+#define HI3798CV200_FIXED_48M                  82
+#define HI3798CV200_FIXED_60M                  83
+#define HI3798CV200_FIXED_166P5M               84
+#define HI3798CV200_SDIO0_MUX                  85
+#define HI3798CV200_COMBPHY0_MUX               86
+
+#define HI3798CV200_CRG_NR_CLKS                        128
 
 static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = {
        { HISTB_OSC_CLK, "clk_osc", NULL, 0, 24000000, },
@@ -74,9 +75,9 @@ static const char *const mmc_mux_p[] = {
                "100m", "50m", "25m", "200m", "150m" };
 static u32 mmc_mux_table[] = {0, 1, 2, 3, 6};
 
-static const char *const comphy1_mux_p[] = {
+static const char *const comphy_mux_p[] = {
                "100m", "25m"};
-static u32 comphy1_mux_table[] = {2, 3};
+static u32 comphy_mux_table[] = {2, 3};
 
 static const char *const sdio_mux_p[] = {
                "100m", "50m", "150m", "166p5m" };
@@ -85,14 +86,29 @@ static u32 sdio_mux_table[] = {0, 1, 2, 3};
 static struct hisi_mux_clock hi3798cv200_mux_clks[] = {
        { HI3798CV200_MMC_MUX, "mmc_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
                CLK_SET_RATE_PARENT, 0xa0, 8, 3, 0, mmc_mux_table, },
+       { HI3798CV200_COMBPHY0_MUX, "combphy0_mux",
+               comphy_mux_p, ARRAY_SIZE(comphy_mux_p),
+               CLK_SET_RATE_PARENT, 0x188, 2, 2, 0, comphy_mux_table, },
        { HI3798CV200_COMBPHY1_MUX, "combphy1_mux",
-               comphy1_mux_p, ARRAY_SIZE(comphy1_mux_p),
-               CLK_SET_RATE_PARENT, 0x188, 10, 2, 0, comphy1_mux_table, },
+               comphy_mux_p, ARRAY_SIZE(comphy_mux_p),
+               CLK_SET_RATE_PARENT, 0x188, 10, 2, 0, comphy_mux_table, },
        { HI3798CV200_SDIO0_MUX, "sdio0_mux", sdio_mux_p,
                ARRAY_SIZE(sdio_mux_p), CLK_SET_RATE_PARENT,
                0x9c, 8, 2, 0, sdio_mux_table, },
 };
 
+static u32 mmc_phase_regvals[] = {0, 1, 2, 3, 4, 5, 6, 7};
+static u32 mmc_phase_degrees[] = {0, 45, 90, 135, 180, 225, 270, 315};
+
+static struct hisi_phase_clock hi3798cv200_phase_clks[] = {
+       { HISTB_MMC_SAMPLE_CLK, "mmc_sample", "clk_mmc_ciu",
+               CLK_SET_RATE_PARENT, 0xa0, 12, 3, mmc_phase_degrees,
+               mmc_phase_regvals, ARRAY_SIZE(mmc_phase_regvals) },
+       { HISTB_MMC_DRV_CLK, "mmc_drive", "clk_mmc_ciu",
+               CLK_SET_RATE_PARENT, 0xa0, 16, 3, mmc_phase_degrees,
+               mmc_phase_regvals, ARRAY_SIZE(mmc_phase_regvals) },
+};
+
 static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
        /* UART */
        { HISTB_UART2_CLK, "clk_uart2", "75m",
@@ -147,6 +163,9 @@ static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
                CLK_SET_RATE_PARENT, 0xcc, 4, 0, },
        { HISTB_ETH1_MACIF_CLK, "clk_macif1", "clk_bus_m1",
                CLK_SET_RATE_PARENT, 0xcc, 25, 0, },
+       /* COMBPHY0 */
+       { HISTB_COMBPHY0_CLK, "clk_combphy0", "combphy0_mux",
+               CLK_SET_RATE_PARENT, 0x188, 0, 0, },
        /* COMBPHY1 */
        { HISTB_COMBPHY1_CLK, "clk_combphy1", "combphy1_mux",
                CLK_SET_RATE_PARENT, 0x188, 8, 0, },
@@ -161,6 +180,8 @@ static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
                CLK_SET_RATE_PARENT, 0xb8, 1, 0 },
        { HISTB_USB2_UTMI_CLK, "clk_u2_utmi", "60m",
                CLK_SET_RATE_PARENT, 0xb8, 5, 0 },
+       { HISTB_USB2_OTG_UTMI_CLK, "clk_u2_otg_utmi", "60m",
+               CLK_SET_RATE_PARENT, 0xb8, 3, 0 },
        { HISTB_USB2_PHY1_REF_CLK, "clk_u2_phy1_ref", "24m",
                CLK_SET_RATE_PARENT, 0xbc, 0, 0 },
        { HISTB_USB2_PHY2_REF_CLK, "clk_u2_phy2_ref", "24m",
@@ -177,6 +198,14 @@ static struct hisi_clock_data *hi3798cv200_clk_register(
        if (!clk_data)
                return ERR_PTR(-ENOMEM);
 
+       /* hisi_phase_clock is resource managed */
+       ret = hisi_clk_register_phase(&pdev->dev,
+                               hi3798cv200_phase_clks,
+                               ARRAY_SIZE(hi3798cv200_phase_clks),
+                               clk_data);
+       if (ret)
+               return ERR_PTR(ret);
+
        ret = hisi_clk_register_fixed_rate(hi3798cv200_fixed_rate_clks,
                                     ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
                                     clk_data);
@@ -202,18 +231,17 @@ static struct hisi_clock_data *hi3798cv200_clk_register(
 
        return clk_data;
 
-unregister_fixed_rate:
-       hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
-                               ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
+unregister_gate:
+       hisi_clk_unregister_gate(hi3798cv200_gate_clks,
+                               ARRAY_SIZE(hi3798cv200_gate_clks),
                                clk_data);
-
 unregister_mux:
        hisi_clk_unregister_mux(hi3798cv200_mux_clks,
                                ARRAY_SIZE(hi3798cv200_mux_clks),
                                clk_data);
-unregister_gate:
-       hisi_clk_unregister_gate(hi3798cv200_gate_clks,
-                               ARRAY_SIZE(hi3798cv200_gate_clks),
+unregister_fixed_rate:
+       hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
+                               ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
                                clk_data);
        return ERR_PTR(ret);
 }
@@ -245,7 +273,7 @@ static const struct hisi_crg_funcs hi3798cv200_crg_funcs = {
 #define HI3798CV200_SYSCTRL_NR_CLKS 16
 
 static const struct hisi_gate_clock hi3798cv200_sysctrl_gate_clks[] = {
-       { HISTB_IR_CLK, "clk_ir", "100m",
+       { HISTB_IR_CLK, "clk_ir", "24m",
                CLK_SET_RATE_PARENT, 0x48, 4, 0, },
        { HISTB_TIMER01_CLK, "clk_timer01", "24m",
                CLK_SET_RATE_PARENT, 0x48, 6, 0, },
index f91f2b2e11cdd63dc1cfc3f97e48e09b45943d78..8c3baa7e6496697afce236738fa36bd130b5dcce 100644 (file)
@@ -22,6 +22,7 @@ obj-$(CONFIG_SOC_IMX35)  += clk-imx35.o
 obj-$(CONFIG_SOC_IMX5)   += clk-imx51-imx53.o
 obj-$(CONFIG_SOC_IMX6Q)  += clk-imx6q.o
 obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o
+obj-$(CONFIG_SOC_IMX6SLL) += clk-imx6sll.o
 obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
index 6df3389687bc0fe9e4afae264e3c825ea11bb35e..99036527eb0d8f1fc7d418d1f284dbe172fc21b3 100644 (file)
@@ -101,7 +101,7 @@ struct clk *imx_clk_busy_divider(const char *name, const char *parent_name,
 
        init.name = name;
        init.ops = &clk_busy_divider_ops;
-       init.flags = CLK_SET_RATE_PARENT;
+       init.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL;
        init.parent_names = &parent_name;
        init.num_parents = 1;
 
@@ -175,7 +175,7 @@ struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift,
 
        init.name = name;
        init.ops = &clk_busy_mux_ops;
-       init.flags = 0;
+       init.flags = CLK_IS_CRITICAL;
        init.parent_names = parent_names;
        init.num_parents = num_parents;
 
diff --git a/drivers/clk/imx/clk-imx6sll.c b/drivers/clk/imx/clk-imx6sll.c
new file mode 100644 (file)
index 0000000..3651c77
--- /dev/null
@@ -0,0 +1,340 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2018 NXP.
+ */
+
+#include <dt-bindings/clock/imx6sll-clock.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk.h"
+
+#define CCM_ANALOG_PLL_BYPASS          (0x1 << 16)
+#define BM_CCM_CCDR_MMDC_CH0_MASK      (0x2 << 16)
+#define xPLL_CLR(offset)               (offset + 0x8)
+
+static const char *pll_bypass_src_sels[] = { "osc", "dummy", };
+static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", };
+static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", };
+static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", };
+static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", };
+static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", };
+static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", };
+static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", };
+static const char *step_sels[] = { "osc", "pll2_pfd2_396m", };
+static const char *pll1_sw_sels[] = { "pll1_sys", "step", };
+static const char *axi_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_540m", };
+static const char *axi_sels[] = {"periph", "axi_alt_sel", };
+static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", };
+static const char *periph2_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll4_audio_div", };
+static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", };
+static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "osc", };
+static const char *periph_sels[] = { "periph_pre", "periph_clk2", };
+static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", };
+static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
+static const char *ssi_sels[] = {"pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio_div", "dummy",};
+static const char *spdif_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll5_video_div", "pll3_usb_otg", };
+static const char *ldb_di0_div_sels[] = { "ldb_di0_div_3_5", "ldb_di0_div_7", };
+static const char *ldb_di1_div_sels[] = { "ldb_di1_div_3_5", "ldb_di1_div_7", };
+static const char *ldb_di0_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_pfd3_594m", "pll2_pfd1_594m", "pll3_pfd3_454m", };
+static const char *ldb_di1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", };
+static const char *lcdif_pre_sels[] = { "pll2_bus", "pll3_pfd3_454m", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_540m", };
+static const char *ecspi_sels[] = { "pll3_60m", "osc", };
+static const char *uart_sels[] = { "pll3_80m", "osc", };
+static const char *perclk_sels[] = { "ipg", "osc", };
+static const char *lcdif_sels[] = { "lcdif_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+
+static const char *epdc_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd2_508m", };
+static const char *epdc_sels[] = { "epdc_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+
+static struct clk *clks[IMX6SLL_CLK_END];
+static struct clk_onecell_data clk_data;
+
+static const struct clk_div_table post_div_table[] = {
+       { .val = 2, .div = 1, },
+       { .val = 1, .div = 2, },
+       { .val = 0, .div = 4, },
+       { }
+};
+
+static const struct clk_div_table video_div_table[] = {
+       { .val = 0, .div = 1, },
+       { .val = 1, .div = 2, },
+       { .val = 2, .div = 1, },
+       { .val = 3, .div = 4, },
+       { }
+};
+
+static u32 share_count_audio;
+static u32 share_count_ssi1;
+static u32 share_count_ssi2;
+static u32 share_count_ssi3;
+
+static void __init imx6sll_clocks_init(struct device_node *ccm_node)
+{
+       struct device_node *np;
+       void __iomem *base;
+
+       clks[IMX6SLL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+
+       clks[IMX6SLL_CLK_CKIL] = of_clk_get_by_name(ccm_node, "ckil");
+       clks[IMX6SLL_CLK_OSC] = of_clk_get_by_name(ccm_node, "osc");
+
+       /* ipp_di clock is external input */
+       clks[IMX6SLL_CLK_IPP_DI0] = of_clk_get_by_name(ccm_node, "ipp_di0");
+       clks[IMX6SLL_CLK_IPP_DI1] = of_clk_get_by_name(ccm_node, "ipp_di1");
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx6sll-anatop");
+       base = of_iomap(np, 0);
+       WARN_ON(!base);
+
+       /* Do not bypass PLLs initially */
+       writel_relaxed(CCM_ANALOG_PLL_BYPASS, base + xPLL_CLR(0x0));
+       writel_relaxed(CCM_ANALOG_PLL_BYPASS, base + xPLL_CLR(0x10));
+       writel_relaxed(CCM_ANALOG_PLL_BYPASS, base + xPLL_CLR(0x20));
+       writel_relaxed(CCM_ANALOG_PLL_BYPASS, base + xPLL_CLR(0x30));
+       writel_relaxed(CCM_ANALOG_PLL_BYPASS, base + xPLL_CLR(0x70));
+       writel_relaxed(CCM_ANALOG_PLL_BYPASS, base + xPLL_CLR(0xa0));
+       writel_relaxed(CCM_ANALOG_PLL_BYPASS, base + xPLL_CLR(0xe0));
+
+       clks[IMX6SLL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6SLL_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6SLL_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6SLL_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6SLL_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6SLL_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6SLL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+
+       clks[IMX6SLL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,    "pll1", "pll1_bypass_src", base + 0x00, 0x7f);
+       clks[IMX6SLL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1);
+       clks[IMX6SLL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,    "pll3", "pll3_bypass_src", base + 0x10, 0x3);
+       clks[IMX6SLL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,     "pll4", "pll4_bypass_src", base + 0x70, 0x7f);
+       clks[IMX6SLL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,     "pll5", "pll5_bypass_src", base + 0xa0, 0x7f);
+       clks[IMX6SLL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,   "pll6", "pll6_bypass_src", base + 0xe0, 0x3);
+       clks[IMX6SLL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,    "pll7", "pll7_bypass_src", base + 0x20, 0x3);
+
+       clks[IMX6SLL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6SLL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6SLL_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6SLL_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6SLL_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6SLL_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6SLL_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
+
+       clks[IMX6SLL_CLK_PLL1_SYS]      = imx_clk_fixed_factor("pll1_sys", "pll1_bypass", 1, 1);
+       clks[IMX6SLL_CLK_PLL2_BUS]      = imx_clk_gate("pll2_bus",         "pll2_bypass", base + 0x30, 13);
+       clks[IMX6SLL_CLK_PLL3_USB_OTG]  = imx_clk_gate("pll3_usb_otg",     "pll3_bypass", base + 0x10, 13);
+       clks[IMX6SLL_CLK_PLL4_AUDIO]    = imx_clk_gate("pll4_audio",       "pll4_bypass", base + 0x70, 13);
+       clks[IMX6SLL_CLK_PLL5_VIDEO]    = imx_clk_gate("pll5_video",       "pll5_bypass", base + 0xa0, 13);
+       clks[IMX6SLL_CLK_PLL6_ENET]     = imx_clk_gate("pll6_enet",        "pll6_bypass", base + 0xe0, 13);
+       clks[IMX6SLL_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host",    "pll7_bypass", base + 0x20, 13);
+
+       /*
+        * Bit 20 is the reserved and read-only bit, we do this only for:
+        * - Do nothing for usbphy clk_enable/disable
+        * - Keep refcount when do usbphy clk_enable/disable, in that case,
+        * the clk framework many need to enable/disable usbphy's parent
+        */
+       clks[IMX6SLL_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg",  base + 0x10, 20);
+       clks[IMX6SLL_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
+
+       /*
+        * usbphy*_gate needs to be on after system boots up, and software
+        * never needs to control it anymore.
+        */
+       if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
+               clks[IMX6SLL_CLK_USBPHY1_GATE] = imx_clk_gate_flags("usbphy1_gate", "dummy", base + 0x10, 6, CLK_IS_CRITICAL);
+               clks[IMX6SLL_CLK_USBPHY2_GATE] = imx_clk_gate_flags("usbphy2_gate", "dummy", base + 0x20, 6, CLK_IS_CRITICAL);
+       }
+
+       /*                                      name               parent_name     reg          idx */
+       clks[IMX6SLL_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0);
+       clks[IMX6SLL_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1);
+       clks[IMX6SLL_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2);
+       clks[IMX6SLL_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3_594m", "pll2_bus", base + 0x100, 3);
+       clks[IMX6SLL_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0, 0);
+       clks[IMX6SLL_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0, 1);
+       clks[IMX6SLL_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0, 2);
+       clks[IMX6SLL_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0, 3);
+
+       clks[IMX6SLL_CLK_PLL4_POST_DIV]  = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio",
+                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+       clks[IMX6SLL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div",
+                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 15, 1, 0, &imx_ccm_lock);
+       clks[IMX6SLL_CLK_PLL5_POST_DIV]  = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video",
+                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
+       clks[IMX6SLL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div",
+                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
+
+       /*                                                 name         parent_name      mult  div */
+       clks[IMX6SLL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2);
+       clks[IMX6SLL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg",   1, 4);
+       clks[IMX6SLL_CLK_PLL3_80M]  = imx_clk_fixed_factor("pll3_80m",  "pll3_usb_otg",   1, 6);
+       clks[IMX6SLL_CLK_PLL3_60M]  = imx_clk_fixed_factor("pll3_60m",  "pll3_usb_otg",   1, 8);
+
+       np = ccm_node;
+       base = of_iomap(np, 0);
+       WARN_ON(!base);
+
+       clks[IMX6SLL_CLK_STEP]            = imx_clk_mux("step", base + 0x0c, 8, 1, step_sels, ARRAY_SIZE(step_sels));
+       clks[IMX6SLL_CLK_PLL1_SW]         = imx_clk_mux_flags("pll1_sw",   base + 0x0c, 2,  1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels), 0);
+       clks[IMX6SLL_CLK_AXI_ALT_SEL]     = imx_clk_mux("axi_alt_sel",     base + 0x14, 7,  1, axi_alt_sels, ARRAY_SIZE(axi_alt_sels));
+       clks[IMX6SLL_CLK_AXI_SEL]         = imx_clk_mux_flags("axi_sel",   base + 0x14, 6,  1, axi_sels, ARRAY_SIZE(axi_sels), 0);
+       clks[IMX6SLL_CLK_PERIPH_PRE]      = imx_clk_mux("periph_pre",      base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
+       clks[IMX6SLL_CLK_PERIPH2_PRE]     = imx_clk_mux("periph2_pre",     base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels));
+       clks[IMX6SLL_CLK_PERIPH_CLK2_SEL]  = imx_clk_mux("periph_clk2_sel",  base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
+       clks[IMX6SLL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+       clks[IMX6SLL_CLK_USDHC1_SEL]      = imx_clk_mux("usdhc1_sel",   base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+       clks[IMX6SLL_CLK_USDHC2_SEL]      = imx_clk_mux("usdhc2_sel",   base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+       clks[IMX6SLL_CLK_USDHC3_SEL]      = imx_clk_mux("usdhc3_sel",   base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+       clks[IMX6SLL_CLK_SSI1_SEL]        = imx_clk_mux("ssi1_sel",     base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
+       clks[IMX6SLL_CLK_SSI2_SEL]        = imx_clk_mux("ssi2_sel",     base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
+       clks[IMX6SLL_CLK_SSI3_SEL]        = imx_clk_mux("ssi3_sel",     base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
+       clks[IMX6SLL_CLK_PERCLK_SEL]      = imx_clk_mux("perclk_sel",   base + 0x1c, 6,  1, perclk_sels, ARRAY_SIZE(perclk_sels));
+       clks[IMX6SLL_CLK_UART_SEL]        = imx_clk_mux("uart_sel",     base + 0x24, 6,  1, uart_sels, ARRAY_SIZE(uart_sels));
+       clks[IMX6SLL_CLK_SPDIF_SEL]       = imx_clk_mux("spdif_sel",    base + 0x30, 20, 2, spdif_sels, ARRAY_SIZE(spdif_sels));
+       clks[IMX6SLL_CLK_EXTERN_AUDIO_SEL] = imx_clk_mux("extern_audio_sel", base + 0x30, 7,  2, spdif_sels, ARRAY_SIZE(spdif_sels));
+       clks[IMX6SLL_CLK_EPDC_PRE_SEL]    = imx_clk_mux("epdc_pre_sel", base + 0x34, 15, 3, epdc_pre_sels, ARRAY_SIZE(epdc_pre_sels));
+       clks[IMX6SLL_CLK_EPDC_SEL]        = imx_clk_mux("epdc_sel",     base + 0x34, 9, 3, epdc_sels, ARRAY_SIZE(epdc_sels));
+       clks[IMX6SLL_CLK_ECSPI_SEL]       = imx_clk_mux("ecspi_sel",    base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
+       clks[IMX6SLL_CLK_LCDIF_PRE_SEL]   = imx_clk_mux("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels));
+       clks[IMX6SLL_CLK_LCDIF_SEL]       = imx_clk_mux("lcdif_sel",     base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels));
+
+       clks[IMX6SLL_CLK_PERIPH]  = imx_clk_busy_mux("periph",  base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels));
+       clks[IMX6SLL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels));
+
+       clks[IMX6SLL_CLK_PERIPH_CLK2]   = imx_clk_divider("periph_clk2",   "periph_clk2_sel",   base + 0x14, 27, 3);
+       clks[IMX6SLL_CLK_PERIPH2_CLK2]  = imx_clk_divider("periph2_clk2",  "periph2_clk2_sel",  base + 0x14, 0,  3);
+       clks[IMX6SLL_CLK_IPG]           = imx_clk_divider("ipg",           "ahb",               base + 0x14, 8,  2);
+       clks[IMX6SLL_CLK_LCDIF_PODF]    = imx_clk_divider("lcdif_podf",    "lcdif_pred",        base + 0x18, 23, 3);
+       clks[IMX6SLL_CLK_PERCLK]        = imx_clk_divider("perclk",        "perclk_sel",        base + 0x1c, 0,  6);
+       clks[IMX6SLL_CLK_USDHC3_PODF]   = imx_clk_divider("usdhc3_podf",   "usdhc3_sel",        base + 0x24, 19, 3);
+       clks[IMX6SLL_CLK_USDHC2_PODF]   = imx_clk_divider("usdhc2_podf",   "usdhc2_sel",        base + 0x24, 16, 3);
+       clks[IMX6SLL_CLK_USDHC1_PODF]   = imx_clk_divider("usdhc1_podf",   "usdhc1_sel",        base + 0x24, 11, 3);
+       clks[IMX6SLL_CLK_UART_PODF]     = imx_clk_divider("uart_podf",     "uart_sel",          base + 0x24, 0,  6);
+       clks[IMX6SLL_CLK_SSI3_PRED]     = imx_clk_divider("ssi3_pred",     "ssi3_sel",          base + 0x28, 22, 3);
+       clks[IMX6SLL_CLK_SSI3_PODF]     = imx_clk_divider("ssi3_podf",     "ssi3_pred",         base + 0x28, 16, 6);
+       clks[IMX6SLL_CLK_SSI1_PRED]     = imx_clk_divider("ssi1_pred",     "ssi1_sel",          base + 0x28, 6,  3);
+       clks[IMX6SLL_CLK_SSI1_PODF]     = imx_clk_divider("ssi1_podf",     "ssi1_pred",         base + 0x28, 0,  6);
+       clks[IMX6SLL_CLK_SSI2_PRED]     = imx_clk_divider("ssi2_pred",     "ssi2_sel",          base + 0x2c, 6,  3);
+       clks[IMX6SLL_CLK_SSI2_PODF]     = imx_clk_divider("ssi2_podf",     "ssi2_pred",         base + 0x2c, 0,  6);
+       clks[IMX6SLL_CLK_SPDIF_PRED]    = imx_clk_divider("spdif_pred",    "spdif_sel",         base + 0x30, 25, 3);
+       clks[IMX6SLL_CLK_SPDIF_PODF]    = imx_clk_divider("spdif_podf",    "spdif_pred",        base + 0x30, 22, 3);
+       clks[IMX6SLL_CLK_EXTERN_AUDIO_PRED] = imx_clk_divider("extern_audio_pred", "extern_audio_sel",  base + 0x30, 12, 3);
+       clks[IMX6SLL_CLK_EXTERN_AUDIO_PODF] = imx_clk_divider("extern_audio_podf", "extern_audio_pred", base + 0x30, 9,  3);
+       clks[IMX6SLL_CLK_EPDC_PODF]  = imx_clk_divider("epdc_podf",  "epdc_pre_sel",  base + 0x34, 12, 3);
+       clks[IMX6SLL_CLK_ECSPI_PODF] = imx_clk_divider("ecspi_podf", "ecspi_sel",     base + 0x38, 19, 6);
+       clks[IMX6SLL_CLK_LCDIF_PRED] = imx_clk_divider("lcdif_pred", "lcdif_pre_sel", base + 0x38, 12, 3);
+
+       clks[IMX6SLL_CLK_ARM]           = imx_clk_busy_divider("arm",       "pll1_sw",  base +  0x10, 0,  3,  base + 0x48, 16);
+       clks[IMX6SLL_CLK_MMDC_PODF]     = imx_clk_busy_divider("mmdc_podf", "periph2",  base +  0x14, 3,  3,  base + 0x48, 2);
+       clks[IMX6SLL_CLK_AXI_PODF]      = imx_clk_busy_divider("axi",       "axi_sel",  base +  0x14, 16, 3,  base + 0x48, 0);
+       clks[IMX6SLL_CLK_AHB]           = imx_clk_busy_divider("ahb",       "periph",   base +  0x14, 10, 3,  base + 0x48, 1);
+
+       clks[IMX6SLL_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+       clks[IMX6SLL_CLK_LDB_DI0_DIV_7]   = imx_clk_fixed_factor("ldb_di0_div_7",   "ldb_di0_sel", 1, 7);
+       clks[IMX6SLL_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+       clks[IMX6SLL_CLK_LDB_DI1_DIV_7]   = imx_clk_fixed_factor("ldb_di1_div_7",   "ldb_di1_sel", 1, 7);
+
+       clks[IMX6SLL_CLK_LDB_DI0_SEL]   = imx_clk_mux("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels));
+       clks[IMX6SLL_CLK_LDB_DI1_SEL]   = imx_clk_mux("ldb_di1_sel", base + 0x1c, 7, 3, ldb_di1_sels, ARRAY_SIZE(ldb_di1_sels));
+       clks[IMX6SLL_CLK_LDB_DI0_DIV_SEL] = imx_clk_mux("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));
+       clks[IMX6SLL_CLK_LDB_DI1_DIV_SEL] = imx_clk_mux("ldb_di1_div_sel", base + 0x20, 10, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels));
+
+       /* CCGR0 */
+       clks[IMX6SLL_CLK_AIPSTZ1]       = imx_clk_gate2_flags("aips_tz1", "ahb", base + 0x68, 0, CLK_IS_CRITICAL);
+       clks[IMX6SLL_CLK_AIPSTZ2]       = imx_clk_gate2_flags("aips_tz2", "ahb", base + 0x68, 2, CLK_IS_CRITICAL);
+       clks[IMX6SLL_CLK_DCP]           = imx_clk_gate2("dcp", "ahb", base + 0x68, 10);
+       clks[IMX6SLL_CLK_UART2_IPG]     = imx_clk_gate2("uart2_ipg", "ipg", base + 0x68, 28);
+       clks[IMX6SLL_CLK_UART2_SERIAL]  = imx_clk_gate2("uart2_serial", "uart_podf", base + 0x68, 28);
+
+       /* CCGR1 */
+       clks[IMX6SLL_CLK_ECSPI1]        = imx_clk_gate2("ecspi1",       "ecspi_podf", base + 0x6c, 0);
+       clks[IMX6SLL_CLK_ECSPI2]        = imx_clk_gate2("ecspi2",       "ecspi_podf", base + 0x6c, 2);
+       clks[IMX6SLL_CLK_ECSPI3]        = imx_clk_gate2("ecspi3",       "ecspi_podf", base + 0x6c, 4);
+       clks[IMX6SLL_CLK_ECSPI4]        = imx_clk_gate2("ecspi4",       "ecspi_podf", base + 0x6c, 6);
+       clks[IMX6SLL_CLK_UART3_IPG]     = imx_clk_gate2("uart3_ipg",    "ipg", base + 0x6c, 10);
+       clks[IMX6SLL_CLK_UART3_SERIAL]  = imx_clk_gate2("uart3_serial", "uart_podf", base + 0x6c, 10);
+       clks[IMX6SLL_CLK_EPIT1]         = imx_clk_gate2("epit1",        "perclk", base + 0x6c, 12);
+       clks[IMX6SLL_CLK_EPIT2]         = imx_clk_gate2("epit2",        "perclk", base + 0x6c, 14);
+       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);
+
+       /* CCGR2 */
+       clks[IMX6SLL_CLK_CSI]           = imx_clk_gate2("csi",          "axi",    base + 0x70,  2);
+       clks[IMX6SLL_CLK_I2C1]          = imx_clk_gate2("i2c1",         "perclk", base + 0x70,  6);
+       clks[IMX6SLL_CLK_I2C2]          = imx_clk_gate2("i2c2",         "perclk", base + 0x70,  8);
+       clks[IMX6SLL_CLK_I2C3]          = imx_clk_gate2("i2c3",         "perclk", base + 0x70,  10);
+       clks[IMX6SLL_CLK_OCOTP]         = imx_clk_gate2("ocotp",        "ipg",    base + 0x70,  12);
+       clks[IMX6SLL_CLK_LCDIF_APB]     = imx_clk_gate2("lcdif_apb",    "axi",    base + 0x70,  28);
+       clks[IMX6SLL_CLK_PXP]           = imx_clk_gate2("pxp",          "axi",    base + 0x70,  30);
+
+       /* CCGR3 */
+       clks[IMX6SLL_CLK_UART5_IPG]     = imx_clk_gate2("uart5_ipg",    "ipg",          base + 0x74, 2);
+       clks[IMX6SLL_CLK_UART5_SERIAL]  = imx_clk_gate2("uart5_serial", "uart_podf",    base + 0x74, 2);
+       clks[IMX6SLL_CLK_EPDC_AXI]      = imx_clk_gate2("epdc_aclk",    "axi",          base + 0x74, 4);
+       clks[IMX6SLL_CLK_EPDC_PIX]      = imx_clk_gate2("epdc_pix",     "epdc_podf",    base + 0x74, 4);
+       clks[IMX6SLL_CLK_LCDIF_PIX]     = imx_clk_gate2("lcdif_pix",    "lcdif_podf",   base + 0x74, 10);
+       clks[IMX6SLL_CLK_WDOG1]         = imx_clk_gate2("wdog1",        "ipg",          base + 0x74, 16);
+       clks[IMX6SLL_CLK_MMDC_P0_FAST]  = imx_clk_gate_flags("mmdc_p0_fast", "mmdc_podf",  base + 0x74, 20, CLK_IS_CRITICAL);
+       clks[IMX6SLL_CLK_MMDC_P0_IPG]   = imx_clk_gate2_flags("mmdc_p0_ipg", "ipg",        base + 0x74, 24, CLK_IS_CRITICAL);
+       clks[IMX6SLL_CLK_OCRAM]         = imx_clk_gate_flags("ocram","ahb",                base + 0x74, 28, CLK_IS_CRITICAL);
+
+       /* CCGR4 */
+       clks[IMX6SLL_CLK_PWM1]          = imx_clk_gate2("pwm1", "perclk", base + 0x78, 16);
+       clks[IMX6SLL_CLK_PWM2]          = imx_clk_gate2("pwm2", "perclk", base + 0x78, 18);
+       clks[IMX6SLL_CLK_PWM3]          = imx_clk_gate2("pwm3", "perclk", base + 0x78, 20);
+       clks[IMX6SLL_CLK_PWM4]          = imx_clk_gate2("pwm4", "perclk", base + 0x78, 22);
+
+       /* CCGR5 */
+       clks[IMX6SLL_CLK_ROM]           = imx_clk_gate2_flags("rom", "ahb", base + 0x7c, 0, CLK_IS_CRITICAL);
+       clks[IMX6SLL_CLK_SDMA]          = imx_clk_gate2("sdma",  "ahb", base + 0x7c, 6);
+       clks[IMX6SLL_CLK_WDOG2]         = imx_clk_gate2("wdog2", "ipg", base + 0x7c, 10);
+       clks[IMX6SLL_CLK_SPBA]          = imx_clk_gate2("spba",  "ipg", base + 0x7c, 12);
+       clks[IMX6SLL_CLK_EXTERN_AUDIO]  = imx_clk_gate2_shared("extern_audio",  "extern_audio_podf", base + 0x7c, 14, &share_count_audio);
+       clks[IMX6SLL_CLK_SPDIF]         = imx_clk_gate2_shared("spdif",         "spdif_podf",   base + 0x7c, 14, &share_count_audio);
+       clks[IMX6SLL_CLK_SPDIF_GCLK]    = imx_clk_gate2_shared("spdif_gclk",    "ipg",          base + 0x7c, 14, &share_count_audio);
+       clks[IMX6SLL_CLK_SSI1]          = imx_clk_gate2_shared("ssi1",          "ssi1_podf",    base + 0x7c, 18, &share_count_ssi1);
+       clks[IMX6SLL_CLK_SSI1_IPG]      = imx_clk_gate2_shared("ssi1_ipg",      "ipg",          base + 0x7c, 18, &share_count_ssi1);
+       clks[IMX6SLL_CLK_SSI2]          = imx_clk_gate2_shared("ssi2",          "ssi2_podf",    base + 0x7c, 20, &share_count_ssi2);
+       clks[IMX6SLL_CLK_SSI2_IPG]      = imx_clk_gate2_shared("ssi2_ipg",      "ipg",          base + 0x7c, 20, &share_count_ssi2);
+       clks[IMX6SLL_CLK_SSI3]          = imx_clk_gate2_shared("ssi3",          "ssi3_podf",    base + 0x7c, 22, &share_count_ssi3);
+       clks[IMX6SLL_CLK_SSI3_IPG]      = imx_clk_gate2_shared("ssi3_ipg",      "ipg",          base + 0x7c, 22, &share_count_ssi3);
+       clks[IMX6SLL_CLK_UART1_IPG]     = imx_clk_gate2("uart1_ipg",    "ipg",          base + 0x7c, 24);
+       clks[IMX6SLL_CLK_UART1_SERIAL]  = imx_clk_gate2("uart1_serial", "uart_podf",    base + 0x7c, 24);
+
+       /* CCGR6 */
+       clks[IMX6SLL_CLK_USBOH3]        = imx_clk_gate2("usboh3", "ipg",          base + 0x80,  0);
+       clks[IMX6SLL_CLK_USDHC1]        = imx_clk_gate2("usdhc1", "usdhc1_podf",  base + 0x80,  2);
+       clks[IMX6SLL_CLK_USDHC2]        = imx_clk_gate2("usdhc2", "usdhc2_podf",  base + 0x80,  4);
+       clks[IMX6SLL_CLK_USDHC3]        = imx_clk_gate2("usdhc3", "usdhc3_podf",  base + 0x80,  6);
+
+       /* mask handshake of mmdc */
+       writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + 0x4);
+
+       imx_check_clocks(clks, ARRAY_SIZE(clks));
+
+       clk_data.clks = clks;
+       clk_data.clk_num = ARRAY_SIZE(clks);
+       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+       /* Lower the AHB clock rate before changing the clock source. */
+       clk_set_rate(clks[IMX6SLL_CLK_AHB], 99000000);
+
+       /* Change periph_pre clock to pll2_bus to adjust AXI rate to 264MHz */
+       clk_set_parent(clks[IMX6SLL_CLK_PERIPH_CLK2_SEL], clks[IMX6SLL_CLK_PLL3_USB_OTG]);
+       clk_set_parent(clks[IMX6SLL_CLK_PERIPH], clks[IMX6SLL_CLK_PERIPH_CLK2]);
+       clk_set_parent(clks[IMX6SLL_CLK_PERIPH_PRE], clks[IMX6SLL_CLK_PLL2_BUS]);
+       clk_set_parent(clks[IMX6SLL_CLK_PERIPH], clks[IMX6SLL_CLK_PERIPH_PRE]);
+
+       clk_set_rate(clks[IMX6SLL_CLK_AHB], 132000000);
+}
+CLK_OF_DECLARE_DRIVER(imx6sll, "fsl,imx6sll-ccm", imx6sll_clocks_init);
index e6d389e333d7d15bdb30cde8d2db45abc1706f3b..bc3f9ebf2d9e9124b64f0749fa1e32c81764a2a1 100644 (file)
@@ -63,17 +63,17 @@ static const char *lcdif2_sels[]    = { "lcdif2_podf", "ipp_di0", "ipp_di1", "ldb_d
 static const char *display_sels[]      = { "pll2_bus", "pll2_pfd2_396m", "pll3_usb_otg", "pll3_pfd1_540m", };
 static const char *csi_sels[]          = { "osc", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
 static const char *cko1_sels[]         = {
-       "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div",
-       "dummy", "ocram", "dummy", "pxp_axi", "epdc_axi", "lcdif_pix",
-       "epdc_pix", "ahb", "ipg", "perclk", "ckil", "pll4_audio_div",
+       "dummy", "dummy", "dummy", "dummy",
+       "vadc", "ocram", "qspi2", "m4", "enet_ahb", "lcdif2_pix",
+       "lcdif1_pix", "ahb", "ipg", "perclk", "ckil", "pll4_audio_div",
 };
 static const char *cko2_sels[]         = {
        "dummy", "mmdc_p0_fast", "usdhc4", "usdhc1", "dummy", "wrck",
        "ecspi_root", "dummy", "usdhc3", "pcie", "arm", "csi_core",
-       "lcdif_axi", "dummy", "osc", "dummy", "gpu2d_ovg_core",
-       "usdhc2", "ssi1", "ssi2", "ssi3", "gpu2d_core", "dummy",
-       "dummy", "dummy", "dummy", "esai_extal", "eim_slow", "uart_serial",
-       "spdif", "asrc", "dummy",
+       "display_axi", "dummy", "osc", "dummy", "dummy",
+       "usdhc2", "ssi1", "ssi2", "ssi3", "gpu_axi_podf", "dummy",
+       "can_podf", "lvds1_out", "qspi1", "esai_extal", "eim_slow",
+       "uart_serial", "spdif", "audio", "dummy",
 };
 static const char *cko_sels[] = { "cko1", "cko2", };
 static const char *lvds_sels[] = {
index 85c1181644697153c7b52ddd417bbe7630c8b5b1..114ecbb94ec5ed8d5e364c981d740ecc305d553a 100644 (file)
@@ -308,7 +308,10 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        clks[IMX6UL_CLK_SAI2_PODF]      = imx_clk_divider("sai2_podf",     "sai2_pred",         base + 0x2c, 0,  6);
        clks[IMX6UL_CLK_SPDIF_PRED]     = imx_clk_divider("spdif_pred",    "spdif_sel",         base + 0x30, 25, 3);
        clks[IMX6UL_CLK_SPDIF_PODF]     = imx_clk_divider("spdif_podf",    "spdif_pred",        base + 0x30, 22, 3);
-       clks[IMX6UL_CLK_SIM_PODF]       = imx_clk_divider("sim_podf",      "sim_pre_sel",       base + 0x34, 12, 3);
+       if (clk_on_imx6ul())
+               clks[IMX6UL_CLK_SIM_PODF]       = imx_clk_divider("sim_podf",      "sim_pre_sel",       base + 0x34, 12, 3);
+       else if (clk_on_imx6ull())
+               clks[IMX6ULL_CLK_EPDC_PODF]     = imx_clk_divider("epdc_podf",     "epdc_pre_sel",      base + 0x34, 12, 3);
        clks[IMX6UL_CLK_ECSPI_PODF]     = imx_clk_divider("ecspi_podf",    "ecspi_sel",         base + 0x38, 19, 6);
        clks[IMX6UL_CLK_LCDIF_PRED]     = imx_clk_divider("lcdif_pred",    "lcdif_pre_sel",     base + 0x38, 12, 3);
        clks[IMX6UL_CLK_CSI_PODF]       = imx_clk_divider("csi_podf",      "csi_sel",           base + 0x3c, 11, 3);
index 617beb234259bf234c7636b7f60d07327cb9d8c5..975a20d3cc94969faf060cc3184fda03bcebfd64 100644 (file)
@@ -51,20 +51,20 @@ static const char *arm_a7_sel[] = { "osc", "pll_arm_main_clk",
 
 static const char *arm_m4_sel[] = { "osc", "pll_sys_main_240m_clk",
        "pll_enet_250m_clk", "pll_sys_pfd2_270m_clk",
-       "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main_clk",
+       "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_post_div",
        "pll_usb_main_clk", };
 
 static const char *axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk",
        "pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd5_clk",
-       "pll_audio_post_div", "pll_video_main_clk", "pll_sys_pfd7_clk", };
+       "pll_audio_post_div", "pll_video_post_div", "pll_sys_pfd7_clk", };
 
 static const char *disp_axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk",
        "pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd6_clk",
-       "pll_sys_pfd7_clk", "pll_audio_post_div", "pll_video_main_clk", };
+       "pll_sys_pfd7_clk", "pll_audio_post_div", "pll_video_post_div", };
 
 static const char *enet_axi_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
        "pll_dram_533m_clk", "pll_enet_250m_clk",
-       "pll_sys_main_240m_clk", "pll_audio_post_div", "pll_video_main_clk",
+       "pll_sys_main_240m_clk", "pll_audio_post_div", "pll_video_post_div",
        "pll_sys_pfd4_clk", };
 
 static const char *nand_usdhc_bus_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
@@ -74,8 +74,8 @@ static const char *nand_usdhc_bus_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
 
 static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
        "pll_dram_533m_clk", "pll_sys_pfd0_392m_clk",
-       "pll_enet_125m_clk", "pll_usb_main_clk", "pll_audio_post_div",
-       "pll_video_main_clk", };
+       "pll_enet_250m_clk", "pll_usb_main_clk", "pll_audio_post_div",
+       "pll_video_post_div", };
 
 static const char *dram_phym_sel[] = { "pll_dram_main_clk",
        "dram_phym_alt_clk", };
@@ -86,7 +86,7 @@ static const char *dram_sel[] = { "pll_dram_main_clk",
 static const char *dram_phym_alt_sel[] = { "osc", "pll_dram_533m_clk",
        "pll_sys_main_clk", "pll_enet_500m_clk",
        "pll_usb_main_clk", "pll_sys_pfd7_clk", "pll_audio_post_div",
-       "pll_video_main_clk", };
+       "pll_video_post_div", };
 
 static const char *dram_alt_sel[] = { "osc", "pll_dram_533m_clk",
        "pll_sys_main_clk", "pll_enet_500m_clk",
@@ -108,62 +108,62 @@ static const char *pcie_phy_sel[] = { "osc", "pll_enet_100m_clk",
 
 static const char *epdc_pixel_sel[] = { "osc", "pll_sys_pfd1_332m_clk",
        "pll_dram_533m_clk", "pll_sys_main_clk", "pll_sys_pfd5_clk",
-       "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", "pll_video_main_clk", };
+       "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", "pll_video_post_div", };
 
 static const char *lcdif_pixel_sel[] = { "osc", "pll_sys_pfd5_clk",
        "pll_dram_533m_clk", "ext_clk_3", "pll_sys_pfd4_clk",
-       "pll_sys_pfd2_270m_clk", "pll_video_main_clk",
+       "pll_sys_pfd2_270m_clk", "pll_video_post_div",
        "pll_usb_main_clk", };
 
 static const char *mipi_dsi_sel[] = { "osc", "pll_sys_pfd5_clk",
        "pll_sys_pfd3_clk", "pll_sys_main_clk", "pll_sys_pfd0_196m_clk",
-       "pll_dram_533m_clk", "pll_video_main_clk", "pll_audio_post_div", };
+       "pll_dram_533m_clk", "pll_video_post_div", "pll_audio_post_div", };
 
 static const char *mipi_csi_sel[] = { "osc", "pll_sys_pfd4_clk",
        "pll_sys_pfd3_clk", "pll_sys_main_clk", "pll_sys_pfd0_196m_clk",
-       "pll_dram_533m_clk", "pll_video_main_clk", "pll_audio_post_div", };
+       "pll_dram_533m_clk", "pll_video_post_div", "pll_audio_post_div", };
 
 static const char *mipi_dphy_sel[] = { "osc", "pll_sys_main_120m_clk",
        "pll_dram_533m_clk", "pll_sys_pfd5_clk", "ref_1m_clk", "ext_clk_2",
-       "pll_video_main_clk", "ext_clk_3", };
+       "pll_video_post_div", "ext_clk_3", };
 
 static const char *sai1_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
-       "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_main_clk",
+       "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_post_div",
        "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_2", };
 
 static const char *sai2_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
-       "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_main_clk",
+       "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_post_div",
        "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_2", };
 
 static const char *sai3_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
-       "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_main_clk",
+       "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_post_div",
        "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_clk_3", };
 
 static const char *spdif_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
-       "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_main_clk",
+       "pll_audio_post_div", "pll_dram_533m_clk", "pll_video_post_div",
        "pll_sys_pfd4_clk", "pll_enet_125m_clk", "ext_3_clk", };
 
 static const char *enet1_ref_sel[] = { "osc", "pll_enet_125m_clk",
        "pll_enet_50m_clk", "pll_enet_25m_clk",
-       "pll_sys_main_120m_clk", "pll_audio_post_div", "pll_video_main_clk",
+       "pll_sys_main_120m_clk", "pll_audio_post_div", "pll_video_post_div",
        "ext_clk_4", };
 
 static const char *enet1_time_sel[] = { "osc", "pll_enet_100m_clk",
        "pll_audio_post_div", "ext_clk_1", "ext_clk_2", "ext_clk_3",
-       "ext_clk_4", "pll_video_main_clk", };
+       "ext_clk_4", "pll_video_post_div", };
 
 static const char *enet2_ref_sel[] = { "osc", "pll_enet_125m_clk",
        "pll_enet_50m_clk", "pll_enet_25m_clk",
-       "pll_sys_main_120m_clk", "pll_audio_post_div", "pll_video_main_clk",
+       "pll_sys_main_120m_clk", "pll_audio_post_div", "pll_video_post_div",
        "ext_clk_4", };
 
 static const char *enet2_time_sel[] = { "osc", "pll_enet_100m_clk",
        "pll_audio_post_div", "ext_clk_1", "ext_clk_2", "ext_clk_3",
-       "ext_clk_4", "pll_video_main_clk", };
+       "ext_clk_4", "pll_video_post_div", };
 
 static const char *enet_phy_ref_sel[] = { "osc", "pll_enet_25m_clk",
        "pll_enet_50m_clk", "pll_enet_125m_clk",
-       "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main_clk",
+       "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_post_div",
        "pll_sys_pfd3_clk", };
 
 static const char *eim_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
@@ -174,7 +174,7 @@ static const char *eim_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
 static const char *nand_sel[] = { "osc", "pll_sys_main_clk",
        "pll_dram_533m_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd3_clk",
        "pll_enet_500m_clk", "pll_enet_250m_clk",
-       "pll_video_main_clk", };
+       "pll_video_post_div", };
 
 static const char *qspi_sel[] = { "osc", "pll_sys_pfd4_clk",
        "pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd3_clk",
@@ -204,22 +204,22 @@ static const char *can2_sel[] = { "osc", "pll_sys_main_120m_clk",
 
 static const char *i2c1_sel[] = { "osc", "pll_sys_main_120m_clk",
        "pll_enet_50m_clk", "pll_dram_533m_clk",
-       "pll_audio_post_div", "pll_video_main_clk", "pll_usb_main_clk",
+       "pll_audio_post_div", "pll_video_post_div", "pll_usb_main_clk",
        "pll_sys_pfd2_135m_clk", };
 
 static const char *i2c2_sel[] = { "osc", "pll_sys_main_120m_clk",
        "pll_enet_50m_clk", "pll_dram_533m_clk",
-       "pll_audio_post_div", "pll_video_main_clk", "pll_usb_main_clk",
+       "pll_audio_post_div", "pll_video_post_div", "pll_usb_main_clk",
        "pll_sys_pfd2_135m_clk", };
 
 static const char *i2c3_sel[] = { "osc", "pll_sys_main_120m_clk",
        "pll_enet_50m_clk", "pll_dram_533m_clk",
-       "pll_audio_post_div", "pll_video_main_clk", "pll_usb_main_clk",
+       "pll_audio_post_div", "pll_video_post_div", "pll_usb_main_clk",
        "pll_sys_pfd2_135m_clk", };
 
 static const char *i2c4_sel[] = { "osc", "pll_sys_main_120m_clk",
        "pll_enet_50m_clk", "pll_dram_533m_clk",
-       "pll_audio_post_div", "pll_video_main_clk", "pll_usb_main_clk",
+       "pll_audio_post_div", "pll_video_post_div", "pll_usb_main_clk",
        "pll_sys_pfd2_135m_clk", };
 
 static const char *uart1_sel[] = { "osc", "pll_sys_main_240m_clk",
@@ -279,27 +279,27 @@ static const char *ecspi4_sel[] = { "osc", "pll_sys_main_240m_clk",
 
 static const char *pwm1_sel[] = { "osc", "pll_enet_100m_clk",
        "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div",
-       "ext_clk_1", "ref_1m_clk", "pll_video_main_clk", };
+       "ext_clk_1", "ref_1m_clk", "pll_video_post_div", };
 
 static const char *pwm2_sel[] = { "osc", "pll_enet_100m_clk",
        "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div",
-       "ext_clk_1", "ref_1m_clk", "pll_video_main_clk", };
+       "ext_clk_1", "ref_1m_clk", "pll_video_post_div", };
 
 static const char *pwm3_sel[] = { "osc", "pll_enet_100m_clk",
        "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div",
-       "ext_clk_2", "ref_1m_clk", "pll_video_main_clk", };
+       "ext_clk_2", "ref_1m_clk", "pll_video_post_div", };
 
 static const char *pwm4_sel[] = { "osc", "pll_enet_100m_clk",
        "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div",
-       "ext_clk_2", "ref_1m_clk", "pll_video_main_clk", };
+       "ext_clk_2", "ref_1m_clk", "pll_video_post_div", };
 
 static const char *flextimer1_sel[] = { "osc", "pll_enet_100m_clk",
        "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div",
-       "ext_clk_3", "ref_1m_clk", "pll_video_main_clk", };
+       "ext_clk_3", "ref_1m_clk", "pll_video_post_div", };
 
 static const char *flextimer2_sel[] = { "osc", "pll_enet_100m_clk",
        "pll_sys_main_120m_clk", "pll_enet_40m_clk", "pll_audio_post_div",
-       "ext_clk_3", "ref_1m_clk", "pll_video_main_clk", };
+       "ext_clk_3", "ref_1m_clk", "pll_video_post_div", };
 
 static const char *sim1_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
        "pll_sys_main_120m_clk", "pll_dram_533m_clk",
@@ -308,23 +308,23 @@ static const char *sim1_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
 
 static const char *sim2_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
        "pll_sys_main_120m_clk", "pll_dram_533m_clk",
-       "pll_usb_main_clk", "pll_video_main_clk", "pll_enet_125m_clk",
+       "pll_usb_main_clk", "pll_video_post_div", "pll_enet_125m_clk",
        "pll_sys_pfd7_clk", };
 
 static const char *gpt1_sel[] = { "osc", "pll_enet_100m_clk",
-       "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk",
+       "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_post_div",
        "ref_1m_clk", "pll_audio_post_div", "ext_clk_1", };
 
 static const char *gpt2_sel[] = { "osc", "pll_enet_100m_clk",
-       "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk",
+       "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_post_div",
        "ref_1m_clk", "pll_audio_post_div", "ext_clk_2", };
 
 static const char *gpt3_sel[] = { "osc", "pll_enet_100m_clk",
-       "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk",
+       "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_post_div",
        "ref_1m_clk", "pll_audio_post_div", "ext_clk_3", };
 
 static const char *gpt4_sel[] = { "osc", "pll_enet_100m_clk",
-       "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_main_clk",
+       "pll_sys_pfd0_392m_clk", "pll_enet_40m_clk", "pll_video_post_div",
        "ref_1m_clk", "pll_audio_post_div", "ext_clk_4", };
 
 static const char *trace_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
@@ -339,12 +339,12 @@ static const char *wdog_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
 
 static const char *csi_mclk_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
        "pll_sys_main_120m_clk", "pll_dram_533m_clk",
-       "pll_enet_125m_clk", "pll_audio_post_div", "pll_video_main_clk",
+       "pll_enet_125m_clk", "pll_audio_post_div", "pll_video_post_div",
        "pll_usb_main_clk", };
 
 static const char *audio_mclk_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
        "pll_sys_main_120m_clk", "pll_dram_533m_clk",
-       "pll_enet_125m_clk", "pll_audio_post_div", "pll_video_main_clk",
+       "pll_enet_125m_clk", "pll_audio_post_div", "pll_video_post_div",
        "pll_usb_main_clk", };
 
 static const char *wrclk_sel[] = { "osc", "pll_enet_40m_clk",
@@ -358,13 +358,13 @@ static const char *clko1_sel[] = { "osc", "pll_sys_main_clk",
 
 static const char *clko2_sel[] = { "osc", "pll_sys_main_240m_clk",
        "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_166m_clk", "pll_sys_pfd4_clk",
-       "pll_audio_post_div", "pll_video_main_clk", "ckil", };
+       "pll_audio_post_div", "pll_video_post_div", "ckil", };
 
 static const char *lvds1_sel[] = { "pll_arm_main_clk",
        "pll_sys_main_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_332m_clk",
        "pll_sys_pfd2_270m_clk", "pll_sys_pfd3_clk", "pll_sys_pfd4_clk",
        "pll_sys_pfd5_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk",
-       "pll_audio_post_div", "pll_video_main_clk", "pll_enet_500m_clk",
+       "pll_audio_post_div", "pll_video_post_div", "pll_enet_500m_clk",
        "pll_enet_250m_clk", "pll_enet_125m_clk", "pll_enet_100m_clk",
        "pll_enet_50m_clk", "pll_enet_40m_clk", "pll_enet_25m_clk",
        "pll_dram_main_clk", };
@@ -433,23 +433,22 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
        clks[IMX7D_PLL_AUDIO_MAIN_BYPASS] = imx_clk_mux_flags("pll_audio_main_bypass", base + 0xf0, 16, 1, pll_audio_bypass_sel, ARRAY_SIZE(pll_audio_bypass_sel), CLK_SET_RATE_PARENT);
        clks[IMX7D_PLL_VIDEO_MAIN_BYPASS] = imx_clk_mux_flags("pll_video_main_bypass", base + 0x130, 16, 1, pll_video_bypass_sel, ARRAY_SIZE(pll_video_bypass_sel), CLK_SET_RATE_PARENT);
 
-       clk_set_parent(clks[IMX7D_PLL_ARM_MAIN_BYPASS], clks[IMX7D_PLL_ARM_MAIN]);
-       clk_set_parent(clks[IMX7D_PLL_DRAM_MAIN_BYPASS], clks[IMX7D_PLL_DRAM_MAIN]);
-       clk_set_parent(clks[IMX7D_PLL_SYS_MAIN_BYPASS], clks[IMX7D_PLL_SYS_MAIN]);
-       clk_set_parent(clks[IMX7D_PLL_ENET_MAIN_BYPASS], clks[IMX7D_PLL_ENET_MAIN]);
-       clk_set_parent(clks[IMX7D_PLL_AUDIO_MAIN_BYPASS], clks[IMX7D_PLL_AUDIO_MAIN]);
-       clk_set_parent(clks[IMX7D_PLL_VIDEO_MAIN_BYPASS], clks[IMX7D_PLL_VIDEO_MAIN]);
-
        clks[IMX7D_PLL_ARM_MAIN_CLK] = imx_clk_gate("pll_arm_main_clk", "pll_arm_main_bypass", base + 0x60, 13);
-       clks[IMX7D_PLL_DRAM_MAIN_CLK] = imx_clk_gate("pll_dram_main_clk", "pll_dram_main_bypass", base + 0x70, 13);
+       clks[IMX7D_PLL_DRAM_MAIN_CLK] = imx_clk_gate("pll_dram_main_clk", "pll_dram_test_div", base + 0x70, 13);
        clks[IMX7D_PLL_SYS_MAIN_CLK] = imx_clk_gate("pll_sys_main_clk", "pll_sys_main_bypass", base + 0xb0, 13);
        clks[IMX7D_PLL_AUDIO_MAIN_CLK] = imx_clk_gate("pll_audio_main_clk", "pll_audio_main_bypass", base + 0xf0, 13);
        clks[IMX7D_PLL_VIDEO_MAIN_CLK] = imx_clk_gate("pll_video_main_clk", "pll_video_main_bypass", base + 0x130, 13);
 
+       clks[IMX7D_PLL_DRAM_TEST_DIV]  = clk_register_divider_table(NULL, "pll_dram_test_div", "pll_dram_main_bypass",
+                               CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x70, 21, 2, 0, test_div_table, &imx_ccm_lock);
        clks[IMX7D_PLL_AUDIO_TEST_DIV]  = clk_register_divider_table(NULL, "pll_audio_test_div", "pll_audio_main_clk",
                                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xf0, 19, 2, 0, test_div_table, &imx_ccm_lock);
        clks[IMX7D_PLL_AUDIO_POST_DIV] = clk_register_divider_table(NULL, "pll_audio_post_div", "pll_audio_test_div",
                                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xf0, 22, 2, 0, post_div_table, &imx_ccm_lock);
+       clks[IMX7D_PLL_VIDEO_TEST_DIV]  = clk_register_divider_table(NULL, "pll_video_test_div", "pll_video_main_clk",
+                               CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x130, 19, 2, 0, test_div_table, &imx_ccm_lock);
+       clks[IMX7D_PLL_VIDEO_POST_DIV] = clk_register_divider_table(NULL, "pll_video_post_div", "pll_video_test_div",
+                               CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x130, 22, 2, 0, post_div_table, &imx_ccm_lock);
 
        clks[IMX7D_PLL_SYS_PFD0_392M_CLK] = imx_clk_pfd("pll_sys_pfd0_392m_clk", "pll_sys_main_clk", base + 0xc0, 0);
        clks[IMX7D_PLL_SYS_PFD1_332M_CLK] = imx_clk_pfd("pll_sys_pfd1_332m_clk", "pll_sys_main_clk", base + 0xc0, 1);
@@ -797,7 +796,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
        clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
        clks[IMX7D_SNVS_CLK] = imx_clk_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0);
        clks[IMX7D_CAAM_CLK] = imx_clk_gate4("caam_clk", "ipg_root_clk", base + 0x4240, 0);
-       clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate4("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4420, 0);
+       clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate4("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4690, 0);
        clks[IMX7D_SDMA_CORE_CLK] = imx_clk_gate4("sdma_root_clk", "ahb_root_clk", base + 0x4480, 0);
        clks[IMX7D_PCIE_CTRL_ROOT_CLK] = imx_clk_gate4("pcie_ctrl_root_clk", "pcie_ctrl_post_div", base + 0x4600, 0);
        clks[IMX7D_PCIE_PHY_ROOT_CLK] = imx_clk_gate4("pcie_phy_root_clk", "pcie_phy_post_div", base + 0x4600, 0);
@@ -863,6 +862,9 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
        clks[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_gate4("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0);
        clks[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_gate4("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0);
        clks[IMX7D_WRCLK_ROOT_CLK] = imx_clk_gate4("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0);
+       clks[IMX7D_USB_CTRL_CLK] = imx_clk_gate4("usb_ctrl_clk", "ahb_root_clk", base + 0x4680, 0);
+       clks[IMX7D_USB_PHY1_CLK] = imx_clk_gate4("usb_phy1_clk", "pll_usb1_main_clk", base + 0x46a0, 0);
+       clks[IMX7D_USB_PHY2_CLK] = imx_clk_gate4("usb_phy2_clk", "pll_usb_main_clk", base + 0x46b0, 0);
        clks[IMX7D_ADC_ROOT_CLK] = imx_clk_gate4("adc_root_clk", "ipg_root_clk", base + 0x4200, 0);
 
        clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
@@ -882,12 +884,23 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
        for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
                clk_prepare_enable(clks[clks_init_on[i]]);
 
+       clk_set_parent(clks[IMX7D_PLL_ARM_MAIN_BYPASS], clks[IMX7D_PLL_ARM_MAIN]);
+       clk_set_parent(clks[IMX7D_PLL_DRAM_MAIN_BYPASS], clks[IMX7D_PLL_DRAM_MAIN]);
+       clk_set_parent(clks[IMX7D_PLL_SYS_MAIN_BYPASS], clks[IMX7D_PLL_SYS_MAIN]);
+       clk_set_parent(clks[IMX7D_PLL_ENET_MAIN_BYPASS], clks[IMX7D_PLL_ENET_MAIN]);
+       clk_set_parent(clks[IMX7D_PLL_AUDIO_MAIN_BYPASS], clks[IMX7D_PLL_AUDIO_MAIN]);
+       clk_set_parent(clks[IMX7D_PLL_VIDEO_MAIN_BYPASS], clks[IMX7D_PLL_VIDEO_MAIN]);
+
        /* use old gpt clk setting, gpt1 root clk must be twice as gpt counter freq */
        clk_set_parent(clks[IMX7D_GPT1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]);
 
        /* set uart module clock's parent clock source that must be great then 80MHz */
        clk_set_parent(clks[IMX7D_UART1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]);
 
+       /* Set clock rate for USBPHY, the USB_PLL at CCM is from USBOTG2 */
+       clks[IMX7D_USB1_MAIN_480M_CLK] = imx_clk_fixed_factor("pll_usb1_main_clk", "osc", 20, 1);
+       clks[IMX7D_USB_MAIN_480M_CLK] = imx_clk_fixed_factor("pll_usb_main_clk", "osc", 20, 1);
+
        imx_register_uart_clocks(uart_clks);
 
 }
index 85b5cbe9744caff244e41634db93d619ada1123c..eeba3cb14e2de8432ec8acb358bb6e0fad1a0f73 100644 (file)
@@ -182,8 +182,12 @@ static long clk_pllv2_round_rate(struct clk_hw *hw, unsigned long rate,
                unsigned long *prate)
 {
        u32 dp_op, dp_mfd, dp_mfn;
+       int ret;
+
+       ret = __clk_pllv2_set_rate(rate, *prate, &dp_op, &dp_mfd, &dp_mfn);
+       if (ret)
+               return ret;
 
-       __clk_pllv2_set_rate(rate, *prate, &dp_op, &dp_mfd, &dp_mfn);
        return __clk_pllv2_recalc_rate(*prate, MXC_PLL_DP_CTL_DPDCK0_2_EN,
                        dp_op, dp_mfd, dp_mfn);
 }
index d69c4bbf35971e7b46d7e4ea38f98f2661324454..8076ec040f375f2715c227d64f909e562ae178b5 100644 (file)
@@ -123,6 +123,13 @@ static inline struct clk *imx_clk_gate(const char *name, const char *parent,
                        shift, 0, &imx_ccm_lock);
 }
 
+static inline struct clk *imx_clk_gate_flags(const char *name, const char *parent,
+               void __iomem *reg, u8 shift, unsigned long flags)
+{
+       return clk_register_gate(NULL, name, parent, flags | CLK_SET_RATE_PARENT, reg,
+                       shift, 0, &imx_ccm_lock);
+}
+
 static inline struct clk *imx_clk_gate_dis(const char *name, const char *parent,
                void __iomem *reg, u8 shift)
 {
@@ -137,6 +144,13 @@ static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
                        shift, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
+static inline struct clk *imx_clk_gate2_flags(const char *name, const char *parent,
+               void __iomem *reg, u8 shift, unsigned long flags)
+{
+       return clk_register_gate2(NULL, name, parent, flags | CLK_SET_RATE_PARENT, reg,
+                       shift, 0x3, 0, &imx_ccm_lock, NULL);
+}
+
 static inline struct clk *imx_clk_gate2_shared(const char *name,
                const char *parent, void __iomem *reg, u8 shift,
                unsigned int *share_count)
index 9cdf9d5050aca80858d3dc9dfcea416d91912b97..4cb70bed89a9f1fc23841d46f70bc1da0616a395 100644 (file)
 #define SCI_CLK_ALLOW_FREQ_CHANGE      BIT(1)
 #define SCI_CLK_INPUT_TERMINATION      BIT(2)
 
-/**
- * struct sci_clk_data - TI SCI clock data
- * @dev: device index
- * @num_clks: number of clocks for this device
- */
-struct sci_clk_data {
-       u16 dev;
-       u16 num_clks;
-};
-
 /**
  * struct sci_clk_provider - TI SCI clock provider representation
  * @sci: Handle to the System Control Interface protocol handler
  * @ops: Pointer to the SCI ops to be used by the clocks
  * @dev: Device pointer for the clock provider
- * @clk_data: Clock data
  * @clocks: Clocks array for this device
  * @num_clocks: Total number of clocks for this provider
  */
@@ -51,8 +40,7 @@ struct sci_clk_provider {
        const struct ti_sci_handle *sci;
        const struct ti_sci_clk_ops *ops;
        struct device *dev;
-       const struct sci_clk_data *clk_data;
-       struct clk_hw **clocks;
+       struct sci_clk **clocks;
        int num_clocks;
 };
 
@@ -61,6 +49,7 @@ struct sci_clk_provider {
  * @hw:                 Hardware clock cookie for common clock framework
  * @dev_id:     Device index
  * @clk_id:     Clock index
+ * @num_parents: Number of parents for this clock
  * @provider:   Master clock provider
  * @flags:      Flags for the clock
  */
@@ -68,6 +57,7 @@ struct sci_clk {
        struct clk_hw hw;
        u16 dev_id;
        u8 clk_id;
+       u8 num_parents;
        struct sci_clk_provider *provider;
        u8 flags;
 };
@@ -273,38 +263,22 @@ static const struct clk_ops sci_clk_ops = {
 /**
  * _sci_clk_get - Gets a handle for an SCI clock
  * @provider: Handle to SCI clock provider
- * @dev_id: device ID for the clock to register
- * @clk_id: clock ID for the clock to register
+ * @sci_clk: Handle to the SCI clock to populate
  *
  * Gets a handle to an existing TI SCI hw clock, or builds a new clock
  * entry and registers it with the common clock framework. Called from
  * the common clock framework, when a corresponding of_clk_get call is
  * executed, or recursively from itself when parsing parent clocks.
- * Returns a pointer to the hw clock struct, or ERR_PTR value in failure.
+ * Returns 0 on success, negative error code on failure.
  */
-static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
-                                    u16 dev_id, u8 clk_id)
+static int _sci_clk_build(struct sci_clk_provider *provider,
+                         struct sci_clk *sci_clk)
 {
        struct clk_init_data init = { NULL };
-       struct sci_clk *sci_clk = NULL;
        char *name = NULL;
        char **parent_names = NULL;
        int i;
-       int ret;
-
-       sci_clk = devm_kzalloc(provider->dev, sizeof(*sci_clk), GFP_KERNEL);
-       if (!sci_clk)
-               return ERR_PTR(-ENOMEM);
-
-       sci_clk->dev_id = dev_id;
-       sci_clk->clk_id = clk_id;
-       sci_clk->provider = provider;
-
-       ret = provider->ops->get_num_parents(provider->sci, dev_id,
-                                            clk_id,
-                                            &init.num_parents);
-       if (ret)
-               goto err;
+       int ret = 0;
 
        name = kasprintf(GFP_KERNEL, "%s:%d:%d", dev_name(provider->dev),
                         sci_clk->dev_id, sci_clk->clk_id);
@@ -317,11 +291,11 @@ static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
         * to have mux functionality. Otherwise it is going to act as a root
         * clock.
         */
-       if (init.num_parents < 2)
-               init.num_parents = 0;
+       if (sci_clk->num_parents < 2)
+               sci_clk->num_parents = 0;
 
-       if (init.num_parents) {
-               parent_names = kcalloc(init.num_parents, sizeof(char *),
+       if (sci_clk->num_parents) {
+               parent_names = kcalloc(sci_clk->num_parents, sizeof(char *),
                                       GFP_KERNEL);
 
                if (!parent_names) {
@@ -329,7 +303,7 @@ static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
                        goto err;
                }
 
-               for (i = 0; i < init.num_parents; i++) {
+               for (i = 0; i < sci_clk->num_parents; i++) {
                        char *parent_name;
 
                        parent_name = kasprintf(GFP_KERNEL, "%s:%d:%d",
@@ -346,6 +320,7 @@ static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
        }
 
        init.ops = &sci_clk_ops;
+       init.num_parents = sci_clk->num_parents;
        sci_clk->hw.init = &init;
 
        ret = devm_clk_hw_register(provider->dev, &sci_clk->hw);
@@ -354,7 +329,7 @@ static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
 
 err:
        if (parent_names) {
-               for (i = 0; i < init.num_parents; i++)
+               for (i = 0; i < sci_clk->num_parents; i++)
                        kfree(parent_names[i]);
 
                kfree(parent_names);
@@ -362,10 +337,7 @@ err:
 
        kfree(name);
 
-       if (ret)
-               return ERR_PTR(ret);
-
-       return &sci_clk->hw;
+       return ret;
 }
 
 static int _cmp_sci_clk(const void *a, const void *b)
@@ -414,253 +386,20 @@ static struct clk_hw *sci_clk_get(struct of_phandle_args *clkspec, void *data)
 
 static int ti_sci_init_clocks(struct sci_clk_provider *p)
 {
-       const struct sci_clk_data *data = p->clk_data;
-       struct clk_hw *hw;
        int i;
-       int num_clks = 0;
-
-       while (data->num_clks) {
-               num_clks += data->num_clks;
-               data++;
-       }
-
-       p->num_clocks = num_clks;
-
-       p->clocks = devm_kcalloc(p->dev, num_clks, sizeof(struct sci_clk),
-                                GFP_KERNEL);
-       if (!p->clocks)
-               return -ENOMEM;
-
-       num_clks = 0;
-
-       data = p->clk_data;
-
-       while (data->num_clks) {
-               for (i = 0; i < data->num_clks; i++) {
-                       hw = _sci_clk_build(p, data->dev, i);
-                       if (!IS_ERR(hw)) {
-                               p->clocks[num_clks++] = hw;
-                               continue;
-                       }
-
-                       /* Skip any holes in the clock lists */
-                       if (PTR_ERR(hw) == -ENODEV)
-                               continue;
+       int ret;
 
-                       return PTR_ERR(hw);
-               }
-               data++;
+       for (i = 0; i < p->num_clocks; i++) {
+               ret = _sci_clk_build(p, p->clocks[i]);
+               if (ret)
+                       return ret;
        }
 
        return 0;
 }
 
-static const struct sci_clk_data k2g_clk_data[] = {
-       /* pmmc */
-       { .dev = 0x0, .num_clks = 4 },
-
-       /* mlb0 */
-       { .dev = 0x1, .num_clks = 5 },
-
-       /* dss0 */
-       { .dev = 0x2, .num_clks = 2 },
-
-       /* mcbsp0 */
-       { .dev = 0x3, .num_clks = 8 },
-
-       /* mcasp0 */
-       { .dev = 0x4, .num_clks = 8 },
-
-       /* mcasp1 */
-       { .dev = 0x5, .num_clks = 8 },
-
-       /* mcasp2 */
-       { .dev = 0x6, .num_clks = 8 },
-
-       /* dcan0 */
-       { .dev = 0x8, .num_clks = 2 },
-
-       /* dcan1 */
-       { .dev = 0x9, .num_clks = 2 },
-
-       /* emif0 */
-       { .dev = 0xa, .num_clks = 6 },
-
-       /* mmchs0 */
-       { .dev = 0xb, .num_clks = 3 },
-
-       /* mmchs1 */
-       { .dev = 0xc, .num_clks = 3 },
-
-       /* gpmc0 */
-       { .dev = 0xd, .num_clks = 1 },
-
-       /* elm0 */
-       { .dev = 0xe, .num_clks = 1 },
-
-       /* spi0 */
-       { .dev = 0x10, .num_clks = 1 },
-
-       /* spi1 */
-       { .dev = 0x11, .num_clks = 1 },
-
-       /* spi2 */
-       { .dev = 0x12, .num_clks = 1 },
-
-       /* spi3 */
-       { .dev = 0x13, .num_clks = 1 },
-
-       /* icss0 */
-       { .dev = 0x14, .num_clks = 6 },
-
-       /* icss1 */
-       { .dev = 0x15, .num_clks = 6 },
-
-       /* usb0 */
-       { .dev = 0x16, .num_clks = 7 },
-
-       /* usb1 */
-       { .dev = 0x17, .num_clks = 7 },
-
-       /* nss0 */
-       { .dev = 0x18, .num_clks = 14 },
-
-       /* pcie0 */
-       { .dev = 0x19, .num_clks = 1 },
-
-       /* gpio0 */
-       { .dev = 0x1b, .num_clks = 1 },
-
-       /* gpio1 */
-       { .dev = 0x1c, .num_clks = 1 },
-
-       /* timer64_0 */
-       { .dev = 0x1d, .num_clks = 9 },
-
-       /* timer64_1 */
-       { .dev = 0x1e, .num_clks = 9 },
-
-       /* timer64_2 */
-       { .dev = 0x1f, .num_clks = 9 },
-
-       /* timer64_3 */
-       { .dev = 0x20, .num_clks = 9 },
-
-       /* timer64_4 */
-       { .dev = 0x21, .num_clks = 9 },
-
-       /* timer64_5 */
-       { .dev = 0x22, .num_clks = 9 },
-
-       /* timer64_6 */
-       { .dev = 0x23, .num_clks = 9 },
-
-       /* msgmgr0 */
-       { .dev = 0x25, .num_clks = 1 },
-
-       /* bootcfg0 */
-       { .dev = 0x26, .num_clks = 1 },
-
-       /* arm_bootrom0 */
-       { .dev = 0x27, .num_clks = 1 },
-
-       /* dsp_bootrom0 */
-       { .dev = 0x29, .num_clks = 1 },
-
-       /* debugss0 */
-       { .dev = 0x2b, .num_clks = 8 },
-
-       /* uart0 */
-       { .dev = 0x2c, .num_clks = 1 },
-
-       /* uart1 */
-       { .dev = 0x2d, .num_clks = 1 },
-
-       /* uart2 */
-       { .dev = 0x2e, .num_clks = 1 },
-
-       /* ehrpwm0 */
-       { .dev = 0x2f, .num_clks = 1 },
-
-       /* ehrpwm1 */
-       { .dev = 0x30, .num_clks = 1 },
-
-       /* ehrpwm2 */
-       { .dev = 0x31, .num_clks = 1 },
-
-       /* ehrpwm3 */
-       { .dev = 0x32, .num_clks = 1 },
-
-       /* ehrpwm4 */
-       { .dev = 0x33, .num_clks = 1 },
-
-       /* ehrpwm5 */
-       { .dev = 0x34, .num_clks = 1 },
-
-       /* eqep0 */
-       { .dev = 0x35, .num_clks = 1 },
-
-       /* eqep1 */
-       { .dev = 0x36, .num_clks = 1 },
-
-       /* eqep2 */
-       { .dev = 0x37, .num_clks = 1 },
-
-       /* ecap0 */
-       { .dev = 0x38, .num_clks = 1 },
-
-       /* ecap1 */
-       { .dev = 0x39, .num_clks = 1 },
-
-       /* i2c0 */
-       { .dev = 0x3a, .num_clks = 1 },
-
-       /* i2c1 */
-       { .dev = 0x3b, .num_clks = 1 },
-
-       /* i2c2 */
-       { .dev = 0x3c, .num_clks = 1 },
-
-       /* edma0 */
-       { .dev = 0x3f, .num_clks = 2 },
-
-       /* semaphore0 */
-       { .dev = 0x40, .num_clks = 1 },
-
-       /* intc0 */
-       { .dev = 0x41, .num_clks = 1 },
-
-       /* gic0 */
-       { .dev = 0x42, .num_clks = 1 },
-
-       /* qspi0 */
-       { .dev = 0x43, .num_clks = 5 },
-
-       /* arm_64b_counter0 */
-       { .dev = 0x44, .num_clks = 2 },
-
-       /* tetris0 */
-       { .dev = 0x45, .num_clks = 2 },
-
-       /* cgem0 */
-       { .dev = 0x46, .num_clks = 2 },
-
-       /* msmc0 */
-       { .dev = 0x47, .num_clks = 1 },
-
-       /* cbass0 */
-       { .dev = 0x49, .num_clks = 1 },
-
-       /* board0 */
-       { .dev = 0x4c, .num_clks = 36 },
-
-       /* edma1 */
-       { .dev = 0x4f, .num_clks = 2 },
-       { .num_clks = 0 },
-};
-
 static const struct of_device_id ti_sci_clk_of_match[] = {
-       { .compatible = "ti,k2g-sci-clk", .data = &k2g_clk_data },
+       { .compatible = "ti,k2g-sci-clk" },
        { /* Sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, ti_sci_clk_of_match);
@@ -681,12 +420,16 @@ static int ti_sci_clk_probe(struct platform_device *pdev)
        struct device_node *np = dev->of_node;
        struct sci_clk_provider *provider;
        const struct ti_sci_handle *handle;
-       const struct sci_clk_data *data;
        int ret;
-
-       data = of_device_get_match_data(dev);
-       if (!data)
-               return -EINVAL;
+       int num_clks = 0;
+       struct sci_clk **clks = NULL;
+       struct sci_clk **tmp_clks;
+       struct sci_clk *sci_clk;
+       int max_clks = 0;
+       int clk_id = 0;
+       int dev_id = 0;
+       u8 num_parents;
+       int gap_size = 0;
 
        handle = devm_ti_sci_get_handle(dev);
        if (IS_ERR(handle))
@@ -696,12 +439,69 @@ static int ti_sci_clk_probe(struct platform_device *pdev)
        if (!provider)
                return -ENOMEM;
 
-       provider->clk_data = data;
-
        provider->sci = handle;
        provider->ops = &handle->ops.clk_ops;
        provider->dev = dev;
 
+       while (1) {
+               ret = provider->ops->get_num_parents(provider->sci, dev_id,
+                                                    clk_id, &num_parents);
+               if (ret) {
+                       gap_size++;
+                       if (!clk_id) {
+                               if (gap_size >= 5)
+                                       break;
+                               dev_id++;
+                       } else {
+                               if (gap_size >= 2) {
+                                       dev_id++;
+                                       clk_id = 0;
+                                       gap_size = 0;
+                               } else {
+                                       clk_id++;
+                               }
+                       }
+                       continue;
+               }
+
+               gap_size = 0;
+
+               if (num_clks == max_clks) {
+                       tmp_clks = devm_kmalloc_array(dev, max_clks + 64,
+                                                     sizeof(sci_clk),
+                                                     GFP_KERNEL);
+                       memcpy(tmp_clks, clks, max_clks * sizeof(sci_clk));
+                       if (max_clks)
+                               devm_kfree(dev, clks);
+                       max_clks += 64;
+                       clks = tmp_clks;
+               }
+
+               sci_clk = devm_kzalloc(dev, sizeof(*sci_clk), GFP_KERNEL);
+               if (!sci_clk)
+                       return -ENOMEM;
+               sci_clk->dev_id = dev_id;
+               sci_clk->clk_id = clk_id;
+               sci_clk->provider = provider;
+               sci_clk->num_parents = num_parents;
+
+               clks[num_clks] = sci_clk;
+
+               clk_id++;
+               num_clks++;
+       }
+
+       provider->clocks = devm_kmalloc_array(dev, num_clks, sizeof(sci_clk),
+                                             GFP_KERNEL);
+       if (!provider->clocks)
+               return -ENOMEM;
+
+       memcpy(provider->clocks, clks, num_clks * sizeof(sci_clk));
+
+       provider->num_clocks = num_clks;
+
+       devm_kfree(dev, clks);
+
        ret = ti_sci_init_clocks(provider);
        if (ret) {
                pr_err("ti-sci-init-clocks failed.\n");
index 1f9ea0f21df132db1aa62d88877bdf7486bf8904..92afe5989e97e322b838fd1b175e1a11386c7649 100644 (file)
@@ -54,6 +54,12 @@ config COMMON_CLK_MT2701_BDPSYS
        ---help---
          This driver supports MediaTek MT2701 bdpsys clocks.
 
+config COMMON_CLK_MT2701_AUDSYS
+       bool "Clock driver for Mediatek MT2701 audsys"
+       depends on COMMON_CLK_MT2701
+       ---help---
+         This driver supports Mediatek MT2701 audsys clocks.
+
 config COMMON_CLK_MT2712
        bool "Clock driver for MediaTek MT2712"
        depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
index 5160fdc4bbb8e6892c01389944faefeb1ed3d7da..b80eff2abb315bae42078fc89d3f723eab4224c7 100644 (file)
@@ -6,6 +6,7 @@ obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o
 obj-$(CONFIG_COMMON_CLK_MT6797_VDECSYS) += clk-mt6797-vdec.o
 obj-$(CONFIG_COMMON_CLK_MT6797_VENCSYS) += clk-mt6797-venc.o
 obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o
+obj-$(CONFIG_COMMON_CLK_MT2701_AUDSYS) += clk-mt2701-aud.o
 obj-$(CONFIG_COMMON_CLK_MT2701_BDPSYS) += clk-mt2701-bdp.o
 obj-$(CONFIG_COMMON_CLK_MT2701_ETHSYS) += clk-mt2701-eth.o
 obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o
diff --git a/drivers/clk/mediatek/clk-mt2701-aud.c b/drivers/clk/mediatek/clk-mt2701-aud.c
new file mode 100644 (file)
index 0000000..e66896a
--- /dev/null
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+#define GATE_AUDIO0(_id, _name, _parent, _shift) {     \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &audio0_cg_regs,                        \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_no_setclr,     \
+       }
+
+#define GATE_AUDIO1(_id, _name, _parent, _shift) {     \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &audio1_cg_regs,                        \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_no_setclr,     \
+       }
+
+#define GATE_AUDIO2(_id, _name, _parent, _shift) {     \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &audio2_cg_regs,                        \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_no_setclr,     \
+       }
+
+#define GATE_AUDIO3(_id, _name, _parent, _shift) {     \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &audio3_cg_regs,                        \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_no_setclr,     \
+       }
+
+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 = 0x10,
+       .clr_ofs = 0x10,
+       .sta_ofs = 0x10,
+};
+
+static const struct mtk_gate_regs audio2_cg_regs = {
+       .set_ofs = 0x14,
+       .clr_ofs = 0x14,
+       .sta_ofs = 0x14,
+};
+
+static const struct mtk_gate_regs audio3_cg_regs = {
+       .set_ofs = 0x634,
+       .clr_ofs = 0x634,
+       .sta_ofs = 0x634,
+};
+
+static const struct mtk_gate audio_clks[] = {
+       /* AUDIO0 */
+       GATE_AUDIO0(CLK_AUD_AFE, "audio_afe", "aud_intbus_sel", 2),
+       GATE_AUDIO0(CLK_AUD_HDMI, "audio_hdmi", "audpll_sel", 20),
+       GATE_AUDIO0(CLK_AUD_SPDF, "audio_spdf", "audpll_sel", 21),
+       GATE_AUDIO0(CLK_AUD_SPDF2, "audio_spdf2", "audpll_sel", 22),
+       GATE_AUDIO0(CLK_AUD_APLL, "audio_apll", "audpll_sel", 23),
+       /* AUDIO1 */
+       GATE_AUDIO1(CLK_AUD_I2SIN1, "audio_i2sin1", "aud_mux1_sel", 0),
+       GATE_AUDIO1(CLK_AUD_I2SIN2, "audio_i2sin2", "aud_mux1_sel", 1),
+       GATE_AUDIO1(CLK_AUD_I2SIN3, "audio_i2sin3", "aud_mux1_sel", 2),
+       GATE_AUDIO1(CLK_AUD_I2SIN4, "audio_i2sin4", "aud_mux1_sel", 3),
+       GATE_AUDIO1(CLK_AUD_I2SIN5, "audio_i2sin5", "aud_mux1_sel", 4),
+       GATE_AUDIO1(CLK_AUD_I2SIN6, "audio_i2sin6", "aud_mux1_sel", 5),
+       GATE_AUDIO1(CLK_AUD_I2SO1, "audio_i2so1", "aud_mux1_sel", 6),
+       GATE_AUDIO1(CLK_AUD_I2SO2, "audio_i2so2", "aud_mux1_sel", 7),
+       GATE_AUDIO1(CLK_AUD_I2SO3, "audio_i2so3", "aud_mux1_sel", 8),
+       GATE_AUDIO1(CLK_AUD_I2SO4, "audio_i2so4", "aud_mux1_sel", 9),
+       GATE_AUDIO1(CLK_AUD_I2SO5, "audio_i2so5", "aud_mux1_sel", 10),
+       GATE_AUDIO1(CLK_AUD_I2SO6, "audio_i2so6", "aud_mux1_sel", 11),
+       GATE_AUDIO1(CLK_AUD_ASRCI1, "audio_asrci1", "asm_h_sel", 12),
+       GATE_AUDIO1(CLK_AUD_ASRCI2, "audio_asrci2", "asm_h_sel", 13),
+       GATE_AUDIO1(CLK_AUD_ASRCO1, "audio_asrco1", "asm_h_sel", 14),
+       GATE_AUDIO1(CLK_AUD_ASRCO2, "audio_asrco2", "asm_h_sel", 15),
+       GATE_AUDIO1(CLK_AUD_INTDIR, "audio_intdir", "intdir_sel", 20),
+       GATE_AUDIO1(CLK_AUD_A1SYS, "audio_a1sys", "aud_mux1_sel", 21),
+       GATE_AUDIO1(CLK_AUD_A2SYS, "audio_a2sys", "aud_mux2_sel", 22),
+       GATE_AUDIO1(CLK_AUD_AFE_CONN, "audio_afe_conn", "aud_mux1_sel", 23),
+       GATE_AUDIO1(CLK_AUD_AFE_MRGIF, "audio_afe_mrgif", "aud_mux1_sel", 25),
+       /* AUDIO2 */
+       GATE_AUDIO2(CLK_AUD_MMIF_UL1, "audio_ul1", "aud_mux1_sel", 0),
+       GATE_AUDIO2(CLK_AUD_MMIF_UL2, "audio_ul2", "aud_mux1_sel", 1),
+       GATE_AUDIO2(CLK_AUD_MMIF_UL3, "audio_ul3", "aud_mux1_sel", 2),
+       GATE_AUDIO2(CLK_AUD_MMIF_UL4, "audio_ul4", "aud_mux1_sel", 3),
+       GATE_AUDIO2(CLK_AUD_MMIF_UL5, "audio_ul5", "aud_mux1_sel", 4),
+       GATE_AUDIO2(CLK_AUD_MMIF_UL6, "audio_ul6", "aud_mux1_sel", 5),
+       GATE_AUDIO2(CLK_AUD_MMIF_DL1, "audio_dl1", "aud_mux1_sel", 6),
+       GATE_AUDIO2(CLK_AUD_MMIF_DL2, "audio_dl2", "aud_mux1_sel", 7),
+       GATE_AUDIO2(CLK_AUD_MMIF_DL3, "audio_dl3", "aud_mux1_sel", 8),
+       GATE_AUDIO2(CLK_AUD_MMIF_DL4, "audio_dl4", "aud_mux1_sel", 9),
+       GATE_AUDIO2(CLK_AUD_MMIF_DL5, "audio_dl5", "aud_mux1_sel", 10),
+       GATE_AUDIO2(CLK_AUD_MMIF_DL6, "audio_dl6", "aud_mux1_sel", 11),
+       GATE_AUDIO2(CLK_AUD_MMIF_DLMCH, "audio_dlmch", "aud_mux1_sel", 12),
+       GATE_AUDIO2(CLK_AUD_MMIF_ARB1, "audio_arb1", "aud_mux1_sel", 13),
+       GATE_AUDIO2(CLK_AUD_MMIF_AWB1, "audio_awb", "aud_mux1_sel", 14),
+       GATE_AUDIO2(CLK_AUD_MMIF_AWB2, "audio_awb2", "aud_mux1_sel", 15),
+       GATE_AUDIO2(CLK_AUD_MMIF_DAI, "audio_dai", "aud_mux1_sel", 16),
+       /* AUDIO3 */
+       GATE_AUDIO3(CLK_AUD_ASRCI3, "audio_asrci3", "asm_h_sel", 2),
+       GATE_AUDIO3(CLK_AUD_ASRCI4, "audio_asrci4", "asm_h_sel", 3),
+       GATE_AUDIO3(CLK_AUD_ASRCI5, "audio_asrci5", "asm_h_sel", 4),
+       GATE_AUDIO3(CLK_AUD_ASRCI6, "audio_asrci6", "asm_h_sel", 5),
+       GATE_AUDIO3(CLK_AUD_ASRCO3, "audio_asrco3", "asm_h_sel", 6),
+       GATE_AUDIO3(CLK_AUD_ASRCO4, "audio_asrco4", "asm_h_sel", 7),
+       GATE_AUDIO3(CLK_AUD_ASRCO5, "audio_asrco5", "asm_h_sel", 8),
+       GATE_AUDIO3(CLK_AUD_ASRCO6, "audio_asrco6", "asm_h_sel", 9),
+       GATE_AUDIO3(CLK_AUD_MEM_ASRC1, "audio_mem_asrc1", "asm_h_sel", 10),
+       GATE_AUDIO3(CLK_AUD_MEM_ASRC2, "audio_mem_asrc2", "asm_h_sel", 11),
+       GATE_AUDIO3(CLK_AUD_MEM_ASRC3, "audio_mem_asrc3", "asm_h_sel", 12),
+       GATE_AUDIO3(CLK_AUD_MEM_ASRC4, "audio_mem_asrc4", "asm_h_sel", 13),
+       GATE_AUDIO3(CLK_AUD_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14),
+};
+
+static const struct of_device_id of_match_clk_mt2701_aud[] = {
+       { .compatible = "mediatek,mt2701-audsys", },
+       {}
+};
+
+static int clk_mt2701_aud_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+       int r;
+
+       clk_data = mtk_alloc_clk_data(CLK_AUD_NR);
+
+       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) {
+               dev_err(&pdev->dev,
+                       "could not register clock provider: %s: %d\n",
+                       pdev->name, r);
+
+               goto err_clk_provider;
+       }
+
+       r = devm_of_platform_populate(&pdev->dev);
+       if (r)
+               goto err_plat_populate;
+
+       return 0;
+
+err_plat_populate:
+       of_clk_del_provider(node);
+err_clk_provider:
+       return r;
+}
+
+static struct platform_driver clk_mt2701_aud_drv = {
+       .probe = clk_mt2701_aud_probe,
+       .driver = {
+               .name = "clk-mt2701-aud",
+               .of_match_table = of_match_clk_mt2701_aud,
+       },
+};
+
+builtin_platform_driver(clk_mt2701_aud_drv);
index 8e7f16fd87c93b80f586d2f223c95c38a10be967..deca7527f92f6d033175d199b4aead45258aa01c 100644 (file)
@@ -148,6 +148,7 @@ static const struct mtk_fixed_factor top_fixed_divs[] = {
        FACTOR(CLK_TOP_CLK26M_D8, "clk26m_d8", "clk26m", 1, 8),
        FACTOR(CLK_TOP_32K_INTERNAL, "32k_internal", "clk26m", 1, 793),
        FACTOR(CLK_TOP_32K_EXTERNAL, "32k_external", "rtc32k", 1, 1),
+       FACTOR(CLK_TOP_AXISEL_D4, "axisel_d4", "axi_sel", 1, 4),
 };
 
 static const char * const axi_parents[] = {
@@ -857,13 +858,13 @@ static const struct mtk_gate peri_clks[] = {
        GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
        GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
        GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
-       GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
-       GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
-       GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
-       GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
-       GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
-       GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
-       GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
+       GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axisel_d4", 8),
+       GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axisel_d4", 7),
+       GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axisel_d4", 6),
+       GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axisel_d4", 5),
+       GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axisel_d4", 4),
+       GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axisel_d4", 3),
+       GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axisel_d4", 2),
        GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
        GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "nfi2x_sel", 0),
 
index 498d137993885289dfaf02934d8d2a6227e31384..991d4093726e5c1a191af47895a2dd247a53f9dc 100644 (file)
@@ -221,6 +221,8 @@ static const struct mtk_fixed_factor top_divs[] = {
                4),
        FACTOR(CLK_TOP_D2A_ULCLK_6P5M, "d2a_ulclk_6p5m", "clk26m", 1,
                4),
+       FACTOR(CLK_TOP_APLL1_D3, "apll1_d3", "apll1_ck", 1,
+               3),
 };
 
 static const char * const axi_parents[] = {
@@ -625,7 +627,7 @@ static const char * const ether_125m_parents[] = {
 static const char * const ether_50m_parents[] = {
        "clk26m",
        "etherpll_50m",
-       "univpll_d26",
+       "apll1_d3",
        "univpll3_d4"
 };
 
@@ -686,7 +688,7 @@ static const char * const i2c_parents[] = {
 
 static const char * const msdc0p_aes_parents[] = {
        "clk26m",
-       "msdcpll_ck",
+       "syspll_d2",
        "univpll_d3",
        "vcodecpll_ck"
 };
@@ -719,6 +721,17 @@ static const char * const aud_apll2_parents[] = {
        "clkaud_ext_i_2"
 };
 
+static const char * const apll1_ref_parents[] = {
+       "clkaud_ext_i_2",
+       "clkaud_ext_i_1",
+       "clki2si0_mck_i",
+       "clki2si1_mck_i",
+       "clki2si2_mck_i",
+       "clktdmin_mclk_i",
+       "clki2si2_mck_i",
+       "clktdmin_mclk_i"
+};
+
 static const char * const audull_vtx_parents[] = {
        "d2a_ulclk_6p5m",
        "clkaud_ext_i_0"
@@ -886,6 +899,10 @@ static struct mtk_composite top_muxes[] = {
                aud_apll2_parents, 0x134, 1, 1),
        MUX(CLK_TOP_DA_AUDULL_VTX_6P5M_SEL, "audull_vtx_sel",
                audull_vtx_parents, 0x134, 31, 1),
+       MUX(CLK_TOP_APLL1_REF_SEL, "apll1_ref_sel",
+               apll1_ref_parents, 0x134, 4, 3),
+       MUX(CLK_TOP_APLL2_REF_SEL, "apll2_ref_sel",
+               apll1_ref_parents, 0x134, 7, 3),
 };
 
 static const char * const mcu_mp0_parents[] = {
@@ -932,36 +949,56 @@ static const struct mtk_clk_divider top_adj_divs[] = {
        DIV_ADJ(CLK_TOP_APLL_DIV7, "apll_div7", "i2si3_sel", 0x128, 24, 8),
 };
 
-static const struct mtk_gate_regs top_cg_regs = {
+static const struct mtk_gate_regs top0_cg_regs = {
        .set_ofs = 0x120,
        .clr_ofs = 0x120,
        .sta_ofs = 0x120,
 };
 
-#define GATE_TOP(_id, _name, _parent, _shift) {        \
+static const struct mtk_gate_regs top1_cg_regs = {
+       .set_ofs = 0x424,
+       .clr_ofs = 0x424,
+       .sta_ofs = 0x424,
+};
+
+#define GATE_TOP0(_id, _name, _parent, _shift) {       \
                .id = _id,                              \
                .name = _name,                          \
                .parent_name = _parent,                 \
-               .regs = &top_cg_regs,                   \
+               .regs = &top0_cg_regs,                  \
                .shift = _shift,                        \
                .ops = &mtk_clk_gate_ops_no_setclr,     \
        }
 
+#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_no_setclr_inv, \
+       }
+
 static const struct mtk_gate top_clks[] = {
-       GATE_TOP(CLK_TOP_APLL_DIV_PDN0, "apll_div_pdn0", "i2so1_sel", 0),
-       GATE_TOP(CLK_TOP_APLL_DIV_PDN1, "apll_div_pdn1", "i2so2_sel", 1),
-       GATE_TOP(CLK_TOP_APLL_DIV_PDN2, "apll_div_pdn2", "i2so3_sel", 2),
-       GATE_TOP(CLK_TOP_APLL_DIV_PDN3, "apll_div_pdn3", "tdmo0_sel", 3),
-       GATE_TOP(CLK_TOP_APLL_DIV_PDN4, "apll_div_pdn4", "tdmo1_sel", 4),
-       GATE_TOP(CLK_TOP_APLL_DIV_PDN5, "apll_div_pdn5", "i2si1_sel", 5),
-       GATE_TOP(CLK_TOP_APLL_DIV_PDN6, "apll_div_pdn6", "i2si2_sel", 6),
-       GATE_TOP(CLK_TOP_APLL_DIV_PDN7, "apll_div_pdn7", "i2si3_sel", 7),
+       /* TOP0 */
+       GATE_TOP0(CLK_TOP_APLL_DIV_PDN0, "apll_div_pdn0", "i2so1_sel", 0),
+       GATE_TOP0(CLK_TOP_APLL_DIV_PDN1, "apll_div_pdn1", "i2so2_sel", 1),
+       GATE_TOP0(CLK_TOP_APLL_DIV_PDN2, "apll_div_pdn2", "i2so3_sel", 2),
+       GATE_TOP0(CLK_TOP_APLL_DIV_PDN3, "apll_div_pdn3", "tdmo0_sel", 3),
+       GATE_TOP0(CLK_TOP_APLL_DIV_PDN4, "apll_div_pdn4", "tdmo1_sel", 4),
+       GATE_TOP0(CLK_TOP_APLL_DIV_PDN5, "apll_div_pdn5", "i2si1_sel", 5),
+       GATE_TOP0(CLK_TOP_APLL_DIV_PDN6, "apll_div_pdn6", "i2si2_sel", 6),
+       GATE_TOP0(CLK_TOP_APLL_DIV_PDN7, "apll_div_pdn7", "i2si3_sel", 7),
+       /* TOP1 */
+       GATE_TOP1(CLK_TOP_NFI2X_EN, "nfi2x_en", "nfi2x_sel", 0),
+       GATE_TOP1(CLK_TOP_NFIECC_EN, "nfiecc_en", "nfiecc_sel", 1),
+       GATE_TOP1(CLK_TOP_NFI1X_CK_EN, "nfi1x_ck_en", "nfi2x_sel", 2),
 };
 
 static const struct mtk_gate_regs infra_cg_regs = {
        .set_ofs = 0x40,
        .clr_ofs = 0x44,
-       .sta_ofs = 0x40,
+       .sta_ofs = 0x48,
 };
 
 #define GATE_INFRA(_id, _name, _parent, _shift) {      \
@@ -1120,6 +1157,10 @@ static const struct mtk_gate peri_clks[] = {
                "msdc50_0_h_sel", 4),
        GATE_PERI2(CLK_PERI_MSDC50_3_HCLK_EN, "per_msdc50_3_h",
                "msdc50_3_h_sel", 5),
+       GATE_PERI2(CLK_PERI_MSDC30_0_QTR_EN, "per_msdc30_0_q",
+               "axi_sel", 6),
+       GATE_PERI2(CLK_PERI_MSDC30_3_QTR_EN, "per_msdc30_3_q",
+               "mem_sel", 7),
 };
 
 #define MT2712_PLL_FMAX                (3000UL * MHZ)
index fad7d9fc53bae98d784f26a03fc87cab5f1fdb14..4f3d47b41b3e9e3fad18093e578517b4fe88e21b 100644 (file)
@@ -106,6 +106,7 @@ static const struct mtk_gate audio_clks[] = {
        GATE_AUDIO1(CLK_AUDIO_INTDIR, "audio_intdir", "intdir_sel", 20),
        GATE_AUDIO1(CLK_AUDIO_A1SYS, "audio_a1sys", "a1sys_hp_sel", 21),
        GATE_AUDIO1(CLK_AUDIO_A2SYS, "audio_a2sys", "a2sys_hp_sel", 22),
+       GATE_AUDIO1(CLK_AUDIO_AFE_CONN, "audio_afe_conn", "a1sys_hp_sel", 23),
        /* AUDIO2 */
        GATE_AUDIO2(CLK_AUDIO_UL1, "audio_ul1", "a1sys_hp_sel", 0),
        GATE_AUDIO2(CLK_AUDIO_UL2, "audio_ul2", "a1sys_hp_sel", 1),
@@ -149,11 +150,23 @@ static int clk_mt7622_audiosys_init(struct platform_device *pdev)
                               clk_data);
 
        r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
-       if (r)
+       if (r) {
                dev_err(&pdev->dev,
                        "could not register clock provider: %s: %d\n",
                        pdev->name, r);
 
+               goto err_clk_provider;
+       }
+
+       r = devm_of_platform_populate(&pdev->dev);
+       if (r)
+               goto err_plat_populate;
+
+       return 0;
+
+err_plat_populate:
+       of_clk_del_provider(node);
+err_clk_provider:
        return r;
 }
 
index 7694302c70a485c31ba30053c3d62376e89314c3..d5cbec522aec65f0e08b034ba1c68f5dc97f1a4a 100644 (file)
@@ -3,10 +3,15 @@ config COMMON_CLK_AMLOGIC
        depends on OF
        depends on ARCH_MESON || COMPILE_TEST
 
+config COMMON_CLK_REGMAP_MESON
+       bool
+       select REGMAP
+
 config COMMON_CLK_MESON8B
        bool
        depends on COMMON_CLK_AMLOGIC
        select RESET_CONTROLLER
+       select COMMON_CLK_REGMAP_MESON
        help
          Support for the clock controller on AmLogic S802 (Meson8),
          S805 (Meson8b) and S812 (Meson8m2) devices. Say Y if you
@@ -16,6 +21,8 @@ config COMMON_CLK_GXBB
        bool
        depends on COMMON_CLK_AMLOGIC
        select RESET_CONTROLLER
+       select COMMON_CLK_REGMAP_MESON
+       select MFD_SYSCON
        help
          Support for the clock controller on AmLogic S905 devices, aka gxbb.
          Say Y if you want peripherals and CPU frequency scaling to work.
@@ -24,6 +31,8 @@ config COMMON_CLK_AXG
        bool
        depends on COMMON_CLK_AMLOGIC
        select RESET_CONTROLLER
+       select COMMON_CLK_REGMAP_MESON
+       select MFD_SYSCON
        help
          Support for the clock controller on AmLogic A113D devices, aka axg.
          Say Y if you want peripherals and CPU frequency scaling to work.
index 3c03ce583798e57056fa82494db3b7ed90e30b13..ffee82e60b7acd896c64735434c97e4e1f0f67ea 100644 (file)
@@ -2,7 +2,8 @@
 # Makefile for Meson specific clk
 #
 
-obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o
+obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-audio-divider.o
 obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
-obj-$(CONFIG_COMMON_CLK_GXBB)   += gxbb.o gxbb-aoclk.o gxbb-aoclk-regmap.o gxbb-aoclk-32k.o
+obj-$(CONFIG_COMMON_CLK_GXBB)   += gxbb.o gxbb-aoclk.o gxbb-aoclk-32k.o
 obj-$(CONFIG_COMMON_CLK_AXG)    += axg.o
+obj-$(CONFIG_COMMON_CLK_REGMAP_MESON)  += clk-regmap.o
index 1294f3ad7cd5968434b8feda4751c89a52759656..5f5d468c1efe6cf24f309beb88495b7fa9e86598 100644 (file)
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/init.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/mfd/syscon.h>
 #include <linux/platform_device.h>
-#include <linux/init.h>
+#include <linux/regmap.h>
 
 #include "clkc.h"
 #include "axg.h"
 
 static DEFINE_SPINLOCK(meson_clk_lock);
 
-static const struct pll_rate_table sys_pll_rate_table[] = {
-       PLL_RATE(24000000, 56, 1, 2),
-       PLL_RATE(48000000, 64, 1, 2),
-       PLL_RATE(72000000, 72, 1, 2),
-       PLL_RATE(96000000, 64, 1, 2),
-       PLL_RATE(120000000, 80, 1, 2),
-       PLL_RATE(144000000, 96, 1, 2),
-       PLL_RATE(168000000, 56, 1, 1),
-       PLL_RATE(192000000, 64, 1, 1),
-       PLL_RATE(216000000, 72, 1, 1),
-       PLL_RATE(240000000, 80, 1, 1),
-       PLL_RATE(264000000, 88, 1, 1),
-       PLL_RATE(288000000, 96, 1, 1),
-       PLL_RATE(312000000, 52, 1, 2),
-       PLL_RATE(336000000, 56, 1, 2),
-       PLL_RATE(360000000, 60, 1, 2),
-       PLL_RATE(384000000, 64, 1, 2),
-       PLL_RATE(408000000, 68, 1, 2),
-       PLL_RATE(432000000, 72, 1, 2),
-       PLL_RATE(456000000, 76, 1, 2),
-       PLL_RATE(480000000, 80, 1, 2),
-       PLL_RATE(504000000, 84, 1, 2),
-       PLL_RATE(528000000, 88, 1, 2),
-       PLL_RATE(552000000, 92, 1, 2),
-       PLL_RATE(576000000, 96, 1, 2),
-       PLL_RATE(600000000, 50, 1, 1),
-       PLL_RATE(624000000, 52, 1, 1),
-       PLL_RATE(648000000, 54, 1, 1),
-       PLL_RATE(672000000, 56, 1, 1),
-       PLL_RATE(696000000, 58, 1, 1),
-       PLL_RATE(720000000, 60, 1, 1),
-       PLL_RATE(744000000, 62, 1, 1),
-       PLL_RATE(768000000, 64, 1, 1),
-       PLL_RATE(792000000, 66, 1, 1),
-       PLL_RATE(816000000, 68, 1, 1),
-       PLL_RATE(840000000, 70, 1, 1),
-       PLL_RATE(864000000, 72, 1, 1),
-       PLL_RATE(888000000, 74, 1, 1),
-       PLL_RATE(912000000, 76, 1, 1),
-       PLL_RATE(936000000, 78, 1, 1),
-       PLL_RATE(960000000, 80, 1, 1),
-       PLL_RATE(984000000, 82, 1, 1),
-       PLL_RATE(1008000000, 84, 1, 1),
-       PLL_RATE(1032000000, 86, 1, 1),
-       PLL_RATE(1056000000, 88, 1, 1),
-       PLL_RATE(1080000000, 90, 1, 1),
-       PLL_RATE(1104000000, 92, 1, 1),
-       PLL_RATE(1128000000, 94, 1, 1),
-       PLL_RATE(1152000000, 96, 1, 1),
-       PLL_RATE(1176000000, 98, 1, 1),
-       PLL_RATE(1200000000, 50, 1, 0),
-       PLL_RATE(1224000000, 51, 1, 0),
-       PLL_RATE(1248000000, 52, 1, 0),
-       PLL_RATE(1272000000, 53, 1, 0),
-       PLL_RATE(1296000000, 54, 1, 0),
-       PLL_RATE(1320000000, 55, 1, 0),
-       PLL_RATE(1344000000, 56, 1, 0),
-       PLL_RATE(1368000000, 57, 1, 0),
-       PLL_RATE(1392000000, 58, 1, 0),
-       PLL_RATE(1416000000, 59, 1, 0),
-       PLL_RATE(1440000000, 60, 1, 0),
-       PLL_RATE(1464000000, 61, 1, 0),
-       PLL_RATE(1488000000, 62, 1, 0),
-       PLL_RATE(1512000000, 63, 1, 0),
-       PLL_RATE(1536000000, 64, 1, 0),
-       PLL_RATE(1560000000, 65, 1, 0),
-       PLL_RATE(1584000000, 66, 1, 0),
-       PLL_RATE(1608000000, 67, 1, 0),
-       PLL_RATE(1632000000, 68, 1, 0),
-       PLL_RATE(1656000000, 68, 1, 0),
-       PLL_RATE(1680000000, 68, 1, 0),
-       PLL_RATE(1704000000, 68, 1, 0),
-       PLL_RATE(1728000000, 69, 1, 0),
-       PLL_RATE(1752000000, 69, 1, 0),
-       PLL_RATE(1776000000, 69, 1, 0),
-       PLL_RATE(1800000000, 69, 1, 0),
-       PLL_RATE(1824000000, 70, 1, 0),
-       PLL_RATE(1848000000, 70, 1, 0),
-       PLL_RATE(1872000000, 70, 1, 0),
-       PLL_RATE(1896000000, 70, 1, 0),
-       PLL_RATE(1920000000, 71, 1, 0),
-       PLL_RATE(1944000000, 71, 1, 0),
-       PLL_RATE(1968000000, 71, 1, 0),
-       PLL_RATE(1992000000, 71, 1, 0),
-       PLL_RATE(2016000000, 72, 1, 0),
-       PLL_RATE(2040000000, 72, 1, 0),
-       PLL_RATE(2064000000, 72, 1, 0),
-       PLL_RATE(2088000000, 72, 1, 0),
-       PLL_RATE(2112000000, 73, 1, 0),
-       { /* sentinel */ },
-};
-
-static struct meson_clk_pll axg_fixed_pll = {
-       .m = {
-               .reg_off = HHI_MPLL_CNTL,
-               .shift   = 0,
-               .width   = 9,
-       },
-       .n = {
-               .reg_off = HHI_MPLL_CNTL,
-               .shift   = 9,
-               .width   = 5,
-       },
-       .od = {
-               .reg_off = HHI_MPLL_CNTL,
-               .shift   = 16,
-               .width   = 2,
+static struct clk_regmap axg_fixed_pll = {
+       .data = &(struct meson_clk_pll_data){
+               .m = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .od = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 16,
+                       .width   = 2,
+               },
+               .frac = {
+                       .reg_off = HHI_MPLL_CNTL2,
+                       .shift   = 0,
+                       .width   = 12,
+               },
+               .l = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 29,
+                       .width   = 1,
+               },
        },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "fixed_pll",
                .ops = &meson_clk_pll_ro_ops,
@@ -138,25 +64,34 @@ static struct meson_clk_pll axg_fixed_pll = {
        },
 };
 
-static struct meson_clk_pll axg_sys_pll = {
-       .m = {
-               .reg_off = HHI_SYS_PLL_CNTL,
-               .shift   = 0,
-               .width   = 9,
+static struct clk_regmap axg_sys_pll = {
+       .data = &(struct meson_clk_pll_data){
+               .m = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .od = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 16,
+                       .width   = 2,
+               },
+               .l = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 29,
+                       .width   = 1,
+               },
        },
-       .n = {
-               .reg_off = HHI_SYS_PLL_CNTL,
-               .shift   = 9,
-               .width   = 5,
-       },
-       .od = {
-               .reg_off = HHI_SYS_PLL_CNTL,
-               .shift   = 10,
-               .width   = 2,
-       },
-       .rate_table = sys_pll_rate_table,
-       .rate_count = ARRAY_SIZE(sys_pll_rate_table),
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "sys_pll",
                .ops = &meson_clk_pll_ro_ops,
@@ -257,40 +192,51 @@ static const struct pll_rate_table axg_gp0_pll_rate_table[] = {
        { /* sentinel */ },
 };
 
-static struct pll_params_table axg_gp0_params_table[] = {
-       PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250),
-       PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000),
-       PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be),
-       PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288),
-       PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d),
-       PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000),
-};
-
-static struct meson_clk_pll axg_gp0_pll = {
-       .m = {
-               .reg_off = HHI_GP0_PLL_CNTL,
-               .shift   = 0,
-               .width   = 9,
-       },
-       .n = {
-               .reg_off = HHI_GP0_PLL_CNTL,
-               .shift   = 9,
-               .width   = 5,
-       },
-       .od = {
-               .reg_off = HHI_GP0_PLL_CNTL,
-               .shift   = 16,
-               .width   = 2,
-       },
-       .params = {
-               .params_table = axg_gp0_params_table,
-               .params_count = ARRAY_SIZE(axg_gp0_params_table),
-               .no_init_reset = true,
-               .reset_lock_loop = true,
-       },
-       .rate_table = axg_gp0_pll_rate_table,
-       .rate_count = ARRAY_SIZE(axg_gp0_pll_rate_table),
-       .lock = &meson_clk_lock,
+static const struct reg_sequence axg_gp0_init_regs[] = {
+       { .reg = HHI_GP0_PLL_CNTL1,     .def = 0xc084b000 },
+       { .reg = HHI_GP0_PLL_CNTL2,     .def = 0xb75020be },
+       { .reg = HHI_GP0_PLL_CNTL3,     .def = 0x0a59a288 },
+       { .reg = HHI_GP0_PLL_CNTL4,     .def = 0xc000004d },
+       { .reg = HHI_GP0_PLL_CNTL5,     .def = 0x00078000 },
+       { .reg = HHI_GP0_PLL_CNTL,      .def = 0x40010250 },
+};
+
+static struct clk_regmap axg_gp0_pll = {
+       .data = &(struct meson_clk_pll_data){
+               .m = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .od = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 16,
+                       .width   = 2,
+               },
+               .frac = {
+                       .reg_off = HHI_GP0_PLL_CNTL1,
+                       .shift   = 0,
+                       .width   = 10,
+               },
+               .l = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+               .table = axg_gp0_pll_rate_table,
+               .init_regs = axg_gp0_init_regs,
+               .init_count = ARRAY_SIZE(axg_gp0_init_regs),
+       },
        .hw.init = &(struct clk_init_data){
                .name = "gp0_pll",
                .ops = &meson_clk_pll_ops,
@@ -299,234 +245,427 @@ static struct meson_clk_pll axg_gp0_pll = {
        },
 };
 
+static const struct reg_sequence axg_hifi_init_regs[] = {
+       { .reg = HHI_HIFI_PLL_CNTL1,    .def = 0xc084b000 },
+       { .reg = HHI_HIFI_PLL_CNTL2,    .def = 0xb75020be },
+       { .reg = HHI_HIFI_PLL_CNTL3,    .def = 0x0a6a3a88 },
+       { .reg = HHI_HIFI_PLL_CNTL4,    .def = 0xc000004d },
+       { .reg = HHI_HIFI_PLL_CNTL5,    .def = 0x00058000 },
+       { .reg = HHI_HIFI_PLL_CNTL,     .def = 0x40010250 },
+};
+
+static struct clk_regmap axg_hifi_pll = {
+       .data = &(struct meson_clk_pll_data){
+               .m = {
+                       .reg_off = HHI_HIFI_PLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = HHI_HIFI_PLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .od = {
+                       .reg_off = HHI_HIFI_PLL_CNTL,
+                       .shift   = 16,
+                       .width   = 2,
+               },
+               .frac = {
+                       .reg_off = HHI_HIFI_PLL_CNTL5,
+                       .shift   = 0,
+                       .width   = 13,
+               },
+               .l = {
+                       .reg_off = HHI_HIFI_PLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_HIFI_PLL_CNTL,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+               .table = axg_gp0_pll_rate_table,
+               .init_regs = axg_hifi_init_regs,
+               .init_count = ARRAY_SIZE(axg_hifi_init_regs),
+               .flags = CLK_MESON_PLL_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "hifi_pll",
+               .ops = &meson_clk_pll_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+       },
+};
 
-static struct clk_fixed_factor axg_fclk_div2 = {
+static struct clk_fixed_factor axg_fclk_div2_div = {
        .mult = 1,
        .div = 2,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div2",
+               .name = "fclk_div2_div",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct clk_fixed_factor axg_fclk_div3 = {
+static struct clk_regmap axg_fclk_div2 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 27,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div2",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div2_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor axg_fclk_div3_div = {
        .mult = 1,
        .div = 3,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div3",
+               .name = "fclk_div3_div",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct clk_fixed_factor axg_fclk_div4 = {
+static struct clk_regmap axg_fclk_div3 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 28,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div3",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div3_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor axg_fclk_div4_div = {
        .mult = 1,
        .div = 4,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div4",
+               .name = "fclk_div4_div",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct clk_fixed_factor axg_fclk_div5 = {
+static struct clk_regmap axg_fclk_div4 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 29,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div4",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div4_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor axg_fclk_div5_div = {
        .mult = 1,
        .div = 5,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div5",
+               .name = "fclk_div5_div",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct clk_fixed_factor axg_fclk_div7 = {
+static struct clk_regmap axg_fclk_div5 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 30,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div5",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div5_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor axg_fclk_div7_div = {
        .mult = 1,
        .div = 7,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div7",
+               .name = "fclk_div7_div",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct meson_clk_mpll axg_mpll0 = {
-       .sdm = {
-               .reg_off = HHI_MPLL_CNTL7,
-               .shift   = 0,
-               .width   = 14,
+static struct clk_regmap axg_fclk_div7 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 31,
        },
-       .sdm_en = {
-               .reg_off = HHI_MPLL_CNTL7,
-               .shift   = 15,
-               .width   = 1,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div7",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div7_div" },
+               .num_parents = 1,
        },
-       .n2 = {
-               .reg_off = HHI_MPLL_CNTL7,
-               .shift   = 16,
-               .width   = 9,
+};
+
+static struct clk_regmap axg_mpll_prediv = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_MPLL_CNTL5,
+               .shift = 12,
+               .width = 1,
        },
-       .en = {
-               .reg_off = HHI_MPLL_CNTL7,
-               .shift   = 14,
-               .width   = 1,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll_prediv",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
        },
-       .ssen = {
-               .reg_off = HHI_MPLL_CNTL,
-               .shift   = 25,
-               .width   = 1,
+};
+
+static struct clk_regmap axg_mpll0_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 0,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 15,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 16,
+                       .width   = 9,
+               },
+               .ssen = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 25,
+                       .width   = 1,
+               },
+               .misc = {
+                       .reg_off = HHI_PLL_TOP_MISC,
+                       .shift   = 0,
+                       .width   = 1,
+               },
+               .lock = &meson_clk_lock,
        },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
-               .name = "mpll0",
+               .name = "mpll0_div",
                .ops = &meson_clk_mpll_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_names = (const char *[]){ "mpll_prediv" },
                .num_parents = 1,
        },
 };
 
-static struct meson_clk_mpll axg_mpll1 = {
-       .sdm = {
-               .reg_off = HHI_MPLL_CNTL8,
-               .shift   = 0,
-               .width   = 14,
+static struct clk_regmap axg_mpll0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL7,
+               .bit_idx = 14,
        },
-       .sdm_en = {
-               .reg_off = HHI_MPLL_CNTL8,
-               .shift   = 15,
-               .width   = 1,
-       },
-       .n2 = {
-               .reg_off = HHI_MPLL_CNTL8,
-               .shift   = 16,
-               .width   = 9,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll0",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpll0_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
        },
-       .en = {
-               .reg_off = HHI_MPLL_CNTL8,
-               .shift   = 14,
-               .width   = 1,
+};
+
+static struct clk_regmap axg_mpll1_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL_CNTL8,
+                       .shift   = 0,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL_CNTL8,
+                       .shift   = 15,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL_CNTL8,
+                       .shift   = 16,
+                       .width   = 9,
+               },
+               .misc = {
+                       .reg_off = HHI_PLL_TOP_MISC,
+                       .shift   = 1,
+                       .width   = 1,
+               },
+               .lock = &meson_clk_lock,
        },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
-               .name = "mpll1",
+               .name = "mpll1_div",
                .ops = &meson_clk_mpll_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_names = (const char *[]){ "mpll_prediv" },
                .num_parents = 1,
        },
 };
 
-static struct meson_clk_mpll axg_mpll2 = {
-       .sdm = {
-               .reg_off = HHI_MPLL_CNTL9,
-               .shift   = 0,
-               .width   = 14,
+static struct clk_regmap axg_mpll1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL8,
+               .bit_idx = 14,
        },
-       .sdm_en = {
-               .reg_off = HHI_MPLL_CNTL9,
-               .shift   = 15,
-               .width   = 1,
-       },
-       .n2 = {
-               .reg_off = HHI_MPLL_CNTL9,
-               .shift   = 16,
-               .width   = 9,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpll1_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
        },
-       .en = {
-               .reg_off = HHI_MPLL_CNTL9,
-               .shift   = 14,
-               .width   = 1,
+};
+
+static struct clk_regmap axg_mpll2_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL_CNTL9,
+                       .shift   = 0,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL_CNTL9,
+                       .shift   = 15,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL_CNTL9,
+                       .shift   = 16,
+                       .width   = 9,
+               },
+               .misc = {
+                       .reg_off = HHI_PLL_TOP_MISC,
+                       .shift   = 2,
+                       .width   = 1,
+               },
+               .lock = &meson_clk_lock,
        },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
-               .name = "mpll2",
+               .name = "mpll2_div",
                .ops = &meson_clk_mpll_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_names = (const char *[]){ "mpll_prediv" },
                .num_parents = 1,
        },
 };
 
-static struct meson_clk_mpll axg_mpll3 = {
-       .sdm = {
-               .reg_off = HHI_MPLL3_CNTL0,
-               .shift   = 12,
-               .width   = 14,
+static struct clk_regmap axg_mpll2 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL9,
+               .bit_idx = 14,
        },
-       .sdm_en = {
-               .reg_off = HHI_MPLL3_CNTL0,
-               .shift   = 11,
-               .width   = 1,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll2",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpll2_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap axg_mpll3_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL3_CNTL0,
+                       .shift   = 12,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL3_CNTL0,
+                       .shift   = 11,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL3_CNTL0,
+                       .shift   = 2,
+                       .width   = 9,
+               },
+               .misc = {
+                       .reg_off = HHI_PLL_TOP_MISC,
+                       .shift   = 3,
+                       .width   = 1,
+               },
+               .lock = &meson_clk_lock,
        },
-       .n2 = {
-               .reg_off = HHI_MPLL3_CNTL0,
-               .shift   = 2,
-               .width   = 9,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll3_div",
+               .ops = &meson_clk_mpll_ops,
+               .parent_names = (const char *[]){ "mpll_prediv" },
+               .num_parents = 1,
        },
-       .en = {
-               .reg_off = HHI_MPLL3_CNTL0,
-               .shift   = 0,
-               .width   = 1,
+};
+
+static struct clk_regmap axg_mpll3 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL3_CNTL0,
+               .bit_idx = 0,
        },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "mpll3",
-               .ops = &meson_clk_mpll_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpll3_div" },
                .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-/*
- * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers
- * and should be modeled with their respective PLLs via the forthcoming
- * coordinated clock rates feature
- */
 static u32 mux_table_clk81[]   = { 0, 2, 3, 4, 5, 6, 7 };
 static const char * const clk81_parent_names[] = {
        "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
        "fclk_div3", "fclk_div5"
 };
 
-static struct clk_mux axg_mpeg_clk_sel = {
-       .reg = (void *)HHI_MPEG_CLK_CNTL,
-       .mask = 0x7,
-       .shift = 12,
-       .flags = CLK_MUX_READ_ONLY,
-       .table = mux_table_clk81,
-       .lock = &meson_clk_lock,
+static struct clk_regmap axg_mpeg_clk_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_MPEG_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 12,
+               .table = mux_table_clk81,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "mpeg_clk_sel",
-               .ops = &clk_mux_ro_ops,
+               .ops = &clk_regmap_mux_ro_ops,
                .parent_names = clk81_parent_names,
                .num_parents = ARRAY_SIZE(clk81_parent_names),
        },
 };
 
-static struct clk_divider axg_mpeg_clk_div = {
-       .reg = (void *)HHI_MPEG_CLK_CNTL,
-       .shift = 0,
-       .width = 7,
-       .lock = &meson_clk_lock,
+static struct clk_regmap axg_mpeg_clk_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_MPEG_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "mpeg_clk_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "mpeg_clk_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_gate axg_clk81 = {
-       .reg = (void *)HHI_MPEG_CLK_CNTL,
-       .bit_idx = 7,
-       .lock = &meson_clk_lock,
+static struct clk_regmap axg_clk81 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPEG_CLK_CNTL,
+               .bit_idx = 7,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "clk81",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "mpeg_clk_div" },
                .num_parents = 1,
                .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
@@ -545,42 +684,45 @@ static const char * const axg_sd_emmc_clk0_parent_names[] = {
 };
 
 /* SDcard clock */
-static struct clk_mux axg_sd_emmc_b_clk0_sel = {
-       .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
-       .mask = 0x7,
-       .shift = 25,
-       .lock = &meson_clk_lock,
+static struct clk_regmap axg_sd_emmc_b_clk0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 25,
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_b_clk0_sel",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                .parent_names = axg_sd_emmc_clk0_parent_names,
                .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names),
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_divider axg_sd_emmc_b_clk0_div = {
-       .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
-       .shift = 16,
-       .width = 7,
-       .lock = &meson_clk_lock,
-       .flags = CLK_DIVIDER_ROUND_CLOSEST,
+static struct clk_regmap axg_sd_emmc_b_clk0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .shift = 16,
+               .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_b_clk0_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_gate axg_sd_emmc_b_clk0 = {
-       .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
-       .bit_idx = 23,
-       .lock = &meson_clk_lock,
+static struct clk_regmap axg_sd_emmc_b_clk0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .bit_idx = 23,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "sd_emmc_b_clk0",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
@@ -588,42 +730,45 @@ static struct clk_gate axg_sd_emmc_b_clk0 = {
 };
 
 /* EMMC/NAND clock */
-static struct clk_mux axg_sd_emmc_c_clk0_sel = {
-       .reg = (void *)HHI_NAND_CLK_CNTL,
-       .mask = 0x7,
-       .shift = 9,
-       .lock = &meson_clk_lock,
+static struct clk_regmap axg_sd_emmc_c_clk0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_NAND_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 9,
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_c_clk0_sel",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                .parent_names = axg_sd_emmc_clk0_parent_names,
                .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names),
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_divider axg_sd_emmc_c_clk0_div = {
-       .reg = (void *)HHI_NAND_CLK_CNTL,
-       .shift = 0,
-       .width = 7,
-       .lock = &meson_clk_lock,
-       .flags = CLK_DIVIDER_ROUND_CLOSEST,
+static struct clk_regmap axg_sd_emmc_c_clk0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_NAND_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_c_clk0_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_gate axg_sd_emmc_c_clk0 = {
-       .reg = (void *)HHI_NAND_CLK_CNTL,
-       .bit_idx = 7,
-       .lock = &meson_clk_lock,
+static struct clk_regmap axg_sd_emmc_c_clk0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_NAND_CLK_CNTL,
+               .bit_idx = 7,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "sd_emmc_c_clk0",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
@@ -750,27 +895,24 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = {
                [CLKID_SD_EMMC_C_CLK0_SEL]      = &axg_sd_emmc_c_clk0_sel.hw,
                [CLKID_SD_EMMC_C_CLK0_DIV]      = &axg_sd_emmc_c_clk0_div.hw,
                [CLKID_SD_EMMC_C_CLK0]          = &axg_sd_emmc_c_clk0.hw,
+               [CLKID_MPLL0_DIV]               = &axg_mpll0_div.hw,
+               [CLKID_MPLL1_DIV]               = &axg_mpll1_div.hw,
+               [CLKID_MPLL2_DIV]               = &axg_mpll2_div.hw,
+               [CLKID_MPLL3_DIV]               = &axg_mpll3_div.hw,
+               [CLKID_HIFI_PLL]                = &axg_hifi_pll.hw,
+               [CLKID_MPLL_PREDIV]             = &axg_mpll_prediv.hw,
+               [CLKID_FCLK_DIV2_DIV]           = &axg_fclk_div2_div.hw,
+               [CLKID_FCLK_DIV3_DIV]           = &axg_fclk_div3_div.hw,
+               [CLKID_FCLK_DIV4_DIV]           = &axg_fclk_div4_div.hw,
+               [CLKID_FCLK_DIV5_DIV]           = &axg_fclk_div5_div.hw,
+               [CLKID_FCLK_DIV7_DIV]           = &axg_fclk_div7_div.hw,
                [NR_CLKS]                       = NULL,
        },
        .num = NR_CLKS,
 };
 
-/* Convenience tables to populate base addresses in .probe */
-
-static struct meson_clk_pll *const axg_clk_plls[] = {
-       &axg_fixed_pll,
-       &axg_sys_pll,
-       &axg_gp0_pll,
-};
-
-static struct meson_clk_mpll *const axg_clk_mplls[] = {
-       &axg_mpll0,
-       &axg_mpll1,
-       &axg_mpll2,
-       &axg_mpll3,
-};
-
-static struct clk_gate *const axg_clk_gates[] = {
+/* Convenience table to populate regmap in .probe */
+static struct clk_regmap *const axg_clk_regmaps[] = {
        &axg_clk81,
        &axg_ddr,
        &axg_audio_locker,
@@ -818,113 +960,100 @@ static struct clk_gate *const axg_clk_gates[] = {
        &axg_ao_i2c,
        &axg_sd_emmc_b_clk0,
        &axg_sd_emmc_c_clk0,
-};
-
-static struct clk_mux *const axg_clk_muxes[] = {
-       &axg_mpeg_clk_sel,
-       &axg_sd_emmc_b_clk0_sel,
-       &axg_sd_emmc_c_clk0_sel,
-};
-
-static struct clk_divider *const axg_clk_dividers[] = {
        &axg_mpeg_clk_div,
        &axg_sd_emmc_b_clk0_div,
        &axg_sd_emmc_c_clk0_div,
-};
-
-struct clkc_data {
-       struct clk_gate *const *clk_gates;
-       unsigned int clk_gates_count;
-       struct meson_clk_mpll *const *clk_mplls;
-       unsigned int clk_mplls_count;
-       struct meson_clk_pll *const *clk_plls;
-       unsigned int clk_plls_count;
-       struct clk_mux *const *clk_muxes;
-       unsigned int clk_muxes_count;
-       struct clk_divider *const *clk_dividers;
-       unsigned int clk_dividers_count;
-       struct clk_hw_onecell_data *hw_onecell_data;
-};
-
-static const struct clkc_data axg_clkc_data = {
-       .clk_gates = axg_clk_gates,
-       .clk_gates_count = ARRAY_SIZE(axg_clk_gates),
-       .clk_mplls = axg_clk_mplls,
-       .clk_mplls_count = ARRAY_SIZE(axg_clk_mplls),
-       .clk_plls = axg_clk_plls,
-       .clk_plls_count = ARRAY_SIZE(axg_clk_plls),
-       .clk_muxes = axg_clk_muxes,
-       .clk_muxes_count = ARRAY_SIZE(axg_clk_muxes),
-       .clk_dividers = axg_clk_dividers,
-       .clk_dividers_count = ARRAY_SIZE(axg_clk_dividers),
-       .hw_onecell_data = &axg_hw_onecell_data,
+       &axg_mpeg_clk_sel,
+       &axg_sd_emmc_b_clk0_sel,
+       &axg_sd_emmc_c_clk0_sel,
+       &axg_mpll0,
+       &axg_mpll1,
+       &axg_mpll2,
+       &axg_mpll3,
+       &axg_mpll0_div,
+       &axg_mpll1_div,
+       &axg_mpll2_div,
+       &axg_mpll3_div,
+       &axg_fixed_pll,
+       &axg_sys_pll,
+       &axg_gp0_pll,
+       &axg_hifi_pll,
+       &axg_mpll_prediv,
+       &axg_fclk_div2,
+       &axg_fclk_div3,
+       &axg_fclk_div4,
+       &axg_fclk_div5,
+       &axg_fclk_div7,
 };
 
 static const struct of_device_id clkc_match_table[] = {
-       { .compatible = "amlogic,axg-clkc", .data = &axg_clkc_data },
+       { .compatible = "amlogic,axg-clkc" },
        {}
 };
 
+static const struct regmap_config clkc_regmap_config = {
+       .reg_bits       = 32,
+       .val_bits       = 32,
+       .reg_stride     = 4,
+};
+
 static int axg_clkc_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       const struct clkc_data *clkc_data;
        struct resource *res;
-       void __iomem *clk_base;
-       int ret, clkid, i;
-
-       clkc_data = of_device_get_match_data(&pdev->dev);
-       if (!clkc_data)
-               return -EINVAL;
-
-       /*  Generic clocks and PLLs */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -EINVAL;
-       clk_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-       if (!clk_base) {
-               dev_err(&pdev->dev, "Unable to map clk base\n");
-               return -ENXIO;
-       }
+       void __iomem *clk_base = NULL;
+       struct regmap *map;
+       int ret, i;
 
-       /* Populate base address for PLLs */
-       for (i = 0; i < clkc_data->clk_plls_count; i++)
-               clkc_data->clk_plls[i]->base = clk_base;
+       /* Get the hhi system controller node if available */
+       map = syscon_node_to_regmap(of_get_parent(dev->of_node));
+       if (IS_ERR(map)) {
+               dev_err(dev,
+                       "failed to get HHI regmap - Trying obsolete regs\n");
 
-       /* Populate base address for MPLLs */
-       for (i = 0; i < clkc_data->clk_mplls_count; i++)
-               clkc_data->clk_mplls[i]->base = clk_base;
+               /*
+                * FIXME: HHI registers should be accessed through
+                * the appropriate system controller. This is required because
+                * there is more than just clocks in this register space
+                *
+                * This fallback method is only provided temporarily until
+                * all the platform DTs are properly using the syscon node
+                */
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+               if (!res)
+                       return -EINVAL;
 
-       /* Populate base address for gates */
-       for (i = 0; i < clkc_data->clk_gates_count; i++)
-               clkc_data->clk_gates[i]->reg = clk_base +
-                       (u64)clkc_data->clk_gates[i]->reg;
 
-       /* Populate base address for muxes */
-       for (i = 0; i < clkc_data->clk_muxes_count; i++)
-               clkc_data->clk_muxes[i]->reg = clk_base +
-                       (u64)clkc_data->clk_muxes[i]->reg;
+               clk_base = devm_ioremap(dev, res->start, resource_size(res));
+               if (!clk_base) {
+                       dev_err(dev, "Unable to map clk base\n");
+                       return -ENXIO;
+               }
+
+               map = devm_regmap_init_mmio(dev, clk_base,
+                                           &clkc_regmap_config);
+               if (IS_ERR(map))
+                       return PTR_ERR(map);
+       }
 
-       /* Populate base address for dividers */
-       for (i = 0; i < clkc_data->clk_dividers_count; i++)
-               clkc_data->clk_dividers[i]->reg = clk_base +
-                       (u64)clkc_data->clk_dividers[i]->reg;
+       /* Populate regmap for the regmap backed clocks */
+       for (i = 0; i < ARRAY_SIZE(axg_clk_regmaps); i++)
+               axg_clk_regmaps[i]->map = map;
 
-       for (clkid = 0; clkid < clkc_data->hw_onecell_data->num; clkid++) {
+       for (i = 0; i < axg_hw_onecell_data.num; i++) {
                /* array might be sparse */
-               if (!clkc_data->hw_onecell_data->hws[clkid])
+               if (!axg_hw_onecell_data.hws[i])
                        continue;
 
-               ret = devm_clk_hw_register(dev,
-                                       clkc_data->hw_onecell_data->hws[clkid]);
+               ret = devm_clk_hw_register(dev, axg_hw_onecell_data.hws[i]);
                if (ret) {
-                       dev_err(&pdev->dev, "Clock registration failed\n");
+                       dev_err(dev, "Clock registration failed\n");
                        return ret;
                }
        }
 
-       return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
-                       clkc_data->hw_onecell_data);
+       return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+                                          &axg_hw_onecell_data);
 }
 
 static struct platform_driver axg_driver = {
index ce0bafdb6b28a399ee2b515be69bc1a03276bd4c..b421df6a7ea0e4adfa6427af88bb551b90f0db75 100644 (file)
 #define CLKID_SD_EMMC_B_CLK0_DIV               62
 #define CLKID_SD_EMMC_C_CLK0_SEL               63
 #define CLKID_SD_EMMC_C_CLK0_DIV               64
+#define CLKID_MPLL0_DIV                                65
+#define CLKID_MPLL1_DIV                                66
+#define CLKID_MPLL2_DIV                                67
+#define CLKID_MPLL3_DIV                                68
+#define CLKID_MPLL_PREDIV                      70
+#define CLKID_FCLK_DIV2_DIV                    71
+#define CLKID_FCLK_DIV3_DIV                    72
+#define CLKID_FCLK_DIV4_DIV                    73
+#define CLKID_FCLK_DIV5_DIV                    74
+#define CLKID_FCLK_DIV7_DIV                    75
 
-#define NR_CLKS                                        65
+#define NR_CLKS                                        76
 
 /* include the CLKIDs that have been made part of the DT binding */
 #include <dt-bindings/clock/axg-clkc.h>
index 6c07db06642d04a89ca1281bf0bd5f986687fde3..f7ab5b1db3420bbf64df6932c327d68b6a6944aa 100644 (file)
 #include <linux/clk-provider.h>
 #include "clkc.h"
 
-#define to_meson_clk_audio_divider(_hw) container_of(_hw, \
-                               struct meson_clk_audio_divider, hw)
+static inline struct meson_clk_audio_div_data *
+meson_clk_audio_div_data(struct clk_regmap *clk)
+{
+       return (struct meson_clk_audio_div_data *)clk->data;
+}
 
 static int _div_round(unsigned long parent_rate, unsigned long rate,
                      unsigned long flags)
@@ -45,15 +48,9 @@ static int _get_val(unsigned long parent_rate, unsigned long rate)
        return DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1;
 }
 
-static int _valid_divider(struct clk_hw *hw, int divider)
+static int _valid_divider(unsigned int width, int divider)
 {
-       struct meson_clk_audio_divider *adiv =
-               to_meson_clk_audio_divider(hw);
-       int max_divider;
-       u8 width;
-
-       width = adiv->div.width;
-       max_divider = 1 << width;
+       int max_divider = 1 << width;
 
        return clamp(divider, 1, max_divider);
 }
@@ -61,14 +58,11 @@ static int _valid_divider(struct clk_hw *hw, int divider)
 static unsigned long audio_divider_recalc_rate(struct clk_hw *hw,
                                               unsigned long parent_rate)
 {
-       struct meson_clk_audio_divider *adiv =
-               to_meson_clk_audio_divider(hw);
-       struct parm *p;
-       unsigned long reg, divider;
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk);
+       unsigned long divider;
 
-       p = &adiv->div;
-       reg = readl(adiv->base + p->reg_off);
-       divider = PARM_GET(p->width, p->shift, reg) + 1;
+       divider = meson_parm_read(clk->map, &adiv->div);
 
        return DIV_ROUND_UP_ULL((u64)parent_rate, divider);
 }
@@ -77,14 +71,14 @@ static long audio_divider_round_rate(struct clk_hw *hw,
                                     unsigned long rate,
                                     unsigned long *parent_rate)
 {
-       struct meson_clk_audio_divider *adiv =
-               to_meson_clk_audio_divider(hw);
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk);
        unsigned long max_prate;
        int divider;
 
        if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
                divider = _div_round(*parent_rate, rate, adiv->flags);
-               divider = _valid_divider(hw, divider);
+               divider = _valid_divider(adiv->div.width, divider);
                return DIV_ROUND_UP_ULL((u64)*parent_rate, divider);
        }
 
@@ -93,7 +87,7 @@ static long audio_divider_round_rate(struct clk_hw *hw,
 
        /* Get the corresponding rounded down divider */
        divider = max_prate / rate;
-       divider = _valid_divider(hw, divider);
+       divider = _valid_divider(adiv->div.width, divider);
 
        /* Get actual rate of the parent */
        *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
@@ -106,28 +100,11 @@ static int audio_divider_set_rate(struct clk_hw *hw,
                                  unsigned long rate,
                                  unsigned long parent_rate)
 {
-       struct meson_clk_audio_divider *adiv =
-               to_meson_clk_audio_divider(hw);
-       struct parm *p;
-       unsigned long reg, flags = 0;
-       int val;
-
-       val = _get_val(parent_rate, rate);
-
-       if (adiv->lock)
-               spin_lock_irqsave(adiv->lock, flags);
-       else
-               __acquire(adiv->lock);
-
-       p = &adiv->div;
-       reg = readl(adiv->base + p->reg_off);
-       reg = PARM_SET(p->width, p->shift, reg, val);
-       writel(reg, adiv->base + p->reg_off);
-
-       if (adiv->lock)
-               spin_unlock_irqrestore(adiv->lock, flags);
-       else
-               __release(adiv->lock);
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_audio_div_data *adiv = meson_clk_audio_div_data(clk);
+       int val = _get_val(parent_rate, rate);
+
+       meson_parm_write(clk->map, &adiv->div, val);
 
        return 0;
 }
diff --git a/drivers/clk/meson/clk-cpu.c b/drivers/clk/meson/clk-cpu.c
deleted file mode 100644 (file)
index f8b2b7e..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 2015 Endless Mobile, Inc.
- * Author: Carlo Caione <carlo@endlessm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * CPU clock path:
- *
- *                           +-[/N]-----|3|
- *             MUX2  +--[/3]-+----------|2| MUX1
- * [sys_pll]---|1|   |--[/2]------------|1|-|1|
- *             | |---+------------------|0| | |----- [a5_clk]
- *          +--|0|                          | |
- * [xtal]---+-------------------------------|0|
- *
- *
- *
- */
-
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-
-#define MESON_CPU_CLK_CNTL1            0x00
-#define MESON_CPU_CLK_CNTL             0x40
-
-#define MESON_CPU_CLK_MUX1             BIT(7)
-#define MESON_CPU_CLK_MUX2             BIT(0)
-
-#define MESON_N_WIDTH                  9
-#define MESON_N_SHIFT                  20
-#define MESON_SEL_WIDTH                        2
-#define MESON_SEL_SHIFT                        2
-
-#include "clkc.h"
-
-#define to_meson_clk_cpu_hw(_hw) container_of(_hw, struct meson_clk_cpu, hw)
-#define to_meson_clk_cpu_nb(_nb) container_of(_nb, struct meson_clk_cpu, clk_nb)
-
-static long meson_clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
-                                    unsigned long *prate)
-{
-       struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
-
-       return divider_round_rate(hw, rate, prate, clk_cpu->div_table,
-                                 MESON_N_WIDTH, CLK_DIVIDER_ROUND_CLOSEST);
-}
-
-static int meson_clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
-                                 unsigned long parent_rate)
-{
-       struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
-       unsigned int div, sel, N = 0;
-       u32 reg;
-
-       div = DIV_ROUND_UP(parent_rate, rate);
-
-       if (div <= 3) {
-               sel = div - 1;
-       } else {
-               sel = 3;
-               N = div / 2;
-       }
-
-       reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
-       reg = PARM_SET(MESON_N_WIDTH, MESON_N_SHIFT, reg, N);
-       writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
-
-       reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
-       reg = PARM_SET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg, sel);
-       writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
-
-       return 0;
-}
-
-static unsigned long meson_clk_cpu_recalc_rate(struct clk_hw *hw,
-                                              unsigned long parent_rate)
-{
-       struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
-       unsigned int N, sel;
-       unsigned int div = 1;
-       u32 reg;
-
-       reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
-       N = PARM_GET(MESON_N_WIDTH, MESON_N_SHIFT, reg);
-
-       reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
-       sel = PARM_GET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg);
-
-       if (sel < 3)
-               div = sel + 1;
-       else
-               div = 2 * N;
-
-       return parent_rate / div;
-}
-
-/* FIXME MUX1 & MUX2 should be struct clk_hw objects */
-static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu,
-                                        struct clk_notifier_data *ndata)
-{
-       u32 cpu_clk_cntl;
-
-       /* switch MUX1 to xtal */
-       cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off
-                               + MESON_CPU_CLK_CNTL);
-       cpu_clk_cntl &= ~MESON_CPU_CLK_MUX1;
-       writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
-                               + MESON_CPU_CLK_CNTL);
-       udelay(100);
-
-       /* switch MUX2 to sys-pll */
-       cpu_clk_cntl |= MESON_CPU_CLK_MUX2;
-       writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
-                               + MESON_CPU_CLK_CNTL);
-
-       return 0;
-}
-
-/* FIXME MUX1 & MUX2 should be struct clk_hw objects */
-static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu,
-                                         struct clk_notifier_data *ndata)
-{
-       u32 cpu_clk_cntl;
-
-       /* switch MUX1 to divisors' output */
-       cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off
-                               + MESON_CPU_CLK_CNTL);
-       cpu_clk_cntl |= MESON_CPU_CLK_MUX1;
-       writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
-                               + MESON_CPU_CLK_CNTL);
-       udelay(100);
-
-       return 0;
-}
-
-/*
- * This clock notifier is called when the frequency of the of the parent
- * PLL clock is to be changed. We use the xtal input as temporary parent
- * while the PLL frequency is stabilized.
- */
-int meson_clk_cpu_notifier_cb(struct notifier_block *nb,
-                                    unsigned long event, void *data)
-{
-       struct clk_notifier_data *ndata = data;
-       struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_nb(nb);
-       int ret = 0;
-
-       if (event == PRE_RATE_CHANGE)
-               ret = meson_clk_cpu_pre_rate_change(clk_cpu, ndata);
-       else if (event == POST_RATE_CHANGE)
-               ret = meson_clk_cpu_post_rate_change(clk_cpu, ndata);
-
-       return notifier_from_errno(ret);
-}
-
-const struct clk_ops meson_clk_cpu_ops = {
-       .recalc_rate    = meson_clk_cpu_recalc_rate,
-       .round_rate     = meson_clk_cpu_round_rate,
-       .set_rate       = meson_clk_cpu_set_rate,
-};
index 5144360e2c804760720783098288dd3f104e5164..0df1227b65b38ee8e135b81882946c5e6eeddfa4 100644 (file)
 #define N2_MIN 4
 #define N2_MAX 511
 
-#define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
+static inline struct meson_clk_mpll_data *
+meson_clk_mpll_data(struct clk_regmap *clk)
+{
+       return (struct meson_clk_mpll_data *)clk->data;
+}
 
 static long rate_from_params(unsigned long parent_rate,
-                                     unsigned long sdm,
-                                     unsigned long n2)
+                            unsigned int sdm,
+                            unsigned int n2)
 {
        unsigned long divisor = (SDM_DEN * n2) + sdm;
 
@@ -84,8 +88,8 @@ static long rate_from_params(unsigned long parent_rate,
 
 static void params_from_rate(unsigned long requested_rate,
                             unsigned long parent_rate,
-                            unsigned long *sdm,
-                            unsigned long *n2)
+                            unsigned int *sdm,
+                            unsigned int *n2)
 {
        uint64_t div = parent_rate;
        unsigned long rem = do_div(div, requested_rate);
@@ -105,31 +109,23 @@ static void params_from_rate(unsigned long requested_rate,
 static unsigned long mpll_recalc_rate(struct clk_hw *hw,
                unsigned long parent_rate)
 {
-       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
-       struct parm *p;
-       unsigned long reg, sdm, n2;
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk);
+       unsigned int sdm, n2;
        long rate;
 
-       p = &mpll->sdm;
-       reg = readl(mpll->base + p->reg_off);
-       sdm = PARM_GET(p->width, p->shift, reg);
-
-       p = &mpll->n2;
-       reg = readl(mpll->base + p->reg_off);
-       n2 = PARM_GET(p->width, p->shift, reg);
+       sdm = meson_parm_read(clk->map, &mpll->sdm);
+       n2 = meson_parm_read(clk->map, &mpll->n2);
 
        rate = rate_from_params(parent_rate, sdm, n2);
-       if (rate < 0)
-               return 0;
-
-       return rate;
+       return rate < 0 ? 0 : rate;
 }
 
 static long mpll_round_rate(struct clk_hw *hw,
                            unsigned long rate,
                            unsigned long *parent_rate)
 {
-       unsigned long sdm, n2;
+       unsigned int sdm, n2;
 
        params_from_rate(rate, *parent_rate, &sdm, &n2);
        return rate_from_params(*parent_rate, sdm, n2);
@@ -139,9 +135,9 @@ static int mpll_set_rate(struct clk_hw *hw,
                         unsigned long rate,
                         unsigned long parent_rate)
 {
-       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
-       struct parm *p;
-       unsigned long reg, sdm, n2;
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk);
+       unsigned int sdm, n2;
        unsigned long flags = 0;
 
        params_from_rate(rate, parent_rate, &sdm, &n2);
@@ -151,97 +147,36 @@ static int mpll_set_rate(struct clk_hw *hw,
        else
                __acquire(mpll->lock);
 
-       p = &mpll->sdm;
-       reg = readl(mpll->base + p->reg_off);
-       reg = PARM_SET(p->width, p->shift, reg, sdm);
-       writel(reg, mpll->base + p->reg_off);
-
-       p = &mpll->sdm_en;
-       reg = readl(mpll->base + p->reg_off);
-       reg = PARM_SET(p->width, p->shift, reg, 1);
-       writel(reg, mpll->base + p->reg_off);
-
-       p = &mpll->ssen;
-       if (p->width != 0) {
-               reg = readl(mpll->base + p->reg_off);
-               reg = PARM_SET(p->width, p->shift, reg, 1);
-               writel(reg, mpll->base + p->reg_off);
-       }
-
-       p = &mpll->n2;
-       reg = readl(mpll->base + p->reg_off);
-       reg = PARM_SET(p->width, p->shift, reg, n2);
-       writel(reg, mpll->base + p->reg_off);
-
-       if (mpll->lock)
-               spin_unlock_irqrestore(mpll->lock, flags);
-       else
-               __release(mpll->lock);
-
-       return 0;
-}
+       /* Enable and set the fractional part */
+       meson_parm_write(clk->map, &mpll->sdm, sdm);
+       meson_parm_write(clk->map, &mpll->sdm_en, 1);
 
-static void mpll_enable_core(struct clk_hw *hw, int enable)
-{
-       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
-       struct parm *p;
-       unsigned long reg;
-       unsigned long flags = 0;
+       /* Set additional fractional part enable if required */
+       if (MESON_PARM_APPLICABLE(&mpll->ssen))
+               meson_parm_write(clk->map, &mpll->ssen, 1);
 
-       if (mpll->lock)
-               spin_lock_irqsave(mpll->lock, flags);
-       else
-               __acquire(mpll->lock);
+       /* Set the integer divider part */
+       meson_parm_write(clk->map, &mpll->n2, n2);
 
-       p = &mpll->en;
-       reg = readl(mpll->base + p->reg_off);
-       reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0);
-       writel(reg, mpll->base + p->reg_off);
+       /* Set the magic misc bit if required */
+       if (MESON_PARM_APPLICABLE(&mpll->misc))
+               meson_parm_write(clk->map, &mpll->misc, 1);
 
        if (mpll->lock)
                spin_unlock_irqrestore(mpll->lock, flags);
        else
                __release(mpll->lock);
-}
-
-
-static int mpll_enable(struct clk_hw *hw)
-{
-       mpll_enable_core(hw, 1);
 
        return 0;
 }
 
-static void mpll_disable(struct clk_hw *hw)
-{
-       mpll_enable_core(hw, 0);
-}
-
-static int mpll_is_enabled(struct clk_hw *hw)
-{
-       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
-       struct parm *p;
-       unsigned long reg;
-       int en;
-
-       p = &mpll->en;
-       reg = readl(mpll->base + p->reg_off);
-       en = PARM_GET(p->width, p->shift, reg);
-
-       return en;
-}
-
 const struct clk_ops meson_clk_mpll_ro_ops = {
        .recalc_rate    = mpll_recalc_rate,
        .round_rate     = mpll_round_rate,
-       .is_enabled     = mpll_is_enabled,
 };
 
 const struct clk_ops meson_clk_mpll_ops = {
        .recalc_rate    = mpll_recalc_rate,
        .round_rate     = mpll_round_rate,
        .set_rate       = mpll_set_rate,
-       .enable         = mpll_enable,
-       .disable        = mpll_disable,
-       .is_enabled     = mpll_is_enabled,
 };
index 01341553f50b77cde511388e3f36443c89b45c00..65a7bd9035516c4400cf57270dc1ba128cf964ec 100644 (file)
@@ -2,6 +2,9 @@
  * Copyright (c) 2015 Endless Mobile, Inc.
  * Author: Carlo Caione <carlo@endlessm.com>
  *
+ * Copyright (c) 2018 Baylibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
  * version 2, as published by the Free Software Foundation.
  *                |        |
  *               FREF     VCO
  *
- * out = (in * M / N) >> OD
+ * out = in * (m + frac / frac_max) / (n << sum(ods))
  */
 
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/math64.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
 
 #include "clkc.h"
 
-#define MESON_PLL_RESET                                BIT(29)
-#define MESON_PLL_LOCK                         BIT(31)
-
-#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
-
-static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
-                                               unsigned long parent_rate)
+static inline struct meson_clk_pll_data *
+meson_clk_pll_data(struct clk_regmap *clk)
 {
-       struct meson_clk_pll *pll = to_meson_clk_pll(hw);
-       struct parm *p;
-       unsigned long parent_rate_mhz = parent_rate / 1000000;
-       unsigned long rate_mhz;
-       u16 n, m, frac = 0, od, od2 = 0;
-       u32 reg;
-
-       p = &pll->n;
-       reg = readl(pll->base + p->reg_off);
-       n = PARM_GET(p->width, p->shift, reg);
-
-       p = &pll->m;
-       reg = readl(pll->base + p->reg_off);
-       m = PARM_GET(p->width, p->shift, reg);
-
-       p = &pll->od;
-       reg = readl(pll->base + p->reg_off);
-       od = PARM_GET(p->width, p->shift, reg);
-
-       p = &pll->od2;
-       if (p->width) {
-               reg = readl(pll->base + p->reg_off);
-               od2 = PARM_GET(p->width, p->shift, reg);
-       }
-
-       p = &pll->frac;
-       if (p->width) {
-               reg = readl(pll->base + p->reg_off);
-               frac = PARM_GET(p->width, p->shift, reg);
-               rate_mhz = (parent_rate_mhz * m + \
-                               (parent_rate_mhz * frac >> 12)) * 2 / n;
-               rate_mhz = rate_mhz >> od >> od2;
-       } else
-               rate_mhz = (parent_rate_mhz * m / n) >> od >> od2;
-
-       return rate_mhz * 1000000;
+       return (struct meson_clk_pll_data *)clk->data;
 }
 
-static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
-                                    unsigned long *parent_rate)
+static unsigned long __pll_params_to_rate(unsigned long parent_rate,
+                                         const struct pll_rate_table *pllt,
+                                         u16 frac,
+                                         struct meson_clk_pll_data *pll)
 {
-       struct meson_clk_pll *pll = to_meson_clk_pll(hw);
-       const struct pll_rate_table *rate_table = pll->rate_table;
-       int i;
+       u64 rate = (u64)parent_rate * pllt->m;
+       unsigned int od = pllt->od + pllt->od2 + pllt->od3;
 
-       for (i = 0; i < pll->rate_count; i++) {
-               if (rate <= rate_table[i].rate)
-                       return rate_table[i].rate;
+       if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
+               u64 frac_rate = (u64)parent_rate * frac;
+
+               rate += DIV_ROUND_UP_ULL(frac_rate,
+                                        (1 << pll->frac.width));
        }
 
-       /* else return the smallest value */
-       return rate_table[0].rate;
+       return DIV_ROUND_UP_ULL(rate, pllt->n << od);
 }
 
-static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_pll *pll,
-                                                              unsigned long rate)
+static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
+                                               unsigned long parent_rate)
 {
-       const struct pll_rate_table *rate_table = pll->rate_table;
-       int i;
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+       struct pll_rate_table pllt;
+       u16 frac;
 
-       for (i = 0; i < pll->rate_count; i++) {
-               if (rate == rate_table[i].rate)
-                       return &rate_table[i];
-       }
-       return NULL;
+       pllt.n = meson_parm_read(clk->map, &pll->n);
+       pllt.m = meson_parm_read(clk->map, &pll->m);
+       pllt.od = meson_parm_read(clk->map, &pll->od);
+
+       pllt.od2 = MESON_PARM_APPLICABLE(&pll->od2) ?
+               meson_parm_read(clk->map, &pll->od2) :
+               0;
+
+       pllt.od3 = MESON_PARM_APPLICABLE(&pll->od3) ?
+               meson_parm_read(clk->map, &pll->od3) :
+               0;
+
+       frac = MESON_PARM_APPLICABLE(&pll->frac) ?
+               meson_parm_read(clk->map, &pll->frac) :
+               0;
+
+       return __pll_params_to_rate(parent_rate, &pllt, frac, pll);
 }
 
-/* Specific wait loop for GXL/GXM GP0 PLL */
-static int meson_clk_pll_wait_lock_reset(struct meson_clk_pll *pll,
-                                        struct parm *p_n)
+static u16 __pll_params_with_frac(unsigned long rate,
+                                 unsigned long parent_rate,
+                                 const struct pll_rate_table *pllt,
+                                 struct meson_clk_pll_data *pll)
 {
-       int delay = 100;
-       u32 reg;
+       u16 frac_max = (1 << pll->frac.width);
+       u64 val = (u64)rate * pllt->n;
 
-       while (delay > 0) {
-               reg = readl(pll->base + p_n->reg_off);
-               writel(reg | MESON_PLL_RESET, pll->base + p_n->reg_off);
-               udelay(10);
-               writel(reg & ~MESON_PLL_RESET, pll->base + p_n->reg_off);
+       val <<= pllt->od + pllt->od2 + pllt->od3;
 
-               /* This delay comes from AMLogic tree clk-gp0-gxl driver */
-               mdelay(1);
+       if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST)
+               val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate);
+       else
+               val = div_u64(val * frac_max, parent_rate);
 
-               reg = readl(pll->base + p_n->reg_off);
-               if (reg & MESON_PLL_LOCK)
-                       return 0;
-               delay--;
+       val -= pllt->m * frac_max;
+
+       return min((u16)val, (u16)(frac_max - 1));
+}
+
+static const struct pll_rate_table *
+meson_clk_get_pll_settings(unsigned long rate,
+                          struct meson_clk_pll_data *pll)
+{
+       const struct pll_rate_table *table = pll->table;
+       unsigned int i = 0;
+
+       if (!table)
+               return NULL;
+
+       /* Find the first table element exceeding rate */
+       while (table[i].rate && table[i].rate <= rate)
+               i++;
+
+       if (i != 0) {
+               if (MESON_PARM_APPLICABLE(&pll->frac) ||
+                   !(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
+                   (abs(rate - table[i - 1].rate) <
+                    abs(rate - table[i].rate)))
+                       i--;
        }
-       return -ETIMEDOUT;
+
+       return (struct pll_rate_table *)&table[i];
 }
 
-static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
-                                  struct parm *p_n)
+static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+                                    unsigned long *parent_rate)
 {
-       int delay = 24000000;
-       u32 reg;
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+       const struct pll_rate_table *pllt =
+               meson_clk_get_pll_settings(rate, pll);
+       u16 frac;
+
+       if (!pllt)
+               return meson_clk_pll_recalc_rate(hw, *parent_rate);
+
+       if (!MESON_PARM_APPLICABLE(&pll->frac)
+           || rate == pllt->rate)
+               return pllt->rate;
+
+       /*
+        * The rate provided by the setting is not an exact match, let's
+        * try to improve the result using the fractional parameter
+        */
+       frac = __pll_params_with_frac(rate, *parent_rate, pllt, pll);
+
+       return __pll_params_to_rate(*parent_rate, pllt, frac, pll);
+}
 
-       while (delay > 0) {
-               reg = readl(pll->base + p_n->reg_off);
+static int meson_clk_pll_wait_lock(struct clk_hw *hw)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+       int delay = 24000000;
 
-               if (reg & MESON_PLL_LOCK)
+       do {
+               /* Is the clock locked now ? */
+               if (meson_parm_read(clk->map, &pll->l))
                        return 0;
+
                delay--;
-       }
+       } while (delay > 0);
+
        return -ETIMEDOUT;
 }
 
-static void meson_clk_pll_init_params(struct meson_clk_pll *pll)
+static void meson_clk_pll_init(struct clk_hw *hw)
 {
-       int i;
-
-       for (i = 0 ; i < pll->params.params_count ; ++i)
-               writel(pll->params.params_table[i].value,
-                      pll->base + pll->params.params_table[i].reg_off);
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+
+       if (pll->init_count) {
+               meson_parm_write(clk->map, &pll->rst, 1);
+               regmap_multi_reg_write(clk->map, pll->init_regs,
+                                      pll->init_count);
+               meson_parm_write(clk->map, &pll->rst, 0);
+       }
 }
 
 static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
                                  unsigned long parent_rate)
 {
-       struct meson_clk_pll *pll = to_meson_clk_pll(hw);
-       struct parm *p;
-       const struct pll_rate_table *rate_set;
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+       const struct pll_rate_table *pllt;
        unsigned long old_rate;
-       int ret = 0;
-       u32 reg;
+       u16 frac = 0;
 
        if (parent_rate == 0 || rate == 0)
                return -EINVAL;
 
        old_rate = rate;
 
-       rate_set = meson_clk_get_pll_settings(pll, rate);
-       if (!rate_set)
+       pllt = meson_clk_get_pll_settings(rate, pll);
+       if (!pllt)
                return -EINVAL;
 
-       /* Initialize the PLL in a clean state if specified */
-       if (pll->params.params_count)
-               meson_clk_pll_init_params(pll);
-
-       /* PLL reset */
-       p = &pll->n;
-       reg = readl(pll->base + p->reg_off);
-       /* If no_init_reset is provided, avoid resetting at this point */
-       if (!pll->params.no_init_reset)
-               writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
-
-       reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
-       writel(reg, pll->base + p->reg_off);
-
-       p = &pll->m;
-       reg = readl(pll->base + p->reg_off);
-       reg = PARM_SET(p->width, p->shift, reg, rate_set->m);
-       writel(reg, pll->base + p->reg_off);
-
-       p = &pll->od;
-       reg = readl(pll->base + p->reg_off);
-       reg = PARM_SET(p->width, p->shift, reg, rate_set->od);
-       writel(reg, pll->base + p->reg_off);
-
-       p = &pll->od2;
-       if (p->width) {
-               reg = readl(pll->base + p->reg_off);
-               reg = PARM_SET(p->width, p->shift, reg, rate_set->od2);
-               writel(reg, pll->base + p->reg_off);
-       }
+       /* Put the pll in reset to write the params */
+       meson_parm_write(clk->map, &pll->rst, 1);
 
-       p = &pll->frac;
-       if (p->width) {
-               reg = readl(pll->base + p->reg_off);
-               reg = PARM_SET(p->width, p->shift, reg, rate_set->frac);
-               writel(reg, pll->base + p->reg_off);
-       }
+       meson_parm_write(clk->map, &pll->n, pllt->n);
+       meson_parm_write(clk->map, &pll->m, pllt->m);
+       meson_parm_write(clk->map, &pll->od, pllt->od);
+
+       if (MESON_PARM_APPLICABLE(&pll->od2))
+               meson_parm_write(clk->map, &pll->od2, pllt->od2);
+
+       if (MESON_PARM_APPLICABLE(&pll->od3))
+               meson_parm_write(clk->map, &pll->od3, pllt->od3);
 
-       p = &pll->n;
-       /* If clear_reset_for_lock is provided, remove the reset bit here */
-       if (pll->params.clear_reset_for_lock) {
-               reg = readl(pll->base + p->reg_off);
-               writel(reg & ~MESON_PLL_RESET, pll->base + p->reg_off);
+       if (MESON_PARM_APPLICABLE(&pll->frac)) {
+               frac = __pll_params_with_frac(rate, parent_rate, pllt, pll);
+               meson_parm_write(clk->map, &pll->frac, frac);
        }
 
-       /* If reset_lock_loop, use a special loop including resetting */
-       if (pll->params.reset_lock_loop)
-               ret = meson_clk_pll_wait_lock_reset(pll, p);
-       else
-               ret = meson_clk_pll_wait_lock(pll, p);
-       if (ret) {
+       /* make sure the reset is cleared at this point */
+       meson_parm_write(clk->map, &pll->rst, 0);
+
+       if (meson_clk_pll_wait_lock(hw)) {
                pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
                        __func__, old_rate);
+               /*
+                * FIXME: Do we really need/want this HACK ?
+                * It looks unsafe. what happens if the clock gets into a
+                * broken state and we can't lock back on the old_rate ? Looks
+                * like an infinite recursion is possible
+                */
                meson_clk_pll_set_rate(hw, old_rate, parent_rate);
        }
 
-       return ret;
+       return 0;
 }
 
 const struct clk_ops meson_clk_pll_ops = {
+       .init           = meson_clk_pll_init,
        .recalc_rate    = meson_clk_pll_recalc_rate,
        .round_rate     = meson_clk_pll_round_rate,
        .set_rate       = meson_clk_pll_set_rate,
diff --git a/drivers/clk/meson/clk-regmap.c b/drivers/clk/meson/clk-regmap.c
new file mode 100644 (file)
index 0000000..3645fdb
--- /dev/null
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018 BayLibre, SAS.
+// Author: Jerome Brunet <jbrunet@baylibre.com>
+
+#include "clk-regmap.h"
+
+static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk);
+       int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+
+       set ^= enable;
+
+       return regmap_update_bits(clk->map, gate->offset, BIT(gate->bit_idx),
+                                 set ? BIT(gate->bit_idx) : 0);
+}
+
+static int clk_regmap_gate_enable(struct clk_hw *hw)
+{
+       return clk_regmap_gate_endisable(hw, 1);
+}
+
+static void clk_regmap_gate_disable(struct clk_hw *hw)
+{
+       clk_regmap_gate_endisable(hw, 0);
+}
+
+static int clk_regmap_gate_is_enabled(struct clk_hw *hw)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk);
+       unsigned int val;
+
+       regmap_read(clk->map, gate->offset, &val);
+       if (gate->flags & CLK_GATE_SET_TO_DISABLE)
+               val ^= BIT(gate->bit_idx);
+
+       val &= BIT(gate->bit_idx);
+
+       return val ? 1 : 0;
+}
+
+const struct clk_ops clk_regmap_gate_ops = {
+       .enable = clk_regmap_gate_enable,
+       .disable = clk_regmap_gate_disable,
+       .is_enabled = clk_regmap_gate_is_enabled,
+};
+EXPORT_SYMBOL_GPL(clk_regmap_gate_ops);
+
+static unsigned long clk_regmap_div_recalc_rate(struct clk_hw *hw,
+                                               unsigned long prate)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(clk->map, div->offset, &val);
+       if (ret)
+               /* Gives a hint that something is wrong */
+               return 0;
+
+       val >>= div->shift;
+       val &= clk_div_mask(div->width);
+       return divider_recalc_rate(hw, prate, val, div->table, div->flags,
+                                  div->width);
+}
+
+static long clk_regmap_div_round_rate(struct clk_hw *hw, unsigned long rate,
+                                     unsigned long *prate)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
+       unsigned int val;
+       int ret;
+
+       /* if read only, just return current value */
+       if (div->flags & CLK_DIVIDER_READ_ONLY) {
+               ret = regmap_read(clk->map, div->offset, &val);
+               if (ret)
+                       /* Gives a hint that something is wrong */
+                       return 0;
+
+               val >>= div->shift;
+               val &= clk_div_mask(div->width);
+
+               return divider_ro_round_rate(hw, rate, prate, div->table,
+                                            div->width, div->flags, val);
+       }
+
+       return divider_round_rate(hw, rate, prate, div->table, div->width,
+                                 div->flags);
+}
+
+static int clk_regmap_div_set_rate(struct clk_hw *hw, unsigned long rate,
+                                  unsigned long parent_rate)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
+       unsigned int val;
+       int ret;
+
+       ret = divider_get_val(rate, parent_rate, div->table, div->width,
+                             div->flags);
+       if (ret < 0)
+               return ret;
+
+       val = (unsigned int)ret << div->shift;
+       return regmap_update_bits(clk->map, div->offset,
+                                 clk_div_mask(div->width) << div->shift, val);
+};
+
+/* Would prefer clk_regmap_div_ro_ops but clashes with qcom */
+
+const struct clk_ops clk_regmap_divider_ops = {
+       .recalc_rate = clk_regmap_div_recalc_rate,
+       .round_rate = clk_regmap_div_round_rate,
+       .set_rate = clk_regmap_div_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_regmap_divider_ops);
+
+const struct clk_ops clk_regmap_divider_ro_ops = {
+       .recalc_rate = clk_regmap_div_recalc_rate,
+       .round_rate = clk_regmap_div_round_rate,
+};
+EXPORT_SYMBOL_GPL(clk_regmap_divider_ro_ops);
+
+static u8 clk_regmap_mux_get_parent(struct clk_hw *hw)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk);
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(clk->map, mux->offset, &val);
+       if (ret)
+               return ret;
+
+       val >>= mux->shift;
+       val &= mux->mask;
+       return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
+}
+
+static int clk_regmap_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk);
+       unsigned int val = clk_mux_index_to_val(mux->table, mux->flags, index);
+
+       return regmap_update_bits(clk->map, mux->offset,
+                                 mux->mask << mux->shift,
+                                 val << mux->shift);
+}
+
+const struct clk_ops clk_regmap_mux_ops = {
+       .get_parent = clk_regmap_mux_get_parent,
+       .set_parent = clk_regmap_mux_set_parent,
+       .determine_rate = __clk_mux_determine_rate,
+};
+EXPORT_SYMBOL_GPL(clk_regmap_mux_ops);
+
+const struct clk_ops clk_regmap_mux_ro_ops = {
+       .get_parent = clk_regmap_mux_get_parent,
+};
+EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops);
diff --git a/drivers/clk/meson/clk-regmap.h b/drivers/clk/meson/clk-regmap.h
new file mode 100644 (file)
index 0000000..627c888
--- /dev/null
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018 BayLibre, SAS.
+// Author: Jerome Brunet <jbrunet@baylibre.com>
+
+#ifndef __CLK_REGMAP_H
+#define __CLK_REGMAP_H
+
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+
+/**
+ * struct clk_regmap - regmap backed clock
+ *
+ * @hw:                handle between common and hardware-specific interfaces
+ * @map:       pointer to the regmap structure controlling the clock
+ * @data:      data specific to the clock type
+ *
+ * Clock which is controlled by regmap backed registers. The actual type of
+ * of the clock is controlled by the clock_ops and data.
+ */
+struct clk_regmap {
+       struct clk_hw   hw;
+       struct regmap   *map;
+       void            *data;
+};
+
+#define to_clk_regmap(_hw) container_of(_hw, struct clk_regmap, hw)
+
+/**
+ * struct clk_regmap_gate_data - regmap backed gate specific data
+ *
+ * @offset:    offset of the register controlling gate
+ * @bit_idx:   single bit controlling gate
+ * @flags:     hardware-specific flags
+ *
+ * Flags:
+ * Same as clk_gate except CLK_GATE_HIWORD_MASK which is ignored
+ */
+struct clk_regmap_gate_data {
+       unsigned int    offset;
+       u8              bit_idx;
+       u8              flags;
+};
+
+static inline struct clk_regmap_gate_data *
+clk_get_regmap_gate_data(struct clk_regmap *clk)
+{
+       return (struct clk_regmap_gate_data *)clk->data;
+}
+
+extern const struct clk_ops clk_regmap_gate_ops;
+
+/**
+ * struct clk_regmap_div_data - regmap backed adjustable divider specific data
+ *
+ * @offset:    offset of the register controlling the divider
+ * @shift:     shift to the divider bit field
+ * @width:     width of the divider bit field
+ * @table:     array of value/divider pairs, last entry should have div = 0
+ *
+ * Flags:
+ * Same as clk_divider except CLK_DIVIDER_HIWORD_MASK which is ignored
+ */
+struct clk_regmap_div_data {
+       unsigned int    offset;
+       u8              shift;
+       u8              width;
+       u8              flags;
+       const struct clk_div_table      *table;
+};
+
+static inline struct clk_regmap_div_data *
+clk_get_regmap_div_data(struct clk_regmap *clk)
+{
+       return (struct clk_regmap_div_data *)clk->data;
+}
+
+extern const struct clk_ops clk_regmap_divider_ops;
+extern const struct clk_ops clk_regmap_divider_ro_ops;
+
+/**
+ * struct clk_regmap_mux_data - regmap backed multiplexer clock specific data
+ *
+ * @hw:                handle between common and hardware-specific interfaces
+ * @offset:    offset of theregister controlling multiplexer
+ * @table:     array of parent indexed register values
+ * @shift:     shift to multiplexer bit field
+ * @mask:      mask of mutliplexer bit field
+ * @flags:     hardware-specific flags
+ *
+ * Flags:
+ * Same as clk_divider except CLK_MUX_HIWORD_MASK which is ignored
+ */
+struct clk_regmap_mux_data {
+       unsigned int    offset;
+       u32             *table;
+       u32             mask;
+       u8              shift;
+       u8              flags;
+};
+
+static inline struct clk_regmap_mux_data *
+clk_get_regmap_mux_data(struct clk_regmap *clk)
+{
+       return (struct clk_regmap_mux_data *)clk->data;
+}
+
+extern const struct clk_ops clk_regmap_mux_ops;
+extern const struct clk_ops clk_regmap_mux_ro_ops;
+
+#endif /* __CLK_REGMAP_H */
index c2ff0520ce533f7633b46b0b9f56a3a4827fcba9..8fe73c4edca8ef091da760b42402eb33395cca48 100644 (file)
@@ -18,6 +18,9 @@
 #ifndef __CLKC_H
 #define __CLKC_H
 
+#include <linux/clk-provider.h>
+#include "clk-regmap.h"
+
 #define PMASK(width)                   GENMASK(width - 1, 0)
 #define SETPMASK(width, shift)         GENMASK(shift + width - 1, shift)
 #define CLRPMASK(width, shift)         (~SETPMASK(width, shift))
@@ -35,13 +38,29 @@ struct parm {
        u8      width;
 };
 
+static inline unsigned int meson_parm_read(struct regmap *map, struct parm *p)
+{
+       unsigned int val;
+
+       regmap_read(map, p->reg_off, &val);
+       return PARM_GET(p->width, p->shift, val);
+}
+
+static inline void meson_parm_write(struct regmap *map, struct parm *p,
+                                   unsigned int val)
+{
+       regmap_update_bits(map, p->reg_off, SETPMASK(p->width, p->shift),
+                          val << p->shift);
+}
+
+
 struct pll_rate_table {
        unsigned long   rate;
        u16             m;
        u16             n;
        u16             od;
        u16             od2;
-       u16             frac;
+       u16             od3;
 };
 
 #define PLL_RATE(_r, _m, _n, _od)                                      \
@@ -50,97 +69,53 @@ struct pll_rate_table {
                .m              = (_m),                                 \
                .n              = (_n),                                 \
                .od             = (_od),                                \
-       }                                                               \
-
-#define PLL_FRAC_RATE(_r, _m, _n, _od, _od2, _frac)                    \
-       {                                                               \
-               .rate           = (_r),                                 \
-               .m              = (_m),                                 \
-               .n              = (_n),                                 \
-               .od             = (_od),                                \
-               .od2            = (_od2),                               \
-               .frac           = (_frac),                              \
-       }                                                               \
-
-struct pll_params_table {
-       unsigned int reg_off;
-       unsigned int value;
-};
-
-#define PLL_PARAM(_reg, _val)                                          \
-       {                                                               \
-               .reg_off        = (_reg),                               \
-               .value          = (_val),                               \
        }
 
-struct pll_setup_params {
-       struct pll_params_table *params_table;
-       unsigned int params_count;
-       /* Workaround for GP0, do not reset before configuring */
-       bool no_init_reset;
-       /* Workaround for GP0, unreset right before checking for lock */
-       bool clear_reset_for_lock;
-       /* Workaround for GXL GP0, reset in the lock checking loop */
-       bool reset_lock_loop;
-};
+#define CLK_MESON_PLL_ROUND_CLOSEST    BIT(0)
 
-struct meson_clk_pll {
-       struct clk_hw hw;
-       void __iomem *base;
+struct meson_clk_pll_data {
        struct parm m;
        struct parm n;
        struct parm frac;
        struct parm od;
        struct parm od2;
-       const struct pll_setup_params params;
-       const struct pll_rate_table *rate_table;
-       unsigned int rate_count;
-       spinlock_t *lock;
+       struct parm od3;
+       struct parm l;
+       struct parm rst;
+       const struct reg_sequence *init_regs;
+       unsigned int init_count;
+       const struct pll_rate_table *table;
+       u8 flags;
 };
 
 #define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
 
-struct meson_clk_cpu {
-       struct clk_hw hw;
-       void __iomem *base;
-       u16 reg_off;
-       struct notifier_block clk_nb;
-       const struct clk_div_table *div_table;
-};
-
-int meson_clk_cpu_notifier_cb(struct notifier_block *nb, unsigned long event,
-               void *data);
-
-struct meson_clk_mpll {
-       struct clk_hw hw;
-       void __iomem *base;
+struct meson_clk_mpll_data {
        struct parm sdm;
        struct parm sdm_en;
        struct parm n2;
-       struct parm en;
        struct parm ssen;
+       struct parm misc;
        spinlock_t *lock;
 };
 
-struct meson_clk_audio_divider {
-       struct clk_hw hw;
-       void __iomem *base;
+struct meson_clk_audio_div_data {
        struct parm div;
        u8 flags;
-       spinlock_t *lock;
 };
 
 #define MESON_GATE(_name, _reg, _bit)                                  \
-struct clk_gate _name = {                                              \
-       .reg = (void __iomem *) _reg,                                   \
-       .bit_idx = (_bit),                                              \
-       .lock = &meson_clk_lock,                                        \
-       .hw.init = &(struct clk_init_data) {                            \
-               .name = #_name,                                 \
-               .ops = &clk_gate_ops,                                   \
+struct clk_regmap _name = {                                            \
+       .data = &(struct clk_regmap_gate_data){                         \
+               .offset = (_reg),                                       \
+               .bit_idx = (_bit),                                      \
+       },                                                              \
+       .hw.init = &(struct clk_init_data) {                            \
+               .name = #_name,                                         \
+               .ops = &clk_regmap_gate_ops,                            \
                .parent_names = (const char *[]){ "clk81" },            \
                .num_parents = 1,                                       \
-               .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),     \
+               .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),     \
        },                                                              \
 };
 
diff --git a/drivers/clk/meson/gxbb-aoclk-regmap.c b/drivers/clk/meson/gxbb-aoclk-regmap.c
deleted file mode 100644 (file)
index 2515fbf..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2017 BayLibre, SAS.
- * Author: Neil Armstrong <narmstrong@baylibre.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <linux/clk-provider.h>
-#include <linux/bitfield.h>
-#include <linux/regmap.h>
-#include "gxbb-aoclk.h"
-
-static int aoclk_gate_regmap_enable(struct clk_hw *hw)
-{
-       struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw);
-
-       return regmap_update_bits(gate->regmap, AO_RTI_GEN_CNTL_REG0,
-                                 BIT(gate->bit_idx), BIT(gate->bit_idx));
-}
-
-static void aoclk_gate_regmap_disable(struct clk_hw *hw)
-{
-       struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw);
-
-       regmap_update_bits(gate->regmap, AO_RTI_GEN_CNTL_REG0,
-                          BIT(gate->bit_idx), 0);
-}
-
-static int aoclk_gate_regmap_is_enabled(struct clk_hw *hw)
-{
-       struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw);
-       unsigned int val;
-       int ret;
-
-       ret = regmap_read(gate->regmap, AO_RTI_GEN_CNTL_REG0, &val);
-       if (ret)
-               return ret;
-
-       return (val & BIT(gate->bit_idx)) != 0;
-}
-
-const struct clk_ops meson_aoclk_gate_regmap_ops = {
-       .enable = aoclk_gate_regmap_enable,
-       .disable = aoclk_gate_regmap_disable,
-       .is_enabled = aoclk_gate_regmap_is_enabled,
-};
index 6c161e0a8e59c248c2d8116f78904b1fd3a045ad..9ec23ae9a2195d898c6a6b06816b9b942a4da4e4 100644 (file)
 #include <linux/delay.h>
 #include <dt-bindings/clock/gxbb-aoclkc.h>
 #include <dt-bindings/reset/gxbb-aoclkc.h>
+#include "clk-regmap.h"
 #include "gxbb-aoclk.h"
 
-static DEFINE_SPINLOCK(gxbb_aoclk_lock);
-
 struct gxbb_aoclk_reset_controller {
        struct reset_controller_dev reset;
        unsigned int *data;
@@ -87,12 +86,14 @@ static const struct reset_control_ops gxbb_aoclk_reset_ops = {
 };
 
 #define GXBB_AO_GATE(_name, _bit)                                      \
-static struct aoclk_gate_regmap _name##_ao = {                         \
-       .bit_idx = (_bit),                                              \
-       .lock = &gxbb_aoclk_lock,                                       \
+static struct clk_regmap _name##_ao = {                                        \
+       .data = &(struct clk_regmap_gate_data) {                        \
+               .offset = AO_RTI_GEN_CNTL_REG0,                         \
+               .bit_idx = (_bit),                                      \
+       },                                                              \
        .hw.init = &(struct clk_init_data) {                            \
                .name = #_name "_ao",                                   \
-               .ops = &meson_aoclk_gate_regmap_ops,                    \
+               .ops = &clk_regmap_gate_ops,                            \
                .parent_names = (const char *[]){ "clk81" },            \
                .num_parents = 1,                                       \
                .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),     \
@@ -107,7 +108,6 @@ GXBB_AO_GATE(uart2, 5);
 GXBB_AO_GATE(ir_blaster, 6);
 
 static struct aoclk_cec_32k cec_32k_ao = {
-       .lock = &gxbb_aoclk_lock,
        .hw.init = &(struct clk_init_data) {
                .name = "cec_32k_ao",
                .ops = &meson_aoclk_cec_32k_ops,
@@ -126,7 +126,7 @@ static unsigned int gxbb_aoclk_reset[] = {
        [RESET_AO_IR_BLASTER] = 23,
 };
 
-static struct aoclk_gate_regmap *gxbb_aoclk_gate[] = {
+static struct clk_regmap *gxbb_aoclk_gate[] = {
        [CLKID_AO_REMOTE] = &remote_ao,
        [CLKID_AO_I2C_MASTER] = &i2c_master_ao,
        [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao,
@@ -177,10 +177,10 @@ static int gxbb_aoclkc_probe(struct platform_device *pdev)
         * Populate regmap and register all clks
         */
        for (clkid = 0; clkid < ARRAY_SIZE(gxbb_aoclk_gate); clkid++) {
-               gxbb_aoclk_gate[clkid]->regmap = regmap;
+               gxbb_aoclk_gate[clkid]->map = regmap;
 
                ret = devm_clk_hw_register(dev,
-                                       gxbb_aoclk_onecell_data.hws[clkid]);
+                                          gxbb_aoclk_onecell_data.hws[clkid]);
                if (ret)
                        return ret;
        }
index e8604c8f7eee280c7101fe9fd20281160063e663..0be78383f2574ce30458ceb95051eeb215cdbc72 100644 (file)
 #define AO_RTC_ALT_CLK_CNTL0   0x94
 #define AO_RTC_ALT_CLK_CNTL1   0x98
 
-struct aoclk_gate_regmap {
-       struct clk_hw hw;
-       unsigned bit_idx;
-       struct regmap *regmap;
-       spinlock_t *lock;
-};
-
-#define to_aoclk_gate_regmap(_hw) \
-       container_of(_hw, struct aoclk_gate_regmap, hw)
-
 extern const struct clk_ops meson_aoclk_gate_regmap_ops;
 
 struct aoclk_cec_32k {
        struct clk_hw hw;
        struct regmap *regmap;
-       spinlock_t *lock;
 };
 
 #define to_aoclk_cec_32k(_hw) container_of(_hw, struct aoclk_cec_32k, hw)
index af24455af5b4d551a287bfcf59b975fa9dfd1df4..b1e4d955761088ba228ee16a92ac9b6bdb69fc89 100644 (file)
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/init.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/mfd/syscon.h>
 #include <linux/platform_device.h>
-#include <linux/init.h>
+#include <linux/regmap.h>
 
 #include "clkc.h"
 #include "gxbb.h"
+#include "clk-regmap.h"
 
 static DEFINE_SPINLOCK(meson_clk_lock);
 
-static const struct pll_rate_table sys_pll_rate_table[] = {
-       PLL_RATE(24000000, 56, 1, 2),
-       PLL_RATE(48000000, 64, 1, 2),
-       PLL_RATE(72000000, 72, 1, 2),
-       PLL_RATE(96000000, 64, 1, 2),
-       PLL_RATE(120000000, 80, 1, 2),
-       PLL_RATE(144000000, 96, 1, 2),
-       PLL_RATE(168000000, 56, 1, 1),
-       PLL_RATE(192000000, 64, 1, 1),
-       PLL_RATE(216000000, 72, 1, 1),
-       PLL_RATE(240000000, 80, 1, 1),
-       PLL_RATE(264000000, 88, 1, 1),
-       PLL_RATE(288000000, 96, 1, 1),
-       PLL_RATE(312000000, 52, 1, 2),
-       PLL_RATE(336000000, 56, 1, 2),
-       PLL_RATE(360000000, 60, 1, 2),
-       PLL_RATE(384000000, 64, 1, 2),
-       PLL_RATE(408000000, 68, 1, 2),
-       PLL_RATE(432000000, 72, 1, 2),
-       PLL_RATE(456000000, 76, 1, 2),
-       PLL_RATE(480000000, 80, 1, 2),
-       PLL_RATE(504000000, 84, 1, 2),
-       PLL_RATE(528000000, 88, 1, 2),
-       PLL_RATE(552000000, 92, 1, 2),
-       PLL_RATE(576000000, 96, 1, 2),
-       PLL_RATE(600000000, 50, 1, 1),
-       PLL_RATE(624000000, 52, 1, 1),
-       PLL_RATE(648000000, 54, 1, 1),
-       PLL_RATE(672000000, 56, 1, 1),
-       PLL_RATE(696000000, 58, 1, 1),
-       PLL_RATE(720000000, 60, 1, 1),
-       PLL_RATE(744000000, 62, 1, 1),
-       PLL_RATE(768000000, 64, 1, 1),
-       PLL_RATE(792000000, 66, 1, 1),
-       PLL_RATE(816000000, 68, 1, 1),
-       PLL_RATE(840000000, 70, 1, 1),
-       PLL_RATE(864000000, 72, 1, 1),
-       PLL_RATE(888000000, 74, 1, 1),
-       PLL_RATE(912000000, 76, 1, 1),
-       PLL_RATE(936000000, 78, 1, 1),
-       PLL_RATE(960000000, 80, 1, 1),
-       PLL_RATE(984000000, 82, 1, 1),
-       PLL_RATE(1008000000, 84, 1, 1),
-       PLL_RATE(1032000000, 86, 1, 1),
-       PLL_RATE(1056000000, 88, 1, 1),
-       PLL_RATE(1080000000, 90, 1, 1),
-       PLL_RATE(1104000000, 92, 1, 1),
-       PLL_RATE(1128000000, 94, 1, 1),
-       PLL_RATE(1152000000, 96, 1, 1),
-       PLL_RATE(1176000000, 98, 1, 1),
-       PLL_RATE(1200000000, 50, 1, 0),
-       PLL_RATE(1224000000, 51, 1, 0),
-       PLL_RATE(1248000000, 52, 1, 0),
-       PLL_RATE(1272000000, 53, 1, 0),
-       PLL_RATE(1296000000, 54, 1, 0),
-       PLL_RATE(1320000000, 55, 1, 0),
-       PLL_RATE(1344000000, 56, 1, 0),
-       PLL_RATE(1368000000, 57, 1, 0),
-       PLL_RATE(1392000000, 58, 1, 0),
-       PLL_RATE(1416000000, 59, 1, 0),
-       PLL_RATE(1440000000, 60, 1, 0),
-       PLL_RATE(1464000000, 61, 1, 0),
-       PLL_RATE(1488000000, 62, 1, 0),
-       PLL_RATE(1512000000, 63, 1, 0),
-       PLL_RATE(1536000000, 64, 1, 0),
-       PLL_RATE(1560000000, 65, 1, 0),
-       PLL_RATE(1584000000, 66, 1, 0),
-       PLL_RATE(1608000000, 67, 1, 0),
-       PLL_RATE(1632000000, 68, 1, 0),
-       PLL_RATE(1656000000, 68, 1, 0),
-       PLL_RATE(1680000000, 68, 1, 0),
-       PLL_RATE(1704000000, 68, 1, 0),
-       PLL_RATE(1728000000, 69, 1, 0),
-       PLL_RATE(1752000000, 69, 1, 0),
-       PLL_RATE(1776000000, 69, 1, 0),
-       PLL_RATE(1800000000, 69, 1, 0),
-       PLL_RATE(1824000000, 70, 1, 0),
-       PLL_RATE(1848000000, 70, 1, 0),
-       PLL_RATE(1872000000, 70, 1, 0),
-       PLL_RATE(1896000000, 70, 1, 0),
-       PLL_RATE(1920000000, 71, 1, 0),
-       PLL_RATE(1944000000, 71, 1, 0),
-       PLL_RATE(1968000000, 71, 1, 0),
-       PLL_RATE(1992000000, 71, 1, 0),
-       PLL_RATE(2016000000, 72, 1, 0),
-       PLL_RATE(2040000000, 72, 1, 0),
-       PLL_RATE(2064000000, 72, 1, 0),
-       PLL_RATE(2088000000, 72, 1, 0),
-       PLL_RATE(2112000000, 73, 1, 0),
-       { /* sentinel */ },
-};
-
 static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = {
        PLL_RATE(96000000, 32, 1, 3),
        PLL_RATE(99000000, 33, 1, 3),
@@ -278,23 +189,39 @@ static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
        { /* sentinel */ },
 };
 
-static struct meson_clk_pll gxbb_fixed_pll = {
-       .m = {
-               .reg_off = HHI_MPLL_CNTL,
-               .shift   = 0,
-               .width   = 9,
+static struct clk_regmap gxbb_fixed_pll = {
+       .data = &(struct meson_clk_pll_data){
+               .m = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .od = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 16,
+                       .width   = 2,
+               },
+               .frac = {
+                       .reg_off = HHI_MPLL_CNTL2,
+                       .shift   = 0,
+                       .width   = 12,
+               },
+               .l = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 29,
+                       .width   = 1,
+               },
        },
-       .n = {
-               .reg_off = HHI_MPLL_CNTL,
-               .shift   = 9,
-               .width   = 5,
-       },
-       .od = {
-               .reg_off = HHI_MPLL_CNTL,
-               .shift   = 16,
-               .width   = 2,
-       },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "fixed_pll",
                .ops = &meson_clk_pll_ro_ops,
@@ -304,33 +231,118 @@ static struct meson_clk_pll gxbb_fixed_pll = {
        },
 };
 
-static struct meson_clk_pll gxbb_hdmi_pll = {
-       .m = {
-               .reg_off = HHI_HDMI_PLL_CNTL,
-               .shift   = 0,
-               .width   = 9,
-       },
-       .n = {
-               .reg_off = HHI_HDMI_PLL_CNTL,
-               .shift   = 9,
-               .width   = 5,
+static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
+       .mult = 2,
+       .div = 1,
+       .hw.init = &(struct clk_init_data){
+               .name = "hdmi_pll_pre_mult",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
        },
-       .frac = {
-               .reg_off = HHI_HDMI_PLL_CNTL2,
-               .shift   = 0,
-               .width   = 12,
+};
+
+static struct clk_regmap gxbb_hdmi_pll = {
+       .data = &(struct meson_clk_pll_data){
+               .m = {
+                       .reg_off = HHI_HDMI_PLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = HHI_HDMI_PLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .frac = {
+                       .reg_off = HHI_HDMI_PLL_CNTL2,
+                       .shift   = 0,
+                       .width   = 12,
+               },
+               .od = {
+                       .reg_off = HHI_HDMI_PLL_CNTL2,
+                       .shift   = 16,
+                       .width   = 2,
+               },
+               .od2 = {
+                       .reg_off = HHI_HDMI_PLL_CNTL2,
+                       .shift   = 22,
+                       .width   = 2,
+               },
+               .od3 = {
+                       .reg_off = HHI_HDMI_PLL_CNTL2,
+                       .shift   = 18,
+                       .width   = 2,
+               },
+               .l = {
+                       .reg_off = HHI_HDMI_PLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_HDMI_PLL_CNTL,
+                       .shift   = 28,
+                       .width   = 1,
+               },
        },
-       .od = {
-               .reg_off = HHI_HDMI_PLL_CNTL2,
-               .shift   = 16,
-               .width   = 2,
+       .hw.init = &(struct clk_init_data){
+               .name = "hdmi_pll",
+               .ops = &meson_clk_pll_ro_ops,
+               .parent_names = (const char *[]){ "hdmi_pll_pre_mult" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
        },
-       .od2 = {
-               .reg_off = HHI_HDMI_PLL_CNTL2,
-               .shift   = 22,
-               .width   = 2,
+};
+
+static struct clk_regmap gxl_hdmi_pll = {
+       .data = &(struct meson_clk_pll_data){
+               .m = {
+                       .reg_off = HHI_HDMI_PLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = HHI_HDMI_PLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .frac = {
+                       /*
+                        * On gxl, there is a register shift due to
+                        * HHI_HDMI_PLL_CNTL1 which does not exist on gxbb,
+                        * so we compute the register offset based on the PLL
+                        * base to get it right
+                        */
+                       .reg_off = HHI_HDMI_PLL_CNTL + 4,
+                       .shift   = 0,
+                       .width   = 12,
+               },
+               .od = {
+                       .reg_off = HHI_HDMI_PLL_CNTL + 8,
+                       .shift   = 21,
+                       .width   = 2,
+               },
+               .od2 = {
+                       .reg_off = HHI_HDMI_PLL_CNTL + 8,
+                       .shift   = 23,
+                       .width   = 2,
+               },
+               .od3 = {
+                       .reg_off = HHI_HDMI_PLL_CNTL + 8,
+                       .shift   = 19,
+                       .width   = 2,
+               },
+               .l = {
+                       .reg_off = HHI_HDMI_PLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_HDMI_PLL_CNTL,
+                       .shift   = 29,
+                       .width   = 1,
+               },
        },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "hdmi_pll",
                .ops = &meson_clk_pll_ro_ops,
@@ -340,25 +352,34 @@ static struct meson_clk_pll gxbb_hdmi_pll = {
        },
 };
 
-static struct meson_clk_pll gxbb_sys_pll = {
-       .m = {
-               .reg_off = HHI_SYS_PLL_CNTL,
-               .shift   = 0,
-               .width   = 9,
-       },
-       .n = {
-               .reg_off = HHI_SYS_PLL_CNTL,
-               .shift   = 9,
-               .width   = 5,
+static struct clk_regmap gxbb_sys_pll = {
+       .data = &(struct meson_clk_pll_data){
+               .m = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .od = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 10,
+                       .width   = 2,
+               },
+               .l = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 29,
+                       .width   = 1,
+               },
        },
-       .od = {
-               .reg_off = HHI_SYS_PLL_CNTL,
-               .shift   = 10,
-               .width   = 2,
-       },
-       .rate_table = sys_pll_rate_table,
-       .rate_count = ARRAY_SIZE(sys_pll_rate_table),
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "sys_pll",
                .ops = &meson_clk_pll_ro_ops,
@@ -368,38 +389,44 @@ static struct meson_clk_pll gxbb_sys_pll = {
        },
 };
 
-struct pll_params_table gxbb_gp0_params_table[] = {
-       PLL_PARAM(HHI_GP0_PLL_CNTL, 0x6a000228),
-       PLL_PARAM(HHI_GP0_PLL_CNTL2, 0x69c80000),
-       PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a5590c4),
-       PLL_PARAM(HHI_GP0_PLL_CNTL4, 0x0000500d),
-};
-
-static struct meson_clk_pll gxbb_gp0_pll = {
-       .m = {
-               .reg_off = HHI_GP0_PLL_CNTL,
-               .shift   = 0,
-               .width   = 9,
-       },
-       .n = {
-               .reg_off = HHI_GP0_PLL_CNTL,
-               .shift   = 9,
-               .width   = 5,
-       },
-       .od = {
-               .reg_off = HHI_GP0_PLL_CNTL,
-               .shift   = 16,
-               .width   = 2,
-       },
-       .params = {
-               .params_table = gxbb_gp0_params_table,
-               .params_count = ARRAY_SIZE(gxbb_gp0_params_table),
-               .no_init_reset = true,
-               .clear_reset_for_lock = true,
+static const struct reg_sequence gxbb_gp0_init_regs[] = {
+       { .reg = HHI_GP0_PLL_CNTL2,     .def = 0x69c80000 },
+       { .reg = HHI_GP0_PLL_CNTL3,     .def = 0x0a5590c4 },
+       { .reg = HHI_GP0_PLL_CNTL4,     .def = 0x0000500d },
+       { .reg = HHI_GP0_PLL_CNTL,      .def = 0x4a000228 },
+};
+
+static struct clk_regmap gxbb_gp0_pll = {
+       .data = &(struct meson_clk_pll_data){
+               .m = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .od = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 16,
+                       .width   = 2,
+               },
+               .l = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+               .table = gxbb_gp0_pll_rate_table,
+               .init_regs = gxbb_gp0_init_regs,
+               .init_count = ARRAY_SIZE(gxbb_gp0_init_regs),
        },
-       .rate_table = gxbb_gp0_pll_rate_table,
-       .rate_count = ARRAY_SIZE(gxbb_gp0_pll_rate_table),
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "gp0_pll",
                .ops = &meson_clk_pll_ops,
@@ -409,40 +436,51 @@ static struct meson_clk_pll gxbb_gp0_pll = {
        },
 };
 
-struct pll_params_table gxl_gp0_params_table[] = {
-       PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250),
-       PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000),
-       PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be),
-       PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288),
-       PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d),
-       PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000),
-};
-
-static struct meson_clk_pll gxl_gp0_pll = {
-       .m = {
-               .reg_off = HHI_GP0_PLL_CNTL,
-               .shift   = 0,
-               .width   = 9,
-       },
-       .n = {
-               .reg_off = HHI_GP0_PLL_CNTL,
-               .shift   = 9,
-               .width   = 5,
-       },
-       .od = {
-               .reg_off = HHI_GP0_PLL_CNTL,
-               .shift   = 16,
-               .width   = 2,
+static const struct reg_sequence gxl_gp0_init_regs[] = {
+       { .reg = HHI_GP0_PLL_CNTL1,     .def = 0xc084b000 },
+       { .reg = HHI_GP0_PLL_CNTL2,     .def = 0xb75020be },
+       { .reg = HHI_GP0_PLL_CNTL3,     .def = 0x0a59a288 },
+       { .reg = HHI_GP0_PLL_CNTL4,     .def = 0xc000004d },
+       { .reg = HHI_GP0_PLL_CNTL5,     .def = 0x00078000 },
+       { .reg = HHI_GP0_PLL_CNTL,      .def = 0x40010250 },
+};
+
+static struct clk_regmap gxl_gp0_pll = {
+       .data = &(struct meson_clk_pll_data){
+               .m = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .od = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 16,
+                       .width   = 2,
+               },
+               .frac = {
+                       .reg_off = HHI_GP0_PLL_CNTL1,
+                       .shift   = 0,
+                       .width   = 10,
+               },
+               .l = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_GP0_PLL_CNTL,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+               .table = gxl_gp0_pll_rate_table,
+               .init_regs = gxl_gp0_init_regs,
+               .init_count = ARRAY_SIZE(gxl_gp0_init_regs),
        },
-       .params = {
-               .params_table = gxl_gp0_params_table,
-               .params_count = ARRAY_SIZE(gxl_gp0_params_table),
-               .no_init_reset = true,
-               .reset_lock_loop = true,
-       },
-       .rate_table = gxl_gp0_pll_rate_table,
-       .rate_count = ARRAY_SIZE(gxl_gp0_pll_rate_table),
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "gp0_pll",
                .ops = &meson_clk_pll_ops,
@@ -452,161 +490,267 @@ static struct meson_clk_pll gxl_gp0_pll = {
        },
 };
 
-static struct clk_fixed_factor gxbb_fclk_div2 = {
+static struct clk_fixed_factor gxbb_fclk_div2_div = {
        .mult = 1,
        .div = 2,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div2",
+               .name = "fclk_div2_div",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct clk_fixed_factor gxbb_fclk_div3 = {
+static struct clk_regmap gxbb_fclk_div2 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 27,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div2",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div2_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor gxbb_fclk_div3_div = {
        .mult = 1,
        .div = 3,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div3",
+               .name = "fclk_div3_div",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct clk_fixed_factor gxbb_fclk_div4 = {
+static struct clk_regmap gxbb_fclk_div3 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 28,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div3",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div3_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor gxbb_fclk_div4_div = {
        .mult = 1,
        .div = 4,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div4",
+               .name = "fclk_div4_div",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct clk_fixed_factor gxbb_fclk_div5 = {
+static struct clk_regmap gxbb_fclk_div4 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 29,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div4",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div4_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor gxbb_fclk_div5_div = {
        .mult = 1,
        .div = 5,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div5",
+               .name = "fclk_div5_div",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct clk_fixed_factor gxbb_fclk_div7 = {
+static struct clk_regmap gxbb_fclk_div5 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 30,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div5",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div5_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor gxbb_fclk_div7_div = {
        .mult = 1,
        .div = 7,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div7",
+               .name = "fclk_div7_div",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct meson_clk_mpll gxbb_mpll0 = {
-       .sdm = {
-               .reg_off = HHI_MPLL_CNTL7,
-               .shift   = 0,
-               .width   = 14,
+static struct clk_regmap gxbb_fclk_div7 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 31,
        },
-       .sdm_en = {
-               .reg_off = HHI_MPLL_CNTL7,
-               .shift   = 15,
-               .width   = 1,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div7",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div7_div" },
+               .num_parents = 1,
        },
-       .n2 = {
-               .reg_off = HHI_MPLL_CNTL7,
-               .shift   = 16,
-               .width   = 9,
+};
+
+static struct clk_regmap gxbb_mpll_prediv = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_MPLL_CNTL5,
+               .shift = 12,
+               .width = 1,
        },
-       .en = {
-               .reg_off = HHI_MPLL_CNTL7,
-               .shift   = 14,
-               .width   = 1,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll_prediv",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
        },
-       .ssen = {
-               .reg_off = HHI_MPLL_CNTL,
-               .shift   = 25,
-               .width   = 1,
+};
+
+static struct clk_regmap gxbb_mpll0_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 0,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 15,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 16,
+                       .width   = 9,
+               },
+               .ssen = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 25,
+                       .width   = 1,
+               },
+               .lock = &meson_clk_lock,
        },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
-               .name = "mpll0",
+               .name = "mpll0_div",
                .ops = &meson_clk_mpll_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_names = (const char *[]){ "mpll_prediv" },
                .num_parents = 1,
        },
 };
 
-static struct meson_clk_mpll gxbb_mpll1 = {
-       .sdm = {
-               .reg_off = HHI_MPLL_CNTL8,
-               .shift   = 0,
-               .width   = 14,
-       },
-       .sdm_en = {
-               .reg_off = HHI_MPLL_CNTL8,
-               .shift   = 15,
-               .width   = 1,
+static struct clk_regmap gxbb_mpll0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL7,
+               .bit_idx = 14,
        },
-       .n2 = {
-               .reg_off = HHI_MPLL_CNTL8,
-               .shift   = 16,
-               .width   = 9,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll0",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpll0_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
        },
-       .en = {
-               .reg_off = HHI_MPLL_CNTL8,
-               .shift   = 14,
-               .width   = 1,
+};
+
+static struct clk_regmap gxbb_mpll1_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL_CNTL8,
+                       .shift   = 0,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL_CNTL8,
+                       .shift   = 15,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL_CNTL8,
+                       .shift   = 16,
+                       .width   = 9,
+               },
+               .lock = &meson_clk_lock,
        },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
-               .name = "mpll1",
+               .name = "mpll1_div",
                .ops = &meson_clk_mpll_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_names = (const char *[]){ "mpll_prediv" },
                .num_parents = 1,
        },
 };
 
-static struct meson_clk_mpll gxbb_mpll2 = {
-       .sdm = {
-               .reg_off = HHI_MPLL_CNTL9,
-               .shift   = 0,
-               .width   = 14,
-       },
-       .sdm_en = {
-               .reg_off = HHI_MPLL_CNTL9,
-               .shift   = 15,
-               .width   = 1,
+static struct clk_regmap gxbb_mpll1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL8,
+               .bit_idx = 14,
        },
-       .n2 = {
-               .reg_off = HHI_MPLL_CNTL9,
-               .shift   = 16,
-               .width   = 9,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpll1_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
        },
-       .en = {
-               .reg_off = HHI_MPLL_CNTL9,
-               .shift   = 14,
-               .width   = 1,
+};
+
+static struct clk_regmap gxbb_mpll2_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL_CNTL9,
+                       .shift   = 0,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL_CNTL9,
+                       .shift   = 15,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL_CNTL9,
+                       .shift   = 16,
+                       .width   = 9,
+               },
+               .lock = &meson_clk_lock,
        },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
-               .name = "mpll2",
+               .name = "mpll2_div",
                .ops = &meson_clk_mpll_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_names = (const char *[]){ "mpll_prediv" },
                .num_parents = 1,
        },
 };
 
-/*
- * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers
- * and should be modeled with their respective PLLs via the forthcoming
- * coordinated clock rates feature
- */
+static struct clk_regmap gxbb_mpll2 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL9,
+               .bit_idx = 14,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll2",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpll2_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
 
 static u32 mux_table_clk81[]   = { 0, 2, 3, 4, 5, 6, 7 };
 static const char * const clk81_parent_names[] = {
@@ -614,16 +758,16 @@ static const char * const clk81_parent_names[] = {
        "fclk_div3", "fclk_div5"
 };
 
-static struct clk_mux gxbb_mpeg_clk_sel = {
-       .reg = (void *)HHI_MPEG_CLK_CNTL,
-       .mask = 0x7,
-       .shift = 12,
-       .flags = CLK_MUX_READ_ONLY,
-       .table = mux_table_clk81,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mpeg_clk_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_MPEG_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 12,
+               .table = mux_table_clk81,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "mpeg_clk_sel",
-               .ops = &clk_mux_ro_ops,
+               .ops = &clk_regmap_mux_ro_ops,
                /*
                 * bits 14:12 selects from 8 possible parents:
                 * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
@@ -631,72 +775,75 @@ static struct clk_mux gxbb_mpeg_clk_sel = {
                 */
                .parent_names = clk81_parent_names,
                .num_parents = ARRAY_SIZE(clk81_parent_names),
-               .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
        },
 };
 
-static struct clk_divider gxbb_mpeg_clk_div = {
-       .reg = (void *)HHI_MPEG_CLK_CNTL,
-       .shift = 0,
-       .width = 7,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mpeg_clk_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_MPEG_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "mpeg_clk_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ro_ops,
                .parent_names = (const char *[]){ "mpeg_clk_sel" },
                .num_parents = 1,
-               .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
        },
 };
 
-/* the mother of dragons^W gates */
-static struct clk_gate gxbb_clk81 = {
-       .reg = (void *)HHI_MPEG_CLK_CNTL,
-       .bit_idx = 7,
-       .lock = &meson_clk_lock,
+/* the mother of dragons gates */
+static struct clk_regmap gxbb_clk81 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPEG_CLK_CNTL,
+               .bit_idx = 7,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "clk81",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "mpeg_clk_div" },
                .num_parents = 1,
-               .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
+               .flags = CLK_IS_CRITICAL,
        },
 };
 
-static struct clk_mux gxbb_sar_adc_clk_sel = {
-       .reg = (void *)HHI_SAR_CLK_CNTL,
-       .mask = 0x3,
-       .shift = 9,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sar_adc_clk_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SAR_CLK_CNTL,
+               .mask = 0x3,
+               .shift = 9,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "sar_adc_clk_sel",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                /* NOTE: The datasheet doesn't list the parents for bit 10 */
                .parent_names = (const char *[]){ "xtal", "clk81", },
                .num_parents = 2,
        },
 };
 
-static struct clk_divider gxbb_sar_adc_clk_div = {
-       .reg = (void *)HHI_SAR_CLK_CNTL,
-       .shift = 0,
-       .width = 8,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sar_adc_clk_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SAR_CLK_CNTL,
+               .shift = 0,
+               .width = 8,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "sar_adc_clk_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "sar_adc_clk_sel" },
                .num_parents = 1,
        },
 };
 
-static struct clk_gate gxbb_sar_adc_clk = {
-       .reg = (void *)HHI_SAR_CLK_CNTL,
-       .bit_idx = 8,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sar_adc_clk = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SAR_CLK_CNTL,
+               .bit_idx = 8,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "sar_adc_clk",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "sar_adc_clk_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
@@ -708,21 +855,20 @@ static struct clk_gate gxbb_sar_adc_clk = {
  * muxed by a glitch-free switch.
  */
 
-static u32 mux_table_mali_0_1[] = {0, 1, 2, 3, 4, 5, 6, 7};
 static const char * const gxbb_mali_0_1_parent_names[] = {
        "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7",
        "fclk_div4", "fclk_div3", "fclk_div5"
 };
 
-static struct clk_mux gxbb_mali_0_sel = {
-       .reg = (void *)HHI_MALI_CLK_CNTL,
-       .mask = 0x7,
-       .shift = 9,
-       .table = mux_table_mali_0_1,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mali_0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 9,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "mali_0_sel",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                /*
                 * bits 10:9 selects from 8 possible parents:
                 * xtal, gp0_pll, mpll2, mpll1, fclk_div7,
@@ -734,42 +880,44 @@ static struct clk_mux gxbb_mali_0_sel = {
        },
 };
 
-static struct clk_divider gxbb_mali_0_div = {
-       .reg = (void *)HHI_MALI_CLK_CNTL,
-       .shift = 0,
-       .width = 7,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mali_0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "mali_0_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "mali_0_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_NO_REPARENT,
        },
 };
 
-static struct clk_gate gxbb_mali_0 = {
-       .reg = (void *)HHI_MALI_CLK_CNTL,
-       .bit_idx = 8,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mali_0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .bit_idx = 8,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "mali_0",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "mali_0_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_mux gxbb_mali_1_sel = {
-       .reg = (void *)HHI_MALI_CLK_CNTL,
-       .mask = 0x7,
-       .shift = 25,
-       .table = mux_table_mali_0_1,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mali_1_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 25,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "mali_1_sel",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                /*
                 * bits 10:9 selects from 8 possible parents:
                 * xtal, gp0_pll, mpll2, mpll1, fclk_div7,
@@ -781,77 +929,79 @@ static struct clk_mux gxbb_mali_1_sel = {
        },
 };
 
-static struct clk_divider gxbb_mali_1_div = {
-       .reg = (void *)HHI_MALI_CLK_CNTL,
-       .shift = 16,
-       .width = 7,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mali_1_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .shift = 16,
+               .width = 7,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "mali_1_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "mali_1_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_NO_REPARENT,
        },
 };
 
-static struct clk_gate gxbb_mali_1 = {
-       .reg = (void *)HHI_MALI_CLK_CNTL,
-       .bit_idx = 24,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mali_1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .bit_idx = 24,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "mali_1",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "mali_1_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static u32 mux_table_mali[] = {0, 1};
 static const char * const gxbb_mali_parent_names[] = {
        "mali_0", "mali_1"
 };
 
-static struct clk_mux gxbb_mali = {
-       .reg = (void *)HHI_MALI_CLK_CNTL,
-       .mask = 1,
-       .shift = 31,
-       .table = mux_table_mali,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_mali = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .mask = 1,
+               .shift = 31,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "mali",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                .parent_names = gxbb_mali_parent_names,
                .num_parents = 2,
                .flags = CLK_SET_RATE_NO_REPARENT,
        },
 };
 
-static struct clk_mux gxbb_cts_amclk_sel = {
-       .reg = (void *) HHI_AUD_CLK_CNTL,
-       .mask = 0x3,
-       .shift = 9,
-       /* Default parent unknown (register reset value: 0) */
-       .table = (u32[]){ 1, 2, 3 },
-       .lock = &meson_clk_lock,
-               .hw.init = &(struct clk_init_data){
+static struct clk_regmap gxbb_cts_amclk_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_AUD_CLK_CNTL,
+               .mask = 0x3,
+               .shift = 9,
+               .table = (u32[]){ 1, 2, 3 },
+       },
+       .hw.init = &(struct clk_init_data){
                .name = "cts_amclk_sel",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
                .num_parents = 3,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct meson_clk_audio_divider gxbb_cts_amclk_div = {
-       .div = {
-               .reg_off = HHI_AUD_CLK_CNTL,
-               .shift   = 0,
-               .width   = 8,
+static struct clk_regmap gxbb_cts_amclk_div = {
+       .data = &(struct meson_clk_audio_div_data){
+               .div = {
+                       .reg_off = HHI_AUD_CLK_CNTL,
+                       .shift   = 0,
+                       .width   = 8,
+               },
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
        },
-       .flags = CLK_DIVIDER_ROUND_CLOSEST,
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "cts_amclk_div",
                .ops = &meson_clk_audio_divider_ops,
@@ -861,71 +1011,75 @@ static struct meson_clk_audio_divider gxbb_cts_amclk_div = {
        },
 };
 
-static struct clk_gate gxbb_cts_amclk = {
-       .reg = (void *) HHI_AUD_CLK_CNTL,
-       .bit_idx = 8,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_cts_amclk = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_AUD_CLK_CNTL,
+               .bit_idx = 8,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "cts_amclk",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "cts_amclk_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_mux gxbb_cts_mclk_i958_sel = {
-       .reg = (void *)HHI_AUD_CLK_CNTL2,
-       .mask = 0x3,
-       .shift = 25,
-       /* Default parent unknown (register reset value: 0) */
-       .table = (u32[]){ 1, 2, 3 },
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_cts_mclk_i958_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_AUD_CLK_CNTL2,
+               .mask = 0x3,
+               .shift = 25,
+               .table = (u32[]){ 1, 2, 3 },
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "cts_mclk_i958_sel",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
                .num_parents = 3,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_divider gxbb_cts_mclk_i958_div = {
-       .reg = (void *)HHI_AUD_CLK_CNTL2,
-       .shift = 16,
-       .width = 8,
-       .lock = &meson_clk_lock,
-       .flags = CLK_DIVIDER_ROUND_CLOSEST,
+static struct clk_regmap gxbb_cts_mclk_i958_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_AUD_CLK_CNTL2,
+               .shift = 16,
+               .width = 8,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "cts_mclk_i958_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "cts_mclk_i958_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_gate gxbb_cts_mclk_i958 = {
-       .reg = (void *)HHI_AUD_CLK_CNTL2,
-       .bit_idx = 24,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_cts_mclk_i958 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_AUD_CLK_CNTL2,
+               .bit_idx = 24,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "cts_mclk_i958",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "cts_mclk_i958_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_mux gxbb_cts_i958 = {
-       .reg = (void *)HHI_AUD_CLK_CNTL2,
-       .mask = 0x1,
-       .shift = 27,
-       .lock = &meson_clk_lock,
-               .hw.init = &(struct clk_init_data){
+static struct clk_regmap gxbb_cts_i958 = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_AUD_CLK_CNTL2,
+               .mask = 0x1,
+               .shift = 27,
+               },
+       .hw.init = &(struct clk_init_data){
                .name = "cts_i958",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                .parent_names = (const char *[]){ "cts_amclk", "cts_mclk_i958" },
                .num_parents = 2,
                /*
@@ -936,27 +1090,29 @@ static struct clk_mux gxbb_cts_i958 = {
        },
 };
 
-static struct clk_divider gxbb_32k_clk_div = {
-       .reg = (void *)HHI_32K_CLK_CNTL,
-       .shift = 0,
-       .width = 14,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_32k_clk_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_32K_CLK_CNTL,
+               .shift = 0,
+               .width = 14,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "32k_clk_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "32k_clk_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST,
        },
 };
 
-static struct clk_gate gxbb_32k_clk = {
-       .reg = (void *)HHI_32K_CLK_CNTL,
-       .bit_idx = 15,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_32k_clk = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_32K_CLK_CNTL,
+               .bit_idx = 15,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "32k_clk",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "32k_clk_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
@@ -967,14 +1123,15 @@ static const char * const gxbb_32k_clk_parent_names[] = {
        "xtal", "cts_slow_oscin", "fclk_div3", "fclk_div5"
 };
 
-static struct clk_mux gxbb_32k_clk_sel = {
-       .reg = (void *)HHI_32K_CLK_CNTL,
-       .mask = 0x3,
-       .shift = 16,
-       .lock = &meson_clk_lock,
-               .hw.init = &(struct clk_init_data){
+static struct clk_regmap gxbb_32k_clk_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_32K_CLK_CNTL,
+               .mask = 0x3,
+               .shift = 16,
+               },
+       .hw.init = &(struct clk_init_data){
                .name = "32k_clk_sel",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                .parent_names = gxbb_32k_clk_parent_names,
                .num_parents = 4,
                .flags = CLK_SET_RATE_PARENT,
@@ -993,42 +1150,45 @@ static const char * const gxbb_sd_emmc_clk0_parent_names[] = {
 };
 
 /* SDIO clock */
-static struct clk_mux gxbb_sd_emmc_a_clk0_sel = {
-       .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
-       .mask = 0x7,
-       .shift = 9,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sd_emmc_a_clk0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 9,
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_a_clk0_sel",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                .parent_names = gxbb_sd_emmc_clk0_parent_names,
                .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_divider gxbb_sd_emmc_a_clk0_div = {
-       .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
-       .shift = 0,
-       .width = 7,
-       .lock = &meson_clk_lock,
-       .flags = CLK_DIVIDER_ROUND_CLOSEST,
+static struct clk_regmap gxbb_sd_emmc_a_clk0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_a_clk0_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_gate gxbb_sd_emmc_a_clk0 = {
-       .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
-       .bit_idx = 7,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sd_emmc_a_clk0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .bit_idx = 7,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "sd_emmc_a_clk0",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
@@ -1036,42 +1196,45 @@ static struct clk_gate gxbb_sd_emmc_a_clk0 = {
 };
 
 /* SDcard clock */
-static struct clk_mux gxbb_sd_emmc_b_clk0_sel = {
-       .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
-       .mask = 0x7,
-       .shift = 25,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sd_emmc_b_clk0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 25,
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_b_clk0_sel",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                .parent_names = gxbb_sd_emmc_clk0_parent_names,
                .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_divider gxbb_sd_emmc_b_clk0_div = {
-       .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
-       .shift = 16,
-       .width = 7,
-       .lock = &meson_clk_lock,
-       .flags = CLK_DIVIDER_ROUND_CLOSEST,
+static struct clk_regmap gxbb_sd_emmc_b_clk0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .shift = 16,
+               .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_b_clk0_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_gate gxbb_sd_emmc_b_clk0 = {
-       .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
-       .bit_idx = 23,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sd_emmc_b_clk0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .bit_idx = 23,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "sd_emmc_b_clk0",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
@@ -1079,42 +1242,45 @@ static struct clk_gate gxbb_sd_emmc_b_clk0 = {
 };
 
 /* EMMC/NAND clock */
-static struct clk_mux gxbb_sd_emmc_c_clk0_sel = {
-       .reg = (void *)HHI_NAND_CLK_CNTL,
-       .mask = 0x7,
-       .shift = 9,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sd_emmc_c_clk0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_NAND_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 9,
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_c_clk0_sel",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                .parent_names = gxbb_sd_emmc_clk0_parent_names,
                .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_divider gxbb_sd_emmc_c_clk0_div = {
-       .reg = (void *)HHI_NAND_CLK_CNTL,
-       .shift = 0,
-       .width = 7,
-       .lock = &meson_clk_lock,
-       .flags = CLK_DIVIDER_ROUND_CLOSEST,
+static struct clk_regmap gxbb_sd_emmc_c_clk0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_NAND_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_c_clk0_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_gate gxbb_sd_emmc_c_clk0 = {
-       .reg = (void *)HHI_NAND_CLK_CNTL,
-       .bit_idx = 7,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_sd_emmc_c_clk0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_NAND_CLK_CNTL,
+               .bit_idx = 7,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "sd_emmc_c_clk0",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
@@ -1123,20 +1289,19 @@ static struct clk_gate gxbb_sd_emmc_c_clk0 = {
 
 /* VPU Clock */
 
-static u32 mux_table_vpu[] = {0, 1, 2, 3};
 static const char * const gxbb_vpu_parent_names[] = {
        "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
 };
 
-static struct clk_mux gxbb_vpu_0_sel = {
-       .reg = (void *)HHI_VPU_CLK_CNTL,
-       .mask = 0x3,
-       .shift = 9,
-       .lock = &meson_clk_lock,
-       .table = mux_table_vpu,
+static struct clk_regmap gxbb_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_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                /*
                 * bits 9:10 selects from 4 possible parents:
                 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
@@ -1147,42 +1312,44 @@ static struct clk_mux gxbb_vpu_0_sel = {
        },
 };
 
-static struct clk_divider gxbb_vpu_0_div = {
-       .reg = (void *)HHI_VPU_CLK_CNTL,
-       .shift = 0,
-       .width = 7,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_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_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "vpu_0_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_gate gxbb_vpu_0 = {
-       .reg = (void *)HHI_VPU_CLK_CNTL,
-       .bit_idx = 8,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_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_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "vpu_0_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
 };
 
-static struct clk_mux gxbb_vpu_1_sel = {
-       .reg = (void *)HHI_VPU_CLK_CNTL,
-       .mask = 0x3,
-       .shift = 25,
-       .lock = &meson_clk_lock,
-       .table = mux_table_vpu,
+static struct clk_regmap gxbb_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_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                /*
                 * bits 25:26 selects from 4 possible parents:
                 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
@@ -1193,41 +1360,44 @@ static struct clk_mux gxbb_vpu_1_sel = {
        },
 };
 
-static struct clk_divider gxbb_vpu_1_div = {
-       .reg = (void *)HHI_VPU_CLK_CNTL,
-       .shift = 16,
-       .width = 7,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_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_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "vpu_1_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_gate gxbb_vpu_1 = {
-       .reg = (void *)HHI_VPU_CLK_CNTL,
-       .bit_idx = 24,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_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_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "vpu_1_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
 };
 
-static struct clk_mux gxbb_vpu = {
-       .reg = (void *)HHI_VPU_CLK_CNTL,
-       .mask = 1,
-       .shift = 31,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_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_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                /*
                 * bit 31 selects from 2 possible parents:
                 * vpu_0 or vpu_1
@@ -1240,20 +1410,19 @@ static struct clk_mux gxbb_vpu = {
 
 /* VAPB Clock */
 
-static u32 mux_table_vapb[] = {0, 1, 2, 3};
 static const char * const gxbb_vapb_parent_names[] = {
        "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
 };
 
-static struct clk_mux gxbb_vapb_0_sel = {
-       .reg = (void *)HHI_VAPBCLK_CNTL,
-       .mask = 0x3,
-       .shift = 9,
-       .lock = &meson_clk_lock,
-       .table = mux_table_vapb,
+static struct clk_regmap gxbb_vapb_0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .mask = 0x3,
+               .shift = 9,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "vapb_0_sel",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                /*
                 * bits 9:10 selects from 4 possible parents:
                 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
@@ -1264,42 +1433,44 @@ static struct clk_mux gxbb_vapb_0_sel = {
        },
 };
 
-static struct clk_divider gxbb_vapb_0_div = {
-       .reg = (void *)HHI_VAPBCLK_CNTL,
-       .shift = 0,
-       .width = 7,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vapb_0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "vapb_0_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "vapb_0_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_gate gxbb_vapb_0 = {
-       .reg = (void *)HHI_VAPBCLK_CNTL,
-       .bit_idx = 8,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vapb_0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .bit_idx = 8,
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "vapb_0",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "vapb_0_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
 };
 
-static struct clk_mux gxbb_vapb_1_sel = {
-       .reg = (void *)HHI_VAPBCLK_CNTL,
-       .mask = 0x3,
-       .shift = 25,
-       .lock = &meson_clk_lock,
-       .table = mux_table_vapb,
+static struct clk_regmap gxbb_vapb_1_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .mask = 0x3,
+               .shift = 25,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "vapb_1_sel",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                /*
                 * bits 25:26 selects from 4 possible parents:
                 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
@@ -1310,41 +1481,44 @@ static struct clk_mux gxbb_vapb_1_sel = {
        },
 };
 
-static struct clk_divider gxbb_vapb_1_div = {
-       .reg = (void *)HHI_VAPBCLK_CNTL,
-       .shift = 16,
-       .width = 7,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vapb_1_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .shift = 16,
+               .width = 7,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "vapb_1_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ops,
                .parent_names = (const char *[]){ "vapb_1_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static struct clk_gate gxbb_vapb_1 = {
-       .reg = (void *)HHI_VAPBCLK_CNTL,
-       .bit_idx = 24,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vapb_1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .bit_idx = 24,
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "vapb_1",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "vapb_1_div" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
 };
 
-static struct clk_mux gxbb_vapb_sel = {
-       .reg = (void *)HHI_VAPBCLK_CNTL,
-       .mask = 1,
-       .shift = 31,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vapb_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .mask = 1,
+               .shift = 31,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "vapb_sel",
-               .ops = &clk_mux_ops,
+               .ops = &clk_regmap_mux_ops,
                /*
                 * bit 31 selects from 2 possible parents:
                 * vapb_0 or vapb_1
@@ -1355,13 +1529,14 @@ static struct clk_mux gxbb_vapb_sel = {
        },
 };
 
-static struct clk_gate gxbb_vapb = {
-       .reg = (void *)HHI_VAPBCLK_CNTL,
-       .bit_idx = 30,
-       .lock = &meson_clk_lock,
+static struct clk_regmap gxbb_vapb = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .bit_idx = 30,
+       },
        .hw.init = &(struct clk_init_data) {
                .name = "vapb",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "vapb_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
@@ -1601,6 +1776,16 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
                [CLKID_VAPB_1]              = &gxbb_vapb_1.hw,
                [CLKID_VAPB_SEL]            = &gxbb_vapb_sel.hw,
                [CLKID_VAPB]                = &gxbb_vapb.hw,
+               [CLKID_HDMI_PLL_PRE_MULT]   = &gxbb_hdmi_pll_pre_mult.hw,
+               [CLKID_MPLL0_DIV]           = &gxbb_mpll0_div.hw,
+               [CLKID_MPLL1_DIV]           = &gxbb_mpll1_div.hw,
+               [CLKID_MPLL2_DIV]           = &gxbb_mpll2_div.hw,
+               [CLKID_MPLL_PREDIV]         = &gxbb_mpll_prediv.hw,
+               [CLKID_FCLK_DIV2_DIV]       = &gxbb_fclk_div2_div.hw,
+               [CLKID_FCLK_DIV3_DIV]       = &gxbb_fclk_div3_div.hw,
+               [CLKID_FCLK_DIV4_DIV]       = &gxbb_fclk_div4_div.hw,
+               [CLKID_FCLK_DIV5_DIV]       = &gxbb_fclk_div5_div.hw,
+               [CLKID_FCLK_DIV7_DIV]       = &gxbb_fclk_div7_div.hw,
                [NR_CLKS]                   = NULL,
        },
        .num = NR_CLKS,
@@ -1609,7 +1794,7 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
 static struct clk_hw_onecell_data gxl_hw_onecell_data = {
        .hws = {
                [CLKID_SYS_PLL]             = &gxbb_sys_pll.hw,
-               [CLKID_HDMI_PLL]            = &gxbb_hdmi_pll.hw,
+               [CLKID_HDMI_PLL]            = &gxl_hdmi_pll.hw,
                [CLKID_FIXED_PLL]           = &gxbb_fixed_pll.hw,
                [CLKID_FCLK_DIV2]           = &gxbb_fclk_div2.hw,
                [CLKID_FCLK_DIV3]           = &gxbb_fclk_div3.hw,
@@ -1748,34 +1933,31 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
                [CLKID_VAPB_1]              = &gxbb_vapb_1.hw,
                [CLKID_VAPB_SEL]            = &gxbb_vapb_sel.hw,
                [CLKID_VAPB]                = &gxbb_vapb.hw,
+               [CLKID_MPLL0_DIV]           = &gxbb_mpll0_div.hw,
+               [CLKID_MPLL1_DIV]           = &gxbb_mpll1_div.hw,
+               [CLKID_MPLL2_DIV]           = &gxbb_mpll2_div.hw,
+               [CLKID_MPLL_PREDIV]         = &gxbb_mpll_prediv.hw,
+               [CLKID_FCLK_DIV2_DIV]       = &gxbb_fclk_div2_div.hw,
+               [CLKID_FCLK_DIV3_DIV]       = &gxbb_fclk_div3_div.hw,
+               [CLKID_FCLK_DIV4_DIV]       = &gxbb_fclk_div4_div.hw,
+               [CLKID_FCLK_DIV5_DIV]       = &gxbb_fclk_div5_div.hw,
+               [CLKID_FCLK_DIV7_DIV]       = &gxbb_fclk_div7_div.hw,
                [NR_CLKS]                   = NULL,
        },
        .num = NR_CLKS,
 };
 
-/* Convenience tables to populate base addresses in .probe */
-
-static struct meson_clk_pll *const gxbb_clk_plls[] = {
-       &gxbb_fixed_pll,
-       &gxbb_hdmi_pll,
-       &gxbb_sys_pll,
+static struct clk_regmap *const gxbb_clk_regmaps[] = {
        &gxbb_gp0_pll,
-};
-
-static struct meson_clk_pll *const gxl_clk_plls[] = {
-       &gxbb_fixed_pll,
        &gxbb_hdmi_pll,
-       &gxbb_sys_pll,
-       &gxl_gp0_pll,
 };
 
-static struct meson_clk_mpll *const gxbb_clk_mplls[] = {
-       &gxbb_mpll0,
-       &gxbb_mpll1,
-       &gxbb_mpll2,
+static struct clk_regmap *const gxl_clk_regmaps[] = {
+       &gxl_gp0_pll,
+       &gxl_hdmi_pll,
 };
 
-static struct clk_gate *const gxbb_clk_gates[] = {
+static struct clk_regmap *const gx_clk_regmaps[] = {
        &gxbb_clk81,
        &gxbb_ddr,
        &gxbb_dos,
@@ -1872,9 +2054,19 @@ static struct clk_gate *const gxbb_clk_gates[] = {
        &gxbb_vapb_0,
        &gxbb_vapb_1,
        &gxbb_vapb,
-};
-
-static struct clk_mux *const gxbb_clk_muxes[] = {
+       &gxbb_mpeg_clk_div,
+       &gxbb_sar_adc_clk_div,
+       &gxbb_mali_0_div,
+       &gxbb_mali_1_div,
+       &gxbb_cts_mclk_i958_div,
+       &gxbb_32k_clk_div,
+       &gxbb_sd_emmc_a_clk0_div,
+       &gxbb_sd_emmc_b_clk0_div,
+       &gxbb_sd_emmc_c_clk0_div,
+       &gxbb_vpu_0_div,
+       &gxbb_vpu_1_div,
+       &gxbb_vapb_0_div,
+       &gxbb_vapb_1_div,
        &gxbb_mpeg_clk_sel,
        &gxbb_sar_adc_clk_sel,
        &gxbb_mali_0_sel,
@@ -1893,73 +2085,38 @@ static struct clk_mux *const gxbb_clk_muxes[] = {
        &gxbb_vapb_0_sel,
        &gxbb_vapb_1_sel,
        &gxbb_vapb_sel,
-};
-
-static struct clk_divider *const gxbb_clk_dividers[] = {
-       &gxbb_mpeg_clk_div,
-       &gxbb_sar_adc_clk_div,
-       &gxbb_mali_0_div,
-       &gxbb_mali_1_div,
-       &gxbb_cts_mclk_i958_div,
-       &gxbb_32k_clk_div,
-       &gxbb_sd_emmc_a_clk0_div,
-       &gxbb_sd_emmc_b_clk0_div,
-       &gxbb_sd_emmc_c_clk0_div,
-       &gxbb_vpu_0_div,
-       &gxbb_vpu_1_div,
-       &gxbb_vapb_0_div,
-       &gxbb_vapb_1_div,
-};
-
-static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = {
+       &gxbb_mpll0,
+       &gxbb_mpll1,
+       &gxbb_mpll2,
+       &gxbb_mpll0_div,
+       &gxbb_mpll1_div,
+       &gxbb_mpll2_div,
        &gxbb_cts_amclk_div,
+       &gxbb_fixed_pll,
+       &gxbb_sys_pll,
+       &gxbb_mpll_prediv,
+       &gxbb_fclk_div2,
+       &gxbb_fclk_div3,
+       &gxbb_fclk_div4,
+       &gxbb_fclk_div5,
+       &gxbb_fclk_div7,
 };
 
 struct clkc_data {
-       struct clk_gate *const *clk_gates;
-       unsigned int clk_gates_count;
-       struct meson_clk_mpll *const *clk_mplls;
-       unsigned int clk_mplls_count;
-       struct meson_clk_pll *const *clk_plls;
-       unsigned int clk_plls_count;
-       struct clk_mux *const *clk_muxes;
-       unsigned int clk_muxes_count;
-       struct clk_divider *const *clk_dividers;
-       unsigned int clk_dividers_count;
-       struct meson_clk_audio_divider *const *clk_audio_dividers;
-       unsigned int clk_audio_dividers_count;
+       struct clk_regmap *const *regmap_clks;
+       unsigned int regmap_clks_count;
        struct clk_hw_onecell_data *hw_onecell_data;
 };
 
 static const struct clkc_data gxbb_clkc_data = {
-       .clk_gates = gxbb_clk_gates,
-       .clk_gates_count = ARRAY_SIZE(gxbb_clk_gates),
-       .clk_mplls = gxbb_clk_mplls,
-       .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls),
-       .clk_plls = gxbb_clk_plls,
-       .clk_plls_count = ARRAY_SIZE(gxbb_clk_plls),
-       .clk_muxes = gxbb_clk_muxes,
-       .clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes),
-       .clk_dividers = gxbb_clk_dividers,
-       .clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
-       .clk_audio_dividers = gxbb_audio_dividers,
-       .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
+       .regmap_clks = gxbb_clk_regmaps,
+       .regmap_clks_count = ARRAY_SIZE(gxbb_clk_regmaps),
        .hw_onecell_data = &gxbb_hw_onecell_data,
 };
 
 static const struct clkc_data gxl_clkc_data = {
-       .clk_gates = gxbb_clk_gates,
-       .clk_gates_count = ARRAY_SIZE(gxbb_clk_gates),
-       .clk_mplls = gxbb_clk_mplls,
-       .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls),
-       .clk_plls = gxl_clk_plls,
-       .clk_plls_count = ARRAY_SIZE(gxl_clk_plls),
-       .clk_muxes = gxbb_clk_muxes,
-       .clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes),
-       .clk_dividers = gxbb_clk_dividers,
-       .clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
-       .clk_audio_dividers = gxbb_audio_dividers,
-       .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
+       .regmap_clks = gxl_clk_regmaps,
+       .regmap_clks_count = ARRAY_SIZE(gxl_clk_regmaps),
        .hw_onecell_data = &gxl_hw_onecell_data,
 };
 
@@ -1969,71 +2126,79 @@ static const struct of_device_id clkc_match_table[] = {
        {},
 };
 
+static const struct regmap_config clkc_regmap_config = {
+       .reg_bits       = 32,
+       .val_bits       = 32,
+       .reg_stride     = 4,
+};
+
 static int gxbb_clkc_probe(struct platform_device *pdev)
 {
        const struct clkc_data *clkc_data;
+       struct resource *res;
        void __iomem *clk_base;
-       int ret, clkid, i;
+       struct regmap *map;
+       int ret, i;
        struct device *dev = &pdev->dev;
 
-       clkc_data = of_device_get_match_data(&pdev->dev);
+       clkc_data = of_device_get_match_data(dev);
        if (!clkc_data)
                return -EINVAL;
 
-       /*  Generic clocks and PLLs */
-       clk_base = of_iomap(dev->of_node, 0);
-       if (!clk_base) {
-               pr_err("%s: Unable to map clk base\n", __func__);
-               return -ENXIO;
-       }
-
-       /* Populate base address for PLLs */
-       for (i = 0; i < clkc_data->clk_plls_count; i++)
-               clkc_data->clk_plls[i]->base = clk_base;
-
-       /* Populate base address for MPLLs */
-       for (i = 0; i < clkc_data->clk_mplls_count; i++)
-               clkc_data->clk_mplls[i]->base = clk_base;
+       /* Get the hhi system controller node if available */
+       map = syscon_node_to_regmap(of_get_parent(dev->of_node));
+       if (IS_ERR(map)) {
+               dev_err(dev,
+                       "failed to get HHI regmap - Trying obsolete regs\n");
 
-       /* Populate base address for gates */
-       for (i = 0; i < clkc_data->clk_gates_count; i++)
-               clkc_data->clk_gates[i]->reg = clk_base +
-                       (u64)clkc_data->clk_gates[i]->reg;
-
-       /* Populate base address for muxes */
-       for (i = 0; i < clkc_data->clk_muxes_count; i++)
-               clkc_data->clk_muxes[i]->reg = clk_base +
-                       (u64)clkc_data->clk_muxes[i]->reg;
+               /*
+                * FIXME: HHI registers should be accessed through
+                * the appropriate system controller. This is required because
+                * there is more than just clocks in this register space
+                *
+                * This fallback method is only provided temporarily until
+                * all the platform DTs are properly using the syscon node
+                */
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+               if (!res)
+                       return -EINVAL;
+
+               clk_base = devm_ioremap(dev, res->start, resource_size(res));
+               if (!clk_base) {
+                       dev_err(dev, "Unable to map clk base\n");
+                       return -ENXIO;
+               }
+
+               map = devm_regmap_init_mmio(dev, clk_base,
+                                           &clkc_regmap_config);
+               if (IS_ERR(map))
+                       return PTR_ERR(map);
+       }
 
-       /* Populate base address for dividers */
-       for (i = 0; i < clkc_data->clk_dividers_count; i++)
-               clkc_data->clk_dividers[i]->reg = clk_base +
-                       (u64)clkc_data->clk_dividers[i]->reg;
+       /* Populate regmap for the common regmap backed clocks */
+       for (i = 0; i < ARRAY_SIZE(gx_clk_regmaps); i++)
+               gx_clk_regmaps[i]->map = map;
 
-       /* Populate base address for the audio dividers */
-       for (i = 0; i < clkc_data->clk_audio_dividers_count; i++)
-               clkc_data->clk_audio_dividers[i]->base = clk_base;
+       /* Populate regmap for soc specific clocks */
+       for (i = 0; i < clkc_data->regmap_clks_count; i++)
+               clkc_data->regmap_clks[i]->map = map;
 
-       /*
-        * register all clks
-        */
-       for (clkid = 0; clkid < clkc_data->hw_onecell_data->num; clkid++) {
+       /* Register all clks */
+       for (i = 0; i < clkc_data->hw_onecell_data->num; i++) {
                /* array might be sparse */
-               if (!clkc_data->hw_onecell_data->hws[clkid])
+               if (!clkc_data->hw_onecell_data->hws[i])
                        continue;
 
                ret = devm_clk_hw_register(dev,
-                                       clkc_data->hw_onecell_data->hws[clkid]);
-               if (ret)
-                       goto iounmap;
+                                          clkc_data->hw_onecell_data->hws[i]);
+               if (ret) {
+                       dev_err(dev, "Clock registration failed\n");
+                       return ret;
+               }
        }
 
-       return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
-                       clkc_data->hw_onecell_data);
-
-iounmap:
-       iounmap(clk_base);
-       return ret;
+       return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+                                          clkc_data->hw_onecell_data);
 }
 
 static struct platform_driver gxbb_driver = {
index aee6fbba20043275cd25adce6b2548febcbea2b9..9febf3f03739eba72870397b4238a25f15dae5f7 100644 (file)
 #define CLKID_VPU_1_DIV                  130
 #define CLKID_VAPB_0_DIV         134
 #define CLKID_VAPB_1_DIV         137
-
-#define NR_CLKS                          141
+#define CLKID_HDMI_PLL_PRE_MULT          141
+#define CLKID_MPLL0_DIV                  142
+#define CLKID_MPLL1_DIV                  143
+#define CLKID_MPLL2_DIV                  144
+#define CLKID_MPLL_PREDIV        145
+#define CLKID_FCLK_DIV2_DIV      146
+#define CLKID_FCLK_DIV3_DIV      147
+#define CLKID_FCLK_DIV4_DIV      148
+#define CLKID_FCLK_DIV5_DIV      149
+#define CLKID_FCLK_DIV7_DIV      150
+
+#define NR_CLKS                          151
 
 /* include the CLKIDs that have been made part of the DT binding */
 #include <dt-bindings/clock/gxbb-clkc.h>
index 3ffea80c1308a68ec8925ef4e5af63017468aaf9..cc2992493e0b6cd1ba6ad53154f2476454eb2a08 100644 (file)
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/init.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/reset-controller.h>
 #include <linux/slab.h>
-#include <linux/init.h>
+#include <linux/regmap.h>
 
 #include "clkc.h"
 #include "meson8b.h"
+#include "clk-regmap.h"
 
 static DEFINE_SPINLOCK(meson_clk_lock);
 
@@ -97,20 +99,6 @@ static const struct pll_rate_table sys_pll_rate_table[] = {
        { /* sentinel */ },
 };
 
-static const struct clk_div_table cpu_div_table[] = {
-       { .val = 1, .div = 1 },
-       { .val = 2, .div = 2 },
-       { .val = 3, .div = 3 },
-       { .val = 2, .div = 4 },
-       { .val = 3, .div = 6 },
-       { .val = 4, .div = 8 },
-       { .val = 5, .div = 10 },
-       { .val = 6, .div = 12 },
-       { .val = 7, .div = 14 },
-       { .val = 8, .div = 16 },
-       { /* sentinel */ },
-};
-
 static struct clk_fixed_rate meson8b_xtal = {
        .fixed_rate = 24000000,
        .hw.init = &(struct clk_init_data){
@@ -120,23 +108,39 @@ static struct clk_fixed_rate meson8b_xtal = {
        },
 };
 
-static struct meson_clk_pll meson8b_fixed_pll = {
-       .m = {
-               .reg_off = HHI_MPLL_CNTL,
-               .shift   = 0,
-               .width   = 9,
-       },
-       .n = {
-               .reg_off = HHI_MPLL_CNTL,
-               .shift   = 9,
-               .width   = 5,
-       },
-       .od = {
-               .reg_off = HHI_MPLL_CNTL,
-               .shift   = 16,
-               .width   = 2,
+static struct clk_regmap meson8b_fixed_pll = {
+       .data = &(struct meson_clk_pll_data){
+               .m = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .od = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 16,
+                       .width   = 2,
+               },
+               .frac = {
+                       .reg_off = HHI_MPLL_CNTL2,
+                       .shift   = 0,
+                       .width   = 12,
+               },
+               .l = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 29,
+                       .width   = 1,
+               },
        },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "fixed_pll",
                .ops = &meson_clk_pll_ro_ops,
@@ -146,23 +150,34 @@ static struct meson_clk_pll meson8b_fixed_pll = {
        },
 };
 
-static struct meson_clk_pll meson8b_vid_pll = {
-       .m = {
-               .reg_off = HHI_VID_PLL_CNTL,
-               .shift   = 0,
-               .width   = 9,
+static struct clk_regmap meson8b_vid_pll = {
+       .data = &(struct meson_clk_pll_data){
+               .m = {
+                       .reg_off = HHI_VID_PLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = HHI_VID_PLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .od = {
+                       .reg_off = HHI_VID_PLL_CNTL,
+                       .shift   = 16,
+                       .width   = 2,
+               },
+               .l = {
+                       .reg_off = HHI_VID_PLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_VID_PLL_CNTL,
+                       .shift   = 29,
+                       .width   = 1,
+               },
        },
-       .n = {
-               .reg_off = HHI_VID_PLL_CNTL,
-               .shift   = 9,
-               .width   = 5,
-       },
-       .od = {
-               .reg_off = HHI_VID_PLL_CNTL,
-               .shift   = 16,
-               .width   = 2,
-       },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "vid_pll",
                .ops = &meson_clk_pll_ro_ops,
@@ -172,213 +187,317 @@ static struct meson_clk_pll meson8b_vid_pll = {
        },
 };
 
-static struct meson_clk_pll meson8b_sys_pll = {
-       .m = {
-               .reg_off = HHI_SYS_PLL_CNTL,
-               .shift   = 0,
-               .width   = 9,
-       },
-       .n = {
-               .reg_off = HHI_SYS_PLL_CNTL,
-               .shift   = 9,
-               .width   = 5,
+static struct clk_regmap meson8b_sys_pll = {
+       .data = &(struct meson_clk_pll_data){
+               .m = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 0,
+                       .width   = 9,
+               },
+               .n = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 9,
+                       .width   = 5,
+               },
+               .od = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 16,
+                       .width   = 2,
+               },
+               .l = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_SYS_PLL_CNTL,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+               .table = sys_pll_rate_table,
        },
-       .od = {
-               .reg_off = HHI_SYS_PLL_CNTL,
-               .shift   = 16,
-               .width   = 2,
-       },
-       .rate_table = sys_pll_rate_table,
-       .rate_count = ARRAY_SIZE(sys_pll_rate_table),
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "sys_pll",
-               .ops = &meson_clk_pll_ops,
+               .ops = &meson_clk_pll_ro_ops,
                .parent_names = (const char *[]){ "xtal" },
                .num_parents = 1,
                .flags = CLK_GET_RATE_NOCACHE,
        },
 };
 
-static struct clk_fixed_factor meson8b_fclk_div2 = {
+static struct clk_fixed_factor meson8b_fclk_div2_div = {
        .mult = 1,
        .div = 2,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div2",
+               .name = "fclk_div2_div",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct clk_fixed_factor meson8b_fclk_div3 = {
+static struct clk_regmap meson8b_fclk_div2 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 27,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div2",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div2_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor meson8b_fclk_div3_div = {
        .mult = 1,
        .div = 3,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div3",
+               .name = "fclk_div_div3",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct clk_fixed_factor meson8b_fclk_div4 = {
+static struct clk_regmap meson8b_fclk_div3 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 28,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div3",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div3_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor meson8b_fclk_div4_div = {
        .mult = 1,
        .div = 4,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div4",
+               .name = "fclk_div4_div",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct clk_fixed_factor meson8b_fclk_div5 = {
+static struct clk_regmap meson8b_fclk_div4 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 29,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div4",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div4_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor meson8b_fclk_div5_div = {
        .mult = 1,
        .div = 5,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div5",
+               .name = "fclk_div5_div",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct clk_fixed_factor meson8b_fclk_div7 = {
+static struct clk_regmap meson8b_fclk_div5 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 30,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div5",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div5_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor meson8b_fclk_div7_div = {
        .mult = 1,
        .div = 7,
        .hw.init = &(struct clk_init_data){
-               .name = "fclk_div7",
+               .name = "fclk_div7_div",
                .ops = &clk_fixed_factor_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
 };
 
-static struct meson_clk_mpll meson8b_mpll0 = {
-       .sdm = {
-               .reg_off = HHI_MPLL_CNTL7,
-               .shift   = 0,
-               .width   = 14,
+static struct clk_regmap meson8b_fclk_div7 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL6,
+               .bit_idx = 31,
        },
-       .sdm_en = {
-               .reg_off = HHI_MPLL_CNTL7,
-               .shift   = 15,
-               .width   = 1,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div7",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div7_div" },
+               .num_parents = 1,
        },
-       .n2 = {
-               .reg_off = HHI_MPLL_CNTL7,
-               .shift   = 16,
-               .width   = 9,
+};
+
+static struct clk_regmap meson8b_mpll_prediv = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_MPLL_CNTL5,
+               .shift = 12,
+               .width = 1,
        },
-       .en = {
-               .reg_off = HHI_MPLL_CNTL7,
-               .shift   = 14,
-               .width   = 1,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll_prediv",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
        },
-       .ssen = {
-               .reg_off = HHI_MPLL_CNTL,
-               .shift   = 25,
-               .width   = 1,
+};
+
+static struct clk_regmap meson8b_mpll0_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 0,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 15,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 16,
+                       .width   = 9,
+               },
+               .ssen = {
+                       .reg_off = HHI_MPLL_CNTL,
+                       .shift   = 25,
+                       .width   = 1,
+               },
+               .lock = &meson_clk_lock,
        },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
-               .name = "mpll0",
+               .name = "mpll0_div",
                .ops = &meson_clk_mpll_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_names = (const char *[]){ "mpll_prediv" },
                .num_parents = 1,
        },
 };
 
-static struct meson_clk_mpll meson8b_mpll1 = {
-       .sdm = {
-               .reg_off = HHI_MPLL_CNTL8,
-               .shift   = 0,
-               .width   = 14,
+static struct clk_regmap meson8b_mpll0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL7,
+               .bit_idx = 14,
        },
-       .sdm_en = {
-               .reg_off = HHI_MPLL_CNTL8,
-               .shift   = 15,
-               .width   = 1,
-       },
-       .n2 = {
-               .reg_off = HHI_MPLL_CNTL8,
-               .shift   = 16,
-               .width   = 9,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll0",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpll0_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
        },
-       .en = {
-               .reg_off = HHI_MPLL_CNTL8,
-               .shift   = 14,
-               .width   = 1,
+};
+
+static struct clk_regmap meson8b_mpll1_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL_CNTL8,
+                       .shift   = 0,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL_CNTL8,
+                       .shift   = 15,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL_CNTL8,
+                       .shift   = 16,
+                       .width   = 9,
+               },
+               .lock = &meson_clk_lock,
        },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
-               .name = "mpll1",
+               .name = "mpll1_div",
                .ops = &meson_clk_mpll_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_names = (const char *[]){ "mpll_prediv" },
                .num_parents = 1,
        },
 };
 
-static struct meson_clk_mpll meson8b_mpll2 = {
-       .sdm = {
-               .reg_off = HHI_MPLL_CNTL9,
-               .shift   = 0,
-               .width   = 14,
-       },
-       .sdm_en = {
-               .reg_off = HHI_MPLL_CNTL9,
-               .shift   = 15,
-               .width   = 1,
+static struct clk_regmap meson8b_mpll1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL8,
+               .bit_idx = 14,
        },
-       .n2 = {
-               .reg_off = HHI_MPLL_CNTL9,
-               .shift   = 16,
-               .width   = 9,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpll1_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
        },
-       .en = {
-               .reg_off = HHI_MPLL_CNTL9,
-               .shift   = 14,
-               .width   = 1,
+};
+
+static struct clk_regmap meson8b_mpll2_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL_CNTL9,
+                       .shift   = 0,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL_CNTL9,
+                       .shift   = 15,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL_CNTL9,
+                       .shift   = 16,
+                       .width   = 9,
+               },
+               .lock = &meson_clk_lock,
        },
-       .lock = &meson_clk_lock,
        .hw.init = &(struct clk_init_data){
-               .name = "mpll2",
+               .name = "mpll2_div",
                .ops = &meson_clk_mpll_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_names = (const char *[]){ "mpll_prediv" },
                .num_parents = 1,
        },
 };
 
-/*
- * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL
- * post-dividers and should be modeled with their respective PLLs via the
- * forthcoming coordinated clock rates feature
- */
-static struct meson_clk_cpu meson8b_cpu_clk = {
-       .reg_off = HHI_SYS_CPU_CLK_CNTL1,
-       .div_table = cpu_div_table,
-       .clk_nb.notifier_call = meson_clk_cpu_notifier_cb,
+static struct clk_regmap meson8b_mpll2 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL9,
+               .bit_idx = 14,
+       },
        .hw.init = &(struct clk_init_data){
-               .name = "cpu_clk",
-               .ops = &meson_clk_cpu_ops,
-               .parent_names = (const char *[]){ "sys_pll" },
+               .name = "mpll2",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpll2_div" },
                .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
        },
 };
 
 static u32 mux_table_clk81[]   = { 6, 5, 7 };
-
-struct clk_mux meson8b_mpeg_clk_sel = {
-       .reg = (void *)HHI_MPEG_CLK_CNTL,
-       .mask = 0x7,
-       .shift = 12,
-       .flags = CLK_MUX_READ_ONLY,
-       .table = mux_table_clk81,
-       .lock = &meson_clk_lock,
+static struct clk_regmap meson8b_mpeg_clk_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_MPEG_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 12,
+               .table = mux_table_clk81,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "mpeg_clk_sel",
-               .ops = &clk_mux_ro_ops,
+               .ops = &clk_regmap_mux_ro_ops,
                /*
                 * FIXME bits 14:12 selects from 8 possible parents:
                 * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
@@ -387,34 +506,136 @@ struct clk_mux meson8b_mpeg_clk_sel = {
                .parent_names = (const char *[]){ "fclk_div3", "fclk_div4",
                        "fclk_div5" },
                .num_parents = 3,
-               .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
        },
 };
 
-struct clk_divider meson8b_mpeg_clk_div = {
-       .reg = (void *)HHI_MPEG_CLK_CNTL,
-       .shift = 0,
-       .width = 7,
-       .lock = &meson_clk_lock,
+static struct clk_regmap meson8b_mpeg_clk_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_MPEG_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "mpeg_clk_div",
-               .ops = &clk_divider_ops,
+               .ops = &clk_regmap_divider_ro_ops,
                .parent_names = (const char *[]){ "mpeg_clk_sel" },
                .num_parents = 1,
-               .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
        },
 };
 
-struct clk_gate meson8b_clk81 = {
-       .reg = (void *)HHI_MPEG_CLK_CNTL,
-       .bit_idx = 7,
-       .lock = &meson_clk_lock,
+static struct clk_regmap meson8b_clk81 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPEG_CLK_CNTL,
+               .bit_idx = 7,
+       },
        .hw.init = &(struct clk_init_data){
                .name = "clk81",
-               .ops = &clk_gate_ops,
+               .ops = &clk_regmap_gate_ops,
                .parent_names = (const char *[]){ "mpeg_clk_div" },
                .num_parents = 1,
-               .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
+               .flags = CLK_IS_CRITICAL,
+       },
+};
+
+static struct clk_regmap meson8b_cpu_in_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x1,
+               .shift = 0,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_in_sel",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ "xtal", "sys_pll" },
+               .num_parents = 2,
+               .flags = (CLK_SET_RATE_PARENT |
+                         CLK_SET_RATE_NO_REPARENT),
+       },
+};
+
+static struct clk_fixed_factor meson8b_cpu_div2 = {
+       .mult = 1,
+       .div = 2,
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_div2",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "cpu_in_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_fixed_factor meson8b_cpu_div3 = {
+       .mult = 1,
+       .div = 3,
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_div3",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "cpu_in_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static const struct clk_div_table cpu_scale_table[] = {
+       { .val = 2, .div = 4 },
+       { .val = 3, .div = 6 },
+       { .val = 4, .div = 8 },
+       { .val = 5, .div = 10 },
+       { .val = 6, .div = 12 },
+       { .val = 7, .div = 14 },
+       { .val = 8, .div = 16 },
+       { /* sentinel */ },
+};
+
+static struct clk_regmap meson8b_cpu_scale_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset =  HHI_SYS_CPU_CLK_CNTL1,
+               .shift = 20,
+               .width = 9,
+               .table = cpu_scale_table,
+               .flags = CLK_DIVIDER_ALLOW_ZERO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_scale_div",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "cpu_in_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_cpu_scale_out_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x3,
+               .shift = 2,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_scale_out_sel",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]) { "cpu_in_sel",
+                                                  "cpu_div2",
+                                                  "cpu_div3",
+                                                  "cpu_scale_div" },
+               .num_parents = 4,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_cpu_clk = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x1,
+               .shift = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ "xtal", "cpu_out_sel" },
+               .num_parents = 2,
+               .flags = (CLK_SET_RATE_PARENT |
+                         CLK_SET_RATE_NO_REPARENT),
        },
 };
 
@@ -599,24 +820,26 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
                [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_DIV2]            = &meson8b_cpu_div2.hw,
+               [CLKID_CPU_DIV3]            = &meson8b_cpu_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,
                [CLK_NR_CLKS]               = NULL,
        },
        .num = CLK_NR_CLKS,
 };
 
-static struct meson_clk_pll *const meson8b_clk_plls[] = {
-       &meson8b_fixed_pll,
-       &meson8b_vid_pll,
-       &meson8b_sys_pll,
-};
-
-static struct meson_clk_mpll *const meson8b_clk_mplls[] = {
-       &meson8b_mpll0,
-       &meson8b_mpll1,
-       &meson8b_mpll2,
-};
-
-static struct clk_gate *const meson8b_clk_gates[] = {
+static struct clk_regmap *const meson8b_clk_regmaps[] = {
        &meson8b_clk81,
        &meson8b_ddr,
        &meson8b_dos,
@@ -695,14 +918,27 @@ static struct clk_gate *const meson8b_clk_gates[] = {
        &meson8b_ao_ahb_sram,
        &meson8b_ao_ahb_bus,
        &meson8b_ao_iface,
-};
-
-static struct clk_mux *const meson8b_clk_muxes[] = {
-       &meson8b_mpeg_clk_sel,
-};
-
-static struct clk_divider *const meson8b_clk_dividers[] = {
        &meson8b_mpeg_clk_div,
+       &meson8b_mpeg_clk_sel,
+       &meson8b_mpll0,
+       &meson8b_mpll1,
+       &meson8b_mpll2,
+       &meson8b_mpll0_div,
+       &meson8b_mpll1_div,
+       &meson8b_mpll2_div,
+       &meson8b_fixed_pll,
+       &meson8b_vid_pll,
+       &meson8b_sys_pll,
+       &meson8b_cpu_in_sel,
+       &meson8b_cpu_scale_div,
+       &meson8b_cpu_scale_out_sel,
+       &meson8b_cpu_clk,
+       &meson8b_mpll_prediv,
+       &meson8b_fclk_div2,
+       &meson8b_fclk_div3,
+       &meson8b_fclk_div4,
+       &meson8b_fclk_div5,
+       &meson8b_fclk_div7,
 };
 
 static const struct meson8b_clk_reset_line {
@@ -804,82 +1040,45 @@ static const struct reset_control_ops meson8b_clk_reset_ops = {
        .deassert = meson8b_clk_reset_deassert,
 };
 
+static const struct regmap_config clkc_regmap_config = {
+       .reg_bits       = 32,
+       .val_bits       = 32,
+       .reg_stride     = 4,
+};
+
 static int meson8b_clkc_probe(struct platform_device *pdev)
 {
-       int ret, clkid, i;
-       struct clk_hw *parent_hw;
-       struct clk *parent_clk;
+       int ret, i;
        struct device *dev = &pdev->dev;
+       struct regmap *map;
 
        if (!clk_base)
                return -ENXIO;
 
-       /* Populate base address for PLLs */
-       for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++)
-               meson8b_clk_plls[i]->base = clk_base;
-
-       /* Populate base address for MPLLs */
-       for (i = 0; i < ARRAY_SIZE(meson8b_clk_mplls); i++)
-               meson8b_clk_mplls[i]->base = clk_base;
-
-       /* Populate the base address for CPU clk */
-       meson8b_cpu_clk.base = clk_base;
-
-       /* Populate base address for gates */
-       for (i = 0; i < ARRAY_SIZE(meson8b_clk_gates); i++)
-               meson8b_clk_gates[i]->reg = clk_base +
-                       (u32)meson8b_clk_gates[i]->reg;
-
-       /* Populate base address for muxes */
-       for (i = 0; i < ARRAY_SIZE(meson8b_clk_muxes); i++)
-               meson8b_clk_muxes[i]->reg = clk_base +
-                       (u32)meson8b_clk_muxes[i]->reg;
+       map = devm_regmap_init_mmio(dev, clk_base, &clkc_regmap_config);
+       if (IS_ERR(map))
+               return PTR_ERR(map);
 
-       /* Populate base address for dividers */
-       for (i = 0; i < ARRAY_SIZE(meson8b_clk_dividers); i++)
-               meson8b_clk_dividers[i]->reg = clk_base +
-                       (u32)meson8b_clk_dividers[i]->reg;
+       /* Populate regmap for the regmap backed clocks */
+       for (i = 0; i < ARRAY_SIZE(meson8b_clk_regmaps); i++)
+               meson8b_clk_regmaps[i]->map = map;
 
        /*
         * register all clks
         * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
         */
-       for (clkid = CLKID_XTAL; clkid < CLK_NR_CLKS; clkid++) {
+       for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) {
                /* array might be sparse */
-               if (!meson8b_hw_onecell_data.hws[clkid])
+               if (!meson8b_hw_onecell_data.hws[i])
                        continue;
 
-               /* FIXME convert to devm_clk_register */
-               ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[clkid]);
+               ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[i]);
                if (ret)
                        return ret;
        }
 
-       /*
-        * Register CPU clk notifier
-        *
-        * FIXME this is wrong for a lot of reasons. First, the muxes should be
-        * struct clk_hw objects. Second, we shouldn't program the muxes in
-        * notifier handlers. The tricky programming sequence will be handled
-        * by the forthcoming coordinated clock rates mechanism once that
-        * feature is released.
-        *
-        * Furthermore, looking up the parent this way is terrible. At some
-        * point we will stop allocating a default struct clk when registering
-        * a new clk_hw, and this hack will no longer work. Releasing the ccr
-        * feature before that time solves the problem :-)
-        */
-       parent_hw = clk_hw_get_parent(&meson8b_cpu_clk.hw);
-       parent_clk = parent_hw->clk;
-       ret = clk_notifier_register(parent_clk, &meson8b_cpu_clk.clk_nb);
-       if (ret) {
-               pr_err("%s: failed to register clock notifier for cpu_clk\n",
-                               __func__);
-               return ret;
-       }
-
-       return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
-                       &meson8b_hw_onecell_data);
+       return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+                                          &meson8b_hw_onecell_data);
 }
 
 static const struct of_device_id meson8b_clkc_match_table[] = {
index 2eaf8a52e7dd84c15704f7dfbc5d99166140fce2..6e414bd36981f63164f1c9ffedbf683821da4241 100644 (file)
  * will remain defined here.
  */
 
-#define CLK_NR_CLKS            96
+#define CLKID_MPLL0_DIV                96
+#define CLKID_MPLL1_DIV                97
+#define CLKID_MPLL2_DIV                98
+#define CLKID_CPU_IN_SEL       99
+#define CLKID_CPU_DIV2         100
+#define CLKID_CPU_DIV3         101
+#define CLKID_CPU_SCALE_DIV    102
+#define CLKID_CPU_SCALE_OUT_SEL        103
+#define CLKID_MPLL_PREDIV      104
+#define CLKID_FCLK_DIV2_DIV    105
+#define CLKID_FCLK_DIV3_DIV    106
+#define CLKID_FCLK_DIV4_DIV    107
+#define CLKID_FCLK_DIV5_DIV    108
+#define CLKID_FCLK_DIV7_DIV    109
+
+#define CLK_NR_CLKS            110
 
 /*
  * include the CLKID and RESETID that have
index 394aa6f03f01ffee1ed370896dbc2946a06b17df..9ff4ea63932d507c9a5b7289e34eddf125193652 100644 (file)
@@ -46,11 +46,11 @@ static u32 __init armada_38x_get_tclk_freq(void __iomem *sar)
 }
 
 static const u32 armada_38x_cpu_frequencies[] __initconst = {
-       0, 0, 0, 0,
-       1066 * 1000 * 1000, 0, 0, 0,
+       666 * 1000 * 1000,  0, 800 * 1000 * 1000, 0,
+       1066 * 1000 * 1000, 0, 1200 * 1000 * 1000, 0,
        1332 * 1000 * 1000, 0, 0, 0,
        1600 * 1000 * 1000, 0, 0, 0,
-       1866 * 1000 * 1000,
+       1866 * 1000 * 1000, 0, 0, 2000 * 1000 * 1000,
 };
 
 static u32 __init armada_38x_get_cpu_freq(void __iomem *sar)
@@ -76,11 +76,11 @@ static const struct coreclk_ratio armada_38x_coreclk_ratios[] __initconst = {
 };
 
 static const int armada_38x_cpu_l2_ratios[32][2] __initconst = {
-       {0, 1}, {0, 1}, {0, 1}, {0, 1},
-       {1, 2}, {0, 1}, {0, 1}, {0, 1},
-       {1, 2}, {0, 1}, {0, 1}, {0, 1},
+       {1, 2}, {0, 1}, {1, 2}, {0, 1},
+       {1, 2}, {0, 1}, {1, 2}, {0, 1},
        {1, 2}, {0, 1}, {0, 1}, {0, 1},
        {1, 2}, {0, 1}, {0, 1}, {0, 1},
+       {1, 2}, {0, 1}, {0, 1}, {1, 2},
        {0, 1}, {0, 1}, {0, 1}, {0, 1},
        {0, 1}, {0, 1}, {0, 1}, {0, 1},
        {0, 1}, {0, 1}, {0, 1}, {0, 1},
@@ -91,7 +91,7 @@ static const int armada_38x_cpu_ddr_ratios[32][2] __initconst = {
        {1, 2}, {0, 1}, {0, 1}, {0, 1},
        {1, 2}, {0, 1}, {0, 1}, {0, 1},
        {1, 2}, {0, 1}, {0, 1}, {0, 1},
-       {1, 2}, {0, 1}, {0, 1}, {0, 1},
+       {1, 2}, {0, 1}, {0, 1}, {7, 15},
        {0, 1}, {0, 1}, {0, 1}, {0, 1},
        {0, 1}, {0, 1}, {0, 1}, {0, 1},
        {0, 1}, {0, 1}, {0, 1}, {0, 1},
index ca9a0a53617471f3e92154a4657dee9ef88988e8..75bf7b8f282fc4e4cc0e342e16d5594b7cba1274 100644 (file)
 /*
  * CP110 has 6 core clocks:
  *
- *  - APLL             (1 Ghz)
- *    - PPv2 core      (1/3 APLL)
- *    - EIP            (1/2 APLL)
- *     - Core          (1/2 EIP)
- *    - SDIO           (2/5 APLL)
+ *  - PLL0             (1 Ghz)
+ *    - PPv2 core      (1/3 PLL0)
+ *    - x2 Core                (1/2 PLL0)
+ *     - Core          (1/2 x2 Core)
+ *    - SDIO           (2/5 PLL0)
  *
  *  - NAND clock, which is either:
  *    - Equal to SDIO clock
- *    - 2/5 APLL
+ *    - 2/5 PLL0
  *
- * CP110 has 32 gatable clocks, for the various peripherals in the
- * IP. They have fairly complicated parent/child relationships.
+ * CP110 has 32 gatable clocks, for the various peripherals in the IP.
  */
 
 #define pr_fmt(fmt) "cp110-system-controller: " fmt
@@ -53,9 +52,9 @@ enum {
 #define CP110_CLK_NUM \
        (CP110_MAX_CORE_CLOCKS + CP110_MAX_GATABLE_CLOCKS)
 
-#define CP110_CORE_APLL                        0
+#define CP110_CORE_PLL0                        0
 #define CP110_CORE_PPV2                        1
-#define CP110_CORE_EIP                 2
+#define CP110_CORE_X2CORE              2
 #define CP110_CORE_CORE                        3
 #define CP110_CORE_NAND                        4
 #define CP110_CORE_SDIO                        5
@@ -237,7 +236,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
        struct regmap *regmap;
        struct device *dev = &pdev->dev;
        struct device_node *np = dev->of_node;
-       const char *ppv2_name, *apll_name, *core_name, *eip_name, *nand_name,
+       const char *ppv2_name, *pll0_name, *core_name, *x2core_name, *nand_name,
                *sdio_name;
        struct clk_hw_onecell_data *cp110_clk_data;
        struct clk_hw *hw, **cp110_clks;
@@ -263,20 +262,20 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
        cp110_clks = cp110_clk_data->hws;
        cp110_clk_data->num = CP110_CLK_NUM;
 
-       /* Register the APLL which is the root of the hw tree */
-       apll_name = cp110_unique_name(dev, syscon_node, "apll");
-       hw = clk_hw_register_fixed_rate(NULL, apll_name, NULL, 0,
+       /* Register the PLL0 which is the root of the hw tree */
+       pll0_name = cp110_unique_name(dev, syscon_node, "pll0");
+       hw = clk_hw_register_fixed_rate(NULL, pll0_name, NULL, 0,
                                        1000 * 1000 * 1000);
        if (IS_ERR(hw)) {
                ret = PTR_ERR(hw);
-               goto fail_apll;
+               goto fail_pll0;
        }
 
-       cp110_clks[CP110_CORE_APLL] = hw;
+       cp110_clks[CP110_CORE_PLL0] = hw;
 
-       /* PPv2 is APLL/3 */
+       /* PPv2 is PLL0/3 */
        ppv2_name = cp110_unique_name(dev, syscon_node, "ppv2-core");
-       hw = clk_hw_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3);
+       hw = clk_hw_register_fixed_factor(NULL, ppv2_name, pll0_name, 0, 1, 3);
        if (IS_ERR(hw)) {
                ret = PTR_ERR(hw);
                goto fail_ppv2;
@@ -284,30 +283,32 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
 
        cp110_clks[CP110_CORE_PPV2] = hw;
 
-       /* EIP clock is APLL/2 */
-       eip_name = cp110_unique_name(dev, syscon_node, "eip");
-       hw = clk_hw_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2);
+       /* X2CORE clock is PLL0/2 */
+       x2core_name = cp110_unique_name(dev, syscon_node, "x2core");
+       hw = clk_hw_register_fixed_factor(NULL, x2core_name, pll0_name,
+                                         0, 1, 2);
        if (IS_ERR(hw)) {
                ret = PTR_ERR(hw);
                goto fail_eip;
        }
 
-       cp110_clks[CP110_CORE_EIP] = hw;
+       cp110_clks[CP110_CORE_X2CORE] = hw;
 
-       /* Core clock is EIP/2 */
+       /* Core clock is X2CORE/2 */
        core_name = cp110_unique_name(dev, syscon_node, "core");
-       hw = clk_hw_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2);
+       hw = clk_hw_register_fixed_factor(NULL, core_name, x2core_name,
+                                         0, 1, 2);
        if (IS_ERR(hw)) {
                ret = PTR_ERR(hw);
                goto fail_core;
        }
 
        cp110_clks[CP110_CORE_CORE] = hw;
-       /* NAND can be either APLL/2.5 or core clock */
+       /* NAND can be either PLL0/2.5 or core clock */
        nand_name = cp110_unique_name(dev, syscon_node, "nand-core");
        if (nand_clk_ctrl & NF_CLOCK_SEL_400_MASK)
                hw = clk_hw_register_fixed_factor(NULL, nand_name,
-                                                  apll_name, 0, 2, 5);
+                                                  pll0_name, 0, 2, 5);
        else
                hw = clk_hw_register_fixed_factor(NULL, nand_name,
                                                   core_name, 0, 1, 1);
@@ -318,10 +319,10 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
 
        cp110_clks[CP110_CORE_NAND] = hw;
 
-       /* SDIO clock is APLL/2.5 */
+       /* SDIO clock is PLL0/2.5 */
        sdio_name = cp110_unique_name(dev, syscon_node, "sdio-core");
        hw = clk_hw_register_fixed_factor(NULL, sdio_name,
-                                         apll_name, 0, 2, 5);
+                                         pll0_name, 0, 2, 5);
        if (IS_ERR(hw)) {
                ret = PTR_ERR(hw);
                goto fail_sdio;
@@ -341,40 +342,23 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
                        continue;
 
                switch (i) {
-               case CP110_GATE_AUDIO:
-               case CP110_GATE_COMM_UNIT:
-               case CP110_GATE_EIP150:
-               case CP110_GATE_EIP197:
-               case CP110_GATE_SLOW_IO:
-                       parent = gate_name[CP110_GATE_MAIN];
-                       break;
-               case CP110_GATE_MG:
-                       parent = gate_name[CP110_GATE_MG_CORE];
-                       break;
                case CP110_GATE_NAND:
                        parent = nand_name;
                        break;
+               case CP110_GATE_MG:
+               case CP110_GATE_GOP_DP:
                case CP110_GATE_PPV2:
                        parent = ppv2_name;
                        break;
                case CP110_GATE_SDIO:
                        parent = sdio_name;
                        break;
-               case CP110_GATE_GOP_DP:
-                       parent = gate_name[CP110_GATE_SDMMC_GOP];
-                       break;
-               case CP110_GATE_XOR1:
-               case CP110_GATE_XOR0:
-               case CP110_GATE_PCIE_X1_0:
-               case CP110_GATE_PCIE_X1_1:
+               case CP110_GATE_MAIN:
+               case CP110_GATE_PCIE_XOR:
                case CP110_GATE_PCIE_X4:
-                       parent = gate_name[CP110_GATE_PCIE_XOR];
-                       break;
-               case CP110_GATE_SATA:
-               case CP110_GATE_USB3H0:
-               case CP110_GATE_USB3H1:
-               case CP110_GATE_USB3DEV:
-                       parent = gate_name[CP110_GATE_SATA_USB];
+               case CP110_GATE_EIP150:
+               case CP110_GATE_EIP197:
+                       parent = x2core_name;
                        break;
                default:
                        parent = core_name;
@@ -413,12 +397,12 @@ fail_sdio:
 fail_nand:
        clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
 fail_core:
-       clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
+       clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_X2CORE]);
 fail_eip:
        clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
 fail_ppv2:
-       clk_hw_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
-fail_apll:
+       clk_hw_unregister_fixed_rate(cp110_clks[CP110_CORE_PLL0]);
+fail_pll0:
        return ret;
 }
 
index f5d815f577e05c4a98f3bd19e404b50c8c065282..5eeecee17b695c8de0c4c134e3ec03dfea8e6e5b 100644 (file)
@@ -67,6 +67,7 @@
 #define LPC32XX_USB_CLK_STS            0xF8
 
 static struct regmap_config lpc32xx_scb_regmap_config = {
+       .name = "scb",
        .reg_bits = 32,
        .val_bits = 32,
        .reg_stride = 4,
index 4e9b8c2c8980a2af785ef1b026cf8d9fb8a6bb73..1ee75a5e93f4e681206326d94f3b56c7ebbb4c8b 100644 (file)
@@ -28,22 +28,14 @@ static long div_round_ro_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct clk_regmap_div *divider = to_clk_regmap_div(hw);
        struct clk_regmap *clkr = &divider->clkr;
-       u32 div;
-       struct clk_hw *hw_parent = clk_hw_get_parent(hw);
-
-       regmap_read(clkr->regmap, divider->reg, &div);
-       div >>= divider->shift;
-       div &= BIT(divider->width) - 1;
-       div += 1;
-
-       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
-               if (!hw_parent)
-                       return -EINVAL;
+       u32 val;
 
-               *prate = clk_hw_round_rate(hw_parent, rate * div);
-       }
+       regmap_read(clkr->regmap, divider->reg, &val);
+       val >>= divider->shift;
+       val &= BIT(divider->width) - 1;
 
-       return DIV_ROUND_UP_ULL((u64)*prate, div);
+       return divider_ro_round_rate(hw, rate, prate, NULL, divider->width,
+                                    CLK_DIVIDER_ROUND_CLOSEST, val);
 }
 
 static long div_round_rate(struct clk_hw *hw, unsigned long rate,
index c60f61b10c7f9335bc269489b84b4d16d44863a7..b949814476640fee5b869704e0eb11b63cba060a 100644 (file)
@@ -29,6 +29,7 @@
 
 #define QCOM_RPM_MISC_CLK_TYPE                         0x306b6c63
 #define QCOM_RPM_SCALING_ENABLE_ID                     0x2
+#define QCOM_RPM_XO_MODE_ON                            0x2
 
 #define DEFINE_CLK_RPM(_platform, _name, _active, r_id)                              \
        static struct clk_rpm _platform##_##_active;                          \
                },                                                            \
        }
 
+#define DEFINE_CLK_RPM_XO_BUFFER(_platform, _name, _active, offset)          \
+       static struct clk_rpm _platform##_##_name = {                         \
+               .rpm_clk_id = QCOM_RPM_CXO_BUFFERS,                           \
+               .xo_offset = (offset),                                        \
+               .hw.init = &(struct clk_init_data){                           \
+                       .ops = &clk_rpm_xo_ops,                       \
+                       .name = #_name,                                       \
+                       .parent_names = (const char *[]){ "cxo_board" },      \
+                       .num_parents = 1,                                     \
+               },                                                            \
+       }
+
 #define DEFINE_CLK_RPM_FIXED(_platform, _name, _active, r_id, r)             \
        static struct clk_rpm _platform##_##_name = {                         \
                .rpm_clk_id = (r_id),                                         \
 
 #define to_clk_rpm(_hw) container_of(_hw, struct clk_rpm, hw)
 
+struct rpm_cc;
+
 struct clk_rpm {
        const int rpm_clk_id;
+       const int xo_offset;
        const bool active_only;
        unsigned long rate;
        bool enabled;
@@ -135,12 +151,15 @@ struct clk_rpm {
        struct clk_rpm *peer;
        struct clk_hw hw;
        struct qcom_rpm *rpm;
+       struct rpm_cc *rpm_cc;
 };
 
 struct rpm_cc {
        struct qcom_rpm *rpm;
        struct clk_rpm **clks;
        size_t num_clks;
+       u32 xo_buffer_value;
+       struct mutex xo_lock;
 };
 
 struct rpm_clk_desc {
@@ -159,7 +178,8 @@ static int clk_rpm_handoff(struct clk_rpm *r)
         * The vendor tree simply reads the status for this
         * RPM clock.
         */
-       if (r->rpm_clk_id == QCOM_RPM_PLL_4)
+       if (r->rpm_clk_id == QCOM_RPM_PLL_4 ||
+               r->rpm_clk_id == QCOM_RPM_CXO_BUFFERS)
                return 0;
 
        ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
@@ -288,6 +308,46 @@ out:
        mutex_unlock(&rpm_clk_lock);
 }
 
+static int clk_rpm_xo_prepare(struct clk_hw *hw)
+{
+       struct clk_rpm *r = to_clk_rpm(hw);
+       struct rpm_cc *rcc = r->rpm_cc;
+       int ret, clk_id = r->rpm_clk_id;
+       u32 value;
+
+       mutex_lock(&rcc->xo_lock);
+
+       value = rcc->xo_buffer_value | (QCOM_RPM_XO_MODE_ON << r->xo_offset);
+       ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, clk_id, &value, 1);
+       if (!ret) {
+               r->enabled = true;
+               rcc->xo_buffer_value = value;
+       }
+
+       mutex_unlock(&rcc->xo_lock);
+
+       return ret;
+}
+
+static void clk_rpm_xo_unprepare(struct clk_hw *hw)
+{
+       struct clk_rpm *r = to_clk_rpm(hw);
+       struct rpm_cc *rcc = r->rpm_cc;
+       int ret, clk_id = r->rpm_clk_id;
+       u32 value;
+
+       mutex_lock(&rcc->xo_lock);
+
+       value = rcc->xo_buffer_value & ~(QCOM_RPM_XO_MODE_ON << r->xo_offset);
+       ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, clk_id, &value, 1);
+       if (!ret) {
+               r->enabled = false;
+               rcc->xo_buffer_value = value;
+       }
+
+       mutex_unlock(&rcc->xo_lock);
+}
+
 static int clk_rpm_fixed_prepare(struct clk_hw *hw)
 {
        struct clk_rpm *r = to_clk_rpm(hw);
@@ -378,6 +438,11 @@ static unsigned long clk_rpm_recalc_rate(struct clk_hw *hw,
        return r->rate;
 }
 
+static const struct clk_ops clk_rpm_xo_ops = {
+       .prepare        = clk_rpm_xo_prepare,
+       .unprepare      = clk_rpm_xo_unprepare,
+};
+
 static const struct clk_ops clk_rpm_fixed_ops = {
        .prepare        = clk_rpm_fixed_prepare,
        .unprepare      = clk_rpm_fixed_unprepare,
@@ -449,6 +514,11 @@ DEFINE_CLK_RPM(apq8064, mmfpb_clk, mmfpb_a_clk, QCOM_RPM_MMFPB_CLK);
 DEFINE_CLK_RPM(apq8064, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK);
 DEFINE_CLK_RPM(apq8064, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK);
 DEFINE_CLK_RPM(apq8064, qdss_clk, qdss_a_clk, QCOM_RPM_QDSS_CLK);
+DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_d0_clk, xo_d0_a_clk, 0);
+DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_d1_clk, xo_d1_a_clk, 8);
+DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a0_clk, xo_a0_a_clk, 16);
+DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a1_clk, xo_a1_a_clk, 24);
+DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a2_clk, xo_a2_a_clk, 28);
 
 static struct clk_rpm *apq8064_clks[] = {
        [RPM_APPS_FABRIC_CLK] = &apq8064_afab_clk,
@@ -469,6 +539,11 @@ static struct clk_rpm *apq8064_clks[] = {
        [RPM_SFPB_A_CLK] = &apq8064_sfpb_a_clk,
        [RPM_QDSS_CLK] = &apq8064_qdss_clk,
        [RPM_QDSS_A_CLK] = &apq8064_qdss_a_clk,
+       [RPM_XO_D0] = &apq8064_xo_d0_clk,
+       [RPM_XO_D1] = &apq8064_xo_d1_clk,
+       [RPM_XO_A0] = &apq8064_xo_a0_clk,
+       [RPM_XO_A1] = &apq8064_xo_a1_clk,
+       [RPM_XO_A2] = &apq8064_xo_a2_clk,
 };
 
 static const struct rpm_clk_desc rpm_clk_apq8064 = {
@@ -526,12 +601,14 @@ static int rpm_clk_probe(struct platform_device *pdev)
 
        rcc->clks = rpm_clks;
        rcc->num_clks = num_clks;
+       mutex_init(&rcc->xo_lock);
 
        for (i = 0; i < num_clks; i++) {
                if (!rpm_clks[i])
                        continue;
 
                rpm_clks[i]->rpm = rpm;
+               rpm_clks[i]->rpm_cc = rcc;
 
                ret = clk_rpm_handoff(rpm_clks[i]);
                if (ret)
index c26d9007bfc41c5c21053b3bd2ff9d5ba4dc2a29..850c02a5224846530b0f601a97edae69ba569919 100644 (file)
@@ -686,7 +686,7 @@ static int rpm_smd_clk_probe(struct platform_device *pdev)
                        goto err;
        }
 
-       ret = of_clk_add_hw_provider(pdev->dev.of_node, qcom_smdrpm_clk_hw_get,
+       ret = devm_of_clk_add_hw_provider(&pdev->dev, qcom_smdrpm_clk_hw_get,
                                     rcc);
        if (ret)
                goto err;
@@ -697,19 +697,12 @@ err:
        return ret;
 }
 
-static int rpm_smd_clk_remove(struct platform_device *pdev)
-{
-       of_clk_del_provider(pdev->dev.of_node);
-       return 0;
-}
-
 static struct platform_driver rpm_smd_clk_driver = {
        .driver = {
                .name = "qcom-clk-smd-rpm",
                .of_match_table = rpm_smd_clk_match_table,
        },
        .probe = rpm_smd_clk_probe,
-       .remove = rpm_smd_clk_remove,
 };
 
 static int __init rpm_smd_clk_init(void)
index 5d7451209206956bac1596e867029ac4713347ff..3d645293279726697261451d18adcd4e23246b38 100644 (file)
@@ -2895,7 +2895,7 @@ static struct clk_branch gcc_aggre0_snoc_axi_clk = {
                        .name = "gcc_aggre0_snoc_axi_clk",
                        .parent_names = (const char *[]){ "system_noc_clk_src" },
                        .num_parents = 1,
-                       .flags = CLK_SET_RATE_PARENT,
+                       .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -2910,7 +2910,7 @@ static struct clk_branch gcc_aggre0_cnoc_ahb_clk = {
                        .name = "gcc_aggre0_cnoc_ahb_clk",
                        .parent_names = (const char *[]){ "config_noc_clk_src" },
                        .num_parents = 1,
-                       .flags = CLK_SET_RATE_PARENT,
+                       .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -2925,7 +2925,7 @@ static struct clk_branch gcc_smmu_aggre0_axi_clk = {
                        .name = "gcc_smmu_aggre0_axi_clk",
                        .parent_names = (const char *[]){ "system_noc_clk_src" },
                        .num_parents = 1,
-                       .flags = CLK_SET_RATE_PARENT,
+                       .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -2940,7 +2940,7 @@ static struct clk_branch gcc_smmu_aggre0_ahb_clk = {
                        .name = "gcc_smmu_aggre0_ahb_clk",
                        .parent_names = (const char *[]){ "config_noc_clk_src" },
                        .num_parents = 1,
-                       .flags = CLK_SET_RATE_PARENT,
+                       .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
                        .ops = &clk_branch2_ops,
                },
        },
index 43b5a89c4b282db8fc12ce2a7279cc05fece19b4..ef76c861ec840c19f8f56b165e3cff3877e25c44 100644 (file)
@@ -15,7 +15,9 @@ config CLK_RENESAS
        select CLK_R8A7794 if ARCH_R8A7794
        select CLK_R8A7795 if ARCH_R8A7795
        select CLK_R8A7796 if ARCH_R8A7796
+       select CLK_R8A77965 if ARCH_R8A77965
        select CLK_R8A77970 if ARCH_R8A77970
+       select CLK_R8A77980 if ARCH_R8A77980
        select CLK_R8A77995 if ARCH_R8A77995
        select CLK_SH73A0 if ARCH_SH73A0
 
@@ -24,12 +26,13 @@ if CLK_RENESAS
 config CLK_RENESAS_LEGACY
        bool "Legacy DT clock support"
        depends on CLK_R8A7790 || CLK_R8A7791 || CLK_R8A7792 || CLK_R8A7794
-       default y
        help
          Enable backward compatibility with old device trees describing a
          hierarchical representation of the various CPG and MSTP clocks.
 
          Say Y if you want your kernel to work with old DTBs.
+         It is safe to say N if you use the DTS that is supplied with the
+         current kernel source tree.
 
 # SoC
 config CLK_EMEV2
@@ -96,10 +99,18 @@ config CLK_R8A7796
        bool "R-Car M3-W clock support" if COMPILE_TEST
        select CLK_RCAR_GEN3_CPG
 
+config CLK_R8A77965
+       bool "R-Car M3-N clock support" if COMPILE_TEST
+       select CLK_RCAR_GEN3_CPG
+
 config CLK_R8A77970
        bool "R-Car V3M clock support" if COMPILE_TEST
        select CLK_RCAR_GEN3_CPG
 
+config CLK_R8A77980
+       bool "R-Car V3H clock support" if COMPILE_TEST
+       select CLK_RCAR_GEN3_CPG
+
 config CLK_R8A77995
        bool "R-Car D3 clock support" if COMPILE_TEST
        select CLK_RCAR_GEN3_CPG
index 34c4e0b37afa0c081c8340e577da03506226fee6..6c0f19636e3e2353bd6d91cc7c1d1a1993c1b8e1 100644 (file)
@@ -14,7 +14,9 @@ obj-$(CONFIG_CLK_R8A7792)             += r8a7792-cpg-mssr.o
 obj-$(CONFIG_CLK_R8A7794)              += r8a7794-cpg-mssr.o
 obj-$(CONFIG_CLK_R8A7795)              += r8a7795-cpg-mssr.o
 obj-$(CONFIG_CLK_R8A7796)              += r8a7796-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A77965)             += r8a77965-cpg-mssr.o
 obj-$(CONFIG_CLK_R8A77970)             += r8a77970-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A77980)             += r8a77980-cpg-mssr.o
 obj-$(CONFIG_CLK_R8A77995)             += r8a77995-cpg-mssr.o
 obj-$(CONFIG_CLK_SH73A0)               += clk-sh73a0.o
 
index 151336d2ba59e689c2b83bb1255000581cd25043..9febbf42c3df6979a8c667c8d08a1e7846acba8d 100644 (file)
@@ -53,9 +53,9 @@ static int cpg_div6_clock_enable(struct clk_hw *hw)
        struct div6_clock *clock = to_div6_clock(hw);
        u32 val;
 
-       val = (clk_readl(clock->reg) & ~(CPG_DIV6_DIV_MASK | CPG_DIV6_CKSTP))
+       val = (readl(clock->reg) & ~(CPG_DIV6_DIV_MASK | CPG_DIV6_CKSTP))
            | CPG_DIV6_DIV(clock->div - 1);
-       clk_writel(val, clock->reg);
+       writel(val, clock->reg);
 
        return 0;
 }
@@ -65,7 +65,7 @@ static void cpg_div6_clock_disable(struct clk_hw *hw)
        struct div6_clock *clock = to_div6_clock(hw);
        u32 val;
 
-       val = clk_readl(clock->reg);
+       val = readl(clock->reg);
        val |= CPG_DIV6_CKSTP;
        /*
         * DIV6 clocks require the divisor field to be non-zero when stopping
@@ -75,14 +75,14 @@ static void cpg_div6_clock_disable(struct clk_hw *hw)
         */
        if (!(val & CPG_DIV6_DIV_MASK))
                val |= CPG_DIV6_DIV_MASK;
-       clk_writel(val, clock->reg);
+       writel(val, clock->reg);
 }
 
 static int cpg_div6_clock_is_enabled(struct clk_hw *hw)
 {
        struct div6_clock *clock = to_div6_clock(hw);
 
-       return !(clk_readl(clock->reg) & CPG_DIV6_CKSTP);
+       return !(readl(clock->reg) & CPG_DIV6_CKSTP);
 }
 
 static unsigned long cpg_div6_clock_recalc_rate(struct clk_hw *hw,
@@ -122,10 +122,10 @@ static int cpg_div6_clock_set_rate(struct clk_hw *hw, unsigned long rate,
 
        clock->div = div;
 
-       val = clk_readl(clock->reg) & ~CPG_DIV6_DIV_MASK;
+       val = readl(clock->reg) & ~CPG_DIV6_DIV_MASK;
        /* Only program the new divisor if the clock isn't stopped. */
        if (!(val & CPG_DIV6_CKSTP))
-               clk_writel(val | CPG_DIV6_DIV(clock->div - 1), clock->reg);
+               writel(val | CPG_DIV6_DIV(clock->div - 1), clock->reg);
 
        return 0;
 }
@@ -139,7 +139,7 @@ static u8 cpg_div6_clock_get_parent(struct clk_hw *hw)
        if (clock->src_width == 0)
                return 0;
 
-       hw_index = (clk_readl(clock->reg) >> clock->src_shift) &
+       hw_index = (readl(clock->reg) >> clock->src_shift) &
                   (BIT(clock->src_width) - 1);
        for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
                if (clock->parents[i] == hw_index)
@@ -163,8 +163,8 @@ static int cpg_div6_clock_set_parent(struct clk_hw *hw, u8 index)
        mask = ~((BIT(clock->src_width) - 1) << clock->src_shift);
        hw_index = clock->parents[index];
 
-       clk_writel((clk_readl(clock->reg) & mask) |
-               (hw_index << clock->src_shift), clock->reg);
+       writel((readl(clock->reg) & mask) | (hw_index << clock->src_shift),
+              clock->reg);
 
        return 0;
 }
@@ -241,7 +241,7 @@ struct clk * __init cpg_div6_register(const char *name,
         * Read the divisor. Disabling the clock overwrites the divisor, so we
         * need to cache its value for the enable operation.
         */
-       clock->div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1;
+       clock->div = (readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1;
 
        switch (num_parents) {
        case 1:
index 858c24d4da8f62f8c1fc16fcc15bcf7283517081..e82adcb16a52a3b790c34fc2a49079615a7bf907 100644 (file)
@@ -64,13 +64,13 @@ struct mstp_clock {
 static inline u32 cpg_mstp_read(struct mstp_clock_group *group,
                                u32 __iomem *reg)
 {
-       return group->width_8bit ? readb(reg) : clk_readl(reg);
+       return group->width_8bit ? readb(reg) : readl(reg);
 }
 
 static inline void cpg_mstp_write(struct mstp_clock_group *group, u32 val,
                                  u32 __iomem *reg)
 {
-       group->width_8bit ? writeb(val, reg) : clk_writel(val, reg);
+       group->width_8bit ? writeb(val, reg) : writel(val, reg);
 }
 
 static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
index 28d204bb659e7879de4d7ad48c9221dfe4106af6..7b903ce4c9015ad76a476c7f45707bd5960d390b 100644 (file)
@@ -71,7 +71,7 @@ r8a73a4_cpg_register_clock(struct device_node *np, struct r8a73a4_cpg *cpg,
 
 
        if (!strcmp(name, "main")) {
-               u32 ckscr = clk_readl(cpg->reg + CPG_CKSCR);
+               u32 ckscr = readl(cpg->reg + CPG_CKSCR);
 
                switch ((ckscr >> 28) & 3) {
                case 0: /* extal1 */
@@ -95,14 +95,14 @@ r8a73a4_cpg_register_clock(struct device_node *np, struct r8a73a4_cpg *cpg,
                 * clock implementation and we currently have no need to change
                 * the multiplier value.
                 */
-               u32 value = clk_readl(cpg->reg + CPG_PLL0CR);
+               u32 value = readl(cpg->reg + CPG_PLL0CR);
 
                parent_name = "main";
                mult = ((value >> 24) & 0x7f) + 1;
                if (value & BIT(20))
                        div = 2;
        } else if (!strcmp(name, "pll1")) {
-               u32 value = clk_readl(cpg->reg + CPG_PLL1CR);
+               u32 value = readl(cpg->reg + CPG_PLL1CR);
 
                parent_name = "main";
                /* XXX: enable bit? */
@@ -125,7 +125,7 @@ r8a73a4_cpg_register_clock(struct device_node *np, struct r8a73a4_cpg *cpg,
                default:
                        return ERR_PTR(-EINVAL);
                }
-               value = clk_readl(cpg->reg + cr);
+               value = readl(cpg->reg + cr);
                switch ((value >> 5) & 7) {
                case 0:
                        parent_name = "main";
@@ -161,8 +161,7 @@ r8a73a4_cpg_register_clock(struct device_node *np, struct r8a73a4_cpg *cpg,
                        shift = 0;
                }
                div *= 32;
-               mult = 0x20 - ((clk_readl(cpg->reg + CPG_FRQCRC) >> shift)
-                      & 0x1f);
+               mult = 0x20 - ((readl(cpg->reg + CPG_FRQCRC) >> shift) & 0x1f);
        } else {
                struct div4_clk *c;
 
index 2f7ce6696b6c0f1d98a9cd9d91dfe861acb8dc16..d074f8e982d0851cae185375f7548e6cebeb74c6 100644 (file)
@@ -98,20 +98,20 @@ r8a7740_cpg_register_clock(struct device_node *np, struct r8a7740_cpg *cpg,
                 * clock implementation and we currently have no need to change
                 * the multiplier value.
                 */
-               u32 value = clk_readl(cpg->reg + CPG_FRQCRC);
+               u32 value = readl(cpg->reg + CPG_FRQCRC);
                parent_name = "system";
                mult = ((value >> 24) & 0x7f) + 1;
        } else if (!strcmp(name, "pllc1")) {
-               u32 value = clk_readl(cpg->reg + CPG_FRQCRA);
+               u32 value = readl(cpg->reg + CPG_FRQCRA);
                parent_name = "system";
                mult = ((value >> 24) & 0x7f) + 1;
                div = 2;
        } else if (!strcmp(name, "pllc2")) {
-               u32 value = clk_readl(cpg->reg + CPG_PLLC2CR);
+               u32 value = readl(cpg->reg + CPG_PLLC2CR);
                parent_name = "system";
                mult = ((value >> 24) & 0x3f) + 1;
        } else if (!strcmp(name, "usb24s")) {
-               u32 value = clk_readl(cpg->reg + CPG_USBCKCR);
+               u32 value = readl(cpg->reg + CPG_USBCKCR);
                if (value & BIT(7))
                        /* extal2 */
                        parent_name = of_clk_get_parent_name(np, 1);
index d14cbe1ca29ac0098610b1364b8fefb5ae07027d..ee32a022e6da9548bfd13e1b82b811332a9869ab 100644 (file)
@@ -62,8 +62,7 @@ static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
        unsigned int mult;
        unsigned int val;
 
-       val = (clk_readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK)
-           >> CPG_FRQCRC_ZFC_SHIFT;
+       val = (readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) >> CPG_FRQCRC_ZFC_SHIFT;
        mult = 32 - val;
 
        return div_u64((u64)parent_rate * mult, 32);
@@ -95,21 +94,21 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
        mult = div_u64((u64)rate * 32, parent_rate);
        mult = clamp(mult, 1U, 32U);
 
-       if (clk_readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+       if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
                return -EBUSY;
 
-       val = clk_readl(zclk->reg);
+       val = readl(zclk->reg);
        val &= ~CPG_FRQCRC_ZFC_MASK;
        val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT;
-       clk_writel(val, zclk->reg);
+       writel(val, zclk->reg);
 
        /*
         * Set KICK bit in FRQCRB to update hardware setting and wait for
         * clock change completion.
         */
-       kick = clk_readl(zclk->kick_reg);
+       kick = readl(zclk->kick_reg);
        kick |= CPG_FRQCRB_KICK;
-       clk_writel(kick, zclk->kick_reg);
+       writel(kick, zclk->kick_reg);
 
        /*
         * Note: There is no HW information about the worst case latency.
@@ -121,7 +120,7 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
         * "super" safe value.
         */
        for (i = 1000; i; i--) {
-               if (!(clk_readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+               if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
                        return 0;
 
                cpu_relax();
@@ -332,7 +331,7 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
                        mult = config->pll0_mult;
                        div = 3;
                } else {
-                       u32 value = clk_readl(cpg->reg + CPG_PLL0CR);
+                       u32 value = readl(cpg->reg + CPG_PLL0CR);
                        mult = ((value >> 24) & ((1 << 7) - 1)) + 1;
                }
                parent_name = "main";
index 127c58135c8fec76b812b186b4f0d6d670ca828f..67dd712aa723c77c2ffab83c3913c78ac9abd439 100644 (file)
@@ -75,9 +75,9 @@ rz_cpg_register_clock(struct device_node *np, struct rz_cpg *cpg, const char *na
         * let them run at fixed current speed and implement the details later.
         */
        if (strcmp(name, "i") == 0)
-               val = (clk_readl(cpg->reg + CPG_FRQCR) >> 8) & 3;
+               val = (readl(cpg->reg + CPG_FRQCR) >> 8) & 3;
        else if (strcmp(name, "g") == 0)
-               val = clk_readl(cpg->reg + CPG_FRQCR2) & 3;
+               val = readl(cpg->reg + CPG_FRQCR2) & 3;
        else
                return ERR_PTR(-EINVAL);
 
index eea38f6ea77e995d287831a5d6b34bd7663883c0..bab33610eb6caedfd5bd41e60874fea0cb00a906 100644 (file)
@@ -46,7 +46,7 @@ struct div4_clk {
        unsigned int shift;
 };
 
-static struct div4_clk div4_clks[] = {
+static const struct div4_clk div4_clks[] = {
        { "zg", "pll0", CPG_FRQCRA, 16 },
        { "m3", "pll1", CPG_FRQCRA, 12 },
        { "b",  "pll1", CPG_FRQCRA,  8 },
@@ -79,13 +79,13 @@ sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg,
 {
        const struct clk_div_table *table = NULL;
        unsigned int shift, reg, width;
-       const char *parent_name;
+       const char *parent_name = NULL;
        unsigned int mult = 1;
        unsigned int div = 1;
 
        if (!strcmp(name, "main")) {
                /* extal1, extal1_div2, extal2, extal2_div2 */
-               u32 parent_idx = (clk_readl(cpg->reg + CPG_CKSCR) >> 28) & 3;
+               u32 parent_idx = (readl(cpg->reg + CPG_CKSCR) >> 28) & 3;
 
                parent_name = of_clk_get_parent_name(np, parent_idx >> 1);
                div = (parent_idx & 1) + 1;
@@ -110,11 +110,11 @@ sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg,
                default:
                        return ERR_PTR(-EINVAL);
                }
-               if (clk_readl(cpg->reg + CPG_PLLECR) & BIT(enable_bit)) {
-                       mult = ((clk_readl(enable_reg) >> 24) & 0x3f) + 1;
+               if (readl(cpg->reg + CPG_PLLECR) & BIT(enable_bit)) {
+                       mult = ((readl(enable_reg) >> 24) & 0x3f) + 1;
                        /* handle CFG bit for PLL1 and PLL2 */
                        if (enable_bit == 1 || enable_bit == 2)
-                               if (clk_readl(enable_reg) & BIT(20))
+                               if (readl(enable_reg) & BIT(20))
                                        mult *= 2;
                }
        } else if (!strcmp(name, "dsi0phy") || !strcmp(name, "dsi1phy")) {
@@ -135,7 +135,7 @@ sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg,
                shift = 24;
                width = 5;
        } else {
-               struct div4_clk *c;
+               const struct div4_clk *c;
 
                for (c = div4_clks; c->name; c++) {
                        if (!strcmp(name, c->name)) {
@@ -193,9 +193,9 @@ static void __init sh73a0_cpg_clocks_init(struct device_node *np)
                return;
 
        /* Set SDHI clocks to a known state */
-       clk_writel(0x108, cpg->reg + CPG_SD0CKCR);
-       clk_writel(0x108, cpg->reg + CPG_SD1CKCR);
-       clk_writel(0x108, cpg->reg + CPG_SD2CKCR);
+       writel(0x108, cpg->reg + CPG_SD0CKCR);
+       writel(0x108, cpg->reg + CPG_SD1CKCR);
+       writel(0x108, cpg->reg + CPG_SD2CKCR);
 
        for (i = 0; i < num_clks; ++i) {
                const char *name;
index 6dc0b3082aa6e87e3bf7749701a2eee80c909f54..d3c8b1e2969fd3058407c1f81b3db828ac1fd491 100644 (file)
@@ -117,6 +117,7 @@ static const struct mssr_mod_clk r8a7743_mod_clks[] __initconst = {
        DEF_MOD("cmt1",                  329,   R8A7743_CLK_R),
        DEF_MOD("usbhs-dmac0",           330,   R8A7743_CLK_HP),
        DEF_MOD("usbhs-dmac1",           331,   R8A7743_CLK_HP),
+       DEF_MOD("rwdt",                  402,   R8A7743_CLK_R),
        DEF_MOD("irqc",                  407,   R8A7743_CLK_CP),
        DEF_MOD("intc-sys",              408,   R8A7743_CLK_ZS),
        DEF_MOD("audio-dmac1",           501,   R8A7743_CLK_HP),
@@ -195,6 +196,7 @@ static const struct mssr_mod_clk r8a7743_mod_clks[] __initconst = {
 };
 
 static const unsigned int r8a7743_crit_mod_clks[] __initconst = {
+       MOD_CLK_ID(402),        /* RWDT */
        MOD_CLK_ID(408),        /* INTC-SYS (GIC) */
 };
 
index 2859504cc8668199f69f8bd32c4ae3d9c5bdfe3f..87f5a3619e4f9d6058bd6fb185d5116538fcad1a 100644 (file)
@@ -114,6 +114,7 @@ static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = {
        DEF_MOD("cmt1",                  329,   R8A7745_CLK_R),
        DEF_MOD("usbhs-dmac0",           330,   R8A7745_CLK_HP),
        DEF_MOD("usbhs-dmac1",           331,   R8A7745_CLK_HP),
+       DEF_MOD("rwdt",                  402,   R8A7745_CLK_R),
        DEF_MOD("irqc",                  407,   R8A7745_CLK_CP),
        DEF_MOD("intc-sys",              408,   R8A7745_CLK_ZS),
        DEF_MOD("audio-dmac0",           502,   R8A7745_CLK_HP),
@@ -180,6 +181,7 @@ static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = {
 };
 
 static const unsigned int r8a7745_crit_mod_clks[] __initconst = {
+       MOD_CLK_ID(402),        /* RWDT */
        MOD_CLK_ID(408),        /* INTC-SYS (GIC) */
 };
 
index 46bb55bb223de0b668b0947c97561d91517d1158..f936cb74b6811678f8ba93a003a573afc0c0151d 100644 (file)
@@ -140,6 +140,7 @@ static const struct mssr_mod_clk r8a7790_mod_clks[] __initconst = {
        DEF_MOD("cmt1",                  329,   R8A7790_CLK_R),
        DEF_MOD("usbhs-dmac0",           330,   R8A7790_CLK_HP),
        DEF_MOD("usbhs-dmac1",           331,   R8A7790_CLK_HP),
+       DEF_MOD("rwdt",                  402,   R8A7790_CLK_R),
        DEF_MOD("irqc",                  407,   R8A7790_CLK_CP),
        DEF_MOD("intc-sys",              408,   R8A7790_CLK_ZS),
        DEF_MOD("audio-dmac1",           501,   R8A7790_CLK_HP),
@@ -211,6 +212,7 @@ static const struct mssr_mod_clk r8a7790_mod_clks[] __initconst = {
 };
 
 static const unsigned int r8a7790_crit_mod_clks[] __initconst = {
+       MOD_CLK_ID(402),        /* RWDT */
        MOD_CLK_ID(408),        /* INTC-SYS (GIC) */
 };
 
index c0b51f9bb27893500edda12e15b8e0ab99a4f0e5..820b220b09cc6bdbeaa35f7f7c4bcf164d25ef78 100644 (file)
@@ -128,6 +128,7 @@ static const struct mssr_mod_clk r8a7791_mod_clks[] __initconst = {
        DEF_MOD("cmt1",                  329,   R8A7791_CLK_R),
        DEF_MOD("usbhs-dmac0",           330,   R8A7791_CLK_HP),
        DEF_MOD("usbhs-dmac1",           331,   R8A7791_CLK_HP),
+       DEF_MOD("rwdt",                  402,   R8A7791_CLK_R),
        DEF_MOD("irqc",                  407,   R8A7791_CLK_CP),
        DEF_MOD("intc-sys",              408,   R8A7791_CLK_ZS),
        DEF_MOD("audio-dmac1",           501,   R8A7791_CLK_HP),
@@ -209,6 +210,7 @@ static const struct mssr_mod_clk r8a7791_mod_clks[] __initconst = {
 };
 
 static const unsigned int r8a7791_crit_mod_clks[] __initconst = {
+       MOD_CLK_ID(402),        /* RWDT */
        MOD_CLK_ID(408),        /* INTC-SYS (GIC) */
 };
 
index 7f85bbf20bf782b7098a2276a3e0a2eb62f3b24a..609a540804965c404bf5bf5f8bb9ff497c9bc363 100644 (file)
@@ -98,6 +98,7 @@ static const struct mssr_mod_clk r8a7792_mod_clks[] __initconst = {
        DEF_MOD("tpu0",                  304,   R8A7792_CLK_CP),
        DEF_MOD("sdhi0",                 314,   R8A7792_CLK_SD),
        DEF_MOD("cmt1",                  329,   R8A7792_CLK_R),
+       DEF_MOD("rwdt",                  402,   R8A7792_CLK_R),
        DEF_MOD("irqc",                  407,   R8A7792_CLK_CP),
        DEF_MOD("intc-sys",              408,   R8A7792_CLK_ZS),
        DEF_MOD("audio-dmac0",           502,   R8A7792_CLK_HP),
@@ -154,6 +155,7 @@ static const struct mssr_mod_clk r8a7792_mod_clks[] __initconst = {
 };
 
 static const unsigned int r8a7792_crit_mod_clks[] __initconst = {
+       MOD_CLK_ID(402),        /* RWDT */
        MOD_CLK_ID(408),        /* INTC-SYS (GIC) */
 };
 
index ec091a42da54d8c81a9d8460d1ca9037d5fcb7f4..2a40bbeaeeafc2a458b25bd8c8dd3482024db035 100644 (file)
@@ -121,6 +121,7 @@ static const struct mssr_mod_clk r8a7794_mod_clks[] __initconst = {
        DEF_MOD("cmt1",                  329,   R8A7794_CLK_R),
        DEF_MOD("usbhs-dmac0",           330,   R8A7794_CLK_HP),
        DEF_MOD("usbhs-dmac1",           331,   R8A7794_CLK_HP),
+       DEF_MOD("rwdt",                  402,   R8A7794_CLK_R),
        DEF_MOD("irqc",                  407,   R8A7794_CLK_CP),
        DEF_MOD("intc-sys",              408,   R8A7794_CLK_ZS),
        DEF_MOD("audio-dmac0",           502,   R8A7794_CLK_HP),
@@ -190,6 +191,7 @@ static const struct mssr_mod_clk r8a7794_mod_clks[] __initconst = {
 };
 
 static const unsigned int r8a7794_crit_mod_clks[] __initconst = {
+       MOD_CLK_ID(402),        /* RWDT */
        MOD_CLK_ID(408),        /* INTC-SYS (GIC) */
 };
 
index b1d9f48eae9e6ad492d1bc7b634ef4f32c9fd341..775b0ceaa3378a83fe37800ccc1d50c857bd965a 100644 (file)
@@ -74,6 +74,8 @@ static struct cpg_core_clk r8a7795_core_clks[] __initdata = {
        DEF_FIXED(".sdsrc",     CLK_SDSRC,         CLK_PLL1_DIV2,  2, 1),
 
        /* 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_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),
index 41e29734126ba33a805ff2a14a8d0bcf7b5b97a9..dfb267a92f2a20d384b9f0ea1f04859eb71aeefc 100644 (file)
@@ -74,6 +74,8 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
        DEF_FIXED(".sdsrc",     CLK_SDSRC,         CLK_PLL1_DIV2,  2, 1),
 
        /* 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_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),
diff --git a/drivers/clk/renesas/r8a77965-cpg-mssr.c b/drivers/clk/renesas/r8a77965-cpg-mssr.c
new file mode 100644 (file)
index 0000000..b1acfb6
--- /dev/null
@@ -0,0 +1,334 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a77965 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2018 Jacopo Mondi <jacopo+renesas@jmondi.org>
+ *
+ * Based on r8a7795-cpg-mssr.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a77965-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+       /* Core Clock Outputs exported to DT */
+       LAST_DT_CORE_CLK = R8A77965_CLK_OSC,
+
+       /* External Input Clocks */
+       CLK_EXTAL,
+       CLK_EXTALR,
+
+       /* Internal Core Clocks */
+       CLK_MAIN,
+       CLK_PLL0,
+       CLK_PLL1,
+       CLK_PLL3,
+       CLK_PLL4,
+       CLK_PLL1_DIV2,
+       CLK_PLL1_DIV4,
+       CLK_S0,
+       CLK_S1,
+       CLK_S2,
+       CLK_S3,
+       CLK_SDSRC,
+       CLK_SSPSRC,
+       CLK_RINT,
+
+       /* Module Clocks */
+       MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a77965_core_clks[] __initconst = {
+       /* External Clock Inputs */
+       DEF_INPUT("extal",      CLK_EXTAL),
+       DEF_INPUT("extalr",     CLK_EXTALR),
+
+       /* Internal Core Clocks */
+       DEF_BASE(".main",       CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+       DEF_BASE(".pll0",       CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
+       DEF_BASE(".pll1",       CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+       DEF_BASE(".pll3",       CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+       DEF_BASE(".pll4",       CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN),
+
+       DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2,          CLK_PLL1,       2, 1),
+       DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4,          CLK_PLL1_DIV2,  2, 1),
+       DEF_FIXED(".s0",        CLK_S0,                 CLK_PLL1_DIV2,  2, 1),
+       DEF_FIXED(".s1",        CLK_S1,                 CLK_PLL1_DIV2,  3, 1),
+       DEF_FIXED(".s2",        CLK_S2,                 CLK_PLL1_DIV2,  4, 1),
+       DEF_FIXED(".s3",        CLK_S3,                 CLK_PLL1_DIV2,  6, 1),
+       DEF_FIXED(".sdsrc",     CLK_SDSRC,              CLK_PLL1_DIV2,  2, 1),
+
+       /* Core Clock Outputs */
+       DEF_BASE("z",           R8A77965_CLK_Z,         CLK_TYPE_GEN3_Z, CLK_PLL0),
+       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),
+       DEF_FIXED("zx",         R8A77965_CLK_ZX,        CLK_PLL1_DIV2,  2, 1),
+       DEF_FIXED("s0d1",       R8A77965_CLK_S0D1,      CLK_S0,         1, 1),
+       DEF_FIXED("s0d2",       R8A77965_CLK_S0D2,      CLK_S0,         2, 1),
+       DEF_FIXED("s0d3",       R8A77965_CLK_S0D3,      CLK_S0,         3, 1),
+       DEF_FIXED("s0d4",       R8A77965_CLK_S0D4,      CLK_S0,         4, 1),
+       DEF_FIXED("s0d6",       R8A77965_CLK_S0D6,      CLK_S0,         6, 1),
+       DEF_FIXED("s0d8",       R8A77965_CLK_S0D8,      CLK_S0,         8, 1),
+       DEF_FIXED("s0d12",      R8A77965_CLK_S0D12,     CLK_S0,         12, 1),
+       DEF_FIXED("s1d1",       R8A77965_CLK_S1D1,      CLK_S1,         1, 1),
+       DEF_FIXED("s1d2",       R8A77965_CLK_S1D2,      CLK_S1,         2, 1),
+       DEF_FIXED("s1d4",       R8A77965_CLK_S1D4,      CLK_S1,         4, 1),
+       DEF_FIXED("s2d1",       R8A77965_CLK_S2D1,      CLK_S2,         1, 1),
+       DEF_FIXED("s2d2",       R8A77965_CLK_S2D2,      CLK_S2,         2, 1),
+       DEF_FIXED("s2d4",       R8A77965_CLK_S2D4,      CLK_S2,         4, 1),
+       DEF_FIXED("s3d1",       R8A77965_CLK_S3D1,      CLK_S3,         1, 1),
+       DEF_FIXED("s3d2",       R8A77965_CLK_S3D2,      CLK_S3,         2, 1),
+       DEF_FIXED("s3d4",       R8A77965_CLK_S3D4,      CLK_S3,         4, 1),
+
+       DEF_GEN3_SD("sd0",      R8A77965_CLK_SD0,       CLK_SDSRC,      0x074),
+       DEF_GEN3_SD("sd1",      R8A77965_CLK_SD1,       CLK_SDSRC,      0x078),
+       DEF_GEN3_SD("sd2",      R8A77965_CLK_SD2,       CLK_SDSRC,      0x268),
+       DEF_GEN3_SD("sd3",      R8A77965_CLK_SD3,       CLK_SDSRC,      0x26c),
+
+       DEF_FIXED("cl",         R8A77965_CLK_CL,        CLK_PLL1_DIV2,  48, 1),
+       DEF_FIXED("cp",         R8A77965_CLK_CP,        CLK_EXTAL,      2, 1),
+
+       DEF_DIV6P1("canfd",     R8A77965_CLK_CANFD,     CLK_PLL1_DIV4,  0x244),
+       DEF_DIV6P1("csi0",      R8A77965_CLK_CSI0,      CLK_PLL1_DIV4,  0x00c),
+       DEF_DIV6P1("mso",       R8A77965_CLK_MSO,       CLK_PLL1_DIV4,  0x014),
+       DEF_DIV6P1("hdmi",      R8A77965_CLK_HDMI,      CLK_PLL1_DIV4,  0x250),
+
+       DEF_DIV6_RO("osc",      R8A77965_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8),
+       DEF_DIV6_RO("r_int",    CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32),
+
+       DEF_BASE("r",           R8A77965_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
+};
+
+static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = {
+       DEF_MOD("scif5",                202,    R8A77965_CLK_S3D4),
+       DEF_MOD("scif4",                203,    R8A77965_CLK_S3D4),
+       DEF_MOD("scif3",                204,    R8A77965_CLK_S3D4),
+       DEF_MOD("scif1",                206,    R8A77965_CLK_S3D4),
+       DEF_MOD("scif0",                207,    R8A77965_CLK_S3D4),
+       DEF_MOD("sys-dmac2",            217,    R8A77965_CLK_S0D3),
+       DEF_MOD("sys-dmac1",            218,    R8A77965_CLK_S0D3),
+       DEF_MOD("sys-dmac0",            219,    R8A77965_CLK_S0D3),
+
+       DEF_MOD("cmt3",                 300,    R8A77965_CLK_R),
+       DEF_MOD("cmt2",                 301,    R8A77965_CLK_R),
+       DEF_MOD("cmt1",                 302,    R8A77965_CLK_R),
+       DEF_MOD("cmt0",                 303,    R8A77965_CLK_R),
+       DEF_MOD("scif2",                310,    R8A77965_CLK_S3D4),
+       DEF_MOD("sdif3",                311,    R8A77965_CLK_SD3),
+       DEF_MOD("sdif2",                312,    R8A77965_CLK_SD2),
+       DEF_MOD("sdif1",                313,    R8A77965_CLK_SD1),
+       DEF_MOD("sdif0",                314,    R8A77965_CLK_SD0),
+       DEF_MOD("pcie1",                318,    R8A77965_CLK_S3D1),
+       DEF_MOD("pcie0",                319,    R8A77965_CLK_S3D1),
+       DEF_MOD("usb3-if0",             328,    R8A77965_CLK_S3D1),
+       DEF_MOD("usb-dmac0",            330,    R8A77965_CLK_S3D1),
+       DEF_MOD("usb-dmac1",            331,    R8A77965_CLK_S3D1),
+
+       DEF_MOD("rwdt",                 402,    R8A77965_CLK_R),
+       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("hscif4",               516,    R8A77965_CLK_S3D1),
+       DEF_MOD("hscif3",               517,    R8A77965_CLK_S3D1),
+       DEF_MOD("hscif2",               518,    R8A77965_CLK_S3D1),
+       DEF_MOD("hscif1",               519,    R8A77965_CLK_S3D1),
+       DEF_MOD("hscif0",               520,    R8A77965_CLK_S3D1),
+       DEF_MOD("thermal",              522,    R8A77965_CLK_CP),
+       DEF_MOD("pwm",                  523,    R8A77965_CLK_S0D12),
+
+       DEF_MOD("fcpvd1",               602,    R8A77965_CLK_S0D2),
+       DEF_MOD("fcpvd0",               603,    R8A77965_CLK_S0D2),
+       DEF_MOD("fcpvb0",               607,    R8A77965_CLK_S0D1),
+       DEF_MOD("fcpvi0",               611,    R8A77965_CLK_S0D1),
+       DEF_MOD("fcpf0",                615,    R8A77965_CLK_S0D1),
+       DEF_MOD("fcpcs",                619,    R8A77965_CLK_S0D2),
+       DEF_MOD("vspd1",                622,    R8A77965_CLK_S0D2),
+       DEF_MOD("vspd0",                623,    R8A77965_CLK_S0D2),
+       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("csi20",                714,    R8A77965_CLK_CSI0),
+       DEF_MOD("csi40",                716,    R8A77965_CLK_CSI0),
+       DEF_MOD("du3",                  721,    R8A77965_CLK_S2D1),
+       DEF_MOD("du1",                  723,    R8A77965_CLK_S2D1),
+       DEF_MOD("du0",                  724,    R8A77965_CLK_S2D1),
+       DEF_MOD("lvds",                 727,    R8A77965_CLK_S2D1),
+       DEF_MOD("hdmi0",                729,    R8A77965_CLK_HDMI),
+
+       DEF_MOD("vin7",                 804,    R8A77965_CLK_S0D2),
+       DEF_MOD("vin6",                 805,    R8A77965_CLK_S0D2),
+       DEF_MOD("vin5",                 806,    R8A77965_CLK_S0D2),
+       DEF_MOD("vin4",                 807,    R8A77965_CLK_S0D2),
+       DEF_MOD("vin3",                 808,    R8A77965_CLK_S0D2),
+       DEF_MOD("vin2",                 809,    R8A77965_CLK_S0D2),
+       DEF_MOD("vin1",                 810,    R8A77965_CLK_S0D2),
+       DEF_MOD("vin0",                 811,    R8A77965_CLK_S0D2),
+       DEF_MOD("etheravb",             812,    R8A77965_CLK_S0D6),
+       DEF_MOD("imr1",                 822,    R8A77965_CLK_S0D2),
+       DEF_MOD("imr0",                 823,    R8A77965_CLK_S0D2),
+
+       DEF_MOD("gpio7",                905,    R8A77965_CLK_S3D4),
+       DEF_MOD("gpio6",                906,    R8A77965_CLK_S3D4),
+       DEF_MOD("gpio5",                907,    R8A77965_CLK_S3D4),
+       DEF_MOD("gpio4",                908,    R8A77965_CLK_S3D4),
+       DEF_MOD("gpio3",                909,    R8A77965_CLK_S3D4),
+       DEF_MOD("gpio2",                910,    R8A77965_CLK_S3D4),
+       DEF_MOD("gpio1",                911,    R8A77965_CLK_S3D4),
+       DEF_MOD("gpio0",                912,    R8A77965_CLK_S3D4),
+       DEF_MOD("can-fd",               914,    R8A77965_CLK_S3D2),
+       DEF_MOD("can-if1",              915,    R8A77965_CLK_S3D4),
+       DEF_MOD("can-if0",              916,    R8A77965_CLK_S3D4),
+       DEF_MOD("i2c6",                 918,    R8A77965_CLK_S0D6),
+       DEF_MOD("i2c5",                 919,    R8A77965_CLK_S0D6),
+       DEF_MOD("i2c-dvfs",             926,    R8A77965_CLK_CP),
+       DEF_MOD("i2c4",                 927,    R8A77965_CLK_S0D6),
+       DEF_MOD("i2c3",                 928,    R8A77965_CLK_S0D6),
+       DEF_MOD("i2c2",                 929,    R8A77965_CLK_S3D2),
+       DEF_MOD("i2c1",                 930,    R8A77965_CLK_S3D2),
+       DEF_MOD("i2c0",                 931,    R8A77965_CLK_S3D2),
+
+       DEF_MOD("ssi-all",              1005,   R8A77965_CLK_S3D4),
+       DEF_MOD("ssi9",                 1006,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi8",                 1007,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi7",                 1008,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi6",                 1009,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi5",                 1010,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi4",                 1011,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi3",                 1012,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi2",                 1013,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi1",                 1014,   MOD_CLK_ID(1005)),
+       DEF_MOD("ssi0",                 1015,   MOD_CLK_ID(1005)),
+       DEF_MOD("scu-all",              1017,   R8A77965_CLK_S3D4),
+       DEF_MOD("scu-dvc1",             1018,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-dvc0",             1019,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-ctu1-mix1",        1020,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-ctu0-mix0",        1021,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src9",             1022,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src8",             1023,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src7",             1024,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src6",             1025,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src5",             1026,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src4",             1027,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src3",             1028,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src2",             1029,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src1",             1030,   MOD_CLK_ID(1017)),
+       DEF_MOD("scu-src0",             1031,   MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a77965_crit_mod_clks[] __initconst = {
+       MOD_CLK_ID(408),        /* INTC-AP (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ *   MD                EXTAL           PLL0    PLL1    PLL3    PLL4
+ * 14 13 19 17 (MHz)
+ *-----------------------------------------------------------
+ * 0  0  0  0  16.66 x 1       x180    x192    x192    x144
+ * 0  0  0  1  16.66 x 1       x180    x192    x128    x144
+ * 0  0  1  0  Prohibited setting
+ * 0  0  1  1  16.66 x 1       x180    x192    x192    x144
+ * 0  1  0  0  20    x 1       x150    x160    x160    x120
+ * 0  1  0  1  20    x 1       x150    x160    x106    x120
+ * 0  1  1  0  Prohibited setting
+ * 0  1  1  1  20    x 1       x150    x160    x160    x120
+ * 1  0  0  0  25    x 1       x120    x128    x128    x96
+ * 1  0  0  1  25    x 1       x120    x128    x84     x96
+ * 1  0  1  0  Prohibited setting
+ * 1  0  1  1  25    x 1       x120    x128    x128    x96
+ * 1  1  0  0  33.33 / 2       x180    x192    x192    x144
+ * 1  1  0  1  33.33 / 2       x180    x192    x128    x144
+ * 1  1  1  0  Prohibited setting
+ * 1  1  1  1  33.33 / 2       x180    x192    x192    x144
+ */
+#define CPG_PLL_CONFIG_INDEX(md)       ((((md) & BIT(14)) >> 11) | \
+                                        (((md) & BIT(13)) >> 11) | \
+                                        (((md) & BIT(19)) >> 18) | \
+                                        (((md) & BIT(17)) >> 17))
+
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
+       /* EXTAL div    PLL1 mult/div   PLL3 mult/div */
+       { 1,            192,    1,      192,    1,      },
+       { 1,            192,    1,      128,    1,      },
+       { 0, /* Prohibited setting */                   },
+       { 1,            192,    1,      192,    1,      },
+       { 1,            160,    1,      160,    1,      },
+       { 1,            160,    1,      106,    1,      },
+       { 0, /* Prohibited setting */                   },
+       { 1,            160,    1,      160,    1,      },
+       { 1,            128,    1,      128,    1,      },
+       { 1,            128,    1,      84,     1,      },
+       { 0, /* Prohibited setting */                   },
+       { 1,            128,    1,      128,    1,      },
+       { 2,            192,    1,      192,    1,      },
+       { 2,            192,    1,      128,    1,      },
+       { 0, /* Prohibited setting */                   },
+       { 2,            192,    1,      192,    1,      },
+};
+
+static int __init r8a77965_cpg_mssr_init(struct device *dev)
+{
+       const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+       u32 cpg_mode;
+       int error;
+
+       error = rcar_rst_read_mode_pins(&cpg_mode);
+       if (error)
+               return error;
+
+       cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+       if (!cpg_pll_config->extal_div) {
+               dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
+               return -EINVAL;
+       }
+
+       return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+};
+
+const struct cpg_mssr_info r8a77965_cpg_mssr_info __initconst = {
+       /* Core Clocks */
+       .core_clks              = r8a77965_core_clks,
+       .num_core_clks          = ARRAY_SIZE(r8a77965_core_clks),
+       .last_dt_core_clk       = LAST_DT_CORE_CLK,
+       .num_total_core_clks    = MOD_CLK_BASE,
+
+       /* Module Clocks */
+       .mod_clks               = r8a77965_mod_clks,
+       .num_mod_clks           = ARRAY_SIZE(r8a77965_mod_clks),
+       .num_hw_mod_clks        = 12 * 32,
+
+       /* Critical Module Clocks */
+       .crit_mod_clks          = r8a77965_crit_mod_clks,
+       .num_crit_mod_clks      = ARRAY_SIZE(r8a77965_crit_mod_clks),
+
+       /* Callbacks */
+       .init                   = r8a77965_cpg_mssr_init,
+       .cpg_clk_register       = rcar_gen3_cpg_clk_register,
+};
diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c
new file mode 100644 (file)
index 0000000..7aaae73
--- /dev/null
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * r8a77980 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ * Copyright (C) 2018 Cogent Embedded, Inc.
+ *
+ * Based on r8a7795-cpg-mssr.c
+ *
+ * Copyright (C) 2015 Glider bvba
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+#include <linux/sys_soc.h>
+
+#include <dt-bindings/clock/r8a77980-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen3-cpg.h"
+
+enum clk_ids {
+       /* Core Clock Outputs exported to DT */
+       LAST_DT_CORE_CLK = R8A77980_CLK_OSC,
+
+       /* External Input Clocks */
+       CLK_EXTAL,
+       CLK_EXTALR,
+
+       /* Internal Core Clocks */
+       CLK_MAIN,
+       CLK_PLL1,
+       CLK_PLL2,
+       CLK_PLL3,
+       CLK_PLL1_DIV2,
+       CLK_PLL1_DIV4,
+       CLK_S0,
+       CLK_S1,
+       CLK_S2,
+       CLK_S3,
+       CLK_SDSRC,
+
+       /* Module Clocks */
+       MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a77980_core_clks[] __initconst = {
+       /* External Clock Inputs */
+       DEF_INPUT("extal",  CLK_EXTAL),
+       DEF_INPUT("extalr", CLK_EXTALR),
+
+       /* Internal Core Clocks */
+       DEF_BASE(".main",       CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
+       DEF_BASE(".pll1",       CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
+       DEF_BASE(".pll2",       CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN),
+       DEF_BASE(".pll3",       CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
+
+       DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2,     CLK_PLL1,       2, 1),
+       DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4,     CLK_PLL1_DIV2,  2, 1),
+       DEF_FIXED(".s0",        CLK_S0,            CLK_PLL1_DIV2,  2, 1),
+       DEF_FIXED(".s1",        CLK_S1,            CLK_PLL1_DIV2,  3, 1),
+       DEF_FIXED(".s2",        CLK_S2,            CLK_PLL1_DIV2,  4, 1),
+       DEF_FIXED(".s3",        CLK_S3,            CLK_PLL1_DIV2,  6, 1),
+       DEF_FIXED(".sdsrc",     CLK_SDSRC,         CLK_PLL1_DIV2,  2, 1),
+
+       /* Core Clock Outputs */
+       DEF_FIXED("ztr",        R8A77980_CLK_ZTR,   CLK_PLL1_DIV2,  6, 1),
+       DEF_FIXED("ztrd2",      R8A77980_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
+       DEF_FIXED("zt",         R8A77980_CLK_ZT,    CLK_PLL1_DIV2,  4, 1),
+       DEF_FIXED("zx",         R8A77980_CLK_ZX,    CLK_PLL1_DIV2,  2, 1),
+       DEF_FIXED("s0d1",       R8A77980_CLK_S0D1,  CLK_S0,         1, 1),
+       DEF_FIXED("s0d2",       R8A77980_CLK_S0D2,  CLK_S0,         2, 1),
+       DEF_FIXED("s0d3",       R8A77980_CLK_S0D3,  CLK_S0,         3, 1),
+       DEF_FIXED("s0d4",       R8A77980_CLK_S0D4,  CLK_S0,         4, 1),
+       DEF_FIXED("s0d6",       R8A77980_CLK_S0D6,  CLK_S0,         6, 1),
+       DEF_FIXED("s0d12",      R8A77980_CLK_S0D12, CLK_S0,        12, 1),
+       DEF_FIXED("s0d24",      R8A77980_CLK_S0D24, CLK_S0,        24, 1),
+       DEF_FIXED("s1d1",       R8A77980_CLK_S1D1,  CLK_S1,         1, 1),
+       DEF_FIXED("s1d2",       R8A77980_CLK_S1D2,  CLK_S1,         2, 1),
+       DEF_FIXED("s1d4",       R8A77980_CLK_S1D4,  CLK_S1,         4, 1),
+       DEF_FIXED("s2d1",       R8A77980_CLK_S2D1,  CLK_S2,         1, 1),
+       DEF_FIXED("s2d2",       R8A77980_CLK_S2D2,  CLK_S2,         2, 1),
+       DEF_FIXED("s2d4",       R8A77980_CLK_S2D4,  CLK_S2,         4, 1),
+       DEF_FIXED("s3d1",       R8A77980_CLK_S3D1,  CLK_S3,         1, 1),
+       DEF_FIXED("s3d2",       R8A77980_CLK_S3D2,  CLK_S3,         2, 1),
+       DEF_FIXED("s3d4",       R8A77980_CLK_S3D4,  CLK_S3,         4, 1),
+
+       DEF_GEN3_SD("sd0",      R8A77980_CLK_SD0,   CLK_SDSRC,    0x0074),
+
+       DEF_FIXED("cl",         R8A77980_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
+       DEF_FIXED("cp",         R8A77980_CLK_CP,    CLK_EXTAL,      2, 1),
+       DEF_FIXED("cpex",       R8A77980_CLK_CPEX,  CLK_EXTAL,      2, 1),
+
+       DEF_DIV6P1("canfd",     R8A77980_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
+       DEF_DIV6P1("csi0",      R8A77980_CLK_CSI0,  CLK_PLL1_DIV4, 0x00c),
+       DEF_DIV6P1("mso",       R8A77980_CLK_MSO,   CLK_PLL1_DIV4, 0x014),
+};
+
+static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = {
+       DEF_MOD("tmu4",                  121,   R8A77980_CLK_S0D6),
+       DEF_MOD("tmu3",                  122,   R8A77980_CLK_S0D6),
+       DEF_MOD("tmu2",                  123,   R8A77980_CLK_S0D6),
+       DEF_MOD("tmu1",                  124,   R8A77980_CLK_S0D6),
+       DEF_MOD("tmu0",                  125,   R8A77980_CLK_CP),
+       DEF_MOD("scif4",                 203,   R8A77980_CLK_S3D4),
+       DEF_MOD("scif3",                 204,   R8A77980_CLK_S3D4),
+       DEF_MOD("scif1",                 206,   R8A77980_CLK_S3D4),
+       DEF_MOD("scif0",                 207,   R8A77980_CLK_S3D4),
+       DEF_MOD("msiof3",                208,   R8A77980_CLK_MSO),
+       DEF_MOD("msiof2",                209,   R8A77980_CLK_MSO),
+       DEF_MOD("msiof1",                210,   R8A77980_CLK_MSO),
+       DEF_MOD("msiof0",                211,   R8A77980_CLK_MSO),
+       DEF_MOD("sys-dmac2",             217,   R8A77980_CLK_S0D3),
+       DEF_MOD("sys-dmac1",             218,   R8A77980_CLK_S0D3),
+       DEF_MOD("tpu0",                  304,   R8A77980_CLK_S3D4),
+       DEF_MOD("sdif",                  314,   R8A77980_CLK_SD0),
+       DEF_MOD("pciec0",                319,   R8A77980_CLK_S3D1),
+       DEF_MOD("intc-ex",               407,   R8A77980_CLK_CP),
+       DEF_MOD("intc-ap",               408,   R8A77980_CLK_S0D3),
+       DEF_MOD("hscif3",                517,   R8A77980_CLK_S3D1),
+       DEF_MOD("hscif2",                518,   R8A77980_CLK_S3D1),
+       DEF_MOD("hscif1",                519,   R8A77980_CLK_S3D1),
+       DEF_MOD("hscif0",                520,   R8A77980_CLK_S3D1),
+       DEF_MOD("imp4",                  521,   R8A77980_CLK_S1D1),
+       DEF_MOD("thermal",               522,   R8A77980_CLK_CP),
+       DEF_MOD("pwm",                   523,   R8A77980_CLK_S0D12),
+       DEF_MOD("impdma1",               526,   R8A77980_CLK_S1D1),
+       DEF_MOD("impdma0",               527,   R8A77980_CLK_S1D1),
+       DEF_MOD("imp-ocv4",              528,   R8A77980_CLK_S1D1),
+       DEF_MOD("imp-ocv3",              529,   R8A77980_CLK_S1D1),
+       DEF_MOD("imp-ocv2",              531,   R8A77980_CLK_S1D1),
+       DEF_MOD("fcpvd0",                603,   R8A77980_CLK_S3D1),
+       DEF_MOD("vspd0",                 623,   R8A77980_CLK_S3D1),
+       DEF_MOD("csi41",                 715,   R8A77980_CLK_CSI0),
+       DEF_MOD("csi40",                 716,   R8A77980_CLK_CSI0),
+       DEF_MOD("du0",                   724,   R8A77980_CLK_S2D1),
+       DEF_MOD("lvds",                  727,   R8A77980_CLK_S2D1),
+       DEF_MOD("etheravb",              812,   R8A77980_CLK_S3D2),
+       DEF_MOD("gether",                813,   R8A77980_CLK_S3D2),
+       DEF_MOD("imp3",                  824,   R8A77980_CLK_S1D1),
+       DEF_MOD("imp2",                  825,   R8A77980_CLK_S1D1),
+       DEF_MOD("imp1",                  826,   R8A77980_CLK_S1D1),
+       DEF_MOD("imp0",                  827,   R8A77980_CLK_S1D1),
+       DEF_MOD("imp-ocv1",              828,   R8A77980_CLK_S1D1),
+       DEF_MOD("imp-ocv0",              829,   R8A77980_CLK_S1D1),
+       DEF_MOD("impram",                830,   R8A77980_CLK_S1D1),
+       DEF_MOD("impcnn",                831,   R8A77980_CLK_S1D1),
+       DEF_MOD("gpio5",                 907,   R8A77980_CLK_CP),
+       DEF_MOD("gpio4",                 908,   R8A77980_CLK_CP),
+       DEF_MOD("gpio3",                 909,   R8A77980_CLK_CP),
+       DEF_MOD("gpio2",                 910,   R8A77980_CLK_CP),
+       DEF_MOD("gpio1",                 911,   R8A77980_CLK_CP),
+       DEF_MOD("gpio0",                 912,   R8A77980_CLK_CP),
+       DEF_MOD("can-fd",                914,   R8A77980_CLK_S3D2),
+       DEF_MOD("i2c4",                  927,   R8A77980_CLK_S0D6),
+       DEF_MOD("i2c3",                  928,   R8A77980_CLK_S0D6),
+       DEF_MOD("i2c2",                  929,   R8A77980_CLK_S3D2),
+       DEF_MOD("i2c1",                  930,   R8A77980_CLK_S3D2),
+       DEF_MOD("i2c0",                  931,   R8A77980_CLK_S3D2),
+};
+
+static const unsigned int r8a77980_crit_mod_clks[] __initconst = {
+       MOD_CLK_ID(408),        /* INTC-AP (GIC) */
+};
+
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ *   MD                EXTAL           PLL2    PLL1    PLL3
+ * 14 13       (MHz)
+ * --------------------------------------------------
+ * 0  0                16.66 x 1       x240    x192    x192
+ * 0  1                20    x 1       x200    x160    x160
+ * 1  0                27    x 1       x148    x118    x118
+ * 1  1                33.33 / 2       x240    x192    x192
+ */
+#define CPG_PLL_CONFIG_INDEX(md)       ((((md) & BIT(14)) >> 13) | \
+                                        (((md) & BIT(13)) >> 13))
+
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[4] __initconst = {
+       /* EXTAL div    PLL1 mult/div   PLL3 mult/div */
+       { 1,            192,    1,      192,    1,      },
+       { 1,            160,    1,      160,    1,      },
+       { 1,            118,    1,      118,    1,      },
+       { 2,            192,    1,      192,    1,      },
+};
+
+static int __init r8a77980_cpg_mssr_init(struct device *dev)
+{
+       const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
+       u32 cpg_mode;
+       int error;
+
+       error = rcar_rst_read_mode_pins(&cpg_mode);
+       if (error)
+               return error;
+
+       cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+       return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a77980_cpg_mssr_info __initconst = {
+       /* Core Clocks */
+       .core_clks = r8a77980_core_clks,
+       .num_core_clks = ARRAY_SIZE(r8a77980_core_clks),
+       .last_dt_core_clk = LAST_DT_CORE_CLK,
+       .num_total_core_clks = MOD_CLK_BASE,
+
+       /* Module Clocks */
+       .mod_clks = r8a77980_mod_clks,
+       .num_mod_clks = ARRAY_SIZE(r8a77980_mod_clks),
+       .num_hw_mod_clks = 12 * 32,
+
+       /* Critical Module Clocks */
+       .crit_mod_clks = r8a77980_crit_mod_clks,
+       .num_crit_mod_clks = ARRAY_SIZE(r8a77980_crit_mod_clks),
+
+       /* Callbacks */
+       .init = r8a77980_cpg_mssr_init,
+       .cpg_clk_register = rcar_gen3_cpg_clk_register,
+};
index 0904886f55015a3bdf309f7bdb38add0fd08a7e3..628b63b85d3f09c5cfdf37dea4b565953e41264a 100644 (file)
@@ -13,6 +13,7 @@
  */
 
 #include <linux/bug.h>
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/device.h>
@@ -61,6 +62,140 @@ static void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
        raw_notifier_chain_register(notifiers, &csn->nb);
 }
 
+/*
+ * Z Clock & Z2 Clock
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable.  clk->rate = (parent->rate * mult / 32 ) / 2
+ * parent - fixed parent.  No clk_set_parent support
+ */
+#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;
+};
+
+#define to_z_clk(_hw)  container_of(_hw, struct cpg_z_clk, hw)
+
+static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
+                                          unsigned long parent_rate)
+{
+       struct cpg_z_clk *zclk = to_z_clk(hw);
+       unsigned int mult;
+       u32 val;
+
+       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);
+}
+
+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;
+       unsigned int mult;
+
+       mult = div_u64(rate * 32ULL, prate);
+       mult = clamp(mult, 1U, 32U);
+
+       return (u64)prate * mult / 32;
+}
+
+static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+                             unsigned long parent_rate)
+{
+       struct cpg_z_clk *zclk = to_z_clk(hw);
+       unsigned int mult;
+       unsigned int i;
+       u32 val, kick;
+
+       /* Factor of 2 is for fixed divider */
+       mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL * 2, parent_rate);
+       mult = clamp(mult, 1U, 32U);
+
+       if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+               return -EBUSY;
+
+       val = readl(zclk->reg) & ~zclk->mask;
+       val |= ((32 - mult) << __ffs(zclk->mask)) & zclk->mask;
+       writel(val, zclk->reg);
+
+       /*
+        * Set KICK bit in FRQCRB to update hardware setting and wait for
+        * clock change completion.
+        */
+       kick = readl(zclk->kick_reg);
+       kick |= CPG_FRQCRB_KICK;
+       writel(kick, zclk->kick_reg);
+
+       /*
+        * Note: There is no HW information about the worst case latency.
+        *
+        * Using experimental measurements, it seems that no more than
+        * ~10 iterations are needed, independently of the CPU rate.
+        * Since this value might be dependent of external xtal rate, pll1
+        * rate or even the other emulation clocks rate, use 1000 as a
+        * "super" safe value.
+        */
+       for (i = 1000; i; i--) {
+               if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+                       return 0;
+
+               cpu_relax();
+       }
+
+       return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_z_clk_ops = {
+       .recalc_rate = cpg_z_clk_recalc_rate,
+       .round_rate = cpg_z_clk_round_rate,
+       .set_rate = cpg_z_clk_set_rate,
+};
+
+static struct clk * __init cpg_z_clk_register(const char *name,
+                                             const char *parent_name,
+                                             void __iomem *reg,
+                                             unsigned long mask)
+{
+       struct clk_init_data init;
+       struct cpg_z_clk *zclk;
+       struct clk *clk;
+
+       zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
+       if (!zclk)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &cpg_z_clk_ops;
+       init.flags = 0;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       zclk->reg = reg + CPG_FRQCRC;
+       zclk->kick_reg = reg + CPG_FRQCRB;
+       zclk->hw.init = &init;
+       zclk->mask = mask;
+
+       clk = clk_register(NULL, &zclk->hw);
+       if (IS_ERR(clk))
+               kfree(zclk);
+
+       return clk;
+}
+
 /*
  * SDn Clock
  */
@@ -420,6 +555,14 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
                mult = 1;
                break;
 
+       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);
+
        default:
                return ERR_PTR(-EINVAL);
        }
index 2e4284399f530f96cf249238a5beb813408d8d34..ea4f8fc3c4c972e79418cef9a251bad3bd4fcbee 100644 (file)
@@ -21,6 +21,8 @@ enum rcar_gen3_clk_types {
        CLK_TYPE_GEN3_SD,
        CLK_TYPE_GEN3_R,
        CLK_TYPE_GEN3_PE,
+       CLK_TYPE_GEN3_Z,
+       CLK_TYPE_GEN3_Z2,
 };
 
 #define DEF_GEN3_SD(_name, _id, _parent, _offset)      \
index e3cc72c813114b79e35407f291ab32e05234e3cc..4e88e980fb7697fce7fd4b68d32d78b4c3666ec0 100644 (file)
@@ -693,12 +693,24 @@ static const struct of_device_id cpg_mssr_match[] = {
                .data = &r8a7796_cpg_mssr_info,
        },
 #endif
+#ifdef CONFIG_CLK_R8A77965
+       {
+               .compatible = "renesas,r8a77965-cpg-mssr",
+               .data = &r8a77965_cpg_mssr_info,
+       },
+#endif
 #ifdef CONFIG_CLK_R8A77970
        {
                .compatible = "renesas,r8a77970-cpg-mssr",
                .data = &r8a77970_cpg_mssr_info,
        },
 #endif
+#ifdef CONFIG_CLK_R8A77980
+       {
+               .compatible = "renesas,r8a77980-cpg-mssr",
+               .data = &r8a77980_cpg_mssr_info,
+       },
+#endif
 #ifdef CONFIG_CLK_R8A77995
        {
                .compatible = "renesas,r8a77995-cpg-mssr",
index 0745b09303082ef9bf65288bca5dac66ae0b00c1..97ccb093c10fc93541ca341f1d7611bb508fd03b 100644 (file)
@@ -139,7 +139,9 @@ extern const struct cpg_mssr_info r8a7792_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a7794_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a7795_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a7796_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a77965_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a77970_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a77980_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a77995_cpg_mssr_info;
 
 
index 077fcdc7908bb9f3791fe20bc60a0266327ca050..026a26bb702d9b9f6ab53a6ffaa8864149dfc01b 100644 (file)
@@ -25,6 +25,8 @@ struct rockchip_mmc_clock {
        void __iomem    *reg;
        int             id;
        int             shift;
+       int             cached_phase;
+       struct notifier_block clk_rate_change_nb;
 };
 
 #define to_mmc_clock(_hw) container_of(_hw, struct rockchip_mmc_clock, hw)
@@ -58,6 +60,12 @@ static int rockchip_mmc_get_phase(struct clk_hw *hw)
        u16 degrees;
        u32 delay_num = 0;
 
+       /* See the comment for rockchip_mmc_set_phase below */
+       if (!rate) {
+               pr_err("%s: invalid clk rate\n", __func__);
+               return -EINVAL;
+       }
+
        raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift);
 
        degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
@@ -84,6 +92,23 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
        u32 raw_value;
        u32 delay;
 
+       /*
+        * The below calculation is based on the output clock from
+        * MMC host to the card, which expects the phase clock inherits
+        * the clock rate from its parent, namely the output clock
+        * provider of MMC host. However, things may go wrong if
+        * (1) It is orphan.
+        * (2) It is assigned to the wrong parent.
+        *
+        * This check help debug the case (1), which seems to be the
+        * most likely problem we often face and which makes it difficult
+        * for people to debug unstable mmc tuning results.
+        */
+       if (!rate) {
+               pr_err("%s: invalid clk rate\n", __func__);
+               return -EINVAL;
+       }
+
        nineties = degrees / 90;
        remainder = (degrees % 90);
 
@@ -139,6 +164,41 @@ static const struct clk_ops rockchip_mmc_clk_ops = {
        .set_phase      = rockchip_mmc_set_phase,
 };
 
+#define to_rockchip_mmc_clock(x) \
+       container_of(x, struct rockchip_mmc_clock, clk_rate_change_nb)
+static int rockchip_mmc_clk_rate_notify(struct notifier_block *nb,
+                                       unsigned long event, void *data)
+{
+       struct rockchip_mmc_clock *mmc_clock = to_rockchip_mmc_clock(nb);
+       struct clk_notifier_data *ndata = data;
+
+       /*
+        * rockchip_mmc_clk is mostly used by mmc controllers to sample
+        * the intput data, which expects the fixed phase after the tuning
+        * process. However if the clock rate is changed, the phase is stale
+        * and may break the data sampling. So here we try to restore the phase
+        * for that case, except that
+        * (1) cached_phase is invaild since we inevitably cached it when the
+        * clock provider be reparented from orphan to its real parent in the
+        * first place. Otherwise we may mess up the initialization of MMC cards
+        * since we only set the default sample phase and drive phase later on.
+        * (2) the new coming rate is higher than the older one since mmc driver
+        * set the max-frequency to match the boards' ability but we can't go
+        * over the heads of that, otherwise the tests smoke out the issue.
+        */
+       if (ndata->old_rate <= ndata->new_rate)
+               return NOTIFY_DONE;
+
+       if (event == PRE_RATE_CHANGE)
+               mmc_clock->cached_phase =
+                       rockchip_mmc_get_phase(&mmc_clock->hw);
+       else if (mmc_clock->cached_phase != -EINVAL &&
+                event == POST_RATE_CHANGE)
+               rockchip_mmc_set_phase(&mmc_clock->hw, mmc_clock->cached_phase);
+
+       return NOTIFY_DONE;
+}
+
 struct clk *rockchip_clk_register_mmc(const char *name,
                                const char *const *parent_names, u8 num_parents,
                                void __iomem *reg, int shift)
@@ -146,6 +206,7 @@ struct clk *rockchip_clk_register_mmc(const char *name,
        struct clk_init_data init;
        struct rockchip_mmc_clock *mmc_clock;
        struct clk *clk;
+       int ret;
 
        mmc_clock = kmalloc(sizeof(*mmc_clock), GFP_KERNEL);
        if (!mmc_clock)
@@ -162,8 +223,21 @@ struct clk *rockchip_clk_register_mmc(const char *name,
        mmc_clock->shift = shift;
 
        clk = clk_register(NULL, &mmc_clock->hw);
-       if (IS_ERR(clk))
-               kfree(mmc_clock);
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
+               goto err_register;
+       }
+
+       mmc_clock->clk_rate_change_nb.notifier_call =
+                               &rockchip_mmc_clk_rate_notify;
+       ret = clk_notifier_register(clk, &mmc_clock->clk_rate_change_nb);
+       if (ret)
+               goto err_notifier;
 
        return clk;
+err_notifier:
+       clk_unregister(clk);
+err_register:
+       kfree(mmc_clock);
+       return ERR_PTR(ret);
 }
index 11e7f2d1c0548166f8b762582414b3337f363a6f..7af48184b0224b1428ba1e9788f941511a47c9bb 100644 (file)
@@ -387,7 +387,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
                        RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 6, DFLAGS,
                        RK2928_CLKGATE_CON(2), 15, GFLAGS),
 
-       COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
+       COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0,
                        RK2928_CLKSEL_CON(11), 8, 2, MFLAGS, 0, 8, DFLAGS,
                        RK2928_CLKGATE_CON(2), 11, GFLAGS),
 
index b04f29774ee73c53924ecd1d4a7aae6f2116e419..252366a5231f766dd6a9df28fb7a755b7a6021f7 100644 (file)
@@ -304,7 +304,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
        COMPOSITE_NOMUX(0, "aclk_core", "armclk", CLK_IGNORE_UNUSED,
                        RK3328_CLKSEL_CON(1), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
                        RK3328_CLKGATE_CON(7), 1, GFLAGS),
-       GATE(0, "aclk_core_niu", "aclk_core", CLK_IGNORE_UNUSED,
+       GATE(0, "aclk_core_niu", "aclk_core", 0,
                        RK3328_CLKGATE_CON(13), 0, GFLAGS),
        GATE(0, "aclk_gic400", "aclk_core", CLK_IGNORE_UNUSED,
                        RK3328_CLKGATE_CON(13), 1, GFLAGS),
@@ -318,7 +318,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
                        RK3328_CLKGATE_CON(6), 6, GFLAGS),
        GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", CLK_SET_RATE_PARENT,
                        RK3328_CLKGATE_CON(14), 0, GFLAGS),
-       GATE(0, "aclk_gpu_niu", "aclk_gpu_pre", CLK_IGNORE_UNUSED,
+       GATE(0, "aclk_gpu_niu", "aclk_gpu_pre", 0,
                        RK3328_CLKGATE_CON(14), 1, GFLAGS),
 
        /* PD_DDR */
@@ -513,9 +513,9 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
                        RK3328_CLKGATE_CON(24), 0, GFLAGS),
        GATE(HCLK_RKVDEC, "hclk_rkvdec", "hclk_rkvdec_pre", CLK_SET_RATE_PARENT,
                        RK3328_CLKGATE_CON(24), 1, GFLAGS),
-       GATE(0, "aclk_rkvdec_niu", "aclk_rkvdec_pre", CLK_IGNORE_UNUSED,
+       GATE(0, "aclk_rkvdec_niu", "aclk_rkvdec_pre", 0,
                        RK3328_CLKGATE_CON(24), 2, GFLAGS),
-       GATE(0, "hclk_rkvdec_niu", "hclk_rkvdec_pre", CLK_IGNORE_UNUSED,
+       GATE(0, "hclk_rkvdec_niu", "hclk_rkvdec_pre", 0,
                        RK3328_CLKGATE_CON(24), 3, GFLAGS),
 
        COMPOSITE(SCLK_VDEC_CABAC, "sclk_vdec_cabac", mux_4plls_p, 0,
@@ -535,9 +535,9 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
                        RK3328_CLKGATE_CON(23), 0, GFLAGS),
        GATE(HCLK_VPU, "hclk_vpu", "hclk_vpu_pre", CLK_SET_RATE_PARENT,
                        RK3328_CLKGATE_CON(23), 1, GFLAGS),
-       GATE(0, "aclk_vpu_niu", "aclk_vpu_pre", CLK_IGNORE_UNUSED,
+       GATE(0, "aclk_vpu_niu", "aclk_vpu_pre", 0,
                        RK3328_CLKGATE_CON(23), 2, GFLAGS),
-       GATE(0, "hclk_vpu_niu", "hclk_vpu_pre", CLK_IGNORE_UNUSED,
+       GATE(0, "hclk_vpu_niu", "hclk_vpu_pre", 0,
                        RK3328_CLKGATE_CON(23), 3, GFLAGS),
 
        COMPOSITE(ACLK_RKVENC, "aclk_rkvenc", mux_4plls_p, 0,
@@ -545,9 +545,9 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
                        RK3328_CLKGATE_CON(6), 3, GFLAGS),
        FACTOR_GATE(HCLK_RKVENC, "hclk_rkvenc", "aclk_rkvenc", 0, 1, 4,
                        RK3328_CLKGATE_CON(11), 4, GFLAGS),
-       GATE(0, "aclk_rkvenc_niu", "aclk_rkvenc", CLK_IGNORE_UNUSED,
+       GATE(0, "aclk_rkvenc_niu", "aclk_rkvenc", 0,
                        RK3328_CLKGATE_CON(25), 0, GFLAGS),
-       GATE(0, "hclk_rkvenc_niu", "hclk_rkvenc", CLK_IGNORE_UNUSED,
+       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),
@@ -588,7 +588,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
        COMPOSITE(ACLK_VOP_PRE, "aclk_vop_pre", mux_4plls_p, 0,
                        RK3328_CLKSEL_CON(39), 6, 2, MFLAGS, 0, 5, DFLAGS,
                        RK3328_CLKGATE_CON(5), 5, GFLAGS),
-       GATE(0, "clk_hdmi_sfc", "xin24m", 0,
+       GATE(SCLK_HDMI_SFC, "sclk_hdmi_sfc", "xin24m", 0,
                        RK3328_CLKGATE_CON(5), 4, GFLAGS),
 
        COMPOSITE_NODIV(0, "clk_cif_src", mux_2plls_p, 0,
@@ -602,7 +602,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
                        RK3328_CLKGATE_CON(5), 6, GFLAGS),
        DIV(DCLK_HDMIPHY, "dclk_hdmiphy", "dclk_lcdc_src", 0,
                        RK3328_CLKSEL_CON(40), 3, 3, DFLAGS),
-       MUX(DCLK_LCDC, "dclk_lcdc", mux_dclk_lcdc_p, 0,
+       MUX(DCLK_LCDC, "dclk_lcdc", mux_dclk_lcdc_p,  CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
                        RK3328_CLKSEL_CON(40), 1, 1, MFLAGS),
 
        /*
@@ -709,14 +709,14 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
 
        /* PD_VOP */
        GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3328_CLKGATE_CON(21), 10, GFLAGS),
-       GATE(0, "aclk_rga_niu", "aclk_rga_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(22), 3, GFLAGS),
+       GATE(0, "aclk_rga_niu", "aclk_rga_pre", 0, RK3328_CLKGATE_CON(22), 3, GFLAGS),
        GATE(ACLK_VOP, "aclk_vop", "aclk_vop_pre", 0, RK3328_CLKGATE_CON(21), 2, GFLAGS),
-       GATE(0, "aclk_vop_niu", "aclk_vop_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(21), 4, GFLAGS),
+       GATE(0, "aclk_vop_niu", "aclk_vop_pre", 0, RK3328_CLKGATE_CON(21), 4, GFLAGS),
 
        GATE(ACLK_IEP, "aclk_iep", "aclk_vio_pre", 0, RK3328_CLKGATE_CON(21), 6, GFLAGS),
        GATE(ACLK_CIF, "aclk_cif", "aclk_vio_pre", 0, RK3328_CLKGATE_CON(21), 8, GFLAGS),
        GATE(ACLK_HDCP, "aclk_hdcp", "aclk_vio_pre", 0, RK3328_CLKGATE_CON(21), 15, GFLAGS),
-       GATE(0, "aclk_vio_niu", "aclk_vio_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(22), 2, GFLAGS),
+       GATE(0, "aclk_vio_niu", "aclk_vio_pre", 0, RK3328_CLKGATE_CON(22), 2, GFLAGS),
 
        GATE(HCLK_VOP, "hclk_vop", "hclk_vio_pre", 0, RK3328_CLKGATE_CON(21), 3, GFLAGS),
        GATE(0, "hclk_vop_niu", "hclk_vio_pre", 0, RK3328_CLKGATE_CON(21), 5, GFLAGS),
@@ -724,10 +724,10 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
        GATE(HCLK_CIF, "hclk_cif", "hclk_vio_pre", 0, RK3328_CLKGATE_CON(21), 9, GFLAGS),
        GATE(HCLK_RGA, "hclk_rga", "hclk_vio_pre", 0, RK3328_CLKGATE_CON(21), 11, GFLAGS),
        GATE(0, "hclk_ahb1tom", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(21), 12, GFLAGS),
-       GATE(0, "pclk_vio_h2p", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(21), 13, GFLAGS),
-       GATE(0, "hclk_vio_h2p", "hclk_vio_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(21), 14, GFLAGS),
+       GATE(0, "pclk_vio_h2p", "hclk_vio_pre", 0, RK3328_CLKGATE_CON(21), 13, GFLAGS),
+       GATE(0, "hclk_vio_h2p", "hclk_vio_pre", 0, RK3328_CLKGATE_CON(21), 14, GFLAGS),
        GATE(HCLK_HDCP, "hclk_hdcp", "hclk_vio_pre", 0, RK3328_CLKGATE_CON(22), 0, GFLAGS),
-       GATE(HCLK_VIO, "hclk_vio", "hclk_vio_pre", 0, RK3328_CLKGATE_CON(22), 1, GFLAGS),
+       GATE(0, "hclk_vio_niu", "hclk_vio_pre", 0, RK3328_CLKGATE_CON(22), 1, GFLAGS),
        GATE(PCLK_HDMI, "pclk_hdmi", "hclk_vio_pre", 0, RK3328_CLKGATE_CON(22), 4, GFLAGS),
        GATE(PCLK_HDCP, "pclk_hdcp", "hclk_vio_pre", 0, RK3328_CLKGATE_CON(22), 5, GFLAGS),
 
@@ -743,19 +743,19 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
        GATE(HCLK_HOST0_ARB, "hclk_host0_arb", "hclk_peri", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(19), 7, GFLAGS),
        GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK3328_CLKGATE_CON(19), 8, GFLAGS),
        GATE(HCLK_OTG_PMU, "hclk_otg_pmu", "hclk_peri", 0, RK3328_CLKGATE_CON(19), 9, GFLAGS),
-       GATE(0, "hclk_peri_niu", "hclk_peri", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(19), 12, GFLAGS),
-       GATE(0, "pclk_peri_niu", "hclk_peri", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(19), 13, GFLAGS),
+       GATE(0, "hclk_peri_niu", "hclk_peri", 0, RK3328_CLKGATE_CON(19), 12, GFLAGS),
+       GATE(0, "pclk_peri_niu", "hclk_peri", 0, RK3328_CLKGATE_CON(19), 13, GFLAGS),
 
        /* PD_GMAC */
        GATE(ACLK_MAC2PHY, "aclk_mac2phy", "aclk_gmac", 0, RK3328_CLKGATE_CON(26), 0, GFLAGS),
        GATE(ACLK_MAC2IO, "aclk_mac2io", "aclk_gmac", 0, RK3328_CLKGATE_CON(26), 2, GFLAGS),
-       GATE(0, "aclk_gmac_niu", "aclk_gmac", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(26), 4, GFLAGS),
+       GATE(0, "aclk_gmac_niu", "aclk_gmac", 0, RK3328_CLKGATE_CON(26), 4, GFLAGS),
        GATE(PCLK_MAC2PHY, "pclk_mac2phy", "pclk_gmac", 0, RK3328_CLKGATE_CON(26), 1, GFLAGS),
        GATE(PCLK_MAC2IO, "pclk_mac2io", "pclk_gmac", 0, RK3328_CLKGATE_CON(26), 3, GFLAGS),
-       GATE(0, "pclk_gmac_niu", "pclk_gmac", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(26), 5, GFLAGS),
+       GATE(0, "pclk_gmac_niu", "pclk_gmac", 0, RK3328_CLKGATE_CON(26), 5, GFLAGS),
 
        /* PD_BUS */
-       GATE(0, "aclk_bus_niu", "aclk_bus_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(15), 12, GFLAGS),
+       GATE(0, "aclk_bus_niu", "aclk_bus_pre", 0, RK3328_CLKGATE_CON(15), 12, GFLAGS),
        GATE(ACLK_DCF, "aclk_dcf", "aclk_bus_pre", 0, RK3328_CLKGATE_CON(15), 11, GFLAGS),
        GATE(ACLK_TSP, "aclk_tsp", "aclk_bus_pre", 0, RK3328_CLKGATE_CON(17), 12, GFLAGS),
        GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(15), 0, GFLAGS),
@@ -769,10 +769,10 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
        GATE(HCLK_TSP, "hclk_tsp", "hclk_bus_pre", 0, RK3328_CLKGATE_CON(17), 11, GFLAGS),
        GATE(HCLK_CRYPTO_MST, "hclk_crypto_mst", "hclk_bus_pre", 0, RK3328_CLKGATE_CON(15), 7, GFLAGS),
        GATE(HCLK_CRYPTO_SLV, "hclk_crypto_slv", "hclk_bus_pre", 0, RK3328_CLKGATE_CON(15), 8, GFLAGS),
-       GATE(0, "hclk_bus_niu", "hclk_bus_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(15), 13, GFLAGS),
+       GATE(0, "hclk_bus_niu", "hclk_bus_pre", 0, RK3328_CLKGATE_CON(15), 13, GFLAGS),
        GATE(HCLK_PDM, "hclk_pdm", "hclk_bus_pre", 0, RK3328_CLKGATE_CON(28), 0, GFLAGS),
 
-       GATE(0, "pclk_bus_niu", "pclk_bus", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(15), 14, GFLAGS),
+       GATE(0, "pclk_bus_niu", "pclk_bus", 0, RK3328_CLKGATE_CON(15), 14, GFLAGS),
        GATE(0, "pclk_efuse", "pclk_bus", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(15), 9, GFLAGS),
        GATE(0, "pclk_otp", "pclk_bus", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(28), 4, GFLAGS),
        GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus", 0, RK3328_CLKGATE_CON(15), 10, GFLAGS),
@@ -807,37 +807,42 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
        GATE(0, "pclk_acodecphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(17), 5, GFLAGS),
        GATE(PCLK_HDMIPHY, "pclk_hdmiphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(17), 7, GFLAGS),
        GATE(0, "pclk_vdacphy", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(17), 8, GFLAGS),
-       GATE(0, "pclk_phy_niu", "pclk_phy_pre", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(15), 15, GFLAGS),
+       GATE(0, "pclk_phy_niu", "pclk_phy_pre", 0, RK3328_CLKGATE_CON(15), 15, GFLAGS),
 
        /* PD_MMC */
-       MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc",
+       MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "clk_sdmmc",
            RK3328_SDMMC_CON0, 1),
-       MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc",
+       MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "clk_sdmmc",
            RK3328_SDMMC_CON1, 1),
 
-       MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio",
+       MMC(SCLK_SDIO_DRV, "sdio_drv", "clk_sdio",
            RK3328_SDIO_CON0, 1),
-       MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio",
+       MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "clk_sdio",
            RK3328_SDIO_CON1, 1),
 
-       MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc",
+       MMC(SCLK_EMMC_DRV, "emmc_drv", "clk_emmc",
            RK3328_EMMC_CON0, 1),
-       MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc",
+       MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "clk_emmc",
            RK3328_EMMC_CON1, 1),
 
-       MMC(SCLK_SDMMC_EXT_DRV, "sdmmc_ext_drv", "sclk_sdmmc_ext",
+       MMC(SCLK_SDMMC_EXT_DRV, "sdmmc_ext_drv", "clk_sdmmc_ext",
            RK3328_SDMMC_EXT_CON0, 1),
-       MMC(SCLK_SDMMC_EXT_SAMPLE, "sdmmc_ext_sample", "sclk_sdmmc_ext",
+       MMC(SCLK_SDMMC_EXT_SAMPLE, "sdmmc_ext_sample", "clk_sdmmc_ext",
            RK3328_SDMMC_EXT_CON1, 1),
 };
 
 static const char *const rk3328_critical_clocks[] __initconst = {
        "aclk_bus",
+       "aclk_bus_niu",
        "pclk_bus",
+       "pclk_bus_niu",
        "hclk_bus",
+       "hclk_bus_niu",
        "aclk_peri",
        "hclk_peri",
+       "hclk_peri_niu",
        "pclk_peri",
+       "pclk_peri_niu",
        "pclk_dbg",
        "aclk_core_niu",
        "aclk_gic400",
@@ -861,6 +866,20 @@ static const char *const rk3328_critical_clocks[] __initconst = {
        "aclk_rga_niu",
        "pclk_vio_h2p",
        "hclk_vio_h2p",
+       "aclk_vio_niu",
+       "hclk_vio_niu",
+       "aclk_vop_niu",
+       "hclk_vop_niu",
+       "aclk_gpu_niu",
+       "aclk_rkvdec_niu",
+       "hclk_rkvdec_niu",
+       "aclk_vpu_niu",
+       "hclk_vpu_niu",
+       "aclk_rkvenc_niu",
+       "hclk_rkvenc_niu",
+       "aclk_gmac_niu",
+       "pclk_gmac_niu",
+       "pclk_phy_niu",
 };
 
 static void __init rk3328_clk_init(struct device_node *np)
index 6847120b61cdeff87b7de7995c412df5a7d6449c..bca10d618f0a8731905115b3b57ab6533e2529f1 100644 (file)
@@ -57,6 +57,7 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = {
        RK3036_PLL_RATE(1656000000, 1, 69, 1, 1, 1, 0),
        RK3036_PLL_RATE(1632000000, 1, 68, 1, 1, 1, 0),
        RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+       RK3036_PLL_RATE(1600000000, 3, 200, 1, 1, 1, 0),
        RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
        RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
        RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
@@ -670,7 +671,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
                        RK3399_CLKGATE_CON(9), 7, GFLAGS,
                        &rk3399_uart3_fracmux),
 
-       COMPOSITE(0, "pclk_ddr", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
+       COMPOSITE(PCLK_DDR, "pclk_ddr", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
                        RK3399_CLKSEL_CON(6), 15, 1, MFLAGS, 8, 5, DFLAGS,
                        RK3399_CLKGATE_CON(3), 4, GFLAGS),
 
@@ -886,7 +887,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
                        RK3399_CLKGATE_CON(31), 8, GFLAGS),
 
        /* sdio & sdmmc */
-       COMPOSITE(0, "hclk_sd", mux_pll_src_cpll_gpll_p, 0,
+       COMPOSITE(HCLK_SD, "hclk_sd", mux_pll_src_cpll_gpll_p, 0,
                        RK3399_CLKSEL_CON(13), 15, 1, MFLAGS, 8, 5, DFLAGS,
                        RK3399_CLKGATE_CON(12), 13, GFLAGS),
        GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_sd", 0,
index 35dbd63c2f49b03b87866b870b0700aebf333867..3cd8ad59e0b79fd2f6c1fe8b4b90316e7ab3d137 100644 (file)
@@ -57,6 +57,7 @@ static struct clk *rockchip_clk_register_branch(const char *name,
        struct clk_divider *div = NULL;
        const struct clk_ops *mux_ops = NULL, *div_ops = NULL,
                             *gate_ops = NULL;
+       int ret;
 
        if (num_parents > 1) {
                mux = kzalloc(sizeof(*mux), GFP_KERNEL);
@@ -74,8 +75,10 @@ static struct clk *rockchip_clk_register_branch(const char *name,
 
        if (gate_offset >= 0) {
                gate = kzalloc(sizeof(*gate), GFP_KERNEL);
-               if (!gate)
+               if (!gate) {
+                       ret = -ENOMEM;
                        goto err_gate;
+               }
 
                gate->flags = gate_flags;
                gate->reg = base + gate_offset;
@@ -86,8 +89,10 @@ static struct clk *rockchip_clk_register_branch(const char *name,
 
        if (div_width > 0) {
                div = kzalloc(sizeof(*div), GFP_KERNEL);
-               if (!div)
+               if (!div) {
+                       ret = -ENOMEM;
                        goto err_div;
+               }
 
                div->flags = div_flags;
                div->reg = base + muxdiv_offset;
@@ -106,12 +111,19 @@ static struct clk *rockchip_clk_register_branch(const char *name,
                                     gate ? &gate->hw : NULL, gate_ops,
                                     flags);
 
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
+               goto err_composite;
+       }
+
        return clk;
+err_composite:
+       kfree(div);
 err_div:
        kfree(gate);
 err_gate:
        kfree(mux);
-       return ERR_PTR(-ENOMEM);
+       return ERR_PTR(ret);
 }
 
 struct rockchip_clk_frac {
@@ -291,8 +303,10 @@ static struct clk *rockchip_clk_register_frac_branch(
                init.num_parents = child->num_parents;
 
                mux_clk = clk_register(NULL, &frac_mux->hw);
-               if (IS_ERR(mux_clk))
+               if (IS_ERR(mux_clk)) {
+                       kfree(frac);
                        return clk;
+               }
 
                rockchip_clk_add_lookup(ctx, mux_clk, child->id);
 
index ef8900bc077f60c78b2a097c9cd89457973229db..513826393158d90f50f1adf62bdd111399cc1ebd 100644 (file)
@@ -8,9 +8,11 @@ obj-$(CONFIG_SOC_EXYNOS3250)   += clk-exynos3250.o
 obj-$(CONFIG_ARCH_EXYNOS4)     += clk-exynos4.o
 obj-$(CONFIG_ARCH_EXYNOS4)     += clk-exynos4412-isp.o
 obj-$(CONFIG_SOC_EXYNOS5250)   += clk-exynos5250.o
+obj-$(CONFIG_SOC_EXYNOS5250)   += clk-exynos5-subcmu.o
 obj-$(CONFIG_SOC_EXYNOS5260)   += clk-exynos5260.o
 obj-$(CONFIG_SOC_EXYNOS5410)   += clk-exynos5410.o
 obj-$(CONFIG_SOC_EXYNOS5420)   += clk-exynos5420.o
+obj-$(CONFIG_SOC_EXYNOS5420)   += clk-exynos5-subcmu.o
 obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK)  += clk-exynos5433.o
 obj-$(CONFIG_SOC_EXYNOS5440)   += clk-exynos5440.o
 obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o
index 5bfc92ee3129a5fec4df14c58f7024a64ed15058..b4b057c7301c0147728a38e8200792a41c9d5100 100644 (file)
@@ -143,10 +143,8 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        reg_base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(reg_base)) {
-               dev_err(dev, "failed to map audss registers\n");
+       if (IS_ERR(reg_base))
                return PTR_ERR(reg_base);
-       }
 
        epll = ERR_PTR(-ENODEV);
 
index 1b81e283f60589c900c5bfc6370a125d8c8c845d..27c9d23657b32fbab4b43ee6459fca3d11a46be8 100644 (file)
@@ -670,73 +670,73 @@ static const struct samsung_gate_clock gate_clks[] __initconst = {
 
 /* APLL & MPLL & BPLL & UPLL */
 static const struct samsung_pll_rate_table exynos3250_pll_rates[] __initconst = {
-       PLL_35XX_RATE(1200000000, 400, 4, 1),
-       PLL_35XX_RATE(1100000000, 275, 3, 1),
-       PLL_35XX_RATE(1066000000, 533, 6, 1),
-       PLL_35XX_RATE(1000000000, 250, 3, 1),
-       PLL_35XX_RATE( 960000000, 320, 4, 1),
-       PLL_35XX_RATE( 900000000, 300, 4, 1),
-       PLL_35XX_RATE( 850000000, 425, 6, 1),
-       PLL_35XX_RATE( 800000000, 200, 3, 1),
-       PLL_35XX_RATE( 700000000, 175, 3, 1),
-       PLL_35XX_RATE( 667000000, 667, 12, 1),
-       PLL_35XX_RATE( 600000000, 400, 4, 2),
-       PLL_35XX_RATE( 533000000, 533, 6, 2),
-       PLL_35XX_RATE( 520000000, 260, 3, 2),
-       PLL_35XX_RATE( 500000000, 250, 3, 2),
-       PLL_35XX_RATE( 400000000, 200, 3, 2),
-       PLL_35XX_RATE( 200000000, 200, 3, 3),
-       PLL_35XX_RATE( 100000000, 200, 3, 4),
+       PLL_35XX_RATE(24 * MHZ, 1200000000, 400, 4, 1),
+       PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 3, 1),
+       PLL_35XX_RATE(24 * MHZ, 1066000000, 533, 6, 1),
+       PLL_35XX_RATE(24 * MHZ, 1000000000, 250, 3, 1),
+       PLL_35XX_RATE(24 * MHZ,  960000000, 320, 4, 1),
+       PLL_35XX_RATE(24 * MHZ,  900000000, 300, 4, 1),
+       PLL_35XX_RATE(24 * MHZ,  850000000, 425, 6, 1),
+       PLL_35XX_RATE(24 * MHZ,  800000000, 200, 3, 1),
+       PLL_35XX_RATE(24 * MHZ,  700000000, 175, 3, 1),
+       PLL_35XX_RATE(24 * MHZ,  667000000, 667, 12, 1),
+       PLL_35XX_RATE(24 * MHZ,  600000000, 400, 4, 2),
+       PLL_35XX_RATE(24 * MHZ,  533000000, 533, 6, 2),
+       PLL_35XX_RATE(24 * MHZ,  520000000, 260, 3, 2),
+       PLL_35XX_RATE(24 * MHZ,  500000000, 250, 3, 2),
+       PLL_35XX_RATE(24 * MHZ,  400000000, 200, 3, 2),
+       PLL_35XX_RATE(24 * MHZ,  200000000, 200, 3, 3),
+       PLL_35XX_RATE(24 * MHZ,  100000000, 200, 3, 4),
        { /* sentinel */ }
 };
 
 /* EPLL */
 static const struct samsung_pll_rate_table exynos3250_epll_rates[] __initconst = {
-       PLL_36XX_RATE(800000000, 200, 3, 1,     0),
-       PLL_36XX_RATE(288000000,  96, 2, 2,     0),
-       PLL_36XX_RATE(192000000, 128, 2, 3,     0),
-       PLL_36XX_RATE(144000000,  96, 2, 3,     0),
-       PLL_36XX_RATE( 96000000, 128, 2, 4,     0),
-       PLL_36XX_RATE( 84000000, 112, 2, 4,     0),
-       PLL_36XX_RATE( 80000004, 106, 2, 4, 43691),
-       PLL_36XX_RATE( 73728000,  98, 2, 4, 19923),
-       PLL_36XX_RATE( 67737598, 270, 3, 5, 62285),
-       PLL_36XX_RATE( 65535999, 174, 2, 5, 49982),
-       PLL_36XX_RATE( 50000000, 200, 3, 5,     0),
-       PLL_36XX_RATE( 49152002, 131, 2, 5,  4719),
-       PLL_36XX_RATE( 48000000, 128, 2, 5,     0),
-       PLL_36XX_RATE( 45158401, 180, 3, 5, 41524),
+       PLL_36XX_RATE(24 * MHZ, 800000000, 200, 3, 1,     0),
+       PLL_36XX_RATE(24 * MHZ, 288000000,  96, 2, 2,     0),
+       PLL_36XX_RATE(24 * MHZ, 192000000, 128, 2, 3,     0),
+       PLL_36XX_RATE(24 * MHZ, 144000000,  96, 2, 3,     0),
+       PLL_36XX_RATE(24 * MHZ,  96000000, 128, 2, 4,     0),
+       PLL_36XX_RATE(24 * MHZ,  84000000, 112, 2, 4,     0),
+       PLL_36XX_RATE(24 * MHZ,  80000003, 106, 2, 4, 43691),
+       PLL_36XX_RATE(24 * MHZ,  73728000,  98, 2, 4, 19923),
+       PLL_36XX_RATE(24 * MHZ,  67737598, 270, 3, 5, 62285),
+       PLL_36XX_RATE(24 * MHZ,  65535999, 174, 2, 5, 49982),
+       PLL_36XX_RATE(24 * MHZ,  50000000, 200, 3, 5,     0),
+       PLL_36XX_RATE(24 * MHZ,  49152002, 131, 2, 5,  4719),
+       PLL_36XX_RATE(24 * MHZ,  48000000, 128, 2, 5,     0),
+       PLL_36XX_RATE(24 * MHZ,  45158401, 180, 3, 5, 41524),
        { /* sentinel */ }
 };
 
 /* VPLL */
 static const struct samsung_pll_rate_table exynos3250_vpll_rates[] __initconst = {
-       PLL_36XX_RATE(600000000, 100, 2, 1,     0),
-       PLL_36XX_RATE(533000000, 266, 3, 2, 32768),
-       PLL_36XX_RATE(519230987, 173, 2, 2,  5046),
-       PLL_36XX_RATE(500000000, 250, 3, 2,     0),
-       PLL_36XX_RATE(445500000, 148, 2, 2, 32768),
-       PLL_36XX_RATE(445055007, 148, 2, 2, 23047),
-       PLL_36XX_RATE(400000000, 200, 3, 2,     0),
-       PLL_36XX_RATE(371250000, 123, 2, 2, 49152),
-       PLL_36XX_RATE(370878997, 185, 3, 2, 28803),
-       PLL_36XX_RATE(340000000, 170, 3, 2,     0),
-       PLL_36XX_RATE(335000015, 111, 2, 2, 43691),
-       PLL_36XX_RATE(333000000, 111, 2, 2,     0),
-       PLL_36XX_RATE(330000000, 110, 2, 2,     0),
-       PLL_36XX_RATE(320000015, 106, 2, 2, 43691),
-       PLL_36XX_RATE(300000000, 100, 2, 2,     0),
-       PLL_36XX_RATE(275000000, 275, 3, 3,     0),
-       PLL_36XX_RATE(222750000, 148, 2, 3, 32768),
-       PLL_36XX_RATE(222528007, 148, 2, 3, 23069),
-       PLL_36XX_RATE(160000000, 160, 3, 3,     0),
-       PLL_36XX_RATE(148500000,  99, 2, 3,     0),
-       PLL_36XX_RATE(148352005,  98, 2, 3, 59070),
-       PLL_36XX_RATE(108000000, 144, 2, 4,     0),
-       PLL_36XX_RATE( 74250000,  99, 2, 4,     0),
-       PLL_36XX_RATE( 74176002,  98, 3, 4, 59070),
-       PLL_36XX_RATE( 54054000, 216, 3, 5, 14156),
-       PLL_36XX_RATE( 54000000, 144, 2, 5,     0),
+       PLL_36XX_RATE(24 * MHZ, 600000000, 100, 2, 1,     0),
+       PLL_36XX_RATE(24 * MHZ, 533000000, 266, 3, 2, 32768),
+       PLL_36XX_RATE(24 * MHZ, 519230987, 173, 2, 2,  5046),
+       PLL_36XX_RATE(24 * MHZ, 500000000, 250, 3, 2,     0),
+       PLL_36XX_RATE(24 * MHZ, 445500000, 148, 2, 2, 32768),
+       PLL_36XX_RATE(24 * MHZ, 445055007, 148, 2, 2, 23047),
+       PLL_36XX_RATE(24 * MHZ, 400000000, 200, 3, 2,     0),
+       PLL_36XX_RATE(24 * MHZ, 371250000, 123, 2, 2, 49152),
+       PLL_36XX_RATE(24 * MHZ, 370878997, 185, 3, 2, 28803),
+       PLL_36XX_RATE(24 * MHZ, 340000000, 170, 3, 2,     0),
+       PLL_36XX_RATE(24 * MHZ, 335000015, 111, 2, 2, 43691),
+       PLL_36XX_RATE(24 * MHZ, 333000000, 111, 2, 2,     0),
+       PLL_36XX_RATE(24 * MHZ, 330000000, 110, 2, 2,     0),
+       PLL_36XX_RATE(24 * MHZ, 320000015, 106, 2, 2, 43691),
+       PLL_36XX_RATE(24 * MHZ, 300000000, 100, 2, 2,     0),
+       PLL_36XX_RATE(24 * MHZ, 275000000, 275, 3, 3,     0),
+       PLL_36XX_RATE(24 * MHZ, 222750000, 148, 2, 3, 32768),
+       PLL_36XX_RATE(24 * MHZ, 222528007, 148, 2, 3, 23069),
+       PLL_36XX_RATE(24 * MHZ, 160000000, 160, 3, 3,     0),
+       PLL_36XX_RATE(24 * MHZ, 148500000,  99, 2, 3,     0),
+       PLL_36XX_RATE(24 * MHZ, 148352005,  98, 2, 3, 59070),
+       PLL_36XX_RATE(24 * MHZ, 108000000, 144, 2, 4,     0),
+       PLL_36XX_RATE(24 * MHZ,  74250000,  99, 2, 4,     0),
+       PLL_36XX_RATE(24 * MHZ,  74176002,  98, 2, 4, 59070),
+       PLL_36XX_RATE(24 * MHZ,  54054000, 216, 3, 5, 14156),
+       PLL_36XX_RATE(24 * MHZ,  54000000, 144, 2, 5,     0),
        { /* sentinel */ }
 };
 
index 134f25f2a913861c2ce2a2f89ce5a5221e14a98c..0421960eb96333048e709c4df6308c3e8338fb7b 100644 (file)
@@ -1266,77 +1266,78 @@ static const struct of_device_id ext_clk_match[] __initconst = {
 
 /* PLLs PMS values */
 static const struct samsung_pll_rate_table exynos4210_apll_rates[] __initconst = {
-       PLL_45XX_RATE(1200000000, 150,  3, 1, 28),
-       PLL_45XX_RATE(1000000000, 250,  6, 1, 28),
-       PLL_45XX_RATE( 800000000, 200,  6, 1, 28),
-       PLL_45XX_RATE( 666857142, 389, 14, 1, 13),
-       PLL_45XX_RATE( 600000000, 100,  4, 1, 13),
-       PLL_45XX_RATE( 533000000, 533, 24, 1,  5),
-       PLL_45XX_RATE( 500000000, 250,  6, 2, 28),
-       PLL_45XX_RATE( 400000000, 200,  6, 2, 28),
-       PLL_45XX_RATE( 200000000, 200,  6, 3, 28),
+       PLL_4508_RATE(24 * MHZ, 1200000000, 150,  3, 1, 28),
+       PLL_4508_RATE(24 * MHZ, 1000000000, 250,  6, 1, 28),
+       PLL_4508_RATE(24 * MHZ,  800000000, 200,  6, 1, 28),
+       PLL_4508_RATE(24 * MHZ,  666857142, 389, 14, 1, 13),
+       PLL_4508_RATE(24 * MHZ,  600000000, 100,  4, 1, 13),
+       PLL_4508_RATE(24 * MHZ,  533000000, 533, 24, 1,  5),
+       PLL_4508_RATE(24 * MHZ,  500000000, 250,  6, 2, 28),
+       PLL_4508_RATE(24 * MHZ,  400000000, 200,  6, 2, 28),
+       PLL_4508_RATE(24 * MHZ,  200000000, 200,  6, 3, 28),
        { /* sentinel */ }
 };
 
 static const struct samsung_pll_rate_table exynos4210_epll_rates[] __initconst = {
-       PLL_4600_RATE(192000000, 48, 3, 1,     0, 0),
-       PLL_4600_RATE(180633605, 45, 3, 1, 10381, 0),
-       PLL_4600_RATE(180000000, 45, 3, 1,     0, 0),
-       PLL_4600_RATE( 73727996, 73, 3, 3, 47710, 1),
-       PLL_4600_RATE( 67737602, 90, 4, 3, 20762, 1),
-       PLL_4600_RATE( 49151992, 49, 3, 3,  9961, 0),
-       PLL_4600_RATE( 45158401, 45, 3, 3, 10381, 0),
+       PLL_4600_RATE(24 * MHZ, 192000000, 48, 3, 1,     0, 0),
+       PLL_4600_RATE(24 * MHZ, 180633605, 45, 3, 1, 10381, 0),
+       PLL_4600_RATE(24 * MHZ, 180000000, 45, 3, 1,     0, 0),
+       PLL_4600_RATE(24 * MHZ,  73727996, 73, 3, 3, 47710, 1),
+       PLL_4600_RATE(24 * MHZ,  67737602, 90, 4, 3, 20762, 1),
+       PLL_4600_RATE(24 * MHZ,  49151992, 49, 3, 3,  9961, 0),
+       PLL_4600_RATE(24 * MHZ,  45158401, 45, 3, 3, 10381, 0),
        { /* sentinel */ }
 };
 
 static const struct samsung_pll_rate_table exynos4210_vpll_rates[] __initconst = {
-       PLL_4650_RATE(360000000, 44, 3, 0, 1024, 0, 14, 0),
-       PLL_4650_RATE(324000000, 53, 2, 1, 1024, 1,  1, 1),
-       PLL_4650_RATE(259617187, 63, 3, 1, 1950, 0, 20, 1),
-       PLL_4650_RATE(110000000, 53, 3, 2, 2048, 0, 17, 0),
-       PLL_4650_RATE( 55360351, 53, 3, 3, 2417, 0, 17, 0),
+       PLL_4650_RATE(24 * MHZ, 360000000, 44, 3, 0, 1024, 0, 14, 0),
+       PLL_4650_RATE(24 * MHZ, 324000000, 53, 2, 1, 1024, 1,  1, 1),
+       PLL_4650_RATE(24 * MHZ, 259617187, 63, 3, 1, 1950, 0, 20, 1),
+       PLL_4650_RATE(24 * MHZ, 110000000, 53, 3, 2, 2048, 0, 17, 0),
+       PLL_4650_RATE(24 * MHZ,  55360351, 53, 3, 3, 2417, 0, 17, 0),
        { /* sentinel */ }
 };
 
 static const struct samsung_pll_rate_table exynos4x12_apll_rates[] __initconst = {
-       PLL_35XX_RATE(1704000000, 213, 3, 0),
-       PLL_35XX_RATE(1600000000, 200, 3, 0),
-       PLL_35XX_RATE(1500000000, 250, 4, 0),
-       PLL_35XX_RATE(1400000000, 175, 3, 0),
-       PLL_35XX_RATE(1300000000, 325, 6, 0),
-       PLL_35XX_RATE(1200000000, 200, 4, 0),
-       PLL_35XX_RATE(1100000000, 275, 6, 0),
-       PLL_35XX_RATE(1000000000, 125, 3, 0),
-       PLL_35XX_RATE( 900000000, 150, 4, 0),
-       PLL_35XX_RATE( 800000000, 100, 3, 0),
-       PLL_35XX_RATE( 700000000, 175, 3, 1),
-       PLL_35XX_RATE( 600000000, 200, 4, 1),
-       PLL_35XX_RATE( 500000000, 125, 3, 1),
-       PLL_35XX_RATE( 400000000, 100, 3, 1),
-       PLL_35XX_RATE( 300000000, 200, 4, 2),
-       PLL_35XX_RATE( 200000000, 100, 3, 2),
+       PLL_35XX_RATE(24 * MHZ, 1704000000, 213, 3, 0),
+       PLL_35XX_RATE(24 * MHZ, 1600000000, 200, 3, 0),
+       PLL_35XX_RATE(24 * MHZ, 1500000000, 250, 4, 0),
+       PLL_35XX_RATE(24 * MHZ, 1400000000, 175, 3, 0),
+       PLL_35XX_RATE(24 * MHZ, 1300000000, 325, 6, 0),
+       PLL_35XX_RATE(24 * MHZ, 1200000000, 200, 4, 0),
+       PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 6, 0),
+       PLL_35XX_RATE(24 * MHZ, 1000000000, 125, 3, 0),
+       PLL_35XX_RATE(24 * MHZ,  900000000, 150, 4, 0),
+       PLL_35XX_RATE(24 * MHZ,  800000000, 100, 3, 0),
+       PLL_35XX_RATE(24 * MHZ,  700000000, 175, 3, 1),
+       PLL_35XX_RATE(24 * MHZ,  600000000, 200, 4, 1),
+       PLL_35XX_RATE(24 * MHZ,  500000000, 125, 3, 1),
+       PLL_35XX_RATE(24 * MHZ,  400000000, 100, 3, 1),
+       PLL_35XX_RATE(24 * MHZ,  300000000, 200, 4, 2),
+       PLL_35XX_RATE(24 * MHZ,  200000000, 100, 3, 2),
        { /* sentinel */ }
 };
 
 static const struct samsung_pll_rate_table exynos4x12_epll_rates[] __initconst = {
-       PLL_36XX_RATE(192000000, 48, 3, 1,     0),
-       PLL_36XX_RATE(180633605, 45, 3, 1, 10381),
-       PLL_36XX_RATE(180000000, 45, 3, 1,     0),
-       PLL_36XX_RATE( 73727996, 73, 3, 3, 47710),
-       PLL_36XX_RATE( 67737602, 90, 4, 3, 20762),
-       PLL_36XX_RATE( 49151992, 49, 3, 3,  9961),
-       PLL_36XX_RATE( 45158401, 45, 3, 3, 10381),
+       PLL_36XX_RATE(24 * MHZ, 196608001, 197, 3, 3, -25690),
+       PLL_36XX_RATE(24 * MHZ, 192000000, 48, 3, 1,     0),
+       PLL_36XX_RATE(24 * MHZ, 180633605, 45, 3, 1, 10381),
+       PLL_36XX_RATE(24 * MHZ, 180000000, 45, 3, 1,     0),
+       PLL_36XX_RATE(24 * MHZ,  73727996, 73, 3, 3, 47710),
+       PLL_36XX_RATE(24 * MHZ,  67737602, 90, 4, 3, 20762),
+       PLL_36XX_RATE(24 * MHZ,  49151992, 49, 3, 3,  9961),
+       PLL_36XX_RATE(24 * MHZ,  45158401, 45, 3, 3, 10381),
        { /* sentinel */ }
 };
 
 static const struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initconst = {
-       PLL_36XX_RATE(533000000, 133, 3, 1, 16384),
-       PLL_36XX_RATE(440000000, 110, 3, 1,     0),
-       PLL_36XX_RATE(350000000, 175, 3, 2,     0),
-       PLL_36XX_RATE(266000000, 133, 3, 2,     0),
-       PLL_36XX_RATE(160000000, 160, 3, 3,     0),
-       PLL_36XX_RATE(106031250,  53, 3, 2,  1024),
-       PLL_36XX_RATE( 53015625,  53, 3, 3,  1024),
+       PLL_36XX_RATE(24 * MHZ, 533000000, 133, 3, 1, 16384),
+       PLL_36XX_RATE(24 * MHZ, 440000000, 110, 3, 1,     0),
+       PLL_36XX_RATE(24 * MHZ, 350000000, 175, 3, 2,     0),
+       PLL_36XX_RATE(24 * MHZ, 266000000, 133, 3, 2,     0),
+       PLL_36XX_RATE(24 * MHZ, 160000000, 160, 3, 3,     0),
+       PLL_36XX_RATE(24 * MHZ, 106031250,  53, 3, 2,  1024),
+       PLL_36XX_RATE(24 * MHZ,  53015625,  53, 3, 3,  1024),
        { /* sentinel */ }
 };
 
diff --git a/drivers/clk/samsung/clk-exynos5-subcmu.c b/drivers/clk/samsung/clk-exynos5-subcmu.c
new file mode 100644 (file)
index 0000000..9330628
--- /dev/null
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 Samsung Electronics Co., Ltd.
+// Author: Marek Szyprowski <m.szyprowski@samsung.com>
+// Common Clock Framework support for Exynos5 power-domain dependent clocks
+
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+
+#include "clk.h"
+#include "clk-exynos5-subcmu.h"
+
+static struct samsung_clk_provider *ctx;
+static const struct exynos5_subcmu_info *cmu;
+static int nr_cmus;
+
+static void exynos5_subcmu_clk_save(void __iomem *base,
+                                   struct exynos5_subcmu_reg_dump *rd,
+                                   unsigned int num_regs)
+{
+       for (; num_regs > 0; --num_regs, ++rd) {
+               rd->save = readl(base + rd->offset);
+               writel((rd->save & ~rd->mask) | rd->value, base + rd->offset);
+               rd->save &= rd->mask;
+       }
+};
+
+static void exynos5_subcmu_clk_restore(void __iomem *base,
+                                      struct exynos5_subcmu_reg_dump *rd,
+                                      unsigned int num_regs)
+{
+       for (; num_regs > 0; --num_regs, ++rd)
+               writel((readl(base + rd->offset) & ~rd->mask) | rd->save,
+                      base + rd->offset);
+}
+
+static void exynos5_subcmu_defer_gate(struct samsung_clk_provider *ctx,
+                             const struct samsung_gate_clock *list, int nr_clk)
+{
+       while (nr_clk--)
+               samsung_clk_add_lookup(ctx, ERR_PTR(-EPROBE_DEFER), list++->id);
+}
+
+/*
+ * Pass the needed clock provider context and register sub-CMU clocks
+ *
+ * NOTE: This function has to be called from the main, OF_CLK_DECLARE-
+ * initialized clock provider driver. This happens very early during boot
+ * process. Then this driver, during core_initcall registers two platform
+ * drivers: one which binds to the same device-tree node as OF_CLK_DECLARE
+ * driver and second, for handling its per-domain child-devices. Those
+ * platform drivers are bound to their devices a bit later in arch_initcall,
+ * when OF-core populates all device-tree nodes.
+ */
+void exynos5_subcmus_init(struct samsung_clk_provider *_ctx, int _nr_cmus,
+                         const struct exynos5_subcmu_info *_cmu)
+{
+       ctx = _ctx;
+       cmu = _cmu;
+       nr_cmus = _nr_cmus;
+
+       for (; _nr_cmus--; _cmu++) {
+               exynos5_subcmu_defer_gate(ctx, _cmu->gate_clks,
+                                         _cmu->nr_gate_clks);
+               exynos5_subcmu_clk_save(ctx->reg_base, _cmu->suspend_regs,
+                                       _cmu->nr_suspend_regs);
+       }
+}
+
+static int __maybe_unused exynos5_subcmu_suspend(struct device *dev)
+{
+       struct exynos5_subcmu_info *info = dev_get_drvdata(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&ctx->lock, flags);
+       exynos5_subcmu_clk_save(ctx->reg_base, info->suspend_regs,
+                               info->nr_suspend_regs);
+       spin_unlock_irqrestore(&ctx->lock, flags);
+
+       return 0;
+}
+
+static int __maybe_unused exynos5_subcmu_resume(struct device *dev)
+{
+       struct exynos5_subcmu_info *info = dev_get_drvdata(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&ctx->lock, flags);
+       exynos5_subcmu_clk_restore(ctx->reg_base, info->suspend_regs,
+                                  info->nr_suspend_regs);
+       spin_unlock_irqrestore(&ctx->lock, flags);
+
+       return 0;
+}
+
+static int __init exynos5_subcmu_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct exynos5_subcmu_info *info = dev_get_drvdata(dev);
+
+       pm_runtime_set_suspended(dev);
+       pm_runtime_enable(dev);
+       pm_runtime_get(dev);
+
+       ctx->dev = dev;
+       samsung_clk_register_div(ctx, info->div_clks, info->nr_div_clks);
+       samsung_clk_register_gate(ctx, info->gate_clks, info->nr_gate_clks);
+       ctx->dev = NULL;
+
+       pm_runtime_put_sync(dev);
+
+       return 0;
+}
+
+static const struct dev_pm_ops exynos5_subcmu_pm_ops = {
+       SET_RUNTIME_PM_OPS(exynos5_subcmu_suspend,
+                          exynos5_subcmu_resume, NULL)
+       SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+                                    pm_runtime_force_resume)
+};
+
+static struct platform_driver exynos5_subcmu_driver __refdata = {
+       .driver = {
+               .name = "exynos5-subcmu",
+               .suppress_bind_attrs = true,
+               .pm = &exynos5_subcmu_pm_ops,
+       },
+       .probe = exynos5_subcmu_probe,
+};
+
+static int __init exynos5_clk_register_subcmu(struct device *parent,
+                                        const struct exynos5_subcmu_info *info,
+                                             struct device_node *pd_node)
+{
+       struct of_phandle_args genpdspec = { .np = pd_node };
+       struct platform_device *pdev;
+
+       pdev = platform_device_alloc(info->pd_name, -1);
+       pdev->dev.parent = parent;
+       pdev->driver_override = "exynos5-subcmu";
+       platform_set_drvdata(pdev, (void *)info);
+       of_genpd_add_device(&genpdspec, &pdev->dev);
+       platform_device_add(pdev);
+
+       return 0;
+}
+
+static int __init exynos5_clk_probe(struct platform_device *pdev)
+{
+       struct device_node *np;
+       const char *name;
+       int i;
+
+       for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
+               if (of_property_read_string(np, "label", &name) < 0)
+                       continue;
+               for (i = 0; i < nr_cmus; i++)
+                       if (strcmp(cmu[i].pd_name, name) == 0)
+                               exynos5_clk_register_subcmu(&pdev->dev,
+                                                           &cmu[i], np);
+       }
+       return 0;
+}
+
+static const struct of_device_id exynos5_clk_of_match[] = {
+       { .compatible = "samsung,exynos5250-clock", },
+       { .compatible = "samsung,exynos5420-clock", },
+       { .compatible = "samsung,exynos5800-clock", },
+       { },
+};
+
+static struct platform_driver exynos5_clk_driver __refdata = {
+       .driver = {
+               .name = "exynos5-clock",
+               .of_match_table = exynos5_clk_of_match,
+               .suppress_bind_attrs = true,
+       },
+       .probe = exynos5_clk_probe,
+};
+
+static int __init exynos5_clk_drv_init(void)
+{
+       platform_driver_register(&exynos5_clk_driver);
+       platform_driver_register(&exynos5_subcmu_driver);
+       return 0;
+}
+core_initcall(exynos5_clk_drv_init);
diff --git a/drivers/clk/samsung/clk-exynos5-subcmu.h b/drivers/clk/samsung/clk-exynos5-subcmu.h
new file mode 100644 (file)
index 0000000..755ee8a
--- /dev/null
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __CLK_EXYNOS5_SUBCMU_H
+#define __CLK_EXYNOS5_SUBCMU_H
+
+struct exynos5_subcmu_reg_dump {
+       u32 offset;
+       u32 value;
+       u32 mask;
+       u32 save;
+};
+
+struct exynos5_subcmu_info {
+       const struct samsung_div_clock *div_clks;
+       unsigned int nr_div_clks;
+       const struct samsung_gate_clock *gate_clks;
+       unsigned int nr_gate_clks;
+       struct exynos5_subcmu_reg_dump *suspend_regs;
+       unsigned int nr_suspend_regs;
+       const char *pd_name;
+};
+
+void exynos5_subcmus_init(struct samsung_clk_provider *ctx, int nr_cmus,
+                         const struct exynos5_subcmu_info *cmu);
+
+#endif
index 9b073c98a8910e02be6420454a6d198275de27fc..347fd80c351b06211a34cfcf7fc934e35bb7483f 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "clk.h"
 #include "clk-cpu.h"
+#include "clk-exynos5-subcmu.h"
 
 #define APLL_LOCK              0x0
 #define APLL_CON0              0x100
@@ -560,6 +561,8 @@ static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = {
                0),
        GATE(CLK_GSCL3, "gscl3", "mout_aclk266_gscl_sub", GATE_IP_GSCL, 3, 0,
                0),
+       GATE(CLK_CAMIF_TOP, "camif_top", "mout_aclk266_gscl_sub",
+                       GATE_IP_GSCL, 4, 0, 0),
        GATE(CLK_GSCL_WA, "gscl_wa", "div_gscl_wa", GATE_IP_GSCL, 5, 0, 0),
        GATE(CLK_GSCL_WB, "gscl_wb", "div_gscl_wb", GATE_IP_GSCL, 6, 0, 0),
        GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "mout_aclk266_gscl_sub",
@@ -570,18 +573,11 @@ static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = {
                        GATE_IP_GSCL, 9, 0, 0),
        GATE(CLK_SMMU_GSCL3, "smmu_gscl3", "mout_aclk266_gscl_sub",
                        GATE_IP_GSCL, 10, 0, 0),
+       GATE(CLK_SMMU_FIMC_LITE0, "smmu_fimc_lite0", "mout_aclk266_gscl_sub",
+                       GATE_IP_GSCL, 11, 0, 0),
+       GATE(CLK_SMMU_FIMC_LITE1, "smmu_fimc_lite1", "mout_aclk266_gscl_sub",
+                       GATE_IP_GSCL, 12, 0, 0),
 
-       GATE(CLK_FIMD1, "fimd1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 0, 0,
-               0),
-       GATE(CLK_MIE1, "mie1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 1, 0,
-               0),
-       GATE(CLK_DSIM0, "dsim0", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 3, 0,
-               0),
-       GATE(CLK_DP, "dp", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 4, 0, 0),
-       GATE(CLK_MIXER, "mixer", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 5, 0,
-               0),
-       GATE(CLK_HDMI, "hdmi", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 6, 0,
-               0),
 
        GATE(CLK_MFC, "mfc", "mout_aclk333_sub", GATE_IP_MFC, 0, 0, 0),
        GATE(CLK_SMMU_MFCR, "smmu_mfcr", "mout_aclk333_sub", GATE_IP_MFC, 1, 0,
@@ -671,10 +667,6 @@ static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = {
        GATE(CLK_WDT, "wdt", "div_aclk66", GATE_IP_PERIS, 19, 0, 0),
        GATE(CLK_RTC, "rtc", "div_aclk66", GATE_IP_PERIS, 20, 0, 0),
        GATE(CLK_TMU, "tmu", "div_aclk66", GATE_IP_PERIS, 21, 0, 0),
-       GATE(CLK_SMMU_TV, "smmu_tv", "mout_aclk200_disp1_sub",
-                       GATE_IP_DISP1, 9, 0, 0),
-       GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "mout_aclk200_disp1_sub",
-                       GATE_IP_DISP1, 8, 0, 0),
        GATE(CLK_SMMU_2D, "smmu_2d", "div_aclk200", GATE_IP_ACP, 7, 0, 0),
        GATE(CLK_SMMU_FIMC_ISP, "smmu_fimc_isp", "mout_aclk_266_isp_sub",
                        GATE_IP_ISP0, 8, 0, 0),
@@ -698,48 +690,80 @@ static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = {
                        GATE_IP_ISP1, 7, 0, 0),
 };
 
+static const struct samsung_gate_clock exynos5250_disp_gate_clks[] __initconst = {
+       GATE(CLK_FIMD1, "fimd1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 0, 0,
+               0),
+       GATE(CLK_MIE1, "mie1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 1, 0,
+               0),
+       GATE(CLK_DSIM0, "dsim0", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 3, 0,
+               0),
+       GATE(CLK_DP, "dp", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 4, 0, 0),
+       GATE(CLK_MIXER, "mixer", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 5, 0,
+               0),
+       GATE(CLK_HDMI, "hdmi", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 6, 0,
+               0),
+       GATE(CLK_SMMU_TV, "smmu_tv", "mout_aclk200_disp1_sub",
+                       GATE_IP_DISP1, 9, 0, 0),
+       GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "mout_aclk200_disp1_sub",
+                       GATE_IP_DISP1, 8, 0, 0),
+};
+
+static struct exynos5_subcmu_reg_dump exynos5250_disp_suspend_regs[] = {
+       { GATE_IP_DISP1, 0xffffffff, 0xffffffff }, /* DISP1 gates */
+       { SRC_TOP3, 0, BIT(4) },        /* MUX mout_aclk200_disp1_sub */
+       { SRC_TOP3, 0, BIT(6) },        /* MUX mout_aclk300_disp1_sub */
+};
+
+static const struct exynos5_subcmu_info exynos5250_disp_subcmu = {
+       .gate_clks      = exynos5250_disp_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5250_disp_gate_clks),
+       .suspend_regs   = exynos5250_disp_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5250_disp_suspend_regs),
+       .pd_name        = "DISP1",
+};
+
 static const struct samsung_pll_rate_table vpll_24mhz_tbl[] __initconst = {
        /* sorted in descending order */
        /* PLL_36XX_RATE(rate, m, p, s, k) */
-       PLL_36XX_RATE(266000000, 266, 3, 3, 0),
+       PLL_36XX_RATE(24 * MHZ, 266000000, 266, 3, 3, 0),
        /* Not in UM, but need for eDP on snow */
-       PLL_36XX_RATE(70500000, 94, 2, 4, 0),
+       PLL_36XX_RATE(24 * MHZ, 70500000, 94, 2, 4, 0),
        { },
 };
 
 static const struct samsung_pll_rate_table epll_24mhz_tbl[] __initconst = {
        /* sorted in descending order */
        /* PLL_36XX_RATE(rate, m, p, s, k) */
-       PLL_36XX_RATE(192000000, 64, 2, 2, 0),
-       PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
-       PLL_36XX_RATE(180000000, 90, 3, 2, 0),
-       PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
-       PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
-       PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
-       PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
-       PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
+       PLL_36XX_RATE(24 * MHZ, 192000000, 64, 2, 2, 0),
+       PLL_36XX_RATE(24 * MHZ, 180633605, 90, 3, 2, 20762),
+       PLL_36XX_RATE(24 * MHZ, 180000000, 90, 3, 2, 0),
+       PLL_36XX_RATE(24 * MHZ, 73728000, 98, 2, 4, 19923),
+       PLL_36XX_RATE(24 * MHZ, 67737602, 90, 2, 4, 20762),
+       PLL_36XX_RATE(24 * MHZ, 49152000, 98, 3, 4, 19923),
+       PLL_36XX_RATE(24 * MHZ, 45158401, 90, 3, 4, 20762),
+       PLL_36XX_RATE(24 * MHZ, 32768001, 131, 3, 5, 4719),
        { },
 };
 
 static const struct samsung_pll_rate_table apll_24mhz_tbl[] __initconst = {
        /* sorted in descending order */
-       /* PLL_35XX_RATE(rate, m, p, s) */
-       PLL_35XX_RATE(1700000000, 425, 6, 0),
-       PLL_35XX_RATE(1600000000, 200, 3, 0),
-       PLL_35XX_RATE(1500000000, 250, 4, 0),
-       PLL_35XX_RATE(1400000000, 175, 3, 0),
-       PLL_35XX_RATE(1300000000, 325, 6, 0),
-       PLL_35XX_RATE(1200000000, 200, 4, 0),
-       PLL_35XX_RATE(1100000000, 275, 6, 0),
-       PLL_35XX_RATE(1000000000, 125, 3, 0),
-       PLL_35XX_RATE(900000000, 150, 4, 0),
-       PLL_35XX_RATE(800000000, 100, 3, 0),
-       PLL_35XX_RATE(700000000, 175, 3, 1),
-       PLL_35XX_RATE(600000000, 200, 4, 1),
-       PLL_35XX_RATE(500000000, 125, 3, 1),
-       PLL_35XX_RATE(400000000, 100, 3, 1),
-       PLL_35XX_RATE(300000000, 200, 4, 2),
-       PLL_35XX_RATE(200000000, 100, 3, 2),
+       /* PLL_35XX_RATE(fin, rate, m, p, s) */
+       PLL_35XX_RATE(24 * MHZ, 1700000000, 425, 6, 0),
+       PLL_35XX_RATE(24 * MHZ, 1600000000, 200, 3, 0),
+       PLL_35XX_RATE(24 * MHZ, 1500000000, 250, 4, 0),
+       PLL_35XX_RATE(24 * MHZ, 1400000000, 175, 3, 0),
+       PLL_35XX_RATE(24 * MHZ, 1300000000, 325, 6, 0),
+       PLL_35XX_RATE(24 * MHZ, 1200000000, 200, 4, 0),
+       PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 6, 0),
+       PLL_35XX_RATE(24 * MHZ, 1000000000, 125, 3, 0),
+       PLL_35XX_RATE(24 * MHZ, 900000000, 150, 4, 0),
+       PLL_35XX_RATE(24 * MHZ, 800000000, 100, 3, 0),
+       PLL_35XX_RATE(24 * MHZ, 700000000, 175, 3, 1),
+       PLL_35XX_RATE(24 * MHZ, 600000000, 200, 4, 1),
+       PLL_35XX_RATE(24 * MHZ, 500000000, 125, 3, 1),
+       PLL_35XX_RATE(24 * MHZ, 400000000, 100, 3, 1),
+       PLL_35XX_RATE(24 * MHZ, 300000000, 200, 4, 2),
+       PLL_35XX_RATE(24 * MHZ, 200000000, 100, 3, 2),
 };
 
 static struct samsung_pll_clock exynos5250_plls[nr_plls] __initdata = {
@@ -859,10 +883,11 @@ static void __init exynos5250_clk_init(struct device_node *np)
        __raw_writel(tmp, reg_base + PWR_CTRL2);
 
        exynos5250_clk_sleep_init();
+       exynos5_subcmus_init(ctx, 1, &exynos5250_disp_subcmu);
 
        samsung_clk_of_add_provider(np, ctx);
 
        pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
                        _get_rate("div_arm2"));
 }
-CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);
+CLK_OF_DECLARE_DRIVER(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);
index fd1d9bfc151b9c4f41f2f2adae512710dc52801f..2cc2583abd879dbd5ec8ec6466ca4a60401374b5 100644 (file)
  * DISP_PLL, EGL_PLL, KFC_PLL, MEM_PLL, BUS_PLL, MEDIA_PLL, G3D_PLL.
  */
 static const struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initconst = {
-       PLL_35XX_RATE(1700000000, 425, 6, 0),
-       PLL_35XX_RATE(1600000000, 200, 3, 0),
-       PLL_35XX_RATE(1500000000, 250, 4, 0),
-       PLL_35XX_RATE(1400000000, 175, 3, 0),
-       PLL_35XX_RATE(1300000000, 325, 6, 0),
-       PLL_35XX_RATE(1200000000, 400, 4, 1),
-       PLL_35XX_RATE(1100000000, 275, 3, 1),
-       PLL_35XX_RATE(1000000000, 250, 3, 1),
-       PLL_35XX_RATE(933000000, 311, 4, 1),
-       PLL_35XX_RATE(900000000, 300, 4, 1),
-       PLL_35XX_RATE(800000000, 200, 3, 1),
-       PLL_35XX_RATE(733000000, 733, 12, 1),
-       PLL_35XX_RATE(700000000, 175, 3, 1),
-       PLL_35XX_RATE(667000000, 667, 12, 1),
-       PLL_35XX_RATE(633000000, 211, 4, 1),
-       PLL_35XX_RATE(620000000, 310, 3, 2),
-       PLL_35XX_RATE(600000000, 400, 4, 2),
-       PLL_35XX_RATE(543000000, 362, 4, 2),
-       PLL_35XX_RATE(533000000, 533, 6, 2),
-       PLL_35XX_RATE(500000000, 250, 3, 2),
-       PLL_35XX_RATE(450000000, 300, 4, 2),
-       PLL_35XX_RATE(400000000, 200, 3, 2),
-       PLL_35XX_RATE(350000000, 175, 3, 2),
-       PLL_35XX_RATE(300000000, 400, 4, 3),
-       PLL_35XX_RATE(266000000, 266, 3, 3),
-       PLL_35XX_RATE(200000000, 200, 3, 3),
-       PLL_35XX_RATE(160000000, 160, 3, 3),
+       PLL_35XX_RATE(24 * MHZ, 1700000000, 425, 6, 0),
+       PLL_35XX_RATE(24 * MHZ, 1600000000, 200, 3, 0),
+       PLL_35XX_RATE(24 * MHZ, 1500000000, 250, 4, 0),
+       PLL_35XX_RATE(24 * MHZ, 1400000000, 175, 3, 0),
+       PLL_35XX_RATE(24 * MHZ, 1300000000, 325, 6, 0),
+       PLL_35XX_RATE(24 * MHZ, 1200000000, 400, 4, 1),
+       PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 3, 1),
+       PLL_35XX_RATE(24 * MHZ, 1000000000, 250, 3, 1),
+       PLL_35XX_RATE(24 * MHZ, 933000000, 311, 4, 1),
+       PLL_35XX_RATE(24 * MHZ, 900000000, 300, 4, 1),
+       PLL_35XX_RATE(24 * MHZ, 800000000, 200, 3, 1),
+       PLL_35XX_RATE(24 * MHZ, 733000000, 733, 12, 1),
+       PLL_35XX_RATE(24 * MHZ, 700000000, 175, 3, 1),
+       PLL_35XX_RATE(24 * MHZ, 667000000, 667, 12, 1),
+       PLL_35XX_RATE(24 * MHZ, 633000000, 211, 4, 1),
+       PLL_35XX_RATE(24 * MHZ, 620000000, 310, 3, 2),
+       PLL_35XX_RATE(24 * MHZ, 600000000, 400, 4, 2),
+       PLL_35XX_RATE(24 * MHZ, 543000000, 362, 4, 2),
+       PLL_35XX_RATE(24 * MHZ, 533000000, 533, 6, 2),
+       PLL_35XX_RATE(24 * MHZ, 500000000, 250, 3, 2),
+       PLL_35XX_RATE(24 * MHZ, 450000000, 300, 4, 2),
+       PLL_35XX_RATE(24 * MHZ, 400000000, 200, 3, 2),
+       PLL_35XX_RATE(24 * MHZ, 350000000, 175, 3, 2),
+       PLL_35XX_RATE(24 * MHZ, 300000000, 400, 4, 3),
+       PLL_35XX_RATE(24 * MHZ, 266000000, 266, 3, 3),
+       PLL_35XX_RATE(24 * MHZ, 200000000, 200, 3, 3),
+       PLL_35XX_RATE(24 * MHZ, 160000000, 160, 3, 3),
 };
 
 /*
  * Applicable for 2650 Type PLL for AUD_PLL.
  */
 static const struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initconst = {
-       PLL_36XX_RATE(1600000000, 200, 3, 0, 0),
-       PLL_36XX_RATE(1200000000, 100, 2, 0, 0),
-       PLL_36XX_RATE(1000000000, 250, 3, 1, 0),
-       PLL_36XX_RATE(800000000, 200, 3, 1, 0),
-       PLL_36XX_RATE(600000000, 100, 2, 1, 0),
-       PLL_36XX_RATE(532000000, 266, 3, 2, 0),
-       PLL_36XX_RATE(480000000, 160, 2, 2, 0),
-       PLL_36XX_RATE(432000000, 144, 2, 2, 0),
-       PLL_36XX_RATE(400000000, 200, 3, 2, 0),
-       PLL_36XX_RATE(394073130, 459, 7, 2, 49282),
-       PLL_36XX_RATE(333000000, 111, 2, 2, 0),
-       PLL_36XX_RATE(300000000, 100, 2, 2, 0),
-       PLL_36XX_RATE(266000000, 266, 3, 3, 0),
-       PLL_36XX_RATE(200000000, 200, 3, 3, 0),
-       PLL_36XX_RATE(166000000, 166, 3, 3, 0),
-       PLL_36XX_RATE(133000000, 266, 3, 4, 0),
-       PLL_36XX_RATE(100000000, 200, 3, 4, 0),
-       PLL_36XX_RATE(66000000, 176, 2, 5, 0),
+       PLL_36XX_RATE(24 * MHZ, 1600000000, 200, 3, 0, 0),
+       PLL_36XX_RATE(24 * MHZ, 1200000000, 100, 2, 0, 0),
+       PLL_36XX_RATE(24 * MHZ, 1000000000, 250, 3, 1, 0),
+       PLL_36XX_RATE(24 * MHZ, 800000000, 200, 3, 1, 0),
+       PLL_36XX_RATE(24 * MHZ, 600000000, 100, 2, 1, 0),
+       PLL_36XX_RATE(24 * MHZ, 532000000, 266, 3, 2, 0),
+       PLL_36XX_RATE(24 * MHZ, 480000000, 160, 2, 2, 0),
+       PLL_36XX_RATE(24 * MHZ, 432000000, 144, 2, 2, 0),
+       PLL_36XX_RATE(24 * MHZ, 400000000, 200, 3, 2, 0),
+       PLL_36XX_RATE(24 * MHZ, 394073128, 459, 7, 2, 49282),
+       PLL_36XX_RATE(24 * MHZ, 333000000, 111, 2, 2, 0),
+       PLL_36XX_RATE(24 * MHZ, 300000000, 100, 2, 2, 0),
+       PLL_36XX_RATE(24 * MHZ, 266000000, 266, 3, 3, 0),
+       PLL_36XX_RATE(24 * MHZ, 200000000, 200, 3, 3, 0),
+       PLL_36XX_RATE(24 * MHZ, 166000000, 166, 3, 3, 0),
+       PLL_36XX_RATE(24 * MHZ, 133000000, 266, 3, 4, 0),
+       PLL_36XX_RATE(24 * MHZ, 100000000, 200, 3, 4, 0),
+       PLL_36XX_RATE(24 * MHZ, 66000000, 176, 2, 5, 0),
 };
 
 /* CMU_AUD */
index fc471a49e8f4fe066924099ea944d9e4dc212681..0a0b09591e6fd8493242e05df2943e1cfa0666ab 100644 (file)
@@ -226,16 +226,16 @@ static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = {
 };
 
 static const struct samsung_pll_rate_table exynos5410_pll2550x_24mhz_tbl[] __initconst = {
-       PLL_36XX_RATE(400000000U, 200, 3, 2, 0),
-       PLL_36XX_RATE(333000000U, 111, 2, 2, 0),
-       PLL_36XX_RATE(300000000U, 100, 2, 2, 0),
-       PLL_36XX_RATE(266000000U, 266, 3, 3, 0),
-       PLL_36XX_RATE(200000000U, 200, 3, 3, 0),
-       PLL_36XX_RATE(192000000U, 192, 3, 3, 0),
-       PLL_36XX_RATE(166000000U, 166, 3, 3, 0),
-       PLL_36XX_RATE(133000000U, 266, 3, 4, 0),
-       PLL_36XX_RATE(100000000U, 200, 3, 4, 0),
-       PLL_36XX_RATE(66000000U,  176, 2, 5, 0),
+       PLL_36XX_RATE(24 * MHZ, 400000000U, 200, 3, 2, 0),
+       PLL_36XX_RATE(24 * MHZ, 333000000U, 111, 2, 2, 0),
+       PLL_36XX_RATE(24 * MHZ, 300000000U, 100, 2, 2, 0),
+       PLL_36XX_RATE(24 * MHZ, 266000000U, 266, 3, 3, 0),
+       PLL_36XX_RATE(24 * MHZ, 200000000U, 200, 3, 3, 0),
+       PLL_36XX_RATE(24 * MHZ, 192000000U, 192, 3, 3, 0),
+       PLL_36XX_RATE(24 * MHZ, 166000000U, 166, 3, 3, 0),
+       PLL_36XX_RATE(24 * MHZ, 133000000U, 266, 3, 4, 0),
+       PLL_36XX_RATE(24 * MHZ, 100000000U, 200, 3, 4, 0),
+       PLL_36XX_RATE(24 * MHZ, 66000000U,  176, 2, 5, 0),
 };
 
 static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
index 45d34f601e9e0abfa5eac115272df833c4c86ce1..95e1bf69449b75c1812c095f2db2483deac91dae 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "clk.h"
 #include "clk-cpu.h"
+#include "clk-exynos5-subcmu.h"
 
 #define APLL_LOCK              0x0
 #define APLL_CON0              0x100
@@ -620,7 +621,8 @@ static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = {
 
        MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore",
                        mout_group5_5800_p, SRC_TOP7, 16, 2),
-       MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_p, SRC_TOP7, 20, 2),
+       MUX_F(0, "mout_mau_epll_clk", mout_mau_epll_clk_p, SRC_TOP7, 20, 2,
+             CLK_SET_RATE_PARENT, 0),
 
        MUX(0, "mout_fimd1", mout_group3_p, SRC_DISP10, 4, 1),
 };
@@ -863,7 +865,6 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = {
        DIV(0, "dout_mipi1", "mout_mipi1", DIV_DISP10, 16, 8),
        DIV(0, "dout_dp1", "mout_dp1", DIV_DISP10, 24, 4),
        DIV(CLK_DOUT_PIXEL, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4),
-       DIV(0, "dout_disp1_blk", "aclk200_disp1", DIV2_RATIO0, 16, 2),
        DIV(CLK_DOUT_ACLK400_DISP1, "dout_aclk400_disp1",
                        "mout_aclk400_disp1", DIV_TOP2, 4, 3),
 
@@ -912,8 +913,6 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = {
        DIV(0, "dout_spi1", "mout_spi1", DIV_PERIC1, 24, 4),
        DIV(0, "dout_spi2", "mout_spi2", DIV_PERIC1, 28, 4),
 
-       /* Mfc Block */
-       DIV(0, "dout_mfc_blk", "mout_user_aclk333", DIV4_RATIO, 0, 2),
 
        /* PCM */
        DIV(0, "dout_pcm1", "dout_audio1", DIV_PERIC2, 16, 8),
@@ -932,8 +931,6 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = {
        DIV(0, "dout_spi2_pre", "dout_spi2", DIV_PERIC4, 24, 8),
 
        /* GSCL Block */
-       DIV(0, "dout_gscl_blk_300", "mout_user_aclk300_gscl",
-                       DIV2_RATIO0, 4, 2),
        DIV(0, "dout_gscl_blk_333", "aclk333_432_gscl", DIV2_RATIO0, 6, 2),
 
        /* MSCL Block */
@@ -1190,8 +1187,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
        GATE(CLK_SCLK_GSCL_WB, "sclk_gscl_wb", "mout_user_aclk333_432_gscl",
                        GATE_TOP_SCLK_GSCL, 7, 0, 0),
 
-       GATE(CLK_GSCL0, "gscl0", "aclk300_gscl", GATE_IP_GSCL0, 0, 0, 0),
-       GATE(CLK_GSCL1, "gscl1", "aclk300_gscl", GATE_IP_GSCL0, 1, 0, 0),
        GATE(CLK_FIMC_3AA, "fimc_3aa", "aclk333_432_gscl",
                        GATE_IP_GSCL0, 4, 0, 0),
        GATE(CLK_FIMC_LITE0, "fimc_lite0", "aclk333_432_gscl",
@@ -1205,10 +1200,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
                        GATE_IP_GSCL1, 3, 0, 0),
        GATE(CLK_SMMU_FIMCL1, "smmu_fimcl1", "dout_gscl_blk_333",
                        GATE_IP_GSCL1, 4, 0, 0),
-       GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "dout_gscl_blk_300",
-                       GATE_IP_GSCL1, 6, 0, 0),
-       GATE(CLK_SMMU_GSCL1, "smmu_gscl1", "dout_gscl_blk_300",
-                       GATE_IP_GSCL1, 7, 0, 0),
        GATE(CLK_GSCL_WA, "gscl_wa", "sclk_gscl_wa", GATE_IP_GSCL1, 12, 0, 0),
        GATE(CLK_GSCL_WB, "gscl_wb", "sclk_gscl_wb", GATE_IP_GSCL1, 13, 0, 0),
        GATE(CLK_SMMU_FIMCL3, "smmu_fimcl3,", "dout_gscl_blk_333",
@@ -1227,18 +1218,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
        GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk",
                        GATE_IP_MSCL, 10, 0, 0),
 
-       GATE(CLK_FIMD1, "fimd1", "aclk300_disp1", GATE_IP_DISP1, 0, 0, 0),
-       GATE(CLK_DSIM1, "dsim1", "aclk200_disp1", GATE_IP_DISP1, 3, 0, 0),
-       GATE(CLK_DP1, "dp1", "aclk200_disp1", GATE_IP_DISP1, 4, 0, 0),
-       GATE(CLK_MIXER, "mixer", "aclk200_disp1", GATE_IP_DISP1, 5, 0, 0),
-       GATE(CLK_HDMI, "hdmi", "aclk200_disp1", GATE_IP_DISP1, 6, 0, 0),
-       GATE(CLK_SMMU_FIMD1M0, "smmu_fimd1m0", "dout_disp1_blk",
-                       GATE_IP_DISP1, 7, 0, 0),
-       GATE(CLK_SMMU_FIMD1M1, "smmu_fimd1m1", "dout_disp1_blk",
-                       GATE_IP_DISP1, 8, 0, 0),
-       GATE(CLK_SMMU_MIXER, "smmu_mixer", "aclk200_disp1",
-                       GATE_IP_DISP1, 9, 0, 0),
-
        /* ISP */
        GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "dout_uart_isp",
                        GATE_TOP_SCLK_ISP, 0, CLK_SET_RATE_PARENT, 0),
@@ -1255,48 +1234,138 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
        GATE(CLK_SCLK_ISP_SENSOR2, "sclk_isp_sensor2", "dout_isp_sensor2",
                        GATE_TOP_SCLK_ISP, 12, CLK_SET_RATE_PARENT, 0),
 
+       GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
+};
+
+static const struct samsung_div_clock exynos5x_disp_div_clks[] __initconst = {
+       DIV(0, "dout_disp1_blk", "aclk200_disp1", DIV2_RATIO0, 16, 2),
+};
+
+static const struct samsung_gate_clock exynos5x_disp_gate_clks[] __initconst = {
+       GATE(CLK_FIMD1, "fimd1", "aclk300_disp1", GATE_IP_DISP1, 0, 0, 0),
+       GATE(CLK_DSIM1, "dsim1", "aclk200_disp1", GATE_IP_DISP1, 3, 0, 0),
+       GATE(CLK_DP1, "dp1", "aclk200_disp1", GATE_IP_DISP1, 4, 0, 0),
+       GATE(CLK_MIXER, "mixer", "aclk200_disp1", GATE_IP_DISP1, 5, 0, 0),
+       GATE(CLK_HDMI, "hdmi", "aclk200_disp1", GATE_IP_DISP1, 6, 0, 0),
+       GATE(CLK_SMMU_FIMD1M0, "smmu_fimd1m0", "dout_disp1_blk",
+                       GATE_IP_DISP1, 7, 0, 0),
+       GATE(CLK_SMMU_FIMD1M1, "smmu_fimd1m1", "dout_disp1_blk",
+                       GATE_IP_DISP1, 8, 0, 0),
+       GATE(CLK_SMMU_MIXER, "smmu_mixer", "aclk200_disp1",
+                       GATE_IP_DISP1, 9, 0, 0),
+};
+
+static struct exynos5_subcmu_reg_dump exynos5x_disp_suspend_regs[] = {
+       { GATE_IP_DISP1, 0xffffffff, 0xffffffff }, /* DISP1 gates */
+       { SRC_TOP5, 0, BIT(0) },        /* MUX mout_user_aclk400_disp1 */
+       { SRC_TOP5, 0, BIT(24) },       /* MUX mout_user_aclk300_disp1 */
+       { SRC_TOP3, 0, BIT(8) },        /* MUX mout_user_aclk200_disp1 */
+       { DIV2_RATIO0, 0, 0x30000 },            /* DIV dout_disp1_blk */
+};
+
+static const struct samsung_div_clock exynos5x_gsc_div_clks[] __initconst = {
+       DIV(0, "dout_gscl_blk_300", "mout_user_aclk300_gscl",
+                       DIV2_RATIO0, 4, 2),
+};
+
+static const struct samsung_gate_clock exynos5x_gsc_gate_clks[] __initconst = {
+       GATE(CLK_GSCL0, "gscl0", "aclk300_gscl", GATE_IP_GSCL0, 0, 0, 0),
+       GATE(CLK_GSCL1, "gscl1", "aclk300_gscl", GATE_IP_GSCL0, 1, 0, 0),
+       GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "dout_gscl_blk_300",
+                       GATE_IP_GSCL1, 6, 0, 0),
+       GATE(CLK_SMMU_GSCL1, "smmu_gscl1", "dout_gscl_blk_300",
+                       GATE_IP_GSCL1, 7, 0, 0),
+};
+
+static struct exynos5_subcmu_reg_dump exynos5x_gsc_suspend_regs[] = {
+       { GATE_IP_GSCL0, 0x3, 0x3 },    /* GSC gates */
+       { GATE_IP_GSCL1, 0xc0, 0xc0 },  /* GSC gates */
+       { SRC_TOP5, 0, BIT(28) },       /* MUX mout_user_aclk300_gscl */
+       { DIV2_RATIO0, 0, 0x30 },       /* DIV dout_gscl_blk_300 */
+};
+
+static const struct samsung_div_clock exynos5x_mfc_div_clks[] __initconst = {
+       DIV(0, "dout_mfc_blk", "mout_user_aclk333", DIV4_RATIO, 0, 2),
+};
+
+static const struct samsung_gate_clock exynos5x_mfc_gate_clks[] __initconst = {
        GATE(CLK_MFC, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0),
        GATE(CLK_SMMU_MFCL, "smmu_mfcl", "dout_mfc_blk", GATE_IP_MFC, 1, 0, 0),
        GATE(CLK_SMMU_MFCR, "smmu_mfcr", "dout_mfc_blk", GATE_IP_MFC, 2, 0, 0),
+};
 
-       GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
+static struct exynos5_subcmu_reg_dump exynos5x_mfc_suspend_regs[] = {
+       { GATE_IP_MFC, 0xffffffff, 0xffffffff }, /* MFC gates */
+       { SRC_TOP4, 0, BIT(28) },               /* MUX mout_user_aclk333 */
+       { DIV4_RATIO, 0, 0x3 },                 /* DIV dout_mfc_blk */
+};
+
+static const struct exynos5_subcmu_info exynos5x_subcmus[] = {
+       {
+               .div_clks       = exynos5x_disp_div_clks,
+               .nr_div_clks    = ARRAY_SIZE(exynos5x_disp_div_clks),
+               .gate_clks      = exynos5x_disp_gate_clks,
+               .nr_gate_clks   = ARRAY_SIZE(exynos5x_disp_gate_clks),
+               .suspend_regs   = exynos5x_disp_suspend_regs,
+               .nr_suspend_regs = ARRAY_SIZE(exynos5x_disp_suspend_regs),
+               .pd_name        = "DISP",
+       }, {
+               .div_clks       = exynos5x_gsc_div_clks,
+               .nr_div_clks    = ARRAY_SIZE(exynos5x_gsc_div_clks),
+               .gate_clks      = exynos5x_gsc_gate_clks,
+               .nr_gate_clks   = ARRAY_SIZE(exynos5x_gsc_gate_clks),
+               .suspend_regs   = exynos5x_gsc_suspend_regs,
+               .nr_suspend_regs = ARRAY_SIZE(exynos5x_gsc_suspend_regs),
+               .pd_name        = "GSC",
+       }, {
+               .div_clks       = exynos5x_mfc_div_clks,
+               .nr_div_clks    = ARRAY_SIZE(exynos5x_mfc_div_clks),
+               .gate_clks      = exynos5x_mfc_gate_clks,
+               .nr_gate_clks   = ARRAY_SIZE(exynos5x_mfc_gate_clks),
+               .suspend_regs   = exynos5x_mfc_suspend_regs,
+               .nr_suspend_regs = ARRAY_SIZE(exynos5x_mfc_suspend_regs),
+               .pd_name        = "MFC",
+       },
 };
 
 static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __initconst = {
-       PLL_35XX_RATE(2000000000, 250, 3, 0),
-       PLL_35XX_RATE(1900000000, 475, 6, 0),
-       PLL_35XX_RATE(1800000000, 225, 3, 0),
-       PLL_35XX_RATE(1700000000, 425, 6, 0),
-       PLL_35XX_RATE(1600000000, 200, 3, 0),
-       PLL_35XX_RATE(1500000000, 250, 4, 0),
-       PLL_35XX_RATE(1400000000, 175, 3, 0),
-       PLL_35XX_RATE(1300000000, 325, 6, 0),
-       PLL_35XX_RATE(1200000000, 200, 2, 1),
-       PLL_35XX_RATE(1100000000, 275, 3, 1),
-       PLL_35XX_RATE(1000000000, 250, 3, 1),
-       PLL_35XX_RATE(900000000,  150, 2, 1),
-       PLL_35XX_RATE(800000000,  200, 3, 1),
-       PLL_35XX_RATE(700000000,  175, 3, 1),
-       PLL_35XX_RATE(600000000,  200, 2, 2),
-       PLL_35XX_RATE(500000000,  250, 3, 2),
-       PLL_35XX_RATE(400000000,  200, 3, 2),
-       PLL_35XX_RATE(300000000,  200, 2, 3),
-       PLL_35XX_RATE(200000000,  200, 3, 3),
+       PLL_35XX_RATE(24 * MHZ, 2000000000, 250, 3, 0),
+       PLL_35XX_RATE(24 * MHZ, 1900000000, 475, 6, 0),
+       PLL_35XX_RATE(24 * MHZ, 1800000000, 225, 3, 0),
+       PLL_35XX_RATE(24 * MHZ, 1700000000, 425, 6, 0),
+       PLL_35XX_RATE(24 * MHZ, 1600000000, 200, 3, 0),
+       PLL_35XX_RATE(24 * MHZ, 1500000000, 250, 4, 0),
+       PLL_35XX_RATE(24 * MHZ, 1400000000, 175, 3, 0),
+       PLL_35XX_RATE(24 * MHZ, 1300000000, 325, 6, 0),
+       PLL_35XX_RATE(24 * MHZ, 1200000000, 200, 2, 1),
+       PLL_35XX_RATE(24 * MHZ, 1100000000, 275, 3, 1),
+       PLL_35XX_RATE(24 * MHZ, 1000000000, 250, 3, 1),
+       PLL_35XX_RATE(24 * MHZ, 900000000,  150, 2, 1),
+       PLL_35XX_RATE(24 * MHZ, 800000000,  200, 3, 1),
+       PLL_35XX_RATE(24 * MHZ, 700000000,  175, 3, 1),
+       PLL_35XX_RATE(24 * MHZ, 600000000,  200, 2, 2),
+       PLL_35XX_RATE(24 * MHZ, 500000000,  250, 3, 2),
+       PLL_35XX_RATE(24 * MHZ, 400000000,  200, 3, 2),
+       PLL_35XX_RATE(24 * MHZ, 300000000,  200, 2, 3),
+       PLL_35XX_RATE(24 * MHZ, 200000000,  200, 3, 3),
 };
 
 static const struct samsung_pll_rate_table exynos5420_epll_24mhz_tbl[] = {
-       PLL_36XX_RATE(600000000U, 100, 2, 1, 0),
-       PLL_36XX_RATE(400000000U, 200, 3, 2, 0),
-       PLL_36XX_RATE(393216003U, 197, 3, 2, -25690),
-       PLL_36XX_RATE(361267218U, 301, 5, 2, 3671),
-       PLL_36XX_RATE(200000000U, 200, 3, 3, 0),
-       PLL_36XX_RATE(196608001U, 197, 3, 3, -25690),
-       PLL_36XX_RATE(180633609U, 301, 5, 3, 3671),
-       PLL_36XX_RATE(131072006U, 131, 3, 3, 4719),
-       PLL_36XX_RATE(100000000U, 200, 3, 4, 0),
-       PLL_36XX_RATE( 65536003U, 131, 3, 4, 4719),
-       PLL_36XX_RATE( 49152000U, 197, 3, 5, -25690),
-       PLL_36XX_RATE( 32768001U, 131, 3, 5, 4719),
+       PLL_36XX_RATE(24 * MHZ, 600000000U, 100, 2, 1, 0),
+       PLL_36XX_RATE(24 * MHZ, 400000000U, 200, 3, 2, 0),
+       PLL_36XX_RATE(24 * MHZ, 393216003U, 197, 3, 2, -25690),
+       PLL_36XX_RATE(24 * MHZ, 361267218U, 301, 5, 2, 3671),
+       PLL_36XX_RATE(24 * MHZ, 200000000U, 200, 3, 3, 0),
+       PLL_36XX_RATE(24 * MHZ, 196608001U, 197, 3, 3, -25690),
+       PLL_36XX_RATE(24 * MHZ, 180633609U, 301, 5, 3, 3671),
+       PLL_36XX_RATE(24 * MHZ, 131072006U, 131, 3, 3, 4719),
+       PLL_36XX_RATE(24 * MHZ, 100000000U, 200, 3, 4, 0),
+       PLL_36XX_RATE(24 * MHZ,  73728000U, 98, 2, 4, 19923),
+       PLL_36XX_RATE(24 * MHZ,  67737602U, 90, 2, 4, 20762),
+       PLL_36XX_RATE(24 * MHZ,  65536003U, 131, 3, 4, 4719),
+       PLL_36XX_RATE(24 * MHZ,  49152000U, 197, 3, 5, -25690),
+       PLL_36XX_RATE(24 * MHZ,  45158401U, 90, 3, 4, 20762),
+       PLL_36XX_RATE(24 * MHZ,  32768001U, 131, 3, 5, 4719),
 };
 
 static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
@@ -1472,6 +1541,8 @@ static void __init exynos5x_clk_init(struct device_node *np,
                exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0);
 
        exynos5420_clk_sleep_init();
+       exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5x_subcmus),
+                            exynos5x_subcmus);
 
        samsung_clk_of_add_provider(np, ctx);
 }
@@ -1480,10 +1551,12 @@ static void __init exynos5420_clk_init(struct device_node *np)
 {
        exynos5x_clk_init(np, EXYNOS5420);
 }
-CLK_OF_DECLARE(exynos5420_clk, "samsung,exynos5420-clock", exynos5420_clk_init);
+CLK_OF_DECLARE_DRIVER(exynos5420_clk, "samsung,exynos5420-clock",
+                     exynos5420_clk_init);
 
 static void __init exynos5800_clk_init(struct device_node *np)
 {
        exynos5x_clk_init(np, EXYNOS5800);
 }
-CLK_OF_DECLARE(exynos5800_clk, "samsung,exynos5800-clock", exynos5800_clk_init);
+CLK_OF_DECLARE_DRIVER(exynos5800_clk, "samsung,exynos5800-clock",
+                     exynos5800_clk_init);
index db270908037abc097d1ec7b43a1a10677cc7eaed..5305ace514b2dd03c922cf12f9e53d01505c8595 100644 (file)
@@ -703,68 +703,69 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
  * & MPHY_PLL & G3D_PLL & DISP_PLL & ISP_PLL
  */
 static const struct samsung_pll_rate_table exynos5433_pll_rates[] __initconst = {
-       PLL_35XX_RATE(2500000000U, 625, 6,  0),
-       PLL_35XX_RATE(2400000000U, 500, 5,  0),
-       PLL_35XX_RATE(2300000000U, 575, 6,  0),
-       PLL_35XX_RATE(2200000000U, 550, 6,  0),
-       PLL_35XX_RATE(2100000000U, 350, 4,  0),
-       PLL_35XX_RATE(2000000000U, 500, 6,  0),
-       PLL_35XX_RATE(1900000000U, 475, 6,  0),
-       PLL_35XX_RATE(1800000000U, 375, 5,  0),
-       PLL_35XX_RATE(1700000000U, 425, 6,  0),
-       PLL_35XX_RATE(1600000000U, 400, 6,  0),
-       PLL_35XX_RATE(1500000000U, 250, 4,  0),
-       PLL_35XX_RATE(1400000000U, 350, 6,  0),
-       PLL_35XX_RATE(1332000000U, 222, 4,  0),
-       PLL_35XX_RATE(1300000000U, 325, 6,  0),
-       PLL_35XX_RATE(1200000000U, 500, 5,  1),
-       PLL_35XX_RATE(1100000000U, 550, 6,  1),
-       PLL_35XX_RATE(1086000000U, 362, 4,  1),
-       PLL_35XX_RATE(1066000000U, 533, 6,  1),
-       PLL_35XX_RATE(1000000000U, 500, 6,  1),
-       PLL_35XX_RATE(933000000U,  311, 4,  1),
-       PLL_35XX_RATE(921000000U,  307, 4,  1),
-       PLL_35XX_RATE(900000000U,  375, 5,  1),
-       PLL_35XX_RATE(825000000U,  275, 4,  1),
-       PLL_35XX_RATE(800000000U,  400, 6,  1),
-       PLL_35XX_RATE(733000000U,  733, 12, 1),
-       PLL_35XX_RATE(700000000U,  175, 3,  1),
-       PLL_35XX_RATE(667000000U,  222, 4,  1),
-       PLL_35XX_RATE(633000000U,  211, 4,  1),
-       PLL_35XX_RATE(600000000U,  500, 5,  2),
-       PLL_35XX_RATE(552000000U,  460, 5,  2),
-       PLL_35XX_RATE(550000000U,  550, 6,  2),
-       PLL_35XX_RATE(543000000U,  362, 4,  2),
-       PLL_35XX_RATE(533000000U,  533, 6,  2),
-       PLL_35XX_RATE(500000000U,  500, 6,  2),
-       PLL_35XX_RATE(444000000U,  370, 5,  2),
-       PLL_35XX_RATE(420000000U,  350, 5,  2),
-       PLL_35XX_RATE(400000000U,  400, 6,  2),
-       PLL_35XX_RATE(350000000U,  350, 6,  2),
-       PLL_35XX_RATE(333000000U,  222, 4,  2),
-       PLL_35XX_RATE(300000000U,  500, 5,  3),
-       PLL_35XX_RATE(278000000U,  556, 6,  3),
-       PLL_35XX_RATE(266000000U,  532, 6,  3),
-       PLL_35XX_RATE(250000000U,  500, 6,  3),
-       PLL_35XX_RATE(200000000U,  400, 6,  3),
-       PLL_35XX_RATE(166000000U,  332, 6,  3),
-       PLL_35XX_RATE(160000000U,  320, 6,  3),
-       PLL_35XX_RATE(133000000U,  532, 6,  4),
-       PLL_35XX_RATE(100000000U,  400, 6,  4),
+       PLL_35XX_RATE(24 * MHZ, 2500000000U, 625, 6,  0),
+       PLL_35XX_RATE(24 * MHZ, 2400000000U, 500, 5,  0),
+       PLL_35XX_RATE(24 * MHZ, 2300000000U, 575, 6,  0),
+       PLL_35XX_RATE(24 * MHZ, 2200000000U, 550, 6,  0),
+       PLL_35XX_RATE(24 * MHZ, 2100000000U, 350, 4,  0),
+       PLL_35XX_RATE(24 * MHZ, 2000000000U, 500, 6,  0),
+       PLL_35XX_RATE(24 * MHZ, 1900000000U, 475, 6,  0),
+       PLL_35XX_RATE(24 * MHZ, 1800000000U, 375, 5,  0),
+       PLL_35XX_RATE(24 * MHZ, 1700000000U, 425, 6,  0),
+       PLL_35XX_RATE(24 * MHZ, 1600000000U, 400, 6,  0),
+       PLL_35XX_RATE(24 * MHZ, 1500000000U, 250, 4,  0),
+       PLL_35XX_RATE(24 * MHZ, 1400000000U, 350, 6,  0),
+       PLL_35XX_RATE(24 * MHZ, 1332000000U, 222, 4,  0),
+       PLL_35XX_RATE(24 * MHZ, 1300000000U, 325, 6,  0),
+       PLL_35XX_RATE(24 * MHZ, 1200000000U, 500, 5,  1),
+       PLL_35XX_RATE(24 * MHZ, 1100000000U, 550, 6,  1),
+       PLL_35XX_RATE(24 * MHZ, 1086000000U, 362, 4,  1),
+       PLL_35XX_RATE(24 * MHZ, 1066000000U, 533, 6,  1),
+       PLL_35XX_RATE(24 * MHZ, 1000000000U, 500, 6,  1),
+       PLL_35XX_RATE(24 * MHZ, 933000000U,  311, 4,  1),
+       PLL_35XX_RATE(24 * MHZ, 921000000U,  307, 4,  1),
+       PLL_35XX_RATE(24 * MHZ, 900000000U,  375, 5,  1),
+       PLL_35XX_RATE(24 * MHZ, 825000000U,  275, 4,  1),
+       PLL_35XX_RATE(24 * MHZ, 800000000U,  400, 6,  1),
+       PLL_35XX_RATE(24 * MHZ, 733000000U,  733, 12, 1),
+       PLL_35XX_RATE(24 * MHZ, 700000000U,  175, 3,  1),
+       PLL_35XX_RATE(24 * MHZ, 666000000U,  222, 4,  1),
+       PLL_35XX_RATE(24 * MHZ, 633000000U,  211, 4,  1),
+       PLL_35XX_RATE(24 * MHZ, 600000000U,  500, 5,  2),
+       PLL_35XX_RATE(24 * MHZ, 552000000U,  460, 5,  2),
+       PLL_35XX_RATE(24 * MHZ, 550000000U,  550, 6,  2),
+       PLL_35XX_RATE(24 * MHZ, 543000000U,  362, 4,  2),
+       PLL_35XX_RATE(24 * MHZ, 533000000U,  533, 6,  2),
+       PLL_35XX_RATE(24 * MHZ, 500000000U,  500, 6,  2),
+       PLL_35XX_RATE(24 * MHZ, 444000000U,  370, 5,  2),
+       PLL_35XX_RATE(24 * MHZ, 420000000U,  350, 5,  2),
+       PLL_35XX_RATE(24 * MHZ, 400000000U,  400, 6,  2),
+       PLL_35XX_RATE(24 * MHZ, 350000000U,  350, 6,  2),
+       PLL_35XX_RATE(24 * MHZ, 333000000U,  222, 4,  2),
+       PLL_35XX_RATE(24 * MHZ, 300000000U,  500, 5,  3),
+       PLL_35XX_RATE(24 * MHZ, 278000000U,  556, 6,  3),
+       PLL_35XX_RATE(24 * MHZ, 266000000U,  532, 6,  3),
+       PLL_35XX_RATE(24 * MHZ, 250000000U,  500, 6,  3),
+       PLL_35XX_RATE(24 * MHZ, 200000000U,  400, 6,  3),
+       PLL_35XX_RATE(24 * MHZ, 166000000U,  332, 6,  3),
+       PLL_35XX_RATE(24 * MHZ, 160000000U,  320, 6,  3),
+       PLL_35XX_RATE(24 * MHZ, 133000000U,  532, 6,  4),
+       PLL_35XX_RATE(24 * MHZ, 100000000U,  400, 6,  4),
        { /* sentinel */ }
 };
 
 /* AUD_PLL */
 static const struct samsung_pll_rate_table exynos5433_aud_pll_rates[] __initconst = {
-       PLL_36XX_RATE(400000000U, 200, 3, 2,      0),
-       PLL_36XX_RATE(393216000U, 197, 3, 2, -25690),
-       PLL_36XX_RATE(384000000U, 128, 2, 2,      0),
-       PLL_36XX_RATE(368640000U, 246, 4, 2, -15729),
-       PLL_36XX_RATE(361507200U, 181, 3, 2, -16148),
-       PLL_36XX_RATE(338688000U, 113, 2, 2,  -6816),
-       PLL_36XX_RATE(294912000U,  98, 1, 3,  19923),
-       PLL_36XX_RATE(288000000U,  96, 1, 3,      0),
-       PLL_36XX_RATE(252000000U,  84, 1, 3,      0),
+       PLL_36XX_RATE(24 * MHZ, 400000000U, 200, 3, 2,      0),
+       PLL_36XX_RATE(24 * MHZ, 393216003U, 197, 3, 2, -25690),
+       PLL_36XX_RATE(24 * MHZ, 384000000U, 128, 2, 2,      0),
+       PLL_36XX_RATE(24 * MHZ, 368639991U, 246, 4, 2, -15729),
+       PLL_36XX_RATE(24 * MHZ, 361507202U, 181, 3, 2, -16148),
+       PLL_36XX_RATE(24 * MHZ, 338687988U, 113, 2, 2,  -6816),
+       PLL_36XX_RATE(24 * MHZ, 294912002U,  98, 1, 3,  19923),
+       PLL_36XX_RATE(24 * MHZ, 288000000U,  96, 1, 3,      0),
+       PLL_36XX_RATE(24 * MHZ, 252000000U,  84, 1, 3,      0),
+       PLL_36XX_RATE(24 * MHZ, 196608001U, 197, 3, 3, -25690),
        { /* sentinel */ }
 };
 
@@ -1672,7 +1673,7 @@ static const struct samsung_gate_clock peric_gate_clks[] __initconst = {
                        ENABLE_SCLK_PERIC, 11, CLK_SET_RATE_PARENT, 0),
        GATE(CLK_SCLK_IOCLK_I2S1_BCLK, "sclk_ioclk_i2s1_bclk",
                        "ioclk_i2s1_bclk_in", ENABLE_SCLK_PERIC, 10,
-                       CLK_SET_RATE_PARENT, 0),
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
        GATE(CLK_SCLK_SPDIF, "sclk_spdif", "sclk_spdif_peric",
                        ENABLE_SCLK_PERIC, 8, CLK_SET_RATE_PARENT, 0),
        GATE(CLK_SCLK_PCM1, "sclk_pcm1", "sclk_pcm1_peric",
@@ -5513,10 +5514,8 @@ static int __init exynos5433_cmu_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        reg_base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(reg_base)) {
-               dev_err(dev, "failed to map registers\n");
+       if (IS_ERR(reg_base))
                return PTR_ERR(reg_base);
-       }
 
        for (i = 0; i < info->nr_clk_ids; ++i)
                ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
index 5931a4140c3d3f264d75510c277e06401dc31944..492d5169108002c2ad24e2d019cf5bbbb205ce70 100644 (file)
@@ -140,7 +140,7 @@ static const struct samsung_div_clock topc_div_clks[] __initconst = {
 };
 
 static const struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initconst = {
-       PLL_36XX_RATE(491520000, 20, 1, 0, 31457),
+       PLL_36XX_RATE(24 * MHZ, 491519897, 20, 1, 0, 31457),
        {},
 };
 
index 61eb8abbfd9c3142ae8173f0311686e3dfc937ad..ca57b3dfa814a3f585e575a438775ba65f1b405c 100644 (file)
@@ -41,35 +41,62 @@ enum samsung_pll_type {
        pll_1460x,
 };
 
-#define PLL_35XX_RATE(_rate, _m, _p, _s)                       \
+#define PLL_RATE(_fin, _m, _p, _s, _k, _ks) \
+       ((u64)(_fin) * (BIT(_ks) * (_m) + (_k)) / BIT(_ks) / ((_p) << (_s)))
+#define PLL_VALID_RATE(_fin, _fout, _m, _p, _s, _k, _ks) ((_fout) + \
+       BUILD_BUG_ON_ZERO(PLL_RATE(_fin, _m, _p, _s, _k, _ks) != (_fout)))
+
+#define PLL_35XX_RATE(_fin, _rate, _m, _p, _s)                 \
+       {                                                       \
+               .rate   =       PLL_VALID_RATE(_fin, _rate,     \
+                               _m, _p, _s, 0, 16),             \
+               .mdiv   =       (_m),                           \
+               .pdiv   =       (_p),                           \
+               .sdiv   =       (_s),                           \
+       }
+
+#define PLL_S3C2410_MPLL_RATE(_fin, _rate, _m, _p, _s)         \
+       {                                                       \
+               .rate   =       PLL_VALID_RATE(_fin, _rate,     \
+                               _m + 8, _p + 2, _s, 0, 16),     \
+               .mdiv   =       (_m),                           \
+               .pdiv   =       (_p),                           \
+               .sdiv   =       (_s),                           \
+       }
+
+#define PLL_S3C2440_MPLL_RATE(_fin, _rate, _m, _p, _s)         \
        {                                                       \
-               .rate   =       (_rate),                                \
+               .rate   =       PLL_VALID_RATE(_fin, _rate,     \
+                               2 * (_m + 8), _p + 2, _s, 0, 16), \
                .mdiv   =       (_m),                           \
                .pdiv   =       (_p),                           \
                .sdiv   =       (_s),                           \
        }
 
-#define PLL_36XX_RATE(_rate, _m, _p, _s, _k)                   \
+#define PLL_36XX_RATE(_fin, _rate, _m, _p, _s, _k)             \
        {                                                       \
-               .rate   =       (_rate),                                \
+               .rate   =       PLL_VALID_RATE(_fin, _rate,     \
+                               _m, _p, _s, _k, 16),            \
                .mdiv   =       (_m),                           \
                .pdiv   =       (_p),                           \
                .sdiv   =       (_s),                           \
                .kdiv   =       (_k),                           \
        }
 
-#define PLL_45XX_RATE(_rate, _m, _p, _s, _afc)                 \
+#define PLL_4508_RATE(_fin, _rate, _m, _p, _s, _afc)           \
        {                                                       \
-               .rate   =       (_rate),                        \
+               .rate   =       PLL_VALID_RATE(_fin, _rate,     \
+                               _m, _p, _s - 1, 0, 16),         \
                .mdiv   =       (_m),                           \
                .pdiv   =       (_p),                           \
                .sdiv   =       (_s),                           \
                .afc    =       (_afc),                         \
        }
 
-#define PLL_4600_RATE(_rate, _m, _p, _s, _k, _vsel)            \
+#define PLL_4600_RATE(_fin, _rate, _m, _p, _s, _k, _vsel)      \
        {                                                       \
-               .rate   =       (_rate),                        \
+               .rate   =       PLL_VALID_RATE(_fin, _rate,     \
+                               _m, _p, _s, _k, 16),            \
                .mdiv   =       (_m),                           \
                .pdiv   =       (_p),                           \
                .sdiv   =       (_s),                           \
@@ -77,9 +104,10 @@ enum samsung_pll_type {
                .vsel   =       (_vsel),                        \
        }
 
-#define PLL_4650_RATE(_rate, _m, _p, _s, _k, _mfr, _mrr, _vsel)        \
+#define PLL_4650_RATE(_fin, _rate, _m, _p, _s, _k, _mfr, _mrr, _vsel) \
        {                                                       \
-               .rate   =       (_rate),                        \
+               .rate   =       PLL_VALID_RATE(_fin, _rate,     \
+                               _m, _p, _s, _k, 10),            \
                .mdiv   =       (_m),                           \
                .pdiv   =       (_p),                           \
                .sdiv   =       (_s),                           \
index e0650c33863bbc221f981374a26f2503c2c6dc1f..a9c88747505428cf30a71316da0e313b7bd415a3 100644 (file)
@@ -95,7 +95,7 @@ static void __init s3c2410_clk_sleep_init(void) {}
 
 PNAME(fclk_p) = { "mpll", "div_slow" };
 
-struct samsung_mux_clock s3c2410_common_muxes[] __initdata = {
+static struct samsung_mux_clock s3c2410_common_muxes[] __initdata = {
        MUX(FCLK, "fclk", fclk_p, CLKSLOW, 4, 1),
 };
 
@@ -111,12 +111,12 @@ static struct clk_div_table divslow_d[] = {
        { /* sentinel */ },
 };
 
-struct samsung_div_clock s3c2410_common_dividers[] __initdata = {
+static struct samsung_div_clock s3c2410_common_dividers[] __initdata = {
        DIV_T(0, "div_slow", "xti", CLKSLOW, 0, 3, divslow_d),
        DIV(PCLK, "pclk", "hclk", CLKDIVN, 0, 1),
 };
 
-struct samsung_gate_clock s3c2410_common_gates[] __initdata = {
+static struct samsung_gate_clock s3c2410_common_gates[] __initdata = {
        GATE(PCLK_SPI, "spi", "pclk", CLKCON, 18, 0, 0),
        GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 17, 0, 0),
        GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 16, 0, 0),
@@ -135,7 +135,7 @@ struct samsung_gate_clock s3c2410_common_gates[] __initdata = {
 };
 
 /* should be added _after_ the soc-specific clocks are created */
-struct samsung_clock_alias s3c2410_common_aliases[] __initdata = {
+static struct samsung_clock_alias s3c2410_common_aliases[] __initdata = {
        ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"),
        ALIAS(PCLK_ADC, NULL, "adc"),
        ALIAS(PCLK_RTC, NULL, "rtc"),
@@ -162,34 +162,34 @@ struct samsung_clock_alias s3c2410_common_aliases[] __initdata = {
 static struct samsung_pll_rate_table pll_s3c2410_12mhz_tbl[] __initdata = {
        /* sorted in descending order */
        /* 2410A extras */
-       PLL_35XX_RATE(270000000, 127, 1, 1),
-       PLL_35XX_RATE(268000000, 126, 1, 1),
-       PLL_35XX_RATE(266000000, 125, 1, 1),
-       PLL_35XX_RATE(226000000, 105, 1, 1),
-       PLL_35XX_RATE(210000000, 132, 2, 1),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 270000000, 127, 1, 1),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 268000000, 126, 1, 1),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 266000000, 125, 1, 1),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 226000000, 105, 1, 1),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 210000000, 132, 2, 1),
        /* 2410 common */
-       PLL_35XX_RATE(203000000, 161, 3, 1),
-       PLL_35XX_RATE(192000000, 88, 1, 1),
-       PLL_35XX_RATE(186000000, 85, 1, 1),
-       PLL_35XX_RATE(180000000, 82, 1, 1),
-       PLL_35XX_RATE(170000000, 77, 1, 1),
-       PLL_35XX_RATE(158000000, 71, 1, 1),
-       PLL_35XX_RATE(152000000, 68, 1, 1),
-       PLL_35XX_RATE(147000000, 90, 2, 1),
-       PLL_35XX_RATE(135000000, 82, 2, 1),
-       PLL_35XX_RATE(124000000, 116, 1, 2),
-       PLL_35XX_RATE(118000000, 150, 2, 2),
-       PLL_35XX_RATE(113000000, 105, 1, 2),
-       PLL_35XX_RATE(101000000, 127, 2, 2),
-       PLL_35XX_RATE(90000000, 112, 2, 2),
-       PLL_35XX_RATE(85000000, 105, 2, 2),
-       PLL_35XX_RATE(79000000, 71, 1, 2),
-       PLL_35XX_RATE(68000000, 82, 2, 2),
-       PLL_35XX_RATE(56000000, 142, 2, 3),
-       PLL_35XX_RATE(48000000, 120, 2, 3),
-       PLL_35XX_RATE(51000000, 161, 3, 3),
-       PLL_35XX_RATE(45000000, 82, 1, 3),
-       PLL_35XX_RATE(34000000, 82, 2, 3),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 202800000, 161, 3, 1),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 192000000, 88, 1, 1),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 186000000, 85, 1, 1),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 180000000, 82, 1, 1),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 170000000, 77, 1, 1),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 158000000, 71, 1, 1),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 152000000, 68, 1, 1),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 147000000, 90, 2, 1),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 135000000, 82, 2, 1),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 124000000, 116, 1, 2),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 118500000, 150, 2, 2),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 113000000, 105, 1, 2),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 101250000, 127, 2, 2),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 90000000, 112, 2, 2),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 84750000, 105, 2, 2),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 79000000, 71, 1, 2),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 67500000, 82, 2, 2),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 56250000, 142, 2, 3),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 48000000, 120, 2, 3),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 50700000, 161, 3, 3),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 45000000, 82, 1, 3),
+       PLL_S3C2410_MPLL_RATE(12 * MHZ, 33750000, 82, 2, 3),
        { /* sentinel */ },
 };
 
@@ -200,11 +200,11 @@ static struct samsung_pll_clock s3c2410_plls[] __initdata = {
                                                LOCKTIME, UPLLCON, NULL),
 };
 
-struct samsung_div_clock s3c2410_dividers[] __initdata = {
+static struct samsung_div_clock s3c2410_dividers[] __initdata = {
        DIV(HCLK, "hclk", "mpll", CLKDIVN, 1, 1),
 };
 
-struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = {
+static struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = {
        /*
         * armclk is directly supplied by the fclk, without
         * switching possibility like on the s3c244x below.
@@ -215,7 +215,7 @@ struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = {
        FFACTOR(UCLK, "uclk", "upll", 1, 1, 0),
 };
 
-struct samsung_clock_alias s3c2410_aliases[] __initdata = {
+static struct samsung_clock_alias s3c2410_aliases[] __initdata = {
        ALIAS(PCLK_UART0, "s3c2410-uart.0", "uart"),
        ALIAS(PCLK_UART1, "s3c2410-uart.1", "uart"),
        ALIAS(PCLK_UART2, "s3c2410-uart.2", "uart"),
@@ -229,33 +229,33 @@ struct samsung_clock_alias s3c2410_aliases[] __initdata = {
 
 static struct samsung_pll_rate_table pll_s3c244x_12mhz_tbl[] __initdata = {
        /* sorted in descending order */
-       PLL_35XX_RATE(400000000, 0x5c, 1, 1),
-       PLL_35XX_RATE(390000000, 0x7a, 2, 1),
-       PLL_35XX_RATE(380000000, 0x57, 1, 1),
-       PLL_35XX_RATE(370000000, 0xb1, 4, 1),
-       PLL_35XX_RATE(360000000, 0x70, 2, 1),
-       PLL_35XX_RATE(350000000, 0xa7, 4, 1),
-       PLL_35XX_RATE(340000000, 0x4d, 1, 1),
-       PLL_35XX_RATE(330000000, 0x66, 2, 1),
-       PLL_35XX_RATE(320000000, 0x98, 4, 1),
-       PLL_35XX_RATE(310000000, 0x93, 4, 1),
-       PLL_35XX_RATE(300000000, 0x75, 3, 1),
-       PLL_35XX_RATE(240000000, 0x70, 1, 2),
-       PLL_35XX_RATE(230000000, 0x6b, 1, 2),
-       PLL_35XX_RATE(220000000, 0x66, 1, 2),
-       PLL_35XX_RATE(210000000, 0x84, 2, 2),
-       PLL_35XX_RATE(200000000, 0x5c, 1, 2),
-       PLL_35XX_RATE(190000000, 0x57, 1, 2),
-       PLL_35XX_RATE(180000000, 0x70, 2, 2),
-       PLL_35XX_RATE(170000000, 0x4d, 1, 2),
-       PLL_35XX_RATE(160000000, 0x98, 4, 2),
-       PLL_35XX_RATE(150000000, 0x75, 3, 2),
-       PLL_35XX_RATE(120000000, 0x70, 1, 3),
-       PLL_35XX_RATE(110000000, 0x66, 1, 3),
-       PLL_35XX_RATE(100000000, 0x5c, 1, 3),
-       PLL_35XX_RATE(90000000, 0x70, 2, 3),
-       PLL_35XX_RATE(80000000, 0x98, 4, 3),
-       PLL_35XX_RATE(75000000, 0x75, 3, 3),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 400000000, 0x5c, 1, 1),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 390000000, 0x7a, 2, 1),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 380000000, 0x57, 1, 1),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 370000000, 0xb1, 4, 1),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 360000000, 0x70, 2, 1),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 350000000, 0xa7, 4, 1),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 340000000, 0x4d, 1, 1),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 330000000, 0x66, 2, 1),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 320000000, 0x98, 4, 1),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 310000000, 0x93, 4, 1),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 300000000, 0x75, 3, 1),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 240000000, 0x70, 1, 2),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 230000000, 0x6b, 1, 2),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 220000000, 0x66, 1, 2),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 210000000, 0x84, 2, 2),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 200000000, 0x5c, 1, 2),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 190000000, 0x57, 1, 2),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 180000000, 0x70, 2, 2),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 170000000, 0x4d, 1, 2),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 160000000, 0x98, 4, 2),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 150000000, 0x75, 3, 2),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 120000000, 0x70, 1, 3),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 110000000, 0x66, 1, 3),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 100000000, 0x5c, 1, 3),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 90000000, 0x70, 2, 3),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 80000000, 0x98, 4, 3),
+       PLL_S3C2440_MPLL_RATE(12 * MHZ, 75000000, 0x75, 3, 3),
        { /* sentinel */ },
 };
 
@@ -269,12 +269,12 @@ static struct samsung_pll_clock s3c244x_common_plls[] __initdata = {
 PNAME(hclk_p) = { "fclk", "div_hclk_2", "div_hclk_4", "div_hclk_3" };
 PNAME(armclk_p) = { "fclk", "hclk" };
 
-struct samsung_mux_clock s3c244x_common_muxes[] __initdata = {
+static struct samsung_mux_clock s3c244x_common_muxes[] __initdata = {
        MUX(HCLK, "hclk", hclk_p, CLKDIVN, 1, 2),
        MUX(ARMCLK, "armclk", armclk_p, CAMDIVN, 12, 1),
 };
 
-struct samsung_fixed_factor_clock s3c244x_common_ffactor[] __initdata = {
+static struct samsung_fixed_factor_clock s3c244x_common_ffactor[] __initdata = {
        FFACTOR(0, "div_hclk_2", "fclk", 1, 2, 0),
        FFACTOR(0, "ff_cam", "div_cam", 2, 1, CLK_SET_RATE_PARENT),
 };
@@ -291,7 +291,7 @@ static struct clk_div_table div_hclk_3_d[] = {
        { /* sentinel */ },
 };
 
-struct samsung_div_clock s3c244x_common_dividers[] __initdata = {
+static struct samsung_div_clock s3c244x_common_dividers[] __initdata = {
        DIV(UCLK, "uclk", "upll", CLKDIVN, 3, 1),
        DIV(0, "div_hclk", "fclk", CLKDIVN, 1, 1),
        DIV_T(0, "div_hclk_4", "fclk", CAMDIVN, 9, 1, div_hclk_4_d),
@@ -299,11 +299,11 @@ struct samsung_div_clock s3c244x_common_dividers[] __initdata = {
        DIV(0, "div_cam", "upll", CAMDIVN, 0, 3),
 };
 
-struct samsung_gate_clock s3c244x_common_gates[] __initdata = {
+static struct samsung_gate_clock s3c244x_common_gates[] __initdata = {
        GATE(HCLK_CAM, "cam", "hclk", CLKCON, 19, 0, 0),
 };
 
-struct samsung_clock_alias s3c244x_common_aliases[] __initdata = {
+static struct samsung_clock_alias s3c244x_common_aliases[] __initdata = {
        ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"),
        ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"),
        ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"),
@@ -318,23 +318,23 @@ struct samsung_clock_alias s3c244x_common_aliases[] __initdata = {
 
 PNAME(s3c2440_camif_p) = { "upll", "ff_cam" };
 
-struct samsung_mux_clock s3c2440_muxes[] __initdata = {
+static struct samsung_mux_clock s3c2440_muxes[] __initdata = {
        MUX(CAMIF, "camif", s3c2440_camif_p, CAMDIVN, 4, 1),
 };
 
-struct samsung_gate_clock s3c2440_gates[] __initdata = {
+static struct samsung_gate_clock s3c2440_gates[] __initdata = {
        GATE(PCLK_AC97, "ac97", "pclk", CLKCON, 20, 0, 0),
 };
 
 /* S3C2442 specific clocks */
 
-struct samsung_fixed_factor_clock s3c2442_ffactor[] __initdata = {
+static struct samsung_fixed_factor_clock s3c2442_ffactor[] __initdata = {
        FFACTOR(0, "upll_3", "upll", 1, 3, 0),
 };
 
 PNAME(s3c2442_camif_p) = { "upll", "ff_cam", "upll", "upll_3" };
 
-struct samsung_mux_clock s3c2442_muxes[] __initdata = {
+static struct samsung_mux_clock s3c2442_muxes[] __initdata = {
        MUX(CAMIF, "camif", s3c2442_camif_p, CAMDIVN, 4, 2),
 };
 
@@ -343,7 +343,7 @@ struct samsung_mux_clock s3c2442_muxes[] __initdata = {
  * Only necessary until the devicetree-move is complete
  */
 #define XTI    1
-struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = {
        FRATE(XTI, "xti", NULL, 0, 0),
 };
 
@@ -468,18 +468,18 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
 
 static void __init s3c2410_clk_init(struct device_node *np)
 {
-       s3c2410_common_clk_init(np, 0, S3C2410, 0);
+       s3c2410_common_clk_init(np, 0, S3C2410, NULL);
 }
 CLK_OF_DECLARE(s3c2410_clk, "samsung,s3c2410-clock", s3c2410_clk_init);
 
 static void __init s3c2440_clk_init(struct device_node *np)
 {
-       s3c2410_common_clk_init(np, 0, S3C2440, 0);
+       s3c2410_common_clk_init(np, 0, S3C2440, NULL);
 }
 CLK_OF_DECLARE(s3c2440_clk, "samsung,s3c2440-clock", s3c2440_clk_init);
 
 static void __init s3c2442_clk_init(struct device_node *np)
 {
-       s3c2410_common_clk_init(np, 0, S3C2442, 0);
+       s3c2410_common_clk_init(np, 0, S3C2442, NULL);
 }
 CLK_OF_DECLARE(s3c2442_clk, "samsung,s3c2442-clock", s3c2442_clk_init);
index b8340a49921b71c4423b2805a326332046ffe7e3..6bc94d3aff78f58eef7469f41a4af54ab08aa41f 100644 (file)
 #define CLKSRC         0x1c
 #define SWRST          0x30
 
-/* list of PLLs to be registered */
-enum s3c2412_plls {
-       mpll, upll,
-};
-
 static void __iomem *reg_base;
 
 #ifdef CONFIG_PM_SLEEP
@@ -98,7 +93,7 @@ static struct clk_div_table divxti_d[] = {
        { /* sentinel */ },
 };
 
-struct samsung_div_clock s3c2412_dividers[] __initdata = {
+static struct samsung_div_clock s3c2412_dividers[] __initdata = {
        DIV_T(0, "div_xti", "xti", CLKSRC, 0, 3, divxti_d),
        DIV(0, "div_cam", "mux_cam", CLKDIVN, 16, 4),
        DIV(0, "div_i2s", "mux_i2s", CLKDIVN, 12, 4),
@@ -110,7 +105,7 @@ struct samsung_div_clock s3c2412_dividers[] __initdata = {
        DIV(HCLK, "hclk", "armdiv", CLKDIVN, 0, 2),
 };
 
-struct samsung_fixed_factor_clock s3c2412_ffactor[] __initdata = {
+static struct samsung_fixed_factor_clock s3c2412_ffactor[] __initdata = {
        FFACTOR(0, "ff_hclk", "hclk", 2, 1, CLK_SET_RATE_PARENT),
 };
 
@@ -130,7 +125,7 @@ PNAME(msysclk_p) = { "mdivclk", "mpll" };
 PNAME(mdivclk_p) = { "xti", "div_xti" };
 PNAME(armclk_p) = { "armdiv", "hclk" };
 
-struct samsung_mux_clock s3c2412_muxes[] __initdata = {
+static struct samsung_mux_clock s3c2412_muxes[] __initdata = {
        MUX(0, "erefclk", erefclk_p, CLKSRC, 14, 2),
        MUX(0, "urefclk", urefclk_p, CLKSRC, 12, 2),
        MUX(0, "mux_cam", camclk_p, CLKSRC, 11, 1),
@@ -144,13 +139,11 @@ struct samsung_mux_clock s3c2412_muxes[] __initdata = {
 };
 
 static struct samsung_pll_clock s3c2412_plls[] __initdata = {
-       [mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti",
-                                               LOCKTIME, MPLLCON, NULL),
-       [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "urefclk",
-                                               LOCKTIME, UPLLCON, NULL),
+       PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti", LOCKTIME, MPLLCON, NULL),
+       PLL(pll_s3c2410_upll, UPLL, "upll", "urefclk", LOCKTIME, UPLLCON, NULL),
 };
 
-struct samsung_gate_clock s3c2412_gates[] __initdata = {
+static struct samsung_gate_clock s3c2412_gates[] __initdata = {
        GATE(PCLK_WDT, "wdt", "pclk", CLKCON, 28, 0, 0),
        GATE(PCLK_SPI, "spi", "pclk", CLKCON, 27, 0, 0),
        GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 26, 0, 0),
@@ -181,7 +174,7 @@ struct samsung_gate_clock s3c2412_gates[] __initdata = {
        GATE(HCLK_DMA0, "dma0", "hclk", CLKCON, 0, CLK_IGNORE_UNUSED, 0),
 };
 
-struct samsung_clock_alias s3c2412_aliases[] __initdata = {
+static struct samsung_clock_alias s3c2412_aliases[] __initdata = {
        ALIAS(PCLK_UART0, "s3c2412-uart.0", "uart"),
        ALIAS(PCLK_UART1, "s3c2412-uart.1", "uart"),
        ALIAS(PCLK_UART2, "s3c2412-uart.2", "uart"),
@@ -231,7 +224,7 @@ static struct notifier_block s3c2412_restart_handler = {
  * Only necessary until the devicetree-move is complete
  */
 #define XTI    1
-struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = {
        FRATE(XTI, "xti", NULL, 0, 0),
        FRATE(0, "ext", NULL, 0, 0),
 };
@@ -296,6 +289,6 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
 
 static void __init s3c2412_clk_init(struct device_node *np)
 {
-       s3c2412_common_clk_init(np, 0, 0, 0);
+       s3c2412_common_clk_init(np, 0, 0, NULL);
 }
 CLK_OF_DECLARE(s3c2412_clk, "samsung,s3c2412-clock", s3c2412_clk_init);
index d94b85a4235604bfd8212d80925382acd7a9d9b3..c46e6d5bc9bccbe6472a2c13b7ff52e01cc0e948 100644 (file)
@@ -41,11 +41,6 @@ enum supported_socs {
        S3C2450,
 };
 
-/* list of PLLs to be registered */
-enum s3c2443_plls {
-       mpll, epll,
-};
-
 static void __iomem *reg_base;
 
 #ifdef CONFIG_PM_SLEEP
@@ -113,7 +108,7 @@ PNAME(msysclk_p) = { "mpllref", "mpll" };
 PNAME(armclk_p) = { "armdiv" , "hclk" };
 PNAME(i2s0_p) = { "div_i2s0", "ext_i2s", "epllref", "epllref" };
 
-struct samsung_mux_clock s3c2443_common_muxes[] __initdata = {
+static struct samsung_mux_clock s3c2443_common_muxes[] __initdata = {
        MUX(0, "epllref", epllref_p, CLKSRC, 7, 2),
        MUX(ESYSCLK, "esysclk", esysclk_p, CLKSRC, 6, 1),
        MUX(0, "mpllref", mpllref_p, CLKSRC, 3, 1),
@@ -141,7 +136,7 @@ static struct clk_div_table mdivclk_d[] = {
        { /* sentinel */ },
 };
 
-struct samsung_div_clock s3c2443_common_dividers[] __initdata = {
+static struct samsung_div_clock s3c2443_common_dividers[] __initdata = {
        DIV_T(0, "mdivclk", "xti", CLKDIV0, 6, 3, mdivclk_d),
        DIV(0, "prediv", "msysclk", CLKDIV0, 4, 2),
        DIV_T(HCLK, "hclk", "prediv", CLKDIV0, 0, 2, hclk_d),
@@ -154,7 +149,7 @@ struct samsung_div_clock s3c2443_common_dividers[] __initdata = {
        DIV(0, "div_usbhost", "esysclk", CLKDIV1, 4, 2),
 };
 
-struct samsung_gate_clock s3c2443_common_gates[] __initdata = {
+static struct samsung_gate_clock s3c2443_common_gates[] __initdata = {
        GATE(SCLK_HSMMC_EXT, "sclk_hsmmcext", "ext", SCLKCON, 13, 0, 0),
        GATE(SCLK_HSMMC1, "sclk_hsmmc1", "div_hsmmc1", SCLKCON, 12, 0, 0),
        GATE(SCLK_FIMD, "sclk_fimd", "div_fimd", SCLKCON, 10, 0, 0),
@@ -188,7 +183,7 @@ struct samsung_gate_clock s3c2443_common_gates[] __initdata = {
        GATE(PCLK_UART0, "uart0", "pclk", PCLKCON, 0, 0, 0),
 };
 
-struct samsung_clock_alias s3c2443_common_aliases[] __initdata = {
+static struct samsung_clock_alias s3c2443_common_aliases[] __initdata = {
        ALIAS(MSYSCLK, NULL, "msysclk"),
        ALIAS(ARMCLK, NULL, "armclk"),
        ALIAS(MPLL, NULL, "mpll"),
@@ -225,10 +220,8 @@ struct samsung_clock_alias s3c2443_common_aliases[] __initdata = {
 /* S3C2416 specific clocks */
 
 static struct samsung_pll_clock s3c2416_pll_clks[] __initdata = {
-       [mpll] = PLL(pll_6552_s3c2416, MPLL, "mpll", "mpllref",
-                                               LOCKCON0, MPLLCON, NULL),
-       [epll] = PLL(pll_6553, EPLL, "epll", "epllref",
-                                               LOCKCON1, EPLLCON, NULL),
+       PLL(pll_6552_s3c2416, MPLL, "mpll", "mpllref", LOCKCON0, MPLLCON, NULL),
+       PLL(pll_6553, EPLL, "epll", "epllref", LOCKCON1, EPLLCON, NULL),
 };
 
 PNAME(s3c2416_hsmmc0_p) = { "sclk_hsmmc0", "sclk_hsmmcext" };
@@ -245,19 +238,19 @@ static struct clk_div_table armdiv_s3c2416_d[] = {
        { /* sentinel */ },
 };
 
-struct samsung_div_clock s3c2416_dividers[] __initdata = {
+static struct samsung_div_clock s3c2416_dividers[] __initdata = {
        DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 3, armdiv_s3c2416_d),
        DIV(0, "div_hsspi0_mpll", "msysclk", CLKDIV2, 0, 4),
        DIV(0, "div_hsmmc0", "esysclk", CLKDIV2, 6, 2),
 };
 
-struct samsung_mux_clock s3c2416_muxes[] __initdata = {
+static struct samsung_mux_clock s3c2416_muxes[] __initdata = {
        MUX(MUX_HSMMC0, "mux_hsmmc0", s3c2416_hsmmc0_p, CLKSRC, 16, 1),
        MUX(MUX_HSMMC1, "mux_hsmmc1", s3c2416_hsmmc1_p, CLKSRC, 17, 1),
        MUX(MUX_HSSPI0, "mux_hsspi0", s3c2416_hsspi0_p, CLKSRC, 18, 1),
 };
 
-struct samsung_gate_clock s3c2416_gates[] __initdata = {
+static struct samsung_gate_clock s3c2416_gates[] __initdata = {
        GATE(0, "hsspi0_mpll", "div_hsspi0_mpll", SCLKCON, 19, 0, 0),
        GATE(0, "hsspi0_epll", "div_hsspi0_epll", SCLKCON, 14, 0, 0),
        GATE(0, "sclk_hsmmc0", "div_hsmmc0", SCLKCON, 6, 0, 0),
@@ -267,7 +260,7 @@ struct samsung_gate_clock s3c2416_gates[] __initdata = {
        GATE(PCLK_PCM, "pcm", "pclk", PCLKCON, 19, 0, 0),
 };
 
-struct samsung_clock_alias s3c2416_aliases[] __initdata = {
+static struct samsung_clock_alias s3c2416_aliases[] __initdata = {
        ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
        ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
        ALIAS(MUX_HSMMC0, "s3c-sdhci.0", "mmc_busclk.2"),
@@ -279,10 +272,8 @@ struct samsung_clock_alias s3c2416_aliases[] __initdata = {
 /* S3C2443 specific clocks */
 
 static struct samsung_pll_clock s3c2443_pll_clks[] __initdata = {
-       [mpll] = PLL(pll_3000, MPLL, "mpll", "mpllref",
-                                               LOCKCON0, MPLLCON, NULL),
-       [epll] = PLL(pll_2126, EPLL, "epll", "epllref",
-                                               LOCKCON1, EPLLCON, NULL),
+       PLL(pll_3000, MPLL, "mpll", "mpllref", LOCKCON0, MPLLCON, NULL),
+       PLL(pll_2126, EPLL, "epll", "epllref", LOCKCON1, EPLLCON, NULL),
 };
 
 static struct clk_div_table armdiv_s3c2443_d[] = {
@@ -297,12 +288,12 @@ static struct clk_div_table armdiv_s3c2443_d[] = {
        { /* sentinel */ },
 };
 
-struct samsung_div_clock s3c2443_dividers[] __initdata = {
+static struct samsung_div_clock s3c2443_dividers[] __initdata = {
        DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 4, armdiv_s3c2443_d),
        DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4),
 };
 
-struct samsung_gate_clock s3c2443_gates[] __initdata = {
+static struct samsung_gate_clock s3c2443_gates[] __initdata = {
        GATE(SCLK_HSSPI0, "sclk_hsspi0", "div_hsspi0_epll", SCLKCON, 14, 0, 0),
        GATE(SCLK_CAM, "sclk_cam", "div_cam", SCLKCON, 11, 0, 0),
        GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, CLK_IGNORE_UNUSED, 0),
@@ -311,7 +302,7 @@ struct samsung_gate_clock s3c2443_gates[] __initdata = {
        GATE(PCLK_SDI, "sdi", "pclk", PCLKCON, 5, 0, 0),
 };
 
-struct samsung_clock_alias s3c2443_aliases[] __initdata = {
+static struct samsung_clock_alias s3c2443_aliases[] __initdata = {
        ALIAS(SCLK_HSSPI0, "s3c2443-spi.0", "spi_busclk2"),
        ALIAS(SCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"),
        ALIAS(SCLK_CAM, NULL, "camif-upll"),
@@ -327,20 +318,20 @@ PNAME(s3c2450_cam_p) = { "div_cam", "hclk" };
 PNAME(s3c2450_hsspi1_p) = { "hsspi1_epll", "hsspi1_mpll" };
 PNAME(i2s1_p) = { "div_i2s1", "ext_i2s", "epllref", "epllref" };
 
-struct samsung_div_clock s3c2450_dividers[] __initdata = {
+static struct samsung_div_clock s3c2450_dividers[] __initdata = {
        DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4),
        DIV(0, "div_hsspi1_epll", "esysclk", CLKDIV2, 24, 2),
        DIV(0, "div_hsspi1_mpll", "msysclk", CLKDIV2, 16, 4),
        DIV(0, "div_i2s1", "esysclk", CLKDIV2, 12, 4),
 };
 
-struct samsung_mux_clock s3c2450_muxes[] __initdata = {
+static struct samsung_mux_clock s3c2450_muxes[] __initdata = {
        MUX(0, "mux_cam", s3c2450_cam_p, CLKSRC, 20, 1),
        MUX(MUX_HSSPI1, "mux_hsspi1", s3c2450_hsspi1_p, CLKSRC, 19, 1),
        MUX(0, "mux_i2s1", i2s1_p, CLKSRC, 12, 2),
 };
 
-struct samsung_gate_clock s3c2450_gates[] __initdata = {
+static struct samsung_gate_clock s3c2450_gates[] __initdata = {
        GATE(SCLK_I2S1, "sclk_i2s1", "div_i2s1", SCLKCON, 5, 0, 0),
        GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, 0, 0),
        GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0),
@@ -351,7 +342,7 @@ struct samsung_gate_clock s3c2450_gates[] __initdata = {
        GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 14, 0, 0),
 };
 
-struct samsung_clock_alias s3c2450_aliases[] __initdata = {
+static struct samsung_clock_alias s3c2450_aliases[] __initdata = {
        ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi"),
        ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi_busclk0"),
        ALIAS(MUX_HSSPI1, "s3c2443-spi.1", "spi_busclk2"),
@@ -374,7 +365,7 @@ static struct notifier_block s3c2443_restart_handler = {
  * fixed rate clocks generated outside the soc
  * Only necessary until the devicetree-move is complete
  */
-struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = {
        FRATE(0, "xti", NULL, 0, 0),
        FRATE(0, "ext", NULL, 0, 0),
        FRATE(0, "ext_i2s", NULL, 0, 0),
@@ -470,18 +461,18 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
 
 static void __init s3c2416_clk_init(struct device_node *np)
 {
-       s3c2443_common_clk_init(np, 0, S3C2416, 0);
+       s3c2443_common_clk_init(np, 0, S3C2416, NULL);
 }
 CLK_OF_DECLARE(s3c2416_clk, "samsung,s3c2416-clock", s3c2416_clk_init);
 
 static void __init s3c2443_clk_init(struct device_node *np)
 {
-       s3c2443_common_clk_init(np, 0, S3C2443, 0);
+       s3c2443_common_clk_init(np, 0, S3C2443, NULL);
 }
 CLK_OF_DECLARE(s3c2443_clk, "samsung,s3c2443-clock", s3c2443_clk_init);
 
 static void __init s3c2450_clk_init(struct device_node *np)
 {
-       s3c2443_common_clk_init(np, 0, S3C2450, 0);
+       s3c2443_common_clk_init(np, 0, S3C2450, NULL);
 }
 CLK_OF_DECLARE(s3c2450_clk, "samsung,s3c2450-clock", s3c2450_clk_init);
index 7306867a0ab80c21228a47626468f5bbde68a1f3..6db01cf5ab8364901905c68e584b6418c7cff509 100644 (file)
 #define GATE_ON(_id, cname, pname, o, b) \
                GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED, 0)
 
-/* list of PLLs to be registered */
-enum s3c64xx_plls {
-       apll, mpll, epll,
-};
-
 static void __iomem *reg_base;
 static bool is_s3c6400;
 
@@ -364,12 +359,12 @@ GATE_CLOCKS(s3c6410_gate_clks) __initdata = {
 
 /* List of PLL clocks. */
 static struct samsung_pll_clock s3c64xx_pll_clks[] __initdata = {
-       [apll] = PLL(pll_6552, FOUT_APLL, "fout_apll", "fin_pll",
-                                               APLL_LOCK, APLL_CON, NULL),
-       [mpll] = PLL(pll_6552, FOUT_MPLL, "fout_mpll", "fin_pll",
-                                               MPLL_LOCK, MPLL_CON, NULL),
-       [epll] = PLL(pll_6553, FOUT_EPLL, "fout_epll", "fin_pll",
-                                               EPLL_LOCK, EPLL_CON0, NULL),
+       PLL(pll_6552, FOUT_APLL, "fout_apll", "fin_pll",
+                                       APLL_LOCK, APLL_CON, NULL),
+       PLL(pll_6552, FOUT_MPLL, "fout_mpll", "fin_pll",
+                                       MPLL_LOCK, MPLL_CON, NULL),
+       PLL(pll_6553, FOUT_EPLL, "fout_epll", "fin_pll",
+                                       EPLL_LOCK, EPLL_CON0, NULL),
 };
 
 /* Aliases for common s3c64xx clocks. */
index 9146c20fe21f41936ffd91ee387c712e5702e93e..ce5aa7802eb8a6a7ccc56edc61d1101fd04bc0be 100644 (file)
@@ -1,6 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-y += clk.o
-obj-y += clk-gate.o
-obj-y += clk-pll.o
-obj-y += clk-periph.o
-obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
+obj-$(CONFIG_ARCH_SOCFPGA) += clk.o clk-gate.o clk-pll.o clk-periph.o
+obj-$(CONFIG_ARCH_SOCFPGA) += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
+obj-$(CONFIG_ARCH_STRATIX10) += clk-s10.o
+obj-$(CONFIG_ARCH_STRATIX10) += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c
new file mode 100644 (file)
index 0000000..eee2d48
--- /dev/null
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier:    GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include "stratix10-clk.h"
+#include "clk.h"
+
+#define SOCFPGA_CS_PDBG_CLK    "cs_pdbg_clk"
+#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
+
+static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
+                                                 unsigned long parent_rate)
+{
+       struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+       u32 div = 1, val;
+
+       if (socfpgaclk->fixed_div) {
+               div = socfpgaclk->fixed_div;
+       } else if (socfpgaclk->div_reg) {
+               val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+               val &= GENMASK(socfpgaclk->width - 1, 0);
+               div = (1 << val);
+       }
+       return parent_rate / div;
+}
+
+static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
+                                                 unsigned long parent_rate)
+{
+       struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+       u32 div = 1, val;
+
+       val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+       val &= GENMASK(socfpgaclk->width - 1, 0);
+       div = (1 << val);
+       div = div ? 4 : 1;
+
+       return parent_rate / div;
+}
+
+static u8 socfpga_gate_get_parent(struct clk_hw *hwclk)
+{
+       struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+       u32 mask;
+       u8 parent = 0;
+
+       if (socfpgaclk->bypass_reg) {
+               mask = (0x1 << socfpgaclk->bypass_shift);
+               parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
+                         socfpgaclk->bypass_shift);
+       }
+       return parent;
+}
+
+static struct clk_ops gateclk_ops = {
+       .recalc_rate = socfpga_gate_clk_recalc_rate,
+       .get_parent = socfpga_gate_get_parent,
+};
+
+static const struct clk_ops dbgclk_ops = {
+       .recalc_rate = socfpga_dbg_clk_recalc_rate,
+       .get_parent = socfpga_gate_get_parent,
+};
+
+struct clk *s10_register_gate(const char *name, const char *parent_name,
+                             const char * const *parent_names,
+                             u8 num_parents, unsigned long flags,
+                             void __iomem *regbase, unsigned long gate_reg,
+                             unsigned long gate_idx, unsigned long div_reg,
+                             unsigned long div_offset, u8 div_width,
+                             unsigned long bypass_reg, u8 bypass_shift,
+                             u8 fixed_div)
+{
+       struct clk *clk;
+       struct socfpga_gate_clk *socfpga_clk;
+       struct clk_init_data init;
+
+       socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
+       if (!socfpga_clk)
+               return NULL;
+
+       socfpga_clk->hw.reg = regbase + gate_reg;
+       socfpga_clk->hw.bit_idx = gate_idx;
+
+       gateclk_ops.enable = clk_gate_ops.enable;
+       gateclk_ops.disable = clk_gate_ops.disable;
+
+       socfpga_clk->fixed_div = fixed_div;
+
+       if (div_reg)
+               socfpga_clk->div_reg = regbase + div_reg;
+       else
+               socfpga_clk->div_reg = NULL;
+
+       socfpga_clk->width = div_width;
+       socfpga_clk->shift = div_offset;
+
+       if (bypass_reg)
+               socfpga_clk->bypass_reg = regbase + bypass_reg;
+       else
+               socfpga_clk->bypass_reg = NULL;
+       socfpga_clk->bypass_shift = bypass_shift;
+
+       if (streq(name, "cs_pdbg_clk"))
+               init.ops = &dbgclk_ops;
+       else
+               init.ops = &gateclk_ops;
+
+       init.name = name;
+       init.flags = flags;
+
+       init.num_parents = num_parents;
+       init.parent_names = parent_names ? parent_names : &parent_name;
+       socfpga_clk->hw.hw.init = &init;
+
+       clk = clk_register(NULL, &socfpga_clk->hw.hw);
+       if (WARN_ON(IS_ERR(clk))) {
+               kfree(socfpga_clk);
+               return NULL;
+       }
+
+       return clk;
+}
diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c
new file mode 100644 (file)
index 0000000..568f59b
--- /dev/null
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier:    GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+
+#include "stratix10-clk.h"
+#include "clk.h"
+
+#define CLK_MGR_FREE_SHIFT             16
+#define CLK_MGR_FREE_MASK              0x7
+#define SWCTRLBTCLKSEN_SHIFT           8
+
+#define to_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
+
+static unsigned long clk_peri_c_clk_recalc_rate(struct clk_hw *hwclk,
+                                            unsigned long parent_rate)
+{
+       struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+       unsigned long div = 1;
+       u32 val;
+
+       val = readl(socfpgaclk->hw.reg);
+       val &= GENMASK(SWCTRLBTCLKSEN_SHIFT - 1, 0);
+       parent_rate /= val;
+
+       return parent_rate / div;
+}
+
+static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
+                                            unsigned long parent_rate)
+{
+       struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+       unsigned long div = 1;
+
+       if (socfpgaclk->fixed_div) {
+               div = socfpgaclk->fixed_div;
+       } else {
+               if (!socfpgaclk->bypass_reg)
+                       div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
+       }
+
+       return parent_rate / div;
+}
+
+static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
+{
+       struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+       u32 clk_src, mask;
+       u8 parent;
+
+       if (socfpgaclk->bypass_reg) {
+               mask = (0x1 << socfpgaclk->bypass_shift);
+               parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
+                          socfpgaclk->bypass_shift);
+       } else {
+               clk_src = readl(socfpgaclk->hw.reg);
+               parent = (clk_src >> CLK_MGR_FREE_SHIFT) &
+                       CLK_MGR_FREE_MASK;
+       }
+       return parent;
+}
+
+static const struct clk_ops peri_c_clk_ops = {
+       .recalc_rate = clk_peri_c_clk_recalc_rate,
+       .get_parent = clk_periclk_get_parent,
+};
+
+static const struct clk_ops peri_cnt_clk_ops = {
+       .recalc_rate = clk_peri_cnt_clk_recalc_rate,
+       .get_parent = clk_periclk_get_parent,
+};
+
+struct clk *s10_register_periph(const char *name, const char *parent_name,
+                               const char * const *parent_names,
+                               u8 num_parents, unsigned long flags,
+                               void __iomem *reg, unsigned long offset)
+{
+       struct clk *clk;
+       struct socfpga_periph_clk *periph_clk;
+       struct clk_init_data init;
+
+       periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
+       if (WARN_ON(!periph_clk))
+               return NULL;
+
+       periph_clk->hw.reg = reg + offset;
+
+       init.name = name;
+       init.ops = &peri_c_clk_ops;
+       init.flags = flags;
+
+       init.num_parents = num_parents;
+       init.parent_names = parent_names ? parent_names : &parent_name;
+
+       periph_clk->hw.hw.init = &init;
+
+       clk = clk_register(NULL, &periph_clk->hw.hw);
+       if (WARN_ON(IS_ERR(clk))) {
+               kfree(periph_clk);
+               return NULL;
+       }
+       return clk;
+}
+
+struct clk *s10_register_cnt_periph(const char *name, const char *parent_name,
+                                   const char * const *parent_names,
+                                   u8 num_parents, unsigned long flags,
+                                   void __iomem *regbase, unsigned long offset,
+                                   u8 fixed_divider, unsigned long bypass_reg,
+                                   unsigned long bypass_shift)
+{
+       struct clk *clk;
+       struct socfpga_periph_clk *periph_clk;
+       struct clk_init_data init;
+
+       periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
+       if (WARN_ON(!periph_clk))
+               return NULL;
+
+       if (offset)
+               periph_clk->hw.reg = regbase + offset;
+       else
+               periph_clk->hw.reg = NULL;
+
+       if (bypass_reg)
+               periph_clk->bypass_reg = regbase + bypass_reg;
+       else
+               periph_clk->bypass_reg = NULL;
+       periph_clk->bypass_shift = bypass_shift;
+       periph_clk->fixed_div = fixed_divider;
+
+       init.name = name;
+       init.ops = &peri_cnt_clk_ops;
+       init.flags = flags;
+
+       init.num_parents = num_parents;
+       init.parent_names = parent_names ? parent_names : &parent_name;
+
+       periph_clk->hw.hw.init = &init;
+
+       clk = clk_register(NULL, &periph_clk->hw.hw);
+       if (WARN_ON(IS_ERR(clk))) {
+               kfree(periph_clk);
+               return NULL;
+       }
+       return clk;
+}
diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c
new file mode 100644 (file)
index 0000000..2d5d8b4
--- /dev/null
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier:    GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+
+#include "stratix10-clk.h"
+#include "clk.h"
+
+/* Clock Manager offsets */
+#define CLK_MGR_PLL_CLK_SRC_SHIFT      16
+#define CLK_MGR_PLL_CLK_SRC_MASK       0x3
+
+/* PLL Clock enable bits */
+#define SOCFPGA_PLL_POWER              0
+#define SOCFPGA_PLL_RESET_MASK         0x2
+#define SOCFPGA_PLL_REFDIV_MASK                0x00003F00
+#define SOCFPGA_PLL_REFDIV_SHIFT       8
+#define SOCFPGA_PLL_MDIV_MASK          0xFF000000
+#define SOCFPGA_PLL_MDIV_SHIFT         24
+#define SWCTRLBTCLKSEL_MASK            0x200
+#define SWCTRLBTCLKSEL_SHIFT           9
+
+#define SOCFPGA_BOOT_CLK               "boot_clk"
+
+#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
+                                        unsigned long parent_rate)
+{
+       struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+       unsigned long mdiv;
+       unsigned long refdiv;
+       unsigned long reg;
+       unsigned long long vco_freq;
+
+       /* read VCO1 reg for numerator and denominator */
+       reg = readl(socfpgaclk->hw.reg);
+       refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
+       vco_freq = (unsigned long long)parent_rate / refdiv;
+
+       /* Read mdiv and fdiv from the fdbck register */
+       reg = readl(socfpgaclk->hw.reg + 0x4);
+       mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
+       vco_freq = (unsigned long long)parent_rate * (mdiv + 6);
+
+       return (unsigned long)vco_freq;
+}
+
+static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
+                                        unsigned long parent_rate)
+{
+       struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+       u32 div = 1;
+
+       div = ((readl(socfpgaclk->hw.reg) &
+               SWCTRLBTCLKSEL_MASK) >>
+               SWCTRLBTCLKSEL_SHIFT);
+       div += 1;
+       return parent_rate /= div;
+}
+
+
+static u8 clk_pll_get_parent(struct clk_hw *hwclk)
+{
+       struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+       u32 pll_src;
+
+       pll_src = readl(socfpgaclk->hw.reg);
+       return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
+               CLK_MGR_PLL_CLK_SRC_MASK;
+}
+
+static u8 clk_boot_get_parent(struct clk_hw *hwclk)
+{
+       struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+       u32 pll_src;
+
+       pll_src = readl(socfpgaclk->hw.reg);
+       return (pll_src >> SWCTRLBTCLKSEL_SHIFT) &
+               SWCTRLBTCLKSEL_MASK;
+}
+
+static int clk_pll_prepare(struct clk_hw *hwclk)
+{
+       struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+       u32 reg;
+
+       /* Bring PLL out of reset */
+       reg = readl(socfpgaclk->hw.reg);
+       reg |= SOCFPGA_PLL_RESET_MASK;
+       writel(reg, socfpgaclk->hw.reg);
+
+       return 0;
+}
+
+static struct clk_ops clk_pll_ops = {
+       .recalc_rate = clk_pll_recalc_rate,
+       .get_parent = clk_pll_get_parent,
+       .prepare = clk_pll_prepare,
+};
+
+static struct clk_ops clk_boot_ops = {
+       .recalc_rate = clk_boot_clk_recalc_rate,
+       .get_parent = clk_boot_get_parent,
+       .prepare = clk_pll_prepare,
+};
+
+struct clk *s10_register_pll(const char *name, const char * const *parent_names,
+                                   u8 num_parents, unsigned long flags,
+                                   void __iomem *reg, unsigned long offset)
+{
+       struct clk *clk;
+       struct socfpga_pll *pll_clk;
+       struct clk_init_data init;
+
+       pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
+       if (WARN_ON(!pll_clk))
+               return NULL;
+
+       pll_clk->hw.reg = reg + offset;
+
+       if (streq(name, SOCFPGA_BOOT_CLK))
+               init.ops = &clk_boot_ops;
+       else
+               init.ops = &clk_pll_ops;
+
+       init.name = name;
+       init.flags = flags;
+
+       init.num_parents = num_parents;
+       init.parent_names = parent_names;
+       pll_clk->hw.hw.init = &init;
+
+       pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
+       clk_pll_ops.enable = clk_gate_ops.enable;
+       clk_pll_ops.disable = clk_gate_ops.disable;
+
+       clk = clk_register(NULL, &pll_clk->hw.hw);
+       if (WARN_ON(IS_ERR(clk))) {
+               kfree(pll_clk);
+               return NULL;
+       }
+       return clk;
+}
diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
new file mode 100644 (file)
index 0000000..3a11c38
--- /dev/null
@@ -0,0 +1,345 @@
+// SPDX-License-Identifier:    GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/clock/stratix10-clock.h>
+
+#include "stratix10-clk.h"
+
+static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
+                                       "f2s_free_clk",};
+static const char * const cntr_mux[] = { "main_pll", "periph_pll",
+                                        "osc1", "cb_intosc_hs_div2_clk",
+                                        "f2s_free_clk"};
+static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
+
+static const char * const noc_free_mux[] = {"main_noc_base_clk",
+                                           "peri_noc_base_clk",
+                                           "osc1", "cb_intosc_hs_div2_clk",
+                                           "f2s_free_clk"};
+
+static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
+static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
+static const char * const emac_ptp_free_mux[] = {"peri_emac_ptp_clk", "boot_clk"};
+static const char * const gpio_db_free_mux[] = {"peri_gpio_db_clk", "boot_clk"};
+static const char * const sdmmc_free_mux[] = {"peri_sdmmc_clk", "boot_clk"};
+static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"};
+static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
+static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
+
+static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
+static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
+static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
+
+/* clocks in AO (always on) controller */
+static const struct stratix10_pll_clock s10_pll_clks[] = {
+       { STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
+         0x0},
+       { STRATIX10_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux),
+         0, 0x74},
+       { STRATIX10_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux),
+         0, 0xe4},
+};
+
+static const struct stratix10_perip_c_clock s10_main_perip_c_clks[] = {
+       { STRATIX10_MAIN_MPU_BASE_CLK, "main_mpu_base_clk", "main_pll", NULL, 1, 0, 0x84},
+       { STRATIX10_MAIN_NOC_BASE_CLK, "main_noc_base_clk", "main_pll", NULL, 1, 0, 0x88},
+       { STRATIX10_PERI_MPU_BASE_CLK, "peri_mpu_base_clk", "periph_pll", NULL, 1, 0,
+         0xF4},
+       { STRATIX10_PERI_NOC_BASE_CLK, "peri_noc_base_clk", "periph_pll", NULL, 1, 0,
+         0xF8},
+};
+
+static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
+       { STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+          0, 0x48, 0, 0, 0},
+       { STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
+         0, 0x4C, 0, 0, 0},
+       { STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0,
+         0x50, 0, 0, 0},
+       { STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0,
+         0x54, 0, 0, 0},
+       { STRATIX10_MAIN_EMAC_PTP_CLK, "main_emac_ptp_clk", "main_noc_base_clk", NULL, 1, 0,
+         0x58, 0, 0, 0},
+       { STRATIX10_MAIN_GPIO_DB_CLK, "main_gpio_db_clk", "main_noc_base_clk", NULL, 1, 0,
+         0x5C, 0, 0, 0},
+       { STRATIX10_MAIN_SDMMC_CLK, "main_sdmmc_clk", "main_noc_base_clk", NULL, 1, 0,
+         0x60, 0, 0, 0},
+       { STRATIX10_MAIN_S2F_USR0_CLK, "main_s2f_usr0_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+         0, 0x64, 0, 0, 0},
+       { STRATIX10_MAIN_S2F_USR1_CLK, "main_s2f_usr1_clk", "main_noc_base_clk", NULL, 1, 0,
+         0x68, 0, 0, 0},
+       { STRATIX10_MAIN_PSI_REF_CLK, "main_psi_ref_clk", "main_noc_base_clk", NULL, 1, 0,
+         0x6C, 0, 0, 0},
+       { STRATIX10_PERI_EMACA_CLK, "peri_emaca_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+         0, 0xBC, 0, 0, 0},
+       { STRATIX10_PERI_EMACB_CLK, "peri_emacb_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+         0, 0xC0, 0, 0, 0},
+       { STRATIX10_PERI_EMAC_PTP_CLK, "peri_emac_ptp_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+         0, 0xC4, 0, 0, 0},
+       { STRATIX10_PERI_GPIO_DB_CLK, "peri_gpio_db_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+         0, 0xC8, 0, 0, 0},
+       { STRATIX10_PERI_SDMMC_CLK, "peri_sdmmc_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+         0, 0xCC, 0, 0, 0},
+       { STRATIX10_PERI_S2F_USR0_CLK, "peri_s2f_usr0_clk", "peri_noc_base_clk", NULL, 1, 0,
+         0xD0, 0, 0, 0},
+       { STRATIX10_PERI_S2F_USR1_CLK, "peri_s2f_usr1_clk", NULL, cntr_mux, ARRAY_SIZE(cntr_mux),
+         0, 0xD4, 0, 0, 0},
+       { STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0,
+         0xD8, 0, 0, 0},
+       { STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
+         0, 4, 0, 0},
+       { STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
+         0, 0, 0, 0x3C, 1},
+       { STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
+         0, 0, 4, 0xB0, 0},
+       { STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
+         0, 0, 4, 0xB0, 1},
+       { STRATIX10_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
+         ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 4, 0xB0, 2},
+       { STRATIX10_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
+         ARRAY_SIZE(gpio_db_free_mux), 0, 0, 0, 0xB0, 3},
+       { STRATIX10_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
+         ARRAY_SIZE(sdmmc_free_mux), 0, 0, 0, 0xB0, 4},
+       { STRATIX10_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
+         ARRAY_SIZE(s2f_usr1_free_mux), 0, 0, 0, 0xB0, 5},
+       { STRATIX10_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
+         ARRAY_SIZE(psi_ref_free_mux), 0, 0, 0, 0xB0, 6},
+};
+
+static const struct stratix10_gate_clock s10_gate_clks[] = {
+       { STRATIX10_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x30,
+         0, 0, 0, 0, 0x3C, 0, 0},
+       { STRATIX10_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x30,
+         0, 0, 0, 0, 0, 0, 4},
+       { STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30,
+         0, 0, 0, 0, 0, 0, 2},
+       { STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30,
+         1, 0x70, 0, 2, 0, 0, 0},
+       { STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30,
+         2, 0x70, 8, 2, 0, 0, 0},
+       { STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30,
+         3, 0x70, 16, 2, 0, 0, 0},
+       { STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30,
+         4, 0x70, 24, 2, 0, 0, 0},
+       { STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30,
+         4, 0x70, 26, 2, 0, 0, 0},
+       { STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30,
+         4, 0x70, 28, 1, 0, 0, 0},
+       { STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30,
+         5, 0, 0, 0, 0, 0, 0},
+       { STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30,
+         6, 0, 0, 0, 0, 0, 0},
+       { STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
+         0, 0, 0, 0, 0xDC, 26, 0},
+       { STRATIX10_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
+         1, 0, 0, 0, 0xDC, 27, 0},
+       { STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
+         2, 0, 0, 0, 0xDC, 28, 0},
+       { STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4,
+         3, 0, 0, 0, 0, 0, 0},
+       { STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4,
+         4, 0xE0, 0, 16, 0, 0, 0},
+       { STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4,
+         5, 0, 0, 0, 0, 0, 4},
+       { STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4,
+         6, 0, 0, 0, 0, 0, 0},
+       { STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4,
+         7, 0, 0, 0, 0, 0, 0},
+       { STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
+         8, 0, 0, 0, 0, 0, 0},
+       { STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
+         9, 0, 0, 0, 0, 0, 0},
+       { STRATIX10_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0xA4,
+         10, 0, 0, 0, 0, 0, 0},
+};
+
+static int s10_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
+                                   int nums, struct stratix10_clock_data *data)
+{
+       struct clk *clk;
+       void __iomem *base = data->base;
+       int i;
+
+       for (i = 0; i < nums; i++) {
+               clk = s10_register_periph(clks[i].name, clks[i].parent_name,
+                                         clks[i].parent_names, clks[i].num_parents,
+                                         clks[i].flags, base, clks[i].offset);
+               if (IS_ERR(clk)) {
+                       pr_err("%s: failed to register clock %s\n",
+                              __func__, clks[i].name);
+                       continue;
+               }
+               data->clk_data.clks[clks[i].id] = clk;
+       }
+       return 0;
+}
+
+static int s10_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
+                                     int nums, struct stratix10_clock_data *data)
+{
+       struct clk *clk;
+       void __iomem *base = data->base;
+       int i;
+
+       for (i = 0; i < nums; i++) {
+               clk = s10_register_cnt_periph(clks[i].name, clks[i].parent_name,
+                                             clks[i].parent_names,
+                                             clks[i].num_parents,
+                                             clks[i].flags, base,
+                                             clks[i].offset,
+                                             clks[i].fixed_divider,
+                                             clks[i].bypass_reg,
+                                             clks[i].bypass_shift);
+               if (IS_ERR(clk)) {
+                       pr_err("%s: failed to register clock %s\n",
+                              __func__, clks[i].name);
+                       continue;
+               }
+               data->clk_data.clks[clks[i].id] = clk;
+       }
+
+       return 0;
+}
+
+static int s10_clk_register_gate(const struct stratix10_gate_clock *clks,
+                                int nums, struct stratix10_clock_data *data)
+{
+       struct clk *clk;
+       void __iomem *base = data->base;
+       int i;
+
+       for (i = 0; i < nums; i++) {
+               clk = s10_register_gate(clks[i].name, clks[i].parent_name,
+                                       clks[i].parent_names,
+                                       clks[i].num_parents,
+                                       clks[i].flags, base,
+                                       clks[i].gate_reg,
+                                       clks[i].gate_idx, clks[i].div_reg,
+                                       clks[i].div_offset, clks[i].div_width,
+                                       clks[i].bypass_reg,
+                                       clks[i].bypass_shift,
+                                       clks[i].fixed_div);
+               if (IS_ERR(clk)) {
+                       pr_err("%s: failed to register clock %s\n",
+                              __func__, clks[i].name);
+                       continue;
+               }
+               data->clk_data.clks[clks[i].id] = clk;
+       }
+
+       return 0;
+}
+
+static int s10_clk_register_pll(const struct stratix10_pll_clock *clks,
+                                int nums, struct stratix10_clock_data *data)
+{
+       struct clk *clk;
+       void __iomem *base = data->base;
+       int i;
+
+       for (i = 0; i < nums; i++) {
+               clk = s10_register_pll(clks[i].name, clks[i].parent_names,
+                                   clks[i].num_parents,
+                                   clks[i].flags, base,
+                                   clks[i].offset);
+               if (IS_ERR(clk)) {
+                       pr_err("%s: failed to register clock %s\n",
+                              __func__, clks[i].name);
+                       continue;
+               }
+               data->clk_data.clks[clks[i].id] = clk;
+       }
+
+       return 0;
+}
+
+static struct stratix10_clock_data *__socfpga_s10_clk_init(struct device_node *np,
+                                                   int nr_clks)
+{
+       struct stratix10_clock_data *clk_data;
+       struct clk **clk_table;
+       void __iomem *base;
+
+       base = of_iomap(np, 0);
+       if (!base) {
+               pr_err("%s: failed to map clock registers\n", __func__);
+               goto err;
+       }
+
+       clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+       if (!clk_data)
+               goto err;
+
+       clk_data->base = base;
+       clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
+       if (!clk_table)
+               goto err_data;
+
+       clk_data->clk_data.clks = clk_table;
+       clk_data->clk_data.clk_num = nr_clks;
+       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
+       return clk_data;
+
+err_data:
+       kfree(clk_data);
+err:
+       return NULL;
+}
+
+static int s10_clkmgr_init(struct device_node *np)
+{
+       struct stratix10_clock_data *clk_data;
+
+       clk_data = __socfpga_s10_clk_init(np, STRATIX10_NUM_CLKS);
+       if (!clk_data)
+               return -ENOMEM;
+
+       s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data);
+
+       s10_clk_register_c_perip(s10_main_perip_c_clks,
+                                ARRAY_SIZE(s10_main_perip_c_clks), clk_data);
+
+       s10_clk_register_cnt_perip(s10_main_perip_cnt_clks,
+                                  ARRAY_SIZE(s10_main_perip_cnt_clks),
+                                  clk_data);
+
+       s10_clk_register_gate(s10_gate_clks, ARRAY_SIZE(s10_gate_clks),
+                             clk_data);
+       return 0;
+}
+
+static int s10_clkmgr_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+
+       s10_clkmgr_init(np);
+
+       return 0;
+}
+
+static const struct of_device_id stratix10_clkmgr_match_table[] = {
+       { .compatible = "intel,stratix10-clkmgr",
+         .data = s10_clkmgr_init },
+       { }
+};
+
+static struct platform_driver stratix10_clkmgr_driver = {
+       .probe          = s10_clkmgr_probe,
+       .driver         = {
+               .name   = "stratix10-clkmgr",
+               .of_match_table = stratix10_clkmgr_match_table,
+       },
+};
+
+static int __init s10_clk_init(void)
+{
+       return platform_driver_register(&stratix10_clkmgr_driver);
+}
+core_initcall(s10_clk_init);
index 9cf1230115b176d42d6143232383e685c2b44b7b..26c3a265cf78a1e41202a6b3179f0719bf6fbc2f 100644 (file)
@@ -54,9 +54,11 @@ struct socfpga_gate_clk {
        char *parent_name;
        u32 fixed_div;
        void __iomem *div_reg;
+       void __iomem *bypass_reg;
        struct regmap *sys_mgr_base_addr;
        u32 width;      /* only valid if div_reg != 0 */
        u32 shift;      /* only valid if div_reg != 0 */
+       u32 bypass_shift;      /* only valid if bypass_reg != 0 */
        u32 clk_phase[2];
 };
 
@@ -65,8 +67,10 @@ struct socfpga_periph_clk {
        char *parent_name;
        u32 fixed_div;
        void __iomem *div_reg;
+       void __iomem *bypass_reg;
        u32 width;      /* only valid if div_reg != 0 */
        u32 shift;      /* only valid if div_reg != 0 */
+       u32 bypass_shift;      /* only valid if bypass_reg != 0 */
 };
 
 #endif /* SOCFPGA_CLK_H */
diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
new file mode 100644 (file)
index 0000000..e8e1219
--- /dev/null
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier:    GPL-2.0 */
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+
+#ifndef        __STRATIX10_CLK_H
+#define        __STRATIX10_CLK_H
+
+struct stratix10_clock_data {
+       struct clk_onecell_data clk_data;
+       void __iomem            *base;
+};
+
+struct stratix10_pll_clock {
+       unsigned int            id;
+       const char              *name;
+       const char              *const *parent_names;
+       u8                      num_parents;
+       unsigned long           flags;
+       unsigned long           offset;
+};
+
+struct stratix10_perip_c_clock {
+       unsigned int            id;
+       const char              *name;
+       const char              *parent_name;
+       const char              *const *parent_names;
+       u8                      num_parents;
+       unsigned long           flags;
+       unsigned long           offset;
+};
+
+struct stratix10_perip_cnt_clock {
+       unsigned int            id;
+       const char              *name;
+       const char              *parent_name;
+       const char              *const *parent_names;
+       u8                      num_parents;
+       unsigned long           flags;
+       unsigned long           offset;
+       u8                      fixed_divider;
+       unsigned long           bypass_reg;
+       unsigned long           bypass_shift;
+};
+
+struct stratix10_gate_clock {
+       unsigned int            id;
+       const char              *name;
+       const char              *parent_name;
+       const char              *const *parent_names;
+       u8                      num_parents;
+       unsigned long           flags;
+       unsigned long           gate_reg;
+       u8                      gate_idx;
+       unsigned long           div_reg;
+       u8                      div_offset;
+       u8                      div_width;
+       unsigned long           bypass_reg;
+       u8                      bypass_shift;
+       u8                      fixed_div;
+};
+
+struct clk *s10_register_pll(const char *, const char *const *, u8,
+                            unsigned long, void __iomem *, unsigned long);
+
+struct clk *s10_register_periph(const char *, const char *,
+                               const char * const *, u8, unsigned long,
+                               void __iomem *, unsigned long);
+struct clk *s10_register_cnt_periph(const char *, const char *,
+                                   const char * const *, u8,
+                                   unsigned long, void __iomem *,
+                                   unsigned long, u8, unsigned long,
+                                   unsigned long);
+struct clk *s10_register_gate(const char *, const char *,
+                             const char * const *, u8,
+                             unsigned long, void __iomem *,
+                             unsigned long, unsigned long,
+                             unsigned long, unsigned long, u8,
+                             unsigned long, u8, u8);
+#endif /* __STRATIX10_CLK_H */
index ed5c027df0f49f20d97bd089a6ffc4120ecdec71..9980ab55271ba2f71f7ad09ba04d2bbd23468eb7 100644 (file)
@@ -959,6 +959,44 @@ static SPRD_SC_GATE_CLK(sdio2_2x_en,       "sdio2-2x-en",  "aon-apb", 0x13c,
                               0x1000, BIT(6), 0, 0);
 static SPRD_SC_GATE_CLK(emmc_2x_en,    "emmc-2x-en",   "aon-apb", 0x13c,
                               0x1000, BIT(9), 0, 0);
+static SPRD_SC_GATE_CLK(arch_rtc_eb, "arch-rtc-eb",    "aon-apb", 0x10,
+                    0x1000, BIT(0), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(kpb_rtc_eb, "kpb-rtc-eb",      "aon-apb", 0x10,
+                    0x1000, BIT(1), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aon_syst_rtc_eb, "aon-syst-rtc-eb",    "aon-apb", 0x10,
+                    0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_syst_rtc_eb, "ap-syst-rtc-eb",      "aon-apb", 0x10,
+                    0x1000, BIT(3), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aon_tmr_rtc_eb, "aon-tmr-rtc-eb",      "aon-apb", 0x10,
+                    0x1000, BIT(4), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_tmr0_rtc_eb, "ap-tmr0-rtc-eb",      "aon-apb", 0x10,
+                    0x1000, BIT(5), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(eic_rtc_eb, "eic-rtc-eb",      "aon-apb", 0x10,
+                    0x1000, BIT(6), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(eic_rtcdv5_eb, "eic-rtcdv5-eb",        "aon-apb", 0x10,
+                    0x1000, BIT(7), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_wdg_rtc_eb, "ap-wdg-rtc-eb",        "aon-apb", 0x10,
+                    0x1000, BIT(9), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_tmr1_rtc_eb, "ap-tmr1-rtc-eb",      "aon-apb", 0x10,
+                    0x1000, BIT(15), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_tmr2_rtc_eb, "ap-tmr2-rtc-eb",      "aon-apb", 0x10,
+                    0x1000, BIT(16), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(dcxo_tmr_rtc_eb, "dcxo-tmr-rtc-eb",    "aon-apb", 0x10,
+                    0x1000, BIT(17), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(bb_cal_rtc_eb, "bb-cal-rtc-eb",        "aon-apb", 0x10,
+                    0x1000, BIT(18), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(avs_big_rtc_eb, "avs-big-rtc-eb",      "aon-apb", 0x10,
+                    0x1000, BIT(20), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(avs_lit_rtc_eb, "avs-lit-rtc-eb",      "aon-apb", 0x10,
+                    0x1000, BIT(21), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(avs_gpu0_rtc_eb, "avs-gpu0-rtc-eb",    "aon-apb", 0x10,
+                    0x1000, BIT(22), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(avs_gpu1_rtc_eb, "avs-gpu1-rtc-eb",    "aon-apb", 0x10,
+                    0x1000, BIT(23), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(gpu_ts_eb, "gpu-ts-eb",        "aon-apb", 0x10,
+                    0x1000, BIT(24), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(rtcdv10_eb, "rtcdv10-eb",      "aon-apb", 0x10,
+                    0x1000, BIT(27), CLK_IGNORE_UNUSED, 0);
 
 static struct sprd_clk_common *sc9860_aon_gate[] = {
        /* address base is 0x402e0000 */
@@ -1030,6 +1068,25 @@ static struct sprd_clk_common *sc9860_aon_gate[] = {
        &sdio1_2x_en.common,
        &sdio2_2x_en.common,
        &emmc_2x_en.common,
+       &arch_rtc_eb.common,
+       &kpb_rtc_eb.common,
+       &aon_syst_rtc_eb.common,
+       &ap_syst_rtc_eb.common,
+       &aon_tmr_rtc_eb.common,
+       &ap_tmr0_rtc_eb.common,
+       &eic_rtc_eb.common,
+       &eic_rtcdv5_eb.common,
+       &ap_wdg_rtc_eb.common,
+       &ap_tmr1_rtc_eb.common,
+       &ap_tmr2_rtc_eb.common,
+       &dcxo_tmr_rtc_eb.common,
+       &bb_cal_rtc_eb.common,
+       &avs_big_rtc_eb.common,
+       &avs_lit_rtc_eb.common,
+       &avs_gpu0_rtc_eb.common,
+       &avs_gpu1_rtc_eb.common,
+       &gpu_ts_eb.common,
+       &rtcdv10_eb.common,
 };
 
 static struct clk_hw_onecell_data sc9860_aon_gate_hws = {
@@ -1102,6 +1159,25 @@ static struct clk_hw_onecell_data sc9860_aon_gate_hws = {
                [CLK_SDIO1_2X_EN]       = &sdio1_2x_en.common.hw,
                [CLK_SDIO2_2X_EN]       = &sdio2_2x_en.common.hw,
                [CLK_EMMC_2X_EN]        = &emmc_2x_en.common.hw,
+               [CLK_ARCH_RTC_EB]       = &arch_rtc_eb.common.hw,
+               [CLK_KPB_RTC_EB]        = &kpb_rtc_eb.common.hw,
+               [CLK_AON_SYST_RTC_EB]   = &aon_syst_rtc_eb.common.hw,
+               [CLK_AP_SYST_RTC_EB]    = &ap_syst_rtc_eb.common.hw,
+               [CLK_AON_TMR_RTC_EB]    = &aon_tmr_rtc_eb.common.hw,
+               [CLK_AP_TMR0_RTC_EB]    = &ap_tmr0_rtc_eb.common.hw,
+               [CLK_EIC_RTC_EB]        = &eic_rtc_eb.common.hw,
+               [CLK_EIC_RTCDV5_EB]     = &eic_rtcdv5_eb.common.hw,
+               [CLK_AP_WDG_RTC_EB]     = &ap_wdg_rtc_eb.common.hw,
+               [CLK_AP_TMR1_RTC_EB]    = &ap_tmr1_rtc_eb.common.hw,
+               [CLK_AP_TMR2_RTC_EB]    = &ap_tmr2_rtc_eb.common.hw,
+               [CLK_DCXO_TMR_RTC_EB]   = &dcxo_tmr_rtc_eb.common.hw,
+               [CLK_BB_CAL_RTC_EB]     = &bb_cal_rtc_eb.common.hw,
+               [CLK_AVS_BIG_RTC_EB]    = &avs_big_rtc_eb.common.hw,
+               [CLK_AVS_LIT_RTC_EB]    = &avs_lit_rtc_eb.common.hw,
+               [CLK_AVS_GPU0_RTC_EB]   = &avs_gpu0_rtc_eb.common.hw,
+               [CLK_AVS_GPU1_RTC_EB]   = &avs_gpu1_rtc_eb.common.hw,
+               [CLK_GPU_TS_EB]         = &gpu_ts_eb.common.hw,
+               [CLK_RTCDV10_EB]        = &rtcdv10_eb.common.hw,
        },
        .num    = CLK_AON_GATE_NUM,
 };
index 6427d0ebe2defa30539fedc5e92915973276a7d9..79dfd296c3d174686b6ace8da7d9cca219ff37b7 100644 (file)
@@ -11,15 +11,13 @@ config SUN50I_A64_CCU
        default ARM64 && ARCH_SUNXI
        depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
 
+config SUN50I_H6_CCU
+       bool "Support for the Allwinner H6 CCU"
+       default ARM64 && ARCH_SUNXI
+       depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
+
 config SUN4I_A10_CCU
        bool "Support for the Allwinner A10/A20 CCU"
-       select SUNXI_CCU_DIV
-       select SUNXI_CCU_MULT
-       select SUNXI_CCU_NK
-       select SUNXI_CCU_NKM
-       select SUNXI_CCU_NM
-       select SUNXI_CCU_MP
-       select SUNXI_CCU_PHASE
        default MACH_SUN4I
        default MACH_SUN7I
        depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
index 4141c3fe08ae1eaccb3ca77d4d1989649c3ac718..128a40ee5c5eef405a71dc43bbba83a7fc8877f3 100644 (file)
@@ -22,6 +22,7 @@ lib-$(CONFIG_SUNXI_CCU)               += ccu_mp.o
 
 # SoC support
 obj-$(CONFIG_SUN50I_A64_CCU)   += ccu-sun50i-a64.o
+obj-$(CONFIG_SUN50I_H6_CCU)    += ccu-sun50i-h6.o
 obj-$(CONFIG_SUN4I_A10_CCU)    += ccu-sun4i-a10.o
 obj-$(CONFIG_SUN5I_CCU)                += ccu-sun5i.o
 obj-$(CONFIG_SUN6I_A31_CCU)    += ccu-sun6i-a31.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
new file mode 100644 (file)
index 0000000..bdbfe78
--- /dev/null
@@ -0,0 +1,1211 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+#include "ccu_mult.h"
+#include "ccu_nk.h"
+#include "ccu_nkm.h"
+#include "ccu_nkmp.h"
+#include "ccu_nm.h"
+
+#include "ccu-sun50i-h6.h"
+
+/*
+ * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However
+ * P should only be used for output frequencies lower than 288 MHz.
+ *
+ * For now we can just model it as a multiplier clock, and force P to /1.
+ *
+ * The M factor is present in the register's description, but not in the
+ * frequency formula, and it's documented as "M is only used for backdoor
+ * testing", so it's not modelled and then force to 0.
+ */
+#define SUN50I_H6_PLL_CPUX_REG         0x000
+static struct ccu_mult pll_cpux_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .mult           = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+       .common         = {
+               .reg            = 0x000,
+               .hw.init        = CLK_HW_INIT("pll-cpux", "osc24M",
+                                             &ccu_mult_ops,
+                                             CLK_SET_RATE_UNGATE),
+       },
+};
+
+/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
+#define SUN50I_H6_PLL_DDR0_REG         0x010
+static struct ccu_nkmp pll_ddr0_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
+       .p              = _SUNXI_CCU_DIV(0, 1), /* output divider */
+       .common         = {
+               .reg            = 0x010,
+               .hw.init        = CLK_HW_INIT("pll-ddr0", "osc24M",
+                                             &ccu_nkmp_ops,
+                                             CLK_SET_RATE_UNGATE),
+       },
+};
+
+#define SUN50I_H6_PLL_PERIPH0_REG      0x020
+static struct ccu_nkmp pll_periph0_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
+       .p              = _SUNXI_CCU_DIV(0, 1), /* output divider */
+       .fixed_post_div = 4,
+       .common         = {
+               .reg            = 0x020,
+               .features       = CCU_FEATURE_FIXED_POSTDIV,
+               .hw.init        = CLK_HW_INIT("pll-periph0", "osc24M",
+                                             &ccu_nkmp_ops,
+                                             CLK_SET_RATE_UNGATE),
+       },
+};
+
+#define SUN50I_H6_PLL_PERIPH1_REG      0x028
+static struct ccu_nkmp pll_periph1_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
+       .p              = _SUNXI_CCU_DIV(0, 1), /* output divider */
+       .fixed_post_div = 4,
+       .common         = {
+               .reg            = 0x028,
+               .features       = CCU_FEATURE_FIXED_POSTDIV,
+               .hw.init        = CLK_HW_INIT("pll-periph1", "osc24M",
+                                             &ccu_nkmp_ops,
+                                             CLK_SET_RATE_UNGATE),
+       },
+};
+
+#define SUN50I_H6_PLL_GPU_REG          0x030
+static struct ccu_nkmp pll_gpu_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
+       .p              = _SUNXI_CCU_DIV(0, 1), /* output divider */
+       .common         = {
+               .reg            = 0x030,
+               .hw.init        = CLK_HW_INIT("pll-gpu", "osc24M",
+                                             &ccu_nkmp_ops,
+                                             CLK_SET_RATE_UNGATE),
+       },
+};
+
+/*
+ * For Video PLLs, the output divider is described as "used for testing"
+ * in the user manual. So it's not modelled and forced to 0.
+ */
+#define SUN50I_H6_PLL_VIDEO0_REG       0x040
+static struct ccu_nm pll_video0_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
+       .fixed_post_div = 4,
+       .common         = {
+               .reg            = 0x040,
+               .features       = CCU_FEATURE_FIXED_POSTDIV,
+               .hw.init        = CLK_HW_INIT("pll-video0", "osc24M",
+                                             &ccu_nm_ops,
+                                             CLK_SET_RATE_UNGATE),
+       },
+};
+
+#define SUN50I_H6_PLL_VIDEO1_REG       0x048
+static struct ccu_nm pll_video1_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
+       .fixed_post_div = 4,
+       .common         = {
+               .reg            = 0x048,
+               .features       = CCU_FEATURE_FIXED_POSTDIV,
+               .hw.init        = CLK_HW_INIT("pll-video1", "osc24M",
+                                             &ccu_nm_ops,
+                                             CLK_SET_RATE_UNGATE),
+       },
+};
+
+#define SUN50I_H6_PLL_VE_REG           0x058
+static struct ccu_nkmp pll_ve_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
+       .p              = _SUNXI_CCU_DIV(0, 1), /* output divider */
+       .common         = {
+               .reg            = 0x058,
+               .hw.init        = CLK_HW_INIT("pll-ve", "osc24M",
+                                             &ccu_nkmp_ops,
+                                             CLK_SET_RATE_UNGATE),
+       },
+};
+
+#define SUN50I_H6_PLL_DE_REG           0x060
+static struct ccu_nkmp pll_de_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
+       .p              = _SUNXI_CCU_DIV(0, 1), /* output divider */
+       .common         = {
+               .reg            = 0x060,
+               .hw.init        = CLK_HW_INIT("pll-de", "osc24M",
+                                             &ccu_nkmp_ops,
+                                             CLK_SET_RATE_UNGATE),
+       },
+};
+
+#define SUN50I_H6_PLL_HSIC_REG         0x070
+static struct ccu_nkmp pll_hsic_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
+       .p              = _SUNXI_CCU_DIV(0, 1), /* output divider */
+       .common         = {
+               .reg            = 0x070,
+               .hw.init        = CLK_HW_INIT("pll-hsic", "osc24M",
+                                             &ccu_nkmp_ops,
+                                             CLK_SET_RATE_UNGATE),
+       },
+};
+
+/*
+ * The Audio PLL is supposed to have 3 outputs: 2 fixed factors from
+ * the base (2x and 4x), and one variable divider (the one true pll audio).
+ *
+ * We don't have any need for the variable divider for now, so we just
+ * hardcode it to match with the clock names.
+ */
+#define SUN50I_H6_PLL_AUDIO_REG                0x078
+static struct ccu_nm pll_audio_base_clk = {
+       .enable         = BIT(31),
+       .lock           = BIT(28),
+       .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
+       .common         = {
+               .reg            = 0x078,
+               .hw.init        = CLK_HW_INIT("pll-audio-base", "osc24M",
+                                             &ccu_nm_ops,
+                                             CLK_SET_RATE_UNGATE),
+       },
+};
+
+static const char * const cpux_parents[] = { "osc24M", "osc32k",
+                                            "iosc", "pll-cpux" };
+static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
+                    0x500, 24, 2, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
+static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0);
+static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0);
+
+static const char * const psi_ahb1_ahb2_parents[] = { "osc24M", "osc32k",
+                                                     "iosc", "pll-periph0" };
+static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2",
+                            psi_ahb1_ahb2_parents,
+                            0x510,
+                            0, 5,      /* M */
+                            16, 2,     /* P */
+                            24, 2,     /* mux */
+                            0);
+
+static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k",
+                                                      "psi-ahb1-ahb2",
+                                                      "pll-periph0" };
+static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c,
+                            0, 5,      /* M */
+                            16, 2,     /* P */
+                            24, 2,     /* mux */
+                            0);
+
+static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520,
+                            0, 5,      /* M */
+                            16, 2,     /* P */
+                            24, 2,     /* mux */
+                            0);
+
+static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524,
+                            0, 5,      /* M */
+                            16, 2,     /* P */
+                            24, 2,     /* mux */
+                            0);
+
+static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x",
+                                            "pll-ddr0", "pll-periph0-4x" };
+static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x540,
+                                      0, 3,    /* M */
+                                      24, 2,   /* mux */
+                                      BIT(31), /* gate */
+                                      CLK_IS_CRITICAL);
+
+static const char * const de_parents[] = { "pll-de", "pll-periph0-2x" };
+static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
+                                      0, 4,    /* M */
+                                      24, 1,   /* mux */
+                                      BIT(31), /* gate */
+                                      0);
+
+static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2",
+                     0x60c, BIT(0), 0);
+
+static const char * const deinterlace_parents[] = { "pll-periph0",
+                                                   "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace",
+                                      deinterlace_parents,
+                                      0x620,
+                                      0, 4,    /* M */
+                                      24, 1,   /* mux */
+                                      BIT(31), /* gate */
+                                      0);
+
+static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "psi-ahb1-ahb2",
+                     0x62c, BIT(0), 0);
+
+static const char * const gpu_parents[] = { "pll-gpu" };
+static SUNXI_CCU_M_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
+                                      0, 3,    /* M */
+                                      24, 1,   /* mux */
+                                      BIT(31), /* gate */
+                                      0);
+
+static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2",
+                     0x67c, BIT(0), 0);
+
+/* Also applies to EMCE */
+static const char * const ce_parents[] = { "osc24M", "pll-periph0-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
+                                       0, 4,   /* M */
+                                       8, 2,   /* N */
+                                       24, 1,  /* mux */
+                                       BIT(31),/* gate */
+                                       0);
+
+static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "psi-ahb1-ahb2",
+                     0x68c, BIT(0), 0);
+
+static const char * const ve_parents[] = { "pll-ve" };
+static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
+                                      0, 3,    /* M */
+                                      24, 1,   /* mux */
+                                      BIT(31), /* gate */
+                                      0);
+
+static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2",
+                     0x69c, BIT(0), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(emce_clk, "emce", ce_parents, 0x6b0,
+                                       0, 4,   /* M */
+                                       8, 2,   /* N */
+                                       24, 1,  /* mux */
+                                       BIT(31),/* gate */
+                                       0);
+
+static SUNXI_CCU_GATE(bus_emce_clk, "bus-emce", "psi-ahb1-ahb2",
+                     0x6bc, BIT(0), 0);
+
+static const char * const vp9_parents[] = { "pll-ve", "pll-periph0-2x" };
+static SUNXI_CCU_M_WITH_MUX_GATE(vp9_clk, "vp9", vp9_parents, 0x6c0,
+                                      0, 3,    /* M */
+                                      24, 1,   /* mux */
+                                      BIT(31), /* gate */
+                                      0);
+
+static SUNXI_CCU_GATE(bus_vp9_clk, "bus-vp9", "psi-ahb1-ahb2",
+                     0x6cc, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "psi-ahb1-ahb2",
+                     0x70c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "psi-ahb1-ahb2",
+                     0x71c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "psi-ahb1-ahb2",
+                     0x72c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "psi-ahb1-ahb2",
+                     0x73c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x740, BIT(31), 0);
+
+static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2",
+                     0x78c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2",
+                     0x79c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x79c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0);
+
+static const char * const dram_parents[] = { "pll-ddr0" };
+static struct ccu_div dram_clk = {
+       .div            = _SUNXI_CCU_DIV(0, 2),
+       .mux            = _SUNXI_CCU_MUX(24, 2),
+       .common = {
+               .reg            = 0x800,
+               .hw.init        = CLK_HW_INIT_PARENTS("dram",
+                                                     dram_parents,
+                                                     &ccu_div_ops,
+                                                     CLK_IS_CRITICAL),
+       },
+};
+
+static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "mbus",
+                     0x804, BIT(0), 0);
+static SUNXI_CCU_GATE(mbus_ve_clk, "mbus-ve", "mbus",
+                     0x804, BIT(1), 0);
+static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "mbus",
+                     0x804, BIT(2), 0);
+static SUNXI_CCU_GATE(mbus_ts_clk, "mbus-ts", "mbus",
+                     0x804, BIT(3), 0);
+static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "mbus",
+                     0x804, BIT(5), 0);
+static SUNXI_CCU_GATE(mbus_csi_clk, "mbus-csi", "mbus",
+                     0x804, BIT(8), 0);
+static SUNXI_CCU_GATE(mbus_deinterlace_clk, "mbus-deinterlace", "mbus",
+                     0x804, BIT(11), 0);
+
+static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "psi-ahb1-ahb2",
+                     0x80c, BIT(0), CLK_IS_CRITICAL);
+
+static const char * const nand_spi_parents[] = { "osc24M", "pll-periph0",
+                                            "pll-periph1", "pll-periph0-2x",
+                                            "pll-periph1-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_spi_parents, 0x810,
+                                       0, 4,   /* M */
+                                       8, 2,   /* N */
+                                       24, 3,  /* mux */
+                                       BIT(31),/* gate */
+                                       0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_spi_parents, 0x814,
+                                       0, 4,   /* M */
+                                       8, 2,   /* N */
+                                       24, 3,  /* mux */
+                                       BIT(31),/* gate */
+                                       0);
+
+static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0);
+
+static const char * const mmc_parents[] = { "osc24M", "pll-periph0-2x",
+                                           "pll-periph1-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc_parents, 0x830,
+                                       0, 4,   /* M */
+                                       8, 2,   /* N */
+                                       24, 3,  /* mux */
+                                       BIT(31),/* gate */
+                                       0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc_parents, 0x834,
+                                       0, 4,   /* M */
+                                       8, 2,   /* N */
+                                       24, 3,  /* mux */
+                                       BIT(31),/* gate */
+                                       0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc_parents, 0x838,
+                                       0, 4,   /* M */
+                                       8, 2,   /* N */
+                                       24, 3,  /* mux */
+                                       BIT(31),/* gate */
+                                       0);
+
+static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb3", 0x84c, BIT(2), 0);
+
+static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3), 0);
+
+static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", 0x91c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", 0x91c, BIT(3), 0);
+
+static SUNXI_CCU_GATE(bus_scr0_clk, "bus-scr0", "apb2", 0x93c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_scr1_clk, "bus-scr1", "apb2", 0x93c, BIT(1), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", nand_spi_parents, 0x940,
+                                       0, 4,   /* M */
+                                       8, 2,   /* N */
+                                       24, 3,  /* mux */
+                                       BIT(31),/* gate */
+                                       0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", nand_spi_parents, 0x944,
+                                       0, 4,   /* M */
+                                       8, 2,   /* N */
+                                       24, 3,  /* mux */
+                                       BIT(31),/* gate */
+                                       0);
+
+static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb3", 0x96c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb3", 0x96c, BIT(1), 0);
+
+static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb3", 0x97c, BIT(0), 0);
+
+static const char * const ts_parents[] = { "osc24M", "pll-periph0" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x9b0,
+                                       0, 4,   /* M */
+                                       8, 2,   /* N */
+                                       24, 1,  /* mux */
+                                       BIT(31),/* gate */
+                                       0);
+
+static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb3", 0x9bc, BIT(0), 0);
+
+static const char * const ir_tx_parents[] = { "osc32k", "osc24M" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_parents, 0x9c0,
+                                       0, 4,   /* M */
+                                       8, 2,   /* N */
+                                       24, 1,  /* mux */
+                                       BIT(31),/* gate */
+                                       0);
+
+static SUNXI_CCU_GATE(bus_ir_tx_clk, "bus-ir-tx", "apb1", 0x9cc, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", 0x9fc, BIT(0), 0);
+
+static const char * const audio_parents[] = { "pll-audio", "pll-audio-2x", "pll-audio-4x" };
+static struct ccu_div i2s3_clk = {
+       .enable         = BIT(31),
+       .div            = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+       .mux            = _SUNXI_CCU_MUX(24, 2),
+       .common         = {
+               .reg            = 0xa0c,
+               .hw.init        = CLK_HW_INIT_PARENTS("i2s3",
+                                                     audio_parents,
+                                                     &ccu_div_ops,
+                                                     0),
+       },
+};
+
+static struct ccu_div i2s0_clk = {
+       .enable         = BIT(31),
+       .div            = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+       .mux            = _SUNXI_CCU_MUX(24, 2),
+       .common         = {
+               .reg            = 0xa10,
+               .hw.init        = CLK_HW_INIT_PARENTS("i2s0",
+                                                     audio_parents,
+                                                     &ccu_div_ops,
+                                                     0),
+       },
+};
+
+static struct ccu_div i2s1_clk = {
+       .enable         = BIT(31),
+       .div            = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+       .mux            = _SUNXI_CCU_MUX(24, 2),
+       .common         = {
+               .reg            = 0xa14,
+               .hw.init        = CLK_HW_INIT_PARENTS("i2s1",
+                                                     audio_parents,
+                                                     &ccu_div_ops,
+                                                     0),
+       },
+};
+
+static struct ccu_div i2s2_clk = {
+       .enable         = BIT(31),
+       .div            = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+       .mux            = _SUNXI_CCU_MUX(24, 2),
+       .common         = {
+               .reg            = 0xa18,
+               .hw.init        = CLK_HW_INIT_PARENTS("i2s2",
+                                                     audio_parents,
+                                                     &ccu_div_ops,
+                                                     0),
+       },
+};
+
+static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", 0xa1c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", 0xa1c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_i2s2_clk, "bus-i2s2", "apb1", 0xa1c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_i2s3_clk, "bus-i2s3", "apb1", 0xa1c, BIT(3), 0);
+
+static struct ccu_div spdif_clk = {
+       .enable         = BIT(31),
+       .div            = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+       .mux            = _SUNXI_CCU_MUX(24, 2),
+       .common         = {
+               .reg            = 0xa20,
+               .hw.init        = CLK_HW_INIT_PARENTS("spdif",
+                                                     audio_parents,
+                                                     &ccu_div_ops,
+                                                     0),
+       },
+};
+
+static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0), 0);
+
+static struct ccu_div dmic_clk = {
+       .enable         = BIT(31),
+       .div            = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+       .mux            = _SUNXI_CCU_MUX(24, 2),
+       .common         = {
+               .reg            = 0xa40,
+               .hw.init        = CLK_HW_INIT_PARENTS("dmic",
+                                                     audio_parents,
+                                                     &ccu_div_ops,
+                                                     0),
+       },
+};
+
+static SUNXI_CCU_GATE(bus_dmic_clk, "bus-dmic", "apb1", 0xa4c, BIT(0), 0);
+
+static struct ccu_div audio_hub_clk = {
+       .enable         = BIT(31),
+       .div            = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+       .mux            = _SUNXI_CCU_MUX(24, 2),
+       .common         = {
+               .reg            = 0xa60,
+               .hw.init        = CLK_HW_INIT_PARENTS("audio-hub",
+                                                     audio_parents,
+                                                     &ccu_div_ops,
+                                                     0),
+       },
+};
+
+static SUNXI_CCU_GATE(bus_audio_hub_clk, "bus-audio-hub", "apb1", 0xa6c, BIT(0), 0);
+
+/*
+ * There are OHCI 12M clock source selection bits for 2 USB 2.0 ports.
+ * We will force them to 0 (12M divided from 48M).
+ */
+#define SUN50I_H6_USB0_CLK_REG         0xa70
+#define SUN50I_H6_USB3_CLK_REG         0xa7c
+
+static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 0xa70, BIT(29), 0);
+
+static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 0xa74, BIT(29), 0);
+
+static SUNXI_CCU_GATE(usb_ohci3_clk, "usb-ohci3", "osc12M", 0xa7c, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy3_clk, "usb-phy3", "osc12M", 0xa7c, BIT(29), 0);
+static SUNXI_CCU_GATE(usb_hsic_12m_clk, "usb-hsic-12M", "osc12M", 0xa7c, BIT(27), 0);
+static SUNXI_CCU_GATE(usb_hsic_clk, "usb-hsic", "pll-hsic", 0xa7c, BIT(26), 0);
+
+static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb3", 0xa8c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_ohci3_clk, "bus-ohci3", "ahb3", 0xa8c, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb3", 0xa8c, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_xhci_clk, "bus-xhci", "ahb3", 0xa8c, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_ehci3_clk, "bus-ehci3", "ahb3", 0xa8c, BIT(7), 0);
+static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb3", 0xa8c, BIT(8), 0);
+
+static CLK_FIXED_FACTOR(pcie_ref_100m_clk, "pcie-ref-100M",
+                       "pll-periph0-4x", 24, 1, 0);
+static SUNXI_CCU_GATE(pcie_ref_clk, "pcie-ref", "pcie-ref-100M",
+                     0xab0, BIT(31), 0);
+static SUNXI_CCU_GATE(pcie_ref_out_clk, "pcie-ref-out", "pcie-ref",
+                     0xab0, BIT(30), 0);
+
+static SUNXI_CCU_M_WITH_GATE(pcie_maxi_clk, "pcie-maxi",
+                            "pll-periph0", 0xab4,
+                            0, 4,      /* M */
+                            BIT(31),   /* gate */
+                            0);
+
+static SUNXI_CCU_M_WITH_GATE(pcie_aux_clk, "pcie-aux", "osc24M", 0xab8,
+                            0, 5,      /* M */
+                            BIT(31),   /* gate */
+                            0);
+
+static SUNXI_CCU_GATE(bus_pcie_clk, "bus-pcie", "psi-ahb1-ahb2",
+                     0xabc, BIT(0), 0);
+
+static const char * const hdmi_parents[] = { "pll-video0", "pll-video1",
+                                             "pll-video1-4x" };
+static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, 0xb00,
+                                0, 4,          /* M */
+                                24, 2,         /* mux */
+                                BIT(31),       /* gate */
+                                0);
+
+static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0xb04, BIT(31), 0);
+
+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 },
+};
+static struct ccu_mux hdmi_cec_clk = {
+       .enable         = BIT(31),
+
+       .mux            = {
+               .shift  = 24,
+               .width  = 2,
+
+               .fixed_predivs  = hdmi_cec_predivs,
+               .n_predivs      = ARRAY_SIZE(hdmi_cec_predivs),
+       },
+
+       .common         = {
+               .reg            = 0xb10,
+               .features       = CCU_FEATURE_VARIABLE_PREDIV,
+               .hw.init        = CLK_HW_INIT_PARENTS("hdmi-cec",
+                                                     hdmi_cec_parents,
+                                                     &ccu_mux_ops,
+                                                     0),
+       },
+};
+
+static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb3", 0xb1c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_tcon_top_clk, "bus-tcon-top", "ahb3",
+                     0xb5c, BIT(0), 0);
+
+static const char * const tcon_lcd0_parents[] = { "pll-video0",
+                                                 "pll-video0-4x",
+                                                 "pll-video1" };
+static SUNXI_CCU_MUX_WITH_GATE(tcon_lcd0_clk, "tcon-lcd0",
+                              tcon_lcd0_parents, 0xb60,
+                              24, 3,   /* mux */
+                              BIT(31), /* gate */
+                              0);
+
+static SUNXI_CCU_GATE(bus_tcon_lcd0_clk, "bus-tcon-lcd0", "ahb3",
+                     0xb7c, BIT(0), 0);
+
+static const char * const tcon_tv0_parents[] = { "pll-video0",
+                                                "pll-video0-4x",
+                                                "pll-video1",
+                                                "pll-video1-4x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
+                                 tcon_tv0_parents, 0xb80,
+                                 0, 4,         /* M */
+                                 8, 2,         /* P */
+                                 24, 3,        /* mux */
+                                 BIT(31),      /* gate */
+                                 0);
+
+static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb3",
+                     0xb9c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(csi_cci_clk, "csi-cci", "osc24M", 0xc00, BIT(0), 0);
+
+static const char * const csi_top_parents[] = { "pll-video0", "pll-ve",
+                                             "pll-periph0" };
+static const u8 csi_top_table[] = { 0, 2, 3 };
+static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_top_clk, "csi-top",
+                                      csi_top_parents, csi_top_table, 0xc04,
+                                      0, 4,    /* M */
+                                      24, 3,   /* mux */
+                                      BIT(31), /* gate */
+                                      0);
+
+static const char * const csi_mclk_parents[] = { "osc24M", "pll-video0",
+                                              "pll-periph0", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk",
+                                csi_mclk_parents, 0xc08,
+                                0, 5,          /* M */
+                                24, 3,         /* mux */
+                                BIT(31),       /* gate */
+                                0);
+
+static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi", "ahb3", 0xc2c, BIT(0), 0);
+
+static const char * const hdcp_parents[] = { "pll-periph0", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(hdcp_clk, "hdcp", hdcp_parents, 0xc40,
+                                0, 4,          /* M */
+                                24, 2,         /* mux */
+                                BIT(31),       /* gate */
+                                0);
+
+static SUNXI_CCU_GATE(bus_hdcp_clk, "bus-hdcp", "ahb3", 0xc4c, BIT(0), 0);
+
+/* Fixed factor clocks */
+static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 2, 1, 0);
+
+/*
+ * The divider of pll-audio is fixed to 8 now, as pll-audio-4x has a
+ * fixed post-divider 2.
+ */
+static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
+                       "pll-audio-base", 8, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
+                       "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
+                       "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
+
+static CLK_FIXED_FACTOR(pll_periph0_4x_clk, "pll-periph0-4x",
+                       "pll-periph0", 1, 4, 0);
+static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
+                       "pll-periph0", 1, 2, 0);
+
+static CLK_FIXED_FACTOR(pll_periph1_4x_clk, "pll-periph1-4x",
+                       "pll-periph1", 1, 4, 0);
+static CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x",
+                       "pll-periph1", 1, 2, 0);
+
+static CLK_FIXED_FACTOR(pll_video0_4x_clk, "pll-video0-4x",
+                       "pll-video0", 1, 4, CLK_SET_RATE_PARENT);
+
+static CLK_FIXED_FACTOR(pll_video1_4x_clk, "pll-video1-4x",
+                       "pll-video1", 1, 4, CLK_SET_RATE_PARENT);
+
+static struct ccu_common *sun50i_h6_ccu_clks[] = {
+       &pll_cpux_clk.common,
+       &pll_ddr0_clk.common,
+       &pll_periph0_clk.common,
+       &pll_periph1_clk.common,
+       &pll_gpu_clk.common,
+       &pll_video0_clk.common,
+       &pll_video1_clk.common,
+       &pll_ve_clk.common,
+       &pll_de_clk.common,
+       &pll_hsic_clk.common,
+       &pll_audio_base_clk.common,
+       &cpux_clk.common,
+       &axi_clk.common,
+       &cpux_apb_clk.common,
+       &psi_ahb1_ahb2_clk.common,
+       &ahb3_clk.common,
+       &apb1_clk.common,
+       &apb2_clk.common,
+       &mbus_clk.common,
+       &de_clk.common,
+       &bus_de_clk.common,
+       &deinterlace_clk.common,
+       &bus_deinterlace_clk.common,
+       &gpu_clk.common,
+       &bus_gpu_clk.common,
+       &ce_clk.common,
+       &bus_ce_clk.common,
+       &ve_clk.common,
+       &bus_ve_clk.common,
+       &emce_clk.common,
+       &bus_emce_clk.common,
+       &vp9_clk.common,
+       &bus_vp9_clk.common,
+       &bus_dma_clk.common,
+       &bus_msgbox_clk.common,
+       &bus_spinlock_clk.common,
+       &bus_hstimer_clk.common,
+       &avs_clk.common,
+       &bus_dbg_clk.common,
+       &bus_psi_clk.common,
+       &bus_pwm_clk.common,
+       &bus_iommu_clk.common,
+       &dram_clk.common,
+       &mbus_dma_clk.common,
+       &mbus_ve_clk.common,
+       &mbus_ce_clk.common,
+       &mbus_ts_clk.common,
+       &mbus_nand_clk.common,
+       &mbus_csi_clk.common,
+       &mbus_deinterlace_clk.common,
+       &bus_dram_clk.common,
+       &nand0_clk.common,
+       &nand1_clk.common,
+       &bus_nand_clk.common,
+       &mmc0_clk.common,
+       &mmc1_clk.common,
+       &mmc2_clk.common,
+       &bus_mmc0_clk.common,
+       &bus_mmc1_clk.common,
+       &bus_mmc2_clk.common,
+       &bus_uart0_clk.common,
+       &bus_uart1_clk.common,
+       &bus_uart2_clk.common,
+       &bus_uart3_clk.common,
+       &bus_i2c0_clk.common,
+       &bus_i2c1_clk.common,
+       &bus_i2c2_clk.common,
+       &bus_i2c3_clk.common,
+       &bus_scr0_clk.common,
+       &bus_scr1_clk.common,
+       &spi0_clk.common,
+       &spi1_clk.common,
+       &bus_spi0_clk.common,
+       &bus_spi1_clk.common,
+       &bus_emac_clk.common,
+       &ts_clk.common,
+       &bus_ts_clk.common,
+       &ir_tx_clk.common,
+       &bus_ir_tx_clk.common,
+       &bus_ths_clk.common,
+       &i2s3_clk.common,
+       &i2s0_clk.common,
+       &i2s1_clk.common,
+       &i2s2_clk.common,
+       &bus_i2s0_clk.common,
+       &bus_i2s1_clk.common,
+       &bus_i2s2_clk.common,
+       &bus_i2s3_clk.common,
+       &spdif_clk.common,
+       &bus_spdif_clk.common,
+       &dmic_clk.common,
+       &bus_dmic_clk.common,
+       &audio_hub_clk.common,
+       &bus_audio_hub_clk.common,
+       &usb_ohci0_clk.common,
+       &usb_phy0_clk.common,
+       &usb_phy1_clk.common,
+       &usb_ohci3_clk.common,
+       &usb_phy3_clk.common,
+       &usb_hsic_12m_clk.common,
+       &usb_hsic_clk.common,
+       &bus_ohci0_clk.common,
+       &bus_ohci3_clk.common,
+       &bus_ehci0_clk.common,
+       &bus_xhci_clk.common,
+       &bus_ehci3_clk.common,
+       &bus_otg_clk.common,
+       &pcie_ref_clk.common,
+       &pcie_ref_out_clk.common,
+       &pcie_maxi_clk.common,
+       &pcie_aux_clk.common,
+       &bus_pcie_clk.common,
+       &hdmi_clk.common,
+       &hdmi_slow_clk.common,
+       &hdmi_cec_clk.common,
+       &bus_hdmi_clk.common,
+       &bus_tcon_top_clk.common,
+       &tcon_lcd0_clk.common,
+       &bus_tcon_lcd0_clk.common,
+       &tcon_tv0_clk.common,
+       &bus_tcon_tv0_clk.common,
+       &csi_cci_clk.common,
+       &csi_top_clk.common,
+       &csi_mclk_clk.common,
+       &bus_csi_clk.common,
+       &hdcp_clk.common,
+       &bus_hdcp_clk.common,
+};
+
+static struct clk_hw_onecell_data sun50i_h6_hw_clks = {
+       .hws    = {
+               [CLK_OSC12M]            = &osc12M_clk.hw,
+               [CLK_PLL_CPUX]          = &pll_cpux_clk.common.hw,
+               [CLK_PLL_DDR0]          = &pll_ddr0_clk.common.hw,
+               [CLK_PLL_PERIPH0]       = &pll_periph0_clk.common.hw,
+               [CLK_PLL_PERIPH0_2X]    = &pll_periph0_2x_clk.hw,
+               [CLK_PLL_PERIPH0_4X]    = &pll_periph0_4x_clk.hw,
+               [CLK_PLL_PERIPH1]       = &pll_periph1_clk.common.hw,
+               [CLK_PLL_PERIPH1_2X]    = &pll_periph1_2x_clk.hw,
+               [CLK_PLL_PERIPH1_4X]    = &pll_periph1_4x_clk.hw,
+               [CLK_PLL_GPU]           = &pll_gpu_clk.common.hw,
+               [CLK_PLL_VIDEO0]        = &pll_video0_clk.common.hw,
+               [CLK_PLL_VIDEO0_4X]     = &pll_video0_4x_clk.hw,
+               [CLK_PLL_VIDEO1]        = &pll_video1_clk.common.hw,
+               [CLK_PLL_VIDEO1_4X]     = &pll_video1_4x_clk.hw,
+               [CLK_PLL_VE]            = &pll_ve_clk.common.hw,
+               [CLK_PLL_DE]            = &pll_de_clk.common.hw,
+               [CLK_PLL_HSIC]          = &pll_hsic_clk.common.hw,
+               [CLK_PLL_AUDIO_BASE]    = &pll_audio_base_clk.common.hw,
+               [CLK_PLL_AUDIO]         = &pll_audio_clk.hw,
+               [CLK_PLL_AUDIO_2X]      = &pll_audio_2x_clk.hw,
+               [CLK_PLL_AUDIO_4X]      = &pll_audio_4x_clk.hw,
+               [CLK_CPUX]              = &cpux_clk.common.hw,
+               [CLK_AXI]               = &axi_clk.common.hw,
+               [CLK_CPUX_APB]          = &cpux_apb_clk.common.hw,
+               [CLK_PSI_AHB1_AHB2]     = &psi_ahb1_ahb2_clk.common.hw,
+               [CLK_AHB3]              = &ahb3_clk.common.hw,
+               [CLK_APB1]              = &apb1_clk.common.hw,
+               [CLK_APB2]              = &apb2_clk.common.hw,
+               [CLK_MBUS]              = &mbus_clk.common.hw,
+               [CLK_DE]                = &de_clk.common.hw,
+               [CLK_BUS_DE]            = &bus_de_clk.common.hw,
+               [CLK_DEINTERLACE]       = &deinterlace_clk.common.hw,
+               [CLK_BUS_DEINTERLACE]   = &bus_deinterlace_clk.common.hw,
+               [CLK_GPU]               = &gpu_clk.common.hw,
+               [CLK_BUS_GPU]           = &bus_gpu_clk.common.hw,
+               [CLK_CE]                = &ce_clk.common.hw,
+               [CLK_BUS_CE]            = &bus_ce_clk.common.hw,
+               [CLK_VE]                = &ve_clk.common.hw,
+               [CLK_BUS_VE]            = &bus_ve_clk.common.hw,
+               [CLK_EMCE]              = &emce_clk.common.hw,
+               [CLK_BUS_EMCE]          = &bus_emce_clk.common.hw,
+               [CLK_VP9]               = &vp9_clk.common.hw,
+               [CLK_BUS_VP9]           = &bus_vp9_clk.common.hw,
+               [CLK_BUS_DMA]           = &bus_dma_clk.common.hw,
+               [CLK_BUS_MSGBOX]        = &bus_msgbox_clk.common.hw,
+               [CLK_BUS_SPINLOCK]      = &bus_spinlock_clk.common.hw,
+               [CLK_BUS_HSTIMER]       = &bus_hstimer_clk.common.hw,
+               [CLK_AVS]               = &avs_clk.common.hw,
+               [CLK_BUS_DBG]           = &bus_dbg_clk.common.hw,
+               [CLK_BUS_PSI]           = &bus_psi_clk.common.hw,
+               [CLK_BUS_PWM]           = &bus_pwm_clk.common.hw,
+               [CLK_BUS_IOMMU]         = &bus_iommu_clk.common.hw,
+               [CLK_DRAM]              = &dram_clk.common.hw,
+               [CLK_MBUS_DMA]          = &mbus_dma_clk.common.hw,
+               [CLK_MBUS_VE]           = &mbus_ve_clk.common.hw,
+               [CLK_MBUS_CE]           = &mbus_ce_clk.common.hw,
+               [CLK_MBUS_TS]           = &mbus_ts_clk.common.hw,
+               [CLK_MBUS_NAND]         = &mbus_nand_clk.common.hw,
+               [CLK_MBUS_CSI]          = &mbus_csi_clk.common.hw,
+               [CLK_MBUS_DEINTERLACE]  = &mbus_deinterlace_clk.common.hw,
+               [CLK_BUS_DRAM]          = &bus_dram_clk.common.hw,
+               [CLK_NAND0]             = &nand0_clk.common.hw,
+               [CLK_NAND1]             = &nand1_clk.common.hw,
+               [CLK_BUS_NAND]          = &bus_nand_clk.common.hw,
+               [CLK_MMC0]              = &mmc0_clk.common.hw,
+               [CLK_MMC1]              = &mmc1_clk.common.hw,
+               [CLK_MMC2]              = &mmc2_clk.common.hw,
+               [CLK_BUS_MMC0]          = &bus_mmc0_clk.common.hw,
+               [CLK_BUS_MMC1]          = &bus_mmc1_clk.common.hw,
+               [CLK_BUS_MMC2]          = &bus_mmc2_clk.common.hw,
+               [CLK_BUS_UART0]         = &bus_uart0_clk.common.hw,
+               [CLK_BUS_UART1]         = &bus_uart1_clk.common.hw,
+               [CLK_BUS_UART2]         = &bus_uart2_clk.common.hw,
+               [CLK_BUS_UART3]         = &bus_uart3_clk.common.hw,
+               [CLK_BUS_I2C0]          = &bus_i2c0_clk.common.hw,
+               [CLK_BUS_I2C1]          = &bus_i2c1_clk.common.hw,
+               [CLK_BUS_I2C2]          = &bus_i2c2_clk.common.hw,
+               [CLK_BUS_I2C3]          = &bus_i2c3_clk.common.hw,
+               [CLK_BUS_SCR0]          = &bus_scr0_clk.common.hw,
+               [CLK_BUS_SCR1]          = &bus_scr1_clk.common.hw,
+               [CLK_SPI0]              = &spi0_clk.common.hw,
+               [CLK_SPI1]              = &spi1_clk.common.hw,
+               [CLK_BUS_SPI0]          = &bus_spi0_clk.common.hw,
+               [CLK_BUS_SPI1]          = &bus_spi1_clk.common.hw,
+               [CLK_BUS_EMAC]          = &bus_emac_clk.common.hw,
+               [CLK_TS]                = &ts_clk.common.hw,
+               [CLK_BUS_TS]            = &bus_ts_clk.common.hw,
+               [CLK_IR_TX]             = &ir_tx_clk.common.hw,
+               [CLK_BUS_IR_TX]         = &bus_ir_tx_clk.common.hw,
+               [CLK_BUS_THS]           = &bus_ths_clk.common.hw,
+               [CLK_I2S3]              = &i2s3_clk.common.hw,
+               [CLK_I2S0]              = &i2s0_clk.common.hw,
+               [CLK_I2S1]              = &i2s1_clk.common.hw,
+               [CLK_I2S2]              = &i2s2_clk.common.hw,
+               [CLK_BUS_I2S0]          = &bus_i2s0_clk.common.hw,
+               [CLK_BUS_I2S1]          = &bus_i2s1_clk.common.hw,
+               [CLK_BUS_I2S2]          = &bus_i2s2_clk.common.hw,
+               [CLK_BUS_I2S3]          = &bus_i2s3_clk.common.hw,
+               [CLK_SPDIF]             = &spdif_clk.common.hw,
+               [CLK_BUS_SPDIF]         = &bus_spdif_clk.common.hw,
+               [CLK_DMIC]              = &dmic_clk.common.hw,
+               [CLK_BUS_DMIC]          = &bus_dmic_clk.common.hw,
+               [CLK_AUDIO_HUB]         = &audio_hub_clk.common.hw,
+               [CLK_BUS_AUDIO_HUB]     = &bus_audio_hub_clk.common.hw,
+               [CLK_USB_OHCI0]         = &usb_ohci0_clk.common.hw,
+               [CLK_USB_PHY0]          = &usb_phy0_clk.common.hw,
+               [CLK_USB_PHY1]          = &usb_phy1_clk.common.hw,
+               [CLK_USB_OHCI3]         = &usb_ohci3_clk.common.hw,
+               [CLK_USB_PHY3]          = &usb_phy3_clk.common.hw,
+               [CLK_USB_HSIC_12M]      = &usb_hsic_12m_clk.common.hw,
+               [CLK_USB_HSIC]          = &usb_hsic_clk.common.hw,
+               [CLK_BUS_OHCI0]         = &bus_ohci0_clk.common.hw,
+               [CLK_BUS_OHCI3]         = &bus_ohci3_clk.common.hw,
+               [CLK_BUS_EHCI0]         = &bus_ehci0_clk.common.hw,
+               [CLK_BUS_XHCI]          = &bus_xhci_clk.common.hw,
+               [CLK_BUS_EHCI3]         = &bus_ehci3_clk.common.hw,
+               [CLK_BUS_OTG]           = &bus_otg_clk.common.hw,
+               [CLK_PCIE_REF_100M]     = &pcie_ref_100m_clk.hw,
+               [CLK_PCIE_REF]          = &pcie_ref_clk.common.hw,
+               [CLK_PCIE_REF_OUT]      = &pcie_ref_out_clk.common.hw,
+               [CLK_PCIE_MAXI]         = &pcie_maxi_clk.common.hw,
+               [CLK_PCIE_AUX]          = &pcie_aux_clk.common.hw,
+               [CLK_BUS_PCIE]          = &bus_pcie_clk.common.hw,
+               [CLK_HDMI]              = &hdmi_clk.common.hw,
+               [CLK_HDMI_SLOW]         = &hdmi_slow_clk.common.hw,
+               [CLK_HDMI_CEC]          = &hdmi_cec_clk.common.hw,
+               [CLK_BUS_HDMI]          = &bus_hdmi_clk.common.hw,
+               [CLK_BUS_TCON_TOP]      = &bus_tcon_top_clk.common.hw,
+               [CLK_TCON_LCD0]         = &tcon_lcd0_clk.common.hw,
+               [CLK_BUS_TCON_LCD0]     = &bus_tcon_lcd0_clk.common.hw,
+               [CLK_TCON_TV0]          = &tcon_tv0_clk.common.hw,
+               [CLK_BUS_TCON_TV0]      = &bus_tcon_tv0_clk.common.hw,
+               [CLK_CSI_CCI]           = &csi_cci_clk.common.hw,
+               [CLK_CSI_TOP]           = &csi_top_clk.common.hw,
+               [CLK_CSI_MCLK]          = &csi_mclk_clk.common.hw,
+               [CLK_BUS_CSI]           = &bus_csi_clk.common.hw,
+               [CLK_HDCP]              = &hdcp_clk.common.hw,
+               [CLK_BUS_HDCP]          = &bus_hdcp_clk.common.hw,
+       },
+       .num = CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun50i_h6_ccu_resets[] = {
+       [RST_MBUS]              = { 0x540, BIT(30) },
+
+       [RST_BUS_DE]            = { 0x60c, BIT(16) },
+       [RST_BUS_DEINTERLACE]   = { 0x62c, BIT(16) },
+       [RST_BUS_GPU]           = { 0x67c, BIT(16) },
+       [RST_BUS_CE]            = { 0x68c, BIT(16) },
+       [RST_BUS_VE]            = { 0x69c, BIT(16) },
+       [RST_BUS_EMCE]          = { 0x6bc, BIT(16) },
+       [RST_BUS_VP9]           = { 0x6cc, BIT(16) },
+       [RST_BUS_DMA]           = { 0x70c, BIT(16) },
+       [RST_BUS_MSGBOX]        = { 0x71c, BIT(16) },
+       [RST_BUS_SPINLOCK]      = { 0x72c, BIT(16) },
+       [RST_BUS_HSTIMER]       = { 0x73c, BIT(16) },
+       [RST_BUS_DBG]           = { 0x78c, BIT(16) },
+       [RST_BUS_PSI]           = { 0x79c, BIT(16) },
+       [RST_BUS_PWM]           = { 0x7ac, BIT(16) },
+       [RST_BUS_IOMMU]         = { 0x7bc, BIT(16) },
+       [RST_BUS_DRAM]          = { 0x80c, BIT(16) },
+       [RST_BUS_NAND]          = { 0x82c, BIT(16) },
+       [RST_BUS_MMC0]          = { 0x84c, BIT(16) },
+       [RST_BUS_MMC1]          = { 0x84c, BIT(17) },
+       [RST_BUS_MMC2]          = { 0x84c, BIT(18) },
+       [RST_BUS_UART0]         = { 0x90c, BIT(16) },
+       [RST_BUS_UART1]         = { 0x90c, BIT(17) },
+       [RST_BUS_UART2]         = { 0x90c, BIT(18) },
+       [RST_BUS_UART3]         = { 0x90c, BIT(19) },
+       [RST_BUS_I2C0]          = { 0x91c, BIT(16) },
+       [RST_BUS_I2C1]          = { 0x91c, BIT(17) },
+       [RST_BUS_I2C2]          = { 0x91c, BIT(18) },
+       [RST_BUS_I2C3]          = { 0x91c, BIT(19) },
+       [RST_BUS_SCR0]          = { 0x93c, BIT(16) },
+       [RST_BUS_SCR1]          = { 0x93c, BIT(17) },
+       [RST_BUS_SPI0]          = { 0x96c, BIT(16) },
+       [RST_BUS_SPI1]          = { 0x96c, BIT(17) },
+       [RST_BUS_EMAC]          = { 0x97c, BIT(16) },
+       [RST_BUS_TS]            = { 0x9bc, BIT(16) },
+       [RST_BUS_IR_TX]         = { 0x9cc, BIT(16) },
+       [RST_BUS_THS]           = { 0x9fc, BIT(16) },
+       [RST_BUS_I2S0]          = { 0xa1c, BIT(16) },
+       [RST_BUS_I2S1]          = { 0xa1c, BIT(17) },
+       [RST_BUS_I2S2]          = { 0xa1c, BIT(18) },
+       [RST_BUS_I2S3]          = { 0xa1c, BIT(19) },
+       [RST_BUS_SPDIF]         = { 0xa2c, BIT(16) },
+       [RST_BUS_DMIC]          = { 0xa4c, BIT(16) },
+       [RST_BUS_AUDIO_HUB]     = { 0xa6c, BIT(16) },
+
+       [RST_USB_PHY0]          = { 0xa70, BIT(30) },
+       [RST_USB_PHY1]          = { 0xa74, BIT(30) },
+       [RST_USB_PHY3]          = { 0xa7c, BIT(30) },
+       [RST_USB_HSIC]          = { 0xa7c, BIT(28) },
+
+       [RST_BUS_OHCI0]         = { 0xa8c, BIT(16) },
+       [RST_BUS_OHCI3]         = { 0xa8c, BIT(19) },
+       [RST_BUS_EHCI0]         = { 0xa8c, BIT(20) },
+       [RST_BUS_XHCI]          = { 0xa8c, BIT(21) },
+       [RST_BUS_EHCI3]         = { 0xa8c, BIT(23) },
+       [RST_BUS_OTG]           = { 0xa8c, BIT(24) },
+       [RST_BUS_PCIE]          = { 0xabc, BIT(16) },
+
+       [RST_PCIE_POWERUP]      = { 0xabc, BIT(17) },
+
+       [RST_BUS_HDMI]          = { 0xb1c, BIT(16) },
+       [RST_BUS_HDMI_SUB]      = { 0xb1c, BIT(17) },
+       [RST_BUS_TCON_TOP]      = { 0xb5c, BIT(16) },
+       [RST_BUS_TCON_LCD0]     = { 0xb7c, BIT(16) },
+       [RST_BUS_TCON_TV0]      = { 0xb9c, BIT(16) },
+       [RST_BUS_CSI]           = { 0xc2c, BIT(16) },
+       [RST_BUS_HDCP]          = { 0xc4c, BIT(16) },
+};
+
+static const struct sunxi_ccu_desc sun50i_h6_ccu_desc = {
+       .ccu_clks       = sun50i_h6_ccu_clks,
+       .num_ccu_clks   = ARRAY_SIZE(sun50i_h6_ccu_clks),
+
+       .hw_clks        = &sun50i_h6_hw_clks,
+
+       .resets         = sun50i_h6_ccu_resets,
+       .num_resets     = ARRAY_SIZE(sun50i_h6_ccu_resets),
+};
+
+static const u32 pll_regs[] = {
+       SUN50I_H6_PLL_CPUX_REG,
+       SUN50I_H6_PLL_DDR0_REG,
+       SUN50I_H6_PLL_PERIPH0_REG,
+       SUN50I_H6_PLL_PERIPH1_REG,
+       SUN50I_H6_PLL_GPU_REG,
+       SUN50I_H6_PLL_VIDEO0_REG,
+       SUN50I_H6_PLL_VIDEO1_REG,
+       SUN50I_H6_PLL_VE_REG,
+       SUN50I_H6_PLL_DE_REG,
+       SUN50I_H6_PLL_HSIC_REG,
+       SUN50I_H6_PLL_AUDIO_REG,
+};
+
+static const u32 pll_video_regs[] = {
+       SUN50I_H6_PLL_VIDEO0_REG,
+       SUN50I_H6_PLL_VIDEO1_REG,
+};
+
+static const u32 usb2_clk_regs[] = {
+       SUN50I_H6_USB0_CLK_REG,
+       SUN50I_H6_USB3_CLK_REG,
+};
+
+static int sun50i_h6_ccu_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       void __iomem *reg;
+       u32 val;
+       int i;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       reg = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(reg))
+               return PTR_ERR(reg);
+
+       /* Enable the lock bits on all PLLs */
+       for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
+               val = readl(reg + pll_regs[i]);
+               val |= BIT(29);
+               writel(val, reg + pll_regs[i]);
+       }
+
+       /*
+        * Force the output divider of video PLLs to 0.
+        *
+        * See the comment before pll-video0 definition for the reason.
+        */
+       for (i = 0; i < ARRAY_SIZE(pll_video_regs); i++) {
+               val = readl(reg + pll_video_regs[i]);
+               val &= ~BIT(0);
+               writel(val, reg + pll_video_regs[i]);
+       }
+
+       /*
+        * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz)
+        *
+        * This clock mux is still mysterious, and the code just enforces
+        * it to have a valid clock parent.
+        */
+       for (i = 0; i < ARRAY_SIZE(usb2_clk_regs); i++) {
+               val = readl(reg + usb2_clk_regs[i]);
+               val &= ~GENMASK(25, 24);
+               writel (val, reg + usb2_clk_regs[i]);
+       }
+
+       /*
+        * Force the post-divider of pll-audio to 8 and the output divider
+        * of it to 1, to make the clock name represents the real frequency.
+        */
+       val = readl(reg + SUN50I_H6_PLL_AUDIO_REG);
+       val &= ~(GENMASK(21, 16) | BIT(0));
+       writel(val | (7 << 16), reg + SUN50I_H6_PLL_AUDIO_REG);
+
+       return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc);
+}
+
+static const struct of_device_id sun50i_h6_ccu_ids[] = {
+       { .compatible = "allwinner,sun50i-h6-ccu" },
+       { }
+};
+
+static struct platform_driver sun50i_h6_ccu_driver = {
+       .probe  = sun50i_h6_ccu_probe,
+       .driver = {
+               .name   = "sun50i-h6-ccu",
+               .of_match_table = sun50i_h6_ccu_ids,
+       },
+};
+builtin_platform_driver(sun50i_h6_ccu_driver);
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.h b/drivers/clk/sunxi-ng/ccu-sun50i-h6.h
new file mode 100644 (file)
index 0000000..2ccfe44
--- /dev/null
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2016 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#ifndef _CCU_SUN50I_H6_H_
+#define _CCU_SUN50I_H6_H_
+
+#include <dt-bindings/clock/sun50i-h6-ccu.h>
+#include <dt-bindings/reset/sun50i-h6-ccu.h>
+
+#define CLK_OSC12M             0
+#define CLK_PLL_CPUX           1
+#define CLK_PLL_DDR0           2
+
+/* PLL_PERIPH0 exported for PRCM */
+
+#define CLK_PLL_PERIPH0_2X     4
+#define CLK_PLL_PERIPH0_4X     5
+#define CLK_PLL_PERIPH1                6
+#define CLK_PLL_PERIPH1_2X     7
+#define CLK_PLL_PERIPH1_4X     8
+#define CLK_PLL_GPU            9
+#define CLK_PLL_VIDEO0         10
+#define CLK_PLL_VIDEO0_4X      11
+#define CLK_PLL_VIDEO1         12
+#define CLK_PLL_VIDEO1_4X      13
+#define CLK_PLL_VE             14
+#define CLK_PLL_DE             15
+#define CLK_PLL_HSIC           16
+#define CLK_PLL_AUDIO_BASE     17
+#define CLK_PLL_AUDIO          18
+#define CLK_PLL_AUDIO_2X       19
+#define CLK_PLL_AUDIO_4X       20
+
+/* CPUX clock exported for DVFS */
+
+#define CLK_AXI                        22
+#define CLK_CPUX_APB           23
+#define CLK_PSI_AHB1_AHB2      24
+#define CLK_AHB3               25
+
+/* APB1 clock exported for PIO */
+
+#define CLK_APB2               27
+#define CLK_MBUS               28
+
+/* All module clocks and bus gates are exported except DRAM */
+
+#define CLK_DRAM               52
+
+#define CLK_BUS_DRAM           60
+
+#define CLK_NUMBER             (CLK_BUS_HDCP + 1)
+
+#endif /* _CCU_SUN50I_H6_H_ */
index 29bc0566b776e7444f8a07c9a8660073a1ddadb8..77ed0b0ba6819d94317e12f31ac25896143e2a77 100644 (file)
@@ -69,17 +69,18 @@ static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
                                       BIT(28), /* lock */
                                       CLK_SET_RATE_UNGATE);
 
-static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video",
-                                       "osc24M", 0x0010,
-                                       8, 7,           /* N */
-                                       0, 4,           /* M */
-                                       BIT(24),        /* frac enable */
-                                       BIT(25),        /* frac select */
-                                       270000000,      /* frac rate 0 */
-                                       297000000,      /* frac rate 1 */
-                                       BIT(31),        /* gate */
-                                       BIT(28),        /* lock */
-                                       CLK_SET_RATE_UNGATE);
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video_clk, "pll-video",
+                                           "osc24M", 0x0010,
+                                           192000000,  /* Minimum rate */
+                                           8, 7,       /* N */
+                                           0, 4,       /* M */
+                                           BIT(24),    /* frac enable */
+                                           BIT(25),    /* frac select */
+                                           270000000,  /* frac rate 0 */
+                                           297000000,  /* frac rate 1 */
+                                           BIT(31),    /* gate */
+                                           BIT(28),    /* lock */
+                                           CLK_SET_RATE_UNGATE);
 
 static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
                                        "osc24M", 0x0018,
@@ -451,11 +452,13 @@ 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 tcon_parents[] = { "pll-video" };
 static SUNXI_CCU_M_WITH_MUX_GATE(tcon_clk, "tcon", tcon_parents,
-                                0x118, 0, 4, 24, 3, BIT(31), 0);
+                                0x118, 0, 4, 24, 3, BIT(31),
+                                CLK_SET_RATE_PARENT);
 
 static const char * const tve_parents[] = { "pll-de", "pll-periph1" };
 static SUNXI_CCU_M_WITH_MUX_GATE(tve_clk, "tve", tve_parents,
@@ -486,7 +489,8 @@ static SUNXI_CCU_GATE(avs_clk,              "avs",          "osc24M",
 
 static const char * const hdmi_parents[] = { "pll-video" };
 static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,
-                                0x150, 0, 4, 24, 2, BIT(31), 0);
+                                0x150, 0, 4, 24, 2, BIT(31),
+                                CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_GATE(hdmi_ddc_clk,    "hdmi-ddc",     "osc24M",
                      0x154, BIT(31), 0);
index 1b4baea37d810351d541d0b0a91d8a78a8524a95..73d7392c968ce3d1b433ed8f9113dfd89c9018a0 100644 (file)
@@ -26,7 +26,9 @@
 #define CLK_PLL_AUDIO_2X       3
 #define CLK_PLL_AUDIO_4X       4
 #define CLK_PLL_AUDIO_8X       5
-#define CLK_PLL_VIDEO          6
+
+/* PLL_VIDEO is exported */
+
 #define CLK_PLL_VE             7
 #define CLK_PLL_DDR            8
 
index e58c95787f94c7c6cb7c1ca96330d4680940bc74..ebd9436d2c7cd382ed86a3bee1957a5db48b7530 100644 (file)
@@ -20,6 +20,18 @@ struct _ccu_nkmp {
        unsigned long   p, min_p, max_p;
 };
 
+static unsigned long ccu_nkmp_calc_rate(unsigned long parent,
+                                       unsigned long n, unsigned long k,
+                                       unsigned long m, unsigned long p)
+{
+       u64 rate = parent;
+
+       rate *= n * k;
+       do_div(rate, m * p);
+
+       return rate;
+}
+
 static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate,
                               struct _ccu_nkmp *nkmp)
 {
@@ -33,7 +45,9 @@ static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate,
                                for (_p = nkmp->min_p; _p <= nkmp->max_p; _p <<= 1) {
                                        unsigned long tmp_rate;
 
-                                       tmp_rate = parent * _n * _k / (_m * _p);
+                                       tmp_rate = ccu_nkmp_calc_rate(parent,
+                                                                     _n, _k,
+                                                                     _m, _p);
 
                                        if (tmp_rate > rate)
                                                continue;
@@ -81,7 +95,7 @@ static unsigned long ccu_nkmp_recalc_rate(struct clk_hw *hw,
                                        unsigned long parent_rate)
 {
        struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
-       unsigned long n, m, k, p;
+       unsigned long n, m, k, p, rate;
        u32 reg;
 
        reg = readl(nkmp->common.base + nkmp->common.reg);
@@ -107,7 +121,11 @@ static unsigned long ccu_nkmp_recalc_rate(struct clk_hw *hw,
        p = reg >> nkmp->p.shift;
        p &= (1 << nkmp->p.width) - 1;
 
-       return (parent_rate * n * k >> p) / m;
+       rate = ccu_nkmp_calc_rate(parent_rate, n, k, m, 1 << p);
+       if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
+               rate /= nkmp->fixed_post_div;
+
+       return rate;
 }
 
 static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -116,6 +134,9 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
        struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
        struct _ccu_nkmp _nkmp;
 
+       if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
+               rate *= nkmp->fixed_post_div;
+
        _nkmp.min_n = nkmp->n.min ?: 1;
        _nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width;
        _nkmp.min_k = nkmp->k.min ?: 1;
@@ -127,17 +148,26 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
 
        ccu_nkmp_find_best(*parent_rate, rate, &_nkmp);
 
-       return *parent_rate * _nkmp.n * _nkmp.k / (_nkmp.m * _nkmp.p);
+       rate = ccu_nkmp_calc_rate(*parent_rate, _nkmp.n, _nkmp.k,
+                                 _nkmp.m, _nkmp.p);
+       if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
+               rate = rate / nkmp->fixed_post_div;
+
+       return rate;
 }
 
 static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
                           unsigned long parent_rate)
 {
        struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
+       u32 n_mask, k_mask, m_mask, p_mask;
        struct _ccu_nkmp _nkmp;
        unsigned long flags;
        u32 reg;
 
+       if (nkmp->common.features & CCU_FEATURE_FIXED_POSTDIV)
+               rate = rate * nkmp->fixed_post_div;
+
        _nkmp.min_n = nkmp->n.min ?: 1;
        _nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width;
        _nkmp.min_k = nkmp->k.min ?: 1;
@@ -149,18 +179,20 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
 
        ccu_nkmp_find_best(parent_rate, rate, &_nkmp);
 
+       n_mask = GENMASK(nkmp->n.width + nkmp->n.shift - 1, nkmp->n.shift);
+       k_mask = GENMASK(nkmp->k.width + nkmp->k.shift - 1, nkmp->k.shift);
+       m_mask = GENMASK(nkmp->m.width + nkmp->m.shift - 1, nkmp->m.shift);
+       p_mask = GENMASK(nkmp->p.width + nkmp->p.shift - 1, nkmp->p.shift);
+
        spin_lock_irqsave(nkmp->common.lock, flags);
 
        reg = readl(nkmp->common.base + nkmp->common.reg);
-       reg &= ~GENMASK(nkmp->n.width + nkmp->n.shift - 1, nkmp->n.shift);
-       reg &= ~GENMASK(nkmp->k.width + nkmp->k.shift - 1, nkmp->k.shift);
-       reg &= ~GENMASK(nkmp->m.width + nkmp->m.shift - 1, nkmp->m.shift);
-       reg &= ~GENMASK(nkmp->p.width + nkmp->p.shift - 1, nkmp->p.shift);
-
-       reg |= (_nkmp.n - nkmp->n.offset) << nkmp->n.shift;
-       reg |= (_nkmp.k - nkmp->k.offset) << nkmp->k.shift;
-       reg |= (_nkmp.m - nkmp->m.offset) << nkmp->m.shift;
-       reg |= ilog2(_nkmp.p) << nkmp->p.shift;
+       reg &= ~(n_mask | k_mask | m_mask | p_mask);
+
+       reg |= ((_nkmp.n - nkmp->n.offset) << nkmp->n.shift) & n_mask;
+       reg |= ((_nkmp.k - nkmp->k.offset) << nkmp->k.shift) & k_mask;
+       reg |= ((_nkmp.m - nkmp->m.offset) << nkmp->m.shift) & m_mask;
+       reg |= (ilog2(_nkmp.p) << nkmp->p.shift) & p_mask;
 
        writel(reg, nkmp->common.base + nkmp->common.reg);
 
index a82facbc61446d6c0cc36f4771c70aaf17090574..6940503e7fc4665d36fd889e3ec25fa258a14f40 100644 (file)
@@ -34,6 +34,8 @@ struct ccu_nkmp {
        struct ccu_div_internal         m;
        struct ccu_div_internal         p;
 
+       unsigned int            fixed_post_div;
+
        struct ccu_common       common;
 };
 
index a16de092bf94d408c960e347183bb3603d7f542c..4e2073307f34013e215fd827cc7048f6d4608bc6 100644 (file)
@@ -117,6 +117,13 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
        if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
                rate *= nm->fixed_post_div;
 
+       if (rate < nm->min_rate) {
+               rate = nm->min_rate;
+               if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
+                       rate /= nm->fixed_post_div;
+               return rate;
+       }
+
        if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) {
                if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
                        rate /= nm->fixed_post_div;
index eba586b4c7d0d5863d29e922b5241bb21c23177a..1d8b459c50b7c8d90e2085eeacc402c61989641c 100644 (file)
@@ -37,6 +37,7 @@ struct ccu_nm {
        struct ccu_sdm_internal         sdm;
 
        unsigned int            fixed_post_div;
+       unsigned int            min_rate;
 
        struct ccu_common       common;
 };
@@ -88,6 +89,32 @@ struct ccu_nm {
                },                                                      \
        }
 
+#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(_struct, _name, _parent,  \
+                                            _reg, _min_rate,           \
+                                            _nshift, _nwidth,          \
+                                            _mshift, _mwidth,          \
+                                            _frac_en, _frac_sel,       \
+                                            _frac_rate_0, _frac_rate_1,\
+                                            _gate, _lock, _flags)      \
+       struct ccu_nm _struct = {                                       \
+               .enable         = _gate,                                \
+               .lock           = _lock,                                \
+               .n              = _SUNXI_CCU_MULT(_nshift, _nwidth),    \
+               .m              = _SUNXI_CCU_DIV(_mshift, _mwidth),     \
+               .frac           = _SUNXI_CCU_FRAC(_frac_en, _frac_sel,  \
+                                                 _frac_rate_0,         \
+                                                 _frac_rate_1),        \
+               .min_rate       = _min_rate,                            \
+               .common         = {                                     \
+                       .reg            = _reg,                         \
+                       .features       = CCU_FEATURE_FRACTIONAL,       \
+                       .hw.init        = CLK_HW_INIT(_name,            \
+                                                     _parent,          \
+                                                     &ccu_nm_ops,      \
+                                                     _flags),          \
+               },                                                      \
+       }
+
 #define SUNXI_CCU_NM_WITH_GATE_LOCK(_struct, _name, _parent, _reg,     \
                                    _nshift, _nwidth,                   \
                                    _mshift, _mwidth,                   \
index 11a5066e5c27641113ef1fc4510159b987edb2f9..5234acd30e898e81754ec48f32ccd85db05bfc53 100644 (file)
@@ -515,7 +515,7 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
 
        init.name = "emc";
        init.ops = &tegra_clk_emc_ops;
-       init.flags = 0;
+       init.flags = CLK_IS_CRITICAL;
        init.parent_names = emc_parent_clk_names;
        init.num_parents = ARRAY_SIZE(emc_parent_clk_names);
 
index 7c369e21c91cb8d156f08dc6b1756ecd01a7e2dd..830d1c87fa7cb6d089ff95992a3e2592691801ea 100644 (file)
@@ -1151,6 +1151,8 @@ static const struct clk_ops tegra_clk_pllu_ops = {
        .enable = clk_pllu_enable,
        .disable = clk_pll_disable,
        .recalc_rate = clk_pll_recalc_rate,
+       .round_rate = clk_pll_round_rate,
+       .set_rate = clk_pll_set_rate,
 };
 
 static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
index c02711927d7912cac57e74194df6781adfa1764c..2acba2986bc60fbcba58700a1142c5c6f4bccfbf 100644 (file)
@@ -830,7 +830,7 @@ static struct tegra_periph_init_data gate_clks[] = {
        GATE("xusb_host", "xusb_host_src", 89, 0, tegra_clk_xusb_host, 0),
        GATE("xusb_ss", "xusb_ss_src", 156, 0, tegra_clk_xusb_ss, 0),
        GATE("xusb_dev", "xusb_dev_src", 95, 0, tegra_clk_xusb_dev, 0),
-       GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IGNORE_UNUSED),
+       GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IS_CRITICAL),
        GATE("sata_cold", "clk_m", 129, TEGRA_PERIPH_ON_APB, tegra_clk_sata_cold, 0),
        GATE("ispa", "isp", 23, 0, tegra_clk_ispa, 0),
        GATE("ispb", "isp", 3, 0, tegra_clk_ispb, 0),
index 10047107c1dc39720275537b5dddb86db4438e6a..89d6b47a27a8b067ae540029abd32ed5df635757 100644 (file)
@@ -125,7 +125,8 @@ static void __init tegra_sclk_init(void __iomem *clk_base,
                /* SCLK */
                dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks);
                if (dt_clk) {
-                       clk = clk_register_divider(NULL, "sclk", "sclk_mux", 0,
+                       clk = clk_register_divider(NULL, "sclk", "sclk_mux",
+                                               CLK_IS_CRITICAL,
                                                clk_base + SCLK_DIVIDER, 0, 8,
                                                0, &sysrate_lock);
                        *dt_clk = clk;
@@ -137,7 +138,8 @@ static void __init tegra_sclk_init(void __iomem *clk_base,
                        clk = tegra_clk_register_super_mux("sclk",
                                                gen_info->sclk_parents,
                                                gen_info->num_sclk_parents,
-                                               CLK_SET_RATE_PARENT,
+                                               CLK_SET_RATE_PARENT |
+                                               CLK_IS_CRITICAL,
                                                clk_base + SCLK_BURST_POLICY,
                                                0, 4, 0, 0, NULL);
                        *dt_clk = clk;
@@ -151,7 +153,7 @@ static void __init tegra_sclk_init(void __iomem *clk_base,
                                   clk_base + SYSTEM_CLK_RATE, 4, 2, 0,
                                   &sysrate_lock);
                clk = clk_register_gate(NULL, "hclk", "hclk_div",
-                               CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+                               CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
                                clk_base + SYSTEM_CLK_RATE,
                                7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
                *dt_clk = clk;
index 63087d17c3e2c31f0e4e29127a7885c8a510f924..5d5a22d529f563e08e2fe414e7c93c0b8c07e331 100644 (file)
@@ -955,8 +955,7 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
 
        /* PLLM */
        clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc,
-                            CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
-                            &pll_m_params, NULL);
+                            CLK_SET_RATE_GATE, &pll_m_params, NULL);
        clks[TEGRA114_CLK_PLL_M] = clk;
 
        /* PLLM_OUT1 */
@@ -1190,6 +1189,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
        { TEGRA114_CLK_XUSB_HS_SRC, TEGRA114_CLK_XUSB_SS_DIV2, 61200000, 0 },
        { TEGRA114_CLK_XUSB_FALCON_SRC, TEGRA114_CLK_PLL_P, 204000000, 0 },
        { TEGRA114_CLK_XUSB_HOST_SRC, TEGRA114_CLK_PLL_P, 102000000, 0 },
+       { TEGRA114_CLK_VDE, TEGRA114_CLK_CLK_MAX, 600000000, 0 },
        /* must be the last entry */
        { TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0 },
 };
index e81ea5b11577144da660ed3f0f9dd829d4486f98..50088e976611d98e3a96d42a525e8ae4b67ffec1 100644 (file)
@@ -1089,8 +1089,7 @@ static void __init tegra124_pll_init(void __iomem *clk_base,
 
        /* PLLM */
        clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc,
-                            CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
-                            &pll_m_params, NULL);
+                            CLK_SET_RATE_GATE, &pll_m_params, NULL);
        clk_register_clkdev(clk, "pll_m", NULL);
        clks[TEGRA124_CLK_PLL_M] = clk;
 
@@ -1099,7 +1098,7 @@ static void __init tegra124_pll_init(void __iomem *clk_base,
                                clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
                                8, 8, 1, NULL);
        clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
-                               clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
+                               clk_base + PLLM_OUT, 1, 0,
                                CLK_SET_RATE_PARENT, 0, NULL);
        clk_register_clkdev(clk, "pll_m_out1", NULL);
        clks[TEGRA124_CLK_PLL_M_OUT1] = clk;
@@ -1268,11 +1267,11 @@ static struct tegra_clk_init_table common_init_table[] __initdata = {
        { TEGRA124_CLK_I2S2, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
        { TEGRA124_CLK_I2S3, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
        { TEGRA124_CLK_I2S4, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
-       { TEGRA124_CLK_VDE, TEGRA124_CLK_PLL_P, 0, 0 },
+       { TEGRA124_CLK_VDE, TEGRA124_CLK_CLK_MAX, 600000000, 0 },
        { TEGRA124_CLK_HOST1X, TEGRA124_CLK_PLL_P, 136000000, 1 },
        { TEGRA124_CLK_DSIALP, TEGRA124_CLK_PLL_P, 68000000, 0 },
        { TEGRA124_CLK_DSIBLP, TEGRA124_CLK_PLL_P, 68000000, 0 },
-       { TEGRA124_CLK_SCLK, TEGRA124_CLK_PLL_P_OUT2, 102000000, 1 },
+       { TEGRA124_CLK_SCLK, TEGRA124_CLK_PLL_P_OUT2, 102000000, 0 },
        { TEGRA124_CLK_DFLL_SOC, TEGRA124_CLK_PLL_P, 51000000, 1 },
        { TEGRA124_CLK_DFLL_REF, TEGRA124_CLK_PLL_P, 51000000, 1 },
        { TEGRA124_CLK_PLL_C, TEGRA124_CLK_CLK_MAX, 768000000, 0 },
index cbd5a2e5c569bc2b3471eb4154aa42ee6e083f97..0ee56dd04cecce438244351929f1919525fed678 100644 (file)
@@ -576,6 +576,7 @@ static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = {
        [tegra_clk_afi] = { .dt_id = TEGRA20_CLK_AFI, .present = true },
        [tegra_clk_fuse] = { .dt_id = TEGRA20_CLK_FUSE, .present = true },
        [tegra_clk_kfuse] = { .dt_id = TEGRA20_CLK_KFUSE, .present = true },
+       [tegra_clk_emc] = { .dt_id = TEGRA20_CLK_EMC, .present = true },
 };
 
 static unsigned long tegra20_clk_measure_input_freq(void)
@@ -651,8 +652,7 @@ static void tegra20_pll_init(void)
 
        /* PLLM */
        clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, NULL,
-                           CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
-                           &pll_m_params, NULL);
+                           CLK_SET_RATE_GATE, &pll_m_params, NULL);
        clks[TEGRA20_CLK_PLL_M] = clk;
 
        /* PLLM_OUT1 */
@@ -660,7 +660,7 @@ static void tegra20_pll_init(void)
                                clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
                                8, 8, 1, NULL);
        clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
-                               clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
+                               clk_base + PLLM_OUT, 1, 0,
                                CLK_SET_RATE_PARENT, 0, NULL);
        clks[TEGRA20_CLK_PLL_M_OUT1] = clk;
 
@@ -723,7 +723,8 @@ static void tegra20_super_clk_init(void)
 
        /* SCLK */
        clk = tegra_clk_register_super_mux("sclk", sclk_parents,
-                             ARRAY_SIZE(sclk_parents), CLK_SET_RATE_PARENT,
+                             ARRAY_SIZE(sclk_parents),
+                             CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
                              clk_base + SCLK_BURST_POLICY, 0, 4, 0, 0, NULL);
        clks[TEGRA20_CLK_SCLK] = clk;
 
@@ -814,9 +815,6 @@ static void __init tegra20_periph_clk_init(void)
                               CLK_SET_RATE_NO_REPARENT,
                               clk_base + CLK_SOURCE_EMC,
                               30, 2, 0, &emc_lock);
-       clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0,
-                                   57, periph_clk_enb_refcnt);
-       clks[TEGRA20_CLK_EMC] = clk;
 
        clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
                                    &emc_lock);
@@ -1019,13 +1017,12 @@ static struct tegra_clk_init_table init_table[] __initdata = {
        { TEGRA20_CLK_PLL_P_OUT2, TEGRA20_CLK_CLK_MAX, 48000000, 1 },
        { TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1 },
        { TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1 },
-       { TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 1 },
-       { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 216000000, 1 },
-       { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 0, 1 },
-       { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 0, 1 },
-       { TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 1 },
+       { TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 0 },
+       { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 240000000, 0 },
+       { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 240000000, 0 },
+       { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 240000000, 0 },
+       { TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 0 },
        { TEGRA20_CLK_CSITE, TEGRA20_CLK_CLK_MAX, 0, 1 },
-       { TEGRA20_CLK_EMC, TEGRA20_CLK_CLK_MAX, 0, 1 },
        { TEGRA20_CLK_CCLK, TEGRA20_CLK_CLK_MAX, 0, 1 },
        { TEGRA20_CLK_UARTA, TEGRA20_CLK_PLL_P, 0, 0 },
        { TEGRA20_CLK_UARTB, TEGRA20_CLK_PLL_P, 0, 0 },
@@ -1051,6 +1048,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
        { TEGRA20_CLK_DISP2, TEGRA20_CLK_PLL_P, 600000000, 0 },
        { TEGRA20_CLK_GR2D, TEGRA20_CLK_PLL_C, 300000000, 0 },
        { TEGRA20_CLK_GR3D, TEGRA20_CLK_PLL_C, 300000000, 0 },
+       { TEGRA20_CLK_VDE, TEGRA20_CLK_CLK_MAX, 300000000, 0 },
        /* must be the last entry */
        { TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_CLK_MAX, 0, 0 },
 };
index 9e6260869eb94bee9e9b3c5f17dd7aedbc6c0a79..9fb5d51ccce47b487039fe6ef65fa3716bd73345 100644 (file)
 #include <linux/of_address.h>
 #include <linux/delay.h>
 #include <linux/export.h>
+#include <linux/mutex.h>
 #include <linux/clk/tegra.h>
 #include <dt-bindings/clock/tegra210-car.h>
 #include <dt-bindings/reset/tegra210-car.h>
 #include <linux/iopoll.h>
+#include <soc/tegra/pmc.h>
 
 #include "clk.h"
 #include "clk-id.h"
@@ -41,6 +43,7 @@
 #define CLK_SOURCE_CSITE 0x1d4
 #define CLK_SOURCE_EMC 0x19c
 #define CLK_SOURCE_SOR1 0x410
+#define CLK_SOURCE_LA 0x1f8
 
 #define PLLC_BASE 0x80
 #define PLLC_OUT 0x84
 #define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2a8
 #define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2ac
 
+#define LVL2_CLK_GATE_OVRA 0xf8
+#define LVL2_CLK_GATE_OVRC 0x3a0
+#define LVL2_CLK_GATE_OVRD 0x3a4
+#define LVL2_CLK_GATE_OVRE 0x554
+
+/* I2S registers to handle during APE MBIST WAR */
+#define TEGRA210_I2S_BASE  0x1000
+#define TEGRA210_I2S_SIZE  0x100
+#define TEGRA210_I2S_CTRLS 5
+#define TEGRA210_I2S_CG    0x88
+#define TEGRA210_I2S_CTRL  0xa0
+
+/* DISPA registers to handle during MBIST WAR */
+#define DC_CMD_DISPLAY_COMMAND 0xc8
+#define DC_COM_DSC_TOP_CTL 0xcf8
+
+/* VIC register to handle during MBIST WAR */
+#define NV_PVIC_THI_SLCG_OVERRIDE_LOW 0x8c
+
+/* APE, DISPA and VIC base addesses needed for MBIST WAR */
+#define TEGRA210_AHUB_BASE  0x702d0000
+#define TEGRA210_DISPA_BASE 0x54200000
+#define TEGRA210_VIC_BASE  0x54340000
+
 /*
  * SDM fractional divisor is 16-bit 2's complement signed number within
  * (-2^12 ... 2^12-1) range. Represented in PLL data structure as unsigned
@@ -255,8 +282,22 @@ static struct cpu_clk_suspend_context {
 } tegra210_cpu_clk_sctx;
 #endif
 
+struct tegra210_domain_mbist_war {
+       void (*handle_lvl2_ovr)(struct tegra210_domain_mbist_war *mbist);
+       const u32 lvl2_offset;
+       const u32 lvl2_mask;
+       const unsigned int num_clks;
+       const unsigned int *clk_init_data;
+       struct clk_bulk_data *clks;
+};
+
+static struct clk **clks;
+
 static void __iomem *clk_base;
 static void __iomem *pmc_base;
+static void __iomem *ahub_base;
+static void __iomem *dispa_base;
+static void __iomem *vic_base;
 
 static unsigned long osc_freq;
 static unsigned long pll_ref_freq;
@@ -267,6 +308,7 @@ static DEFINE_SPINLOCK(pll_re_lock);
 static DEFINE_SPINLOCK(pll_u_lock);
 static DEFINE_SPINLOCK(sor1_lock);
 static DEFINE_SPINLOCK(emc_lock);
+static DEFINE_MUTEX(lvl2_ovr_lock);
 
 /* possible OSC frequencies in Hz */
 static unsigned long tegra210_input_freq[] = {
@@ -310,6 +352,8 @@ static const char *mux_pllmcp_clkm[] = {
 #define PLLA_MISC2_WRITE_MASK          0x06ffffff
 
 /* PLLD */
+#define PLLD_BASE_CSI_CLKSOURCE                (1 << 23)
+
 #define PLLD_MISC0_EN_SDM              (1 << 16)
 #define PLLD_MISC0_LOCK_OVERRIDE       (1 << 17)
 #define PLLD_MISC0_LOCK_ENABLE         (1 << 18)
@@ -513,6 +557,115 @@ void tegra210_set_sata_pll_seq_sw(bool state)
 }
 EXPORT_SYMBOL_GPL(tegra210_set_sata_pll_seq_sw);
 
+static void tegra210_generic_mbist_war(struct tegra210_domain_mbist_war *mbist)
+{
+       u32 val;
+
+       val = readl_relaxed(clk_base + mbist->lvl2_offset);
+       writel_relaxed(val | mbist->lvl2_mask, clk_base + mbist->lvl2_offset);
+       fence_udelay(1, clk_base);
+       writel_relaxed(val, clk_base + mbist->lvl2_offset);
+       fence_udelay(1, clk_base);
+}
+
+static void tegra210_venc_mbist_war(struct tegra210_domain_mbist_war *mbist)
+{
+       u32 csi_src, ovra, ovre;
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&pll_d_lock, flags);
+
+       csi_src = readl_relaxed(clk_base + PLLD_BASE);
+       writel_relaxed(csi_src | PLLD_BASE_CSI_CLKSOURCE, clk_base + PLLD_BASE);
+       fence_udelay(1, clk_base);
+
+       ovra = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRA);
+       writel_relaxed(ovra | BIT(15), clk_base + LVL2_CLK_GATE_OVRA);
+       ovre = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRE);
+       writel_relaxed(ovre | BIT(3), clk_base + LVL2_CLK_GATE_OVRE);
+       fence_udelay(1, clk_base);
+
+       writel_relaxed(ovra, clk_base + LVL2_CLK_GATE_OVRA);
+       writel_relaxed(ovre, clk_base + LVL2_CLK_GATE_OVRE);
+       writel_relaxed(csi_src, clk_base + PLLD_BASE);
+       fence_udelay(1, clk_base);
+
+       spin_unlock_irqrestore(&pll_d_lock, flags);
+}
+
+static void tegra210_disp_mbist_war(struct tegra210_domain_mbist_war *mbist)
+{
+       u32 ovra, dsc_top_ctrl;
+
+       ovra = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRA);
+       writel_relaxed(ovra | BIT(1), clk_base + LVL2_CLK_GATE_OVRA);
+       fence_udelay(1, clk_base);
+
+       dsc_top_ctrl = readl_relaxed(dispa_base + DC_COM_DSC_TOP_CTL);
+       writel_relaxed(dsc_top_ctrl | BIT(2), dispa_base + DC_COM_DSC_TOP_CTL);
+       readl_relaxed(dispa_base + DC_CMD_DISPLAY_COMMAND);
+       writel_relaxed(dsc_top_ctrl, dispa_base + DC_COM_DSC_TOP_CTL);
+       readl_relaxed(dispa_base + DC_CMD_DISPLAY_COMMAND);
+
+       writel_relaxed(ovra, clk_base + LVL2_CLK_GATE_OVRA);
+       fence_udelay(1, clk_base);
+}
+
+static void tegra210_vic_mbist_war(struct tegra210_domain_mbist_war *mbist)
+{
+       u32 ovre, val;
+
+       ovre = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRE);
+       writel_relaxed(ovre | BIT(5), clk_base + LVL2_CLK_GATE_OVRE);
+       fence_udelay(1, clk_base);
+
+       val = readl_relaxed(vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW);
+       writel_relaxed(val | BIT(0) | GENMASK(7, 2) | BIT(24),
+                       vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW);
+       fence_udelay(1, vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW);
+
+       writel_relaxed(val, vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW);
+       readl(vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW);
+
+       writel_relaxed(ovre, clk_base + LVL2_CLK_GATE_OVRE);
+       fence_udelay(1, clk_base);
+}
+
+static void tegra210_ape_mbist_war(struct tegra210_domain_mbist_war *mbist)
+{
+       void __iomem *i2s_base;
+       unsigned int i;
+       u32 ovrc, ovre;
+
+       ovrc = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRC);
+       ovre = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRE);
+       writel_relaxed(ovrc | BIT(1), clk_base + LVL2_CLK_GATE_OVRC);
+       writel_relaxed(ovre | BIT(10) | BIT(11),
+                       clk_base + LVL2_CLK_GATE_OVRE);
+       fence_udelay(1, clk_base);
+
+       i2s_base = ahub_base + TEGRA210_I2S_BASE;
+
+       for (i = 0; i < TEGRA210_I2S_CTRLS; i++) {
+               u32 i2s_ctrl;
+
+               i2s_ctrl = readl_relaxed(i2s_base + TEGRA210_I2S_CTRL);
+               writel_relaxed(i2s_ctrl | BIT(10),
+                               i2s_base + TEGRA210_I2S_CTRL);
+               writel_relaxed(0, i2s_base + TEGRA210_I2S_CG);
+               readl(i2s_base + TEGRA210_I2S_CG);
+               writel_relaxed(1, i2s_base + TEGRA210_I2S_CG);
+               writel_relaxed(i2s_ctrl, i2s_base + TEGRA210_I2S_CTRL);
+               readl(i2s_base + TEGRA210_I2S_CTRL);
+
+               i2s_base += TEGRA210_I2S_SIZE;
+       }
+
+       writel_relaxed(ovrc, clk_base + LVL2_CLK_GATE_OVRC);
+       writel_relaxed(ovre, clk_base + LVL2_CLK_GATE_OVRE);
+       fence_udelay(1, clk_base);
+}
+
 static inline void _pll_misc_chk_default(void __iomem *base,
                                        struct tegra_clk_pll_params *params,
                                        u8 misc_num, u32 default_val, u32 mask)
@@ -2411,13 +2564,150 @@ static struct tegra_audio_clk_info tegra210_audio_plls[] = {
        { "pll_a1", &pll_a1_params, tegra_clk_pll_a1, "pll_ref" },
 };
 
-static struct clk **clks;
-
 static const char * const aclk_parents[] = {
        "pll_a1", "pll_c", "pll_p", "pll_a_out0", "pll_c2", "pll_c3",
        "clk_m"
 };
 
+static const unsigned int nvjpg_slcg_clkids[] = { TEGRA210_CLK_NVDEC };
+static const unsigned int nvdec_slcg_clkids[] = { TEGRA210_CLK_NVJPG };
+static const unsigned int sor_slcg_clkids[] = { TEGRA210_CLK_HDA2CODEC_2X,
+       TEGRA210_CLK_HDA2HDMI, TEGRA210_CLK_DISP1, TEGRA210_CLK_DISP2 };
+static const unsigned int disp_slcg_clkids[] = { TEGRA210_CLK_LA,
+       TEGRA210_CLK_HOST1X};
+static const unsigned int xusba_slcg_clkids[] = { TEGRA210_CLK_XUSB_HOST,
+       TEGRA210_CLK_XUSB_DEV };
+static const unsigned int xusbb_slcg_clkids[] = { TEGRA210_CLK_XUSB_HOST,
+       TEGRA210_CLK_XUSB_SS };
+static const unsigned int xusbc_slcg_clkids[] = { TEGRA210_CLK_XUSB_DEV,
+       TEGRA210_CLK_XUSB_SS };
+static const unsigned int venc_slcg_clkids[] = { TEGRA210_CLK_HOST1X,
+       TEGRA210_CLK_PLL_D };
+static const unsigned int ape_slcg_clkids[] = { TEGRA210_CLK_ACLK,
+       TEGRA210_CLK_I2S0, TEGRA210_CLK_I2S1, TEGRA210_CLK_I2S2,
+       TEGRA210_CLK_I2S3, TEGRA210_CLK_I2S4, TEGRA210_CLK_SPDIF_OUT,
+       TEGRA210_CLK_D_AUDIO };
+static const unsigned int vic_slcg_clkids[] = { TEGRA210_CLK_HOST1X };
+
+static struct tegra210_domain_mbist_war tegra210_pg_mbist_war[] = {
+       [TEGRA_POWERGATE_VENC] = {
+               .handle_lvl2_ovr = tegra210_venc_mbist_war,
+               .num_clks = ARRAY_SIZE(venc_slcg_clkids),
+               .clk_init_data = venc_slcg_clkids,
+       },
+       [TEGRA_POWERGATE_SATA] = {
+               .handle_lvl2_ovr = tegra210_generic_mbist_war,
+               .lvl2_offset = LVL2_CLK_GATE_OVRC,
+               .lvl2_mask = BIT(0) | BIT(17) | BIT(19),
+       },
+       [TEGRA_POWERGATE_MPE] = {
+               .handle_lvl2_ovr = tegra210_generic_mbist_war,
+               .lvl2_offset = LVL2_CLK_GATE_OVRE,
+               .lvl2_mask = BIT(2),
+       },
+       [TEGRA_POWERGATE_SOR] = {
+               .handle_lvl2_ovr = tegra210_generic_mbist_war,
+               .num_clks = ARRAY_SIZE(sor_slcg_clkids),
+               .clk_init_data = sor_slcg_clkids,
+               .lvl2_offset = LVL2_CLK_GATE_OVRA,
+               .lvl2_mask = BIT(1) | BIT(2),
+       },
+       [TEGRA_POWERGATE_DIS] = {
+               .handle_lvl2_ovr = tegra210_disp_mbist_war,
+               .num_clks = ARRAY_SIZE(disp_slcg_clkids),
+               .clk_init_data = disp_slcg_clkids,
+       },
+       [TEGRA_POWERGATE_DISB] = {
+               .num_clks = ARRAY_SIZE(disp_slcg_clkids),
+               .clk_init_data = disp_slcg_clkids,
+               .handle_lvl2_ovr = tegra210_generic_mbist_war,
+               .lvl2_offset = LVL2_CLK_GATE_OVRA,
+               .lvl2_mask = BIT(2),
+       },
+       [TEGRA_POWERGATE_XUSBA] = {
+               .num_clks = ARRAY_SIZE(xusba_slcg_clkids),
+               .clk_init_data = xusba_slcg_clkids,
+               .handle_lvl2_ovr = tegra210_generic_mbist_war,
+               .lvl2_offset = LVL2_CLK_GATE_OVRC,
+               .lvl2_mask = BIT(30) | BIT(31),
+       },
+       [TEGRA_POWERGATE_XUSBB] = {
+               .num_clks = ARRAY_SIZE(xusbb_slcg_clkids),
+               .clk_init_data = xusbb_slcg_clkids,
+               .handle_lvl2_ovr = tegra210_generic_mbist_war,
+               .lvl2_offset = LVL2_CLK_GATE_OVRC,
+               .lvl2_mask = BIT(30) | BIT(31),
+       },
+       [TEGRA_POWERGATE_XUSBC] = {
+               .num_clks = ARRAY_SIZE(xusbc_slcg_clkids),
+               .clk_init_data = xusbc_slcg_clkids,
+               .handle_lvl2_ovr = tegra210_generic_mbist_war,
+               .lvl2_offset = LVL2_CLK_GATE_OVRC,
+               .lvl2_mask = BIT(30) | BIT(31),
+       },
+       [TEGRA_POWERGATE_VIC] = {
+               .num_clks = ARRAY_SIZE(vic_slcg_clkids),
+               .clk_init_data = vic_slcg_clkids,
+               .handle_lvl2_ovr = tegra210_vic_mbist_war,
+       },
+       [TEGRA_POWERGATE_NVDEC] = {
+               .num_clks = ARRAY_SIZE(nvdec_slcg_clkids),
+               .clk_init_data = nvdec_slcg_clkids,
+               .handle_lvl2_ovr = tegra210_generic_mbist_war,
+               .lvl2_offset = LVL2_CLK_GATE_OVRC,
+               .lvl2_mask = BIT(9) | BIT(31),
+       },
+       [TEGRA_POWERGATE_NVJPG] = {
+               .num_clks = ARRAY_SIZE(nvjpg_slcg_clkids),
+               .clk_init_data = nvjpg_slcg_clkids,
+               .handle_lvl2_ovr = tegra210_generic_mbist_war,
+               .lvl2_offset = LVL2_CLK_GATE_OVRC,
+               .lvl2_mask = BIT(9) | BIT(31),
+       },
+       [TEGRA_POWERGATE_AUD] = {
+               .num_clks = ARRAY_SIZE(ape_slcg_clkids),
+               .clk_init_data = ape_slcg_clkids,
+               .handle_lvl2_ovr = tegra210_ape_mbist_war,
+       },
+       [TEGRA_POWERGATE_VE2] = {
+               .handle_lvl2_ovr = tegra210_generic_mbist_war,
+               .lvl2_offset = LVL2_CLK_GATE_OVRD,
+               .lvl2_mask = BIT(22),
+       },
+};
+
+int tegra210_clk_handle_mbist_war(unsigned int id)
+{
+       int err;
+       struct tegra210_domain_mbist_war *mbist_war;
+
+       if (id >= ARRAY_SIZE(tegra210_pg_mbist_war)) {
+               WARN(1, "unknown domain id in MBIST WAR handler\n");
+               return -EINVAL;
+       }
+
+       mbist_war = &tegra210_pg_mbist_war[id];
+       if (!mbist_war->handle_lvl2_ovr)
+               return 0;
+
+       if (mbist_war->num_clks && !mbist_war->clks)
+               return -ENODEV;
+
+       err = clk_bulk_prepare_enable(mbist_war->num_clks, mbist_war->clks);
+       if (err < 0)
+               return err;
+
+       mutex_lock(&lvl2_ovr_lock);
+
+       mbist_war->handle_lvl2_ovr(mbist_war);
+
+       mutex_unlock(&lvl2_ovr_lock);
+
+       clk_bulk_disable_unprepare(mbist_war->num_clks, mbist_war->clks);
+
+       return 0;
+}
+
 void tegra210_put_utmipll_in_iddq(void)
 {
        u32 reg;
@@ -2654,6 +2944,13 @@ static struct tegra_periph_init_data tegra210_periph[] = {
                              sor1_parents_idx, 0, &sor1_lock),
 };
 
+static const char * const la_parents[] = {
+       "pll_p", "pll_c2", "pll_c", "pll_c3", "pll_re_out1", "pll_a1", "clk_m", "pll_c4_out0"
+};
+
+static struct tegra_clk_periph tegra210_la =
+       TEGRA_CLK_PERIPH(29, 7, 9, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, 76, 0, NULL, 0);
+
 static __init void tegra210_periph_clk_init(void __iomem *clk_base,
                                            void __iomem *pmc_base)
 {
@@ -2700,6 +2997,12 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base,
                                             periph_clk_enb_refcnt);
        clks[TEGRA210_CLK_DSIB] = clk;
 
+       /* la */
+       clk = tegra_clk_register_periph("la", la_parents,
+                       ARRAY_SIZE(la_parents), &tegra210_la, clk_base,
+                       CLK_SOURCE_LA, 0);
+       clks[TEGRA210_CLK_LA] = clk;
+
        /* emc mux */
        clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
                               ARRAY_SIZE(mux_pllmcp_clkm), 0,
@@ -3025,7 +3328,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
        { TEGRA210_CLK_I2S4, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 },
        { TEGRA210_CLK_HOST1X, TEGRA210_CLK_PLL_P, 136000000, 1 },
        { TEGRA210_CLK_SCLK_MUX, TEGRA210_CLK_PLL_P, 0, 1 },
-       { TEGRA210_CLK_SCLK, TEGRA210_CLK_CLK_MAX, 102000000, 1 },
+       { TEGRA210_CLK_SCLK, TEGRA210_CLK_CLK_MAX, 102000000, 0 },
        { TEGRA210_CLK_DFLL_SOC, TEGRA210_CLK_PLL_P, 51000000, 1 },
        { TEGRA210_CLK_DFLL_REF, TEGRA210_CLK_PLL_P, 51000000, 1 },
        { TEGRA210_CLK_SBC4, TEGRA210_CLK_PLL_P, 12000000, 1 },
@@ -3040,7 +3343,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
        { TEGRA210_CLK_XUSB_DEV_SRC, TEGRA210_CLK_PLL_P_OUT_XUSB, 102000000, 0 },
        { TEGRA210_CLK_SATA, TEGRA210_CLK_PLL_P, 104000000, 0 },
        { TEGRA210_CLK_SATA_OOB, TEGRA210_CLK_PLL_P, 204000000, 0 },
-       { TEGRA210_CLK_EMC, TEGRA210_CLK_CLK_MAX, 0, 1 },
        { TEGRA210_CLK_MSELECT, TEGRA210_CLK_CLK_MAX, 0, 1 },
        { TEGRA210_CLK_CSITE, TEGRA210_CLK_CLK_MAX, 0, 1 },
        /* TODO find a way to enable this on-demand */
@@ -3149,6 +3451,37 @@ static int tegra210_reset_deassert(unsigned long id)
        return 0;
 }
 
+static void tegra210_mbist_clk_init(void)
+{
+       unsigned int i, j;
+
+       for (i = 0; i < ARRAY_SIZE(tegra210_pg_mbist_war); i++) {
+               unsigned int num_clks = tegra210_pg_mbist_war[i].num_clks;
+               struct clk_bulk_data *clk_data;
+
+               if (!num_clks)
+                       continue;
+
+               clk_data = kmalloc_array(num_clks, sizeof(*clk_data),
+                                        GFP_KERNEL);
+               if (WARN_ON(!clk_data))
+                       return;
+
+               tegra210_pg_mbist_war[i].clks = clk_data;
+               for (j = 0; j < num_clks; j++) {
+                       int clk_id = tegra210_pg_mbist_war[i].clk_init_data[j];
+                       struct clk *clk = clks[clk_id];
+
+                       if (WARN(IS_ERR(clk), "clk_id: %d\n", clk_id)) {
+                               kfree(clk_data);
+                               tegra210_pg_mbist_war[i].clks = NULL;
+                               break;
+                       }
+                       clk_data[j].clk = clk;
+               }
+       }
+}
+
 /**
  * tegra210_clock_init - Tegra210-specific clock initialization
  * @np: struct device_node * of the DT node for the SoC CAR IP block
@@ -3183,6 +3516,24 @@ static void __init tegra210_clock_init(struct device_node *np)
                return;
        }
 
+       ahub_base = ioremap(TEGRA210_AHUB_BASE, SZ_64K);
+       if (!ahub_base) {
+               pr_err("ioremap tegra210 APE failed\n");
+               return;
+       }
+
+       dispa_base = ioremap(TEGRA210_DISPA_BASE, SZ_256K);
+       if (!dispa_base) {
+               pr_err("ioremap tegra210 DISPA failed\n");
+               return;
+       }
+
+       vic_base = ioremap(TEGRA210_VIC_BASE, SZ_256K);
+       if (!vic_base) {
+               pr_err("ioremap tegra210 VIC failed\n");
+               return;
+       }
+
        clks = tegra_clk_init(clk_base, TEGRA210_CLK_CLK_MAX,
                              TEGRA210_CAR_BANK_COUNT);
        if (!clks)
@@ -3219,6 +3570,8 @@ static void __init tegra210_clock_init(struct device_node *np)
        tegra_add_of_provider(np);
        tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
 
+       tegra210_mbist_clk_init();
+
        tegra_cpu_car_ops = &tegra210_cpu_car_ops;
 }
 CLK_OF_DECLARE(tegra210, "nvidia,tegra210-car", tegra210_clock_init);
index bee84c554932ce1f54f5f32eff0078f7b7f19868..b316dfb6f6c7a6c45943b7cd7b18010d7a8b0409 100644 (file)
@@ -819,6 +819,7 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = {
        [tegra_clk_pll_a] = { .dt_id = TEGRA30_CLK_PLL_A, .present = true },
        [tegra_clk_pll_a_out0] = { .dt_id = TEGRA30_CLK_PLL_A_OUT0, .present = true },
        [tegra_clk_cec] = { .dt_id = TEGRA30_CLK_CEC, .present = true },
+       [tegra_clk_emc] = { .dt_id = TEGRA30_CLK_EMC, .present = true },
 };
 
 static const char *pll_e_parents[] = { "pll_ref", "pll_p" };
@@ -843,8 +844,7 @@ static void __init tegra30_pll_init(void)
 
        /* PLLM */
        clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, pmc_base,
-                           CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
-                           &pll_m_params, NULL);
+                           CLK_SET_RATE_GATE, &pll_m_params, NULL);
        clks[TEGRA30_CLK_PLL_M] = clk;
 
        /* PLLM_OUT1 */
@@ -852,7 +852,7 @@ static void __init tegra30_pll_init(void)
                                clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
                                8, 8, 1, NULL);
        clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
-                               clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
+                               clk_base + PLLM_OUT, 1, 0,
                                CLK_SET_RATE_PARENT, 0, NULL);
        clks[TEGRA30_CLK_PLL_M_OUT1] = clk;
 
@@ -990,7 +990,7 @@ static void __init tegra30_super_clk_init(void)
        /* SCLK */
        clk = tegra_clk_register_super_mux("sclk", sclk_parents,
                                  ARRAY_SIZE(sclk_parents),
-                                 CLK_SET_RATE_PARENT,
+                                 CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
                                  clk_base + SCLK_BURST_POLICY,
                                  0, 4, 0, 0, NULL);
        clks[TEGRA30_CLK_SCLK] = clk;
@@ -1060,9 +1060,6 @@ static void __init tegra30_periph_clk_init(void)
                               CLK_SET_RATE_NO_REPARENT,
                               clk_base + CLK_SOURCE_EMC,
                               30, 2, 0, &emc_lock);
-       clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0,
-                                   57, periph_clk_enb_refcnt);
-       clks[TEGRA30_CLK_EMC] = clk;
 
        clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
                                    &emc_lock);
@@ -1252,10 +1249,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
        { TEGRA30_CLK_SDMMC1, TEGRA30_CLK_PLL_P, 48000000, 0 },
        { TEGRA30_CLK_SDMMC2, TEGRA30_CLK_PLL_P, 48000000, 0 },
        { TEGRA30_CLK_SDMMC3, TEGRA30_CLK_PLL_P, 48000000, 0 },
-       { TEGRA30_CLK_PLL_M, TEGRA30_CLK_CLK_MAX, 0, 1 },
-       { TEGRA30_CLK_PCLK, TEGRA30_CLK_CLK_MAX, 0, 1 },
        { TEGRA30_CLK_CSITE, TEGRA30_CLK_CLK_MAX, 0, 1 },
-       { TEGRA30_CLK_EMC, TEGRA30_CLK_CLK_MAX, 0, 1 },
        { TEGRA30_CLK_MSELECT, TEGRA30_CLK_CLK_MAX, 0, 1 },
        { TEGRA30_CLK_SBC1, TEGRA30_CLK_PLL_P, 100000000, 0 },
        { TEGRA30_CLK_SBC2, TEGRA30_CLK_PLL_P, 100000000, 0 },
@@ -1272,6 +1266,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
        { TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 },
        { TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 },
        { TEGRA30_CLK_PLL_U, TEGRA30_CLK_CLK_MAX, 480000000, 0 },
+       { TEGRA30_CLK_VDE, TEGRA30_CLK_CLK_MAX, 600000000, 0 },
        /* must be the last entry */
        { TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 },
 };
index 3b2763df51c2e0f7c5a5113f8df68dbbc4cb9b21..ba7e20e6a82ba84363259c2e705b8f5585bd7902 100644 (file)
@@ -812,4 +812,11 @@ int tegra_pll_wait_for_lock(struct tegra_clk_pll *pll);
 u16 tegra_pll_get_fixed_mdiv(struct clk_hw *hw, unsigned long input_rate);
 int tegra_pll_p_div_to_hw(struct tegra_clk_pll *pll, u8 p_div);
 
+/* Combined read fence with delay */
+#define fence_udelay(delay, reg)       \
+       do {                            \
+               readl(reg);             \
+               udelay(delay);          \
+       } while (0)
+
 #endif /* TEGRA_CLK_H */
index f4d6802a85444d1581abc8d024f9f2003ec96c31..7d22e1af224770d7084cd7d8ec29e24d3f87368f 100644 (file)
@@ -55,6 +55,29 @@ static void clk_memmap_writel(u32 val, const struct clk_omap_reg *reg)
                writel_relaxed(val, io->mem + reg->offset);
 }
 
+static void _clk_rmw(u32 val, u32 mask, void __iomem *ptr)
+{
+       u32 v;
+
+       v = readl_relaxed(ptr);
+       v &= ~mask;
+       v |= val;
+       writel_relaxed(v, ptr);
+}
+
+static void clk_memmap_rmw(u32 val, u32 mask, const struct clk_omap_reg *reg)
+{
+       struct clk_iomap *io = clk_memmaps[reg->index];
+
+       if (reg->ptr) {
+               _clk_rmw(val, mask, reg->ptr);
+       } else if (io->regmap) {
+               regmap_update_bits(io->regmap, reg->offset, mask, val);
+       } else {
+               _clk_rmw(val, mask, io->mem + reg->offset);
+       }
+}
+
 static u32 clk_memmap_readl(const struct clk_omap_reg *reg)
 {
        u32 val;
@@ -89,6 +112,7 @@ int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops)
        ti_clk_ll_ops = ops;
        ops->clk_readl = clk_memmap_readl;
        ops->clk_writel = clk_memmap_writel;
+       ops->clk_rmw = clk_memmap_rmw;
 
        return 0;
 }
@@ -251,6 +275,20 @@ int ti_clk_get_reg_addr(struct device_node *node, int index,
        return 0;
 }
 
+void ti_clk_latch(struct clk_omap_reg *reg, s8 shift)
+{
+       u32 latch;
+
+       if (shift < 0)
+               return;
+
+       latch = 1 << shift;
+
+       ti_clk_ll_ops->clk_rmw(latch, latch, reg);
+       ti_clk_ll_ops->clk_rmw(0, latch, reg);
+       ti_clk_ll_ops->clk_readl(reg); /* OCP barrier */
+}
+
 /**
  * omap2_clk_provider_init - init master clock provider
  * @parent: master node
index d9b43bfc25325687302876374d8e9e337a315eec..b58278077226e75b2e38304bfa10a45d48fa7dfc 100644 (file)
@@ -22,6 +22,7 @@ struct clk_omap_divider {
        u8                      shift;
        u8                      width;
        u8                      flags;
+       s8                      latch;
        const struct clk_div_table      *table;
 };
 
@@ -33,6 +34,7 @@ struct clk_omap_mux {
        u32                     *table;
        u32                     mask;
        u8                      shift;
+       s8                      latch;
        u8                      flags;
 };
 
@@ -74,6 +76,11 @@ enum {
 #define CLKF_CORE                      (1 << 9)
 #define CLKF_J_TYPE                    (1 << 10)
 
+/* CLKCTRL flags */
+#define CLKF_SW_SUP                    BIT(5)
+#define CLKF_HW_SUP                    BIT(6)
+#define CLKF_NO_IDLEST                 BIT(7)
+
 #define CLK(dev, con, ck)              \
        {                               \
                .lk = {                 \
@@ -183,10 +190,6 @@ extern const struct omap_clkctrl_data am438x_clkctrl_data[];
 extern const struct omap_clkctrl_data dm814_clkctrl_data[];
 extern const struct omap_clkctrl_data dm816_clkctrl_data[];
 
-#define CLKF_SW_SUP    BIT(0)
-#define CLKF_HW_SUP    BIT(1)
-#define CLKF_NO_IDLEST BIT(2)
-
 typedef void (*ti_of_clk_init_cb_t)(void *, struct device_node *);
 
 struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
@@ -194,6 +197,8 @@ struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
 int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con);
 void ti_clk_add_aliases(void);
 
+void ti_clk_latch(struct clk_omap_reg *reg, s8 shift);
+
 struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup);
 
 int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
index 77f93f6d2806a19662b3f2c94128ee491cfc4fe2..aaa277dd6d991e9de2cb7bc7f9087d7d131a9637 100644 (file)
@@ -263,6 +263,8 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
        val |= value << divider->shift;
        ti_clk_ll_ops->clk_writel(val, &divider->reg);
 
+       ti_clk_latch(&divider->reg, divider->latch);
+
        return 0;
 }
 
@@ -276,7 +278,8 @@ static struct clk *_register_divider(struct device *dev, const char *name,
                                     const char *parent_name,
                                     unsigned long flags,
                                     struct clk_omap_reg *reg,
-                                    u8 shift, u8 width, u8 clk_divider_flags,
+                                    u8 shift, u8 width, s8 latch,
+                                    u8 clk_divider_flags,
                                     const struct clk_div_table *table)
 {
        struct clk_omap_divider *div;
@@ -305,6 +308,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
        memcpy(&div->reg, reg, sizeof(*reg));
        div->shift = shift;
        div->width = width;
+       div->latch = latch;
        div->flags = clk_divider_flags;
        div->hw.init = &init;
        div->table = table;
@@ -420,6 +424,7 @@ struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
        div->table = _get_div_table_from_setup(setup, &div->width);
 
        div->shift = setup->bit_shift;
+       div->latch = -EINVAL;
 
        return &div->hw;
 }
@@ -452,7 +457,7 @@ struct clk *ti_clk_register_divider(struct ti_clk *setup)
 
        clk = _register_divider(NULL, setup->name, div->parent,
                                flags, &reg, div->bit_shift,
-                               width, div_flags, table);
+                               width, -EINVAL, div_flags, table);
 
        if (IS_ERR(clk))
                kfree(table);
@@ -556,7 +561,7 @@ static int _get_divider_width(struct device_node *node,
 
 static int __init ti_clk_divider_populate(struct device_node *node,
        struct clk_omap_reg *reg, const struct clk_div_table **table,
-       u32 *flags, u8 *div_flags, u8 *width, u8 *shift)
+       u32 *flags, u8 *div_flags, u8 *width, u8 *shift, s8 *latch)
 {
        u32 val;
        int ret;
@@ -570,6 +575,13 @@ static int __init ti_clk_divider_populate(struct device_node *node,
        else
                *shift = 0;
 
+       if (latch) {
+               if (!of_property_read_u32(node, "ti,latch-bit", &val))
+                       *latch = val;
+               else
+                       *latch = -EINVAL;
+       }
+
        *flags = 0;
        *div_flags = 0;
 
@@ -606,17 +618,18 @@ static void __init of_ti_divider_clk_setup(struct device_node *node)
        u8 clk_divider_flags = 0;
        u8 width = 0;
        u8 shift = 0;
+       s8 latch = -EINVAL;
        const struct clk_div_table *table = NULL;
        u32 flags = 0;
 
        parent_name = of_clk_get_parent_name(node, 0);
 
        if (ti_clk_divider_populate(node, &reg, &table, &flags,
-                                   &clk_divider_flags, &width, &shift))
+                                   &clk_divider_flags, &width, &shift, &latch))
                goto cleanup;
 
        clk = _register_divider(NULL, node->name, parent_name, flags, &reg,
-                               shift, width, clk_divider_flags, table);
+                               shift, width, latch, clk_divider_flags, table);
 
        if (!IS_ERR(clk)) {
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
@@ -639,7 +652,8 @@ static void __init of_ti_composite_divider_clk_setup(struct device_node *node)
                return;
 
        if (ti_clk_divider_populate(node, &div->reg, &div->table, &val,
-                                   &div->flags, &div->width, &div->shift) < 0)
+                                   &div->flags, &div->width, &div->shift,
+                                   NULL) < 0)
                goto cleanup;
 
        if (!ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER))
index d4705803f3d3c7f72cfdc9f969bde508c4a1197a..69a4308a5a983b9e027eb8610ac5da53c8b15cec 100644 (file)
@@ -86,6 +86,7 @@ static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index)
        }
        val |= index << mux->shift;
        ti_clk_ll_ops->clk_writel(val, &mux->reg);
+       ti_clk_latch(&mux->reg, mux->latch);
 
        return 0;
 }
@@ -100,7 +101,7 @@ static struct clk *_register_mux(struct device *dev, const char *name,
                                 const char * const *parent_names,
                                 u8 num_parents, unsigned long flags,
                                 struct clk_omap_reg *reg, u8 shift, u32 mask,
-                                u8 clk_mux_flags, u32 *table)
+                                s8 latch, u8 clk_mux_flags, u32 *table)
 {
        struct clk_omap_mux *mux;
        struct clk *clk;
@@ -121,6 +122,7 @@ static struct clk *_register_mux(struct device *dev, const char *name,
        memcpy(&mux->reg, reg, sizeof(*reg));
        mux->shift = shift;
        mux->mask = mask;
+       mux->latch = latch;
        mux->flags = clk_mux_flags;
        mux->table = table;
        mux->hw.init = &init;
@@ -160,7 +162,7 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup)
                flags |= CLK_SET_RATE_PARENT;
 
        return _register_mux(NULL, setup->name, mux->parents, mux->num_parents,
-                            flags, &reg, mux->bit_shift, mask,
+                            flags, &reg, mux->bit_shift, mask, -EINVAL,
                             mux_flags, NULL);
 }
 
@@ -179,6 +181,7 @@ static void of_mux_clk_setup(struct device_node *node)
        u8 clk_mux_flags = 0;
        u32 mask = 0;
        u32 shift = 0;
+       s32 latch = -EINVAL;
        u32 flags = CLK_SET_RATE_NO_REPARENT;
 
        num_parents = of_clk_get_parent_count(node);
@@ -197,6 +200,8 @@ static void of_mux_clk_setup(struct device_node *node)
 
        of_property_read_u32(node, "ti,bit-shift", &shift);
 
+       of_property_read_u32(node, "ti,latch-bit", &latch);
+
        if (of_property_read_bool(node, "ti,index-starts-at-one"))
                clk_mux_flags |= CLK_MUX_INDEX_ONE;
 
@@ -211,7 +216,8 @@ static void of_mux_clk_setup(struct device_node *node)
        mask = (1 << fls(mask)) - 1;
 
        clk = _register_mux(NULL, node->name, parent_names, num_parents,
-                           flags, &reg, shift, mask, clk_mux_flags, NULL);
+                           flags, &reg, shift, mask, latch, clk_mux_flags,
+                           NULL);
 
        if (!IS_ERR(clk))
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
@@ -234,6 +240,7 @@ struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup)
                return ERR_PTR(-ENOMEM);
 
        mux->shift = setup->bit_shift;
+       mux->latch = -EINVAL;
 
        mux->reg.index = setup->module;
        mux->reg.offset = setup->reg;
index d244e724e19858dfb8b8c5297e9852a61ba0ce50..ebc78ab2df0596360858d43b35d33c99fc72da8d 100644 (file)
 #define UNIPHIER_PRO4_SYS_CLK_USB3(idx, ch)                            \
        UNIPHIER_CLK_GATE("usb3" #ch, (idx), NULL, 0x2104, 16 + (ch))
 
+#define UNIPHIER_PRO4_SYS_CLK_AIO(idx)                                 \
+       UNIPHIER_CLK_FACTOR("aio-io200m", -1, "spll", 1, 8),            \
+       UNIPHIER_CLK_GATE("aio", (idx), "aio-io200m", 0x2104, 13)
+
+#define UNIPHIER_PRO5_SYS_CLK_AIO(idx)                                 \
+       UNIPHIER_CLK_FACTOR("aio-io200m", -1, "spll", 1, 12),           \
+       UNIPHIER_CLK_GATE("aio", (idx), "aio-io200m", 0x2104, 13)
+
 #define UNIPHIER_LD11_SYS_CLK_AIO(idx)                                 \
        UNIPHIER_CLK_FACTOR("aio-io200m", -1, "spll", 1, 10),           \
        UNIPHIER_CLK_GATE("aio", (idx), "aio-io200m", 0x2108, 0)
@@ -94,16 +102,22 @@ const struct uniphier_clk_data uniphier_pro4_sys_clk_data[] = {
        UNIPHIER_CLK_FACTOR("upll", -1, "ref", 288, 25),        /* 288 MHz */
        UNIPHIER_CLK_FACTOR("a2pll", -1, "upll", 256, 125),     /* 589.824 MHz */
        UNIPHIER_CLK_FACTOR("vpll27a", -1, "ref", 270, 25),     /* 270 MHz */
+       UNIPHIER_CLK_FACTOR("gpll", -1, "ref", 10, 1),          /* 250 MHz */
        UNIPHIER_CLK_FACTOR("uart", 0, "a2pll", 1, 8),
        UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 32),
        UNIPHIER_LD4_SYS_CLK_NAND(2),
        UNIPHIER_LD4_SYS_CLK_SD,
        UNIPHIER_CLK_FACTOR("usb2", -1, "upll", 1, 12),
        UNIPHIER_PRO4_SYS_CLK_ETHER(6),
+       UNIPHIER_CLK_GATE("ether-gb", 7, "gpll", 0x2104, 5),
        UNIPHIER_LD4_SYS_CLK_STDMAC(8),                 /* HSC, MIO, RLE */
+       UNIPHIER_CLK_GATE("ether-phy", 10, "ref", 0x2260, 0),
        UNIPHIER_PRO4_SYS_CLK_GIO(12),                  /* Ether, SATA, USB3 */
        UNIPHIER_PRO4_SYS_CLK_USB3(14, 0),
        UNIPHIER_PRO4_SYS_CLK_USB3(15, 1),
+       UNIPHIER_CLK_GATE("sata0", 28, NULL, 0x2104, 18),
+       UNIPHIER_CLK_GATE("sata1", 29, NULL, 0x2104, 19),
+       UNIPHIER_PRO4_SYS_CLK_AIO(40),
        { /* sentinel */ }
 };
 
@@ -132,6 +146,8 @@ const struct uniphier_clk_data uniphier_pro5_sys_clk_data[] = {
        UNIPHIER_PRO4_SYS_CLK_GIO(12),                          /* PCIe, USB3 */
        UNIPHIER_PRO4_SYS_CLK_USB3(14, 0),
        UNIPHIER_PRO4_SYS_CLK_USB3(15, 1),
+       UNIPHIER_CLK_GATE("pcie", 24, NULL, 0x2108, 2),
+       UNIPHIER_PRO5_SYS_CLK_AIO(40),
        { /* sentinel */ }
 };
 
@@ -149,6 +165,8 @@ const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = {
        /* The document mentions 0x2104 bit 18, but not functional */
        UNIPHIER_CLK_GATE("usb30-phy", 16, NULL, 0x2104, 19),
        UNIPHIER_CLK_GATE("usb31-phy", 20, NULL, 0x2104, 20),
+       UNIPHIER_CLK_GATE("sata0", 28, NULL, 0x2104, 22),
+       UNIPHIER_PRO5_SYS_CLK_AIO(40),
        { /* sentinel */ }
 };
 
@@ -205,6 +223,7 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = {
        UNIPHIER_CLK_GATE("usb30", 14, NULL, 0x210c, 14),
        UNIPHIER_CLK_GATE("usb30-phy0", 16, NULL, 0x210c, 12),
        UNIPHIER_CLK_GATE("usb30-phy1", 17, NULL, 0x210c, 13),
+       UNIPHIER_CLK_GATE("pcie", 24, NULL, 0x210c, 4),
        UNIPHIER_LD11_SYS_CLK_AIO(40),
        UNIPHIER_LD11_SYS_CLK_EVEA(41),
        UNIPHIER_LD11_SYS_CLK_EXIV(42),
@@ -233,6 +252,8 @@ const struct uniphier_clk_data uniphier_pxs3_sys_clk_data[] = {
        UNIPHIER_LD20_SYS_CLK_SD,
        UNIPHIER_LD11_SYS_CLK_NAND(2),
        UNIPHIER_LD11_SYS_CLK_EMMC(4),
+       UNIPHIER_CLK_GATE("ether0", 6, NULL, 0x210c, 9),
+       UNIPHIER_CLK_GATE("ether1", 7, NULL, 0x210c, 10),
        UNIPHIER_CLK_GATE("usb30", 12, NULL, 0x210c, 4),        /* =GIO0 */
        UNIPHIER_CLK_GATE("usb31-0", 13, NULL, 0x210c, 5),      /* =GIO1 */
        UNIPHIER_CLK_GATE("usb31-1", 14, NULL, 0x210c, 6),      /* =GIO1-1 */
@@ -241,6 +262,10 @@ const struct uniphier_clk_data uniphier_pxs3_sys_clk_data[] = {
        UNIPHIER_CLK_GATE("usb30-phy2", 18, NULL, 0x210c, 20),
        UNIPHIER_CLK_GATE("usb31-phy0", 20, NULL, 0x210c, 17),
        UNIPHIER_CLK_GATE("usb31-phy1", 21, NULL, 0x210c, 19),
+       UNIPHIER_CLK_GATE("pcie", 24, NULL, 0x210c, 3),
+       UNIPHIER_CLK_GATE("sata0", 28, NULL, 0x210c, 7),
+       UNIPHIER_CLK_GATE("sata1", 29, NULL, 0x210c, 8),
+       UNIPHIER_CLK_GATE("sata-phy", 30, NULL, 0x210c, 21),
        /* CPU gears */
        UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8),
        UNIPHIER_CLK_DIV4("spll", 2, 3, 4, 8),
index fedc083dc8beda67140e252b406123b9c980ea6c..53fd29002401a82aca05c048cc339b0f39dc50e0 100644 (file)
@@ -10,8 +10,6 @@ obj-y += clk-sysctrl.o
 
 # Clock definitions
 obj-y += u8500_of_clk.o
-obj-y += u9540_clk.o
-obj-y += u8540_clk.o
 
 # ABX500 clock driver
 obj-y += abx500-clk.o
index 2257d12ba988c54b7969c3aee1f99473d908d98b..5a86cd8fe5dee8fd6bb17381e2551dd36cedbb52 100644 (file)
@@ -88,18 +88,6 @@ static int ab8500_reg_clks(struct device *dev)
        return 0;
 }
 
-/* Clock definitions for ab8540 */
-static int ab8540_reg_clks(struct device *dev)
-{
-       return 0;
-}
-
-/* Clock definitions for ab9540 */
-static int ab9540_reg_clks(struct device *dev)
-{
-       return 0;
-}
-
 static int abx500_clk_probe(struct platform_device *pdev)
 {
        struct ab8500 *parent = dev_get_drvdata(pdev->dev.parent);
@@ -107,10 +95,6 @@ static int abx500_clk_probe(struct platform_device *pdev)
 
        if (is_ab8500(parent) || is_ab8505(parent)) {
                ret = ab8500_reg_clks(&pdev->dev);
-       } else if (is_ab8540(parent)) {
-               ret = ab8540_reg_clks(&pdev->dev);
-       } else if (is_ab9540(parent)) {
-               ret = ab9540_reg_clks(&pdev->dev);
        } else {
                dev_err(&pdev->dev, "non supported plf id\n");
                return -ENODEV;
diff --git a/drivers/clk/ux500/u8540_clk.c b/drivers/clk/ux500/u8540_clk.c
deleted file mode 100644 (file)
index 133859f..0000000
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * Clock definitions for u8540 platform.
- *
- * Copyright (C) 2012 ST-Ericsson SA
- * Author: Ulf Hansson <ulf.hansson@linaro.org>
- *
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/clkdev.h>
-#include <linux/clk-provider.h>
-#include <linux/mfd/dbx500-prcmu.h>
-#include "clk.h"
-
-/* CLKRST4 is missing making it hard to index things */
-enum clkrst_index {
-       CLKRST1_INDEX = 0,
-       CLKRST2_INDEX,
-       CLKRST3_INDEX,
-       CLKRST5_INDEX,
-       CLKRST6_INDEX,
-       CLKRST_MAX,
-};
-
-static void u8540_clk_init(struct device_node *np)
-{
-       struct clk *clk;
-       u32 bases[CLKRST_MAX];
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(bases); i++) {
-               struct resource r;
-
-               if (of_address_to_resource(np, i, &r))
-                       /* Not much choice but to continue */
-                       pr_err("failed to get CLKRST %d base address\n",
-                              i + 1);
-               bases[i] = r.start;
-       }
-
-       /* Clock sources. */
-       /* Fixed ClockGen */
-       clk = clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0,
-                               CLK_IGNORE_UNUSED);
-       clk_register_clkdev(clk, "soc0_pll", NULL);
-
-       clk = clk_reg_prcmu_gate("soc1_pll", NULL, PRCMU_PLLSOC1,
-                               CLK_IGNORE_UNUSED);
-       clk_register_clkdev(clk, "soc1_pll", NULL);
-
-       clk = clk_reg_prcmu_gate("ddr_pll", NULL, PRCMU_PLLDDR,
-                               CLK_IGNORE_UNUSED);
-       clk_register_clkdev(clk, "ddr_pll", NULL);
-
-       clk = clk_register_fixed_rate(NULL, "rtc32k", NULL,
-                               CLK_IGNORE_UNUSED,
-                               32768);
-       clk_register_clkdev(clk, "clk32k", NULL);
-       clk_register_clkdev(clk, "apb_pclk", "rtc-pl031");
-
-       clk = clk_register_fixed_rate(NULL, "ulp38m4", NULL,
-                               CLK_IGNORE_UNUSED,
-                               38400000);
-
-       clk = clk_reg_prcmu_gate("uartclk", NULL, PRCMU_UARTCLK, 0);
-       clk_register_clkdev(clk, NULL, "UART");
-
-       /* msp02clk needs a abx500 clk as parent. Handle by abx500 clk driver */
-       clk = clk_reg_prcmu_gate("msp02clk", "ab9540_sysclk12_b1",
-                       PRCMU_MSP02CLK, 0);
-       clk_register_clkdev(clk, NULL, "MSP02");
-
-       clk = clk_reg_prcmu_gate("msp1clk", NULL, PRCMU_MSP1CLK, 0);
-       clk_register_clkdev(clk, NULL, "MSP1");
-
-       clk = clk_reg_prcmu_gate("i2cclk", NULL, PRCMU_I2CCLK, 0);
-       clk_register_clkdev(clk, NULL, "I2C");
-
-       clk = clk_reg_prcmu_gate("slimclk", NULL, PRCMU_SLIMCLK, 0);
-       clk_register_clkdev(clk, NULL, "slim");
-
-       clk = clk_reg_prcmu_gate("per1clk", NULL, PRCMU_PER1CLK, 0);
-       clk_register_clkdev(clk, NULL, "PERIPH1");
-
-       clk = clk_reg_prcmu_gate("per2clk", NULL, PRCMU_PER2CLK, 0);
-       clk_register_clkdev(clk, NULL, "PERIPH2");
-
-       clk = clk_reg_prcmu_gate("per3clk", NULL, PRCMU_PER3CLK, 0);
-       clk_register_clkdev(clk, NULL, "PERIPH3");
-
-       clk = clk_reg_prcmu_gate("per5clk", NULL, PRCMU_PER5CLK, 0);
-       clk_register_clkdev(clk, NULL, "PERIPH5");
-
-       clk = clk_reg_prcmu_gate("per6clk", NULL, PRCMU_PER6CLK, 0);
-       clk_register_clkdev(clk, NULL, "PERIPH6");
-
-       clk = clk_reg_prcmu_gate("per7clk", NULL, PRCMU_PER7CLK, 0);
-       clk_register_clkdev(clk, NULL, "PERIPH7");
-
-       clk = clk_reg_prcmu_scalable("lcdclk", NULL, PRCMU_LCDCLK, 0,
-                               CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "lcd");
-       clk_register_clkdev(clk, "lcd", "mcde");
-
-       clk = clk_reg_prcmu_opp_gate("bmlclk", NULL, PRCMU_BMLCLK, 0);
-       clk_register_clkdev(clk, NULL, "bml");
-
-       clk = clk_reg_prcmu_scalable("hsitxclk", NULL, PRCMU_HSITXCLK, 0,
-                                    CLK_SET_RATE_GATE);
-
-       clk = clk_reg_prcmu_scalable("hsirxclk", NULL, PRCMU_HSIRXCLK, 0,
-                                    CLK_SET_RATE_GATE);
-
-       clk = clk_reg_prcmu_scalable("hdmiclk", NULL, PRCMU_HDMICLK, 0,
-                                    CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "hdmi");
-       clk_register_clkdev(clk, "hdmi", "mcde");
-
-       clk = clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, 0);
-       clk_register_clkdev(clk, NULL, "apeat");
-
-       clk = clk_reg_prcmu_gate("apetraceclk", NULL, PRCMU_APETRACECLK, 0);
-       clk_register_clkdev(clk, NULL, "apetrace");
-
-       clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, 0);
-       clk_register_clkdev(clk, NULL, "mcde");
-       clk_register_clkdev(clk, "mcde", "mcde");
-       clk_register_clkdev(clk, NULL, "dsilink.0");
-       clk_register_clkdev(clk, NULL, "dsilink.1");
-       clk_register_clkdev(clk, NULL, "dsilink.2");
-
-       clk = clk_reg_prcmu_opp_gate("ipi2cclk", NULL, PRCMU_IPI2CCLK, 0);
-       clk_register_clkdev(clk, NULL, "ipi2");
-
-       clk = clk_reg_prcmu_gate("dsialtclk", NULL, PRCMU_DSIALTCLK, 0);
-       clk_register_clkdev(clk, NULL, "dsialt");
-
-       clk = clk_reg_prcmu_gate("dmaclk", NULL, PRCMU_DMACLK, 0);
-       clk_register_clkdev(clk, NULL, "dma40.0");
-
-       clk = clk_reg_prcmu_gate("b2r2clk", NULL, PRCMU_B2R2CLK, 0);
-       clk_register_clkdev(clk, NULL, "b2r2");
-       clk_register_clkdev(clk, NULL, "b2r2_core");
-       clk_register_clkdev(clk, NULL, "U8500-B2R2.0");
-       clk_register_clkdev(clk, NULL, "b2r2_1_core");
-
-       clk = clk_reg_prcmu_scalable("tvclk", NULL, PRCMU_TVCLK, 0,
-                                    CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "tv");
-       clk_register_clkdev(clk, "tv", "mcde");
-
-       clk = clk_reg_prcmu_gate("sspclk", NULL, PRCMU_SSPCLK, 0);
-       clk_register_clkdev(clk, NULL, "SSP");
-
-       clk = clk_reg_prcmu_gate("rngclk", NULL, PRCMU_RNGCLK, 0);
-       clk_register_clkdev(clk, NULL, "rngclk");
-
-       clk = clk_reg_prcmu_gate("uiccclk", NULL, PRCMU_UICCCLK, 0);
-       clk_register_clkdev(clk, NULL, "uicc");
-
-       clk = clk_reg_prcmu_gate("timclk", NULL, PRCMU_TIMCLK, 0);
-       clk_register_clkdev(clk, NULL, "mtu0");
-       clk_register_clkdev(clk, NULL, "mtu1");
-
-       clk = clk_reg_prcmu_opp_volt_scalable("sdmmcclk", NULL,
-                                       PRCMU_SDMMCCLK, 100000000,
-                                       CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdmmc");
-
-       clk = clk_reg_prcmu_opp_volt_scalable("sdmmchclk", NULL,
-                                       PRCMU_SDMMCHCLK, 400000000,
-                                       CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdmmchclk");
-
-       clk = clk_reg_prcmu_gate("hvaclk", NULL, PRCMU_HVACLK, 0);
-       clk_register_clkdev(clk, NULL, "hva");
-
-       clk = clk_reg_prcmu_gate("g1clk", NULL, PRCMU_G1CLK, 0);
-       clk_register_clkdev(clk, NULL, "g1");
-
-       clk = clk_reg_prcmu_scalable("spare1clk", NULL, PRCMU_SPARE1CLK, 0,
-                                    CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsilcd", "mcde");
-
-       clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk",
-                               PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsihs2", "mcde");
-       clk_register_clkdev(clk, "hs_clk", "dsilink.2");
-
-       clk = clk_reg_prcmu_scalable("dsilcd_pll", "spare1clk",
-                               PRCMU_PLLDSI_LCD, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsilcd_pll", "mcde");
-
-       clk = clk_reg_prcmu_scalable("dsi0clk", "dsi_pll",
-                               PRCMU_DSI0CLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsihs0", "mcde");
-
-       clk = clk_reg_prcmu_scalable("dsi0lcdclk", "dsilcd_pll",
-                               PRCMU_DSI0CLK_LCD, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsihs0", "mcde");
-       clk_register_clkdev(clk, "hs_clk", "dsilink.0");
-
-       clk = clk_reg_prcmu_scalable("dsi1clk", "dsi_pll",
-                               PRCMU_DSI1CLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsihs1", "mcde");
-
-       clk = clk_reg_prcmu_scalable("dsi1lcdclk", "dsilcd_pll",
-                               PRCMU_DSI1CLK_LCD, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsihs1", "mcde");
-       clk_register_clkdev(clk, "hs_clk", "dsilink.1");
-
-       clk = clk_reg_prcmu_scalable("dsi0escclk", "tvclk",
-                               PRCMU_DSI0ESCCLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "lp_clk", "dsilink.0");
-       clk_register_clkdev(clk, "dsilp0", "mcde");
-
-       clk = clk_reg_prcmu_scalable("dsi1escclk", "tvclk",
-                               PRCMU_DSI1ESCCLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "lp_clk", "dsilink.1");
-       clk_register_clkdev(clk, "dsilp1", "mcde");
-
-       clk = clk_reg_prcmu_scalable("dsi2escclk", "tvclk",
-                               PRCMU_DSI2ESCCLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "lp_clk", "dsilink.2");
-       clk_register_clkdev(clk, "dsilp2", "mcde");
-
-       clk = clk_reg_prcmu_scalable_rate("armss", NULL,
-                               PRCMU_ARMSS, 0, CLK_IGNORE_UNUSED);
-       clk_register_clkdev(clk, "armss", NULL);
-
-       clk = clk_register_fixed_factor(NULL, "smp_twd", "armss",
-                               CLK_IGNORE_UNUSED, 1, 2);
-       clk_register_clkdev(clk, NULL, "smp_twd");
-
-       /* PRCC P-clocks */
-       /* Peripheral 1 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", bases[CLKRST1_INDEX],
-                               BIT(0), 0);
-       clk_register_clkdev(clk, "apb_pclk", "uart0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", bases[CLKRST1_INDEX],
-                               BIT(1), 0);
-       clk_register_clkdev(clk, "apb_pclk", "uart1");
-
-       clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", bases[CLKRST1_INDEX],
-                               BIT(2), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1");
-
-       clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", bases[CLKRST1_INDEX],
-                               BIT(3), 0);
-       clk_register_clkdev(clk, "apb_pclk", "msp0");
-       clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", bases[CLKRST1_INDEX],
-                               BIT(4), 0);
-       clk_register_clkdev(clk, "apb_pclk", "msp1");
-       clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.1");
-
-       clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", bases[CLKRST1_INDEX],
-                               BIT(5), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", bases[CLKRST1_INDEX],
-                               BIT(6), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2");
-
-       clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", bases[CLKRST1_INDEX],
-                               BIT(7), 0);
-       clk_register_clkdev(clk, NULL, "spi3");
-
-       clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", bases[CLKRST1_INDEX],
-                               BIT(8), 0);
-       clk_register_clkdev(clk, "apb_pclk", "slimbus0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", bases[CLKRST1_INDEX],
-                               BIT(9), 0);
-       clk_register_clkdev(clk, NULL, "gpio.0");
-       clk_register_clkdev(clk, NULL, "gpio.1");
-       clk_register_clkdev(clk, NULL, "gpioblock0");
-       clk_register_clkdev(clk, "apb_pclk", "ab85xx-codec.0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", bases[CLKRST1_INDEX],
-                               BIT(10), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4");
-
-       clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", bases[CLKRST1_INDEX],
-                               BIT(11), 0);
-       clk_register_clkdev(clk, "apb_pclk", "msp3");
-       clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.3");
-
-       /* Peripheral 2 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", bases[CLKRST2_INDEX],
-                               BIT(0), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3");
-
-       clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", bases[CLKRST2_INDEX],
-                               BIT(1), 0);
-       clk_register_clkdev(clk, NULL, "spi2");
-
-       clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", bases[CLKRST2_INDEX],
-                               BIT(2), 0);
-       clk_register_clkdev(clk, NULL, "spi1");
-
-       clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", bases[CLKRST2_INDEX],
-                               BIT(3), 0);
-       clk_register_clkdev(clk, NULL, "pwl");
-
-       clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", bases[CLKRST2_INDEX],
-                               BIT(4), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi4");
-
-       clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", bases[CLKRST2_INDEX],
-                               BIT(5), 0);
-       clk_register_clkdev(clk, "apb_pclk", "msp2");
-       clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.2");
-
-       clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", bases[CLKRST2_INDEX],
-                               BIT(6), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi1");
-
-       clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", bases[CLKRST2_INDEX],
-                               BIT(7), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi3");
-
-       clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", bases[CLKRST2_INDEX],
-                               BIT(8), 0);
-       clk_register_clkdev(clk, NULL, "spi0");
-
-       clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", bases[CLKRST2_INDEX],
-                               BIT(9), 0);
-       clk_register_clkdev(clk, "hsir_hclk", "ste_hsi.0");
-
-       clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", bases[CLKRST2_INDEX],
-                               BIT(10), 0);
-       clk_register_clkdev(clk, "hsit_hclk", "ste_hsi.0");
-
-       clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", bases[CLKRST2_INDEX],
-                               BIT(11), 0);
-       clk_register_clkdev(clk, NULL, "gpio.6");
-       clk_register_clkdev(clk, NULL, "gpio.7");
-       clk_register_clkdev(clk, NULL, "gpioblock1");
-
-       clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", bases[CLKRST2_INDEX],
-                               BIT(12), 0);
-       clk_register_clkdev(clk, "msp4-pclk", "ab85xx-codec.0");
-
-       /* Peripheral 3 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", bases[CLKRST3_INDEX],
-                               BIT(0), 0);
-       clk_register_clkdev(clk, NULL, "fsmc");
-
-       clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", bases[CLKRST3_INDEX],
-                               BIT(1), 0);
-       clk_register_clkdev(clk, "apb_pclk", "ssp0");
-
-       clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", bases[CLKRST3_INDEX],
-                               BIT(2), 0);
-       clk_register_clkdev(clk, "apb_pclk", "ssp1");
-
-       clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", bases[CLKRST3_INDEX],
-                               BIT(3), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0");
-
-       clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", bases[CLKRST3_INDEX],
-                               BIT(4), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi2");
-
-       clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", bases[CLKRST3_INDEX],
-                               BIT(5), 0);
-       clk_register_clkdev(clk, "apb_pclk", "ske");
-       clk_register_clkdev(clk, "apb_pclk", "nmk-ske-keypad");
-
-       clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", bases[CLKRST3_INDEX],
-                               BIT(6), 0);
-       clk_register_clkdev(clk, "apb_pclk", "uart2");
-
-       clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", bases[CLKRST3_INDEX],
-                               BIT(7), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi5");
-
-       clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", bases[CLKRST3_INDEX],
-                               BIT(8), 0);
-       clk_register_clkdev(clk, NULL, "gpio.2");
-       clk_register_clkdev(clk, NULL, "gpio.3");
-       clk_register_clkdev(clk, NULL, "gpio.4");
-       clk_register_clkdev(clk, NULL, "gpio.5");
-       clk_register_clkdev(clk, NULL, "gpioblock2");
-
-       clk = clk_reg_prcc_pclk("p3_pclk9", "per3clk", bases[CLKRST3_INDEX],
-                               BIT(9), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.5");
-
-       clk = clk_reg_prcc_pclk("p3_pclk10", "per3clk", bases[CLKRST3_INDEX],
-                               BIT(10), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.6");
-
-       clk = clk_reg_prcc_pclk("p3_pclk11", "per3clk", bases[CLKRST3_INDEX],
-                               BIT(11), 0);
-       clk_register_clkdev(clk, "apb_pclk", "uart3");
-
-       clk = clk_reg_prcc_pclk("p3_pclk12", "per3clk", bases[CLKRST3_INDEX],
-                               BIT(12), 0);
-       clk_register_clkdev(clk, "apb_pclk", "uart4");
-
-       /* Peripheral 5 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", bases[CLKRST5_INDEX],
-                               BIT(0), 0);
-       clk_register_clkdev(clk, "usb", "musb-ux500.0");
-       clk_register_clkdev(clk, "usbclk", "ab-iddet.0");
-
-       clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", bases[CLKRST5_INDEX],
-                               BIT(1), 0);
-       clk_register_clkdev(clk, NULL, "gpio.8");
-       clk_register_clkdev(clk, NULL, "gpioblock3");
-
-       /* Peripheral 6 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", bases[CLKRST6_INDEX],
-                               BIT(0), 0);
-       clk_register_clkdev(clk, "apb_pclk", "rng");
-
-       clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", bases[CLKRST6_INDEX],
-                               BIT(1), 0);
-       clk_register_clkdev(clk, NULL, "cryp0");
-       clk_register_clkdev(clk, NULL, "cryp1");
-
-       clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", bases[CLKRST6_INDEX],
-                               BIT(2), 0);
-       clk_register_clkdev(clk, NULL, "hash0");
-
-       clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", bases[CLKRST6_INDEX],
-                               BIT(3), 0);
-       clk_register_clkdev(clk, NULL, "pka");
-
-       clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", bases[CLKRST6_INDEX],
-                               BIT(4), 0);
-       clk_register_clkdev(clk, NULL, "db8540-hash1");
-
-       clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", bases[CLKRST6_INDEX],
-                               BIT(5), 0);
-       clk_register_clkdev(clk, NULL, "cfgreg");
-
-       clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", bases[CLKRST6_INDEX],
-                               BIT(6), 0);
-       clk_register_clkdev(clk, "apb_pclk", "mtu0");
-
-       clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", bases[CLKRST6_INDEX],
-                               BIT(7), 0);
-       clk_register_clkdev(clk, "apb_pclk", "mtu1");
-
-       /*
-        * PRCC K-clocks  ==> see table PRCC_PCKEN/PRCC_KCKEN
-        * This differs from the internal implementation:
-        * We don't use the PERPIH[n| clock as parent, since those _should_
-        * only be used as parents for the P-clocks.
-        * TODO: "parentjoin" with corresponding P-clocks for all K-clocks.
-        */
-
-       /* Peripheral 1 : PRCC K-clocks */
-       clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk",
-                       bases[CLKRST1_INDEX], BIT(0), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "uart0");
-
-       clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk",
-                       bases[CLKRST1_INDEX], BIT(1), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "uart1");
-
-       clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
-                       bases[CLKRST1_INDEX], BIT(2), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.1");
-
-       clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
-                       bases[CLKRST1_INDEX], BIT(3), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "msp0");
-       clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.0");
-
-       clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
-                       bases[CLKRST1_INDEX], BIT(4), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "msp1");
-       clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.1");
-
-       clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmchclk",
-                       bases[CLKRST1_INDEX], BIT(5), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi0");
-
-       clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
-                       bases[CLKRST1_INDEX], BIT(6), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.2");
-
-       clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
-                       bases[CLKRST1_INDEX], BIT(8), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "slimbus0");
-
-       clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
-                       bases[CLKRST1_INDEX], BIT(9), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.4");
-
-       clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
-                       bases[CLKRST1_INDEX], BIT(10), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "msp3");
-       clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.3");
-
-       /* Peripheral 2 : PRCC K-clocks */
-       clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
-                       bases[CLKRST2_INDEX], BIT(0), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.3");
-
-       clk = clk_reg_prcc_kclk("p2_pwl_kclk", "rtc32k",
-                       bases[CLKRST2_INDEX], BIT(1), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "pwl");
-
-       clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmchclk",
-                       bases[CLKRST2_INDEX], BIT(2), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi4");
-
-       clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
-                       bases[CLKRST2_INDEX], BIT(3), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "msp2");
-       clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.2");
-
-       clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmchclk",
-                       bases[CLKRST2_INDEX], BIT(4), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi1");
-
-       clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk",
-                       bases[CLKRST2_INDEX], BIT(5), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi3");
-
-       clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk",
-                       bases[CLKRST2_INDEX], BIT(6),
-                       CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
-       clk_register_clkdev(clk, "hsir_hsirxclk", "ste_hsi.0");
-
-       clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk",
-                       bases[CLKRST2_INDEX], BIT(7),
-                       CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
-       clk_register_clkdev(clk, "hsit_hsitxclk", "ste_hsi.0");
-
-       /* Should only be 9540, but might be added for 85xx as well */
-       clk = clk_reg_prcc_kclk("p2_msp4_kclk", "msp02clk",
-                       bases[CLKRST2_INDEX], BIT(9), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "msp4");
-       clk_register_clkdev(clk, "msp4", "ab85xx-codec.0");
-
-       /* Peripheral 3 : PRCC K-clocks */
-       clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
-                       bases[CLKRST3_INDEX], BIT(1), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "ssp0");
-
-       clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
-                       bases[CLKRST3_INDEX], BIT(2), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "ssp1");
-
-       clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
-                       bases[CLKRST3_INDEX], BIT(3), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.0");
-
-       clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmchclk",
-                       bases[CLKRST3_INDEX], BIT(4), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi2");
-
-       clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k",
-                       bases[CLKRST3_INDEX], BIT(5), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "ske");
-       clk_register_clkdev(clk, NULL, "nmk-ske-keypad");
-
-       clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk",
-                       bases[CLKRST3_INDEX], BIT(6), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "uart2");
-
-       clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk",
-                       bases[CLKRST3_INDEX], BIT(7), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi5");
-
-       clk = clk_reg_prcc_kclk("p3_i2c5_kclk", "i2cclk",
-                       bases[CLKRST3_INDEX], BIT(8), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.5");
-
-       clk = clk_reg_prcc_kclk("p3_i2c6_kclk", "i2cclk",
-                       bases[CLKRST3_INDEX], BIT(9), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.6");
-
-       clk = clk_reg_prcc_kclk("p3_uart3_kclk", "uartclk",
-                       bases[CLKRST3_INDEX], BIT(10), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "uart3");
-
-       clk = clk_reg_prcc_kclk("p3_uart4_kclk", "uartclk",
-                       bases[CLKRST3_INDEX], BIT(11), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "uart4");
-
-       /* Peripheral 6 : PRCC K-clocks */
-       clk = clk_reg_prcc_kclk("p6_rng_kclk", "rngclk",
-                       bases[CLKRST6_INDEX], BIT(0), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "rng");
-}
-CLK_OF_DECLARE(u8540_clks, "stericsson,u8540-clks", u8540_clk_init);
diff --git a/drivers/clk/ux500/u9540_clk.c b/drivers/clk/ux500/u9540_clk.c
deleted file mode 100644 (file)
index 7b6bca4..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Clock definitions for u9540 platform.
- *
- * Copyright (C) 2012 ST-Ericsson SA
- * Author: Ulf Hansson <ulf.hansson@linaro.org>
- *
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#include <linux/clk-provider.h>
-#include <linux/mfd/dbx500-prcmu.h>
-#include "clk.h"
-
-static void u9540_clk_init(struct device_node *np)
-{
-       /* register clocks here */
-}
-CLK_OF_DECLARE(u9540_clks, "stericsson,u9540-clks", u9540_clk_init);
index e7a868b83fe54e8add04ef9c59bb82ff3f23c67f..dd08ecb498be289a6f23dfd7d2f309d254e6dd68 100644 (file)
@@ -44,10 +44,10 @@ static long vexpress_osc_round_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct vexpress_osc *osc = to_vexpress_osc(hw);
 
-       if (WARN_ON(osc->rate_min && rate < osc->rate_min))
+       if (osc->rate_min && rate < osc->rate_min)
                rate = osc->rate_min;
 
-       if (WARN_ON(osc->rate_max && rate > osc->rate_max))
+       if (osc->rate_max && rate > osc->rate_max)
                rate = osc->rate_max;
 
        return rate;
@@ -104,6 +104,7 @@ static int vexpress_osc_probe(struct platform_device *pdev)
                return PTR_ERR(clk);
 
        of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, clk);
+       clk_hw_set_rate_range(&osc->hw, osc->rate_min, osc->rate_max);
 
        dev_dbg(&pdev->dev, "Registered clock '%s'\n", init.name);
 
index b6a436594a199df1b8193d4dd1de032b53c64f06..caf45cf7aa8e638925cc5ad3c10e21d0b2071bd8 100644 (file)
@@ -147,6 +147,12 @@ static __init const char *exynos_get_domain_name(struct device_node *node)
        return kstrdup_const(name, GFP_KERNEL);
 }
 
+static const char *soc_force_no_clk[] = {
+       "samsung,exynos5250-clock",
+       "samsung,exynos5420-clock",
+       "samsung,exynos5800-clock",
+};
+
 static __init int exynos4_pm_init_power_domain(void)
 {
        struct device_node *np;
@@ -183,6 +189,11 @@ static __init int exynos4_pm_init_power_domain(void)
                pd->pd.power_on = exynos_pd_power_on;
                pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg;
 
+               for (i = 0; i < ARRAY_SIZE(soc_force_no_clk); i++)
+                       if (of_find_compatible_node(NULL, NULL,
+                                                   soc_force_no_clk[i]))
+                               goto no_clk;
+
                for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
                        char clk_name[8];
 
index 941ac70e7f3083842f98a96a75a13b9fc18da3fa..555937a25504b76c5ed23f46d2d93713b0e446da 100644 (file)
@@ -67,5 +67,6 @@
 #define CLKID_AO_I2C                           58
 #define CLKID_SD_EMMC_B_CLK0                   59
 #define CLKID_SD_EMMC_C_CLK0                   60
+#define CLKID_HIFI_PLL                         69
 
 #endif /* __AXG_CLKC_H */
index 067f5e501b0c4f2c75f979d221c5cf37d234e244..fab30b3f78b26494d31d73ed8a4e8efd8f7f2191 100644 (file)
 #define HISTB_OSC_CLK                  0
 #define HISTB_APB_CLK                  1
 #define HISTB_AHB_CLK                  2
-#define HISTB_UART1_CLK                3
-#define HISTB_UART2_CLK                4
-#define HISTB_UART3_CLK                5
-#define HISTB_I2C0_CLK         6
-#define HISTB_I2C1_CLK         7
-#define HISTB_I2C2_CLK         8
-#define HISTB_I2C3_CLK         9
-#define HISTB_I2C4_CLK         10
-#define HISTB_I2C5_CLK         11
-#define HISTB_SPI0_CLK         12
-#define HISTB_SPI1_CLK         13
-#define HISTB_SPI2_CLK         14
+#define HISTB_UART1_CLK                        3
+#define HISTB_UART2_CLK                        4
+#define HISTB_UART3_CLK                        5
+#define HISTB_I2C0_CLK                 6
+#define HISTB_I2C1_CLK                 7
+#define HISTB_I2C2_CLK                 8
+#define HISTB_I2C3_CLK                 9
+#define HISTB_I2C4_CLK                 10
+#define HISTB_I2C5_CLK                 11
+#define HISTB_SPI0_CLK                 12
+#define HISTB_SPI1_CLK                 13
+#define HISTB_SPI2_CLK                 14
 #define HISTB_SCI_CLK                  15
 #define HISTB_FMC_CLK                  16
 #define HISTB_MMC_BIU_CLK              17
@@ -43,7 +43,7 @@
 #define HISTB_SDIO0_BIU_CLK            21
 #define HISTB_SDIO0_CIU_CLK            22
 #define HISTB_SDIO0_DRV_CLK            23
-#define HISTB_SDIO0_SAMPLE_CLK 24
+#define HISTB_SDIO0_SAMPLE_CLK         24
 #define HISTB_PCIE_AUX_CLK             25
 #define HISTB_PCIE_PIPE_CLK            26
 #define HISTB_PCIE_SYS_CLK             27
 #define HISTB_ETH1_MAC_CLK             31
 #define HISTB_ETH1_MACIF_CLK           32
 #define HISTB_COMBPHY1_CLK             33
-#define HISTB_USB2_BUS_CLK     34
-#define HISTB_USB2_PHY_CLK     35
-#define HISTB_USB2_UTMI_CLK    36
-#define HISTB_USB2_12M_CLK     37
-#define HISTB_USB2_48M_CLK     38
-#define HISTB_USB2_OTG_UTMI_CLK        39
-#define HISTB_USB2_PHY1_REF_CLK        40
-#define HISTB_USB2_PHY2_REF_CLK        41
+#define HISTB_USB2_BUS_CLK             34
+#define HISTB_USB2_PHY_CLK             35
+#define HISTB_USB2_UTMI_CLK            36
+#define HISTB_USB2_12M_CLK             37
+#define HISTB_USB2_48M_CLK             38
+#define HISTB_USB2_OTG_UTMI_CLK                39
+#define HISTB_USB2_PHY1_REF_CLK                40
+#define HISTB_USB2_PHY2_REF_CLK                41
+#define HISTB_COMBPHY0_CLK             42
 
 /* clocks provided by mcu CRG */
-#define HISTB_MCE_CLK  1
-#define HISTB_IR_CLK   2
-#define HISTB_TIMER01_CLK      3
-#define HISTB_LEDC_CLK 4
-#define HISTB_UART0_CLK        5
-#define HISTB_LSADC_CLK        6
+#define HISTB_MCE_CLK                  1
+#define HISTB_IR_CLK                   2
+#define HISTB_TIMER01_CLK              3
+#define HISTB_LEDC_CLK                 4
+#define HISTB_UART0_CLK                        5
+#define HISTB_LSADC_CLK                        6
 
 #endif /* __DTS_HISTB_CLOCK_H */
diff --git a/include/dt-bindings/clock/imx6sll-clock.h b/include/dt-bindings/clock/imx6sll-clock.h
new file mode 100644 (file)
index 0000000..151111e
--- /dev/null
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2018 NXP.
+ *
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX6SLL_H
+#define __DT_BINDINGS_CLOCK_IMX6SLL_H
+
+#define IMX6SLL_CLK_DUMMY              0
+#define IMX6SLL_CLK_CKIL               1
+#define IMX6SLL_CLK_OSC                        2
+#define IMX6SLL_PLL1_BYPASS_SRC                3
+#define IMX6SLL_PLL2_BYPASS_SRC                4
+#define IMX6SLL_PLL3_BYPASS_SRC                5
+#define IMX6SLL_PLL4_BYPASS_SRC                6
+#define IMX6SLL_PLL5_BYPASS_SRC                7
+#define IMX6SLL_PLL6_BYPASS_SRC                8
+#define IMX6SLL_PLL7_BYPASS_SRC                9
+#define IMX6SLL_CLK_PLL1               10
+#define IMX6SLL_CLK_PLL2               11
+#define IMX6SLL_CLK_PLL3               12
+#define IMX6SLL_CLK_PLL4               13
+#define IMX6SLL_CLK_PLL5               14
+#define IMX6SLL_CLK_PLL6               15
+#define IMX6SLL_CLK_PLL7               16
+#define IMX6SLL_PLL1_BYPASS            17
+#define IMX6SLL_PLL2_BYPASS            18
+#define IMX6SLL_PLL3_BYPASS            19
+#define IMX6SLL_PLL4_BYPASS            20
+#define IMX6SLL_PLL5_BYPASS            21
+#define IMX6SLL_PLL6_BYPASS            22
+#define IMX6SLL_PLL7_BYPASS            23
+#define IMX6SLL_CLK_PLL1_SYS           24
+#define IMX6SLL_CLK_PLL2_BUS           25
+#define IMX6SLL_CLK_PLL3_USB_OTG       26
+#define IMX6SLL_CLK_PLL4_AUDIO         27
+#define IMX6SLL_CLK_PLL5_VIDEO         28
+#define IMX6SLL_CLK_PLL6_ENET          29
+#define IMX6SLL_CLK_PLL7_USB_HOST      30
+#define IMX6SLL_CLK_USBPHY1            31
+#define IMX6SLL_CLK_USBPHY2            32
+#define IMX6SLL_CLK_USBPHY1_GATE       33
+#define IMX6SLL_CLK_USBPHY2_GATE       34
+#define IMX6SLL_CLK_PLL2_PFD0          35
+#define IMX6SLL_CLK_PLL2_PFD1          36
+#define IMX6SLL_CLK_PLL2_PFD2          37
+#define IMX6SLL_CLK_PLL2_PFD3          38
+#define IMX6SLL_CLK_PLL3_PFD0          39
+#define IMX6SLL_CLK_PLL3_PFD1          40
+#define IMX6SLL_CLK_PLL3_PFD2          41
+#define IMX6SLL_CLK_PLL3_PFD3          42
+#define IMX6SLL_CLK_PLL4_POST_DIV      43
+#define IMX6SLL_CLK_PLL4_AUDIO_DIV     44
+#define IMX6SLL_CLK_PLL5_POST_DIV      45
+#define IMX6SLL_CLK_PLL5_VIDEO_DIV     46
+#define IMX6SLL_CLK_PLL2_198M          47
+#define IMX6SLL_CLK_PLL3_120M          48
+#define IMX6SLL_CLK_PLL3_80M           49
+#define IMX6SLL_CLK_PLL3_60M           50
+#define IMX6SLL_CLK_STEP               51
+#define IMX6SLL_CLK_PLL1_SW            52
+#define IMX6SLL_CLK_AXI_ALT_SEL                53
+#define IMX6SLL_CLK_AXI_SEL            54
+#define IMX6SLL_CLK_PERIPH_PRE         55
+#define IMX6SLL_CLK_PERIPH2_PRE                56
+#define IMX6SLL_CLK_PERIPH_CLK2_SEL    57
+#define IMX6SLL_CLK_PERIPH2_CLK2_SEL   58
+#define IMX6SLL_CLK_PERCLK_SEL         59
+#define IMX6SLL_CLK_USDHC1_SEL         60
+#define IMX6SLL_CLK_USDHC2_SEL         61
+#define IMX6SLL_CLK_USDHC3_SEL         62
+#define IMX6SLL_CLK_SSI1_SEL           63
+#define IMX6SLL_CLK_SSI2_SEL           64
+#define IMX6SLL_CLK_SSI3_SEL           65
+#define IMX6SLL_CLK_PXP_SEL            66
+#define IMX6SLL_CLK_LCDIF_PRE_SEL      67
+#define IMX6SLL_CLK_LCDIF_SEL          68
+#define IMX6SLL_CLK_EPDC_PRE_SEL       69
+#define IMX6SLL_CLK_SPDIF_SEL          70
+#define IMX6SLL_CLK_ECSPI_SEL          71
+#define IMX6SLL_CLK_UART_SEL           72
+#define IMX6SLL_CLK_ARM                        73
+#define IMX6SLL_CLK_PERIPH             74
+#define IMX6SLL_CLK_PERIPH2            75
+#define IMX6SLL_CLK_PERIPH2_CLK2       76
+#define IMX6SLL_CLK_PERIPH_CLK2                77
+#define IMX6SLL_CLK_MMDC_PODF          78
+#define IMX6SLL_CLK_AXI_PODF           79
+#define IMX6SLL_CLK_AHB                        80
+#define IMX6SLL_CLK_IPG                        81
+#define IMX6SLL_CLK_PERCLK             82
+#define IMX6SLL_CLK_USDHC1_PODF                83
+#define IMX6SLL_CLK_USDHC2_PODF                84
+#define IMX6SLL_CLK_USDHC3_PODF                85
+#define IMX6SLL_CLK_SSI1_PRED          86
+#define IMX6SLL_CLK_SSI2_PRED          87
+#define IMX6SLL_CLK_SSI3_PRED          88
+#define IMX6SLL_CLK_SSI1_PODF          89
+#define IMX6SLL_CLK_SSI2_PODF          90
+#define IMX6SLL_CLK_SSI3_PODF          91
+#define IMX6SLL_CLK_PXP_PODF           92
+#define IMX6SLL_CLK_LCDIF_PRED         93
+#define IMX6SLL_CLK_LCDIF_PODF         94
+#define IMX6SLL_CLK_EPDC_SEL           95
+#define IMX6SLL_CLK_EPDC_PODF          96
+#define IMX6SLL_CLK_SPDIF_PRED         97
+#define IMX6SLL_CLK_SPDIF_PODF         98
+#define IMX6SLL_CLK_ECSPI_PODF         99
+#define IMX6SLL_CLK_UART_PODF          100
+
+/* CCGR 0 */
+#define IMX6SLL_CLK_AIPSTZ1            101
+#define IMX6SLL_CLK_AIPSTZ2            102
+#define IMX6SLL_CLK_DCP                        103
+#define IMX6SLL_CLK_UART2_IPG          104
+#define IMX6SLL_CLK_UART2_SERIAL       105
+
+/* CCGR 1 */
+#define IMX6SLL_CLK_ECSPI1             106
+#define IMX6SLL_CLK_ECSPI2             107
+#define IMX6SLL_CLK_ECSPI3             108
+#define IMX6SLL_CLK_ECSPI4             109
+#define IMX6SLL_CLK_UART3_IPG          110
+#define IMX6SLL_CLK_UART3_SERIAL       111
+#define IMX6SLL_CLK_UART4_IPG          112
+#define IMX6SLL_CLK_UART4_SERIAL       113
+#define IMX6SLL_CLK_EPIT1              114
+#define IMX6SLL_CLK_EPIT2              115
+#define IMX6SLL_CLK_GPT_BUS            116
+#define IMX6SLL_CLK_GPT_SERIAL         117
+
+/* CCGR2 */
+#define IMX6SLL_CLK_CSI                        118
+#define IMX6SLL_CLK_I2C1               119
+#define IMX6SLL_CLK_I2C2               120
+#define IMX6SLL_CLK_I2C3               121
+#define IMX6SLL_CLK_OCOTP              122
+#define IMX6SLL_CLK_LCDIF_APB          123
+#define IMX6SLL_CLK_PXP                        124
+
+/* CCGR3 */
+#define IMX6SLL_CLK_UART5_IPG          125
+#define IMX6SLL_CLK_UART5_SERIAL       126
+#define IMX6SLL_CLK_EPDC_AXI           127
+#define IMX6SLL_CLK_EPDC_PIX           128
+#define IMX6SLL_CLK_LCDIF_PIX          129
+#define IMX6SLL_CLK_WDOG1              130
+#define IMX6SLL_CLK_MMDC_P0_FAST       131
+#define IMX6SLL_CLK_MMDC_P0_IPG                132
+#define IMX6SLL_CLK_OCRAM              133
+
+/* CCGR4 */
+#define IMX6SLL_CLK_PWM1               134
+#define IMX6SLL_CLK_PWM2               135
+#define IMX6SLL_CLK_PWM3               136
+#define IMX6SLL_CLK_PWM4               137
+
+/* CCGR 5 */
+#define IMX6SLL_CLK_ROM                        138
+#define IMX6SLL_CLK_SDMA               139
+#define IMX6SLL_CLK_KPP                        140
+#define IMX6SLL_CLK_WDOG2              141
+#define IMX6SLL_CLK_SPBA               142
+#define IMX6SLL_CLK_SPDIF              143
+#define IMX6SLL_CLK_SPDIF_GCLK         144
+#define IMX6SLL_CLK_SSI1               145
+#define IMX6SLL_CLK_SSI1_IPG           146
+#define IMX6SLL_CLK_SSI2               147
+#define IMX6SLL_CLK_SSI2_IPG           148
+#define IMX6SLL_CLK_SSI3               149
+#define IMX6SLL_CLK_SSI3_IPG           150
+#define IMX6SLL_CLK_UART1_IPG          151
+#define IMX6SLL_CLK_UART1_SERIAL       152
+
+/* CCGR 6 */
+#define IMX6SLL_CLK_USBOH3             153
+#define IMX6SLL_CLK_USDHC1             154
+#define IMX6SLL_CLK_USDHC2             155
+#define IMX6SLL_CLK_USDHC3             156
+
+#define IMX6SLL_CLK_IPP_DI0            157
+#define IMX6SLL_CLK_IPP_DI1            158
+#define IMX6SLL_CLK_LDB_DI0_SEL                159
+#define IMX6SLL_CLK_LDB_DI0_DIV_3_5    160
+#define IMX6SLL_CLK_LDB_DI0_DIV_7      161
+#define IMX6SLL_CLK_LDB_DI0_DIV_SEL    162
+#define IMX6SLL_CLK_LDB_DI0            163
+#define IMX6SLL_CLK_LDB_DI1_SEL                164
+#define IMX6SLL_CLK_LDB_DI1_DIV_3_5    165
+#define IMX6SLL_CLK_LDB_DI1_DIV_7      166
+#define IMX6SLL_CLK_LDB_DI1_DIV_SEL    167
+#define IMX6SLL_CLK_LDB_DI1            168
+#define IMX6SLL_CLK_EXTERN_AUDIO_SEL    169
+#define IMX6SLL_CLK_EXTERN_AUDIO_PRED   170
+#define IMX6SLL_CLK_EXTERN_AUDIO_PODF   171
+#define IMX6SLL_CLK_EXTERN_AUDIO        172
+
+#define IMX6SLL_CLK_END                        173
+
+#endif /* __DT_BINDINGS_CLOCK_IMX6SLL_H */
index 551f7600ab586a46ff90548e9fcf977d9083674a..24e93dfcee9ffa40225544a9778d818841f99d81 100644 (file)
 #define CLK_TOP_AUD_EXT1                       156
 #define CLK_TOP_AUD_EXT2                       157
 #define CLK_TOP_NFI1X_PAD                      158
-#define CLK_TOP_NR                             159
+#define CLK_TOP_AXISEL_D4                      159
+#define CLK_TOP_NR                             160
 
 /* APMIXEDSYS */
 
index 48a8e797a617a8ac94d050f52442fd51decef5e8..76265836a1e1dcfac22e8fdbc2714de76c7d583d 100644 (file)
 #define CLK_TOP_APLL_DIV_PDN5          183
 #define CLK_TOP_APLL_DIV_PDN6          184
 #define CLK_TOP_APLL_DIV_PDN7          185
-#define CLK_TOP_NR_CLK                 186
+#define CLK_TOP_APLL1_D3               186
+#define CLK_TOP_APLL1_REF_SEL          187
+#define CLK_TOP_APLL2_REF_SEL          188
+#define CLK_TOP_NFI2X_EN               189
+#define CLK_TOP_NFIECC_EN              190
+#define CLK_TOP_NFI1X_CK_EN            191
+#define CLK_TOP_NR_CLK                 192
 
 /* INFRACFG */
 
 #define CLK_PERI_MSDC30_3_EN           41
 #define CLK_PERI_MSDC50_0_HCLK_EN      42
 #define CLK_PERI_MSDC50_3_HCLK_EN      43
-#define CLK_PERI_NR_CLK                        44
+#define CLK_PERI_MSDC30_0_QTR_EN       44
+#define CLK_PERI_MSDC30_3_QTR_EN       45
+#define CLK_PERI_NR_CLK                        46
 
 /* MCUCFG */
 
index 3e514ed51d153c0a20a9ab126cf8f50c232afc4a..e9d77f0e8bce6fc65ff7ad30cc86a1d9c2e753e6 100644 (file)
 #define CLK_AUDIO_MEM_ASRC3            43
 #define CLK_AUDIO_MEM_ASRC4            44
 #define CLK_AUDIO_MEM_ASRC5            45
-#define CLK_AUDIO_NR_CLK               46
+#define CLK_AUDIO_AFE_CONN             46
+#define CLK_AUDIO_NR_CLK               47
 
 /* SSUSBSYS */
 
index b8337a5fa34775330e28fb1a6c42aae20b520489..c585b82b9c056d489f8f383d8da9cf40bfb6948f 100644 (file)
 #define RPM_SMI_CLK                            22
 #define RPM_SMI_A_CLK                          23
 #define RPM_PLL4_CLK                           24
+#define RPM_XO_D0                              25
+#define RPM_XO_D1                              26
+#define RPM_XO_A0                              27
+#define RPM_XO_A1                              28
+#define RPM_XO_A2                              29
 
 /* SMD RPM clocks */
 #define RPM_SMD_XO_CLK_SRC                             0
diff --git a/include/dt-bindings/clock/r8a77965-cpg-mssr.h b/include/dt-bindings/clock/r8a77965-cpg-mssr.h
new file mode 100644 (file)
index 0000000..6d3b5a9
--- /dev/null
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Jacopo Mondi <jacopo+renesas@jmondi.org>
+ */
+#ifndef __DT_BINDINGS_CLOCK_R8A77965_CPG_MSSR_H__
+#define __DT_BINDINGS_CLOCK_R8A77965_CPG_MSSR_H__
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+/* r8a77965 CPG Core Clocks */
+#define R8A77965_CLK_Z                 0
+#define R8A77965_CLK_ZR                        1
+#define R8A77965_CLK_ZG                        2
+#define R8A77965_CLK_ZTR               3
+#define R8A77965_CLK_ZTRD2             4
+#define R8A77965_CLK_ZT                        5
+#define R8A77965_CLK_ZX                        6
+#define R8A77965_CLK_S0D1              7
+#define R8A77965_CLK_S0D2              8
+#define R8A77965_CLK_S0D3              9
+#define R8A77965_CLK_S0D4              10
+#define R8A77965_CLK_S0D6              11
+#define R8A77965_CLK_S0D8              12
+#define R8A77965_CLK_S0D12             13
+#define R8A77965_CLK_S1D1              14
+#define R8A77965_CLK_S1D2              15
+#define R8A77965_CLK_S1D4              16
+#define R8A77965_CLK_S2D1              17
+#define R8A77965_CLK_S2D2              18
+#define R8A77965_CLK_S2D4              19
+#define R8A77965_CLK_S3D1              20
+#define R8A77965_CLK_S3D2              21
+#define R8A77965_CLK_S3D4              22
+#define R8A77965_CLK_LB                        23
+#define R8A77965_CLK_CL                        24
+#define R8A77965_CLK_ZB3               25
+#define R8A77965_CLK_ZB3D2             26
+#define R8A77965_CLK_CR                        27
+#define R8A77965_CLK_CRD2              28
+#define R8A77965_CLK_SD0H              29
+#define R8A77965_CLK_SD0               30
+#define R8A77965_CLK_SD1H              31
+#define R8A77965_CLK_SD1               32
+#define R8A77965_CLK_SD2H              33
+#define R8A77965_CLK_SD2               34
+#define R8A77965_CLK_SD3H              35
+#define R8A77965_CLK_SD3               36
+#define R8A77965_CLK_SSP2              37
+#define R8A77965_CLK_SSP1              38
+#define R8A77965_CLK_SSPRS             39
+#define R8A77965_CLK_RPC               40
+#define R8A77965_CLK_RPCD2             41
+#define R8A77965_CLK_MSO               42
+#define R8A77965_CLK_CANFD             43
+#define R8A77965_CLK_HDMI              44
+#define R8A77965_CLK_CSI0              45
+#define R8A77965_CLK_CP                        46
+#define R8A77965_CLK_CPEX              47
+#define R8A77965_CLK_R                 48
+#define R8A77965_CLK_OSC               49
+
+#endif /* __DT_BINDINGS_CLOCK_R8A77965_CPG_MSSR_H__ */
diff --git a/include/dt-bindings/clock/r8a77980-cpg-mssr.h b/include/dt-bindings/clock/r8a77980-cpg-mssr.h
new file mode 100644 (file)
index 0000000..a4c0d76
--- /dev/null
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ * Copyright (C) 2018 Cogent Embedded, Inc.
+ */
+#ifndef __DT_BINDINGS_CLOCK_R8A77980_CPG_MSSR_H__
+#define __DT_BINDINGS_CLOCK_R8A77980_CPG_MSSR_H__
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+
+/* r8a77980 CPG Core Clocks */
+#define R8A77980_CLK_Z2                        0
+#define R8A77980_CLK_ZR                        1
+#define R8A77980_CLK_ZTR               2
+#define R8A77980_CLK_ZTRD2             3
+#define R8A77980_CLK_ZT                        4
+#define R8A77980_CLK_ZX                        5
+#define R8A77980_CLK_S0D1              6
+#define R8A77980_CLK_S0D2              7
+#define R8A77980_CLK_S0D3              8
+#define R8A77980_CLK_S0D4              9
+#define R8A77980_CLK_S0D6              10
+#define R8A77980_CLK_S0D12             11
+#define R8A77980_CLK_S0D24             12
+#define R8A77980_CLK_S1D1              13
+#define R8A77980_CLK_S1D2              14
+#define R8A77980_CLK_S1D4              15
+#define R8A77980_CLK_S2D1              16
+#define R8A77980_CLK_S2D2              17
+#define R8A77980_CLK_S2D4              18
+#define R8A77980_CLK_S3D1              19
+#define R8A77980_CLK_S3D2              20
+#define R8A77980_CLK_S3D4              21
+#define R8A77980_CLK_LB                        22
+#define R8A77980_CLK_CL                        23
+#define R8A77980_CLK_ZB3               24
+#define R8A77980_CLK_ZB3D2             25
+#define R8A77980_CLK_ZB3D4             26
+#define R8A77980_CLK_SD0H              27
+#define R8A77980_CLK_SD0               28
+#define R8A77980_CLK_RPC               29
+#define R8A77980_CLK_RPCD2             30
+#define R8A77980_CLK_MSO               31
+#define R8A77980_CLK_CANFD             32
+#define R8A77980_CLK_CSI0              33
+#define R8A77980_CLK_CP                        34
+#define R8A77980_CLK_CPEX              35
+#define R8A77980_CLK_R                 36
+#define R8A77980_CLK_OSC               37
+
+#endif /* __DT_BINDINGS_CLOCK_R8A77980_CPG_MSSR_H__ */
index d2b26a4b43ebde2eae06c6fd596895e5147adc76..a82a0109faffe92689fcd05cdc2d963dca5dee78 100644 (file)
 #define HCLK_VPU_PRE           324
 #define HCLK_VIO_PRE           325
 #define HCLK_VPU               326
-#define HCLK_VIO               327
 #define HCLK_BUS_PRE           328
 #define HCLK_PERI_PRE          329
 #define HCLK_H264              330
index 4cb202f090c2ef57cb78c94722cf5f39f64e6c0a..f2ab4631df0dd850504d5b2b9ee433e55e73f4d3 100644 (file)
 #define        CLK_SDIO1_2X_EN         65
 #define        CLK_SDIO2_2X_EN         66
 #define        CLK_EMMC_2X_EN          67
-#define CLK_AON_GATE_NUM       (CLK_EMMC_2X_EN + 1)
+#define        CLK_ARCH_RTC_EB         68
+#define        CLK_KPB_RTC_EB          69
+#define        CLK_AON_SYST_RTC_EB     70
+#define        CLK_AP_SYST_RTC_EB      71
+#define        CLK_AON_TMR_RTC_EB      72
+#define        CLK_AP_TMR0_RTC_EB      73
+#define        CLK_EIC_RTC_EB          74
+#define        CLK_EIC_RTCDV5_EB       75
+#define        CLK_AP_WDG_RTC_EB       76
+#define        CLK_AP_TMR1_RTC_EB      77
+#define        CLK_AP_TMR2_RTC_EB      78
+#define        CLK_DCXO_TMR_RTC_EB     79
+#define        CLK_BB_CAL_RTC_EB       80
+#define        CLK_AVS_BIG_RTC_EB      81
+#define        CLK_AVS_LIT_RTC_EB      82
+#define        CLK_AVS_GPU0_RTC_EB     83
+#define        CLK_AVS_GPU1_RTC_EB     84
+#define        CLK_GPU_TS_EB           85
+#define        CLK_RTCDV10_EB          86
+#define        CLK_AON_GATE_NUM        (CLK_RTCDV10_EB + 1)
 
 #define        CLK_LIT_MCU             0
 #define        CLK_BIG_MCU             1
index 49bb3c203e5c0988a2c8dd2ecfb9ad786bdf3f82..58d8b515be55f4a2a44aaf3b10b41191747cb994 100644 (file)
 #define CLK_SAI2               11
 #define CLK_I2SQ_PDIV          12
 #define CLK_SAIQ_PDIV          13
-
-#define END_PRIMARY_CLK                14
-
 #define CLK_HSI                        14
 #define CLK_SYSCLK             15
+#define CLK_F469_DSI           16
+
+#define END_PRIMARY_CLK                17
+
 #define CLK_HDMI_CEC           16
 #define CLK_SPDIF              17
 #define CLK_USART1             18
diff --git a/include/dt-bindings/clock/stm32mp1-clks.h b/include/dt-bindings/clock/stm32mp1-clks.h
new file mode 100644 (file)
index 0000000..86e3ec6
--- /dev/null
@@ -0,0 +1,254 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Gabriel Fernandez <gabriel.fernandez@st.com> for STMicroelectronics.
+ */
+
+#ifndef _DT_BINDINGS_STM32MP1_CLKS_H_
+#define _DT_BINDINGS_STM32MP1_CLKS_H_
+
+/* OSCILLATOR clocks */
+#define CK_HSE         0
+#define CK_CSI         1
+#define CK_LSI         2
+#define CK_LSE         3
+#define CK_HSI         4
+#define CK_HSE_DIV2    5
+
+/* Bus clocks */
+#define TIM2           6
+#define TIM3           7
+#define TIM4           8
+#define TIM5           9
+#define TIM6           10
+#define TIM7           11
+#define TIM12          12
+#define TIM13          13
+#define TIM14          14
+#define LPTIM1         15
+#define SPI2           16
+#define SPI3           17
+#define USART2         18
+#define USART3         19
+#define UART4          20
+#define UART5          21
+#define UART7          22
+#define UART8          23
+#define I2C1           24
+#define I2C2           25
+#define I2C3           26
+#define I2C5           27
+#define SPDIF          28
+#define CEC            29
+#define DAC12          30
+#define MDIO           31
+#define TIM1           32
+#define TIM8           33
+#define TIM15          34
+#define TIM16          35
+#define TIM17          36
+#define SPI1           37
+#define SPI4           38
+#define SPI5           39
+#define USART6         40
+#define SAI1           41
+#define SAI2           42
+#define SAI3           43
+#define DFSDM          44
+#define FDCAN          45
+#define LPTIM2         46
+#define LPTIM3         47
+#define LPTIM4         48
+#define LPTIM5         49
+#define SAI4           50
+#define SYSCFG         51
+#define VREF           52
+#define TMPSENS                53
+#define PMBCTRL                54
+#define HDP            55
+#define LTDC           56
+#define DSI            57
+#define IWDG2          58
+#define USBPHY         59
+#define STGENRO                60
+#define SPI6           61
+#define I2C4           62
+#define I2C6           63
+#define USART1         64
+#define RTCAPB         65
+#define TZC            66
+#define TZPC           67
+#define IWDG1          68
+#define BSEC           69
+#define STGEN          70
+#define DMA1           71
+#define DMA2           72
+#define DMAMUX         73
+#define ADC12          74
+#define USBO           75
+#define SDMMC3         76
+#define DCMI           77
+#define CRYP2          78
+#define HASH2          79
+#define RNG2           80
+#define CRC2           81
+#define HSEM           82
+#define IPCC           83
+#define GPIOA          84
+#define GPIOB          85
+#define GPIOC          86
+#define GPIOD          87
+#define GPIOE          88
+#define GPIOF          89
+#define GPIOG          90
+#define GPIOH          91
+#define GPIOI          92
+#define GPIOJ          93
+#define GPIOK          94
+#define GPIOZ          95
+#define CRYP1          96
+#define HASH1          97
+#define RNG1           98
+#define BKPSRAM                99
+#define MDMA           100
+#define GPU            101
+#define ETHCK          102
+#define ETHTX          103
+#define ETHRX          104
+#define ETHMAC         105
+#define FMC            106
+#define QSPI           107
+#define SDMMC1         108
+#define SDMMC2         109
+#define CRC1           110
+#define USBH           111
+#define ETHSTP         112
+
+/* Kernel clocks */
+#define SDMMC1_K       118
+#define SDMMC2_K       119
+#define SDMMC3_K       120
+#define FMC_K          121
+#define QSPI_K         122
+#define ETHCK_K                123
+#define RNG1_K         124
+#define RNG2_K         125
+#define GPU_K          126
+#define USBPHY_K       127
+#define STGEN_K                128
+#define SPDIF_K                129
+#define SPI1_K         130
+#define SPI2_K         131
+#define SPI3_K         132
+#define SPI4_K         133
+#define SPI5_K         134
+#define SPI6_K         135
+#define CEC_K          136
+#define I2C1_K         137
+#define I2C2_K         138
+#define I2C3_K         139
+#define I2C4_K         140
+#define I2C5_K         141
+#define I2C6_K         142
+#define LPTIM1_K       143
+#define LPTIM2_K       144
+#define LPTIM3_K       145
+#define LPTIM4_K       146
+#define LPTIM5_K       147
+#define USART1_K       148
+#define USART2_K       149
+#define USART3_K       150
+#define UART4_K                151
+#define UART5_K                152
+#define USART6_K       153
+#define UART7_K                154
+#define UART8_K                155
+#define DFSDM_K                156
+#define FDCAN_K                157
+#define SAI1_K         158
+#define SAI2_K         159
+#define SAI3_K         160
+#define SAI4_K         161
+#define ADC12_K                162
+#define DSI_K          163
+#define DSI_PX         164
+#define ADFSDM_K       165
+#define USBO_K         166
+#define LTDC_PX                167
+#define DAC12_K                168
+#define ETHPTP_K       169
+
+/* PLL */
+#define PLL1           176
+#define PLL2           177
+#define PLL3           178
+#define PLL4           179
+
+/* ODF */
+#define PLL1_P         180
+#define PLL1_Q         181
+#define PLL1_R         182
+#define PLL2_P         183
+#define PLL2_Q         184
+#define PLL2_R         185
+#define PLL3_P         186
+#define PLL3_Q         187
+#define PLL3_R         188
+#define PLL4_P         189
+#define PLL4_Q         190
+#define PLL4_R         191
+
+/* AUX */
+#define RTC            192
+
+/* MCLK */
+#define CK_PER         193
+#define CK_MPU         194
+#define CK_AXI         195
+#define CK_MCU         196
+
+/* Time base */
+#define TIM2_K         197
+#define TIM3_K         198
+#define TIM4_K         199
+#define TIM5_K         200
+#define TIM6_K         201
+#define TIM7_K         202
+#define TIM12_K                203
+#define TIM13_K                204
+#define TIM14_K                205
+#define TIM1_K         206
+#define TIM8_K         207
+#define TIM15_K                208
+#define TIM16_K                209
+#define TIM17_K                210
+
+/* MCO clocks */
+#define CK_MCO1                211
+#define CK_MCO2                212
+
+/* TRACE & DEBUG clocks */
+#define DBG            213
+#define CK_DBG         214
+#define CK_TRACE       215
+
+/* DDR */
+#define DDRC1          220
+#define DDRC1LP                221
+#define DDRC2          222
+#define DDRC2LP                223
+#define DDRPHYC                224
+#define DDRPHYCLP      225
+#define DDRCAPB                226
+#define DDRCAPBLP      227
+#define AXIDCG         228
+#define DDRPHYCAPB     229
+#define DDRPHYCAPBLP   230
+#define DDRPERFM       231
+
+#define STM32MP1_LAST_CLK 232
+
+#define LTDC_K         LTDC_PX
+#define ETHMAC_K       ETHCK_K
+
+#endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */
diff --git a/include/dt-bindings/clock/stratix10-clock.h b/include/dt-bindings/clock/stratix10-clock.h
new file mode 100644 (file)
index 0000000..0ac1c90
--- /dev/null
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier:    GPL-2.0 */
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+
+#ifndef __STRATIX10_CLOCK_H
+#define __STRATIX10_CLOCK_H
+
+/* fixed rate clocks */
+#define STRATIX10_OSC1                 0
+#define STRATIX10_CB_INTOSC_HS_DIV2_CLK        1
+#define STRATIX10_CB_INTOSC_LS_CLK     2
+#define STRATIX10_F2S_FREE_CLK         3
+
+/* fixed factor clocks */
+#define STRATIX10_L4_SYS_FREE_CLK      4
+#define STRATIX10_MPU_PERIPH_CLK       5
+#define STRATIX10_MPU_L2RAM_CLK                6
+#define STRATIX10_SDMMC_CIU_CLK                7
+
+/* PLL clocks */
+#define STRATIX10_MAIN_PLL_CLK         8
+#define STRATIX10_PERIPH_PLL_CLK       9
+#define STRATIX10_BOOT_CLK             10
+
+/* Periph clocks */
+#define STRATIX10_MAIN_MPU_BASE_CLK    11
+#define STRATIX10_MAIN_NOC_BASE_CLK    12
+#define STRATIX10_MAIN_EMACA_CLK       13
+#define STRATIX10_MAIN_EMACB_CLK       14
+#define STRATIX10_MAIN_EMAC_PTP_CLK    15
+#define STRATIX10_MAIN_GPIO_DB_CLK     16
+#define STRATIX10_MAIN_SDMMC_CLK       17
+#define STRATIX10_MAIN_S2F_USR0_CLK    18
+#define STRATIX10_MAIN_S2F_USR1_CLK    19
+#define STRATIX10_MAIN_PSI_REF_CLK     20
+
+#define STRATIX10_PERI_MPU_BASE_CLK    21
+#define STRATIX10_PERI_NOC_BASE_CLK    22
+#define STRATIX10_PERI_EMACA_CLK       23
+#define STRATIX10_PERI_EMACB_CLK       24
+#define STRATIX10_PERI_EMAC_PTP_CLK    25
+#define STRATIX10_PERI_GPIO_DB_CLK     26
+#define STRATIX10_PERI_SDMMC_CLK       27
+#define STRATIX10_PERI_S2F_USR0_CLK    28
+#define STRATIX10_PERI_S2F_USR1_CLK    29
+#define STRATIX10_PERI_PSI_REF_CLK     30
+
+#define STRATIX10_MPU_FREE_CLK         31
+#define STRATIX10_NOC_FREE_CLK         32
+#define STRATIX10_S2F_USR0_CLK         33
+#define STRATIX10_NOC_CLK              34
+#define STRATIX10_EMAC_A_FREE_CLK      35
+#define STRATIX10_EMAC_B_FREE_CLK      36
+#define STRATIX10_EMAC_PTP_FREE_CLK    37
+#define STRATIX10_GPIO_DB_FREE_CLK     38
+#define STRATIX10_SDMMC_FREE_CLK       39
+#define STRATIX10_S2F_USER1_FREE_CLK   40
+#define STRATIX10_PSI_REF_FREE_CLK     41
+
+/* Gate clocks */
+#define STRATIX10_MPU_CLK              42
+#define STRATIX10_L4_MAIN_CLK          43
+#define STRATIX10_L4_MP_CLK            44
+#define STRATIX10_L4_SP_CLK            45
+#define STRATIX10_CS_AT_CLK            46
+#define STRATIX10_CS_TRACE_CLK         47
+#define STRATIX10_CS_PDBG_CLK          48
+#define STRATIX10_CS_TIMER_CLK         49
+#define STRATIX10_S2F_USER0_CLK                50
+#define STRATIX10_S2F_USER1_CLK                51
+#define STRATIX10_EMAC0_CLK            52
+#define STRATIX10_EMAC1_CLK            53
+#define STRATIX10_EMAC2_CLK            54
+#define STRATIX10_EMAC_PTP_CLK         55
+#define STRATIX10_GPIO_DB_CLK          56
+#define STRATIX10_SDMMC_CLK            57
+#define STRATIX10_PSI_REF_CLK          58
+#define STRATIX10_USB_CLK              59
+#define STRATIX10_SPI_M_CLK            60
+#define STRATIX10_NAND_CLK             61
+#define STRATIX10_NUM_CLKS             62
+
+#endif /* __STRATIX10_CLOCK_H */
diff --git a/include/dt-bindings/clock/sun50i-h6-ccu.h b/include/dt-bindings/clock/sun50i-h6-ccu.h
new file mode 100644 (file)
index 0000000..a1545cd
--- /dev/null
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN50I_H6_H_
+#define _DT_BINDINGS_CLK_SUN50I_H6_H_
+
+#define CLK_PLL_PERIPH0                3
+
+#define CLK_CPUX               21
+
+#define CLK_APB1               26
+
+#define CLK_DE                 29
+#define CLK_BUS_DE             30
+#define CLK_DEINTERLACE                31
+#define CLK_BUS_DEINTERLACE    32
+#define CLK_GPU                        33
+#define CLK_BUS_GPU            34
+#define CLK_CE                 35
+#define CLK_BUS_CE             36
+#define CLK_VE                 37
+#define CLK_BUS_VE             38
+#define CLK_EMCE               39
+#define CLK_BUS_EMCE           40
+#define CLK_VP9                        41
+#define CLK_BUS_VP9            42
+#define CLK_BUS_DMA            43
+#define CLK_BUS_MSGBOX         44
+#define CLK_BUS_SPINLOCK       45
+#define CLK_BUS_HSTIMER                46
+#define CLK_AVS                        47
+#define CLK_BUS_DBG            48
+#define CLK_BUS_PSI            49
+#define CLK_BUS_PWM            50
+#define CLK_BUS_IOMMU          51
+
+#define CLK_MBUS_DMA           53
+#define CLK_MBUS_VE            54
+#define CLK_MBUS_CE            55
+#define CLK_MBUS_TS            56
+#define CLK_MBUS_NAND          57
+#define CLK_MBUS_CSI           58
+#define CLK_MBUS_DEINTERLACE   59
+
+#define CLK_NAND0              61
+#define CLK_NAND1              62
+#define CLK_BUS_NAND           63
+#define CLK_MMC0               64
+#define CLK_MMC1               65
+#define CLK_MMC2               66
+#define CLK_BUS_MMC0           67
+#define CLK_BUS_MMC1           68
+#define CLK_BUS_MMC2           69
+#define CLK_BUS_UART0          70
+#define CLK_BUS_UART1          71
+#define CLK_BUS_UART2          72
+#define CLK_BUS_UART3          73
+#define CLK_BUS_I2C0           74
+#define CLK_BUS_I2C1           75
+#define CLK_BUS_I2C2           76
+#define CLK_BUS_I2C3           77
+#define CLK_BUS_SCR0           78
+#define CLK_BUS_SCR1           79
+#define CLK_SPI0               80
+#define CLK_SPI1               81
+#define CLK_BUS_SPI0           82
+#define CLK_BUS_SPI1           83
+#define CLK_BUS_EMAC           84
+#define CLK_TS                 85
+#define CLK_BUS_TS             86
+#define CLK_IR_TX              87
+#define CLK_BUS_IR_TX          88
+#define CLK_BUS_THS            89
+#define CLK_I2S3               90
+#define CLK_I2S0               91
+#define CLK_I2S1               92
+#define CLK_I2S2               93
+#define CLK_BUS_I2S0           94
+#define CLK_BUS_I2S1           95
+#define CLK_BUS_I2S2           96
+#define CLK_BUS_I2S3           97
+#define CLK_SPDIF              98
+#define CLK_BUS_SPDIF          99
+#define CLK_DMIC               100
+#define CLK_BUS_DMIC           101
+#define CLK_AUDIO_HUB          102
+#define CLK_BUS_AUDIO_HUB      103
+#define CLK_USB_OHCI0          104
+#define CLK_USB_PHY0           105
+#define CLK_USB_PHY1           106
+#define CLK_USB_OHCI3          107
+#define CLK_USB_PHY3           108
+#define CLK_USB_HSIC_12M       109
+#define CLK_USB_HSIC           110
+#define CLK_BUS_OHCI0          111
+#define CLK_BUS_OHCI3          112
+#define CLK_BUS_EHCI0          113
+#define CLK_BUS_XHCI           114
+#define CLK_BUS_EHCI3          115
+#define CLK_BUS_OTG            116
+#define CLK_PCIE_REF_100M      117
+#define CLK_PCIE_REF           118
+#define CLK_PCIE_REF_OUT       119
+#define CLK_PCIE_MAXI          120
+#define CLK_PCIE_AUX           121
+#define CLK_BUS_PCIE           122
+#define CLK_HDMI               123
+#define CLK_HDMI_SLOW          124
+#define CLK_HDMI_CEC           125
+#define CLK_BUS_HDMI           126
+#define CLK_BUS_TCON_TOP       127
+#define CLK_TCON_LCD0          128
+#define CLK_BUS_TCON_LCD0      129
+#define CLK_TCON_TV0           130
+#define CLK_BUS_TCON_TV0       131
+#define CLK_CSI_CCI            132
+#define CLK_CSI_TOP            133
+#define CLK_CSI_MCLK           134
+#define CLK_BUS_CSI            135
+#define CLK_HDCP               136
+#define CLK_BUS_HDCP           137
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_H6_H_ */
index e139fe5c62ecd5c8375e7bc8fd503465e475985b..c5f7e9a70968956e60e40ace87f80b842c5a072e 100644 (file)
@@ -43,6 +43,8 @@
 #ifndef _DT_BINDINGS_CLK_SUN8I_H3_H_
 #define _DT_BINDINGS_CLK_SUN8I_H3_H_
 
+#define CLK_PLL_VIDEO          6
+
 #define CLK_PLL_PERIPH0                9
 
 #define CLK_CPUX               14
index 6422314e46ebaa3c9ac97059464f3e9d85c96d96..6b77e721f6b1f1ebb9406e3294f704f4195a57dd 100644 (file)
@@ -95,7 +95,7 @@
 #define TEGRA210_CLK_CSITE 73
 /* 74 */
 /* 75 */
-/* 76 */
+#define TEGRA210_CLK_LA 76
 /* 77 */
 #define TEGRA210_CLK_SOC_THERM 78
 #define TEGRA210_CLK_DTV 79
diff --git a/include/dt-bindings/reset/sun50i-h6-ccu.h b/include/dt-bindings/reset/sun50i-h6-ccu.h
new file mode 100644 (file)
index 0000000..81106f4
--- /dev/null
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#ifndef _DT_BINDINGS_RESET_SUN50I_H6_H_
+#define _DT_BINDINGS_RESET_SUN50I_H6_H_
+
+#define RST_MBUS               0
+#define RST_BUS_DE             1
+#define RST_BUS_DEINTERLACE    2
+#define RST_BUS_GPU            3
+#define RST_BUS_CE             4
+#define RST_BUS_VE             5
+#define RST_BUS_EMCE           6
+#define RST_BUS_VP9            7
+#define RST_BUS_DMA            8
+#define RST_BUS_MSGBOX         9
+#define RST_BUS_SPINLOCK       10
+#define RST_BUS_HSTIMER                11
+#define RST_BUS_DBG            12
+#define RST_BUS_PSI            13
+#define RST_BUS_PWM            14
+#define RST_BUS_IOMMU          15
+#define RST_BUS_DRAM           16
+#define RST_BUS_NAND           17
+#define RST_BUS_MMC0           18
+#define RST_BUS_MMC1           19
+#define RST_BUS_MMC2           20
+#define RST_BUS_UART0          21
+#define RST_BUS_UART1          22
+#define RST_BUS_UART2          23
+#define RST_BUS_UART3          24
+#define RST_BUS_I2C0           25
+#define RST_BUS_I2C1           26
+#define RST_BUS_I2C2           27
+#define RST_BUS_I2C3           28
+#define RST_BUS_SCR0           29
+#define RST_BUS_SCR1           30
+#define RST_BUS_SPI0           31
+#define RST_BUS_SPI1           32
+#define RST_BUS_EMAC           33
+#define RST_BUS_TS             34
+#define RST_BUS_IR_TX          35
+#define RST_BUS_THS            36
+#define RST_BUS_I2S0           37
+#define RST_BUS_I2S1           38
+#define RST_BUS_I2S2           39
+#define RST_BUS_I2S3           40
+#define RST_BUS_SPDIF          41
+#define RST_BUS_DMIC           42
+#define RST_BUS_AUDIO_HUB      43
+#define RST_USB_PHY0           44
+#define RST_USB_PHY1           45
+#define RST_USB_PHY3           46
+#define RST_USB_HSIC           47
+#define RST_BUS_OHCI0          48
+#define RST_BUS_OHCI3          49
+#define RST_BUS_EHCI0          50
+#define RST_BUS_XHCI           51
+#define RST_BUS_EHCI3          52
+#define RST_BUS_OTG            53
+#define RST_BUS_PCIE           54
+#define RST_PCIE_POWERUP       55
+#define RST_BUS_HDMI           56
+#define RST_BUS_HDMI_SUB       57
+#define RST_BUS_TCON_TOP       58
+#define RST_BUS_TCON_LCD0      59
+#define RST_BUS_TCON_TV0       60
+#define RST_BUS_CSI            61
+#define RST_BUS_HDCP           62
+
+#endif /* _DT_BINDINGS_RESET_SUN50I_H6_H_ */
index f711be6e8c445504fe9ca34a5fe14228b926fc12..210a890008f9e12987e578b949e6702864d076f6 100644 (file)
@@ -399,6 +399,7 @@ struct clk_divider {
        spinlock_t      *lock;
 };
 
+#define clk_div_mask(width)    ((1 << (width)) - 1)
 #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
 
 #define CLK_DIVIDER_ONE_BASED          BIT(0)
@@ -419,6 +420,10 @@ long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
                               unsigned long rate, unsigned long *prate,
                               const struct clk_div_table *table,
                               u8 width, unsigned long flags);
+long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
+                                 unsigned long rate, unsigned long *prate,
+                                 const struct clk_div_table *table, u8 width,
+                                 unsigned long flags, unsigned int val);
 int divider_get_val(unsigned long rate, unsigned long parent_rate,
                const struct clk_div_table *table, u8 width,
                unsigned long flags);
@@ -449,8 +454,9 @@ void clk_hw_unregister_divider(struct clk_hw *hw);
  *
  * @hw:                handle between common and hardware-specific interfaces
  * @reg:       register controlling multiplexer
+ * @table:     array of register values corresponding to the parent index
  * @shift:     shift to multiplexer bit field
- * @width:     width of mutliplexer bit field
+ * @mask:      mask of mutliplexer bit field
  * @flags:     hardware-specific flags
  * @lock:      register lock
  *
@@ -510,6 +516,10 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
                void __iomem *reg, u8 shift, u32 mask,
                u8 clk_mux_flags, u32 *table, spinlock_t *lock);
 
+int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
+                        unsigned int val);
+unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index);
+
 void clk_unregister_mux(struct clk *clk);
 void clk_hw_unregister_mux(struct clk_hw *hw);
 
@@ -774,6 +784,17 @@ static inline long divider_round_rate(struct clk_hw *hw, unsigned long rate,
                                         rate, prate, table, width, flags);
 }
 
+static inline long divider_ro_round_rate(struct clk_hw *hw, unsigned long rate,
+                                        unsigned long *prate,
+                                        const struct clk_div_table *table,
+                                        u8 width, unsigned long flags,
+                                        unsigned int val)
+{
+       return divider_ro_round_rate_parent(hw, clk_hw_get_parent(hw),
+                                           rate, prate, table, width, flags,
+                                           val);
+}
+
 /*
  * FIXME clock api without lock protection
  */
index 4c4ef9f34db316d6163d52c4a144807b218e9ba5..0dbd0885b2c238f88cb9f2243ff4ecf158113c23 100644 (file)
@@ -209,7 +209,7 @@ static inline int clk_prepare(struct clk *clk)
        return 0;
 }
 
-static inline int clk_bulk_prepare(int num_clks, struct clk_bulk_data *clks)
+static inline int __must_check clk_bulk_prepare(int num_clks, struct clk_bulk_data *clks)
 {
        might_sleep();
        return 0;
@@ -603,8 +603,8 @@ static inline struct clk *clk_get(struct device *dev, const char *id)
        return NULL;
 }
 
-static inline int clk_bulk_get(struct device *dev, int num_clks,
-                              struct clk_bulk_data *clks)
+static inline int __must_check clk_bulk_get(struct device *dev, int num_clks,
+                                           struct clk_bulk_data *clks)
 {
        return 0;
 }
@@ -614,8 +614,8 @@ static inline struct clk *devm_clk_get(struct device *dev, const char *id)
        return NULL;
 }
 
-static inline int devm_clk_bulk_get(struct device *dev, int num_clks,
-                                   struct clk_bulk_data *clks)
+static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
+                                                struct clk_bulk_data *clks)
 {
        return 0;
 }
@@ -645,7 +645,7 @@ static inline int clk_enable(struct clk *clk)
        return 0;
 }
 
-static inline int clk_bulk_enable(int num_clks, struct clk_bulk_data *clks)
+static inline int __must_check clk_bulk_enable(int num_clks, struct clk_bulk_data *clks)
 {
        return 0;
 }
@@ -719,8 +719,8 @@ static inline void clk_disable_unprepare(struct clk *clk)
        clk_unprepare(clk);
 }
 
-static inline int clk_bulk_prepare_enable(int num_clks,
-                                         struct clk_bulk_data *clks)
+static inline int __must_check clk_bulk_prepare_enable(int num_clks,
+                                       struct clk_bulk_data *clks)
 {
        int ret;
 
index d23c9cf26993b5f4518710c2495f426cb48abf85..afb9edfa5d58c847c84793c907d9bf7871f25df0 100644 (file)
@@ -128,5 +128,6 @@ extern void tegra210_sata_pll_hw_sequence_start(void);
 extern void tegra210_set_sata_pll_seq_sw(bool state);
 extern void tegra210_put_utmipll_in_iddq(void);
 extern void tegra210_put_utmipll_out_iddq(void);
+extern int tegra210_clk_handle_mbist_war(unsigned int id);
 
 #endif /* __LINUX_CLK_TEGRA_H_ */
index 7e3bceee348940959b711e62fd5aba186db5914e..a8faa38b1ed60bd5a7a306abda6b39413e677090 100644 (file)
@@ -212,6 +212,7 @@ enum {
  * struct ti_clk_ll_ops - low-level ops for clocks
  * @clk_readl: pointer to register read function
  * @clk_writel: pointer to register write function
+ * @clk_rmw: pointer to register read-modify-write function
  * @clkdm_clk_enable: pointer to clockdomain enable function
  * @clkdm_clk_disable: pointer to clockdomain disable function
  * @clkdm_lookup: pointer to clockdomain lookup function
@@ -227,6 +228,7 @@ enum {
 struct ti_clk_ll_ops {
        u32     (*clk_readl)(const struct clk_omap_reg *reg);
        void    (*clk_writel)(u32 val, const struct clk_omap_reg *reg);
+       void    (*clk_rmw)(u32 val, u32 mask, const struct clk_omap_reg *reg);
        int     (*clkdm_clk_enable)(struct clockdomain *clkdm, struct clk *clk);
        int     (*clkdm_clk_disable)(struct clockdomain *clkdm,
                                     struct clk *clk);
diff --git a/include/linux/platform_data/clk-da8xx-cfgchip.h b/include/linux/platform_data/clk-da8xx-cfgchip.h
new file mode 100644 (file)
index 0000000..de0f77d
--- /dev/null
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * clk-da8xx-cfgchip - TI DaVinci DA8xx CFGCHIP clock driver
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#ifndef __LINUX_PLATFORM_DATA_CLK_DA8XX_CFGCHIP_H__
+#define __LINUX_PLATFORM_DATA_CLK_DA8XX_CFGCHIP_H__
+
+#include <linux/regmap.h>
+
+/**
+ * da8xx_cfgchip_clk_platform_data
+ * @cfgchip: CFGCHIP syscon regmap
+ */
+struct da8xx_cfgchip_clk_platform_data {
+       struct regmap *cfgchip;
+};
+
+#endif /* __LINUX_PLATFORM_DATA_CLK_DA8XX_CFGCHIP_H__ */
diff --git a/include/linux/platform_data/clk-davinci-pll.h b/include/linux/platform_data/clk-davinci-pll.h
new file mode 100644 (file)
index 0000000..e55dab1
--- /dev/null
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLL clock driver for TI Davinci SoCs
+ *
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ */
+
+#ifndef __LINUX_PLATFORM_DATA_CLK_DAVINCI_PLL_H__
+#define __LINUX_PLATFORM_DATA_CLK_DAVINCI_PLL_H__
+
+#include <linux/regmap.h>
+
+/**
+ * davinci_pll_platform_data
+ * @cfgchip: CFGCHIP syscon regmap
+ */
+struct davinci_pll_platform_data {
+       struct regmap *cfgchip;
+};
+
+#endif /* __LINUX_PLATFORM_DATA_CLK_DAVINCI_PLL_H__ */