Commit dddd564d authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents dd6ec12f 3cf50f6b
...@@ -7,6 +7,14 @@ registers giving access to numerous features: clocks, pin-muxing and ...@@ -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 many other SoC configuration items. This DT binding allows to describe
this system controller. 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 The Device Tree node representing the AP806 system controller provides
a number of clocks: a number of clocks:
...@@ -17,19 +25,76 @@ a number of clocks: ...@@ -17,19 +25,76 @@ a number of clocks:
Required properties: Required properties:
- compatible: must be: - compatible: must be: "marvell,ap806-clock"
"marvell,ap806-system-controller", "syscon"
- reg: register area of the AP806 system controller
- #clock-cells: must be set to 1 - #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: Example:
ap_syscon: system-controller@6f4000 {
compatible = "syscon", "simple-mfd";
reg = <0x6f4000 0x1000>;
syscon: system-controller@6f4000 { ap_clk: clock {
compatible = "marvell,ap806-system-controller", "syscon"; compatible = "marvell,ap806-clock";
#clock-cells = <1>; #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 ...@@ -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 to describe the first system controller, which provides registers to
configure various aspects of the SoC. 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 The Device Tree node representing this System Controller 0 provides a
number of clocks: number of clocks:
...@@ -27,6 +34,7 @@ The following clocks are available: ...@@ -27,6 +34,7 @@ The following clocks are available:
- 0 2 EIP - 0 2 EIP
- 0 3 Core - 0 3 Core
- 0 4 NAND core - 0 4 NAND core
- 0 5 SDIO core
- Gatable clocks - Gatable clocks
- 1 0 Audio - 1 0 Audio
- 1 1 Comm Unit - 1 1 Comm Unit
...@@ -56,28 +64,126 @@ The following clocks are available: ...@@ -56,28 +64,126 @@ The following clocks are available:
Required properties: Required properties:
- compatible: must be: - compatible: must be:
"marvell,cp110-system-controller0", "syscon"; "marvell,cp110-clock"
- reg: register area of the CP110 system controller 0
- #clock-cells: must be set to 2 - #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" Pinctrl:
- 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", For common binding part and usage, refer to the file
"cpm-pcie_x10", "cpm-pcie_x11", "cpm-pcie_x4", "cpm-pcie-xor", "cpm-sata", Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt.
"cpm-sata-usb", "cpm-main", "cpm-sd-mmc-gop", "none", "none", "cpm-slow-io",
"cpm-usb3h0", "cpm-usb3h1", "cpm-usb3dev", "cpm-eip150", "cpm-eip197"; 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: Example:
cpm_syscon0: system-controller@440000 { cpm_syscon0: system-controller@440000 {
compatible = "marvell,cp110-system-controller0", "syscon"; compatible = "syscon", "simple-mfd";
reg = <0x440000 0x1000>; reg = <0x440000 0x1000>;
cpm_clk: clock {
compatible = "marvell,cp110-clock";
#clock-cells = <2>; #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";
};
};
* 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 The Amlogic Meson8 / Meson8b / Meson8m2 clock controller generates and
controllers within the SoC. supplies clock to various controllers within the SoC.
Required Properties: 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: - reg: it must be composed by two tuples:
0) physical base address of the xtal register and length of memory 0) physical base address of the xtal register and length of memory
mapped region. mapped region.
......
...@@ -11,6 +11,7 @@ Required Properties: ...@@ -11,6 +11,7 @@ Required Properties:
- compatible: the compatible should be one of the following strings to - compatible: the compatible should be one of the following strings to
indicate the clock controller functionality. indicate the clock controller functionality.
- "hisilicon,hi6220-acpu-sctrl"
- "hisilicon,hi6220-aoctrl" - "hisilicon,hi6220-aoctrl"
- "hisilicon,hi6220-sysctrl" - "hisilicon,hi6220-sysctrl"
- "hisilicon,hi6220-mediactrl" - "hisilicon,hi6220-mediactrl"
......
...@@ -8,6 +8,7 @@ Required properties : ...@@ -8,6 +8,7 @@ Required properties :
"qcom,gcc-apq8084" "qcom,gcc-apq8084"
"qcom,gcc-ipq8064" "qcom,gcc-ipq8064"
"qcom,gcc-ipq4019" "qcom,gcc-ipq4019"
"qcom,gcc-ipq8074"
"qcom,gcc-msm8660" "qcom,gcc-msm8660"
"qcom,gcc-msm8916" "qcom,gcc-msm8916"
"qcom,gcc-msm8960" "qcom,gcc-msm8960"
......
...@@ -57,6 +57,11 @@ Optional properties: ...@@ -57,6 +57,11 @@ Optional properties:
- clocks: If clock-frequency is not specified, sysclk may be provided - clocks: If clock-frequency is not specified, sysclk may be provided
as an input clock. Either clock-frequency or clocks must be as an input clock. Either clock-frequency or clocks must be
provided. 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 2. Clock Provider
...@@ -73,6 +78,7 @@ second cell is the clock index for the specified type. ...@@ -73,6 +78,7 @@ second cell is the clock index for the specified type.
2 hwaccel index (n in CLKCGnHWACSR) 2 hwaccel index (n in CLKCGnHWACSR)
3 fman 0 for fm1, 1 for fm2 3 fman 0 for fm1, 1 for fm2
4 platform pll 0=pll, 1=pll/2, 2=pll/3, 3=pll/4 4 platform pll 0=pll, 1=pll/2, 2=pll/3, 3=pll/4
5 coreclk must be 0
3. Example 3. Example
......
...@@ -15,6 +15,11 @@ Required Properties: ...@@ -15,6 +15,11 @@ Required Properties:
- compatible: Must be one of: - compatible: Must be one of:
- "renesas,r8a7743-cpg-mssr" for the r8a7743 SoC (RZ/G1M) - "renesas,r8a7743-cpg-mssr" for the r8a7743 SoC (RZ/G1M)
- "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E) - "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,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3)
- "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W) - "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W)
...@@ -24,9 +29,10 @@ Required Properties: ...@@ -24,9 +29,10 @@ Required Properties:
- clocks: References to external parent clocks, one entry for each entry in - clocks: References to external parent clocks, one entry for each entry in
clock-names clock-names
- clock-names: List of external parent clock names. Valid names are: - 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) - "extalr" (r8a7795, r8a7796)
- "usb_extal" (r8a7743, r8a7745) - "usb_extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7793, r8a7794)
- #clock-cells: Must be 2 - #clock-cells: Must be 2
- For CPG core clocks, the two clock specifier cells must be "CPG_CORE" - For CPG core clocks, the two clock specifier cells must be "CPG_CORE"
......
* 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";
};
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 : ...@@ -6,6 +6,8 @@ Required properties :
- "allwinner,sun6i-a31-ccu" - "allwinner,sun6i-a31-ccu"
- "allwinner,sun8i-a23-ccu" - "allwinner,sun8i-a23-ccu"
- "allwinner,sun8i-a33-ccu" - "allwinner,sun8i-a33-ccu"
- "allwinner,sun8i-a83t-ccu"
- "allwinner,sun8i-a83t-r-ccu"
- "allwinner,sun8i-h3-ccu" - "allwinner,sun8i-h3-ccu"
- "allwinner,sun8i-h3-r-ccu" - "allwinner,sun8i-h3-r-ccu"
- "allwinner,sun8i-v3s-ccu" - "allwinner,sun8i-v3s-ccu"
...@@ -18,11 +20,12 @@ Required properties : ...@@ -18,11 +20,12 @@ Required properties :
- clocks: phandle to the oscillators feeding the CCU. Two are needed: - clocks: phandle to the oscillators feeding the CCU. Two are needed:
- "hosc": the high frequency oscillator (usually at 24MHz) - "hosc": the high frequency oscillator (usually at 24MHz)
- "losc": the low frequency oscillator (usually at 32kHz) - "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-names: Must contain the clock names described just above
- #clock-cells : must contain 1 - #clock-cells : must contain 1
- #reset-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 - "pll-periph": the SoC's peripheral PLL from the main CCU
- "iosc": the SoC's internal frequency oscillator - "iosc": the SoC's internal frequency oscillator
......
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>;
};
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 @@ ...@@ -2,17 +2,27 @@
Required properties: Required properties:
- compatible : Should be "marvell,orion-gpio", "marvell,mv78200-gpio" - compatible : Should be "marvell,orion-gpio", "marvell,mv78200-gpio",
or "marvell,armadaxp-gpio". "marvell,orion-gpio" should be used for "marvell,armadaxp-gpio" or "marvell,armada-8k-gpio".
Orion, Kirkwood, Dove, Discovery (except MV78200) and Armada
370. "marvell,mv78200-gpio" should be used for the Discovery "marvell,orion-gpio" should be used for Orion, Kirkwood, Dove,
MV78200. "marvel,armadaxp-gpio" should be used for all Armada XP Discovery (except MV78200) and Armada 370. "marvell,mv78200-gpio"
SoCs (MV78230, MV78260, MV78460). 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 - reg: Address and length of the register set for the device. Only one
entry is expected, except for the "marvell,armadaxp-gpio" variant entry is expected, except for the "marvell,armadaxp-gpio" variant
for which two entries are expected: one for the general registers, 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 - interrupts: The list of interrupts that are used for all the pins
managed by this GPIO bank. There can be more than one interrupt 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 ...@@ -12872,6 +12872,8 @@ F: Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
F: include/dt-bindings/genpd/k2g.h F: include/dt-bindings/genpd/k2g.h
F: drivers/soc/ti/ti_sci_pm_domains.c F: drivers/soc/ti/ti_sci_pm_domains.c
F: Documentation/devicetree/bindings/reset/ti,sci-reset.txt 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 F: drivers/reset/reset-ti-sci.c
THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER
......
...@@ -160,11 +160,6 @@ void clk_deactivate(struct clk *clk) ...@@ -160,11 +160,6 @@ void clk_deactivate(struct clk *clk)
} }
EXPORT_SYMBOL(clk_deactivate); 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) static inline u32 get_counter_resolution(void)
{ {
u32 res; u32 res;
......
...@@ -126,6 +126,15 @@ config COMMON_CLK_CS2000_CP ...@@ -126,6 +126,15 @@ config COMMON_CLK_CS2000_CP
help help
If you say yes here you get support for the CS2000 clock multiplier. 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 config COMMON_CLK_S2MPS11
tristate "Clock driver for S2MPS1X/S5M8767 MFD" tristate "Clock driver for S2MPS1X/S5M8767 MFD"
depends on MFD_SEC_CORE || COMPILE_TEST depends on MFD_SEC_CORE || COMPILE_TEST
...@@ -164,13 +173,6 @@ config COMMON_CLK_XGENE ...@@ -164,13 +173,6 @@ config COMMON_CLK_XGENE
---help--- ---help---
Sypport for the APM X-Gene SoC reference, PLL, and device clocks. 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 config COMMON_CLK_NXP
def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX) def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
select REGMAP_MMIO if ARCH_LPC32XX select REGMAP_MMIO if ARCH_LPC32XX
...@@ -219,6 +221,7 @@ config COMMON_CLK_VC5 ...@@ -219,6 +221,7 @@ config COMMON_CLK_VC5
source "drivers/clk/bcm/Kconfig" source "drivers/clk/bcm/Kconfig"
source "drivers/clk/hisilicon/Kconfig" source "drivers/clk/hisilicon/Kconfig"
source "drivers/clk/keystone/Kconfig"
source "drivers/clk/mediatek/Kconfig" source "drivers/clk/mediatek/Kconfig"
source "drivers/clk/meson/Kconfig" source "drivers/clk/meson/Kconfig"
source "drivers/clk/mvebu/Kconfig" source "drivers/clk/mvebu/Kconfig"
......
# common clock types # 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_CLKDEV_LOOKUP) += clkdev.o
obj-$(CONFIG_COMMON_CLK) += clk.o obj-$(CONFIG_COMMON_CLK) += clk.o
obj-$(CONFIG_COMMON_CLK) += clk-divider.o obj-$(CONFIG_COMMON_CLK) += clk-divider.o
...@@ -25,6 +25,7 @@ obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o ...@@ -25,6 +25,7 @@ obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o
obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o
obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.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_ARCH_HIGHBANK) += clk-highbank.o
obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o
...@@ -61,7 +62,7 @@ obj-$(CONFIG_H8300) += h8300/ ...@@ -61,7 +62,7 @@ obj-$(CONFIG_H8300) += h8300/
obj-$(CONFIG_ARCH_HISI) += hisilicon/ obj-$(CONFIG_ARCH_HISI) += hisilicon/
obj-$(CONFIG_ARCH_MXC) += imx/ obj-$(CONFIG_ARCH_MXC) += imx/
obj-$(CONFIG_MACH_INGENIC) += ingenic/ obj-$(CONFIG_MACH_INGENIC) += ingenic/
obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ obj-$(CONFIG_ARCH_KEYSTONE) += keystone/
obj-$(CONFIG_MACH_LOONGSON32) += loongson1/ obj-$(CONFIG_MACH_LOONGSON32) += loongson1/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += meson/ obj-$(CONFIG_COMMON_CLK_AMLOGIC) += meson/
...@@ -75,7 +76,7 @@ obj-$(CONFIG_COMMON_CLK_NXP) += nxp/ ...@@ -75,7 +76,7 @@ obj-$(CONFIG_COMMON_CLK_NXP) += nxp/
obj-$(CONFIG_MACH_PISTACHIO) += pistachio/ obj-$(CONFIG_MACH_PISTACHIO) += pistachio/
obj-$(CONFIG_COMMON_CLK_PXA) += pxa/ obj-$(CONFIG_COMMON_CLK_PXA) += pxa/
obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/
obj-$(CONFIG_ARCH_RENESAS) += renesas/ obj-y += renesas/
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
obj-$(CONFIG_ARCH_SIRF) += sirf/ obj-$(CONFIG_ARCH_SIRF) += sirf/
......
...@@ -260,13 +260,15 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, ...@@ -260,13 +260,15 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
gck->lock = lock; gck->lock = lock;
gck->range = *range; gck->range = *range;
clk_generated_startup(gck);
hw = &gck->hw; hw = &gck->hw;
ret = clk_hw_register(NULL, &gck->hw); ret = clk_hw_register(NULL, &gck->hw);
if (ret) { if (ret) {
kfree(gck); kfree(gck);
hw = ERR_PTR(ret); hw = ERR_PTR(ret);
} else } else {
clk_generated_startup(gck); pmc_register_id(id);
}
return hw; return hw;
} }
......
...@@ -367,8 +367,10 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock, ...@@ -367,8 +367,10 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
if (ret) { if (ret) {
kfree(periph); kfree(periph);
hw = ERR_PTR(ret); hw = ERR_PTR(ret);
} else } else {
clk_sam9x5_peripheral_autodiv(periph); clk_sam9x5_peripheral_autodiv(periph);
pmc_register_id(id);
}
return hw; return hw;
} }
......
...@@ -13,12 +13,16 @@ ...@@ -13,12 +13,16 @@
#include <linux/clk/at91_pmc.h> #include <linux/clk/at91_pmc.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/syscore_ops.h>
#include <asm/proc-fns.h> #include <asm/proc-fns.h>
#include "pmc.h" #include "pmc.h"
#define PMC_MAX_IDS 128
int of_at91_get_clk_range(struct device_node *np, const char *propname, int of_at91_get_clk_range(struct device_node *np, const char *propname,
struct clk_range *range) struct clk_range *range)
{ {
...@@ -41,3 +45,128 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname, ...@@ -41,3 +45,128 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname,
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(of_at91_get_clk_range); 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 { ...@@ -29,4 +29,10 @@ struct clk_range {
int of_at91_get_clk_range(struct device_node *np, const char *propname, int of_at91_get_clk_range(struct device_node *np, const char *propname,
struct clk_range *range); 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_ */ #endif /* __PMC_H_ */
...@@ -46,3 +46,11 @@ config CLK_BCM_NS2 ...@@ -46,3 +46,11 @@ config CLK_BCM_NS2
default ARCH_BCM_IPROC default ARCH_BCM_IPROC
help help
Enable common clock framework support for the Broadcom Northstar 2 SoC 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 ...@@ -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_CYGNUS) += clk-cygnus.o
obj-$(CONFIG_CLK_BCM_NSP) += clk-nsp.o obj-$(CONFIG_CLK_BCM_NSP) += clk-nsp.o
obj-$(CONFIG_CLK_BCM_NS2) += clk-ns2.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 { ...@@ -530,6 +530,7 @@ struct bcm2835_clock_data {
bool is_vpu_clock; bool is_vpu_clock;
bool is_mash_clock; bool is_mash_clock;
bool low_jitter;
u32 tcnt_mux; u32 tcnt_mux;
}; };
...@@ -616,8 +617,10 @@ static unsigned long bcm2835_pll_get_rate(struct clk_hw *hw, ...@@ -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) & using_prediv = cprman_read(cprman, data->ana_reg_base + 4) &
data->ana->fb_prediv_mask; data->ana->fb_prediv_mask;
if (using_prediv) if (using_prediv) {
ndiv *= 2; ndiv *= 2;
fdiv *= 2;
}
return bcm2835_pll_rate_from_divisors(parent_rate, ndiv, fdiv, pdiv); 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, ...@@ -1124,7 +1127,8 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
int parent_idx, int parent_idx,
unsigned long rate, unsigned long rate,
u32 *div, u32 *div,
unsigned long *prate) unsigned long *prate,
unsigned long *avgrate)
{ {
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
struct bcm2835_cprman *cprman = clock->cprman; struct bcm2835_cprman *cprman = clock->cprman;
...@@ -1139,8 +1143,25 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw, ...@@ -1139,8 +1143,25 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
*prate = clk_hw_get_rate(parent); *prate = clk_hw_get_rate(parent);
*div = bcm2835_clock_choose_div(hw, rate, *prate, true); *div = bcm2835_clock_choose_div(hw, rate, *prate, true);
return bcm2835_clock_rate_from_divisor(clock, *prate, *avgrate = bcm2835_clock_rate_from_divisor(clock, *prate, *div);
*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) if (data->frac_bits)
...@@ -1167,6 +1188,7 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw, ...@@ -1167,6 +1188,7 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
*div = curdiv << CM_DIV_FRAC_BITS; *div = curdiv << CM_DIV_FRAC_BITS;
*prate = curdiv * best_rate; *prate = curdiv * best_rate;
*avgrate = best_rate;
return best_rate; return best_rate;
} }
...@@ -1178,6 +1200,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw, ...@@ -1178,6 +1200,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
bool current_parent_is_pllc; bool current_parent_is_pllc;
unsigned long rate, best_rate = 0; unsigned long rate, best_rate = 0;
unsigned long prate, best_prate = 0; unsigned long prate, best_prate = 0;
unsigned long avgrate, best_avgrate = 0;
size_t i; size_t i;
u32 div; u32 div;
...@@ -1202,11 +1225,13 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw, ...@@ -1202,11 +1225,13 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
continue; continue;
rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate, rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
&div, &prate); &div, &prate,
&avgrate);
if (rate > best_rate && rate <= req->rate) { if (rate > best_rate && rate <= req->rate) {
best_parent = parent; best_parent = parent;
best_prate = prate; best_prate = prate;
best_rate = rate; best_rate = rate;
best_avgrate = avgrate;
} }
} }
...@@ -1216,7 +1241,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw, ...@@ -1216,7 +1241,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
req->best_parent_hw = best_parent; req->best_parent_hw = best_parent;
req->best_parent_rate = best_prate; req->best_parent_rate = best_prate;
req->rate = best_rate; req->rate = best_avgrate;
return 0; return 0;
} }
...@@ -1516,6 +1541,31 @@ static const char *const bcm2835_clock_per_parents[] = { ...@@ -1516,6 +1541,31 @@ static const char *const bcm2835_clock_per_parents[] = {
.parents = bcm2835_clock_per_parents, \ .parents = bcm2835_clock_per_parents, \
__VA_ARGS__) __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 */ /* main vpu parent mux */
static const char *const bcm2835_clock_vpu_parents[] = { static const char *const bcm2835_clock_vpu_parents[] = {
"gnd", "gnd",
...@@ -1993,13 +2043,14 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { ...@@ -1993,13 +2043,14 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.int_bits = 4, .int_bits = 4,
.frac_bits = 8, .frac_bits = 8,
.tcnt_mux = 22), .tcnt_mux = 22),
[BCM2835_CLOCK_PCM] = REGISTER_PER_CLK( [BCM2835_CLOCK_PCM] = REGISTER_PCM_CLK(
.name = "pcm", .name = "pcm",
.ctl_reg = CM_PCMCTL, .ctl_reg = CM_PCMCTL,
.div_reg = CM_PCMDIV, .div_reg = CM_PCMDIV,
.int_bits = 12, .int_bits = 12,
.frac_bits = 12, .frac_bits = 12,
.is_mash_clock = true, .is_mash_clock = true,
.low_jitter = true,
.tcnt_mux = 23), .tcnt_mux = 23),
[BCM2835_CLOCK_PWM] = REGISTER_PER_CLK( [BCM2835_CLOCK_PWM] = REGISTER_PER_CLK(
.name = "pwm", .name = "pwm",
......
...@@ -617,7 +617,7 @@ static void iproc_pll_sw_cfg(struct iproc_pll *pll) ...@@ -617,7 +617,7 @@ static void iproc_pll_sw_cfg(struct iproc_pll *pll)
} }
} }
void __init iproc_pll_clk_setup(struct device_node *node, void iproc_pll_clk_setup(struct device_node *node,
const struct iproc_pll_ctrl *pll_ctrl, const struct iproc_pll_ctrl *pll_ctrl,
const struct iproc_pll_vco_param *vco, const struct iproc_pll_vco_param *vco,
unsigned int num_vco_entries, unsigned int num_vco_entries,
......
/*
* 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);
/*
* 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) ...@@ -109,7 +109,7 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
rc = clk_set_rate(clk, rate); rc = clk_set_rate(clk, rate);
if (rc < 0) 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_name(clk), rate, rc,
clk_get_rate(clk)); clk_get_rate(clk));
clk_put(clk); clk_put(clk);
......
...@@ -34,6 +34,42 @@ struct clk *devm_clk_get(struct device *dev, const char *id) ...@@ -34,6 +34,42 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
} }
EXPORT_SYMBOL(devm_clk_get); 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) static int devm_clk_match(struct device *dev, void *res, void *data)
{ {
struct clk **c = res; struct clk **c = res;
......
...@@ -275,7 +275,8 @@ static int _next_div(const struct clk_div_table *table, int div, ...@@ -275,7 +275,8 @@ static int _next_div(const struct clk_div_table *table, int div,
return 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, unsigned long *best_parent_rate,
const struct clk_div_table *table, u8 width, const struct clk_div_table *table, u8 width,
unsigned long flags) unsigned long flags)
...@@ -314,8 +315,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, ...@@ -314,8 +315,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
*best_parent_rate = parent_rate_saved; *best_parent_rate = parent_rate_saved;
return i; return i;
} }
parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), parent_rate = clk_hw_round_rate(parent, rate * i);
rate * i);
now = DIV_ROUND_UP_ULL((u64)parent_rate, i); now = DIV_ROUND_UP_ULL((u64)parent_rate, i);
if (_is_best_div(rate, now, best, flags)) { if (_is_best_div(rate, now, best, flags)) {
bestdiv = i; bestdiv = i;
...@@ -326,23 +326,24 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, ...@@ -326,23 +326,24 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
if (!bestdiv) { if (!bestdiv) {
bestdiv = _get_maxdiv(table, width, flags); 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; return bestdiv;
} }
long divider_round_rate(struct clk_hw *hw, unsigned long rate, long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
unsigned long *prate, const struct clk_div_table *table, unsigned long rate, unsigned long *prate,
const struct clk_div_table *table,
u8 width, unsigned long flags) u8 width, unsigned long flags)
{ {
int div; 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); 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, static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate) unsigned long *prate)
......
This diff is collapsed.
...@@ -229,6 +229,7 @@ static int palmas_clks_init_configure(struct palmas_clock_info *cinfo) ...@@ -229,6 +229,7 @@ static int palmas_clks_init_configure(struct palmas_clock_info *cinfo)
if (ret < 0) { if (ret < 0) {
dev_err(cinfo->dev, "Ext config for %s failed, %d\n", dev_err(cinfo->dev, "Ext config for %s failed, %d\n",
cinfo->clk_desc->clk_name, ret); cinfo->clk_desc->clk_name, ret);
clk_unprepare(cinfo->hw.clk);
return ret; return ret;
} }
} }
......
...@@ -87,7 +87,7 @@ struct clockgen { ...@@ -87,7 +87,7 @@ struct clockgen {
struct device_node *node; struct device_node *node;
void __iomem *regs; void __iomem *regs;
struct clockgen_chipinfo info; /* mutable copy */ struct clockgen_chipinfo info; /* mutable copy */
struct clk *sysclk; struct clk *sysclk, *coreclk;
struct clockgen_pll pll[6]; struct clockgen_pll pll[6];
struct clk *cmux[NUM_CMUX]; struct clk *cmux[NUM_CMUX];
struct clk *hwaccel[NUM_HWACCEL]; struct clk *hwaccel[NUM_HWACCEL];
...@@ -904,7 +904,12 @@ static void __init create_muxes(struct clockgen *cg) ...@@ -904,7 +904,12 @@ static void __init create_muxes(struct clockgen *cg)
static void __init clockgen_init(struct device_node *np); 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) static void __init legacy_init_clockgen(struct device_node *np)
{ {
if (!clockgen.node) if (!clockgen.node)
...@@ -945,18 +950,13 @@ static struct clk __init ...@@ -945,18 +950,13 @@ static struct clk __init
return clk_register_fixed_rate(NULL, name, NULL, 0, rate); 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 *input_name;
const char *parent_name;
clk = of_clk_get(clockgen.node, 0);
if (IS_ERR(clk))
return clk;
/* Register the input clock under the desired name. */ /* Register the input clock under the desired name. */
parent_name = __clk_get_name(clk); input_name = __clk_get_name(clk);
clk = clk_register_fixed_factor(NULL, name, parent_name, clk = clk_register_fixed_factor(NULL, name, input_name,
0, 1, 1); 0, 1, 1);
if (IS_ERR(clk)) if (IS_ERR(clk))
pr_err("%s: Couldn't register %s: %ld\n", __func__, name, pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
...@@ -965,6 +965,29 @@ static struct clk *sysclk_from_parent(const char *name) ...@@ -965,6 +965,29 @@ static struct clk *sysclk_from_parent(const char *name)
return clk; 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) static struct clk * __init create_sysclk(const char *name)
{ {
struct device_node *sysclk; struct device_node *sysclk;
...@@ -974,7 +997,11 @@ static struct clk * __init create_sysclk(const char *name) ...@@ -974,7 +997,11 @@ static struct clk * __init create_sysclk(const char *name)
if (!IS_ERR(clk)) if (!IS_ERR(clk))
return 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)) if (!IS_ERR(clk))
return clk; return clk;
...@@ -985,7 +1012,27 @@ static struct clk * __init create_sysclk(const char *name) ...@@ -985,7 +1012,27 @@ static struct clk * __init create_sysclk(const char *name)
return clk; 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; return NULL;
} }
...@@ -1008,11 +1055,19 @@ static void __init create_one_pll(struct clockgen *cg, int idx) ...@@ -1008,11 +1055,19 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
u32 __iomem *reg; u32 __iomem *reg;
u32 mult; u32 mult;
struct clockgen_pll *pll = &cg->pll[idx]; struct clockgen_pll *pll = &cg->pll[idx];
const char *input = "cg-sysclk";
int i; int i;
if (!(cg->info.pll_mask & (1 << idx))) if (!(cg->info.pll_mask & (1 << idx)))
return; return;
if (cg->coreclk && idx != PLATFORM_PLL) {
if (IS_ERR(cg->coreclk))
return;
input = "cg-coreclk";
}
if (cg->info.flags & CG_VER3) { if (cg->info.flags & CG_VER3) {
switch (idx) { switch (idx) {
case PLATFORM_PLL: case PLATFORM_PLL:
...@@ -1063,7 +1118,7 @@ static void __init create_one_pll(struct clockgen *cg, int idx) ...@@ -1063,7 +1118,7 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
"cg-pll%d-div%d", idx, i + 1); "cg-pll%d-div%d", idx, i + 1);
clk = clk_register_fixed_factor(NULL, 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)) { if (IS_ERR(clk)) {
pr_err("%s: %s: register failed %ld\n", pr_err("%s: %s: register failed %ld\n",
__func__, pll->div[i].name, PTR_ERR(clk)); __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) ...@@ -1200,6 +1255,13 @@ static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data)
goto bad_args; goto bad_args;
clk = pll->div[idx].clk; clk = pll->div[idx].clk;
break; break;
case 5:
if (idx != 0)
goto bad_args;
clk = cg->coreclk;
if (IS_ERR(clk))
clk = NULL;
break;
default: default:
goto bad_args; goto bad_args;
} }
...@@ -1311,6 +1373,7 @@ static void __init clockgen_init(struct device_node *np) ...@@ -1311,6 +1373,7 @@ static void __init clockgen_init(struct device_node *np)
clockgen.info.flags |= CG_CMUX_GE_PLAT; clockgen.info.flags |= CG_CMUX_GE_PLAT;
clockgen.sysclk = create_sysclk("cg-sysclk"); clockgen.sysclk = create_sysclk("cg-sysclk");
clockgen.coreclk = create_coreclk("cg-coreclk");
create_plls(&clockgen); create_plls(&clockgen);
create_muxes(&clockgen); create_muxes(&clockgen);
......
...@@ -71,15 +71,15 @@ static const struct clk_ops scpi_clk_ops = { ...@@ -71,15 +71,15 @@ static const struct clk_ops scpi_clk_ops = {
}; };
/* find closest match to given frequency in OPP table */ /* 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; int idx;
u32 fmin = 0, fmax = ~0, ftmp; unsigned long fmin = 0, fmax = ~0, ftmp;
const struct scpi_opp *opp = clk->info->opps; const struct scpi_opp *opp = clk->info->opps;
for (idx = 0; idx < clk->info->count; idx++, opp++) { for (idx = 0; idx < clk->info->count; idx++, opp++) {
ftmp = opp->freq; ftmp = opp->freq;
if (ftmp >= (u32)rate) { if (ftmp >= rate) {
if (ftmp <= fmax) if (ftmp <= fmax)
fmax = ftmp; fmax = ftmp;
break; break;
...@@ -245,9 +245,11 @@ static int scpi_clk_add(struct device *dev, struct device_node *np, ...@@ -245,9 +245,11 @@ static int scpi_clk_add(struct device *dev, struct device_node *np,
sclk->id = val; sclk->id = val;
err = scpi_clk_ops_init(dev, match, sclk, name); err = scpi_clk_ops_init(dev, match, sclk, name);
if (err) if (err) {
dev_err(dev, "failed to register clock '%s'\n", name); dev_err(dev, "failed to register clock '%s'\n", name);
else return err;
}
dev_dbg(dev, "Registered clock '%s'\n", name); dev_dbg(dev, "Registered clock '%s'\n", name);
clk_data->clk[idx] = sclk; clk_data->clk[idx] = sclk;
} }
......
This diff is collapsed.
...@@ -285,3 +285,25 @@ static void __init hi6220_clk_power_init(struct device_node *np) ...@@ -285,3 +285,25 @@ static void __init hi6220_clk_power_init(struct device_node *np)
ARRAY_SIZE(hi6220_div_clks_power), clk_data); ARRAY_SIZE(hi6220_div_clks_power), clk_data);
} }
CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-pmctrl", hi6220_clk_power_init); 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 @@ ...@@ -44,6 +44,9 @@
#define HI3798CV200_ETH_BUS0_CLK 78 #define HI3798CV200_ETH_BUS0_CLK 78
#define HI3798CV200_ETH_BUS1_CLK 79 #define HI3798CV200_ETH_BUS1_CLK 79
#define HI3798CV200_COMBPHY1_MUX 80 #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 #define HI3798CV200_CRG_NR_CLKS 128
...@@ -51,9 +54,12 @@ static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = { ...@@ -51,9 +54,12 @@ static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = {
{ HISTB_OSC_CLK, "clk_osc", NULL, 0, 24000000, }, { HISTB_OSC_CLK, "clk_osc", NULL, 0, 24000000, },
{ HISTB_APB_CLK, "clk_apb", NULL, 0, 100000000, }, { HISTB_APB_CLK, "clk_apb", NULL, 0, 100000000, },
{ HISTB_AHB_CLK, "clk_ahb", NULL, 0, 200000000, }, { HISTB_AHB_CLK, "clk_ahb", NULL, 0, 200000000, },
{ HI3798CV200_FIXED_12M, "12m", NULL, 0, 12000000, },
{ HI3798CV200_FIXED_24M, "24m", NULL, 0, 24000000, }, { HI3798CV200_FIXED_24M, "24m", NULL, 0, 24000000, },
{ HI3798CV200_FIXED_25M, "25m", NULL, 0, 25000000, }, { HI3798CV200_FIXED_25M, "25m", NULL, 0, 25000000, },
{ HI3798CV200_FIXED_48M, "48m", NULL, 0, 48000000, },
{ HI3798CV200_FIXED_50M, "50m", NULL, 0, 50000000, }, { HI3798CV200_FIXED_50M, "50m", NULL, 0, 50000000, },
{ HI3798CV200_FIXED_60M, "60m", NULL, 0, 60000000, },
{ HI3798CV200_FIXED_75M, "75m", NULL, 0, 75000000, }, { HI3798CV200_FIXED_75M, "75m", NULL, 0, 75000000, },
{ HI3798CV200_FIXED_100M, "100m", NULL, 0, 100000000, }, { HI3798CV200_FIXED_100M, "100m", NULL, 0, 100000000, },
{ HI3798CV200_FIXED_150M, "150m", NULL, 0, 150000000, }, { HI3798CV200_FIXED_150M, "150m", NULL, 0, 150000000, },
...@@ -134,6 +140,21 @@ static const struct hisi_gate_clock hi3798cv200_gate_clks[] = { ...@@ -134,6 +140,21 @@ static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
/* COMBPHY1 */ /* COMBPHY1 */
{ HISTB_COMBPHY1_CLK, "clk_combphy1", "combphy1_mux", { HISTB_COMBPHY1_CLK, "clk_combphy1", "combphy1_mux",
CLK_SET_RATE_PARENT, 0x188, 8, 0, }, 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( static struct hisi_clock_data *hi3798cv200_clk_register(
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
static u32 share_count_sai1; static u32 share_count_sai1;
static u32 share_count_sai2; static u32 share_count_sai2;
static u32 share_count_sai3; static u32 share_count_sai3;
static u32 share_count_nand;
static struct clk_div_table test_div_table[] = { static struct clk_div_table test_div_table[] = {
{ .val = 3, .div = 1, }, { .val = 3, .div = 1, },
...@@ -424,7 +425,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) ...@@ -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_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_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_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_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); 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) ...@@ -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_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_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_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_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_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); 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) ...@@ -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_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_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_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_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_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); clks[IMX7D_USDHC2_ROOT_CLK] = imx_clk_gate4("usdhc2_root_clk", "usdhc2_post_div", base + 0x46d0, 0);
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define BM_PLL_POWER (0x1 << 12) #define BM_PLL_POWER (0x1 << 12)
#define BM_PLL_LOCK (0x1 << 31) #define BM_PLL_LOCK (0x1 << 31)
#define IMX7_ENET_PLL_POWER (0x1 << 5) #define IMX7_ENET_PLL_POWER (0x1 << 5)
#define IMX7_DDR_PLL_POWER (0x1 << 20)
/** /**
* struct clk_pllv3 - IMX PLL clock version 3 * 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, ...@@ -451,6 +452,10 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
pll->ref_clock = 500000000; pll->ref_clock = 500000000;
ops = &clk_pllv3_enet_ops; ops = &clk_pllv3_enet_ops;
break; break;
case IMX_PLLV3_DDR_IMX7:
pll->power_bit = IMX7_DDR_PLL_POWER;
ops = &clk_pllv3_av_ops;
break;
default: default:
ops = &clk_pllv3_ops; ops = &clk_pllv3_ops;
} }
......
...@@ -35,6 +35,7 @@ enum imx_pllv3_type { ...@@ -35,6 +35,7 @@ enum imx_pllv3_type {
IMX_PLLV3_ENET, IMX_PLLV3_ENET,
IMX_PLLV3_ENET_IMX7, IMX_PLLV3_ENET_IMX7,
IMX_PLLV3_SYS_VF610, IMX_PLLV3_SYS_VF610,
IMX_PLLV3_DDR_IMX7,
}; };
struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
......
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.
obj-y += pll.o gate.o obj-$(CONFIG_COMMON_CLK_KEYSTONE) += pll.o gate.o
obj-$(CONFIG_TI_SCI_CLK) += sci-clk.o
This diff is collapsed.
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_RESET_CONTROLLER) += reset.o
obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o
......
/*
* 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;
}
/*
* 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 @@ ...@@ -20,6 +20,7 @@
#include "clk-mtk.h" #include "clk-mtk.h"
#include "clk-gate.h" #include "clk-gate.h"
#include "clk-cpumux.h"
#include <dt-bindings/clock/mt2701-clk.h> #include <dt-bindings/clock/mt2701-clk.h>
...@@ -493,6 +494,10 @@ static const char * const cpu_parents[] = { ...@@ -493,6 +494,10 @@ static const char * const cpu_parents[] = {
"mmpll" "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[] = { static const struct mtk_composite top_muxes[] = {
MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
0x0040, 0, 3, 7, CLK_IS_CRITICAL), 0x0040, 0, 3, 7, CLK_IS_CRITICAL),
...@@ -759,6 +764,9 @@ static void mtk_infrasys_init_early(struct device_node *node) ...@@ -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), mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
infra_clk_data); 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); r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
if (r) if (r)
pr_err("%s(): could not register clock provider: %d\n", pr_err("%s(): could not register clock provider: %d\n",
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "clk-mtk.h" #include "clk-mtk.h"
#include "clk-gate.h" #include "clk-gate.h"
#include "clk-cpumux.h"
#include <dt-bindings/clock/mt8173-clk.h> #include <dt-bindings/clock/mt8173-clk.h>
...@@ -525,6 +526,25 @@ static const char * const i2s3_b_ck_parents[] __initconst = { ...@@ -525,6 +526,25 @@ static const char * const i2s3_b_ck_parents[] __initconst = {
"apll2_div5" "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 = { static const struct mtk_composite top_muxes[] __initconst = {
/* CLK_CFG_0 */ /* CLK_CFG_0 */
MUX(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3), 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) ...@@ -948,6 +968,9 @@ static void __init mtk_infrasys_init(struct device_node *node)
clk_data); clk_data);
mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), 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); r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r) if (r)
pr_err("%s(): could not register clock provider: %d\n", pr_err("%s(): could not register clock provider: %d\n",
......
...@@ -7,9 +7,9 @@ config COMMON_CLK_MESON8B ...@@ -7,9 +7,9 @@ config COMMON_CLK_MESON8B
bool bool
depends on COMMON_CLK_AMLOGIC depends on COMMON_CLK_AMLOGIC
help help
Support for the clock controller on AmLogic S805 devices, aka Support for the clock controller on AmLogic S802 (Meson8),
meson8b. Say Y if you want peripherals and CPU frequency scaling to S805 (Meson8b) and S812 (Meson8m2) devices. Say Y if you
work. want peripherals and CPU frequency scaling to work.
config COMMON_CLK_GXBB config COMMON_CLK_GXBB
bool bool
......
...@@ -278,20 +278,6 @@ static const struct pll_rate_table gxl_gp0_pll_rate_table[] = { ...@@ -278,20 +278,6 @@ static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
{ /* sentinel */ }, { /* 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 = { static struct meson_clk_pll gxbb_fixed_pll = {
.m = { .m = {
.reg_off = HHI_MPLL_CNTL, .reg_off = HHI_MPLL_CNTL,
...@@ -612,23 +598,16 @@ static struct meson_clk_mpll gxbb_mpll2 = { ...@@ -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 * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers
* post-dividers and should be modeled with their respective PLLs via the * and should be modeled with their respective PLLs via the forthcoming
* forthcoming coordinated clock rates feature * 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 = { static struct clk_mux gxbb_mpeg_clk_sel = {
.reg = (void *)HHI_MPEG_CLK_CNTL, .reg = (void *)HHI_MPEG_CLK_CNTL,
...@@ -641,13 +620,12 @@ static struct clk_mux gxbb_mpeg_clk_sel = { ...@@ -641,13 +620,12 @@ static struct clk_mux gxbb_mpeg_clk_sel = {
.name = "mpeg_clk_sel", .name = "mpeg_clk_sel",
.ops = &clk_mux_ro_ops, .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, * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
* fclk_div4, fclk_div3, fclk_div5 * fclk_div4, fclk_div3, fclk_div5
*/ */
.parent_names = (const char *[]){ "fclk_div3", "fclk_div4", .parent_names = clk81_parent_names,
"fclk_div5" }, .num_parents = ARRAY_SIZE(clk81_parent_names),
.num_parents = 3,
.flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED), .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
}, },
}; };
...@@ -676,7 +654,7 @@ static struct clk_gate gxbb_clk81 = { ...@@ -676,7 +654,7 @@ static struct clk_gate gxbb_clk81 = {
.ops = &clk_gate_ops, .ops = &clk_gate_ops,
.parent_names = (const char *[]){ "mpeg_clk_div" }, .parent_names = (const char *[]){ "mpeg_clk_div" },
.num_parents = 1, .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 = { ...@@ -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 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", "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7",
"fclk_div4", "fclk_div3", "fclk_div5" "fclk_div4", "fclk_div3", "fclk_div5"
}; };
...@@ -826,7 +804,7 @@ static struct clk_gate gxbb_mali_1 = { ...@@ -826,7 +804,7 @@ static struct clk_gate gxbb_mali_1 = {
}; };
static u32 mux_table_mali[] = {0, 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" "mali_0", "mali_1"
}; };
...@@ -951,6 +929,51 @@ static struct clk_mux gxbb_cts_i958 = { ...@@ -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 */ /* Everything Else (EE) domain gates */
static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0); static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0);
static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1); static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1);
...@@ -1045,7 +1068,6 @@ static MESON_GATE(gxbb_ao_i2c, HHI_GCLK_AO, 4); ...@@ -1045,7 +1068,6 @@ static MESON_GATE(gxbb_ao_i2c, HHI_GCLK_AO, 4);
static struct clk_hw_onecell_data gxbb_hw_onecell_data = { static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
.hws = { .hws = {
[CLKID_SYS_PLL] = &gxbb_sys_pll.hw, [CLKID_SYS_PLL] = &gxbb_sys_pll.hw,
[CLKID_CPUCLK] = &gxbb_cpu_clk.hw,
[CLKID_HDMI_PLL] = &gxbb_hdmi_pll.hw, [CLKID_HDMI_PLL] = &gxbb_hdmi_pll.hw,
[CLKID_FIXED_PLL] = &gxbb_fixed_pll.hw, [CLKID_FIXED_PLL] = &gxbb_fixed_pll.hw,
[CLKID_FCLK_DIV2] = &gxbb_fclk_div2.hw, [CLKID_FCLK_DIV2] = &gxbb_fclk_div2.hw,
...@@ -1158,6 +1180,9 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { ...@@ -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_SEL] = &gxbb_cts_mclk_i958_sel.hw,
[CLKID_CTS_MCLK_I958_DIV] = &gxbb_cts_mclk_i958_div.hw, [CLKID_CTS_MCLK_I958_DIV] = &gxbb_cts_mclk_i958_div.hw,
[CLKID_CTS_I958] = &gxbb_cts_i958.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, .num = NR_CLKS,
}; };
...@@ -1165,7 +1190,6 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { ...@@ -1165,7 +1190,6 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
static struct clk_hw_onecell_data gxl_hw_onecell_data = { static struct clk_hw_onecell_data gxl_hw_onecell_data = {
.hws = { .hws = {
[CLKID_SYS_PLL] = &gxbb_sys_pll.hw, [CLKID_SYS_PLL] = &gxbb_sys_pll.hw,
[CLKID_CPUCLK] = &gxbb_cpu_clk.hw,
[CLKID_HDMI_PLL] = &gxbb_hdmi_pll.hw, [CLKID_HDMI_PLL] = &gxbb_hdmi_pll.hw,
[CLKID_FIXED_PLL] = &gxbb_fixed_pll.hw, [CLKID_FIXED_PLL] = &gxbb_fixed_pll.hw,
[CLKID_FCLK_DIV2] = &gxbb_fclk_div2.hw, [CLKID_FCLK_DIV2] = &gxbb_fclk_div2.hw,
...@@ -1278,6 +1302,9 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { ...@@ -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_SEL] = &gxbb_cts_mclk_i958_sel.hw,
[CLKID_CTS_MCLK_I958_DIV] = &gxbb_cts_mclk_i958_div.hw, [CLKID_CTS_MCLK_I958_DIV] = &gxbb_cts_mclk_i958_div.hw,
[CLKID_CTS_I958] = &gxbb_cts_i958.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, .num = NR_CLKS,
}; };
...@@ -1392,6 +1419,7 @@ static struct clk_gate *const gxbb_clk_gates[] = { ...@@ -1392,6 +1419,7 @@ static struct clk_gate *const gxbb_clk_gates[] = {
&gxbb_mali_1, &gxbb_mali_1,
&gxbb_cts_amclk, &gxbb_cts_amclk,
&gxbb_cts_mclk_i958, &gxbb_cts_mclk_i958,
&gxbb_32k_clk,
}; };
static struct clk_mux *const gxbb_clk_muxes[] = { static struct clk_mux *const gxbb_clk_muxes[] = {
...@@ -1403,6 +1431,7 @@ 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_amclk_sel,
&gxbb_cts_mclk_i958_sel, &gxbb_cts_mclk_i958_sel,
&gxbb_cts_i958, &gxbb_cts_i958,
&gxbb_32k_clk_sel,
}; };
static struct clk_divider *const gxbb_clk_dividers[] = { static struct clk_divider *const gxbb_clk_dividers[] = {
...@@ -1411,6 +1440,7 @@ 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_0_div,
&gxbb_mali_1_div, &gxbb_mali_1_div,
&gxbb_cts_mclk_i958_div, &gxbb_cts_mclk_i958_div,
&gxbb_32k_clk_div,
}; };
static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = {
...@@ -1430,7 +1460,6 @@ struct clkc_data { ...@@ -1430,7 +1460,6 @@ struct clkc_data {
unsigned int clk_dividers_count; unsigned int clk_dividers_count;
struct meson_clk_audio_divider *const *clk_audio_dividers; struct meson_clk_audio_divider *const *clk_audio_dividers;
unsigned int clk_audio_dividers_count; unsigned int clk_audio_dividers_count;
struct meson_clk_cpu *cpu_clk;
struct clk_hw_onecell_data *hw_onecell_data; struct clk_hw_onecell_data *hw_onecell_data;
}; };
...@@ -1447,7 +1476,6 @@ static const struct clkc_data gxbb_clkc_data = { ...@@ -1447,7 +1476,6 @@ static const struct clkc_data gxbb_clkc_data = {
.clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers), .clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
.clk_audio_dividers = gxbb_audio_dividers, .clk_audio_dividers = gxbb_audio_dividers,
.clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers), .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
.cpu_clk = &gxbb_cpu_clk,
.hw_onecell_data = &gxbb_hw_onecell_data, .hw_onecell_data = &gxbb_hw_onecell_data,
}; };
...@@ -1464,7 +1492,6 @@ static const struct clkc_data gxl_clkc_data = { ...@@ -1464,7 +1492,6 @@ static const struct clkc_data gxl_clkc_data = {
.clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers), .clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
.clk_audio_dividers = gxbb_audio_dividers, .clk_audio_dividers = gxbb_audio_dividers,
.clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers), .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
.cpu_clk = &gxbb_cpu_clk,
.hw_onecell_data = &gxl_hw_onecell_data, .hw_onecell_data = &gxl_hw_onecell_data,
}; };
...@@ -1479,8 +1506,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev) ...@@ -1479,8 +1506,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
const struct clkc_data *clkc_data; const struct clkc_data *clkc_data;
void __iomem *clk_base; void __iomem *clk_base;
int ret, clkid, i; int ret, clkid, i;
struct clk_hw *parent_hw;
struct clk *parent_clk;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
clkc_data = of_device_get_match_data(&pdev->dev); clkc_data = of_device_get_match_data(&pdev->dev);
...@@ -1502,9 +1527,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev) ...@@ -1502,9 +1527,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
for (i = 0; i < clkc_data->clk_mplls_count; i++) for (i = 0; i < clkc_data->clk_mplls_count; i++)
clkc_data->clk_mplls[i]->base = clk_base; 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 */ /* Populate base address for gates */
for (i = 0; i < clkc_data->clk_gates_count; i++) for (i = 0; i < clkc_data->clk_gates_count; i++)
clkc_data->clk_gates[i]->reg = clk_base + clkc_data->clk_gates[i]->reg = clk_base +
...@@ -1538,29 +1560,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev) ...@@ -1538,29 +1560,6 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
goto iounmap; 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, return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
clkc_data->hw_onecell_data); clkc_data->hw_onecell_data);
......
...@@ -171,7 +171,7 @@ ...@@ -171,7 +171,7 @@
* to be exposed to client nodes in DT: include/dt-bindings/clock/gxbb-clkc.h * to be exposed to client nodes in DT: include/dt-bindings/clock/gxbb-clkc.h
*/ */
#define CLKID_SYS_PLL 0 #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 */ /* CLKID_HDMI_PLL */
#define CLKID_FIXED_PLL 3 #define CLKID_FIXED_PLL 3
/* CLKID_FCLK_DIV2 */ /* CLKID_FCLK_DIV2 */
...@@ -284,8 +284,11 @@ ...@@ -284,8 +284,11 @@
#define CLKID_CTS_MCLK_I958_SEL 111 #define CLKID_CTS_MCLK_I958_SEL 111
#define CLKID_CTS_MCLK_I958_DIV 112 #define CLKID_CTS_MCLK_I958_DIV 112
/* CLKID_CTS_I958 */ /* 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 the CLKIDs that have been made part of the stable DT binding */
#include <dt-bindings/clock/gxbb-clkc.h> #include <dt-bindings/clock/gxbb-clkc.h>
......
/* /*
* AmLogic S805 / Meson8b Clock Controller Driver * AmLogic S802 (Meson8) / S805 (Meson8b) / S812 (Meson8m2) Clock Controller
* Driver
* *
* Copyright (c) 2015 Endless Mobile, Inc. * Copyright (c) 2015 Endless Mobile, Inc.
* Author: Carlo Caione <carlo@endlessm.com> * Author: Carlo Caione <carlo@endlessm.com>
...@@ -399,7 +400,7 @@ struct clk_gate meson8b_clk81 = { ...@@ -399,7 +400,7 @@ struct clk_gate meson8b_clk81 = {
.ops = &clk_gate_ops, .ops = &clk_gate_ops,
.parent_names = (const char *[]){ "mpeg_clk_div" }, .parent_names = (const char *[]){ "mpeg_clk_div" },
.num_parents = 1, .num_parents = 1,
.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
}, },
}; };
...@@ -777,7 +778,9 @@ static int meson8b_clkc_probe(struct platform_device *pdev) ...@@ -777,7 +778,9 @@ static int meson8b_clkc_probe(struct platform_device *pdev)
} }
static const struct of_device_id meson8b_clkc_match_table[] = { static const struct of_device_id meson8b_clkc_match_table[] = {
{ .compatible = "amlogic,meson8-clkc" },
{ .compatible = "amlogic,meson8b-clkc" }, { .compatible = "amlogic,meson8b-clkc" },
{ .compatible = "amlogic,meson8m2-clkc" },
{ } { }
}; };
......
...@@ -32,24 +32,38 @@ static struct clk_onecell_data ap806_clk_data = { ...@@ -32,24 +32,38 @@ static struct clk_onecell_data ap806_clk_data = {
.clk_num = AP806_CLK_NUM, .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; unsigned int freq_mode, cpuclk_freq;
const char *name, *fixedclk_name; 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; struct regmap *regmap;
u32 reg; u32 reg;
int ret; int ret;
regmap = syscon_node_to_regmap(np); regmap = syscon_node_to_regmap(syscon_node);
if (IS_ERR(regmap)) { if (IS_ERR(regmap)) {
dev_err(&pdev->dev, "cannot get regmap\n"); dev_err(dev, "cannot get regmap\n");
return PTR_ERR(regmap); return PTR_ERR(regmap);
} }
ret = regmap_read(regmap, AP806_SAR_REG, &reg); ret = regmap_read(regmap, AP806_SAR_REG, &reg);
if (ret) { if (ret) {
dev_err(&pdev->dev, "cannot read from regmap\n"); dev_err(dev, "cannot read from regmap\n");
return ret; return ret;
} }
...@@ -89,7 +103,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) ...@@ -89,7 +103,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev)
cpuclk_freq = 600; cpuclk_freq = 600;
break; break;
default: default:
dev_err(&pdev->dev, "invalid SAR value\n"); dev_err(dev, "invalid SAR value\n");
return -EINVAL; return -EINVAL;
} }
...@@ -97,18 +111,16 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) ...@@ -97,18 +111,16 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev)
cpuclk_freq *= 1000 * 1000; cpuclk_freq *= 1000 * 1000;
/* CPU clocks depend on the Sample At Reset configuration */ /* CPU clocks depend on the Sample At Reset configuration */
of_property_read_string_index(np, "clock-output-names", name = ap806_unique_name(dev, syscon_node, "cpu-cluster-0");
0, &name); ap806_clks[0] = clk_register_fixed_rate(dev, name, NULL,
ap806_clks[0] = clk_register_fixed_rate(&pdev->dev, name, NULL,
0, cpuclk_freq); 0, cpuclk_freq);
if (IS_ERR(ap806_clks[0])) { if (IS_ERR(ap806_clks[0])) {
ret = PTR_ERR(ap806_clks[0]); ret = PTR_ERR(ap806_clks[0]);
goto fail0; goto fail0;
} }
of_property_read_string_index(np, "clock-output-names", name = ap806_unique_name(dev, syscon_node, "cpu-cluster-1");
1, &name); ap806_clks[1] = clk_register_fixed_rate(dev, name, NULL, 0,
ap806_clks[1] = clk_register_fixed_rate(&pdev->dev, name, NULL, 0,
cpuclk_freq); cpuclk_freq);
if (IS_ERR(ap806_clks[1])) { if (IS_ERR(ap806_clks[1])) {
ret = PTR_ERR(ap806_clks[1]); ret = PTR_ERR(ap806_clks[1]);
...@@ -116,9 +128,8 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) ...@@ -116,9 +128,8 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev)
} }
/* Fixed clock is always 1200 Mhz */ /* Fixed clock is always 1200 Mhz */
of_property_read_string_index(np, "clock-output-names", fixedclk_name = ap806_unique_name(dev, syscon_node, "fixed");
2, &fixedclk_name); ap806_clks[2] = clk_register_fixed_rate(dev, fixedclk_name, NULL,
ap806_clks[2] = clk_register_fixed_rate(&pdev->dev, fixedclk_name, NULL,
0, 1200 * 1000 * 1000); 0, 1200 * 1000 * 1000);
if (IS_ERR(ap806_clks[2])) { if (IS_ERR(ap806_clks[2])) {
ret = PTR_ERR(ap806_clks[2]); ret = PTR_ERR(ap806_clks[2]);
...@@ -126,8 +137,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) ...@@ -126,8 +137,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev)
} }
/* MSS Clock is fixed clock divided by 6 */ /* MSS Clock is fixed clock divided by 6 */
of_property_read_string_index(np, "clock-output-names", name = ap806_unique_name(dev, syscon_node, "mss");
3, &name);
ap806_clks[3] = clk_register_fixed_factor(NULL, name, fixedclk_name, ap806_clks[3] = clk_register_fixed_factor(NULL, name, fixedclk_name,
0, 1, 6); 0, 1, 6);
if (IS_ERR(ap806_clks[3])) { if (IS_ERR(ap806_clks[3])) {
...@@ -135,13 +145,8 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) ...@@ -135,13 +145,8 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev)
goto fail3; goto fail3;
} }
/* eMMC Clock is fixed clock divided by 3 */ /* SDIO(/eMMC) Clock is fixed clock divided by 3 */
if (of_property_read_string_index(np, "clock-output-names", name = ap806_unique_name(dev, syscon_node, "sdio");
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, ap806_clks[4] = clk_register_fixed_factor(NULL, name,
fixedclk_name, fixedclk_name,
0, 1, 3); 0, 1, 3);
...@@ -149,7 +154,6 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) ...@@ -149,7 +154,6 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev)
ret = PTR_ERR(ap806_clks[4]); ret = PTR_ERR(ap806_clks[4]);
goto fail4; goto fail4;
} }
}
of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data); of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data);
ret = of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data); ret = of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data);
...@@ -172,17 +176,48 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) ...@@ -172,17 +176,48 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev)
return ret; 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", }, { .compatible = "marvell,ap806-system-controller", },
{ } { }
}; };
static struct platform_driver ap806_syscon_driver = { static struct platform_driver ap806_syscon_legacy_driver = {
.probe = ap806_syscon_clk_probe, .probe = ap806_syscon_legacy_probe,
.driver = { .driver = {
.name = "marvell-ap806-system-controller", .name = "marvell-ap806-system-controller",
.of_match_table = ap806_syscon_of_match, .of_match_table = ap806_syscon_legacy_of_match,
.suppress_bind_attrs = true,
},
};
builtin_platform_driver(ap806_syscon_legacy_driver);
static const struct of_device_id ap806_clock_of_match[] = {
{ .compatible = "marvell,ap806-clock", },
{ }
};
static struct platform_driver ap806_clock_driver = {
.probe = ap806_clock_probe,
.driver = {
.name = "marvell-ap806-clock",
.of_match_table = ap806_clock_of_match,
.suppress_bind_attrs = true, .suppress_bind_attrs = true,
}, },
}; };
builtin_platform_driver(ap806_syscon_driver); builtin_platform_driver(ap806_clock_driver);
...@@ -49,7 +49,8 @@ static const u32 armada_38x_cpu_frequencies[] __initconst = { ...@@ -49,7 +49,8 @@ static const u32 armada_38x_cpu_frequencies[] __initconst = {
0, 0, 0, 0, 0, 0, 0, 0,
1066 * 1000 * 1000, 0, 0, 0, 1066 * 1000 * 1000, 0, 0, 0,
1332 * 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) 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 = { ...@@ -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}, {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}, {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 = { ...@@ -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}, {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}, {0, 1}, {0, 1}, {0, 1}, {0, 1},
{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1},
......
This diff is collapsed.
...@@ -82,6 +82,15 @@ config IPQ_LCC_806X ...@@ -82,6 +82,15 @@ config IPQ_LCC_806X
Say Y if you want to use audio devices such as i2s, pcm, Say Y if you want to use audio devices such as i2s, pcm,
S/PDIF, etc. 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 config MSM_GCC_8660
tristate "MSM8660 Global Clock Controller" tristate "MSM8660 Global Clock Controller"
depends on COMMON_CLK_QCOM depends on COMMON_CLK_QCOM
......
...@@ -17,6 +17,7 @@ obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o ...@@ -17,6 +17,7 @@ obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.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_IPQ_LCC_806X) += lcc-ipq806x.o
obj-$(CONFIG_MDM_GCC_9615) += gcc-mdm9615.o obj-$(CONFIG_MDM_GCC_9615) += gcc-mdm9615.o
obj-$(CONFIG_MDM_LCC_9615) += lcc-mdm9615.o obj-$(CONFIG_MDM_LCC_9615) += lcc-mdm9615.o
......
This diff is collapsed.
...@@ -1430,6 +1430,7 @@ static struct clk_branch gcc_ultaudio_stc_xo_clk = { ...@@ -1430,6 +1430,7 @@ static struct clk_branch gcc_ultaudio_stc_xo_clk = {
}; };
static const struct freq_tbl ftbl_codec_clk[] = { static const struct freq_tbl ftbl_codec_clk[] = {
F(9600000, P_XO, 2, 0, 0),
F(19200000, P_XO, 1, 0, 0), F(19200000, P_XO, 1, 0, 0),
F(11289600, P_EXT_MCLK, 1, 0, 0), F(11289600, P_EXT_MCLK, 1, 0, 0),
{ } { }
......
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 config CLK_RENESAS_CPG_MSSR
bool bool
default y if ARCH_R8A7743 select CLK_RENESAS_DIV6
default y if ARCH_R8A7745
default y if ARCH_R8A7795
default y if ARCH_R8A7796
config CLK_RENESAS_CPG_MSTP config CLK_RENESAS_CPG_MSTP
bool bool
default y if ARCH_R7S72100
default y if ARCH_R8A73A4 config CLK_RENESAS_DIV6
default y if ARCH_R8A7740 bool "DIV6 clock support" if COMPILE_TEST
default y if ARCH_R8A7778
default y if ARCH_R8A7779 endif # CLK_RENESAS
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
obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o # SoC
obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o obj-$(CONFIG_CLK_EMEV2) += clk-emev2.o
obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o clk-div6.o obj-$(CONFIG_CLK_RZA1) += clk-rz.o
obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o clk-div6.o obj-$(CONFIG_CLK_R8A73A4) += clk-r8a73a4.o
obj-$(CONFIG_ARCH_R8A7743) += r8a7743-cpg-mssr.o rcar-gen2-cpg.o obj-$(CONFIG_CLK_R8A7740) += clk-r8a7740.o
obj-$(CONFIG_ARCH_R8A7745) += r8a7745-cpg-mssr.o rcar-gen2-cpg.o obj-$(CONFIG_CLK_R8A7743) += r8a7743-cpg-mssr.o
obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o obj-$(CONFIG_CLK_R8A7745) += r8a7745-cpg-mssr.o
obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o obj-$(CONFIG_CLK_R8A7778) += clk-r8a7778.o
obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_CLK_R8A7779) += clk-r8a7779.o
obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_CLK_R8A7790) += r8a7790-cpg-mssr.o
obj-$(CONFIG_ARCH_R8A7792) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_CLK_R8A7791) += r8a7791-cpg-mssr.o
obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_CLK_R8A7792) += r8a7792-cpg-mssr.o
obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_CLK_R8A7794) += r8a7794-cpg-mssr.o
obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o rcar-gen3-cpg.o obj-$(CONFIG_CLK_R8A7795) += r8a7795-cpg-mssr.o
obj-$(CONFIG_ARCH_R8A7796) += r8a7796-cpg-mssr.o rcar-gen3-cpg.o obj-$(CONFIG_CLK_R8A7796) += r8a7796-cpg-mssr.o
obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-div6.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_CPG_MSTP) += clk-mstp.o
obj-$(CONFIG_CLK_RENESAS_DIV6) += clk-div6.o
...@@ -325,7 +325,7 @@ int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev) ...@@ -325,7 +325,7 @@ int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev)
void cpg_mstp_detach_dev(struct generic_pm_domain *unused, struct device *dev) 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); pm_clk_destroy(dev);
} }
......
...@@ -272,11 +272,14 @@ struct cpg_pll_config { ...@@ -272,11 +272,14 @@ struct cpg_pll_config {
unsigned int extal_div; unsigned int extal_div;
unsigned int pll1_mult; unsigned int pll1_mult;
unsigned int pll3_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 = { static const struct cpg_pll_config cpg_pll_configs[8] __initconst = {
{ 1, 208, 106 }, { 1, 208, 88 }, { 1, 156, 80 }, { 1, 156, 66 }, { 1, 208, 106, 200 }, { 1, 208, 88, 200 },
{ 2, 240, 122 }, { 2, 240, 102 }, { 2, 208, 106 }, { 2, 208, 88 }, { 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 */ /* SDHI divisors */
...@@ -298,6 +301,12 @@ static const struct clk_div_table cpg_sd01_div_table[] = { ...@@ -298,6 +301,12 @@ static const struct clk_div_table cpg_sd01_div_table[] = {
static u32 cpg_mode __initdata; 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 static struct clk * __init
rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
const struct cpg_pll_config *config, const struct cpg_pll_config *config,
...@@ -318,9 +327,15 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, ...@@ -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 * clock implementation and we currently have no need to change
* the multiplier value. * the multiplier value.
*/ */
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); u32 value = clk_readl(cpg->reg + CPG_PLL0CR);
parent_name = "main";
mult = ((value >> 24) & ((1 << 7) - 1)) + 1; mult = ((value >> 24) & ((1 << 7) - 1)) + 1;
}
parent_name = "main";
} else if (!strcmp(name, "pll1")) { } else if (!strcmp(name, "pll1")) {
parent_name = "main"; parent_name = "main";
mult = config->pll1_mult / 2; mult = config->pll1_mult / 2;
......
...@@ -167,16 +167,12 @@ static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = { ...@@ -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-dvc0", 1019, MOD_CLK_ID(1017)),
DEF_MOD("scu-ctu1-mix1", 1020, 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-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-src6", 1025, MOD_CLK_ID(1017)),
DEF_MOD("scu-src5", 1026, 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-src4", 1027, MOD_CLK_ID(1017)),
DEF_MOD("scu-src3", 1028, 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-src2", 1029, MOD_CLK_ID(1017)),
DEF_MOD("scu-src1", 1030, 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("scifa3", 1106, R8A7745_CLK_MP),
DEF_MOD("scifa4", 1107, R8A7745_CLK_MP), DEF_MOD("scifa4", 1107, R8A7745_CLK_MP),
DEF_MOD("scifa5", 1108, R8A7745_CLK_MP), DEF_MOD("scifa5", 1108, R8A7745_CLK_MP),
...@@ -194,31 +190,22 @@ static const unsigned int r8a7745_crit_mod_clks[] __initconst = { ...@@ -194,31 +190,22 @@ static const unsigned int r8a7745_crit_mod_clks[] __initconst = {
* MD EXTAL PLL0 PLL1 PLL3 * MD EXTAL PLL0 PLL1 PLL3
* 14 13 19 (MHz) *1 *2 * 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 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 * 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 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 1 1 30 / 2 x200/3 x208/2 x88
* *
* *1 : Table 7.5b indicates VCO output (PLL0 = VCO/3) * *1 : Table 7.5b indicates VCO output (PLL0 = VCO/3)
* *2 : Table 7.5b indicates VCO output (PLL1 = VCO/2) * *2 : Table 7.5b indicates VCO output (PLL1 = VCO/2)
*/ */
#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \ #define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \
(((md) & BIT(13)) >> 12) | \ (((md) & BIT(13)) >> 13))
(((md) & BIT(19)) >> 19))
static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = { static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
/* EXTAL div PLL1 mult PLL3 mult PLL0 mult */ /* EXTAL div PLL1 mult PLL3 mult PLL0 mult */
{ 1, 208, 106, 200 },
{ 1, 208, 88, 200 }, { 1, 208, 88, 200 },
{ 1, 156, 80, 150 },
{ 1, 156, 66, 150 }, { 1, 156, 66, 150 },
{ 2, 240, 122, 230 },
{ 2, 240, 102, 230 }, { 2, 240, 102, 230 },
{ 2, 208, 106, 200 },
{ 2, 208, 88, 200 }, { 2, 208, 88, 200 },
}; };
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -132,6 +132,10 @@ struct cpg_mssr_info { ...@@ -132,6 +132,10 @@ struct cpg_mssr_info {
extern const struct cpg_mssr_info r8a7743_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 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 r8a7795_cpg_mssr_info;
extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; extern const struct cpg_mssr_info r8a7796_cpg_mssr_info;
......
...@@ -14,6 +14,7 @@ obj-$(CONFIG_RESET_CONTROLLER) += softrst.o ...@@ -14,6 +14,7 @@ obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
obj-y += clk-rv1108.o obj-y += clk-rv1108.o
obj-y += clk-rk3036.o obj-y += clk-rk3036.o
obj-y += clk-rk3128.o
obj-y += clk-rk3188.o obj-y += clk-rk3188.o
obj-y += clk-rk3228.o obj-y += clk-rk3228.o
obj-y += clk-rk3288.o obj-y += clk-rk3288.o
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment