mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-11 16:29:05 +00:00
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:
commit
dddd564dbb
@ -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>;
|
||||
};
|
||||
};
|
||||
|
@ -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";
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -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.
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -0,0 +1,56 @@
|
||||
* Rockchip RK3128 Clock and Reset Unit
|
||||
|
||||
The RK3128 clock controller generates and supplies clock to various
|
||||
controllers within the SoC and also implements a reset controller for SoC
|
||||
peripherals.
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: should be "rockchip,rk3128-cru"
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- #clock-cells: should be 1.
|
||||
- #reset-cells: should be 1.
|
||||
|
||||
Optional Properties:
|
||||
|
||||
- rockchip,grf: phandle to the syscon managing the "general register files"
|
||||
If missing pll rates are not changeable, due to the missing pll lock status.
|
||||
|
||||
Each clock is assigned an identifier and client nodes can use this identifier
|
||||
to specify the clock which they consume. All available clocks are defined as
|
||||
preprocessor macros in the dt-bindings/clock/rk3128-cru.h headers and can be
|
||||
used in device tree sources. Similar macros exist for the reset sources in
|
||||
these files.
|
||||
|
||||
External clocks:
|
||||
|
||||
There are several clocks that are generated outside the SoC. It is expected
|
||||
that they are defined using standard clock bindings with following
|
||||
clock-output-names:
|
||||
- "xin24m" - crystal input - required,
|
||||
- "ext_i2s" - external I2S clock - optional,
|
||||
- "gmac_clkin" - external GMAC clock - optional
|
||||
|
||||
Example: Clock controller node:
|
||||
|
||||
cru: cru@20000000 {
|
||||
compatible = "rockchip,rk3128-cru";
|
||||
reg = <0x20000000 0x1000>;
|
||||
rockchip,grf = <&grf>;
|
||||
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
Example: UART controller node that consumes the clock generated by the clock
|
||||
controller:
|
||||
|
||||
uart2: serial@20068000 {
|
||||
compatible = "rockchip,serial";
|
||||
reg = <0x20068000 0x100>;
|
||||
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-frequency = <24000000>;
|
||||
clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
|
||||
clock-names = "sclk_uart", "pclk_uart";
|
||||
};
|
31
Documentation/devicetree/bindings/clock/sun8i-de2.txt
Normal file
31
Documentation/devicetree/bindings/clock/sun8i-de2.txt
Normal 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>;
|
||||
};
|
@ -6,6 +6,8 @@ Required properties :
|
||||
- "allwinner,sun6i-a31-ccu"
|
||||
- "allwinner,sun8i-a23-ccu"
|
||||
- "allwinner,sun8i-a33-ccu"
|
||||
- "allwinner,sun8i-a83t-ccu"
|
||||
- "allwinner,sun8i-a83t-r-ccu"
|
||||
- "allwinner,sun8i-h3-ccu"
|
||||
- "allwinner,sun8i-h3-r-ccu"
|
||||
- "allwinner,sun8i-v3s-ccu"
|
||||
@ -18,11 +20,12 @@ Required properties :
|
||||
- clocks: phandle to the oscillators feeding the CCU. Two are needed:
|
||||
- "hosc": the high frequency oscillator (usually at 24MHz)
|
||||
- "losc": the low frequency oscillator (usually at 32kHz)
|
||||
On the A83T, this is the internal 16MHz oscillator divided by 512
|
||||
- clock-names: Must contain the clock names described just above
|
||||
- #clock-cells : must contain 1
|
||||
- #reset-cells : must contain 1
|
||||
|
||||
For the PRCM CCUs on H3/A64, two more clocks are needed:
|
||||
For the PRCM CCUs on A83T/H3/A64, two more clocks are needed:
|
||||
- "pll-periph": the SoC's peripheral PLL from the main CCU
|
||||
- "iosc": the SoC's internal frequency oscillator
|
||||
|
||||
|
37
Documentation/devicetree/bindings/clock/ti,sci-clk.txt
Normal file
37
Documentation/devicetree/bindings/clock/ti,sci-clk.txt
Normal 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>;
|
||||
};
|
56
Documentation/devicetree/bindings/clock/ti-clkctrl.txt
Normal file
56
Documentation/devicetree/bindings/clock/ti-clkctrl.txt
Normal 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>;
|
||||
};
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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/
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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_ */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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
327
drivers/clk/bcm/clk-sr.c
Normal 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
157
drivers/clk/clk-bulk.c
Normal 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);
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
455
drivers/clk/clk-gemini.c
Normal 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);
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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[] = {
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ enum imx_pllv3_type {
|
||||
IMX_PLLV3_ENET,
|
||||
IMX_PLLV3_ENET_IMX7,
|
||||
IMX_PLLV3_SYS_VF610,
|
||||
IMX_PLLV3_DDR_IMX7,
|
||||
};
|
||||
|
||||
struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
|
||||
|
16
drivers/clk/keystone/Kconfig
Normal file
16
drivers/clk/keystone/Kconfig
Normal 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.
|
@ -1 +1,2 @@
|
||||
obj-y += pll.o gate.o
|
||||
obj-$(CONFIG_COMMON_CLK_KEYSTONE) += pll.o gate.o
|
||||
obj-$(CONFIG_TI_SCI_CLK) += sci-clk.o
|
||||
|
724
drivers/clk/keystone/sci-clk.c
Normal file
724
drivers/clk/keystone/sci-clk.c
Normal 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,
|
||||
¤t_state);
|
||||
if (ret) {
|
||||
dev_err(clk->provider->dev,
|
||||
"is_prepared failed for dev=%d, clk=%d, ret=%d\n",
|
||||
clk->dev_id, clk->clk_id, ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return req_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* sci_clk_recalc_rate - Get clock rate for a TI SCI clock
|
||||
* @hw: clock to get rate for
|
||||
* @parent_rate: parent rate provided by common clock framework, not used
|
||||
*
|
||||
* Gets the current clock rate of a TI SCI clock. Returns the current
|
||||
* clock rate, or zero in failure.
|
||||
*/
|
||||
static unsigned long sci_clk_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sci_clk *clk = to_sci_clk(hw);
|
||||
u64 freq;
|
||||
int ret;
|
||||
|
||||
ret = clk->provider->ops->get_freq(clk->provider->sci, clk->dev_id,
|
||||
clk->clk_id, &freq);
|
||||
if (ret) {
|
||||
dev_err(clk->provider->dev,
|
||||
"recalc-rate failed for dev=%d, clk=%d, ret=%d\n",
|
||||
clk->dev_id, clk->clk_id, ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
/**
|
||||
* sci_clk_determine_rate - Determines a clock rate a clock can be set to
|
||||
* @hw: clock to change rate for
|
||||
* @req: requested rate configuration for the clock
|
||||
*
|
||||
* Determines a suitable clock rate and parent for a TI SCI clock.
|
||||
* The parent handling is un-used, as generally the parent clock rates
|
||||
* are not known by the kernel; instead these are internally handled
|
||||
* by the firmware. Returns 0 on success, negative error value on failure.
|
||||
*/
|
||||
static int sci_clk_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct sci_clk *clk = to_sci_clk(hw);
|
||||
int ret;
|
||||
u64 new_rate;
|
||||
|
||||
ret = clk->provider->ops->get_best_match_freq(clk->provider->sci,
|
||||
clk->dev_id,
|
||||
clk->clk_id,
|
||||
req->min_rate,
|
||||
req->rate,
|
||||
req->max_rate,
|
||||
&new_rate);
|
||||
if (ret) {
|
||||
dev_err(clk->provider->dev,
|
||||
"determine-rate failed for dev=%d, clk=%d, ret=%d\n",
|
||||
clk->dev_id, clk->clk_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
req->rate = new_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* sci_clk_set_rate - Set rate for a TI SCI clock
|
||||
* @hw: clock to change rate for
|
||||
* @rate: target rate for the clock
|
||||
* @parent_rate: rate of the clock parent, not used for TI SCI clocks
|
||||
*
|
||||
* Sets a clock frequency for a TI SCI clock. Returns the TI SCI
|
||||
* protocol status.
|
||||
*/
|
||||
static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sci_clk *clk = to_sci_clk(hw);
|
||||
|
||||
return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id,
|
||||
clk->clk_id, rate, rate, rate);
|
||||
}
|
||||
|
||||
/**
|
||||
* sci_clk_get_parent - Get the current parent of a TI SCI clock
|
||||
* @hw: clock to get parent for
|
||||
*
|
||||
* Returns the index of the currently selected parent for a TI SCI clock.
|
||||
*/
|
||||
static u8 sci_clk_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct sci_clk *clk = to_sci_clk(hw);
|
||||
u8 parent_id;
|
||||
int ret;
|
||||
|
||||
ret = clk->provider->ops->get_parent(clk->provider->sci, clk->dev_id,
|
||||
clk->clk_id, &parent_id);
|
||||
if (ret) {
|
||||
dev_err(clk->provider->dev,
|
||||
"get-parent failed for dev=%d, clk=%d, ret=%d\n",
|
||||
clk->dev_id, clk->clk_id, ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return parent_id - clk->clk_id - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* sci_clk_set_parent - Set the parent of a TI SCI clock
|
||||
* @hw: clock to set parent for
|
||||
* @index: new parent index for the clock
|
||||
*
|
||||
* Sets the parent of a TI SCI clock. Return TI SCI protocol status.
|
||||
*/
|
||||
static int sci_clk_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct sci_clk *clk = to_sci_clk(hw);
|
||||
|
||||
return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id,
|
||||
clk->clk_id,
|
||||
index + 1 + clk->clk_id);
|
||||
}
|
||||
|
||||
static const struct clk_ops sci_clk_ops = {
|
||||
.prepare = sci_clk_prepare,
|
||||
.unprepare = sci_clk_unprepare,
|
||||
.is_prepared = sci_clk_is_prepared,
|
||||
.recalc_rate = sci_clk_recalc_rate,
|
||||
.determine_rate = sci_clk_determine_rate,
|
||||
.set_rate = sci_clk_set_rate,
|
||||
.get_parent = sci_clk_get_parent,
|
||||
.set_parent = sci_clk_set_parent,
|
||||
};
|
||||
|
||||
/**
|
||||
* _sci_clk_get - Gets a handle for an SCI clock
|
||||
* @provider: Handle to SCI clock provider
|
||||
* @dev_id: device ID for the clock to register
|
||||
* @clk_id: clock ID for the clock to register
|
||||
*
|
||||
* Gets a handle to an existing TI SCI hw clock, or builds a new clock
|
||||
* entry and registers it with the common clock framework. Called from
|
||||
* the common clock framework, when a corresponding of_clk_get call is
|
||||
* executed, or recursively from itself when parsing parent clocks.
|
||||
* Returns a pointer to the hw clock struct, or ERR_PTR value in failure.
|
||||
*/
|
||||
static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider,
|
||||
u16 dev_id, u8 clk_id)
|
||||
{
|
||||
struct clk_init_data init = { NULL };
|
||||
struct sci_clk *sci_clk = NULL;
|
||||
char *name = NULL;
|
||||
char **parent_names = NULL;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
sci_clk = devm_kzalloc(provider->dev, sizeof(*sci_clk), GFP_KERNEL);
|
||||
if (!sci_clk)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
sci_clk->dev_id = dev_id;
|
||||
sci_clk->clk_id = clk_id;
|
||||
sci_clk->provider = provider;
|
||||
|
||||
ret = provider->ops->get_num_parents(provider->sci, dev_id,
|
||||
clk_id,
|
||||
&init.num_parents);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
name = kasprintf(GFP_KERNEL, "%s:%d:%d", dev_name(provider->dev),
|
||||
sci_clk->dev_id, sci_clk->clk_id);
|
||||
|
||||
init.name = name;
|
||||
|
||||
/*
|
||||
* From kernel point of view, we only care about a clocks parents,
|
||||
* if it has more than 1 possible parent. In this case, it is going
|
||||
* to have mux functionality. Otherwise it is going to act as a root
|
||||
* clock.
|
||||
*/
|
||||
if (init.num_parents < 2)
|
||||
init.num_parents = 0;
|
||||
|
||||
if (init.num_parents) {
|
||||
parent_names = kcalloc(init.num_parents, sizeof(char *),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!parent_names) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < init.num_parents; i++) {
|
||||
char *parent_name;
|
||||
|
||||
parent_name = kasprintf(GFP_KERNEL, "%s:%d:%d",
|
||||
dev_name(provider->dev),
|
||||
sci_clk->dev_id,
|
||||
sci_clk->clk_id + 1 + i);
|
||||
if (!parent_name) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
parent_names[i] = parent_name;
|
||||
}
|
||||
init.parent_names = (void *)parent_names;
|
||||
}
|
||||
|
||||
init.ops = &sci_clk_ops;
|
||||
sci_clk->hw.init = &init;
|
||||
|
||||
ret = devm_clk_hw_register(provider->dev, &sci_clk->hw);
|
||||
if (ret)
|
||||
dev_err(provider->dev, "failed clk register with %d\n", ret);
|
||||
|
||||
err:
|
||||
if (parent_names) {
|
||||
for (i = 0; i < init.num_parents; i++)
|
||||
kfree(parent_names[i]);
|
||||
|
||||
kfree(parent_names);
|
||||
}
|
||||
|
||||
kfree(name);
|
||||
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return &sci_clk->hw;
|
||||
}
|
||||
|
||||
/**
|
||||
* sci_clk_get - Xlate function for getting clock handles
|
||||
* @clkspec: device tree clock specifier
|
||||
* @data: pointer to the clock provider
|
||||
*
|
||||
* Xlate function for retrieving clock TI SCI hw clock handles based on
|
||||
* device tree clock specifier. Called from the common clock framework,
|
||||
* when a corresponding of_clk_get call is executed. Returns a pointer
|
||||
* to the TI SCI hw clock struct, or ERR_PTR value in failure.
|
||||
*/
|
||||
static struct clk_hw *sci_clk_get(struct of_phandle_args *clkspec, void *data)
|
||||
{
|
||||
struct sci_clk_provider *provider = data;
|
||||
u16 dev_id;
|
||||
u8 clk_id;
|
||||
const struct sci_clk_data *clks = provider->clk_data;
|
||||
struct clk_hw **clocks = provider->clocks;
|
||||
|
||||
if (clkspec->args_count != 2)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
dev_id = clkspec->args[0];
|
||||
clk_id = clkspec->args[1];
|
||||
|
||||
while (clks->num_clks) {
|
||||
if (clks->dev == dev_id) {
|
||||
if (clk_id >= clks->num_clks)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return clocks[clk_id];
|
||||
}
|
||||
|
||||
clks++;
|
||||
}
|
||||
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static int ti_sci_init_clocks(struct sci_clk_provider *p)
|
||||
{
|
||||
const struct sci_clk_data *data = p->clk_data;
|
||||
struct clk_hw *hw;
|
||||
int i;
|
||||
|
||||
while (data->num_clks) {
|
||||
p->clocks = devm_kcalloc(p->dev, data->num_clks,
|
||||
sizeof(struct sci_clk),
|
||||
GFP_KERNEL);
|
||||
if (!p->clocks)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < data->num_clks; i++) {
|
||||
hw = _sci_clk_build(p, data->dev, i);
|
||||
if (!IS_ERR(hw)) {
|
||||
p->clocks[i] = hw;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Skip any holes in the clock lists */
|
||||
if (PTR_ERR(hw) == -ENODEV)
|
||||
continue;
|
||||
|
||||
return PTR_ERR(hw);
|
||||
}
|
||||
data++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sci_clk_data k2g_clk_data[] = {
|
||||
/* pmmc */
|
||||
{ .dev = 0x0, .num_clks = 4 },
|
||||
|
||||
/* mlb0 */
|
||||
{ .dev = 0x1, .num_clks = 5 },
|
||||
|
||||
/* dss0 */
|
||||
{ .dev = 0x2, .num_clks = 2 },
|
||||
|
||||
/* mcbsp0 */
|
||||
{ .dev = 0x3, .num_clks = 8 },
|
||||
|
||||
/* mcasp0 */
|
||||
{ .dev = 0x4, .num_clks = 8 },
|
||||
|
||||
/* mcasp1 */
|
||||
{ .dev = 0x5, .num_clks = 8 },
|
||||
|
||||
/* mcasp2 */
|
||||
{ .dev = 0x6, .num_clks = 8 },
|
||||
|
||||
/* dcan0 */
|
||||
{ .dev = 0x8, .num_clks = 2 },
|
||||
|
||||
/* dcan1 */
|
||||
{ .dev = 0x9, .num_clks = 2 },
|
||||
|
||||
/* emif0 */
|
||||
{ .dev = 0xa, .num_clks = 6 },
|
||||
|
||||
/* mmchs0 */
|
||||
{ .dev = 0xb, .num_clks = 3 },
|
||||
|
||||
/* mmchs1 */
|
||||
{ .dev = 0xc, .num_clks = 3 },
|
||||
|
||||
/* gpmc0 */
|
||||
{ .dev = 0xd, .num_clks = 1 },
|
||||
|
||||
/* elm0 */
|
||||
{ .dev = 0xe, .num_clks = 1 },
|
||||
|
||||
/* spi0 */
|
||||
{ .dev = 0x10, .num_clks = 1 },
|
||||
|
||||
/* spi1 */
|
||||
{ .dev = 0x11, .num_clks = 1 },
|
||||
|
||||
/* spi2 */
|
||||
{ .dev = 0x12, .num_clks = 1 },
|
||||
|
||||
/* spi3 */
|
||||
{ .dev = 0x13, .num_clks = 1 },
|
||||
|
||||
/* icss0 */
|
||||
{ .dev = 0x14, .num_clks = 6 },
|
||||
|
||||
/* icss1 */
|
||||
{ .dev = 0x15, .num_clks = 6 },
|
||||
|
||||
/* usb0 */
|
||||
{ .dev = 0x16, .num_clks = 7 },
|
||||
|
||||
/* usb1 */
|
||||
{ .dev = 0x17, .num_clks = 7 },
|
||||
|
||||
/* nss0 */
|
||||
{ .dev = 0x18, .num_clks = 14 },
|
||||
|
||||
/* pcie0 */
|
||||
{ .dev = 0x19, .num_clks = 1 },
|
||||
|
||||
/* gpio0 */
|
||||
{ .dev = 0x1b, .num_clks = 1 },
|
||||
|
||||
/* gpio1 */
|
||||
{ .dev = 0x1c, .num_clks = 1 },
|
||||
|
||||
/* timer64_0 */
|
||||
{ .dev = 0x1d, .num_clks = 9 },
|
||||
|
||||
/* timer64_1 */
|
||||
{ .dev = 0x1e, .num_clks = 9 },
|
||||
|
||||
/* timer64_2 */
|
||||
{ .dev = 0x1f, .num_clks = 9 },
|
||||
|
||||
/* timer64_3 */
|
||||
{ .dev = 0x20, .num_clks = 9 },
|
||||
|
||||
/* timer64_4 */
|
||||
{ .dev = 0x21, .num_clks = 9 },
|
||||
|
||||
/* timer64_5 */
|
||||
{ .dev = 0x22, .num_clks = 9 },
|
||||
|
||||
/* timer64_6 */
|
||||
{ .dev = 0x23, .num_clks = 9 },
|
||||
|
||||
/* msgmgr0 */
|
||||
{ .dev = 0x25, .num_clks = 1 },
|
||||
|
||||
/* bootcfg0 */
|
||||
{ .dev = 0x26, .num_clks = 1 },
|
||||
|
||||
/* arm_bootrom0 */
|
||||
{ .dev = 0x27, .num_clks = 1 },
|
||||
|
||||
/* dsp_bootrom0 */
|
||||
{ .dev = 0x29, .num_clks = 1 },
|
||||
|
||||
/* debugss0 */
|
||||
{ .dev = 0x2b, .num_clks = 8 },
|
||||
|
||||
/* uart0 */
|
||||
{ .dev = 0x2c, .num_clks = 1 },
|
||||
|
||||
/* uart1 */
|
||||
{ .dev = 0x2d, .num_clks = 1 },
|
||||
|
||||
/* uart2 */
|
||||
{ .dev = 0x2e, .num_clks = 1 },
|
||||
|
||||
/* ehrpwm0 */
|
||||
{ .dev = 0x2f, .num_clks = 1 },
|
||||
|
||||
/* ehrpwm1 */
|
||||
{ .dev = 0x30, .num_clks = 1 },
|
||||
|
||||
/* ehrpwm2 */
|
||||
{ .dev = 0x31, .num_clks = 1 },
|
||||
|
||||
/* ehrpwm3 */
|
||||
{ .dev = 0x32, .num_clks = 1 },
|
||||
|
||||
/* ehrpwm4 */
|
||||
{ .dev = 0x33, .num_clks = 1 },
|
||||
|
||||
/* ehrpwm5 */
|
||||
{ .dev = 0x34, .num_clks = 1 },
|
||||
|
||||
/* eqep0 */
|
||||
{ .dev = 0x35, .num_clks = 1 },
|
||||
|
||||
/* eqep1 */
|
||||
{ .dev = 0x36, .num_clks = 1 },
|
||||
|
||||
/* eqep2 */
|
||||
{ .dev = 0x37, .num_clks = 1 },
|
||||
|
||||
/* ecap0 */
|
||||
{ .dev = 0x38, .num_clks = 1 },
|
||||
|
||||
/* ecap1 */
|
||||
{ .dev = 0x39, .num_clks = 1 },
|
||||
|
||||
/* i2c0 */
|
||||
{ .dev = 0x3a, .num_clks = 1 },
|
||||
|
||||
/* i2c1 */
|
||||
{ .dev = 0x3b, .num_clks = 1 },
|
||||
|
||||
/* i2c2 */
|
||||
{ .dev = 0x3c, .num_clks = 1 },
|
||||
|
||||
/* edma0 */
|
||||
{ .dev = 0x3f, .num_clks = 2 },
|
||||
|
||||
/* semaphore0 */
|
||||
{ .dev = 0x40, .num_clks = 1 },
|
||||
|
||||
/* intc0 */
|
||||
{ .dev = 0x41, .num_clks = 1 },
|
||||
|
||||
/* gic0 */
|
||||
{ .dev = 0x42, .num_clks = 1 },
|
||||
|
||||
/* qspi0 */
|
||||
{ .dev = 0x43, .num_clks = 5 },
|
||||
|
||||
/* arm_64b_counter0 */
|
||||
{ .dev = 0x44, .num_clks = 2 },
|
||||
|
||||
/* tetris0 */
|
||||
{ .dev = 0x45, .num_clks = 2 },
|
||||
|
||||
/* cgem0 */
|
||||
{ .dev = 0x46, .num_clks = 2 },
|
||||
|
||||
/* msmc0 */
|
||||
{ .dev = 0x47, .num_clks = 1 },
|
||||
|
||||
/* cbass0 */
|
||||
{ .dev = 0x49, .num_clks = 1 },
|
||||
|
||||
/* board0 */
|
||||
{ .dev = 0x4c, .num_clks = 36 },
|
||||
|
||||
/* edma1 */
|
||||
{ .dev = 0x4f, .num_clks = 2 },
|
||||
{ .num_clks = 0 },
|
||||
};
|
||||
|
||||
static const struct of_device_id ti_sci_clk_of_match[] = {
|
||||
{ .compatible = "ti,k2g-sci-clk", .data = &k2g_clk_data },
|
||||
{ /* Sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ti_sci_clk_of_match);
|
||||
|
||||
/**
|
||||
* ti_sci_clk_probe - Probe function for the TI SCI clock driver
|
||||
* @pdev: platform device pointer to be probed
|
||||
*
|
||||
* Probes the TI SCI clock device. Allocates a new clock provider
|
||||
* and registers this to the common clock framework. Also applies
|
||||
* any required flags to the identified clocks via clock lists
|
||||
* supplied from DT. Returns 0 for success, negative error value
|
||||
* for failure.
|
||||
*/
|
||||
static int ti_sci_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct sci_clk_provider *provider;
|
||||
const struct ti_sci_handle *handle;
|
||||
const struct sci_clk_data *data;
|
||||
int ret;
|
||||
|
||||
data = of_device_get_match_data(dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
handle = devm_ti_sci_get_handle(dev);
|
||||
if (IS_ERR(handle))
|
||||
return PTR_ERR(handle);
|
||||
|
||||
provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL);
|
||||
if (!provider)
|
||||
return -ENOMEM;
|
||||
|
||||
provider->clk_data = data;
|
||||
|
||||
provider->sci = handle;
|
||||
provider->ops = &handle->ops.clk_ops;
|
||||
provider->dev = dev;
|
||||
|
||||
ret = ti_sci_init_clocks(provider);
|
||||
if (ret) {
|
||||
pr_err("ti-sci-init-clocks failed.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return of_clk_add_hw_provider(np, sci_clk_get, provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* ti_sci_clk_remove - Remove TI SCI clock device
|
||||
* @pdev: platform device pointer for the device to be removed
|
||||
*
|
||||
* Removes the TI SCI device. Unregisters the clock provider registered
|
||||
* via common clock framework. Any memory allocated for the device will
|
||||
* be free'd silently via the devm framework. Returns 0 always.
|
||||
*/
|
||||
static int ti_sci_clk_remove(struct platform_device *pdev)
|
||||
{
|
||||
of_clk_del_provider(pdev->dev.of_node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ti_sci_clk_driver = {
|
||||
.probe = ti_sci_clk_probe,
|
||||
.remove = ti_sci_clk_remove,
|
||||
.driver = {
|
||||
.name = "ti-sci-clk",
|
||||
.of_match_table = of_match_ptr(ti_sci_clk_of_match),
|
||||
},
|
||||
};
|
||||
module_platform_driver(ti_sci_clk_driver);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("TI System Control Interface(SCI) Clock driver");
|
||||
MODULE_AUTHOR("Tero Kristo");
|
||||
MODULE_ALIAS("platform:ti-sci-clk");
|
@ -1,4 +1,4 @@
|
||||
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
|
||||
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o
|
||||
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o
|
||||
|
120
drivers/clk/mediatek/clk-cpumux.c
Normal file
120
drivers/clk/mediatek/clk-cpumux.c
Normal 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;
|
||||
}
|
30
drivers/clk/mediatek/clk-cpumux.h
Normal file
30
drivers/clk/mediatek/clk-cpumux.h
Normal 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 */
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -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, ®);
|
||||
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);
|
||||
|
@ -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},
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -17,6 +17,7 @@ obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
|
||||
obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
|
||||
obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
|
||||
obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
|
||||
obj-$(CONFIG_IPQ_GCC_8074) += gcc-ipq8074.o
|
||||
obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o
|
||||
obj-$(CONFIG_MDM_GCC_9615) += gcc-mdm9615.o
|
||||
obj-$(CONFIG_MDM_LCC_9615) += lcc-mdm9615.o
|
||||
|
1007
drivers/clk/qcom/gcc-ipq8074.c
Normal file
1007
drivers/clk/qcom/gcc-ipq8074.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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),
|
||||
{ }
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -167,16 +167,12 @@ static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = {
|
||||
DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scifa3", 1106, R8A7745_CLK_MP),
|
||||
DEF_MOD("scifa4", 1107, R8A7745_CLK_MP),
|
||||
DEF_MOD("scifa5", 1108, R8A7745_CLK_MP),
|
||||
@ -194,31 +190,22 @@ static const unsigned int r8a7745_crit_mod_clks[] __initconst = {
|
||||
* MD EXTAL PLL0 PLL1 PLL3
|
||||
* 14 13 19 (MHz) *1 *2
|
||||
*---------------------------------------------------
|
||||
* 0 0 0 15 x200/3 x208/2 x106
|
||||
* 0 0 1 15 x200/3 x208/2 x88
|
||||
* 0 1 0 20 x150/3 x156/2 x80
|
||||
* 0 1 1 20 x150/3 x156/2 x66
|
||||
* 1 0 0 26 / 2 x230/3 x240/2 x122
|
||||
* 1 0 1 26 / 2 x230/3 x240/2 x102
|
||||
* 1 1 0 30 / 2 x200/3 x208/2 x106
|
||||
* 1 1 1 30 / 2 x200/3 x208/2 x88
|
||||
*
|
||||
* *1 : Table 7.5b indicates VCO output (PLL0 = VCO/3)
|
||||
* *2 : Table 7.5b indicates VCO output (PLL1 = VCO/2)
|
||||
*/
|
||||
#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
|
||||
(((md) & BIT(13)) >> 12) | \
|
||||
(((md) & BIT(19)) >> 19))
|
||||
#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \
|
||||
(((md) & BIT(13)) >> 13))
|
||||
|
||||
static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
|
||||
/* EXTAL div PLL1 mult PLL3 mult PLL0 mult */
|
||||
{ 1, 208, 106, 200 },
|
||||
{ 1, 208, 88, 200 },
|
||||
{ 1, 156, 80, 150 },
|
||||
{ 1, 156, 66, 150 },
|
||||
{ 2, 240, 122, 230 },
|
||||
{ 2, 240, 102, 230 },
|
||||
{ 2, 208, 106, 200 },
|
||||
{ 2, 208, 88, 200 },
|
||||
};
|
||||
|
||||
|
278
drivers/clk/renesas/r8a7790-cpg-mssr.c
Normal file
278
drivers/clk/renesas/r8a7790-cpg-mssr.c
Normal 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,
|
||||
};
|
286
drivers/clk/renesas/r8a7791-cpg-mssr.c
Normal file
286
drivers/clk/renesas/r8a7791-cpg-mssr.c
Normal 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,
|
||||
};
|
221
drivers/clk/renesas/r8a7792-cpg-mssr.c
Normal file
221
drivers/clk/renesas/r8a7792-cpg-mssr.c
Normal 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,
|
||||
};
|
255
drivers/clk/renesas/r8a7794-cpg-mssr.c
Normal file
255
drivers/clk/renesas/r8a7794-cpg-mssr.c
Normal 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,
|
||||
};
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
@ -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 = {
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -436,6 +436,7 @@ static const char *const rk3036_critical_clocks[] __initconst = {
|
||||
"aclk_peri",
|
||||
"hclk_peri",
|
||||
"pclk_peri",
|
||||
"pclk_ddrupctl",
|
||||
};
|
||||
|
||||
static void __init rk3036_clk_init(struct device_node *np)
|
||||
|
612
drivers/clk/rockchip/clk-rk3128.c
Normal file
612
drivers/clk/rockchip/clk-rk3128.c
Normal 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);
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 = {
|
||||
|
@ -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
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -180,6 +180,9 @@ static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0);
|
||||
|
||||
static const char * const ahb1_parents[] = { "osc32k", "osc24M",
|
||||
"axi" , "pll-periph" };
|
||||
static const struct ccu_mux_var_prediv ahb1_predivs[] = {
|
||||
{ .index = 3, .shift = 6, .width = 2 },
|
||||
};
|
||||
static struct ccu_div ahb1_clk = {
|
||||
.div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
|
||||
|
||||
@ -187,11 +190,8 @@ static struct ccu_div ahb1_clk = {
|
||||
.shift = 12,
|
||||
.width = 2,
|
||||
|
||||
.variable_prediv = {
|
||||
.index = 3,
|
||||
.shift = 6,
|
||||
.width = 2,
|
||||
},
|
||||
.var_predivs = ahb1_predivs,
|
||||
.n_var_predivs = ARRAY_SIZE(ahb1_predivs),
|
||||
},
|
||||
|
||||
.common = {
|
||||
|
922
drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
Normal file
922
drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
Normal 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);
|
64
drivers/clk/sunxi-ng/ccu-sun8i-a83t.h
Normal file
64
drivers/clk/sunxi-ng/ccu-sun8i-a83t.h
Normal 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
Loading…
x
Reference in New Issue
Block a user