Selaa lähdekoodia

Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

Pull clk updates from Stephen Boyd:
 "This time we've got one core change to introduce a bulk clk_get API,
  some new clk drivers and updates for old ones. The diff is pretty
  spread out across a handful of different SoC clk drivers for Broadcom,
  TI, Qualcomm, Renesas, Rockchip, Samsung, and Allwinner, mostly due to
  the introduction of new drivers.

  Core:
   - New clk bulk get APIs
   - Clk divider APIs gained the ability to consider a different parent
     than the current one

  New Drivers:
   - Renesas r8a779{0,1,2,4} CPG/MSSR
   - TI Keystone SCI firmware controlled clks and OMAP4 clkctrl
   - Qualcomm IPQ8074 SoCs
   - Cortina Systems Gemini (SL3516/CS3516)
   - Rockchip rk3128 SoCs
   - Allwinner A83T clk control units
   - Broadcom Stingray SoCs
   - CPU clks for Mediatek MT8173/MT2701/MT7623 SoCs

  Removed Drivers:
   - Old non-DT version of the Realview clk driver

  Updates:
   - Renesas Kconfig/Makefile cleanups
   - Amlogic CEC EE clk support
   - Improved Armada 7K/8K cp110 clk support
   - Rockchip clk id exposing, critical clk markings
   - Samsung converted to clk_hw registration APIs
   - Fixes for Samsung exynos5420 audio clks
   - USB2 clks for Hisilicon hi3798cv200 SoC and video/camera clks for
     hi3660"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (147 commits)
  clk: gemini: Read status before using the value
  clk: scpi: error when clock fails to register
  clk: at91: Add sama5d2 suspend/resume
  gpio: dt-bindings: Add documentation for gpio controllers on Armada 7K/8K
  clk: keystone: TI_SCI_PROTOCOL is needed for clk driver
  clk: samsung: audss: Fix silent hang on Exynos4412 due to disabled EPLL
  clk: uniphier: provide NAND controller clock rate
  clk: hisilicon: add usb2 clocks for hi3798cv200 SoC
  clk: Add Gemini SoC clock controller
  clk: iproc: Remove __init marking on iproc_pll_clk_setup()
  clk: bcm: Add clocks for Stingray SOC
  dt-bindings: clk: Extend binding doc for Stingray SOC
  clk: mediatek: export cpu multiplexer clock for MT8173 SoCs
  clk: mediatek: export cpu multiplexer clock for MT2701/MT7623 SoCs
  clk: mediatek: add missing cpu mux causing Mediatek cpufreq can't work
  clk: renesas: cpg-mssr: Use of_device_get_match_data() helper
  clk: hi6220: add acpu clock
  clk: zx296718: export I2S mux clocks
  clk: imx7d: create clocks behind rawnand clock gate
  clk: hi3660: Set PPLL2 to 2880M
  ...
Linus Torvalds 8 vuotta sitten
vanhempi
commit
dddd564dbb
100 muutettua tiedostoa jossa 7435 lisäystä ja 799 poistoa
  1. 75 10
      Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt
  2. 125 19
      Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt
  3. 7 4
      Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt
  4. 1 0
      Documentation/devicetree/bindings/clock/hi6220-clock.txt
  5. 1 0
      Documentation/devicetree/bindings/clock/qcom,gcc.txt
  6. 6 0
      Documentation/devicetree/bindings/clock/qoriq-clock.txt
  7. 8 2
      Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
  8. 56 0
      Documentation/devicetree/bindings/clock/rockchip,rk3128-cru.txt
  9. 31 0
      Documentation/devicetree/bindings/clock/sun8i-de2.txt
  10. 4 1
      Documentation/devicetree/bindings/clock/sunxi-ccu.txt
  11. 37 0
      Documentation/devicetree/bindings/clock/ti,sci-clk.txt
  12. 56 0
      Documentation/devicetree/bindings/clock/ti-clkctrl.txt
  13. 17 7
      Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
  14. 2 0
      MAINTAINERS
  15. 0 5
      arch/mips/lantiq/clk.c
  16. 10 7
      drivers/clk/Kconfig
  17. 4 3
      drivers/clk/Makefile
  18. 4 2
      drivers/clk/at91/clk-generated.c
  19. 3 1
      drivers/clk/at91/clk-peripheral.c
  20. 129 0
      drivers/clk/at91/pmc.c
  21. 6 0
      drivers/clk/at91/pmc.h
  22. 8 0
      drivers/clk/bcm/Kconfig
  23. 1 0
      drivers/clk/bcm/Makefile
  24. 58 7
      drivers/clk/bcm/clk-bcm2835.c
  25. 6 6
      drivers/clk/bcm/clk-iproc-pll.c
  26. 327 0
      drivers/clk/bcm/clk-sr.c
  27. 157 0
      drivers/clk/clk-bulk.c
  28. 1 1
      drivers/clk/clk-conf.c
  29. 36 0
      drivers/clk/clk-devres.c
  30. 10 9
      drivers/clk/clk-divider.c
  31. 455 0
      drivers/clk/clk-gemini.c
  32. 1 0
      drivers/clk/clk-palmas.c
  33. 77 14
      drivers/clk/clk-qoriq.c
  34. 8 6
      drivers/clk/clk-scpi.c
  35. 84 14
      drivers/clk/hisilicon/clk-hi3660.c
  36. 22 0
      drivers/clk/hisilicon/clk-hi6220.c
  37. 21 0
      drivers/clk/hisilicon/crg-hi3798cv200.c
  38. 5 3
      drivers/clk/imx/clk-imx7d.c
  39. 5 0
      drivers/clk/imx/clk-pllv3.c
  40. 1 0
      drivers/clk/imx/clk.h
  41. 16 0
      drivers/clk/keystone/Kconfig
  42. 2 1
      drivers/clk/keystone/Makefile
  43. 724 0
      drivers/clk/keystone/sci-clk.c
  44. 1 1
      drivers/clk/mediatek/Makefile
  45. 120 0
      drivers/clk/mediatek/clk-cpumux.c
  46. 30 0
      drivers/clk/mediatek/clk-cpumux.h
  47. 8 0
      drivers/clk/mediatek/clk-mt2701.c
  48. 23 0
      drivers/clk/mediatek/clk-mt8173.c
  49. 3 3
      drivers/clk/meson/Kconfig
  50. 68 69
      drivers/clk/meson/gxbb.c
  51. 5 2
      drivers/clk/meson/gxbb.h
  52. 5 2
      drivers/clk/meson/meson8b.c
  53. 71 36
      drivers/clk/mvebu/ap806-system-controller.c
  54. 4 3
      drivers/clk/mvebu/armada-38x.c
  55. 137 62
      drivers/clk/mvebu/cp110-system-controller.c
  56. 9 0
      drivers/clk/qcom/Kconfig
  57. 1 0
      drivers/clk/qcom/Makefile
  58. 1007 0
      drivers/clk/qcom/gcc-ipq8074.c
  59. 1 0
      drivers/clk/qcom/gcc-msm8916.c
  60. 124 15
      drivers/clk/renesas/Kconfig
  61. 24 17
      drivers/clk/renesas/Makefile
  62. 1 1
      drivers/clk/renesas/clk-mstp.c
  63. 19 4
      drivers/clk/renesas/clk-rcar-gen2.c
  64. 2 15
      drivers/clk/renesas/r8a7745-cpg-mssr.c
  65. 278 0
      drivers/clk/renesas/r8a7790-cpg-mssr.c
  66. 286 0
      drivers/clk/renesas/r8a7791-cpg-mssr.c
  67. 221 0
      drivers/clk/renesas/r8a7792-cpg-mssr.c
  68. 255 0
      drivers/clk/renesas/r8a7794-cpg-mssr.c
  69. 30 13
      drivers/clk/renesas/r8a7795-cpg-mssr.c
  70. 39 0
      drivers/clk/renesas/r8a7796-cpg-mssr.c
  71. 36 7
      drivers/clk/renesas/renesas-cpg-mssr.c
  72. 4 0
      drivers/clk/renesas/renesas-cpg-mssr.h
  73. 1 0
      drivers/clk/rockchip/Makefile
  74. 1 0
      drivers/clk/rockchip/clk-rk3036.c
  75. 612 0
      drivers/clk/rockchip/clk-rk3128.c
  76. 105 59
      drivers/clk/rockchip/clk-rk3228.c
  77. 10 4
      drivers/clk/rockchip/clk-rk3288.c
  78. 4 1
      drivers/clk/rockchip/clk-rk3368.c
  79. 2 2
      drivers/clk/rockchip/clk-rk3399.c
  80. 8 9
      drivers/clk/samsung/clk-cpu.c
  81. 30 28
      drivers/clk/samsung/clk-exynos-audss.c
  82. 9 9
      drivers/clk/samsung/clk-exynos-clkout.c
  83. 23 4
      drivers/clk/samsung/clk-exynos5420.c
  84. 57 44
      drivers/clk/samsung/clk-pll.c
  85. 0 4
      drivers/clk/samsung/clk-pll.h
  86. 37 38
      drivers/clk/samsung/clk-s3c2410-dclk.c
  87. 27 25
      drivers/clk/samsung/clk-s5pv210-audss.c
  88. 41 50
      drivers/clk/samsung/clk.c
  89. 4 5
      drivers/clk/samsung/clk.h
  90. 1 1
      drivers/clk/socfpga/clk-gate-a10.c
  91. 3 0
      drivers/clk/socfpga/clk.h
  92. 7 109
      drivers/clk/sunxi-ng/Kconfig
  93. 24 13
      drivers/clk/sunxi-ng/Makefile
  94. 5 5
      drivers/clk/sunxi-ng/ccu-sun50i-a64.c
  95. 4 2
      drivers/clk/sunxi-ng/ccu-sun5i.h
  96. 5 5
      drivers/clk/sunxi-ng/ccu-sun6i-a31.c
  97. 5 5
      drivers/clk/sunxi-ng/ccu-sun8i-a23.c
  98. 5 5
      drivers/clk/sunxi-ng/ccu-sun8i-a33.c
  99. 922 0
      drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
  100. 64 0
      drivers/clk/sunxi-ng/ccu-sun8i-a83t.h

+ 75 - 10
Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt

@@ -7,6 +7,14 @@ registers giving access to numerous features: clocks, pin-muxing and
 many other SoC configuration items. This DT binding allows to describe
 this system controller.
 
+For the top level node:
+ - compatible: must be: "syscon", "simple-mfd";
+  - reg: register area of the AP806 system controller
+
+Clocks:
+-------
+
+
 The Device Tree node representing the AP806 system controller provides
 a number of clocks:
 
@@ -17,19 +25,76 @@ a number of clocks:
 
 Required properties:
 
- - compatible: must be:
-     "marvell,ap806-system-controller", "syscon"
- - reg: register area of the AP806 system controller
+ - compatible: must be: "marvell,ap806-clock"
  - #clock-cells: must be set to 1
- - clock-output-names: must be defined to:
-    "ap-cpu-cluster-0", "ap-cpu-cluster-1", "ap-fixed", "ap-mss"
+
+Pinctrl:
+--------
+
+For common binding part and usage, refer to
+Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt.
+
+Required properties:
+- compatible must be "marvell,ap806-pinctrl",
+
+Available mpp pins/groups and functions:
+Note: brackets (x) are not part of the mpp name for marvell,function and given
+only for more detailed description in this document.
+
+name	pins	functions
+================================================================================
+mpp0	0	gpio, sdio(clk), spi0(clk)
+mpp1	1	gpio, sdio(cmd), spi0(miso)
+mpp2	2	gpio, sdio(d0), spi0(mosi)
+mpp3	3	gpio, sdio(d1), spi0(cs0n)
+mpp4	4	gpio, sdio(d2), i2c0(sda)
+mpp5	5	gpio, sdio(d3), i2c0(sdk)
+mpp6	6	gpio, sdio(ds)
+mpp7	7	gpio, sdio(d4), uart1(rxd)
+mpp8	8	gpio, sdio(d5), uart1(txd)
+mpp9	9	gpio, sdio(d6), spi0(cs1n)
+mpp10	10	gpio, sdio(d7)
+mpp11	11	gpio, uart0(txd)
+mpp12	12	gpio, sdio(pw_off), sdio(hw_rst)
+mpp13	13	gpio
+mpp14	14	gpio
+mpp15	15	gpio
+mpp16	16	gpio
+mpp17	17	gpio
+mpp18	18	gpio
+mpp19	19	gpio, uart0(rxd), sdio(pw_off)
+
+GPIO:
+-----
+For common binding part and usage, refer to
+Documentation/devicetree/bindings/gpio/gpio-mvebu.txt.
+
+Required properties:
+
+- compatible: "marvell,armada-8k-gpio"
+
+- offset: offset address inside the syscon block
 
 Example:
+ap_syscon: system-controller@6f4000 {
+	compatible = "syscon", "simple-mfd";
+	reg = <0x6f4000 0x1000>;
 
-	syscon: system-controller@6f4000 {
-		compatible = "marvell,ap806-system-controller", "syscon";
+	ap_clk: clock {
+		compatible = "marvell,ap806-clock";
 		#clock-cells = <1>;
-		clock-output-names = "ap-cpu-cluster-0", "ap-cpu-cluster-1",
-				     "ap-fixed", "ap-mss";
-		reg = <0x6f4000 0x1000>;
 	};
+
+	ap_pinctrl: pinctrl {
+		compatible = "marvell,ap806-pinctrl";
+	};
+
+	ap_gpio: gpio {
+		compatible = "marvell,armada-8k-gpio";
+		offset = <0x1040>;
+		ngpios = <19>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-ranges = <&ap_pinctrl 0 0 19>;
+	};
+};

+ 125 - 19
Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt

@@ -7,6 +7,13 @@ Controller 0 and System Controller 1. This Device Tree binding allows
 to describe the first system controller, which provides registers to
 configure various aspects of the SoC.
 
+For the top level node:
+ - compatible: must be: "syscon", "simple-mfd";
+ - reg: register area of the CP110 system controller 0
+
+Clocks:
+-------
+
 The Device Tree node representing this System Controller 0 provides a
 number of clocks:
 
@@ -27,6 +34,7 @@ The following clocks are available:
    - 0 2	EIP
    - 0 3	Core
    - 0 4	NAND core
+   - 0 5	SDIO core
  - Gatable clocks
    - 1 0	Audio
    - 1 1	Comm Unit
@@ -56,28 +64,126 @@ The following clocks are available:
 Required properties:
 
  - compatible: must be:
-     "marvell,cp110-system-controller0", "syscon";
- - reg: register area of the CP110 system controller 0
+     "marvell,cp110-clock"
  - #clock-cells: must be set to 2
- - core-clock-output-names must be set to:
-	"cpm-apll", "cpm-ppv2-core", "cpm-eip", "cpm-core", "cpm-nand-core"
- - gate-clock-output-names must be set to:
-	"cpm-audio", "cpm-communit", "cpm-nand", "cpm-ppv2", "cpm-sdio",
-	"cpm-mg-domain", "cpm-mg-core", "cpm-xor1", "cpm-xor0", "cpm-gop-dp", "none",
-	"cpm-pcie_x10", "cpm-pcie_x11", "cpm-pcie_x4", "cpm-pcie-xor", "cpm-sata",
-	"cpm-sata-usb", "cpm-main", "cpm-sd-mmc-gop", "none", "none", "cpm-slow-io",
-	"cpm-usb3h0", "cpm-usb3h1", "cpm-usb3dev", "cpm-eip150", "cpm-eip197";
+
+Pinctrl:
+--------
+
+For common binding part and usage, refer to the file
+Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt.
+
+Required properties:
+
+- compatible: "marvell,armada-7k-pinctrl",
+  "marvell,armada-8k-cpm-pinctrl" or "marvell,armada-8k-cps-pinctrl"
+  depending on the specific variant of the SoC being used.
+
+Available mpp pins/groups and functions:
+Note: brackets (x) are not part of the mpp name for marvell,function and given
+only for more detailed description in this document.
+
+name	pins	functions
+================================================================================
+mpp0	0	gpio, dev(ale1), au(i2smclk), ge0(rxd3), tdm(pclk), ptp(pulse), mss_i2c(sda), uart0(rxd), sata0(present_act), ge(mdio)
+mpp1	1	gpio, dev(ale0), au(i2sdo_spdifo), ge0(rxd2), tdm(drx), ptp(clk), mss_i2c(sck), uart0(txd), sata1(present_act), ge(mdc)
+mpp2	2	gpio, dev(ad15), au(i2sextclk), ge0(rxd1), tdm(dtx), mss_uart(rxd), ptp(pclk_out), i2c1(sck), uart1(rxd), sata0(present_act), xg(mdc)
+mpp3	3	gpio, dev(ad14), au(i2slrclk), ge0(rxd0), tdm(fsync), mss_uart(txd), pcie(rstoutn), i2c1(sda), uart1(txd), sata1(present_act), xg(mdio)
+mpp4	4	gpio, dev(ad13), au(i2sbclk), ge0(rxctl), tdm(rstn), mss_uart(rxd), uart1(cts), pcie0(clkreq), uart3(rxd), ge(mdc)
+mpp5	5	gpio, dev(ad12), au(i2sdi), ge0(rxclk), tdm(intn), mss_uart(txd), uart1(rts), pcie1(clkreq), uart3(txd), ge(mdio)
+mpp6	6	gpio, dev(ad11), ge0(txd3), spi0(csn2), au(i2sextclk), sata1(present_act), pcie2(clkreq), uart0(rxd), ptp(pulse)
+mpp7	7	gpio, dev(ad10), ge0(txd2), spi0(csn1), spi1(csn1), sata0(present_act), led(data), uart0(txd), ptp(clk)
+mpp8	8	gpio, dev(ad9), ge0(txd1), spi0(csn0), spi1(csn0), uart0(cts), led(stb), uart2(rxd), ptp(pclk_out), synce1(clk)
+mpp9	9	gpio, dev(ad8), ge0(txd0), spi0(mosi), spi1(mosi), pcie(rstoutn), synce2(clk)
+mpp10	10	gpio, dev(readyn), ge0(txctl), spi0(miso), spi1(miso), uart0(cts), sata1(present_act)
+mpp11	11	gpio, dev(wen1), ge0(txclkout), spi0(clk), spi1(clk), uart0(rts), led(clk), uart2(txd), sata0(present_act)
+mpp12	12	gpio, dev(clk_out), nf(rbn1), spi1(csn1), ge0(rxclk)
+mpp13	13	gpio, dev(burstn), nf(rbn0), spi1(miso), ge0(rxctl), mss_spi(miso)
+mpp14	14	gpio, dev(bootcsn), dev(csn0), spi1(csn0), spi0(csn3), au(i2sextclk), spi0(miso), sata0(present_act), mss_spi(csn)
+mpp15	15	gpio, dev(ad7), spi1(mosi), spi0(mosi), mss_spi(mosi), ptp(pulse_cp2cp)
+mpp16	16	gpio, dev(ad6), spi1(clk), mss_spi(clk)
+mpp17	17	gpio, dev(ad5), ge0(txd3)
+mpp18	18	gpio, dev(ad4), ge0(txd2), ptp(clk_cp2cp)
+mpp19	19	gpio, dev(ad3), ge0(txd1), wakeup(out_cp2cp)
+mpp20	20	gpio, dev(ad2), ge0(txd0)
+mpp21	21	gpio, dev(ad1), ge0(txctl), sei(in_cp2cp)
+mpp22	22	gpio, dev(ad0), ge0(txclkout), wakeup(in_cp2cp)
+mpp23	23	gpio, dev(a1), au(i2smclk), link(rd_in_cp2cp)
+mpp24	24	gpio, dev(a0), au(i2slrclk)
+mpp25	25	gpio, dev(oen), au(i2sdo_spdifo)
+mpp26	26	gpio, dev(wen0), au(i2sbclk)
+mpp27	27	gpio, dev(csn0), spi1(miso), mss_gpio4, ge0(rxd3), spi0(csn4), ge(mdio), sata0(present_act), uart0(rts), rei(in_cp2cp)
+mpp28	28	gpio, dev(csn1), spi1(csn0), mss_gpio5, ge0(rxd2), spi0(csn5), pcie2(clkreq), ptp(pulse), ge(mdc), sata1(present_act), uart0(cts), led(data)
+mpp29	29	gpio, dev(csn2), spi1(mosi), mss_gpio6, ge0(rxd1), spi0(csn6), pcie1(clkreq), ptp(clk), mss_i2c(sda), sata0(present_act), uart0(rxd), led(stb)
+mpp30	30	gpio, dev(csn3), spi1(clk), mss_gpio7, ge0(rxd0), spi0(csn7), pcie0(clkreq), ptp(pclk_out), mss_i2c(sck), sata1(present_act), uart0(txd), led(clk)
+mpp31	31	gpio, dev(a2), mss_gpio4, pcie(rstoutn), ge(mdc)
+mpp32	32	gpio, mii(col), mii(txerr), mss_spi(miso), tdm(drx), au(i2sextclk), au(i2sdi), ge(mdio), sdio(v18_en), pcie1(clkreq), mss_gpio0
+mpp33	33	gpio, mii(txclk), sdio(pwr10), mss_spi(csn), tdm(fsync), au(i2smclk), sdio(bus_pwr), xg(mdio), pcie2(clkreq), mss_gpio1
+mpp34	34	gpio, mii(rxerr), sdio(pwr11), mss_spi(mosi), tdm(dtx), au(i2slrclk), sdio(wr_protect), ge(mdc), pcie0(clkreq), mss_gpio2
+mpp35	35	gpio, sata1(present_act), i2c1(sda), mss_spi(clk), tdm(pclk), au(i2sdo_spdifo), sdio(card_detect), xg(mdio), ge(mdio), pcie(rstoutn), mss_gpio3
+mpp36	36	gpio, synce2(clk), i2c1(sck), ptp(clk), synce1(clk), au(i2sbclk), sata0(present_act), xg(mdc), ge(mdc), pcie2(clkreq), mss_gpio5
+mpp37	37	gpio, uart2(rxd), i2c0(sck), ptp(pclk_out), tdm(intn), mss_i2c(sck), sata1(present_act), ge(mdc), xg(mdc), pcie1(clkreq), mss_gpio6, link(rd_out_cp2cp)
+mpp38	38	gpio, uart2(txd), i2c0(sda), ptp(pulse), tdm(rstn), mss_i2c(sda), sata0(present_act), ge(mdio), xg(mdio), au(i2sextclk), mss_gpio7, ptp(pulse_cp2cp)
+mpp39	39	gpio, sdio(wr_protect), au(i2sbclk), ptp(clk), spi0(csn1), sata1(present_act), mss_gpio0
+mpp40	40	gpio, sdio(pwr11), synce1(clk), mss_i2c(sda), au(i2sdo_spdifo), ptp(pclk_out), spi0(clk), uart1(txd), ge(mdio), sata0(present_act), mss_gpio1
+mpp41	41	gpio, sdio(pwr10), sdio(bus_pwr), mss_i2c(sck), au(i2slrclk), ptp(pulse), spi0(mosi), uart1(rxd), ge(mdc), sata1(present_act), mss_gpio2, rei(out_cp2cp)
+mpp42	42	gpio, sdio(v18_en), sdio(wr_protect), synce2(clk), au(i2smclk), mss_uart(txd), spi0(miso), uart1(cts), xg(mdc), sata0(present_act), mss_gpio4
+mpp43	43	gpio, sdio(card_detect), synce1(clk), au(i2sextclk), mss_uart(rxd), spi0(csn0), uart1(rts), xg(mdio), sata1(present_act), mss_gpio5, wakeup(out_cp2cp)
+mpp44	44	gpio, ge1(txd2), uart0(rts), ptp(clk_cp2cp)
+mpp45	45	gpio, ge1(txd3), uart0(txd), pcie(rstoutn)
+mpp46	46	gpio, ge1(txd1), uart1(rts)
+mpp47	47	gpio, ge1(txd0), spi1(clk), uart1(txd), ge(mdc)
+mpp48	48	gpio, ge1(txctl_txen), spi1(mosi), xg(mdc), wakeup(in_cp2cp)
+mpp49	49	gpio, ge1(txclkout), mii(crs), spi1(miso), uart1(rxd), ge(mdio), pcie0(clkreq), sdio(v18_en), sei(out_cp2cp)
+mpp50	50	gpio, ge1(rxclk), mss_i2c(sda), spi1(csn0), uart2(txd), uart0(rxd), xg(mdio), sdio(pwr11)
+mpp51	51	gpio, ge1(rxd0), mss_i2c(sck), spi1(csn1), uart2(rxd), uart0(cts), sdio(pwr10)
+mpp52	52	gpio, ge1(rxd1), synce1(clk), synce2(clk), spi1(csn2), uart1(cts), led(clk), pcie(rstoutn), pcie0(clkreq)
+mpp53	53	gpio, ge1(rxd2), ptp(clk), spi1(csn3), uart1(rxd), led(stb), sdio(led)
+mpp54	54	gpio, ge1(rxd3), synce2(clk), ptp(pclk_out), synce1(clk), led(data), sdio(hw_rst), sdio(wr_protect)
+mpp55	55	gpio, ge1(rxctl_rxdv), ptp(pulse), sdio(led), sdio(card_detect)
+mpp56	56	gpio, tdm(drx), au(i2sdo_spdifo), spi0(clk), uart1(rxd), sata1(present_act), sdio(clk)
+mpp57	57	gpio, mss_i2c(sda), ptp(pclk_out), tdm(intn), au(i2sbclk), spi0(mosi), uart1(txd), sata0(present_act), sdio(cmd)
+mpp58	58	gpio, mss_i2c(sck), ptp(clk), tdm(rstn), au(i2sdi), spi0(miso), uart1(cts), led(clk), sdio(d0)
+mpp59	59	gpio, mss_gpio7, synce2(clk), tdm(fsync), au(i2slrclk), spi0(csn0), uart0(cts), led(stb), uart1(txd), sdio(d1)
+mpp60	60	gpio, mss_gpio6, ptp(pulse), tdm(dtx), au(i2smclk), spi0(csn1), uart0(rts), led(data), uart1(rxd), sdio(d2)
+mpp61	61	gpio, mss_gpio5, ptp(clk), tdm(pclk), au(i2sextclk), spi0(csn2), uart0(txd), uart2(txd), sata1(present_act), ge(mdio), sdio(d3)
+mpp62	62	gpio, mss_gpio4, synce1(clk), ptp(pclk_out), sata1(present_act), spi0(csn3), uart0(rxd), uart2(rxd), sata0(present_act), ge(mdc)
+
+GPIO:
+-----
+
+For common binding part and usage, refer to
+Documentation/devicetree/bindings/gpio/gpio-mvebu.txt.
+
+Required properties:
+
+- compatible: "marvell,armada-8k-gpio"
+
+- offset: offset address inside the syscon block
 
 Example:
 
-	cpm_syscon0: system-controller@440000 {
-		compatible = "marvell,cp110-system-controller0", "syscon";
-		reg = <0x440000 0x1000>;
+cpm_syscon0: system-controller@440000 {
+	compatible = "syscon", "simple-mfd";
+	reg = <0x440000 0x1000>;
+
+	cpm_clk: clock {
+		compatible = "marvell,cp110-clock";
 		#clock-cells = <2>;
-		core-clock-output-names = "cpm-apll", "cpm-ppv2-core", "cpm-eip", "cpm-core", "cpm-nand-core";
-		gate-clock-output-names = "cpm-audio", "cpm-communit", "cpm-nand", "cpm-ppv2", "cpm-sdio",
-			"cpm-mg-domain", "cpm-mg-core", "cpm-xor1", "cpm-xor0", "cpm-gop-dp", "none",
-			"cpm-pcie_x10", "cpm-pcie_x11", "cpm-pcie_x4", "cpm-pcie-xor", "cpm-sata",
-			"cpm-sata-usb", "cpm-main", "cpm-sd-mmc-gop", "none", "none", "cpm-slow-io",
-			"cpm-usb3h0", "cpm-usb3h1", "cpm-usb3dev", "cpm-eip150", "cpm-eip197";
 	};
+
+	cpm_pinctrl: pinctrl {
+		compatible = "marvell,armada-8k-cpm-pinctrl";
+	};
+
+	cpm_gpio1: gpio@100 {
+		compatible = "marvell,armada-8k-gpio";
+		offset = <0x100>;
+		ngpios = <32>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-ranges = <&cpm_pinctrl 0 0 32>;
+		status = "disabled";
+	};
+
+};

+ 7 - 4
Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt

@@ -1,11 +1,14 @@
-* Amlogic Meson8b Clock and Reset Unit
+* Amlogic Meson8, Meson8b and Meson8m2 Clock and Reset Unit
 
-The Amlogic Meson8b clock controller generates and supplies clock to various
-controllers within the SoC.
+The Amlogic Meson8 / Meson8b / Meson8m2 clock controller generates and
+supplies clock to various controllers within the SoC.
 
 Required Properties:
 
-- compatible: should be "amlogic,meson8b-clkc"
+- compatible: must be one of:
+	- "amlogic,meson8-clkc" for Meson8 (S802) SoCs
+	- "amlogic,meson8b-clkc" for Meson8 (S805) SoCs
+	- "amlogic,meson8m2-clkc" for Meson8m2 (S812) SoCs
 - reg: it must be composed by two tuples:
 	0) physical base address of the xtal register and length of memory
 	   mapped region.

+ 1 - 0
Documentation/devicetree/bindings/clock/hi6220-clock.txt

@@ -11,6 +11,7 @@ Required Properties:
 - compatible: the compatible should be one of the following strings to
 	indicate the clock controller functionality.
 
+	- "hisilicon,hi6220-acpu-sctrl"
 	- "hisilicon,hi6220-aoctrl"
 	- "hisilicon,hi6220-sysctrl"
 	- "hisilicon,hi6220-mediactrl"

+ 1 - 0
Documentation/devicetree/bindings/clock/qcom,gcc.txt

@@ -8,6 +8,7 @@ Required properties :
 			"qcom,gcc-apq8084"
 			"qcom,gcc-ipq8064"
 			"qcom,gcc-ipq4019"
+			"qcom,gcc-ipq8074"
 			"qcom,gcc-msm8660"
 			"qcom,gcc-msm8916"
 			"qcom,gcc-msm8960"

+ 6 - 0
Documentation/devicetree/bindings/clock/qoriq-clock.txt

@@ -57,6 +57,11 @@ Optional properties:
 - clocks: If clock-frequency is not specified, sysclk may be provided
 	as an input clock.  Either clock-frequency or clocks must be
 	provided.
+	A second input clock, called "coreclk", may be provided if
+	core PLLs are based on a different input clock from the
+	platform PLL.
+- clock-names: Required if a coreclk is present.  Valid names are
+	"sysclk" and "coreclk".
 
 2. Clock Provider
 
@@ -73,6 +78,7 @@ second cell is the clock index for the specified type.
 	2	hwaccel		index (n in CLKCGnHWACSR)
 	3	fman		0 for fm1, 1 for fm2
 	4	platform pll	0=pll, 1=pll/2, 2=pll/3, 3=pll/4
+	5	coreclk		must be 0
 
 3. Example
 

+ 8 - 2
Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt

@@ -15,6 +15,11 @@ Required Properties:
   - compatible: Must be one of:
       - "renesas,r8a7743-cpg-mssr" for the r8a7743 SoC (RZ/G1M)
       - "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E)
+      - "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)
+      - "renesas,r8a7793-cpg-mssr" for the r8a7793 SoC (R-Car M2-N)
+      - "renesas,r8a7794-cpg-mssr" for the r8a7794 SoC (R-Car E2)
       - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3)
       - "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W)
 
@@ -24,9 +29,10 @@ 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, r8a7795, r8a7796)
+      - "extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794,
+		 r8a7795, r8a7796)
       - "extalr" (r8a7795, r8a7796)
-      - "usb_extal" (r8a7743, r8a7745)
+      - "usb_extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7793, r8a7794)
 
   - #clock-cells: Must be 2
       - For CPG core clocks, the two clock specifier cells must be "CPG_CORE"

+ 56 - 0
Documentation/devicetree/bindings/clock/rockchip,rk3128-cru.txt

@@ -0,0 +1,56 @@
+* Rockchip RK3128 Clock and Reset Unit
+
+The RK3128 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk3128-cru"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+  If missing pll rates are not changeable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk3128-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "ext_i2s" - external I2S clock - optional,
+ - "gmac_clkin" - external GMAC clock - optional
+
+Example: Clock controller node:
+
+	cru: cru@20000000 {
+		compatible = "rockchip,rk3128-cru";
+		reg = <0x20000000 0x1000>;
+		rockchip,grf = <&grf>;
+
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+	uart2: serial@20068000 {
+		compatible = "rockchip,serial";
+		reg = <0x20068000 0x100>;
+		interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+		clock-names = "sclk_uart", "pclk_uart";
+	};

+ 31 - 0
Documentation/devicetree/bindings/clock/sun8i-de2.txt

@@ -0,0 +1,31 @@
+Allwinner Display Engine 2.0 Clock Control Binding
+--------------------------------------------------
+
+Required properties :
+- compatible: must contain one of the following compatibles:
+		- "allwinner,sun8i-a83t-de2-clk"
+		- "allwinner,sun8i-v3s-de2-clk"
+		- "allwinner,sun50i-h5-de2-clk"
+
+- reg: Must contain the registers base address and length
+- clocks: phandle to the clocks feeding the display engine subsystem.
+	  Three are needed:
+  - "mod": the display engine module clock
+  - "bus": the bus clock for the whole display engine subsystem
+- clock-names: Must contain the clock names described just above
+- resets: phandle to the reset control for the display engine subsystem.
+- #clock-cells : must contain 1
+- #reset-cells : must contain 1
+
+Example:
+de2_clocks: clock@1000000 {
+	compatible = "allwinner,sun8i-a83t-de2-clk";
+	reg = <0x01000000 0x100000>;
+	clocks = <&ccu CLK_BUS_DE>,
+		 <&ccu CLK_DE>;
+	clock-names = "bus",
+		      "mod";
+	resets = <&ccu RST_BUS_DE>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};

+ 4 - 1
Documentation/devicetree/bindings/clock/sunxi-ccu.txt

@@ -6,6 +6,8 @@ Required properties :
 		- "allwinner,sun6i-a31-ccu"
 		- "allwinner,sun8i-a23-ccu"
 		- "allwinner,sun8i-a33-ccu"
+		- "allwinner,sun8i-a83t-ccu"
+		- "allwinner,sun8i-a83t-r-ccu"
 		- "allwinner,sun8i-h3-ccu"
 		- "allwinner,sun8i-h3-r-ccu"
 		- "allwinner,sun8i-v3s-ccu"
@@ -18,11 +20,12 @@ Required properties :
 - clocks: phandle to the oscillators feeding the CCU. Two are needed:
   - "hosc": the high frequency oscillator (usually at 24MHz)
   - "losc": the low frequency oscillator (usually at 32kHz)
+	    On the A83T, this is the internal 16MHz oscillator divided by 512
 - clock-names: Must contain the clock names described just above
 - #clock-cells : must contain 1
 - #reset-cells : must contain 1
 
-For the PRCM CCUs on H3/A64, two more clocks are needed:
+For the PRCM CCUs on A83T/H3/A64, two more clocks are needed:
 - "pll-periph": the SoC's peripheral PLL from the main CCU
 - "iosc": the SoC's internal frequency oscillator
 

+ 37 - 0
Documentation/devicetree/bindings/clock/ti,sci-clk.txt

@@ -0,0 +1,37 @@
+Texas Instruments TI-SCI Clocks
+===============================
+
+All clocks on Texas Instruments' SoCs that contain a System Controller,
+are only controlled by this entity. Communication between a host processor
+running an OS and the System Controller happens through a protocol known
+as TI-SCI[1]. This clock implementation plugs into the common clock
+framework and makes use of the TI-SCI protocol on clock API requests.
+
+[1] Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
+
+Required properties:
+-------------------
+- compatible: Must be "ti,k2g-sci-clk"
+- #clock-cells: Shall be 2.
+  In clock consumers, this cell represents the device ID and clock ID
+  exposed by the PM firmware. The assignments can be found in the header
+  files <dt-bindings/genpd/<soc>.h> (which covers the device IDs) and
+  <dt-bindings/clock/<soc>.h> (which covers the clock IDs), where <soc>
+  is the SoC involved, for example 'k2g'.
+
+Examples:
+--------
+
+pmmc: pmmc {
+	compatible = "ti,k2g-sci";
+
+	k2g_clks: clocks {
+		compatible = "ti,k2g-sci-clk";
+		#clock-cells = <2>;
+	};
+};
+
+uart0: serial@2530c00 {
+	compatible = "ns16550a";
+	clocks = <&k2g_clks 0x2c 0>;
+};

+ 56 - 0
Documentation/devicetree/bindings/clock/ti-clkctrl.txt

@@ -0,0 +1,56 @@
+Texas Instruments clkctrl clock binding
+
+Texas Instruments SoCs can have a clkctrl clock controller for each
+interconnect target module. The clkctrl clock controller manages functional
+and interface clocks for each module. Each clkctrl controller can also
+gate one or more optional functional clocks for a module, and can have one
+or more clock muxes. There is a clkctrl clock controller typically for each
+interconnect target module on omap4 and later variants.
+
+The clock consumers can specify the index of the clkctrl clock using
+the hardware offset from the clkctrl instance register space. The optional
+clocks can be specified by clkctrl hardware offset and the index of the
+optional clock.
+
+For more information, please see the Linux clock framework binding at
+Documentation/devicetree/bindings/clock/clock-bindings.txt.
+
+Required properties :
+- compatible : shall be "ti,clkctrl"
+- #clock-cells : shall contain 2 with the first entry being the instance
+		 offset from the clock domain base and the second being the
+		 clock index
+
+Example: Clock controller node on omap 4430:
+
+&cm2 {
+	l4per: cm@1400 {
+		cm_l4per@0 {
+			cm_l4per_clkctrl: clk@20 {
+				compatible = "ti,clkctrl";
+				reg = <0x20 0x1b0>;
+				#clock-cells = <2>;
+			};
+		};
+	};
+};
+
+Example: Preprocessor helper macros in dt-bindings/clock/ti-clkctrl.h
+
+#define OMAP4_CLKCTRL_OFFSET		0x20
+#define OMAP4_CLKCTRL_INDEX(offset)	((offset) - OMAP4_CLKCTRL_OFFSET)
+#define MODULEMODE_HWCTRL		1
+#define MODULEMODE_SWCTRL		2
+
+#define OMAP4_GPTIMER10_CLKTRL		OMAP4_CLKCTRL_INDEX(0x28)
+#define OMAP4_GPTIMER11_CLKTRL		OMAP4_CLKCTRL_INDEX(0x30)
+#define OMAP4_GPTIMER2_CLKTRL		OMAP4_CLKCTRL_INDEX(0x38)
+...
+#define OMAP4_GPIO2_CLKCTRL		OMAP_CLKCTRL_INDEX(0x60)
+
+Example: Clock consumer node for GPIO2:
+
+&gpio2 {
+       clocks = <&cm_l4per_clkctrl OMAP4_GPIO2_CLKCTRL 0
+		 &cm_l4per_clkctrl OMAP4_GPIO2_CLKCTRL 8>;
+};

+ 17 - 7
Documentation/devicetree/bindings/gpio/gpio-mvebu.txt

@@ -2,17 +2,27 @@
 
 Required properties:
 
-- compatible : Should be "marvell,orion-gpio", "marvell,mv78200-gpio"
-  or "marvell,armadaxp-gpio". "marvell,orion-gpio" should be used for
-  Orion, Kirkwood, Dove, Discovery (except MV78200) and Armada
-  370. "marvell,mv78200-gpio" should be used for the Discovery
-  MV78200. "marvel,armadaxp-gpio" should be used for all Armada XP
-  SoCs (MV78230, MV78260, MV78460).
+- compatible : Should be "marvell,orion-gpio", "marvell,mv78200-gpio",
+  "marvell,armadaxp-gpio" or "marvell,armada-8k-gpio".
+
+    "marvell,orion-gpio" should be used for Orion, Kirkwood, Dove,
+    Discovery (except MV78200) and Armada 370. "marvell,mv78200-gpio"
+    should be used for the Discovery MV78200.
+
+    "marvel,armadaxp-gpio" should be used for all Armada XP SoCs
+    (MV78230, MV78260, MV78460).
+
+    "marvell,armada-8k-gpio" should be used for the Armada 7K and 8K
+    SoCs (either from AP or CP), see
+    Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt
+    and
+    Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt
+    for specific details about the offset property.
 
 - reg: Address and length of the register set for the device. Only one
   entry is expected, except for the "marvell,armadaxp-gpio" variant
   for which two entries are expected: one for the general registers,
-  one for the per-cpu registers.
+  one for the per-cpu registers. Not used for marvell,armada-8k-gpio.
 
 - interrupts: The list of interrupts that are used for all the pins
   managed by this GPIO bank. There can be more than one interrupt

+ 2 - 0
MAINTAINERS

@@ -12872,6 +12872,8 @@ F:	Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
 F:	include/dt-bindings/genpd/k2g.h
 F:	drivers/soc/ti/ti_sci_pm_domains.c
 F:	Documentation/devicetree/bindings/reset/ti,sci-reset.txt
+F:	Documentation/devicetree/bindings/clock/ti,sci-clk.txt
+F:	drivers/clk/keystone/sci-clk.c
 F:	drivers/reset/reset-ti-sci.c
 
 THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER

+ 0 - 5
arch/mips/lantiq/clk.c

@@ -160,11 +160,6 @@ void clk_deactivate(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_deactivate);
 
-struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
-{
-	return NULL;
-}
-
 static inline u32 get_counter_resolution(void)
 {
 	u32 res;

+ 10 - 7
drivers/clk/Kconfig

@@ -126,6 +126,15 @@ config COMMON_CLK_CS2000_CP
 	help
 	  If you say yes here you get support for the CS2000 clock multiplier.
 
+config COMMON_CLK_GEMINI
+	bool "Clock driver for Cortina Systems Gemini SoC"
+	depends on ARCH_GEMINI || COMPILE_TEST
+	select MFD_SYSCON
+	select RESET_CONTROLLER
+	---help---
+	  This driver supports the SoC clocks on the Cortina Systems Gemini
+	  platform, also known as SL3516 or CS3516.
+
 config COMMON_CLK_S2MPS11
 	tristate "Clock driver for S2MPS1X/S5M8767 MFD"
 	depends on MFD_SEC_CORE || COMPILE_TEST
@@ -164,13 +173,6 @@ config COMMON_CLK_XGENE
 	---help---
 	  Sypport for the APM X-Gene SoC reference, PLL, and device clocks.
 
-config COMMON_CLK_KEYSTONE
-	tristate "Clock drivers for Keystone based SOCs"
-	depends on (ARCH_KEYSTONE || COMPILE_TEST) && OF
-	---help---
-          Supports clock drivers for Keystone based SOCs. These SOCs have local
-	  a power sleep control module that gate the clock to the IPs and PLLs.
-
 config COMMON_CLK_NXP
 	def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
 	select REGMAP_MMIO if ARCH_LPC32XX
@@ -219,6 +221,7 @@ config COMMON_CLK_VC5
 
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
+source "drivers/clk/keystone/Kconfig"
 source "drivers/clk/mediatek/Kconfig"
 source "drivers/clk/meson/Kconfig"
 source "drivers/clk/mvebu/Kconfig"

+ 4 - 3
drivers/clk/Makefile

@@ -1,5 +1,5 @@
 # common clock types
-obj-$(CONFIG_HAVE_CLK)		+= clk-devres.o
+obj-$(CONFIG_HAVE_CLK)		+= clk-devres.o clk-bulk.o
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 obj-$(CONFIG_COMMON_CLK)	+= clk.o
 obj-$(CONFIG_COMMON_CLK)	+= clk-divider.o
@@ -25,6 +25,7 @@ obj-$(CONFIG_COMMON_CLK_CDCE925)	+= clk-cdce925.o
 obj-$(CONFIG_ARCH_CLPS711X)		+= clk-clps711x.o
 obj-$(CONFIG_COMMON_CLK_CS2000_CP)	+= clk-cs2000-cp.o
 obj-$(CONFIG_ARCH_EFM32)		+= clk-efm32gg.o
+obj-$(CONFIG_COMMON_CLK_GEMINI)		+= clk-gemini.o
 obj-$(CONFIG_ARCH_HIGHBANK)		+= clk-highbank.o
 obj-$(CONFIG_COMMON_CLK_MAX77686)	+= clk-max77686.o
 obj-$(CONFIG_ARCH_MB86S7X)		+= clk-mb86s7x.o
@@ -61,7 +62,7 @@ obj-$(CONFIG_H8300)			+= h8300/
 obj-$(CONFIG_ARCH_HISI)			+= hisilicon/
 obj-$(CONFIG_ARCH_MXC)			+= imx/
 obj-$(CONFIG_MACH_INGENIC)		+= ingenic/
-obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
+obj-$(CONFIG_ARCH_KEYSTONE)		+= keystone/
 obj-$(CONFIG_MACH_LOONGSON32)		+= loongson1/
 obj-$(CONFIG_ARCH_MEDIATEK)		+= mediatek/
 obj-$(CONFIG_COMMON_CLK_AMLOGIC)	+= meson/
@@ -75,7 +76,7 @@ obj-$(CONFIG_COMMON_CLK_NXP)		+= nxp/
 obj-$(CONFIG_MACH_PISTACHIO)		+= pistachio/
 obj-$(CONFIG_COMMON_CLK_PXA)		+= pxa/
 obj-$(CONFIG_COMMON_CLK_QCOM)		+= qcom/
-obj-$(CONFIG_ARCH_RENESAS)		+= renesas/
+obj-y					+= renesas/
 obj-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip/
 obj-$(CONFIG_COMMON_CLK_SAMSUNG)	+= samsung/
 obj-$(CONFIG_ARCH_SIRF)			+= sirf/

+ 4 - 2
drivers/clk/at91/clk-generated.c

@@ -260,13 +260,15 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
 	gck->lock = lock;
 	gck->range = *range;
 
+	clk_generated_startup(gck);
 	hw = &gck->hw;
 	ret = clk_hw_register(NULL, &gck->hw);
 	if (ret) {
 		kfree(gck);
 		hw = ERR_PTR(ret);
-	} else
-		clk_generated_startup(gck);
+	} else {
+		pmc_register_id(id);
+	}
 
 	return hw;
 }

+ 3 - 1
drivers/clk/at91/clk-peripheral.c

@@ -367,8 +367,10 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
 	if (ret) {
 		kfree(periph);
 		hw = ERR_PTR(ret);
-	} else
+	} else {
 		clk_sam9x5_peripheral_autodiv(periph);
+		pmc_register_id(id);
+	}
 
 	return hw;
 }

+ 129 - 0
drivers/clk/at91/pmc.c

@@ -13,12 +13,16 @@
 #include <linux/clk/at91_pmc.h>
 #include <linux/of.h>
 #include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
 #include <linux/regmap.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/proc-fns.h>
 
 #include "pmc.h"
 
+#define PMC_MAX_IDS 128
+
 int of_at91_get_clk_range(struct device_node *np, const char *propname,
 			  struct clk_range *range)
 {
@@ -41,3 +45,128 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname,
 	return 0;
 }
 EXPORT_SYMBOL_GPL(of_at91_get_clk_range);
+
+#ifdef CONFIG_PM
+static struct regmap *pmcreg;
+
+static u8 registered_ids[PMC_MAX_IDS];
+
+static struct
+{
+	u32 scsr;
+	u32 pcsr0;
+	u32 uckr;
+	u32 mor;
+	u32 mcfr;
+	u32 pllar;
+	u32 mckr;
+	u32 usb;
+	u32 imr;
+	u32 pcsr1;
+	u32 pcr[PMC_MAX_IDS];
+	u32 audio_pll0;
+	u32 audio_pll1;
+} pmc_cache;
+
+void pmc_register_id(u8 id)
+{
+	int i;
+
+	for (i = 0; i < PMC_MAX_IDS; i++) {
+		if (registered_ids[i] == 0) {
+			registered_ids[i] = id;
+			break;
+		}
+		if (registered_ids[i] == id)
+			break;
+	}
+}
+
+static int pmc_suspend(void)
+{
+	int i;
+
+	regmap_read(pmcreg, AT91_PMC_IMR, &pmc_cache.scsr);
+	regmap_read(pmcreg, AT91_PMC_PCSR, &pmc_cache.pcsr0);
+	regmap_read(pmcreg, AT91_CKGR_UCKR, &pmc_cache.uckr);
+	regmap_read(pmcreg, AT91_CKGR_MOR, &pmc_cache.mor);
+	regmap_read(pmcreg, AT91_CKGR_MCFR, &pmc_cache.mcfr);
+	regmap_read(pmcreg, AT91_CKGR_PLLAR, &pmc_cache.pllar);
+	regmap_read(pmcreg, AT91_PMC_MCKR, &pmc_cache.mckr);
+	regmap_read(pmcreg, AT91_PMC_USB, &pmc_cache.usb);
+	regmap_read(pmcreg, AT91_PMC_IMR, &pmc_cache.imr);
+	regmap_read(pmcreg, AT91_PMC_PCSR1, &pmc_cache.pcsr1);
+
+	for (i = 0; registered_ids[i]; i++) {
+		regmap_write(pmcreg, AT91_PMC_PCR,
+			     (registered_ids[i] & AT91_PMC_PCR_PID_MASK));
+		regmap_read(pmcreg, AT91_PMC_PCR,
+			    &pmc_cache.pcr[registered_ids[i]]);
+	}
+
+	return 0;
+}
+
+static void pmc_resume(void)
+{
+	int i, ret = 0;
+	u32 tmp;
+
+	regmap_read(pmcreg, AT91_PMC_MCKR, &tmp);
+	if (pmc_cache.mckr != tmp)
+		pr_warn("MCKR was not configured properly by the firmware\n");
+	regmap_read(pmcreg, AT91_CKGR_PLLAR, &tmp);
+	if (pmc_cache.pllar != tmp)
+		pr_warn("PLLAR was not configured properly by the firmware\n");
+
+	regmap_write(pmcreg, AT91_PMC_IMR, pmc_cache.scsr);
+	regmap_write(pmcreg, AT91_PMC_PCER, pmc_cache.pcsr0);
+	regmap_write(pmcreg, AT91_CKGR_UCKR, pmc_cache.uckr);
+	regmap_write(pmcreg, AT91_CKGR_MOR, pmc_cache.mor);
+	regmap_write(pmcreg, AT91_CKGR_MCFR, pmc_cache.mcfr);
+	regmap_write(pmcreg, AT91_PMC_USB, pmc_cache.usb);
+	regmap_write(pmcreg, AT91_PMC_IMR, pmc_cache.imr);
+	regmap_write(pmcreg, AT91_PMC_PCER1, pmc_cache.pcsr1);
+
+	for (i = 0; registered_ids[i]; i++) {
+		regmap_write(pmcreg, AT91_PMC_PCR,
+			     pmc_cache.pcr[registered_ids[i]] |
+			     AT91_PMC_PCR_CMD);
+	}
+
+	if (pmc_cache.uckr & AT91_PMC_UPLLEN) {
+		ret = regmap_read_poll_timeout(pmcreg, AT91_PMC_SR, tmp,
+					       !(tmp & AT91_PMC_LOCKU),
+					       10, 5000);
+		if (ret)
+			pr_crit("USB PLL didn't lock when resuming\n");
+	}
+}
+
+static struct syscore_ops pmc_syscore_ops = {
+	.suspend = pmc_suspend,
+	.resume = pmc_resume,
+};
+
+static const struct of_device_id sama5d2_pmc_dt_ids[] = {
+	{ .compatible = "atmel,sama5d2-pmc" },
+	{ /* sentinel */ }
+};
+
+static int __init pmc_register_ops(void)
+{
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, sama5d2_pmc_dt_ids);
+
+	pmcreg = syscon_node_to_regmap(np);
+	if (IS_ERR(pmcreg))
+		return PTR_ERR(pmcreg);
+
+	register_syscore_ops(&pmc_syscore_ops);
+
+	return 0;
+}
+/* This has to happen before arch_initcall because of the tcb_clksrc driver */
+postcore_initcall(pmc_register_ops);
+#endif

+ 6 - 0
drivers/clk/at91/pmc.h

@@ -29,4 +29,10 @@ struct clk_range {
 int of_at91_get_clk_range(struct device_node *np, const char *propname,
 			  struct clk_range *range);
 
+#ifdef CONFIG_PM
+void pmc_register_id(u8 id);
+#else
+static inline void pmc_register_id(u8 id) {}
+#endif
+
 #endif /* __PMC_H_ */

+ 8 - 0
drivers/clk/bcm/Kconfig

@@ -46,3 +46,11 @@ config CLK_BCM_NS2
 	default ARCH_BCM_IPROC
 	help
 	  Enable common clock framework support for the Broadcom Northstar 2 SoC
+
+config CLK_BCM_SR
+	bool "Broadcom Stingray clock support"
+	depends on ARCH_BCM_IPROC || COMPILE_TEST
+	select COMMON_CLK_IPROC
+	default ARCH_BCM_IPROC
+	help
+	  Enable common clock framework support for the Broadcom Stingray SoC

+ 1 - 0
drivers/clk/bcm/Makefile

@@ -10,3 +10,4 @@ obj-$(CONFIG_ARCH_BCM_53573)	+= clk-bcm53573-ilp.o
 obj-$(CONFIG_CLK_BCM_CYGNUS)	+= clk-cygnus.o
 obj-$(CONFIG_CLK_BCM_NSP)	+= clk-nsp.o
 obj-$(CONFIG_CLK_BCM_NS2)	+= clk-ns2.o
+obj-$(CONFIG_CLK_BCM_SR)	+= clk-sr.o

+ 58 - 7
drivers/clk/bcm/clk-bcm2835.c

@@ -530,6 +530,7 @@ struct bcm2835_clock_data {
 
 	bool is_vpu_clock;
 	bool is_mash_clock;
+	bool low_jitter;
 
 	u32 tcnt_mux;
 };
@@ -616,8 +617,10 @@ static unsigned long bcm2835_pll_get_rate(struct clk_hw *hw,
 	using_prediv = cprman_read(cprman, data->ana_reg_base + 4) &
 		data->ana->fb_prediv_mask;
 
-	if (using_prediv)
+	if (using_prediv) {
 		ndiv *= 2;
+		fdiv *= 2;
+	}
 
 	return bcm2835_pll_rate_from_divisors(parent_rate, ndiv, fdiv, pdiv);
 }
@@ -1124,7 +1127,8 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
 							int parent_idx,
 							unsigned long rate,
 							u32 *div,
-							unsigned long *prate)
+							unsigned long *prate,
+							unsigned long *avgrate)
 {
 	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 	struct bcm2835_cprman *cprman = clock->cprman;
@@ -1139,8 +1143,25 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
 		*prate = clk_hw_get_rate(parent);
 		*div = bcm2835_clock_choose_div(hw, rate, *prate, true);
 
-		return bcm2835_clock_rate_from_divisor(clock, *prate,
-						       *div);
+		*avgrate = bcm2835_clock_rate_from_divisor(clock, *prate, *div);
+
+		if (data->low_jitter && (*div & CM_DIV_FRAC_MASK)) {
+			unsigned long high, low;
+			u32 int_div = *div & ~CM_DIV_FRAC_MASK;
+
+			high = bcm2835_clock_rate_from_divisor(clock, *prate,
+							       int_div);
+			int_div += CM_DIV_FRAC_MASK + 1;
+			low = bcm2835_clock_rate_from_divisor(clock, *prate,
+							      int_div);
+
+			/*
+			 * Return a value which is the maximum deviation
+			 * below the ideal rate, for use as a metric.
+			 */
+			return *avgrate - max(*avgrate - low, high - *avgrate);
+		}
+		return *avgrate;
 	}
 
 	if (data->frac_bits)
@@ -1167,6 +1188,7 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
 
 	*div = curdiv << CM_DIV_FRAC_BITS;
 	*prate = curdiv * best_rate;
+	*avgrate = best_rate;
 
 	return best_rate;
 }
@@ -1178,6 +1200,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
 	bool current_parent_is_pllc;
 	unsigned long rate, best_rate = 0;
 	unsigned long prate, best_prate = 0;
+	unsigned long avgrate, best_avgrate = 0;
 	size_t i;
 	u32 div;
 
@@ -1202,11 +1225,13 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
 			continue;
 
 		rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
-							  &div, &prate);
+							  &div, &prate,
+							  &avgrate);
 		if (rate > best_rate && rate <= req->rate) {
 			best_parent = parent;
 			best_prate = prate;
 			best_rate = rate;
+			best_avgrate = avgrate;
 		}
 	}
 
@@ -1216,7 +1241,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
 	req->best_parent_hw = best_parent;
 	req->best_parent_rate = best_prate;
 
-	req->rate = best_rate;
+	req->rate = best_avgrate;
 
 	return 0;
 }
@@ -1516,6 +1541,31 @@ static const char *const bcm2835_clock_per_parents[] = {
 	.parents = bcm2835_clock_per_parents,				\
 	__VA_ARGS__)
 
+/*
+ * Restrict clock sources for the PCM peripheral to the oscillator and
+ * PLLD_PER because other source may have varying rates or be switched
+ * off.
+ *
+ * Prevent other sources from being selected by replacing their names in
+ * the list of potential parents with dummy entries (entry index is
+ * significant).
+ */
+static const char *const bcm2835_pcm_per_parents[] = {
+	"-",
+	"xosc",
+	"-",
+	"-",
+	"-",
+	"-",
+	"plld_per",
+	"-",
+};
+
+#define REGISTER_PCM_CLK(...)	REGISTER_CLK(				\
+	.num_mux_parents = ARRAY_SIZE(bcm2835_pcm_per_parents),		\
+	.parents = bcm2835_pcm_per_parents,				\
+	__VA_ARGS__)
+
 /* main vpu parent mux */
 static const char *const bcm2835_clock_vpu_parents[] = {
 	"gnd",
@@ -1993,13 +2043,14 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
 		.int_bits = 4,
 		.frac_bits = 8,
 		.tcnt_mux = 22),
-	[BCM2835_CLOCK_PCM]	= REGISTER_PER_CLK(
+	[BCM2835_CLOCK_PCM]	= REGISTER_PCM_CLK(
 		.name = "pcm",
 		.ctl_reg = CM_PCMCTL,
 		.div_reg = CM_PCMDIV,
 		.int_bits = 12,
 		.frac_bits = 12,
 		.is_mash_clock = true,
+		.low_jitter = true,
 		.tcnt_mux = 23),
 	[BCM2835_CLOCK_PWM]	= REGISTER_PER_CLK(
 		.name = "pwm",

+ 6 - 6
drivers/clk/bcm/clk-iproc-pll.c

@@ -617,12 +617,12 @@ static void iproc_pll_sw_cfg(struct iproc_pll *pll)
 	}
 }
 
-void __init iproc_pll_clk_setup(struct device_node *node,
-				const struct iproc_pll_ctrl *pll_ctrl,
-				const struct iproc_pll_vco_param *vco,
-				unsigned int num_vco_entries,
-				const struct iproc_clk_ctrl *clk_ctrl,
-				unsigned int num_clks)
+void iproc_pll_clk_setup(struct device_node *node,
+			 const struct iproc_pll_ctrl *pll_ctrl,
+			 const struct iproc_pll_vco_param *vco,
+			 unsigned int num_vco_entries,
+			 const struct iproc_clk_ctrl *clk_ctrl,
+			 unsigned int num_clks)
 {
 	int i, ret;
 	struct iproc_pll *pll;

+ 327 - 0
drivers/clk/bcm/clk-sr.c

@@ -0,0 +1,327 @@
+/*
+ * Copyright 2017 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation (the "GPL").
+ *
+ * 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 version 2 (GPLv2) for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 (GPLv2) along with this source code.
+ */
+
+#include <linux/err.h>
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/clock/bcm-sr.h>
+#include "clk-iproc.h"
+
+#define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
+
+#define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
+	.pwr_shift = ps, .iso_shift = is }
+
+#define SW_CTRL_VAL(o, s) { .offset = o, .shift = s, }
+
+#define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
+	.p_reset_shift = prs }
+
+#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, \
+	.ki_shift = kis, .ki_width = kiw, .kp_shift = kps, .kp_width = kpw, \
+	.ka_shift = kas, .ka_width = kaw }
+
+#define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }
+
+#define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
+	.hold_shift = hs, .bypass_shift = bs }
+
+
+static const struct iproc_pll_ctrl sr_genpll0 = {
+	.flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
+		IPROC_CLK_PLL_NEEDS_SW_CFG,
+	.aon = AON_VAL(0x0, 5, 1, 0),
+	.reset = RESET_VAL(0x0, 12, 11),
+	.dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
+	.sw_ctrl = SW_CTRL_VAL(0x10, 31),
+	.ndiv_int = REG_VAL(0x10, 20, 10),
+	.ndiv_frac = REG_VAL(0x10, 0, 20),
+	.pdiv = REG_VAL(0x14, 0, 4),
+	.status = REG_VAL(0x30, 12, 1),
+};
+
+static const struct iproc_clk_ctrl sr_genpll0_clk[] = {
+	[BCM_SR_GENPLL0_SATA_CLK] = {
+		.channel = BCM_SR_GENPLL0_SATA_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 6, 0, 12),
+		.mdiv = REG_VAL(0x18, 0, 9),
+	},
+	[BCM_SR_GENPLL0_SCR_CLK] = {
+		.channel = BCM_SR_GENPLL0_SCR_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 7, 1, 13),
+		.mdiv = REG_VAL(0x18, 10, 9),
+	},
+	[BCM_SR_GENPLL0_250M_CLK] = {
+		.channel = BCM_SR_GENPLL0_250M_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 8, 2, 14),
+		.mdiv = REG_VAL(0x18, 20, 9),
+	},
+	[BCM_SR_GENPLL0_PCIE_AXI_CLK] = {
+		.channel = BCM_SR_GENPLL0_PCIE_AXI_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 9, 3, 15),
+		.mdiv = REG_VAL(0x1c, 0, 9),
+	},
+	[BCM_SR_GENPLL0_PAXC_AXI_X2_CLK] = {
+		.channel = BCM_SR_GENPLL0_PAXC_AXI_X2_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 10, 4, 16),
+		.mdiv = REG_VAL(0x1c, 10, 9),
+	},
+	[BCM_SR_GENPLL0_PAXC_AXI_CLK] = {
+		.channel = BCM_SR_GENPLL0_PAXC_AXI_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 11, 5, 17),
+		.mdiv = REG_VAL(0x1c, 20, 9),
+	},
+};
+
+static int sr_genpll0_clk_init(struct platform_device *pdev)
+{
+	iproc_pll_clk_setup(pdev->dev.of_node,
+			    &sr_genpll0, NULL, 0, sr_genpll0_clk,
+			    ARRAY_SIZE(sr_genpll0_clk));
+	return 0;
+}
+
+static const struct iproc_pll_ctrl sr_genpll3 = {
+	.flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
+		IPROC_CLK_PLL_NEEDS_SW_CFG,
+	.aon = AON_VAL(0x0, 1, 19, 18),
+	.reset = RESET_VAL(0x0, 12, 11),
+	.dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
+	.sw_ctrl = SW_CTRL_VAL(0x10, 31),
+	.ndiv_int = REG_VAL(0x10, 20, 10),
+	.ndiv_frac = REG_VAL(0x10, 0, 20),
+	.pdiv = REG_VAL(0x14, 0, 4),
+	.status = REG_VAL(0x30, 12, 1),
+};
+
+static const struct iproc_clk_ctrl sr_genpll3_clk[] = {
+	[BCM_SR_GENPLL3_HSLS_CLK] = {
+		.channel = BCM_SR_GENPLL3_HSLS_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 6, 0, 12),
+		.mdiv = REG_VAL(0x18, 0, 9),
+	},
+	[BCM_SR_GENPLL3_SDIO_CLK] = {
+		.channel = BCM_SR_GENPLL3_SDIO_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 7, 1, 13),
+		.mdiv = REG_VAL(0x18, 10, 9),
+	},
+};
+
+static void sr_genpll3_clk_init(struct device_node *node)
+{
+	iproc_pll_clk_setup(node, &sr_genpll3, NULL, 0, sr_genpll3_clk,
+			    ARRAY_SIZE(sr_genpll3_clk));
+}
+CLK_OF_DECLARE(sr_genpll3_clk, "brcm,sr-genpll3", sr_genpll3_clk_init);
+
+static const struct iproc_pll_ctrl sr_genpll4 = {
+	.flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
+		IPROC_CLK_PLL_NEEDS_SW_CFG,
+	.aon = AON_VAL(0x0, 1, 25, 24),
+	.reset = RESET_VAL(0x0, 12, 11),
+	.dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
+	.sw_ctrl = SW_CTRL_VAL(0x10, 31),
+	.ndiv_int = REG_VAL(0x10, 20, 10),
+	.ndiv_frac = REG_VAL(0x10, 0, 20),
+	.pdiv = REG_VAL(0x14, 0, 4),
+	.status = REG_VAL(0x30, 12, 1),
+};
+
+static const struct iproc_clk_ctrl sr_genpll4_clk[] = {
+	[BCM_SR_GENPLL4_CCN_CLK] = {
+		.channel = BCM_SR_GENPLL4_CCN_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 6, 0, 12),
+		.mdiv = REG_VAL(0x18, 0, 9),
+	},
+};
+
+static int sr_genpll4_clk_init(struct platform_device *pdev)
+{
+	iproc_pll_clk_setup(pdev->dev.of_node,
+			    &sr_genpll4, NULL, 0, sr_genpll4_clk,
+			    ARRAY_SIZE(sr_genpll4_clk));
+	return 0;
+}
+
+static const struct iproc_pll_ctrl sr_genpll5 = {
+	.flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
+		IPROC_CLK_PLL_NEEDS_SW_CFG,
+	.aon = AON_VAL(0x0, 1, 1, 0),
+	.reset = RESET_VAL(0x0, 12, 11),
+	.dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
+	.sw_ctrl = SW_CTRL_VAL(0x10, 31),
+	.ndiv_int = REG_VAL(0x10, 20, 10),
+	.ndiv_frac = REG_VAL(0x10, 0, 20),
+	.pdiv = REG_VAL(0x14, 0, 4),
+	.status = REG_VAL(0x30, 12, 1),
+};
+
+static const struct iproc_clk_ctrl sr_genpll5_clk[] = {
+	[BCM_SR_GENPLL5_FS_CLK] = {
+		.channel = BCM_SR_GENPLL5_FS_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 6, 0, 12),
+		.mdiv = REG_VAL(0x18, 0, 9),
+	},
+	[BCM_SR_GENPLL5_SPU_CLK] = {
+		.channel = BCM_SR_GENPLL5_SPU_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x4, 6, 0, 12),
+		.mdiv = REG_VAL(0x18, 10, 9),
+	},
+};
+
+static int sr_genpll5_clk_init(struct platform_device *pdev)
+{
+	iproc_pll_clk_setup(pdev->dev.of_node,
+			    &sr_genpll5, NULL, 0, sr_genpll5_clk,
+			    ARRAY_SIZE(sr_genpll5_clk));
+	return 0;
+}
+
+static const struct iproc_pll_ctrl sr_lcpll0 = {
+	.flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
+	.aon = AON_VAL(0x0, 2, 19, 18),
+	.reset = RESET_VAL(0x0, 31, 30),
+	.sw_ctrl = SW_CTRL_VAL(0x4, 31),
+	.ndiv_int = REG_VAL(0x4, 16, 10),
+	.pdiv = REG_VAL(0x4, 26, 4),
+	.status = REG_VAL(0x38, 12, 1),
+};
+
+static const struct iproc_clk_ctrl sr_lcpll0_clk[] = {
+	[BCM_SR_LCPLL0_SATA_REF_CLK] = {
+		.channel = BCM_SR_LCPLL0_SATA_REF_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x0, 7, 1, 13),
+		.mdiv = REG_VAL(0x14, 0, 9),
+	},
+	[BCM_SR_LCPLL0_USB_REF_CLK] = {
+		.channel = BCM_SR_LCPLL0_USB_REF_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x0, 8, 2, 14),
+		.mdiv = REG_VAL(0x14, 10, 9),
+	},
+	[BCM_SR_LCPLL0_SATA_REFPN_CLK] = {
+		.channel = BCM_SR_LCPLL0_SATA_REFPN_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x0, 9, 3, 15),
+		.mdiv = REG_VAL(0x14, 20, 9),
+	},
+};
+
+static int sr_lcpll0_clk_init(struct platform_device *pdev)
+{
+	iproc_pll_clk_setup(pdev->dev.of_node,
+			    &sr_lcpll0, NULL, 0, sr_lcpll0_clk,
+			    ARRAY_SIZE(sr_lcpll0_clk));
+	return 0;
+}
+
+static const struct iproc_pll_ctrl sr_lcpll1 = {
+	.flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
+	.aon = AON_VAL(0x0, 2, 22, 21),
+	.reset = RESET_VAL(0x0, 31, 30),
+	.sw_ctrl = SW_CTRL_VAL(0x4, 31),
+	.ndiv_int = REG_VAL(0x4, 16, 10),
+	.pdiv = REG_VAL(0x4, 26, 4),
+	.status = REG_VAL(0x38, 12, 1),
+};
+
+static const struct iproc_clk_ctrl sr_lcpll1_clk[] = {
+	[BCM_SR_LCPLL1_WAN_CLK] = {
+		.channel = BCM_SR_LCPLL1_WAN_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x0, 7, 1, 13),
+		.mdiv = REG_VAL(0x14, 0, 9),
+	},
+};
+
+static int sr_lcpll1_clk_init(struct platform_device *pdev)
+{
+	iproc_pll_clk_setup(pdev->dev.of_node,
+			    &sr_lcpll1, NULL, 0, sr_lcpll1_clk,
+			    ARRAY_SIZE(sr_lcpll1_clk));
+	return 0;
+}
+
+static const struct iproc_pll_ctrl sr_lcpll_pcie = {
+	.flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
+	.aon = AON_VAL(0x0, 2, 25, 24),
+	.reset = RESET_VAL(0x0, 31, 30),
+	.sw_ctrl = SW_CTRL_VAL(0x4, 31),
+	.ndiv_int = REG_VAL(0x4, 16, 10),
+	.pdiv = REG_VAL(0x4, 26, 4),
+	.status = REG_VAL(0x38, 12, 1),
+};
+
+static const struct iproc_clk_ctrl sr_lcpll_pcie_clk[] = {
+	[BCM_SR_LCPLL_PCIE_PHY_REF_CLK] = {
+		.channel = BCM_SR_LCPLL_PCIE_PHY_REF_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = ENABLE_VAL(0x0, 7, 1, 13),
+		.mdiv = REG_VAL(0x14, 0, 9),
+	},
+};
+
+static int sr_lcpll_pcie_clk_init(struct platform_device *pdev)
+{
+	iproc_pll_clk_setup(pdev->dev.of_node,
+			    &sr_lcpll_pcie, NULL, 0, sr_lcpll_pcie_clk,
+			    ARRAY_SIZE(sr_lcpll_pcie_clk));
+	return 0;
+}
+
+static const struct of_device_id sr_clk_dt_ids[] = {
+	{ .compatible = "brcm,sr-genpll0", .data = sr_genpll0_clk_init },
+	{ .compatible = "brcm,sr-genpll4", .data = sr_genpll4_clk_init },
+	{ .compatible = "brcm,sr-genpll5", .data = sr_genpll5_clk_init },
+	{ .compatible = "brcm,sr-lcpll0", .data = sr_lcpll0_clk_init },
+	{ .compatible = "brcm,sr-lcpll1", .data = sr_lcpll1_clk_init },
+	{ .compatible = "brcm,sr-lcpll-pcie", .data = sr_lcpll_pcie_clk_init },
+	{ /* sentinel */ }
+};
+
+static int sr_clk_probe(struct platform_device *pdev)
+{
+	int (*probe_func)(struct platform_device *);
+
+	probe_func = of_device_get_match_data(&pdev->dev);
+	if (!probe_func)
+		return -ENODEV;
+
+	return probe_func(pdev);
+}
+
+static struct platform_driver sr_clk_driver = {
+	.driver = {
+		.name = "sr-clk",
+		.of_match_table = sr_clk_dt_ids,
+	},
+	.probe = sr_clk_probe,
+};
+builtin_platform_driver(sr_clk_driver);

+ 157 - 0
drivers/clk/clk-bulk.c

@@ -0,0 +1,157 @@
+/*
+ * Copyright 2017 NXP
+ *
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/export.h>
+
+void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)
+{
+	while (--num_clks >= 0) {
+		clk_put(clks[num_clks].clk);
+		clks[num_clks].clk = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(clk_bulk_put);
+
+int __must_check clk_bulk_get(struct device *dev, 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 = clk_get(dev, clks[i].id);
+		if (IS_ERR(clks[i].clk)) {
+			ret = PTR_ERR(clks[i].clk);
+			dev_err(dev, "Failed to get clk '%s': %d\n",
+				clks[i].id, ret);
+			clks[i].clk = NULL;
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	clk_bulk_put(i, clks);
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_bulk_get);
+
+#ifdef CONFIG_HAVE_CLK_PREPARE
+
+/**
+ * clk_bulk_unprepare - undo preparation of a set of clock sources
+ * @num_clks: the number of clk_bulk_data
+ * @clks: the clk_bulk_data table being unprepared
+ *
+ * clk_bulk_unprepare may sleep, which differentiates it from clk_bulk_disable.
+ * Returns 0 on success, -EERROR otherwise.
+ */
+void clk_bulk_unprepare(int num_clks, const struct clk_bulk_data *clks)
+{
+	while (--num_clks >= 0)
+		clk_unprepare(clks[num_clks].clk);
+}
+EXPORT_SYMBOL_GPL(clk_bulk_unprepare);
+
+/**
+ * clk_bulk_prepare - prepare a set of clocks
+ * @num_clks: the number of clk_bulk_data
+ * @clks: the clk_bulk_data table being prepared
+ *
+ * clk_bulk_prepare may sleep, which differentiates it from clk_bulk_enable.
+ * Returns 0 on success, -EERROR otherwise.
+ */
+int __must_check clk_bulk_prepare(int num_clks,
+				  const struct clk_bulk_data *clks)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i < num_clks; i++) {
+		ret = clk_prepare(clks[i].clk);
+		if (ret) {
+			pr_err("Failed to prepare clk '%s': %d\n",
+				clks[i].id, ret);
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	clk_bulk_unprepare(i, clks);
+
+	return  ret;
+}
+
+#endif /* CONFIG_HAVE_CLK_PREPARE */
+
+/**
+ * clk_bulk_disable - gate a set of clocks
+ * @num_clks: the number of clk_bulk_data
+ * @clks: the clk_bulk_data table being gated
+ *
+ * clk_bulk_disable must not sleep, which differentiates it from
+ * clk_bulk_unprepare. clk_bulk_disable must be called before
+ * clk_bulk_unprepare.
+ */
+void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks)
+{
+
+	while (--num_clks >= 0)
+		clk_disable(clks[num_clks].clk);
+}
+EXPORT_SYMBOL_GPL(clk_bulk_disable);
+
+/**
+ * clk_bulk_enable - ungate a set of clocks
+ * @num_clks: the number of clk_bulk_data
+ * @clks: the clk_bulk_data table being ungated
+ *
+ * clk_bulk_enable must not sleep
+ * Returns 0 on success, -EERROR otherwise.
+ */
+int __must_check clk_bulk_enable(int num_clks, const struct clk_bulk_data *clks)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i < num_clks; i++) {
+		ret = clk_enable(clks[i].clk);
+		if (ret) {
+			pr_err("Failed to enable clk '%s': %d\n",
+				clks[i].id, ret);
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	clk_bulk_disable(i, clks);
+
+	return  ret;
+}
+EXPORT_SYMBOL_GPL(clk_bulk_enable);

+ 1 - 1
drivers/clk/clk-conf.c

@@ -109,7 +109,7 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
 
 			rc = clk_set_rate(clk, rate);
 			if (rc < 0)
-				pr_err("clk: couldn't set %s clk rate to %d (%d), current rate: %ld\n",
+				pr_err("clk: couldn't set %s clk rate to %u (%d), current rate: %lu\n",
 				       __clk_get_name(clk), rate, rc,
 				       clk_get_rate(clk));
 			clk_put(clk);

+ 36 - 0
drivers/clk/clk-devres.c

@@ -34,6 +34,42 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL(devm_clk_get);
 
+struct clk_bulk_devres {
+	struct clk_bulk_data *clks;
+	int num_clks;
+};
+
+static void devm_clk_bulk_release(struct device *dev, void *res)
+{
+	struct clk_bulk_devres *devres = res;
+
+	clk_bulk_put(devres->num_clks, devres->clks);
+}
+
+int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
+		      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(dev, num_clks, clks);
+	if (!ret) {
+		devres->clks = clks;
+		devres->num_clks = num_clks;
+		devres_add(dev, devres);
+	} else {
+		devres_free(devres);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(devm_clk_bulk_get);
+
 static int devm_clk_match(struct device *dev, void *res, void *data)
 {
 	struct clk **c = res;

+ 10 - 9
drivers/clk/clk-divider.c

@@ -275,7 +275,8 @@ static int _next_div(const struct clk_div_table *table, int div,
 	return div;
 }
 
-static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
+static int clk_divider_bestdiv(struct clk_hw *hw, struct clk_hw *parent,
+			       unsigned long rate,
 			       unsigned long *best_parent_rate,
 			       const struct clk_div_table *table, u8 width,
 			       unsigned long flags)
@@ -314,8 +315,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 			*best_parent_rate = parent_rate_saved;
 			return i;
 		}
-		parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
-					       rate * i);
+		parent_rate = clk_hw_round_rate(parent, rate * i);
 		now = DIV_ROUND_UP_ULL((u64)parent_rate, i);
 		if (_is_best_div(rate, now, best, flags)) {
 			bestdiv = i;
@@ -326,23 +326,24 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 
 	if (!bestdiv) {
 		bestdiv = _get_maxdiv(table, width, flags);
-		*best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), 1);
+		*best_parent_rate = clk_hw_round_rate(parent, 1);
 	}
 
 	return bestdiv;
 }
 
-long divider_round_rate(struct clk_hw *hw, unsigned long rate,
-			unsigned long *prate, const struct clk_div_table *table,
-			u8 width, unsigned long flags)
+long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
+			       unsigned long rate, unsigned long *prate,
+			       const struct clk_div_table *table,
+			       u8 width, unsigned long flags)
 {
 	int div;
 
-	div = clk_divider_bestdiv(hw, rate, prate, table, width, flags);
+	div = clk_divider_bestdiv(hw, parent, rate, prate, table, width, flags);
 
 	return DIV_ROUND_UP_ULL((u64)*prate, div);
 }
-EXPORT_SYMBOL_GPL(divider_round_rate);
+EXPORT_SYMBOL_GPL(divider_round_rate_parent);
 
 static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
 				unsigned long *prate)

+ 455 - 0
drivers/clk/clk-gemini.c

@@ -0,0 +1,455 @@
+/*
+ * Cortina Gemini SoC Clock Controller driver
+ * Copyright (c) 2017 Linus Walleij <linus.walleij@linaro.org>
+ */
+
+#define pr_fmt(fmt) "clk-gemini: " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+#include <linux/reset-controller.h>
+#include <dt-bindings/reset/cortina,gemini-reset.h>
+#include <dt-bindings/clock/cortina,gemini-clock.h>
+
+/* Globally visible clocks */
+static DEFINE_SPINLOCK(gemini_clk_lock);
+
+#define GEMINI_GLOBAL_STATUS		0x04
+#define PLL_OSC_SEL			BIT(30)
+#define AHBSPEED_SHIFT			(15)
+#define AHBSPEED_MASK			0x07
+#define CPU_AHB_RATIO_SHIFT		(18)
+#define CPU_AHB_RATIO_MASK		0x03
+
+#define GEMINI_GLOBAL_PLL_CONTROL	0x08
+
+#define GEMINI_GLOBAL_SOFT_RESET	0x0c
+
+#define GEMINI_GLOBAL_MISC_CONTROL	0x30
+#define PCI_CLK_66MHZ			BIT(18)
+#define PCI_CLK_OE			BIT(17)
+
+#define GEMINI_GLOBAL_CLOCK_CONTROL	0x34
+#define PCI_CLKRUN_EN			BIT(16)
+#define TVC_HALFDIV_SHIFT		(24)
+#define TVC_HALFDIV_MASK		0x1f
+#define SECURITY_CLK_SEL		BIT(29)
+
+#define GEMINI_GLOBAL_PCI_DLL_CONTROL	0x44
+#define PCI_DLL_BYPASS			BIT(31)
+#define PCI_DLL_TAP_SEL_MASK		0x1f
+
+/**
+ * struct gemini_data_data - Gemini gated clocks
+ * @bit_idx: the bit used to gate this clock in the clock register
+ * @name: the clock name
+ * @parent_name: the name of the parent clock
+ * @flags: standard clock framework flags
+ */
+struct gemini_gate_data {
+	u8 bit_idx;
+	const char *name;
+	const char *parent_name;
+	unsigned long flags;
+};
+
+/**
+ * struct clk_gemini_pci - Gemini PCI clock
+ * @hw: corresponding clock hardware entry
+ * @map: regmap to access the registers
+ * @rate: current rate
+ */
+struct clk_gemini_pci {
+	struct clk_hw hw;
+	struct regmap *map;
+	unsigned long rate;
+};
+
+/**
+ * struct gemini_reset - gemini reset controller
+ * @map: regmap to access the containing system controller
+ * @rcdev: reset controller device
+ */
+struct gemini_reset {
+	struct regmap *map;
+	struct reset_controller_dev rcdev;
+};
+
+/* Keeps track of all clocks */
+static struct clk_hw_onecell_data *gemini_clk_data;
+
+static const struct gemini_gate_data gemini_gates[] = {
+	{ 1, "security-gate", "secdiv", 0 },
+	{ 2, "gmac0-gate", "ahb", 0 },
+	{ 3, "gmac1-gate", "ahb", 0 },
+	{ 4, "sata0-gate", "ahb", 0 },
+	{ 5, "sata1-gate", "ahb", 0 },
+	{ 6, "usb0-gate", "ahb", 0 },
+	{ 7, "usb1-gate", "ahb", 0 },
+	{ 8, "ide-gate", "ahb", 0 },
+	{ 9, "pci-gate", "ahb", 0 },
+	/*
+	 * The DDR controller may never have a driver, but certainly must
+	 * not be gated off.
+	 */
+	{ 10, "ddr-gate", "ahb", CLK_IS_CRITICAL },
+	/*
+	 * The flash controller must be on to access NOR flash through the
+	 * memory map.
+	 */
+	{ 11, "flash-gate", "ahb", CLK_IGNORE_UNUSED },
+	{ 12, "tvc-gate", "ahb", 0 },
+	{ 13, "boot-gate", "apb", 0 },
+};
+
+#define to_pciclk(_hw) container_of(_hw, struct clk_gemini_pci, hw)
+
+#define to_gemini_reset(p) container_of((p), struct gemini_reset, rcdev)
+
+static unsigned long gemini_pci_recalc_rate(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	struct clk_gemini_pci *pciclk = to_pciclk(hw);
+	u32 val;
+
+	regmap_read(pciclk->map, GEMINI_GLOBAL_MISC_CONTROL, &val);
+	if (val & PCI_CLK_66MHZ)
+		return 66000000;
+	return 33000000;
+}
+
+static long gemini_pci_round_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long *prate)
+{
+	/* We support 33 and 66 MHz */
+	if (rate < 48000000)
+		return 33000000;
+	return 66000000;
+}
+
+static int gemini_pci_set_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long parent_rate)
+{
+	struct clk_gemini_pci *pciclk = to_pciclk(hw);
+
+	if (rate == 33000000)
+		return regmap_update_bits(pciclk->map,
+					  GEMINI_GLOBAL_MISC_CONTROL,
+					  PCI_CLK_66MHZ, 0);
+	if (rate == 66000000)
+		return regmap_update_bits(pciclk->map,
+					  GEMINI_GLOBAL_MISC_CONTROL,
+					  0, PCI_CLK_66MHZ);
+	return -EINVAL;
+}
+
+static int gemini_pci_enable(struct clk_hw *hw)
+{
+	struct clk_gemini_pci *pciclk = to_pciclk(hw);
+
+	regmap_update_bits(pciclk->map, GEMINI_GLOBAL_CLOCK_CONTROL,
+			   0, PCI_CLKRUN_EN);
+	regmap_update_bits(pciclk->map,
+			   GEMINI_GLOBAL_MISC_CONTROL,
+			   0, PCI_CLK_OE);
+	return 0;
+}
+
+static void gemini_pci_disable(struct clk_hw *hw)
+{
+	struct clk_gemini_pci *pciclk = to_pciclk(hw);
+
+	regmap_update_bits(pciclk->map,
+			   GEMINI_GLOBAL_MISC_CONTROL,
+			   PCI_CLK_OE, 0);
+	regmap_update_bits(pciclk->map, GEMINI_GLOBAL_CLOCK_CONTROL,
+			   PCI_CLKRUN_EN, 0);
+}
+
+static int gemini_pci_is_enabled(struct clk_hw *hw)
+{
+	struct clk_gemini_pci *pciclk = to_pciclk(hw);
+	unsigned int val;
+
+	regmap_read(pciclk->map, GEMINI_GLOBAL_CLOCK_CONTROL, &val);
+	return !!(val & PCI_CLKRUN_EN);
+}
+
+static const struct clk_ops gemini_pci_clk_ops = {
+	.recalc_rate = gemini_pci_recalc_rate,
+	.round_rate = gemini_pci_round_rate,
+	.set_rate = gemini_pci_set_rate,
+	.enable = gemini_pci_enable,
+	.disable = gemini_pci_disable,
+	.is_enabled = gemini_pci_is_enabled,
+};
+
+static struct clk_hw *gemini_pci_clk_setup(const char *name,
+					   const char *parent_name,
+					   struct regmap *map)
+{
+	struct clk_gemini_pci *pciclk;
+	struct clk_init_data init;
+	int ret;
+
+	pciclk = kzalloc(sizeof(*pciclk), GFP_KERNEL);
+	if (!pciclk)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &gemini_pci_clk_ops;
+	init.flags = 0;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+	pciclk->map = map;
+	pciclk->hw.init = &init;
+
+	ret = clk_hw_register(NULL, &pciclk->hw);
+	if (ret) {
+		kfree(pciclk);
+		return ERR_PTR(ret);
+	}
+
+	return &pciclk->hw;
+}
+
+/*
+ * This is a self-deasserting reset controller.
+ */
+static int gemini_reset(struct reset_controller_dev *rcdev,
+			unsigned long id)
+{
+	struct gemini_reset *gr = to_gemini_reset(rcdev);
+
+	/* Manual says to always set BIT 30 (CPU1) to 1 */
+	return regmap_write(gr->map,
+			    GEMINI_GLOBAL_SOFT_RESET,
+			    BIT(GEMINI_RESET_CPU1) | BIT(id));
+}
+
+static int gemini_reset_status(struct reset_controller_dev *rcdev,
+			     unsigned long id)
+{
+	struct gemini_reset *gr = to_gemini_reset(rcdev);
+	u32 val;
+	int ret;
+
+	ret = regmap_read(gr->map, GEMINI_GLOBAL_SOFT_RESET, &val);
+	if (ret)
+		return ret;
+
+	return !!(val & BIT(id));
+}
+
+static const struct reset_control_ops gemini_reset_ops = {
+	.reset = gemini_reset,
+	.status = gemini_reset_status,
+};
+
+static int gemini_clk_probe(struct platform_device *pdev)
+{
+	/* Gives the fracions 1x, 1.5x, 1.85x and 2x */
+	unsigned int cpu_ahb_mult[4] = { 1, 3, 24, 2 };
+	unsigned int cpu_ahb_div[4] = { 1, 2, 13, 1 };
+	void __iomem *base;
+	struct gemini_reset *gr;
+	struct regmap *map;
+	struct clk_hw *hw;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	unsigned int mult, div;
+	struct resource *res;
+	u32 val;
+	int ret;
+	int i;
+
+	gr = devm_kzalloc(dev, sizeof(*gr), GFP_KERNEL);
+	if (!gr)
+		return -ENOMEM;
+
+	/* Remap the system controller for the exclusive register */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	map = syscon_node_to_regmap(np);
+	if (IS_ERR(map)) {
+		dev_err(dev, "no syscon regmap\n");
+		return PTR_ERR(map);
+	}
+
+	gr->map = map;
+	gr->rcdev.owner = THIS_MODULE;
+	gr->rcdev.nr_resets = 32;
+	gr->rcdev.ops = &gemini_reset_ops;
+	gr->rcdev.of_node = np;
+
+	ret = devm_reset_controller_register(dev, &gr->rcdev);
+	if (ret) {
+		dev_err(dev, "could not register reset controller\n");
+		return ret;
+	}
+
+	/* RTC clock 32768 Hz */
+	hw = clk_hw_register_fixed_rate(NULL, "rtc", NULL, 0, 32768);
+	gemini_clk_data->hws[GEMINI_CLK_RTC] = hw;
+
+	/* CPU clock derived as a fixed ratio from the AHB clock */
+	regmap_read(map, GEMINI_GLOBAL_STATUS, &val);
+	val >>= CPU_AHB_RATIO_SHIFT;
+	val &= CPU_AHB_RATIO_MASK;
+	hw = clk_hw_register_fixed_factor(NULL, "cpu", "ahb", 0,
+					  cpu_ahb_mult[val],
+					  cpu_ahb_div[val]);
+	gemini_clk_data->hws[GEMINI_CLK_CPU] = hw;
+
+	/* Security clock is 1:1 or 0.75 of APB */
+	regmap_read(map, GEMINI_GLOBAL_CLOCK_CONTROL, &val);
+	if (val & SECURITY_CLK_SEL) {
+		mult = 1;
+		div = 1;
+	} else {
+		mult = 3;
+		div = 4;
+	}
+	hw = clk_hw_register_fixed_factor(NULL, "secdiv", "ahb", 0, mult, div);
+
+	/*
+	 * These are the leaf gates, at boot no clocks are gated.
+	 */
+	for (i = 0; i < ARRAY_SIZE(gemini_gates); i++) {
+		const struct gemini_gate_data *gd;
+
+		gd = &gemini_gates[i];
+		gemini_clk_data->hws[GEMINI_CLK_GATES + i] =
+			clk_hw_register_gate(NULL, gd->name,
+					     gd->parent_name,
+					     gd->flags,
+					     base + GEMINI_GLOBAL_CLOCK_CONTROL,
+					     gd->bit_idx,
+					     CLK_GATE_SET_TO_DISABLE,
+					     &gemini_clk_lock);
+	}
+
+	/*
+	 * The TV Interface Controller has a 5-bit half divider register.
+	 * This clock is supposed to be 27MHz as this is an exact multiple
+	 * of PAL and NTSC frequencies. The register is undocumented :(
+	 * FIXME: figure out the parent and how the divider works.
+	 */
+	mult = 1;
+	div = ((val >> TVC_HALFDIV_SHIFT) & TVC_HALFDIV_MASK);
+	dev_dbg(dev, "TVC half divider value = %d\n", div);
+	div += 1;
+	hw = clk_hw_register_fixed_rate(NULL, "tvcdiv", "xtal", 0, 27000000);
+	gemini_clk_data->hws[GEMINI_CLK_TVC] = hw;
+
+	/* FIXME: very unclear what the parent is */
+	hw = gemini_pci_clk_setup("PCI", "xtal", map);
+	gemini_clk_data->hws[GEMINI_CLK_PCI] = hw;
+
+	/* FIXME: very unclear what the parent is */
+	hw = clk_hw_register_fixed_rate(NULL, "uart", "xtal", 0, 48000000);
+	gemini_clk_data->hws[GEMINI_CLK_UART] = hw;
+
+	return 0;
+}
+
+static const struct of_device_id gemini_clk_dt_ids[] = {
+	{ .compatible = "cortina,gemini-syscon", },
+	{ /* sentinel */ },
+};
+
+static struct platform_driver gemini_clk_driver = {
+	.probe  = gemini_clk_probe,
+	.driver = {
+		.name = "gemini-clk",
+		.of_match_table = gemini_clk_dt_ids,
+		.suppress_bind_attrs = true,
+	},
+};
+builtin_platform_driver(gemini_clk_driver);
+
+static void __init gemini_cc_init(struct device_node *np)
+{
+	struct regmap *map;
+	struct clk_hw *hw;
+	unsigned long freq;
+	unsigned int mult, div;
+	u32 val;
+	int ret;
+	int i;
+
+	gemini_clk_data = kzalloc(sizeof(*gemini_clk_data) +
+			sizeof(*gemini_clk_data->hws) * GEMINI_NUM_CLKS,
+			GFP_KERNEL);
+	if (!gemini_clk_data)
+		return;
+
+	/*
+	 * This way all clock fetched before the platform device probes,
+	 * except those we assign here for early use, will be deferred.
+	 */
+	for (i = 0; i < GEMINI_NUM_CLKS; i++)
+		gemini_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER);
+
+	map = syscon_node_to_regmap(np);
+	if (IS_ERR(map)) {
+		pr_err("no syscon regmap\n");
+		return;
+	}
+	/*
+	 * We check that the regmap works on this very first access,
+	 * but as this is an MMIO-backed regmap, subsequent regmap
+	 * access is not going to fail and we skip error checks from
+	 * this point.
+	 */
+	ret = regmap_read(map, GEMINI_GLOBAL_STATUS, &val);
+	if (ret) {
+		pr_err("failed to read global status register\n");
+		return;
+	}
+
+	/*
+	 * XTAL is the crystal oscillator, 60 or 30 MHz selected from
+	 * strap pin E6
+	 */
+	if (val & PLL_OSC_SEL)
+		freq = 30000000;
+	else
+		freq = 60000000;
+	hw = clk_hw_register_fixed_rate(NULL, "xtal", NULL, 0, freq);
+	pr_debug("main crystal @%lu MHz\n", freq / 1000000);
+
+	/* VCO clock derived from the crystal */
+	mult = 13 + ((val >> AHBSPEED_SHIFT) & AHBSPEED_MASK);
+	div = 2;
+	/* If we run on 30 MHz crystal we have to multiply with two */
+	if (val & PLL_OSC_SEL)
+		mult *= 2;
+	hw = clk_hw_register_fixed_factor(NULL, "vco", "xtal", 0, mult, div);
+
+	/* The AHB clock is always 1/3 of the VCO */
+	hw = clk_hw_register_fixed_factor(NULL, "ahb", "vco", 0, 1, 3);
+	gemini_clk_data->hws[GEMINI_CLK_AHB] = hw;
+
+	/* The APB clock is always 1/6 of the AHB */
+	hw = clk_hw_register_fixed_factor(NULL, "apb", "ahb", 0, 1, 6);
+	gemini_clk_data->hws[GEMINI_CLK_APB] = hw;
+
+	/* Register the clocks to be accessed by the device tree */
+	gemini_clk_data->num = GEMINI_NUM_CLKS;
+	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, gemini_clk_data);
+}
+CLK_OF_DECLARE_DRIVER(gemini_cc, "cortina,gemini-syscon", gemini_cc_init);

+ 1 - 0
drivers/clk/clk-palmas.c

@@ -229,6 +229,7 @@ static int palmas_clks_init_configure(struct palmas_clock_info *cinfo)
 		if (ret < 0) {
 			dev_err(cinfo->dev, "Ext config for %s failed, %d\n",
 				cinfo->clk_desc->clk_name, ret);
+			clk_unprepare(cinfo->hw.clk);
 			return ret;
 		}
 	}

+ 77 - 14
drivers/clk/clk-qoriq.c

@@ -87,7 +87,7 @@ struct clockgen {
 	struct device_node *node;
 	void __iomem *regs;
 	struct clockgen_chipinfo info; /* mutable copy */
-	struct clk *sysclk;
+	struct clk *sysclk, *coreclk;
 	struct clockgen_pll pll[6];
 	struct clk *cmux[NUM_CMUX];
 	struct clk *hwaccel[NUM_HWACCEL];
@@ -904,7 +904,12 @@ static void __init create_muxes(struct clockgen *cg)
 
 static void __init clockgen_init(struct device_node *np);
 
-/* Legacy nodes may get probed before the parent clockgen node */
+/*
+ * Legacy nodes may get probed before the parent clockgen node.
+ * It is assumed that device trees with legacy nodes will not
+ * contain a "clocks" property -- otherwise the input clocks may
+ * not be initialized at this point.
+ */
 static void __init legacy_init_clockgen(struct device_node *np)
 {
 	if (!clockgen.node)
@@ -945,18 +950,13 @@ static struct clk __init
 	return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
 }
 
-static struct clk *sysclk_from_parent(const char *name)
+static struct clk __init *input_clock(const char *name, struct clk *clk)
 {
-	struct clk *clk;
-	const char *parent_name;
-
-	clk = of_clk_get(clockgen.node, 0);
-	if (IS_ERR(clk))
-		return clk;
+	const char *input_name;
 
 	/* Register the input clock under the desired name. */
-	parent_name = __clk_get_name(clk);
-	clk = clk_register_fixed_factor(NULL, name, parent_name,
+	input_name = __clk_get_name(clk);
+	clk = clk_register_fixed_factor(NULL, name, input_name,
 					0, 1, 1);
 	if (IS_ERR(clk))
 		pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
@@ -965,6 +965,29 @@ static struct clk *sysclk_from_parent(const char *name)
 	return clk;
 }
 
+static struct clk __init *input_clock_by_name(const char *name,
+					      const char *dtname)
+{
+	struct clk *clk;
+
+	clk = of_clk_get_by_name(clockgen.node, dtname);
+	if (IS_ERR(clk))
+		return clk;
+
+	return input_clock(name, clk);
+}
+
+static struct clk __init *input_clock_by_index(const char *name, int idx)
+{
+	struct clk *clk;
+
+	clk = of_clk_get(clockgen.node, 0);
+	if (IS_ERR(clk))
+		return clk;
+
+	return input_clock(name, clk);
+}
+
 static struct clk * __init create_sysclk(const char *name)
 {
 	struct device_node *sysclk;
@@ -974,7 +997,11 @@ static struct clk * __init create_sysclk(const char *name)
 	if (!IS_ERR(clk))
 		return clk;
 
-	clk = sysclk_from_parent(name);
+	clk = input_clock_by_name(name, "sysclk");
+	if (!IS_ERR(clk))
+		return clk;
+
+	clk = input_clock_by_index(name, 0);
 	if (!IS_ERR(clk))
 		return clk;
 
@@ -985,7 +1012,27 @@ static struct clk * __init create_sysclk(const char *name)
 			return clk;
 	}
 
-	pr_err("%s: No input clock\n", __func__);
+	pr_err("%s: No input sysclk\n", __func__);
+	return NULL;
+}
+
+static struct clk * __init create_coreclk(const char *name)
+{
+	struct clk *clk;
+
+	clk = input_clock_by_name(name, "coreclk");
+	if (!IS_ERR(clk))
+		return clk;
+
+	/*
+	 * This indicates a mix of legacy nodes with the new coreclk
+	 * mechanism, which should never happen.  If this error occurs,
+	 * don't use the wrong input clock just because coreclk isn't
+	 * ready yet.
+	 */
+	if (WARN_ON(PTR_ERR(clk) == -EPROBE_DEFER))
+		return clk;
+
 	return NULL;
 }
 
@@ -1008,11 +1055,19 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
 	u32 __iomem *reg;
 	u32 mult;
 	struct clockgen_pll *pll = &cg->pll[idx];
+	const char *input = "cg-sysclk";
 	int i;
 
 	if (!(cg->info.pll_mask & (1 << idx)))
 		return;
 
+	if (cg->coreclk && idx != PLATFORM_PLL) {
+		if (IS_ERR(cg->coreclk))
+			return;
+
+		input = "cg-coreclk";
+	}
+
 	if (cg->info.flags & CG_VER3) {
 		switch (idx) {
 		case PLATFORM_PLL:
@@ -1063,7 +1118,7 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
 			 "cg-pll%d-div%d", idx, i + 1);
 
 		clk = clk_register_fixed_factor(NULL,
-				pll->div[i].name, "cg-sysclk", 0, mult, i + 1);
+				pll->div[i].name, input, 0, mult, i + 1);
 		if (IS_ERR(clk)) {
 			pr_err("%s: %s: register failed %ld\n",
 			       __func__, pll->div[i].name, PTR_ERR(clk));
@@ -1200,6 +1255,13 @@ static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data)
 			goto bad_args;
 		clk = pll->div[idx].clk;
 		break;
+	case 5:
+		if (idx != 0)
+			goto bad_args;
+		clk = cg->coreclk;
+		if (IS_ERR(clk))
+			clk = NULL;
+		break;
 	default:
 		goto bad_args;
 	}
@@ -1311,6 +1373,7 @@ static void __init clockgen_init(struct device_node *np)
 		clockgen.info.flags |= CG_CMUX_GE_PLAT;
 
 	clockgen.sysclk = create_sysclk("cg-sysclk");
+	clockgen.coreclk = create_coreclk("cg-coreclk");
 	create_plls(&clockgen);
 	create_muxes(&clockgen);
 

+ 8 - 6
drivers/clk/clk-scpi.c

@@ -71,15 +71,15 @@ static const struct clk_ops scpi_clk_ops = {
 };
 
 /* find closest match to given frequency in OPP table */
-static int __scpi_dvfs_round_rate(struct scpi_clk *clk, unsigned long rate)
+static long __scpi_dvfs_round_rate(struct scpi_clk *clk, unsigned long rate)
 {
 	int idx;
-	u32 fmin = 0, fmax = ~0, ftmp;
+	unsigned long fmin = 0, fmax = ~0, ftmp;
 	const struct scpi_opp *opp = clk->info->opps;
 
 	for (idx = 0; idx < clk->info->count; idx++, opp++) {
 		ftmp = opp->freq;
-		if (ftmp >= (u32)rate) {
+		if (ftmp >= rate) {
 			if (ftmp <= fmax)
 				fmax = ftmp;
 			break;
@@ -245,10 +245,12 @@ static int scpi_clk_add(struct device *dev, struct device_node *np,
 		sclk->id = val;
 
 		err = scpi_clk_ops_init(dev, match, sclk, name);
-		if (err)
+		if (err) {
 			dev_err(dev, "failed to register clock '%s'\n", name);
-		else
-			dev_dbg(dev, "Registered clock '%s'\n", name);
+			return err;
+		}
+
+		dev_dbg(dev, "Registered clock '%s'\n", name);
 		clk_data->clk[idx] = sclk;
 	}
 

+ 84 - 14
drivers/clk/hisilicon/clk-hi3660.c

@@ -20,7 +20,7 @@ static const struct hisi_fixed_rate_clock hi3660_fixed_rate_clks[] = {
 	{ HI3660_CLK_FLL_SRC, "clk_fll_src", NULL, 0, 128000000, },
 	{ HI3660_CLK_PPLL0, "clk_ppll0", NULL, 0, 1600000000, },
 	{ HI3660_CLK_PPLL1, "clk_ppll1", NULL, 0, 1866000000, },
-	{ HI3660_CLK_PPLL2, "clk_ppll2", NULL, 0, 960000000, },
+	{ HI3660_CLK_PPLL2, "clk_ppll2", NULL, 0, 2880000000UL, },
 	{ HI3660_CLK_PPLL3, "clk_ppll3", NULL, 0, 1290000000, },
 	{ HI3660_CLK_SCPLL, "clk_scpll", NULL, 0, 245760000, },
 	{ HI3660_PCLK, "pclk", NULL, 0, 20000000, },
@@ -42,14 +42,19 @@ static const struct hisi_fixed_factor_clock hi3660_crg_fixed_factor_clks[] = {
 	{ HI3660_CLK_GATE_I2C6, "clk_gate_i2c6", "clk_i2c6_iomcu", 1, 4, 0, },
 	{ HI3660_CLK_DIV_SYSBUS, "clk_div_sysbus", "clk_mux_sysbus", 1, 7, 0, },
 	{ HI3660_CLK_DIV_320M, "clk_div_320m", "clk_320m_pll_gt", 1, 5, 0, },
-	{ HI3660_CLK_DIV_A53, "clk_div_a53hpm", "clk_a53hpm_andgt", 1, 2, 0, },
+	{ HI3660_CLK_DIV_A53, "clk_div_a53hpm", "clk_a53hpm_andgt", 1, 6, 0, },
 	{ HI3660_CLK_GATE_SPI0, "clk_gate_spi0", "clk_ppll0", 1, 8, 0, },
 	{ HI3660_CLK_GATE_SPI2, "clk_gate_spi2", "clk_ppll0", 1, 8, 0, },
 	{ HI3660_PCIEPHY_REF, "clk_pciephy_ref", "clk_div_pciephy", 1, 1, 0, },
 	{ HI3660_CLK_ABB_USB, "clk_abb_usb", "clk_gate_usb_tcxo_en", 1, 1, 0 },
+	{ HI3660_VENC_VOLT_HOLD, "venc_volt_hold", "peri_volt_hold", 1, 1, 0, },
+	{ HI3660_CLK_FAC_ISP_SNCLK, "clk_isp_snclk_fac", "clk_isp_snclk_angt",
+	  1, 10, 0, },
 };
 
 static const struct hisi_gate_clock hi3660_crgctrl_gate_sep_clks[] = {
+	{ HI3660_PERI_VOLT_HOLD, "peri_volt_hold", "clkin_sys",
+	  CLK_SET_RATE_PARENT, 0x0, 0, 0, },
 	{ HI3660_HCLK_GATE_SDIO0, "hclk_gate_sdio0", "clk_div_sysbus",
 	  CLK_SET_RATE_PARENT, 0x0, 21, 0, },
 	{ HI3660_HCLK_GATE_SD, "hclk_gate_sd", "clk_div_sysbus",
@@ -120,6 +125,10 @@ static const struct hisi_gate_clock hi3660_crgctrl_gate_sep_clks[] = {
 	  CLK_SET_RATE_PARENT, 0x20, 27, 0, },
 	{ HI3660_CLK_GATE_DMAC, "clk_gate_dmac", "clk_div_sysbus",
 	  CLK_SET_RATE_PARENT, 0x30, 1, 0, },
+	{ HI3660_CLK_GATE_VENC, "clk_gate_venc", "clk_div_venc",
+	  CLK_SET_RATE_PARENT, 0x30, 10, 0, },
+	{ HI3660_CLK_GATE_VDEC, "clk_gate_vdec", "clk_div_vdec",
+	  CLK_SET_RATE_PARENT, 0x30, 11, 0, },
 	{ HI3660_PCLK_GATE_DSS, "pclk_gate_dss", "clk_div_cfgbus",
 	  CLK_SET_RATE_PARENT, 0x30, 12, 0, },
 	{ HI3660_ACLK_GATE_DSS, "aclk_gate_dss", "clk_gate_vivobus",
@@ -148,6 +157,12 @@ static const struct hisi_gate_clock hi3660_crgctrl_gate_sep_clks[] = {
 	  CLK_SET_RATE_PARENT, 0x40, 17, 0, },
 	{ HI3660_CLK_GATE_SDIO0, "clk_gate_sdio0", "clk_mux_sdio_sys",
 	  CLK_SET_RATE_PARENT, 0x40, 19, 0, },
+	{ HI3660_CLK_GATE_ISP_SNCLK0, "clk_gate_isp_snclk0",
+	  "clk_isp_snclk_mux", CLK_SET_RATE_PARENT, 0x50, 16, 0, },
+	{ HI3660_CLK_GATE_ISP_SNCLK1, "clk_gate_isp_snclk1",
+	  "clk_isp_snclk_mux", CLK_SET_RATE_PARENT, 0x50, 17, 0, },
+	{ HI3660_CLK_GATE_ISP_SNCLK2, "clk_gate_isp_snclk2",
+	  "clk_isp_snclk_mux", CLK_SET_RATE_PARENT, 0x50, 18, 0, },
 	{ HI3660_CLK_GATE_UFS_SUBSYS, "clk_gate_ufs_subsys", "clk_div_sysbus",
 	  CLK_SET_RATE_PARENT, 0x50, 21, 0, },
 	{ HI3660_PCLK_GATE_DSI0, "pclk_gate_dsi0", "clk_div_cfgbus",
@@ -171,6 +186,10 @@ static const struct hisi_gate_clock hi3660_crgctrl_gate_clks[] = {
 	  CLK_SET_RATE_PARENT, 0xf0, 7, CLK_GATE_HIWORD_MASK, },
 	{ HI3660_CLK_ANDGT_EDC0, "clk_andgt_edc0", "clk_mux_edc0",
 	  CLK_SET_RATE_PARENT, 0xf0, 8, CLK_GATE_HIWORD_MASK, },
+	{ HI3660_CLK_ANDGT_VDEC, "clk_andgt_vdec", "clk_mux_vdec",
+	  CLK_SET_RATE_PARENT, 0xf0, 15, CLK_GATE_HIWORD_MASK, },
+	{ HI3660_CLK_ANDGT_VENC, "clk_andgt_venc", "clk_mux_venc",
+	  CLK_SET_RATE_PARENT, 0xf4, 0, CLK_GATE_HIWORD_MASK, },
 	{ HI3660_CLK_GATE_UFSPHY_GT, "clk_gate_ufsphy_gt", "clk_div_ufsperi",
 	  CLK_SET_RATE_PARENT, 0xf4, 1, CLK_GATE_HIWORD_MASK, },
 	{ HI3660_CLK_ANDGT_MMC, "clk_andgt_mmc", "clk_mux_mmc_pll",
@@ -195,6 +214,8 @@ static const struct hisi_gate_clock hi3660_crgctrl_gate_clks[] = {
 	  CLK_SET_RATE_PARENT, 0xf8, 3, CLK_GATE_HIWORD_MASK, },
 	{ HI3660_CLK_320M_PLL_GT, "clk_320m_pll_gt", "clk_mux_320m",
 	  CLK_SET_RATE_PARENT, 0xf8, 10, 0, },
+	{ HI3660_CLK_ANGT_ISP_SNCLK, "clk_isp_snclk_angt", "clk_div_a53hpm",
+	  CLK_SET_RATE_PARENT, 0x108, 2, CLK_GATE_HIWORD_MASK, },
 	{ HI3660_AUTODIV_EMMC0BUS, "autodiv_emmc0bus", "autodiv_sysbus",
 	  CLK_SET_RATE_PARENT, 0x404, 1, CLK_GATE_HIWORD_MASK, },
 	{ HI3660_AUTODIV_SYSBUS, "autodiv_sysbus", "clk_div_sysbus",
@@ -205,6 +226,8 @@ static const struct hisi_gate_clock hi3660_crgctrl_gate_clks[] = {
 	  "clk_gate_ufs_tcxo_en", CLK_SET_RATE_PARENT, 0x420, 14, 0, },
 };
 
+static const char *const
+clk_mux_sysbus_p[] = {"clk_ppll1", "clk_ppll0"};
 static const char *const
 clk_mux_sdio_sys_p[] = {"clk_factor_mmc", "clk_div_sdio",};
 static const char *const
@@ -237,10 +260,14 @@ static const char *const
 clk_mux_spi_p[] = {"clkin_sys", "clk_div_spi",};
 static const char *const
 clk_mux_i2c_p[] = {"clkin_sys", "clk_div_i2c",};
+static const char *const
+clk_mux_venc_p[] = {"clk_ppll0", "clk_ppll1", "clk_ppll3", "clk_ppll3",};
+static const char *const
+clk_mux_isp_snclk_p[] = {"clkin_sys", "clk_isp_snclk_div"};
 
 static const struct hisi_mux_clock hi3660_crgctrl_mux_clks[] = {
-	{ HI3660_CLK_MUX_SYSBUS, "clk_mux_sysbus", clk_mux_sdio_sys_p,
-	  ARRAY_SIZE(clk_mux_sdio_sys_p), CLK_SET_RATE_PARENT, 0xac, 0, 1,
+	{ HI3660_CLK_MUX_SYSBUS, "clk_mux_sysbus", clk_mux_sysbus_p,
+	  ARRAY_SIZE(clk_mux_sysbus_p), CLK_SET_RATE_PARENT, 0xac, 0, 1,
 	  CLK_MUX_HIWORD_MASK, },
 	{ HI3660_CLK_MUX_UART0, "clk_mux_uart0", clk_mux_uart0_p,
 	  ARRAY_SIZE(clk_mux_uart0_p), CLK_SET_RATE_PARENT, 0xac, 2, 1,
@@ -281,6 +308,12 @@ static const struct hisi_mux_clock hi3660_crgctrl_mux_clks[] = {
 	{ HI3660_CLK_MUX_SDIO_PLL, "clk_mux_sdio_pll", clk_mux_pll_p,
 	  ARRAY_SIZE(clk_mux_pll_p), CLK_SET_RATE_PARENT, 0xc0, 4, 2,
 	  CLK_MUX_HIWORD_MASK, },
+	{ HI3660_CLK_MUX_VENC, "clk_mux_venc", clk_mux_venc_p,
+	  ARRAY_SIZE(clk_mux_venc_p), CLK_SET_RATE_PARENT, 0xc8, 11, 2,
+	  CLK_MUX_HIWORD_MASK, },
+	{ HI3660_CLK_MUX_VDEC, "clk_mux_vdec", clk_mux_pll0123_p,
+	  ARRAY_SIZE(clk_mux_pll0123_p), CLK_SET_RATE_PARENT, 0xcc, 5, 2,
+	  CLK_MUX_HIWORD_MASK, },
 	{ HI3660_CLK_MUX_VIVOBUS, "clk_mux_vivobus", clk_mux_pll0123_p,
 	  ARRAY_SIZE(clk_mux_pll0123_p), CLK_SET_RATE_PARENT, 0xd0, 12, 2,
 	  CLK_MUX_HIWORD_MASK, },
@@ -290,6 +323,9 @@ static const struct hisi_mux_clock hi3660_crgctrl_mux_clks[] = {
 	{ HI3660_CLK_MUX_320M, "clk_mux_320m", clk_mux_pll02p,
 	  ARRAY_SIZE(clk_mux_pll02p), CLK_SET_RATE_PARENT, 0x100, 0, 1,
 	  CLK_MUX_HIWORD_MASK, },
+	{ HI3660_CLK_MUX_ISP_SNCLK, "clk_isp_snclk_mux", clk_mux_isp_snclk_p,
+	  ARRAY_SIZE(clk_mux_isp_snclk_p), CLK_SET_RATE_PARENT, 0x108, 3, 1,
+	  CLK_MUX_HIWORD_MASK, },
 	{ HI3660_CLK_MUX_IOPERI, "clk_mux_ioperi", clk_mux_ioperi_p,
 	  ARRAY_SIZE(clk_mux_ioperi_p), CLK_SET_RATE_PARENT, 0x108, 10, 1,
 	  CLK_MUX_HIWORD_MASK, },
@@ -316,6 +352,10 @@ static const struct hisi_divider_clock hi3660_crgctrl_divider_clks[] = {
 	  CLK_SET_RATE_PARENT, 0xc0, 8, 6, CLK_DIVIDER_HIWORD_MASK, 0, },
 	{ HI3660_CLK_DIV_SPI, "clk_div_spi", "clk_andgt_spi",
 	  CLK_SET_RATE_PARENT, 0xc4, 12, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
+	{ HI3660_CLK_DIV_VENC, "clk_div_venc", "clk_andgt_venc",
+	  CLK_SET_RATE_PARENT, 0xc8, 6, 5, CLK_DIVIDER_HIWORD_MASK, 0, },
+	{ HI3660_CLK_DIV_VDEC, "clk_div_vdec", "clk_andgt_vdec",
+	  CLK_SET_RATE_PARENT, 0xcc, 0, 5, CLK_DIVIDER_HIWORD_MASK, 0, },
 	{ HI3660_CLK_DIV_VIVOBUS, "clk_div_vivobus", "clk_vivobus_andgt",
 	  CLK_SET_RATE_PARENT, 0xd0, 7, 5, CLK_DIVIDER_HIWORD_MASK, 0, },
 	{ HI3660_CLK_DIV_I2C, "clk_div_i2c", "clk_div_320m",
@@ -332,6 +372,8 @@ static const struct hisi_divider_clock hi3660_crgctrl_divider_clks[] = {
 	  CLK_SET_RATE_PARENT, 0xec, 14, 1, CLK_DIVIDER_HIWORD_MASK, 0, },
 	{ HI3660_CLK_DIV_AOMM, "clk_div_aomm", "clk_aomm_andgt",
 	  CLK_SET_RATE_PARENT, 0x100, 7, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
+	{ HI3660_CLK_DIV_ISP_SNCLK, "clk_isp_snclk_div", "clk_isp_snclk_fac",
+	  CLK_SET_RATE_PARENT, 0x108, 0, 2, CLK_DIVIDER_HIWORD_MASK, 0, },
 	{ HI3660_CLK_DIV_IOPERI, "clk_div_ioperi", "clk_mux_ioperi",
 	  CLK_SET_RATE_PARENT, 0x108, 11, 4, CLK_DIVIDER_HIWORD_MASK, 0, },
 };
@@ -427,6 +469,8 @@ static const struct hisi_gate_clock hi3660_iomcu_gate_sep_clks[] = {
 	  CLK_SET_RATE_PARENT, 0x90, 0, 0, },
 };
 
+static struct hisi_clock_data *clk_crgctrl_data;
+
 static void hi3660_clk_iomcu_init(struct device_node *np)
 {
 	struct hisi_clock_data *clk_data;
@@ -489,38 +533,64 @@ static void hi3660_clk_sctrl_init(struct device_node *np)
 				  clk_data);
 }
 
-static void hi3660_clk_crgctrl_init(struct device_node *np)
+static void hi3660_clk_crgctrl_early_init(struct device_node *np)
 {
-	struct hisi_clock_data *clk_data;
 	int nr = ARRAY_SIZE(hi3660_fixed_rate_clks) +
 		 ARRAY_SIZE(hi3660_crgctrl_gate_sep_clks) +
 		 ARRAY_SIZE(hi3660_crgctrl_gate_clks) +
 		 ARRAY_SIZE(hi3660_crgctrl_mux_clks) +
 		 ARRAY_SIZE(hi3660_crg_fixed_factor_clks) +
 		 ARRAY_SIZE(hi3660_crgctrl_divider_clks);
+	int i;
 
-	clk_data = hisi_clk_init(np, nr);
-	if (!clk_data)
+	clk_crgctrl_data = hisi_clk_init(np, nr);
+	if (!clk_crgctrl_data)
 		return;
 
+	for (i = 0; i < nr; i++)
+		clk_crgctrl_data->clk_data.clks[i] = ERR_PTR(-EPROBE_DEFER);
+
 	hisi_clk_register_fixed_rate(hi3660_fixed_rate_clks,
 				     ARRAY_SIZE(hi3660_fixed_rate_clks),
-				     clk_data);
+				     clk_crgctrl_data);
+}
+CLK_OF_DECLARE_DRIVER(hi3660_clk_crgctrl, "hisilicon,hi3660-crgctrl",
+		      hi3660_clk_crgctrl_early_init);
+
+static void hi3660_clk_crgctrl_init(struct device_node *np)
+{
+	struct clk **clks;
+	int i;
+
+	if (!clk_crgctrl_data)
+		hi3660_clk_crgctrl_early_init(np);
+
+	/* clk_crgctrl_data initialization failed */
+	if (!clk_crgctrl_data)
+		return;
+
 	hisi_clk_register_gate_sep(hi3660_crgctrl_gate_sep_clks,
 				   ARRAY_SIZE(hi3660_crgctrl_gate_sep_clks),
-				   clk_data);
+				   clk_crgctrl_data);
 	hisi_clk_register_gate(hi3660_crgctrl_gate_clks,
 			       ARRAY_SIZE(hi3660_crgctrl_gate_clks),
-			       clk_data);
+			       clk_crgctrl_data);
 	hisi_clk_register_mux(hi3660_crgctrl_mux_clks,
 			      ARRAY_SIZE(hi3660_crgctrl_mux_clks),
-			      clk_data);
+			      clk_crgctrl_data);
 	hisi_clk_register_fixed_factor(hi3660_crg_fixed_factor_clks,
 				       ARRAY_SIZE(hi3660_crg_fixed_factor_clks),
-				       clk_data);
+				       clk_crgctrl_data);
 	hisi_clk_register_divider(hi3660_crgctrl_divider_clks,
 				  ARRAY_SIZE(hi3660_crgctrl_divider_clks),
-				  clk_data);
+				  clk_crgctrl_data);
+
+	clks = clk_crgctrl_data->clk_data.clks;
+	for (i = 0; i < clk_crgctrl_data->clk_data.clk_num; i++) {
+		if (IS_ERR(clks[i]) && PTR_ERR(clks[i]) != -EPROBE_DEFER)
+			pr_err("Failed to register crgctrl clock[%d] err=%ld\n",
+			       i, PTR_ERR(clks[i]));
+	}
 }
 
 static const struct of_device_id hi3660_clk_match_table[] = {

+ 22 - 0
drivers/clk/hisilicon/clk-hi6220.c

@@ -285,3 +285,25 @@ static void __init hi6220_clk_power_init(struct device_node *np)
 				ARRAY_SIZE(hi6220_div_clks_power), clk_data);
 }
 CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-pmctrl", hi6220_clk_power_init);
+
+/* clocks in acpu */
+static const struct hisi_gate_clock hi6220_acpu_sc_gate_sep_clks[] = {
+	{ HI6220_ACPU_SFT_AT_S, "sft_at_s", "cs_atb",
+	  CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0xc, 11, 0, },
+};
+
+static void __init hi6220_clk_acpu_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+	int nr = ARRAY_SIZE(hi6220_acpu_sc_gate_sep_clks);
+
+	clk_data = hisi_clk_init(np, nr);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_gate_sep(hi6220_acpu_sc_gate_sep_clks,
+				   ARRAY_SIZE(hi6220_acpu_sc_gate_sep_clks),
+				   clk_data);
+}
+
+CLK_OF_DECLARE(hi6220_clk_acpu, "hisilicon,hi6220-acpu-sctrl", hi6220_clk_acpu_init);

+ 21 - 0
drivers/clk/hisilicon/crg-hi3798cv200.c

@@ -44,6 +44,9 @@
 #define HI3798CV200_ETH_BUS0_CLK	78
 #define HI3798CV200_ETH_BUS1_CLK	79
 #define HI3798CV200_COMBPHY1_MUX	80
+#define HI3798CV200_FIXED_12M	81
+#define HI3798CV200_FIXED_48M	82
+#define HI3798CV200_FIXED_60M	83
 
 #define HI3798CV200_CRG_NR_CLKS		128
 
@@ -51,9 +54,12 @@ static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = {
 	{ HISTB_OSC_CLK, "clk_osc", NULL, 0, 24000000, },
 	{ HISTB_APB_CLK, "clk_apb", NULL, 0, 100000000, },
 	{ HISTB_AHB_CLK, "clk_ahb", NULL, 0, 200000000, },
+	{ HI3798CV200_FIXED_12M, "12m", NULL, 0, 12000000, },
 	{ HI3798CV200_FIXED_24M, "24m", NULL, 0, 24000000, },
 	{ HI3798CV200_FIXED_25M, "25m", NULL, 0, 25000000, },
+	{ HI3798CV200_FIXED_48M, "48m", NULL, 0, 48000000, },
 	{ HI3798CV200_FIXED_50M, "50m", NULL, 0, 50000000, },
+	{ HI3798CV200_FIXED_60M, "60m", NULL, 0, 60000000, },
 	{ HI3798CV200_FIXED_75M, "75m", NULL, 0, 75000000, },
 	{ HI3798CV200_FIXED_100M, "100m", NULL, 0, 100000000, },
 	{ HI3798CV200_FIXED_150M, "150m", NULL, 0, 150000000, },
@@ -134,6 +140,21 @@ static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
 	/* COMBPHY1 */
 	{ HISTB_COMBPHY1_CLK, "clk_combphy1", "combphy1_mux",
 		CLK_SET_RATE_PARENT, 0x188, 8, 0, },
+	/* USB2 */
+	{ HISTB_USB2_BUS_CLK, "clk_u2_bus", "clk_ahb",
+		CLK_SET_RATE_PARENT, 0xb8, 0, 0, },
+	{ HISTB_USB2_PHY_CLK, "clk_u2_phy", "60m",
+		CLK_SET_RATE_PARENT, 0xb8, 4, 0, },
+	{ HISTB_USB2_12M_CLK, "clk_u2_12m", "12m",
+		CLK_SET_RATE_PARENT, 0xb8, 2, 0 },
+	{ HISTB_USB2_48M_CLK, "clk_u2_48m", "48m",
+		CLK_SET_RATE_PARENT, 0xb8, 1, 0 },
+	{ HISTB_USB2_UTMI_CLK, "clk_u2_utmi", "60m",
+		CLK_SET_RATE_PARENT, 0xb8, 5, 0 },
+	{ HISTB_USB2_PHY1_REF_CLK, "clk_u2_phy1_ref", "24m",
+		CLK_SET_RATE_PARENT, 0xbc, 0, 0 },
+	{ HISTB_USB2_PHY2_REF_CLK, "clk_u2_phy2_ref", "24m",
+		CLK_SET_RATE_PARENT, 0xbc, 2, 0 },
 };
 
 static struct hisi_clock_data *hi3798cv200_clk_register(

+ 5 - 3
drivers/clk/imx/clk-imx7d.c

@@ -25,6 +25,7 @@
 static u32 share_count_sai1;
 static u32 share_count_sai2;
 static u32 share_count_sai3;
+static u32 share_count_nand;
 
 static struct clk_div_table test_div_table[] = {
 	{ .val = 3, .div = 1, },
@@ -424,7 +425,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
 	clks[IMX7D_PLL_VIDEO_MAIN_SRC] = imx_clk_mux("pll_video_main_src", base + 0x130, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
 
 	clks[IMX7D_PLL_ARM_MAIN]  = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_arm_main", "osc", base + 0x60, 0x7f);
-	clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_dram_main", "osc", base + 0x70, 0x7f);
+	clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_DDR_IMX7, "pll_dram_main", "osc", base + 0x70, 0x7f);
 	clks[IMX7D_PLL_SYS_MAIN]  = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll_sys_main", "osc", base + 0xb0, 0x1);
 	clks[IMX7D_PLL_ENET_MAIN] = imx_clk_pllv3(IMX_PLLV3_ENET_IMX7, "pll_enet_main", "osc", base + 0xe0, 0x0);
 	clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_audio_main", "osc", base + 0xf0, 0x7f);
@@ -748,7 +749,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
 	clks[IMX7D_ENET2_TIME_ROOT_DIV] = imx_clk_divider2("enet2_time_post_div", "enet2_time_pre_div", base + 0xa880, 0, 6);
 	clks[IMX7D_ENET_PHY_REF_ROOT_DIV] = imx_clk_divider2("enet_phy_ref_post_div", "enet_phy_ref_pre_div", base + 0xa900, 0, 6);
 	clks[IMX7D_EIM_ROOT_DIV] = imx_clk_divider2("eim_post_div", "eim_pre_div", base + 0xa980, 0, 6);
-	clks[IMX7D_NAND_ROOT_DIV] = imx_clk_divider2("nand_post_div", "nand_pre_div", base + 0xaa00, 0, 6);
+	clks[IMX7D_NAND_ROOT_CLK] = imx_clk_divider2("nand_root_clk", "nand_pre_div", base + 0xaa00, 0, 6);
 	clks[IMX7D_QSPI_ROOT_DIV] = imx_clk_divider2("qspi_post_div", "qspi_pre_div", base + 0xaa80, 0, 6);
 	clks[IMX7D_USDHC1_ROOT_DIV] = imx_clk_divider2("usdhc1_post_div", "usdhc1_pre_div", base + 0xab00, 0, 6);
 	clks[IMX7D_USDHC2_ROOT_DIV] = imx_clk_divider2("usdhc2_post_div", "usdhc2_pre_div", base + 0xab80, 0, 6);
@@ -825,7 +826,8 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
 	clks[IMX7D_ENET2_TIME_ROOT_CLK] = imx_clk_gate4("enet2_time_root_clk", "enet2_time_post_div", base + 0x4510, 0);
 	clks[IMX7D_ENET_PHY_REF_ROOT_CLK] = imx_clk_gate4("enet_phy_ref_root_clk", "enet_phy_ref_post_div", base + 0x4520, 0);
 	clks[IMX7D_EIM_ROOT_CLK] = imx_clk_gate4("eim_root_clk", "eim_post_div", base + 0x4160, 0);
-	clks[IMX7D_NAND_ROOT_CLK] = imx_clk_gate4("nand_root_clk", "nand_post_div", base + 0x4140, 0);
+	clks[IMX7D_NAND_RAWNAND_CLK] = imx_clk_gate2_shared2("nand_rawnand_clk", "nand_root_clk", base + 0x4140, 0, &share_count_nand);
+	clks[IMX7D_NAND_USDHC_BUS_RAWNAND_CLK] = imx_clk_gate2_shared2("nand_usdhc_rawnand_clk", "nand_usdhc_root_clk", base + 0x4140, 0, &share_count_nand);
 	clks[IMX7D_QSPI_ROOT_CLK] = imx_clk_gate4("qspi_root_clk", "qspi_post_div", base + 0x4150, 0);
 	clks[IMX7D_USDHC1_ROOT_CLK] = imx_clk_gate4("usdhc1_root_clk", "usdhc1_post_div", base + 0x46c0, 0);
 	clks[IMX7D_USDHC2_ROOT_CLK] = imx_clk_gate4("usdhc2_root_clk", "usdhc2_post_div", base + 0x46d0, 0);

+ 5 - 0
drivers/clk/imx/clk-pllv3.c

@@ -27,6 +27,7 @@
 #define BM_PLL_POWER		(0x1 << 12)
 #define BM_PLL_LOCK		(0x1 << 31)
 #define IMX7_ENET_PLL_POWER	(0x1 << 5)
+#define IMX7_DDR_PLL_POWER	(0x1 << 20)
 
 /**
  * struct clk_pllv3 - IMX PLL clock version 3
@@ -451,6 +452,10 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
 		pll->ref_clock = 500000000;
 		ops = &clk_pllv3_enet_ops;
 		break;
+	case IMX_PLLV3_DDR_IMX7:
+		pll->power_bit = IMX7_DDR_PLL_POWER;
+		ops = &clk_pllv3_av_ops;
+		break;
 	default:
 		ops = &clk_pllv3_ops;
 	}

+ 1 - 0
drivers/clk/imx/clk.h

@@ -35,6 +35,7 @@ enum imx_pllv3_type {
 	IMX_PLLV3_ENET,
 	IMX_PLLV3_ENET_IMX7,
 	IMX_PLLV3_SYS_VF610,
+	IMX_PLLV3_DDR_IMX7,
 };
 
 struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,

+ 16 - 0
drivers/clk/keystone/Kconfig

@@ -0,0 +1,16 @@
+config COMMON_CLK_KEYSTONE
+	tristate "Clock drivers for Keystone based SOCs"
+	depends on (ARCH_KEYSTONE || COMPILE_TEST) && OF
+	---help---
+	  Supports clock drivers for Keystone based SOCs. These SOCs have local
+	  a power sleep control module that gate the clock to the IPs and PLLs.
+
+config TI_SCI_CLK
+	tristate "TI System Control Interface clock drivers"
+	depends on (ARCH_KEYSTONE || COMPILE_TEST) && OF
+	depends on TI_SCI_PROTOCOL
+	default ARCH_KEYSTONE
+	---help---
+	  This adds the clock driver support over TI System Control Interface.
+	  If you wish to use clock resources from the PMMC firmware, say Y.
+	  Otherwise, say N.

+ 2 - 1
drivers/clk/keystone/Makefile

@@ -1 +1,2 @@
-obj-y			+= pll.o gate.o
+obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= pll.o gate.o
+obj-$(CONFIG_TI_SCI_CLK)		+= sci-clk.o

+ 724 - 0
drivers/clk/keystone/sci-clk.c

@@ -0,0 +1,724 @@
+/*
+ * SCI Clock driver for keystone based devices
+ *
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *	Tero Kristo <t-kristo@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/soc/ti/ti_sci_protocol.h>
+
+#define SCI_CLK_SSC_ENABLE		BIT(0)
+#define SCI_CLK_ALLOW_FREQ_CHANGE	BIT(1)
+#define SCI_CLK_INPUT_TERMINATION	BIT(2)
+
+/**
+ * struct sci_clk_data - TI SCI clock data
+ * @dev: device index
+ * @num_clks: number of clocks for this device
+ */
+struct sci_clk_data {
+	u16 dev;
+	u16 num_clks;
+};
+
+/**
+ * struct sci_clk_provider - TI SCI clock provider representation
+ * @sci: Handle to the System Control Interface protocol handler
+ * @ops: Pointer to the SCI ops to be used by the clocks
+ * @dev: Device pointer for the clock provider
+ * @clk_data: Clock data
+ * @clocks: Clocks array for this device
+ */
+struct sci_clk_provider {
+	const struct ti_sci_handle *sci;
+	const struct ti_sci_clk_ops *ops;
+	struct device *dev;
+	const struct sci_clk_data *clk_data;
+	struct clk_hw **clocks;
+};
+
+/**
+ * struct sci_clk - TI SCI clock representation
+ * @hw:		 Hardware clock cookie for common clock framework
+ * @dev_id:	 Device index
+ * @clk_id:	 Clock index
+ * @node:	 Clocks list link
+ * @provider:	 Master clock provider
+ * @flags:	 Flags for the clock
+ */
+struct sci_clk {
+	struct clk_hw hw;
+	u16 dev_id;
+	u8 clk_id;
+	struct list_head node;
+	struct sci_clk_provider *provider;
+	u8 flags;
+};
+
+#define to_sci_clk(_hw) container_of(_hw, struct sci_clk, hw)
+
+/**
+ * sci_clk_prepare - Prepare (enable) a TI SCI clock
+ * @hw: clock to prepare
+ *
+ * Prepares a clock to be actively used. Returns the SCI protocol status.
+ */
+static int sci_clk_prepare(struct clk_hw *hw)
+{
+	struct sci_clk *clk = to_sci_clk(hw);
+	bool enable_ssc = clk->flags & SCI_CLK_SSC_ENABLE;
+	bool allow_freq_change = clk->flags & SCI_CLK_ALLOW_FREQ_CHANGE;
+	bool input_termination = clk->flags & SCI_CLK_INPUT_TERMINATION;
+
+	return clk->provider->ops->get_clock(clk->provider->sci, clk->dev_id,
+					     clk->clk_id, enable_ssc,
+					     allow_freq_change,
+					     input_termination);
+}
+
+/**
+ * sci_clk_unprepare - Un-prepares (disables) a TI SCI clock
+ * @hw: clock to unprepare
+ *
+ * Un-prepares a clock from active state.
+ */
+static void sci_clk_unprepare(struct clk_hw *hw)
+{
+	struct sci_clk *clk = to_sci_clk(hw);
+	int ret;
+
+	ret = clk->provider->ops->put_clock(clk->provider->sci, clk->dev_id,
+					    clk->clk_id);
+	if (ret)
+		dev_err(clk->provider->dev,
+			"unprepare failed for dev=%d, clk=%d, ret=%d\n",
+			clk->dev_id, clk->clk_id, ret);
+}
+
+/**
+ * sci_clk_is_prepared - Check if a TI SCI clock is prepared or not
+ * @hw: clock to check status for
+ *
+ * Checks if a clock is prepared (enabled) in hardware. Returns non-zero
+ * value if clock is enabled, zero otherwise.
+ */
+static int sci_clk_is_prepared(struct clk_hw *hw)
+{
+	struct sci_clk *clk = to_sci_clk(hw);
+	bool req_state, current_state;
+	int ret;
+
+	ret = clk->provider->ops->is_on(clk->provider->sci, clk->dev_id,
+					clk->clk_id, &req_state,
+					&current_state);
+	if (ret) {
+		dev_err(clk->provider->dev,
+			"is_prepared failed for dev=%d, clk=%d, ret=%d\n",
+			clk->dev_id, clk->clk_id, ret);
+		return 0;
+	}
+
+	return req_state;
+}
+
+/**
+ * sci_clk_recalc_rate - Get clock rate for a TI SCI clock
+ * @hw: clock to get rate for
+ * @parent_rate: parent rate provided by common clock framework, not used
+ *
+ * Gets the current clock rate of a TI SCI clock. Returns the current
+ * clock rate, or zero in failure.
+ */
+static unsigned long sci_clk_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct sci_clk *clk = to_sci_clk(hw);
+	u64 freq;
+	int ret;
+
+	ret = clk->provider->ops->get_freq(clk->provider->sci, clk->dev_id,
+					   clk->clk_id, &freq);
+	if (ret) {
+		dev_err(clk->provider->dev,
+			"recalc-rate failed for dev=%d, clk=%d, ret=%d\n",
+			clk->dev_id, clk->clk_id, ret);
+		return 0;
+	}
+
+	return freq;
+}
+
+/**
+ * sci_clk_determine_rate - Determines a clock rate a clock can be set to
+ * @hw: clock to change rate for
+ * @req: requested rate configuration for the clock
+ *
+ * Determines a suitable clock rate and parent for a TI SCI clock.
+ * The parent handling is un-used, as generally the parent clock rates
+ * are not known by the kernel; instead these are internally handled
+ * by the firmware. Returns 0 on success, negative error value on failure.
+ */
+static int sci_clk_determine_rate(struct clk_hw *hw,
+				  struct clk_rate_request *req)
+{
+	struct sci_clk *clk = to_sci_clk(hw);
+	int ret;
+	u64 new_rate;
+
+	ret = clk->provider->ops->get_best_match_freq(clk->provider->sci,
+						      clk->dev_id,
+						      clk->clk_id,
+						      req->min_rate,
+						      req->rate,
+						      req->max_rate,
+						      &new_rate);
+	if (ret) {
+		dev_err(clk->provider->dev,
+			"determine-rate failed for dev=%d, clk=%d, ret=%d\n",
+			clk->dev_id, clk->clk_id, ret);
+		return ret;
+	}
+
+	req->rate = new_rate;
+
+	return 0;
+}
+
+/**
+ * sci_clk_set_rate - Set rate for a TI SCI clock
+ * @hw: clock to change rate for
+ * @rate: target rate for the clock
+ * @parent_rate: rate of the clock parent, not used for TI SCI clocks
+ *
+ * Sets a clock frequency for a TI SCI clock. Returns the TI SCI
+ * protocol status.
+ */
+static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	struct sci_clk *clk = to_sci_clk(hw);
+
+	return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id,
+					    clk->clk_id, rate, rate, rate);
+}
+
+/**
+ * sci_clk_get_parent - Get the current parent of a TI SCI clock
+ * @hw: clock to get parent for
+ *
+ * Returns the index of the currently selected parent for a TI SCI clock.
+ */
+static u8 sci_clk_get_parent(struct clk_hw *hw)
+{
+	struct sci_clk *clk = to_sci_clk(hw);
+	u8 parent_id;
+	int ret;
+
+	ret = clk->provider->ops->get_parent(clk->provider->sci, clk->dev_id,
+					     clk->clk_id, &parent_id);
+	if (ret) {
+		dev_err(clk->provider->dev,
+			"get-parent failed for dev=%d, clk=%d, ret=%d\n",
+			clk->dev_id, clk->clk_id, ret);
+		return 0;
+	}
+
+	return parent_id - clk->clk_id - 1;
+}
+
+/**
+ * sci_clk_set_parent - Set the parent of a TI SCI clock
+ * @hw: clock to set parent for
+ * @index: new parent index for the clock
+ *
+ * Sets the parent of a TI SCI clock. Return TI SCI protocol status.
+ */
+static int sci_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct sci_clk *clk = to_sci_clk(hw);
+
+	return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id,
+					      clk->clk_id,
+					      index + 1 + clk->clk_id);
+}
+
+static const struct clk_ops sci_clk_ops = {
+	.prepare = sci_clk_prepare,
+	.unprepare = sci_clk_unprepare,
+	.is_prepared = sci_clk_is_prepared,
+	.recalc_rate = sci_clk_recalc_rate,
+	.determine_rate = sci_clk_determine_rate,
+	.set_rate = sci_clk_set_rate,
+	.get_parent = sci_clk_get_parent,
+	.set_parent = sci_clk_set_parent,
+};
+
+/**
+ * _sci_clk_get - Gets a handle for an SCI clock
+ * @provider: Handle to SCI clock provider
+ * @dev_id: device ID for the clock to register
+ * @clk_id: clock ID for the clock to register
+ *
+ * Gets a handle to an existing TI SCI hw clock, or builds a new clock
+ * entry and registers it with the common clock framework. Called from
+ * the common clock framework, when a corresponding of_clk_get call is
+ * executed, or recursively from itself when parsing parent clocks.
+ * Returns a pointer to the hw clock struct, or ERR_PTR value in failure.
+ */
+static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
+				     u16 dev_id, u8 clk_id)
+{
+	struct clk_init_data init = { NULL };
+	struct sci_clk *sci_clk = NULL;
+	char *name = NULL;
+	char **parent_names = NULL;
+	int i;
+	int ret;
+
+	sci_clk = devm_kzalloc(provider->dev, sizeof(*sci_clk), GFP_KERNEL);
+	if (!sci_clk)
+		return ERR_PTR(-ENOMEM);
+
+	sci_clk->dev_id = dev_id;
+	sci_clk->clk_id = clk_id;
+	sci_clk->provider = provider;
+
+	ret = provider->ops->get_num_parents(provider->sci, dev_id,
+					     clk_id,
+					     &init.num_parents);
+	if (ret)
+		goto err;
+
+	name = kasprintf(GFP_KERNEL, "%s:%d:%d", dev_name(provider->dev),
+			 sci_clk->dev_id, sci_clk->clk_id);
+
+	init.name = name;
+
+	/*
+	 * From kernel point of view, we only care about a clocks parents,
+	 * if it has more than 1 possible parent. In this case, it is going
+	 * to have mux functionality. Otherwise it is going to act as a root
+	 * clock.
+	 */
+	if (init.num_parents < 2)
+		init.num_parents = 0;
+
+	if (init.num_parents) {
+		parent_names = kcalloc(init.num_parents, sizeof(char *),
+				       GFP_KERNEL);
+
+		if (!parent_names) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		for (i = 0; i < init.num_parents; i++) {
+			char *parent_name;
+
+			parent_name = kasprintf(GFP_KERNEL, "%s:%d:%d",
+						dev_name(provider->dev),
+						sci_clk->dev_id,
+						sci_clk->clk_id + 1 + i);
+			if (!parent_name) {
+				ret = -ENOMEM;
+				goto err;
+			}
+			parent_names[i] = parent_name;
+		}
+		init.parent_names = (void *)parent_names;
+	}
+
+	init.ops = &sci_clk_ops;
+	sci_clk->hw.init = &init;
+
+	ret = devm_clk_hw_register(provider->dev, &sci_clk->hw);
+	if (ret)
+		dev_err(provider->dev, "failed clk register with %d\n", ret);
+
+err:
+	if (parent_names) {
+		for (i = 0; i < init.num_parents; i++)
+			kfree(parent_names[i]);
+
+		kfree(parent_names);
+	}
+
+	kfree(name);
+
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &sci_clk->hw;
+}
+
+/**
+ * sci_clk_get - Xlate function for getting clock handles
+ * @clkspec: device tree clock specifier
+ * @data: pointer to the clock provider
+ *
+ * Xlate function for retrieving clock TI SCI hw clock handles based on
+ * device tree clock specifier. Called from the common clock framework,
+ * when a corresponding of_clk_get call is executed. Returns a pointer
+ * to the TI SCI hw clock struct, or ERR_PTR value in failure.
+ */
+static struct clk_hw *sci_clk_get(struct of_phandle_args *clkspec, void *data)
+{
+	struct sci_clk_provider *provider = data;
+	u16 dev_id;
+	u8 clk_id;
+	const struct sci_clk_data *clks = provider->clk_data;
+	struct clk_hw **clocks = provider->clocks;
+
+	if (clkspec->args_count != 2)
+		return ERR_PTR(-EINVAL);
+
+	dev_id = clkspec->args[0];
+	clk_id = clkspec->args[1];
+
+	while (clks->num_clks) {
+		if (clks->dev == dev_id) {
+			if (clk_id >= clks->num_clks)
+				return ERR_PTR(-EINVAL);
+
+			return clocks[clk_id];
+		}
+
+		clks++;
+	}
+
+	return ERR_PTR(-ENODEV);
+}
+
+static int ti_sci_init_clocks(struct sci_clk_provider *p)
+{
+	const struct sci_clk_data *data = p->clk_data;
+	struct clk_hw *hw;
+	int i;
+
+	while (data->num_clks) {
+		p->clocks = devm_kcalloc(p->dev, data->num_clks,
+					 sizeof(struct sci_clk),
+					 GFP_KERNEL);
+		if (!p->clocks)
+			return -ENOMEM;
+
+		for (i = 0; i < data->num_clks; i++) {
+			hw = _sci_clk_build(p, data->dev, i);
+			if (!IS_ERR(hw)) {
+				p->clocks[i] = hw;
+				continue;
+			}
+
+			/* Skip any holes in the clock lists */
+			if (PTR_ERR(hw) == -ENODEV)
+				continue;
+
+			return PTR_ERR(hw);
+		}
+		data++;
+	}
+
+	return 0;
+}
+
+static const struct sci_clk_data k2g_clk_data[] = {
+	/* pmmc */
+	{ .dev = 0x0, .num_clks = 4 },
+
+	/* mlb0 */
+	{ .dev = 0x1, .num_clks = 5 },
+
+	/* dss0 */
+	{ .dev = 0x2, .num_clks = 2 },
+
+	/* mcbsp0 */
+	{ .dev = 0x3, .num_clks = 8 },
+
+	/* mcasp0 */
+	{ .dev = 0x4, .num_clks = 8 },
+
+	/* mcasp1 */
+	{ .dev = 0x5, .num_clks = 8 },
+
+	/* mcasp2 */
+	{ .dev = 0x6, .num_clks = 8 },
+
+	/* dcan0 */
+	{ .dev = 0x8, .num_clks = 2 },
+
+	/* dcan1 */
+	{ .dev = 0x9, .num_clks = 2 },
+
+	/* emif0 */
+	{ .dev = 0xa, .num_clks = 6 },
+
+	/* mmchs0 */
+	{ .dev = 0xb, .num_clks = 3 },
+
+	/* mmchs1 */
+	{ .dev = 0xc, .num_clks = 3 },
+
+	/* gpmc0 */
+	{ .dev = 0xd, .num_clks = 1 },
+
+	/* elm0 */
+	{ .dev = 0xe, .num_clks = 1 },
+
+	/* spi0 */
+	{ .dev = 0x10, .num_clks = 1 },
+
+	/* spi1 */
+	{ .dev = 0x11, .num_clks = 1 },
+
+	/* spi2 */
+	{ .dev = 0x12, .num_clks = 1 },
+
+	/* spi3 */
+	{ .dev = 0x13, .num_clks = 1 },
+
+	/* icss0 */
+	{ .dev = 0x14, .num_clks = 6 },
+
+	/* icss1 */
+	{ .dev = 0x15, .num_clks = 6 },
+
+	/* usb0 */
+	{ .dev = 0x16, .num_clks = 7 },
+
+	/* usb1 */
+	{ .dev = 0x17, .num_clks = 7 },
+
+	/* nss0 */
+	{ .dev = 0x18, .num_clks = 14 },
+
+	/* pcie0 */
+	{ .dev = 0x19, .num_clks = 1 },
+
+	/* gpio0 */
+	{ .dev = 0x1b, .num_clks = 1 },
+
+	/* gpio1 */
+	{ .dev = 0x1c, .num_clks = 1 },
+
+	/* timer64_0 */
+	{ .dev = 0x1d, .num_clks = 9 },
+
+	/* timer64_1 */
+	{ .dev = 0x1e, .num_clks = 9 },
+
+	/* timer64_2 */
+	{ .dev = 0x1f, .num_clks = 9 },
+
+	/* timer64_3 */
+	{ .dev = 0x20, .num_clks = 9 },
+
+	/* timer64_4 */
+	{ .dev = 0x21, .num_clks = 9 },
+
+	/* timer64_5 */
+	{ .dev = 0x22, .num_clks = 9 },
+
+	/* timer64_6 */
+	{ .dev = 0x23, .num_clks = 9 },
+
+	/* msgmgr0 */
+	{ .dev = 0x25, .num_clks = 1 },
+
+	/* bootcfg0 */
+	{ .dev = 0x26, .num_clks = 1 },
+
+	/* arm_bootrom0 */
+	{ .dev = 0x27, .num_clks = 1 },
+
+	/* dsp_bootrom0 */
+	{ .dev = 0x29, .num_clks = 1 },
+
+	/* debugss0 */
+	{ .dev = 0x2b, .num_clks = 8 },
+
+	/* uart0 */
+	{ .dev = 0x2c, .num_clks = 1 },
+
+	/* uart1 */
+	{ .dev = 0x2d, .num_clks = 1 },
+
+	/* uart2 */
+	{ .dev = 0x2e, .num_clks = 1 },
+
+	/* ehrpwm0 */
+	{ .dev = 0x2f, .num_clks = 1 },
+
+	/* ehrpwm1 */
+	{ .dev = 0x30, .num_clks = 1 },
+
+	/* ehrpwm2 */
+	{ .dev = 0x31, .num_clks = 1 },
+
+	/* ehrpwm3 */
+	{ .dev = 0x32, .num_clks = 1 },
+
+	/* ehrpwm4 */
+	{ .dev = 0x33, .num_clks = 1 },
+
+	/* ehrpwm5 */
+	{ .dev = 0x34, .num_clks = 1 },
+
+	/* eqep0 */
+	{ .dev = 0x35, .num_clks = 1 },
+
+	/* eqep1 */
+	{ .dev = 0x36, .num_clks = 1 },
+
+	/* eqep2 */
+	{ .dev = 0x37, .num_clks = 1 },
+
+	/* ecap0 */
+	{ .dev = 0x38, .num_clks = 1 },
+
+	/* ecap1 */
+	{ .dev = 0x39, .num_clks = 1 },
+
+	/* i2c0 */
+	{ .dev = 0x3a, .num_clks = 1 },
+
+	/* i2c1 */
+	{ .dev = 0x3b, .num_clks = 1 },
+
+	/* i2c2 */
+	{ .dev = 0x3c, .num_clks = 1 },
+
+	/* edma0 */
+	{ .dev = 0x3f, .num_clks = 2 },
+
+	/* semaphore0 */
+	{ .dev = 0x40, .num_clks = 1 },
+
+	/* intc0 */
+	{ .dev = 0x41, .num_clks = 1 },
+
+	/* gic0 */
+	{ .dev = 0x42, .num_clks = 1 },
+
+	/* qspi0 */
+	{ .dev = 0x43, .num_clks = 5 },
+
+	/* arm_64b_counter0 */
+	{ .dev = 0x44, .num_clks = 2 },
+
+	/* tetris0 */
+	{ .dev = 0x45, .num_clks = 2 },
+
+	/* cgem0 */
+	{ .dev = 0x46, .num_clks = 2 },
+
+	/* msmc0 */
+	{ .dev = 0x47, .num_clks = 1 },
+
+	/* cbass0 */
+	{ .dev = 0x49, .num_clks = 1 },
+
+	/* board0 */
+	{ .dev = 0x4c, .num_clks = 36 },
+
+	/* edma1 */
+	{ .dev = 0x4f, .num_clks = 2 },
+	{ .num_clks = 0 },
+};
+
+static const struct of_device_id ti_sci_clk_of_match[] = {
+	{ .compatible = "ti,k2g-sci-clk", .data = &k2g_clk_data },
+	{ /* Sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ti_sci_clk_of_match);
+
+/**
+ * ti_sci_clk_probe - Probe function for the TI SCI clock driver
+ * @pdev: platform device pointer to be probed
+ *
+ * Probes the TI SCI clock device. Allocates a new clock provider
+ * and registers this to the common clock framework. Also applies
+ * any required flags to the identified clocks via clock lists
+ * supplied from DT. Returns 0 for success, negative error value
+ * for failure.
+ */
+static int ti_sci_clk_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct sci_clk_provider *provider;
+	const struct ti_sci_handle *handle;
+	const struct sci_clk_data *data;
+	int ret;
+
+	data = of_device_get_match_data(dev);
+	if (!data)
+		return -EINVAL;
+
+	handle = devm_ti_sci_get_handle(dev);
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL);
+	if (!provider)
+		return -ENOMEM;
+
+	provider->clk_data = data;
+
+	provider->sci = handle;
+	provider->ops = &handle->ops.clk_ops;
+	provider->dev = dev;
+
+	ret = ti_sci_init_clocks(provider);
+	if (ret) {
+		pr_err("ti-sci-init-clocks failed.\n");
+		return ret;
+	}
+
+	return of_clk_add_hw_provider(np, sci_clk_get, provider);
+}
+
+/**
+ * ti_sci_clk_remove - Remove TI SCI clock device
+ * @pdev: platform device pointer for the device to be removed
+ *
+ * Removes the TI SCI device. Unregisters the clock provider registered
+ * via common clock framework. Any memory allocated for the device will
+ * be free'd silently via the devm framework. Returns 0 always.
+ */
+static int ti_sci_clk_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+
+	return 0;
+}
+
+static struct platform_driver ti_sci_clk_driver = {
+	.probe = ti_sci_clk_probe,
+	.remove = ti_sci_clk_remove,
+	.driver = {
+		.name = "ti-sci-clk",
+		.of_match_table = of_match_ptr(ti_sci_clk_of_match),
+	},
+};
+module_platform_driver(ti_sci_clk_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TI System Control Interface(SCI) Clock driver");
+MODULE_AUTHOR("Tero Kristo");
+MODULE_ALIAS("platform:ti-sci-clk");

+ 1 - 1
drivers/clk/mediatek/Makefile

@@ -1,4 +1,4 @@
-obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
+obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
 obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
 obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o

+ 120 - 0
drivers/clk/mediatek/clk-cpumux.c

@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2015 Linaro Ltd.
+ * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+#include "clk-cpumux.h"
+
+static inline struct mtk_clk_cpumux *to_mtk_clk_cpumux(struct clk_hw *_hw)
+{
+	return container_of(_hw, struct mtk_clk_cpumux, hw);
+}
+
+static u8 clk_cpumux_get_parent(struct clk_hw *hw)
+{
+	struct mtk_clk_cpumux *mux = to_mtk_clk_cpumux(hw);
+	int num_parents = clk_hw_get_num_parents(hw);
+	unsigned int val;
+
+	regmap_read(mux->regmap, mux->reg, &val);
+
+	val >>= mux->shift;
+	val &= mux->mask;
+
+	if (val >= num_parents)
+		return -EINVAL;
+
+	return val;
+}
+
+static int clk_cpumux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct mtk_clk_cpumux *mux = to_mtk_clk_cpumux(hw);
+	u32 mask, val;
+
+	val = index << mux->shift;
+	mask = mux->mask << mux->shift;
+
+	return regmap_update_bits(mux->regmap, mux->reg, mask, val);
+}
+
+static const struct clk_ops clk_cpumux_ops = {
+	.get_parent = clk_cpumux_get_parent,
+	.set_parent = clk_cpumux_set_parent,
+};
+
+static struct clk __init *
+mtk_clk_register_cpumux(const struct mtk_composite *mux,
+			struct regmap *regmap)
+{
+	struct mtk_clk_cpumux *cpumux;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	cpumux = kzalloc(sizeof(*cpumux), GFP_KERNEL);
+	if (!cpumux)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = mux->name;
+	init.ops = &clk_cpumux_ops;
+	init.parent_names = mux->parent_names;
+	init.num_parents = mux->num_parents;
+	init.flags = mux->flags;
+
+	cpumux->reg = mux->mux_reg;
+	cpumux->shift = mux->mux_shift;
+	cpumux->mask = BIT(mux->mux_width) - 1;
+	cpumux->regmap = regmap;
+	cpumux->hw.init = &init;
+
+	clk = clk_register(NULL, &cpumux->hw);
+	if (IS_ERR(clk))
+		kfree(cpumux);
+
+	return clk;
+}
+
+int __init mtk_clk_register_cpumuxes(struct device_node *node,
+				     const struct mtk_composite *clks, int num,
+				     struct clk_onecell_data *clk_data)
+{
+	int i;
+	struct clk *clk;
+	struct regmap *regmap;
+
+	regmap = syscon_node_to_regmap(node);
+	if (IS_ERR(regmap)) {
+		pr_err("Cannot find regmap for %s: %ld\n", node->full_name,
+		       PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	for (i = 0; i < num; i++) {
+		const struct mtk_composite *mux = &clks[i];
+
+		clk = mtk_clk_register_cpumux(mux, regmap);
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+			       mux->name, PTR_ERR(clk));
+			continue;
+		}
+
+		clk_data->clks[mux->id] = clk;
+	}
+
+	return 0;
+}

+ 30 - 0
drivers/clk/mediatek/clk-cpumux.h

@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 Linaro Ltd.
+ * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DRV_CLK_CPUMUX_H
+#define __DRV_CLK_CPUMUX_H
+
+struct mtk_clk_cpumux {
+	struct clk_hw	hw;
+	struct regmap	*regmap;
+	u32		reg;
+	u32		mask;
+	u8		shift;
+};
+
+int mtk_clk_register_cpumuxes(struct device_node *node,
+			      const struct mtk_composite *clks, int num,
+			      struct clk_onecell_data *clk_data);
+
+#endif /* __DRV_CLK_CPUMUX_H */

+ 8 - 0
drivers/clk/mediatek/clk-mt2701.c

@@ -20,6 +20,7 @@
 
 #include "clk-mtk.h"
 #include "clk-gate.h"
+#include "clk-cpumux.h"
 
 #include <dt-bindings/clock/mt2701-clk.h>
 
@@ -493,6 +494,10 @@ static const char * const cpu_parents[] = {
 	"mmpll"
 };
 
+static const struct mtk_composite cpu_muxes[] __initconst = {
+	MUX(CLK_INFRA_CPUSEL, "infra_cpu_sel", cpu_parents, 0x0000, 2, 2),
+};
+
 static const struct mtk_composite top_muxes[] = {
 	MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
 		0x0040, 0, 3, 7, CLK_IS_CRITICAL),
@@ -759,6 +764,9 @@ static void mtk_infrasys_init_early(struct device_node *node)
 	mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
 						infra_clk_data);
 
+	mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes),
+				  infra_clk_data);
+
 	r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
 	if (r)
 		pr_err("%s(): could not register clock provider: %d\n",

+ 23 - 0
drivers/clk/mediatek/clk-mt8173.c

@@ -18,6 +18,7 @@
 
 #include "clk-mtk.h"
 #include "clk-gate.h"
+#include "clk-cpumux.h"
 
 #include <dt-bindings/clock/mt8173-clk.h>
 
@@ -525,6 +526,25 @@ static const char * const i2s3_b_ck_parents[] __initconst = {
 	"apll2_div5"
 };
 
+static const char * const ca53_parents[] __initconst = {
+	"clk26m",
+	"armca7pll",
+	"mainpll",
+	"univpll"
+};
+
+static const char * const ca57_parents[] __initconst = {
+	"clk26m",
+	"armca15pll",
+	"mainpll",
+	"univpll"
+};
+
+static const struct mtk_composite cpu_muxes[] __initconst = {
+	MUX(CLK_INFRA_CA53SEL, "infra_ca53_sel", ca53_parents, 0x0000, 0, 2),
+	MUX(CLK_INFRA_CA57SEL, "infra_ca57_sel", ca57_parents, 0x0000, 2, 2),
+};
+
 static const struct mtk_composite top_muxes[] __initconst = {
 	/* CLK_CFG_0 */
 	MUX(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3),
@@ -948,6 +968,9 @@ static void __init mtk_infrasys_init(struct device_node *node)
 						clk_data);
 	mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data);
 
+	mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes),
+				  clk_data);
+
 	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
 	if (r)
 		pr_err("%s(): could not register clock provider: %d\n",

+ 3 - 3
drivers/clk/meson/Kconfig

@@ -7,9 +7,9 @@ config COMMON_CLK_MESON8B
 	bool
 	depends on COMMON_CLK_AMLOGIC
 	help
-	  Support for the clock controller on AmLogic S805 devices, aka
-	  meson8b. Say Y if you want peripherals and CPU frequency scaling to
-	  work.
+	  Support for the clock controller on AmLogic S802 (Meson8),
+	  S805 (Meson8b) and S812 (Meson8m2) devices. Say Y if you
+	  want peripherals and CPU frequency scaling to work.
 
 config COMMON_CLK_GXBB
 	bool

+ 68 - 69
drivers/clk/meson/gxbb.c

@@ -278,20 +278,6 @@ static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
 	{ /* sentinel */ },
 };
 
-static const struct clk_div_table cpu_div_table[] = {
-	{ .val = 1, .div = 1 },
-	{ .val = 2, .div = 2 },
-	{ .val = 3, .div = 3 },
-	{ .val = 2, .div = 4 },
-	{ .val = 3, .div = 6 },
-	{ .val = 4, .div = 8 },
-	{ .val = 5, .div = 10 },
-	{ .val = 6, .div = 12 },
-	{ .val = 7, .div = 14 },
-	{ .val = 8, .div = 16 },
-	{ /* sentinel */ },
-};
-
 static struct meson_clk_pll gxbb_fixed_pll = {
 	.m = {
 		.reg_off = HHI_MPLL_CNTL,
@@ -612,23 +598,16 @@ static struct meson_clk_mpll gxbb_mpll2 = {
 };
 
 /*
- * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL
- * post-dividers and should be modeled with their respective PLLs via the
- * forthcoming coordinated clock rates feature
+ * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers
+ * and should be modeled with their respective PLLs via the forthcoming
+ * coordinated clock rates feature
  */
-static struct meson_clk_cpu gxbb_cpu_clk = {
-	.reg_off = HHI_SYS_CPU_CLK_CNTL1,
-	.div_table = cpu_div_table,
-	.clk_nb.notifier_call = meson_clk_cpu_notifier_cb,
-	.hw.init = &(struct clk_init_data){
-		.name = "cpu_clk",
-		.ops = &meson_clk_cpu_ops,
-		.parent_names = (const char *[]){ "sys_pll" },
-		.num_parents = 1,
-	},
-};
 
-static u32 mux_table_clk81[]	= { 6, 5, 7 };
+static u32 mux_table_clk81[]	= { 0, 2, 3, 4, 5, 6, 7 };
+static const char * const clk81_parent_names[] = {
+	"xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
+	"fclk_div3", "fclk_div5"
+};
 
 static struct clk_mux gxbb_mpeg_clk_sel = {
 	.reg = (void *)HHI_MPEG_CLK_CNTL,
@@ -641,13 +620,12 @@ static struct clk_mux gxbb_mpeg_clk_sel = {
 		.name = "mpeg_clk_sel",
 		.ops = &clk_mux_ro_ops,
 		/*
-		 * FIXME bits 14:12 selects from 8 possible parents:
+		 * bits 14:12 selects from 8 possible parents:
 		 * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
 		 * fclk_div4, fclk_div3, fclk_div5
 		 */
-		.parent_names = (const char *[]){ "fclk_div3", "fclk_div4",
-			"fclk_div5" },
-		.num_parents = 3,
+		.parent_names = clk81_parent_names,
+		.num_parents = ARRAY_SIZE(clk81_parent_names),
 		.flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
 	},
 };
@@ -676,7 +654,7 @@ static struct clk_gate gxbb_clk81 = {
 		.ops = &clk_gate_ops,
 		.parent_names = (const char *[]){ "mpeg_clk_div" },
 		.num_parents = 1,
-		.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED | CLK_IS_CRITICAL),
+		.flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
 	},
 };
 
@@ -726,7 +704,7 @@ static struct clk_gate gxbb_sar_adc_clk = {
  */
 
 static u32 mux_table_mali_0_1[] = {0, 1, 2, 3, 4, 5, 6, 7};
-static const char *gxbb_mali_0_1_parent_names[] = {
+static const char * const gxbb_mali_0_1_parent_names[] = {
 	"xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7",
 	"fclk_div4", "fclk_div3", "fclk_div5"
 };
@@ -826,7 +804,7 @@ static struct clk_gate gxbb_mali_1 = {
 };
 
 static u32 mux_table_mali[] = {0, 1};
-static const char *gxbb_mali_parent_names[] = {
+static const char * const gxbb_mali_parent_names[] = {
 	"mali_0", "mali_1"
 };
 
@@ -951,6 +929,51 @@ static struct clk_mux gxbb_cts_i958 = {
 	},
 };
 
+static struct clk_divider gxbb_32k_clk_div = {
+	.reg = (void *)HHI_32K_CLK_CNTL,
+	.shift = 0,
+	.width = 14,
+	.lock = &clk_lock,
+	.hw.init = &(struct clk_init_data){
+		.name = "32k_clk_div",
+		.ops = &clk_divider_ops,
+		.parent_names = (const char *[]){ "32k_clk_sel" },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST,
+	},
+};
+
+static struct clk_gate gxbb_32k_clk = {
+	.reg = (void *)HHI_32K_CLK_CNTL,
+	.bit_idx = 15,
+	.lock = &clk_lock,
+	.hw.init = &(struct clk_init_data){
+		.name = "32k_clk",
+		.ops = &clk_gate_ops,
+		.parent_names = (const char *[]){ "32k_clk_div" },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const char * const gxbb_32k_clk_parent_names[] = {
+	"xtal", "cts_slow_oscin", "fclk_div3", "fclk_div5"
+};
+
+static struct clk_mux gxbb_32k_clk_sel = {
+	.reg = (void *)HHI_32K_CLK_CNTL,
+	.mask = 0x3,
+	.shift = 16,
+	.lock = &clk_lock,
+		.hw.init = &(struct clk_init_data){
+		.name = "32k_clk_sel",
+		.ops = &clk_mux_ops,
+		.parent_names = gxbb_32k_clk_parent_names,
+		.num_parents = 4,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
 /* Everything Else (EE) domain gates */
 static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0);
 static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1);
@@ -1045,7 +1068,6 @@ static MESON_GATE(gxbb_ao_i2c, HHI_GCLK_AO, 4);
 static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
 	.hws = {
 		[CLKID_SYS_PLL]		    = &gxbb_sys_pll.hw,
-		[CLKID_CPUCLK]		    = &gxbb_cpu_clk.hw,
 		[CLKID_HDMI_PLL]	    = &gxbb_hdmi_pll.hw,
 		[CLKID_FIXED_PLL]	    = &gxbb_fixed_pll.hw,
 		[CLKID_FCLK_DIV2]	    = &gxbb_fclk_div2.hw,
@@ -1158,6 +1180,9 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
 		[CLKID_CTS_MCLK_I958_SEL]   = &gxbb_cts_mclk_i958_sel.hw,
 		[CLKID_CTS_MCLK_I958_DIV]   = &gxbb_cts_mclk_i958_div.hw,
 		[CLKID_CTS_I958]	    = &gxbb_cts_i958.hw,
+		[CLKID_32K_CLK]		    = &gxbb_32k_clk.hw,
+		[CLKID_32K_CLK_SEL]	    = &gxbb_32k_clk_sel.hw,
+		[CLKID_32K_CLK_DIV]	    = &gxbb_32k_clk_div.hw,
 	},
 	.num = NR_CLKS,
 };
@@ -1165,7 +1190,6 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
 static struct clk_hw_onecell_data gxl_hw_onecell_data = {
 	.hws = {
 		[CLKID_SYS_PLL]		    = &gxbb_sys_pll.hw,
-		[CLKID_CPUCLK]		    = &gxbb_cpu_clk.hw,
 		[CLKID_HDMI_PLL]	    = &gxbb_hdmi_pll.hw,
 		[CLKID_FIXED_PLL]	    = &gxbb_fixed_pll.hw,
 		[CLKID_FCLK_DIV2]	    = &gxbb_fclk_div2.hw,
@@ -1278,6 +1302,9 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
 		[CLKID_CTS_MCLK_I958_SEL]   = &gxbb_cts_mclk_i958_sel.hw,
 		[CLKID_CTS_MCLK_I958_DIV]   = &gxbb_cts_mclk_i958_div.hw,
 		[CLKID_CTS_I958]	    = &gxbb_cts_i958.hw,
+		[CLKID_32K_CLK]		    = &gxbb_32k_clk.hw,
+		[CLKID_32K_CLK_SEL]	    = &gxbb_32k_clk_sel.hw,
+		[CLKID_32K_CLK_DIV]	    = &gxbb_32k_clk_div.hw,
 	},
 	.num = NR_CLKS,
 };
@@ -1392,6 +1419,7 @@ static struct clk_gate *const gxbb_clk_gates[] = {
 	&gxbb_mali_1,
 	&gxbb_cts_amclk,
 	&gxbb_cts_mclk_i958,
+	&gxbb_32k_clk,
 };
 
 static struct clk_mux *const gxbb_clk_muxes[] = {
@@ -1403,6 +1431,7 @@ static struct clk_mux *const gxbb_clk_muxes[] = {
 	&gxbb_cts_amclk_sel,
 	&gxbb_cts_mclk_i958_sel,
 	&gxbb_cts_i958,
+	&gxbb_32k_clk_sel,
 };
 
 static struct clk_divider *const gxbb_clk_dividers[] = {
@@ -1411,6 +1440,7 @@ static struct clk_divider *const gxbb_clk_dividers[] = {
 	&gxbb_mali_0_div,
 	&gxbb_mali_1_div,
 	&gxbb_cts_mclk_i958_div,
+	&gxbb_32k_clk_div,
 };
 
 static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = {
@@ -1430,7 +1460,6 @@ struct clkc_data {
 	unsigned int clk_dividers_count;
 	struct meson_clk_audio_divider *const *clk_audio_dividers;
 	unsigned int clk_audio_dividers_count;
-	struct meson_clk_cpu *cpu_clk;
 	struct clk_hw_onecell_data *hw_onecell_data;
 };
 
@@ -1447,7 +1476,6 @@ static const struct clkc_data gxbb_clkc_data = {
 	.clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
 	.clk_audio_dividers = gxbb_audio_dividers,
 	.clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
-	.cpu_clk = &gxbb_cpu_clk,
 	.hw_onecell_data = &gxbb_hw_onecell_data,
 };
 
@@ -1464,7 +1492,6 @@ static const struct clkc_data gxl_clkc_data = {
 	.clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
 	.clk_audio_dividers = gxbb_audio_dividers,
 	.clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
-	.cpu_clk = &gxbb_cpu_clk,
 	.hw_onecell_data = &gxl_hw_onecell_data,
 };
 
@@ -1479,8 +1506,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
 	const struct clkc_data *clkc_data;
 	void __iomem *clk_base;
 	int ret, clkid, i;
-	struct clk_hw *parent_hw;
-	struct clk *parent_clk;
 	struct device *dev = &pdev->dev;
 
 	clkc_data = of_device_get_match_data(&pdev->dev);
@@ -1502,9 +1527,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
 	for (i = 0; i < clkc_data->clk_mplls_count; i++)
 		clkc_data->clk_mplls[i]->base = clk_base;
 
-	/* Populate the base address for CPU clk */
-	clkc_data->cpu_clk->base = clk_base;
-
 	/* Populate base address for gates */
 	for (i = 0; i < clkc_data->clk_gates_count; i++)
 		clkc_data->clk_gates[i]->reg = clk_base +
@@ -1538,29 +1560,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
 			goto iounmap;
 	}
 
-	/*
-	 * Register CPU clk notifier
-	 *
-	 * FIXME this is wrong for a lot of reasons. First, the muxes should be
-	 * struct clk_hw objects. Second, we shouldn't program the muxes in
-	 * notifier handlers. The tricky programming sequence will be handled
-	 * by the forthcoming coordinated clock rates mechanism once that
-	 * feature is released.
-	 *
-	 * Furthermore, looking up the parent this way is terrible. At some
-	 * point we will stop allocating a default struct clk when registering
-	 * a new clk_hw, and this hack will no longer work. Releasing the ccr
-	 * feature before that time solves the problem :-)
-	 */
-	parent_hw = clk_hw_get_parent(&clkc_data->cpu_clk->hw);
-	parent_clk = parent_hw->clk;
-	ret = clk_notifier_register(parent_clk, &clkc_data->cpu_clk->clk_nb);
-	if (ret) {
-		pr_err("%s: failed to register clock notifier for cpu_clk\n",
-				__func__);
-		goto iounmap;
-	}
-
 	return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
 			clkc_data->hw_onecell_data);
 

+ 5 - 2
drivers/clk/meson/gxbb.h

@@ -171,7 +171,7 @@
  * to be exposed to client nodes in DT: include/dt-bindings/clock/gxbb-clkc.h
  */
 #define CLKID_SYS_PLL		  0
-#define CLKID_CPUCLK		  1
+/* ID 1 is unused (it was used by the non-existing CLKID_CPUCLK before) */
 /* CLKID_HDMI_PLL */
 #define CLKID_FIXED_PLL		  3
 /* CLKID_FCLK_DIV2 */
@@ -284,8 +284,11 @@
 #define CLKID_CTS_MCLK_I958_SEL	  111
 #define CLKID_CTS_MCLK_I958_DIV	  112
 /* CLKID_CTS_I958 */
+#define CLKID_32K_CLK		  114
+#define CLKID_32K_CLK_SEL	  115
+#define CLKID_32K_CLK_DIV	  116
 
-#define NR_CLKS			  114
+#define NR_CLKS			  117
 
 /* include the CLKIDs that have been made part of the stable DT binding */
 #include <dt-bindings/clock/gxbb-clkc.h>

+ 5 - 2
drivers/clk/meson/meson8b.c

@@ -1,5 +1,6 @@
 /*
- * AmLogic S805 / Meson8b Clock Controller Driver
+ * AmLogic S802 (Meson8) / S805 (Meson8b) / S812 (Meson8m2) Clock Controller
+ * Driver
  *
  * Copyright (c) 2015 Endless Mobile, Inc.
  * Author: Carlo Caione <carlo@endlessm.com>
@@ -399,7 +400,7 @@ struct clk_gate meson8b_clk81 = {
 		.ops = &clk_gate_ops,
 		.parent_names = (const char *[]){ "mpeg_clk_div" },
 		.num_parents = 1,
-		.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
+		.flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
 	},
 };
 
@@ -777,7 +778,9 @@ iounmap:
 }
 
 static const struct of_device_id meson8b_clkc_match_table[] = {
+	{ .compatible = "amlogic,meson8-clkc" },
 	{ .compatible = "amlogic,meson8b-clkc" },
+	{ .compatible = "amlogic,meson8m2-clkc" },
 	{ }
 };
 

+ 71 - 36
drivers/clk/mvebu/ap806-system-controller.c

@@ -32,24 +32,38 @@ static struct clk_onecell_data ap806_clk_data = {
 	.clk_num = AP806_CLK_NUM,
 };
 
-static int ap806_syscon_clk_probe(struct platform_device *pdev)
+static char *ap806_unique_name(struct device *dev, struct device_node *np,
+			       char *name)
+{
+	const __be32 *reg;
+	u64 addr;
+
+	reg = of_get_property(np, "reg", NULL);
+	addr = of_translate_address(np, reg);
+	return devm_kasprintf(dev, GFP_KERNEL, "%llx-%s",
+			(unsigned long long)addr, name);
+}
+
+static int ap806_syscon_common_probe(struct platform_device *pdev,
+				     struct device_node *syscon_node)
 {
 	unsigned int freq_mode, cpuclk_freq;
 	const char *name, *fixedclk_name;
-	struct device_node *np = pdev->dev.of_node;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
 	struct regmap *regmap;
 	u32 reg;
 	int ret;
 
-	regmap = syscon_node_to_regmap(np);
+	regmap = syscon_node_to_regmap(syscon_node);
 	if (IS_ERR(regmap)) {
-		dev_err(&pdev->dev, "cannot get regmap\n");
+		dev_err(dev, "cannot get regmap\n");
 		return PTR_ERR(regmap);
 	}
 
 	ret = regmap_read(regmap, AP806_SAR_REG, &reg);
 	if (ret) {
-		dev_err(&pdev->dev, "cannot read from regmap\n");
+		dev_err(dev, "cannot read from regmap\n");
 		return ret;
 	}
 
@@ -89,7 +103,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev)
 		cpuclk_freq = 600;
 		break;
 	default:
-		dev_err(&pdev->dev, "invalid SAR value\n");
+		dev_err(dev, "invalid SAR value\n");
 		return -EINVAL;
 	}
 
@@ -97,18 +111,16 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev)
 	cpuclk_freq *= 1000 * 1000;
 
 	/* CPU clocks depend on the Sample At Reset configuration */
-	of_property_read_string_index(np, "clock-output-names",
-				      0, &name);
-	ap806_clks[0] = clk_register_fixed_rate(&pdev->dev, name, NULL,
+	name = ap806_unique_name(dev, syscon_node, "cpu-cluster-0");
+	ap806_clks[0] = clk_register_fixed_rate(dev, name, NULL,
 						0, cpuclk_freq);
 	if (IS_ERR(ap806_clks[0])) {
 		ret = PTR_ERR(ap806_clks[0]);
 		goto fail0;
 	}
 
-	of_property_read_string_index(np, "clock-output-names",
-				      1, &name);
-	ap806_clks[1] = clk_register_fixed_rate(&pdev->dev, name, NULL, 0,
+	name = ap806_unique_name(dev, syscon_node, "cpu-cluster-1");
+	ap806_clks[1] = clk_register_fixed_rate(dev, name, NULL, 0,
 						cpuclk_freq);
 	if (IS_ERR(ap806_clks[1])) {
 		ret = PTR_ERR(ap806_clks[1]);
@@ -116,9 +128,8 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev)
 	}
 
 	/* Fixed clock is always 1200 Mhz */
-	of_property_read_string_index(np, "clock-output-names",
-				      2, &fixedclk_name);
-	ap806_clks[2] = clk_register_fixed_rate(&pdev->dev, fixedclk_name, NULL,
+	fixedclk_name = ap806_unique_name(dev, syscon_node, "fixed");
+	ap806_clks[2] = clk_register_fixed_rate(dev, fixedclk_name, NULL,
 						0, 1200 * 1000 * 1000);
 	if (IS_ERR(ap806_clks[2])) {
 		ret = PTR_ERR(ap806_clks[2]);
@@ -126,8 +137,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev)
 	}
 
 	/* MSS Clock is fixed clock divided by 6 */
-	of_property_read_string_index(np, "clock-output-names",
-				      3, &name);
+	name = ap806_unique_name(dev, syscon_node, "mss");
 	ap806_clks[3] = clk_register_fixed_factor(NULL, name, fixedclk_name,
 						  0, 1, 6);
 	if (IS_ERR(ap806_clks[3])) {
@@ -135,20 +145,14 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev)
 		goto fail3;
 	}
 
-	/* eMMC Clock is fixed clock divided by 3 */
-	if (of_property_read_string_index(np, "clock-output-names",
-					  4, &name)) {
-		ap806_clk_data.clk_num--;
-		dev_warn(&pdev->dev,
-			 "eMMC clock missing: update the device tree!\n");
-	} else {
-		ap806_clks[4] = clk_register_fixed_factor(NULL, name,
-							  fixedclk_name,
-							  0, 1, 3);
-		if (IS_ERR(ap806_clks[4])) {
-			ret = PTR_ERR(ap806_clks[4]);
-			goto fail4;
-		}
+	/* SDIO(/eMMC) Clock is fixed clock divided by 3 */
+	name = ap806_unique_name(dev, syscon_node, "sdio");
+	ap806_clks[4] = clk_register_fixed_factor(NULL, name,
+						  fixedclk_name,
+						  0, 1, 3);
+	if (IS_ERR(ap806_clks[4])) {
+		ret = PTR_ERR(ap806_clks[4]);
+		goto fail4;
 	}
 
 	of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data);
@@ -172,17 +176,48 @@ fail0:
 	return ret;
 }
 
-static const struct of_device_id ap806_syscon_of_match[] = {
+static int ap806_syscon_legacy_probe(struct platform_device *pdev)
+{
+	dev_warn(&pdev->dev, FW_WARN "Using legacy device tree binding\n");
+	dev_warn(&pdev->dev, FW_WARN "Update your device tree:\n");
+	dev_warn(&pdev->dev, FW_WARN
+		 "This binding won't be supported in future kernel\n");
+
+	return ap806_syscon_common_probe(pdev, pdev->dev.of_node);
+
+}
+
+static int ap806_clock_probe(struct platform_device *pdev)
+{
+	return ap806_syscon_common_probe(pdev, pdev->dev.of_node->parent);
+}
+
+static const struct of_device_id ap806_syscon_legacy_of_match[] = {
 	{ .compatible = "marvell,ap806-system-controller", },
 	{ }
 };
 
-static struct platform_driver ap806_syscon_driver = {
-	.probe = ap806_syscon_clk_probe,
+static struct platform_driver ap806_syscon_legacy_driver = {
+	.probe = ap806_syscon_legacy_probe,
 	.driver		= {
 		.name	= "marvell-ap806-system-controller",
-		.of_match_table = ap806_syscon_of_match,
+		.of_match_table = ap806_syscon_legacy_of_match,
+		.suppress_bind_attrs = true,
+	},
+};
+builtin_platform_driver(ap806_syscon_legacy_driver);
+
+static const struct of_device_id ap806_clock_of_match[] = {
+	{ .compatible = "marvell,ap806-clock", },
+	{ }
+};
+
+static struct platform_driver ap806_clock_driver = {
+	.probe = ap806_clock_probe,
+	.driver		= {
+		.name	= "marvell-ap806-clock",
+		.of_match_table = ap806_clock_of_match,
 		.suppress_bind_attrs = true,
 	},
 };
-builtin_platform_driver(ap806_syscon_driver);
+builtin_platform_driver(ap806_clock_driver);

+ 4 - 3
drivers/clk/mvebu/armada-38x.c

@@ -49,7 +49,8 @@ static const u32 armada_38x_cpu_frequencies[] __initconst = {
 	0, 0, 0, 0,
 	1066 * 1000 * 1000, 0, 0, 0,
 	1332 * 1000 * 1000, 0, 0, 0,
-	1600 * 1000 * 1000,
+	1600 * 1000 * 1000, 0, 0, 0,
+	1866 * 1000 * 1000,
 };
 
 static u32 __init armada_38x_get_cpu_freq(void __iomem *sar)
@@ -79,7 +80,7 @@ static const int armada_38x_cpu_l2_ratios[32][2] __initconst = {
 	{1, 2}, {0, 1}, {0, 1}, {0, 1},
 	{1, 2}, {0, 1}, {0, 1}, {0, 1},
 	{1, 2}, {0, 1}, {0, 1}, {0, 1},
-	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{1, 2}, {0, 1}, {0, 1}, {0, 1},
 	{0, 1}, {0, 1}, {0, 1}, {0, 1},
 	{0, 1}, {0, 1}, {0, 1}, {0, 1},
 	{0, 1}, {0, 1}, {0, 1}, {0, 1},
@@ -90,7 +91,7 @@ static const int armada_38x_cpu_ddr_ratios[32][2] __initconst = {
 	{1, 2}, {0, 1}, {0, 1}, {0, 1},
 	{1, 2}, {0, 1}, {0, 1}, {0, 1},
 	{1, 2}, {0, 1}, {0, 1}, {0, 1},
-	{0, 1}, {0, 1}, {0, 1}, {0, 1},
+	{1, 2}, {0, 1}, {0, 1}, {0, 1},
 	{0, 1}, {0, 1}, {0, 1}, {0, 1},
 	{0, 1}, {0, 1}, {0, 1}, {0, 1},
 	{0, 1}, {0, 1}, {0, 1}, {0, 1},

+ 137 - 62
drivers/clk/mvebu/cp110-system-controller.c

@@ -11,15 +11,16 @@
  */
 
 /*
- * CP110 has 5 core clocks:
+ * CP110 has 6 core clocks:
  *
  *  - APLL		(1 Ghz)
  *    - PPv2 core	(1/3 APLL)
  *    - EIP		(1/2 APLL)
- *      - Core		(1/2 EIP)
+ *     - Core		(1/2 EIP)
+ *    - SDIO		(2/5 APLL)
  *
  *  - NAND clock, which is either:
- *    - Equal to the core clock
+ *    - Equal to SDIO clock
  *    - 2/5 APLL
  *
  * CP110 has 32 gatable clocks, for the various peripherals in the
@@ -46,7 +47,7 @@ enum {
 	CP110_CLK_TYPE_GATABLE,
 };
 
-#define CP110_MAX_CORE_CLOCKS		5
+#define CP110_MAX_CORE_CLOCKS		6
 #define CP110_MAX_GATABLE_CLOCKS	32
 
 #define CP110_CLK_NUM \
@@ -57,6 +58,7 @@ enum {
 #define CP110_CORE_EIP			2
 #define CP110_CORE_CORE			3
 #define CP110_CORE_NAND			4
+#define CP110_CORE_SDIO			5
 
 /* A number of gatable clocks need special handling */
 #define CP110_GATE_AUDIO		0
@@ -84,6 +86,33 @@ enum {
 #define CP110_GATE_EIP150		25
 #define CP110_GATE_EIP197		26
 
+static const char * const gate_base_names[] = {
+	[CP110_GATE_AUDIO]	= "audio",
+	[CP110_GATE_COMM_UNIT]	= "communit",
+	[CP110_GATE_NAND]	= "nand",
+	[CP110_GATE_PPV2]	= "ppv2",
+	[CP110_GATE_SDIO]	= "sdio",
+	[CP110_GATE_MG]		= "mg-domain",
+	[CP110_GATE_MG_CORE]	= "mg-core",
+	[CP110_GATE_XOR1]	= "xor1",
+	[CP110_GATE_XOR0]	= "xor0",
+	[CP110_GATE_GOP_DP]	= "gop-dp",
+	[CP110_GATE_PCIE_X1_0]	= "pcie_x10",
+	[CP110_GATE_PCIE_X1_1]	= "pcie_x11",
+	[CP110_GATE_PCIE_X4]	= "pcie_x4",
+	[CP110_GATE_PCIE_XOR]	= "pcie-xor",
+	[CP110_GATE_SATA]	= "sata",
+	[CP110_GATE_SATA_USB]	= "sata-usb",
+	[CP110_GATE_MAIN]	= "main",
+	[CP110_GATE_SDMMC_GOP]	= "sd-mmc-gop",
+	[CP110_GATE_SLOW_IO]	= "slow-io",
+	[CP110_GATE_USB3H0]	= "usb3h0",
+	[CP110_GATE_USB3H1]	= "usb3h1",
+	[CP110_GATE_USB3DEV]	= "usb3dev",
+	[CP110_GATE_EIP150]	= "eip150",
+	[CP110_GATE_EIP197]	= "eip197"
+};
+
 struct cp110_gate_clk {
 	struct clk_hw hw;
 	struct regmap *regmap;
@@ -186,17 +215,37 @@ static struct clk_hw *cp110_of_clk_get(struct of_phandle_args *clkspec,
 	return ERR_PTR(-EINVAL);
 }
 
-static int cp110_syscon_clk_probe(struct platform_device *pdev)
+static char *cp110_unique_name(struct device *dev, struct device_node *np,
+			       const char *name)
+{
+	const __be32 *reg;
+	u64 addr;
+
+	/* Do not create a name if there is no clock */
+	if (!name)
+		return NULL;
+
+	reg = of_get_property(np, "reg", NULL);
+	addr = of_translate_address(np, reg);
+	return devm_kasprintf(dev, GFP_KERNEL, "%llx-%s",
+			      (unsigned long long)addr, name);
+}
+
+static int cp110_syscon_common_probe(struct platform_device *pdev,
+				     struct device_node *syscon_node)
 {
 	struct regmap *regmap;
-	struct device_node *np = pdev->dev.of_node;
-	const char *ppv2_name, *apll_name, *core_name, *eip_name, *nand_name;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	const char *ppv2_name, *apll_name, *core_name, *eip_name, *nand_name,
+		*sdio_name;
 	struct clk_hw_onecell_data *cp110_clk_data;
 	struct clk_hw *hw, **cp110_clks;
 	u32 nand_clk_ctrl;
 	int i, ret;
+	char *gate_name[ARRAY_SIZE(gate_base_names)];
 
-	regmap = syscon_node_to_regmap(np);
+	regmap = syscon_node_to_regmap(syscon_node);
 	if (IS_ERR(regmap))
 		return PTR_ERR(regmap);
 
@@ -205,7 +254,7 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	cp110_clk_data = devm_kzalloc(&pdev->dev, sizeof(*cp110_clk_data) +
+	cp110_clk_data = devm_kzalloc(dev, sizeof(*cp110_clk_data) +
 				      sizeof(struct clk_hw *) * CP110_CLK_NUM,
 				      GFP_KERNEL);
 	if (!cp110_clk_data)
@@ -215,53 +264,47 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
 	cp110_clk_data->num = CP110_CLK_NUM;
 
 	/* Register the APLL which is the root of the hw tree */
-	of_property_read_string_index(np, "core-clock-output-names",
-				      CP110_CORE_APLL, &apll_name);
+	apll_name = cp110_unique_name(dev, syscon_node, "apll");
 	hw = clk_hw_register_fixed_rate(NULL, apll_name, NULL, 0,
 					1000 * 1000 * 1000);
 	if (IS_ERR(hw)) {
 		ret = PTR_ERR(hw);
-		goto fail0;
+		goto fail_apll;
 	}
 
 	cp110_clks[CP110_CORE_APLL] = hw;
 
 	/* PPv2 is APLL/3 */
-	of_property_read_string_index(np, "core-clock-output-names",
-				      CP110_CORE_PPV2, &ppv2_name);
+	ppv2_name = cp110_unique_name(dev, syscon_node, "ppv2-core");
 	hw = clk_hw_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3);
 	if (IS_ERR(hw)) {
 		ret = PTR_ERR(hw);
-		goto fail1;
+		goto fail_ppv2;
 	}
 
 	cp110_clks[CP110_CORE_PPV2] = hw;
 
 	/* EIP clock is APLL/2 */
-	of_property_read_string_index(np, "core-clock-output-names",
-				      CP110_CORE_EIP, &eip_name);
+	eip_name = cp110_unique_name(dev, syscon_node, "eip");
 	hw = clk_hw_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2);
 	if (IS_ERR(hw)) {
 		ret = PTR_ERR(hw);
-		goto fail2;
+		goto fail_eip;
 	}
 
 	cp110_clks[CP110_CORE_EIP] = hw;
 
 	/* Core clock is EIP/2 */
-	of_property_read_string_index(np, "core-clock-output-names",
-				      CP110_CORE_CORE, &core_name);
+	core_name = cp110_unique_name(dev, syscon_node, "core");
 	hw = clk_hw_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2);
 	if (IS_ERR(hw)) {
 		ret = PTR_ERR(hw);
-		goto fail3;
+		goto fail_core;
 	}
 
 	cp110_clks[CP110_CORE_CORE] = hw;
-
 	/* NAND can be either APLL/2.5 or core clock */
-	of_property_read_string_index(np, "core-clock-output-names",
-				      CP110_CORE_NAND, &nand_name);
+	nand_name = cp110_unique_name(dev, syscon_node, "nand-core");
 	if (nand_clk_ctrl & NF_CLOCK_SEL_400_MASK)
 		hw = clk_hw_register_fixed_factor(NULL, nand_name,
 						   apll_name, 0, 2, 5);
@@ -270,23 +313,31 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
 						   core_name, 0, 1, 1);
 	if (IS_ERR(hw)) {
 		ret = PTR_ERR(hw);
-		goto fail4;
+		goto fail_nand;
 	}
 
 	cp110_clks[CP110_CORE_NAND] = hw;
 
-	for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
-		const char *parent, *name;
-		int ret;
-
-		ret = of_property_read_string_index(np,
-						    "gate-clock-output-names",
-						    i, &name);
-		/* Reached the end of the list? */
-		if (ret < 0)
-			break;
+	/* SDIO clock is APLL/2.5 */
+	sdio_name = cp110_unique_name(dev, syscon_node, "sdio-core");
+	hw = clk_hw_register_fixed_factor(NULL, sdio_name,
+					  apll_name, 0, 2, 5);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
+		goto fail_sdio;
+	}
+
+	cp110_clks[CP110_CORE_SDIO] = hw;
+
+	/* create the unique name for all the gate clocks */
+	for (i = 0; i < ARRAY_SIZE(gate_base_names); i++)
+		gate_name[i] =	cp110_unique_name(dev, syscon_node,
+						  gate_base_names[i]);
+
+	for (i = 0; i < ARRAY_SIZE(gate_base_names); i++) {
+		const char *parent;
 
-		if (!strcmp(name, "none"))
+		if (gate_name[i] == NULL)
 			continue;
 
 		switch (i) {
@@ -295,14 +346,10 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
 		case CP110_GATE_EIP150:
 		case CP110_GATE_EIP197:
 		case CP110_GATE_SLOW_IO:
-			of_property_read_string_index(np,
-						      "gate-clock-output-names",
-						      CP110_GATE_MAIN, &parent);
+			parent = gate_name[CP110_GATE_MAIN];
 			break;
 		case CP110_GATE_MG:
-			of_property_read_string_index(np,
-						      "gate-clock-output-names",
-						      CP110_GATE_MG_CORE, &parent);
+			parent = gate_name[CP110_GATE_MG_CORE];
 			break;
 		case CP110_GATE_NAND:
 			parent = nand_name;
@@ -311,34 +358,30 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
 			parent = ppv2_name;
 			break;
 		case CP110_GATE_SDIO:
+			parent = sdio_name;
+			break;
 		case CP110_GATE_GOP_DP:
-			of_property_read_string_index(np,
-						      "gate-clock-output-names",
-						      CP110_GATE_SDMMC_GOP, &parent);
+			parent = gate_name[CP110_GATE_SDMMC_GOP];
 			break;
 		case CP110_GATE_XOR1:
 		case CP110_GATE_XOR0:
 		case CP110_GATE_PCIE_X1_0:
 		case CP110_GATE_PCIE_X1_1:
 		case CP110_GATE_PCIE_X4:
-			of_property_read_string_index(np,
-						      "gate-clock-output-names",
-						      CP110_GATE_PCIE_XOR, &parent);
+			parent = gate_name[CP110_GATE_PCIE_XOR];
 			break;
 		case CP110_GATE_SATA:
 		case CP110_GATE_USB3H0:
 		case CP110_GATE_USB3H1:
 		case CP110_GATE_USB3DEV:
-			of_property_read_string_index(np,
-						      "gate-clock-output-names",
-						      CP110_GATE_SATA_USB, &parent);
+			parent = gate_name[CP110_GATE_SATA_USB];
 			break;
 		default:
 			parent = core_name;
 			break;
 		}
+		hw = cp110_register_gate(gate_name[i], parent, regmap, i);
 
-		hw = cp110_register_gate(name, parent, regmap, i);
 		if (IS_ERR(hw)) {
 			ret = PTR_ERR(hw);
 			goto fail_gate;
@@ -364,30 +407,62 @@ fail_gate:
 			cp110_unregister_gate(hw);
 	}
 
+	clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_SDIO]);
+fail_sdio:
 	clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
-fail4:
+fail_nand:
 	clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
-fail3:
+fail_core:
 	clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
-fail2:
+fail_eip:
 	clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
-fail1:
+fail_ppv2:
 	clk_hw_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
-fail0:
+fail_apll:
 	return ret;
 }
 
-static const struct of_device_id cp110_syscon_of_match[] = {
+static int cp110_syscon_legacy_clk_probe(struct platform_device *pdev)
+{
+	dev_warn(&pdev->dev, FW_WARN "Using legacy device tree binding\n");
+	dev_warn(&pdev->dev, FW_WARN "Update your device tree:\n");
+	dev_warn(&pdev->dev, FW_WARN
+		 "This binding won't be supported in future kernels\n");
+
+	return cp110_syscon_common_probe(pdev, pdev->dev.of_node);
+}
+
+static int cp110_clk_probe(struct platform_device *pdev)
+{
+	return cp110_syscon_common_probe(pdev, pdev->dev.of_node->parent);
+}
+
+static const struct of_device_id cp110_syscon_legacy_of_match[] = {
 	{ .compatible = "marvell,cp110-system-controller0", },
 	{ }
 };
 
-static struct platform_driver cp110_syscon_driver = {
-	.probe = cp110_syscon_clk_probe,
+static struct platform_driver cp110_syscon_legacy_driver = {
+	.probe = cp110_syscon_legacy_clk_probe,
 	.driver		= {
 		.name	= "marvell-cp110-system-controller0",
-		.of_match_table = cp110_syscon_of_match,
+		.of_match_table = cp110_syscon_legacy_of_match,
+		.suppress_bind_attrs = true,
+	},
+};
+builtin_platform_driver(cp110_syscon_legacy_driver);
+
+static const struct of_device_id cp110_clock_of_match[] = {
+	{ .compatible = "marvell,cp110-clock", },
+	{ }
+};
+
+static struct platform_driver cp110_clock_driver = {
+	.probe = cp110_clk_probe,
+	.driver		= {
+		.name	= "marvell-cp110-clock",
+		.of_match_table = cp110_clock_of_match,
 		.suppress_bind_attrs = true,
 	},
 };
-builtin_platform_driver(cp110_syscon_driver);
+builtin_platform_driver(cp110_clock_driver);

+ 9 - 0
drivers/clk/qcom/Kconfig

@@ -82,6 +82,15 @@ config IPQ_LCC_806X
 	  Say Y if you want to use audio devices such as i2s, pcm,
 	  S/PDIF, etc.
 
+config IPQ_GCC_8074
+	tristate "IPQ8074 Global Clock Controller"
+	depends on COMMON_CLK_QCOM
+	help
+	  Support for global clock controller on ipq8074 devices.
+	  Say Y if you want to use peripheral devices such as UART, SPI,
+	  i2c, USB, SD/eMMC, etc. Select this for the root clock
+	  of ipq8074.
+
 config MSM_GCC_8660
 	tristate "MSM8660 Global Clock Controller"
 	depends on COMMON_CLK_QCOM

+ 1 - 0
drivers/clk/qcom/Makefile

@@ -17,6 +17,7 @@ obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
 obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
 obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
 obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
+obj-$(CONFIG_IPQ_GCC_8074) += gcc-ipq8074.o
 obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o
 obj-$(CONFIG_MDM_GCC_9615) += gcc-mdm9615.o
 obj-$(CONFIG_MDM_LCC_9615) += lcc-mdm9615.o

+ 1007 - 0
drivers/clk/qcom/gcc-ipq8074.c

@@ -0,0 +1,1007 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,gcc-ipq8074.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "clk-alpha-pll.h"
+#include "reset.h"
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+enum {
+	P_XO,
+	P_GPLL0,
+	P_GPLL0_DIV2,
+};
+
+static const char * const gcc_xo_gpll0_gpll0_out_main_div2[] = {
+	"xo",
+	"gpll0",
+	"gpll0_out_main_div2",
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll0_out_main_div2_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 1 },
+	{ P_GPLL0_DIV2, 4 },
+};
+
+static struct clk_alpha_pll gpll0_main = {
+	.offset = 0x21000,
+	.clkr = {
+		.enable_reg = 0x0b000,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gpll0_main",
+			.parent_names = (const char *[]){
+				"xo"
+			},
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_ops,
+		},
+	},
+};
+
+static struct clk_fixed_factor gpll0_out_main_div2 = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "gpll0_out_main_div2",
+		.parent_names = (const char *[]){
+			"gpll0_main"
+		},
+		.num_parents = 1,
+		.ops = &clk_fixed_factor_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_alpha_pll_postdiv gpll0 = {
+	.offset = 0x21000,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "gpll0",
+		.parent_names = (const char *[]){
+			"gpll0_main"
+		},
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_pcnoc_bfdcd_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(50000000, P_GPLL0, 16, 0, 0),
+	F(100000000, P_GPLL0, 8, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 pcnoc_bfdcd_clk_src = {
+	.cmd_rcgr = 0x27000,
+	.freq_tbl = ftbl_pcnoc_bfdcd_clk_src,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pcnoc_bfdcd_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+		.flags = CLK_IS_CRITICAL,
+	},
+};
+
+static struct clk_fixed_factor pcnoc_clk_src = {
+	.mult = 1,
+	.div = 1,
+	.hw.init = &(struct clk_init_data){
+		.name = "pcnoc_clk_src",
+		.parent_names = (const char *[]){
+			"pcnoc_bfdcd_clk_src"
+		},
+		.num_parents = 1,
+		.ops = &clk_fixed_factor_ops,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_branch gcc_sleep_clk_src = {
+	.halt_reg = 0x30000,
+	.clkr = {
+		.enable_reg = 0x30000,
+		.enable_mask = BIT(1),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_sleep_clk_src",
+			.parent_names = (const char *[]){
+				"sleep_clk"
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static const struct freq_tbl ftbl_blsp1_qup_i2c_apps_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(25000000, P_GPLL0_DIV2, 16, 0, 0),
+	F(50000000, P_GPLL0, 16, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0200c,
+	.freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup1_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_blsp1_qup_spi_apps_clk_src[] = {
+	F(960000, P_XO, 10, 1, 2),
+	F(4800000, P_XO, 4, 0, 0),
+	F(9600000, P_XO, 2, 0, 0),
+	F(12500000, P_GPLL0_DIV2, 16, 1, 2),
+	F(16000000, P_GPLL0, 10, 1, 5),
+	F(19200000, P_XO, 1, 0, 0),
+	F(25000000, P_GPLL0, 16, 1, 2),
+	F(50000000, P_GPLL0, 16, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
+	.cmd_rcgr = 0x02024,
+	.freq_tbl = ftbl_blsp1_qup_spi_apps_clk_src,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup1_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x03000,
+	.freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup2_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
+	.cmd_rcgr = 0x03014,
+	.freq_tbl = ftbl_blsp1_qup_spi_apps_clk_src,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup2_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x04000,
+	.freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup3_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
+	.cmd_rcgr = 0x04014,
+	.freq_tbl = ftbl_blsp1_qup_spi_apps_clk_src,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup3_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x05000,
+	.freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup4_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
+	.cmd_rcgr = 0x05014,
+	.freq_tbl = ftbl_blsp1_qup_spi_apps_clk_src,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup4_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x06000,
+	.freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup5_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = {
+	.cmd_rcgr = 0x06014,
+	.freq_tbl = ftbl_blsp1_qup_spi_apps_clk_src,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup5_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x07000,
+	.freq_tbl = ftbl_blsp1_qup_i2c_apps_clk_src,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup6_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = {
+	.cmd_rcgr = 0x07014,
+	.freq_tbl = ftbl_blsp1_qup_spi_apps_clk_src,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup6_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_blsp1_uart_apps_clk_src[] = {
+	F(3686400, P_GPLL0_DIV2, 1, 144, 15625),
+	F(7372800, P_GPLL0_DIV2, 1, 288, 15625),
+	F(14745600, P_GPLL0_DIV2, 1, 576, 15625),
+	F(16000000, P_GPLL0_DIV2, 5, 1, 5),
+	F(19200000, P_XO, 1, 0, 0),
+	F(24000000, P_GPLL0, 1, 3, 100),
+	F(25000000, P_GPLL0, 16, 1, 2),
+	F(32000000, P_GPLL0, 1, 1, 25),
+	F(40000000, P_GPLL0, 1, 1, 20),
+	F(46400000, P_GPLL0, 1, 29, 500),
+	F(48000000, P_GPLL0, 1, 3, 50),
+	F(51200000, P_GPLL0, 1, 8, 125),
+	F(56000000, P_GPLL0, 1, 7, 100),
+	F(58982400, P_GPLL0, 1, 1152, 15625),
+	F(60000000, P_GPLL0, 1, 3, 40),
+	F(64000000, P_GPLL0, 12.5, 1, 1),
+	{ }
+};
+
+static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
+	.cmd_rcgr = 0x02044,
+	.freq_tbl = ftbl_blsp1_uart_apps_clk_src,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart1_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
+	.cmd_rcgr = 0x03034,
+	.freq_tbl = ftbl_blsp1_uart_apps_clk_src,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart2_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart3_apps_clk_src = {
+	.cmd_rcgr = 0x04034,
+	.freq_tbl = ftbl_blsp1_uart_apps_clk_src,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart3_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart4_apps_clk_src = {
+	.cmd_rcgr = 0x05034,
+	.freq_tbl = ftbl_blsp1_uart_apps_clk_src,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart4_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart5_apps_clk_src = {
+	.cmd_rcgr = 0x06034,
+	.freq_tbl = ftbl_blsp1_uart_apps_clk_src,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart5_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart6_apps_clk_src = {
+	.cmd_rcgr = 0x07034,
+	.freq_tbl = ftbl_blsp1_uart_apps_clk_src,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart6_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
+		.num_parents = 3,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch gcc_blsp1_ahb_clk = {
+	.halt_reg = 0x01008,
+	.clkr = {
+		.enable_reg = 0x01008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_ahb_clk",
+			.parent_names = (const char *[]){
+				"pcnoc_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
+	.halt_reg = 0x02008,
+	.clkr = {
+		.enable_reg = 0x02008,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup1_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup1_i2c_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
+	.halt_reg = 0x02004,
+	.clkr = {
+		.enable_reg = 0x02004,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup1_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup1_spi_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
+	.halt_reg = 0x03010,
+	.clkr = {
+		.enable_reg = 0x03010,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup2_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup2_i2c_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
+	.halt_reg = 0x0300c,
+	.clkr = {
+		.enable_reg = 0x0300c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup2_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup2_spi_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
+	.halt_reg = 0x04010,
+	.clkr = {
+		.enable_reg = 0x04010,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup3_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup3_i2c_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
+	.halt_reg = 0x0400c,
+	.clkr = {
+		.enable_reg = 0x0400c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup3_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup3_spi_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
+	.halt_reg = 0x05010,
+	.clkr = {
+		.enable_reg = 0x05010,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup4_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup4_i2c_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
+	.halt_reg = 0x0500c,
+	.clkr = {
+		.enable_reg = 0x0500c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup4_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup4_spi_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = {
+	.halt_reg = 0x06010,
+	.clkr = {
+		.enable_reg = 0x06010,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup5_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup5_i2c_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = {
+	.halt_reg = 0x0600c,
+	.clkr = {
+		.enable_reg = 0x0600c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup5_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup5_spi_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = {
+	.halt_reg = 0x07010,
+	.clkr = {
+		.enable_reg = 0x07010,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup6_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup6_i2c_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = {
+	.halt_reg = 0x0700c,
+	.clkr = {
+		.enable_reg = 0x0700c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup6_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup6_spi_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart1_apps_clk = {
+	.halt_reg = 0x0203c,
+	.clkr = {
+		.enable_reg = 0x0203c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart1_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_uart1_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart2_apps_clk = {
+	.halt_reg = 0x0302c,
+	.clkr = {
+		.enable_reg = 0x0302c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart2_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_uart2_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart3_apps_clk = {
+	.halt_reg = 0x0402c,
+	.clkr = {
+		.enable_reg = 0x0402c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart3_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_uart3_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart4_apps_clk = {
+	.halt_reg = 0x0502c,
+	.clkr = {
+		.enable_reg = 0x0502c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart4_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_uart4_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart5_apps_clk = {
+	.halt_reg = 0x0602c,
+	.clkr = {
+		.enable_reg = 0x0602c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart5_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_uart5_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart6_apps_clk = {
+	.halt_reg = 0x0702c,
+	.clkr = {
+		.enable_reg = 0x0702c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart6_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_uart6_apps_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_prng_ahb_clk = {
+	.halt_reg = 0x13004,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x0b004,
+		.enable_mask = BIT(8),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_prng_ahb_clk",
+			.parent_names = (const char *[]){
+				"pcnoc_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_qpic_ahb_clk = {
+	.halt_reg = 0x57024,
+	.clkr = {
+		.enable_reg = 0x57024,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_qpic_ahb_clk",
+			.parent_names = (const char *[]){
+				"pcnoc_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_qpic_clk = {
+	.halt_reg = 0x57020,
+	.clkr = {
+		.enable_reg = 0x57020,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_qpic_clk",
+			.parent_names = (const char *[]){
+				"pcnoc_clk_src"
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_hw *gcc_ipq8074_hws[] = {
+	&gpll0_out_main_div2.hw,
+	&pcnoc_clk_src.hw,
+};
+
+static struct clk_regmap *gcc_ipq8074_clks[] = {
+	[GPLL0_MAIN] = &gpll0_main.clkr,
+	[GPLL0] = &gpll0.clkr,
+	[PCNOC_BFDCD_CLK_SRC] = &pcnoc_bfdcd_clk_src.clkr,
+	[GCC_SLEEP_CLK_SRC] = &gcc_sleep_clk_src.clkr,
+	[BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
+	[BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
+	[BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
+	[BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr,
+	[BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr,
+	[BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr,
+	[BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr,
+	[BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr,
+	[BLSP1_QUP5_I2C_APPS_CLK_SRC] = &blsp1_qup5_i2c_apps_clk_src.clkr,
+	[BLSP1_QUP5_SPI_APPS_CLK_SRC] = &blsp1_qup5_spi_apps_clk_src.clkr,
+	[BLSP1_QUP6_I2C_APPS_CLK_SRC] = &blsp1_qup6_i2c_apps_clk_src.clkr,
+	[BLSP1_QUP6_SPI_APPS_CLK_SRC] = &blsp1_qup6_spi_apps_clk_src.clkr,
+	[BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr,
+	[BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr,
+	[BLSP1_UART3_APPS_CLK_SRC] = &blsp1_uart3_apps_clk_src.clkr,
+	[BLSP1_UART4_APPS_CLK_SRC] = &blsp1_uart4_apps_clk_src.clkr,
+	[BLSP1_UART5_APPS_CLK_SRC] = &blsp1_uart5_apps_clk_src.clkr,
+	[BLSP1_UART6_APPS_CLK_SRC] = &blsp1_uart6_apps_clk_src.clkr,
+	[GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
+	[GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
+	[GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
+	[GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr,
+	[GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr,
+	[GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr,
+	[GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr,
+	[GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr,
+	[GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
+	[GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
+	[GCC_BLSP1_UART3_APPS_CLK] = &gcc_blsp1_uart3_apps_clk.clkr,
+	[GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr,
+	[GCC_BLSP1_UART5_APPS_CLK] = &gcc_blsp1_uart5_apps_clk.clkr,
+	[GCC_BLSP1_UART6_APPS_CLK] = &gcc_blsp1_uart6_apps_clk.clkr,
+	[GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
+	[GCC_QPIC_AHB_CLK] = &gcc_qpic_ahb_clk.clkr,
+	[GCC_QPIC_CLK] = &gcc_qpic_clk.clkr,
+};
+
+static const struct qcom_reset_map gcc_ipq8074_resets[] = {
+	[GCC_BLSP1_BCR] = { 0x01000, 0 },
+	[GCC_BLSP1_QUP1_BCR] = { 0x02000, 0 },
+	[GCC_BLSP1_UART1_BCR] = { 0x02038, 0 },
+	[GCC_BLSP1_QUP2_BCR] = { 0x03008, 0 },
+	[GCC_BLSP1_UART2_BCR] = { 0x03028, 0 },
+	[GCC_BLSP1_QUP3_BCR] = { 0x04008, 0 },
+	[GCC_BLSP1_UART3_BCR] = { 0x04028, 0 },
+	[GCC_BLSP1_QUP4_BCR] = { 0x05008, 0 },
+	[GCC_BLSP1_UART4_BCR] = { 0x05028, 0 },
+	[GCC_BLSP1_QUP5_BCR] = { 0x06008, 0 },
+	[GCC_BLSP1_UART5_BCR] = { 0x06028, 0 },
+	[GCC_BLSP1_QUP6_BCR] = { 0x07008, 0 },
+	[GCC_BLSP1_UART6_BCR] = { 0x07028, 0 },
+	[GCC_IMEM_BCR] = { 0x0e000, 0 },
+	[GCC_SMMU_BCR] = { 0x12000, 0 },
+	[GCC_APSS_TCU_BCR] = { 0x12050, 0 },
+	[GCC_SMMU_XPU_BCR] = { 0x12054, 0 },
+	[GCC_PCNOC_TBU_BCR] = { 0x12058, 0 },
+	[GCC_SMMU_CFG_BCR] = { 0x1208c, 0 },
+	[GCC_PRNG_BCR] = { 0x13000, 0 },
+	[GCC_BOOT_ROM_BCR] = { 0x13008, 0 },
+	[GCC_CRYPTO_BCR] = { 0x16000, 0 },
+	[GCC_WCSS_BCR] = { 0x18000, 0 },
+	[GCC_WCSS_Q6_BCR] = { 0x18100, 0 },
+	[GCC_NSS_BCR] = { 0x19000, 0 },
+	[GCC_SEC_CTRL_BCR] = { 0x1a000, 0 },
+	[GCC_ADSS_BCR] = { 0x1c000, 0 },
+	[GCC_DDRSS_BCR] = { 0x1e000, 0 },
+	[GCC_SYSTEM_NOC_BCR] = { 0x26000, 0 },
+	[GCC_PCNOC_BCR] = { 0x27018, 0 },
+	[GCC_TCSR_BCR] = { 0x28000, 0 },
+	[GCC_QDSS_BCR] = { 0x29000, 0 },
+	[GCC_DCD_BCR] = { 0x2a000, 0 },
+	[GCC_MSG_RAM_BCR] = { 0x2b000, 0 },
+	[GCC_MPM_BCR] = { 0x2c000, 0 },
+	[GCC_SPMI_BCR] = { 0x2e000, 0 },
+	[GCC_SPDM_BCR] = { 0x2f000, 0 },
+	[GCC_RBCPR_BCR] = { 0x33000, 0 },
+	[GCC_RBCPR_MX_BCR] = { 0x33014, 0 },
+	[GCC_TLMM_BCR] = { 0x34000, 0 },
+	[GCC_RBCPR_WCSS_BCR] = { 0x3a000, 0 },
+	[GCC_USB0_PHY_BCR] = { 0x3e034, 0 },
+	[GCC_USB3PHY_0_PHY_BCR] = { 0x3e03c, 0 },
+	[GCC_USB0_BCR] = { 0x3e070, 0 },
+	[GCC_USB1_PHY_BCR] = { 0x3f034, 0 },
+	[GCC_USB3PHY_1_PHY_BCR] = { 0x3f03c, 0 },
+	[GCC_USB1_BCR] = { 0x3f070, 0 },
+	[GCC_QUSB2_0_PHY_BCR] = { 0x4103c, 0 },
+	[GCC_QUSB2_1_PHY_BCR] = { 0x41040, 0 },
+	[GCC_SDCC1_BCR] = { 0x42000, 0 },
+	[GCC_SDCC2_BCR] = { 0x43000, 0 },
+	[GCC_SNOC_BUS_TIMEOUT0_BCR] = { 0x47000, 0 },
+	[GCC_SNOC_BUS_TIMEOUT2_BCR] = { 0x47008, 0 },
+	[GCC_SNOC_BUS_TIMEOUT3_BCR] = { 0x47010, 0 },
+	[GCC_PCNOC_BUS_TIMEOUT0_BCR] = { 0x48000, 0 },
+	[GCC_PCNOC_BUS_TIMEOUT1_BCR] = { 0x48008, 0 },
+	[GCC_PCNOC_BUS_TIMEOUT2_BCR] = { 0x48010, 0 },
+	[GCC_PCNOC_BUS_TIMEOUT3_BCR] = { 0x48018, 0 },
+	[GCC_PCNOC_BUS_TIMEOUT4_BCR] = { 0x48020, 0 },
+	[GCC_PCNOC_BUS_TIMEOUT5_BCR] = { 0x48028, 0 },
+	[GCC_PCNOC_BUS_TIMEOUT6_BCR] = { 0x48030, 0 },
+	[GCC_PCNOC_BUS_TIMEOUT7_BCR] = { 0x48038, 0 },
+	[GCC_PCNOC_BUS_TIMEOUT8_BCR] = { 0x48040, 0 },
+	[GCC_PCNOC_BUS_TIMEOUT9_BCR] = { 0x48048, 0 },
+	[GCC_UNIPHY0_BCR] = { 0x56000, 0 },
+	[GCC_UNIPHY1_BCR] = { 0x56100, 0 },
+	[GCC_UNIPHY2_BCR] = { 0x56200, 0 },
+	[GCC_CMN_12GPLL_BCR] = { 0x56300, 0 },
+	[GCC_QPIC_BCR] = { 0x57018, 0 },
+	[GCC_MDIO_BCR] = { 0x58000, 0 },
+	[GCC_PCIE1_TBU_BCR] = { 0x65000, 0 },
+	[GCC_WCSS_CORE_TBU_BCR] = { 0x66000, 0 },
+	[GCC_WCSS_Q6_TBU_BCR] = { 0x67000, 0 },
+	[GCC_USB0_TBU_BCR] = { 0x6a000, 0 },
+	[GCC_USB1_TBU_BCR] = { 0x6a004, 0 },
+	[GCC_PCIE0_TBU_BCR] = { 0x6b000, 0 },
+	[GCC_NSS_NOC_TBU_BCR] = { 0x6e000, 0 },
+	[GCC_PCIE0_BCR] = { 0x75004, 0 },
+	[GCC_PCIE0_PHY_BCR] = { 0x75038, 0 },
+	[GCC_PCIE0PHY_PHY_BCR] = { 0x7503c, 0 },
+	[GCC_PCIE0_LINK_DOWN_BCR] = { 0x75044, 0 },
+	[GCC_PCIE1_BCR] = { 0x76004, 0 },
+	[GCC_PCIE1_PHY_BCR] = { 0x76038, 0 },
+	[GCC_PCIE1PHY_PHY_BCR] = { 0x7603c, 0 },
+	[GCC_PCIE1_LINK_DOWN_BCR] = { 0x76044, 0 },
+	[GCC_DCC_BCR] = { 0x77000, 0 },
+	[GCC_APC0_VOLTAGE_DROOP_DETECTOR_BCR] = { 0x78000, 0 },
+	[GCC_APC1_VOLTAGE_DROOP_DETECTOR_BCR] = { 0x79000, 0 },
+	[GCC_SMMU_CATS_BCR] = { 0x7c000, 0 },
+};
+
+static const struct of_device_id gcc_ipq8074_match_table[] = {
+	{ .compatible = "qcom,gcc-ipq8074" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, gcc_ipq8074_match_table);
+
+static const struct regmap_config gcc_ipq8074_regmap_config = {
+	.reg_bits       = 32,
+	.reg_stride     = 4,
+	.val_bits       = 32,
+	.max_register   = 0x7fffc,
+	.fast_io	= true,
+};
+
+static const struct qcom_cc_desc gcc_ipq8074_desc = {
+	.config = &gcc_ipq8074_regmap_config,
+	.clks = gcc_ipq8074_clks,
+	.num_clks = ARRAY_SIZE(gcc_ipq8074_clks),
+	.resets = gcc_ipq8074_resets,
+	.num_resets = ARRAY_SIZE(gcc_ipq8074_resets),
+};
+
+static int gcc_ipq8074_probe(struct platform_device *pdev)
+{
+	int ret, i;
+
+	for (i = 0; i < ARRAY_SIZE(gcc_ipq8074_hws); i++) {
+		ret = devm_clk_hw_register(&pdev->dev, gcc_ipq8074_hws[i]);
+		if (ret)
+			return ret;
+	}
+
+	return qcom_cc_probe(pdev, &gcc_ipq8074_desc);
+}
+
+static struct platform_driver gcc_ipq8074_driver = {
+	.probe = gcc_ipq8074_probe,
+	.driver = {
+		.name   = "qcom,gcc-ipq8074",
+		.of_match_table = gcc_ipq8074_match_table,
+	},
+};
+
+static int __init gcc_ipq8074_init(void)
+{
+	return platform_driver_register(&gcc_ipq8074_driver);
+}
+core_initcall(gcc_ipq8074_init);
+
+static void __exit gcc_ipq8074_exit(void)
+{
+	platform_driver_unregister(&gcc_ipq8074_driver);
+}
+module_exit(gcc_ipq8074_exit);
+
+MODULE_DESCRIPTION("QCOM GCC IPQ8074 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:gcc-ipq8074");

+ 1 - 0
drivers/clk/qcom/gcc-msm8916.c

@@ -1430,6 +1430,7 @@ static struct clk_branch gcc_ultaudio_stc_xo_clk = {
 };
 
 static const struct freq_tbl ftbl_codec_clk[] = {
+	F(9600000, P_XO, 2, 0, 0),
 	F(19200000, P_XO, 1, 0, 0),
 	F(11289600, P_EXT_MCLK, 1, 0, 0),
 	{ }

+ 124 - 15
drivers/clk/renesas/Kconfig

@@ -1,20 +1,129 @@
+config CLK_RENESAS
+	bool "Renesas SoC clock support" if COMPILE_TEST && !ARCH_RENESAS
+	default y if ARCH_RENESAS
+	select CLK_EMEV2 if ARCH_EMEV2
+	select CLK_RZA1 if ARCH_R7S72100
+	select CLK_R8A73A4 if ARCH_R8A73A4
+	select CLK_R8A7740 if ARCH_R8A7740
+	select CLK_R8A7743 if ARCH_R8A7743
+	select CLK_R8A7745 if ARCH_R8A7745
+	select CLK_R8A7778 if ARCH_R8A7778
+	select CLK_R8A7779 if ARCH_R8A7779
+	select CLK_R8A7790 if ARCH_R8A7790
+	select CLK_R8A7791 if ARCH_R8A7791 || ARCH_R8A7793
+	select CLK_R8A7792 if ARCH_R8A7792
+	select CLK_R8A7794 if ARCH_R8A7794
+	select CLK_R8A7795 if ARCH_R8A7795
+	select CLK_R8A7796 if ARCH_R8A7796
+	select CLK_SH73A0 if ARCH_SH73A0
+
+if CLK_RENESAS
+
+config CLK_RENESAS_LEGACY
+	bool "Legacy DT clock support"
+	depends on CLK_R8A7790 || CLK_R8A7791 || CLK_R8A7792 || CLK_R8A7794
+	default y
+	help
+	  Enable backward compatibility with old device trees describing a
+	  hierarchical representation of the various CPG and MSTP clocks.
+
+	  Say Y if you want your kernel to work with old DTBs.
+
+# SoC
+config CLK_EMEV2
+	bool "Emma Mobile EV2 clock support" if COMPILE_TEST
+
+config CLK_RZA1
+	bool
+	select CLK_RENESAS_CPG_MSTP
+
+config CLK_R8A73A4
+	bool
+	select CLK_RENESAS_CPG_MSTP
+	select CLK_RENESAS_DIV6
+
+config CLK_R8A7740
+	bool
+	select CLK_RENESAS_CPG_MSTP
+	select CLK_RENESAS_DIV6
+
+config CLK_R8A7743
+	bool
+	select CLK_RCAR_GEN2_CPG
+
+config CLK_R8A7745
+	bool
+	select CLK_RCAR_GEN2_CPG
+
+config CLK_R8A7778
+	bool
+	select CLK_RENESAS_CPG_MSTP
+
+config CLK_R8A7779
+	bool
+	select CLK_RENESAS_CPG_MSTP
+
+config CLK_R8A7790
+	bool
+	select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY
+	select CLK_RCAR_GEN2_CPG
+	select CLK_RENESAS_DIV6
+
+config CLK_R8A7791
+	bool
+	select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY
+	select CLK_RCAR_GEN2_CPG
+	select CLK_RENESAS_DIV6
+
+config CLK_R8A7792
+	bool
+	select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY
+	select CLK_RCAR_GEN2_CPG
+
+config CLK_R8A7794
+	bool
+	select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY
+	select CLK_RCAR_GEN2_CPG
+	select CLK_RENESAS_DIV6
+
+config CLK_R8A7795
+	bool
+	select CLK_RCAR_GEN3_CPG
+
+config CLK_R8A7796
+	bool
+	select CLK_RCAR_GEN3_CPG
+
+config CLK_SH73A0
+	bool
+	select CLK_RENESAS_CPG_MSTP
+	select CLK_RENESAS_DIV6
+
+
+# Family
+config CLK_RCAR_GEN2
+	bool
+	select CLK_RENESAS_CPG_MSTP
+	select CLK_RENESAS_DIV6
+
+config CLK_RCAR_GEN2_CPG
+	bool
+	select CLK_RENESAS_CPG_MSSR
+
+config CLK_RCAR_GEN3_CPG
+	bool
+	select CLK_RENESAS_CPG_MSSR
+
+
+# Generic
 config CLK_RENESAS_CPG_MSSR
 	bool
-	default y if ARCH_R8A7743
-	default y if ARCH_R8A7745
-	default y if ARCH_R8A7795
-	default y if ARCH_R8A7796
+	select CLK_RENESAS_DIV6
 
 config CLK_RENESAS_CPG_MSTP
 	bool
-	default y if ARCH_R7S72100
-	default y if ARCH_R8A73A4
-	default y if ARCH_R8A7740
-	default y if ARCH_R8A7778
-	default y if ARCH_R8A7779
-	default y if ARCH_R8A7790
-	default y if ARCH_R8A7791
-	default y if ARCH_R8A7792
-	default y if ARCH_R8A7793
-	default y if ARCH_R8A7794
-	default y if ARCH_SH73A0
+
+config CLK_RENESAS_DIV6
+	bool "DIV6 clock support" if COMPILE_TEST
+
+endif # CLK_RENESAS

+ 24 - 17
drivers/clk/renesas/Makefile

@@ -1,19 +1,26 @@
-obj-$(CONFIG_ARCH_EMEV2)		+= clk-emev2.o
-obj-$(CONFIG_ARCH_R7S72100)		+= clk-rz.o
-obj-$(CONFIG_ARCH_R8A73A4)		+= clk-r8a73a4.o clk-div6.o
-obj-$(CONFIG_ARCH_R8A7740)		+= clk-r8a7740.o clk-div6.o
-obj-$(CONFIG_ARCH_R8A7743)		+= r8a7743-cpg-mssr.o rcar-gen2-cpg.o
-obj-$(CONFIG_ARCH_R8A7745)		+= r8a7745-cpg-mssr.o rcar-gen2-cpg.o
-obj-$(CONFIG_ARCH_R8A7778)		+= clk-r8a7778.o
-obj-$(CONFIG_ARCH_R8A7779)		+= clk-r8a7779.o
-obj-$(CONFIG_ARCH_R8A7790)		+= clk-rcar-gen2.o clk-div6.o
-obj-$(CONFIG_ARCH_R8A7791)		+= clk-rcar-gen2.o clk-div6.o
-obj-$(CONFIG_ARCH_R8A7792)		+= clk-rcar-gen2.o clk-div6.o
-obj-$(CONFIG_ARCH_R8A7793)		+= clk-rcar-gen2.o clk-div6.o
-obj-$(CONFIG_ARCH_R8A7794)		+= clk-rcar-gen2.o clk-div6.o
-obj-$(CONFIG_ARCH_R8A7795)		+= r8a7795-cpg-mssr.o rcar-gen3-cpg.o
-obj-$(CONFIG_ARCH_R8A7796)		+= r8a7796-cpg-mssr.o rcar-gen3-cpg.o
-obj-$(CONFIG_ARCH_SH73A0)		+= clk-sh73a0.o clk-div6.o
+# SoC
+obj-$(CONFIG_CLK_EMEV2)			+= clk-emev2.o
+obj-$(CONFIG_CLK_RZA1)			+= clk-rz.o
+obj-$(CONFIG_CLK_R8A73A4)		+= clk-r8a73a4.o
+obj-$(CONFIG_CLK_R8A7740)		+= clk-r8a7740.o
+obj-$(CONFIG_CLK_R8A7743)		+= r8a7743-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A7745)		+= r8a7745-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A7778)		+= clk-r8a7778.o
+obj-$(CONFIG_CLK_R8A7779)		+= clk-r8a7779.o
+obj-$(CONFIG_CLK_R8A7790)		+= r8a7790-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A7791)		+= r8a7791-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A7792)		+= r8a7792-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A7794)		+= r8a7794-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A7795)		+= r8a7795-cpg-mssr.o
+obj-$(CONFIG_CLK_R8A7796)		+= r8a7796-cpg-mssr.o
+obj-$(CONFIG_CLK_SH73A0)		+= clk-sh73a0.o
 
-obj-$(CONFIG_CLK_RENESAS_CPG_MSSR)	+= renesas-cpg-mssr.o clk-div6.o
+# Family
+obj-$(CONFIG_CLK_RCAR_GEN2)		+= clk-rcar-gen2.o
+obj-$(CONFIG_CLK_RCAR_GEN2_CPG)		+= rcar-gen2-cpg.o
+obj-$(CONFIG_CLK_RCAR_GEN3_CPG)		+= rcar-gen3-cpg.o
+
+# Generic
+obj-$(CONFIG_CLK_RENESAS_CPG_MSSR)	+= renesas-cpg-mssr.o
 obj-$(CONFIG_CLK_RENESAS_CPG_MSTP)	+= clk-mstp.o
+obj-$(CONFIG_CLK_RENESAS_DIV6)		+= clk-div6.o

+ 1 - 1
drivers/clk/renesas/clk-mstp.c

@@ -325,7 +325,7 @@ fail_put:
 
 void cpg_mstp_detach_dev(struct generic_pm_domain *unused, struct device *dev)
 {
-	if (!list_empty(&dev->power.subsys_data->clock_list))
+	if (!pm_clk_no_clocks(dev))
 		pm_clk_destroy(dev);
 }
 

+ 19 - 4
drivers/clk/renesas/clk-rcar-gen2.c

@@ -272,11 +272,14 @@ struct cpg_pll_config {
 	unsigned int extal_div;
 	unsigned int pll1_mult;
 	unsigned int pll3_mult;
+	unsigned int pll0_mult;		/* For R-Car V2H and E2 only */
 };
 
 static const struct cpg_pll_config cpg_pll_configs[8] __initconst = {
-	{ 1, 208, 106 }, { 1, 208,  88 }, { 1, 156,  80 }, { 1, 156,  66 },
-	{ 2, 240, 122 }, { 2, 240, 102 }, { 2, 208, 106 }, { 2, 208,  88 },
+	{ 1, 208, 106, 200 }, { 1, 208,  88, 200 },
+	{ 1, 156,  80, 150 }, { 1, 156,  66, 150 },
+	{ 2, 240, 122, 230 }, { 2, 240, 102, 230 },
+	{ 2, 208, 106, 200 }, { 2, 208,  88, 200 },
 };
 
 /* SDHI divisors */
@@ -298,6 +301,12 @@ static const struct clk_div_table cpg_sd01_div_table[] = {
 
 static u32 cpg_mode __initdata;
 
+static const char * const pll0_mult_match[] = {
+	"renesas,r8a7792-cpg-clocks",
+	"renesas,r8a7794-cpg-clocks",
+	NULL
+};
+
 static struct clk * __init
 rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
 			     const struct cpg_pll_config *config,
@@ -318,9 +327,15 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
 		 * clock implementation and we currently have no need to change
 		 * the multiplier value.
 		 */
-		u32 value = clk_readl(cpg->reg + CPG_PLL0CR);
+		if (of_device_compatible_match(np, pll0_mult_match)) {
+			/* R-Car V2H and E2 do not have PLL0CR */
+			mult = config->pll0_mult;
+			div = 3;
+		} else {
+			u32 value = clk_readl(cpg->reg + CPG_PLL0CR);
+			mult = ((value >> 24) & ((1 << 7) - 1)) + 1;
+		}
 		parent_name = "main";
-		mult = ((value >> 24) & ((1 << 7) - 1)) + 1;
 	} else if (!strcmp(name, "pll1")) {
 		parent_name = "main";
 		mult = config->pll1_mult / 2;

+ 2 - 15
drivers/clk/renesas/r8a7745-cpg-mssr.c

@@ -167,16 +167,12 @@ static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = {
 	DEF_MOD("scu-dvc0",		1019,	MOD_CLK_ID(1017)),
 	DEF_MOD("scu-ctu1-mix1",	1020,	MOD_CLK_ID(1017)),
 	DEF_MOD("scu-ctu0-mix0",	1021,	MOD_CLK_ID(1017)),
-	DEF_MOD("scu-src9",		1022,	MOD_CLK_ID(1017)),
-	DEF_MOD("scu-src8",		1023,	MOD_CLK_ID(1017)),
-	DEF_MOD("scu-src7",		1024,	MOD_CLK_ID(1017)),
 	DEF_MOD("scu-src6",		1025,	MOD_CLK_ID(1017)),
 	DEF_MOD("scu-src5",		1026,	MOD_CLK_ID(1017)),
 	DEF_MOD("scu-src4",		1027,	MOD_CLK_ID(1017)),
 	DEF_MOD("scu-src3",		1028,	MOD_CLK_ID(1017)),
 	DEF_MOD("scu-src2",		1029,	MOD_CLK_ID(1017)),
 	DEF_MOD("scu-src1",		1030,	MOD_CLK_ID(1017)),
-	DEF_MOD("scu-src0",		1031,	MOD_CLK_ID(1017)),
 	DEF_MOD("scifa3",		1106,	R8A7745_CLK_MP),
 	DEF_MOD("scifa4",		1107,	R8A7745_CLK_MP),
 	DEF_MOD("scifa5",		1108,	R8A7745_CLK_MP),
@@ -194,31 +190,22 @@ static const unsigned int r8a7745_crit_mod_clks[] __initconst = {
  *    MD	EXTAL		PLL0	PLL1	PLL3
  * 14 13 19	(MHz)		*1	*2
  *---------------------------------------------------
- * 0  0  0	15		x200/3	x208/2	x106
  * 0  0  1	15		x200/3	x208/2	x88
- * 0  1  0	20		x150/3	x156/2	x80
  * 0  1  1	20		x150/3	x156/2	x66
- * 1  0  0	26 / 2		x230/3	x240/2	x122
  * 1  0  1	26 / 2		x230/3	x240/2	x102
- * 1  1  0	30 / 2		x200/3	x208/2	x106
  * 1  1  1	30 / 2		x200/3	x208/2	x88
  *
  * *1 :	Table 7.5b indicates VCO output (PLL0 = VCO/3)
  * *2 :	Table 7.5b indicates VCO output (PLL1 = VCO/2)
  */
-#define CPG_PLL_CONFIG_INDEX(md)	((((md) & BIT(14)) >> 12) | \
-					 (((md) & BIT(13)) >> 12) | \
-					 (((md) & BIT(19)) >> 19))
+#define CPG_PLL_CONFIG_INDEX(md)	((((md) & BIT(14)) >> 13) | \
+					 (((md) & BIT(13)) >> 13))
 
 static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
 	/* EXTAL div	PLL1 mult	PLL3 mult	PLL0 mult */
-	{ 1,		208,		106,		200	},
 	{ 1,		208,		88,		200	},
-	{ 1,		156,		80,		150	},
 	{ 1,		156,		66,		150	},
-	{ 2,		240,		122,		230	},
 	{ 2,		240,		102,		230	},
-	{ 2,		208,		106,		200	},
 	{ 2,		208,		88,		200	},
 };
 

+ 278 - 0
drivers/clk/renesas/r8a7790-cpg-mssr.c

@@ -0,0 +1,278 @@
+/*
+ * r8a7790 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2017 Glider bvba
+ *
+ * Based on clk-rcar-gen2.c
+ *
+ * Copyright (C) 2013 Ideas On Board SPRL
+ *
+ * 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; version 2 of the License.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7790-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+	/* Core Clock Outputs exported to DT */
+	LAST_DT_CORE_CLK = R8A7790_CLK_OSC,
+
+	/* External Input Clocks */
+	CLK_EXTAL,
+	CLK_USB_EXTAL,
+
+	/* Internal Core Clocks */
+	CLK_MAIN,
+	CLK_PLL0,
+	CLK_PLL1,
+	CLK_PLL3,
+	CLK_PLL1_DIV2,
+
+	/* Module Clocks */
+	MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7790_core_clks[] __initconst = {
+	/* External Clock Inputs */
+	DEF_INPUT("extal",     CLK_EXTAL),
+	DEF_INPUT("usb_extal", CLK_USB_EXTAL),
+
+	/* Internal Core Clocks */
+	DEF_BASE(".main",       CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+	DEF_BASE(".pll0",       CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+	DEF_BASE(".pll1",       CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+	DEF_BASE(".pll3",       CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+	DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+	/* Core Clock Outputs */
+	DEF_BASE("z",    R8A7790_CLK_Z,    CLK_TYPE_GEN2_Z,    CLK_PLL0),
+	DEF_BASE("lb",   R8A7790_CLK_LB,   CLK_TYPE_GEN2_LB,   CLK_PLL1),
+	DEF_BASE("adsp", R8A7790_CLK_ADSP, CLK_TYPE_GEN2_ADSP, CLK_PLL1),
+	DEF_BASE("sdh",  R8A7790_CLK_SDH,  CLK_TYPE_GEN2_SDH,  CLK_PLL1),
+	DEF_BASE("sd0",  R8A7790_CLK_SD0,  CLK_TYPE_GEN2_SD0,  CLK_PLL1),
+	DEF_BASE("sd1",  R8A7790_CLK_SD1,  CLK_TYPE_GEN2_SD1,  CLK_PLL1),
+	DEF_BASE("qspi", R8A7790_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+	DEF_BASE("rcan", R8A7790_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL),
+
+	DEF_FIXED("z2",     R8A7790_CLK_Z2,    CLK_PLL1,          2, 1),
+	DEF_FIXED("zg",     R8A7790_CLK_ZG,    CLK_PLL1,          3, 1),
+	DEF_FIXED("zx",     R8A7790_CLK_ZX,    CLK_PLL1,          3, 1),
+	DEF_FIXED("zs",     R8A7790_CLK_ZS,    CLK_PLL1,          6, 1),
+	DEF_FIXED("hp",     R8A7790_CLK_HP,    CLK_PLL1,         12, 1),
+	DEF_FIXED("i",      R8A7790_CLK_I,     CLK_PLL1,          2, 1),
+	DEF_FIXED("b",      R8A7790_CLK_B,     CLK_PLL1,         12, 1),
+	DEF_FIXED("p",      R8A7790_CLK_P,     CLK_PLL1,         24, 1),
+	DEF_FIXED("cl",     R8A7790_CLK_CL,    CLK_PLL1,         48, 1),
+	DEF_FIXED("m2",     R8A7790_CLK_M2,    CLK_PLL1,          8, 1),
+	DEF_FIXED("imp",    R8A7790_CLK_IMP,   CLK_PLL1,          4, 1),
+	DEF_FIXED("zb3",    R8A7790_CLK_ZB3,   CLK_PLL3,          4, 1),
+	DEF_FIXED("zb3d2",  R8A7790_CLK_ZB3D2, CLK_PLL3,          8, 1),
+	DEF_FIXED("ddr",    R8A7790_CLK_DDR,   CLK_PLL3,          8, 1),
+	DEF_FIXED("mp",     R8A7790_CLK_MP,    CLK_PLL1_DIV2,    15, 1),
+	DEF_FIXED("cp",     R8A7790_CLK_CP,    CLK_EXTAL,         2, 1),
+	DEF_FIXED("r",      R8A7790_CLK_R,     CLK_PLL1,      49152, 1),
+	DEF_FIXED("osc",    R8A7790_CLK_OSC,   CLK_PLL1,      12288, 1),
+
+	DEF_DIV6P1("sd2",   R8A7790_CLK_SD2,   CLK_PLL1_DIV2, 0x078),
+	DEF_DIV6P1("sd3",   R8A7790_CLK_SD3,   CLK_PLL1_DIV2, 0x26c),
+	DEF_DIV6P1("mmc0",  R8A7790_CLK_MMC0,  CLK_PLL1_DIV2, 0x240),
+	DEF_DIV6P1("mmc1",  R8A7790_CLK_MMC1,  CLK_PLL1_DIV2, 0x244),
+	DEF_DIV6P1("ssp",   R8A7790_CLK_SSP,   CLK_PLL1_DIV2, 0x248),
+	DEF_DIV6P1("ssprs", R8A7790_CLK_SSPRS, CLK_PLL1_DIV2, 0x24c),
+};
+
+static const struct mssr_mod_clk r8a7790_mod_clks[] __initconst = {
+	DEF_MOD("msiof0",		   0,	R8A7790_CLK_MP),
+	DEF_MOD("vcp1",			 100,	R8A7790_CLK_ZS),
+	DEF_MOD("vcp0",			 101,	R8A7790_CLK_ZS),
+	DEF_MOD("vpc1",			 102,	R8A7790_CLK_ZS),
+	DEF_MOD("vpc0",			 103,	R8A7790_CLK_ZS),
+	DEF_MOD("jpu",			 106,	R8A7790_CLK_M2),
+	DEF_MOD("ssp1",			 109,	R8A7790_CLK_ZS),
+	DEF_MOD("tmu1",			 111,	R8A7790_CLK_P),
+	DEF_MOD("3dg",			 112,	R8A7790_CLK_ZG),
+	DEF_MOD("2d-dmac",		 115,	R8A7790_CLK_ZS),
+	DEF_MOD("fdp1-2",		 117,	R8A7790_CLK_ZS),
+	DEF_MOD("fdp1-1",		 118,	R8A7790_CLK_ZS),
+	DEF_MOD("fdp1-0",		 119,	R8A7790_CLK_ZS),
+	DEF_MOD("tmu3",			 121,	R8A7790_CLK_P),
+	DEF_MOD("tmu2",			 122,	R8A7790_CLK_P),
+	DEF_MOD("cmt0",			 124,	R8A7790_CLK_R),
+	DEF_MOD("tmu0",			 125,	R8A7790_CLK_CP),
+	DEF_MOD("vsp1du1",		 127,	R8A7790_CLK_ZS),
+	DEF_MOD("vsp1du0",		 128,	R8A7790_CLK_ZS),
+	DEF_MOD("vsp1-rt",		 130,	R8A7790_CLK_ZS),
+	DEF_MOD("vsp1-sy",		 131,	R8A7790_CLK_ZS),
+	DEF_MOD("scifa2",		 202,	R8A7790_CLK_MP),
+	DEF_MOD("scifa1",		 203,	R8A7790_CLK_MP),
+	DEF_MOD("scifa0",		 204,	R8A7790_CLK_MP),
+	DEF_MOD("msiof2",		 205,	R8A7790_CLK_MP),
+	DEF_MOD("scifb0",		 206,	R8A7790_CLK_MP),
+	DEF_MOD("scifb1",		 207,	R8A7790_CLK_MP),
+	DEF_MOD("msiof1",		 208,	R8A7790_CLK_MP),
+	DEF_MOD("msiof3",		 215,	R8A7790_CLK_MP),
+	DEF_MOD("scifb2",		 216,	R8A7790_CLK_MP),
+	DEF_MOD("sys-dmac1",		 218,	R8A7790_CLK_ZS),
+	DEF_MOD("sys-dmac0",		 219,	R8A7790_CLK_ZS),
+	DEF_MOD("iic2",			 300,	R8A7790_CLK_HP),
+	DEF_MOD("tpu0",			 304,	R8A7790_CLK_CP),
+	DEF_MOD("mmcif1",		 305,	R8A7790_CLK_MMC1),
+	DEF_MOD("scif2",		 310,	R8A7790_CLK_P),
+	DEF_MOD("sdhi3",		 311,	R8A7790_CLK_SD3),
+	DEF_MOD("sdhi2",		 312,	R8A7790_CLK_SD2),
+	DEF_MOD("sdhi1",		 313,	R8A7790_CLK_SD1),
+	DEF_MOD("sdhi0",		 314,	R8A7790_CLK_SD0),
+	DEF_MOD("mmcif0",		 315,	R8A7790_CLK_MMC0),
+	DEF_MOD("iic0",			 318,	R8A7790_CLK_HP),
+	DEF_MOD("pciec",		 319,	R8A7790_CLK_MP),
+	DEF_MOD("iic1",			 323,	R8A7790_CLK_HP),
+	DEF_MOD("usb3.0",		 328,	R8A7790_CLK_MP),
+	DEF_MOD("cmt1",			 329,	R8A7790_CLK_R),
+	DEF_MOD("usbhs-dmac0",		 330,	R8A7790_CLK_HP),
+	DEF_MOD("usbhs-dmac1",		 331,	R8A7790_CLK_HP),
+	DEF_MOD("irqc",			 407,	R8A7790_CLK_CP),
+	DEF_MOD("intc-sys",		 408,	R8A7790_CLK_ZS),
+	DEF_MOD("audio-dmac1",		 501,	R8A7790_CLK_HP),
+	DEF_MOD("audio-dmac0",		 502,	R8A7790_CLK_HP),
+	DEF_MOD("adsp_mod",		 506,	R8A7790_CLK_ADSP),
+	DEF_MOD("thermal",		 522,	CLK_EXTAL),
+	DEF_MOD("pwm",			 523,	R8A7790_CLK_P),
+	DEF_MOD("usb-ehci",		 703,	R8A7790_CLK_MP),
+	DEF_MOD("usbhs",		 704,	R8A7790_CLK_HP),
+	DEF_MOD("hscif1",		 716,	R8A7790_CLK_ZS),
+	DEF_MOD("hscif0",		 717,	R8A7790_CLK_ZS),
+	DEF_MOD("scif1",		 720,	R8A7790_CLK_P),
+	DEF_MOD("scif0",		 721,	R8A7790_CLK_P),
+	DEF_MOD("du2",			 722,	R8A7790_CLK_ZX),
+	DEF_MOD("du1",			 723,	R8A7790_CLK_ZX),
+	DEF_MOD("du0",			 724,	R8A7790_CLK_ZX),
+	DEF_MOD("lvds1",		 725,	R8A7790_CLK_ZX),
+	DEF_MOD("lvds0",		 726,	R8A7790_CLK_ZX),
+	DEF_MOD("mlb",			 802,	R8A7790_CLK_HP),
+	DEF_MOD("vin3",			 808,	R8A7790_CLK_ZG),
+	DEF_MOD("vin2",			 809,	R8A7790_CLK_ZG),
+	DEF_MOD("vin1",			 810,	R8A7790_CLK_ZG),
+	DEF_MOD("vin0",			 811,	R8A7790_CLK_ZG),
+	DEF_MOD("etheravb",		 812,	R8A7790_CLK_HP),
+	DEF_MOD("ether",		 813,	R8A7790_CLK_P),
+	DEF_MOD("sata1",		 814,	R8A7790_CLK_ZS),
+	DEF_MOD("sata0",		 815,	R8A7790_CLK_ZS),
+	DEF_MOD("gyro-adc",		 901,	R8A7790_CLK_P),
+	DEF_MOD("gpio5",		 907,	R8A7790_CLK_CP),
+	DEF_MOD("gpio4",		 908,	R8A7790_CLK_CP),
+	DEF_MOD("gpio3",		 909,	R8A7790_CLK_CP),
+	DEF_MOD("gpio2",		 910,	R8A7790_CLK_CP),
+	DEF_MOD("gpio1",		 911,	R8A7790_CLK_CP),
+	DEF_MOD("gpio0",		 912,	R8A7790_CLK_CP),
+	DEF_MOD("can1",			 915,	R8A7790_CLK_P),
+	DEF_MOD("can0",			 916,	R8A7790_CLK_P),
+	DEF_MOD("qspi_mod",		 917,	R8A7790_CLK_QSPI),
+	DEF_MOD("iicdvfs",		 926,	R8A7790_CLK_CP),
+	DEF_MOD("i2c3",			 928,	R8A7790_CLK_HP),
+	DEF_MOD("i2c2",			 929,	R8A7790_CLK_HP),
+	DEF_MOD("i2c1",			 930,	R8A7790_CLK_HP),
+	DEF_MOD("i2c0",			 931,	R8A7790_CLK_HP),
+	DEF_MOD("ssi-all",		1005,	R8A7790_CLK_P),
+	DEF_MOD("ssi9",			1006,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi8",			1007,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi7",			1008,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi6",			1009,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi5",			1010,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi4",			1011,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi3",			1012,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi2",			1013,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi1",			1014,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi0",			1015,	MOD_CLK_ID(1005)),
+	DEF_MOD("scu-all",		1017,	R8A7790_CLK_P),
+	DEF_MOD("scu-dvc1",		1018,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-dvc0",		1019,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu1-mix1",	1020,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu0-mix0",	1021,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src9",		1022,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src8",		1023,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src7",		1024,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src6",		1025,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src5",		1026,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src4",		1027,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src3",		1028,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src2",		1029,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src1",		1030,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src0",		1031,	MOD_CLK_ID(1017)),
+};
+
+static const unsigned int r8a7790_crit_mod_clks[] __initconst = {
+	MOD_CLK_ID(408),	/* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ *   MD		EXTAL		PLL0	PLL1	PLL3
+ * 14 13 19	(MHz)		*1	*1
+ *---------------------------------------------------
+ * 0  0  0	15		x172/2	x208/2	x106
+ * 0  0  1	15		x172/2	x208/2	x88
+ * 0  1  0	20		x130/2	x156/2	x80
+ * 0  1  1	20		x130/2	x156/2	x66
+ * 1  0  0	26 / 2		x200/2	x240/2	x122
+ * 1  0  1	26 / 2		x200/2	x240/2	x102
+ * 1  1  0	30 / 2		x172/2	x208/2	x106
+ * 1  1  1	30 / 2		x172/2	x208/2	x88
+ *
+ * *1 :	Table 7.5a indicates VCO output (PLLx = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md)	((((md) & BIT(14)) >> 12) | \
+					 (((md) & BIT(13)) >> 12) | \
+					 (((md) & BIT(19)) >> 19))
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+	{ 1, 208, 106 }, { 1, 208,  88 }, { 1, 156,  80 }, { 1, 156,  66 },
+	{ 2, 240, 122 }, { 2, 240, 102 }, { 2, 208, 106 }, { 2, 208,  88 },
+};
+
+static int __init r8a7790_cpg_mssr_init(struct device *dev)
+{
+	const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+	u32 cpg_mode;
+	int error;
+
+	error = rcar_rst_read_mode_pins(&cpg_mode);
+	if (error)
+		return error;
+
+	cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+	return rcar_gen2_cpg_init(cpg_pll_config, 2, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7790_cpg_mssr_info __initconst = {
+	/* Core Clocks */
+	.core_clks = r8a7790_core_clks,
+	.num_core_clks = ARRAY_SIZE(r8a7790_core_clks),
+	.last_dt_core_clk = LAST_DT_CORE_CLK,
+	.num_total_core_clks = MOD_CLK_BASE,
+
+	/* Module Clocks */
+	.mod_clks = r8a7790_mod_clks,
+	.num_mod_clks = ARRAY_SIZE(r8a7790_mod_clks),
+	.num_hw_mod_clks = 12 * 32,
+
+	/* Critical Module Clocks */
+	.crit_mod_clks = r8a7790_crit_mod_clks,
+	.num_crit_mod_clks = ARRAY_SIZE(r8a7790_crit_mod_clks),
+
+	/* Callbacks */
+	.init = r8a7790_cpg_mssr_init,
+	.cpg_clk_register = rcar_gen2_cpg_clk_register,
+};

+ 286 - 0
drivers/clk/renesas/r8a7791-cpg-mssr.c

@@ -0,0 +1,286 @@
+/*
+ * r8a7791 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2015-2017 Glider bvba
+ *
+ * Based on clk-rcar-gen2.c
+ *
+ * Copyright (C) 2013 Ideas On Board SPRL
+ *
+ * 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; version 2 of the License.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7791-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+	/* Core Clock Outputs exported to DT */
+	LAST_DT_CORE_CLK = R8A7791_CLK_OSC,
+
+	/* External Input Clocks */
+	CLK_EXTAL,
+	CLK_USB_EXTAL,
+
+	/* Internal Core Clocks */
+	CLK_MAIN,
+	CLK_PLL0,
+	CLK_PLL1,
+	CLK_PLL3,
+	CLK_PLL1_DIV2,
+
+	/* Module Clocks */
+	MOD_CLK_BASE
+};
+
+static struct cpg_core_clk r8a7791_core_clks[] __initdata = {
+	/* External Clock Inputs */
+	DEF_INPUT("extal",     CLK_EXTAL),
+	DEF_INPUT("usb_extal", CLK_USB_EXTAL),
+
+	/* Internal Core Clocks */
+	DEF_BASE(".main",       CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+	DEF_BASE(".pll0",       CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+	DEF_BASE(".pll1",       CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+	DEF_BASE(".pll3",       CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+	DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+	/* Core Clock Outputs */
+	DEF_BASE("z",    R8A7791_CLK_Z,    CLK_TYPE_GEN2_Z,    CLK_PLL0),
+	DEF_BASE("lb",   R8A7791_CLK_LB,   CLK_TYPE_GEN2_LB,   CLK_PLL1),
+	DEF_BASE("adsp", R8A7791_CLK_ADSP, CLK_TYPE_GEN2_ADSP, CLK_PLL1),
+	DEF_BASE("sdh",  R8A7791_CLK_SDH,  CLK_TYPE_GEN2_SDH,  CLK_PLL1),
+	DEF_BASE("sd0",  R8A7791_CLK_SD0,  CLK_TYPE_GEN2_SD0,  CLK_PLL1),
+	DEF_BASE("qspi", R8A7791_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+	DEF_BASE("rcan", R8A7791_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL),
+
+	DEF_FIXED("zg",     R8A7791_CLK_ZG,    CLK_PLL1,          3, 1),
+	DEF_FIXED("zx",     R8A7791_CLK_ZX,    CLK_PLL1,          3, 1),
+	DEF_FIXED("zs",     R8A7791_CLK_ZS,    CLK_PLL1,          6, 1),
+	DEF_FIXED("hp",     R8A7791_CLK_HP,    CLK_PLL1,         12, 1),
+	DEF_FIXED("i",      R8A7791_CLK_I,     CLK_PLL1,          2, 1),
+	DEF_FIXED("b",      R8A7791_CLK_B,     CLK_PLL1,         12, 1),
+	DEF_FIXED("p",      R8A7791_CLK_P,     CLK_PLL1,         24, 1),
+	DEF_FIXED("cl",     R8A7791_CLK_CL,    CLK_PLL1,         48, 1),
+	DEF_FIXED("m2",     R8A7791_CLK_M2,    CLK_PLL1,          8, 1),
+	DEF_FIXED("zb3",    R8A7791_CLK_ZB3,   CLK_PLL3,          4, 1),
+	DEF_FIXED("zb3d2",  R8A7791_CLK_ZB3D2, CLK_PLL3,          8, 1),
+	DEF_FIXED("ddr",    R8A7791_CLK_DDR,   CLK_PLL3,          8, 1),
+	DEF_FIXED("mp",     R8A7791_CLK_MP,    CLK_PLL1_DIV2,    15, 1),
+	DEF_FIXED("cp",     R8A7791_CLK_CP,    CLK_EXTAL,         2, 1),
+	DEF_FIXED("r",      R8A7791_CLK_R,     CLK_PLL1,      49152, 1),
+	DEF_FIXED("osc",    R8A7791_CLK_OSC,   CLK_PLL1,      12288, 1),
+
+	DEF_DIV6P1("sd2",   R8A7791_CLK_SD2,   CLK_PLL1_DIV2, 0x078),
+	DEF_DIV6P1("sd3",   R8A7791_CLK_SD3,   CLK_PLL1_DIV2, 0x26c),
+	DEF_DIV6P1("mmc0",  R8A7791_CLK_MMC0,  CLK_PLL1_DIV2, 0x240),
+	DEF_DIV6P1("ssp",   R8A7791_CLK_SSP,   CLK_PLL1_DIV2, 0x248),
+	DEF_DIV6P1("ssprs", R8A7791_CLK_SSPRS, CLK_PLL1_DIV2, 0x24c),
+};
+
+static const struct mssr_mod_clk r8a7791_mod_clks[] __initconst = {
+	DEF_MOD("msiof0",		   0,	R8A7791_CLK_MP),
+	DEF_MOD("vcp0",			 101,	R8A7791_CLK_ZS),
+	DEF_MOD("vpc0",			 103,	R8A7791_CLK_ZS),
+	DEF_MOD("jpu",			 106,	R8A7791_CLK_M2),
+	DEF_MOD("ssp1",			 109,	R8A7791_CLK_ZS),
+	DEF_MOD("tmu1",			 111,	R8A7791_CLK_P),
+	DEF_MOD("3dg",			 112,	R8A7791_CLK_ZG),
+	DEF_MOD("2d-dmac",		 115,	R8A7791_CLK_ZS),
+	DEF_MOD("fdp1-1",		 118,	R8A7791_CLK_ZS),
+	DEF_MOD("fdp1-0",		 119,	R8A7791_CLK_ZS),
+	DEF_MOD("tmu3",			 121,	R8A7791_CLK_P),
+	DEF_MOD("tmu2",			 122,	R8A7791_CLK_P),
+	DEF_MOD("cmt0",			 124,	R8A7791_CLK_R),
+	DEF_MOD("tmu0",			 125,	R8A7791_CLK_CP),
+	DEF_MOD("vsp1du1",		 127,	R8A7791_CLK_ZS),
+	DEF_MOD("vsp1du0",		 128,	R8A7791_CLK_ZS),
+	DEF_MOD("vsp1-sy",		 131,	R8A7791_CLK_ZS),
+	DEF_MOD("scifa2",		 202,	R8A7791_CLK_MP),
+	DEF_MOD("scifa1",		 203,	R8A7791_CLK_MP),
+	DEF_MOD("scifa0",		 204,	R8A7791_CLK_MP),
+	DEF_MOD("msiof2",		 205,	R8A7791_CLK_MP),
+	DEF_MOD("scifb0",		 206,	R8A7791_CLK_MP),
+	DEF_MOD("scifb1",		 207,	R8A7791_CLK_MP),
+	DEF_MOD("msiof1",		 208,	R8A7791_CLK_MP),
+	DEF_MOD("scifb2",		 216,	R8A7791_CLK_MP),
+	DEF_MOD("sys-dmac1",		 218,	R8A7791_CLK_ZS),
+	DEF_MOD("sys-dmac0",		 219,	R8A7791_CLK_ZS),
+	DEF_MOD("tpu0",			 304,	R8A7791_CLK_CP),
+	DEF_MOD("sdhi3",		 311,	R8A7791_CLK_SD3),
+	DEF_MOD("sdhi2",		 312,	R8A7791_CLK_SD2),
+	DEF_MOD("sdhi0",		 314,	R8A7791_CLK_SD0),
+	DEF_MOD("mmcif0",		 315,	R8A7791_CLK_MMC0),
+	DEF_MOD("iic0",			 318,	R8A7791_CLK_HP),
+	DEF_MOD("pciec",		 319,	R8A7791_CLK_MP),
+	DEF_MOD("iic1",			 323,	R8A7791_CLK_HP),
+	DEF_MOD("usb3.0",		 328,	R8A7791_CLK_MP),
+	DEF_MOD("cmt1",			 329,	R8A7791_CLK_R),
+	DEF_MOD("usbhs-dmac0",		 330,	R8A7791_CLK_HP),
+	DEF_MOD("usbhs-dmac1",		 331,	R8A7791_CLK_HP),
+	DEF_MOD("irqc",			 407,	R8A7791_CLK_CP),
+	DEF_MOD("intc-sys",		 408,	R8A7791_CLK_ZS),
+	DEF_MOD("audio-dmac1",		 501,	R8A7791_CLK_HP),
+	DEF_MOD("audio-dmac0",		 502,	R8A7791_CLK_HP),
+	DEF_MOD("adsp_mod",		 506,	R8A7791_CLK_ADSP),
+	DEF_MOD("thermal",		 522,	CLK_EXTAL),
+	DEF_MOD("pwm",			 523,	R8A7791_CLK_P),
+	DEF_MOD("usb-ehci",		 703,	R8A7791_CLK_MP),
+	DEF_MOD("usbhs",		 704,	R8A7791_CLK_HP),
+	DEF_MOD("hscif2",		 713,	R8A7791_CLK_ZS),
+	DEF_MOD("scif5",		 714,	R8A7791_CLK_P),
+	DEF_MOD("scif4",		 715,	R8A7791_CLK_P),
+	DEF_MOD("hscif1",		 716,	R8A7791_CLK_ZS),
+	DEF_MOD("hscif0",		 717,	R8A7791_CLK_ZS),
+	DEF_MOD("scif3",		 718,	R8A7791_CLK_P),
+	DEF_MOD("scif2",		 719,	R8A7791_CLK_P),
+	DEF_MOD("scif1",		 720,	R8A7791_CLK_P),
+	DEF_MOD("scif0",		 721,	R8A7791_CLK_P),
+	DEF_MOD("du1",			 723,	R8A7791_CLK_ZX),
+	DEF_MOD("du0",			 724,	R8A7791_CLK_ZX),
+	DEF_MOD("lvds0",		 726,	R8A7791_CLK_ZX),
+	DEF_MOD("ipmmu-sgx",		 800,	R8A7791_CLK_ZX),
+	DEF_MOD("mlb",			 802,	R8A7791_CLK_HP),
+	DEF_MOD("vin2",			 809,	R8A7791_CLK_ZG),
+	DEF_MOD("vin1",			 810,	R8A7791_CLK_ZG),
+	DEF_MOD("vin0",			 811,	R8A7791_CLK_ZG),
+	DEF_MOD("etheravb",		 812,	R8A7791_CLK_HP),
+	DEF_MOD("ether",		 813,	R8A7791_CLK_P),
+	DEF_MOD("sata1",		 814,	R8A7791_CLK_ZS),
+	DEF_MOD("sata0",		 815,	R8A7791_CLK_ZS),
+	DEF_MOD("gyro-adc",		 901,	R8A7791_CLK_P),
+	DEF_MOD("gpio7",		 904,	R8A7791_CLK_CP),
+	DEF_MOD("gpio6",		 905,	R8A7791_CLK_CP),
+	DEF_MOD("gpio5",		 907,	R8A7791_CLK_CP),
+	DEF_MOD("gpio4",		 908,	R8A7791_CLK_CP),
+	DEF_MOD("gpio3",		 909,	R8A7791_CLK_CP),
+	DEF_MOD("gpio2",		 910,	R8A7791_CLK_CP),
+	DEF_MOD("gpio1",		 911,	R8A7791_CLK_CP),
+	DEF_MOD("gpio0",		 912,	R8A7791_CLK_CP),
+	DEF_MOD("can1",			 915,	R8A7791_CLK_P),
+	DEF_MOD("can0",			 916,	R8A7791_CLK_P),
+	DEF_MOD("qspi_mod",		 917,	R8A7791_CLK_QSPI),
+	DEF_MOD("i2c5",			 925,	R8A7791_CLK_HP),
+	DEF_MOD("iicdvfs",		 926,	R8A7791_CLK_CP),
+	DEF_MOD("i2c4",			 927,	R8A7791_CLK_HP),
+	DEF_MOD("i2c3",			 928,	R8A7791_CLK_HP),
+	DEF_MOD("i2c2",			 929,	R8A7791_CLK_HP),
+	DEF_MOD("i2c1",			 930,	R8A7791_CLK_HP),
+	DEF_MOD("i2c0",			 931,	R8A7791_CLK_HP),
+	DEF_MOD("ssi-all",		1005,	R8A7791_CLK_P),
+	DEF_MOD("ssi9",			1006,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi8",			1007,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi7",			1008,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi6",			1009,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi5",			1010,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi4",			1011,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi3",			1012,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi2",			1013,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi1",			1014,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi0",			1015,	MOD_CLK_ID(1005)),
+	DEF_MOD("scu-all",		1017,	R8A7791_CLK_P),
+	DEF_MOD("scu-dvc1",		1018,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-dvc0",		1019,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu1-mix1",	1020,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu0-mix0",	1021,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src9",		1022,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src8",		1023,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src7",		1024,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src6",		1025,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src5",		1026,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src4",		1027,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src3",		1028,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src2",		1029,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src1",		1030,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src0",		1031,	MOD_CLK_ID(1017)),
+	DEF_MOD("scifa3",		1106,	R8A7791_CLK_MP),
+	DEF_MOD("scifa4",		1107,	R8A7791_CLK_MP),
+	DEF_MOD("scifa5",		1108,	R8A7791_CLK_MP),
+};
+
+static const unsigned int r8a7791_crit_mod_clks[] __initconst = {
+	MOD_CLK_ID(408),	/* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ *   MD		EXTAL		PLL0	PLL1	PLL3
+ * 14 13 19	(MHz)		*1	*1
+ *---------------------------------------------------
+ * 0  0  0	15		x172/2	x208/2	x106
+ * 0  0  1	15		x172/2	x208/2	x88
+ * 0  1  0	20		x130/2	x156/2	x80
+ * 0  1  1	20		x130/2	x156/2	x66
+ * 1  0  0	26 / 2		x200/2	x240/2	x122
+ * 1  0  1	26 / 2		x200/2	x240/2	x102
+ * 1  1  0	30 / 2		x172/2	x208/2	x106
+ * 1  1  1	30 / 2		x172/2	x208/2	x88
+ *
+ * *1 :	Table 7.5a indicates VCO output (PLLx = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md)	((((md) & BIT(14)) >> 12) | \
+					 (((md) & BIT(13)) >> 12) | \
+					 (((md) & BIT(19)) >> 19))
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+	{ 1, 208, 106 }, { 1, 208,  88 }, { 1, 156,  80 }, { 1, 156,  66 },
+	{ 2, 240, 122 }, { 2, 240, 102 }, { 2, 208, 106 }, { 2, 208,  88 },
+};
+
+static int __init r8a7791_cpg_mssr_init(struct device *dev)
+{
+	const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+	struct device_node *np = dev->of_node;
+	unsigned int i;
+	u32 cpg_mode;
+	int error;
+
+	error = rcar_rst_read_mode_pins(&cpg_mode);
+	if (error)
+		return error;
+
+	cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+	if (of_device_is_compatible(np, "renesas,r8a7793-cpg-mssr")) {
+		/* R-Car M2-N uses a 1/5 divider for ZG */
+		for (i = 0; i < ARRAY_SIZE(r8a7791_core_clks); i++)
+			if (r8a7791_core_clks[i].id == R8A7791_CLK_ZG) {
+				r8a7791_core_clks[i].div = 5;
+				break;
+			}
+	}
+	return rcar_gen2_cpg_init(cpg_pll_config, 2, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7791_cpg_mssr_info __initconst = {
+	/* Core Clocks */
+	.core_clks = r8a7791_core_clks,
+	.num_core_clks = ARRAY_SIZE(r8a7791_core_clks),
+	.last_dt_core_clk = LAST_DT_CORE_CLK,
+	.num_total_core_clks = MOD_CLK_BASE,
+
+	/* Module Clocks */
+	.mod_clks = r8a7791_mod_clks,
+	.num_mod_clks = ARRAY_SIZE(r8a7791_mod_clks),
+	.num_hw_mod_clks = 12 * 32,
+
+	/* Critical Module Clocks */
+	.crit_mod_clks = r8a7791_crit_mod_clks,
+	.num_crit_mod_clks = ARRAY_SIZE(r8a7791_crit_mod_clks),
+
+	/* Callbacks */
+	.init = r8a7791_cpg_mssr_init,
+	.cpg_clk_register = rcar_gen2_cpg_clk_register,
+};

+ 221 - 0
drivers/clk/renesas/r8a7792-cpg-mssr.c

@@ -0,0 +1,221 @@
+/*
+ * r8a7792 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2017 Glider bvba
+ *
+ * Based on clk-rcar-gen2.c
+ *
+ * Copyright (C) 2013 Ideas On Board SPRL
+ *
+ * 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; version 2 of the License.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7792-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+	/* Core Clock Outputs exported to DT */
+	LAST_DT_CORE_CLK = R8A7792_CLK_OSC,
+
+	/* External Input Clocks */
+	CLK_EXTAL,
+
+	/* Internal Core Clocks */
+	CLK_MAIN,
+	CLK_PLL0,
+	CLK_PLL1,
+	CLK_PLL3,
+	CLK_PLL1_DIV2,
+
+	/* Module Clocks */
+	MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7792_core_clks[] __initconst = {
+	/* External Clock Inputs */
+	DEF_INPUT("extal",     CLK_EXTAL),
+
+	/* Internal Core Clocks */
+	DEF_BASE(".main",       CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+	DEF_BASE(".pll0",       CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+	DEF_BASE(".pll1",       CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+	DEF_BASE(".pll3",       CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+	DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+	/* Core Clock Outputs */
+	DEF_BASE("lb",   R8A7792_CLK_LB,   CLK_TYPE_GEN2_LB,   CLK_PLL1),
+	DEF_BASE("qspi", R8A7792_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+
+	DEF_FIXED("z",      R8A7792_CLK_Z,     CLK_PLL0,          1, 1),
+	DEF_FIXED("zg",     R8A7792_CLK_ZG,    CLK_PLL1,          5, 1),
+	DEF_FIXED("zx",     R8A7792_CLK_ZX,    CLK_PLL1,          3, 1),
+	DEF_FIXED("zs",     R8A7792_CLK_ZS,    CLK_PLL1,          6, 1),
+	DEF_FIXED("hp",     R8A7792_CLK_HP,    CLK_PLL1,         12, 1),
+	DEF_FIXED("i",      R8A7792_CLK_I,     CLK_PLL1,          3, 1),
+	DEF_FIXED("b",      R8A7792_CLK_B,     CLK_PLL1,         12, 1),
+	DEF_FIXED("p",      R8A7792_CLK_P,     CLK_PLL1,         24, 1),
+	DEF_FIXED("cl",     R8A7792_CLK_CL,    CLK_PLL1,         48, 1),
+	DEF_FIXED("m2",     R8A7792_CLK_M2,    CLK_PLL1,          8, 1),
+	DEF_FIXED("imp",    R8A7792_CLK_IMP,   CLK_PLL1,          4, 1),
+	DEF_FIXED("zb3",    R8A7792_CLK_ZB3,   CLK_PLL3,          4, 1),
+	DEF_FIXED("zb3d2",  R8A7792_CLK_ZB3D2, CLK_PLL3,          8, 1),
+	DEF_FIXED("ddr",    R8A7792_CLK_DDR,   CLK_PLL3,          8, 1),
+	DEF_FIXED("sd",     R8A7792_CLK_SD,    CLK_PLL1_DIV2,     8, 1),
+	DEF_FIXED("mp",     R8A7792_CLK_MP,    CLK_PLL1_DIV2,    15, 1),
+	DEF_FIXED("cp",     R8A7792_CLK_CP,    CLK_PLL1,         48, 1),
+	DEF_FIXED("cpex",   R8A7792_CLK_CPEX,  CLK_EXTAL,         2, 1),
+	DEF_FIXED("rcan",   R8A7792_CLK_RCAN,  CLK_PLL1_DIV2,    49, 1),
+	DEF_FIXED("r",      R8A7792_CLK_R,     CLK_PLL1,      49152, 1),
+	DEF_FIXED("osc",    R8A7792_CLK_OSC,   CLK_PLL1,      12288, 1),
+};
+
+static const struct mssr_mod_clk r8a7792_mod_clks[] __initconst = {
+	DEF_MOD("msiof0",		   0,	R8A7792_CLK_MP),
+	DEF_MOD("jpu",			 106,	R8A7792_CLK_M2),
+	DEF_MOD("tmu1",			 111,	R8A7792_CLK_P),
+	DEF_MOD("3dg",			 112,	R8A7792_CLK_ZG),
+	DEF_MOD("2d-dmac",		 115,	R8A7792_CLK_ZS),
+	DEF_MOD("tmu3",			 121,	R8A7792_CLK_P),
+	DEF_MOD("tmu2",			 122,	R8A7792_CLK_P),
+	DEF_MOD("cmt0",			 124,	R8A7792_CLK_R),
+	DEF_MOD("tmu0",			 125,	R8A7792_CLK_CP),
+	DEF_MOD("vsp1du1",		 127,	R8A7792_CLK_ZS),
+	DEF_MOD("vsp1du0",		 128,	R8A7792_CLK_ZS),
+	DEF_MOD("vsp1-sy",		 131,	R8A7792_CLK_ZS),
+	DEF_MOD("msiof1",		 208,	R8A7792_CLK_MP),
+	DEF_MOD("sys-dmac1",		 218,	R8A7792_CLK_ZS),
+	DEF_MOD("sys-dmac0",		 219,	R8A7792_CLK_ZS),
+	DEF_MOD("tpu0",			 304,	R8A7792_CLK_CP),
+	DEF_MOD("sdhi0",		 314,	R8A7792_CLK_SD),
+	DEF_MOD("cmt1",			 329,	R8A7792_CLK_R),
+	DEF_MOD("irqc",			 407,	R8A7792_CLK_CP),
+	DEF_MOD("intc-sys",		 408,	R8A7792_CLK_ZS),
+	DEF_MOD("audio-dmac0",		 502,	R8A7792_CLK_HP),
+	DEF_MOD("thermal",		 522,	CLK_EXTAL),
+	DEF_MOD("pwm",			 523,	R8A7792_CLK_P),
+	DEF_MOD("hscif1",		 716,	R8A7792_CLK_ZS),
+	DEF_MOD("hscif0",		 717,	R8A7792_CLK_ZS),
+	DEF_MOD("scif3",		 718,	R8A7792_CLK_P),
+	DEF_MOD("scif2",		 719,	R8A7792_CLK_P),
+	DEF_MOD("scif1",		 720,	R8A7792_CLK_P),
+	DEF_MOD("scif0",		 721,	R8A7792_CLK_P),
+	DEF_MOD("du1",			 723,	R8A7792_CLK_ZX),
+	DEF_MOD("du0",			 724,	R8A7792_CLK_ZX),
+	DEF_MOD("vin5",			 804,	R8A7792_CLK_ZG),
+	DEF_MOD("vin4",			 805,	R8A7792_CLK_ZG),
+	DEF_MOD("vin3",			 808,	R8A7792_CLK_ZG),
+	DEF_MOD("vin2",			 809,	R8A7792_CLK_ZG),
+	DEF_MOD("vin1",			 810,	R8A7792_CLK_ZG),
+	DEF_MOD("vin0",			 811,	R8A7792_CLK_ZG),
+	DEF_MOD("etheravb",		 812,	R8A7792_CLK_HP),
+	DEF_MOD("gyro-adc",		 901,	R8A7792_CLK_P),
+	DEF_MOD("gpio7",		 904,	R8A7792_CLK_CP),
+	DEF_MOD("gpio6",		 905,	R8A7792_CLK_CP),
+	DEF_MOD("gpio5",		 907,	R8A7792_CLK_CP),
+	DEF_MOD("gpio4",		 908,	R8A7792_CLK_CP),
+	DEF_MOD("gpio3",		 909,	R8A7792_CLK_CP),
+	DEF_MOD("gpio2",		 910,	R8A7792_CLK_CP),
+	DEF_MOD("gpio1",		 911,	R8A7792_CLK_CP),
+	DEF_MOD("gpio0",		 912,	R8A7792_CLK_CP),
+	DEF_MOD("gpio11",		 913,	R8A7792_CLK_CP),
+	DEF_MOD("gpio10",		 914,	R8A7792_CLK_CP),
+	DEF_MOD("can1",			 915,	R8A7792_CLK_P),
+	DEF_MOD("can0",			 916,	R8A7792_CLK_P),
+	DEF_MOD("qspi_mod",		 917,	R8A7792_CLK_QSPI),
+	DEF_MOD("gpio9",		 919,	R8A7792_CLK_CP),
+	DEF_MOD("gpio8",		 921,	R8A7792_CLK_CP),
+	DEF_MOD("i2c5",			 925,	R8A7792_CLK_HP),
+	DEF_MOD("iicdvfs",		 926,	R8A7792_CLK_CP),
+	DEF_MOD("i2c4",			 927,	R8A7792_CLK_HP),
+	DEF_MOD("i2c3",			 928,	R8A7792_CLK_HP),
+	DEF_MOD("i2c2",			 929,	R8A7792_CLK_HP),
+	DEF_MOD("i2c1",			 930,	R8A7792_CLK_HP),
+	DEF_MOD("i2c0",			 931,	R8A7792_CLK_HP),
+	DEF_MOD("ssi-all",		1005,	R8A7792_CLK_P),
+	DEF_MOD("ssi4",			1011,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi3",			1012,	MOD_CLK_ID(1005)),
+};
+
+static const unsigned int r8a7792_crit_mod_clks[] __initconst = {
+	MOD_CLK_ID(408),	/* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ *   MD		EXTAL		PLL0	PLL1	PLL3
+ * 14 13 19	(MHz)		*1	*2
+ *---------------------------------------------------
+ * 0  0  0	15		x200/3	x208/2	x106
+ * 0  0  1	15		x200/3	x208/2	x88
+ * 0  1  0	20		x150/3	x156/2	x80
+ * 0  1  1	20		x150/3	x156/2	x66
+ * 1  0  0	26 / 2		x230/3	x240/2	x122
+ * 1  0  1	26 / 2		x230/3	x240/2	x102
+ * 1  1  0	30 / 2		x200/3	x208/2	x106
+ * 1  1  1	30 / 2		x200/3	x208/2	x88
+ *
+ * *1 :	Table 7.5b indicates VCO output (PLL0 = VCO/3)
+ * *2 :	Table 7.5b indicates VCO output (PLL1 = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md)	((((md) & BIT(14)) >> 12) | \
+					 (((md) & BIT(13)) >> 12) | \
+					 (((md) & BIT(19)) >> 19))
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+	{ 1, 208, 106, 200 },
+	{ 1, 208,  88, 200 },
+	{ 1, 156,  80, 150 },
+	{ 1, 156,  66, 150 },
+	{ 2, 240, 122, 230 },
+	{ 2, 240, 102, 230 },
+	{ 2, 208, 106, 200 },
+	{ 2, 208,  88, 200 },
+};
+
+static int __init r8a7792_cpg_mssr_init(struct device *dev)
+{
+	const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+	u32 cpg_mode;
+	int error;
+
+	error = rcar_rst_read_mode_pins(&cpg_mode);
+	if (error)
+		return error;
+
+	cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+	return rcar_gen2_cpg_init(cpg_pll_config, 3, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7792_cpg_mssr_info __initconst = {
+	/* Core Clocks */
+	.core_clks = r8a7792_core_clks,
+	.num_core_clks = ARRAY_SIZE(r8a7792_core_clks),
+	.last_dt_core_clk = LAST_DT_CORE_CLK,
+	.num_total_core_clks = MOD_CLK_BASE,
+
+	/* Module Clocks */
+	.mod_clks = r8a7792_mod_clks,
+	.num_mod_clks = ARRAY_SIZE(r8a7792_mod_clks),
+	.num_hw_mod_clks = 12 * 32,
+
+	/* Critical Module Clocks */
+	.crit_mod_clks = r8a7792_crit_mod_clks,
+	.num_crit_mod_clks = ARRAY_SIZE(r8a7792_crit_mod_clks),
+
+	/* Callbacks */
+	.init = r8a7792_cpg_mssr_init,
+	.cpg_clk_register = rcar_gen2_cpg_clk_register,
+};

+ 255 - 0
drivers/clk/renesas/r8a7794-cpg-mssr.c

@@ -0,0 +1,255 @@
+/*
+ * r8a7794 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2017 Glider bvba
+ *
+ * Based on clk-rcar-gen2.c
+ *
+ * Copyright (C) 2013 Ideas On Board SPRL
+ *
+ * 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; version 2 of the License.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7794-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+	/* Core Clock Outputs exported to DT */
+	LAST_DT_CORE_CLK = R8A7794_CLK_OSC,
+
+	/* External Input Clocks */
+	CLK_EXTAL,
+	CLK_USB_EXTAL,
+
+	/* Internal Core Clocks */
+	CLK_MAIN,
+	CLK_PLL0,
+	CLK_PLL1,
+	CLK_PLL3,
+	CLK_PLL1_DIV2,
+
+	/* Module Clocks */
+	MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7794_core_clks[] __initconst = {
+	/* External Clock Inputs */
+	DEF_INPUT("extal",     CLK_EXTAL),
+	DEF_INPUT("usb_extal", CLK_USB_EXTAL),
+
+	/* Internal Core Clocks */
+	DEF_BASE(".main",       CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+	DEF_BASE(".pll0",       CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+	DEF_BASE(".pll1",       CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+	DEF_BASE(".pll3",       CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+	DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+	/* Core Clock Outputs */
+	DEF_BASE("lb",   R8A7794_CLK_LB,   CLK_TYPE_GEN2_LB,   CLK_PLL1),
+	DEF_BASE("adsp", R8A7794_CLK_ADSP, CLK_TYPE_GEN2_ADSP, CLK_PLL1),
+	DEF_BASE("sdh",  R8A7794_CLK_SDH,  CLK_TYPE_GEN2_SDH,  CLK_PLL1),
+	DEF_BASE("sd0",  R8A7794_CLK_SD0,  CLK_TYPE_GEN2_SD0,  CLK_PLL1),
+	DEF_BASE("qspi", R8A7794_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2),
+	DEF_BASE("rcan", R8A7794_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL),
+
+	DEF_FIXED("z2",     R8A7794_CLK_Z2,    CLK_PLL0,          1, 1),
+	DEF_FIXED("zg",     R8A7794_CLK_ZG,    CLK_PLL1,          6, 1),
+	DEF_FIXED("zx",     R8A7794_CLK_ZX,    CLK_PLL1,          3, 1),
+	DEF_FIXED("zs",     R8A7794_CLK_ZS,    CLK_PLL1,          6, 1),
+	DEF_FIXED("hp",     R8A7794_CLK_HP,    CLK_PLL1,         12, 1),
+	DEF_FIXED("i",      R8A7794_CLK_I,     CLK_PLL1,          2, 1),
+	DEF_FIXED("b",      R8A7794_CLK_B,     CLK_PLL1,         12, 1),
+	DEF_FIXED("p",      R8A7794_CLK_P,     CLK_PLL1,         24, 1),
+	DEF_FIXED("cl",     R8A7794_CLK_CL,    CLK_PLL1,         48, 1),
+	DEF_FIXED("cp",     R8A7794_CLK_CP,    CLK_PLL1,         48, 1),
+	DEF_FIXED("m2",     R8A7794_CLK_M2,    CLK_PLL1,          8, 1),
+	DEF_FIXED("zb3",    R8A7794_CLK_ZB3,   CLK_PLL3,          4, 1),
+	DEF_FIXED("zb3d2",  R8A7794_CLK_ZB3D2, CLK_PLL3,          8, 1),
+	DEF_FIXED("ddr",    R8A7794_CLK_DDR,   CLK_PLL3,          8, 1),
+	DEF_FIXED("mp",     R8A7794_CLK_MP,    CLK_PLL1_DIV2,    15, 1),
+	DEF_FIXED("cpex",   R8A7794_CLK_CPEX,  CLK_EXTAL,         2, 1),
+	DEF_FIXED("r",      R8A7794_CLK_R,     CLK_PLL1,      49152, 1),
+	DEF_FIXED("osc",    R8A7794_CLK_OSC,   CLK_PLL1,      12288, 1),
+
+	DEF_DIV6P1("sd2",   R8A7794_CLK_SD2,   CLK_PLL1_DIV2, 0x078),
+	DEF_DIV6P1("sd3",   R8A7794_CLK_SD3,   CLK_PLL1_DIV2, 0x26c),
+	DEF_DIV6P1("mmc0",  R8A7794_CLK_MMC0,  CLK_PLL1_DIV2, 0x240),
+};
+
+static const struct mssr_mod_clk r8a7794_mod_clks[] __initconst = {
+	DEF_MOD("msiof0",		   0,	R8A7794_CLK_MP),
+	DEF_MOD("vcp0",			 101,	R8A7794_CLK_ZS),
+	DEF_MOD("vpc0",			 103,	R8A7794_CLK_ZS),
+	DEF_MOD("jpu",			 106,	R8A7794_CLK_M2),
+	DEF_MOD("tmu1",			 111,	R8A7794_CLK_P),
+	DEF_MOD("3dg",			 112,	R8A7794_CLK_ZG),
+	DEF_MOD("2d-dmac",		 115,	R8A7794_CLK_ZS),
+	DEF_MOD("fdp1-0",		 119,	R8A7794_CLK_ZS),
+	DEF_MOD("tmu3",			 121,	R8A7794_CLK_P),
+	DEF_MOD("tmu2",			 122,	R8A7794_CLK_P),
+	DEF_MOD("cmt0",			 124,	R8A7794_CLK_R),
+	DEF_MOD("tmu0",			 125,	R8A7794_CLK_CP),
+	DEF_MOD("vsp1du0",		 128,	R8A7794_CLK_ZS),
+	DEF_MOD("vsp1-sy",		 131,	R8A7794_CLK_ZS),
+	DEF_MOD("scifa2",		 202,	R8A7794_CLK_MP),
+	DEF_MOD("scifa1",		 203,	R8A7794_CLK_MP),
+	DEF_MOD("scifa0",		 204,	R8A7794_CLK_MP),
+	DEF_MOD("msiof2",		 205,	R8A7794_CLK_MP),
+	DEF_MOD("scifb0",		 206,	R8A7794_CLK_MP),
+	DEF_MOD("scifb1",		 207,	R8A7794_CLK_MP),
+	DEF_MOD("msiof1",		 208,	R8A7794_CLK_MP),
+	DEF_MOD("scifb2",		 216,	R8A7794_CLK_MP),
+	DEF_MOD("sys-dmac1",		 218,	R8A7794_CLK_ZS),
+	DEF_MOD("sys-dmac0",		 219,	R8A7794_CLK_ZS),
+	DEF_MOD("tpu0",			 304,	R8A7794_CLK_CP),
+	DEF_MOD("sdhi3",		 311,	R8A7794_CLK_SD3),
+	DEF_MOD("sdhi2",		 312,	R8A7794_CLK_SD2),
+	DEF_MOD("sdhi0",		 314,	R8A7794_CLK_SD0),
+	DEF_MOD("mmcif0",		 315,	R8A7794_CLK_MMC0),
+	DEF_MOD("iic0",			 318,	R8A7794_CLK_HP),
+	DEF_MOD("iic1",			 323,	R8A7794_CLK_HP),
+	DEF_MOD("cmt1",			 329,	R8A7794_CLK_R),
+	DEF_MOD("usbhs-dmac0",		 330,	R8A7794_CLK_HP),
+	DEF_MOD("usbhs-dmac1",		 331,	R8A7794_CLK_HP),
+	DEF_MOD("irqc",			 407,	R8A7794_CLK_CP),
+	DEF_MOD("intc-sys",		 408,	R8A7794_CLK_ZS),
+	DEF_MOD("audio-dmac0",		 502,	R8A7794_CLK_HP),
+	DEF_MOD("adsp_mod",		 506,	R8A7794_CLK_ADSP),
+	DEF_MOD("pwm",			 523,	R8A7794_CLK_P),
+	DEF_MOD("usb-ehci",		 703,	R8A7794_CLK_MP),
+	DEF_MOD("usbhs",		 704,	R8A7794_CLK_HP),
+	DEF_MOD("hscif2",		 713,	R8A7794_CLK_ZS),
+	DEF_MOD("scif5",		 714,	R8A7794_CLK_P),
+	DEF_MOD("scif4",		 715,	R8A7794_CLK_P),
+	DEF_MOD("hscif1",		 716,	R8A7794_CLK_ZS),
+	DEF_MOD("hscif0",		 717,	R8A7794_CLK_ZS),
+	DEF_MOD("scif3",		 718,	R8A7794_CLK_P),
+	DEF_MOD("scif2",		 719,	R8A7794_CLK_P),
+	DEF_MOD("scif1",		 720,	R8A7794_CLK_P),
+	DEF_MOD("scif0",		 721,	R8A7794_CLK_P),
+	DEF_MOD("du1",			 723,	R8A7794_CLK_ZX),
+	DEF_MOD("du0",			 724,	R8A7794_CLK_ZX),
+	DEF_MOD("ipmmu-sgx",		 800,	R8A7794_CLK_ZX),
+	DEF_MOD("mlb",			 802,	R8A7794_CLK_HP),
+	DEF_MOD("vin1",			 810,	R8A7794_CLK_ZG),
+	DEF_MOD("vin0",			 811,	R8A7794_CLK_ZG),
+	DEF_MOD("etheravb",		 812,	R8A7794_CLK_HP),
+	DEF_MOD("ether",		 813,	R8A7794_CLK_P),
+	DEF_MOD("gyro-adc",		 901,	R8A7794_CLK_P),
+	DEF_MOD("gpio6",		 905,	R8A7794_CLK_CP),
+	DEF_MOD("gpio5",		 907,	R8A7794_CLK_CP),
+	DEF_MOD("gpio4",		 908,	R8A7794_CLK_CP),
+	DEF_MOD("gpio3",		 909,	R8A7794_CLK_CP),
+	DEF_MOD("gpio2",		 910,	R8A7794_CLK_CP),
+	DEF_MOD("gpio1",		 911,	R8A7794_CLK_CP),
+	DEF_MOD("gpio0",		 912,	R8A7794_CLK_CP),
+	DEF_MOD("can1",			 915,	R8A7794_CLK_P),
+	DEF_MOD("can0",			 916,	R8A7794_CLK_P),
+	DEF_MOD("qspi_mod",		 917,	R8A7794_CLK_QSPI),
+	DEF_MOD("i2c5",			 925,	R8A7794_CLK_HP),
+	DEF_MOD("i2c4",			 927,	R8A7794_CLK_HP),
+	DEF_MOD("i2c3",			 928,	R8A7794_CLK_HP),
+	DEF_MOD("i2c2",			 929,	R8A7794_CLK_HP),
+	DEF_MOD("i2c1",			 930,	R8A7794_CLK_HP),
+	DEF_MOD("i2c0",			 931,	R8A7794_CLK_HP),
+	DEF_MOD("ssi-all",		1005,	R8A7794_CLK_P),
+	DEF_MOD("ssi9",			1006,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi8",			1007,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi7",			1008,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi6",			1009,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi5",			1010,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi4",			1011,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi3",			1012,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi2",			1013,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi1",			1014,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi0",			1015,	MOD_CLK_ID(1005)),
+	DEF_MOD("scu-all",		1017,	R8A7794_CLK_P),
+	DEF_MOD("scu-dvc1",		1018,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-dvc0",		1019,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu1-mix1",	1020,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu0-mix0",	1021,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src6",		1025,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src5",		1026,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src4",		1027,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src3",		1028,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src2",		1029,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src1",		1030,	MOD_CLK_ID(1017)),
+	DEF_MOD("scifa3",		1106,	R8A7794_CLK_MP),
+	DEF_MOD("scifa4",		1107,	R8A7794_CLK_MP),
+	DEF_MOD("scifa5",		1108,	R8A7794_CLK_MP),
+};
+
+static const unsigned int r8a7794_crit_mod_clks[] __initconst = {
+	MOD_CLK_ID(408),	/* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ *   MD		EXTAL		PLL0	PLL1	PLL3
+ * 14 13 19	(MHz)		*1	*2
+ *---------------------------------------------------
+ * 0  0  1	15		x200/3	x208/2	x88
+ * 0  1  1	20		x150/3	x156/2	x66
+ * 1  0  1	26 / 2		x230/3	x240/2	x102
+ * 1  1  1	30 / 2		x200/3	x208/2	x88
+ *
+ * *1 :	Table 7.5c indicates VCO output (PLL0 = VCO/3)
+ * *2 :	Table 7.5c indicates VCO output (PLL1 = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md)	((((md) & BIT(14)) >> 13) | \
+					 (((md) & BIT(13)) >> 13))
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[4] __initconst = {
+	{ 1, 208,  88, 200 },
+	{ 1, 156,  66, 150 },
+	{ 2, 240, 102, 230 },
+	{ 2, 208,  88, 200 },
+};
+
+static int __init r8a7794_cpg_mssr_init(struct device *dev)
+{
+	const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+	u32 cpg_mode;
+	int error;
+
+	error = rcar_rst_read_mode_pins(&cpg_mode);
+	if (error)
+		return error;
+
+	cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+	return rcar_gen2_cpg_init(cpg_pll_config, 3, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7794_cpg_mssr_info __initconst = {
+	/* Core Clocks */
+	.core_clks = r8a7794_core_clks,
+	.num_core_clks = ARRAY_SIZE(r8a7794_core_clks),
+	.last_dt_core_clk = LAST_DT_CORE_CLK,
+	.num_total_core_clks = MOD_CLK_BASE,
+
+	/* Module Clocks */
+	.mod_clks = r8a7794_mod_clks,
+	.num_mod_clks = ARRAY_SIZE(r8a7794_mod_clks),
+	.num_hw_mod_clks = 12 * 32,
+
+	/* Critical Module Clocks */
+	.crit_mod_clks = r8a7794_crit_mod_clks,
+	.num_crit_mod_clks = ARRAY_SIZE(r8a7794_crit_mod_clks),
+
+	/* Callbacks */
+	.init = r8a7794_cpg_mssr_init,
+	.cpg_clk_register = rcar_gen2_cpg_clk_register,
+};

+ 30 - 13
drivers/clk/renesas/r8a7795-cpg-mssr.c

@@ -141,8 +141,10 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
 	DEF_MOD("sdif0",		 314,	R8A7795_CLK_SD0),
 	DEF_MOD("pcie1",		 318,	R8A7795_CLK_S3D1),
 	DEF_MOD("pcie0",		 319,	R8A7795_CLK_S3D1),
+	DEF_MOD("usb-dmac30",		 326,	R8A7795_CLK_S3D1),
 	DEF_MOD("usb3-if1",		 327,	R8A7795_CLK_S3D1), /* ES1.x */
 	DEF_MOD("usb3-if0",		 328,	R8A7795_CLK_S3D1),
+	DEF_MOD("usb-dmac31",		 329,	R8A7795_CLK_S3D1),
 	DEF_MOD("usb-dmac0",		 330,	R8A7795_CLK_S3D1),
 	DEF_MOD("usb-dmac1",		 331,	R8A7795_CLK_S3D1),
 	DEF_MOD("rwdt",			 402,	R8A7795_CLK_R),
@@ -164,7 +166,7 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
 	DEF_MOD("hscif1",		 519,	R8A7795_CLK_S3D1),
 	DEF_MOD("hscif0",		 520,	R8A7795_CLK_S3D1),
 	DEF_MOD("thermal",		 522,	R8A7795_CLK_CP),
-	DEF_MOD("pwm",			 523,	R8A7795_CLK_S3D4),
+	DEF_MOD("pwm",			 523,	R8A7795_CLK_S0D12),
 	DEF_MOD("fcpvd3",		 600,	R8A7795_CLK_S2D1), /* ES1.x */
 	DEF_MOD("fcpvd2",		 601,	R8A7795_CLK_S0D2),
 	DEF_MOD("fcpvd1",		 602,	R8A7795_CLK_S0D2),
@@ -189,10 +191,12 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
 	DEF_MOD("vspi2",		 629,	R8A7795_CLK_S2D1), /* ES1.x */
 	DEF_MOD("vspi1",		 630,	R8A7795_CLK_S0D1),
 	DEF_MOD("vspi0",		 631,	R8A7795_CLK_S0D1),
+	DEF_MOD("ehci3",		 700,	R8A7795_CLK_S3D4),
 	DEF_MOD("ehci2",		 701,	R8A7795_CLK_S3D4),
 	DEF_MOD("ehci1",		 702,	R8A7795_CLK_S3D4),
 	DEF_MOD("ehci0",		 703,	R8A7795_CLK_S3D4),
 	DEF_MOD("hsusb",		 704,	R8A7795_CLK_S3D4),
+	DEF_MOD("hsusb3",		 705,	R8A7795_CLK_S3D4),
 	DEF_MOD("csi21",		 713,	R8A7795_CLK_CSI0), /* ES1.x */
 	DEF_MOD("csi20",		 714,	R8A7795_CLK_CSI0),
 	DEF_MOD("csi41",		 715,	R8A7795_CLK_CSI0),
@@ -218,22 +222,22 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
 	DEF_MOD("imr2",			 821,	R8A7795_CLK_S0D2),
 	DEF_MOD("imr1",			 822,	R8A7795_CLK_S0D2),
 	DEF_MOD("imr0",			 823,	R8A7795_CLK_S0D2),
-	DEF_MOD("gpio7",		 905,	R8A7795_CLK_CP),
-	DEF_MOD("gpio6",		 906,	R8A7795_CLK_CP),
-	DEF_MOD("gpio5",		 907,	R8A7795_CLK_CP),
-	DEF_MOD("gpio4",		 908,	R8A7795_CLK_CP),
-	DEF_MOD("gpio3",		 909,	R8A7795_CLK_CP),
-	DEF_MOD("gpio2",		 910,	R8A7795_CLK_CP),
-	DEF_MOD("gpio1",		 911,	R8A7795_CLK_CP),
-	DEF_MOD("gpio0",		 912,	R8A7795_CLK_CP),
+	DEF_MOD("gpio7",		 905,	R8A7795_CLK_S3D4),
+	DEF_MOD("gpio6",		 906,	R8A7795_CLK_S3D4),
+	DEF_MOD("gpio5",		 907,	R8A7795_CLK_S3D4),
+	DEF_MOD("gpio4",		 908,	R8A7795_CLK_S3D4),
+	DEF_MOD("gpio3",		 909,	R8A7795_CLK_S3D4),
+	DEF_MOD("gpio2",		 910,	R8A7795_CLK_S3D4),
+	DEF_MOD("gpio1",		 911,	R8A7795_CLK_S3D4),
+	DEF_MOD("gpio0",		 912,	R8A7795_CLK_S3D4),
 	DEF_MOD("can-fd",		 914,	R8A7795_CLK_S3D2),
 	DEF_MOD("can-if1",		 915,	R8A7795_CLK_S3D4),
 	DEF_MOD("can-if0",		 916,	R8A7795_CLK_S3D4),
-	DEF_MOD("i2c6",			 918,	R8A7795_CLK_S3D2),
-	DEF_MOD("i2c5",			 919,	R8A7795_CLK_S3D2),
+	DEF_MOD("i2c6",			 918,	R8A7795_CLK_S0D6),
+	DEF_MOD("i2c5",			 919,	R8A7795_CLK_S0D6),
 	DEF_MOD("i2c-dvfs",		 926,	R8A7795_CLK_CP),
-	DEF_MOD("i2c4",			 927,	R8A7795_CLK_S3D2),
-	DEF_MOD("i2c3",			 928,	R8A7795_CLK_S3D2),
+	DEF_MOD("i2c4",			 927,	R8A7795_CLK_S0D6),
+	DEF_MOD("i2c3",			 928,	R8A7795_CLK_S0D6),
 	DEF_MOD("i2c2",			 929,	R8A7795_CLK_S3D2),
 	DEF_MOD("i2c1",			 930,	R8A7795_CLK_S3D2),
 	DEF_MOD("i2c0",			 931,	R8A7795_CLK_S3D2),
@@ -346,6 +350,7 @@ static const struct mssr_mod_reparent r8a7795es1_mod_reparent[] __initconst = {
 	{ MOD_CLK_ID(219), R8A7795_CLK_S3D1 },	/* SYS-DMAC0 */
 	{ MOD_CLK_ID(501), R8A7795_CLK_S3D1 },	/* AUDMAC1 */
 	{ MOD_CLK_ID(502), R8A7795_CLK_S3D1 },	/* AUDMAC0 */
+	{ MOD_CLK_ID(523), R8A7795_CLK_S3D4 },	/* PWM */
 	{ MOD_CLK_ID(601), R8A7795_CLK_S2D1 },	/* FCPVD2 */
 	{ MOD_CLK_ID(602), R8A7795_CLK_S2D1 },	/* FCPVD1 */
 	{ MOD_CLK_ID(603), R8A7795_CLK_S2D1 },	/* FCPVD0 */
@@ -376,6 +381,18 @@ static const struct mssr_mod_reparent r8a7795es1_mod_reparent[] __initconst = {
 	{ MOD_CLK_ID(821), R8A7795_CLK_S2D1 },	/* IMR2 */
 	{ MOD_CLK_ID(822), R8A7795_CLK_S2D1 },	/* IMR1 */
 	{ MOD_CLK_ID(823), R8A7795_CLK_S2D1 },	/* IMR0 */
+	{ MOD_CLK_ID(905), R8A7795_CLK_CP },	/* GPIO7 */
+	{ MOD_CLK_ID(906), R8A7795_CLK_CP },	/* GPIO6 */
+	{ MOD_CLK_ID(907), R8A7795_CLK_CP },	/* GPIO5 */
+	{ MOD_CLK_ID(908), R8A7795_CLK_CP },	/* GPIO4 */
+	{ MOD_CLK_ID(909), R8A7795_CLK_CP },	/* GPIO3 */
+	{ MOD_CLK_ID(910), R8A7795_CLK_CP },	/* GPIO2 */
+	{ MOD_CLK_ID(911), R8A7795_CLK_CP },	/* GPIO1 */
+	{ MOD_CLK_ID(912), R8A7795_CLK_CP },	/* GPIO0 */
+	{ MOD_CLK_ID(918), R8A7795_CLK_S3D2 },	/* I2C6 */
+	{ MOD_CLK_ID(919), R8A7795_CLK_S3D2 },	/* I2C5 */
+	{ MOD_CLK_ID(927), R8A7795_CLK_S3D2 },	/* I2C4 */
+	{ MOD_CLK_ID(928), R8A7795_CLK_S3D2 },	/* I2C3 */
 };
 
 

+ 39 - 0
drivers/clk/renesas/r8a7796-cpg-mssr.c

@@ -106,6 +106,7 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
 	DEF_DIV6P1("canfd",     R8A7796_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
 	DEF_DIV6P1("csi0",      R8A7796_CLK_CSI0,  CLK_PLL1_DIV4, 0x00c),
 	DEF_DIV6P1("mso",       R8A7796_CLK_MSO,   CLK_PLL1_DIV4, 0x014),
+	DEF_DIV6P1("hdmi",      R8A7796_CLK_HDMI,  CLK_PLL1_DIV4, 0x250),
 
 	DEF_DIV6_RO("osc",      R8A7796_CLK_OSC,   CLK_EXTAL, CPG_RCKCR,  8),
 	DEF_DIV6_RO("r_int",    CLK_RINT,          CLK_EXTAL, CPG_RCKCR, 32),
@@ -135,8 +136,15 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
 	DEF_MOD("sdif2",		 312,	R8A7796_CLK_SD2),
 	DEF_MOD("sdif1",		 313,	R8A7796_CLK_SD1),
 	DEF_MOD("sdif0",		 314,	R8A7796_CLK_SD0),
+	DEF_MOD("pcie1",		 318,	R8A7796_CLK_S3D1),
+	DEF_MOD("pcie0",		 319,	R8A7796_CLK_S3D1),
+	DEF_MOD("usb-dmac0",		 330,	R8A7796_CLK_S3D1),
+	DEF_MOD("usb-dmac1",		 331,	R8A7796_CLK_S3D1),
 	DEF_MOD("rwdt",			 402,	R8A7796_CLK_R),
+	DEF_MOD("intc-ex",		 407,	R8A7796_CLK_CP),
 	DEF_MOD("intc-ap",		 408,	R8A7796_CLK_S3D1),
+	DEF_MOD("audmac1",		 501,	R8A7796_CLK_S0D3),
+	DEF_MOD("audmac0",		 502,	R8A7796_CLK_S0D3),
 	DEF_MOD("drif7",		 508,	R8A7796_CLK_S3D2),
 	DEF_MOD("drif6",		 509,	R8A7796_CLK_S3D2),
 	DEF_MOD("drif5",		 510,	R8A7796_CLK_S3D2),
@@ -151,6 +159,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
 	DEF_MOD("hscif1",		 519,	R8A7796_CLK_S3D1),
 	DEF_MOD("hscif0",		 520,	R8A7796_CLK_S3D1),
 	DEF_MOD("thermal",		 522,	R8A7796_CLK_CP),
+	DEF_MOD("pwm",			 523,	R8A7796_CLK_S0D12),
 	DEF_MOD("fcpvd2",		 601,	R8A7796_CLK_S0D2),
 	DEF_MOD("fcpvd1",		 602,	R8A7796_CLK_S0D2),
 	DEF_MOD("fcpvd0",		 603,	R8A7796_CLK_S0D2),
@@ -164,12 +173,16 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
 	DEF_MOD("vspd0",		 623,	R8A7796_CLK_S0D2),
 	DEF_MOD("vspb",			 626,	R8A7796_CLK_S0D1),
 	DEF_MOD("vspi0",		 631,	R8A7796_CLK_S0D1),
+	DEF_MOD("ehci1",		 702,	R8A7796_CLK_S3D4),
+	DEF_MOD("ehci0",		 703,	R8A7796_CLK_S3D4),
+	DEF_MOD("hsusb",		 704,	R8A7796_CLK_S3D4),
 	DEF_MOD("csi20",		 714,	R8A7796_CLK_CSI0),
 	DEF_MOD("csi40",		 716,	R8A7796_CLK_CSI0),
 	DEF_MOD("du2",			 722,	R8A7796_CLK_S2D1),
 	DEF_MOD("du1",			 723,	R8A7796_CLK_S2D1),
 	DEF_MOD("du0",			 724,	R8A7796_CLK_S2D1),
 	DEF_MOD("lvds",			 727,	R8A7796_CLK_S2D1),
+	DEF_MOD("hdmi0",		 729,	R8A7796_CLK_HDMI),
 	DEF_MOD("vin7",			 804,	R8A7796_CLK_S0D2),
 	DEF_MOD("vin6",			 805,	R8A7796_CLK_S0D2),
 	DEF_MOD("vin5",			 806,	R8A7796_CLK_S0D2),
@@ -200,6 +213,32 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
 	DEF_MOD("i2c2",			 929,	R8A7796_CLK_S3D2),
 	DEF_MOD("i2c1",			 930,	R8A7796_CLK_S3D2),
 	DEF_MOD("i2c0",			 931,	R8A7796_CLK_S3D2),
+	DEF_MOD("ssi-all",		1005,	R8A7796_CLK_S3D4),
+	DEF_MOD("ssi9",			1006,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi8",			1007,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi7",			1008,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi6",			1009,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi5",			1010,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi4",			1011,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi3",			1012,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi2",			1013,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi1",			1014,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi0",			1015,	MOD_CLK_ID(1005)),
+	DEF_MOD("scu-all",		1017,	R8A7796_CLK_S3D4),
+	DEF_MOD("scu-dvc1",		1018,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-dvc0",		1019,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu1-mix1",	1020,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu0-mix0",	1021,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src9",		1022,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src8",		1023,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src7",		1024,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src6",		1025,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src5",		1026,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src4",		1027,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src3",		1028,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src2",		1029,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src1",		1030,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src0",		1031,	MOD_CLK_ID(1017)),
 };
 
 static const unsigned int r8a7796_crit_mod_clks[] __initconst = {

+ 36 - 7
drivers/clk/renesas/renesas-cpg-mssr.c

@@ -257,7 +257,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
 					      const struct cpg_mssr_info *info,
 					      struct cpg_mssr_priv *priv)
 {
-	struct clk *clk = NULL, *parent;
+	struct clk *clk = ERR_PTR(-ENOTSUPP), *parent;
 	struct device *dev = priv->dev;
 	unsigned int id = core->id, div = core->div;
 	const char *parent_name;
@@ -477,7 +477,7 @@ fail_put:
 
 void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev)
 {
-	if (!list_empty(&dev->power.subsys_data->clock_list))
+	if (!pm_clk_no_clocks(dev))
 		pm_clk_destroy(dev);
 }
 
@@ -627,25 +627,54 @@ static inline int cpg_mssr_reset_controller_register(struct cpg_mssr_priv *priv)
 
 
 static const struct of_device_id cpg_mssr_match[] = {
-#ifdef CONFIG_ARCH_R8A7743
+#ifdef CONFIG_CLK_R8A7743
 	{
 		.compatible = "renesas,r8a7743-cpg-mssr",
 		.data = &r8a7743_cpg_mssr_info,
 	},
 #endif
-#ifdef CONFIG_ARCH_R8A7745
+#ifdef CONFIG_CLK_R8A7745
 	{
 		.compatible = "renesas,r8a7745-cpg-mssr",
 		.data = &r8a7745_cpg_mssr_info,
 	},
 #endif
-#ifdef CONFIG_ARCH_R8A7795
+#ifdef CONFIG_CLK_R8A7790
+	{
+		.compatible = "renesas,r8a7790-cpg-mssr",
+		.data = &r8a7790_cpg_mssr_info,
+	},
+#endif
+#ifdef CONFIG_CLK_R8A7791
+	{
+		.compatible = "renesas,r8a7791-cpg-mssr",
+		.data = &r8a7791_cpg_mssr_info,
+	},
+	/* R-Car M2-N is (almost) identical to R-Car M2-W w.r.t. clocks. */
+	{
+		.compatible = "renesas,r8a7793-cpg-mssr",
+		.data = &r8a7791_cpg_mssr_info,
+	},
+#endif
+#ifdef CONFIG_CLK_R8A7792
+	{
+		.compatible = "renesas,r8a7792-cpg-mssr",
+		.data = &r8a7792_cpg_mssr_info,
+	},
+#endif
+#ifdef CONFIG_CLK_R8A7794
+	{
+		.compatible = "renesas,r8a7794-cpg-mssr",
+		.data = &r8a7794_cpg_mssr_info,
+	},
+#endif
+#ifdef CONFIG_CLK_R8A7795
 	{
 		.compatible = "renesas,r8a7795-cpg-mssr",
 		.data = &r8a7795_cpg_mssr_info,
 	},
 #endif
-#ifdef CONFIG_ARCH_R8A7796
+#ifdef CONFIG_CLK_R8A7796
 	{
 		.compatible = "renesas,r8a7796-cpg-mssr",
 		.data = &r8a7796_cpg_mssr_info,
@@ -670,7 +699,7 @@ static int __init cpg_mssr_probe(struct platform_device *pdev)
 	struct clk **clks;
 	int error;
 
-	info = of_match_node(cpg_mssr_match, np)->data;
+	info = of_device_get_match_data(dev);
 	if (info->init) {
 		error = info->init(dev);
 		if (error)

+ 4 - 0
drivers/clk/renesas/renesas-cpg-mssr.h

@@ -132,6 +132,10 @@ struct cpg_mssr_info {
 
 extern const struct cpg_mssr_info r8a7743_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a7745_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7790_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7791_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7792_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7794_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a7795_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a7796_cpg_mssr_info;
 

+ 1 - 0
drivers/clk/rockchip/Makefile

@@ -14,6 +14,7 @@ obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o
 
 obj-y	+= clk-rv1108.o
 obj-y	+= clk-rk3036.o
+obj-y	+= clk-rk3128.o
 obj-y	+= clk-rk3188.o
 obj-y	+= clk-rk3228.o
 obj-y	+= clk-rk3288.o

+ 1 - 0
drivers/clk/rockchip/clk-rk3036.c

@@ -436,6 +436,7 @@ static const char *const rk3036_critical_clocks[] __initconst = {
 	"aclk_peri",
 	"hclk_peri",
 	"pclk_peri",
+	"pclk_ddrupctl",
 };
 
 static void __init rk3036_clk_init(struct device_node *np)

+ 612 - 0
drivers/clk/rockchip/clk-rk3128.c

@@ -0,0 +1,612 @@
+/*
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Author: Elaine <zhangqing@rock-chips.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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+#include <dt-bindings/clock/rk3128-cru.h>
+#include "clk.h"
+
+#define RK3128_GRF_SOC_STATUS0	0x14c
+
+enum rk3128_plls {
+	apll, dpll, cpll, gpll,
+};
+
+static struct rockchip_pll_rate_table rk3128_pll_rates[] = {
+	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+	RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+	RK3036_PLL_RATE(984000000, 1, 82, 2, 1, 1, 0),
+	RK3036_PLL_RATE(960000000, 1, 80, 2, 1, 1, 0),
+	RK3036_PLL_RATE(936000000, 1, 78, 2, 1, 1, 0),
+	RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0),
+	RK3036_PLL_RATE(900000000, 4, 300, 2, 1, 1, 0),
+	RK3036_PLL_RATE(888000000, 1, 74, 2, 1, 1, 0),
+	RK3036_PLL_RATE(864000000, 1, 72, 2, 1, 1, 0),
+	RK3036_PLL_RATE(840000000, 1, 70, 2, 1, 1, 0),
+	RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
+	RK3036_PLL_RATE(800000000, 6, 400, 2, 1, 1, 0),
+	RK3036_PLL_RATE(700000000, 6, 350, 2, 1, 1, 0),
+	RK3036_PLL_RATE(696000000, 1, 58, 2, 1, 1, 0),
+	RK3036_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0),
+	RK3036_PLL_RATE(594000000, 2, 99, 2, 1, 1, 0),
+	RK3036_PLL_RATE(504000000, 1, 63, 3, 1, 1, 0),
+	RK3036_PLL_RATE(500000000, 6, 250, 2, 1, 1, 0),
+	RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0),
+	RK3036_PLL_RATE(312000000, 1, 52, 2, 2, 1, 0),
+	RK3036_PLL_RATE(216000000, 1, 72, 4, 2, 1, 0),
+	RK3036_PLL_RATE(96000000, 1, 64, 4, 4, 1, 0),
+	{ /* sentinel */ },
+};
+
+#define RK3128_DIV_CPU_MASK		0x1f
+#define RK3128_DIV_CPU_SHIFT		8
+
+#define RK3128_DIV_PERI_MASK		0xf
+#define RK3128_DIV_PERI_SHIFT		0
+#define RK3128_DIV_ACLK_MASK		0x7
+#define RK3128_DIV_ACLK_SHIFT		4
+#define RK3128_DIV_HCLK_MASK		0x3
+#define RK3128_DIV_HCLK_SHIFT		8
+#define RK3128_DIV_PCLK_MASK		0x7
+#define RK3128_DIV_PCLK_SHIFT		12
+
+#define RK3128_CLKSEL1(_core_aclk_div, _pclk_dbg_div)			\
+{									\
+	.reg = RK2928_CLKSEL_CON(1),					\
+	.val = HIWORD_UPDATE(_pclk_dbg_div, RK3128_DIV_PERI_MASK,	\
+			     RK3128_DIV_PERI_SHIFT) |			\
+	       HIWORD_UPDATE(_core_aclk_div, RK3128_DIV_ACLK_MASK,	\
+			     RK3128_DIV_ACLK_SHIFT),			\
+}
+
+#define RK3128_CPUCLK_RATE(_prate, _core_aclk_div, _pclk_dbg_div)	\
+{									\
+	.prate = _prate,						\
+	.divs = {							\
+		RK3128_CLKSEL1(_core_aclk_div, _pclk_dbg_div),		\
+	},								\
+}
+
+static struct rockchip_cpuclk_rate_table rk3128_cpuclk_rates[] __initdata = {
+	RK3128_CPUCLK_RATE(1800000000, 1, 7),
+	RK3128_CPUCLK_RATE(1704000000, 1, 7),
+	RK3128_CPUCLK_RATE(1608000000, 1, 7),
+	RK3128_CPUCLK_RATE(1512000000, 1, 7),
+	RK3128_CPUCLK_RATE(1488000000, 1, 5),
+	RK3128_CPUCLK_RATE(1416000000, 1, 5),
+	RK3128_CPUCLK_RATE(1392000000, 1, 5),
+	RK3128_CPUCLK_RATE(1296000000, 1, 5),
+	RK3128_CPUCLK_RATE(1200000000, 1, 5),
+	RK3128_CPUCLK_RATE(1104000000, 1, 5),
+	RK3128_CPUCLK_RATE(1008000000, 1, 5),
+	RK3128_CPUCLK_RATE(912000000, 1, 5),
+	RK3128_CPUCLK_RATE(816000000, 1, 3),
+	RK3128_CPUCLK_RATE(696000000, 1, 3),
+	RK3128_CPUCLK_RATE(600000000, 1, 3),
+	RK3128_CPUCLK_RATE(408000000, 1, 1),
+	RK3128_CPUCLK_RATE(312000000, 1, 1),
+	RK3128_CPUCLK_RATE(216000000,  1, 1),
+	RK3128_CPUCLK_RATE(96000000, 1, 1),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3128_cpuclk_data = {
+	.core_reg = RK2928_CLKSEL_CON(0),
+	.div_core_shift = 0,
+	.div_core_mask = 0x1f,
+	.mux_core_alt = 1,
+	.mux_core_main = 0,
+	.mux_core_shift = 7,
+	.mux_core_mask = 0x1,
+};
+
+PNAME(mux_pll_p)		= { "clk_24m", "xin24m" };
+
+PNAME(mux_ddrphy_p)		= { "dpll_ddr", "gpll_div2_ddr" };
+PNAME(mux_armclk_p)		= { "apll_core", "gpll_div2_core" };
+PNAME(mux_usb480m_p)		= { "usb480m_phy", "xin24m" };
+PNAME(mux_aclk_cpu_src_p)	= { "cpll", "gpll", "gpll_div2", "gpll_div3" };
+
+PNAME(mux_pll_src_5plls_p)	= { "cpll", "gpll", "gpll_div2", "gpll_div3", "usb480m" };
+PNAME(mux_pll_src_4plls_p)	= { "cpll", "gpll", "gpll_div2", "usb480m" };
+PNAME(mux_pll_src_3plls_p)	= { "cpll", "gpll", "gpll_div2" };
+
+PNAME(mux_aclk_peri_src_p)	= { "gpll_peri", "cpll_peri", "gpll_div2_peri", "gpll_div3_peri" };
+PNAME(mux_mmc_src_p)		= { "cpll", "gpll", "gpll_div2", "xin24m" };
+PNAME(mux_clk_cif_out_src_p)		= { "clk_cif_src", "xin24m" };
+PNAME(mux_sclk_vop_src_p)	= { "cpll", "gpll", "gpll_div2", "gpll_div3" };
+
+PNAME(mux_i2s0_p)		= { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" };
+PNAME(mux_i2s1_pre_p)		= { "i2s1_src", "i2s1_frac", "ext_i2s", "xin12m" };
+PNAME(mux_i2s_out_p)		= { "i2s1_pre", "xin12m" };
+PNAME(mux_sclk_spdif_p)		= { "sclk_spdif_src", "spdif_frac", "xin12m" };
+
+PNAME(mux_uart0_p)		= { "uart0_src", "uart0_frac", "xin24m" };
+PNAME(mux_uart1_p)		= { "uart1_src", "uart1_frac", "xin24m" };
+PNAME(mux_uart2_p)		= { "uart2_src", "uart2_frac", "xin24m" };
+
+PNAME(mux_sclk_gmac_p)	= { "sclk_gmac_src", "gmac_clkin" };
+PNAME(mux_sclk_sfc_src_p)	= { "cpll", "gpll", "gpll_div2", "xin24m" };
+
+static struct rockchip_pll_clock rk3128_pll_clks[] __initdata = {
+	[apll] = PLL(pll_rk3036, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0),
+		     RK2928_MODE_CON, 0, 1, 0, rk3128_pll_rates),
+	[dpll] = PLL(pll_rk3036, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4),
+		     RK2928_MODE_CON, 4, 0, 0, NULL),
+	[cpll] = PLL(pll_rk3036, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(8),
+		     RK2928_MODE_CON, 8, 2, 0, rk3128_pll_rates),
+	[gpll] = PLL(pll_rk3036, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(12),
+		     RK2928_MODE_CON, 12, 3, ROCKCHIP_PLL_SYNC_RATE, rk3128_pll_rates),
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+
+static struct rockchip_clk_branch rk3128_i2s0_fracmux __initdata =
+	MUX(0, "i2s0_pre", mux_i2s0_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(9), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3128_i2s1_fracmux __initdata =
+	MUX(0, "i2s1_pre", mux_i2s1_pre_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3128_spdif_fracmux __initdata =
+	MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(6), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3128_uart0_fracmux __initdata =
+	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(13), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3128_uart1_fracmux __initdata =
+	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(14), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3128_uart2_fracmux __initdata =
+	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(15), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3128_clk_branches[] __initdata = {
+	/*
+	 * Clock-Architecture Diagram 1
+	 */
+
+	FACTOR(PLL_GPLL_DIV2, "gpll_div2", "gpll", 0, 1, 2),
+	FACTOR(PLL_GPLL_DIV3, "gpll_div3", "gpll", 0, 1, 3),
+
+	DIV(0, "clk_24m", "xin24m", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(4), 8, 5, DFLAGS),
+
+	/* PD_DDR */
+	GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 2, GFLAGS),
+	GATE(0, "gpll_div2_ddr", "gpll_div2", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 2, GFLAGS),
+	COMPOSITE_NOGATE(0, "ddrphy2x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+	FACTOR(SCLK_DDRC, "clk_ddrc", "ddrphy2x", 0, 1, 2),
+	FACTOR(0, "clk_ddrphy", "ddrphy2x", 0, 1, 2),
+
+	/* PD_CORE */
+	GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 6, GFLAGS),
+	GATE(0, "gpll_div2_core", "gpll_div2", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(0), 6, GFLAGS),
+	COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK2928_CLKGATE_CON(0), 0, GFLAGS),
+	COMPOSITE_NOMUX(0, "armcore", "armclk", CLK_IGNORE_UNUSED,
+			RK2928_CLKSEL_CON(1), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK2928_CLKGATE_CON(0), 7, GFLAGS),
+
+	/* PD_MISC */
+	MUX(SCLK_USB480M, "usb480m", mux_usb480m_p, CLK_SET_RATE_PARENT,
+			RK2928_MISC_CON, 15, 1, MFLAGS),
+
+	/* PD_CPU */
+	COMPOSITE(0, "aclk_cpu_src", mux_aclk_cpu_src_p, 0,
+			RK2928_CLKSEL_CON(0), 13, 2, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(0), 1, GFLAGS),
+	GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_src", 0,
+			RK2928_CLKGATE_CON(0), 3, GFLAGS),
+	COMPOSITE_NOMUX(HCLK_CPU, "hclk_cpu", "aclk_cpu_src", 0,
+			RK2928_CLKSEL_CON(1), 8, 2, DFLAGS,
+			RK2928_CLKGATE_CON(0), 4, GFLAGS),
+	COMPOSITE_NOMUX(PCLK_CPU, "pclk_cpu", "aclk_cpu_src", 0,
+			RK2928_CLKSEL_CON(1), 12, 2, DFLAGS,
+			RK2928_CLKGATE_CON(0), 5, GFLAGS),
+	COMPOSITE_NOMUX(SCLK_CRYPTO, "clk_crypto", "aclk_cpu_src", 0,
+			RK2928_CLKSEL_CON(24), 0, 2, DFLAGS,
+			RK2928_CLKGATE_CON(0), 12, GFLAGS),
+
+	/* PD_VIDEO */
+	COMPOSITE(ACLK_VEPU, "aclk_vepu", mux_pll_src_5plls_p, 0,
+			RK2928_CLKSEL_CON(32), 5, 3, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 9, GFLAGS),
+	FACTOR(HCLK_VEPU, "hclk_vepu", "aclk_vepu", 0, 1, 4),
+
+	COMPOSITE(ACLK_VDPU, "aclk_vdpu", mux_pll_src_5plls_p, 0,
+			RK2928_CLKSEL_CON(32), 13, 3, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 11, GFLAGS),
+	FACTOR_GATE(HCLK_VDPU, "hclk_vdpu", "aclk_vdpu", 0, 1, 4,
+			RK2928_CLKGATE_CON(3), 12, GFLAGS),
+
+	COMPOSITE(SCLK_HEVC_CORE, "sclk_hevc_core", mux_pll_src_5plls_p, 0,
+			RK2928_CLKSEL_CON(34), 13, 3, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 10, GFLAGS),
+
+	/* PD_VIO */
+	COMPOSITE(ACLK_VIO0, "aclk_vio0", mux_pll_src_5plls_p, 0,
+			RK2928_CLKSEL_CON(31), 5, 3, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 0, GFLAGS),
+	COMPOSITE(ACLK_VIO1, "aclk_vio1", mux_pll_src_5plls_p, 0,
+			RK2928_CLKSEL_CON(31), 13, 3, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(1), 4, GFLAGS),
+	COMPOSITE(HCLK_VIO, "hclk_vio", mux_pll_src_4plls_p, 0,
+			RK2928_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(0), 11, GFLAGS),
+
+	/* PD_PERI */
+	GATE(0, "gpll_peri", "gpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(2), 0, GFLAGS),
+	GATE(0, "cpll_peri", "cpll", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(2), 0, GFLAGS),
+	GATE(0, "gpll_div2_peri", "gpll_div2", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(2), 0, GFLAGS),
+	GATE(0, "gpll_div3_peri", "gpll_div3", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(2), 0, GFLAGS),
+	COMPOSITE_NOGATE(0, "aclk_peri_src", mux_aclk_peri_src_p, 0,
+			RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS),
+	COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0,
+			RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+			RK2928_CLKGATE_CON(2), 3, GFLAGS),
+	COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_src", 0,
+			RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+			RK2928_CLKGATE_CON(2), 2, GFLAGS),
+	GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", 0,
+			RK2928_CLKGATE_CON(2), 1, GFLAGS),
+
+	GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 0,
+			RK2928_CLKGATE_CON(10), 3, GFLAGS),
+	GATE(SCLK_TIMER1, "sclk_timer1", "xin24m", 0,
+			RK2928_CLKGATE_CON(10), 4, GFLAGS),
+	GATE(SCLK_TIMER2, "sclk_timer2", "xin24m", 0,
+			RK2928_CLKGATE_CON(10), 5, GFLAGS),
+	GATE(SCLK_TIMER3, "sclk_timer3", "xin24m", 0,
+			RK2928_CLKGATE_CON(10), 6, GFLAGS),
+	GATE(SCLK_TIMER4, "sclk_timer4", "xin24m", 0,
+			RK2928_CLKGATE_CON(10), 7, GFLAGS),
+	GATE(SCLK_TIMER5, "sclk_timer5", "xin24m", 0,
+			RK2928_CLKGATE_CON(10), 8, GFLAGS),
+
+	GATE(SCLK_PVTM_CORE, "clk_pvtm_core", "xin24m", 0,
+			RK2928_CLKGATE_CON(10), 8, GFLAGS),
+	GATE(SCLK_PVTM_GPU, "clk_pvtm_gpu", "xin24m", 0,
+			RK2928_CLKGATE_CON(10), 8, GFLAGS),
+	GATE(SCLK_PVTM_FUNC, "clk_pvtm_func", "xin24m", 0,
+			RK2928_CLKGATE_CON(10), 8, GFLAGS),
+	GATE(SCLK_MIPI_24M, "clk_mipi_24m", "xin24m", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(10), 8, GFLAGS),
+
+	COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
+			RK2928_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 6, DFLAGS,
+			RK2928_CLKGATE_CON(2), 11, GFLAGS),
+
+	COMPOSITE(SCLK_SDIO, "sclk_sdio", mux_mmc_src_p, 0,
+			RK2928_CLKSEL_CON(12), 6, 2, MFLAGS, 0, 6, DFLAGS,
+			RK2928_CLKGATE_CON(2), 13, GFLAGS),
+
+	COMPOSITE(SCLK_EMMC, "sclk_emmc", mux_mmc_src_p, 0,
+			RK2928_CLKSEL_CON(12), 14, 2, MFLAGS, 8, 6, DFLAGS,
+			RK2928_CLKGATE_CON(2), 14, GFLAGS),
+
+	DIV(SCLK_PVTM, "clk_pvtm", "clk_pvtm_func", 0,
+			RK2928_CLKSEL_CON(2), 0, 7, DFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 2
+	 */
+	COMPOSITE(DCLK_VOP, "dclk_vop", mux_sclk_vop_src_p, 0,
+			RK2928_CLKSEL_CON(27), 0, 2, MFLAGS, 8, 8, DFLAGS,
+			RK2928_CLKGATE_CON(3), 1, GFLAGS),
+	COMPOSITE(SCLK_VOP, "sclk_vop", mux_sclk_vop_src_p, 0,
+			RK2928_CLKSEL_CON(28), 0, 2, MFLAGS, 8, 8, DFLAGS,
+			RK2928_CLKGATE_CON(3), 2, GFLAGS),
+	COMPOSITE(DCLK_EBC, "dclk_ebc", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(23), 0, 2, MFLAGS, 8, 8, DFLAGS,
+			RK2928_CLKGATE_CON(3), 4, GFLAGS),
+
+	FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
+
+	COMPOSITE_NODIV(SCLK_CIF_SRC, "sclk_cif_src", mux_pll_src_4plls_p, 0,
+			RK2928_CLKSEL_CON(29), 0, 2, MFLAGS,
+			RK2928_CLKGATE_CON(3), 7, GFLAGS),
+	MUX(SCLK_CIF_OUT_SRC, "sclk_cif_out_src", mux_clk_cif_out_src_p, 0,
+			RK2928_CLKSEL_CON(13), 14, 2, MFLAGS),
+	DIV(SCLK_CIF_OUT, "sclk_cif_out", "sclk_cif_out_src", 0,
+			RK2928_CLKSEL_CON(29), 2, 5, DFLAGS),
+
+	COMPOSITE(0, "i2s0_src", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(9), 14, 2, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(4), 4, GFLAGS),
+	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(8), 0,
+			RK2928_CLKGATE_CON(4), 5, GFLAGS,
+			&rk3128_i2s0_fracmux),
+	GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
+			RK2928_CLKGATE_CON(4), 6, GFLAGS),
+
+	COMPOSITE(0, "i2s1_src", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(3), 14, 2, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(0), 9, GFLAGS),
+	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(7), 0,
+			RK2928_CLKGATE_CON(0), 10, GFLAGS,
+			&rk3128_i2s1_fracmux),
+	GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
+			RK2928_CLKGATE_CON(0), 14, GFLAGS),
+	COMPOSITE_NODIV(SCLK_I2S_OUT, "i2s_out", mux_i2s_out_p, 0,
+			RK2928_CLKSEL_CON(3), 12, 1, MFLAGS,
+			RK2928_CLKGATE_CON(0), 13, GFLAGS),
+
+	COMPOSITE(0, "sclk_spdif_src", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(6), 14, 2, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(2), 10, GFLAGS),
+	COMPOSITE_FRACMUX(0, "spdif_frac", "sclk_spdif_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(20), 0,
+			RK2928_CLKGATE_CON(2), 12, GFLAGS,
+			&rk3128_spdif_fracmux),
+
+	GATE(0, "jtag", "ext_jtag", CLK_IGNORE_UNUSED,
+			RK2928_CLKGATE_CON(1), 3, GFLAGS),
+
+	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin12m", 0,
+			RK2928_CLKGATE_CON(1), 5, GFLAGS),
+	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin12m", 0,
+			RK2928_CLKGATE_CON(1), 6, GFLAGS),
+
+	COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0,
+			RK2928_CLKSEL_CON(24), 8, 8, DFLAGS,
+			RK2928_CLKGATE_CON(2), 8, GFLAGS),
+
+	COMPOSITE(ACLK_GPU, "aclk_gpu", mux_pll_src_5plls_p, 0,
+			RK2928_CLKSEL_CON(34), 5, 3, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 13, GFLAGS),
+
+	COMPOSITE(SCLK_SPI0, "sclk_spi0", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(2), 9, GFLAGS),
+
+	/* PD_UART */
+	COMPOSITE(0, "uart0_src", mux_pll_src_4plls_p, 0,
+			RK2928_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 8, GFLAGS),
+	MUX(0, "uart12_src", mux_pll_src_4plls_p, 0,
+			RK2928_CLKSEL_CON(13), 14, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "uart1_src", "uart12_src", 0,
+			RK2928_CLKSEL_CON(14), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 10, GFLAGS),
+	COMPOSITE_NOMUX(0, "uart2_src", "uart12_src", 0,
+			RK2928_CLKSEL_CON(15), 0, 7, DFLAGS,
+			RK2928_CLKGATE_CON(1), 13, GFLAGS),
+	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(17), 0,
+			RK2928_CLKGATE_CON(1), 9, GFLAGS,
+			&rk3128_uart0_fracmux),
+	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(18), 0,
+			RK2928_CLKGATE_CON(1), 11, GFLAGS,
+			&rk3128_uart1_fracmux),
+	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(19), 0,
+			RK2928_CLKGATE_CON(1), 13, GFLAGS,
+			&rk3128_uart2_fracmux),
+
+	COMPOSITE(SCLK_MAC_SRC, "sclk_gmac_src", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(5), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(1), 7, GFLAGS),
+	MUX(SCLK_MAC, "sclk_gmac", mux_sclk_gmac_p, 0,
+			RK2928_CLKSEL_CON(5), 15, 1, MFLAGS),
+	GATE(SCLK_MAC_REFOUT, "sclk_mac_refout", "sclk_gmac", 0,
+			RK2928_CLKGATE_CON(2), 5, GFLAGS),
+	GATE(SCLK_MAC_REF, "sclk_mac_ref", "sclk_gmac", 0,
+			RK2928_CLKGATE_CON(2), 4, GFLAGS),
+	GATE(SCLK_MAC_RX, "sclk_mac_rx", "sclk_gmac", 0,
+			RK2928_CLKGATE_CON(2), 6, GFLAGS),
+	GATE(SCLK_MAC_TX, "sclk_mac_tx", "sclk_gmac", 0,
+			RK2928_CLKGATE_CON(2), 7, GFLAGS),
+
+	COMPOSITE(SCLK_TSP, "sclk_tsp", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(4), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK2928_CLKGATE_CON(1), 14, GFLAGS),
+
+	COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_3plls_p, 0,
+			RK2928_CLKSEL_CON(2), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(10), 15, GFLAGS),
+
+	COMPOSITE(SCLK_SFC, "sclk_sfc", mux_sclk_sfc_src_p, 0,
+			RK2928_CLKSEL_CON(11), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK2928_CLKGATE_CON(3), 15, GFLAGS),
+
+	COMPOSITE_NOMUX(PCLK_PMU_PRE, "pclk_pmu_pre", "cpll", 0,
+			RK2928_CLKSEL_CON(29), 8, 6, DFLAGS,
+			RK2928_CLKGATE_CON(1), 0, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 3
+	 */
+
+	/* PD_VOP */
+	GATE(ACLK_LCDC0, "aclk_lcdc0", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 0, GFLAGS),
+	GATE(ACLK_CIF, "aclk_cif", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 5, GFLAGS),
+	GATE(ACLK_RGA, "aclk_rga", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 11, GFLAGS),
+	GATE(0, "aclk_vio0_niu", "aclk_vio0", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(6), 13, GFLAGS),
+
+	GATE(ACLK_IEP, "aclk_iep", "aclk_vio1", 0, RK2928_CLKGATE_CON(9), 8, GFLAGS),
+	GATE(0, "aclk_vio1_niu", "aclk_vio1", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 10, GFLAGS),
+
+	GATE(HCLK_VIO_H2P, "hclk_vio_h2p", "hclk_vio", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS),
+	GATE(PCLK_MIPI, "pclk_mipi", "hclk_vio", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS),
+	GATE(HCLK_RGA, "hclk_rga", "hclk_vio", 0, RK2928_CLKGATE_CON(6), 10, GFLAGS),
+	GATE(HCLK_LCDC0, "hclk_lcdc0", "hclk_vio", 0, RK2928_CLKGATE_CON(6), 1, GFLAGS),
+	GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK2928_CLKGATE_CON(9), 7, GFLAGS),
+	GATE(0, "hclk_vio_niu", "hclk_vio", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(6), 12, GFLAGS),
+	GATE(HCLK_CIF, "hclk_cif", "hclk_vio", 0, RK2928_CLKGATE_CON(6), 4, GFLAGS),
+	GATE(HCLK_EBC, "hclk_ebc", "hclk_vio", 0, RK2928_CLKGATE_CON(9), 9, GFLAGS),
+
+	/* PD_PERI */
+	GATE(0, "aclk_peri_axi", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 3, GFLAGS),
+	GATE(ACLK_GMAC, "aclk_gmac", "aclk_peri", 0, RK2928_CLKGATE_CON(10), 10, GFLAGS),
+	GATE(ACLK_DMAC, "aclk_dmac", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS),
+	GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 15, GFLAGS),
+	GATE(0, "aclk_cpu_to_peri", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 2, GFLAGS),
+	GATE(HCLK_GPS, "hclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(3), 14, GFLAGS),
+
+	GATE(HCLK_I2S_8CH, "hclk_i2s_8ch", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
+	GATE(0, "hclk_peri_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 0, GFLAGS),
+	GATE(HCLK_I2S_2CH, "hclk_i2s_2ch", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
+	GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 13, GFLAGS),
+	GATE(HCLK_HOST2, "hclk_host2", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
+	GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(3), 13, GFLAGS),
+	GATE(0, "hclk_peri_ahb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 14, GFLAGS),
+	GATE(HCLK_SPDIF, "hclk_spdif", "hclk_peri", 0, RK2928_CLKGATE_CON(10), 9, GFLAGS),
+	GATE(HCLK_TSP, "hclk_tsp", "hclk_peri", 0, RK2928_CLKGATE_CON(10), 12, GFLAGS),
+	GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 10, GFLAGS),
+	GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 11, GFLAGS),
+	GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 0, GFLAGS),
+	GATE(0, "hclk_emmc_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 6, GFLAGS),
+	GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 9, GFLAGS),
+	GATE(HCLK_USBHOST, "hclk_usbhost", "hclk_peri", 0, RK2928_CLKGATE_CON(10), 14, GFLAGS),
+
+	GATE(PCLK_SIM_CARD, "pclk_sim_card", "pclk_peri", 0, RK2928_CLKGATE_CON(9), 12, GFLAGS),
+	GATE(PCLK_GMAC, "pclk_gmac", "pclk_peri", 0, RK2928_CLKGATE_CON(10), 11, GFLAGS),
+	GATE(0, "pclk_peri_axi", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 1, GFLAGS),
+	GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 12, GFLAGS),
+	GATE(PCLK_UART0, "pclk_uart0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS),
+	GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS),
+	GATE(PCLK_UART2, "pclk_uart2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS),
+	GATE(PCLK_PWM, "pclk_pwm", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 10, GFLAGS),
+	GATE(PCLK_WDT, "pclk_wdt", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS),
+	GATE(PCLK_I2C0, "pclk_i2c0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS),
+	GATE(PCLK_I2C1, "pclk_i2c1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 5, GFLAGS),
+	GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS),
+	GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS),
+	GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 14, GFLAGS),
+	GATE(PCLK_EFUSE, "pclk_efuse", "pclk_peri", 0, RK2928_CLKGATE_CON(5), 2, GFLAGS),
+	GATE(PCLK_TIMER, "pclk_timer", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 7, GFLAGS),
+	GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS),
+	GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS),
+	GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
+	GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS),
+
+	/* PD_BUS */
+	GATE(0, "aclk_initmem", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 12, GFLAGS),
+	GATE(0, "aclk_strc_sys", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 10, GFLAGS),
+
+	GATE(0, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 6, GFLAGS),
+	GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_cpu", 0, RK2928_CLKGATE_CON(3), 5, GFLAGS),
+
+	GATE(PCLK_HDMI, "pclk_hdmi", "pclk_cpu", 0, RK2928_CLKGATE_CON(3), 8, GFLAGS),
+	GATE(PCLK_ACODEC, "pclk_acodec", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS),
+	GATE(0, "pclk_ddrupctl", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 7, GFLAGS),
+	GATE(0, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS),
+	GATE(0, "pclk_mipiphy", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 0, GFLAGS),
+
+	GATE(0, "pclk_pmu", "pclk_pmu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 2, GFLAGS),
+	GATE(0, "pclk_pmu_niu", "pclk_pmu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 3, GFLAGS),
+
+	/* PD_MMC */
+	MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RK3228_SDMMC_CON0, 1),
+	MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 0),
+
+	MMC(SCLK_SDIO_DRV,     "sdio_drv",     "sclk_sdio",  RK3228_SDIO_CON0,  1),
+	MMC(SCLK_SDIO_SAMPLE,  "sdio_sample",  "sclk_sdio",  RK3228_SDIO_CON1,  0),
+
+	MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RK3228_EMMC_CON0,  1),
+	MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RK3228_EMMC_CON1,  0),
+};
+
+static const char *const rk3128_critical_clocks[] __initconst = {
+	"aclk_cpu",
+	"hclk_cpu",
+	"pclk_cpu",
+	"aclk_peri",
+	"hclk_peri",
+	"pclk_peri",
+};
+
+static void __init rk3128_clk_init(struct device_node *np)
+{
+	struct rockchip_clk_provider *ctx;
+	void __iomem *reg_base;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("%s: could not map cru region\n", __func__);
+		return;
+	}
+
+	ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+	if (IS_ERR(ctx)) {
+		pr_err("%s: rockchip clk init failed\n", __func__);
+		iounmap(reg_base);
+		return;
+	}
+
+	rockchip_clk_register_plls(ctx, rk3128_pll_clks,
+				   ARRAY_SIZE(rk3128_pll_clks),
+				   RK3128_GRF_SOC_STATUS0);
+	rockchip_clk_register_branches(ctx, rk3128_clk_branches,
+				  ARRAY_SIZE(rk3128_clk_branches));
+	rockchip_clk_protect_critical(rk3128_critical_clocks,
+				      ARRAY_SIZE(rk3128_critical_clocks));
+
+	rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
+			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
+			&rk3128_cpuclk_data, rk3128_cpuclk_rates,
+			ARRAY_SIZE(rk3128_cpuclk_rates));
+
+	rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
+				  ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+	rockchip_register_restart_notifier(ctx, RK2928_GLB_SRST_FST, NULL);
+
+	rockchip_clk_of_add_provider(np, ctx);
+}
+
+CLK_OF_DECLARE(rk3128_cru, "rockchip,rk3128-cru", rk3128_clk_init);

+ 105 - 59
drivers/clk/rockchip/clk-rk3228.c

@@ -86,25 +86,43 @@ static struct rockchip_pll_rate_table rk3228_pll_rates[] = {
 #define RK3228_DIV_PCLK_MASK		0x7
 #define RK3228_DIV_PCLK_SHIFT		12
 
-#define RK3228_CLKSEL1(_core_peri_div)					\
+#define RK3228_CLKSEL1(_core_aclk_div, _core_peri_div)				\
 	{									\
 		.reg = RK2928_CLKSEL_CON(1),					\
 		.val = HIWORD_UPDATE(_core_peri_div, RK3228_DIV_PERI_MASK,	\
-				RK3228_DIV_PERI_SHIFT)				\
-	}
+				     RK3228_DIV_PERI_SHIFT) |			\
+		       HIWORD_UPDATE(_core_aclk_div, RK3228_DIV_ACLK_MASK,	\
+				     RK3228_DIV_ACLK_SHIFT),			\
+}
 
-#define RK3228_CPUCLK_RATE(_prate, _core_peri_div)			\
-	{								\
-		.prate = _prate,					\
-		.divs = {						\
-			RK3228_CLKSEL1(_core_peri_div),		\
-		},							\
+#define RK3228_CPUCLK_RATE(_prate, _core_aclk_div, _core_peri_div)		\
+	{									\
+		.prate = _prate,						\
+		.divs = {							\
+			RK3228_CLKSEL1(_core_aclk_div, _core_peri_div),		\
+		},								\
 	}
 
 static struct rockchip_cpuclk_rate_table rk3228_cpuclk_rates[] __initdata = {
-	RK3228_CPUCLK_RATE(816000000, 4),
-	RK3228_CPUCLK_RATE(600000000, 4),
-	RK3228_CPUCLK_RATE(312000000, 4),
+	RK3228_CPUCLK_RATE(1800000000, 1, 7),
+	RK3228_CPUCLK_RATE(1704000000, 1, 7),
+	RK3228_CPUCLK_RATE(1608000000, 1, 7),
+	RK3228_CPUCLK_RATE(1512000000, 1, 7),
+	RK3228_CPUCLK_RATE(1488000000, 1, 5),
+	RK3228_CPUCLK_RATE(1416000000, 1, 5),
+	RK3228_CPUCLK_RATE(1392000000, 1, 5),
+	RK3228_CPUCLK_RATE(1296000000, 1, 5),
+	RK3228_CPUCLK_RATE(1200000000, 1, 5),
+	RK3228_CPUCLK_RATE(1104000000, 1, 5),
+	RK3228_CPUCLK_RATE(1008000000, 1, 5),
+	RK3228_CPUCLK_RATE(912000000, 1, 5),
+	RK3228_CPUCLK_RATE(816000000, 1, 3),
+	RK3228_CPUCLK_RATE(696000000, 1, 3),
+	RK3228_CPUCLK_RATE(600000000, 1, 3),
+	RK3228_CPUCLK_RATE(408000000, 1, 1),
+	RK3228_CPUCLK_RATE(312000000, 1, 1),
+	RK3228_CPUCLK_RATE(216000000,  1, 1),
+	RK3228_CPUCLK_RATE(96000000, 1, 1),
 };
 
 static const struct rockchip_cpuclk_reg_data rk3228_cpuclk_data = {
@@ -252,15 +270,15 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
 			RK2928_CLKGATE_CON(0), 1, GFLAGS),
 	COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_aclk_cpu_src_p, 0,
 			RK2928_CLKSEL_CON(0), 13, 2, MFLAGS, 8, 5, DFLAGS),
-	GATE(ARMCLK, "aclk_cpu", "aclk_cpu_src", 0,
+	GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_src", 0,
 			RK2928_CLKGATE_CON(6), 0, GFLAGS),
-	COMPOSITE_NOMUX(0, "hclk_cpu", "aclk_cpu_src", 0,
+	COMPOSITE_NOMUX(HCLK_CPU, "hclk_cpu", "aclk_cpu_src", 0,
 			RK2928_CLKSEL_CON(1), 8, 2, DFLAGS,
 			RK2928_CLKGATE_CON(6), 1, GFLAGS),
 	COMPOSITE_NOMUX(0, "pclk_bus_src", "aclk_cpu_src", 0,
 			RK2928_CLKSEL_CON(1), 12, 3, DFLAGS,
 			RK2928_CLKGATE_CON(6), 2, GFLAGS),
-	GATE(0, "pclk_cpu", "pclk_bus_src", 0,
+	GATE(PCLK_CPU, "pclk_cpu", "pclk_bus_src", 0,
 			RK2928_CLKGATE_CON(6), 3, GFLAGS),
 	GATE(0, "pclk_phy_pre", "pclk_bus_src", 0,
 			RK2928_CLKGATE_CON(6), 4, GFLAGS),
@@ -268,58 +286,58 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
 			RK2928_CLKGATE_CON(6), 13, GFLAGS),
 
 	/* PD_VIDEO */
-	COMPOSITE(0, "aclk_vpu_pre", mux_pll_src_4plls_p, 0,
+	COMPOSITE(ACLK_VPU_PRE, "aclk_vpu_pre", mux_pll_src_4plls_p, 0,
 			RK2928_CLKSEL_CON(32), 5, 2, MFLAGS, 0, 5, DFLAGS,
 			RK2928_CLKGATE_CON(3), 11, GFLAGS),
-	FACTOR_GATE(0, "hclk_vpu_pre", "aclk_vpu_pre", 0, 1, 4,
+	FACTOR_GATE(HCLK_VPU_PRE, "hclk_vpu_pre", "aclk_vpu_pre", 0, 1, 4,
 			RK2928_CLKGATE_CON(4), 4, GFLAGS),
 
-	COMPOSITE(0, "aclk_rkvdec_pre", mux_pll_src_4plls_p, 0,
+	COMPOSITE(ACLK_RKVDEC_PRE, "aclk_rkvdec_pre", mux_pll_src_4plls_p, 0,
 			RK2928_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS,
 			RK2928_CLKGATE_CON(3), 2, GFLAGS),
-	FACTOR_GATE(0, "hclk_rkvdec_pre", "aclk_rkvdec_pre", 0, 1, 4,
+	FACTOR_GATE(HCLK_RKVDEC_PRE, "hclk_rkvdec_pre", "aclk_rkvdec_pre", 0, 1, 4,
 			RK2928_CLKGATE_CON(4), 5, GFLAGS),
 
-	COMPOSITE(0, "sclk_vdec_cabac", mux_pll_src_4plls_p, 0,
+	COMPOSITE(SCLK_VDEC_CABAC, "sclk_vdec_cabac", mux_pll_src_4plls_p, 0,
 			RK2928_CLKSEL_CON(28), 14, 2, MFLAGS, 8, 5, DFLAGS,
 			RK2928_CLKGATE_CON(3), 3, GFLAGS),
 
-	COMPOSITE(0, "sclk_vdec_core", mux_pll_src_4plls_p, 0,
+	COMPOSITE(SCLK_VDEC_CORE, "sclk_vdec_core", mux_pll_src_4plls_p, 0,
 			RK2928_CLKSEL_CON(34), 13, 2, MFLAGS, 8, 5, DFLAGS,
 			RK2928_CLKGATE_CON(3), 4, GFLAGS),
 
 	/* PD_VIO */
-	COMPOSITE(0, "aclk_iep_pre", mux_pll_src_4plls_p, 0,
+	COMPOSITE(ACLK_IEP_PRE, "aclk_iep_pre", mux_pll_src_4plls_p, 0,
 			RK2928_CLKSEL_CON(31), 5, 2, MFLAGS, 0, 5, DFLAGS,
 			RK2928_CLKGATE_CON(3), 0, GFLAGS),
-	DIV(0, "hclk_vio_pre", "aclk_iep_pre", 0,
+	DIV(HCLK_VIO_PRE, "hclk_vio_pre", "aclk_iep_pre", 0,
 			RK2928_CLKSEL_CON(2), 0, 5, DFLAGS),
 
-	COMPOSITE(0, "aclk_hdcp_pre", mux_pll_src_4plls_p, 0,
+	COMPOSITE(ACLK_HDCP_PRE, "aclk_hdcp_pre", mux_pll_src_4plls_p, 0,
 			RK2928_CLKSEL_CON(31), 13, 2, MFLAGS, 8, 5, DFLAGS,
 			RK2928_CLKGATE_CON(1), 4, GFLAGS),
 
 	MUX(0, "sclk_rga_src", mux_pll_src_4plls_p, 0,
 			RK2928_CLKSEL_CON(33), 13, 2, MFLAGS),
-	COMPOSITE_NOMUX(0, "aclk_rga_pre", "sclk_rga_src", 0,
+	COMPOSITE_NOMUX(ACLK_RGA_PRE, "aclk_rga_pre", "sclk_rga_src", 0,
 			RK2928_CLKSEL_CON(33), 8, 5, DFLAGS,
 			RK2928_CLKGATE_CON(1), 2, GFLAGS),
-	COMPOSITE(0, "sclk_rga", mux_sclk_rga_p, 0,
+	COMPOSITE(SCLK_RGA, "sclk_rga", mux_sclk_rga_p, 0,
 			RK2928_CLKSEL_CON(22), 5, 2, MFLAGS, 0, 5, DFLAGS,
 			RK2928_CLKGATE_CON(3), 6, GFLAGS),
 
-	COMPOSITE(0, "aclk_vop_pre", mux_pll_src_4plls_p, 0,
+	COMPOSITE(ACLK_VOP_PRE, "aclk_vop_pre", mux_pll_src_4plls_p, 0,
 			RK2928_CLKSEL_CON(33), 5, 2, MFLAGS, 0, 5, DFLAGS,
 			RK2928_CLKGATE_CON(1), 1, GFLAGS),
 
-	COMPOSITE(0, "sclk_hdcp", mux_pll_src_3plls_p, 0,
+	COMPOSITE(SCLK_HDCP, "sclk_hdcp", mux_pll_src_3plls_p, 0,
 			RK2928_CLKSEL_CON(23), 14, 2, MFLAGS, 8, 6, DFLAGS,
 			RK2928_CLKGATE_CON(3), 5, GFLAGS),
 
 	GATE(SCLK_HDMI_HDCP, "sclk_hdmi_hdcp", "xin24m", 0,
 			RK2928_CLKGATE_CON(3), 7, GFLAGS),
 
-	COMPOSITE(0, "sclk_hdmi_cec", mux_sclk_hdmi_cec_p, 0,
+	COMPOSITE(SCLK_HDMI_CEC, "sclk_hdmi_cec", mux_sclk_hdmi_cec_p, 0,
 			RK2928_CLKSEL_CON(21), 14, 2, MFLAGS, 0, 14, DFLAGS,
 			RK2928_CLKGATE_CON(3), 8, GFLAGS),
 
@@ -354,18 +372,18 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
 	GATE(SCLK_TIMER5, "sclk_timer5", "xin24m", 0,
 			RK2928_CLKGATE_CON(6), 10, GFLAGS),
 
-	COMPOSITE(0, "sclk_crypto", mux_pll_src_2plls_p, 0,
+	COMPOSITE(SCLK_CRYPTO, "sclk_crypto", mux_pll_src_2plls_p, 0,
 			RK2928_CLKSEL_CON(24), 5, 1, MFLAGS, 0, 5, DFLAGS,
 			RK2928_CLKGATE_CON(2), 7, GFLAGS),
 
-	COMPOSITE(0, "sclk_tsp", mux_pll_src_2plls_p, 0,
+	COMPOSITE(SCLK_TSP, "sclk_tsp", mux_pll_src_2plls_p, 0,
 			RK2928_CLKSEL_CON(22), 15, 1, MFLAGS, 8, 5, DFLAGS,
 			RK2928_CLKGATE_CON(2), 6, GFLAGS),
 
-	GATE(0, "sclk_hsadc", "ext_hsadc", 0,
+	GATE(SCLK_HSADC, "sclk_hsadc", "ext_hsadc", 0,
 			RK2928_CLKGATE_CON(10), 12, GFLAGS),
 
-	COMPOSITE(0, "sclk_wifi", mux_pll_src_cpll_gpll_usb480m_p, 0,
+	COMPOSITE(SCLK_WIFI, "sclk_wifi", mux_pll_src_cpll_gpll_usb480m_p, 0,
 			RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 6, DFLAGS,
 			RK2928_CLKGATE_CON(2), 15, GFLAGS),
 
@@ -445,12 +463,12 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
 			RK2928_CLKGATE_CON(2), 12, GFLAGS,
 			&rk3228_spdif_fracmux),
 
-	GATE(0, "jtag", "ext_jtag", 0,
+	GATE(0, "jtag", "ext_jtag", CLK_IGNORE_UNUSED,
 			RK2928_CLKGATE_CON(1), 3, GFLAGS),
 
-	GATE(0, "sclk_otgphy0", "xin24m", 0,
+	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", 0,
 			RK2928_CLKGATE_CON(1), 5, GFLAGS),
-	GATE(0, "sclk_otgphy1", "xin24m", 0,
+	GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", 0,
 			RK2928_CLKGATE_CON(1), 6, GFLAGS),
 
 	COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin24m", 0,
@@ -526,28 +544,28 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
 	 */
 
 	/* PD_VOP */
-	GATE(0, "aclk_rga", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 0, GFLAGS),
+	GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 0, GFLAGS),
 	GATE(0, "aclk_rga_noc", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 11, GFLAGS),
-	GATE(0, "aclk_iep", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 2, GFLAGS),
+	GATE(ACLK_IEP, "aclk_iep", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 2, GFLAGS),
 	GATE(0, "aclk_iep_noc", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 9, GFLAGS),
 
 	GATE(ACLK_VOP, "aclk_vop", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 5, GFLAGS),
 	GATE(0, "aclk_vop_noc", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 12, GFLAGS),
 
-	GATE(0, "aclk_hdcp", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(14), 10, GFLAGS),
+	GATE(ACLK_HDCP, "aclk_hdcp", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(14), 10, GFLAGS),
 	GATE(0, "aclk_hdcp_noc", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(13), 10, GFLAGS),
 
-	GATE(0, "hclk_rga", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 1, GFLAGS),
-	GATE(0, "hclk_iep", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 3, GFLAGS),
+	GATE(HCLK_RGA, "hclk_rga", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 1, GFLAGS),
+	GATE(HCLK_IEP, "hclk_iep", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 3, GFLAGS),
 	GATE(HCLK_VOP, "hclk_vop", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 6, GFLAGS),
 	GATE(0, "hclk_vio_ahb_arbi", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 7, GFLAGS),
 	GATE(0, "hclk_vio_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 8, GFLAGS),
 	GATE(0, "hclk_vop_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 13, GFLAGS),
-	GATE(0, "hclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 7, GFLAGS),
-	GATE(0, "hclk_hdcp_mmu", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 12, GFLAGS),
+	GATE(HCLK_VIO_H2P, "hclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 7, GFLAGS),
+	GATE(HCLK_HDCP_MMU, "hclk_hdcp_mmu", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 12, GFLAGS),
 	GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 6, GFLAGS),
-	GATE(0, "pclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 8, GFLAGS),
-	GATE(0, "pclk_hdcp", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 11, GFLAGS),
+	GATE(PCLK_VIO_H2P, "pclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 8, GFLAGS),
+	GATE(PCLK_HDCP, "pclk_hdcp", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 11, GFLAGS),
 
 	/* PD_PERI */
 	GATE(0, "aclk_peri_noc", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 0, GFLAGS),
@@ -557,12 +575,12 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
 	GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 1, GFLAGS),
 	GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 2, GFLAGS),
 	GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 3, GFLAGS),
-	GATE(0, "hclk_host0", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 6, GFLAGS),
+	GATE(HCLK_HOST0, "hclk_host0", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 6, GFLAGS),
 	GATE(0, "hclk_host0_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 7, GFLAGS),
-	GATE(0, "hclk_host1", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 8, GFLAGS),
+	GATE(HCLK_HOST1, "hclk_host1", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 8, GFLAGS),
 	GATE(0, "hclk_host1_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 9, GFLAGS),
-	GATE(0, "hclk_host2", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 10, GFLAGS),
-	GATE(0, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 12, GFLAGS),
+	GATE(HCLK_HOST2, "hclk_host2", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 10, GFLAGS),
+	GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 12, GFLAGS),
 	GATE(0, "hclk_otg_pmu", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 13, GFLAGS),
 	GATE(0, "hclk_host2_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 14, GFLAGS),
 	GATE(0, "hclk_peri_noc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 1, GFLAGS),
@@ -571,7 +589,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
 	GATE(0, "pclk_peri_noc", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 2, GFLAGS),
 
 	/* PD_GPU */
-	GATE(0, "aclk_gpu", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(13), 14, GFLAGS),
+	GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(13), 14, GFLAGS),
 	GATE(0, "aclk_gpu_noc", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(13), 15, GFLAGS),
 
 	/* PD_BUS */
@@ -585,16 +603,16 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
 	GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS),
 	GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS),
 	GATE(HCLK_SPDIF_8CH, "hclk_spdif_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS),
-	GATE(0, "hclk_tsp", "hclk_cpu", 0, RK2928_CLKGATE_CON(10), 11, GFLAGS),
-	GATE(0, "hclk_crypto_mst", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
-	GATE(0, "hclk_crypto_slv", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS),
+	GATE(HCLK_TSP, "hclk_tsp", "hclk_cpu", 0, RK2928_CLKGATE_CON(10), 11, GFLAGS),
+	GATE(HCLK_M_CRYPTO, "hclk_crypto_mst", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
+	GATE(HCLK_S_CRYPTO, "hclk_crypto_slv", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS),
 
 	GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS),
 	GATE(0, "pclk_ddrmon", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS),
 	GATE(0, "pclk_msch_noc", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(10), 2, GFLAGS),
 
-	GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS),
-	GATE(0, "pclk_efuse_256", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 14, GFLAGS),
+	GATE(PCLK_EFUSE_1024, "pclk_efuse_1024", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS),
+	GATE(PCLK_EFUSE_256, "pclk_efuse_256", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 14, GFLAGS),
 	GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 15, GFLAGS),
 	GATE(PCLK_I2C1, "pclk_i2c1", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 0, GFLAGS),
 	GATE(PCLK_I2C2, "pclk_i2c2", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS),
@@ -622,13 +640,13 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
 	GATE(0, "pclk_vdacphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 8, GFLAGS),
 	GATE(0, "pclk_phy_noc", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 9, GFLAGS),
 
-	GATE(0, "aclk_vpu", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 0, GFLAGS),
+	GATE(ACLK_VPU, "aclk_vpu", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 0, GFLAGS),
 	GATE(0, "aclk_vpu_noc", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 4, GFLAGS),
-	GATE(0, "aclk_rkvdec", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 2, GFLAGS),
+	GATE(ACLK_RKVDEC, "aclk_rkvdec", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 2, GFLAGS),
 	GATE(0, "aclk_rkvdec_noc", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 6, GFLAGS),
-	GATE(0, "hclk_vpu", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 1, GFLAGS),
+	GATE(HCLK_VPU, "hclk_vpu", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 1, GFLAGS),
 	GATE(0, "hclk_vpu_noc", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 5, GFLAGS),
-	GATE(0, "hclk_rkvdec", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 3, GFLAGS),
+	GATE(HCLK_RKVDEC, "hclk_rkvdec", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 3, GFLAGS),
 	GATE(0, "hclk_rkvdec_noc", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 7, GFLAGS),
 
 	/* PD_MMC */
@@ -644,9 +662,37 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
 
 static const char *const rk3228_critical_clocks[] __initconst = {
 	"aclk_cpu",
+	"pclk_cpu",
+	"hclk_cpu",
 	"aclk_peri",
 	"hclk_peri",
 	"pclk_peri",
+	"aclk_rga_noc",
+	"aclk_iep_noc",
+	"aclk_vop_noc",
+	"aclk_hdcp_noc",
+	"hclk_vio_ahb_arbi",
+	"hclk_vio_noc",
+	"hclk_vop_noc",
+	"hclk_host0_arb",
+	"hclk_host1_arb",
+	"hclk_host2_arb",
+	"hclk_otg_pmu",
+	"aclk_gpu_noc",
+	"sclk_initmem_mbist",
+	"aclk_initmem",
+	"hclk_rom",
+	"pclk_ddrupctl",
+	"pclk_ddrmon",
+	"pclk_msch_noc",
+	"pclk_stimer",
+	"pclk_ddrphy",
+	"pclk_acodecphy",
+	"pclk_phy_noc",
+	"aclk_vpu_noc",
+	"aclk_rkvdec_noc",
+	"hclk_vpu_noc",
+	"hclk_rkvdec_noc",
 };
 
 static void __init rk3228_clk_init(struct device_node *np)

+ 10 - 4
drivers/clk/rockchip/clk-rk3288.c

@@ -292,13 +292,13 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	COMPOSITE_NOMUX(0, "aclk_core_mp", "armclk", CLK_IGNORE_UNUSED,
 			RK3288_CLKSEL_CON(0), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
 			RK3288_CLKGATE_CON(12), 6, GFLAGS),
-	COMPOSITE_NOMUX(0, "atclk", "armclk", 0,
+	COMPOSITE_NOMUX(0, "atclk", "armclk", CLK_IGNORE_UNUSED,
 			RK3288_CLKSEL_CON(37), 4, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
 			RK3288_CLKGATE_CON(12), 7, GFLAGS),
 	COMPOSITE_NOMUX(0, "pclk_dbg_pre", "armclk", CLK_IGNORE_UNUSED,
 			RK3288_CLKSEL_CON(37), 9, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
 			RK3288_CLKGATE_CON(12), 8, GFLAGS),
-	GATE(0, "pclk_dbg", "pclk_dbg_pre", 0,
+	GATE(0, "pclk_dbg", "pclk_dbg_pre", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(12), 9, GFLAGS),
 	GATE(0, "cs_dbg", "pclk_dbg_pre", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(12), 10, GFLAGS),
@@ -626,7 +626,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
 			RK3288_CLKSEL_CON(22), 7, IFLAGS),
 
-	GATE(0, "jtag", "ext_jtag", 0,
+	GATE(0, "jtag", "ext_jtag", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(4), 14, GFLAGS),
 
 	COMPOSITE_NODIV(SCLK_USBPHY480M_SRC, "usbphy480m_src", mux_usbphy480m_p, 0,
@@ -635,7 +635,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	COMPOSITE_NODIV(SCLK_HSICPHY480M, "sclk_hsicphy480m", mux_hsicphy480m_p, 0,
 			RK3288_CLKSEL_CON(29), 0, 2, MFLAGS,
 			RK3288_CLKGATE_CON(3), 6, GFLAGS),
-	GATE(0, "hsicphy12m_xin12m", "xin12m", 0,
+	GATE(0, "hsicphy12m_xin12m", "xin12m", CLK_IGNORE_UNUSED,
 			RK3288_CLKGATE_CON(13), 9, GFLAGS),
 	DIV(0, "hsicphy12m_usbphy", "sclk_hsicphy480m", 0,
 			RK3288_CLKSEL_CON(11), 8, 6, DFLAGS),
@@ -816,6 +816,12 @@ static const char *const rk3288_critical_clocks[] __initconst = {
 	"pclk_alive_niu",
 	"pclk_pd_pmu",
 	"pclk_pmu_niu",
+	"pclk_core_niu",
+	"pclk_ddrupctl0",
+	"pclk_publ0",
+	"pclk_ddrupctl1",
+	"pclk_publ1",
+	"pmu_hclk_otg0",
 };
 
 static void __iomem *rk3288_cru_base;

+ 4 - 1
drivers/clk/rockchip/clk-rk3368.c

@@ -638,7 +638,7 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
 	GATE(SCLK_MAC_TX, "sclk_mac_tx", "mac_clk", 0,
 			RK3368_CLKGATE_CON(7), 5, GFLAGS),
 
-	GATE(0, "jtag", "ext_jtag", 0,
+	GATE(0, "jtag", "ext_jtag", CLK_IGNORE_UNUSED,
 			RK3368_CLKGATE_CON(7), 0, GFLAGS),
 
 	COMPOSITE_NODIV(0, "hsic_usbphy_480m", mux_hsic_usbphy480m_p, 0,
@@ -861,6 +861,9 @@ static const char *const rk3368_critical_clocks[] __initconst = {
 	"pclk_pd_alive",
 	"pclk_peri",
 	"hclk_peri",
+	"pclk_ddrphy",
+	"pclk_ddrupctl",
+	"pmu_hclk_otg0",
 };
 
 static void __init rk3368_clk_init(struct device_node *np)

+ 2 - 2
drivers/clk/rockchip/clk-rk3399.c

@@ -1066,13 +1066,13 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
 	/* cif_testout */
 	MUX(0, "clk_testout1_pll_src", mux_pll_src_cpll_gpll_npll_p, 0,
 			RK3399_CLKSEL_CON(38), 6, 2, MFLAGS),
-	COMPOSITE(0, "clk_testout1", mux_clk_testout1_p, 0,
+	COMPOSITE(SCLK_TESTCLKOUT1, "clk_testout1", mux_clk_testout1_p, 0,
 			RK3399_CLKSEL_CON(38), 5, 1, MFLAGS, 0, 5, DFLAGS,
 			RK3399_CLKGATE_CON(13), 14, GFLAGS),
 
 	MUX(0, "clk_testout2_pll_src", mux_pll_src_cpll_gpll_npll_p, 0,
 			RK3399_CLKSEL_CON(38), 14, 2, MFLAGS),
-	COMPOSITE(0, "clk_testout2", mux_clk_testout2_p, 0,
+	COMPOSITE(SCLK_TESTCLKOUT2, "clk_testout2", mux_clk_testout2_p, 0,
 			RK3399_CLKSEL_CON(38), 13, 1, MFLAGS, 8, 5, DFLAGS,
 			RK3399_CLKGATE_CON(13), 15, GFLAGS),
 

+ 8 - 9
drivers/clk/samsung/clk-cpu.c

@@ -410,7 +410,7 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
 {
 	struct exynos_cpuclk *cpuclk;
 	struct clk_init_data init;
-	struct clk *clk;
+	struct clk *parent_clk;
 	int ret = 0;
 
 	cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
@@ -440,15 +440,15 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
 		goto free_cpuclk;
 	}
 
-	clk = __clk_lookup(parent);
-	if (!clk) {
+	parent_clk = __clk_lookup(parent);
+	if (!parent_clk) {
 		pr_err("%s: could not lookup parent clock %s\n",
 				__func__, parent);
 		ret = -EINVAL;
 		goto free_cpuclk;
 	}
 
-	ret = clk_notifier_register(clk, &cpuclk->clk_nb);
+	ret = clk_notifier_register(parent_clk, &cpuclk->clk_nb);
 	if (ret) {
 		pr_err("%s: failed to register clock notifier for %s\n",
 				__func__, name);
@@ -463,20 +463,19 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
 		goto unregister_clk_nb;
 	}
 
-	clk = clk_register(NULL, &cpuclk->hw);
-	if (IS_ERR(clk)) {
+	ret = clk_hw_register(NULL, &cpuclk->hw);
+	if (ret) {
 		pr_err("%s: could not register cpuclk %s\n", __func__,	name);
-		ret = PTR_ERR(clk);
 		goto free_cpuclk_data;
 	}
 
-	samsung_clk_add_lookup(ctx, clk, lookup_id);
+	samsung_clk_add_lookup(ctx, &cpuclk->hw, lookup_id);
 	return 0;
 
 free_cpuclk_data:
 	kfree(cpuclk->cfg);
 unregister_clk_nb:
-	clk_notifier_unregister(__clk_lookup(parent), &cpuclk->clk_nb);
+	clk_notifier_unregister(parent_clk, &cpuclk->clk_nb);
 free_cpuclk:
 	kfree(cpuclk);
 	return ret;

+ 30 - 28
drivers/clk/samsung/clk-exynos-audss.c

@@ -22,9 +22,8 @@
 #include <dt-bindings/clock/exynos-audss-clk.h>
 
 static DEFINE_SPINLOCK(lock);
-static struct clk **clk_table;
 static void __iomem *reg_base;
-static struct clk_onecell_data clk_data;
+static struct clk_hw_onecell_data *clk_data;
 /*
  * On Exynos5420 this will be a clock which has to be enabled before any
  * access to audss registers. Typically a child of EPLL.
@@ -74,6 +73,7 @@ struct exynos_audss_clk_drvdata {
 
 static const struct exynos_audss_clk_drvdata exynos4210_drvdata = {
 	.num_clks	= EXYNOS_AUDSS_MAX_CLKS - 1,
+	.enable_epll	= 1,
 };
 
 static const struct exynos_audss_clk_drvdata exynos5410_drvdata = {
@@ -110,18 +110,18 @@ static void exynos_audss_clk_teardown(void)
 	int i;
 
 	for (i = EXYNOS_MOUT_AUDSS; i < EXYNOS_DOUT_SRP; i++) {
-		if (!IS_ERR(clk_table[i]))
-			clk_unregister_mux(clk_table[i]);
+		if (!IS_ERR(clk_data->hws[i]))
+			clk_hw_unregister_mux(clk_data->hws[i]);
 	}
 
 	for (; i < EXYNOS_SRP_CLK; i++) {
-		if (!IS_ERR(clk_table[i]))
-			clk_unregister_divider(clk_table[i]);
+		if (!IS_ERR(clk_data->hws[i]))
+			clk_hw_unregister_divider(clk_data->hws[i]);
 	}
 
-	for (; i < clk_data.clk_num; i++) {
-		if (!IS_ERR(clk_table[i]))
-			clk_unregister_gate(clk_table[i]);
+	for (; i < clk_data->num; i++) {
+		if (!IS_ERR(clk_data->hws[i]))
+			clk_hw_unregister_gate(clk_data->hws[i]);
 	}
 }
 
@@ -133,6 +133,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
 	const char *sclk_pcm_p = "sclk_pcm0";
 	struct clk *pll_ref, *pll_in, *cdclk, *sclk_audio, *sclk_pcm_in;
 	const struct exynos_audss_clk_drvdata *variant;
+	struct clk_hw **clk_table;
 	struct resource *res;
 	int i, ret = 0;
 
@@ -149,14 +150,15 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
 
 	epll = ERR_PTR(-ENODEV);
 
-	clk_table = devm_kzalloc(&pdev->dev,
-				sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS,
+	clk_data = devm_kzalloc(&pdev->dev,
+				sizeof(*clk_data) +
+				sizeof(*clk_data->hws) * EXYNOS_AUDSS_MAX_CLKS,
 				GFP_KERNEL);
-	if (!clk_table)
+	if (!clk_data)
 		return -ENOMEM;
 
-	clk_data.clks = clk_table;
-	clk_data.clk_num = variant->num_clks;
+	clk_data->num = variant->num_clks;
+	clk_table = clk_data->hws;
 
 	pll_ref = devm_clk_get(&pdev->dev, "pll_ref");
 	pll_in = devm_clk_get(&pdev->dev, "pll_in");
@@ -176,7 +178,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
 			}
 		}
 	}
-	clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
+	clk_table[EXYNOS_MOUT_AUDSS] = clk_hw_register_mux(NULL, "mout_audss",
 				mout_audss_p, ARRAY_SIZE(mout_audss_p),
 				CLK_SET_RATE_NO_REPARENT,
 				reg_base + ASS_CLK_SRC, 0, 1, 0, &lock);
@@ -187,53 +189,53 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
 		mout_i2s_p[1] = __clk_get_name(cdclk);
 	if (!IS_ERR(sclk_audio))
 		mout_i2s_p[2] = __clk_get_name(sclk_audio);
-	clk_table[EXYNOS_MOUT_I2S] = clk_register_mux(NULL, "mout_i2s",
+	clk_table[EXYNOS_MOUT_I2S] = clk_hw_register_mux(NULL, "mout_i2s",
 				mout_i2s_p, ARRAY_SIZE(mout_i2s_p),
 				CLK_SET_RATE_NO_REPARENT,
 				reg_base + ASS_CLK_SRC, 2, 2, 0, &lock);
 
-	clk_table[EXYNOS_DOUT_SRP] = clk_register_divider(NULL, "dout_srp",
+	clk_table[EXYNOS_DOUT_SRP] = clk_hw_register_divider(NULL, "dout_srp",
 				"mout_audss", 0, reg_base + ASS_CLK_DIV, 0, 4,
 				0, &lock);
 
-	clk_table[EXYNOS_DOUT_AUD_BUS] = clk_register_divider(NULL,
+	clk_table[EXYNOS_DOUT_AUD_BUS] = clk_hw_register_divider(NULL,
 				"dout_aud_bus", "dout_srp", 0,
 				reg_base + ASS_CLK_DIV, 4, 4, 0, &lock);
 
-	clk_table[EXYNOS_DOUT_I2S] = clk_register_divider(NULL, "dout_i2s",
+	clk_table[EXYNOS_DOUT_I2S] = clk_hw_register_divider(NULL, "dout_i2s",
 				"mout_i2s", 0, reg_base + ASS_CLK_DIV, 8, 4, 0,
 				&lock);
 
-	clk_table[EXYNOS_SRP_CLK] = clk_register_gate(NULL, "srp_clk",
+	clk_table[EXYNOS_SRP_CLK] = clk_hw_register_gate(NULL, "srp_clk",
 				"dout_srp", CLK_SET_RATE_PARENT,
 				reg_base + ASS_CLK_GATE, 0, 0, &lock);
 
-	clk_table[EXYNOS_I2S_BUS] = clk_register_gate(NULL, "i2s_bus",
+	clk_table[EXYNOS_I2S_BUS] = clk_hw_register_gate(NULL, "i2s_bus",
 				"dout_aud_bus", CLK_SET_RATE_PARENT,
 				reg_base + ASS_CLK_GATE, 2, 0, &lock);
 
-	clk_table[EXYNOS_SCLK_I2S] = clk_register_gate(NULL, "sclk_i2s",
+	clk_table[EXYNOS_SCLK_I2S] = clk_hw_register_gate(NULL, "sclk_i2s",
 				"dout_i2s", CLK_SET_RATE_PARENT,
 				reg_base + ASS_CLK_GATE, 3, 0, &lock);
 
-	clk_table[EXYNOS_PCM_BUS] = clk_register_gate(NULL, "pcm_bus",
+	clk_table[EXYNOS_PCM_BUS] = clk_hw_register_gate(NULL, "pcm_bus",
 				 "sclk_pcm", CLK_SET_RATE_PARENT,
 				reg_base + ASS_CLK_GATE, 4, 0, &lock);
 
 	sclk_pcm_in = devm_clk_get(&pdev->dev, "sclk_pcm_in");
 	if (!IS_ERR(sclk_pcm_in))
 		sclk_pcm_p = __clk_get_name(sclk_pcm_in);
-	clk_table[EXYNOS_SCLK_PCM] = clk_register_gate(NULL, "sclk_pcm",
+	clk_table[EXYNOS_SCLK_PCM] = clk_hw_register_gate(NULL, "sclk_pcm",
 				sclk_pcm_p, CLK_SET_RATE_PARENT,
 				reg_base + ASS_CLK_GATE, 5, 0, &lock);
 
 	if (variant->has_adma_clk) {
-		clk_table[EXYNOS_ADMA] = clk_register_gate(NULL, "adma",
+		clk_table[EXYNOS_ADMA] = clk_hw_register_gate(NULL, "adma",
 				"dout_srp", CLK_SET_RATE_PARENT,
 				reg_base + ASS_CLK_GATE, 9, 0, &lock);
 	}
 
-	for (i = 0; i < clk_data.clk_num; i++) {
+	for (i = 0; i < clk_data->num; i++) {
 		if (IS_ERR(clk_table[i])) {
 			dev_err(&pdev->dev, "failed to register clock %d\n", i);
 			ret = PTR_ERR(clk_table[i]);
@@ -241,8 +243,8 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
 		}
 	}
 
-	ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
-					&clk_data);
+	ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get,
+				     clk_data);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add clock provider\n");
 		goto unregister;

+ 9 - 9
drivers/clk/samsung/clk-exynos-clkout.c

@@ -29,10 +29,9 @@ struct exynos_clkout {
 	struct clk_gate gate;
 	struct clk_mux mux;
 	spinlock_t slock;
-	struct clk_onecell_data data;
-	struct clk *clk_table[EXYNOS_CLKOUT_NR_CLKS];
 	void __iomem *reg;
 	u32 pmu_debug_save;
+	struct clk_hw_onecell_data data;
 };
 
 static struct exynos_clkout *clkout;
@@ -62,7 +61,9 @@ static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
 	int ret;
 	int i;
 
-	clkout = kzalloc(sizeof(*clkout), GFP_KERNEL);
+	clkout = kzalloc(sizeof(*clkout) +
+			 sizeof(*clkout->data.hws) * EXYNOS_CLKOUT_NR_CLKS,
+			 GFP_KERNEL);
 	if (!clkout)
 		return;
 
@@ -100,17 +101,16 @@ static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
 	clkout->mux.shift = EXYNOS_CLKOUT_MUX_SHIFT;
 	clkout->mux.lock = &clkout->slock;
 
-	clkout->clk_table[0] = clk_register_composite(NULL, "clkout",
+	clkout->data.hws[0] = clk_hw_register_composite(NULL, "clkout",
 				parent_names, parent_count, &clkout->mux.hw,
 				&clk_mux_ops, NULL, NULL, &clkout->gate.hw,
 				&clk_gate_ops, CLK_SET_RATE_PARENT
 				| CLK_SET_RATE_NO_REPARENT);
-	if (IS_ERR(clkout->clk_table[0]))
+	if (IS_ERR(clkout->data.hws[0]))
 		goto err_unmap;
 
-	clkout->data.clks = clkout->clk_table;
-	clkout->data.clk_num = EXYNOS_CLKOUT_NR_CLKS;
-	ret = of_clk_add_provider(node, of_clk_src_onecell_get, &clkout->data);
+	clkout->data.num = EXYNOS_CLKOUT_NR_CLKS;
+	ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, &clkout->data);
 	if (ret)
 		goto err_clk_unreg;
 
@@ -119,7 +119,7 @@ static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
 	return;
 
 err_clk_unreg:
-	clk_unregister(clkout->clk_table[0]);
+	clk_hw_unregister(clkout->data.hws[0]);
 err_unmap:
 	iounmap(clkout->reg);
 clks_put:

+ 23 - 4
drivers/clk/samsung/clk-exynos5420.c

@@ -487,6 +487,7 @@ PNAME(mout_group12_5800_p)	= { "dout_aclkfl1_550_cam", "dout_sclk_sw" };
 PNAME(mout_group13_5800_p)	= { "dout_osc_div", "mout_sw_aclkfl1_550_cam" };
 PNAME(mout_group14_5800_p)	= { "dout_aclk550_cam", "dout_sclk_sw" };
 PNAME(mout_group15_5800_p)	= { "dout_osc_div", "mout_sw_aclk550_cam" };
+PNAME(mout_group16_5800_p)	= { "dout_osc_div", "mout_mau_epll_clk" };
 
 /* fixed rate clocks generated outside the soc */
 static struct samsung_fixed_rate_clock
@@ -536,8 +537,8 @@ static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = {
 
 	MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore",
 			mout_mx_mspll_ccore_p, SRC_TOP7, 16, 2),
-	MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p, SRC_TOP7,
-			20, 2),
+	MUX(CLK_MOUT_MAU_EPLL, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p,
+							SRC_TOP7, 20, 2),
 	MUX(0, "sclk_bpll", mout_bpll_p, SRC_TOP7, 24, 1),
 	MUX(0, "mout_epll2", mout_epll2_5800_p, SRC_TOP7, 28, 1),
 
@@ -546,6 +547,8 @@ static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = {
 	MUX(0, "mout_aclk432_cam", mout_group6_5800_p, SRC_TOP8, 24, 2),
 	MUX(0, "mout_aclk432_scaler", mout_group6_5800_p, SRC_TOP8, 28, 2),
 
+	MUX(CLK_MOUT_USER_MAU_EPLL, "mout_user_mau_epll", mout_group16_5800_p,
+							SRC_TOP9, 8, 1),
 	MUX(0, "mout_user_aclk550_cam", mout_group15_5800_p,
 							SRC_TOP9, 16, 1),
 	MUX(0, "mout_user_aclkfl1_550_cam", mout_group13_5800_p,
@@ -703,7 +706,7 @@ static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = {
 	MUX(0, "mout_sclk_spll", mout_spll_p, SRC_TOP6, 8, 1),
 	MUX(0, "mout_sclk_ipll", mout_ipll_p, SRC_TOP6, 12, 1),
 	MUX(0, "mout_sclk_rpll", mout_rpll_p, SRC_TOP6, 16, 1),
-	MUX(0, "mout_sclk_epll", mout_epll_p, SRC_TOP6, 20, 1),
+	MUX(CLK_MOUT_EPLL, "mout_sclk_epll", mout_epll_p, SRC_TOP6, 20, 1),
 	MUX(0, "mout_sclk_dpll", mout_dpll_p, SRC_TOP6, 24, 1),
 	MUX(0, "mout_sclk_cpll", mout_cpll_p, SRC_TOP6, 28, 1),
 
@@ -1277,6 +1280,21 @@ static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __ini
 	PLL_35XX_RATE(200000000,  200, 3, 3),
 };
 
+static const struct samsung_pll_rate_table exynos5420_epll_24mhz_tbl[] = {
+	PLL_36XX_RATE(600000000U, 100, 2, 1, 0),
+	PLL_36XX_RATE(400000000U, 200, 3, 2, 0),
+	PLL_36XX_RATE(393216000U, 197, 3, 2, 25690),
+	PLL_36XX_RATE(361267200U, 301, 5, 2, 3671),
+	PLL_36XX_RATE(200000000U, 200, 3, 3, 0),
+	PLL_36XX_RATE(196608000U, 197, 3, 3, -25690),
+	PLL_36XX_RATE(180633600U, 301, 5, 3, 3671),
+	PLL_36XX_RATE(131072000U, 131, 3, 3, 4719),
+	PLL_36XX_RATE(100000000U, 200, 3, 4, 0),
+	PLL_36XX_RATE(65536000U, 131, 3, 4, 4719),
+	PLL_36XX_RATE(49152000U, 197, 3, 5, 25690),
+	PLL_36XX_RATE(32768000U, 131, 3, 5, 4719),
+};
+
 static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
 	[apll] = PLL(pll_2550, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
 		APLL_CON0, NULL),
@@ -1284,7 +1302,7 @@ static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
 		CPLL_CON0, NULL),
 	[dpll] = PLL(pll_2550, CLK_FOUT_DPLL, "fout_dpll", "fin_pll", DPLL_LOCK,
 		DPLL_CON0, NULL),
-	[epll] = PLL(pll_2650, CLK_FOUT_EPLL, "fout_epll", "fin_pll", EPLL_LOCK,
+	[epll] = PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll", EPLL_LOCK,
 		EPLL_CON0, NULL),
 	[rpll] = PLL(pll_2650, CLK_FOUT_RPLL, "fout_rpll", "fin_pll", RPLL_LOCK,
 		RPLL_CON0, NULL),
@@ -1399,6 +1417,7 @@ static void __init exynos5x_clk_init(struct device_node *np,
 
 	if (_get_rate("fin_pll") == 24 * MHZ) {
 		exynos5x_plls[apll].rate_table = exynos5420_pll2550x_24mhz_tbl;
+		exynos5x_plls[epll].rate_table = exynos5420_epll_24mhz_tbl;
 		exynos5x_plls[kpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
 		exynos5x_plls[bpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
 	}

+ 57 - 44
drivers/clk/samsung/clk-pll.c

@@ -23,6 +23,10 @@ struct samsung_clk_pll {
 	struct clk_hw		hw;
 	void __iomem		*lock_reg;
 	void __iomem		*con_reg;
+	/* PLL enable control bit offset in @con_reg register */
+	unsigned short		enable_offs;
+	/* PLL lock status bit offset in @con_reg register */
+	unsigned short		lock_offs;
 	enum samsung_pll_type	type;
 	unsigned int		rate_count;
 	const struct samsung_pll_rate_table *rate_table;
@@ -61,6 +65,34 @@ static long samsung_pll_round_rate(struct clk_hw *hw,
 	return rate_table[i - 1].rate;
 }
 
+static int samsung_pll3xxx_enable(struct clk_hw *hw)
+{
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
+	u32 tmp;
+
+	tmp = readl_relaxed(pll->con_reg);
+	tmp |= BIT(pll->enable_offs);
+	writel_relaxed(tmp, pll->con_reg);
+
+	/* wait lock time */
+	do {
+		cpu_relax();
+		tmp = readl_relaxed(pll->con_reg);
+	} while (!(tmp & BIT(pll->lock_offs)));
+
+	return 0;
+}
+
+static void samsung_pll3xxx_disable(struct clk_hw *hw)
+{
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
+	u32 tmp;
+
+	tmp = readl_relaxed(pll->con_reg);
+	tmp &= ~BIT(pll->enable_offs);
+	writel_relaxed(tmp, pll->con_reg);
+}
+
 /*
  * PLL2126 Clock Type
  */
@@ -142,34 +174,6 @@ static const struct clk_ops samsung_pll3000_clk_ops = {
 #define PLL35XX_LOCK_STAT_SHIFT	(29)
 #define PLL35XX_ENABLE_SHIFT	(31)
 
-static int samsung_pll35xx_enable(struct clk_hw *hw)
-{
-	struct samsung_clk_pll *pll = to_clk_pll(hw);
-	u32 tmp;
-
-	tmp = readl_relaxed(pll->con_reg);
-	tmp |= BIT(PLL35XX_ENABLE_SHIFT);
-	writel_relaxed(tmp, pll->con_reg);
-
-	/* wait_lock_time */
-	do {
-		cpu_relax();
-		tmp = readl_relaxed(pll->con_reg);
-	} while (!(tmp & BIT(PLL35XX_LOCK_STAT_SHIFT)));
-
-	return 0;
-}
-
-static void samsung_pll35xx_disable(struct clk_hw *hw)
-{
-	struct samsung_clk_pll *pll = to_clk_pll(hw);
-	u32 tmp;
-
-	tmp = readl_relaxed(pll->con_reg);
-	tmp &= ~BIT(PLL35XX_ENABLE_SHIFT);
-	writel_relaxed(tmp, pll->con_reg);
-}
-
 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
 				unsigned long parent_rate)
 {
@@ -238,12 +242,12 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
 			(rate->sdiv << PLL35XX_SDIV_SHIFT);
 	writel_relaxed(tmp, pll->con_reg);
 
-	/* wait_lock_time if enabled */
-	if (tmp & BIT(PLL35XX_ENABLE_SHIFT)) {
+	/* Wait until the PLL is locked if it is enabled. */
+	if (tmp & BIT(pll->enable_offs)) {
 		do {
 			cpu_relax();
 			tmp = readl_relaxed(pll->con_reg);
-		} while (!(tmp & BIT(PLL35XX_LOCK_STAT_SHIFT)));
+		} while (!(tmp & BIT(pll->lock_offs)));
 	}
 	return 0;
 }
@@ -252,8 +256,8 @@ static const struct clk_ops samsung_pll35xx_clk_ops = {
 	.recalc_rate = samsung_pll35xx_recalc_rate,
 	.round_rate = samsung_pll_round_rate,
 	.set_rate = samsung_pll35xx_set_rate,
-	.enable = samsung_pll35xx_enable,
-	.disable = samsung_pll35xx_disable,
+	.enable = samsung_pll3xxx_enable,
+	.disable = samsung_pll3xxx_disable,
 };
 
 static const struct clk_ops samsung_pll35xx_clk_min_ops = {
@@ -275,6 +279,7 @@ static const struct clk_ops samsung_pll35xx_clk_min_ops = {
 #define PLL36XX_SDIV_SHIFT	(0)
 #define PLL36XX_KDIV_SHIFT	(0)
 #define PLL36XX_LOCK_STAT_SHIFT	(29)
+#define PLL36XX_ENABLE_SHIFT	(31)
 
 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
 				unsigned long parent_rate)
@@ -354,10 +359,12 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
 	writel_relaxed(pll_con1, pll->con_reg + 4);
 
 	/* wait_lock_time */
-	do {
-		cpu_relax();
-		tmp = readl_relaxed(pll->con_reg);
-	} while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT)));
+	if (pll_con0 & BIT(pll->enable_offs)) {
+		do {
+			cpu_relax();
+			tmp = readl_relaxed(pll->con_reg);
+		} while (!(tmp & BIT(pll->lock_offs)));
+	}
 
 	return 0;
 }
@@ -366,6 +373,8 @@ static const struct clk_ops samsung_pll36xx_clk_ops = {
 	.recalc_rate = samsung_pll36xx_recalc_rate,
 	.set_rate = samsung_pll36xx_set_rate,
 	.round_rate = samsung_pll_round_rate,
+	.enable = samsung_pll3xxx_enable,
+	.disable = samsung_pll3xxx_disable,
 };
 
 static const struct clk_ops samsung_pll36xx_clk_min_ops = {
@@ -1244,7 +1253,6 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
 				void __iomem *base)
 {
 	struct samsung_clk_pll *pll;
-	struct clk *clk;
 	struct clk_init_data init;
 	int ret, len;
 
@@ -1288,6 +1296,8 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
 	case pll_1450x:
 	case pll_1451x:
 	case pll_1452x:
+		pll->enable_offs = PLL35XX_ENABLE_SHIFT;
+		pll->lock_offs = PLL35XX_LOCK_STAT_SHIFT;
 		if (!pll->rate_table)
 			init.ops = &samsung_pll35xx_clk_min_ops;
 		else
@@ -1306,6 +1316,8 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
 	/* clk_ops for 36xx and 2650 are similar */
 	case pll_36xx:
 	case pll_2650:
+		pll->enable_offs = PLL36XX_ENABLE_SHIFT;
+		pll->lock_offs = PLL36XX_LOCK_STAT_SHIFT;
 		if (!pll->rate_table)
 			init.ops = &samsung_pll36xx_clk_min_ops;
 		else
@@ -1376,20 +1388,21 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
 	pll->lock_reg = base + pll_clk->lock_offset;
 	pll->con_reg = base + pll_clk->con_offset;
 
-	clk = clk_register(NULL, &pll->hw);
-	if (IS_ERR(clk)) {
-		pr_err("%s: failed to register pll clock %s : %ld\n",
-			__func__, pll_clk->name, PTR_ERR(clk));
+	ret = clk_hw_register(NULL, &pll->hw);
+	if (ret) {
+		pr_err("%s: failed to register pll clock %s : %d\n",
+			__func__, pll_clk->name, ret);
 		kfree(pll);
 		return;
 	}
 
-	samsung_clk_add_lookup(ctx, clk, pll_clk->id);
+	samsung_clk_add_lookup(ctx, &pll->hw, pll_clk->id);
 
 	if (!pll_clk->alias)
 		return;
 
-	ret = clk_register_clkdev(clk, pll_clk->alias, pll_clk->dev_name);
+	ret = clk_hw_register_clkdev(&pll->hw, pll_clk->alias,
+				     pll_clk->dev_name);
 	if (ret)
 		pr_err("%s: failed to register lookup for %s : %d",
 			__func__, pll_clk->name, ret);

+ 0 - 4
drivers/clk/samsung/clk-pll.h

@@ -103,8 +103,4 @@ struct samsung_pll_rate_table {
 	unsigned int vsel;
 };
 
-extern struct clk * __init samsung_clk_register_pll2550x(const char *name,
-			const char *pname, const void __iomem *reg_base,
-			const unsigned long offset);
-
 #endif /* __SAMSUNG_CLK_PLL_H */

+ 37 - 38
drivers/clk/samsung/clk-s3c2410-dclk.c

@@ -90,13 +90,13 @@ static const struct clk_ops s3c24xx_clkout_ops = {
 	.determine_rate = __clk_mux_determine_rate,
 };
 
-static struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
-		const char **parent_names, u8 num_parents,
+static struct clk_hw *s3c24xx_register_clkout(struct device *dev,
+		const char *name, const char **parent_names, u8 num_parents,
 		u8 shift, u32 mask)
 {
 	struct s3c24xx_clkout *clkout;
-	struct clk *clk;
 	struct clk_init_data init;
+	int ret;
 
 	/* allocate the clkout */
 	clkout = kzalloc(sizeof(*clkout), GFP_KERNEL);
@@ -113,9 +113,11 @@ static struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
 	clkout->mask = mask;
 	clkout->hw.init = &init;
 
-	clk = clk_register(dev, &clkout->hw);
+	ret = clk_hw_register(dev, &clkout->hw);
+	if (ret)
+		return ERR_PTR(ret);
 
-	return clk;
+	return &clkout->hw;
 }
 
 /*
@@ -125,11 +127,12 @@ static struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
 struct s3c24xx_dclk {
 	struct device *dev;
 	void __iomem *base;
-	struct clk_onecell_data clk_data;
 	struct notifier_block dclk0_div_change_nb;
 	struct notifier_block dclk1_div_change_nb;
 	spinlock_t dclk_lock;
 	unsigned long reg_save;
+	/* clk_data must be the last entry in the structure */
+	struct clk_hw_onecell_data clk_data;
 };
 
 #define to_s3c24xx_dclk0(x) \
@@ -240,28 +243,23 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
 {
 	struct s3c24xx_dclk *s3c24xx_dclk;
 	struct resource *mem;
-	struct clk **clk_table;
 	struct s3c24xx_dclk_drv_data *dclk_variant;
+	struct clk_hw **clk_table;
 	int ret, i;
 
-	s3c24xx_dclk = devm_kzalloc(&pdev->dev, sizeof(*s3c24xx_dclk),
-				    GFP_KERNEL);
+	s3c24xx_dclk = devm_kzalloc(&pdev->dev, sizeof(*s3c24xx_dclk) +
+			    sizeof(*s3c24xx_dclk->clk_data.hws) * DCLK_MAX_CLKS,
+			    GFP_KERNEL);
 	if (!s3c24xx_dclk)
 		return -ENOMEM;
 
+	clk_table = s3c24xx_dclk->clk_data.hws;
+
 	s3c24xx_dclk->dev = &pdev->dev;
+	s3c24xx_dclk->clk_data.num = DCLK_MAX_CLKS;
 	platform_set_drvdata(pdev, s3c24xx_dclk);
 	spin_lock_init(&s3c24xx_dclk->dclk_lock);
 
-	clk_table = devm_kzalloc(&pdev->dev,
-				 sizeof(struct clk *) * DCLK_MAX_CLKS,
-				 GFP_KERNEL);
-	if (!clk_table)
-		return -ENOMEM;
-
-	s3c24xx_dclk->clk_data.clks = clk_table;
-	s3c24xx_dclk->clk_data.clk_num = DCLK_MAX_CLKS;
-
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	s3c24xx_dclk->base = devm_ioremap_resource(&pdev->dev, mem);
 	if (IS_ERR(s3c24xx_dclk->base))
@@ -271,29 +269,29 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
 				platform_get_device_id(pdev)->driver_data;
 
 
-	clk_table[MUX_DCLK0] = clk_register_mux(&pdev->dev, "mux_dclk0",
+	clk_table[MUX_DCLK0] = clk_hw_register_mux(&pdev->dev, "mux_dclk0",
 				dclk_variant->mux_parent_names,
 				dclk_variant->mux_num_parents, 0,
 				s3c24xx_dclk->base, 1, 1, 0,
 				&s3c24xx_dclk->dclk_lock);
-	clk_table[MUX_DCLK1] = clk_register_mux(&pdev->dev, "mux_dclk1",
+	clk_table[MUX_DCLK1] = clk_hw_register_mux(&pdev->dev, "mux_dclk1",
 				dclk_variant->mux_parent_names,
 				dclk_variant->mux_num_parents, 0,
 				s3c24xx_dclk->base, 17, 1, 0,
 				&s3c24xx_dclk->dclk_lock);
 
-	clk_table[DIV_DCLK0] = clk_register_divider(&pdev->dev, "div_dclk0",
+	clk_table[DIV_DCLK0] = clk_hw_register_divider(&pdev->dev, "div_dclk0",
 				"mux_dclk0", 0, s3c24xx_dclk->base,
 				4, 4, 0, &s3c24xx_dclk->dclk_lock);
-	clk_table[DIV_DCLK1] = clk_register_divider(&pdev->dev, "div_dclk1",
+	clk_table[DIV_DCLK1] = clk_hw_register_divider(&pdev->dev, "div_dclk1",
 				"mux_dclk1", 0, s3c24xx_dclk->base,
 				20, 4, 0, &s3c24xx_dclk->dclk_lock);
 
-	clk_table[GATE_DCLK0] = clk_register_gate(&pdev->dev, "gate_dclk0",
+	clk_table[GATE_DCLK0] = clk_hw_register_gate(&pdev->dev, "gate_dclk0",
 				"div_dclk0", CLK_SET_RATE_PARENT,
 				s3c24xx_dclk->base, 0, 0,
 				&s3c24xx_dclk->dclk_lock);
-	clk_table[GATE_DCLK1] = clk_register_gate(&pdev->dev, "gate_dclk1",
+	clk_table[GATE_DCLK1] = clk_hw_register_gate(&pdev->dev, "gate_dclk1",
 				"div_dclk1", CLK_SET_RATE_PARENT,
 				s3c24xx_dclk->base, 16, 0,
 				&s3c24xx_dclk->dclk_lock);
@@ -312,15 +310,16 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
 			goto err_clk_register;
 		}
 
-	ret = clk_register_clkdev(clk_table[MUX_DCLK0], "dclk0", NULL);
+	ret = clk_hw_register_clkdev(clk_table[MUX_DCLK0], "dclk0", NULL);
 	if (!ret)
-		ret = clk_register_clkdev(clk_table[MUX_DCLK1], "dclk1", NULL);
+		ret = clk_hw_register_clkdev(clk_table[MUX_DCLK1], "dclk1",
+					     NULL);
 	if (!ret)
-		ret = clk_register_clkdev(clk_table[MUX_CLKOUT0],
-					  "clkout0", NULL);
+		ret = clk_hw_register_clkdev(clk_table[MUX_CLKOUT0],
+					     "clkout0", NULL);
 	if (!ret)
-		ret = clk_register_clkdev(clk_table[MUX_CLKOUT1],
-					  "clkout1", NULL);
+		ret = clk_hw_register_clkdev(clk_table[MUX_CLKOUT1],
+					     "clkout1", NULL);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register aliases, %d\n", ret);
 		goto err_clk_register;
@@ -332,12 +331,12 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
 	s3c24xx_dclk->dclk1_div_change_nb.notifier_call =
 						s3c24xx_dclk1_div_notify;
 
-	ret = clk_notifier_register(clk_table[DIV_DCLK0],
+	ret = clk_notifier_register(clk_table[DIV_DCLK0]->clk,
 				    &s3c24xx_dclk->dclk0_div_change_nb);
 	if (ret)
 		goto err_clk_register;
 
-	ret = clk_notifier_register(clk_table[DIV_DCLK1],
+	ret = clk_notifier_register(clk_table[DIV_DCLK1]->clk,
 				    &s3c24xx_dclk->dclk1_div_change_nb);
 	if (ret)
 		goto err_dclk_notify;
@@ -345,12 +344,12 @@ static int s3c24xx_dclk_probe(struct platform_device *pdev)
 	return 0;
 
 err_dclk_notify:
-	clk_notifier_unregister(clk_table[DIV_DCLK0],
+	clk_notifier_unregister(clk_table[DIV_DCLK0]->clk,
 				&s3c24xx_dclk->dclk0_div_change_nb);
 err_clk_register:
 	for (i = 0; i < DCLK_MAX_CLKS; i++)
 		if (clk_table[i] && !IS_ERR(clk_table[i]))
-			clk_unregister(clk_table[i]);
+			clk_hw_unregister(clk_table[i]);
 
 	return ret;
 }
@@ -358,16 +357,16 @@ err_clk_register:
 static int s3c24xx_dclk_remove(struct platform_device *pdev)
 {
 	struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev);
-	struct clk **clk_table = s3c24xx_dclk->clk_data.clks;
+	struct clk_hw **clk_table = s3c24xx_dclk->clk_data.hws;
 	int i;
 
-	clk_notifier_unregister(clk_table[DIV_DCLK1],
+	clk_notifier_unregister(clk_table[DIV_DCLK1]->clk,
 				&s3c24xx_dclk->dclk1_div_change_nb);
-	clk_notifier_unregister(clk_table[DIV_DCLK0],
+	clk_notifier_unregister(clk_table[DIV_DCLK0]->clk,
 				&s3c24xx_dclk->dclk0_div_change_nb);
 
 	for (i = 0; i < DCLK_MAX_CLKS; i++)
-		clk_unregister(clk_table[i]);
+		clk_hw_unregister(clk_table[i]);
 
 	return 0;
 }

+ 27 - 25
drivers/clk/samsung/clk-s5pv210-audss.c

@@ -24,9 +24,8 @@
 #include <dt-bindings/clock/s5pv210-audss.h>
 
 static DEFINE_SPINLOCK(lock);
-static struct clk **clk_table;
 static void __iomem *reg_base;
-static struct clk_onecell_data clk_data;
+static struct clk_hw_onecell_data *clk_data;
 
 #define ASS_CLK_SRC 0x0
 #define ASS_CLK_DIV 0x4
@@ -71,6 +70,7 @@ static int s5pv210_audss_clk_probe(struct platform_device *pdev)
 	const char *mout_audss_p[2];
 	const char *mout_i2s_p[3];
 	const char *hclk_p;
+	struct clk_hw **clk_table;
 	struct clk *hclk, *pll_ref, *pll_in, *cdclk, *sclk_audio;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -80,14 +80,16 @@ static int s5pv210_audss_clk_probe(struct platform_device *pdev)
 		return PTR_ERR(reg_base);
 	}
 
-	clk_table = devm_kzalloc(&pdev->dev,
-				sizeof(struct clk *) * AUDSS_MAX_CLKS,
+	clk_data = devm_kzalloc(&pdev->dev,
+				sizeof(*clk_data) +
+				sizeof(*clk_data->hws) * AUDSS_MAX_CLKS,
 				GFP_KERNEL);
-	if (!clk_table)
+
+	if (!clk_data)
 		return -ENOMEM;
 
-	clk_data.clks = clk_table;
-	clk_data.clk_num = AUDSS_MAX_CLKS;
+	clk_data->num = AUDSS_MAX_CLKS;
+	clk_table = clk_data->hws;
 
 	hclk = devm_clk_get(&pdev->dev, "hclk");
 	if (IS_ERR(hclk)) {
@@ -116,7 +118,7 @@ static int s5pv210_audss_clk_probe(struct platform_device *pdev)
 	else
 		mout_audss_p[0] = "xxti";
 	mout_audss_p[1] = __clk_get_name(pll_in);
-	clk_table[CLK_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
+	clk_table[CLK_MOUT_AUDSS] = clk_hw_register_mux(NULL, "mout_audss",
 				mout_audss_p, ARRAY_SIZE(mout_audss_p),
 				CLK_SET_RATE_NO_REPARENT,
 				reg_base + ASS_CLK_SRC, 0, 1, 0, &lock);
@@ -127,44 +129,44 @@ static int s5pv210_audss_clk_probe(struct platform_device *pdev)
 	else
 		mout_i2s_p[1] = "iiscdclk0";
 	mout_i2s_p[2] = __clk_get_name(sclk_audio);
-	clk_table[CLK_MOUT_I2S_A] = clk_register_mux(NULL, "mout_i2s_audss",
+	clk_table[CLK_MOUT_I2S_A] = clk_hw_register_mux(NULL, "mout_i2s_audss",
 				mout_i2s_p, ARRAY_SIZE(mout_i2s_p),
 				CLK_SET_RATE_NO_REPARENT,
 				reg_base + ASS_CLK_SRC, 2, 2, 0, &lock);
 
-	clk_table[CLK_DOUT_AUD_BUS] = clk_register_divider(NULL,
+	clk_table[CLK_DOUT_AUD_BUS] = clk_hw_register_divider(NULL,
 				"dout_aud_bus", "mout_audss", 0,
 				reg_base + ASS_CLK_DIV, 0, 4, 0, &lock);
-	clk_table[CLK_DOUT_I2S_A] = clk_register_divider(NULL, "dout_i2s_audss",
-				"mout_i2s_audss", 0, reg_base + ASS_CLK_DIV,
-				4, 4, 0, &lock);
+	clk_table[CLK_DOUT_I2S_A] = clk_hw_register_divider(NULL,
+				"dout_i2s_audss", "mout_i2s_audss", 0,
+				reg_base + ASS_CLK_DIV, 4, 4, 0, &lock);
 
-	clk_table[CLK_I2S] = clk_register_gate(NULL, "i2s_audss",
+	clk_table[CLK_I2S] = clk_hw_register_gate(NULL, "i2s_audss",
 				"dout_i2s_audss", CLK_SET_RATE_PARENT,
 				reg_base + ASS_CLK_GATE, 6, 0, &lock);
 
 	hclk_p = __clk_get_name(hclk);
 
-	clk_table[CLK_HCLK_I2S] = clk_register_gate(NULL, "hclk_i2s_audss",
+	clk_table[CLK_HCLK_I2S] = clk_hw_register_gate(NULL, "hclk_i2s_audss",
 				hclk_p, CLK_IGNORE_UNUSED,
 				reg_base + ASS_CLK_GATE, 5, 0, &lock);
-	clk_table[CLK_HCLK_UART] = clk_register_gate(NULL, "hclk_uart_audss",
+	clk_table[CLK_HCLK_UART] = clk_hw_register_gate(NULL, "hclk_uart_audss",
 				hclk_p, CLK_IGNORE_UNUSED,
 				reg_base + ASS_CLK_GATE, 4, 0, &lock);
-	clk_table[CLK_HCLK_HWA] = clk_register_gate(NULL, "hclk_hwa_audss",
+	clk_table[CLK_HCLK_HWA] = clk_hw_register_gate(NULL, "hclk_hwa_audss",
 				hclk_p, CLK_IGNORE_UNUSED,
 				reg_base + ASS_CLK_GATE, 3, 0, &lock);
-	clk_table[CLK_HCLK_DMA] = clk_register_gate(NULL, "hclk_dma_audss",
+	clk_table[CLK_HCLK_DMA] = clk_hw_register_gate(NULL, "hclk_dma_audss",
 				hclk_p, CLK_IGNORE_UNUSED,
 				reg_base + ASS_CLK_GATE, 2, 0, &lock);
-	clk_table[CLK_HCLK_BUF] = clk_register_gate(NULL, "hclk_buf_audss",
+	clk_table[CLK_HCLK_BUF] = clk_hw_register_gate(NULL, "hclk_buf_audss",
 				hclk_p, CLK_IGNORE_UNUSED,
 				reg_base + ASS_CLK_GATE, 1, 0, &lock);
-	clk_table[CLK_HCLK_RP] = clk_register_gate(NULL, "hclk_rp_audss",
+	clk_table[CLK_HCLK_RP] = clk_hw_register_gate(NULL, "hclk_rp_audss",
 				hclk_p, CLK_IGNORE_UNUSED,
 				reg_base + ASS_CLK_GATE, 0, 0, &lock);
 
-	for (i = 0; i < clk_data.clk_num; i++) {
+	for (i = 0; i < clk_data->num; i++) {
 		if (IS_ERR(clk_table[i])) {
 			dev_err(&pdev->dev, "failed to register clock %d\n", i);
 			ret = PTR_ERR(clk_table[i]);
@@ -172,8 +174,8 @@ static int s5pv210_audss_clk_probe(struct platform_device *pdev)
 		}
 	}
 
-	ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
-					&clk_data);
+	ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get,
+				     clk_data);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add clock provider\n");
 		goto unregister;
@@ -186,9 +188,9 @@ static int s5pv210_audss_clk_probe(struct platform_device *pdev)
 	return 0;
 
 unregister:
-	for (i = 0; i < clk_data.clk_num; i++) {
+	for (i = 0; i < clk_data->num; i++) {
 		if (!IS_ERR(clk_table[i]))
-			clk_unregister(clk_table[i]);
+			clk_hw_unregister(clk_table[i]);
 	}
 
 	return ret;

+ 41 - 50
drivers/clk/samsung/clk.c

@@ -60,23 +60,18 @@ struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np,
 			void __iomem *base, unsigned long nr_clks)
 {
 	struct samsung_clk_provider *ctx;
-	struct clk **clk_table;
 	int i;
 
-	ctx = kzalloc(sizeof(struct samsung_clk_provider), GFP_KERNEL);
+	ctx = kzalloc(sizeof(struct samsung_clk_provider) +
+		      sizeof(*ctx->clk_data.hws) * nr_clks, GFP_KERNEL);
 	if (!ctx)
 		panic("could not allocate clock provider context.\n");
 
-	clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
-	if (!clk_table)
-		panic("could not allocate clock lookup table\n");
-
 	for (i = 0; i < nr_clks; ++i)
-		clk_table[i] = ERR_PTR(-ENOENT);
+		ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
 
 	ctx->reg_base = base;
-	ctx->clk_data.clks = clk_table;
-	ctx->clk_data.clk_num = nr_clks;
+	ctx->clk_data.num = nr_clks;
 	spin_lock_init(&ctx->lock);
 
 	return ctx;
@@ -86,18 +81,18 @@ void __init samsung_clk_of_add_provider(struct device_node *np,
 				struct samsung_clk_provider *ctx)
 {
 	if (np) {
-		if (of_clk_add_provider(np, of_clk_src_onecell_get,
+		if (of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
 					&ctx->clk_data))
 			panic("could not register clk provider\n");
 	}
 }
 
 /* add a clock instance to the clock lookup table used for dt based lookup */
-void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk,
-				unsigned int id)
+void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
+			    struct clk_hw *clk_hw, unsigned int id)
 {
-	if (ctx->clk_data.clks && id)
-		ctx->clk_data.clks[id] = clk;
+	if (id)
+		ctx->clk_data.hws[id] = clk_hw;
 }
 
 /* register a list of aliases */
@@ -105,14 +100,9 @@ void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
 				const struct samsung_clock_alias *list,
 				unsigned int nr_clk)
 {
-	struct clk *clk;
+	struct clk_hw *clk_hw;
 	unsigned int idx, ret;
 
-	if (!ctx->clk_data.clks) {
-		pr_err("%s: clock table missing\n", __func__);
-		return;
-	}
-
 	for (idx = 0; idx < nr_clk; idx++, list++) {
 		if (!list->id) {
 			pr_err("%s: clock id missing for index %d\n", __func__,
@@ -120,14 +110,15 @@ void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
 			continue;
 		}
 
-		clk = ctx->clk_data.clks[list->id];
-		if (!clk) {
+		clk_hw = ctx->clk_data.hws[list->id];
+		if (!clk_hw) {
 			pr_err("%s: failed to find clock %d\n", __func__,
 				list->id);
 			continue;
 		}
 
-		ret = clk_register_clkdev(clk, list->alias, list->dev_name);
+		ret = clk_hw_register_clkdev(clk_hw, list->alias,
+					     list->dev_name);
 		if (ret)
 			pr_err("%s: failed to register lookup %s\n",
 					__func__, list->alias);
@@ -139,25 +130,25 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
 		const struct samsung_fixed_rate_clock *list,
 		unsigned int nr_clk)
 {
-	struct clk *clk;
+	struct clk_hw *clk_hw;
 	unsigned int idx, ret;
 
 	for (idx = 0; idx < nr_clk; idx++, list++) {
-		clk = clk_register_fixed_rate(NULL, list->name,
+		clk_hw = clk_hw_register_fixed_rate(NULL, list->name,
 			list->parent_name, list->flags, list->fixed_rate);
-		if (IS_ERR(clk)) {
+		if (IS_ERR(clk_hw)) {
 			pr_err("%s: failed to register clock %s\n", __func__,
 				list->name);
 			continue;
 		}
 
-		samsung_clk_add_lookup(ctx, clk, list->id);
+		samsung_clk_add_lookup(ctx, clk_hw, list->id);
 
 		/*
 		 * Unconditionally add a clock lookup for the fixed rate clocks.
 		 * There are not many of these on any of Samsung platforms.
 		 */
-		ret = clk_register_clkdev(clk, list->name, NULL);
+		ret = clk_hw_register_clkdev(clk_hw, list->name, NULL);
 		if (ret)
 			pr_err("%s: failed to register clock lookup for %s",
 				__func__, list->name);
@@ -168,19 +159,19 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
 void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
 		const struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
 {
-	struct clk *clk;
+	struct clk_hw *clk_hw;
 	unsigned int idx;
 
 	for (idx = 0; idx < nr_clk; idx++, list++) {
-		clk = clk_register_fixed_factor(NULL, list->name,
+		clk_hw = clk_hw_register_fixed_factor(NULL, list->name,
 			list->parent_name, list->flags, list->mult, list->div);
-		if (IS_ERR(clk)) {
+		if (IS_ERR(clk_hw)) {
 			pr_err("%s: failed to register clock %s\n", __func__,
 				list->name);
 			continue;
 		}
 
-		samsung_clk_add_lookup(ctx, clk, list->id);
+		samsung_clk_add_lookup(ctx, clk_hw, list->id);
 	}
 }
 
@@ -189,25 +180,25 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
 				const struct samsung_mux_clock *list,
 				unsigned int nr_clk)
 {
-	struct clk *clk;
+	struct clk_hw *clk_hw;
 	unsigned int idx, ret;
 
 	for (idx = 0; idx < nr_clk; idx++, list++) {
-		clk = clk_register_mux(NULL, list->name, list->parent_names,
-			list->num_parents, list->flags,
+		clk_hw = clk_hw_register_mux(NULL, list->name,
+			list->parent_names, list->num_parents, list->flags,
 			ctx->reg_base + list->offset,
 			list->shift, list->width, list->mux_flags, &ctx->lock);
-		if (IS_ERR(clk)) {
+		if (IS_ERR(clk_hw)) {
 			pr_err("%s: failed to register clock %s\n", __func__,
 				list->name);
 			continue;
 		}
 
-		samsung_clk_add_lookup(ctx, clk, list->id);
+		samsung_clk_add_lookup(ctx, clk_hw, list->id);
 
 		/* register a clock lookup only if a clock alias is specified */
 		if (list->alias) {
-			ret = clk_register_clkdev(clk, list->alias,
+			ret = clk_hw_register_clkdev(clk_hw, list->alias,
 						list->dev_name);
 			if (ret)
 				pr_err("%s: failed to register lookup %s\n",
@@ -221,32 +212,32 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
 				const struct samsung_div_clock *list,
 				unsigned int nr_clk)
 {
-	struct clk *clk;
+	struct clk_hw *clk_hw;
 	unsigned int idx, ret;
 
 	for (idx = 0; idx < nr_clk; idx++, list++) {
 		if (list->table)
-			clk = clk_register_divider_table(NULL, list->name,
-				list->parent_name, list->flags,
+			clk_hw = clk_hw_register_divider_table(NULL,
+				list->name, list->parent_name, list->flags,
 				ctx->reg_base + list->offset,
 				list->shift, list->width, list->div_flags,
 				list->table, &ctx->lock);
 		else
-			clk = clk_register_divider(NULL, list->name,
+			clk_hw = clk_hw_register_divider(NULL, list->name,
 				list->parent_name, list->flags,
 				ctx->reg_base + list->offset, list->shift,
 				list->width, list->div_flags, &ctx->lock);
-		if (IS_ERR(clk)) {
+		if (IS_ERR(clk_hw)) {
 			pr_err("%s: failed to register clock %s\n", __func__,
 				list->name);
 			continue;
 		}
 
-		samsung_clk_add_lookup(ctx, clk, list->id);
+		samsung_clk_add_lookup(ctx, clk_hw, list->id);
 
 		/* register a clock lookup only if a clock alias is specified */
 		if (list->alias) {
-			ret = clk_register_clkdev(clk, list->alias,
+			ret = clk_hw_register_clkdev(clk_hw, list->alias,
 						list->dev_name);
 			if (ret)
 				pr_err("%s: failed to register lookup %s\n",
@@ -260,14 +251,14 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
 				const struct samsung_gate_clock *list,
 				unsigned int nr_clk)
 {
-	struct clk *clk;
+	struct clk_hw *clk_hw;
 	unsigned int idx, ret;
 
 	for (idx = 0; idx < nr_clk; idx++, list++) {
-		clk = clk_register_gate(NULL, list->name, list->parent_name,
+		clk_hw = clk_hw_register_gate(NULL, list->name, list->parent_name,
 				list->flags, ctx->reg_base + list->offset,
 				list->bit_idx, list->gate_flags, &ctx->lock);
-		if (IS_ERR(clk)) {
+		if (IS_ERR(clk_hw)) {
 			pr_err("%s: failed to register clock %s\n", __func__,
 				list->name);
 			continue;
@@ -275,14 +266,14 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
 
 		/* register a clock lookup only if a clock alias is specified */
 		if (list->alias) {
-			ret = clk_register_clkdev(clk, list->alias,
+			ret = clk_hw_register_clkdev(clk_hw, list->alias,
 							list->dev_name);
 			if (ret)
 				pr_err("%s: failed to register lookup %s\n",
 					__func__, list->alias);
 		}
 
-		samsung_clk_add_lookup(ctx, clk, list->id);
+		samsung_clk_add_lookup(ctx, clk_hw, list->id);
 	}
 }
 

+ 4 - 5
drivers/clk/samsung/clk.h

@@ -16,18 +16,17 @@
 #include <linux/clk-provider.h>
 #include "clk-pll.h"
 
-struct clk;
-
 /**
  * struct samsung_clk_provider: information about clock provider
  * @reg_base: virtual address for the register base.
- * @clk_data: holds clock related data like clk* and number of clocks.
  * @lock: maintains exclusion between callbacks for a given clock-provider.
+ * @clk_data: holds clock related data like clk_hw* and number of clocks.
  */
 struct samsung_clk_provider {
 	void __iomem *reg_base;
-	struct clk_onecell_data clk_data;
 	spinlock_t lock;
+	/* clk_data must be the last entry due to variable lenght 'hws' array */
+	struct clk_hw_onecell_data clk_data;
 };
 
 /**
@@ -367,7 +366,7 @@ extern void __init samsung_clk_of_register_fixed_ext(
 			const struct of_device_id *clk_matches);
 
 extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
-			struct clk *clk, unsigned int id);
+			struct clk_hw *clk_hw, unsigned int id);
 
 extern void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
 			const struct samsung_clock_alias *list,

+ 1 - 1
drivers/clk/socfpga/clk-gate-a10.c

@@ -86,7 +86,7 @@ static int socfpga_clk_prepare(struct clk_hw *hwclk)
 			}
 		}
 
-		hs_timing = SYSMGR_SDMMC_CTRL_SET(clk_phase[0], clk_phase[1]);
+		hs_timing = SYSMGR_SDMMC_CTRL_SET_AS10(clk_phase[0], clk_phase[1]);
 		if (!IS_ERR(socfpgaclk->sys_mgr_base_addr))
 			regmap_write(socfpgaclk->sys_mgr_base_addr,
 				     SYSMGR_SDMMCGRP_CTRL_OFFSET, hs_timing);

+ 3 - 0
drivers/clk/socfpga/clk.h

@@ -32,6 +32,9 @@
 #define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \
 	((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0))
 
+#define SYSMGR_SDMMC_CTRL_SET_AS10(smplsel, drvsel) \
+	((((smplsel) & 0x7) << 4) | (((drvsel) & 0x7) << 0))
+
 extern void __iomem *clk_mgr_base_addr;
 extern void __iomem *clk_mgr_a10_base_addr;
 

+ 7 - 109
drivers/clk/sunxi-ng/Kconfig

@@ -6,157 +6,55 @@ config SUNXI_CCU
 
 if SUNXI_CCU
 
-# Base clock types
-
-config SUNXI_CCU_DIV
-	bool
-	select SUNXI_CCU_MUX
-
-config SUNXI_CCU_FRAC
-	bool
-
-config SUNXI_CCU_GATE
-	def_bool y
-
-config SUNXI_CCU_MUX
-	bool
-
-config SUNXI_CCU_MULT
-	bool
-	select SUNXI_CCU_MUX
-
-config SUNXI_CCU_PHASE
-	bool
-
-# Multi-factor clocks
-
-config SUNXI_CCU_NK
-	bool
-	select SUNXI_CCU_GATE
-
-config SUNXI_CCU_NKM
-	bool
-	select SUNXI_CCU_GATE
-
-config SUNXI_CCU_NKMP
-	bool
-	select SUNXI_CCU_GATE
-
-config SUNXI_CCU_NM
-	bool
-	select SUNXI_CCU_FRAC
-	select SUNXI_CCU_GATE
-
-config SUNXI_CCU_MP
-	bool
-	select SUNXI_CCU_GATE
-	select SUNXI_CCU_MUX
-
-# SoC Drivers
-
 config SUN50I_A64_CCU
 	bool "Support for the Allwinner A64 CCU"
-	select SUNXI_CCU_DIV
-	select SUNXI_CCU_NK
-	select SUNXI_CCU_NKM
-	select SUNXI_CCU_NKMP
-	select SUNXI_CCU_NM
-	select SUNXI_CCU_MP
-	select SUNXI_CCU_PHASE
 	default ARM64 && ARCH_SUNXI
 	depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
 
 config SUN5I_CCU
 	bool "Support for the Allwinner sun5i family CCM"
-	select SUNXI_CCU_DIV
-	select SUNXI_CCU_MULT
-	select SUNXI_CCU_NK
-	select SUNXI_CCU_NKM
-	select SUNXI_CCU_NM
-	select SUNXI_CCU_MP
-	select SUNXI_CCU_PHASE
 	default MACH_SUN5I
 	depends on MACH_SUN5I || COMPILE_TEST
 
 config SUN6I_A31_CCU
 	bool "Support for the Allwinner A31/A31s CCU"
-	select SUNXI_CCU_DIV
-	select SUNXI_CCU_NK
-	select SUNXI_CCU_NKM
-	select SUNXI_CCU_NKMP
-	select SUNXI_CCU_NM
-	select SUNXI_CCU_MP
-	select SUNXI_CCU_PHASE
 	default MACH_SUN6I
 	depends on MACH_SUN6I || COMPILE_TEST
 
 config SUN8I_A23_CCU
 	bool "Support for the Allwinner A23 CCU"
-	select SUNXI_CCU_DIV
-	select SUNXI_CCU_MULT
-	select SUNXI_CCU_NK
-	select SUNXI_CCU_NKM
-	select SUNXI_CCU_NKMP
-	select SUNXI_CCU_NM
-	select SUNXI_CCU_MP
-	select SUNXI_CCU_PHASE
 	default MACH_SUN8I
 	depends on MACH_SUN8I || COMPILE_TEST
 
 config SUN8I_A33_CCU
 	bool "Support for the Allwinner A33 CCU"
-	select SUNXI_CCU_DIV
-	select SUNXI_CCU_MULT
-	select SUNXI_CCU_NK
-	select SUNXI_CCU_NKM
-	select SUNXI_CCU_NKMP
-	select SUNXI_CCU_NM
-	select SUNXI_CCU_MP
-	select SUNXI_CCU_PHASE
 	default MACH_SUN8I
 	depends on MACH_SUN8I || COMPILE_TEST
 
+config SUN8I_A83T_CCU
+	bool "Support for the Allwinner A83T CCU"
+	default MACH_SUN8I
+
 config SUN8I_H3_CCU
 	bool "Support for the Allwinner H3 CCU"
-	select SUNXI_CCU_DIV
-	select SUNXI_CCU_NK
-	select SUNXI_CCU_NKM
-	select SUNXI_CCU_NKMP
-	select SUNXI_CCU_NM
-	select SUNXI_CCU_MP
-	select SUNXI_CCU_PHASE
 	default MACH_SUN8I || (ARM64 && ARCH_SUNXI)
 	depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST
 
 config SUN8I_V3S_CCU
 	bool "Support for the Allwinner V3s CCU"
-	select SUNXI_CCU_DIV
-	select SUNXI_CCU_NK
-	select SUNXI_CCU_NKM
-	select SUNXI_CCU_NKMP
-	select SUNXI_CCU_NM
-	select SUNXI_CCU_MP
-	select SUNXI_CCU_PHASE
 	default MACH_SUN8I
 	depends on MACH_SUN8I || COMPILE_TEST
 
+config SUN8I_DE2_CCU
+	bool "Support for the Allwinner SoCs DE2 CCU"
+
 config SUN9I_A80_CCU
 	bool "Support for the Allwinner A80 CCU"
-	select SUNXI_CCU_DIV
-	select SUNXI_CCU_MULT
-	select SUNXI_CCU_GATE
-	select SUNXI_CCU_NKMP
-	select SUNXI_CCU_NM
-	select SUNXI_CCU_MP
-	select SUNXI_CCU_PHASE
 	default MACH_SUN9I
 	depends on MACH_SUN9I || COMPILE_TEST
 
 config SUN8I_R_CCU
 	bool "Support for Allwinner SoCs' PRCM CCUs"
-	select SUNXI_CCU_DIV
-	select SUNXI_CCU_GATE
-	select SUNXI_CCU_MP
 	default MACH_SUN8I || (ARCH_SUNXI && ARM64)
 
 endif

+ 24 - 13
drivers/clk/sunxi-ng/Makefile

@@ -1,21 +1,21 @@
 # Common objects
-obj-$(CONFIG_SUNXI_CCU)		+= ccu_common.o
-obj-$(CONFIG_SUNXI_CCU)		+= ccu_reset.o
+lib-$(CONFIG_SUNXI_CCU)		+= ccu_common.o
+lib-$(CONFIG_SUNXI_CCU)		+= ccu_reset.o
 
 # Base clock types
-obj-$(CONFIG_SUNXI_CCU_DIV)	+= ccu_div.o
-obj-$(CONFIG_SUNXI_CCU_FRAC)	+= ccu_frac.o
-obj-$(CONFIG_SUNXI_CCU_GATE)	+= ccu_gate.o
-obj-$(CONFIG_SUNXI_CCU_MUX)	+= ccu_mux.o
-obj-$(CONFIG_SUNXI_CCU_MULT)	+= ccu_mult.o
-obj-$(CONFIG_SUNXI_CCU_PHASE)	+= ccu_phase.o
+lib-$(CONFIG_SUNXI_CCU)		+= ccu_div.o
+lib-$(CONFIG_SUNXI_CCU)		+= ccu_frac.o
+lib-$(CONFIG_SUNXI_CCU)		+= ccu_gate.o
+lib-$(CONFIG_SUNXI_CCU)		+= ccu_mux.o
+lib-$(CONFIG_SUNXI_CCU)		+= ccu_mult.o
+lib-$(CONFIG_SUNXI_CCU)		+= ccu_phase.o
 
 # Multi-factor clocks
-obj-$(CONFIG_SUNXI_CCU_NK)	+= ccu_nk.o
-obj-$(CONFIG_SUNXI_CCU_NKM)	+= ccu_nkm.o
-obj-$(CONFIG_SUNXI_CCU_NKMP)	+= ccu_nkmp.o
-obj-$(CONFIG_SUNXI_CCU_NM)	+= ccu_nm.o
-obj-$(CONFIG_SUNXI_CCU_MP)	+= ccu_mp.o
+lib-$(CONFIG_SUNXI_CCU)		+= ccu_nk.o
+lib-$(CONFIG_SUNXI_CCU)		+= ccu_nkm.o
+lib-$(CONFIG_SUNXI_CCU)		+= ccu_nkmp.o
+lib-$(CONFIG_SUNXI_CCU)		+= ccu_nm.o
+lib-$(CONFIG_SUNXI_CCU)		+= ccu_mp.o
 
 # SoC support
 obj-$(CONFIG_SUN50I_A64_CCU)	+= ccu-sun50i-a64.o
@@ -23,9 +23,20 @@ obj-$(CONFIG_SUN5I_CCU)		+= ccu-sun5i.o
 obj-$(CONFIG_SUN6I_A31_CCU)	+= ccu-sun6i-a31.o
 obj-$(CONFIG_SUN8I_A23_CCU)	+= ccu-sun8i-a23.o
 obj-$(CONFIG_SUN8I_A33_CCU)	+= ccu-sun8i-a33.o
+obj-$(CONFIG_SUN8I_A83T_CCU)	+= ccu-sun8i-a83t.o
 obj-$(CONFIG_SUN8I_H3_CCU)	+= ccu-sun8i-h3.o
 obj-$(CONFIG_SUN8I_V3S_CCU)	+= ccu-sun8i-v3s.o
+obj-$(CONFIG_SUN8I_DE2_CCU)	+= ccu-sun8i-de2.o
 obj-$(CONFIG_SUN8I_R_CCU)	+= ccu-sun8i-r.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80-de.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80-usb.o
+
+# The lib-y file goals is supposed to work only in arch/*/lib or lib/. In our
+# case, we want to use that goal, but even though lib.a will be properly
+# generated, it will not be linked in, eventually resulting in a linker error
+# for missing symbols.
+#
+# We can work around that by explicitly adding lib.a to the obj-y goal. This is
+# an undocumented behaviour, but works well for now.
+obj-$(CONFIG_SUNXI_CCU)		+= lib.a

+ 5 - 5
drivers/clk/sunxi-ng/ccu-sun50i-a64.c

@@ -211,6 +211,9 @@ static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0);
 
 static const char * const ahb1_parents[] = { "osc32k", "osc24M",
 					     "axi", "pll-periph0" };
+static const struct ccu_mux_var_prediv ahb1_predivs[] = {
+	{ .index = 3, .shift = 6, .width = 2 },
+};
 static struct ccu_div ahb1_clk = {
 	.div		= _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
 
@@ -218,11 +221,8 @@ static struct ccu_div ahb1_clk = {
 		.shift	= 12,
 		.width	= 2,
 
-		.variable_prediv	= {
-			.index	= 3,
-			.shift	= 6,
-			.width	= 2,
-		},
+		.var_predivs	= ahb1_predivs,
+		.n_var_predivs	= ARRAY_SIZE(ahb1_predivs),
 	},
 
 	.common		= {

+ 4 - 2
drivers/clk/sunxi-ng/ccu-sun5i.h

@@ -28,15 +28,17 @@
 #define CLK_PLL_AUDIO_4X	6
 #define CLK_PLL_AUDIO_8X	7
 #define CLK_PLL_VIDEO0		8
-#define CLK_PLL_VIDEO0_2X	9
+
+/* The PLL_VIDEO0_2X is exported for HDMI */
+
 #define CLK_PLL_VE		10
 #define CLK_PLL_DDR_BASE	11
 #define CLK_PLL_DDR		12
 #define CLK_PLL_DDR_OTHER	13
 #define CLK_PLL_PERIPH		14
 #define CLK_PLL_VIDEO1		15
-#define CLK_PLL_VIDEO1_2X	16
 
+/* The PLL_VIDEO1_2X is exported for HDMI */
 /* The CPU clock is exported */
 
 #define CLK_AXI			18

+ 5 - 5
drivers/clk/sunxi-ng/ccu-sun6i-a31.c

@@ -195,6 +195,9 @@ static SUNXI_CCU_DIV_TABLE(axi_clk, "axi", "cpu",
 
 static const char * const ahb1_parents[] = { "osc32k", "osc24M",
 					     "axi", "pll-periph" };
+static const struct ccu_mux_var_prediv ahb1_predivs[] = {
+	{ .index = 3, .shift = 6, .width = 2 },
+};
 
 static struct ccu_div ahb1_clk = {
 	.div		= _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
@@ -203,11 +206,8 @@ static struct ccu_div ahb1_clk = {
 		.shift	= 12,
 		.width	= 2,
 
-		.variable_prediv	= {
-			.index	= 3,
-			.shift	= 6,
-			.width	= 2,
-		},
+		.var_predivs	= ahb1_predivs,
+		.n_var_predivs	= ARRAY_SIZE(ahb1_predivs),
 	},
 
 	.common		= {

+ 5 - 5
drivers/clk/sunxi-ng/ccu-sun8i-a23.c

@@ -169,6 +169,9 @@ static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0);
 
 static const char * const ahb1_parents[] = { "osc32k", "osc24M",
 					     "axi" , "pll-periph" };
+static const struct ccu_mux_var_prediv ahb1_predivs[] = {
+	{ .index = 3, .shift = 6, .width = 2 },
+};
 static struct ccu_div ahb1_clk = {
 	.div		= _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
 
@@ -176,11 +179,8 @@ static struct ccu_div ahb1_clk = {
 		.shift	= 12,
 		.width	= 2,
 
-		.variable_prediv	= {
-			.index	= 3,
-			.shift	= 6,
-			.width	= 2,
-		},
+		.var_predivs	= ahb1_predivs,
+		.n_var_predivs	= ARRAY_SIZE(ahb1_predivs),
 	},
 
 	.common		= {

+ 5 - 5
drivers/clk/sunxi-ng/ccu-sun8i-a33.c

@@ -180,6 +180,9 @@ static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0);
 
 static const char * const ahb1_parents[] = { "osc32k", "osc24M",
 					     "axi" , "pll-periph" };
+static const struct ccu_mux_var_prediv ahb1_predivs[] = {
+	{ .index = 3, .shift = 6, .width = 2 },
+};
 static struct ccu_div ahb1_clk = {
 	.div		= _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
 
@@ -187,11 +190,8 @@ static struct ccu_div ahb1_clk = {
 		.shift	= 12,
 		.width	= 2,
 
-		.variable_prediv	= {
-			.index	= 3,
-			.shift	= 6,
-			.width	= 2,
-		},
+		.var_predivs	= ahb1_predivs,
+		.n_var_predivs	= ARRAY_SIZE(ahb1_predivs),
 	},
 
 	.common		= {

+ 922 - 0
drivers/clk/sunxi-ng/ccu-sun8i-a83t.c

@@ -0,0 +1,922 @@
+/*
+ * Copyright (c) 2017 Chen-Yu Tsai. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+#include "ccu_mux.h"
+#include "ccu_nkmp.h"
+#include "ccu_nm.h"
+#include "ccu_phase.h"
+
+#include "ccu-sun8i-a83t.h"
+
+#define CCU_SUN8I_A83T_LOCK_REG	0x20c
+
+/*
+ * The CPU PLLs are actually NP clocks, with P being /1 or /4. However
+ * P should only be used for output frequencies lower than 228 MHz.
+ * Neither mainline Linux, U-boot, nor the vendor BSPs use these.
+ *
+ * For now we can just model it as a multiplier clock, and force P to /1.
+ */
+#define SUN8I_A83T_PLL_C0CPUX_REG	0x000
+#define SUN8I_A83T_PLL_C1CPUX_REG	0x004
+
+static struct ccu_mult pll_c0cpux_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(0),
+	.mult		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
+	.common		= {
+		.reg		= SUN8I_A83T_PLL_C0CPUX_REG,
+		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
+		.features	= CCU_FEATURE_LOCK_REG,
+		.hw.init	= CLK_HW_INIT("pll-c0cpux", "osc24M",
+					      &ccu_mult_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static struct ccu_mult pll_c1cpux_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(1),
+	.mult		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
+	.common		= {
+		.reg		= SUN8I_A83T_PLL_C1CPUX_REG,
+		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
+		.features	= CCU_FEATURE_LOCK_REG,
+		.hw.init	= CLK_HW_INIT("pll-c1cpux", "osc24M",
+					      &ccu_mult_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+/*
+ * The Audio PLL has d1, d2 dividers in addition to the usual N, M
+ * factors. Since we only need 2 frequencies from this PLL: 22.5792 MHz
+ * and 24.576 MHz, ignore them for now. Enforce the default for them,
+ * which is d1 = 0, d2 = 1.
+ */
+#define SUN8I_A83T_PLL_AUDIO_REG	0x008
+
+static struct ccu_nm pll_audio_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(2),
+	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
+	.m		= _SUNXI_CCU_DIV(0, 6),
+	.common		= {
+		.reg		= SUN8I_A83T_PLL_AUDIO_REG,
+		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
+		.features	= CCU_FEATURE_LOCK_REG,
+		.hw.init	= CLK_HW_INIT("pll-audio", "osc24M",
+					      &ccu_nm_ops, CLK_SET_RATE_UNGATE),
+	},
+};
+
+/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
+static struct ccu_nkmp pll_video0_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(3),
+	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
+	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
+	.p		= _SUNXI_CCU_DIV(0, 2), /* output divider */
+	.common		= {
+		.reg		= 0x010,
+		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
+		.features	= CCU_FEATURE_LOCK_REG,
+		.hw.init	= CLK_HW_INIT("pll-video0", "osc24M",
+					      &ccu_nkmp_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static struct ccu_nkmp pll_ve_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(4),
+	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
+	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
+	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
+	.common		= {
+		.reg		= 0x018,
+		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
+		.features	= CCU_FEATURE_LOCK_REG,
+		.hw.init	= CLK_HW_INIT("pll-ve", "osc24M",
+					      &ccu_nkmp_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static struct ccu_nkmp pll_ddr_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(5),
+	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
+	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
+	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
+	.common		= {
+		.reg		= 0x020,
+		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
+		.features	= CCU_FEATURE_LOCK_REG,
+		.hw.init	= CLK_HW_INIT("pll-ddr", "osc24M",
+					      &ccu_nkmp_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static struct ccu_nkmp pll_periph_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(6),
+	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
+	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
+	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
+	.common		= {
+		.reg		= 0x028,
+		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
+		.features	= CCU_FEATURE_LOCK_REG,
+		.hw.init	= CLK_HW_INIT("pll-periph", "osc24M",
+					      &ccu_nkmp_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static struct ccu_nkmp pll_gpu_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(7),
+	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
+	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
+	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
+	.common		= {
+		.reg		= 0x038,
+		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
+		.features	= CCU_FEATURE_LOCK_REG,
+		.hw.init	= CLK_HW_INIT("pll-gpu", "osc24M",
+					      &ccu_nkmp_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static struct ccu_nkmp pll_hsic_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(8),
+	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
+	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
+	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
+	.common		= {
+		.reg		= 0x044,
+		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
+		.features	= CCU_FEATURE_LOCK_REG,
+		.hw.init	= CLK_HW_INIT("pll-hsic", "osc24M",
+					      &ccu_nkmp_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static struct ccu_nkmp pll_de_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(9),
+	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
+	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
+	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
+	.common		= {
+		.reg		= 0x048,
+		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
+		.features	= CCU_FEATURE_LOCK_REG,
+		.hw.init	= CLK_HW_INIT("pll-de", "osc24M",
+					      &ccu_nkmp_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static struct ccu_nkmp pll_video1_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(10),
+	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
+	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
+	.p		= _SUNXI_CCU_DIV(0, 2), /* external divider p */
+	.common		= {
+		.reg		= 0x04c,
+		.lock_reg	= CCU_SUN8I_A83T_LOCK_REG,
+		.features	= CCU_FEATURE_LOCK_REG,
+		.hw.init	= CLK_HW_INIT("pll-video1", "osc24M",
+					      &ccu_nkmp_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+static const char * const c0cpux_parents[] = { "osc24M", "pll-c0cpux" };
+static SUNXI_CCU_MUX(c0cpux_clk, "c0cpux", c0cpux_parents,
+		     0x50, 12, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
+
+static const char * const c1cpux_parents[] = { "osc24M", "pll-c1cpux" };
+static SUNXI_CCU_MUX(c1cpux_clk, "c1cpux", c1cpux_parents,
+		     0x50, 28, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
+
+static SUNXI_CCU_M(axi0_clk, "axi0", "c0cpux", 0x050, 0, 2, 0);
+static SUNXI_CCU_M(axi1_clk, "axi1", "c1cpux", 0x050, 16, 2, 0);
+
+static const char * const ahb1_parents[] = { "osc16M-d512", "osc24M",
+					     "pll-periph",
+					     "pll-periph" };
+static const struct ccu_mux_var_prediv ahb1_predivs[] = {
+	{ .index = 2, .shift = 6, .width = 2 },
+	{ .index = 3, .shift = 6, .width = 2 },
+};
+static struct ccu_div ahb1_clk = {
+	.div		= _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
+	.mux		= {
+		.shift	= 12,
+		.width	= 2,
+
+		.var_predivs	= ahb1_predivs,
+		.n_var_predivs	= ARRAY_SIZE(ahb1_predivs),
+	},
+	.common		= {
+		.reg		= 0x054,
+		.hw.init	= CLK_HW_INIT_PARENTS("ahb1",
+						      ahb1_parents,
+						      &ccu_div_ops,
+						      0),
+	},
+};
+
+static SUNXI_CCU_M(apb1_clk, "apb1", "ahb1", 0x054, 8, 2, 0);
+
+static const char * const apb2_parents[] = { "osc16M-d512", "osc24M",
+					     "pll-periph", "pll-periph" };
+
+static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058,
+			     0, 5,	/* M */
+			     16, 2,	/* P */
+			     24, 2,	/* mux */
+			     0);
+
+static const char * const ahb2_parents[] = { "ahb1", "pll-periph" };
+static const struct ccu_mux_fixed_prediv ahb2_prediv = {
+	.index = 1, .div = 2
+};
+static struct ccu_mux ahb2_clk = {
+	.mux		= {
+		.shift		= 0,
+		.width		= 2,
+		.fixed_predivs	= &ahb2_prediv,
+		.n_predivs	= 1,
+	},
+	.common		= {
+		.reg		= 0x05c,
+		.hw.init	= CLK_HW_INIT_PARENTS("ahb2",
+						      ahb2_parents,
+						      &ccu_mux_ops,
+						      0),
+	},
+};
+
+static SUNXI_CCU_GATE(bus_mipi_dsi_clk,	"bus-mipi-dsi",	"ahb1",
+		      0x060, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_ss_clk,	"bus-ss",	"ahb1",
+		      0x060, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_dma_clk,	"bus-dma",	"ahb1",
+		      0x060, BIT(6), 0);
+static SUNXI_CCU_GATE(bus_mmc0_clk,	"bus-mmc0",	"ahb1",
+		      0x060, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_mmc1_clk,	"bus-mmc1",	"ahb1",
+		      0x060, BIT(9), 0);
+static SUNXI_CCU_GATE(bus_mmc2_clk,	"bus-mmc2",	"ahb1",
+		      0x060, BIT(10), 0);
+static SUNXI_CCU_GATE(bus_nand_clk,	"bus-nand",	"ahb1",
+		      0x060, BIT(13), 0);
+static SUNXI_CCU_GATE(bus_dram_clk,	"bus-dram",	"ahb1",
+		      0x060, BIT(14), 0);
+static SUNXI_CCU_GATE(bus_emac_clk,	"bus-emac",	"ahb2",
+		      0x060, BIT(17), 0);
+static SUNXI_CCU_GATE(bus_hstimer_clk,	"bus-hstimer",	"ahb1",
+		      0x060, BIT(19), 0);
+static SUNXI_CCU_GATE(bus_spi0_clk,	"bus-spi0",	"ahb1",
+		      0x060, BIT(20), 0);
+static SUNXI_CCU_GATE(bus_spi1_clk,	"bus-spi1",	"ahb1",
+		      0x060, BIT(21), 0);
+static SUNXI_CCU_GATE(bus_otg_clk,	"bus-otg",	"ahb1",
+		      0x060, BIT(24), 0);
+static SUNXI_CCU_GATE(bus_ehci0_clk,	"bus-ehci0",	"ahb2",
+		      0x060, BIT(26), 0);
+static SUNXI_CCU_GATE(bus_ehci1_clk,	"bus-ehci1",	"ahb2",
+		      0x060, BIT(27), 0);
+static SUNXI_CCU_GATE(bus_ohci0_clk,	"bus-ohci0",	"ahb2",
+		      0x060, BIT(29), 0);
+
+static SUNXI_CCU_GATE(bus_ve_clk,	"bus-ve",	"ahb1",
+		      0x064, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_tcon0_clk,	"bus-tcon0",	"ahb1",
+		      0x064, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_tcon1_clk,	"bus-tcon1",	"ahb1",
+		      0x064, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_csi_clk,	"bus-csi",	"ahb1",
+		      0x064, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_hdmi_clk,	"bus-hdmi",	"ahb1",
+		      0x064, BIT(11), 0);
+static SUNXI_CCU_GATE(bus_de_clk,	"bus-de",	"ahb1",
+		      0x064, BIT(12), 0);
+static SUNXI_CCU_GATE(bus_gpu_clk,	"bus-gpu",	"ahb1",
+		      0x064, BIT(20), 0);
+static SUNXI_CCU_GATE(bus_msgbox_clk,	"bus-msgbox",	"ahb1",
+		      0x064, BIT(21), 0);
+static SUNXI_CCU_GATE(bus_spinlock_clk,	"bus-spinlock",	"ahb1",
+		      0x064, BIT(22), 0);
+
+static SUNXI_CCU_GATE(bus_spdif_clk,	"bus-spdif",	"apb1",
+		      0x068, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_pio_clk,	"bus-pio",	"apb1",
+		      0x068, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_i2s0_clk,	"bus-i2s0",	"apb1",
+		      0x068, BIT(12), 0);
+static SUNXI_CCU_GATE(bus_i2s1_clk,	"bus-i2s1",	"apb1",
+		      0x068, BIT(13), 0);
+static SUNXI_CCU_GATE(bus_i2s2_clk,	"bus-i2s2",	"apb1",
+		      0x068, BIT(14), 0);
+static SUNXI_CCU_GATE(bus_tdm_clk,	"bus-tdm",	"apb1",
+		      0x068, BIT(15), 0);
+
+static SUNXI_CCU_GATE(bus_i2c0_clk,	"bus-i2c0",	"apb2",
+		      0x06c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2c1_clk,	"bus-i2c1",	"apb2",
+		      0x06c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2c2_clk,	"bus-i2c2",	"apb2",
+		      0x06c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_uart0_clk,	"bus-uart0",	"apb2",
+		      0x06c, BIT(16), 0);
+static SUNXI_CCU_GATE(bus_uart1_clk,	"bus-uart1",	"apb2",
+		      0x06c, BIT(17), 0);
+static SUNXI_CCU_GATE(bus_uart2_clk,	"bus-uart2",	"apb2",
+		      0x06c, BIT(18), 0);
+static SUNXI_CCU_GATE(bus_uart3_clk,	"bus-uart3",	"apb2",
+		      0x06c, BIT(19), 0);
+static SUNXI_CCU_GATE(bus_uart4_clk,	"bus-uart4",	"apb2",
+		      0x06c, BIT(20), 0);
+
+static const char * const cci400_parents[] = { "osc24M", "pll-periph",
+					       "pll-hsic" };
+static struct ccu_div cci400_clk = {
+	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, 0),
+	.mux		= _SUNXI_CCU_MUX(24, 2),
+	.common		= {
+		.reg		= 0x078,
+		.hw.init	= CLK_HW_INIT_PARENTS("cci400",
+						      cci400_parents,
+						      &ccu_div_ops,
+						      CLK_IS_CRITICAL),
+	},
+};
+
+static const char * const mod0_default_parents[] = { "osc24M", "pll-periph" };
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents,
+				  0x080,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents,
+				  0x088,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0-sample", "mmc0",
+		       0x088, 20, 3, 0);
+static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0-output", "mmc0",
+		       0x088, 8, 3, 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents,
+				  0x08c,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1-sample", "mmc1",
+		       0x08c, 20, 3, 0);
+static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1-output", "mmc1",
+		       0x08c, 8, 3, 0);
+
+/* TODO Support MMC2 clock's new timing mode. */
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents,
+				  0x090,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2-sample", "mmc2",
+		       0x090, 20, 3, 0);
+static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2-output", "mmc2",
+		       0x090, 8, 3, 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(ss_clk, "ss", mod0_default_parents,
+				  0x09c,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents,
+				  0x0a0,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 4,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents,
+				  0x0a4,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 4,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_M_WITH_GATE(i2s0_clk, "i2s0", "pll-audio",
+			     0x0b0, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M_WITH_GATE(i2s1_clk, "i2s1", "pll-audio",
+			     0x0b4, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M_WITH_GATE(i2s2_clk, "i2s2", "pll-audio",
+			     0x0b8, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M_WITH_GATE(tdm_clk, "tdm", "pll-audio",
+			     0x0bc, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
+			     0x0c0, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(usb_phy0_clk,	"usb-phy0",	"osc24M",
+		      0x0cc, BIT(8), 0);
+static SUNXI_CCU_GATE(usb_phy1_clk,	"usb-phy1",	"osc24M",
+		      0x0cc, BIT(9), 0);
+static SUNXI_CCU_GATE(usb_hsic_clk,	"usb-hsic",	"pll-hsic",
+		      0x0cc, BIT(10), 0);
+static struct ccu_gate usb_hsic_12m_clk = {
+	.enable	= BIT(11),
+	.common	= {
+		.reg		= 0x0cc,
+		.prediv		= 2,
+		.features	= CCU_FEATURE_ALL_PREDIV,
+		.hw.init	= CLK_HW_INIT("usb-hsic-12m", "osc24M",
+					      &ccu_gate_ops, 0),
+	}
+};
+static SUNXI_CCU_GATE(usb_ohci0_clk,	"usb-ohci0",	"osc24M",
+		      0x0cc, BIT(16), 0);
+
+/* TODO divider has minimum of 2 */
+static SUNXI_CCU_M(dram_clk, "dram", "pll-ddr", 0x0f4, 0, 4, CLK_IS_CRITICAL);
+
+static SUNXI_CCU_GATE(dram_ve_clk,	"dram-ve",	"dram",
+		      0x100, BIT(0), 0);
+static SUNXI_CCU_GATE(dram_csi_clk,	"dram-csi",	"dram",
+		      0x100, BIT(1), 0);
+
+static const char * const tcon0_parents[] = { "pll-video0" };
+static SUNXI_CCU_MUX_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents,
+				 0x118, 24, 3, BIT(31), CLK_SET_RATE_PARENT);
+
+static const char * const tcon1_parents[] = { "pll-video1" };
+static SUNXI_CCU_MUX_WITH_GATE(tcon1_clk, "tcon1", tcon1_parents,
+				 0x11c, 24, 3, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M", 0x130, BIT(16), 0);
+
+static SUNXI_CCU_GATE(mipi_csi_clk, "mipi-csi", "osc24M", 0x130, BIT(31), 0);
+
+static const char * const csi_mclk_parents[] = { "pll-de", "osc24M" };
+static const u8 csi_mclk_table[] = { 3, 5 };
+static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_mclk_clk, "csi-mclk",
+				       csi_mclk_parents, csi_mclk_table,
+				       0x134,
+				       0, 5,	/* M */
+				       10, 3,	/* mux */
+				       BIT(15),	/* gate */
+				       0);
+
+static const char * const csi_sclk_parents[] = { "pll-periph", "pll-ve" };
+static const u8 csi_sclk_table[] = { 0, 5 };
+static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_sclk_clk, "csi-sclk",
+				       csi_sclk_parents, csi_sclk_table,
+				       0x134,
+				       16, 4,	/* M */
+				       24, 3,	/* mux */
+				       BIT(31),	/* gate */
+				       0);
+
+static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", 0x13c,
+			     16, 3, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x144, BIT(31), 0);
+
+static const char * const hdmi_parents[] = { "pll-video1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,
+				 0x150,
+				 0, 4,	/* M */
+				 24, 2,	/* mux */
+				 BIT(31),	/* gate */
+				 CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0x154, BIT(31), 0);
+
+static const char * const mbus_parents[] = { "osc24M", "pll-periph",
+					     "pll-ddr" };
+static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
+				 0x15c,
+				 0, 3,	/* M */
+				 24, 2,	/* mux */
+				 BIT(31),	/* gate */
+				 CLK_IS_CRITICAL);
+
+static const char * const mipi_dsi0_parents[] = { "pll-video0" };
+static const u8 mipi_dsi0_table[] = { 8 };
+static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi0_clk, "mipi-dsi0",
+				       mipi_dsi0_parents, mipi_dsi0_table,
+				       0x168,
+				       0, 4,	/* M */
+				       24, 4,	/* mux */
+				       BIT(31),	/* gate */
+				       CLK_SET_RATE_PARENT);
+
+static const char * const mipi_dsi1_parents[] = { "osc24M", "pll-video0" };
+static const u8 mipi_dsi1_table[] = { 0, 9 };
+static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi1_clk, "mipi-dsi1",
+				       mipi_dsi1_parents, mipi_dsi1_table,
+				       0x16c,
+				       0, 4,	/* M */
+				       24, 4,	/* mux */
+				       BIT(31),	/* gate */
+				       CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_WITH_GATE(gpu_core_clk, "gpu-core", "pll-gpu", 0x1a0,
+			     0, 3, BIT(31), CLK_SET_RATE_PARENT);
+
+static const char * const gpu_memory_parents[] = { "pll-gpu", "pll-ddr" };
+static SUNXI_CCU_M_WITH_MUX_GATE(gpu_memory_clk, "gpu-memory",
+				 gpu_memory_parents,
+				 0x1a4,
+				 0, 3,		/* M */
+				 24, 1,		/* mux */
+				 BIT(31),	/* gate */
+				 CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_WITH_GATE(gpu_hyd_clk, "gpu-hyd", "pll-gpu", 0x1a8,
+			     0, 3, BIT(31), CLK_SET_RATE_PARENT);
+
+static struct ccu_common *sun8i_a83t_ccu_clks[] = {
+	&pll_c0cpux_clk.common,
+	&pll_c1cpux_clk.common,
+	&pll_audio_clk.common,
+	&pll_video0_clk.common,
+	&pll_ve_clk.common,
+	&pll_ddr_clk.common,
+	&pll_periph_clk.common,
+	&pll_gpu_clk.common,
+	&pll_hsic_clk.common,
+	&pll_de_clk.common,
+	&pll_video1_clk.common,
+	&c0cpux_clk.common,
+	&c1cpux_clk.common,
+	&axi0_clk.common,
+	&axi1_clk.common,
+	&ahb1_clk.common,
+	&ahb2_clk.common,
+	&apb1_clk.common,
+	&apb2_clk.common,
+	&bus_mipi_dsi_clk.common,
+	&bus_ss_clk.common,
+	&bus_dma_clk.common,
+	&bus_mmc0_clk.common,
+	&bus_mmc1_clk.common,
+	&bus_mmc2_clk.common,
+	&bus_nand_clk.common,
+	&bus_dram_clk.common,
+	&bus_emac_clk.common,
+	&bus_hstimer_clk.common,
+	&bus_spi0_clk.common,
+	&bus_spi1_clk.common,
+	&bus_otg_clk.common,
+	&bus_ehci0_clk.common,
+	&bus_ehci1_clk.common,
+	&bus_ohci0_clk.common,
+	&bus_ve_clk.common,
+	&bus_tcon0_clk.common,
+	&bus_tcon1_clk.common,
+	&bus_csi_clk.common,
+	&bus_hdmi_clk.common,
+	&bus_de_clk.common,
+	&bus_gpu_clk.common,
+	&bus_msgbox_clk.common,
+	&bus_spinlock_clk.common,
+	&bus_spdif_clk.common,
+	&bus_pio_clk.common,
+	&bus_i2s0_clk.common,
+	&bus_i2s1_clk.common,
+	&bus_i2s2_clk.common,
+	&bus_tdm_clk.common,
+	&bus_i2c0_clk.common,
+	&bus_i2c1_clk.common,
+	&bus_i2c2_clk.common,
+	&bus_uart0_clk.common,
+	&bus_uart1_clk.common,
+	&bus_uart2_clk.common,
+	&bus_uart3_clk.common,
+	&bus_uart4_clk.common,
+	&cci400_clk.common,
+	&nand_clk.common,
+	&mmc0_clk.common,
+	&mmc0_sample_clk.common,
+	&mmc0_output_clk.common,
+	&mmc1_clk.common,
+	&mmc1_sample_clk.common,
+	&mmc1_output_clk.common,
+	&mmc2_clk.common,
+	&mmc2_sample_clk.common,
+	&mmc2_output_clk.common,
+	&ss_clk.common,
+	&spi0_clk.common,
+	&spi1_clk.common,
+	&i2s0_clk.common,
+	&i2s1_clk.common,
+	&i2s2_clk.common,
+	&tdm_clk.common,
+	&spdif_clk.common,
+	&usb_phy0_clk.common,
+	&usb_phy1_clk.common,
+	&usb_hsic_clk.common,
+	&usb_hsic_12m_clk.common,
+	&usb_ohci0_clk.common,
+	&dram_clk.common,
+	&dram_ve_clk.common,
+	&dram_csi_clk.common,
+	&tcon0_clk.common,
+	&tcon1_clk.common,
+	&csi_misc_clk.common,
+	&mipi_csi_clk.common,
+	&csi_mclk_clk.common,
+	&csi_sclk_clk.common,
+	&ve_clk.common,
+	&avs_clk.common,
+	&hdmi_clk.common,
+	&hdmi_slow_clk.common,
+	&mbus_clk.common,
+	&mipi_dsi0_clk.common,
+	&mipi_dsi1_clk.common,
+	&gpu_core_clk.common,
+	&gpu_memory_clk.common,
+	&gpu_hyd_clk.common,
+};
+
+static struct clk_hw_onecell_data sun8i_a83t_hw_clks = {
+	.hws	= {
+		[CLK_PLL_C0CPUX]	= &pll_c0cpux_clk.common.hw,
+		[CLK_PLL_C1CPUX]	= &pll_c1cpux_clk.common.hw,
+		[CLK_PLL_AUDIO]		= &pll_audio_clk.common.hw,
+		[CLK_PLL_VIDEO0]	= &pll_video0_clk.common.hw,
+		[CLK_PLL_VE]		= &pll_ve_clk.common.hw,
+		[CLK_PLL_DDR]		= &pll_ddr_clk.common.hw,
+		[CLK_PLL_PERIPH]	= &pll_periph_clk.common.hw,
+		[CLK_PLL_GPU]		= &pll_gpu_clk.common.hw,
+		[CLK_PLL_HSIC]		= &pll_hsic_clk.common.hw,
+		[CLK_PLL_DE]		= &pll_de_clk.common.hw,
+		[CLK_PLL_VIDEO1]	= &pll_video1_clk.common.hw,
+		[CLK_C0CPUX]		= &c0cpux_clk.common.hw,
+		[CLK_C1CPUX]		= &c1cpux_clk.common.hw,
+		[CLK_AXI0]		= &axi0_clk.common.hw,
+		[CLK_AXI1]		= &axi1_clk.common.hw,
+		[CLK_AHB1]		= &ahb1_clk.common.hw,
+		[CLK_AHB2]		= &ahb2_clk.common.hw,
+		[CLK_APB1]		= &apb1_clk.common.hw,
+		[CLK_APB2]		= &apb2_clk.common.hw,
+		[CLK_BUS_MIPI_DSI]	= &bus_mipi_dsi_clk.common.hw,
+		[CLK_BUS_SS]		= &bus_ss_clk.common.hw,
+		[CLK_BUS_DMA]		= &bus_dma_clk.common.hw,
+		[CLK_BUS_MMC0]		= &bus_mmc0_clk.common.hw,
+		[CLK_BUS_MMC1]		= &bus_mmc1_clk.common.hw,
+		[CLK_BUS_MMC2]		= &bus_mmc2_clk.common.hw,
+		[CLK_BUS_NAND]		= &bus_nand_clk.common.hw,
+		[CLK_BUS_DRAM]		= &bus_dram_clk.common.hw,
+		[CLK_BUS_EMAC]		= &bus_emac_clk.common.hw,
+		[CLK_BUS_HSTIMER]	= &bus_hstimer_clk.common.hw,
+		[CLK_BUS_SPI0]		= &bus_spi0_clk.common.hw,
+		[CLK_BUS_SPI1]		= &bus_spi1_clk.common.hw,
+		[CLK_BUS_OTG]		= &bus_otg_clk.common.hw,
+		[CLK_BUS_EHCI0]		= &bus_ehci0_clk.common.hw,
+		[CLK_BUS_EHCI1]		= &bus_ehci1_clk.common.hw,
+		[CLK_BUS_OHCI0]		= &bus_ohci0_clk.common.hw,
+		[CLK_BUS_VE]		= &bus_ve_clk.common.hw,
+		[CLK_BUS_TCON0]		= &bus_tcon0_clk.common.hw,
+		[CLK_BUS_TCON1]		= &bus_tcon1_clk.common.hw,
+		[CLK_BUS_CSI]		= &bus_csi_clk.common.hw,
+		[CLK_BUS_HDMI]		= &bus_hdmi_clk.common.hw,
+		[CLK_BUS_DE]		= &bus_de_clk.common.hw,
+		[CLK_BUS_GPU]		= &bus_gpu_clk.common.hw,
+		[CLK_BUS_MSGBOX]	= &bus_msgbox_clk.common.hw,
+		[CLK_BUS_SPINLOCK]	= &bus_spinlock_clk.common.hw,
+		[CLK_BUS_SPDIF]		= &bus_spdif_clk.common.hw,
+		[CLK_BUS_PIO]		= &bus_pio_clk.common.hw,
+		[CLK_BUS_I2S0]		= &bus_i2s0_clk.common.hw,
+		[CLK_BUS_I2S1]		= &bus_i2s1_clk.common.hw,
+		[CLK_BUS_I2S2]		= &bus_i2s2_clk.common.hw,
+		[CLK_BUS_TDM]		= &bus_tdm_clk.common.hw,
+		[CLK_BUS_I2C0]		= &bus_i2c0_clk.common.hw,
+		[CLK_BUS_I2C1]		= &bus_i2c1_clk.common.hw,
+		[CLK_BUS_I2C2]		= &bus_i2c2_clk.common.hw,
+		[CLK_BUS_UART0]		= &bus_uart0_clk.common.hw,
+		[CLK_BUS_UART1]		= &bus_uart1_clk.common.hw,
+		[CLK_BUS_UART2]		= &bus_uart2_clk.common.hw,
+		[CLK_BUS_UART3]		= &bus_uart3_clk.common.hw,
+		[CLK_BUS_UART4]		= &bus_uart4_clk.common.hw,
+		[CLK_CCI400]		= &cci400_clk.common.hw,
+		[CLK_NAND]		= &nand_clk.common.hw,
+		[CLK_MMC0]		= &mmc0_clk.common.hw,
+		[CLK_MMC0_SAMPLE]	= &mmc0_sample_clk.common.hw,
+		[CLK_MMC0_OUTPUT]	= &mmc0_output_clk.common.hw,
+		[CLK_MMC1]		= &mmc1_clk.common.hw,
+		[CLK_MMC1_SAMPLE]	= &mmc1_sample_clk.common.hw,
+		[CLK_MMC1_OUTPUT]	= &mmc1_output_clk.common.hw,
+		[CLK_MMC2]		= &mmc2_clk.common.hw,
+		[CLK_MMC2_SAMPLE]	= &mmc2_sample_clk.common.hw,
+		[CLK_MMC2_OUTPUT]	= &mmc2_output_clk.common.hw,
+		[CLK_SS]		= &ss_clk.common.hw,
+		[CLK_SPI0]		= &spi0_clk.common.hw,
+		[CLK_SPI1]		= &spi1_clk.common.hw,
+		[CLK_I2S0]		= &i2s0_clk.common.hw,
+		[CLK_I2S1]		= &i2s1_clk.common.hw,
+		[CLK_I2S2]		= &i2s2_clk.common.hw,
+		[CLK_TDM]		= &tdm_clk.common.hw,
+		[CLK_SPDIF]		= &spdif_clk.common.hw,
+		[CLK_USB_PHY0]		= &usb_phy0_clk.common.hw,
+		[CLK_USB_PHY1]		= &usb_phy1_clk.common.hw,
+		[CLK_USB_HSIC]		= &usb_hsic_clk.common.hw,
+		[CLK_USB_HSIC_12M]	= &usb_hsic_12m_clk.common.hw,
+		[CLK_USB_OHCI0]		= &usb_ohci0_clk.common.hw,
+		[CLK_DRAM]		= &dram_clk.common.hw,
+		[CLK_DRAM_VE]		= &dram_ve_clk.common.hw,
+		[CLK_DRAM_CSI]		= &dram_csi_clk.common.hw,
+		[CLK_TCON0]		= &tcon0_clk.common.hw,
+		[CLK_TCON1]		= &tcon1_clk.common.hw,
+		[CLK_CSI_MISC]		= &csi_misc_clk.common.hw,
+		[CLK_MIPI_CSI]		= &mipi_csi_clk.common.hw,
+		[CLK_CSI_MCLK]		= &csi_mclk_clk.common.hw,
+		[CLK_CSI_SCLK]		= &csi_sclk_clk.common.hw,
+		[CLK_VE]		= &ve_clk.common.hw,
+		[CLK_AVS]		= &avs_clk.common.hw,
+		[CLK_HDMI]		= &hdmi_clk.common.hw,
+		[CLK_HDMI_SLOW]		= &hdmi_slow_clk.common.hw,
+		[CLK_MBUS]		= &mbus_clk.common.hw,
+		[CLK_MIPI_DSI0]		= &mipi_dsi0_clk.common.hw,
+		[CLK_MIPI_DSI1]		= &mipi_dsi1_clk.common.hw,
+		[CLK_GPU_CORE]		= &gpu_core_clk.common.hw,
+		[CLK_GPU_MEMORY]	= &gpu_memory_clk.common.hw,
+		[CLK_GPU_HYD]		= &gpu_hyd_clk.common.hw,
+	},
+	.num	= CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun8i_a83t_ccu_resets[] = {
+	[RST_USB_PHY0]		= { 0x0cc, BIT(0) },
+	[RST_USB_PHY1]		= { 0x0cc, BIT(1) },
+	[RST_USB_HSIC]		= { 0x0cc, BIT(2) },
+	[RST_DRAM]		= { 0x0f4, BIT(31) },
+	[RST_MBUS]		= { 0x0fc, BIT(31) },
+	[RST_BUS_MIPI_DSI]	= { 0x2c0, BIT(1) },
+	[RST_BUS_SS]		= { 0x2c0, BIT(5) },
+	[RST_BUS_DMA]		= { 0x2c0, BIT(6) },
+	[RST_BUS_MMC0]		= { 0x2c0, BIT(8) },
+	[RST_BUS_MMC1]		= { 0x2c0, BIT(9) },
+	[RST_BUS_MMC2]		= { 0x2c0, BIT(10) },
+	[RST_BUS_NAND]		= { 0x2c0, BIT(13) },
+	[RST_BUS_DRAM]		= { 0x2c0, BIT(14) },
+	[RST_BUS_EMAC]		= { 0x2c0, BIT(17) },
+	[RST_BUS_HSTIMER]	= { 0x2c0, BIT(19) },
+	[RST_BUS_SPI0]		= { 0x2c0, BIT(20) },
+	[RST_BUS_SPI1]		= { 0x2c0, BIT(21) },
+	[RST_BUS_OTG]		= { 0x2c0, BIT(24) },
+	[RST_BUS_EHCI0]		= { 0x2c0, BIT(26) },
+	[RST_BUS_EHCI1]		= { 0x2c0, BIT(27) },
+	[RST_BUS_OHCI0]		= { 0x2c0, BIT(29) },
+	[RST_BUS_VE]		= { 0x2c4, BIT(0) },
+	[RST_BUS_TCON0]		= { 0x2c4, BIT(4) },
+	[RST_BUS_TCON1]		= { 0x2c4, BIT(5) },
+	[RST_BUS_CSI]		= { 0x2c4, BIT(8) },
+	[RST_BUS_HDMI0]		= { 0x2c4, BIT(10) },
+	[RST_BUS_HDMI1]		= { 0x2c4, BIT(11) },
+	[RST_BUS_DE]		= { 0x2c4, BIT(12) },
+	[RST_BUS_GPU]		= { 0x2c4, BIT(20) },
+	[RST_BUS_MSGBOX]	= { 0x2c4, BIT(21) },
+	[RST_BUS_SPINLOCK]	= { 0x2c4, BIT(22) },
+	[RST_BUS_LVDS]		= { 0x2c8, BIT(0) },
+	[RST_BUS_SPDIF]		= { 0x2d0, BIT(1) },
+	[RST_BUS_I2S0]		= { 0x2d0, BIT(12) },
+	[RST_BUS_I2S1]		= { 0x2d0, BIT(13) },
+	[RST_BUS_I2S2]		= { 0x2d0, BIT(14) },
+	[RST_BUS_TDM]		= { 0x2d0, BIT(15) },
+	[RST_BUS_I2C0]		= { 0x2d8, BIT(0) },
+	[RST_BUS_I2C1]		= { 0x2d8, BIT(1) },
+	[RST_BUS_I2C2]		= { 0x2d8, BIT(2) },
+	[RST_BUS_UART0]		= { 0x2d8, BIT(16) },
+	[RST_BUS_UART1]		= { 0x2d8, BIT(17) },
+	[RST_BUS_UART2]		= { 0x2d8, BIT(18) },
+	[RST_BUS_UART3]		= { 0x2d8, BIT(19) },
+	[RST_BUS_UART4]		= { 0x2d8, BIT(20) },
+};
+
+static const struct sunxi_ccu_desc sun8i_a83t_ccu_desc = {
+	.ccu_clks	= sun8i_a83t_ccu_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sun8i_a83t_ccu_clks),
+
+	.hw_clks	= &sun8i_a83t_hw_clks,
+
+	.resets		= sun8i_a83t_ccu_resets,
+	.num_resets	= ARRAY_SIZE(sun8i_a83t_ccu_resets),
+};
+
+#define SUN8I_A83T_PLL_P_SHIFT	16
+#define SUN8I_A83T_PLL_N_SHIFT	8
+#define SUN8I_A83T_PLL_N_WIDTH	8
+
+static void sun8i_a83t_cpu_pll_fixup(void __iomem *reg)
+{
+	u32 val = readl(reg);
+
+	/* bail out if P divider is not used */
+	if (!(val & BIT(SUN8I_A83T_PLL_P_SHIFT)))
+		return;
+
+	/*
+	 * If P is used, output should be less than 288 MHz. When we
+	 * set P to 1, we should also decrease the multiplier so the
+	 * output doesn't go out of range, but not too much such that
+	 * the multiplier stays above 12, the minimal operation value.
+	 *
+	 * To keep it simple, set the multiplier to 17, the reset value.
+	 */
+	val &= ~GENMASK(SUN8I_A83T_PLL_N_SHIFT + SUN8I_A83T_PLL_N_WIDTH - 1,
+			SUN8I_A83T_PLL_N_SHIFT);
+	val |= 17 << SUN8I_A83T_PLL_N_SHIFT;
+
+	/* And clear P */
+	val &= ~BIT(SUN8I_A83T_PLL_P_SHIFT);
+
+	writel(val, reg);
+}
+
+static int sun8i_a83t_ccu_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	void __iomem *reg;
+	u32 val;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	reg = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	/* Enforce d1 = 0, d2 = 0 for Audio PLL */
+	val = readl(reg + SUN8I_A83T_PLL_AUDIO_REG);
+	val &= ~(BIT(16) | BIT(18));
+	writel(val, reg + SUN8I_A83T_PLL_AUDIO_REG);
+
+	/* Enforce P = 1 for both CPU cluster PLLs */
+	sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C0CPUX_REG);
+	sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C1CPUX_REG);
+
+	return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8i_a83t_ccu_desc);
+}
+
+static const struct of_device_id sun8i_a83t_ccu_ids[] = {
+	{ .compatible = "allwinner,sun8i-a83t-ccu" },
+	{ }
+};
+
+static struct platform_driver sun8i_a83t_ccu_driver = {
+	.probe	= sun8i_a83t_ccu_probe,
+	.driver	= {
+		.name	= "sun8i-a83t-ccu",
+		.of_match_table	= sun8i_a83t_ccu_ids,
+	},
+};
+builtin_platform_driver(sun8i_a83t_ccu_driver);

+ 64 - 0
drivers/clk/sunxi-ng/ccu-sun8i-a83t.h

@@ -0,0 +1,64 @@
+/*
+ * Copyright 2016 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * 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.
+ */
+
+#ifndef _CCU_SUN8I_A83T_H_
+#define _CCU_SUN8I_A83T_H_
+
+#include <dt-bindings/clock/sun8i-a83t-ccu.h>
+#include <dt-bindings/reset/sun8i-a83t-ccu.h>
+
+#define CLK_PLL_C0CPUX		0
+#define CLK_PLL_C1CPUX		1
+#define CLK_PLL_AUDIO		2
+#define CLK_PLL_VIDEO0		3
+#define CLK_PLL_VE		4
+#define CLK_PLL_DDR		5
+
+/* pll-periph is exported to the PRCM block */
+
+#define CLK_PLL_GPU		7
+#define CLK_PLL_HSIC		8
+
+/* pll-de is exported for the display engine */
+
+#define CLK_PLL_VIDEO1		10
+
+/* The CPUX clocks are exported */
+
+#define CLK_AXI0		13
+#define CLK_AXI1		14
+#define CLK_AHB1		15
+#define CLK_AHB2		16
+#define CLK_APB1		17
+#define CLK_APB2		18
+
+/* bus gates exported */
+
+#define CLK_CCI400		58
+
+/* module and usb clocks exported */
+
+#define CLK_DRAM		82
+
+/* dram gates and more module clocks exported */
+
+#define CLK_MBUS		95
+
+/* more module clocks exported */
+
+#define CLK_NUMBER		(CLK_GPU_HYD + 1)
+
+#endif /* _CCU_SUN8I_A83T_H_ */

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä