Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 31 Oct 2018 18:08:30 +0000 (11:08 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 31 Oct 2018 18:08:30 +0000 (11:08 -0700)
Pull clk updates from Stephen Boyd:
 "This time it looks like a quieter release cycle in the clk tree. I
  guess that's because of summer time holidays/vacations. The biggest
  change in the diffstat is in the Qualcomm clk driver, where they got
  support for CPUs and handful of SoCs. After that, the at91 driver got
  a major rewrite for newer DT bindings that should make things easier
  going forward and the TI code moved to a clockdomain based design.

  The long tail is mostly small driver updates for newer clks and some
  simpler SoC clock drivers such as the Hisilicon and imx support.

  In the core framework, we only have two small changes this time.

  One is a new clk API to get all clks for a device with the bulk clk
  APIs. This allows drivers that don't care about doing anything besides
  turning on all the clks to just clk_get() them all and turn them on.

  The other change is the beginning of a way to support save and restore
  of clk settings in the clk framework. TI is the only user right now,
  but we will want to expand upon this design in the future to support
  more save and restore of clk registers. At least this gets us started
  and works well enough for one SoC, but there's more work in the
  future.

  Core:
   - clk_bulk_get_all() API and friends to get all the clks for a device
   - Basic clk state save/restore hooks

  New Drivers:
   - Renesas RZ/A2 (R7S9210) SoC, including early clocks
   - Rensas RZ/G1N (R8A7744) and RZ/G2E (R8A774C0) SoCs
   - Rensas RZ/G2M (r8a774a1) SoC
   - Qualcomm Krait CPU clk support
   - Qualcomm QCS404 GCC support
   - Qualcomm SDM660 GCC support
   - Qualcomm SDM845 camera clock controller
   - Ingenic jz4725b CGU
   - Hisilicon 3670 SoC support
   - TI SCI clks on K3 SoCs
   - iMX6 MMDC clks
   - Reset Controller (RMU) support for Actions Semi Owl S900 and S700 SoCs

  Updates:
   - Rework at91 PMC clock driver for new DT bindings
   - Nvidia Tegra clk driver MBIST workaround fix
   - S2RAM support for Marvell mvebu periph clks
   - Use updated printk format for OF node names
   - Fix TI code to only search DT subnodes
   - Various static analysis finds
   - Tag various drivers with SPDX license tags
   - Support dynamic frequency switching (DFS) on qcom SDM845 GCC
   - Only use s2mps11 dt-binding defines instead of redefining them in the driver
   - Add some more missing clks to qcom MSM8996 GCC
   - Quad SPI clks on qcom SDM845
   - Add support for CMT timer clocks on R-Car V3H
   - Add support for SHDI and various timer clocks on R-Car V3M
   - Improve OSC and RCLK (watchdog) handling on R-Car Gen3 SoCs
   - Amlogic clk-pll driver improvements and updates
   - Amlogic axg audio controller system clocks
   - Register Amlogic meson8b clock controller early
   - Add support for SATA and Fine Display Processor (FDP) clocks on R-Car M3-N
   - Consolidation of system suspend related code in Exynos, S5P, S3C SoC clk drivers
   - Fixes for system suspend support on Exynos542x (Odroid boards) and Exynos5433 SoC
   - Remove obsoleted Exynos4212 ISP clock definitions
   - Migrated TI am3/4/5 and dra7 SoCs to clockdomain based design
   - TI RTC+DDR sleep mode support for clock save/restore
   - Allwinner A64 display engine support and fixes
   - Allwinner A83t display engine support and fixes"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (186 commits)
  clk: qcom: Remove unused arrays in SDM845 GCC
  clk: fixed-rate: fix of_node_get-put imbalance
  clk: s2mps11: Add used attribute to s2mps11_dt_match
  clk: qcom: gcc-sdm660: Add MODULE_LICENSE
  clk: qcom: Add safe switch hook for krait mux clocks
  dt-bindings: clock: Document qcom,krait-cc
  clk: qcom: Add Krait clock controller driver
  dt-bindings: arm: Document qcom,kpss-gcc
  clk: qcom: Add KPSS ACC/GCC driver
  clk: qcom: Add support for Krait clocks
  clk: qcom: Add IPQ806X's HFPLLs
  clk: qcom: Add MSM8960/APQ8064's HFPLLs
  dt-bindings: clock: Document qcom,hfpll
  clk: qcom: Add HFPLL driver
  clk: qcom: Add support for High-Frequency PLLs (HFPLLs)
  ARM: Add Krait L2 register accessor functions
  clk: imx6q: add mmdc0 ipg clock
  clk: imx6sl: add mmdc ipg clocks
  clk: imx6sll: add mmdc1 ipg clock
  clk: imx6sx: add mmdc1 ipg clock
  ...

284 files changed:
Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt
Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/actions,owl-cmu.txt
Documentation/devicetree/bindings/clock/at91-clock.txt
Documentation/devicetree/bindings/clock/hi3670-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ingenic,cgu.txt
Documentation/devicetree/bindings/clock/qcom,camcc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/qcom,gcc.txt
Documentation/devicetree/bindings/clock/qcom,hfpll.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/qcom,krait-cc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
arch/arm/common/Kconfig
arch/arm/common/Makefile
arch/arm/common/krait-l2-accessors.c [new file with mode: 0644]
arch/arm/include/asm/krait-l2-accessors.h [new file with mode: 0644]
arch/arm/mach-davinci/include/mach/clock.h [deleted file]
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/actions/Kconfig
drivers/clk/actions/Makefile
drivers/clk/actions/owl-common.c
drivers/clk/actions/owl-common.h
drivers/clk/actions/owl-reset.c [new file with mode: 0644]
drivers/clk/actions/owl-reset.h [new file with mode: 0644]
drivers/clk/actions/owl-s700.c
drivers/clk/actions/owl-s900.c
drivers/clk/at91/Makefile
drivers/clk/at91/at91sam9260.c [new file with mode: 0644]
drivers/clk/at91/at91sam9rl.c [new file with mode: 0644]
drivers/clk/at91/at91sam9x5.c [new file with mode: 0644]
drivers/clk/at91/clk-audio-pll.c
drivers/clk/at91/clk-generated.c
drivers/clk/at91/clk-h32mx.c
drivers/clk/at91/clk-i2s-mux.c
drivers/clk/at91/clk-main.c
drivers/clk/at91/clk-master.c
drivers/clk/at91/clk-peripheral.c
drivers/clk/at91/clk-pll.c
drivers/clk/at91/clk-plldiv.c
drivers/clk/at91/clk-programmable.c
drivers/clk/at91/clk-slow.c
drivers/clk/at91/clk-smd.c
drivers/clk/at91/clk-system.c
drivers/clk/at91/clk-usb.c
drivers/clk/at91/clk-utmi.c
drivers/clk/at91/dt-compat.c [new file with mode: 0644]
drivers/clk/at91/pmc.c
drivers/clk/at91/pmc.h
drivers/clk/at91/sama5d2.c [new file with mode: 0644]
drivers/clk/at91/sama5d4.c [new file with mode: 0644]
drivers/clk/axs10x/pll_clock.c
drivers/clk/bcm/clk-kona-setup.c
drivers/clk/clk-asm9260.c
drivers/clk/clk-bulk.c
drivers/clk/clk-cdce925.c
drivers/clk/clk-devres.c
drivers/clk/clk-fixed-factor.c
drivers/clk/clk-fixed-rate.c
drivers/clk/clk-gpio.c
drivers/clk/clk-hsdk-pll.c
drivers/clk/clk-max77686.c
drivers/clk/clk-nomadik.c
drivers/clk/clk-npcm7xx.c
drivers/clk/clk-palmas.c
drivers/clk/clk-qoriq.c
drivers/clk/clk-s2mps11.c
drivers/clk/clk-scmi.c
drivers/clk/clk-scpi.c
drivers/clk/clk-si5351.c
drivers/clk/clk-stm32f4.c
drivers/clk/clk-stm32h7.c
drivers/clk/clk-stm32mp1.c
drivers/clk/clk-tango4.c
drivers/clk/clk.c
drivers/clk/davinci/psc.c
drivers/clk/hisilicon/Kconfig
drivers/clk/hisilicon/Makefile
drivers/clk/hisilicon/clk-hi3670.c [new file with mode: 0644]
drivers/clk/hisilicon/reset.c
drivers/clk/imx/clk-cpu.c
drivers/clk/imx/clk-imx6q.c
drivers/clk/imx/clk-imx6sl.c
drivers/clk/imx/clk-imx6sll.c
drivers/clk/imx/clk-imx6sx.c
drivers/clk/imx/clk-imx6ul.c
drivers/clk/imx/clk-imx7d.c
drivers/clk/imx/clk.h
drivers/clk/ingenic/Kconfig [new file with mode: 0644]
drivers/clk/ingenic/Makefile
drivers/clk/ingenic/jz4725b-cgu.c [new file with mode: 0644]
drivers/clk/keystone/Kconfig
drivers/clk/keystone/gate.c
drivers/clk/keystone/pll.c
drivers/clk/mediatek/clk-mt2701.c
drivers/clk/meson/axg-audio.c
drivers/clk/meson/axg.c
drivers/clk/meson/axg.h
drivers/clk/meson/clk-pll.c
drivers/clk/meson/clkc.h
drivers/clk/meson/gxbb.c
drivers/clk/meson/gxbb.h
drivers/clk/meson/meson8b.c
drivers/clk/meson/meson8b.h
drivers/clk/mmp/clk-of-mmp2.c
drivers/clk/mvebu/ap806-system-controller.c
drivers/clk/mvebu/armada-370.c
drivers/clk/mvebu/armada-375.c
drivers/clk/mvebu/armada-37xx-periph.c
drivers/clk/mvebu/armada-37xx-tbg.c
drivers/clk/mvebu/armada-37xx-xtal.c
drivers/clk/mvebu/armada-38x.c
drivers/clk/mvebu/armada-39x.c
drivers/clk/mvebu/armada-xp.c
drivers/clk/mvebu/clk-corediv.c
drivers/clk/mvebu/clk-cpu.c
drivers/clk/mvebu/common.c
drivers/clk/mvebu/common.h
drivers/clk/mvebu/cp110-system-controller.c
drivers/clk/mvebu/dove.c
drivers/clk/mvebu/kirkwood.c
drivers/clk/mvebu/mv98dx3236.c
drivers/clk/mvebu/orion.c
drivers/clk/qcom/Kconfig
drivers/clk/qcom/Makefile
drivers/clk/qcom/camcc-sdm845.c [new file with mode: 0644]
drivers/clk/qcom/clk-alpha-pll.c
drivers/clk/qcom/clk-branch.c
drivers/clk/qcom/clk-hfpll.c [new file with mode: 0644]
drivers/clk/qcom/clk-hfpll.h [new file with mode: 0644]
drivers/clk/qcom/clk-krait.c [new file with mode: 0644]
drivers/clk/qcom/clk-krait.h [new file with mode: 0644]
drivers/clk/qcom/clk-rcg.h
drivers/clk/qcom/clk-rcg2.c
drivers/clk/qcom/gcc-ipq806x.c
drivers/clk/qcom/gcc-msm8960.c
drivers/clk/qcom/gcc-msm8996.c
drivers/clk/qcom/gcc-qcs404.c [new file with mode: 0644]
drivers/clk/qcom/gcc-sdm660.c [new file with mode: 0644]
drivers/clk/qcom/gcc-sdm845.c
drivers/clk/qcom/hfpll.c [new file with mode: 0644]
drivers/clk/qcom/kpss-xcc.c [new file with mode: 0644]
drivers/clk/qcom/krait-cc.c [new file with mode: 0644]
drivers/clk/renesas/Kconfig
drivers/clk/renesas/Makefile
drivers/clk/renesas/clk-div6.c
drivers/clk/renesas/clk-emev2.c
drivers/clk/renesas/clk-mstp.c
drivers/clk/renesas/clk-r8a73a4.c
drivers/clk/renesas/clk-r8a7740.c
drivers/clk/renesas/clk-r8a7778.c
drivers/clk/renesas/clk-r8a7779.c
drivers/clk/renesas/clk-rcar-gen2.c
drivers/clk/renesas/clk-rz.c
drivers/clk/renesas/clk-sh73a0.c
drivers/clk/renesas/r7s9210-cpg-mssr.c [new file with mode: 0644]
drivers/clk/renesas/r8a7743-cpg-mssr.c
drivers/clk/renesas/r8a7745-cpg-mssr.c
drivers/clk/renesas/r8a774a1-cpg-mssr.c [new file with mode: 0644]
drivers/clk/renesas/r8a774c0-cpg-mssr.c [new file with mode: 0644]
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
drivers/clk/renesas/r8a77970-cpg-mssr.c
drivers/clk/renesas/r8a77980-cpg-mssr.c
drivers/clk/renesas/r8a77990-cpg-mssr.c
drivers/clk/renesas/r8a77995-cpg-mssr.c
drivers/clk/renesas/r9a06g032-clocks.c
drivers/clk/renesas/rcar-gen2-cpg.c
drivers/clk/renesas/rcar-gen2-cpg.h
drivers/clk/renesas/rcar-gen3-cpg.c
drivers/clk/renesas/rcar-gen3-cpg.h
drivers/clk/renesas/rcar-usb2-clock-sel.c
drivers/clk/renesas/renesas-cpg-mssr.c
drivers/clk/renesas/renesas-cpg-mssr.h
drivers/clk/rockchip/clk-ddr.c
drivers/clk/rockchip/clk-rk3188.c
drivers/clk/rockchip/clk-rk3288.c
drivers/clk/rockchip/clk-rk3328.c
drivers/clk/samsung/clk-cpu.c
drivers/clk/samsung/clk-cpu.h
drivers/clk/samsung/clk-exynos-audss.c
drivers/clk/samsung/clk-exynos3250.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos5250.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/samsung/clk-exynos5433.c
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/samsung/clk-s5pv210.c
drivers/clk/samsung/clk.c
drivers/clk/samsung/clk.h
drivers/clk/st/clkgen-fsyn.c
drivers/clk/sunxi-ng/ccu-sun50i-a64.c
drivers/clk/sunxi-ng/ccu-sun50i-a64.h
drivers/clk/sunxi-ng/ccu-sun50i-h6.c
drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
drivers/clk/sunxi-ng/ccu-sun8i-h3.c
drivers/clk/sunxi-ng/ccu-sun8i-r40.c
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/sunxi/clk-mod0.c
drivers/clk/sunxi/clk-sun9i-core.c
drivers/clk/sunxi/clk-sunxi.c
drivers/clk/tegra/clk-dfll.c
drivers/clk/tegra/clk-tegra210.c
drivers/clk/ti/Makefile
drivers/clk/ti/apll.c
drivers/clk/ti/clk-33xx-compat.c [new file with mode: 0644]
drivers/clk/ti/clk-33xx.c
drivers/clk/ti/clk-43xx-compat.c [new file with mode: 0644]
drivers/clk/ti/clk-43xx.c
drivers/clk/ti/clk-7xx-compat.c [new file with mode: 0644]
drivers/clk/ti/clk-7xx.c
drivers/clk/ti/clk-dra7-atl.c
drivers/clk/ti/clk.c
drivers/clk/ti/clkctrl.c
drivers/clk/ti/clock.h
drivers/clk/ti/composite.c
drivers/clk/ti/divider.c
drivers/clk/ti/dpll.c
drivers/clk/ti/dpll3xxx.c
drivers/clk/ti/fapll.c
drivers/clk/ti/fixed-factor.c
drivers/clk/ti/gate.c
drivers/clk/ti/interface.c
drivers/clk/ti/mux.c
drivers/clk/zynq/clkc.c
include/dt-bindings/clock/am3.h
include/dt-bindings/clock/am4.h
include/dt-bindings/clock/at91.h
include/dt-bindings/clock/dra7.h
include/dt-bindings/clock/exynos4.h
include/dt-bindings/clock/hi3670-clock.h [new file with mode: 0644]
include/dt-bindings/clock/imx6qdl-clock.h
include/dt-bindings/clock/imx6sl-clock.h
include/dt-bindings/clock/imx6sll-clock.h
include/dt-bindings/clock/imx6sx-clock.h
include/dt-bindings/clock/imx6ul-clock.h
include/dt-bindings/clock/jz4725b-cgu.h [new file with mode: 0644]
include/dt-bindings/clock/maxim,max77686.h
include/dt-bindings/clock/maxim,max77802.h
include/dt-bindings/clock/qcom,camcc-sdm845.h [new file with mode: 0644]
include/dt-bindings/clock/qcom,gcc-msm8960.h
include/dt-bindings/clock/qcom,gcc-msm8996.h
include/dt-bindings/clock/qcom,gcc-qcs404.h [new file with mode: 0644]
include/dt-bindings/clock/qcom,gcc-sdm660.h [new file with mode: 0644]
include/dt-bindings/clock/qcom,gcc-sdm845.h
include/dt-bindings/clock/r7s72100-clock.h
include/dt-bindings/clock/r7s9210-cpg-mssr.h [new file with mode: 0644]
include/dt-bindings/clock/r8a7743-cpg-mssr.h
include/dt-bindings/clock/r8a7744-cpg-mssr.h [new file with mode: 0644]
include/dt-bindings/clock/r8a7745-cpg-mssr.h
include/dt-bindings/clock/r8a774a1-cpg-mssr.h [new file with mode: 0644]
include/dt-bindings/clock/r8a774c0-cpg-mssr.h [new file with mode: 0644]
include/dt-bindings/clock/r8a7790-cpg-mssr.h
include/dt-bindings/clock/r8a7791-cpg-mssr.h
include/dt-bindings/clock/r8a7792-cpg-mssr.h
include/dt-bindings/clock/r8a7793-clock.h
include/dt-bindings/clock/r8a7793-cpg-mssr.h
include/dt-bindings/clock/r8a7794-clock.h
include/dt-bindings/clock/r8a7794-cpg-mssr.h
include/dt-bindings/clock/r8a7795-cpg-mssr.h
include/dt-bindings/clock/r8a7796-cpg-mssr.h
include/dt-bindings/clock/r8a77970-cpg-mssr.h
include/dt-bindings/clock/r8a77995-cpg-mssr.h
include/dt-bindings/clock/renesas-cpg-mssr.h
include/dt-bindings/clock/rk3188-cru-common.h
include/dt-bindings/clock/samsung,s2mps11.h
include/dt-bindings/clock/samsung,s3c64xx-clock.h
include/dt-bindings/clock/sun50i-a64-ccu.h
include/dt-bindings/reset/actions,s700-reset.h [new file with mode: 0644]
include/dt-bindings/reset/actions,s900-reset.h [new file with mode: 0644]
include/linux/clk-provider.h
include/linux/clk.h
include/linux/clk/renesas.h
include/linux/clk/ti.h

index 1333db9acfee11aa47b9972ac9e41b0e081966ec..7f696362a4a1da1274f244745997bf89b13b8a10 100644 (file)
@@ -21,10 +21,29 @@ PROPERTIES
                    the register region. An optional second element specifies
                    the base address and size of the alias register region.
 
+- clocks:
+        Usage: required
+        Value type: <prop-encoded-array>
+        Definition: reference to the pll parents.
+
+- clock-names:
+        Usage: required
+        Value type: <stringlist>
+        Definition: must be "pll8_vote", "pxo".
+
+- clock-output-names:
+       Usage: optional
+       Value type: <string>
+       Definition: Name of the output clock. Typically acpuX_aux where X is a
+                   CPU number starting at 0.
+
 Example:
 
        clock-controller@2088000 {
                compatible = "qcom,kpss-acc-v2";
                reg = <0x02088000 0x1000>,
                      <0x02008000 0x1000>;
+               clocks = <&gcc PLL8_VOTE>, <&gcc PXO_SRC>;
+               clock-names = "pll8_vote", "pxo";
+               clock-output-names = "acpu0_aux";
        };
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt
new file mode 100644 (file)
index 0000000..e628758
--- /dev/null
@@ -0,0 +1,44 @@
+Krait Processor Sub-system (KPSS) Global Clock Controller (GCC)
+
+PROPERTIES
+
+- compatible:
+       Usage: required
+       Value type: <string>
+       Definition: should be one of the following. The generic compatible
+                       "qcom,kpss-gcc" should also be included.
+                       "qcom,kpss-gcc-ipq8064", "qcom,kpss-gcc"
+                       "qcom,kpss-gcc-apq8064", "qcom,kpss-gcc"
+                       "qcom,kpss-gcc-msm8974", "qcom,kpss-gcc"
+                       "qcom,kpss-gcc-msm8960", "qcom,kpss-gcc"
+
+- reg:
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: base address and size of the register region
+
+- clocks:
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: reference to the pll parents.
+
+- clock-names:
+       Usage: required
+       Value type: <stringlist>
+       Definition: must be "pll8_vote", "pxo".
+
+- clock-output-names:
+       Usage: required
+       Value type: <string>
+       Definition: Name of the output clock. Typically acpu_l2_aux indicating
+                   an L2 cache auxiliary clock.
+
+Example:
+
+       l2cc: clock-controller@2011000 {
+               compatible = "qcom,kpss-gcc-ipq8064", "qcom,kpss-gcc";
+               reg = <0x2011000 0x1000>;
+               clocks = <&gcc PLL8_VOTE>, <&gcc PXO_SRC>;
+               clock-names = "pll8_vote", "pxo";
+               clock-output-names = "acpu_l2_aux";
+       };
index d1e60d2973874b9ffbc140cee9e7f34c2cfbe9d4..2ef86ae96df8cb1ad98b39d92f8b7e7213a67134 100644 (file)
@@ -13,6 +13,7 @@ Required Properties:
   region.
 - clocks: Reference to the parent clocks ("hosc", "losc")
 - #clock-cells: should be 1.
+- #reset-cells: should be 1.
 
 Each clock is assigned an identifier, and client nodes can use this identifier
 to specify the clock which they consume.
@@ -36,6 +37,7 @@ Example: Clock Management Unit node:
                 reg = <0x0 0xe0160000 0x0 0x1000>;
                 clocks = <&hosc>, <&losc>;
                 #clock-cells = <1>;
+                #reset-cells = <1>;
         };
 
 Example: UART controller node that consumes clock generated by the clock
index 8f8f95056f3d4d456fd62726055052a1e60277d5..e9f70fcdfe804bd6d85dffb9627e0d7eef41be7d 100644 (file)
@@ -4,6 +4,8 @@ This binding uses the common clock binding[1].
 
 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
 
+Slow Clock controller:
+
 Required properties:
 - compatible : shall be one of the following:
        "atmel,at91sam9x5-sckc" or
@@ -16,84 +18,6 @@ Required properties:
 
        "atmel,at91sam9x5-clk-slow-rc-osc":
                at91 internal slow RC oscillator
-
-       "atmel,<chip>-pmc":
-               at91 PMC (Power Management Controller)
-               All at91 specific clocks (clocks defined below) must be child
-               node of the PMC node.
-               <chip> can be: at91rm9200, at91sam9260, at91sam9261,
-               at91sam9263, at91sam9g45, at91sam9n12, at91sam9rl, at91sam9x5,
-               sama5d2, sama5d3 or sama5d4.
-
-       "atmel,at91sam9x5-clk-slow" (under sckc node)
-       or
-       "atmel,at91sam9260-clk-slow" (under pmc node):
-               at91 slow clk
-
-       "atmel,at91rm9200-clk-main-osc"
-       "atmel,at91sam9x5-clk-main-rc-osc"
-               at91 main clk sources
-
-       "atmel,at91sam9x5-clk-main"
-       "atmel,at91rm9200-clk-main":
-               at91 main clock
-
-       "atmel,at91rm9200-clk-master" or
-       "atmel,at91sam9x5-clk-master":
-               at91 master clock
-
-       "atmel,at91sam9x5-clk-peripheral" or
-       "atmel,at91rm9200-clk-peripheral":
-               at91 peripheral clocks
-
-       "atmel,at91rm9200-clk-pll" or
-       "atmel,at91sam9g45-clk-pll" or
-       "atmel,at91sam9g20-clk-pllb" or
-       "atmel,sama5d3-clk-pll":
-               at91 pll clocks
-
-       "atmel,at91sam9x5-clk-plldiv":
-               at91 plla divisor
-
-       "atmel,at91rm9200-clk-programmable" or
-       "atmel,at91sam9g45-clk-programmable" or
-       "atmel,at91sam9x5-clk-programmable":
-               at91 programmable clocks
-
-       "atmel,at91sam9x5-clk-smd":
-               at91 SMD (Soft Modem) clock
-
-       "atmel,at91rm9200-clk-system":
-               at91 system clocks
-
-       "atmel,at91rm9200-clk-usb" or
-       "atmel,at91sam9x5-clk-usb" or
-       "atmel,at91sam9n12-clk-usb":
-               at91 usb clock
-
-       "atmel,at91sam9x5-clk-utmi":
-               at91 utmi clock
-
-       "atmel,sama5d4-clk-h32mx":
-               at91 h32mx clock
-
-       "atmel,sama5d2-clk-generated":
-               at91 generated clock
-
-       "atmel,sama5d2-clk-audio-pll-frac":
-               at91 audio fractional pll
-
-       "atmel,sama5d2-clk-audio-pll-pad":
-               at91 audio pll CLK_AUDIO output pin
-
-       "atmel,sama5d2-clk-audio-pll-pmc"
-               at91 audio pll output on AUDIOPLLCLK that feeds the PMC
-               and can be used by peripheral clock or generic clock
-
-       "atmel,sama5d2-clk-i2s-mux" (under pmc node):
-               at91 I2S clock source selection
-
-Required properties for SCKC node:
 - reg : defines the IO memory reserved for the SCKC.
 - #size-cells : shall be 0 (reg is used to encode clk id).
 - #address-cells : shall be 1 (reg is used to encode clk id).
@@ -109,428 +33,30 @@ For example:
                /* put at91 slow clocks here */
        };
 
+Power Management Controller (PMC):
 
-Required properties for internal slow RC oscillator:
-- #clock-cells : from common clock binding; shall be set to 0.
-- clock-frequency : define the internal RC oscillator frequency.
-
-Optional properties:
-- clock-accuracy : define the internal RC oscillator accuracy.
-
-For example:
-       slow_rc_osc: slow_rc_osc {
-               compatible = "atmel,at91sam9x5-clk-slow-rc-osc";
-               clock-frequency = <32768>;
-               clock-accuracy = <50000000>;
-       };
-
-Required properties for slow oscillator:
-- #clock-cells : from common clock binding; shall be set to 0.
-- clocks : shall encode the main osc source clk sources (see atmel datasheet).
+Required properties:
+- compatible : shall be "atmel,<chip>-pmc", "syscon":
+       <chip> can be: at91rm9200, at91sam9260, at91sam9261,
+       at91sam9263, at91sam9g45, at91sam9n12, at91sam9rl, at91sam9g15,
+       at91sam9g25, at91sam9g35, at91sam9x25, at91sam9x35, at91sam9x5,
+       sama5d2, sama5d3 or sama5d4.
+- #clock-cells : from common clock binding; shall be set to 2. The first entry
+  is the type of the clock (core, system, peripheral or generated) and the
+  second entry its index as provided by the datasheet
+- clocks : Must contain an entry for each entry in clock-names.
+- clock-names: Must include the following entries: "slow_clk", "main_xtal"
 
 Optional properties:
 - atmel,osc-bypass : boolean property. Set this when a clock signal is directly
   provided on XIN.
 
 For example:
-       slow_osc: slow_osc {
-               compatible = "atmel,at91rm9200-clk-slow-osc";
-               #clock-cells = <0>;
-               clocks = <&slow_xtal>;
-       };
-
-Required properties for slow clock:
-- #clock-cells : from common clock binding; shall be set to 0.
-- clocks : shall encode the slow clk sources (see atmel datasheet).
-
-For example:
-       clk32k: slck {
-               compatible = "atmel,at91sam9x5-clk-slow";
-               #clock-cells = <0>;
-               clocks = <&slow_rc_osc &slow_osc>;
-       };
-
-Required properties for PMC node:
-- reg : defines the IO memory reserved for the PMC.
-- #size-cells : shall be 0 (reg is used to encode clk id).
-- #address-cells : shall be 1 (reg is used to encode clk id).
-- interrupts : shall be set to PMC interrupt line.
-- interrupt-controller : tell that the PMC is an interrupt controller.
-- #interrupt-cells : must be set to 1. The first cell encodes the interrupt id,
-       and reflect the bit position in the PMC_ER/DR/SR registers.
-       You can use the dt macros defined in dt-bindings/clock/at91.h.
-       0 (AT91_PMC_MOSCS) -> main oscillator ready
-       1 (AT91_PMC_LOCKA) -> PLL A ready
-       2 (AT91_PMC_LOCKB) -> PLL B ready
-       3 (AT91_PMC_MCKRDY) -> master clock ready
-       6 (AT91_PMC_LOCKU) -> UTMI PLL clock ready
-       8 .. 15 (AT91_PMC_PCKRDY(id)) -> programmable clock ready
-       16 (AT91_PMC_MOSCSELS) -> main oscillator selected
-       17 (AT91_PMC_MOSCRCS) -> RC main oscillator stabilized
-       18 (AT91_PMC_CFDEV) -> clock failure detected
-
-For example:
-       pmc: pmc@fffffc00 {
-               compatible = "atmel,sama5d3-pmc";
-               interrupts = <1 4 7>;
-               interrupt-controller;
-               #interrupt-cells = <2>;
-               #size-cells = <0>;
-               #address-cells = <1>;
-
-               /* put at91 clocks here */
-       };
-
-Required properties for main clock internal RC oscillator:
-- interrupts : shall be set to "<0>".
-- clock-frequency : define the internal RC oscillator frequency.
-
-Optional properties:
-- clock-accuracy : define the internal RC oscillator accuracy.
-
-For example:
-       main_rc_osc: main_rc_osc {
-               compatible = "atmel,at91sam9x5-clk-main-rc-osc";
-               interrupt-parent = <&pmc>;
-               interrupts = <0>;
-               clock-frequency = <12000000>;
-               clock-accuracy = <50000000>;
-       };
-
-Required properties for main clock oscillator:
-- interrupts : shall be set to "<0>".
-- #clock-cells : from common clock binding; shall be set to 0.
-- clocks : shall encode the main osc source clk sources (see atmel datasheet).
-
-Optional properties:
-- atmel,osc-bypass : boolean property. Specified if a clock signal is provided
-  on XIN.
-
-  clock signal is directly provided on XIN pin.
-
-For example:
-       main_osc: main_osc {
-               compatible = "atmel,at91rm9200-clk-main-osc";
-               interrupt-parent = <&pmc>;
-               interrupts = <0>;
-               #clock-cells = <0>;
-               clocks = <&main_xtal>;
-       };
-
-Required properties for main clock:
-- interrupts : shall be set to "<0>".
-- #clock-cells : from common clock binding; shall be set to 0.
-- clocks : shall encode the main clk sources (see atmel datasheet).
-
-For example:
-       main: mainck {
-               compatible = "atmel,at91sam9x5-clk-main";
-               interrupt-parent = <&pmc>;
-               interrupts = <0>;
-               #clock-cells = <0>;
-               clocks = <&main_rc_osc &main_osc>;
-       };
-
-Required properties for master clock:
-- interrupts : shall be set to "<3>".
-- #clock-cells : from common clock binding; shall be set to 0.
-- clocks : shall be the master clock sources (see atmel datasheet) phandles.
-       e.g. "<&ck32k>, <&main>, <&plla>, <&pllb>".
-- atmel,clk-output-range : minimum and maximum clock frequency (two u32
-                          fields).
-          e.g. output = <0 133000000>; <=> 0 to 133MHz.
-- atmel,clk-divisors : master clock divisors table (four u32 fields).
-               0 <=> reserved value.
-               e.g. divisors = <1 2 4 6>;
-- atmel,master-clk-have-div3-pres : some SoC use the reserved value 7 in the
-                                   PRES field as CLOCK_DIV3 (e.g sam9x5).
-
-For example:
-       mck: mck {
-               compatible = "atmel,at91rm9200-clk-master";
-               interrupt-parent = <&pmc>;
-               interrupts = <3>;
-               #clock-cells = <0>;
-               atmel,clk-output-range = <0 133000000>;
-               atmel,clk-divisors = <1 2 4 0>;
-       };
-
-Required properties for peripheral clocks:
-- #size-cells : shall be 0 (reg is used to encode clk id).
-- #address-cells : shall be 1 (reg is used to encode clk id).
-- clocks : shall be the master clock phandle.
-       e.g. clocks = <&mck>;
-- name: device tree node describing a specific peripheral clock.
-       * #clock-cells : from common clock binding; shall be set to 0.
-       * reg: peripheral id. See Atmel's datasheets to get a full
-         list of peripheral ids.
-       * atmel,clk-output-range : minimum and maximum clock frequency
-         (two u32 fields). Only valid on at91sam9x5-clk-peripheral
-         compatible IPs.
-
-For example:
-       periph: periphck {
-               compatible = "atmel,at91sam9x5-clk-peripheral";
-               #size-cells = <0>;
-               #address-cells = <1>;
-               clocks = <&mck>;
-
-               ssc0_clk {
-                       #clock-cells = <0>;
-                       reg = <2>;
-                       atmel,clk-output-range = <0 133000000>;
-               };
-
-               usart0_clk {
-                       #clock-cells = <0>;
-                       reg = <3>;
-                       atmel,clk-output-range = <0 66000000>;
-               };
-       };
-
-
-Required properties for pll clocks:
-- interrupts : shall be set to "<1>".
-- #clock-cells : from common clock binding; shall be set to 0.
-- clocks : shall be the main clock phandle.
-- reg : pll id.
-       0 -> PLL A
-       1 -> PLL B
-- atmel,clk-input-range : minimum and maximum source clock frequency (two u32
-                         fields).
-         e.g. input = <1 32000000>; <=> 1 to 32MHz.
-- #atmel,pll-clk-output-range-cells : number of cells reserved for pll output
-                                     range description. Sould be set to 2, 3
-                                     or 4.
-       * 1st and 2nd cells represent the frequency range (min-max).
-       * 3rd cell is optional and represents the OUT field value for the given
-         range.
-       * 4th cell is optional and represents the ICPLL field (PLLICPR
-         register)
-- atmel,pll-clk-output-ranges : pll output frequency ranges + optional parameter
-                               depending on #atmel,pll-output-range-cells
-                               property value.
-
-For example:
-       plla: pllack {
-               compatible = "atmel,at91sam9g45-clk-pll";
-               interrupt-parent = <&pmc>;
-               interrupts = <1>;
-               #clock-cells = <0>;
-               clocks = <&main>;
-               reg = <0>;
-               atmel,clk-input-range = <2000000 32000000>;
-               #atmel,pll-clk-output-range-cells = <4>;
-               atmel,pll-clk-output-ranges = <74500000 800000000 0 0
-                                              69500000 750000000 1 0
-                                              64500000 700000000 2 0
-                                              59500000 650000000 3 0
-                                              54500000 600000000 0 1
-                                              49500000 550000000 1 1
-                                              44500000 500000000 2 1
-                                              40000000 450000000 3 1>;
-       };
-
-Required properties for plldiv clocks (plldiv = pll / 2):
-- #clock-cells : from common clock binding; shall be set to 0.
-- clocks : shall be the plla clock phandle.
-
-The pll divisor is equal to 2 and cannot be changed.
-
-For example:
-       plladiv: plladivck {
-               compatible = "atmel,at91sam9x5-clk-plldiv";
-               #clock-cells = <0>;
-               clocks = <&plla>;
-       };
-
-Required properties for programmable clocks:
-- #size-cells : shall be 0 (reg is used to encode clk id).
-- #address-cells : shall be 1 (reg is used to encode clk id).
-- clocks : shall be the programmable clock source phandles.
-       e.g. clocks = <&clk32k>, <&main>, <&plla>, <&pllb>;
-- name: device tree node describing a specific prog clock.
-       * #clock-cells : from common clock binding; shall be set to 0.
-       * reg : programmable clock id (register offset from  PCKx
-                        register).
-       * interrupts : shall be set to "<(8 + id)>".
-
-For example:
-       prog: progck {
-               compatible = "atmel,at91sam9g45-clk-programmable";
-               #size-cells = <0>;
-               #address-cells = <1>;
-               interrupt-parent = <&pmc>;
-               clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>;
-
-               prog0 {
-                       #clock-cells = <0>;
-                       reg = <0>;
-                       interrupts = <8>;
-               };
-
-               prog1 {
-                       #clock-cells = <0>;
-                       reg = <1>;
-                       interrupts = <9>;
-               };
-       };
-
-
-Required properties for smd clock:
-- #clock-cells : from common clock binding; shall be set to 0.
-- clocks : shall be the smd clock source phandles.
-       e.g. clocks = <&plladiv>, <&utmi>;
-
-For example:
-       smd: smdck {
-               compatible = "atmel,at91sam9x5-clk-smd";
-               #clock-cells = <0>;
-               clocks = <&plladiv>, <&utmi>;
-       };
-
-Required properties for system clocks:
-- #size-cells : shall be 0 (reg is used to encode clk id).
-- #address-cells : shall be 1 (reg is used to encode clk id).
-- name: device tree node describing a specific system clock.
-       * #clock-cells : from common clock binding; shall be set to 0.
-       * reg: system clock id (bit position in SCER/SCDR/SCSR registers).
-             See Atmel's datasheet to get a full list of system clock ids.
-
-For example:
-       system: systemck {
-               compatible = "atmel,at91rm9200-clk-system";
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               ddrck {
-                       #clock-cells = <0>;
-                       reg = <2>;
-                       clocks = <&mck>;
-               };
-
-               uhpck {
-                       #clock-cells = <0>;
-                       reg = <6>;
-                       clocks = <&usb>;
-               };
-
-               udpck {
-                       #clock-cells = <0>;
-                       reg = <7>;
-                       clocks = <&usb>;
-               };
-       };
-
-
-Required properties for usb clock:
-- #clock-cells : from common clock binding; shall be set to 0.
-- clocks : shall be the smd clock source phandles.
-       e.g. clocks = <&pllb>;
-- atmel,clk-divisors (only available for "atmel,at91rm9200-clk-usb"):
-       usb clock divisor table.
-       e.g. divisors = <1 2 4 0>;
-
-For example:
-       usb: usbck {
-               compatible = "atmel,at91sam9x5-clk-usb";
-               #clock-cells = <0>;
-               clocks = <&plladiv>, <&utmi>;
-       };
-
-       usb: usbck {
-               compatible = "atmel,at91rm9200-clk-usb";
-               #clock-cells = <0>;
-               clocks = <&pllb>;
-               atmel,clk-divisors = <1 2 4 0>;
-       };
-
-
-Required properties for utmi clock:
-- interrupts : shall be set to "<AT91_PMC_LOCKU IRQ_TYPE_LEVEL_HIGH>".
-- #clock-cells : from common clock binding; shall be set to 0.
-- clocks : shall be the main clock source phandle.
-
-For example:
-       utmi: utmick {
-               compatible = "atmel,at91sam9x5-clk-utmi";
-               interrupt-parent = <&pmc>;
-               interrupts = <AT91_PMC_LOCKU IRQ_TYPE_LEVEL_HIGH>;
-               #clock-cells = <0>;
-               clocks = <&main>;
-       };
-
-Required properties for 32 bits bus Matrix clock (h32mx clock):
-- #clock-cells : from common clock binding; shall be set to 0.
-- clocks : shall be the master clock source phandle.
-
-For example:
-       h32ck: h32mxck {
-               #clock-cells = <0>;
-               compatible = "atmel,sama5d4-clk-h32mx";
-               clocks = <&mck>;
-       };
-
-Required properties for generated clocks:
-- #size-cells : shall be 0 (reg is used to encode clk id).
-- #address-cells : shall be 1 (reg is used to encode clk id).
-- clocks : shall be the generated clock source phandles.
-       e.g. clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>, <&audio_pll_pmc>;
-- name: device tree node describing a specific generated clock.
-       * #clock-cells : from common clock binding; shall be set to 0.
-       * reg: peripheral id. See Atmel's datasheets to get a full
-         list of peripheral ids.
-       * atmel,clk-output-range : minimum and maximum clock frequency
-         (two u32 fields).
-
-For example:
-       gck {
-               compatible = "atmel,sama5d2-clk-generated";
-               #address-cells = <1>;
-               #size-cells = <0>;
-               clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>, <&audio_pll_pmc>;
-
-               tcb0_gclk: tcb0_gclk {
-                       #clock-cells = <0>;
-                       reg = <35>;
-                       atmel,clk-output-range = <0 83000000>;
-               };
-
-               pwm_gclk: pwm_gclk {
-                       #clock-cells = <0>;
-                       reg = <38>;
-                       atmel,clk-output-range = <0 83000000>;
-               };
-       };
-
-Required properties for I2S mux clocks:
-- #size-cells : shall be 0 (reg is used to encode I2S bus id).
-- #address-cells : shall be 1 (reg is used to encode I2S bus id).
-- name: device tree node describing a specific mux clock.
-       * #clock-cells : from common clock binding; shall be set to 0.
-       * clocks : shall be the mux clock parent phandles; shall be 2 phandles:
-         peripheral and generated clock; the first phandle shall belong to the
-         peripheral clock and the second one shall belong to the generated
-         clock; "clock-indices" property can be user to specify
-         the correct order.
-       * reg: I2S bus id of the corresponding mux clock.
-         e.g. reg = <0>; for i2s0, reg = <1>; for i2s1
-
-For example:
-       i2s_clkmux {
-               compatible = "atmel,sama5d2-clk-i2s-mux";
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               i2s0muxck: i2s0_muxclk {
-                       clocks = <&i2s0_clk>, <&i2s0_gclk>;
-                       #clock-cells = <0>;
-                       reg = <0>;
-               };
-
-               i2s1muxck: i2s1_muxclk {
-                       clocks = <&i2s1_clk>, <&i2s1_gclk>;
-                       #clock-cells = <0>;
-                       reg = <1>;
-               };
+       pmc: pmc@f0018000 {
+               compatible = "atmel,sama5d4-pmc", "syscon";
+               reg = <0xf0018000 0x120>;
+               interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+               #clock-cells = <2>;
+               clocks = <&clk32k>, <&main_xtal>;
+               clock-names = "slow_clk", "main_xtal";
        };
diff --git a/Documentation/devicetree/bindings/clock/hi3670-clock.txt b/Documentation/devicetree/bindings/clock/hi3670-clock.txt
new file mode 100644 (file)
index 0000000..66f3697
--- /dev/null
@@ -0,0 +1,43 @@
+* Hisilicon Hi3670 Clock Controller
+
+The Hi3670 clock controller generates and supplies clock to various
+controllers within the Hi3670 SoC.
+
+Required Properties:
+
+- compatible: the compatible should be one of the following strings to
+       indicate the clock controller functionality.
+
+       - "hisilicon,hi3670-crgctrl"
+       - "hisilicon,hi3670-pctrl"
+       - "hisilicon,hi3670-pmuctrl"
+       - "hisilicon,hi3670-sctrl"
+       - "hisilicon,hi3670-iomcu"
+       - "hisilicon,hi3670-media1-crg"
+       - "hisilicon,hi3670-media2-crg"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in <dt-bindings/clock/hi3670-clock.h>.
+
+Examples:
+       crg_ctrl: clock-controller@fff35000 {
+               compatible = "hisilicon,hi3670-crgctrl", "syscon";
+               reg = <0x0 0xfff35000 0x0 0x1000>;
+               #clock-cells = <1>;
+       };
+
+       uart0: serial@fdf02000 {
+               compatible = "arm,pl011", "arm,primecell";
+               reg = <0x0 0xfdf02000 0x0 0x1000>;
+               interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&crg_ctrl HI3670_CLK_GATE_UART0>,
+                        <&crg_ctrl HI3670_PCLK>;
+               clock-names = "uartclk", "apb_pclk";
+       };
index f8d4134ae4095682182be5313148ddb2394ec017..ba5a442026b71d65e7bda99bd801ec35bc5fed57 100644 (file)
@@ -6,8 +6,11 @@ to provide many different clock signals derived from only 2 external source
 clocks.
 
 Required properties:
-- compatible : Should be "ingenic,<soctype>-cgu".
-  For example "ingenic,jz4740-cgu" or "ingenic,jz4780-cgu".
+- compatible : Should be one of:
+  * ingenic,jz4740-cgu
+  * ingenic,jz4725b-cgu
+  * ingenic,jz4770-cgu
+  * ingenic,jz4780-cgu
 - reg : The address & length of the CGU registers.
 - clocks : List of phandle & clock specifiers for clocks external to the CGU.
   Two such external clocks should be specified - first the external crystal
diff --git a/Documentation/devicetree/bindings/clock/qcom,camcc.txt b/Documentation/devicetree/bindings/clock/qcom,camcc.txt
new file mode 100644 (file)
index 0000000..c5eb669
--- /dev/null
@@ -0,0 +1,18 @@
+Qualcomm Camera Clock & Reset Controller Binding
+------------------------------------------------
+
+Required properties :
+- compatible : shall contain "qcom,sdm845-camcc".
+- reg : shall contain base register location and length.
+- #clock-cells : from common clock binding, shall contain 1.
+- #reset-cells : from common reset binding, shall contain 1.
+- #power-domain-cells : from generic power domain binding, shall contain 1.
+
+Example:
+       camcc: clock-controller@ad00000 {
+               compatible = "qcom,sdm845-camcc";
+               reg = <0xad00000 0x10000>;
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+               #power-domain-cells = <1>;
+       };
index 664ea1fd6c76a18ce158b4fc01b536ba31dfeeda..52d9345c9927b80c40acba737f20f83f4fcbc8e7 100644 (file)
@@ -19,6 +19,9 @@ Required properties :
                        "qcom,gcc-msm8996"
                        "qcom,gcc-msm8998"
                        "qcom,gcc-mdm9615"
+                       "qcom,gcc-qcs404"
+                       "qcom,gcc-sdm630"
+                       "qcom,gcc-sdm660"
                        "qcom,gcc-sdm845"
 
 - reg : shall contain base register location and length
diff --git a/Documentation/devicetree/bindings/clock/qcom,hfpll.txt b/Documentation/devicetree/bindings/clock/qcom,hfpll.txt
new file mode 100644 (file)
index 0000000..ec02a02
--- /dev/null
@@ -0,0 +1,60 @@
+High-Frequency PLL (HFPLL)
+
+PROPERTIES
+
+- compatible:
+       Usage: required
+       Value type: <string>:
+               shall contain only one of the following. The generic
+               compatible "qcom,hfpll" should be also included.
+
+                        "qcom,hfpll-ipq8064", "qcom,hfpll"
+                        "qcom,hfpll-apq8064", "qcom,hfpll"
+                        "qcom,hfpll-msm8974", "qcom,hfpll"
+                        "qcom,hfpll-msm8960", "qcom,hfpll"
+
+- reg:
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: address and size of HPLL registers. An optional second
+                   element specifies the address and size of the alias
+                   register region.
+
+- clocks:
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: reference to the xo clock.
+
+- clock-names:
+       Usage: required
+       Value type: <stringlist>
+       Definition: must be "xo".
+
+- clock-output-names:
+       Usage: required
+       Value type: <string>
+       Definition: Name of the PLL. Typically hfpllX where X is a CPU number
+                   starting at 0. Otherwise hfpll_Y where Y is more specific
+                   such as "l2".
+
+Example:
+
+1) An HFPLL for the L2 cache.
+
+       clock-controller@f9016000 {
+               compatible = "qcom,hfpll-ipq8064", "qcom,hfpll";
+               reg = <0xf9016000 0x30>;
+               clocks = <&xo_board>;
+               clock-names = "xo";
+               clock-output-names = "hfpll_l2";
+       };
+
+2) An HFPLL for CPU0. This HFPLL has the alias register region.
+
+       clock-controller@f908a000 {
+               compatible = "qcom,hfpll-ipq8064", "qcom,hfpll";
+               reg = <0xf908a000 0x30>, <0xf900a000 0x30>;
+               clocks = <&xo_board>;
+               clock-names = "xo";
+               clock-output-names = "hfpll0";
+       };
diff --git a/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt b/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
new file mode 100644 (file)
index 0000000..030ba60
--- /dev/null
@@ -0,0 +1,34 @@
+Krait Clock Controller
+
+PROPERTIES
+
+- compatible:
+       Usage: required
+       Value type: <string>
+       Definition: must be one of:
+                       "qcom,krait-cc-v1"
+                       "qcom,krait-cc-v2"
+
+- #clock-cells:
+       Usage: required
+       Value type: <u32>
+       Definition: must be 1
+
+- clocks:
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: reference to the clock parents of hfpll, secondary muxes.
+
+- clock-names:
+       Usage: required
+       Value type: <stringlist>
+       Definition: must be "hfpll0", "hfpll1", "acpu0_aux", "acpu1_aux", "qsb".
+
+Example:
+
+       kraitcc: clock-controller {
+               compatible = "qcom,krait-cc-v1";
+               clocks = <&hfpll0>, <&hfpll1>, <&acpu0_aux>, <&acpu1_aux>, <qsb>;
+               clock-names = "hfpll0", "hfpll1", "acpu0_aux", "acpu1_aux", "qsb";
+               #clock-cells = <1>;
+       };
index db542abadb75bf0ca395ac0910506bce458fecee..916a601b76a7704931df7797e48f52276e4fd674 100644 (file)
@@ -13,9 +13,13 @@ They provide the following functionalities:
 
 Required Properties:
   - compatible: Must be one of:
+      - "renesas,r7s9210-cpg-mssr" for the r7s9210 SoC (RZ/A2)
       - "renesas,r8a7743-cpg-mssr" for the r8a7743 SoC (RZ/G1M)
+      - "renesas,r8a7744-cpg-mssr" for the r8a7744 SoC (RZ/G1N)
       - "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E)
       - "renesas,r8a77470-cpg-mssr" for the r8a77470 SoC (RZ/G1C)
+      - "renesas,r8a774a1-cpg-mssr" for the r8a774a1 SoC (RZ/G2M)
+      - "renesas,r8a774c0-cpg-mssr" for the r8a774c0 SoC (RZ/G2E)
       - "renesas,r8a7790-cpg-mssr" for the r8a7790 SoC (R-Car H2)
       - "renesas,r8a7791-cpg-mssr" for the r8a7791 SoC (R-Car M2-W)
       - "renesas,r8a7792-cpg-mssr" for the r8a7792 SoC (R-Car V2H)
@@ -35,12 +39,13 @@ Required Properties:
   - clocks: References to external parent clocks, one entry for each entry in
     clock-names
   - clock-names: List of external parent clock names. Valid names are:
-      - "extal" (r8a7743, r8a7745, r8a77470, r8a7790, r8a7791, r8a7792,
-                r8a7793, r8a7794, r8a7795, r8a7796, r8a77965, r8a77970,
-                r8a77980, r8a77990, r8a77995)
-      - "extalr" (r8a7795, r8a7796, r8a77965, r8a77970, r8a77980)
-      - "usb_extal" (r8a7743, r8a7745, r8a77470, r8a7790, r8a7791, r8a7793,
-                    r8a7794)
+      - "extal" (r7s9210, r8a7743, r8a7744, r8a7745, r8a77470, r8a774a1,
+                r8a774c0, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794,
+                r8a7795, r8a7796, r8a77965, r8a77970, r8a77980, r8a77990,
+                r8a77995)
+      - "extalr" (r8a774a1, r8a7795, r8a7796, r8a77965, r8a77970, r8a77980)
+      - "usb_extal" (r8a7743, r8a7744, r8a7745, r8a77470, r8a7790, r8a7791,
+                    r8a7793, r8a7794)
 
   - #clock-cells: Must be 2
       - For CPG core clocks, the two clock specifier cells must be "CPG_CORE"
index e5ad0708849a2f57d14d6e1f8141f6469d44aeeb..c8e198631d4182511d1bb3dee008ceae4c01f4d2 100644 (file)
@@ -7,6 +7,9 @@ config DMABOUNCE
        bool
        select ZONE_DMA
 
+config KRAIT_L2_ACCESSORS
+       bool
+
 config SHARP_LOCOMO
        bool
 
index 3157be413297e5d22ad3174e2082b5199fc3083c..219a260bbe5f78abec23091e7ad07a7b1e992624 100644 (file)
@@ -7,6 +7,7 @@ obj-y                           += firmware.o
 
 obj-$(CONFIG_SA1111)           += sa1111.o
 obj-$(CONFIG_DMABOUNCE)                += dmabounce.o
+obj-$(CONFIG_KRAIT_L2_ACCESSORS) += krait-l2-accessors.o
 obj-$(CONFIG_SHARP_LOCOMO)     += locomo.o
 obj-$(CONFIG_SHARP_PARAM)      += sharpsl_param.o
 obj-$(CONFIG_SHARP_SCOOP)      += scoop.o
diff --git a/arch/arm/common/krait-l2-accessors.c b/arch/arm/common/krait-l2-accessors.c
new file mode 100644 (file)
index 0000000..9a97dda
--- /dev/null
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include <linux/spinlock.h>
+#include <linux/export.h>
+
+#include <asm/barrier.h>
+#include <asm/krait-l2-accessors.h>
+
+static DEFINE_RAW_SPINLOCK(krait_l2_lock);
+
+void krait_set_l2_indirect_reg(u32 addr, u32 val)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&krait_l2_lock, flags);
+       /*
+        * Select the L2 window by poking l2cpselr, then write to the window
+        * via l2cpdr.
+        */
+       asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
+       isb();
+       asm volatile ("mcr p15, 3, %0, c15, c0, 7 @ l2cpdr" : : "r" (val));
+       isb();
+
+       raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
+}
+EXPORT_SYMBOL(krait_set_l2_indirect_reg);
+
+u32 krait_get_l2_indirect_reg(u32 addr)
+{
+       u32 val;
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&krait_l2_lock, flags);
+       /*
+        * Select the L2 window by poking l2cpselr, then read from the window
+        * via l2cpdr.
+        */
+       asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
+       isb();
+       asm volatile ("mrc p15, 3, %0, c15, c0, 7 @ l2cpdr" : "=r" (val));
+
+       raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
+
+       return val;
+}
+EXPORT_SYMBOL(krait_get_l2_indirect_reg);
diff --git a/arch/arm/include/asm/krait-l2-accessors.h b/arch/arm/include/asm/krait-l2-accessors.h
new file mode 100644 (file)
index 0000000..a5f2cdd
--- /dev/null
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASMARM_KRAIT_L2_ACCESSORS_H
+#define __ASMARM_KRAIT_L2_ACCESSORS_H
+
+extern void krait_set_l2_indirect_reg(u32 addr, u32 val);
+extern u32 krait_get_l2_indirect_reg(u32 addr);
+
+#endif
diff --git a/arch/arm/mach-davinci/include/mach/clock.h b/arch/arm/mach-davinci/include/mach/clock.h
deleted file mode 100644 (file)
index 42ed4f2..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * arch/arm/mach-davinci/include/mach/clock.h
- *
- * Clock control driver for DaVinci - header file
- *
- * Authors: Vladimir Barinov <source@mvista.com>
- *
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#ifndef __ASM_ARCH_DAVINCI_CLOCK_H
-#define __ASM_ARCH_DAVINCI_CLOCK_H
-
-struct clk;
-
-int davinci_clk_reset_assert(struct clk *c);
-int davinci_clk_reset_deassert(struct clk *c);
-
-#endif
index 1deafb4db60c296c4f4772d1b182cd2362feea37..81cdb4eaca07fe13322e24593123dc0936f6ece1 100644 (file)
@@ -287,6 +287,7 @@ source "drivers/clk/actions/Kconfig"
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
 source "drivers/clk/imgtec/Kconfig"
+source "drivers/clk/ingenic/Kconfig"
 source "drivers/clk/keystone/Kconfig"
 source "drivers/clk/mediatek/Kconfig"
 source "drivers/clk/meson/Kconfig"
index ad11421bdacd8a64f571d581fdccc39791f73835..72be7a38cff1e8ab8b73e84ee607983c192e7ce9 100644 (file)
@@ -72,7 +72,8 @@ obj-$(CONFIG_H8300)                   += h8300/
 obj-$(CONFIG_ARCH_HISI)                        += hisilicon/
 obj-y                                  += imgtec/
 obj-$(CONFIG_ARCH_MXC)                 += imx/
-obj-$(CONFIG_MACH_INGENIC)             += ingenic/
+obj-y                                  += ingenic/
+obj-$(CONFIG_ARCH_K3)                  += keystone/
 obj-$(CONFIG_ARCH_KEYSTONE)            += keystone/
 obj-$(CONFIG_MACH_LOONGSON32)          += loongson1/
 obj-y                                  += mediatek/
index dc38c85a48339cb49325029b4ac2a1f9b9268bbe..04f0a6355726f0503cfd0c4f84747b02a7d06089 100644 (file)
@@ -2,6 +2,7 @@ config CLK_ACTIONS
        bool "Clock driver for Actions Semi SoCs"
        depends on ARCH_ACTIONS || COMPILE_TEST
        select REGMAP_MMIO
+       select RESET_CONTROLLER
        default ARCH_ACTIONS
 
 if CLK_ACTIONS
index 78c17d56f9913c80c778a649ee4ae9b023b6327e..ccfdf9781ceffd65be8a45a12b6321afe9a60e14 100644 (file)
@@ -7,6 +7,7 @@ clk-owl-y                       += owl-divider.o
 clk-owl-y                      += owl-factor.o
 clk-owl-y                      += owl-composite.o
 clk-owl-y                      += owl-pll.o
+clk-owl-y                      += owl-reset.o
 
 # SoC support
 obj-$(CONFIG_CLK_OWL_S700)     += owl-s700.o
index 61c1071b5180a8168cff7382e31f1d81ee536b49..32dd29e0a37e18ea2e160816e618fe58403db097 100644 (file)
@@ -39,7 +39,7 @@ static void owl_clk_set_regmap(const struct owl_clk_desc *desc,
 }
 
 int owl_clk_regmap_init(struct platform_device *pdev,
-                        const struct owl_clk_desc *desc)
+                       struct owl_clk_desc *desc)
 {
        void __iomem *base;
        struct regmap *regmap;
@@ -57,6 +57,7 @@ int owl_clk_regmap_init(struct platform_device *pdev,
        }
 
        owl_clk_set_regmap(desc, regmap);
+       desc->regmap = regmap;
 
        return 0;
 }
index 4fd726ec54a6c1f2e8a48ad8c38d59514aed5393..5a866a8b913dbca3b6f07389ecb540fa039ecdfc 100644 (file)
@@ -26,6 +26,9 @@ struct owl_clk_desc {
        struct owl_clk_common           **clks;
        unsigned long                   num_clks;
        struct clk_hw_onecell_data      *hw_clks;
+       const struct owl_reset_map      *resets;
+       unsigned long                   num_resets;
+       struct regmap                   *regmap;
 };
 
 static inline struct owl_clk_common *
@@ -35,7 +38,7 @@ static inline struct owl_clk_common *
 }
 
 int owl_clk_regmap_init(struct platform_device *pdev,
-                        const struct owl_clk_desc *desc);
+                       struct owl_clk_desc *desc);
 int owl_clk_probe(struct device *dev, struct clk_hw_onecell_data *hw_clks);
 
 #endif /* _OWL_COMMON_H_ */
diff --git a/drivers/clk/actions/owl-reset.c b/drivers/clk/actions/owl-reset.c
new file mode 100644 (file)
index 0000000..203f8f3
--- /dev/null
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+//
+// Actions Semi Owl SoCs Reset Management Unit driver
+//
+// Copyright (c) 2018 Linaro Ltd.
+// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include "owl-reset.h"
+
+static int owl_reset_assert(struct reset_controller_dev *rcdev,
+                           unsigned long id)
+{
+       struct owl_reset *reset = to_owl_reset(rcdev);
+       const struct owl_reset_map *map = &reset->reset_map[id];
+
+       return regmap_update_bits(reset->regmap, map->reg, map->bit, 0);
+}
+
+static int owl_reset_deassert(struct reset_controller_dev *rcdev,
+                             unsigned long id)
+{
+       struct owl_reset *reset = to_owl_reset(rcdev);
+       const struct owl_reset_map *map = &reset->reset_map[id];
+
+       return regmap_update_bits(reset->regmap, map->reg, map->bit, map->bit);
+}
+
+static int owl_reset_reset(struct reset_controller_dev *rcdev,
+                          unsigned long id)
+{
+       owl_reset_assert(rcdev, id);
+       udelay(1);
+       owl_reset_deassert(rcdev, id);
+
+       return 0;
+}
+
+static int owl_reset_status(struct reset_controller_dev *rcdev,
+                           unsigned long id)
+{
+       struct owl_reset *reset = to_owl_reset(rcdev);
+       const struct owl_reset_map *map = &reset->reset_map[id];
+       u32 reg;
+       int ret;
+
+       ret = regmap_read(reset->regmap, map->reg, &reg);
+       if (ret)
+               return ret;
+
+       /*
+        * The reset control API expects 0 if reset is not asserted,
+        * which is the opposite of what our hardware uses.
+        */
+       return !(map->bit & reg);
+}
+
+const struct reset_control_ops owl_reset_ops = {
+       .assert         = owl_reset_assert,
+       .deassert       = owl_reset_deassert,
+       .reset          = owl_reset_reset,
+       .status         = owl_reset_status,
+};
diff --git a/drivers/clk/actions/owl-reset.h b/drivers/clk/actions/owl-reset.h
new file mode 100644 (file)
index 0000000..10f5774
--- /dev/null
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+//
+// Actions Semi Owl SoCs Reset Management Unit driver
+//
+// Copyright (c) 2018 Linaro Ltd.
+// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+#ifndef _OWL_RESET_H_
+#define _OWL_RESET_H_
+
+#include <linux/reset-controller.h>
+
+struct owl_reset_map {
+       u32     reg;
+       u32     bit;
+};
+
+struct owl_reset {
+       struct reset_controller_dev     rcdev;
+       const struct owl_reset_map      *reset_map;
+       struct regmap                   *regmap;
+};
+
+static inline struct owl_reset *to_owl_reset(struct reset_controller_dev *rcdev)
+{
+       return container_of(rcdev, struct owl_reset, rcdev);
+}
+
+extern const struct reset_control_ops owl_reset_ops;
+
+#endif /* _OWL_RESET_H_ */
index 5e9531392ee57cb03a2bb22dbb5e91ac058d7e20..a2f34d13fb54304357eed076ceb11e31863e76d2 100644 (file)
 #include "owl-gate.h"
 #include "owl-mux.h"
 #include "owl-pll.h"
+#include "owl-reset.h"
 
 #include <dt-bindings/clock/actions,s700-cmu.h>
+#include <dt-bindings/reset/actions,s700-reset.h>
 
 #define CMU_COREPLL            (0x0000)
 #define CMU_DEVPLL             (0x0004)
@@ -569,20 +571,69 @@ static struct clk_hw_onecell_data s700_hw_clks = {
                .num    = CLK_NR_CLKS,
 };
 
-static const struct owl_clk_desc s700_clk_desc = {
+static const struct owl_reset_map s700_resets[] = {
+       [RESET_DE]      = { CMU_DEVRST0, BIT(0) },
+       [RESET_LCD0]    = { CMU_DEVRST0, BIT(1) },
+       [RESET_DSI]     = { CMU_DEVRST0, BIT(2) },
+       [RESET_CSI]     = { CMU_DEVRST0, BIT(13) },
+       [RESET_SI]      = { CMU_DEVRST0, BIT(14) },
+       [RESET_I2C0]    = { CMU_DEVRST1, BIT(0) },
+       [RESET_I2C1]    = { CMU_DEVRST1, BIT(1) },
+       [RESET_I2C2]    = { CMU_DEVRST1, BIT(2) },
+       [RESET_I2C3]    = { CMU_DEVRST1, BIT(3) },
+       [RESET_SPI0]    = { CMU_DEVRST1, BIT(4) },
+       [RESET_SPI1]    = { CMU_DEVRST1, BIT(5) },
+       [RESET_SPI2]    = { CMU_DEVRST1, BIT(6) },
+       [RESET_SPI3]    = { CMU_DEVRST1, BIT(7) },
+       [RESET_UART0]   = { CMU_DEVRST1, BIT(8) },
+       [RESET_UART1]   = { CMU_DEVRST1, BIT(9) },
+       [RESET_UART2]   = { CMU_DEVRST1, BIT(10) },
+       [RESET_UART3]   = { CMU_DEVRST1, BIT(11) },
+       [RESET_UART4]   = { CMU_DEVRST1, BIT(12) },
+       [RESET_UART5]   = { CMU_DEVRST1, BIT(13) },
+       [RESET_UART6]   = { CMU_DEVRST1, BIT(14) },
+       [RESET_KEY]     = { CMU_DEVRST1, BIT(24) },
+       [RESET_GPIO]    = { CMU_DEVRST1, BIT(25) },
+       [RESET_AUDIO]   = { CMU_DEVRST1, BIT(29) },
+};
+
+static struct owl_clk_desc s700_clk_desc = {
        .clks       = s700_clks,
        .num_clks   = ARRAY_SIZE(s700_clks),
 
        .hw_clks    = &s700_hw_clks,
+
+       .resets     = s700_resets,
+       .num_resets = ARRAY_SIZE(s700_resets),
 };
 
 static int s700_clk_probe(struct platform_device *pdev)
 {
-       const struct owl_clk_desc *desc;
+       struct owl_clk_desc *desc;
+       struct owl_reset *reset;
+       int ret;
 
        desc = &s700_clk_desc;
        owl_clk_regmap_init(pdev, desc);
 
+       /*
+        * FIXME: Reset controller registration should be moved to
+        * common code, once all SoCs of Owl family supports it.
+        */
+       reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
+       if (!reset)
+               return -ENOMEM;
+
+       reset->rcdev.of_node = pdev->dev.of_node;
+       reset->rcdev.ops = &owl_reset_ops;
+       reset->rcdev.nr_resets = desc->num_resets;
+       reset->reset_map = desc->resets;
+       reset->regmap = desc->regmap;
+
+       ret = devm_reset_controller_register(&pdev->dev, &reset->rcdev);
+       if (ret)
+               dev_err(&pdev->dev, "Failed to register reset controller\n");
+
        return owl_clk_probe(&pdev->dev, desc->hw_clks);
 }
 
index 7f60ed6afe639e159c5bf771bfe5cbfccd0e669b..790890978424a241c8229c7592c2843b1fdb694d 100644 (file)
 #include "owl-gate.h"
 #include "owl-mux.h"
 #include "owl-pll.h"
+#include "owl-reset.h"
 
 #include <dt-bindings/clock/actions,s900-cmu.h>
+#include <dt-bindings/reset/actions,s900-reset.h>
 
 #define CMU_COREPLL            (0x0000)
 #define CMU_DEVPLL             (0x0004)
@@ -684,20 +686,100 @@ static struct clk_hw_onecell_data s900_hw_clks = {
        .num    = CLK_NR_CLKS,
 };
 
-static const struct owl_clk_desc s900_clk_desc = {
+static const struct owl_reset_map s900_resets[] = {
+       [RESET_DMAC]            = { CMU_DEVRST0, BIT(0) },
+       [RESET_SRAMI]           = { CMU_DEVRST0, BIT(1) },
+       [RESET_DDR_CTL_PHY]     = { CMU_DEVRST0, BIT(2) },
+       [RESET_NANDC0]          = { CMU_DEVRST0, BIT(3) },
+       [RESET_SD0]             = { CMU_DEVRST0, BIT(4) },
+       [RESET_SD1]             = { CMU_DEVRST0, BIT(5) },
+       [RESET_PCM1]            = { CMU_DEVRST0, BIT(6) },
+       [RESET_DE]              = { CMU_DEVRST0, BIT(7) },
+       [RESET_LVDS]            = { CMU_DEVRST0, BIT(8) },
+       [RESET_SD2]             = { CMU_DEVRST0, BIT(9) },
+       [RESET_DSI]             = { CMU_DEVRST0, BIT(10) },
+       [RESET_CSI0]            = { CMU_DEVRST0, BIT(11) },
+       [RESET_BISP_AXI]        = { CMU_DEVRST0, BIT(12) },
+       [RESET_CSI1]            = { CMU_DEVRST0, BIT(13) },
+       [RESET_GPIO]            = { CMU_DEVRST0, BIT(15) },
+       [RESET_EDP]             = { CMU_DEVRST0, BIT(16) },
+       [RESET_AUDIO]           = { CMU_DEVRST0, BIT(17) },
+       [RESET_PCM0]            = { CMU_DEVRST0, BIT(18) },
+       [RESET_HDE]             = { CMU_DEVRST0, BIT(21) },
+       [RESET_GPU3D_PA]        = { CMU_DEVRST0, BIT(22) },
+       [RESET_IMX]             = { CMU_DEVRST0, BIT(23) },
+       [RESET_SE]              = { CMU_DEVRST0, BIT(24) },
+       [RESET_NANDC1]          = { CMU_DEVRST0, BIT(25) },
+       [RESET_SD3]             = { CMU_DEVRST0, BIT(26) },
+       [RESET_GIC]             = { CMU_DEVRST0, BIT(27) },
+       [RESET_GPU3D_PB]        = { CMU_DEVRST0, BIT(28) },
+       [RESET_DDR_CTL_PHY_AXI] = { CMU_DEVRST0, BIT(29) },
+       [RESET_CMU_DDR]         = { CMU_DEVRST0, BIT(30) },
+       [RESET_DMM]             = { CMU_DEVRST0, BIT(31) },
+       [RESET_USB2HUB]         = { CMU_DEVRST1, BIT(0) },
+       [RESET_USB2HSIC]        = { CMU_DEVRST1, BIT(1) },
+       [RESET_HDMI]            = { CMU_DEVRST1, BIT(2) },
+       [RESET_HDCP2TX]         = { CMU_DEVRST1, BIT(3) },
+       [RESET_UART6]           = { CMU_DEVRST1, BIT(4) },
+       [RESET_UART0]           = { CMU_DEVRST1, BIT(5) },
+       [RESET_UART1]           = { CMU_DEVRST1, BIT(6) },
+       [RESET_UART2]           = { CMU_DEVRST1, BIT(7) },
+       [RESET_SPI0]            = { CMU_DEVRST1, BIT(8) },
+       [RESET_SPI1]            = { CMU_DEVRST1, BIT(9) },
+       [RESET_SPI2]            = { CMU_DEVRST1, BIT(10) },
+       [RESET_SPI3]            = { CMU_DEVRST1, BIT(11) },
+       [RESET_I2C0]            = { CMU_DEVRST1, BIT(12) },
+       [RESET_I2C1]            = { CMU_DEVRST1, BIT(13) },
+       [RESET_USB3]            = { CMU_DEVRST1, BIT(14) },
+       [RESET_UART3]           = { CMU_DEVRST1, BIT(15) },
+       [RESET_UART4]           = { CMU_DEVRST1, BIT(16) },
+       [RESET_UART5]           = { CMU_DEVRST1, BIT(17) },
+       [RESET_I2C2]            = { CMU_DEVRST1, BIT(18) },
+       [RESET_I2C3]            = { CMU_DEVRST1, BIT(19) },
+       [RESET_ETHERNET]        = { CMU_DEVRST1, BIT(20) },
+       [RESET_CHIPID]          = { CMU_DEVRST1, BIT(21) },
+       [RESET_I2C4]            = { CMU_DEVRST1, BIT(22) },
+       [RESET_I2C5]            = { CMU_DEVRST1, BIT(23) },
+       [RESET_CPU_SCNT]        = { CMU_DEVRST1, BIT(30) }
+};
+
+static struct owl_clk_desc s900_clk_desc = {
        .clks       = s900_clks,
        .num_clks   = ARRAY_SIZE(s900_clks),
 
        .hw_clks    = &s900_hw_clks,
+
+       .resets     = s900_resets,
+       .num_resets = ARRAY_SIZE(s900_resets),
 };
 
 static int s900_clk_probe(struct platform_device *pdev)
 {
-       const struct owl_clk_desc *desc;
+       struct owl_clk_desc *desc;
+       struct owl_reset *reset;
+       int ret;
 
        desc = &s900_clk_desc;
        owl_clk_regmap_init(pdev, desc);
 
+       /*
+        * FIXME: Reset controller registration should be moved to
+        * common code, once all SoCs of Owl family supports it.
+        */
+       reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
+       if (!reset)
+               return -ENOMEM;
+
+       reset->rcdev.of_node = pdev->dev.of_node;
+       reset->rcdev.ops = &owl_reset_ops;
+       reset->rcdev.nr_resets = desc->num_resets;
+       reset->reset_map = desc->resets;
+       reset->regmap = desc->regmap;
+
+       ret = devm_reset_controller_register(&pdev->dev, &reset->rcdev);
+       if (ret)
+               dev_err(&pdev->dev, "Failed to register reset controller\n");
+
        return owl_clk_probe(&pdev->dev, desc->hw_clks);
 }
 
index facc169ebb68a256366d93dd9c217549be0da5ad..c75df1cad60e646294a1f5e44871a8c82b2ff6e3 100644 (file)
@@ -3,7 +3,7 @@
 # Makefile for at91 specific clk
 #
 
-obj-y += pmc.o sckc.o
+obj-y += pmc.o sckc.o dt-compat.o
 obj-y += clk-slow.o clk-main.o clk-pll.o clk-plldiv.o clk-master.o
 obj-y += clk-system.o clk-peripheral.o clk-programmable.o
 
@@ -14,3 +14,6 @@ obj-$(CONFIG_HAVE_AT91_SMD)           += clk-smd.o
 obj-$(CONFIG_HAVE_AT91_H32MX)          += clk-h32mx.o
 obj-$(CONFIG_HAVE_AT91_GENERATED_CLK)  += clk-generated.o
 obj-$(CONFIG_HAVE_AT91_I2S_MUX_CLK)    += clk-i2s-mux.o
+obj-$(CONFIG_SOC_AT91SAM9) += at91sam9260.o at91sam9rl.o at91sam9x5.o
+obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o
+obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o
diff --git a/drivers/clk/at91/at91sam9260.c b/drivers/clk/at91/at91sam9260.c
new file mode 100644 (file)
index 0000000..b1af5a3
--- /dev/null
@@ -0,0 +1,494 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/at91.h>
+
+#include "pmc.h"
+
+struct sck {
+       char *n;
+       char *p;
+       u8 id;
+};
+
+struct pck {
+       char *n;
+       u8 id;
+};
+
+struct at91sam926x_data {
+       const struct clk_pll_layout *plla_layout;
+       const struct clk_pll_characteristics *plla_characteristics;
+       const struct clk_pll_layout *pllb_layout;
+       const struct clk_pll_characteristics *pllb_characteristics;
+       const struct clk_master_characteristics *mck_characteristics;
+       const struct sck *sck;
+       const struct pck *pck;
+       u8 num_sck;
+       u8 num_pck;
+       u8 num_progck;
+       bool has_slck;
+};
+
+static const struct clk_master_characteristics sam9260_mck_characteristics = {
+       .output = { .min = 0, .max = 105000000 },
+       .divisors = { 1, 2, 4, 0 },
+};
+
+static u8 sam9260_plla_out[] = { 0, 2 };
+
+static u16 sam9260_plla_icpll[] = { 1, 1 };
+
+static struct clk_range sam9260_plla_outputs[] = {
+       { .min = 80000000, .max = 160000000 },
+       { .min = 150000000, .max = 240000000 },
+};
+
+static const struct clk_pll_characteristics sam9260_plla_characteristics = {
+       .input = { .min = 1000000, .max = 32000000 },
+       .num_output = ARRAY_SIZE(sam9260_plla_outputs),
+       .output = sam9260_plla_outputs,
+       .icpll = sam9260_plla_icpll,
+       .out = sam9260_plla_out,
+};
+
+static u8 sam9260_pllb_out[] = { 1 };
+
+static u16 sam9260_pllb_icpll[] = { 1 };
+
+static struct clk_range sam9260_pllb_outputs[] = {
+       { .min = 70000000, .max = 130000000 },
+};
+
+static const struct clk_pll_characteristics sam9260_pllb_characteristics = {
+       .input = { .min = 1000000, .max = 5000000 },
+       .num_output = ARRAY_SIZE(sam9260_pllb_outputs),
+       .output = sam9260_pllb_outputs,
+       .icpll = sam9260_pllb_icpll,
+       .out = sam9260_pllb_out,
+};
+
+static const struct sck at91sam9260_systemck[] = {
+       { .n = "uhpck", .p = "usbck",    .id = 6 },
+       { .n = "udpck", .p = "usbck",    .id = 7 },
+       { .n = "pck0",  .p = "prog0",    .id = 8 },
+       { .n = "pck1",  .p = "prog1",    .id = 9 },
+};
+
+static const struct pck at91sam9260_periphck[] = {
+       { .n = "pioA_clk",   .id = 2 },
+       { .n = "pioB_clk",   .id = 3 },
+       { .n = "pioC_clk",   .id = 4 },
+       { .n = "adc_clk",    .id = 5 },
+       { .n = "usart0_clk", .id = 6 },
+       { .n = "usart1_clk", .id = 7 },
+       { .n = "usart2_clk", .id = 8 },
+       { .n = "mci0_clk",   .id = 9 },
+       { .n = "udc_clk",    .id = 10 },
+       { .n = "twi0_clk",   .id = 11 },
+       { .n = "spi0_clk",   .id = 12 },
+       { .n = "spi1_clk",   .id = 13 },
+       { .n = "ssc0_clk",   .id = 14 },
+       { .n = "tc0_clk",    .id = 17 },
+       { .n = "tc1_clk",    .id = 18 },
+       { .n = "tc2_clk",    .id = 19 },
+       { .n = "ohci_clk",   .id = 20 },
+       { .n = "macb0_clk",  .id = 21 },
+       { .n = "isi_clk",    .id = 22 },
+       { .n = "usart3_clk", .id = 23 },
+       { .n = "uart0_clk",  .id = 24 },
+       { .n = "uart1_clk",  .id = 25 },
+       { .n = "tc3_clk",    .id = 26 },
+       { .n = "tc4_clk",    .id = 27 },
+       { .n = "tc5_clk",    .id = 28 },
+};
+
+static struct at91sam926x_data at91sam9260_data = {
+       .plla_layout = &at91rm9200_pll_layout,
+       .plla_characteristics = &sam9260_plla_characteristics,
+       .pllb_layout = &at91rm9200_pll_layout,
+       .pllb_characteristics = &sam9260_pllb_characteristics,
+       .mck_characteristics = &sam9260_mck_characteristics,
+       .sck = at91sam9260_systemck,
+       .num_sck = ARRAY_SIZE(at91sam9260_systemck),
+       .pck = at91sam9260_periphck,
+       .num_pck = ARRAY_SIZE(at91sam9260_periphck),
+       .num_progck = 2,
+       .has_slck = true,
+};
+
+static const struct clk_master_characteristics sam9g20_mck_characteristics = {
+       .output = { .min = 0, .max = 133000000 },
+       .divisors = { 1, 2, 4, 6 },
+};
+
+static u8 sam9g20_plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
+
+static u16 sam9g20_plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
+
+static struct clk_range sam9g20_plla_outputs[] = {
+       { .min = 745000000, .max = 800000000 },
+       { .min = 695000000, .max = 750000000 },
+       { .min = 645000000, .max = 700000000 },
+       { .min = 595000000, .max = 650000000 },
+       { .min = 545000000, .max = 600000000 },
+       { .min = 495000000, .max = 550000000 },
+       { .min = 445000000, .max = 500000000 },
+       { .min = 400000000, .max = 450000000 },
+};
+
+static const struct clk_pll_characteristics sam9g20_plla_characteristics = {
+       .input = { .min = 2000000, .max = 32000000 },
+       .num_output = ARRAY_SIZE(sam9g20_plla_outputs),
+       .output = sam9g20_plla_outputs,
+       .icpll = sam9g20_plla_icpll,
+       .out = sam9g20_plla_out,
+};
+
+static u8 sam9g20_pllb_out[] = { 0 };
+
+static u16 sam9g20_pllb_icpll[] = { 0 };
+
+static struct clk_range sam9g20_pllb_outputs[] = {
+       { .min = 30000000, .max = 100000000 },
+};
+
+static const struct clk_pll_characteristics sam9g20_pllb_characteristics = {
+       .input = { .min = 2000000, .max = 32000000 },
+       .num_output = ARRAY_SIZE(sam9g20_pllb_outputs),
+       .output = sam9g20_pllb_outputs,
+       .icpll = sam9g20_pllb_icpll,
+       .out = sam9g20_pllb_out,
+};
+
+static struct at91sam926x_data at91sam9g20_data = {
+       .plla_layout = &at91sam9g45_pll_layout,
+       .plla_characteristics = &sam9g20_plla_characteristics,
+       .pllb_layout = &at91sam9g20_pllb_layout,
+       .pllb_characteristics = &sam9g20_pllb_characteristics,
+       .mck_characteristics = &sam9g20_mck_characteristics,
+       .sck = at91sam9260_systemck,
+       .num_sck = ARRAY_SIZE(at91sam9260_systemck),
+       .pck = at91sam9260_periphck,
+       .num_pck = ARRAY_SIZE(at91sam9260_periphck),
+       .num_progck = 2,
+       .has_slck = true,
+};
+
+static const struct clk_master_characteristics sam9261_mck_characteristics = {
+       .output = { .min = 0, .max = 94000000 },
+       .divisors = { 1, 2, 4, 0 },
+};
+
+static struct clk_range sam9261_plla_outputs[] = {
+       { .min = 80000000, .max = 200000000 },
+       { .min = 190000000, .max = 240000000 },
+};
+
+static const struct clk_pll_characteristics sam9261_plla_characteristics = {
+       .input = { .min = 1000000, .max = 32000000 },
+       .num_output = ARRAY_SIZE(sam9261_plla_outputs),
+       .output = sam9261_plla_outputs,
+       .icpll = sam9260_plla_icpll,
+       .out = sam9260_plla_out,
+};
+
+static u8 sam9261_pllb_out[] = { 1 };
+
+static u16 sam9261_pllb_icpll[] = { 1 };
+
+static struct clk_range sam9261_pllb_outputs[] = {
+       { .min = 70000000, .max = 130000000 },
+};
+
+static const struct clk_pll_characteristics sam9261_pllb_characteristics = {
+       .input = { .min = 1000000, .max = 5000000 },
+       .num_output = ARRAY_SIZE(sam9261_pllb_outputs),
+       .output = sam9261_pllb_outputs,
+       .icpll = sam9261_pllb_icpll,
+       .out = sam9261_pllb_out,
+};
+
+static const struct sck at91sam9261_systemck[] = {
+       { .n = "uhpck", .p = "usbck",    .id = 6 },
+       { .n = "udpck", .p = "usbck",    .id = 7 },
+       { .n = "pck0",  .p = "prog0",    .id = 8 },
+       { .n = "pck1",  .p = "prog1",    .id = 9 },
+       { .n = "pck2",  .p = "prog2",    .id = 10 },
+       { .n = "pck3",  .p = "prog3",    .id = 11 },
+       { .n = "hclk0", .p = "masterck", .id = 16 },
+       { .n = "hclk1", .p = "masterck", .id = 17 },
+};
+
+static const struct pck at91sam9261_periphck[] = {
+       { .n = "pioA_clk",   .id = 2, },
+       { .n = "pioB_clk",   .id = 3, },
+       { .n = "pioC_clk",   .id = 4, },
+       { .n = "usart0_clk", .id = 6, },
+       { .n = "usart1_clk", .id = 7, },
+       { .n = "usart2_clk", .id = 8, },
+       { .n = "mci0_clk",   .id = 9, },
+       { .n = "udc_clk",    .id = 10, },
+       { .n = "twi0_clk",   .id = 11, },
+       { .n = "spi0_clk",   .id = 12, },
+       { .n = "spi1_clk",   .id = 13, },
+       { .n = "ssc0_clk",   .id = 14, },
+       { .n = "ssc1_clk",   .id = 15, },
+       { .n = "ssc2_clk",   .id = 16, },
+       { .n = "tc0_clk",    .id = 17, },
+       { .n = "tc1_clk",    .id = 18, },
+       { .n = "tc2_clk",    .id = 19, },
+       { .n = "ohci_clk",   .id = 20, },
+       { .n = "lcd_clk",    .id = 21, },
+};
+
+static struct at91sam926x_data at91sam9261_data = {
+       .plla_layout = &at91rm9200_pll_layout,
+       .plla_characteristics = &sam9261_plla_characteristics,
+       .pllb_layout = &at91rm9200_pll_layout,
+       .pllb_characteristics = &sam9261_pllb_characteristics,
+       .mck_characteristics = &sam9261_mck_characteristics,
+       .sck = at91sam9261_systemck,
+       .num_sck = ARRAY_SIZE(at91sam9261_systemck),
+       .pck = at91sam9261_periphck,
+       .num_pck = ARRAY_SIZE(at91sam9261_periphck),
+       .num_progck = 4,
+};
+
+static const struct clk_master_characteristics sam9263_mck_characteristics = {
+       .output = { .min = 0, .max = 120000000 },
+       .divisors = { 1, 2, 4, 0 },
+};
+
+static struct clk_range sam9263_pll_outputs[] = {
+       { .min = 80000000, .max = 200000000 },
+       { .min = 190000000, .max = 240000000 },
+};
+
+static const struct clk_pll_characteristics sam9263_pll_characteristics = {
+       .input = { .min = 1000000, .max = 32000000 },
+       .num_output = ARRAY_SIZE(sam9263_pll_outputs),
+       .output = sam9263_pll_outputs,
+       .icpll = sam9260_plla_icpll,
+       .out = sam9260_plla_out,
+};
+
+static const struct sck at91sam9263_systemck[] = {
+       { .n = "uhpck", .p = "usbck",    .id = 6 },
+       { .n = "udpck", .p = "usbck",    .id = 7 },
+       { .n = "pck0",  .p = "prog0",    .id = 8 },
+       { .n = "pck1",  .p = "prog1",    .id = 9 },
+       { .n = "pck2",  .p = "prog2",    .id = 10 },
+       { .n = "pck3",  .p = "prog3",    .id = 11 },
+};
+
+static const struct pck at91sam9263_periphck[] = {
+       { .n = "pioA_clk",   .id = 2, },
+       { .n = "pioB_clk",   .id = 3, },
+       { .n = "pioCDE_clk", .id = 4, },
+       { .n = "usart0_clk", .id = 7, },
+       { .n = "usart1_clk", .id = 8, },
+       { .n = "usart2_clk", .id = 9, },
+       { .n = "mci0_clk",   .id = 10, },
+       { .n = "mci1_clk",   .id = 11, },
+       { .n = "can_clk",    .id = 12, },
+       { .n = "twi0_clk",   .id = 13, },
+       { .n = "spi0_clk",   .id = 14, },
+       { .n = "spi1_clk",   .id = 15, },
+       { .n = "ssc0_clk",   .id = 16, },
+       { .n = "ssc1_clk",   .id = 17, },
+       { .n = "ac97_clk",   .id = 18, },
+       { .n = "tcb_clk",    .id = 19, },
+       { .n = "pwm_clk",    .id = 20, },
+       { .n = "macb0_clk",  .id = 21, },
+       { .n = "g2de_clk",   .id = 23, },
+       { .n = "udc_clk",    .id = 24, },
+       { .n = "isi_clk",    .id = 25, },
+       { .n = "lcd_clk",    .id = 26, },
+       { .n = "dma_clk",    .id = 27, },
+       { .n = "ohci_clk",   .id = 29, },
+};
+
+static struct at91sam926x_data at91sam9263_data = {
+       .plla_layout = &at91rm9200_pll_layout,
+       .plla_characteristics = &sam9263_pll_characteristics,
+       .pllb_layout = &at91rm9200_pll_layout,
+       .pllb_characteristics = &sam9263_pll_characteristics,
+       .mck_characteristics = &sam9263_mck_characteristics,
+       .sck = at91sam9263_systemck,
+       .num_sck = ARRAY_SIZE(at91sam9263_systemck),
+       .pck = at91sam9263_periphck,
+       .num_pck = ARRAY_SIZE(at91sam9263_periphck),
+       .num_progck = 4,
+};
+
+static void __init at91sam926x_pmc_setup(struct device_node *np,
+                                        struct at91sam926x_data *data)
+{
+       const char *slowxtal_name, *mainxtal_name;
+       struct pmc_data *at91sam9260_pmc;
+       u32 usb_div[] = { 1, 2, 4, 0 };
+       const char *parent_names[6];
+       const char *slck_name;
+       struct regmap *regmap;
+       struct clk_hw *hw;
+       int i;
+       bool bypass;
+
+       i = of_property_match_string(np, "clock-names", "slow_xtal");
+       if (i < 0)
+               return;
+
+       slowxtal_name = of_clk_get_parent_name(np, i);
+
+       i = of_property_match_string(np, "clock-names", "main_xtal");
+       if (i < 0)
+               return;
+       mainxtal_name = of_clk_get_parent_name(np, i);
+
+       regmap = syscon_node_to_regmap(np);
+       if (IS_ERR(regmap))
+               return;
+
+       at91sam9260_pmc = pmc_data_allocate(PMC_MAIN + 1,
+                                           ndck(data->sck, data->num_sck),
+                                           ndck(data->pck, data->num_pck), 0);
+       if (!at91sam9260_pmc)
+               return;
+
+       bypass = of_property_read_bool(np, "atmel,osc-bypass");
+
+       hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+                                       bypass);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc");
+       if (IS_ERR(hw))
+               goto err_free;
+
+       at91sam9260_pmc->chws[PMC_MAIN] = hw;
+
+       if (data->has_slck) {
+               hw = clk_hw_register_fixed_rate_with_accuracy(NULL,
+                                                             "slow_rc_osc",
+                                                             NULL, 0, 32768,
+                                                             50000000);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               parent_names[0] = "slow_rc_osc";
+               parent_names[1] = "slow_xtal";
+               hw = at91_clk_register_sam9260_slow(regmap, "slck",
+                                                   parent_names, 2);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               at91sam9260_pmc->chws[PMC_SLOW] = hw;
+               slck_name = "slck";
+       } else {
+               slck_name = slowxtal_name;
+       }
+
+       hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
+                                  data->plla_layout,
+                                  data->plla_characteristics);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       hw = at91_clk_register_pll(regmap, "pllbck", "mainck", 1,
+                                  data->pllb_layout,
+                                  data->pllb_characteristics);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       parent_names[0] = slck_name;
+       parent_names[1] = "mainck";
+       parent_names[2] = "pllack";
+       parent_names[3] = "pllbck";
+       hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
+                                     &at91rm9200_master_layout,
+                                     data->mck_characteristics);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       at91sam9260_pmc->chws[PMC_MCK] = hw;
+
+       hw = at91rm9200_clk_register_usb(regmap, "usbck", "pllbck", usb_div);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       parent_names[0] = slck_name;
+       parent_names[1] = "mainck";
+       parent_names[2] = "pllack";
+       parent_names[3] = "pllbck";
+       for (i = 0; i < data->num_progck; i++) {
+               char name[6];
+
+               snprintf(name, sizeof(name), "prog%d", i);
+
+               hw = at91_clk_register_programmable(regmap, name,
+                                                   parent_names, 4, i,
+                                                   &at91rm9200_programmable_layout);
+               if (IS_ERR(hw))
+                       goto err_free;
+       }
+
+       for (i = 0; i < data->num_sck; i++) {
+               hw = at91_clk_register_system(regmap, data->sck[i].n,
+                                             data->sck[i].p,
+                                             data->sck[i].id);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               at91sam9260_pmc->shws[data->sck[i].id] = hw;
+       }
+
+       for (i = 0; i < data->num_pck; i++) {
+               hw = at91_clk_register_peripheral(regmap,
+                                                 data->pck[i].n,
+                                                 "masterck",
+                                                 data->pck[i].id);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               at91sam9260_pmc->phws[data->pck[i].id] = hw;
+       }
+
+       of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9260_pmc);
+
+       return;
+
+err_free:
+       pmc_data_free(at91sam9260_pmc);
+}
+
+static void __init at91sam9260_pmc_setup(struct device_node *np)
+{
+       at91sam926x_pmc_setup(np, &at91sam9260_data);
+}
+CLK_OF_DECLARE_DRIVER(at91sam9260_pmc, "atmel,at91sam9260-pmc",
+                     at91sam9260_pmc_setup);
+
+static void __init at91sam9261_pmc_setup(struct device_node *np)
+{
+       at91sam926x_pmc_setup(np, &at91sam9261_data);
+}
+CLK_OF_DECLARE_DRIVER(at91sam9261_pmc, "atmel,at91sam9261-pmc",
+                     at91sam9261_pmc_setup);
+
+static void __init at91sam9263_pmc_setup(struct device_node *np)
+{
+       at91sam926x_pmc_setup(np, &at91sam9263_data);
+}
+CLK_OF_DECLARE_DRIVER(at91sam9263_pmc, "atmel,at91sam9263-pmc",
+                     at91sam9263_pmc_setup);
+
+static void __init at91sam9g20_pmc_setup(struct device_node *np)
+{
+       at91sam926x_pmc_setup(np, &at91sam9g20_data);
+}
+CLK_OF_DECLARE_DRIVER(at91sam9g20_pmc, "atmel,at91sam9g20-pmc",
+                     at91sam9g20_pmc_setup);
diff --git a/drivers/clk/at91/at91sam9rl.c b/drivers/clk/at91/at91sam9rl.c
new file mode 100644 (file)
index 0000000..5aeef68
--- /dev/null
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/at91.h>
+
+#include "pmc.h"
+
+static const struct clk_master_characteristics sam9rl_mck_characteristics = {
+       .output = { .min = 0, .max = 94000000 },
+       .divisors = { 1, 2, 4, 0 },
+};
+
+static u8 sam9rl_plla_out[] = { 0, 2 };
+
+static struct clk_range sam9rl_plla_outputs[] = {
+       { .min = 80000000, .max = 200000000 },
+       { .min = 190000000, .max = 240000000 },
+};
+
+static const struct clk_pll_characteristics sam9rl_plla_characteristics = {
+       .input = { .min = 1000000, .max = 32000000 },
+       .num_output = ARRAY_SIZE(sam9rl_plla_outputs),
+       .output = sam9rl_plla_outputs,
+       .out = sam9rl_plla_out,
+};
+
+static const struct {
+       char *n;
+       char *p;
+       u8 id;
+} at91sam9rl_systemck[] = {
+       { .n = "pck0",  .p = "prog0",    .id = 8 },
+       { .n = "pck1",  .p = "prog1",    .id = 9 },
+};
+
+static const struct {
+       char *n;
+       u8 id;
+} at91sam9rl_periphck[] = {
+       { .n = "pioA_clk",   .id = 2, },
+       { .n = "pioB_clk",   .id = 3, },
+       { .n = "pioC_clk",   .id = 4, },
+       { .n = "pioD_clk",   .id = 5, },
+       { .n = "usart0_clk", .id = 6, },
+       { .n = "usart1_clk", .id = 7, },
+       { .n = "usart2_clk", .id = 8, },
+       { .n = "usart3_clk", .id = 9, },
+       { .n = "mci0_clk",   .id = 10, },
+       { .n = "twi0_clk",   .id = 11, },
+       { .n = "twi1_clk",   .id = 12, },
+       { .n = "spi0_clk",   .id = 13, },
+       { .n = "ssc0_clk",   .id = 14, },
+       { .n = "ssc1_clk",   .id = 15, },
+       { .n = "tc0_clk",    .id = 16, },
+       { .n = "tc1_clk",    .id = 17, },
+       { .n = "tc2_clk",    .id = 18, },
+       { .n = "pwm_clk",    .id = 19, },
+       { .n = "adc_clk",    .id = 20, },
+       { .n = "dma0_clk",   .id = 21, },
+       { .n = "udphs_clk",  .id = 22, },
+       { .n = "lcd_clk",    .id = 23, },
+};
+
+static void __init at91sam9rl_pmc_setup(struct device_node *np)
+{
+       const char *slck_name, *mainxtal_name;
+       struct pmc_data *at91sam9rl_pmc;
+       const char *parent_names[6];
+       struct regmap *regmap;
+       struct clk_hw *hw;
+       int i;
+
+       i = of_property_match_string(np, "clock-names", "slow_clk");
+       if (i < 0)
+               return;
+
+       slck_name = of_clk_get_parent_name(np, i);
+
+       i = of_property_match_string(np, "clock-names", "main_xtal");
+       if (i < 0)
+               return;
+       mainxtal_name = of_clk_get_parent_name(np, i);
+
+       regmap = syscon_node_to_regmap(np);
+       if (IS_ERR(regmap))
+               return;
+
+       at91sam9rl_pmc = pmc_data_allocate(PMC_MAIN + 1,
+                                          nck(at91sam9rl_systemck),
+                                          nck(at91sam9rl_periphck), 0);
+       if (!at91sam9rl_pmc)
+               return;
+
+       hw = at91_clk_register_rm9200_main(regmap, "mainck", mainxtal_name);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       at91sam9rl_pmc->chws[PMC_MAIN] = hw;
+
+       hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
+                                  &at91rm9200_pll_layout,
+                                  &sam9rl_plla_characteristics);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
+       if (IS_ERR(hw))
+               goto err_free;
+
+       at91sam9rl_pmc->chws[PMC_UTMI] = hw;
+
+       parent_names[0] = slck_name;
+       parent_names[1] = "mainck";
+       parent_names[2] = "pllack";
+       parent_names[3] = "utmick";
+       hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
+                                     &at91rm9200_master_layout,
+                                     &sam9rl_mck_characteristics);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       at91sam9rl_pmc->chws[PMC_MCK] = hw;
+
+       parent_names[0] = slck_name;
+       parent_names[1] = "mainck";
+       parent_names[2] = "pllack";
+       parent_names[3] = "utmick";
+       parent_names[4] = "masterck";
+       for (i = 0; i < 2; i++) {
+               char name[6];
+
+               snprintf(name, sizeof(name), "prog%d", i);
+
+               hw = at91_clk_register_programmable(regmap, name,
+                                                   parent_names, 5, i,
+                                                   &at91rm9200_programmable_layout);
+               if (IS_ERR(hw))
+                       goto err_free;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(at91sam9rl_systemck); i++) {
+               hw = at91_clk_register_system(regmap, at91sam9rl_systemck[i].n,
+                                             at91sam9rl_systemck[i].p,
+                                             at91sam9rl_systemck[i].id);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               at91sam9rl_pmc->shws[at91sam9rl_systemck[i].id] = hw;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(at91sam9rl_periphck); i++) {
+               hw = at91_clk_register_peripheral(regmap,
+                                                 at91sam9rl_periphck[i].n,
+                                                 "masterck",
+                                                 at91sam9rl_periphck[i].id);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               at91sam9rl_pmc->phws[at91sam9rl_periphck[i].id] = hw;
+       }
+
+       of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9rl_pmc);
+
+       return;
+
+err_free:
+       pmc_data_free(at91sam9rl_pmc);
+}
+CLK_OF_DECLARE_DRIVER(at91sam9rl_pmc, "atmel,at91sam9rl-pmc", at91sam9rl_pmc_setup);
diff --git a/drivers/clk/at91/at91sam9x5.c b/drivers/clk/at91/at91sam9x5.c
new file mode 100644 (file)
index 0000000..2fe225a
--- /dev/null
@@ -0,0 +1,309 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/at91.h>
+
+#include "pmc.h"
+
+static const struct clk_master_characteristics mck_characteristics = {
+       .output = { .min = 0, .max = 133333333 },
+       .divisors = { 1, 2, 4, 3 },
+       .have_div3_pres = 1,
+};
+
+static u8 plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
+
+static u16 plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
+
+static struct clk_range plla_outputs[] = {
+       { .min = 745000000, .max = 800000000 },
+       { .min = 695000000, .max = 750000000 },
+       { .min = 645000000, .max = 700000000 },
+       { .min = 595000000, .max = 650000000 },
+       { .min = 545000000, .max = 600000000 },
+       { .min = 495000000, .max = 555000000 },
+       { .min = 445000000, .max = 500000000 },
+       { .min = 400000000, .max = 450000000 },
+};
+
+static const struct clk_pll_characteristics plla_characteristics = {
+       .input = { .min = 2000000, .max = 32000000 },
+       .num_output = ARRAY_SIZE(plla_outputs),
+       .output = plla_outputs,
+       .icpll = plla_icpll,
+       .out = plla_out,
+};
+
+static const struct {
+       char *n;
+       char *p;
+       u8 id;
+} at91sam9x5_systemck[] = {
+       { .n = "ddrck", .p = "masterck", .id = 2 },
+       { .n = "smdck", .p = "smdclk",   .id = 4 },
+       { .n = "uhpck", .p = "usbck",    .id = 6 },
+       { .n = "udpck", .p = "usbck",    .id = 7 },
+       { .n = "pck0",  .p = "prog0",    .id = 8 },
+       { .n = "pck1",  .p = "prog1",    .id = 9 },
+};
+
+struct pck {
+       char *n;
+       u8 id;
+};
+
+static const struct pck at91sam9x5_periphck[] = {
+       { .n = "pioAB_clk",  .id = 2, },
+       { .n = "pioCD_clk",  .id = 3, },
+       { .n = "smd_clk",    .id = 4, },
+       { .n = "usart0_clk", .id = 5, },
+       { .n = "usart1_clk", .id = 6, },
+       { .n = "usart2_clk", .id = 7, },
+       { .n = "twi0_clk",   .id = 9, },
+       { .n = "twi1_clk",   .id = 10, },
+       { .n = "twi2_clk",   .id = 11, },
+       { .n = "mci0_clk",   .id = 12, },
+       { .n = "spi0_clk",   .id = 13, },
+       { .n = "spi1_clk",   .id = 14, },
+       { .n = "uart0_clk",  .id = 15, },
+       { .n = "uart1_clk",  .id = 16, },
+       { .n = "tcb0_clk",   .id = 17, },
+       { .n = "pwm_clk",    .id = 18, },
+       { .n = "adc_clk",    .id = 19, },
+       { .n = "dma0_clk",   .id = 20, },
+       { .n = "dma1_clk",   .id = 21, },
+       { .n = "uhphs_clk",  .id = 22, },
+       { .n = "udphs_clk",  .id = 23, },
+       { .n = "mci1_clk",   .id = 26, },
+       { .n = "ssc0_clk",   .id = 28, },
+};
+
+static const struct pck at91sam9g15_periphck[] = {
+       { .n = "lcdc_clk", .id = 25, },
+       { /* sentinel */}
+};
+
+static const struct pck at91sam9g25_periphck[] = {
+       { .n = "usart3_clk", .id = 8, },
+       { .n = "macb0_clk", .id = 24, },
+       { .n = "isi_clk", .id = 25, },
+       { /* sentinel */}
+};
+
+static const struct pck at91sam9g35_periphck[] = {
+       { .n = "macb0_clk", .id = 24, },
+       { .n = "lcdc_clk", .id = 25, },
+       { /* sentinel */}
+};
+
+static const struct pck at91sam9x25_periphck[] = {
+       { .n = "usart3_clk", .id = 8, },
+       { .n = "macb0_clk", .id = 24, },
+       { .n = "macb1_clk", .id = 27, },
+       { .n = "can0_clk", .id = 29, },
+       { .n = "can1_clk", .id = 30, },
+       { /* sentinel */}
+};
+
+static const struct pck at91sam9x35_periphck[] = {
+       { .n = "macb0_clk", .id = 24, },
+       { .n = "lcdc_clk", .id = 25, },
+       { .n = "can0_clk", .id = 29, },
+       { .n = "can1_clk", .id = 30, },
+       { /* sentinel */}
+};
+
+static void __init at91sam9x5_pmc_setup(struct device_node *np,
+                                       const struct pck *extra_pcks,
+                                       bool has_lcdck)
+{
+       struct clk_range range = CLK_RANGE(0, 0);
+       const char *slck_name, *mainxtal_name;
+       struct pmc_data *at91sam9x5_pmc;
+       const char *parent_names[6];
+       struct regmap *regmap;
+       struct clk_hw *hw;
+       int i;
+       bool bypass;
+
+       i = of_property_match_string(np, "clock-names", "slow_clk");
+       if (i < 0)
+               return;
+
+       slck_name = of_clk_get_parent_name(np, i);
+
+       i = of_property_match_string(np, "clock-names", "main_xtal");
+       if (i < 0)
+               return;
+       mainxtal_name = of_clk_get_parent_name(np, i);
+
+       regmap = syscon_node_to_regmap(np);
+       if (IS_ERR(regmap))
+               return;
+
+       at91sam9x5_pmc = pmc_data_allocate(PMC_MAIN + 1,
+                                          nck(at91sam9x5_systemck),
+                                          nck(at91sam9x35_periphck), 0);
+       if (!at91sam9x5_pmc)
+               return;
+
+       hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
+                                          50000000);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       bypass = of_property_read_bool(np, "atmel,osc-bypass");
+
+       hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+                                       bypass);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       parent_names[0] = "main_rc_osc";
+       parent_names[1] = "main_osc";
+       hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       at91sam9x5_pmc->chws[PMC_MAIN] = hw;
+
+       hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
+                                  &at91rm9200_pll_layout, &plla_characteristics);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack");
+       if (IS_ERR(hw))
+               goto err_free;
+
+       hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
+       if (IS_ERR(hw))
+               goto err_free;
+
+       at91sam9x5_pmc->chws[PMC_UTMI] = hw;
+
+       parent_names[0] = slck_name;
+       parent_names[1] = "mainck";
+       parent_names[2] = "plladivck";
+       parent_names[3] = "utmick";
+       hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
+                                     &at91sam9x5_master_layout,
+                                     &mck_characteristics);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       at91sam9x5_pmc->chws[PMC_MCK] = hw;
+
+       parent_names[0] = "plladivck";
+       parent_names[1] = "utmick";
+       hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       hw = at91sam9x5_clk_register_smd(regmap, "smdclk", parent_names, 2);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       parent_names[0] = slck_name;
+       parent_names[1] = "mainck";
+       parent_names[2] = "plladivck";
+       parent_names[3] = "utmick";
+       parent_names[4] = "mck";
+       for (i = 0; i < 2; i++) {
+               char name[6];
+
+               snprintf(name, sizeof(name), "prog%d", i);
+
+               hw = at91_clk_register_programmable(regmap, name,
+                                                   parent_names, 5, i,
+                                                   &at91sam9x5_programmable_layout);
+               if (IS_ERR(hw))
+                       goto err_free;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(at91sam9x5_systemck); i++) {
+               hw = at91_clk_register_system(regmap, at91sam9x5_systemck[i].n,
+                                             at91sam9x5_systemck[i].p,
+                                             at91sam9x5_systemck[i].id);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               at91sam9x5_pmc->shws[at91sam9x5_systemck[i].id] = hw;
+       }
+
+       if (has_lcdck) {
+               hw = at91_clk_register_system(regmap, "lcdck", "masterck", 3);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               at91sam9x5_pmc->shws[3] = hw;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(at91sam9x5_periphck); i++) {
+               hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+                                                        at91sam9x5_periphck[i].n,
+                                                        "masterck",
+                                                        at91sam9x5_periphck[i].id,
+                                                        &range);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               at91sam9x5_pmc->phws[at91sam9x5_periphck[i].id] = hw;
+       }
+
+       for (i = 0; extra_pcks[i].id; i++) {
+               hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+                                                        extra_pcks[i].n,
+                                                        "masterck",
+                                                        extra_pcks[i].id,
+                                                        &range);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               at91sam9x5_pmc->phws[extra_pcks[i].id] = hw;
+       }
+
+       of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9x5_pmc);
+
+       return;
+
+err_free:
+       pmc_data_free(at91sam9x5_pmc);
+}
+
+static void __init at91sam9g15_pmc_setup(struct device_node *np)
+{
+       at91sam9x5_pmc_setup(np, at91sam9g15_periphck, true);
+}
+CLK_OF_DECLARE_DRIVER(at91sam9g15_pmc, "atmel,at91sam9g15-pmc",
+                     at91sam9g15_pmc_setup);
+
+static void __init at91sam9g25_pmc_setup(struct device_node *np)
+{
+       at91sam9x5_pmc_setup(np, at91sam9g25_periphck, false);
+}
+CLK_OF_DECLARE_DRIVER(at91sam9g25_pmc, "atmel,at91sam9g25-pmc",
+                     at91sam9g25_pmc_setup);
+
+static void __init at91sam9g35_pmc_setup(struct device_node *np)
+{
+       at91sam9x5_pmc_setup(np, at91sam9g35_periphck, true);
+}
+CLK_OF_DECLARE_DRIVER(at91sam9g35_pmc, "atmel,at91sam9g35-pmc",
+                     at91sam9g35_pmc_setup);
+
+static void __init at91sam9x25_pmc_setup(struct device_node *np)
+{
+       at91sam9x5_pmc_setup(np, at91sam9x25_periphck, false);
+}
+CLK_OF_DECLARE_DRIVER(at91sam9x25_pmc, "atmel,at91sam9x25-pmc",
+                     at91sam9x25_pmc_setup);
+
+static void __init at91sam9x35_pmc_setup(struct device_node *np)
+{
+       at91sam9x5_pmc_setup(np, at91sam9x35_periphck, true);
+}
+CLK_OF_DECLARE_DRIVER(at91sam9x35_pmc, "atmel,at91sam9x35-pmc",
+                     at91sam9x35_pmc_setup);
index da7bafcfbe706cef631e86f3df8dc86536f5900c..36d77146a3bd428c3f42aa5b73c3e69253fd58ea 100644 (file)
@@ -43,6 +43,8 @@
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
+#include "pmc.h"
+
 #define AUDIO_PLL_DIV_FRAC     BIT(22)
 #define AUDIO_PLL_ND_MAX       (AT91_PMC_AUDIO_PLL_ND_MASK >> \
                                        AT91_PMC_AUDIO_PLL_ND_OFFSET)
@@ -444,93 +446,94 @@ static const struct clk_ops audio_pll_pmc_ops = {
        .set_rate = clk_audio_pll_pmc_set_rate,
 };
 
-static int of_sama5d2_clk_audio_pll_setup(struct device_node *np,
-                                         struct clk_init_data *init,
-                                         struct clk_hw *hw,
-                                         struct regmap **clk_audio_regmap)
-{
-       struct regmap *regmap;
-       const char *parent_names[1];
-       int ret;
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return PTR_ERR(regmap);
-
-       init->name = np->name;
-       of_clk_parent_fill(np, parent_names, 1);
-       init->parent_names = parent_names;
-       init->num_parents = 1;
-
-       hw->init = init;
-       *clk_audio_regmap = regmap;
-
-       ret = clk_hw_register(NULL, hw);
-       if (ret)
-               return ret;
-
-       return of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-}
-
-static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
+struct clk_hw * __init
+at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name,
+                                const char *parent_name)
 {
        struct clk_audio_frac *frac_ck;
        struct clk_init_data init = {};
+       int ret;
 
        frac_ck = kzalloc(sizeof(*frac_ck), GFP_KERNEL);
        if (!frac_ck)
-               return;
+               return ERR_PTR(-ENOMEM);
 
+       init.name = name;
        init.ops = &audio_pll_frac_ops;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
        init.flags = CLK_SET_RATE_GATE;
 
-       if (of_sama5d2_clk_audio_pll_setup(np, &init, &frac_ck->hw,
-                                          &frac_ck->regmap))
+       frac_ck->hw.init = &init;
+       frac_ck->regmap = regmap;
+
+       ret = clk_hw_register(NULL, &frac_ck->hw);
+       if (ret) {
                kfree(frac_ck);
+               return ERR_PTR(ret);
+       }
+
+       return &frac_ck->hw;
 }
 
-static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np)
+struct clk_hw * __init
+at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name,
+                               const char *parent_name)
 {
        struct clk_audio_pad *apad_ck;
-       struct clk_init_data init = {};
+       struct clk_init_data init;
+       int ret;
 
        apad_ck = kzalloc(sizeof(*apad_ck), GFP_KERNEL);
        if (!apad_ck)
-               return;
+               return ERR_PTR(-ENOMEM);
 
+       init.name = name;
        init.ops = &audio_pll_pad_ops;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
        init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
                CLK_SET_RATE_PARENT;
 
-       if (of_sama5d2_clk_audio_pll_setup(np, &init, &apad_ck->hw,
-                                          &apad_ck->regmap))
+       apad_ck->hw.init = &init;
+       apad_ck->regmap = regmap;
+
+       ret = clk_hw_register(NULL, &apad_ck->hw);
+       if (ret) {
                kfree(apad_ck);
+               return ERR_PTR(ret);
+       }
+
+       return &apad_ck->hw;
 }
 
-static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np)
+struct clk_hw * __init
+at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
+                               const char *parent_name)
 {
-       struct clk_audio_pad *apmc_ck;
-       struct clk_init_data init = {};
+       struct clk_audio_pmc *apmc_ck;
+       struct clk_init_data init;
+       int ret;
 
        apmc_ck = kzalloc(sizeof(*apmc_ck), GFP_KERNEL);
        if (!apmc_ck)
-               return;
+               return ERR_PTR(-ENOMEM);
 
+       init.name = name;
        init.ops = &audio_pll_pmc_ops;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
        init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
                CLK_SET_RATE_PARENT;
 
-       if (of_sama5d2_clk_audio_pll_setup(np, &init, &apmc_ck->hw,
-                                          &apmc_ck->regmap))
+       apmc_ck->hw.init = &init;
+       apmc_ck->regmap = regmap;
+
+       ret = clk_hw_register(NULL, &apmc_ck->hw);
+       if (ret) {
                kfree(apmc_ck);
-}
+               return ERR_PTR(ret);
+       }
 
-CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_frac_setup,
-              "atmel,sama5d2-clk-audio-pll-frac",
-              of_sama5d2_clk_audio_pll_frac_setup);
-CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup,
-              "atmel,sama5d2-clk-audio-pll-pad",
-              of_sama5d2_clk_audio_pll_pad_setup);
-CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup,
-              "atmel,sama5d2-clk-audio-pll-pmc",
-              of_sama5d2_clk_audio_pll_pmc_setup);
+       return &apmc_ck->hw;
+}
index 33481368740e7dc038fe1e32065e2659d8cec730..66e7f7baf9580fe6b6ac7ec837581fb3c0b60d27 100644 (file)
 
 #include "pmc.h"
 
-#define PERIPHERAL_MAX         64
-#define PERIPHERAL_ID_MIN      2
-
-#define GENERATED_SOURCE_MAX   6
 #define GENERATED_MAX_DIV      255
 
-#define GCK_ID_SSC0            43
-#define GCK_ID_SSC1            44
-#define GCK_ID_I2S0            54
-#define GCK_ID_I2S1            55
-#define GCK_ID_CLASSD          59
 #define GCK_INDEX_DT_AUDIO_PLL 5
 
 struct clk_generated {
@@ -279,10 +270,10 @@ static void clk_generated_startup(struct clk_generated *gck)
                                        >> AT91_PMC_PCR_GCKDIV_OFFSET;
 }
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
                            const char *name, const char **parent_names,
-                           u8 num_parents, u8 id,
+                           u8 num_parents, u8 id, bool pll_audio,
                            const struct clk_range *range)
 {
        struct clk_generated *gck;
@@ -306,6 +297,7 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
        gck->regmap = regmap;
        gck->lock = lock;
        gck->range = *range;
+       gck->audio_pll_allowed = pll_audio;
 
        clk_generated_startup(gck);
        hw = &gck->hw;
@@ -319,70 +311,3 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
 
        return hw;
 }
-
-static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
-{
-       int num;
-       u32 id;
-       const char *name;
-       struct clk_hw *hw;
-       unsigned int num_parents;
-       const char *parent_names[GENERATED_SOURCE_MAX];
-       struct device_node *gcknp;
-       struct clk_range range = CLK_RANGE(0, 0);
-       struct regmap *regmap;
-       struct clk_generated *gck;
-
-       num_parents = of_clk_get_parent_count(np);
-       if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX)
-               return;
-
-       of_clk_parent_fill(np, parent_names, num_parents);
-
-       num = of_get_child_count(np);
-       if (!num || num > PERIPHERAL_MAX)
-               return;
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       for_each_child_of_node(np, gcknp) {
-               if (of_property_read_u32(gcknp, "reg", &id))
-                       continue;
-
-               if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX)
-                       continue;
-
-               if (of_property_read_string(np, "clock-output-names", &name))
-                       name = gcknp->name;
-
-               of_at91_get_clk_range(gcknp, "atmel,clk-output-range",
-                                     &range);
-
-               hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name,
-                                                 parent_names, num_parents,
-                                                 id, &range);
-
-               gck = to_clk_generated(hw);
-
-               if (of_device_is_compatible(np,
-                                           "atmel,sama5d2-clk-generated")) {
-                       if (gck->id == GCK_ID_SSC0 || gck->id == GCK_ID_SSC1 ||
-                           gck->id == GCK_ID_I2S0 || gck->id == GCK_ID_I2S1 ||
-                           gck->id == GCK_ID_CLASSD)
-                               gck->audio_pll_allowed = true;
-                       else
-                               gck->audio_pll_allowed = false;
-               } else {
-                       gck->audio_pll_allowed = false;
-               }
-
-               if (IS_ERR(hw))
-                       continue;
-
-               of_clk_add_hw_provider(gcknp, of_clk_hw_simple_get, hw);
-       }
-}
-CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated",
-              of_sama5d2_clk_generated_setup);
index e0daa4a31f881c7b253a2bbc1e97e25f96c8219b..f0a2c6baab37312c365b424daf721e2ecb854c99 100644 (file)
@@ -86,25 +86,19 @@ static const struct clk_ops h32mx_ops = {
        .set_rate = clk_sama5d4_h32mx_set_rate,
 };
 
-static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np)
+struct clk_hw * __init
+at91_clk_register_h32mx(struct regmap *regmap, const char *name,
+                       const char *parent_name)
 {
        struct clk_sama5d4_h32mx *h32mxclk;
        struct clk_init_data init;
-       const char *parent_name;
-       struct regmap *regmap;
        int ret;
 
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
        h32mxclk = kzalloc(sizeof(*h32mxclk), GFP_KERNEL);
        if (!h32mxclk)
-               return;
-
-       parent_name = of_clk_get_parent_name(np, 0);
+               return ERR_PTR(-ENOMEM);
 
-       init.name = np->name;
+       init.name = name;
        init.ops = &h32mx_ops;
        init.parent_names = parent_name ? &parent_name : NULL;
        init.num_parents = parent_name ? 1 : 0;
@@ -116,10 +110,8 @@ static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np)
        ret = clk_hw_register(NULL, &h32mxclk->hw);
        if (ret) {
                kfree(h32mxclk);
-               return;
+               return ERR_PTR(ret);
        }
 
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, &h32mxclk->hw);
+       return &h32mxclk->hw;
 }
-CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx",
-              of_sama5d4_clk_h32mx_setup);
index f0c3c3079f042acec6c8ca84bdcb51449daa4252..fe6ce172b8b069a001c5f659a1adf05b418aca28 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <soc/at91/atmel-sfr.h>
 
-#define        I2S_BUS_NR      2
+#include "pmc.h"
 
 struct clk_i2s_mux {
        struct clk_hw hw;
@@ -48,7 +48,7 @@ static const struct clk_ops clk_i2s_mux_ops = {
        .determine_rate = __clk_mux_determine_rate,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
                          const char * const *parent_names,
                          unsigned int num_parents, u8 bus_id)
@@ -78,39 +78,3 @@ at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
 
        return &i2s_ck->hw;
 }
-
-static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np)
-{
-       struct regmap *regmap_sfr;
-       u8 bus_id;
-       const char *parent_names[2];
-       struct device_node *i2s_mux_np;
-       struct clk_hw *hw;
-       int ret;
-
-       regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
-       if (IS_ERR(regmap_sfr))
-               return;
-
-       for_each_child_of_node(np, i2s_mux_np) {
-               if (of_property_read_u8(i2s_mux_np, "reg", &bus_id))
-                       continue;
-
-               if (bus_id > I2S_BUS_NR)
-                       continue;
-
-               ret = of_clk_parent_fill(i2s_mux_np, parent_names, 2);
-               if (ret != 2)
-                       continue;
-
-               hw = at91_clk_i2s_mux_register(regmap_sfr, i2s_mux_np->name,
-                                              parent_names, 2, bus_id);
-               if (IS_ERR(hw))
-                       continue;
-
-               of_clk_add_hw_provider(i2s_mux_np, of_clk_hw_simple_get, hw);
-       }
-}
-
-CLK_OF_DECLARE(sama5d2_clk_i2s_mux, "atmel,sama5d2-clk-i2s-mux",
-              of_sama5d2_clk_i2s_mux_setup);
index c813c27f2e58c6f8e62c523a1a9a8b1d212a96d8..7ac0facdb28b1b0e76f476da9e7faf54997bae33 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/clkdev.h>
 #include <linux/clk/at91_pmc.h>
 #include <linux/delay.h>
-#include <linux/of.h>
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
 
@@ -128,7 +127,7 @@ static const struct clk_ops main_osc_ops = {
        .is_prepared = clk_main_osc_is_prepared,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_register_main_osc(struct regmap *regmap,
                           const char *name,
                           const char *parent_name,
@@ -171,31 +170,6 @@ at91_clk_register_main_osc(struct regmap *regmap,
        return hw;
 }
 
-static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np)
-{
-       struct clk_hw *hw;
-       const char *name = np->name;
-       const char *parent_name;
-       struct regmap *regmap;
-       bool bypass;
-
-       of_property_read_string(np, "clock-output-names", &name);
-       bypass = of_property_read_bool(np, "atmel,osc-bypass");
-       parent_name = of_clk_get_parent_name(np, 0);
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       hw = at91_clk_register_main_osc(regmap, name, parent_name, bypass);
-       if (IS_ERR(hw))
-               return;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-}
-CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc",
-              of_at91rm9200_clk_main_osc_setup);
-
 static bool clk_main_rc_osc_ready(struct regmap *regmap)
 {
        unsigned int status;
@@ -275,7 +249,7 @@ static const struct clk_ops main_rc_osc_ops = {
        .recalc_accuracy = clk_main_rc_osc_recalc_accuracy,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_register_main_rc_osc(struct regmap *regmap,
                              const char *name,
                              u32 frequency, u32 accuracy)
@@ -313,32 +287,6 @@ at91_clk_register_main_rc_osc(struct regmap *regmap,
        return hw;
 }
 
-static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np)
-{
-       struct clk_hw *hw;
-       u32 frequency = 0;
-       u32 accuracy = 0;
-       const char *name = np->name;
-       struct regmap *regmap;
-
-       of_property_read_string(np, "clock-output-names", &name);
-       of_property_read_u32(np, "clock-frequency", &frequency);
-       of_property_read_u32(np, "clock-accuracy", &accuracy);
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       hw = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy);
-       if (IS_ERR(hw))
-               return;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc",
-              of_at91sam9x5_clk_main_rc_osc_setup);
-
-
 static int clk_main_probe_frequency(struct regmap *regmap)
 {
        unsigned long prep_time, timeout;
@@ -403,7 +351,7 @@ static const struct clk_ops rm9200_main_ops = {
        .recalc_rate = clk_rm9200_main_recalc_rate,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_register_rm9200_main(struct regmap *regmap,
                              const char *name,
                              const char *parent_name)
@@ -442,29 +390,6 @@ at91_clk_register_rm9200_main(struct regmap *regmap,
        return hw;
 }
 
-static void __init of_at91rm9200_clk_main_setup(struct device_node *np)
-{
-       struct clk_hw *hw;
-       const char *parent_name;
-       const char *name = np->name;
-       struct regmap *regmap;
-
-       parent_name = of_clk_get_parent_name(np, 0);
-       of_property_read_string(np, "clock-output-names", &name);
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       hw = at91_clk_register_rm9200_main(regmap, name, parent_name);
-       if (IS_ERR(hw))
-               return;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-}
-CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main",
-              of_at91rm9200_clk_main_setup);
-
 static inline bool clk_sam9x5_main_ready(struct regmap *regmap)
 {
        unsigned int status;
@@ -541,7 +466,7 @@ static const struct clk_ops sam9x5_main_ops = {
        .get_parent = clk_sam9x5_main_get_parent,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_register_sam9x5_main(struct regmap *regmap,
                              const char *name,
                              const char **parent_names,
@@ -583,32 +508,3 @@ at91_clk_register_sam9x5_main(struct regmap *regmap,
 
        return hw;
 }
-
-static void __init of_at91sam9x5_clk_main_setup(struct device_node *np)
-{
-       struct clk_hw *hw;
-       const char *parent_names[2];
-       unsigned int num_parents;
-       const char *name = np->name;
-       struct regmap *regmap;
-
-       num_parents = of_clk_get_parent_count(np);
-       if (num_parents == 0 || num_parents > 2)
-               return;
-
-       of_clk_parent_fill(np, parent_names, num_parents);
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       of_property_read_string(np, "clock-output-names", &name);
-
-       hw = at91_clk_register_sam9x5_main(regmap, name, parent_names,
-                                           num_parents);
-       if (IS_ERR(hw))
-               return;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main",
-              of_at91sam9x5_clk_main_setup);
index e9cba9fc26d706181ea0e73406cd8e60997fde82..eb53b4a8fab635476d6f84449ca7696d006a464a 100644 (file)
 
 #include "pmc.h"
 
-#define MASTER_SOURCE_MAX      4
-
 #define MASTER_PRES_MASK       0x7
 #define MASTER_PRES_MAX                MASTER_PRES_MASK
 #define MASTER_DIV_SHIFT       8
 #define MASTER_DIV_MASK                0x3
 
-struct clk_master_characteristics {
-       struct clk_range output;
-       u32 divisors[4];
-       u8 have_div3_pres;
-};
-
-struct clk_master_layout {
-       u32 mask;
-       u8 pres_shift;
-};
-
 #define to_clk_master(hw) container_of(hw, struct clk_master, hw)
 
 struct clk_master {
@@ -120,7 +107,7 @@ static const struct clk_ops master_ops = {
        .get_parent = clk_master_get_parent,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_register_master(struct regmap *regmap,
                const char *name, int num_parents,
                const char **parent_names,
@@ -161,92 +148,12 @@ at91_clk_register_master(struct regmap *regmap,
 }
 
 
-static const struct clk_master_layout at91rm9200_master_layout = {
+const struct clk_master_layout at91rm9200_master_layout = {
        .mask = 0x31F,
        .pres_shift = 2,
 };
 
-static const struct clk_master_layout at91sam9x5_master_layout = {
+const struct clk_master_layout at91sam9x5_master_layout = {
        .mask = 0x373,
        .pres_shift = 4,
 };
-
-
-static struct clk_master_characteristics * __init
-of_at91_clk_master_get_characteristics(struct device_node *np)
-{
-       struct clk_master_characteristics *characteristics;
-
-       characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
-       if (!characteristics)
-               return NULL;
-
-       if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))
-               goto out_free_characteristics;
-
-       of_property_read_u32_array(np, "atmel,clk-divisors",
-                                  characteristics->divisors, 4);
-
-       characteristics->have_div3_pres =
-               of_property_read_bool(np, "atmel,master-clk-have-div3-pres");
-
-       return characteristics;
-
-out_free_characteristics:
-       kfree(characteristics);
-       return NULL;
-}
-
-static void __init
-of_at91_clk_master_setup(struct device_node *np,
-                        const struct clk_master_layout *layout)
-{
-       struct clk_hw *hw;
-       unsigned int num_parents;
-       const char *parent_names[MASTER_SOURCE_MAX];
-       const char *name = np->name;
-       struct clk_master_characteristics *characteristics;
-       struct regmap *regmap;
-
-       num_parents = of_clk_get_parent_count(np);
-       if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX)
-               return;
-
-       of_clk_parent_fill(np, parent_names, num_parents);
-
-       of_property_read_string(np, "clock-output-names", &name);
-
-       characteristics = of_at91_clk_master_get_characteristics(np);
-       if (!characteristics)
-               return;
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       hw = at91_clk_register_master(regmap, name, num_parents,
-                                      parent_names, layout,
-                                      characteristics);
-       if (IS_ERR(hw))
-               goto out_free_characteristics;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-       return;
-
-out_free_characteristics:
-       kfree(characteristics);
-}
-
-static void __init of_at91rm9200_clk_master_setup(struct device_node *np)
-{
-       of_at91_clk_master_setup(np, &at91rm9200_master_layout);
-}
-CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master",
-              of_at91rm9200_clk_master_setup);
-
-static void __init of_at91sam9x5_clk_master_setup(struct device_node *np)
-{
-       of_at91_clk_master_setup(np, &at91sam9x5_master_layout);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master",
-              of_at91sam9x5_clk_master_setup);
index 7701183692308e8870a669658e8c24b4d14700e4..65c1defa78e4a136c1ddcd0f04d8e2c5882b6811 100644 (file)
 
 DEFINE_SPINLOCK(pmc_pcr_lock);
 
-#define PERIPHERAL_MAX         64
-
-#define PERIPHERAL_AT91RM9200  0
-#define PERIPHERAL_AT91SAM9X5  1
-
 #define PERIPHERAL_ID_MIN      2
 #define PERIPHERAL_ID_MAX      31
 #define PERIPHERAL_MASK(id)    (1 << ((id) & PERIPHERAL_ID_MAX))
@@ -104,7 +99,7 @@ static const struct clk_ops peripheral_ops = {
        .is_enabled = clk_peripheral_is_enabled,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_register_peripheral(struct regmap *regmap, const char *name,
                             const char *parent_name, u32 id)
 {
@@ -331,7 +326,7 @@ static const struct clk_ops sam9x5_peripheral_ops = {
        .set_rate = clk_sam9x5_peripheral_set_rate,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
                                    const char *name, const char *parent_name,
                                    u32 id, const struct clk_range *range)
@@ -374,75 +369,3 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
 
        return hw;
 }
-
-static void __init
-of_at91_clk_periph_setup(struct device_node *np, u8 type)
-{
-       int num;
-       u32 id;
-       struct clk_hw *hw;
-       const char *parent_name;
-       const char *name;
-       struct device_node *periphclknp;
-       struct regmap *regmap;
-
-       parent_name = of_clk_get_parent_name(np, 0);
-       if (!parent_name)
-               return;
-
-       num = of_get_child_count(np);
-       if (!num || num > PERIPHERAL_MAX)
-               return;
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       for_each_child_of_node(np, periphclknp) {
-               if (of_property_read_u32(periphclknp, "reg", &id))
-                       continue;
-
-               if (id >= PERIPHERAL_MAX)
-                       continue;
-
-               if (of_property_read_string(np, "clock-output-names", &name))
-                       name = periphclknp->name;
-
-               if (type == PERIPHERAL_AT91RM9200) {
-                       hw = at91_clk_register_peripheral(regmap, name,
-                                                          parent_name, id);
-               } else {
-                       struct clk_range range = CLK_RANGE(0, 0);
-
-                       of_at91_get_clk_range(periphclknp,
-                                             "atmel,clk-output-range",
-                                             &range);
-
-                       hw = at91_clk_register_sam9x5_peripheral(regmap,
-                                                                 &pmc_pcr_lock,
-                                                                 name,
-                                                                 parent_name,
-                                                                 id, &range);
-               }
-
-               if (IS_ERR(hw))
-                       continue;
-
-               of_clk_add_hw_provider(periphclknp, of_clk_hw_simple_get, hw);
-       }
-}
-
-static void __init of_at91rm9200_clk_periph_setup(struct device_node *np)
-{
-       of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200);
-}
-CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral",
-              of_at91rm9200_clk_periph_setup);
-
-static void __init of_at91sam9x5_clk_periph_setup(struct device_node *np)
-{
-       of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral",
-              of_at91sam9x5_clk_periph_setup);
-
index 72b6091eb7b944f50b6a2e3d9ceafa8077a851d2..b4138fcacf495156a5a14d684cc2e66309b9be6f 100644 (file)
 #define PLL_OUT_SHIFT          14
 #define PLL_MAX_ID             1
 
-struct clk_pll_characteristics {
-       struct clk_range input;
-       int num_output;
-       struct clk_range *output;
-       u16 *icpll;
-       u8 *out;
-};
-
-struct clk_pll_layout {
-       u32 pllr_mask;
-       u16 mul_mask;
-       u8 mul_shift;
-};
-
 #define to_clk_pll(hw) container_of(hw, struct clk_pll, hw)
 
 struct clk_pll {
@@ -133,6 +119,9 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
 {
        struct clk_pll *pll = to_clk_pll(hw);
 
+       if (!pll->div || !pll->mul)
+               return 0;
+
        return (parent_rate / pll->div) * (pll->mul + 1);
 }
 
@@ -285,7 +274,7 @@ static const struct clk_ops pll_ops = {
        .set_rate = clk_pll_set_rate,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_register_pll(struct regmap *regmap, const char *name,
                      const char *parent_name, u8 id,
                      const struct clk_pll_layout *layout,
@@ -331,189 +320,26 @@ at91_clk_register_pll(struct regmap *regmap, const char *name,
 }
 
 
-static const struct clk_pll_layout at91rm9200_pll_layout = {
+const struct clk_pll_layout at91rm9200_pll_layout = {
        .pllr_mask = 0x7FFFFFF,
        .mul_shift = 16,
        .mul_mask = 0x7FF,
 };
 
-static const struct clk_pll_layout at91sam9g45_pll_layout = {
+const struct clk_pll_layout at91sam9g45_pll_layout = {
        .pllr_mask = 0xFFFFFF,
        .mul_shift = 16,
        .mul_mask = 0xFF,
 };
 
-static const struct clk_pll_layout at91sam9g20_pllb_layout = {
+const struct clk_pll_layout at91sam9g20_pllb_layout = {
        .pllr_mask = 0x3FFFFF,
        .mul_shift = 16,
        .mul_mask = 0x3F,
 };
 
-static const struct clk_pll_layout sama5d3_pll_layout = {
+const struct clk_pll_layout sama5d3_pll_layout = {
        .pllr_mask = 0x1FFFFFF,
        .mul_shift = 18,
        .mul_mask = 0x7F,
 };
-
-
-static struct clk_pll_characteristics * __init
-of_at91_clk_pll_get_characteristics(struct device_node *np)
-{
-       int i;
-       int offset;
-       u32 tmp;
-       int num_output;
-       u32 num_cells;
-       struct clk_range input;
-       struct clk_range *output;
-       u8 *out = NULL;
-       u16 *icpll = NULL;
-       struct clk_pll_characteristics *characteristics;
-
-       if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input))
-               return NULL;
-
-       if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells",
-                                &num_cells))
-               return NULL;
-
-       if (num_cells < 2 || num_cells > 4)
-               return NULL;
-
-       if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp))
-               return NULL;
-       num_output = tmp / (sizeof(u32) * num_cells);
-
-       characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
-       if (!characteristics)
-               return NULL;
-
-       output = kcalloc(num_output, sizeof(*output), GFP_KERNEL);
-       if (!output)
-               goto out_free_characteristics;
-
-       if (num_cells > 2) {
-               out = kcalloc(num_output, sizeof(*out), GFP_KERNEL);
-               if (!out)
-                       goto out_free_output;
-       }
-
-       if (num_cells > 3) {
-               icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL);
-               if (!icpll)
-                       goto out_free_output;
-       }
-
-       for (i = 0; i < num_output; i++) {
-               offset = i * num_cells;
-               if (of_property_read_u32_index(np,
-                                              "atmel,pll-clk-output-ranges",
-                                              offset, &tmp))
-                       goto out_free_output;
-               output[i].min = tmp;
-               if (of_property_read_u32_index(np,
-                                              "atmel,pll-clk-output-ranges",
-                                              offset + 1, &tmp))
-                       goto out_free_output;
-               output[i].max = tmp;
-
-               if (num_cells == 2)
-                       continue;
-
-               if (of_property_read_u32_index(np,
-                                              "atmel,pll-clk-output-ranges",
-                                              offset + 2, &tmp))
-                       goto out_free_output;
-               out[i] = tmp;
-
-               if (num_cells == 3)
-                       continue;
-
-               if (of_property_read_u32_index(np,
-                                              "atmel,pll-clk-output-ranges",
-                                              offset + 3, &tmp))
-                       goto out_free_output;
-               icpll[i] = tmp;
-       }
-
-       characteristics->input = input;
-       characteristics->num_output = num_output;
-       characteristics->output = output;
-       characteristics->out = out;
-       characteristics->icpll = icpll;
-       return characteristics;
-
-out_free_output:
-       kfree(icpll);
-       kfree(out);
-       kfree(output);
-out_free_characteristics:
-       kfree(characteristics);
-       return NULL;
-}
-
-static void __init
-of_at91_clk_pll_setup(struct device_node *np,
-                     const struct clk_pll_layout *layout)
-{
-       u32 id;
-       struct clk_hw *hw;
-       struct regmap *regmap;
-       const char *parent_name;
-       const char *name = np->name;
-       struct clk_pll_characteristics *characteristics;
-
-       if (of_property_read_u32(np, "reg", &id))
-               return;
-
-       parent_name = of_clk_get_parent_name(np, 0);
-
-       of_property_read_string(np, "clock-output-names", &name);
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       characteristics = of_at91_clk_pll_get_characteristics(np);
-       if (!characteristics)
-               return;
-
-       hw = at91_clk_register_pll(regmap, name, parent_name, id, layout,
-                                   characteristics);
-       if (IS_ERR(hw))
-               goto out_free_characteristics;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-       return;
-
-out_free_characteristics:
-       kfree(characteristics);
-}
-
-static void __init of_at91rm9200_clk_pll_setup(struct device_node *np)
-{
-       of_at91_clk_pll_setup(np, &at91rm9200_pll_layout);
-}
-CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll",
-              of_at91rm9200_clk_pll_setup);
-
-static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np)
-{
-       of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout);
-}
-CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll",
-              of_at91sam9g45_clk_pll_setup);
-
-static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np)
-{
-       of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout);
-}
-CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb",
-              of_at91sam9g20_clk_pllb_setup);
-
-static void __init of_sama5d3_clk_pll_setup(struct device_node *np)
-{
-       of_at91_clk_pll_setup(np, &sama5d3_pll_layout);
-}
-CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll",
-              of_sama5d3_clk_pll_setup);
index b4afaf22f3fdc93277582746976b4d3ff0af5267..e8c4f8b02f28085a11fb215d3a39f0429e5f4fdc 100644 (file)
@@ -75,7 +75,7 @@ static const struct clk_ops plldiv_ops = {
        .set_rate = clk_plldiv_set_rate,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_register_plldiv(struct regmap *regmap, const char *name,
                         const char *parent_name)
 {
@@ -106,28 +106,3 @@ at91_clk_register_plldiv(struct regmap *regmap, const char *name,
 
        return hw;
 }
-
-static void __init
-of_at91sam9x5_clk_plldiv_setup(struct device_node *np)
-{
-       struct clk_hw *hw;
-       const char *parent_name;
-       const char *name = np->name;
-       struct regmap *regmap;
-
-       parent_name = of_clk_get_parent_name(np, 0);
-
-       of_property_read_string(np, "clock-output-names", &name);
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       hw = at91_clk_register_plldiv(regmap, name, parent_name);
-       if (IS_ERR(hw))
-               return;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv",
-              of_at91sam9x5_clk_plldiv_setup);
index 0e6aab1252fc40dc6a4896abe875f51d9c9b8eb6..5bc68b9c5498496b6f6af33ad87422804dd62ef4 100644 (file)
@@ -17,7 +17,6 @@
 
 #include "pmc.h"
 
-#define PROG_SOURCE_MAX                5
 #define PROG_ID_MAX            7
 
 #define PROG_STATUS_MASK(id)   (1 << ((id) + 8))
 #define PROG_PRES(layout, pckr)        ((pckr >> layout->pres_shift) & PROG_PRES_MASK)
 #define PROG_MAX_RM9200_CSS    3
 
-struct clk_programmable_layout {
-       u8 pres_shift;
-       u8 css_mask;
-       u8 have_slck_mck;
-};
-
 struct clk_programmable {
        struct clk_hw hw;
        struct regmap *regmap;
@@ -170,7 +163,7 @@ static const struct clk_ops programmable_ops = {
        .set_rate = clk_programmable_set_rate,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_register_programmable(struct regmap *regmap,
                               const char *name, const char **parent_names,
                               u8 num_parents, u8 id,
@@ -211,86 +204,20 @@ at91_clk_register_programmable(struct regmap *regmap,
        return hw;
 }
 
-static const struct clk_programmable_layout at91rm9200_programmable_layout = {
+const struct clk_programmable_layout at91rm9200_programmable_layout = {
        .pres_shift = 2,
        .css_mask = 0x3,
        .have_slck_mck = 0,
 };
 
-static const struct clk_programmable_layout at91sam9g45_programmable_layout = {
+const struct clk_programmable_layout at91sam9g45_programmable_layout = {
        .pres_shift = 2,
        .css_mask = 0x3,
        .have_slck_mck = 1,
 };
 
-static const struct clk_programmable_layout at91sam9x5_programmable_layout = {
+const struct clk_programmable_layout at91sam9x5_programmable_layout = {
        .pres_shift = 4,
        .css_mask = 0x7,
        .have_slck_mck = 0,
 };
-
-static void __init
-of_at91_clk_prog_setup(struct device_node *np,
-                      const struct clk_programmable_layout *layout)
-{
-       int num;
-       u32 id;
-       struct clk_hw *hw;
-       unsigned int num_parents;
-       const char *parent_names[PROG_SOURCE_MAX];
-       const char *name;
-       struct device_node *progclknp;
-       struct regmap *regmap;
-
-       num_parents = of_clk_get_parent_count(np);
-       if (num_parents == 0 || num_parents > PROG_SOURCE_MAX)
-               return;
-
-       of_clk_parent_fill(np, parent_names, num_parents);
-
-       num = of_get_child_count(np);
-       if (!num || num > (PROG_ID_MAX + 1))
-               return;
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       for_each_child_of_node(np, progclknp) {
-               if (of_property_read_u32(progclknp, "reg", &id))
-                       continue;
-
-               if (of_property_read_string(np, "clock-output-names", &name))
-                       name = progclknp->name;
-
-               hw = at91_clk_register_programmable(regmap, name,
-                                                    parent_names, num_parents,
-                                                    id, layout);
-               if (IS_ERR(hw))
-                       continue;
-
-               of_clk_add_hw_provider(progclknp, of_clk_hw_simple_get, hw);
-       }
-}
-
-
-static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)
-{
-       of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout);
-}
-CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",
-              of_at91rm9200_clk_prog_setup);
-
-static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)
-{
-       of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout);
-}
-CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",
-              of_at91sam9g45_clk_prog_setup);
-
-static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)
-{
-       of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",
-              of_at91sam9x5_clk_prog_setup);
index 560a8b9abf9312bd921311bcf88d121727750c83..cbb146912f7af0b542bb836398b5f7b1d6eafd6f 100644 (file)
@@ -40,7 +40,7 @@ static const struct clk_ops sam9260_slow_ops = {
        .get_parent = clk_sam9260_slow_get_parent,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_register_sam9260_slow(struct regmap *regmap,
                               const char *name,
                               const char **parent_names,
@@ -79,33 +79,3 @@ at91_clk_register_sam9260_slow(struct regmap *regmap,
 
        return hw;
 }
-
-static void __init of_at91sam9260_clk_slow_setup(struct device_node *np)
-{
-       struct clk_hw *hw;
-       const char *parent_names[2];
-       unsigned int num_parents;
-       const char *name = np->name;
-       struct regmap *regmap;
-
-       num_parents = of_clk_get_parent_count(np);
-       if (num_parents != 2)
-               return;
-
-       of_clk_parent_fill(np, parent_names, num_parents);
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       of_property_read_string(np, "clock-output-names", &name);
-
-       hw = at91_clk_register_sam9260_slow(regmap, name, parent_names,
-                                            num_parents);
-       if (IS_ERR(hw))
-               return;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-}
-
-CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow",
-              of_at91sam9260_clk_slow_setup);
index 965c662b90a5ab6f3dfdcd5b4cd2382d79f4422e..75679fd8a9c742e387103296c9e8ee3fd6418881 100644 (file)
@@ -17,8 +17,6 @@
 
 #include "pmc.h"
 
-#define SMD_SOURCE_MAX         2
-
 #define SMD_DIV_SHIFT          8
 #define SMD_MAX_DIV            0xf
 
@@ -111,7 +109,7 @@ static const struct clk_ops at91sam9x5_smd_ops = {
        .set_rate = at91sam9x5_clk_smd_set_rate,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
                            const char **parent_names, u8 num_parents)
 {
@@ -142,33 +140,3 @@ at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
 
        return hw;
 }
-
-static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np)
-{
-       struct clk_hw *hw;
-       unsigned int num_parents;
-       const char *parent_names[SMD_SOURCE_MAX];
-       const char *name = np->name;
-       struct regmap *regmap;
-
-       num_parents = of_clk_get_parent_count(np);
-       if (num_parents == 0 || num_parents > SMD_SOURCE_MAX)
-               return;
-
-       of_clk_parent_fill(np, parent_names, num_parents);
-
-       of_property_read_string(np, "clock-output-names", &name);
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       hw = at91sam9x5_clk_register_smd(regmap, name, parent_names,
-                                         num_parents);
-       if (IS_ERR(hw))
-               return;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd",
-              of_at91sam9x5_clk_smd_setup);
index 86a36809765de84c94b9e29e55e129b2905b65ae..47bfca93340320130ca50386764bce6e975ea2cf 100644 (file)
@@ -88,7 +88,7 @@ static const struct clk_ops system_ops = {
        .is_prepared = clk_system_is_prepared,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_register_system(struct regmap *regmap, const char *name,
                         const char *parent_name, u8 id)
 {
@@ -123,40 +123,3 @@ at91_clk_register_system(struct regmap *regmap, const char *name,
 
        return hw;
 }
-
-static void __init of_at91rm9200_clk_sys_setup(struct device_node *np)
-{
-       int num;
-       u32 id;
-       struct clk_hw *hw;
-       const char *name;
-       struct device_node *sysclknp;
-       const char *parent_name;
-       struct regmap *regmap;
-
-       num = of_get_child_count(np);
-       if (num > (SYSTEM_MAX_ID + 1))
-               return;
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       for_each_child_of_node(np, sysclknp) {
-               if (of_property_read_u32(sysclknp, "reg", &id))
-                       continue;
-
-               if (of_property_read_string(np, "clock-output-names", &name))
-                       name = sysclknp->name;
-
-               parent_name = of_clk_get_parent_name(sysclknp, 0);
-
-               hw = at91_clk_register_system(regmap, name, parent_name, id);
-               if (IS_ERR(hw))
-                       continue;
-
-               of_clk_add_hw_provider(sysclknp, of_clk_hw_simple_get, hw);
-       }
-}
-CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system",
-              of_at91rm9200_clk_sys_setup);
index 791770a563fcce83d5538a52b5cc86bcc7a925c7..79ee1c760f2a5ba41a7cfaf3a7d748b30ef11f8c 100644 (file)
@@ -17,8 +17,6 @@
 
 #include "pmc.h"
 
-#define USB_SOURCE_MAX         2
-
 #define SAM9X5_USB_DIV_SHIFT   8
 #define SAM9X5_USB_MAX_DIV     0xf
 
@@ -192,7 +190,7 @@ static const struct clk_ops at91sam9n12_usb_ops = {
        .set_rate = at91sam9x5_clk_usb_set_rate,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
                            const char **parent_names, u8 num_parents)
 {
@@ -225,7 +223,7 @@ at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
        return hw;
 }
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
                             const char *parent_name)
 {
@@ -342,7 +340,7 @@ static const struct clk_ops at91rm9200_usb_ops = {
        .set_rate = at91rm9200_clk_usb_set_rate,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
                            const char *parent_name, const u32 *divisors)
 {
@@ -374,89 +372,3 @@ at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
 
        return hw;
 }
-
-static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np)
-{
-       struct clk_hw *hw;
-       unsigned int num_parents;
-       const char *parent_names[USB_SOURCE_MAX];
-       const char *name = np->name;
-       struct regmap *regmap;
-
-       num_parents = of_clk_get_parent_count(np);
-       if (num_parents == 0 || num_parents > USB_SOURCE_MAX)
-               return;
-
-       of_clk_parent_fill(np, parent_names, num_parents);
-
-       of_property_read_string(np, "clock-output-names", &name);
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       hw = at91sam9x5_clk_register_usb(regmap, name, parent_names,
-                                        num_parents);
-       if (IS_ERR(hw))
-               return;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb",
-              of_at91sam9x5_clk_usb_setup);
-
-static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np)
-{
-       struct clk_hw *hw;
-       const char *parent_name;
-       const char *name = np->name;
-       struct regmap *regmap;
-
-       parent_name = of_clk_get_parent_name(np, 0);
-       if (!parent_name)
-               return;
-
-       of_property_read_string(np, "clock-output-names", &name);
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-
-       hw = at91sam9n12_clk_register_usb(regmap, name, parent_name);
-       if (IS_ERR(hw))
-               return;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-}
-CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb",
-              of_at91sam9n12_clk_usb_setup);
-
-static void __init of_at91rm9200_clk_usb_setup(struct device_node *np)
-{
-       struct clk_hw *hw;
-       const char *parent_name;
-       const char *name = np->name;
-       u32 divisors[4] = {0, 0, 0, 0};
-       struct regmap *regmap;
-
-       parent_name = of_clk_get_parent_name(np, 0);
-       if (!parent_name)
-               return;
-
-       of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4);
-       if (!divisors[0])
-               return;
-
-       of_property_read_string(np, "clock-output-names", &name);
-
-       regmap = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap))
-               return;
-       hw = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors);
-       if (IS_ERR(hw))
-               return;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-}
-CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb",
-              of_at91rm9200_clk_usb_setup);
index cd8d689138ff9917822aec3416a101bd0eb665c6..9a970abf34898963e9c689868aa7d9857de22559 100644 (file)
@@ -125,7 +125,7 @@ static const struct clk_ops utmi_ops = {
        .recalc_rate = clk_utmi_recalc_rate,
 };
 
-static struct clk_hw * __init
+struct clk_hw * __init
 at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
                       const char *name, const char *parent_name)
 {
@@ -157,46 +157,3 @@ at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
 
        return hw;
 }
-
-static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
-{
-       struct clk_hw *hw;
-       const char *parent_name;
-       const char *name = np->name;
-       struct regmap *regmap_pmc, *regmap_sfr;
-
-       parent_name = of_clk_get_parent_name(np, 0);
-
-       of_property_read_string(np, "clock-output-names", &name);
-
-       regmap_pmc = syscon_node_to_regmap(of_get_parent(np));
-       if (IS_ERR(regmap_pmc))
-               return;
-
-       /*
-        * If the device supports different mainck rates, this value has to be
-        * set in the UTMI Clock Trimming register.
-        * - 9x5: mainck supports several rates but it is indicated that a
-        *   12 MHz is needed in case of USB.
-        * - sama5d3 and sama5d2: mainck supports several rates. Configuring
-        *   the FREQ field of the UTMI Clock Trimming register is mandatory.
-        * - sama5d4: mainck is at 12 MHz.
-        *
-        * We only need to retrieve sama5d3 or sama5d2 sfr regmap.
-        */
-       regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr");
-       if (IS_ERR(regmap_sfr)) {
-               regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
-               if (IS_ERR(regmap_sfr))
-                       regmap_sfr = NULL;
-       }
-
-       hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name);
-       if (IS_ERR(hw))
-               return;
-
-       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
-       return;
-}
-CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi",
-              of_at91sam9x5_clk_utmi_setup);
diff --git a/drivers/clk/at91/dt-compat.c b/drivers/clk/at91/dt-compat.c
new file mode 100644 (file)
index 0000000..b95bb4e
--- /dev/null
@@ -0,0 +1,961 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/clk-provider.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include "pmc.h"
+
+#define MASTER_SOURCE_MAX      4
+
+#define PERIPHERAL_AT91RM9200  0
+#define PERIPHERAL_AT91SAM9X5  1
+
+#define PERIPHERAL_MAX         64
+
+#define PERIPHERAL_ID_MIN      2
+
+#define PROG_SOURCE_MAX                5
+#define PROG_ID_MAX            7
+
+#define SYSTEM_MAX_ID          31
+
+#ifdef CONFIG_HAVE_AT91_AUDIO_PLL
+static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       const char *name = np->name;
+       const char *parent_name;
+       struct regmap *regmap;
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+
+       hw = at91_clk_register_audio_pll_frac(regmap, name, parent_name);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_frac_setup,
+              "atmel,sama5d2-clk-audio-pll-frac",
+              of_sama5d2_clk_audio_pll_frac_setup);
+
+static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       const char *name = np->name;
+       const char *parent_name;
+       struct regmap *regmap;
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+
+       hw = at91_clk_register_audio_pll_pad(regmap, name, parent_name);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup,
+              "atmel,sama5d2-clk-audio-pll-pad",
+              of_sama5d2_clk_audio_pll_pad_setup);
+
+static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       const char *name = np->name;
+       const char *parent_name;
+       struct regmap *regmap;
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+
+       hw = at91_clk_register_audio_pll_pmc(regmap, name, parent_name);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup,
+              "atmel,sama5d2-clk-audio-pll-pmc",
+              of_sama5d2_clk_audio_pll_pmc_setup);
+#endif /* CONFIG_HAVE_AT91_AUDIO_PLL */
+
+#ifdef CONFIG_HAVE_AT91_GENERATED_CLK
+#define GENERATED_SOURCE_MAX   6
+
+#define GCK_ID_I2S0            54
+#define GCK_ID_I2S1            55
+#define GCK_ID_CLASSD          59
+
+static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
+{
+       int num;
+       u32 id;
+       const char *name;
+       struct clk_hw *hw;
+       unsigned int num_parents;
+       const char *parent_names[GENERATED_SOURCE_MAX];
+       struct device_node *gcknp;
+       struct clk_range range = CLK_RANGE(0, 0);
+       struct regmap *regmap;
+
+       num_parents = of_clk_get_parent_count(np);
+       if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX)
+               return;
+
+       of_clk_parent_fill(np, parent_names, num_parents);
+
+       num = of_get_child_count(np);
+       if (!num || num > PERIPHERAL_MAX)
+               return;
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       for_each_child_of_node(np, gcknp) {
+               bool pll_audio = false;
+
+               if (of_property_read_u32(gcknp, "reg", &id))
+                       continue;
+
+               if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX)
+                       continue;
+
+               if (of_property_read_string(np, "clock-output-names", &name))
+                       name = gcknp->name;
+
+               of_at91_get_clk_range(gcknp, "atmel,clk-output-range",
+                                     &range);
+
+               if (of_device_is_compatible(np, "atmel,sama5d2-clk-generated") &&
+                   (id == GCK_ID_I2S0 || id == GCK_ID_I2S1 ||
+                    id == GCK_ID_CLASSD))
+                       pll_audio = true;
+
+               hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name,
+                                                parent_names, num_parents,
+                                                id, pll_audio, &range);
+               if (IS_ERR(hw))
+                       continue;
+
+               of_clk_add_hw_provider(gcknp, of_clk_hw_simple_get, hw);
+       }
+}
+CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated",
+              of_sama5d2_clk_generated_setup);
+#endif /* CONFIG_HAVE_AT91_GENERATED_CLK */
+
+#ifdef CONFIG_HAVE_AT91_H32MX
+static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       const char *name = np->name;
+       const char *parent_name;
+       struct regmap *regmap;
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+
+       hw = at91_clk_register_h32mx(regmap, name, parent_name);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx",
+              of_sama5d4_clk_h32mx_setup);
+#endif /* CONFIG_HAVE_AT91_H32MX */
+
+#ifdef CONFIG_HAVE_AT91_I2S_MUX_CLK
+#define        I2S_BUS_NR      2
+
+static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np)
+{
+       struct regmap *regmap_sfr;
+       u8 bus_id;
+       const char *parent_names[2];
+       struct device_node *i2s_mux_np;
+       struct clk_hw *hw;
+       int ret;
+
+       regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
+       if (IS_ERR(regmap_sfr))
+               return;
+
+       for_each_child_of_node(np, i2s_mux_np) {
+               if (of_property_read_u8(i2s_mux_np, "reg", &bus_id))
+                       continue;
+
+               if (bus_id > I2S_BUS_NR)
+                       continue;
+
+               ret = of_clk_parent_fill(i2s_mux_np, parent_names, 2);
+               if (ret != 2)
+                       continue;
+
+               hw = at91_clk_i2s_mux_register(regmap_sfr, i2s_mux_np->name,
+                                              parent_names, 2, bus_id);
+               if (IS_ERR(hw))
+                       continue;
+
+               of_clk_add_hw_provider(i2s_mux_np, of_clk_hw_simple_get, hw);
+       }
+}
+CLK_OF_DECLARE(sama5d2_clk_i2s_mux, "atmel,sama5d2-clk-i2s-mux",
+              of_sama5d2_clk_i2s_mux_setup);
+#endif /* CONFIG_HAVE_AT91_I2S_MUX_CLK */
+
+static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       const char *name = np->name;
+       const char *parent_name;
+       struct regmap *regmap;
+       bool bypass;
+
+       of_property_read_string(np, "clock-output-names", &name);
+       bypass = of_property_read_bool(np, "atmel,osc-bypass");
+       parent_name = of_clk_get_parent_name(np, 0);
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       hw = at91_clk_register_main_osc(regmap, name, parent_name, bypass);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc",
+              of_at91rm9200_clk_main_osc_setup);
+
+static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       u32 frequency = 0;
+       u32 accuracy = 0;
+       const char *name = np->name;
+       struct regmap *regmap;
+
+       of_property_read_string(np, "clock-output-names", &name);
+       of_property_read_u32(np, "clock-frequency", &frequency);
+       of_property_read_u32(np, "clock-accuracy", &accuracy);
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       hw = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc",
+              of_at91sam9x5_clk_main_rc_osc_setup);
+
+static void __init of_at91rm9200_clk_main_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       const char *parent_name;
+       const char *name = np->name;
+       struct regmap *regmap;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+       of_property_read_string(np, "clock-output-names", &name);
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       hw = at91_clk_register_rm9200_main(regmap, name, parent_name);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main",
+              of_at91rm9200_clk_main_setup);
+
+static void __init of_at91sam9x5_clk_main_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       const char *parent_names[2];
+       unsigned int num_parents;
+       const char *name = np->name;
+       struct regmap *regmap;
+
+       num_parents = of_clk_get_parent_count(np);
+       if (num_parents == 0 || num_parents > 2)
+               return;
+
+       of_clk_parent_fill(np, parent_names, num_parents);
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       hw = at91_clk_register_sam9x5_main(regmap, name, parent_names,
+                                          num_parents);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main",
+              of_at91sam9x5_clk_main_setup);
+
+static struct clk_master_characteristics * __init
+of_at91_clk_master_get_characteristics(struct device_node *np)
+{
+       struct clk_master_characteristics *characteristics;
+
+       characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
+       if (!characteristics)
+               return NULL;
+
+       if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))
+               goto out_free_characteristics;
+
+       of_property_read_u32_array(np, "atmel,clk-divisors",
+                                  characteristics->divisors, 4);
+
+       characteristics->have_div3_pres =
+               of_property_read_bool(np, "atmel,master-clk-have-div3-pres");
+
+       return characteristics;
+
+out_free_characteristics:
+       kfree(characteristics);
+       return NULL;
+}
+
+static void __init
+of_at91_clk_master_setup(struct device_node *np,
+                        const struct clk_master_layout *layout)
+{
+       struct clk_hw *hw;
+       unsigned int num_parents;
+       const char *parent_names[MASTER_SOURCE_MAX];
+       const char *name = np->name;
+       struct clk_master_characteristics *characteristics;
+       struct regmap *regmap;
+
+       num_parents = of_clk_get_parent_count(np);
+       if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX)
+               return;
+
+       of_clk_parent_fill(np, parent_names, num_parents);
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       characteristics = of_at91_clk_master_get_characteristics(np);
+       if (!characteristics)
+               return;
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       hw = at91_clk_register_master(regmap, name, num_parents,
+                                     parent_names, layout,
+                                     characteristics);
+       if (IS_ERR(hw))
+               goto out_free_characteristics;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+       return;
+
+out_free_characteristics:
+       kfree(characteristics);
+}
+
+static void __init of_at91rm9200_clk_master_setup(struct device_node *np)
+{
+       of_at91_clk_master_setup(np, &at91rm9200_master_layout);
+}
+CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master",
+              of_at91rm9200_clk_master_setup);
+
+static void __init of_at91sam9x5_clk_master_setup(struct device_node *np)
+{
+       of_at91_clk_master_setup(np, &at91sam9x5_master_layout);
+}
+CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master",
+              of_at91sam9x5_clk_master_setup);
+
+static void __init
+of_at91_clk_periph_setup(struct device_node *np, u8 type)
+{
+       int num;
+       u32 id;
+       struct clk_hw *hw;
+       const char *parent_name;
+       const char *name;
+       struct device_node *periphclknp;
+       struct regmap *regmap;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+       if (!parent_name)
+               return;
+
+       num = of_get_child_count(np);
+       if (!num || num > PERIPHERAL_MAX)
+               return;
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       for_each_child_of_node(np, periphclknp) {
+               if (of_property_read_u32(periphclknp, "reg", &id))
+                       continue;
+
+               if (id >= PERIPHERAL_MAX)
+                       continue;
+
+               if (of_property_read_string(np, "clock-output-names", &name))
+                       name = periphclknp->name;
+
+               if (type == PERIPHERAL_AT91RM9200) {
+                       hw = at91_clk_register_peripheral(regmap, name,
+                                                         parent_name, id);
+               } else {
+                       struct clk_range range = CLK_RANGE(0, 0);
+
+                       of_at91_get_clk_range(periphclknp,
+                                             "atmel,clk-output-range",
+                                             &range);
+
+                       hw = at91_clk_register_sam9x5_peripheral(regmap,
+                                                                &pmc_pcr_lock,
+                                                                name,
+                                                                parent_name,
+                                                                id, &range);
+               }
+
+               if (IS_ERR(hw))
+                       continue;
+
+               of_clk_add_hw_provider(periphclknp, of_clk_hw_simple_get, hw);
+       }
+}
+
+static void __init of_at91rm9200_clk_periph_setup(struct device_node *np)
+{
+       of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200);
+}
+CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral",
+              of_at91rm9200_clk_periph_setup);
+
+static void __init of_at91sam9x5_clk_periph_setup(struct device_node *np)
+{
+       of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5);
+}
+CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral",
+              of_at91sam9x5_clk_periph_setup);
+
+static struct clk_pll_characteristics * __init
+of_at91_clk_pll_get_characteristics(struct device_node *np)
+{
+       int i;
+       int offset;
+       u32 tmp;
+       int num_output;
+       u32 num_cells;
+       struct clk_range input;
+       struct clk_range *output;
+       u8 *out = NULL;
+       u16 *icpll = NULL;
+       struct clk_pll_characteristics *characteristics;
+
+       if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input))
+               return NULL;
+
+       if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells",
+                                &num_cells))
+               return NULL;
+
+       if (num_cells < 2 || num_cells > 4)
+               return NULL;
+
+       if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp))
+               return NULL;
+       num_output = tmp / (sizeof(u32) * num_cells);
+
+       characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
+       if (!characteristics)
+               return NULL;
+
+       output = kcalloc(num_output, sizeof(*output), GFP_KERNEL);
+       if (!output)
+               goto out_free_characteristics;
+
+       if (num_cells > 2) {
+               out = kcalloc(num_output, sizeof(*out), GFP_KERNEL);
+               if (!out)
+                       goto out_free_output;
+       }
+
+       if (num_cells > 3) {
+               icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL);
+               if (!icpll)
+                       goto out_free_output;
+       }
+
+       for (i = 0; i < num_output; i++) {
+               offset = i * num_cells;
+               if (of_property_read_u32_index(np,
+                                              "atmel,pll-clk-output-ranges",
+                                              offset, &tmp))
+                       goto out_free_output;
+               output[i].min = tmp;
+               if (of_property_read_u32_index(np,
+                                              "atmel,pll-clk-output-ranges",
+                                              offset + 1, &tmp))
+                       goto out_free_output;
+               output[i].max = tmp;
+
+               if (num_cells == 2)
+                       continue;
+
+               if (of_property_read_u32_index(np,
+                                              "atmel,pll-clk-output-ranges",
+                                              offset + 2, &tmp))
+                       goto out_free_output;
+               out[i] = tmp;
+
+               if (num_cells == 3)
+                       continue;
+
+               if (of_property_read_u32_index(np,
+                                              "atmel,pll-clk-output-ranges",
+                                              offset + 3, &tmp))
+                       goto out_free_output;
+               icpll[i] = tmp;
+       }
+
+       characteristics->input = input;
+       characteristics->num_output = num_output;
+       characteristics->output = output;
+       characteristics->out = out;
+       characteristics->icpll = icpll;
+       return characteristics;
+
+out_free_output:
+       kfree(icpll);
+       kfree(out);
+       kfree(output);
+out_free_characteristics:
+       kfree(characteristics);
+       return NULL;
+}
+
+static void __init
+of_at91_clk_pll_setup(struct device_node *np,
+                     const struct clk_pll_layout *layout)
+{
+       u32 id;
+       struct clk_hw *hw;
+       struct regmap *regmap;
+       const char *parent_name;
+       const char *name = np->name;
+       struct clk_pll_characteristics *characteristics;
+
+       if (of_property_read_u32(np, "reg", &id))
+               return;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       characteristics = of_at91_clk_pll_get_characteristics(np);
+       if (!characteristics)
+               return;
+
+       hw = at91_clk_register_pll(regmap, name, parent_name, id, layout,
+                                  characteristics);
+       if (IS_ERR(hw))
+               goto out_free_characteristics;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+       return;
+
+out_free_characteristics:
+       kfree(characteristics);
+}
+
+static void __init of_at91rm9200_clk_pll_setup(struct device_node *np)
+{
+       of_at91_clk_pll_setup(np, &at91rm9200_pll_layout);
+}
+CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll",
+              of_at91rm9200_clk_pll_setup);
+
+static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np)
+{
+       of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout);
+}
+CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll",
+              of_at91sam9g45_clk_pll_setup);
+
+static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np)
+{
+       of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout);
+}
+CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb",
+              of_at91sam9g20_clk_pllb_setup);
+
+static void __init of_sama5d3_clk_pll_setup(struct device_node *np)
+{
+       of_at91_clk_pll_setup(np, &sama5d3_pll_layout);
+}
+CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll",
+              of_sama5d3_clk_pll_setup);
+
+static void __init
+of_at91sam9x5_clk_plldiv_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       const char *parent_name;
+       const char *name = np->name;
+       struct regmap *regmap;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       hw = at91_clk_register_plldiv(regmap, name, parent_name);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv",
+              of_at91sam9x5_clk_plldiv_setup);
+
+static void __init
+of_at91_clk_prog_setup(struct device_node *np,
+                      const struct clk_programmable_layout *layout)
+{
+       int num;
+       u32 id;
+       struct clk_hw *hw;
+       unsigned int num_parents;
+       const char *parent_names[PROG_SOURCE_MAX];
+       const char *name;
+       struct device_node *progclknp;
+       struct regmap *regmap;
+
+       num_parents = of_clk_get_parent_count(np);
+       if (num_parents == 0 || num_parents > PROG_SOURCE_MAX)
+               return;
+
+       of_clk_parent_fill(np, parent_names, num_parents);
+
+       num = of_get_child_count(np);
+       if (!num || num > (PROG_ID_MAX + 1))
+               return;
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       for_each_child_of_node(np, progclknp) {
+               if (of_property_read_u32(progclknp, "reg", &id))
+                       continue;
+
+               if (of_property_read_string(np, "clock-output-names", &name))
+                       name = progclknp->name;
+
+               hw = at91_clk_register_programmable(regmap, name,
+                                                   parent_names, num_parents,
+                                                   id, layout);
+               if (IS_ERR(hw))
+                       continue;
+
+               of_clk_add_hw_provider(progclknp, of_clk_hw_simple_get, hw);
+       }
+}
+
+static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)
+{
+       of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout);
+}
+CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",
+              of_at91rm9200_clk_prog_setup);
+
+static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)
+{
+       of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout);
+}
+CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",
+              of_at91sam9g45_clk_prog_setup);
+
+static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)
+{
+       of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout);
+}
+CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",
+              of_at91sam9x5_clk_prog_setup);
+
+static void __init of_at91sam9260_clk_slow_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       const char *parent_names[2];
+       unsigned int num_parents;
+       const char *name = np->name;
+       struct regmap *regmap;
+
+       num_parents = of_clk_get_parent_count(np);
+       if (num_parents != 2)
+               return;
+
+       of_clk_parent_fill(np, parent_names, num_parents);
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       hw = at91_clk_register_sam9260_slow(regmap, name, parent_names,
+                                           num_parents);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow",
+              of_at91sam9260_clk_slow_setup);
+
+#ifdef CONFIG_HAVE_AT91_SMD
+#define SMD_SOURCE_MAX         2
+
+static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       unsigned int num_parents;
+       const char *parent_names[SMD_SOURCE_MAX];
+       const char *name = np->name;
+       struct regmap *regmap;
+
+       num_parents = of_clk_get_parent_count(np);
+       if (num_parents == 0 || num_parents > SMD_SOURCE_MAX)
+               return;
+
+       of_clk_parent_fill(np, parent_names, num_parents);
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       hw = at91sam9x5_clk_register_smd(regmap, name, parent_names,
+                                        num_parents);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd",
+              of_at91sam9x5_clk_smd_setup);
+#endif /* CONFIG_HAVE_AT91_SMD */
+
+static void __init of_at91rm9200_clk_sys_setup(struct device_node *np)
+{
+       int num;
+       u32 id;
+       struct clk_hw *hw;
+       const char *name;
+       struct device_node *sysclknp;
+       const char *parent_name;
+       struct regmap *regmap;
+
+       num = of_get_child_count(np);
+       if (num > (SYSTEM_MAX_ID + 1))
+               return;
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       for_each_child_of_node(np, sysclknp) {
+               if (of_property_read_u32(sysclknp, "reg", &id))
+                       continue;
+
+               if (of_property_read_string(np, "clock-output-names", &name))
+                       name = sysclknp->name;
+
+               parent_name = of_clk_get_parent_name(sysclknp, 0);
+
+               hw = at91_clk_register_system(regmap, name, parent_name, id);
+               if (IS_ERR(hw))
+                       continue;
+
+               of_clk_add_hw_provider(sysclknp, of_clk_hw_simple_get, hw);
+       }
+}
+CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system",
+              of_at91rm9200_clk_sys_setup);
+
+#ifdef CONFIG_HAVE_AT91_USB_CLK
+#define USB_SOURCE_MAX         2
+
+static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       unsigned int num_parents;
+       const char *parent_names[USB_SOURCE_MAX];
+       const char *name = np->name;
+       struct regmap *regmap;
+
+       num_parents = of_clk_get_parent_count(np);
+       if (num_parents == 0 || num_parents > USB_SOURCE_MAX)
+               return;
+
+       of_clk_parent_fill(np, parent_names, num_parents);
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       hw = at91sam9x5_clk_register_usb(regmap, name, parent_names,
+                                        num_parents);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb",
+              of_at91sam9x5_clk_usb_setup);
+
+static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       const char *parent_name;
+       const char *name = np->name;
+       struct regmap *regmap;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+       if (!parent_name)
+               return;
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+
+       hw = at91sam9n12_clk_register_usb(regmap, name, parent_name);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb",
+              of_at91sam9n12_clk_usb_setup);
+
+static void __init of_at91rm9200_clk_usb_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       const char *parent_name;
+       const char *name = np->name;
+       u32 divisors[4] = {0, 0, 0, 0};
+       struct regmap *regmap;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+       if (!parent_name)
+               return;
+
+       of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4);
+       if (!divisors[0])
+               return;
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       regmap = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap))
+               return;
+       hw = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb",
+              of_at91rm9200_clk_usb_setup);
+#endif /* CONFIG_HAVE_AT91_USB_CLK */
+
+#ifdef CONFIG_HAVE_AT91_UTMI
+static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
+{
+       struct clk_hw *hw;
+       const char *parent_name;
+       const char *name = np->name;
+       struct regmap *regmap_pmc, *regmap_sfr;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       regmap_pmc = syscon_node_to_regmap(of_get_parent(np));
+       if (IS_ERR(regmap_pmc))
+               return;
+
+       /*
+        * If the device supports different mainck rates, this value has to be
+        * set in the UTMI Clock Trimming register.
+        * - 9x5: mainck supports several rates but it is indicated that a
+        *   12 MHz is needed in case of USB.
+        * - sama5d3 and sama5d2: mainck supports several rates. Configuring
+        *   the FREQ field of the UTMI Clock Trimming register is mandatory.
+        * - sama5d4: mainck is at 12 MHz.
+        *
+        * We only need to retrieve sama5d3 or sama5d2 sfr regmap.
+        */
+       regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr");
+       if (IS_ERR(regmap_sfr)) {
+               regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
+               if (IS_ERR(regmap_sfr))
+                       regmap_sfr = NULL;
+       }
+
+       hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name);
+       if (IS_ERR(hw))
+               return;
+
+       of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
+}
+CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi",
+              of_at91sam9x5_clk_utmi_setup);
+#endif /* CONFIG_HAVE_AT91_UTMI */
index 1fa27f4ea5386304841317fedadca3fd1ab6dd33..db24539d57405253d26c4d4ebc3b6626045d0517 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <asm/proc-fns.h>
 
+#include <dt-bindings/clock/at91.h>
+
 #include "pmc.h"
 
 #define PMC_MAX_IDS 128
@@ -47,6 +49,82 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname,
 }
 EXPORT_SYMBOL_GPL(of_at91_get_clk_range);
 
+struct clk_hw *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data)
+{
+       unsigned int type = clkspec->args[0];
+       unsigned int idx = clkspec->args[1];
+       struct pmc_data *pmc_data = data;
+
+       switch (type) {
+       case PMC_TYPE_CORE:
+               if (idx < pmc_data->ncore)
+                       return pmc_data->chws[idx];
+               break;
+       case PMC_TYPE_SYSTEM:
+               if (idx < pmc_data->nsystem)
+                       return pmc_data->shws[idx];
+               break;
+       case PMC_TYPE_PERIPHERAL:
+               if (idx < pmc_data->nperiph)
+                       return pmc_data->phws[idx];
+               break;
+       case PMC_TYPE_GCK:
+               if (idx < pmc_data->ngck)
+                       return pmc_data->ghws[idx];
+               break;
+       default:
+               break;
+       }
+
+       pr_err("%s: invalid type (%u) or index (%u)\n", __func__, type, idx);
+
+       return ERR_PTR(-EINVAL);
+}
+
+void pmc_data_free(struct pmc_data *pmc_data)
+{
+       kfree(pmc_data->chws);
+       kfree(pmc_data->shws);
+       kfree(pmc_data->phws);
+       kfree(pmc_data->ghws);
+}
+
+struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
+                                  unsigned int nperiph, unsigned int ngck)
+{
+       struct pmc_data *pmc_data = kzalloc(sizeof(*pmc_data), GFP_KERNEL);
+
+       if (!pmc_data)
+               return NULL;
+
+       pmc_data->ncore = ncore;
+       pmc_data->chws = kcalloc(ncore, sizeof(struct clk_hw *), GFP_KERNEL);
+       if (!pmc_data->chws)
+               goto err;
+
+       pmc_data->nsystem = nsystem;
+       pmc_data->shws = kcalloc(nsystem, sizeof(struct clk_hw *), GFP_KERNEL);
+       if (!pmc_data->shws)
+               goto err;
+
+       pmc_data->nperiph = nperiph;
+       pmc_data->phws = kcalloc(nperiph, sizeof(struct clk_hw *), GFP_KERNEL);
+       if (!pmc_data->phws)
+               goto err;
+
+       pmc_data->ngck = ngck;
+       pmc_data->ghws = kcalloc(ngck, sizeof(struct clk_hw *), GFP_KERNEL);
+       if (!pmc_data->ghws)
+               goto err;
+
+       return pmc_data;
+
+err:
+       pmc_data_free(pmc_data);
+
+       return NULL;
+}
+
 #ifdef CONFIG_PM
 static struct regmap *pmcreg;
 
index d22b1fa9ecdce8fa621dc3d7eaa66a4580585911..672a79bda88c960d7655a600834705152f5a4eaf 100644 (file)
 
 extern spinlock_t pmc_pcr_lock;
 
+struct pmc_data {
+       unsigned int ncore;
+       struct clk_hw **chws;
+       unsigned int nsystem;
+       struct clk_hw **shws;
+       unsigned int nperiph;
+       struct clk_hw **phws;
+       unsigned int ngck;
+       struct clk_hw **ghws;
+};
+
 struct clk_range {
        unsigned long min;
        unsigned long max;
@@ -26,9 +37,157 @@ struct clk_range {
 
 #define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,}
 
+struct clk_master_layout {
+       u32 mask;
+       u8 pres_shift;
+};
+
+extern const struct clk_master_layout at91rm9200_master_layout;
+extern const struct clk_master_layout at91sam9x5_master_layout;
+
+struct clk_master_characteristics {
+       struct clk_range output;
+       u32 divisors[4];
+       u8 have_div3_pres;
+};
+
+struct clk_pll_layout {
+       u32 pllr_mask;
+       u16 mul_mask;
+       u8 mul_shift;
+};
+
+extern const struct clk_pll_layout at91rm9200_pll_layout;
+extern const struct clk_pll_layout at91sam9g45_pll_layout;
+extern const struct clk_pll_layout at91sam9g20_pllb_layout;
+extern const struct clk_pll_layout sama5d3_pll_layout;
+
+struct clk_pll_characteristics {
+       struct clk_range input;
+       int num_output;
+       struct clk_range *output;
+       u16 *icpll;
+       u8 *out;
+};
+
+struct clk_programmable_layout {
+       u8 pres_shift;
+       u8 css_mask;
+       u8 have_slck_mck;
+};
+
+extern const struct clk_programmable_layout at91rm9200_programmable_layout;
+extern const struct clk_programmable_layout at91sam9g45_programmable_layout;
+extern const struct clk_programmable_layout at91sam9x5_programmable_layout;
+
+#define ndck(a, s) (a[s - 1].id + 1)
+#define nck(a) (a[ARRAY_SIZE(a) - 1].id + 1)
+struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
+                                  unsigned int nperiph, unsigned int ngck);
+void pmc_data_free(struct pmc_data *pmc_data);
+
 int of_at91_get_clk_range(struct device_node *np, const char *propname,
                          struct clk_range *range);
 
+struct clk_hw *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data);
+
+struct clk_hw * __init
+at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name,
+                                const char *parent_name);
+
+struct clk_hw * __init
+at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name,
+                               const char *parent_name);
+
+struct clk_hw * __init
+at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
+                               const char *parent_name);
+
+struct clk_hw * __init
+at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
+                           const char *name, const char **parent_names,
+                           u8 num_parents, u8 id, bool pll_audio,
+                           const struct clk_range *range);
+
+struct clk_hw * __init
+at91_clk_register_h32mx(struct regmap *regmap, const char *name,
+                       const char *parent_name);
+
+struct clk_hw * __init
+at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
+                         const char * const *parent_names,
+                         unsigned int num_parents, u8 bus_id);
+
+struct clk_hw * __init
+at91_clk_register_main_rc_osc(struct regmap *regmap, const char *name,
+                             u32 frequency, u32 accuracy);
+struct clk_hw * __init
+at91_clk_register_main_osc(struct regmap *regmap, const char *name,
+                          const char *parent_name, bool bypass);
+struct clk_hw * __init
+at91_clk_register_rm9200_main(struct regmap *regmap,
+                             const char *name,
+                             const char *parent_name);
+struct clk_hw * __init
+at91_clk_register_sam9x5_main(struct regmap *regmap, const char *name,
+                             const char **parent_names, int num_parents);
+
+struct clk_hw * __init
+at91_clk_register_master(struct regmap *regmap, const char *name,
+                        int num_parents, const char **parent_names,
+                        const struct clk_master_layout *layout,
+                        const struct clk_master_characteristics *characteristics);
+
+struct clk_hw * __init
+at91_clk_register_peripheral(struct regmap *regmap, const char *name,
+                            const char *parent_name, u32 id);
+struct clk_hw * __init
+at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
+                                   const char *name, const char *parent_name,
+                                   u32 id, const struct clk_range *range);
+
+struct clk_hw * __init
+at91_clk_register_pll(struct regmap *regmap, const char *name,
+                     const char *parent_name, u8 id,
+                     const struct clk_pll_layout *layout,
+                     const struct clk_pll_characteristics *characteristics);
+struct clk_hw * __init
+at91_clk_register_plldiv(struct regmap *regmap, const char *name,
+                        const char *parent_name);
+
+struct clk_hw * __init
+at91_clk_register_programmable(struct regmap *regmap, const char *name,
+                              const char **parent_names, u8 num_parents, u8 id,
+                              const struct clk_programmable_layout *layout);
+
+struct clk_hw * __init
+at91_clk_register_sam9260_slow(struct regmap *regmap,
+                              const char *name,
+                              const char **parent_names,
+                              int num_parents);
+
+struct clk_hw * __init
+at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
+                           const char **parent_names, u8 num_parents);
+
+struct clk_hw * __init
+at91_clk_register_system(struct regmap *regmap, const char *name,
+                        const char *parent_name, u8 id);
+
+struct clk_hw * __init
+at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
+                           const char **parent_names, u8 num_parents);
+struct clk_hw * __init
+at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
+                            const char *parent_name);
+struct clk_hw * __init
+at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
+                           const char *parent_name, const u32 *divisors);
+
+struct clk_hw * __init
+at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
+                      const char *name, const char *parent_name);
+
 #ifdef CONFIG_PM
 void pmc_register_id(u8 id);
 void pmc_register_pck(u8 pck);
diff --git a/drivers/clk/at91/sama5d2.c b/drivers/clk/at91/sama5d2.c
new file mode 100644 (file)
index 0000000..d69ad96
--- /dev/null
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/at91.h>
+
+#include "pmc.h"
+
+static const struct clk_master_characteristics mck_characteristics = {
+       .output = { .min = 124000000, .max = 166000000 },
+       .divisors = { 1, 2, 4, 3 },
+};
+
+static u8 plla_out[] = { 0 };
+
+static u16 plla_icpll[] = { 0 };
+
+static struct clk_range plla_outputs[] = {
+       { .min = 600000000, .max = 1200000000 },
+};
+
+static const struct clk_pll_characteristics plla_characteristics = {
+       .input = { .min = 12000000, .max = 12000000 },
+       .num_output = ARRAY_SIZE(plla_outputs),
+       .output = plla_outputs,
+       .icpll = plla_icpll,
+       .out = plla_out,
+};
+
+static const struct {
+       char *n;
+       char *p;
+       u8 id;
+} sama5d2_systemck[] = {
+       { .n = "ddrck", .p = "masterck", .id = 2 },
+       { .n = "lcdck", .p = "masterck", .id = 3 },
+       { .n = "uhpck", .p = "usbck",    .id = 6 },
+       { .n = "udpck", .p = "usbck",    .id = 7 },
+       { .n = "pck0",  .p = "prog0",    .id = 8 },
+       { .n = "pck1",  .p = "prog1",    .id = 9 },
+       { .n = "pck2",  .p = "prog2",    .id = 10 },
+       { .n = "iscck", .p = "masterck", .id = 18 },
+};
+
+static const struct {
+       char *n;
+       u8 id;
+       struct clk_range r;
+} sama5d2_periph32ck[] = {
+       { .n = "macb0_clk",   .id = 5,  .r = { .min = 0, .max = 83000000 }, },
+       { .n = "tdes_clk",    .id = 11, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "matrix1_clk", .id = 14, },
+       { .n = "hsmc_clk",    .id = 17, },
+       { .n = "pioA_clk",    .id = 18, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "flx0_clk",    .id = 19, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "flx1_clk",    .id = 20, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "flx2_clk",    .id = 21, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "flx3_clk",    .id = 22, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "flx4_clk",    .id = 23, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "uart0_clk",   .id = 24, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "uart1_clk",   .id = 25, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "uart2_clk",   .id = 26, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "uart3_clk",   .id = 27, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "uart4_clk",   .id = 28, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "twi0_clk",    .id = 29, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "twi1_clk",    .id = 30, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "spi0_clk",    .id = 33, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "spi1_clk",    .id = 34, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "tcb0_clk",    .id = 35, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "tcb1_clk",    .id = 36, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "pwm_clk",     .id = 38, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "adc_clk",     .id = 40, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "uhphs_clk",   .id = 41, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "udphs_clk",   .id = 42, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "ssc0_clk",    .id = 43, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "ssc1_clk",    .id = 44, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "trng_clk",    .id = 47, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "pdmic_clk",   .id = 48, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "securam_clk", .id = 51, },
+       { .n = "i2s0_clk",    .id = 54, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "i2s1_clk",    .id = 55, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "can0_clk",    .id = 56, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "can1_clk",    .id = 57, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "classd_clk",  .id = 59, .r = { .min = 0, .max = 83000000 }, },
+};
+
+static const struct {
+       char *n;
+       u8 id;
+} sama5d2_periphck[] = {
+       { .n = "dma0_clk",    .id = 6, },
+       { .n = "dma1_clk",    .id = 7, },
+       { .n = "aes_clk",     .id = 9, },
+       { .n = "aesb_clk",    .id = 10, },
+       { .n = "sha_clk",     .id = 12, },
+       { .n = "mpddr_clk",   .id = 13, },
+       { .n = "matrix0_clk", .id = 15, },
+       { .n = "sdmmc0_hclk", .id = 31, },
+       { .n = "sdmmc1_hclk", .id = 32, },
+       { .n = "lcdc_clk",    .id = 45, },
+       { .n = "isc_clk",     .id = 46, },
+       { .n = "qspi0_clk",   .id = 52, },
+       { .n = "qspi1_clk",   .id = 53, },
+};
+
+static const struct {
+       char *n;
+       u8 id;
+       struct clk_range r;
+       bool pll;
+} sama5d2_gck[] = {
+       { .n = "sdmmc0_gclk", .id = 31, },
+       { .n = "sdmmc1_gclk", .id = 32, },
+       { .n = "tcb0_gclk",   .id = 35, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "tcb1_gclk",   .id = 36, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "pwm_gclk",    .id = 38, .r = { .min = 0, .max = 83000000 }, },
+       { .n = "isc_gclk",    .id = 46, },
+       { .n = "pdmic_gclk",  .id = 48, },
+       { .n = "i2s0_gclk",   .id = 54, .pll = true },
+       { .n = "i2s1_gclk",   .id = 55, .pll = true },
+       { .n = "can0_gclk",   .id = 56, .r = { .min = 0, .max = 80000000 }, },
+       { .n = "can1_gclk",   .id = 57, .r = { .min = 0, .max = 80000000 }, },
+       { .n = "classd_gclk", .id = 59, .r = { .min = 0, .max = 100000000 },
+         .pll = true },
+};
+
+static void __init sama5d2_pmc_setup(struct device_node *np)
+{
+       struct clk_range range = CLK_RANGE(0, 0);
+       const char *slck_name, *mainxtal_name;
+       struct pmc_data *sama5d2_pmc;
+       const char *parent_names[6];
+       struct regmap *regmap, *regmap_sfr;
+       struct clk_hw *hw;
+       int i;
+       bool bypass;
+
+       i = of_property_match_string(np, "clock-names", "slow_clk");
+       if (i < 0)
+               return;
+
+       slck_name = of_clk_get_parent_name(np, i);
+
+       i = of_property_match_string(np, "clock-names", "main_xtal");
+       if (i < 0)
+               return;
+       mainxtal_name = of_clk_get_parent_name(np, i);
+
+       regmap = syscon_node_to_regmap(np);
+       if (IS_ERR(regmap))
+               return;
+
+       sama5d2_pmc = pmc_data_allocate(PMC_I2S1_MUX + 1,
+                                       nck(sama5d2_systemck),
+                                       nck(sama5d2_periph32ck),
+                                       nck(sama5d2_gck));
+       if (!sama5d2_pmc)
+               return;
+
+       hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
+                                          100000000);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       bypass = of_property_read_bool(np, "atmel,osc-bypass");
+
+       hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+                                       bypass);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       parent_names[0] = "main_rc_osc";
+       parent_names[1] = "main_osc";
+       hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       sama5d2_pmc->chws[PMC_MAIN] = hw;
+
+       hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
+                                  &sama5d3_pll_layout, &plla_characteristics);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack");
+       if (IS_ERR(hw))
+               goto err_free;
+
+       hw = at91_clk_register_audio_pll_frac(regmap, "audiopll_fracck",
+                                             "mainck");
+       if (IS_ERR(hw))
+               goto err_free;
+
+       hw = at91_clk_register_audio_pll_pad(regmap, "audiopll_padck",
+                                            "audiopll_fracck");
+       if (IS_ERR(hw))
+               goto err_free;
+
+       hw = at91_clk_register_audio_pll_pmc(regmap, "audiopll_pmcck",
+                                            "audiopll_fracck");
+       if (IS_ERR(hw))
+               goto err_free;
+
+       regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
+       if (IS_ERR(regmap_sfr))
+               regmap_sfr = NULL;
+
+       hw = at91_clk_register_utmi(regmap, regmap_sfr, "utmick", "mainck");
+       if (IS_ERR(hw))
+               goto err_free;
+
+       sama5d2_pmc->chws[PMC_UTMI] = hw;
+
+       parent_names[0] = slck_name;
+       parent_names[1] = "mainck";
+       parent_names[2] = "plladivck";
+       parent_names[3] = "utmick";
+       hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
+                                     &at91sam9x5_master_layout,
+                                     &mck_characteristics);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       sama5d2_pmc->chws[PMC_MCK] = hw;
+
+       hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck");
+       if (IS_ERR(hw))
+               goto err_free;
+
+       sama5d2_pmc->chws[PMC_MCK2] = hw;
+
+       parent_names[0] = "plladivck";
+       parent_names[1] = "utmick";
+       hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       parent_names[0] = slck_name;
+       parent_names[1] = "mainck";
+       parent_names[2] = "plladivck";
+       parent_names[3] = "utmick";
+       parent_names[4] = "mck";
+       for (i = 0; i < 3; i++) {
+               char name[6];
+
+               snprintf(name, sizeof(name), "prog%d", i);
+
+               hw = at91_clk_register_programmable(regmap, name,
+                                                   parent_names, 5, i,
+                                                   &at91sam9x5_programmable_layout);
+               if (IS_ERR(hw))
+                       goto err_free;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(sama5d2_systemck); i++) {
+               hw = at91_clk_register_system(regmap, sama5d2_systemck[i].n,
+                                             sama5d2_systemck[i].p,
+                                             sama5d2_systemck[i].id);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               sama5d2_pmc->shws[sama5d2_systemck[i].id] = hw;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(sama5d2_periphck); i++) {
+               hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+                                                        sama5d2_periphck[i].n,
+                                                        "masterck",
+                                                        sama5d2_periphck[i].id,
+                                                        &range);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               sama5d2_pmc->phws[sama5d2_periphck[i].id] = hw;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(sama5d2_periph32ck); i++) {
+               hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+                                                        sama5d2_periph32ck[i].n,
+                                                        "h32mxck",
+                                                        sama5d2_periph32ck[i].id,
+                                                        &sama5d2_periph32ck[i].r);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               sama5d2_pmc->phws[sama5d2_periph32ck[i].id] = hw;
+       }
+
+       parent_names[0] = slck_name;
+       parent_names[1] = "mainck";
+       parent_names[2] = "plladivck";
+       parent_names[3] = "utmick";
+       parent_names[4] = "mck";
+       parent_names[5] = "audiopll_pmcck";
+       for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) {
+               hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
+                                                sama5d2_gck[i].n,
+                                                parent_names, 6,
+                                                sama5d2_gck[i].id,
+                                                sama5d2_gck[i].pll,
+                                                &sama5d2_gck[i].r);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               sama5d2_pmc->ghws[sama5d2_gck[i].id] = hw;
+       }
+
+       if (regmap_sfr) {
+               parent_names[0] = "i2s0_clk";
+               parent_names[1] = "i2s0_gclk";
+               hw = at91_clk_i2s_mux_register(regmap_sfr, "i2s0_muxclk",
+                                              parent_names, 2, 0);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               sama5d2_pmc->chws[PMC_I2S0_MUX] = hw;
+
+               parent_names[0] = "i2s1_clk";
+               parent_names[1] = "i2s1_gclk";
+               hw = at91_clk_i2s_mux_register(regmap_sfr, "i2s1_muxclk",
+                                              parent_names, 2, 1);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               sama5d2_pmc->chws[PMC_I2S1_MUX] = hw;
+       }
+
+       of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama5d2_pmc);
+
+       return;
+
+err_free:
+       pmc_data_free(sama5d2_pmc);
+}
+CLK_OF_DECLARE_DRIVER(sama5d2_pmc, "atmel,sama5d2-pmc", sama5d2_pmc_setup);
diff --git a/drivers/clk/at91/sama5d4.c b/drivers/clk/at91/sama5d4.c
new file mode 100644 (file)
index 0000000..e358be7
--- /dev/null
@@ -0,0 +1,264 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/at91.h>
+
+#include "pmc.h"
+
+static const struct clk_master_characteristics mck_characteristics = {
+       .output = { .min = 125000000, .max = 200000000 },
+       .divisors = { 1, 2, 4, 3 },
+};
+
+static u8 plla_out[] = { 0 };
+
+static u16 plla_icpll[] = { 0 };
+
+static struct clk_range plla_outputs[] = {
+       { .min = 600000000, .max = 1200000000 },
+};
+
+static const struct clk_pll_characteristics plla_characteristics = {
+       .input = { .min = 12000000, .max = 12000000 },
+       .num_output = ARRAY_SIZE(plla_outputs),
+       .output = plla_outputs,
+       .icpll = plla_icpll,
+       .out = plla_out,
+};
+
+static const struct {
+       char *n;
+       char *p;
+       u8 id;
+} sama5d4_systemck[] = {
+       { .n = "ddrck", .p = "masterck", .id = 2 },
+       { .n = "lcdck", .p = "masterck", .id = 3 },
+       { .n = "smdck", .p = "smdclk",   .id = 4 },
+       { .n = "uhpck", .p = "usbck",    .id = 6 },
+       { .n = "udpck", .p = "usbck",    .id = 7 },
+       { .n = "pck0",  .p = "prog0",    .id = 8 },
+       { .n = "pck1",  .p = "prog1",    .id = 9 },
+       { .n = "pck2",  .p = "prog2",    .id = 10 },
+};
+
+static const struct {
+       char *n;
+       u8 id;
+} sama5d4_periph32ck[] = {
+       { .n = "pioD_clk", .id = 5 },
+       { .n = "usart0_clk", .id = 6 },
+       { .n = "usart1_clk", .id = 7 },
+       { .n = "icm_clk", .id = 9 },
+       { .n = "aes_clk", .id = 12 },
+       { .n = "tdes_clk", .id = 14 },
+       { .n = "sha_clk", .id = 15 },
+       { .n = "matrix1_clk", .id = 17 },
+       { .n = "hsmc_clk", .id = 22 },
+       { .n = "pioA_clk", .id = 23 },
+       { .n = "pioB_clk", .id = 24 },
+       { .n = "pioC_clk", .id = 25 },
+       { .n = "pioE_clk", .id = 26 },
+       { .n = "uart0_clk", .id = 27 },
+       { .n = "uart1_clk", .id = 28 },
+       { .n = "usart2_clk", .id = 29 },
+       { .n = "usart3_clk", .id = 30 },
+       { .n = "usart4_clk", .id = 31 },
+       { .n = "twi0_clk", .id = 32 },
+       { .n = "twi1_clk", .id = 33 },
+       { .n = "twi2_clk", .id = 34 },
+       { .n = "mci0_clk", .id = 35 },
+       { .n = "mci1_clk", .id = 36 },
+       { .n = "spi0_clk", .id = 37 },
+       { .n = "spi1_clk", .id = 38 },
+       { .n = "spi2_clk", .id = 39 },
+       { .n = "tcb0_clk", .id = 40 },
+       { .n = "tcb1_clk", .id = 41 },
+       { .n = "tcb2_clk", .id = 42 },
+       { .n = "pwm_clk", .id = 43 },
+       { .n = "adc_clk", .id = 44 },
+       { .n = "dbgu_clk", .id = 45 },
+       { .n = "uhphs_clk", .id = 46 },
+       { .n = "udphs_clk", .id = 47 },
+       { .n = "ssc0_clk", .id = 48 },
+       { .n = "ssc1_clk", .id = 49 },
+       { .n = "trng_clk", .id = 53 },
+       { .n = "macb0_clk", .id = 54 },
+       { .n = "macb1_clk", .id = 55 },
+       { .n = "fuse_clk", .id = 57 },
+       { .n = "securam_clk", .id = 59 },
+       { .n = "smd_clk", .id = 61 },
+       { .n = "twi3_clk", .id = 62 },
+       { .n = "catb_clk", .id = 63 },
+};
+
+static const struct {
+       char *n;
+       u8 id;
+} sama5d4_periphck[] = {
+       { .n = "dma0_clk", .id = 8 },
+       { .n = "cpkcc_clk", .id = 10 },
+       { .n = "aesb_clk", .id = 13 },
+       { .n = "mpddr_clk", .id = 16 },
+       { .n = "matrix0_clk", .id = 18 },
+       { .n = "vdec_clk", .id = 19 },
+       { .n = "dma1_clk", .id = 50 },
+       { .n = "lcdc_clk", .id = 51 },
+       { .n = "isi_clk", .id = 52 },
+};
+
+static void __init sama5d4_pmc_setup(struct device_node *np)
+{
+       struct clk_range range = CLK_RANGE(0, 0);
+       const char *slck_name, *mainxtal_name;
+       struct pmc_data *sama5d4_pmc;
+       const char *parent_names[5];
+       struct regmap *regmap;
+       struct clk_hw *hw;
+       int i;
+       bool bypass;
+
+       i = of_property_match_string(np, "clock-names", "slow_clk");
+       if (i < 0)
+               return;
+
+       slck_name = of_clk_get_parent_name(np, i);
+
+       i = of_property_match_string(np, "clock-names", "main_xtal");
+       if (i < 0)
+               return;
+       mainxtal_name = of_clk_get_parent_name(np, i);
+
+       regmap = syscon_node_to_regmap(np);
+       if (IS_ERR(regmap))
+               return;
+
+       sama5d4_pmc = pmc_data_allocate(PMC_MCK2 + 1,
+                                       nck(sama5d4_systemck),
+                                       nck(sama5d4_periph32ck), 0);
+       if (!sama5d4_pmc)
+               return;
+
+       hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
+                                          100000000);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       bypass = of_property_read_bool(np, "atmel,osc-bypass");
+
+       hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+                                       bypass);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       parent_names[0] = "main_rc_osc";
+       parent_names[1] = "main_osc";
+       hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
+                                  &sama5d3_pll_layout, &plla_characteristics);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack");
+       if (IS_ERR(hw))
+               goto err_free;
+
+       hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
+       if (IS_ERR(hw))
+               goto err_free;
+
+       sama5d4_pmc->chws[PMC_UTMI] = hw;
+
+       parent_names[0] = slck_name;
+       parent_names[1] = "mainck";
+       parent_names[2] = "plladivck";
+       parent_names[3] = "utmick";
+       hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
+                                     &at91sam9x5_master_layout,
+                                     &mck_characteristics);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       sama5d4_pmc->chws[PMC_MCK] = hw;
+
+       hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck");
+       if (IS_ERR(hw))
+               goto err_free;
+
+       sama5d4_pmc->chws[PMC_MCK2] = hw;
+
+       parent_names[0] = "plladivck";
+       parent_names[1] = "utmick";
+       hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       parent_names[0] = "plladivck";
+       parent_names[1] = "utmick";
+       hw = at91sam9x5_clk_register_smd(regmap, "smdclk", parent_names, 2);
+       if (IS_ERR(hw))
+               goto err_free;
+
+       parent_names[0] = slck_name;
+       parent_names[1] = "mainck";
+       parent_names[2] = "plladivck";
+       parent_names[3] = "utmick";
+       parent_names[4] = "mck";
+       for (i = 0; i < 3; i++) {
+               char name[6];
+
+               snprintf(name, sizeof(name), "prog%d", i);
+
+               hw = at91_clk_register_programmable(regmap, name,
+                                                   parent_names, 5, i,
+                                                   &at91sam9x5_programmable_layout);
+               if (IS_ERR(hw))
+                       goto err_free;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(sama5d4_systemck); i++) {
+               hw = at91_clk_register_system(regmap, sama5d4_systemck[i].n,
+                                             sama5d4_systemck[i].p,
+                                             sama5d4_systemck[i].id);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               sama5d4_pmc->shws[sama5d4_systemck[i].id] = hw;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(sama5d4_periphck); i++) {
+               hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+                                                        sama5d4_periphck[i].n,
+                                                        "masterck",
+                                                        sama5d4_periphck[i].id,
+                                                        &range);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               sama5d4_pmc->phws[sama5d4_periphck[i].id] = hw;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(sama5d4_periph32ck); i++) {
+               hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+                                                        sama5d4_periph32ck[i].n,
+                                                        "h32mxck",
+                                                        sama5d4_periph32ck[i].id,
+                                                        &range);
+               if (IS_ERR(hw))
+                       goto err_free;
+
+               sama5d4_pmc->phws[sama5d4_periph32ck[i].id] = hw;
+       }
+
+       of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama5d4_pmc);
+
+       return;
+
+err_free:
+       pmc_data_free(sama5d4_pmc);
+}
+CLK_OF_DECLARE_DRIVER(sama5d4_pmc, "atmel,sama5d4-pmc", sama5d4_pmc_setup);
index 25d8c240ddfb0f5d2fc61847f11b35badc69d441..c68dada973168474ff063b2eba98a11bfec5556e 100644 (file)
@@ -301,13 +301,13 @@ static void __init of_axs10x_pll_clk_setup(struct device_node *node)
 
        ret = clk_hw_register(NULL, &pll_clk->hw);
        if (ret) {
-               pr_err("failed to register %s clock\n", node->name);
+               pr_err("failed to register %pOFn clock\n", node);
                goto err_unmap_lock;
        }
 
        ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &pll_clk->hw);
        if (ret) {
-               pr_err("failed to add hw provider for %s clock\n", node->name);
+               pr_err("failed to add hw provider for %pOFn clock\n", node);
                goto err_unregister_clk;
        }
 
index 281f4322355c135eded2fc5533a54498a0f0f49f..e65eeef9cbaf16ad3ba4238f0f17a12e70eb6915 100644 (file)
@@ -808,29 +808,29 @@ void __init kona_dt_ccu_setup(struct ccu_data *ccu,
 
        ret = of_address_to_resource(node, 0, &res);
        if (ret) {
-               pr_err("%s: no valid CCU registers found for %s\n", __func__,
-                       node->name);
+               pr_err("%s: no valid CCU registers found for %pOFn\n", __func__,
+                       node);
                goto out_err;
        }
 
        range = resource_size(&res);
        if (range > (resource_size_t)U32_MAX) {
-               pr_err("%s: address range too large for %s\n", __func__,
-                       node->name);
+               pr_err("%s: address range too large for %pOFn\n", __func__,
+                       node);
                goto out_err;
        }
 
        ccu->range = (u32)range;
 
        if (!ccu_data_valid(ccu)) {
-               pr_err("%s: ccu data not valid for %s\n", __func__, node->name);
+               pr_err("%s: ccu data not valid for %pOFn\n", __func__, node);
                goto out_err;
        }
 
        ccu->base = ioremap(res.start, ccu->range);
        if (!ccu->base) {
-               pr_err("%s: unable to map CCU registers for %s\n", __func__,
-                       node->name);
+               pr_err("%s: unable to map CCU registers for %pOFn\n", __func__,
+                       node);
                goto out_err;
        }
        ccu->node = of_node_get(node);
@@ -848,16 +848,16 @@ void __init kona_dt_ccu_setup(struct ccu_data *ccu,
 
        ret = of_clk_add_hw_provider(node, of_clk_kona_onecell_get, ccu);
        if (ret) {
-               pr_err("%s: error adding ccu %s as provider (%d)\n", __func__,
-                               node->name, ret);
+               pr_err("%s: error adding ccu %pOFn as provider (%d)\n", __func__,
+                               node, ret);
                goto out_err;
        }
 
        if (!kona_ccu_init(ccu))
-               pr_err("Broadcom %s initialization had errors\n", node->name);
+               pr_err("Broadcom %pOFn initialization had errors\n", node);
 
        return;
 out_err:
        kona_ccu_teardown(ccu);
-       pr_err("Broadcom %s setup aborted\n", node->name);
+       pr_err("Broadcom %pOFn setup aborted\n", node);
 }
index 44b5441571210468e99cce9d9269dfc57c4bca46..d571a00b5282d2b18774efc21c3d6aea0c660e09 100644 (file)
@@ -281,7 +281,7 @@ static void __init asm9260_acc_init(struct device_node *np)
 
        base = of_io_request_and_map(np, 0, np->name);
        if (IS_ERR(base))
-               panic("%s: unable to map resource", np->name);
+               panic("%pOFn: unable to map resource", np);
 
        /* register pll */
        rate = (ioread32(base + HW_SYSPLLCTRL) & 0xffff) * 1000000;
@@ -292,7 +292,7 @@ static void __init asm9260_acc_init(struct device_node *np)
                        ref_clk, 0, rate, accuracy);
 
        if (IS_ERR(hw))
-               panic("%s: can't register REFCLK. Check DT!", np->name);
+               panic("%pOFn: can't register REFCLK. Check DT!", np);
 
        for (n = 0; n < ARRAY_SIZE(asm9260_mux_clks); n++) {
                const struct asm9260_mux_clock *mc = &asm9260_mux_clks[n];
index 6904ed6da504b0690b3e0a3525370848d080f566..6a7118d4250a6a0409a1d080936e1d1e74bbfb42 100644 (file)
  */
 
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/device.h>
 #include <linux/export.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks,
+                                       struct clk_bulk_data *clks)
+{
+       int ret;
+       int i;
+
+       for (i = 0; i < num_clks; i++)
+               clks[i].clk = NULL;
+
+       for (i = 0; i < num_clks; i++) {
+               clks[i].clk = of_clk_get(np, i);
+               if (IS_ERR(clks[i].clk)) {
+                       ret = PTR_ERR(clks[i].clk);
+                       pr_err("%pOF: Failed to get clk index: %d ret: %d\n",
+                              np, i, ret);
+                       clks[i].clk = NULL;
+                       goto err;
+               }
+       }
+
+       return 0;
+
+err:
+       clk_bulk_put(i, clks);
+
+       return ret;
+}
+
+static int __must_check of_clk_bulk_get_all(struct device_node *np,
+                                           struct clk_bulk_data **clks)
+{
+       struct clk_bulk_data *clk_bulk;
+       int num_clks;
+       int ret;
+
+       num_clks = of_clk_get_parent_count(np);
+       if (!num_clks)
+               return 0;
+
+       clk_bulk = kmalloc_array(num_clks, sizeof(*clk_bulk), GFP_KERNEL);
+       if (!clk_bulk)
+               return -ENOMEM;
+
+       ret = of_clk_bulk_get(np, num_clks, clk_bulk);
+       if (ret) {
+               kfree(clk_bulk);
+               return ret;
+       }
+
+       *clks = clk_bulk;
+
+       return num_clks;
+}
 
 void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)
 {
@@ -59,6 +116,29 @@ err:
 }
 EXPORT_SYMBOL(clk_bulk_get);
 
+void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks)
+{
+       if (IS_ERR_OR_NULL(clks))
+               return;
+
+       clk_bulk_put(num_clks, clks);
+
+       kfree(clks);
+}
+EXPORT_SYMBOL(clk_bulk_put_all);
+
+int __must_check clk_bulk_get_all(struct device *dev,
+                                 struct clk_bulk_data **clks)
+{
+       struct device_node *np = dev_of_node(dev);
+
+       if (!np)
+               return 0;
+
+       return of_clk_bulk_get_all(np, clks);
+}
+EXPORT_SYMBOL(clk_bulk_get_all);
+
 #ifdef CONFIG_HAVE_CLK_PREPARE
 
 /**
index 0a7e7d5a750605c5be12d953ac912f3fb9105962..23c9326ea48c5ef0bc3b5ef00bf9fbbd67e166c8 100644 (file)
@@ -669,8 +669,8 @@ static int cdce925_probe(struct i2c_client *client,
 
        /* Register PLL clocks */
        for (i = 0; i < data->chip_info->num_plls; ++i) {
-               pll_clk_name[i] = kasprintf(GFP_KERNEL, "%s.pll%d",
-                       client->dev.of_node->name, i);
+               pll_clk_name[i] = kasprintf(GFP_KERNEL, "%pOFn.pll%d",
+                       client->dev.of_node, i);
                init.name = pll_clk_name[i];
                data->pll[i].chip = data;
                data->pll[i].hw.init = &init;
@@ -703,6 +703,7 @@ static int cdce925_probe(struct i2c_client *client,
                                0x12 + (i*CDCE925_OFFSET_PLL),
                                0x07, value & 0x07);
                }
+               of_node_put(np_output);
        }
 
        /* Register output clock Y1 */
@@ -710,7 +711,7 @@ static int cdce925_probe(struct i2c_client *client,
        init.flags = 0;
        init.num_parents = 1;
        init.parent_names = &parent_name; /* Mux Y1 to input */
-       init.name = kasprintf(GFP_KERNEL, "%s.Y1", client->dev.of_node->name);
+       init.name = kasprintf(GFP_KERNEL, "%pOFn.Y1", client->dev.of_node);
        data->clk[0].chip = data;
        data->clk[0].hw.init = &init;
        data->clk[0].index = 0;
@@ -727,8 +728,8 @@ static int cdce925_probe(struct i2c_client *client,
        init.flags = CLK_SET_RATE_PARENT;
        init.num_parents = 1;
        for (i = 1; i < data->chip_info->num_outputs; ++i) {
-               init.name = kasprintf(GFP_KERNEL, "%s.Y%d",
-                       client->dev.of_node->name, i+1);
+               init.name = kasprintf(GFP_KERNEL, "%pOFn.Y%d",
+                       client->dev.of_node, i+1);
                data->clk[i].chip = data;
                data->clk[i].hw.init = &init;
                data->clk[i].index = i;
index d854e26a8ddbca3dfb96aad123e974f2175cc455..12c87457eca1e73d4c568bc34a98296c961c6c3c 100644 (file)
@@ -70,6 +70,30 @@ int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
 }
 EXPORT_SYMBOL_GPL(devm_clk_bulk_get);
 
+int __must_check devm_clk_bulk_get_all(struct device *dev,
+                                      struct clk_bulk_data **clks)
+{
+       struct clk_bulk_devres *devres;
+       int ret;
+
+       devres = devres_alloc(devm_clk_bulk_release,
+                             sizeof(*devres), GFP_KERNEL);
+       if (!devres)
+               return -ENOMEM;
+
+       ret = clk_bulk_get_all(dev, &devres->clks);
+       if (ret > 0) {
+               *clks = devres->clks;
+               devres->num_clks = ret;
+               devres_add(dev, devres);
+       } else {
+               devres_free(devres);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all);
+
 static int devm_clk_match(struct device *dev, void *res, void *data)
 {
        struct clk **c = res;
index 20724abd38bd132205713cce2e7960324652d12b..ef0ca9414f371bc3275b7afce529029e10b49f68 100644 (file)
@@ -158,14 +158,14 @@ static struct clk *_of_fixed_factor_clk_setup(struct device_node *node)
        int ret;
 
        if (of_property_read_u32(node, "clock-div", &div)) {
-               pr_err("%s Fixed factor clock <%s> must have a clock-div property\n",
-                       __func__, node->name);
+               pr_err("%s Fixed factor clock <%pOFn> must have a clock-div property\n",
+                       __func__, node);
                return ERR_PTR(-EIO);
        }
 
        if (of_property_read_u32(node, "clock-mult", &mult)) {
-               pr_err("%s Fixed factor clock <%s> must have a clock-mult property\n",
-                       __func__, node->name);
+               pr_err("%s Fixed factor clock <%pOFn> must have a clock-mult property\n",
+                       __func__, node);
                return ERR_PTR(-EIO);
        }
 
index b5c46b3f8764d491da0f8586de8b18eb6d6f4527..6d6475c32ee51612df97f7fcce8c952a004ccdeb 100644 (file)
@@ -200,6 +200,7 @@ static int of_fixed_clk_remove(struct platform_device *pdev)
 {
        struct clk *clk = platform_get_drvdata(pdev);
 
+       of_clk_del_provider(pdev->dev.of_node);
        clk_unregister_fixed_rate(clk);
 
        return 0;
index 40af4fbab4d23f24acda1ab07fe1df887131c243..6a43ce420492f143be8eee203633d2faa2b7942e 100644 (file)
@@ -233,11 +233,11 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
        if (IS_ERR(gpiod)) {
                ret = PTR_ERR(gpiod);
                if (ret == -EPROBE_DEFER)
-                       pr_debug("%s: %s: GPIOs not yet available, retry later\n",
-                                       node->name, __func__);
+                       pr_debug("%pOFn: %s: GPIOs not yet available, retry later\n",
+                                       node, __func__);
                else
-                       pr_err("%s: %s: Can't get '%s' named GPIO property\n",
-                                       node->name, __func__,
+                       pr_err("%pOFn: %s: Can't get '%s' named GPIO property\n",
+                                       node, __func__,
                                        gpio_name);
                return ret;
        }
index c4ee280f454d9213b2bd1a82ac576e7fd790fb42..a47c2b600f20c188fde5c037321afe960dbcd7d9 100644 (file)
@@ -390,13 +390,13 @@ static void __init of_hsdk_pll_clk_setup(struct device_node *node)
 
        ret = clk_hw_register(NULL, &pll_clk->hw);
        if (ret) {
-               pr_err("failed to register %s clock\n", node->name);
+               pr_err("failed to register %pOFn clock\n", node);
                goto err_unmap_spec_regs;
        }
 
        ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &pll_clk->hw);
        if (ret) {
-               pr_err("failed to add hw provider for %s clock\n", node->name);
+               pr_err("failed to add hw provider for %pOFn clock\n", node);
                goto err_unmap_spec_regs;
        }
 
index eb953d3b0b69bef048312fe9b6ec3c2678d815bb..02551fe4b87c5461c69d88a66b5b2f5b8fefbd6d 100644 (file)
@@ -1,24 +1,9 @@
-/*
- * clk-max77686.c - Clock driver for Maxim 77686/MAX77802
- *
- * Copyright (C) 2012 Samsung Electornics
- * Jonghwa Lee <jonghwa3.lee@samsung.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// clk-max77686.c - Clock driver for Maxim 77686/MAX77802
+//
+// Copyright (C) 2012 Samsung Electornics
+// Jonghwa Lee <jonghwa3.lee@samsung.com>
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
index 13ad6d1e509082f12b0466acb127c3cffc858cba..84a24875c6298a3e6ee1ba9688bcef826056e3ca 100644 (file)
@@ -97,8 +97,8 @@ static void __init nomadik_src_init(void)
        }
        src_base = of_iomap(np, 0);
        if (!src_base) {
-               pr_err("%s: must have src parent node with REGS (%s)\n",
-                      __func__, np->name);
+               pr_err("%s: must have src parent node with REGS (%pOFn)\n",
+                      __func__, np);
                return;
        }
 
index c5edf8f2fd1969337b7803ef96884ee9164495fb..27a86b7a34dbf64df553ac8283904310cc2da24c 100644 (file)
@@ -549,7 +549,7 @@ static void __init npcm7xx_clk_init(struct device_node *clk_np)
 
        ret = of_address_to_resource(clk_np, 0, &res);
        if (ret) {
-               pr_err("%s: failed to get resource, ret %d\n", clk_np->name,
+               pr_err("%