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
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABCAAGBQJZXujtAAoJEK0CiJfG5JUl8vIQAKbcH3rX+CS4jrg7Hs2Ghnhn
 ZbTf7vZYa6K7iuL7JHITEScAQ8+l0Bl7eWSfJZRt4oUW3Jt4F+AIs8qBofZAWn4M
 m+kDHs/IfAUITZp/unM/ogFfVcboZObjAK/A2yyRVyMxRkIyyUb6r7SDVpCpGyxU
 1YDAdis2M3F5J9CGV/tpmobnksMUlCnJlI0OGtMUnvY6mDkf8Re89sayMnQ/1Mgp
 CL1YwnqZ0L6rT664IMo74bB7UNjXdMZsuCeITkU+hMVq4NMXErKCcn8lHvP9P+uP
 AoZ8bf9WaQ/CglGFeeFrNQGUf+tiTlYxlVvvNFXR5+rmhu/yKxNI67APaupeERVl
 jMISKAC/A+C1j6JVMCqjM3d75F47SzuZQuQY0ZD0DWoqP9PBzV6IyThHIqWrN5O4
 IceLmD8BrwW+h8bs2SIubIygOGMMqGhVi2XaAAWpmRke7JzmSFOOyE3YGPisaBAq
 EcIF2i2jJ6Ja4rClgfQKOsx25MOILsIp/sMU6iC7U1h4NDj8yP5A13n60U6DuZhu
 ttjN+bXugR81R+bWyzC6Zl/KXF83Ka3ZSJs+XblunPRGKt2q6Kj12HBspkWL1QjY
 aLEEg3fpI/ovQoTMXHj7/G1MD60rxoHCuOjBwSWEQBzA1MiHol+ab/mZKfPsy50C
 116G1XJgtgrLxE00iZ6K
 =Yar+
 -----END PGP SIGNATURE-----

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
  ...
This commit is contained in:
Linus Torvalds 2017-07-07 12:26:13 -07:00
commit dddd564dbb
145 changed files with 10477 additions and 1030 deletions

View File

@ -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>;
};
};

View File

@ -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";
};
};

View File

@ -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.

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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";
};

View File

@ -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>;
};

View File

@ -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

View File

@ -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>;
};

View File

@ -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>;
};

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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"

View File

@ -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/

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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_ */

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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
drivers/clk/bcm/clk-sr.c Normal file
View File

@ -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
drivers/clk/clk-bulk.c Normal file
View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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
drivers/clk/clk-gemini.c Normal file
View File

@ -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);

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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[] = {

View File

@ -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);

View File

@ -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(

View File

@ -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);

View File

@ -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;
}

View File

@ -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,

View File

@ -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.

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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",

View File

@ -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",

View File

@ -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

View File

@ -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);

View File

@ -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>

View File

@ -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" },
{ }
};

View File

@ -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_driver);
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_clock_driver);

View File

@ -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},

View File

@ -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;
/* 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;
}
ret = of_property_read_string_index(np,
"gate-clock-output-names",
i, &name);
/* Reached the end of the list? */
if (ret < 0)
break;
cp110_clks[CP110_CORE_SDIO] = hw;
if (!strcmp(name, "none"))
/* 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 (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_driver);
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_clock_driver);

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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),
{ }

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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 },
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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 */
};

View File

@ -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 = {

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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),

View File

@ -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;

View File

@ -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;

View File

@ -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:

View File

@ -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;
}

View File

@ -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);

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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 = {

View File

@ -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

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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);

View File

@ -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_ */

Some files were not shown because too many files have changed in this diff Show More