Commit e4ca4308 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'clk-for-linus-3.17' of git://git.linaro.org/people/mike.turquette/linux

Pull clock framework updates from Mike Turquette:
 "The clock framework changes for 3.17 are mostly additions of new clock
  drivers and fixes/enhancements to existing clock drivers.  There are
  also some non-critical fixes and improvements to the framework core.

  Changes to the clock framework core include:
   - improvements to printks on errors
   - flattening the previously hierarchal structure of per-clock entries
     in debugfs
   - allow per-clock debugfs entries that are specific to a particular
     clock driver
   - configure initial clock parent and/or initial clock rate from
     Device Tree
   - several feature enhancements to the composite clock type
   - misc fixes

  New clock drivers added include:
   - TI Palmas PMIC
   - Allwinner A23 SoC
   - Qualcomm APQ8084 and IPQ8064 SoCs
   - Rockchip rk3188, rk3066 and rk3288 SoCs
   - STMicroelectronics STiH407 SoC
   - Cirrus Logic CLPS711X SoC

  Many fixes, feature enhancements and further clock tree support for
  existing clock drivers also were merged, such as Samsung's "ARMCLK
  down" power saving feature for their Exynos4 & Exynos5 SoCs"

* tag 'clk-for-linus-3.17' of git://git.linaro.org/people/mike.turquette/linux: (86 commits)
  clk: Add missing of_clk_set_defaults export
  clk: checking wrong variable in __set_clk_parents()
  clk: Propagate any error return from debug_init()
  clk: clps711x: Add DT bindings documentation
  clk: Add CLPS711X clk driver
  clk: st: Use round to closest divider flag
  clk: st: Update frequency tables for fs660c32 and fs432c65
  clk: st: STiH407: Support for clockgenA9
  clk: st: STiH407: Support for clockgenD0/D2/D3
  clk: st: STiH407: Support for clockgenC0
  clk: st: Add quadfs reset handling
  clk: st: Add polarity bit indication
  clk: st: STiH407: Support for clockgenA0
  clk: st: STiH407: Support for A9 MUX Clocks
  clk: st: STiH407: Support for Flexgen Clocks
  clk: st: Adds Flexgen clock binding
  clk: st: Remove uncessary (void *) cast
  clk: st: use static const for clkgen_pll_data tables
  clk: st: use static const for stm_fs tables
  clk: st: Update ST clock binding documentation
  ...
parents e17acfdc b11a6fac
...@@ -12,8 +12,38 @@ Properties: ...@@ -12,8 +12,38 @@ Properties:
- reg : offset and length of the register set. - reg : offset and length of the register set.
- #clock-cells : must be <1>, since PMU requires once cell as clock specifier.
The single specifier cell is used as index to list of clocks
provided by PMU, which is currently:
0 : SoC clock output (CLKOUT pin)
- clock-names : list of clock names for particular CLKOUT mux inputs in
following format:
"clkoutN", where N is a decimal number corresponding to
CLKOUT mux control bits value for given input, e.g.
"clkout0", "clkout7", "clkout15".
- clocks : list of phandles and specifiers to all input clocks listed in
clock-names property.
Example : Example :
pmu_system_controller: system-controller@10040000 { pmu_system_controller: system-controller@10040000 {
compatible = "samsung,exynos5250-pmu", "syscon"; compatible = "samsung,exynos5250-pmu", "syscon";
reg = <0x10040000 0x5000>; reg = <0x10040000 0x5000>;
#clock-cells = <1>;
clock-names = "clkout0", "clkout1", "clkout2", "clkout3",
"clkout4", "clkout8", "clkout9";
clocks = <&clock CLK_OUT_DMC>, <&clock CLK_OUT_TOP>,
<&clock CLK_OUT_LEFTBUS>, <&clock CLK_OUT_RIGHTBUS>,
<&clock CLK_OUT_CPU>, <&clock CLK_XXTI>,
<&clock CLK_XUSBXTI>;
};
Example of clock consumer :
usb3503: usb3503@08 {
/* ... */
clock-names = "refclk";
clocks = <&pmu_system_controller 0>;
/* ... */
}; };
* Palmas 32KHz clocks *
Palmas device has two clock output pins for 32KHz, KG and KG_AUDIO.
This binding uses the common clock binding ./clock-bindings.txt.
Required properties:
- compatible : "ti,palmas-clk32kg" for clk32kg clock
"ti,palmas-clk32kgaudio" for clk32kgaudio clock
- #clock-cells : shall be set to 0.
Optional property:
- ti,external-sleep-control: The external enable input pins controlled the
enable/disable of clocks. The external enable input pins ENABLE1,
ENABLE2 and NSLEEP. The valid values for the external pins are:
PALMAS_EXT_CONTROL_PIN_ENABLE1 for ENABLE1 pin
PALMAS_EXT_CONTROL_PIN_ENABLE2 for ENABLE2 pin
PALMAS_EXT_CONTROL_PIN_NSLEEP for NSLEEP pin
Option 0 or missing this property means the clock is enabled/disabled
via register access and these pins do not have any control.
The macros of external control pins for DTS is defined at
dt-bindings/mfd/palmas.h
Example:
#include <dt-bindings/mfd/palmas.h>
...
palmas: tps65913@58 {
...
clk32kg: palmas_clk32k@0 {
compatible = "ti,palmas-clk32kg";
#clock-cells = <0>;
ti,external-sleep-control = <PALMAS_EXT_CONTROL_PIN_NSLEEP>;
};
...
};
...@@ -131,3 +131,39 @@ clock signal, and a UART. ...@@ -131,3 +131,39 @@ clock signal, and a UART.
("pll" and "pll-switched"). ("pll" and "pll-switched").
* The UART has its baud clock connected the external oscillator and its * The UART has its baud clock connected the external oscillator and its
register clock connected to the PLL clock (the "pll-switched" signal) register clock connected to the PLL clock (the "pll-switched" signal)
==Assigned clock parents and rates==
Some platforms may require initial configuration of default parent clocks
and clock frequencies. Such a configuration can be specified in a device tree
node through assigned-clocks, assigned-clock-parents and assigned-clock-rates
properties. The assigned-clock-parents property should contain a list of parent
clocks in form of phandle and clock specifier pairs, the assigned-clock-parents
property the list of assigned clock frequency values - corresponding to clocks
listed in the assigned-clocks property.
To skip setting parent or rate of a clock its corresponding entry should be
set to 0, or can be omitted if it is not followed by any non-zero entry.
uart@a000 {
compatible = "fsl,imx-uart";
reg = <0xa000 0x1000>;
...
clocks = <&osc 0>, <&pll 1>;
clock-names = "baud", "register";
assigned-clocks = <&clkcon 0>, <&pll 2>;
assigned-clock-parents = <&pll 2>;
assigned-clock-rates = <0>, <460800>;
};
In this example the <&pll 2> clock is set as parent of clock <&clkcon 0> and
the <&pll 2> clock is assigned a frequency value of 460800 Hz.
Configuring a clock's parent and rate through the device node that consumes
the clock can be done only for clocks that have a single user. Specifying
conflicting parent or rate configuration in multiple consumer nodes for
a shared clock is forbidden.
Configuration of common clocks, which affect multiple consumer devices can
be similarly specified in the clock provider node.
* Clock bindings for the Cirrus Logic CLPS711X CPUs
Required properties:
- compatible : Shall contain "cirrus,clps711x-clk".
- reg : Address of the internal register set.
- startup-frequency: Factory set CPU startup frequency in HZ.
- #clock-cells : Should be <1>.
The clock consumer should specify the desired clock by having the clock
ID in its "clocks" phandle cell. See include/dt-bindings/clock/clps711x-clock.h
for the full list of CLPS711X clock IDs.
Example:
clks: clks@80000000 {
#clock-cells = <1>;
compatible = "cirrus,ep7312-clk", "cirrus,clps711x-clk";
reg = <0x80000000 0xc000>;
startup-frequency = <73728000>;
};
...@@ -5,6 +5,8 @@ Required properties : ...@@ -5,6 +5,8 @@ Required properties :
- compatible : shall contain only one of the following: - compatible : shall contain only one of the following:
"qcom,gcc-apq8064" "qcom,gcc-apq8064"
"qcom,gcc-apq8084"
"qcom,gcc-ipq8064"
"qcom,gcc-msm8660" "qcom,gcc-msm8660"
"qcom,gcc-msm8960" "qcom,gcc-msm8960"
"qcom,gcc-msm8974" "qcom,gcc-msm8974"
......
...@@ -4,6 +4,8 @@ Qualcomm Multimedia Clock & Reset Controller Binding ...@@ -4,6 +4,8 @@ Qualcomm Multimedia Clock & Reset Controller Binding
Required properties : Required properties :
- compatible : shall contain only one of the following: - compatible : shall contain only one of the following:
"qcom,mmcc-apq8064"
"qcom,mmcc-apq8084"
"qcom,mmcc-msm8660" "qcom,mmcc-msm8660"
"qcom,mmcc-msm8960" "qcom,mmcc-msm8960"
"qcom,mmcc-msm8974" "qcom,mmcc-msm8974"
......
* Rockchip RK3188/RK3066 Clock and Reset Unit
The RK3188/RK3066 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,rk3188-cru", "rockchip,rk3188a-cru" or
"rockchip,rk3066a-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 changable, 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/rk3188-cru.h and
dt-bindings/clock/rk3066-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,
- "xin32k" - rtc clock - optional,
- "xin27m" - 27mhz crystal input on rk3066 - optional,
- "ext_hsadc" - external HSADC clock - optional,
- "ext_cif0" - external camera clock - optional,
- "ext_rmii" - external RMII clock - optional,
- "ext_jtag" - externalJTAG clock - optional
Example: Clock controller node:
cru: cru@20000000 {
compatible = "rockchip,rk3188-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:
uart0: serial@10124000 {
compatible = "snps,dw-apb-uart";
reg = <0x10124000 0x400>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <1>;
clocks = <&cru SCLK_UART0>;
};
* Rockchip RK3288 Clock and Reset Unit
The RK3288 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,rk3288-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 changable, 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/rk3288-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,
- "xin32k" - rtc clock - optional,
- "ext_i2s" - external I2S clock - optional,
- "ext_hsadc" - external HSADC clock - optional,
- "ext_edp_24m" - external display port clock - optional,
- "ext_vip" - external VIP clock - optional,
- "ext_isp" - external ISP clock - optional,
- "ext_jtag" - external JTAG clock - optional
Example: Clock controller node:
cru: cru@20000000 {
compatible = "rockchip,rk3188-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:
uart0: serial@10124000 {
compatible = "snps,dw-apb-uart";
reg = <0x10124000 0x400>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <1>;
clocks = <&cru SCLK_UART0>;
};
...@@ -6,6 +6,9 @@ This binding uses the common clock binding[1]. ...@@ -6,6 +6,9 @@ This binding uses the common clock binding[1].
== Gate clocks == == Gate clocks ==
These bindings are deprecated!
Please use the soc specific CRU bindings instead.
The gate registers form a continuos block which makes the dt node The gate registers form a continuos block which makes the dt node
structure a matter of taste, as either all gates can be put into structure a matter of taste, as either all gates can be put into
one gate clock spanning all registers or they can be divided into one gate clock spanning all registers or they can be divided into
......
...@@ -24,26 +24,26 @@ Required properties: ...@@ -24,26 +24,26 @@ Required properties:
Example: Example:
clockgenA@fd345000 { clockgen-a@fd345000 {
reg = <0xfd345000 0xb50>; reg = <0xfd345000 0xb50>;
CLK_M_A1_DIV1: CLK_M_A1_DIV1 { clk_m_a1_div1: clk-m-a1-div1 {
#clock-cells = <1>; #clock-cells = <1>;
compatible = "st,clkgena-divmux-c32-odf1", compatible = "st,clkgena-divmux-c32-odf1",
"st,clkgena-divmux"; "st,clkgena-divmux";
clocks = <&CLK_M_A1_OSC_PREDIV>, clocks = <&clk_m_a1_osc_prediv>,
<&CLK_M_A1_PLL0 1>, /* PLL0 PHI1 */ <&clk_m_a1_pll0 1>, /* PLL0 PHI1 */
<&CLK_M_A1_PLL1 1>; /* PLL1 PHI1 */ <&clk_m_a1_pll1 1>; /* PLL1 PHI1 */
clock-output-names = "CLK_M_RX_ICN_TS", clock-output-names = "clk-m-rx-icn-ts",
"CLK_M_RX_ICN_VDP_0", "clk-m-rx-icn-vdp-0",
"", /* Unused */ "", /* unused */
"CLK_M_PRV_T1_BUS", "clk-m-prv-t1-bus",
"CLK_M_ICN_REG_12", "clk-m-icn-reg-12",
"CLK_M_ICN_REG_10", "clk-m-icn-reg-10",
"", /* Unused */ "", /* unused */
"CLK_M_ICN_ST231"; "clk-m-icn-st231";
}; };
}; };
...@@ -17,7 +17,7 @@ Required properties: ...@@ -17,7 +17,7 @@ Required properties:
"st,stih416-clkgenf-vcc-sd", "st,clkgen-mux" "st,stih416-clkgenf-vcc-sd", "st,clkgen-mux"
"st,stih415-clkgen-a9-mux", "st,clkgen-mux" "st,stih415-clkgen-a9-mux", "st,clkgen-mux"
"st,stih416-clkgen-a9-mux", "st,clkgen-mux" "st,stih416-clkgen-a9-mux", "st,clkgen-mux"
"st,stih407-clkgen-a9-mux", "st,clkgen-mux"
- #clock-cells : from common clock binding; shall be set to 0. - #clock-cells : from common clock binding; shall be set to 0.
...@@ -27,10 +27,10 @@ Required properties: ...@@ -27,10 +27,10 @@ Required properties:
Example: Example:
CLK_M_HVA: CLK_M_HVA { clk_m_hva: clk-m-hva@fd690868 {
#clock-cells = <0>; #clock-cells = <0>;
compatible = "st,stih416-clkgenf-vcc-hva", "st,clkgen-mux"; compatible = "st,stih416-clkgenf-vcc-hva", "st,clkgen-mux";
reg = <0xfd690868 4>; reg = <0xfd690868 4>;
clocks = <&CLOCKGEN_F 1>, <&CLK_M_A1_DIV0 3>; clocks = <&clockgen_f 1>, <&clk_m_a1_div0 3>;
}; };
...@@ -19,11 +19,14 @@ Required properties: ...@@ -19,11 +19,14 @@ Required properties:
"st,stih415-plls-c32-ddr", "st,clkgen-plls-c32" "st,stih415-plls-c32-ddr", "st,clkgen-plls-c32"
"st,stih416-plls-c32-a9", "st,clkgen-plls-c32" "st,stih416-plls-c32-a9", "st,clkgen-plls-c32"
"st,stih416-plls-c32-ddr", "st,clkgen-plls-c32" "st,stih416-plls-c32-ddr", "st,clkgen-plls-c32"
"st,stih407-plls-c32-a0", "st,clkgen-plls-c32"
"st,stih407-plls-c32-a9", "st,clkgen-plls-c32"
"st,stih407-plls-c32-c0_0", "st,clkgen-plls-c32"
"st,stih407-plls-c32-c0_1", "st,clkgen-plls-c32"
"st,stih415-gpu-pll-c32", "st,clkgengpu-pll-c32" "st,stih415-gpu-pll-c32", "st,clkgengpu-pll-c32"
"st,stih416-gpu-pll-c32", "st,clkgengpu-pll-c32" "st,stih416-gpu-pll-c32", "st,clkgengpu-pll-c32"
- #clock-cells : From common clock binding; shall be set to 1. - #clock-cells : From common clock binding; shall be set to 1.
- clocks : From common clock binding - clocks : From common clock binding
...@@ -32,17 +35,17 @@ Required properties: ...@@ -32,17 +35,17 @@ Required properties:
Example: Example:
clockgenA@fee62000 { clockgen-a@fee62000 {
reg = <0xfee62000 0xb48>; reg = <0xfee62000 0xb48>;
CLK_S_A0_PLL: CLK_S_A0_PLL { clk_s_a0_pll: clk-s-a0-pll {
#clock-cells = <1>; #clock-cells = <1>;
compatible = "st,clkgena-plls-c65"; compatible = "st,clkgena-plls-c65";
clocks = <&CLK_SYSIN>; clocks = <&clk_sysin>;
clock-output-names = "CLK_S_A0_PLL0_HS", clock-output-names = "clk-s-a0-pll0-hs",
"CLK_S_A0_PLL0_LS", "clk-s-a0-pll0-ls",
"CLK_S_A0_PLL1"; "clk-s-a0-pll1";
}; };
}; };
...@@ -20,17 +20,17 @@ Required properties: ...@@ -20,17 +20,17 @@ Required properties:
Example: Example:
clockgenA@fd345000 { clockgen-a@fd345000 {
reg = <0xfd345000 0xb50>; reg = <0xfd345000 0xb50>;
CLK_M_A2_OSC_PREDIV: CLK_M_A2_OSC_PREDIV { clk_m_a2_osc_prediv: clk-m-a2-osc-prediv {
#clock-cells = <0>; #clock-cells = <0>;
compatible = "st,clkgena-prediv-c32", compatible = "st,clkgena-prediv-c32",
"st,clkgena-prediv"; "st,clkgena-prediv";
clocks = <&CLK_SYSIN>; clocks = <&clk_sysin>;
clock-output-names = "CLK_M_A2_OSC_PREDIV"; clock-output-names = "clk-m-a2-osc-prediv";
}; };
}; };
...@@ -32,22 +32,30 @@ Required properties: ...@@ -32,22 +32,30 @@ Required properties:
Example: Example:
CLOCKGEN_C_VCC: CLOCKGEN_C_VCC { clockgen_c_vcc: clockgen-c-vcc@0xfe8308ac {
#clock-cells = <1>; #clock-cells = <1>;
compatible = "st,stih416-clkgenc", "st,clkgen-vcc"; compatible = "st,stih416-clkgenc", "st,clkgen-vcc";
reg = <0xfe8308ac 12>; reg = <0xfe8308ac 12>;
clocks = <&CLK_S_VCC_HD>, <&CLOCKGEN_C 1>, clocks = <&clk_s_vcc_hd>,
<&CLK_S_TMDS_FROMPHY>, <&CLOCKGEN_C 2>; <&clockgen_c 1>,
<&clk_s_tmds_fromphy>,
clock-output-names = <&clockgen_c 2>;
"CLK_S_PIX_HDMI", "CLK_S_PIX_DVO",
"CLK_S_OUT_DVO", "CLK_S_PIX_HD", clock-output-names = "clk-s-pix-hdmi",
"CLK_S_HDDAC", "CLK_S_DENC", "clk-s-pix-dvo",
"CLK_S_SDDAC", "CLK_S_PIX_MAIN", "clk-s-out-dvo",
"CLK_S_PIX_AUX", "CLK_S_STFE_FRC_0", "clk-s-pix-hd",
"CLK_S_REF_MCRU", "CLK_S_SLAVE_MCRU", "clk-s-hddac",
"CLK_S_TMDS_HDMI", "CLK_S_HDMI_REJECT_PLL", "clk-s-denc",
"CLK_S_THSENS"; "clk-s-sddac",
"clk-s-pix-main",
"clk-s-pix-aux",
"clk-s-stfe-frc-0",
"clk-s-ref-mcru",
"clk-s-slave-mcru",
"clk-s-tmds-hdmi",
"clk-s-hdmi-reject-pll",
"clk-s-thsens";
}; };
...@@ -24,60 +24,77 @@ address is common of all subnode. ...@@ -24,60 +24,77 @@ address is common of all subnode.
quadfs_node { quadfs_node {
... ...
}; };
mux_node {
...
};
vcc_node {
...
};
flexgen_node {
...
};
... ...
}; };
This binding uses the common clock binding[1]. This binding uses the common clock binding[1].
Each subnode should use the binding discribe in [2]..[4] Each subnode should use the binding discribe in [2]..[7]
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
[2] Documentation/devicetree/bindings/clock/st,quadfs.txt [2] Documentation/devicetree/bindings/clock/st,clkgen-divmux.txt
[3] Documentation/devicetree/bindings/clock/st,quadfs.txt [3] Documentation/devicetree/bindings/clock/st,clkgen-mux.txt
[4] Documentation/devicetree/bindings/clock/st,quadfs.txt [4] Documentation/devicetree/bindings/clock/st,clkgen-pll.txt
[5] Documentation/devicetree/bindings/clock/st,clkgen-prediv.txt
[6] Documentation/devicetree/bindings/clock/st,vcc.txt
[7] Documentation/devicetree/bindings/clock/st,quadfs.txt
[8] Documentation/devicetree/bindings/clock/st,flexgen.txt
Required properties: Required properties:
- reg : A Base address and length of the register set. - reg : A Base address and length of the register set.
Example: Example:
clockgenA@fee62000 { clockgen-a@fee62000 {
reg = <0xfee62000 0xb48>; reg = <0xfee62000 0xb48>;
CLK_S_A0_PLL: CLK_S_A0_PLL { clk_s_a0_pll: clk-s-a0-pll {
#clock-cells = <1>; #clock-cells = <1>;
compatible = "st,clkgena-plls-c65"; compatible = "st,clkgena-plls-c65";
clocks = <&CLK_SYSIN>; clocks = <&clk-sysin>;
clock-output-names = "CLK_S_A0_PLL0_HS", clock-output-names = "clk-s-a0-pll0-hs",
"CLK_S_A0_PLL0_LS", "clk-s-a0-pll0-ls",
"CLK_S_A0_PLL1"; "clk-s-a0-pll1";
}; };
CLK_S_A0_OSC_PREDIV: CLK_S_A0_OSC_PREDIV { clk_s_a0_osc_prediv: clk-s-a0-osc-prediv {
#clock-cells = <0>; #clock-cells = <0>;
compatible = "st,clkgena-prediv-c65", compatible = "st,clkgena-prediv-c65",
"st,clkgena-prediv"; "st,clkgena-prediv";
clocks = <&CLK_SYSIN>; clocks = <&clk_sysin>;
clock-output-names = "CLK_S_A0_OSC_PREDIV"; clock-output-names = "clk-s-a0-osc-prediv";
}; };
CLK_S_A0_HS: CLK_S_A0_HS { clk_s_a0_hs: clk-s-a0-hs {
#clock-cells = <1>; #clock-cells = <1>;
compatible = "st,clkgena-divmux-c65-hs", compatible = "st,clkgena-divmux-c65-hs",
"st,clkgena-divmux"; "st,clkgena-divmux";
clocks = <&CLK_S_A0_OSC_PREDIV>, clocks = <&clk-s_a0_osc_prediv>,
<&CLK_S_A0_PLL 0>, /* PLL0 HS */ <&clk-s_a0_pll 0>, /* pll0 hs */
<&CLK_S_A0_PLL 2>; /* PLL1 */ <&clk-s_a0_pll 2>; /* pll1 */
clock-output-names = "CLK_S_FDMA_0", clock-output-names = "clk-s-fdma-0",
"CLK_S_FDMA_1", "clk-s-fdma-1",
""; /* CLK_S_JIT_SENSE */ ""; /* clk-s-jit-sense */
/* Fourth output unused */ /* fourth output unused */
}; };
}; };
Binding for a type of flexgen structure found on certain
STMicroelectronics consumer electronics SoC devices
This structure includes:
- a clock cross bar (represented by a mux element)
- a pre and final dividers (represented by a divider and gate elements)
Flexgen structure is a part of Clockgen[1].
Please find an example below:
Clockgen block diagram
-------------------------------------------------------------------
| Flexgen stucture |
| --------------------------------------------- |
| | ------- -------- -------- | |
clk_sysin | | | | | | | | |
---|-----------------|-->| | | | | | | |
| | | | | | | | | | |
| | ------- | | | |Pre | |Final | | |
| | |PLL0 | | | | |Dividers| |Dividers| | |
| |->| | | | | | x32 | | x32 | | |
| | | odf_0|----|-->| | | | | | | |
| | | | | | | | | | | | |
| | | | | | | | | | | | |
| | | | | | | | | | | | |
| | | | | | | | | | | | |
| | ------- | | | | | | | | |
| | | | | | | | | | |
| | ------- | | Clock | | | | | | |
| | |PLL1 | | | | | | | | | |
| |->| | | | Cross | | | | | | |
| | | odf_0|----|-->| | | | | | CLK_DIV[31:0]
| | | | | | Bar |====>| |====>| |===|=========>
| | | | | | | | | | | | |
| | | | | | | | | | | | |
| | | | | | | | | | | | |
| | ------- | | | | | | | | |
| | | | | | | | | | |
| | ------- | | | | | | | | |
| | |QUADFS | | | | | | | | | |
| |->| ch0|----|-->| | | | | | | |
| | | | | | | | | | | |
| | ch1|----|-->| | | | | | | |
| | | | | | | | | | | |
| | ch2|----|-->| | | DIV | | DIV | | |
| | | | | | | 1 to | | 1 to | | |
| | ch3|----|-->| | | 1024 | | 64 | | |
| ------- | | | | | | | | |
| | ------- -------- -------- | |
| -------------------------------------------- |
| |
-------------------------------------------------------------------
This binding uses the common clock binding[2].
[1] Documentation/devicetree/bindings/clock/st/st,clkgen.txt
[2] Documentation/devicetree/bindings/clock/clock-bindings.txt
Required properties:
- compatible : shall be:
"st,flexgen"
- #clock-cells : from common clock binding; shall be set to 1 (multiple clock
outputs).
- clocks : must be set to the parent's phandle. it's could be output clocks of
a quadsfs or/and a pll or/and clk_sysin (up to 7 clocks)
- clock-output-names : List of strings used to name the clock outputs.
Example:
clk_s_c0_flexgen: clk-s-c0-flexgen {
#clock-cells = <1>;
compatible = "st,flexgen";
clocks = <&clk_s_c0_pll0 0>,
<&clk_s_c0_pll1 0>,
<&clk_s_c0_quadfs 0>,
<&clk_s_c0_quadfs 1>,
<&clk_s_c0_quadfs 2>,
<&clk_s_c0_quadfs 3>,
<&clk_sysin>;
clock-output-names = "clk-icn-gpu",
"clk-fdma",
"clk-nand",
"clk-hva",
"clk-proc-stfe",
"clk-proc-tp",
"clk-rx-icn-dmu",
"clk-rx-icn-hva",
"clk-icn-cpu",
"clk-tx-icn-dmu",
"clk-mmc-0",
"clk-mmc-1",
"clk-jpegdec",
"clk-ext2fa9",
"clk-ic-bdisp-0",
"clk-ic-bdisp-1",
"clk-pp-dmu",
"clk-vid-dmu",
"clk-dss-lpc",
"clk-st231-aud-0",
"clk-st231-gp-1",
"clk-st231-dmu",
"clk-icn-lmi",
"clk-tx-icn-disp-1",
"clk-icn-sbc",
"clk-stfe-frc2",
"clk-eth-phy",
"clk-eth-ref-phyclk",
"clk-flash-promip",
"clk-main-disp",
"clk-aux-disp",
"clk-compo-dvp";
};
...@@ -15,6 +15,9 @@ Required properties: ...@@ -15,6 +15,9 @@ Required properties:
"st,stih416-quadfs432", "st,quadfs" "st,stih416-quadfs432", "st,quadfs"
"st,stih416-quadfs660-E", "st,quadfs" "st,stih416-quadfs660-E", "st,quadfs"
"st,stih416-quadfs660-F", "st,quadfs" "st,stih416-quadfs660-F", "st,quadfs"
"st,stih407-quadfs660-C", "st,quadfs"
"st,stih407-quadfs660-D", "st,quadfs"
- #clock-cells : from common clock binding; shall be set to 1. - #clock-cells : from common clock binding; shall be set to 1.
...@@ -32,14 +35,14 @@ Required properties: ...@@ -32,14 +35,14 @@ Required properties:
Example: Example:
CLOCKGEN_E: CLOCKGEN_E { clockgen_e: clockgen-e@fd3208bc {
#clock-cells = <1>; #clock-cells = <1>;
compatible = "st,stih416-quadfs660-E", "st,quadfs"; compatible = "st,stih416-quadfs660-E", "st,quadfs";
reg = <0xfd3208bc 0xB0>; reg = <0xfd3208bc 0xB0>;
clocks = <&CLK_SYSIN>; clocks = <&clk_sysin>;
clock-output-names = "CLK_M_PIX_MDTP_0", clock-output-names = "clk-m-pix-mdtp-0",
"CLK_M_PIX_MDTP_1", "clk-m-pix-mdtp-1",
"CLK_M_PIX_MDTP_2", "clk-m-pix-mdtp-2",
"CLK_M_MPELPC"; "clk-m-mpelpc";
}; };
...@@ -9,11 +9,13 @@ Required properties: ...@@ -9,11 +9,13 @@ Required properties:
"allwinner,sun4i-a10-osc-clk" - for a gatable oscillator "allwinner,sun4i-a10-osc-clk" - for a gatable oscillator
"allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4 "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4
"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
"allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23
"allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
"allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
"allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31 "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
"allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
"allwinner,sun4i-a10-axi-clk" - for the AXI clock "allwinner,sun4i-a10-axi-clk" - for the AXI clock
"allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23
"allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
"allwinner,sun4i-a10-ahb-clk" - for the AHB clock "allwinner,sun4i-a10-ahb-clk" - for the AHB clock
"allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10 "allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10
...@@ -23,13 +25,16 @@ Required properties: ...@@ -23,13 +25,16 @@ Required properties:
"allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31 "allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31
"allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31 "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31
"allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
"allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23
"allwinner,sun4i-a10-apb0-clk" - for the APB0 clock "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
"allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31 "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31
"allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23
"allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10 "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
"allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
"allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
"allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31 "allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31
"allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
"allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23
"allwinner,sun4i-a10-apb1-clk" - for the APB1 clock "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
"allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
"allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10 "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10
...@@ -37,8 +42,10 @@ Required properties: ...@@ -37,8 +42,10 @@ Required properties:
"allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s "allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s
"allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31 "allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31
"allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20 "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20
"allwinner,sun8i-a23-apb1-gates-clk" - for the APB1 gates on A23
"allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31 "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
"allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
"allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks "allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks
"allwinner,sun7i-a20-out-clk" - for the external output clocks "allwinner,sun7i-a20-out-clk" - for the external output clocks
"allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
......
...@@ -9057,6 +9057,13 @@ L: linux-pm@vger.kernel.org ...@@ -9057,6 +9057,13 @@ L: linux-pm@vger.kernel.org
S: Supported S: Supported
F: drivers/thermal/ti-soc-thermal/ F: drivers/thermal/ti-soc-thermal/
TI CLOCK DRIVER
M: Tero Kristo <t-kristo@ti.com>
L: linux-omap@vger.kernel.org
S: Maintained
F: drivers/clk/ti/
F: include/linux/clk/ti.h
TI FLASH MEDIA INTERFACE DRIVER TI FLASH MEDIA INTERFACE DRIVER
M: Alex Dubov <oakad@yahoo.com> M: Alex Dubov <oakad@yahoo.com>
S: Maintained S: Maintained
......
...@@ -31,6 +31,16 @@ aliases { ...@@ -31,6 +31,16 @@ aliases {
pinctrl2 = &pinctrl_2; pinctrl2 = &pinctrl_2;
}; };
pmu_system_controller: system-controller@10020000 {
clock-names = "clkout0", "clkout1", "clkout2", "clkout3",
"clkout4", "clkout8", "clkout9";
clocks = <&clock CLK_OUT_DMC>, <&clock CLK_OUT_TOP>,
<&clock CLK_OUT_LEFTBUS>, <&clock CLK_OUT_RIGHTBUS>,
<&clock CLK_OUT_CPU>, <&clock CLK_XXTI>,
<&clock CLK_XUSBXTI>;
#clock-cells = <1>;
};
sysram@02020000 { sysram@02020000 {
compatible = "mmio-sram"; compatible = "mmio-sram";
reg = <0x02020000 0x20000>; reg = <0x02020000 0x20000>;
......
...@@ -139,6 +139,13 @@ pinctrl_3: pinctrl@106E0000 { ...@@ -139,6 +139,13 @@ pinctrl_3: pinctrl@106E0000 {
pmu_system_controller: system-controller@10020000 { pmu_system_controller: system-controller@10020000 {
compatible = "samsung,exynos4212-pmu", "syscon"; compatible = "samsung,exynos4212-pmu", "syscon";
clock-names = "clkout0", "clkout1", "clkout2", "clkout3",
"clkout4", "clkout8", "clkout9";
clocks = <&clock CLK_OUT_DMC>, <&clock CLK_OUT_TOP>,
<&clock CLK_OUT_LEFTBUS>, <&clock CLK_OUT_RIGHTBUS>,
<&clock CLK_OUT_CPU>, <&clock CLK_XXTI>,
<&clock CLK_XUSBXTI>;
#clock-cells = <1>;
}; };
g2d@10800000 { g2d@10800000 {
......
...@@ -191,6 +191,9 @@ pinctrl_3: pinctrl@03860000 { ...@@ -191,6 +191,9 @@ pinctrl_3: pinctrl@03860000 {
pmu_system_controller: system-controller@10040000 { pmu_system_controller: system-controller@10040000 {
compatible = "samsung,exynos5250-pmu", "syscon"; compatible = "samsung,exynos5250-pmu", "syscon";
reg = <0x10040000 0x5000>; reg = <0x10040000 0x5000>;
clock-names = "clkout16";
clocks = <&clock CLK_FIN_PLL>;
#clock-cells = <1>;
}; };
sysreg_system_controller: syscon@10050000 { sysreg_system_controller: syscon@10050000 {
......
...@@ -727,6 +727,9 @@ gsc_1: video-scaler@13e10000 { ...@@ -727,6 +727,9 @@ gsc_1: video-scaler@13e10000 {
pmu_system_controller: system-controller@10040000 { pmu_system_controller: system-controller@10040000 {
compatible = "samsung,exynos5420-pmu", "syscon"; compatible = "samsung,exynos5420-pmu", "syscon";
reg = <0x10040000 0x5000>; reg = <0x10040000 0x5000>;
clock-names = "clkout16";
clocks = <&clock CLK_FIN_PLL>;
#clock-cells = <1>;
}; };
sysreg_system_controller: syscon@10050000 { sysreg_system_controller: syscon@10050000 {
......
...@@ -2,6 +2,7 @@ config ARCH_ROCKCHIP ...@@ -2,6 +2,7 @@ config ARCH_ROCKCHIP
bool "Rockchip RK2928 and RK3xxx SOCs" if ARCH_MULTI_V7 bool "Rockchip RK2928 and RK3xxx SOCs" if ARCH_MULTI_V7
select PINCTRL select PINCTRL
select PINCTRL_ROCKCHIP select PINCTRL_ROCKCHIP
select ARCH_HAS_RESET_CONTROLLER
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select ARM_GIC select ARM_GIC
select CACHE_L2X0 select CACHE_L2X0
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/clk/clk-conf.h>
#include "base.h" #include "base.h"
#include "power/power.h" #include "power/power.h"
...@@ -499,6 +500,10 @@ static int platform_drv_probe(struct device *_dev) ...@@ -499,6 +500,10 @@ static int platform_drv_probe(struct device *_dev)
struct platform_device *dev = to_platform_device(_dev); struct platform_device *dev = to_platform_device(_dev);
int ret; int ret;
ret = of_clk_set_defaults(_dev->of_node, false);
if (ret < 0)
return ret;
acpi_dev_pm_attach(_dev, true); acpi_dev_pm_attach(_dev, true);
ret = drv->probe(dev); ret = drv->probe(dev);
......
...@@ -102,6 +102,13 @@ config COMMON_CLK_KEYSTONE ...@@ -102,6 +102,13 @@ config COMMON_CLK_KEYSTONE
Supports clock drivers for Keystone based SOCs. These SOCs have local 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. a power sleep control module that gate the clock to the IPs and PLLs.
config COMMON_CLK_PALMAS
tristate "Clock driver for TI Palmas devices"
depends on MFD_PALMAS
---help---
This driver supports TI Palmas devices 32KHz output KG and KG_AUDIO
using common clock framework.
source "drivers/clk/qcom/Kconfig" source "drivers/clk/qcom/Kconfig"
endmenu endmenu
......
...@@ -9,12 +9,16 @@ obj-$(CONFIG_COMMON_CLK) += clk-gate.o ...@@ -9,12 +9,16 @@ obj-$(CONFIG_COMMON_CLK) += clk-gate.o
obj-$(CONFIG_COMMON_CLK) += clk-mux.o obj-$(CONFIG_COMMON_CLK) += clk-mux.o
obj-$(CONFIG_COMMON_CLK) += clk-composite.o obj-$(CONFIG_COMMON_CLK) += clk-composite.o
obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o
ifeq ($(CONFIG_OF), y)
obj-$(CONFIG_COMMON_CLK) += clk-conf.o
endif
# hardware specific clock types # hardware specific clock types
# please keep this section sorted lexicographically by file/directory path name # please keep this section sorted lexicographically by file/directory path name
obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o
obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
...@@ -22,6 +26,7 @@ obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o ...@@ -22,6 +26,7 @@ obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o
obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o
obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o
obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
......
...@@ -388,6 +388,7 @@ static unsigned long clk_main_recalc_rate(struct at91_pmc *pmc, ...@@ -388,6 +388,7 @@ static unsigned long clk_main_recalc_rate(struct at91_pmc *pmc,
if (parent_rate) if (parent_rate)
return parent_rate; return parent_rate;
pr_warn("Main crystal frequency not set, using approximate value\n");
tmp = pmc_read(pmc, AT91_CKGR_MCFR); tmp = pmc_read(pmc, AT91_CKGR_MCFR);
if (!(tmp & AT91_PMC_MAINRDY)) if (!(tmp & AT91_PMC_MAINRDY))
return 0; return 0;
......
/*
* Cirrus Logic CLPS711X CLK driver
*
* Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/mfd/syscon/clps711x.h>
#include <dt-bindings/clock/clps711x-clock.h>
#define CLPS711X_SYSCON1 (0x0100)
#define CLPS711X_SYSCON2 (0x1100)
#define CLPS711X_SYSFLG2 (CLPS711X_SYSCON2 + SYSFLG_OFFSET)
#define CLPS711X_PLLR (0xa5a8)
#define CLPS711X_EXT_FREQ (13000000)
#define CLPS711X_OSC_FREQ (3686400)
static const struct clk_div_table spi_div_table[] = {
{ .val = 0, .div = 32, },
{ .val = 1, .div = 8, },
{ .val = 2, .div = 2, },
{ .val = 3, .div = 1, },
};
static const struct clk_div_table timer_div_table[] = {
{ .val = 0, .div = 256, },
{ .val = 1, .div = 1, },
};
struct clps711x_clk {
struct clk_onecell_data clk_data;
spinlock_t lock;
struct clk *clks[CLPS711X_CLK_MAX];
};
static struct clps711x_clk * __init _clps711x_clk_init(void __iomem *base,
u32 fref)
{
u32 tmp, f_cpu, f_pll, f_bus, f_tim, f_pwm, f_spi;
struct clps711x_clk *clps711x_clk;
unsigned i;
if (!base)
return ERR_PTR(-ENOMEM);
clps711x_clk = kzalloc(sizeof(*clps711x_clk), GFP_KERNEL);
if (!clps711x_clk)
return ERR_PTR(-ENOMEM);
spin_lock_init(&clps711x_clk->lock);
/* Read PLL multiplier value and sanity check */
tmp = readl(base + CLPS711X_PLLR) >> 24;
if (((tmp >= 10) && (tmp <= 50)) || !fref)
f_pll = DIV_ROUND_UP(CLPS711X_OSC_FREQ * tmp, 2);
else
f_pll = fref;
tmp = readl(base + CLPS711X_SYSFLG2);
if (tmp & SYSFLG2_CKMODE) {
f_cpu = CLPS711X_EXT_FREQ;
f_bus = CLPS711X_EXT_FREQ;
f_spi = DIV_ROUND_CLOSEST(CLPS711X_EXT_FREQ, 96);
f_pll = 0;
f_pwm = DIV_ROUND_CLOSEST(CLPS711X_EXT_FREQ, 128);
} else {
f_cpu = f_pll;
if (f_cpu > 36864000)
f_bus = DIV_ROUND_UP(f_cpu, 2);
else
f_bus = 36864000 / 2;
f_spi = DIV_ROUND_CLOSEST(f_cpu, 576);
f_pwm = DIV_ROUND_CLOSEST(f_cpu, 768);
}
if (tmp & SYSFLG2_CKMODE) {
if (readl(base + CLPS711X_SYSCON2) & SYSCON2_OSTB)
f_tim = DIV_ROUND_CLOSEST(CLPS711X_EXT_FREQ, 26);
else
f_tim = DIV_ROUND_CLOSEST(CLPS711X_EXT_FREQ, 24);
} else
f_tim = DIV_ROUND_CLOSEST(f_cpu, 144);
tmp = readl(base + CLPS711X_SYSCON1);
/* Timer1 in free running mode.
* Counter will wrap around to 0xffff when it underflows
* and will continue to count down.
*/
tmp &= ~(SYSCON1_TC1M | SYSCON1_TC1S);
/* Timer2 in prescale mode.
* Value writen is automatically re-loaded when
* the counter underflows.
*/
tmp |= SYSCON1_TC2M | SYSCON1_TC2S;
writel(tmp, base + CLPS711X_SYSCON1);
clps711x_clk->clks[CLPS711X_CLK_DUMMY] =
clk_register_fixed_rate(NULL, "dummy", NULL, CLK_IS_ROOT, 0);
clps711x_clk->clks[CLPS711X_CLK_CPU] =
clk_register_fixed_rate(NULL, "cpu", NULL, CLK_IS_ROOT, f_cpu);
clps711x_clk->clks[CLPS711X_CLK_BUS] =
clk_register_fixed_rate(NULL, "bus", NULL, CLK_IS_ROOT, f_bus);
clps711x_clk->clks[CLPS711X_CLK_PLL] =
clk_register_fixed_rate(NULL, "pll", NULL, CLK_IS_ROOT, f_pll);
clps711x_clk->clks[CLPS711X_CLK_TIMERREF] =
clk_register_fixed_rate(NULL, "timer_ref", NULL, CLK_IS_ROOT,
f_tim);
clps711x_clk->clks[CLPS711X_CLK_TIMER1] =
clk_register_divider_table(NULL, "timer1", "timer_ref", 0,
base + CLPS711X_SYSCON1, 5, 1, 0,
timer_div_table, &clps711x_clk->lock);
clps711x_clk->clks[CLPS711X_CLK_TIMER2] =
clk_register_divider_table(NULL, "timer2", "timer_ref", 0,
base + CLPS711X_SYSCON1, 7, 1, 0,
timer_div_table, &clps711x_clk->lock);
clps711x_clk->clks[CLPS711X_CLK_PWM] =
clk_register_fixed_rate(NULL, "pwm", NULL, CLK_IS_ROOT, f_pwm);
clps711x_clk->clks[CLPS711X_CLK_SPIREF] =
clk_register_fixed_rate(NULL, "spi_ref", NULL, CLK_IS_ROOT,
f_spi);
clps711x_clk->clks[CLPS711X_CLK_SPI] =
clk_register_divider_table(NULL, "spi", "spi_ref", 0,
base + CLPS711X_SYSCON1, 16, 2, 0,
spi_div_table, &clps711x_clk->lock);
clps711x_clk->clks[CLPS711X_CLK_UART] =
clk_register_fixed_factor(NULL, "uart", "bus", 0, 1, 10);
clps711x_clk->clks[CLPS711X_CLK_TICK] =
clk_register_fixed_rate(NULL, "tick", NULL, CLK_IS_ROOT, 64);
for (i = 0; i < CLPS711X_CLK_MAX; i++)
if (IS_ERR(clps711x_clk->clks[i]))
pr_err("clk %i: register failed with %ld\n",
i, PTR_ERR(clps711x_clk->clks[i]));
return clps711x_clk;
}
void __init clps711x_clk_init(void __iomem *base)
{
struct clps711x_clk *clps711x_clk;
clps711x_clk = _clps711x_clk_init(base, 73728000);
BUG_ON(IS_ERR(clps711x_clk));
/* Clocksource */
clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_TIMER1],
NULL, "clps711x-timer.0");
clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_TIMER2],
NULL, "clps711x-timer.1");
/* Drivers */
clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_PWM],
NULL, "clps711x-pwm");
clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_UART],
NULL, "clps711x-uart.0");
clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_UART],
NULL, "clps711x-uart.1");
}
#ifdef CONFIG_OF
static void __init clps711x_clk_init_dt(struct device_node *np)
{
void __iomem *base = of_iomap(np, 0);
struct clps711x_clk *clps711x_clk;
u32 fref = 0;
WARN_ON(of_property_read_u32(np, "startup-frequency", &fref));
clps711x_clk = _clps711x_clk_init(base, fref);
BUG_ON(IS_ERR(clps711x_clk));
clps711x_clk->clk_data.clks = clps711x_clk->clks;
clps711x_clk->clk_data.clk_num = CLPS711X_CLK_MAX;
of_clk_add_provider(np, of_clk_src_onecell_get,
&clps711x_clk->clk_data);
}
CLK_OF_DECLARE(clps711x, "cirrus,clps711x-clk", clps711x_clk_init_dt);
#endif
...@@ -64,11 +64,56 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, ...@@ -64,11 +64,56 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops *mux_ops = composite->mux_ops; const struct clk_ops *mux_ops = composite->mux_ops;
struct clk_hw *rate_hw = composite->rate_hw; struct clk_hw *rate_hw = composite->rate_hw;
struct clk_hw *mux_hw = composite->mux_hw; struct clk_hw *mux_hw = composite->mux_hw;
struct clk *parent;
unsigned long parent_rate;
long tmp_rate, best_rate = 0;
unsigned long rate_diff;
unsigned long best_rate_diff = ULONG_MAX;
int i;
if (rate_hw && rate_ops && rate_ops->determine_rate) { if (rate_hw && rate_ops && rate_ops->determine_rate) {
rate_hw->clk = hw->clk; rate_hw->clk = hw->clk;
return rate_ops->determine_rate(rate_hw, rate, best_parent_rate, return rate_ops->determine_rate(rate_hw, rate, best_parent_rate,
best_parent_p); best_parent_p);
} else if (rate_hw && rate_ops && rate_ops->round_rate &&
mux_hw && mux_ops && mux_ops->set_parent) {
*best_parent_p = NULL;
if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) {
*best_parent_p = clk_get_parent(mux_hw->clk);
*best_parent_rate = __clk_get_rate(*best_parent_p);
return rate_ops->round_rate(rate_hw, rate,
best_parent_rate);
}
for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) {
parent = clk_get_parent_by_index(mux_hw->clk, i);
if (!parent)
continue;
parent_rate = __clk_get_rate(parent);
tmp_rate = rate_ops->round_rate(rate_hw, rate,
&parent_rate);
if (tmp_rate < 0)
continue;
rate_diff = abs(rate - tmp_rate);
if (!rate_diff || !*best_parent_p
|| best_rate_diff > rate_diff) {
*best_parent_p = parent;
*best_parent_rate = parent_rate;
best_rate_diff = rate_diff;
best_rate = tmp_rate;
}
if (!rate_diff)
return rate;
}
return best_rate;
} else if (mux_hw && mux_ops && mux_ops->determine_rate) { } else if (mux_hw && mux_ops && mux_ops->determine_rate) {
mux_hw->clk = hw->clk; mux_hw->clk = hw->clk;
return mux_ops->determine_rate(mux_hw, rate, best_parent_rate, return mux_ops->determine_rate(mux_hw, rate, best_parent_rate,
...@@ -162,7 +207,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name, ...@@ -162,7 +207,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
clk_composite_ops = &composite->ops; clk_composite_ops = &composite->ops;
if (mux_hw && mux_ops) { if (mux_hw && mux_ops) {
if (!mux_ops->get_parent || !mux_ops->set_parent) { if (!mux_ops->get_parent) {
clk = ERR_PTR(-EINVAL); clk = ERR_PTR(-EINVAL);
goto err; goto err;
} }
...@@ -170,7 +215,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name, ...@@ -170,7 +215,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
composite->mux_hw = mux_hw; composite->mux_hw = mux_hw;
composite->mux_ops = mux_ops; composite->mux_ops = mux_ops;
clk_composite_ops->get_parent = clk_composite_get_parent; clk_composite_ops->get_parent = clk_composite_get_parent;
clk_composite_ops->set_parent = clk_composite_set_parent; if (mux_ops->set_parent)
clk_composite_ops->set_parent = clk_composite_set_parent;
if (mux_ops->determine_rate) if (mux_ops->determine_rate)
clk_composite_ops->determine_rate = clk_composite_determine_rate; clk_composite_ops->determine_rate = clk_composite_determine_rate;
} }
...@@ -180,24 +226,27 @@ struct clk *clk_register_composite(struct device *dev, const char *name, ...@@ -180,24 +226,27 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
clk = ERR_PTR(-EINVAL); clk = ERR_PTR(-EINVAL);
goto err; goto err;
} }
clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
/* .round_rate is a prerequisite for .set_rate */ if (rate_ops->determine_rate)
if (rate_ops->round_rate) { clk_composite_ops->determine_rate =
clk_composite_ops->round_rate = clk_composite_round_rate; clk_composite_determine_rate;
if (rate_ops->set_rate) { else if (rate_ops->round_rate)
clk_composite_ops->set_rate = clk_composite_set_rate; clk_composite_ops->round_rate =
} clk_composite_round_rate;
} else {
WARN(rate_ops->set_rate, /* .set_rate requires either .round_rate or .determine_rate */
"%s: missing round_rate op is required\n", if (rate_ops->set_rate) {
__func__); if (rate_ops->determine_rate || rate_ops->round_rate)
clk_composite_ops->set_rate =
clk_composite_set_rate;
else
WARN(1, "%s: missing round_rate op is required\n",
__func__);
} }
composite->rate_hw = rate_hw; composite->rate_hw = rate_hw;
composite->rate_ops = rate_ops; composite->rate_ops = rate_ops;
clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
if (rate_ops->determine_rate)
clk_composite_ops->determine_rate = clk_composite_determine_rate;
} }
if (gate_hw && gate_ops) { if (gate_hw && gate_ops) {
......
/*
* Copyright (C) 2014 Samsung Electronics Co., Ltd.
* Sylwester Nawrocki <s.nawrocki@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clk/clk-conf.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/printk.h>
#include "clk.h"
static int __set_clk_parents(struct device_node *node, bool clk_supplier)
{
struct of_phandle_args clkspec;
int index, rc, num_parents;
struct clk *clk, *pclk;
num_parents = of_count_phandle_with_args(node, "assigned-clock-parents",
"#clock-cells");
if (num_parents == -EINVAL)
pr_err("clk: invalid value of clock-parents property at %s\n",
node->full_name);
for (index = 0; index < num_parents; index++) {
rc = of_parse_phandle_with_args(node, "assigned-clock-parents",
"#clock-cells", index, &clkspec);
if (rc < 0) {
/* skip empty (null) phandles */
if (rc == -ENOENT)
continue;
else
return rc;
}
if (clkspec.np == node && !clk_supplier)
return 0;
pclk = of_clk_get_by_clkspec(&clkspec);
if (IS_ERR(pclk)) {
pr_warn("clk: couldn't get parent clock %d for %s\n",
index, node->full_name);
return PTR_ERR(pclk);
}
rc = of_parse_phandle_with_args(node, "assigned-clocks",
"#clock-cells", index, &clkspec);
if (rc < 0)
goto err;
if (clkspec.np == node && !clk_supplier) {
rc = 0;
goto err;
}
clk = of_clk_get_by_clkspec(&clkspec);
if (IS_ERR(clk)) {
pr_warn("clk: couldn't get parent clock %d for %s\n",
index, node->full_name);
rc = PTR_ERR(clk);
goto err;
}
rc = clk_set_parent(clk, pclk);
if (rc < 0)
pr_err("clk: failed to reparent %s to %s: %d\n",
__clk_get_name(clk), __clk_get_name(pclk), rc);
clk_put(clk);
clk_put(pclk);
}
return 0;
err:
clk_put(pclk);
return rc;
}
static int __set_clk_rates(struct device_node *node, bool clk_supplier)
{
struct of_phandle_args clkspec;
struct property *prop;
const __be32 *cur;
int rc, index = 0;
struct clk *clk;
u32 rate;
of_property_for_each_u32(node, "assigned-clock-rates", prop, cur, rate) {
if (rate) {
rc = of_parse_phandle_with_args(node, "assigned-clocks",
"#clock-cells", index, &clkspec);
if (rc < 0) {
/* skip empty (null) phandles */
if (rc == -ENOENT)
continue;
else
return rc;
}
if (clkspec.np == node && !clk_supplier)
return 0;
clk = of_clk_get_by_clkspec(&clkspec);
if (IS_ERR(clk)) {
pr_warn("clk: couldn't get clock %d for %s\n",
index, node->full_name);
return PTR_ERR(clk);
}
rc = clk_set_rate(clk, rate);
if (rc < 0)
pr_err("clk: couldn't set %s clock rate: %d\n",
__clk_get_name(clk), rc);
clk_put(clk);
}
index++;
}
return 0;
}
/**
* of_clk_set_defaults() - parse and set assigned clocks configuration
* @node: device node to apply clock settings for
* @clk_supplier: true if clocks supplied by @node should also be considered
*
* This function parses 'assigned-{clocks/clock-parents/clock-rates}' properties
* and sets any specified clock parents and rates. The @clk_supplier argument
* should be set to true if @node may be also a clock supplier of any clock
* listed in its 'assigned-clocks' or 'assigned-clock-parents' properties.
* If @clk_supplier is false the function exits returnning 0 as soon as it
* determines the @node is also a supplier of any of the clocks.
*/
int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
{
int rc;
if (!node)
return 0;
rc = __set_clk_parents(node, clk_supplier);
if (rc < 0)
return rc;
return __set_clk_rates(node, clk_supplier);
}
EXPORT_SYMBOL_GPL(of_clk_set_defaults);
/*
* Clock driver for Palmas device.
*
* Copyright (c) 2013, NVIDIA Corporation.
* Copyright (c) 2013-2014 Texas Instruments, Inc.
*
* Author: Laxman Dewangan <ldewangan@nvidia.com>
* Peter Ujfalusi <peter.ujfalusi@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
* whether express or implied; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/mfd/palmas.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#define PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE1 1
#define PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE2 2
#define PALMAS_CLOCK_DT_EXT_CONTROL_NSLEEP 3
struct palmas_clk32k_desc {
const char *clk_name;
unsigned int control_reg;
unsigned int enable_mask;
unsigned int sleep_mask;
unsigned int sleep_reqstr_id;
int delay;
};
struct palmas_clock_info {
struct device *dev;
struct clk *clk;
struct clk_hw hw;
struct palmas *palmas;
struct palmas_clk32k_desc *clk_desc;
int ext_control_pin;
};
static inline struct palmas_clock_info *to_palmas_clks_info(struct clk_hw *hw)
{
return container_of(hw, struct palmas_clock_info, hw);
}
static unsigned long palmas_clks_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return 32768;
}
static int palmas_clks_prepare(struct clk_hw *hw)
{
struct palmas_clock_info *cinfo = to_palmas_clks_info(hw);
int ret;
ret = palmas_update_bits(cinfo->palmas, PALMAS_RESOURCE_BASE,
cinfo->clk_desc->control_reg,
cinfo->clk_desc->enable_mask,
cinfo->clk_desc->enable_mask);
if (ret < 0)
dev_err(cinfo->dev, "Reg 0x%02x update failed, %d\n",
cinfo->clk_desc->control_reg, ret);
else if (cinfo->clk_desc->delay)
udelay(cinfo->clk_desc->delay);
return ret;
}
static void palmas_clks_unprepare(struct clk_hw *hw)
{
struct palmas_clock_info *cinfo = to_palmas_clks_info(hw);
int ret;
/*
* Clock can be disabled through external pin if it is externally
* controlled.
*/
if (cinfo->ext_control_pin)
return;
ret = palmas_update_bits(cinfo->palmas, PALMAS_RESOURCE_BASE,
cinfo->clk_desc->control_reg,
cinfo->clk_desc->enable_mask, 0);
if (ret < 0)
dev_err(cinfo->dev, "Reg 0x%02x update failed, %d\n",
cinfo->clk_desc->control_reg, ret);
}
static int palmas_clks_is_prepared(struct clk_hw *hw)
{
struct palmas_clock_info *cinfo = to_palmas_clks_info(hw);
int ret;
u32 val;
if (cinfo->ext_control_pin)
return 1;
ret = palmas_read(cinfo->palmas, PALMAS_RESOURCE_BASE,
cinfo->clk_desc->control_reg, &val);
if (ret < 0) {
dev_err(cinfo->dev, "Reg 0x%02x read failed, %d\n",
cinfo->clk_desc->control_reg, ret);
return ret;
}
return !!(val & cinfo->clk_desc->enable_mask);
}
static struct clk_ops palmas_clks_ops = {
.prepare = palmas_clks_prepare,
.unprepare = palmas_clks_unprepare,
.is_prepared = palmas_clks_is_prepared,
.recalc_rate = palmas_clks_recalc_rate,
};
struct palmas_clks_of_match_data {
struct clk_init_data init;
struct palmas_clk32k_desc desc;
};
static struct palmas_clks_of_match_data palmas_of_clk32kg = {
.init = {
.name = "clk32kg",
.ops = &palmas_clks_ops,
.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED,
},
.desc = {
.clk_name = "clk32kg",
.control_reg = PALMAS_CLK32KG_CTRL,
.enable_mask = PALMAS_CLK32KG_CTRL_MODE_ACTIVE,
.sleep_mask = PALMAS_CLK32KG_CTRL_MODE_SLEEP,
.sleep_reqstr_id = PALMAS_EXTERNAL_REQSTR_ID_CLK32KG,
.delay = 200,
},
};
static struct palmas_clks_of_match_data palmas_of_clk32kgaudio = {
.init = {
.name = "clk32kgaudio",
.ops = &palmas_clks_ops,
.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED,
},
.desc = {
.clk_name = "clk32kgaudio",
.control_reg = PALMAS_CLK32KGAUDIO_CTRL,
.enable_mask = PALMAS_CLK32KG_CTRL_MODE_ACTIVE,
.sleep_mask = PALMAS_CLK32KG_CTRL_MODE_SLEEP,
.sleep_reqstr_id = PALMAS_EXTERNAL_REQSTR_ID_CLK32KGAUDIO,
.delay = 200,
},
};
static struct of_device_id palmas_clks_of_match[] = {
{
.compatible = "ti,palmas-clk32kg",
.data = &palmas_of_clk32kg,
},
{
.compatible = "ti,palmas-clk32kgaudio",
.data = &palmas_of_clk32kgaudio,
},
{ },
};
MODULE_DEVICE_TABLE(of, palmas_clks_of_match);
static void palmas_clks_get_clk_data(struct platform_device *pdev,
struct palmas_clock_info *cinfo)
{
struct device_node *node = pdev->dev.of_node;
unsigned int prop;
int ret;
ret = of_property_read_u32(node, "ti,external-sleep-control",
&prop);
if (ret)
return;
switch (prop) {
case PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE1:
prop = PALMAS_EXT_CONTROL_ENABLE1;
break;
case PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE2:
prop = PALMAS_EXT_CONTROL_ENABLE2;
break;
case PALMAS_CLOCK_DT_EXT_CONTROL_NSLEEP:
prop = PALMAS_EXT_CONTROL_NSLEEP;
break;
default:
dev_warn(&pdev->dev, "%s: Invalid ext control option: %u\n",
node->name, prop);
prop = 0;
break;
}
cinfo->ext_control_pin = prop;
}
static int palmas_clks_init_configure(struct palmas_clock_info *cinfo)
{
int ret;
ret = palmas_update_bits(cinfo->palmas, PALMAS_RESOURCE_BASE,
cinfo->clk_desc->control_reg,
cinfo->clk_desc->sleep_mask, 0);
if (ret < 0) {
dev_err(cinfo->dev, "Reg 0x%02x update failed, %d\n",
cinfo->clk_desc->control_reg, ret);
return ret;
}
if (cinfo->ext_control_pin) {
ret = clk_prepare(cinfo->clk);
if (ret < 0) {
dev_err(cinfo->dev, "Clock prep failed, %d\n", ret);
return ret;
}
ret = palmas_ext_control_req_config(cinfo->palmas,
cinfo->clk_desc->sleep_reqstr_id,
cinfo->ext_control_pin, true);
if (ret < 0) {
dev_err(cinfo->dev, "Ext config for %s failed, %d\n",
cinfo->clk_desc->clk_name, ret);
return ret;
}
}
return ret;
}
static int palmas_clks_probe(struct platform_device *pdev)
{
struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
struct device_node *node = pdev->dev.of_node;
struct palmas_clks_of_match_data *match_data;
const struct of_device_id *match;
struct palmas_clock_info *cinfo;
struct clk *clk;
int ret;
match = of_match_device(palmas_clks_of_match, &pdev->dev);
match_data = (struct palmas_clks_of_match_data *)match->data;
cinfo = devm_kzalloc(&pdev->dev, sizeof(*cinfo), GFP_KERNEL);
if (!cinfo)
return -ENOMEM;
palmas_clks_get_clk_data(pdev, cinfo);
platform_set_drvdata(pdev, cinfo);
cinfo->dev = &pdev->dev;
cinfo->palmas = palmas;
cinfo->clk_desc = &match_data->desc;
cinfo->hw.init = &match_data->init;
clk = devm_clk_register(&pdev->dev, &cinfo->hw);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
dev_err(&pdev->dev, "Fail to register clock %s, %d\n",
match_data->desc.clk_name, ret);
return ret;
}
cinfo->clk = clk;
ret = palmas_clks_init_configure(cinfo);
if (ret < 0) {
dev_err(&pdev->dev, "Clock config failed, %d\n", ret);
return ret;
}
ret = of_clk_add_provider(node, of_clk_src_simple_get, cinfo->clk);
if (ret < 0)
dev_err(&pdev->dev, "Fail to add clock driver, %d\n", ret);
return ret;
}
static int palmas_clks_remove(struct platform_device *pdev)
{
of_clk_del_provider(pdev->dev.of_node);
return 0;
}
static struct platform_driver palmas_clks_driver = {
.driver = {
.name = "palmas-clk",
.owner = THIS_MODULE,
.of_match_table = palmas_clks_of_match,
},
.probe = palmas_clks_probe,
.remove = palmas_clks_remove,
};
module_platform_driver(palmas_clks_driver);
MODULE_DESCRIPTION("Clock driver for Palmas Series Devices");
MODULE_ALIAS("platform:palmas-clk");
MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
MODULE_LICENSE("GPL v2");
...@@ -291,7 +291,7 @@ static const struct of_device_id ppc_clk_ids[] __initconst = { ...@@ -291,7 +291,7 @@ static const struct of_device_id ppc_clk_ids[] __initconst = {
{} {}
}; };
static struct platform_driver ppc_corenet_clk_driver = { static struct platform_driver ppc_corenet_clk_driver __initdata = {
.driver = { .driver = {
.name = "ppc_corenet_clock", .name = "ppc_corenet_clock",
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -46,7 +46,6 @@ struct s2mps11_clk { ...@@ -46,7 +46,6 @@ struct s2mps11_clk {
struct clk *clk; struct clk *clk;
struct clk_lookup *lookup; struct clk_lookup *lookup;
u32 mask; u32 mask;
bool enabled;
unsigned int reg; unsigned int reg;
}; };
...@@ -63,8 +62,6 @@ static int s2mps11_clk_prepare(struct clk_hw *hw) ...@@ -63,8 +62,6 @@ static int s2mps11_clk_prepare(struct clk_hw *hw)
ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, ret = regmap_update_bits(s2mps11->iodev->regmap_pmic,
s2mps11->reg, s2mps11->reg,
s2mps11->mask, s2mps11->mask); s2mps11->mask, s2mps11->mask);
if (!ret)
s2mps11->enabled = true;
return ret; return ret;
} }
...@@ -76,32 +73,32 @@ static void s2mps11_clk_unprepare(struct clk_hw *hw) ...@@ -76,32 +73,32 @@ static void s2mps11_clk_unprepare(struct clk_hw *hw)
ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, s2mps11->reg, ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, s2mps11->reg,
s2mps11->mask, ~s2mps11->mask); s2mps11->mask, ~s2mps11->mask);
if (!ret)
s2mps11->enabled = false;
} }
static int s2mps11_clk_is_enabled(struct clk_hw *hw) static int s2mps11_clk_is_prepared(struct clk_hw *hw)
{ {
int ret;
u32 val;
struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw); struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
return s2mps11->enabled; ret = regmap_read(s2mps11->iodev->regmap_pmic,
s2mps11->reg, &val);
if (ret < 0)
return -EINVAL;
return val & s2mps11->mask;
} }
static unsigned long s2mps11_clk_recalc_rate(struct clk_hw *hw, static unsigned long s2mps11_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate) unsigned long parent_rate)
{ {
struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw); return 32768;
if (s2mps11->enabled)
return 32768;
else
return 0;
} }
static struct clk_ops s2mps11_clk_ops = { static struct clk_ops s2mps11_clk_ops = {
.prepare = s2mps11_clk_prepare, .prepare = s2mps11_clk_prepare,
.unprepare = s2mps11_clk_unprepare, .unprepare = s2mps11_clk_unprepare,
.is_enabled = s2mps11_clk_is_enabled, .is_prepared = s2mps11_clk_is_prepared,
.recalc_rate = s2mps11_clk_recalc_rate, .recalc_rate = s2mps11_clk_recalc_rate,
}; };
...@@ -169,7 +166,6 @@ static int s2mps11_clk_probe(struct platform_device *pdev) ...@@ -169,7 +166,6 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
unsigned int s2mps11_reg; unsigned int s2mps11_reg;
struct clk_init_data *clks_init; struct clk_init_data *clks_init;
int i, ret = 0; int i, ret = 0;
u32 val;
s2mps11_clks = devm_kzalloc(&pdev->dev, sizeof(*s2mps11_clk) * s2mps11_clks = devm_kzalloc(&pdev->dev, sizeof(*s2mps11_clk) *
S2MPS11_CLKS_NUM, GFP_KERNEL); S2MPS11_CLKS_NUM, GFP_KERNEL);
...@@ -214,13 +210,6 @@ static int s2mps11_clk_probe(struct platform_device *pdev) ...@@ -214,13 +210,6 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
s2mps11_clk->mask = 1 << i; s2mps11_clk->mask = 1 << i;
s2mps11_clk->reg = s2mps11_reg; s2mps11_clk->reg = s2mps11_reg;
ret = regmap_read(s2mps11_clk->iodev->regmap_pmic,
s2mps11_clk->reg, &val);
if (ret < 0)
goto err_reg;
s2mps11_clk->enabled = val & s2mps11_clk->mask;
s2mps11_clk->clk = devm_clk_register(&pdev->dev, s2mps11_clk->clk = devm_clk_register(&pdev->dev,
&s2mps11_clk->hw); &s2mps11_clk->hw);
if (IS_ERR(s2mps11_clk->clk)) { if (IS_ERR(s2mps11_clk->clk)) {
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
*/ */
#include <linux/clk-private.h> #include <linux/clk-private.h>
#include <linux/clk/clk-conf.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -98,9 +99,19 @@ static void clk_enable_unlock(unsigned long flags) ...@@ -98,9 +99,19 @@ static void clk_enable_unlock(unsigned long flags)
#include <linux/debugfs.h> #include <linux/debugfs.h>
static struct dentry *rootdir; static struct dentry *rootdir;
static struct dentry *orphandir;
static int inited = 0; static int inited = 0;
static struct hlist_head *all_lists[] = {
&clk_root_list,
&clk_orphan_list,
NULL,
};
static struct hlist_head *orphan_list[] = {
&clk_orphan_list,
NULL,
};
static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level) static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
{ {
if (!c) if (!c)
...@@ -130,17 +141,16 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk *c, ...@@ -130,17 +141,16 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
static int clk_summary_show(struct seq_file *s, void *data) static int clk_summary_show(struct seq_file *s, void *data)
{ {
struct clk *c; struct clk *c;
struct hlist_head **lists = (struct hlist_head **)s->private;
seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy\n"); seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy\n");
seq_puts(s, "--------------------------------------------------------------------------------\n"); seq_puts(s, "--------------------------------------------------------------------------------\n");
clk_prepare_lock(); clk_prepare_lock();
hlist_for_each_entry(c, &clk_root_list, child_node) for (; *lists; lists++)
clk_summary_show_subtree(s, c, 0); hlist_for_each_entry(c, *lists, child_node)
clk_summary_show_subtree(s, c, 0);
hlist_for_each_entry(c, &clk_orphan_list, child_node)
clk_summary_show_subtree(s, c, 0);
clk_prepare_unlock(); clk_prepare_unlock();
...@@ -193,21 +203,19 @@ static int clk_dump(struct seq_file *s, void *data) ...@@ -193,21 +203,19 @@ static int clk_dump(struct seq_file *s, void *data)
{ {
struct clk *c; struct clk *c;
bool first_node = true; bool first_node = true;
struct hlist_head **lists = (struct hlist_head **)s->private;
seq_printf(s, "{"); seq_printf(s, "{");
clk_prepare_lock(); clk_prepare_lock();
hlist_for_each_entry(c, &clk_root_list, child_node) { for (; *lists; lists++) {
if (!first_node) hlist_for_each_entry(c, *lists, child_node) {
seq_printf(s, ","); if (!first_node)
first_node = false; seq_puts(s, ",");
clk_dump_subtree(s, c, 0); first_node = false;
} clk_dump_subtree(s, c, 0);
}
hlist_for_each_entry(c, &clk_orphan_list, child_node) {
seq_printf(s, ",");
clk_dump_subtree(s, c, 0);
} }
clk_prepare_unlock(); clk_prepare_unlock();
...@@ -276,9 +284,11 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) ...@@ -276,9 +284,11 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
if (!d) if (!d)
goto err_out; goto err_out;
if (clk->ops->debug_init) if (clk->ops->debug_init) {
if (clk->ops->debug_init(clk->hw, clk->dentry)) ret = clk->ops->debug_init(clk->hw, clk->dentry);
if (ret)
goto err_out; goto err_out;
}
ret = 0; ret = 0;
goto out; goto out;
...@@ -305,7 +315,7 @@ static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry) ...@@ -305,7 +315,7 @@ static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
goto out; goto out;
hlist_for_each_entry(child, &clk->children, child_node) hlist_for_each_entry(child, &clk->children, child_node)
clk_debug_create_subtree(child, clk->dentry); clk_debug_create_subtree(child, pdentry);
ret = 0; ret = 0;
out: out:
...@@ -325,31 +335,12 @@ static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry) ...@@ -325,31 +335,12 @@ static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
*/ */
static int clk_debug_register(struct clk *clk) static int clk_debug_register(struct clk *clk)
{ {
struct clk *parent;
struct dentry *pdentry;
int ret = 0; int ret = 0;
if (!inited) if (!inited)
goto out; goto out;
parent = clk->parent; ret = clk_debug_create_subtree(clk, rootdir);
/*
* Check to see if a clk is a root clk. Also check that it is
* safe to add this clk to debugfs
*/
if (!parent)
if (clk->flags & CLK_IS_ROOT)
pdentry = rootdir;
else
pdentry = orphandir;
else
if (parent->dentry)
pdentry = parent->dentry;
else
goto out;
ret = clk_debug_create_subtree(clk, pdentry);
out: out:
return ret; return ret;
...@@ -370,38 +361,17 @@ static void clk_debug_unregister(struct clk *clk) ...@@ -370,38 +361,17 @@ static void clk_debug_unregister(struct clk *clk)
debugfs_remove_recursive(clk->dentry); debugfs_remove_recursive(clk->dentry);
} }
/** struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode,
* clk_debug_reparent - reparent clk node in the debugfs clk tree void *data, const struct file_operations *fops)
* @clk: the clk being reparented
* @new_parent: the new clk parent, may be NULL
*
* Rename clk entry in the debugfs clk tree if debugfs has been
* initialized. Otherwise it bails out early since the debugfs clk tree
* will be created lazily by clk_debug_init as part of a late_initcall.
*
* Caller must hold prepare_lock.
*/
static void clk_debug_reparent(struct clk *clk, struct clk *new_parent)
{ {
struct dentry *d; struct dentry *d = NULL;
struct dentry *new_parent_d;
if (!inited)
return;
if (new_parent) if (clk->dentry)
new_parent_d = new_parent->dentry; d = debugfs_create_file(name, mode, clk->dentry, data, fops);
else
new_parent_d = orphandir;
d = debugfs_rename(clk->dentry->d_parent, clk->dentry, return d;
new_parent_d, clk->name);
if (d)
clk->dentry = d;
else
pr_debug("%s: failed to rename debugfs entry for %s\n",
__func__, clk->name);
} }
EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
/** /**
* clk_debug_init - lazily create the debugfs clk tree visualization * clk_debug_init - lazily create the debugfs clk tree visualization
...@@ -425,19 +395,24 @@ static int __init clk_debug_init(void) ...@@ -425,19 +395,24 @@ static int __init clk_debug_init(void)
if (!rootdir) if (!rootdir)
return -ENOMEM; return -ENOMEM;
d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, NULL, d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, &all_lists,
&clk_summary_fops); &clk_summary_fops);
if (!d) if (!d)
return -ENOMEM; return -ENOMEM;
d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, NULL, d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, &all_lists,
&clk_dump_fops); &clk_dump_fops);
if (!d) if (!d)
return -ENOMEM; return -ENOMEM;
orphandir = debugfs_create_dir("orphans", rootdir); d = debugfs_create_file("clk_orphan_summary", S_IRUGO, rootdir,
&orphan_list, &clk_summary_fops);
if (!d)
return -ENOMEM;
if (!orphandir) d = debugfs_create_file("clk_orphan_dump", S_IRUGO, rootdir,
&orphan_list, &clk_dump_fops);
if (!d)
return -ENOMEM; return -ENOMEM;
clk_prepare_lock(); clk_prepare_lock();
...@@ -446,7 +421,7 @@ static int __init clk_debug_init(void) ...@@ -446,7 +421,7 @@ static int __init clk_debug_init(void)
clk_debug_create_subtree(clk, rootdir); clk_debug_create_subtree(clk, rootdir);
hlist_for_each_entry(clk, &clk_orphan_list, child_node) hlist_for_each_entry(clk, &clk_orphan_list, child_node)
clk_debug_create_subtree(clk, orphandir); clk_debug_create_subtree(clk, rootdir);
inited = 1; inited = 1;
...@@ -1284,9 +1259,6 @@ static void __clk_set_parent_after(struct clk *clk, struct clk *parent, ...@@ -1284,9 +1259,6 @@ static void __clk_set_parent_after(struct clk *clk, struct clk *parent,
clk_disable(old_parent); clk_disable(old_parent);
__clk_unprepare(old_parent); __clk_unprepare(old_parent);
} }
/* update debugfs with new clk tree topology */
clk_debug_reparent(clk, parent);
} }
static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
...@@ -1683,7 +1655,6 @@ static struct clk *__clk_init_parent(struct clk *clk) ...@@ -1683,7 +1655,6 @@ static struct clk *__clk_init_parent(struct clk *clk)
void __clk_reparent(struct clk *clk, struct clk *new_parent) void __clk_reparent(struct clk *clk, struct clk *new_parent)
{ {
clk_reparent(clk, new_parent); clk_reparent(clk, new_parent);
clk_debug_reparent(clk, new_parent);
__clk_recalc_accuracies(clk); __clk_recalc_accuracies(clk);
__clk_recalc_rates(clk, POST_RATE_CHANGE); __clk_recalc_rates(clk, POST_RATE_CHANGE);
} }
...@@ -2414,6 +2385,7 @@ int of_clk_add_provider(struct device_node *np, ...@@ -2414,6 +2385,7 @@ int of_clk_add_provider(struct device_node *np,
void *data) void *data)
{ {
struct of_clk_provider *cp; struct of_clk_provider *cp;
int ret;
cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL); cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL);
if (!cp) if (!cp)
...@@ -2428,7 +2400,11 @@ int of_clk_add_provider(struct device_node *np, ...@@ -2428,7 +2400,11 @@ int of_clk_add_provider(struct device_node *np,
mutex_unlock(&of_clk_mutex); mutex_unlock(&of_clk_mutex);
pr_debug("Added clock from %s\n", np->full_name); pr_debug("Added clock from %s\n", np->full_name);
return 0; ret = of_clk_set_defaults(np, true);
if (ret < 0)
of_clk_del_provider(np);
return ret;
} }
EXPORT_SYMBOL_GPL(of_clk_add_provider); EXPORT_SYMBOL_GPL(of_clk_add_provider);
...@@ -2605,7 +2581,10 @@ void __init of_clk_init(const struct of_device_id *matches) ...@@ -2605,7 +2581,10 @@ void __init of_clk_init(const struct of_device_id *matches)
list_for_each_entry_safe(clk_provider, next, list_for_each_entry_safe(clk_provider, next,
&clk_provider_list, node) { &clk_provider_list, node) {
if (force || parent_ready(clk_provider->np)) { if (force || parent_ready(clk_provider->np)) {
clk_provider->clk_init_cb(clk_provider->np); clk_provider->clk_init_cb(clk_provider->np);
of_clk_set_defaults(clk_provider->np, true);
list_del(&clk_provider->node); list_del(&clk_provider->node);
kfree(clk_provider); kfree(clk_provider);
is_init_done = true; is_init_done = true;
...@@ -2620,7 +2599,6 @@ void __init of_clk_init(const struct of_device_id *matches) ...@@ -2620,7 +2599,6 @@ void __init of_clk_init(const struct of_device_id *matches)
*/ */
if (!is_init_done) if (!is_init_done)
force = true; force = true;
} }
} }
#endif #endif
...@@ -101,8 +101,9 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name) ...@@ -101,8 +101,9 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
if (!IS_ERR(clk)) if (!IS_ERR(clk))
break; break;
else if (name && index >= 0) { else if (name && index >= 0) {
pr_err("ERROR: could not get clock %s:%s(%i)\n", if (PTR_ERR(clk) != -EPROBE_DEFER)
np->full_name, name ? name : "", index); pr_err("ERROR: could not get clock %s:%s(%i)\n",
np->full_name, name ? name : "", index);
return clk; return clk;
} }
......
...@@ -4,6 +4,31 @@ config COMMON_CLK_QCOM ...@@ -4,6 +4,31 @@ config COMMON_CLK_QCOM
select REGMAP_MMIO select REGMAP_MMIO
select RESET_CONTROLLER select RESET_CONTROLLER
config APQ_GCC_8084
tristate "APQ8084 Global Clock Controller"
depends on COMMON_CLK_QCOM
help
Support for the global clock controller on apq8084 devices.
Say Y if you want to use peripheral devices such as UART, SPI,
i2c, USB, SD/eMMC, SATA, PCIe, etc.
config APQ_MMCC_8084
tristate "APQ8084 Multimedia Clock Controller"
select APQ_GCC_8084
depends on COMMON_CLK_QCOM
help
Support for the multimedia clock controller on apq8084 devices.
Say Y if you want to support multimedia devices such as display,
graphics, video encode/decode, camera, etc.
config IPQ_GCC_806X
tristate "IPQ806x Global Clock Controller"
depends on COMMON_CLK_QCOM
help
Support for the global clock controller on ipq806x devices.
Say Y if you want to use peripheral devices such as UART, SPI,
i2c, USB, SD/eMMC, etc.
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
......
...@@ -8,6 +8,9 @@ clk-qcom-y += clk-rcg2.o ...@@ -8,6 +8,9 @@ clk-qcom-y += clk-rcg2.o
clk-qcom-y += clk-branch.o clk-qcom-y += clk-branch.o
clk-qcom-y += reset.o clk-qcom-y += reset.o
obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o
obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
......
...@@ -166,7 +166,7 @@ const struct clk_ops clk_pll_vote_ops = { ...@@ -166,7 +166,7 @@ const struct clk_ops clk_pll_vote_ops = {
EXPORT_SYMBOL_GPL(clk_pll_vote_ops); EXPORT_SYMBOL_GPL(clk_pll_vote_ops);
static void static void
clk_pll_set_fsm_mode(struct clk_pll *pll, struct regmap *regmap) clk_pll_set_fsm_mode(struct clk_pll *pll, struct regmap *regmap, u8 lock_count)
{ {
u32 val; u32 val;
u32 mask; u32 mask;
...@@ -175,7 +175,7 @@ clk_pll_set_fsm_mode(struct clk_pll *pll, struct regmap *regmap) ...@@ -175,7 +175,7 @@ clk_pll_set_fsm_mode(struct clk_pll *pll, struct regmap *regmap)
regmap_update_bits(regmap, pll->mode_reg, PLL_VOTE_FSM_RESET, 0); regmap_update_bits(regmap, pll->mode_reg, PLL_VOTE_FSM_RESET, 0);
/* Program bias count and lock count */ /* Program bias count and lock count */
val = 1 << PLL_BIAS_COUNT_SHIFT; val = 1 << PLL_BIAS_COUNT_SHIFT | lock_count << PLL_LOCK_COUNT_SHIFT;
mask = PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT; mask = PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT;
mask |= PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT; mask |= PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT;
regmap_update_bits(regmap, pll->mode_reg, mask, val); regmap_update_bits(regmap, pll->mode_reg, mask, val);
...@@ -212,11 +212,20 @@ static void clk_pll_configure(struct clk_pll *pll, struct regmap *regmap, ...@@ -212,11 +212,20 @@ static void clk_pll_configure(struct clk_pll *pll, struct regmap *regmap,
regmap_update_bits(regmap, pll->config_reg, mask, val); regmap_update_bits(regmap, pll->config_reg, mask, val);
} }
void clk_pll_configure_sr(struct clk_pll *pll, struct regmap *regmap,
const struct pll_config *config, bool fsm_mode)
{
clk_pll_configure(pll, regmap, config);
if (fsm_mode)
clk_pll_set_fsm_mode(pll, regmap, 8);
}
EXPORT_SYMBOL_GPL(clk_pll_configure_sr);
void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap, void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
const struct pll_config *config, bool fsm_mode) const struct pll_config *config, bool fsm_mode)
{ {
clk_pll_configure(pll, regmap, config); clk_pll_configure(pll, regmap, config);
if (fsm_mode) if (fsm_mode)
clk_pll_set_fsm_mode(pll, regmap); clk_pll_set_fsm_mode(pll, regmap, 0);
} }
EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp); EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp);
...@@ -60,6 +60,8 @@ struct pll_config { ...@@ -60,6 +60,8 @@ struct pll_config {
u32 aux_output_mask; u32 aux_output_mask;
}; };
void clk_pll_configure_sr(struct clk_pll *pll, struct regmap *regmap,
const struct pll_config *config, bool fsm_mode);
void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap, void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
const struct pll_config *config, bool fsm_mode); const struct pll_config *config, bool fsm_mode);
......
...@@ -417,20 +417,25 @@ static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate, ...@@ -417,20 +417,25 @@ static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p); return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
} }
static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate, static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate) unsigned long *p_rate, struct clk **p)
{ {
struct clk_rcg *rcg = to_clk_rcg(hw); struct clk_rcg *rcg = to_clk_rcg(hw);
const struct freq_tbl *f; const struct freq_tbl *f = rcg->freq_tbl;
*p = clk_get_parent_by_index(hw->clk, f->src);
*p_rate = __clk_round_rate(*p, rate);
return *p_rate;
}
static int __clk_rcg_set_rate(struct clk_rcg *rcg, const struct freq_tbl *f)
{
u32 ns, md, ctl; u32 ns, md, ctl;
struct mn *mn = &rcg->mn; struct mn *mn = &rcg->mn;
u32 mask = 0; u32 mask = 0;
unsigned int reset_reg; unsigned int reset_reg;
f = find_freq(rcg->freq_tbl, rate);
if (!f)
return -EINVAL;
if (rcg->mn.reset_in_cc) if (rcg->mn.reset_in_cc)
reset_reg = rcg->clkr.enable_reg; reset_reg = rcg->clkr.enable_reg;
else else
...@@ -466,6 +471,27 @@ static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -466,6 +471,27 @@ static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
return 0; return 0;
} }
static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_rcg *rcg = to_clk_rcg(hw);
const struct freq_tbl *f;
f = find_freq(rcg->freq_tbl, rate);
if (!f)
return -EINVAL;
return __clk_rcg_set_rate(rcg, f);
}
static int clk_rcg_bypass_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_rcg *rcg = to_clk_rcg(hw);
return __clk_rcg_set_rate(rcg, rcg->freq_tbl);
}
static int __clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate) static int __clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate)
{ {
struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
...@@ -503,6 +529,17 @@ const struct clk_ops clk_rcg_ops = { ...@@ -503,6 +529,17 @@ const struct clk_ops clk_rcg_ops = {
}; };
EXPORT_SYMBOL_GPL(clk_rcg_ops); EXPORT_SYMBOL_GPL(clk_rcg_ops);
const struct clk_ops clk_rcg_bypass_ops = {
.enable = clk_enable_regmap,
.disable = clk_disable_regmap,
.get_parent = clk_rcg_get_parent,
.set_parent = clk_rcg_set_parent,
.recalc_rate = clk_rcg_recalc_rate,
.determine_rate = clk_rcg_bypass_determine_rate,
.set_rate = clk_rcg_bypass_set_rate,
};
EXPORT_SYMBOL_GPL(clk_rcg_bypass_ops);
const struct clk_ops clk_dyn_rcg_ops = { const struct clk_ops clk_dyn_rcg_ops = {
.enable = clk_enable_regmap, .enable = clk_enable_regmap,
.is_enabled = clk_is_enabled_regmap, .is_enabled = clk_is_enabled_regmap,
......
...@@ -95,6 +95,7 @@ struct clk_rcg { ...@@ -95,6 +95,7 @@ struct clk_rcg {
}; };
extern const struct clk_ops clk_rcg_ops; extern const struct clk_ops clk_rcg_ops;
extern const struct clk_ops clk_rcg_bypass_ops;
#define to_clk_rcg(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg, clkr) #define to_clk_rcg(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg, clkr)
......
...@@ -27,30 +27,35 @@ struct qcom_cc { ...@@ -27,30 +27,35 @@ struct qcom_cc {
struct clk *clks[]; struct clk *clks[];
}; };
int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc) struct regmap *
qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc)
{ {
void __iomem *base; void __iomem *base;
struct resource *res; struct resource *res;
struct device *dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return ERR_CAST(base);
return devm_regmap_init_mmio(dev, base, desc->config);
}
EXPORT_SYMBOL_GPL(qcom_cc_map);
int qcom_cc_really_probe(struct platform_device *pdev,
const struct qcom_cc_desc *desc, struct regmap *regmap)
{
int i, ret; int i, ret;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct clk *clk; struct clk *clk;
struct clk_onecell_data *data; struct clk_onecell_data *data;
struct clk **clks; struct clk **clks;
struct regmap *regmap;
struct qcom_reset_controller *reset; struct qcom_reset_controller *reset;
struct qcom_cc *cc; struct qcom_cc *cc;
size_t num_clks = desc->num_clks; size_t num_clks = desc->num_clks;
struct clk_regmap **rclks = desc->clks; struct clk_regmap **rclks = desc->clks;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
regmap = devm_regmap_init_mmio(dev, base, desc->config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks, cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
GFP_KERNEL); GFP_KERNEL);
if (!cc) if (!cc)
...@@ -91,6 +96,18 @@ int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc) ...@@ -91,6 +96,18 @@ int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc)
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(qcom_cc_really_probe);
int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc)
{
struct regmap *regmap;
regmap = qcom_cc_map(pdev, desc);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
return qcom_cc_really_probe(pdev, desc, regmap);
}
EXPORT_SYMBOL_GPL(qcom_cc_probe); EXPORT_SYMBOL_GPL(qcom_cc_probe);
void qcom_cc_remove(struct platform_device *pdev) void qcom_cc_remove(struct platform_device *pdev)
......
...@@ -17,6 +17,7 @@ struct platform_device; ...@@ -17,6 +17,7 @@ struct platform_device;
struct regmap_config; struct regmap_config;
struct clk_regmap; struct clk_regmap;
struct qcom_reset_map; struct qcom_reset_map;
struct regmap;
struct qcom_cc_desc { struct qcom_cc_desc {
const struct regmap_config *config; const struct regmap_config *config;
...@@ -26,6 +27,11 @@ struct qcom_cc_desc { ...@@ -26,6 +27,11 @@ struct qcom_cc_desc {
size_t num_resets; size_t num_resets;
}; };
extern struct regmap *qcom_cc_map(struct platform_device *pdev,
const struct qcom_cc_desc *desc);
extern int qcom_cc_really_probe(struct platform_device *pdev,
const struct qcom_cc_desc *desc,
struct regmap *regmap);
extern int qcom_cc_probe(struct platform_device *pdev, extern int qcom_cc_probe(struct platform_device *pdev,
const struct qcom_cc_desc *desc); const struct qcom_cc_desc *desc);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -2547,18 +2547,16 @@ MODULE_DEVICE_TABLE(of, mmcc_msm8974_match_table); ...@@ -2547,18 +2547,16 @@ MODULE_DEVICE_TABLE(of, mmcc_msm8974_match_table);
static int mmcc_msm8974_probe(struct platform_device *pdev) static int mmcc_msm8974_probe(struct platform_device *pdev)
{ {
int ret;
struct regmap *regmap; struct regmap *regmap;
ret = qcom_cc_probe(pdev, &mmcc_msm8974_desc); regmap = qcom_cc_map(pdev, &mmcc_msm8974_desc);
if (ret) if (IS_ERR(regmap))
return ret; return PTR_ERR(regmap);
regmap = dev_get_regmap(&pdev->dev, NULL);
clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true); clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true);
clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false); clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false);
return 0; return qcom_cc_really_probe(pdev, &mmcc_msm8974_desc, regmap);
} }
static int mmcc_msm8974_remove(struct platform_device *pdev) static int mmcc_msm8974_remove(struct platform_device *pdev)
......
...@@ -3,3 +3,9 @@ ...@@ -3,3 +3,9 @@
# #
obj-y += clk-rockchip.o obj-y += clk-rockchip.o
obj-y += clk.o
obj-y += clk-pll.o
obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
obj-y += clk-rk3188.o
obj-y += clk-rk3288.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2014 MundoReader S.L.
* Author: Heiko Stuebner <heiko@sntech.de>
*
* based on
*
* samsung/clk.c
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* Copyright (c) 2013 Linaro Ltd.
* Author: Thomas Abraham <thomas.ab@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include "clk.h"
/**
* Register a clock branch.
* Most clock branches have a form like
*
* src1 --|--\
* |M |--[GATE]-[DIV]-
* src2 --|--/
*
* sometimes without one of those components.
*/
struct clk *rockchip_clk_register_branch(const char *name,
const char **parent_names, u8 num_parents, void __iomem *base,
int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
u8 div_shift, u8 div_width, u8 div_flags,
struct clk_div_table *div_table, int gate_offset,
u8 gate_shift, u8 gate_flags, unsigned long flags,
spinlock_t *lock)
{
struct clk *clk;
struct clk_mux *mux = NULL;
struct clk_gate *gate = NULL;
struct clk_divider *div = NULL;
const struct clk_ops *mux_ops = NULL, *div_ops = NULL,
*gate_ops = NULL;
if (num_parents > 1) {
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
if (!mux)
return ERR_PTR(-ENOMEM);
mux->reg = base + muxdiv_offset;
mux->shift = mux_shift;
mux->mask = BIT(mux_width) - 1;
mux->flags = mux_flags;
mux->lock = lock;
mux_ops = (mux_flags & CLK_MUX_READ_ONLY) ? &clk_mux_ro_ops
: &clk_mux_ops;
}
if (gate_offset >= 0) {
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate)
return ERR_PTR(-ENOMEM);
gate->flags = gate_flags;
gate->reg = base + gate_offset;
gate->bit_idx = gate_shift;
gate->lock = lock;
gate_ops = &clk_gate_ops;
}
if (div_width > 0) {
div = kzalloc(sizeof(*div), GFP_KERNEL);
if (!div)
return ERR_PTR(-ENOMEM);
div->flags = div_flags;
div->reg = base + muxdiv_offset;
div->shift = div_shift;
div->width = div_width;
div->lock = lock;
div->table = div_table;
div_ops = (div_flags & CLK_DIVIDER_READ_ONLY)
? &clk_divider_ro_ops
: &clk_divider_ops;
}
clk = clk_register_composite(NULL, name, parent_names, num_parents,
mux ? &mux->hw : NULL, mux_ops,
div ? &div->hw : NULL, div_ops,
gate ? &gate->hw : NULL, gate_ops,
flags);
return clk;
}
static DEFINE_SPINLOCK(clk_lock);
static struct clk **clk_table;
static void __iomem *reg_base;
static struct clk_onecell_data clk_data;
static struct device_node *cru_node;
static struct regmap *grf;
void __init rockchip_clk_init(struct device_node *np, void __iomem *base,
unsigned long nr_clks)
{
reg_base = base;
cru_node = np;
grf = ERR_PTR(-EPROBE_DEFER);
clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
if (!clk_table)
pr_err("%s: could not allocate clock lookup table\n", __func__);
clk_data.clks = clk_table;
clk_data.clk_num = nr_clks;
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
}
struct regmap *rockchip_clk_get_grf(void)
{
if (IS_ERR(grf))
grf = syscon_regmap_lookup_by_phandle(cru_node, "rockchip,grf");
return grf;
}
void rockchip_clk_add_lookup(struct clk *clk, unsigned int id)
{
if (clk_table && id)
clk_table[id] = clk;
}
void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list,
unsigned int nr_pll, int grf_lock_offset)
{
struct clk *clk;
int idx;
for (idx = 0; idx < nr_pll; idx++, list++) {
clk = rockchip_clk_register_pll(list->type, list->name,
list->parent_names, list->num_parents,
reg_base, list->con_offset, grf_lock_offset,
list->lock_shift, list->mode_offset,
list->mode_shift, list->rate_table, &clk_lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
continue;
}
rockchip_clk_add_lookup(clk, list->id);
}
}
void __init rockchip_clk_register_branches(
struct rockchip_clk_branch *list,
unsigned int nr_clk)
{
struct clk *clk = NULL;
unsigned int idx;
unsigned long flags;
for (idx = 0; idx < nr_clk; idx++, list++) {
flags = list->flags;
/* catch simple muxes */
switch (list->branch_type) {
case branch_mux:
clk = clk_register_mux(NULL, list->name,
list->parent_names, list->num_parents,
flags, reg_base + list->muxdiv_offset,
list->mux_shift, list->mux_width,
list->mux_flags, &clk_lock);
break;
case branch_divider:
if (list->div_table)
clk = clk_register_divider_table(NULL,
list->name, list->parent_names[0],
flags, reg_base + list->muxdiv_offset,
list->div_shift, list->div_width,
list->div_flags, list->div_table,
&clk_lock);
else
clk = clk_register_divider(NULL, list->name,
list->parent_names[0], flags,
reg_base + list->muxdiv_offset,
list->div_shift, list->div_width,
list->div_flags, &clk_lock);
break;
case branch_fraction_divider:
/* unimplemented */
continue;
break;
case branch_gate:
flags |= CLK_SET_RATE_PARENT;
/* keep all gates untouched for now */
flags |= CLK_IGNORE_UNUSED;
clk = clk_register_gate(NULL, list->name,
list->parent_names[0], flags,
reg_base + list->gate_offset,
list->gate_shift, list->gate_flags, &clk_lock);
break;
case branch_composite:
/* keep all gates untouched for now */
flags |= CLK_IGNORE_UNUSED;
clk = rockchip_clk_register_branch(list->name,
list->parent_names, list->num_parents,
reg_base, list->muxdiv_offset, list->mux_shift,
list->mux_width, list->mux_flags,
list->div_shift, list->div_width,
list->div_flags, list->div_table,
list->gate_offset, list->gate_shift,
list->gate_flags, flags, &clk_lock);
break;
}
/* none of the cases above matched */
if (!clk) {
pr_err("%s: unknown clock type %d\n",
__func__, list->branch_type);
continue;
}
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s: %ld\n",
__func__, list->name, PTR_ERR(clk));
continue;
}
rockchip_clk_add_lookup(clk, list->id);
}
}
This diff is collapsed.
This diff is collapsed.
...@@ -11,6 +11,7 @@ obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o ...@@ -11,6 +11,7 @@ obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o
obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
......
This diff is collapsed.
...@@ -87,6 +87,22 @@ ...@@ -87,6 +87,22 @@
#define SRC_CPU 0x14200 #define SRC_CPU 0x14200
#define DIV_CPU0 0x14500 #define DIV_CPU0 0x14500
#define DIV_CPU1 0x14504 #define DIV_CPU1 0x14504
#define PWR_CTRL1 0x15020
#define PWR_CTRL2 0x15024
/* Below definitions are used for PWR_CTRL settings */
#define PWR_CTRL1_CORE2_DOWN_RATIO(x) (((x) & 0x7) << 28)
#define PWR_CTRL1_CORE1_DOWN_RATIO(x) (((x) & 0x7) << 16)
#define PWR_CTRL1_DIV2_DOWN_EN (1 << 9)
#define PWR_CTRL1_DIV1_DOWN_EN (1 << 8)
#define PWR_CTRL1_USE_CORE3_WFE (1 << 7)
#define PWR_CTRL1_USE_CORE2_WFE (1 << 6)
#define PWR_CTRL1_USE_CORE1_WFE (1 << 5)
#define PWR_CTRL1_USE_CORE0_WFE (1 << 4)
#define PWR_CTRL1_USE_CORE3_WFI (1 << 3)
#define PWR_CTRL1_USE_CORE2_WFI (1 << 2)
#define PWR_CTRL1_USE_CORE1_WFI (1 << 1)
#define PWR_CTRL1_USE_CORE0_WFI (1 << 0)
/* list of PLLs to be registered */ /* list of PLLs to be registered */
enum exynos3250_plls { enum exynos3250_plls {
...@@ -168,6 +184,8 @@ static unsigned long exynos3250_cmu_clk_regs[] __initdata = { ...@@ -168,6 +184,8 @@ static unsigned long exynos3250_cmu_clk_regs[] __initdata = {
SRC_CPU, SRC_CPU,
DIV_CPU0, DIV_CPU0,
DIV_CPU1, DIV_CPU1,
PWR_CTRL1,
PWR_CTRL2,
}; };
static int exynos3250_clk_suspend(void) static int exynos3250_clk_suspend(void)
...@@ -748,6 +766,27 @@ static struct samsung_pll_clock exynos3250_plls[nr_plls] __initdata = { ...@@ -748,6 +766,27 @@ static struct samsung_pll_clock exynos3250_plls[nr_plls] __initdata = {
UPLL_LOCK, UPLL_CON0, NULL), UPLL_LOCK, UPLL_CON0, NULL),
}; };
static void __init exynos3_core_down_clock(void)
{
unsigned int tmp;
/*
* Enable arm clock down (in idle) and set arm divider
* ratios in WFI/WFE state.
*/
tmp = (PWR_CTRL1_CORE2_DOWN_RATIO(7) | PWR_CTRL1_CORE1_DOWN_RATIO(7) |
PWR_CTRL1_DIV2_DOWN_EN | PWR_CTRL1_DIV1_DOWN_EN |
PWR_CTRL1_USE_CORE1_WFE | PWR_CTRL1_USE_CORE0_WFE |
PWR_CTRL1_USE_CORE1_WFI | PWR_CTRL1_USE_CORE0_WFI);
__raw_writel(tmp, reg_base + PWR_CTRL1);
/*
* Disable the clock up feature on Exynos4x12, in case it was
* enabled by bootloader.
*/
__raw_writel(0x0, reg_base + PWR_CTRL2);
}
static void __init exynos3250_cmu_init(struct device_node *np) static void __init exynos3250_cmu_init(struct device_node *np)
{ {
struct samsung_clk_provider *ctx; struct samsung_clk_provider *ctx;
...@@ -775,6 +814,10 @@ static void __init exynos3250_cmu_init(struct device_node *np) ...@@ -775,6 +814,10 @@ static void __init exynos3250_cmu_init(struct device_node *np)
samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks)); samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks));
samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks)); samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks));
exynos3_core_down_clock();
exynos3250_clk_sleep_init(); exynos3250_clk_sleep_init();
samsung_clk_of_add_provider(np, ctx);
} }
CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init); CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init);
This diff is collapsed.
This diff is collapsed.
...@@ -206,6 +206,8 @@ void __init exynos5260_cmu_register_one(struct device_node *np, ...@@ -206,6 +206,8 @@ void __init exynos5260_cmu_register_one(struct device_node *np,
if (cmu->clk_regs) if (cmu->clk_regs)
exynos5260_clk_sleep_init(reg_base, cmu->clk_regs, exynos5260_clk_sleep_init(reg_base, cmu->clk_regs,
cmu->nr_clk_regs); cmu->nr_clk_regs);
samsung_clk_of_add_provider(np, ctx);
} }
......
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