aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-15 22:02:20 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-15 22:02:20 -0400
commitdd1845af24a47b70cf84c29126698884f740ff9c (patch)
treefa12809d854d18ba36a568c21d57ceff43617af1
parentb55b39020289f225bf2455349ce1a67372a0baa9 (diff)
parentb640a6037c9ecd1f0ad23a8e9b4ca5f5b4112508 (diff)
Merge tag 'clk-for-linus-3.16-part2' of git://git.linaro.org/people/mike.turquette/linux
Pull more clock framework updates from Mike Turquette: "This contains the second half the of the clk changes for 3.16. They are simply fixes and code refactoring for the OMAP clock drivers. The sunxi clock driver changes include splitting out the one mega-driver into several smaller pieces and adding support for the A31 SoC clocks" * tag 'clk-for-linus-3.16-part2' of git://git.linaro.org/people/mike.turquette/linux: (25 commits) clk: sunxi: document PRCM clock compatible strings clk: sunxi: add PRCM (Power/Reset/Clock Management) clks support clk: sun6i: Protect SDRAM gating bit clk: sun6i: Protect CPU clock clk: sunxi: Rework clock protection code clk: sunxi: Move the GMAC clock to a file of its own clk: sunxi: Move the 24M oscillator to a file of its own clk: sunxi: Remove calls to clk_put clk: sunxi: document new A31 USB clock compatible clk: sunxi: Implement A31 USB clock ARM: dts: OMAP5/DRA7: use omap5-mpu-dpll-clock capable of dealing with higher frequencies CLK: TI: dpll: support OMAP5 MPU DPLL that need special handling for higher frequencies ARM: OMAP5+: dpll: support Duty Cycle Correction(DCC) CLK: TI: clk-54xx: Set the rate for dpll_abe_m2x2_ck CLK: TI: Driver for DRA7 ATL (Audio Tracking Logic) dt:/bindings: DRA7 ATL (Audio Tracking Logic) clock bindings ARM: dts: dra7xx-clocks: Correct name for atl clkin3 clock CLK: TI: gate: add composite interface clock to OMAP2 only build ARM: OMAP2: clock: add DT boot support for cpufreq_ck CLK: TI: OMAP2: add clock init support ...
-rw-r--r--Documentation/devicetree/bindings/clock/sunxi.txt4
-rw-r--r--Documentation/devicetree/bindings/clock/ti/apll.txt24
-rw-r--r--Documentation/devicetree/bindings/clock/ti/dpll.txt10
-rw-r--r--Documentation/devicetree/bindings/clock/ti/dra7-atl.txt96
-rw-r--r--Documentation/devicetree/bindings/clock/ti/gate.txt29
-rw-r--r--Documentation/devicetree/bindings/clock/ti/interface.txt2
-rw-r--r--arch/arm/boot/dts/dra7xx-clocks.dtsi24
-rw-r--r--arch/arm/boot/dts/omap54xx-clocks.dtsi2
-rw-r--r--arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c53
-rw-r--r--arch/arm/mach-omap2/clock.h13
-rw-r--r--arch/arm/mach-omap2/clock2xxx.h4
-rw-r--r--arch/arm/mach-omap2/dpll3xxx.c9
-rw-r--r--drivers/clk/sunxi/Makefile4
-rw-r--r--drivers/clk/sunxi/clk-a10-hosc.c73
-rw-r--r--drivers/clk/sunxi/clk-a20-gmac.c119
-rw-r--r--drivers/clk/sunxi/clk-sun6i-apb0-gates.c99
-rw-r--r--drivers/clk/sunxi/clk-sun6i-apb0.c77
-rw-r--r--drivers/clk/sunxi/clk-sun6i-ar100.c233
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c239
-rw-r--r--drivers/clk/ti/Makefile4
-rw-r--r--drivers/clk/ti/apll.c181
-rw-r--r--drivers/clk/ti/clk-2xxx.c256
-rw-r--r--drivers/clk/ti/clk-54xx.c6
-rw-r--r--drivers/clk/ti/clk-7xx.c2
-rw-r--r--drivers/clk/ti/clk-dra7-atl.c312
-rw-r--r--drivers/clk/ti/dpll.c138
-rw-r--r--drivers/clk/ti/gate.c2
-rw-r--r--drivers/clk/ti/interface.c11
-rw-r--r--include/dt-bindings/clk/ti-dra7-atl.h40
-rw-r--r--include/linux/clk/ti.h35
30 files changed, 1836 insertions, 265 deletions
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index a5160d8cbb5f..b9ec668bfe62 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -20,12 +20,15 @@ Required properties:
20 "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13 20 "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
21 "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s 21 "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
22 "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20 22 "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
23 "allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31
23 "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31 24 "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31
24 "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 25 "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
25 "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock 26 "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
27 "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31
26 "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10 28 "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
27 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 29 "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
28 "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s 30 "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
31 "allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31
29 "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 32 "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
30 "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock 33 "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
31 "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing 34 "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
@@ -41,6 +44,7 @@ Required properties:
41 "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 44 "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
42 "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20 45 "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20
43 "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13 46 "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
47 "allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31
44 48
45Required properties for all clocks: 49Required properties for all clocks:
46- reg : shall be the control register address for the clock. 50- reg : shall be the control register address for the clock.
diff --git a/Documentation/devicetree/bindings/clock/ti/apll.txt b/Documentation/devicetree/bindings/clock/ti/apll.txt
index 7faf5a68b3be..ade4dd4c30f0 100644
--- a/Documentation/devicetree/bindings/clock/ti/apll.txt
+++ b/Documentation/devicetree/bindings/clock/ti/apll.txt
@@ -14,18 +14,32 @@ a subtype of a DPLL [2], although a simplified one at that.
14[2] Documentation/devicetree/bindings/clock/ti/dpll.txt 14[2] Documentation/devicetree/bindings/clock/ti/dpll.txt
15 15
16Required properties: 16Required properties:
17- compatible : shall be "ti,dra7-apll-clock" 17- compatible : shall be "ti,dra7-apll-clock" or "ti,omap2-apll-clock"
18- #clock-cells : from common clock binding; shall be set to 0. 18- #clock-cells : from common clock binding; shall be set to 0.
19- clocks : link phandles of parent clocks (clk-ref and clk-bypass) 19- clocks : link phandles of parent clocks (clk-ref and clk-bypass)
20- reg : address and length of the register set for controlling the APLL. 20- reg : address and length of the register set for controlling the APLL.
21 It contains the information of registers in the following order: 21 It contains the information of registers in the following order:
22 "control" - contains the control register base address 22 "control" - contains the control register offset
23 "idlest" - contains the idlest register base address 23 "idlest" - contains the idlest register offset
24 "autoidle" - contains the autoidle register offset (OMAP2 only)
25- ti,clock-frequency : static clock frequency for the clock (OMAP2 only)
26- ti,idlest-shift : bit-shift for the idlest field (OMAP2 only)
27- ti,bit-shift : bit-shift for enable and autoidle fields (OMAP2 only)
24 28
25Examples: 29Examples:
26 apll_pcie_ck: apll_pcie_ck@4a008200 { 30 apll_pcie_ck: apll_pcie_ck {
27 #clock-cells = <0>; 31 #clock-cells = <0>;
28 clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>; 32 clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>;
29 reg = <0x4a00821c 0x4>, <0x4a008220 0x4>; 33 reg = <0x021c>, <0x0220>;
30 compatible = "ti,dra7-apll-clock"; 34 compatible = "ti,dra7-apll-clock";
31 }; 35 };
36
37 apll96_ck: apll96_ck {
38 #clock-cells = <0>;
39 compatible = "ti,omap2-apll-clock";
40 clocks = <&sys_ck>;
41 ti,bit-shift = <2>;
42 ti,idlest-shift = <8>;
43 ti,clock-frequency = <96000000>;
44 reg = <0x0500>, <0x0530>, <0x0520>;
45 };
diff --git a/Documentation/devicetree/bindings/clock/ti/dpll.txt b/Documentation/devicetree/bindings/clock/ti/dpll.txt
index 30bfdb7c9f18..df57009ff8e7 100644
--- a/Documentation/devicetree/bindings/clock/ti/dpll.txt
+++ b/Documentation/devicetree/bindings/clock/ti/dpll.txt
@@ -24,12 +24,14 @@ Required properties:
24 "ti,omap4-dpll-core-clock", 24 "ti,omap4-dpll-core-clock",
25 "ti,omap4-dpll-m4xen-clock", 25 "ti,omap4-dpll-m4xen-clock",
26 "ti,omap4-dpll-j-type-clock", 26 "ti,omap4-dpll-j-type-clock",
27 "ti,omap5-mpu-dpll-clock",
27 "ti,am3-dpll-no-gate-clock", 28 "ti,am3-dpll-no-gate-clock",
28 "ti,am3-dpll-j-type-clock", 29 "ti,am3-dpll-j-type-clock",
29 "ti,am3-dpll-no-gate-j-type-clock", 30 "ti,am3-dpll-no-gate-j-type-clock",
30 "ti,am3-dpll-clock", 31 "ti,am3-dpll-clock",
31 "ti,am3-dpll-core-clock", 32 "ti,am3-dpll-core-clock",
32 "ti,am3-dpll-x2-clock", 33 "ti,am3-dpll-x2-clock",
34 "ti,omap2-dpll-core-clock",
33 35
34- #clock-cells : from common clock binding; shall be set to 0. 36- #clock-cells : from common clock binding; shall be set to 0.
35- clocks : link phandles of parent clocks, first entry lists reference clock 37- clocks : link phandles of parent clocks, first entry lists reference clock
@@ -41,6 +43,7 @@ Required properties:
41 "mult-div1" - contains the multiplier / divider register base address 43 "mult-div1" - contains the multiplier / divider register base address
42 "autoidle" - contains the autoidle register base address (optional) 44 "autoidle" - contains the autoidle register base address (optional)
43 ti,am3-* dpll types do not have autoidle register 45 ti,am3-* dpll types do not have autoidle register
46 ti,omap2-* dpll type does not support idlest / autoidle registers
44 47
45Optional properties: 48Optional properties:
46- DPLL mode setting - defining any one or more of the following overrides 49- DPLL mode setting - defining any one or more of the following overrides
@@ -73,3 +76,10 @@ Examples:
73 clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; 76 clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
74 reg = <0x90>, <0x5c>, <0x68>; 77 reg = <0x90>, <0x5c>, <0x68>;
75 }; 78 };
79
80 dpll_ck: dpll_ck {
81 #clock-cells = <0>;
82 compatible = "ti,omap2-dpll-core-clock";
83 clocks = <&sys_ck>, <&sys_ck>;
84 reg = <0x0500>, <0x0540>;
85 };
diff --git a/Documentation/devicetree/bindings/clock/ti/dra7-atl.txt b/Documentation/devicetree/bindings/clock/ti/dra7-atl.txt
new file mode 100644
index 000000000000..585e8c191f50
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/dra7-atl.txt
@@ -0,0 +1,96 @@
1Device Tree Clock bindings for ATL (Audio Tracking Logic) of DRA7 SoC.
2
3The ATL IP is used to generate clock to be used to synchronize baseband and
4audio codec. A single ATL IP provides four ATL clock instances sharing the same
5functional clock but can be configured to provide different clocks.
6ATL can maintain a clock averages to some desired frequency based on the bws/aws
7signals - can compensate the drift between the two ws signal.
8
9In order to provide the support for ATL and it's output clocks (which can be used
10internally within the SoC or external components) two sets of bindings is needed:
11
12Clock tree binding:
13This binding uses the common clock binding[1].
14To be able to integrate the ATL clocks with DT clock tree.
15Provides ccf level representation of the ATL clocks to be used by drivers.
16Since the clock instances are part of a single IP this binding is used as a node
17for the DT clock tree, the IP driver is needed to handle the actual configuration
18of the IP.
19
20[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
21
22Required properties:
23- compatible : shall be "ti,dra7-atl-clock"
24- #clock-cells : from common clock binding; shall be set to 0.
25- clocks : link phandles to functional clock of ATL
26
27Binding for the IP driver:
28This binding is used to configure the IP driver which is going to handle the
29configuration of the IP for the ATL clock instances.
30
31Required properties:
32- compatible : shall be "ti,dra7-atl"
33- reg : base address for the ATL IP
34- ti,provided-clocks : List of phandles to the clocks associated with the ATL
35- clocks : link phandles to functional clock of ATL
36- clock-names : Shall be set to "fck"
37- ti,hwmods : Shall be set to "atl"
38
39Optional properties:
40Configuration of ATL instances:
41- atl{0/1/2/3} {
42 - bws : Baseband word select signal selection
43 - aws : Audio word select signal selection
44};
45
46For valid word select signals, see the dt-bindings/clk/ti-dra7-atl.h include
47file.
48
49Examples:
50/* clock bindings for atl provided clocks */
51atl_clkin0_ck: atl_clkin0_ck {
52 #clock-cells = <0>;
53 compatible = "ti,dra7-atl-clock";
54 clocks = <&atl_gfclk_mux>;
55};
56
57atl_clkin1_ck: atl_clkin1_ck {
58 #clock-cells = <0>;
59 compatible = "ti,dra7-atl-clock";
60 clocks = <&atl_gfclk_mux>;
61};
62
63atl_clkin2_ck: atl_clkin2_ck {
64 #clock-cells = <0>;
65 compatible = "ti,dra7-atl-clock";
66 clocks = <&atl_gfclk_mux>;
67};
68
69atl_clkin3_ck: atl_clkin3_ck {
70 #clock-cells = <0>;
71 compatible = "ti,dra7-atl-clock";
72 clocks = <&atl_gfclk_mux>;
73};
74
75/* binding for the IP */
76atl: atl@4843c000 {
77 compatible = "ti,dra7-atl";
78 reg = <0x4843c000 0x3ff>;
79 ti,hwmods = "atl";
80 ti,provided-clocks = <&atl_clkin0_ck>, <&atl_clkin1_ck>,
81 <&atl_clkin2_ck>, <&atl_clkin3_ck>;
82 clocks = <&atl_gfclk_mux>;
83 clock-names = "fck";
84 status = "disabled";
85};
86
87#include <dt-bindings/clk/ti-dra7-atl.h>
88
89&atl {
90 status = "okay";
91
92 atl2 {
93 bws = <DRA7_ATL_WS_MCASP2_FSX>;
94 aws = <DRA7_ATL_WS_MCASP3_FSX>;
95 };
96};
diff --git a/Documentation/devicetree/bindings/clock/ti/gate.txt b/Documentation/devicetree/bindings/clock/ti/gate.txt
index 125281aaa4ca..03f8fdee62a7 100644
--- a/Documentation/devicetree/bindings/clock/ti/gate.txt
+++ b/Documentation/devicetree/bindings/clock/ti/gate.txt
@@ -25,6 +25,11 @@ Required properties:
25 to map clockdomains properly 25 to map clockdomains properly
26 "ti,hsdiv-gate-clock" - gate clock with OMAP36xx specific hardware handling, 26 "ti,hsdiv-gate-clock" - gate clock with OMAP36xx specific hardware handling,
27 required for a hardware errata 27 required for a hardware errata
28 "ti,composite-gate-clock" - composite gate clock, to be part of composite
29 clock
30 "ti,composite-no-wait-gate-clock" - composite gate clock that does not wait
31 for clock to be active before returning
32 from clk_enable()
28- #clock-cells : from common clock binding; shall be set to 0 33- #clock-cells : from common clock binding; shall be set to 0
29- clocks : link to phandle of parent clock 34- clocks : link to phandle of parent clock
30- reg : offset for register controlling adjustable gate, not needed for 35- reg : offset for register controlling adjustable gate, not needed for
@@ -41,7 +46,7 @@ Examples:
41 #clock-cells = <0>; 46 #clock-cells = <0>;
42 compatible = "ti,gate-clock"; 47 compatible = "ti,gate-clock";
43 clocks = <&core_96m_fck>; 48 clocks = <&core_96m_fck>;
44 reg = <0x48004a00 0x4>; 49 reg = <0x0a00>;
45 ti,bit-shift = <25>; 50 ti,bit-shift = <25>;
46 }; 51 };
47 52
@@ -57,7 +62,7 @@ Examples:
57 #clock-cells = <0>; 62 #clock-cells = <0>;
58 compatible = "ti,dss-gate-clock"; 63 compatible = "ti,dss-gate-clock";
59 clocks = <&dpll4_m4x2_ck>; 64 clocks = <&dpll4_m4x2_ck>;
60 reg = <0x48004e00 0x4>; 65 reg = <0x0e00>;
61 ti,bit-shift = <0>; 66 ti,bit-shift = <0>;
62 }; 67 };
63 68
@@ -65,7 +70,7 @@ Examples:
65 #clock-cells = <0>; 70 #clock-cells = <0>;
66 compatible = "ti,am35xx-gate-clock"; 71 compatible = "ti,am35xx-gate-clock";
67 clocks = <&ipss_ick>; 72 clocks = <&ipss_ick>;
68 reg = <0x4800259c 0x4>; 73 reg = <0x059c>;
69 ti,bit-shift = <1>; 74 ti,bit-shift = <1>;
70 }; 75 };
71 76
@@ -80,6 +85,22 @@ Examples:
80 compatible = "ti,hsdiv-gate-clock"; 85 compatible = "ti,hsdiv-gate-clock";
81 clocks = <&dpll4_m2x2_mul_ck>; 86 clocks = <&dpll4_m2x2_mul_ck>;
82 ti,bit-shift = <0x1b>; 87 ti,bit-shift = <0x1b>;
83 reg = <0x48004d00 0x4>; 88 reg = <0x0d00>;
84 ti,set-bit-to-disable; 89 ti,set-bit-to-disable;
85 }; 90 };
91
92 vlynq_gate_fck: vlynq_gate_fck {
93 #clock-cells = <0>;
94 compatible = "ti,composite-gate-clock";
95 clocks = <&core_ck>;
96 ti,bit-shift = <3>;
97 reg = <0x0200>;
98 };
99
100 sys_clkout2_src_gate: sys_clkout2_src_gate {
101 #clock-cells = <0>;
102 compatible = "ti,composite-no-wait-gate-clock";
103 clocks = <&core_ck>;
104 ti,bit-shift = <15>;
105 reg = <0x0070>;
106 };
diff --git a/Documentation/devicetree/bindings/clock/ti/interface.txt b/Documentation/devicetree/bindings/clock/ti/interface.txt
index 064e8caccac3..3111a409fea6 100644
--- a/Documentation/devicetree/bindings/clock/ti/interface.txt
+++ b/Documentation/devicetree/bindings/clock/ti/interface.txt
@@ -21,6 +21,8 @@ Required properties:
21 "ti,omap3-dss-interface-clock" - interface clock with DSS specific HW handling 21 "ti,omap3-dss-interface-clock" - interface clock with DSS specific HW handling
22 "ti,omap3-ssi-interface-clock" - interface clock with SSI specific HW handling 22 "ti,omap3-ssi-interface-clock" - interface clock with SSI specific HW handling
23 "ti,am35xx-interface-clock" - interface clock with AM35xx specific HW handling 23 "ti,am35xx-interface-clock" - interface clock with AM35xx specific HW handling
24 "ti,omap2430-interface-clock" - interface clock with OMAP2430 specific HW
25 handling
24- #clock-cells : from common clock binding; shall be set to 0 26- #clock-cells : from common clock binding; shall be set to 0
25- clocks : link to phandle of parent clock 27- clocks : link to phandle of parent clock
26- reg : base address for the control register 28- reg : base address for the control register
diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi
index c7676871d9c0..b03cfe49d22b 100644
--- a/arch/arm/boot/dts/dra7xx-clocks.dtsi
+++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi
@@ -26,7 +26,7 @@
26 clock-frequency = <0>; 26 clock-frequency = <0>;
27 }; 27 };
28 28
29 atlclkin3_ck: atlclkin3_ck { 29 atl_clkin3_ck: atl_clkin3_ck {
30 #clock-cells = <0>; 30 #clock-cells = <0>;
31 compatible = "fixed-clock"; 31 compatible = "fixed-clock";
32 clock-frequency = <0>; 32 clock-frequency = <0>;
@@ -277,7 +277,7 @@
277 277
278 dpll_mpu_ck: dpll_mpu_ck { 278 dpll_mpu_ck: dpll_mpu_ck {
279 #clock-cells = <0>; 279 #clock-cells = <0>;
280 compatible = "ti,omap4-dpll-clock"; 280 compatible = "ti,omap5-mpu-dpll-clock";
281 clocks = <&sys_clkin1>, <&mpu_dpll_hs_clk_div>; 281 clocks = <&sys_clkin1>, <&mpu_dpll_hs_clk_div>;
282 reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>; 282 reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>;
283 }; 283 };
@@ -730,7 +730,7 @@
730 mcasp1_ahclkr_mux: mcasp1_ahclkr_mux { 730 mcasp1_ahclkr_mux: mcasp1_ahclkr_mux {
731 #clock-cells = <0>; 731 #clock-cells = <0>;
732 compatible = "ti,mux-clock"; 732 compatible = "ti,mux-clock";
733 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; 733 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
734 ti,bit-shift = <28>; 734 ti,bit-shift = <28>;
735 reg = <0x0550>; 735 reg = <0x0550>;
736 }; 736 };
@@ -738,7 +738,7 @@
738 mcasp1_ahclkx_mux: mcasp1_ahclkx_mux { 738 mcasp1_ahclkx_mux: mcasp1_ahclkx_mux {
739 #clock-cells = <0>; 739 #clock-cells = <0>;
740 compatible = "ti,mux-clock"; 740 compatible = "ti,mux-clock";
741 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; 741 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
742 ti,bit-shift = <24>; 742 ti,bit-shift = <24>;
743 reg = <0x0550>; 743 reg = <0x0550>;
744 }; 744 };
@@ -1639,7 +1639,7 @@
1639 mcasp2_ahclkr_mux: mcasp2_ahclkr_mux { 1639 mcasp2_ahclkr_mux: mcasp2_ahclkr_mux {
1640 #clock-cells = <0>; 1640 #clock-cells = <0>;
1641 compatible = "ti,mux-clock"; 1641 compatible = "ti,mux-clock";
1642 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; 1642 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
1643 ti,bit-shift = <28>; 1643 ti,bit-shift = <28>;
1644 reg = <0x1860>; 1644 reg = <0x1860>;
1645 }; 1645 };
@@ -1647,7 +1647,7 @@
1647 mcasp2_ahclkx_mux: mcasp2_ahclkx_mux { 1647 mcasp2_ahclkx_mux: mcasp2_ahclkx_mux {
1648 #clock-cells = <0>; 1648 #clock-cells = <0>;
1649 compatible = "ti,mux-clock"; 1649 compatible = "ti,mux-clock";
1650 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; 1650 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
1651 ti,bit-shift = <24>; 1651 ti,bit-shift = <24>;
1652 reg = <0x1860>; 1652 reg = <0x1860>;
1653 }; 1653 };
@@ -1663,7 +1663,7 @@
1663 mcasp3_ahclkx_mux: mcasp3_ahclkx_mux { 1663 mcasp3_ahclkx_mux: mcasp3_ahclkx_mux {
1664 #clock-cells = <0>; 1664 #clock-cells = <0>;
1665 compatible = "ti,mux-clock"; 1665 compatible = "ti,mux-clock";
1666 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; 1666 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
1667 ti,bit-shift = <24>; 1667 ti,bit-shift = <24>;
1668 reg = <0x1868>; 1668 reg = <0x1868>;
1669 }; 1669 };
@@ -1679,7 +1679,7 @@
1679 mcasp4_ahclkx_mux: mcasp4_ahclkx_mux { 1679 mcasp4_ahclkx_mux: mcasp4_ahclkx_mux {
1680 #clock-cells = <0>; 1680 #clock-cells = <0>;
1681 compatible = "ti,mux-clock"; 1681 compatible = "ti,mux-clock";
1682 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; 1682 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
1683 ti,bit-shift = <24>; 1683 ti,bit-shift = <24>;
1684 reg = <0x1898>; 1684 reg = <0x1898>;
1685 }; 1685 };
@@ -1695,7 +1695,7 @@
1695 mcasp5_ahclkx_mux: mcasp5_ahclkx_mux { 1695 mcasp5_ahclkx_mux: mcasp5_ahclkx_mux {
1696 #clock-cells = <0>; 1696 #clock-cells = <0>;
1697 compatible = "ti,mux-clock"; 1697 compatible = "ti,mux-clock";
1698 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; 1698 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
1699 ti,bit-shift = <24>; 1699 ti,bit-shift = <24>;
1700 reg = <0x1878>; 1700 reg = <0x1878>;
1701 }; 1701 };
@@ -1711,7 +1711,7 @@
1711 mcasp6_ahclkx_mux: mcasp6_ahclkx_mux { 1711 mcasp6_ahclkx_mux: mcasp6_ahclkx_mux {
1712 #clock-cells = <0>; 1712 #clock-cells = <0>;
1713 compatible = "ti,mux-clock"; 1713 compatible = "ti,mux-clock";
1714 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; 1714 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
1715 ti,bit-shift = <24>; 1715 ti,bit-shift = <24>;
1716 reg = <0x1904>; 1716 reg = <0x1904>;
1717 }; 1717 };
@@ -1727,7 +1727,7 @@
1727 mcasp7_ahclkx_mux: mcasp7_ahclkx_mux { 1727 mcasp7_ahclkx_mux: mcasp7_ahclkx_mux {
1728 #clock-cells = <0>; 1728 #clock-cells = <0>;
1729 compatible = "ti,mux-clock"; 1729 compatible = "ti,mux-clock";
1730 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; 1730 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
1731 ti,bit-shift = <24>; 1731 ti,bit-shift = <24>;
1732 reg = <0x1908>; 1732 reg = <0x1908>;
1733 }; 1733 };
@@ -1743,7 +1743,7 @@
1743 mcasp8_ahclk_mux: mcasp8_ahclk_mux { 1743 mcasp8_ahclk_mux: mcasp8_ahclk_mux {
1744 #clock-cells = <0>; 1744 #clock-cells = <0>;
1745 compatible = "ti,mux-clock"; 1745 compatible = "ti,mux-clock";
1746 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; 1746 clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
1747 ti,bit-shift = <22>; 1747 ti,bit-shift = <22>;
1748 reg = <0x1890>; 1748 reg = <0x1890>;
1749 }; 1749 };
diff --git a/arch/arm/boot/dts/omap54xx-clocks.dtsi b/arch/arm/boot/dts/omap54xx-clocks.dtsi
index aeb142ce8e9d..e67a23b5d788 100644
--- a/arch/arm/boot/dts/omap54xx-clocks.dtsi
+++ b/arch/arm/boot/dts/omap54xx-clocks.dtsi
@@ -335,7 +335,7 @@
335 335
336 dpll_mpu_ck: dpll_mpu_ck { 336 dpll_mpu_ck: dpll_mpu_ck {
337 #clock-cells = <0>; 337 #clock-cells = <0>;
338 compatible = "ti,omap4-dpll-clock"; 338 compatible = "ti,omap5-mpu-dpll-clock";
339 clocks = <&sys_clkin>, <&mpu_dpll_hs_clk_div>; 339 clocks = <&sys_clkin>, <&mpu_dpll_hs_clk_div>;
340 reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>; 340 reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>;
341 }; 341 };
diff --git a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
index b935ed2922d8..85e0b0c06718 100644
--- a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
+++ b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
@@ -208,3 +208,56 @@ void omap2xxx_clkt_vps_late_init(void)
208 clk_put(c); 208 clk_put(c);
209 } 209 }
210} 210}
211
212#ifdef CONFIG_OF
213#include <linux/clk-provider.h>
214#include <linux/clkdev.h>
215
216static const struct clk_ops virt_prcm_set_ops = {
217 .recalc_rate = &omap2_table_mpu_recalc,
218 .set_rate = &omap2_select_table_rate,
219 .round_rate = &omap2_round_to_table_rate,
220};
221
222/**
223 * omap2xxx_clkt_vps_init - initialize virt_prcm_set clock
224 *
225 * Does a manual init for the virtual prcm DVFS clock for OMAP2. This
226 * function is called only from omap2 DT clock init, as the virtual
227 * node is not modelled in the DT clock data.
228 */
229void omap2xxx_clkt_vps_init(void)
230{
231 struct clk_init_data init = { NULL };
232 struct clk_hw_omap *hw = NULL;
233 struct clk *clk;
234 const char *parent_name = "mpu_ck";
235 struct clk_lookup *lookup = NULL;
236
237 omap2xxx_clkt_vps_late_init();
238 omap2xxx_clkt_vps_check_bootloader_rates();
239
240 hw = kzalloc(sizeof(*hw), GFP_KERNEL);
241 lookup = kzalloc(sizeof(*lookup), GFP_KERNEL);
242 if (!hw || !lookup)
243 goto cleanup;
244 init.name = "virt_prcm_set";
245 init.ops = &virt_prcm_set_ops;
246 init.parent_names = &parent_name;
247 init.num_parents = 1;
248
249 hw->hw.init = &init;
250
251 clk = clk_register(NULL, &hw->hw);
252
253 lookup->dev_id = NULL;
254 lookup->con_id = "cpufreq_ck";
255 lookup->clk = clk;
256
257 clkdev_add(lookup);
258 return;
259cleanup:
260 kfree(hw);
261 kfree(lookup);
262}
263#endif
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index bda767a9dea8..12f54d428d7c 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -178,17 +178,6 @@ struct clksel {
178 const struct clksel_rate *rates; 178 const struct clksel_rate *rates;
179}; 179};
180 180
181struct clk_hw_omap_ops {
182 void (*find_idlest)(struct clk_hw_omap *oclk,
183 void __iomem **idlest_reg,
184 u8 *idlest_bit, u8 *idlest_val);
185 void (*find_companion)(struct clk_hw_omap *oclk,
186 void __iomem **other_reg,
187 u8 *other_bit);
188 void (*allow_idle)(struct clk_hw_omap *oclk);
189 void (*deny_idle)(struct clk_hw_omap *oclk);
190};
191
192unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw, 181unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
193 unsigned long parent_rate); 182 unsigned long parent_rate);
194 183
@@ -279,8 +268,6 @@ extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait;
279extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait; 268extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
280extern const struct clk_hw_omap_ops clkhwops_apll54; 269extern const struct clk_hw_omap_ops clkhwops_apll54;
281extern const struct clk_hw_omap_ops clkhwops_apll96; 270extern const struct clk_hw_omap_ops clkhwops_apll96;
282extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
283extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
284 271
285/* clksel_rate blocks shared between OMAP44xx and AM33xx */ 272/* clksel_rate blocks shared between OMAP44xx and AM33xx */
286extern const struct clksel_rate div_1_0_rates[]; 273extern const struct clksel_rate div_1_0_rates[];
diff --git a/arch/arm/mach-omap2/clock2xxx.h b/arch/arm/mach-omap2/clock2xxx.h
index 539dc08afbba..45f41a411603 100644
--- a/arch/arm/mach-omap2/clock2xxx.h
+++ b/arch/arm/mach-omap2/clock2xxx.h
@@ -21,10 +21,6 @@ unsigned long omap2xxx_sys_clk_recalc(struct clk_hw *clk,
21 unsigned long parent_rate); 21 unsigned long parent_rate);
22unsigned long omap2_osc_clk_recalc(struct clk_hw *clk, 22unsigned long omap2_osc_clk_recalc(struct clk_hw *clk,
23 unsigned long parent_rate); 23 unsigned long parent_rate);
24unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
25 unsigned long parent_rate);
26int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate,
27 unsigned long parent_rate);
28void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw); 24void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw);
29unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw, 25unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw,
30 unsigned long parent_rate); 26 unsigned long parent_rate);
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index fcd8036af910..6d7ba37e2257 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -319,6 +319,15 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
319 319
320 /* Set DPLL multiplier, divider */ 320 /* Set DPLL multiplier, divider */
321 v = omap2_clk_readl(clk, dd->mult_div1_reg); 321 v = omap2_clk_readl(clk, dd->mult_div1_reg);
322
323 /* Handle Duty Cycle Correction */
324 if (dd->dcc_mask) {
325 if (dd->last_rounded_rate >= dd->dcc_rate)
326 v |= dd->dcc_mask; /* Enable DCC */
327 else
328 v &= ~dd->dcc_mask; /* Disable DCC */
329 }
330
322 v &= ~(dd->mult_mask | dd->div1_mask); 331 v &= ~(dd->mult_mask | dd->div1_mask);
323 v |= dd->last_rounded_m << __ffs(dd->mult_mask); 332 v |= dd->last_rounded_m << __ffs(dd->mult_mask);
324 v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask); 333 v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask);
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index b5bac917612c..762fd64dbd1f 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -3,3 +3,7 @@
3# 3#
4 4
5obj-y += clk-sunxi.o clk-factors.o 5obj-y += clk-sunxi.o clk-factors.o
6obj-y += clk-a10-hosc.o
7obj-y += clk-a20-gmac.o
8
9obj-$(CONFIG_MFD_SUN6I_PRCM) += clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o
diff --git a/drivers/clk/sunxi/clk-a10-hosc.c b/drivers/clk/sunxi/clk-a10-hosc.c
new file mode 100644
index 000000000000..0481d5d673d6
--- /dev/null
+++ b/drivers/clk/sunxi/clk-a10-hosc.c
@@ -0,0 +1,73 @@
1/*
2 * Copyright 2013 Emilio López
3 *
4 * Emilio López <emilio@elopez.com.ar>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/clk-provider.h>
18#include <linux/clkdev.h>
19#include <linux/of.h>
20#include <linux/of_address.h>
21
22#define SUNXI_OSC24M_GATE 0
23
24static DEFINE_SPINLOCK(hosc_lock);
25
26static void __init sun4i_osc_clk_setup(struct device_node *node)
27{
28 struct clk *clk;
29 struct clk_fixed_rate *fixed;
30 struct clk_gate *gate;
31 const char *clk_name = node->name;
32 u32 rate;
33
34 if (of_property_read_u32(node, "clock-frequency", &rate))
35 return;
36
37 /* allocate fixed-rate and gate clock structs */
38 fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
39 if (!fixed)
40 return;
41 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
42 if (!gate)
43 goto err_free_fixed;
44
45 of_property_read_string(node, "clock-output-names", &clk_name);
46
47 /* set up gate and fixed rate properties */
48 gate->reg = of_iomap(node, 0);
49 gate->bit_idx = SUNXI_OSC24M_GATE;
50 gate->lock = &hosc_lock;
51 fixed->fixed_rate = rate;
52
53 clk = clk_register_composite(NULL, clk_name,
54 NULL, 0,
55 NULL, NULL,
56 &fixed->hw, &clk_fixed_rate_ops,
57 &gate->hw, &clk_gate_ops,
58 CLK_IS_ROOT);
59
60 if (IS_ERR(clk))
61 goto err_free_gate;
62
63 of_clk_add_provider(node, of_clk_src_simple_get, clk);
64 clk_register_clkdev(clk, clk_name, NULL);
65
66 return;
67
68err_free_gate:
69 kfree(gate);
70err_free_fixed:
71 kfree(fixed);
72}
73CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-a10-osc-clk", sun4i_osc_clk_setup);
diff --git a/drivers/clk/sunxi/clk-a20-gmac.c b/drivers/clk/sunxi/clk-a20-gmac.c
new file mode 100644
index 000000000000..633ddc4389ef
--- /dev/null
+++ b/drivers/clk/sunxi/clk-a20-gmac.c
@@ -0,0 +1,119 @@
1/*
2 * Copyright 2013 Emilio López
3 * Emilio López <emilio@elopez.com.ar>
4 *
5 * Copyright 2013 Chen-Yu Tsai
6 * Chen-Yu Tsai <wens@csie.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#include <linux/clk-provider.h>
20#include <linux/clkdev.h>
21#include <linux/of.h>
22#include <linux/of_address.h>
23#include <linux/slab.h>
24
25static DEFINE_SPINLOCK(gmac_lock);
26
27/**
28 * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
29 *
30 * This clock looks something like this
31 * ________________________
32 * MII TX clock from PHY >-----|___________ _________|----> to GMAC core
33 * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
34 * Ext. 125MHz RGMII TX clk >--|__divider__/ |
35 * |________________________|
36 *
37 * The external 125 MHz reference is optional, i.e. GMAC can use its
38 * internal TX clock just fine. The A31 GMAC clock module does not have
39 * the divider controls for the external reference.
40 *
41 * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
42 * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
43 * select the appropriate source and gate/ungate the output to the PHY.
44 *
45 * Only the GMAC should use this clock. Altering the clock so that it doesn't
46 * match the GMAC's operation parameters will result in the GMAC not being
47 * able to send traffic out. The GMAC driver should set the clock rate and
48 * enable/disable this clock to configure the required state. The clock
49 * driver then responds by auto-reparenting the clock.
50 */
51
52#define SUN7I_A20_GMAC_GPIT 2
53#define SUN7I_A20_GMAC_MASK 0x3
54#define SUN7I_A20_GMAC_PARENTS 2
55
56static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
57{
58 struct clk *clk;
59 struct clk_mux *mux;
60 struct clk_gate *gate;
61 const char *clk_name = node->name;
62 const char *parents[SUN7I_A20_GMAC_PARENTS];
63 void *reg;
64
65 if (of_property_read_string(node, "clock-output-names", &clk_name))
66 return;
67
68 /* allocate mux and gate clock structs */
69 mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
70 if (!mux)
71 return;
72
73 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
74 if (!gate)
75 goto free_mux;
76
77 /* gmac clock requires exactly 2 parents */
78 parents[0] = of_clk_get_parent_name(node, 0);
79 parents[1] = of_clk_get_parent_name(node, 1);
80 if (!parents[0] || !parents[1])
81 goto free_gate;
82
83 reg = of_iomap(node, 0);
84 if (!reg)
85 goto free_gate;
86
87 /* set up gate and fixed rate properties */
88 gate->reg = reg;
89 gate->bit_idx = SUN7I_A20_GMAC_GPIT;
90 gate->lock = &gmac_lock;
91 mux->reg = reg;
92 mux->mask = SUN7I_A20_GMAC_MASK;
93 mux->flags = CLK_MUX_INDEX_BIT;
94 mux->lock = &gmac_lock;
95
96 clk = clk_register_composite(NULL, clk_name,
97 parents, SUN7I_A20_GMAC_PARENTS,
98 &mux->hw, &clk_mux_ops,
99 NULL, NULL,
100 &gate->hw, &clk_gate_ops,
101 0);
102
103 if (IS_ERR(clk))
104 goto iounmap_reg;
105
106 of_clk_add_provider(node, of_clk_src_simple_get, clk);
107 clk_register_clkdev(clk, clk_name, NULL);
108
109 return;
110
111iounmap_reg:
112 iounmap(reg);
113free_gate:
114 kfree(gate);
115free_mux:
116 kfree(mux);
117}
118CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
119 sun7i_a20_gmac_clk_setup);
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
new file mode 100644
index 000000000000..44cd27c5c401
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
@@ -0,0 +1,99 @@
1/*
2 * Copyright (C) 2014 Free Electrons
3 *
4 * License Terms: GNU General Public License v2
5 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
6 *
7 * Allwinner A31 APB0 clock gates driver
8 *
9 */
10
11#include <linux/clk-provider.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/platform_device.h>
15
16#define SUN6I_APB0_GATES_MAX_SIZE 32
17
18static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev)
19{
20 struct device_node *np = pdev->dev.of_node;
21 struct clk_onecell_data *clk_data;
22 const char *clk_parent;
23 const char *clk_name;
24 struct resource *r;
25 void __iomem *reg;
26 int gate_id;
27 int ngates;
28 int i;
29
30 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
31 reg = devm_ioremap_resource(&pdev->dev, r);
32 if (!reg)
33 return PTR_ERR(reg);
34
35 clk_parent = of_clk_get_parent_name(np, 0);
36 if (!clk_parent)
37 return -EINVAL;
38
39 ngates = of_property_count_strings(np, "clock-output-names");
40 if (ngates < 0)
41 return ngates;
42
43 if (!ngates || ngates > SUN6I_APB0_GATES_MAX_SIZE)
44 return -EINVAL;
45
46 clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data),
47 GFP_KERNEL);
48 if (!clk_data)
49 return -ENOMEM;
50
51 clk_data->clks = devm_kzalloc(&pdev->dev,
52 SUN6I_APB0_GATES_MAX_SIZE *
53 sizeof(struct clk *),
54 GFP_KERNEL);
55 if (!clk_data->clks)
56 return -ENOMEM;
57
58 for (i = 0; i < ngates; i++) {
59 of_property_read_string_index(np, "clock-output-names",
60 i, &clk_name);
61
62 gate_id = i;
63 of_property_read_u32_index(np, "clock-indices", i, &gate_id);
64
65 WARN_ON(gate_id >= SUN6I_APB0_GATES_MAX_SIZE);
66 if (gate_id >= SUN6I_APB0_GATES_MAX_SIZE)
67 continue;
68
69 clk_data->clks[gate_id] = clk_register_gate(&pdev->dev,
70 clk_name,
71 clk_parent, 0,
72 reg, gate_id,
73 0, NULL);
74 WARN_ON(IS_ERR(clk_data->clks[gate_id]));
75 }
76
77 clk_data->clk_num = ngates;
78
79 return of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
80}
81
82const struct of_device_id sun6i_a31_apb0_gates_clk_dt_ids[] = {
83 { .compatible = "allwinner,sun6i-a31-apb0-gates-clk" },
84 { /* sentinel */ }
85};
86
87static struct platform_driver sun6i_a31_apb0_gates_clk_driver = {
88 .driver = {
89 .name = "sun6i-a31-apb0-gates-clk",
90 .owner = THIS_MODULE,
91 .of_match_table = sun6i_a31_apb0_gates_clk_dt_ids,
92 },
93 .probe = sun6i_a31_apb0_gates_clk_probe,
94};
95module_platform_driver(sun6i_a31_apb0_gates_clk_driver);
96
97MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
98MODULE_DESCRIPTION("Allwinner A31 APB0 gate clocks driver");
99MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0.c b/drivers/clk/sunxi/clk-sun6i-apb0.c
new file mode 100644
index 000000000000..11f17c34c2ae
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun6i-apb0.c
@@ -0,0 +1,77 @@
1/*
2 * Copyright (C) 2014 Free Electrons
3 *
4 * License Terms: GNU General Public License v2
5 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
6 *
7 * Allwinner A31 APB0 clock driver
8 *
9 */
10
11#include <linux/clk-provider.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/platform_device.h>
15
16/*
17 * The APB0 clk has a configurable divisor.
18 *
19 * We must use a clk_div_table and not a regular power of 2
20 * divisor here, because the first 2 values divide the clock
21 * by 2.
22 */
23static const struct clk_div_table sun6i_a31_apb0_divs[] = {
24 { .val = 0, .div = 2, },
25 { .val = 1, .div = 2, },
26 { .val = 2, .div = 4, },
27 { .val = 3, .div = 8, },
28 { /* sentinel */ },
29};
30
31static int sun6i_a31_apb0_clk_probe(struct platform_device *pdev)
32{
33 struct device_node *np = pdev->dev.of_node;
34 const char *clk_name = np->name;
35 const char *clk_parent;
36 struct resource *r;
37 void __iomem *reg;
38 struct clk *clk;
39
40 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
41 reg = devm_ioremap_resource(&pdev->dev, r);
42 if (IS_ERR(reg))
43 return PTR_ERR(reg);
44
45 clk_parent = of_clk_get_parent_name(np, 0);
46 if (!clk_parent)
47 return -EINVAL;
48
49 of_property_read_string(np, "clock-output-names", &clk_name);
50
51 clk = clk_register_divider_table(&pdev->dev, clk_name, clk_parent,
52 0, reg, 0, 2, 0, sun6i_a31_apb0_divs,
53 NULL);
54 if (IS_ERR(clk))
55 return PTR_ERR(clk);
56
57 return of_clk_add_provider(np, of_clk_src_simple_get, clk);
58}
59
60const struct of_device_id sun6i_a31_apb0_clk_dt_ids[] = {
61 { .compatible = "allwinner,sun6i-a31-apb0-clk" },
62 { /* sentinel */ }
63};
64
65static struct platform_driver sun6i_a31_apb0_clk_driver = {
66 .driver = {
67 .name = "sun6i-a31-apb0-clk",
68 .owner = THIS_MODULE,
69 .of_match_table = sun6i_a31_apb0_clk_dt_ids,
70 },
71 .probe = sun6i_a31_apb0_clk_probe,
72};
73module_platform_driver(sun6i_a31_apb0_clk_driver);
74
75MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
76MODULE_DESCRIPTION("Allwinner A31 APB0 clock Driver");
77MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c
new file mode 100644
index 000000000000..f73cc051f0dd
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun6i-ar100.c
@@ -0,0 +1,233 @@
1/*
2 * Copyright (C) 2014 Free Electrons
3 *
4 * License Terms: GNU General Public License v2
5 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
6 *
7 * Allwinner A31 AR100 clock driver
8 *
9 */
10
11#include <linux/clk-provider.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/platform_device.h>
15
16#define SUN6I_AR100_MAX_PARENTS 4
17#define SUN6I_AR100_SHIFT_MASK 0x3
18#define SUN6I_AR100_SHIFT_MAX SUN6I_AR100_SHIFT_MASK
19#define SUN6I_AR100_SHIFT_SHIFT 4
20#define SUN6I_AR100_DIV_MASK 0x1f
21#define SUN6I_AR100_DIV_MAX (SUN6I_AR100_DIV_MASK + 1)
22#define SUN6I_AR100_DIV_SHIFT 8
23#define SUN6I_AR100_MUX_MASK 0x3
24#define SUN6I_AR100_MUX_SHIFT 16
25
26struct ar100_clk {
27 struct clk_hw hw;
28 void __iomem *reg;
29};
30
31static inline struct ar100_clk *to_ar100_clk(struct clk_hw *hw)
32{
33 return container_of(hw, struct ar100_clk, hw);
34}
35
36static unsigned long ar100_recalc_rate(struct clk_hw *hw,
37 unsigned long parent_rate)
38{
39 struct ar100_clk *clk = to_ar100_clk(hw);
40 u32 val = readl(clk->reg);
41 int shift = (val >> SUN6I_AR100_SHIFT_SHIFT) & SUN6I_AR100_SHIFT_MASK;
42 int div = (val >> SUN6I_AR100_DIV_SHIFT) & SUN6I_AR100_DIV_MASK;
43
44 return (parent_rate >> shift) / (div + 1);
45}
46
47static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
48 unsigned long *best_parent_rate,
49 struct clk **best_parent_clk)
50{
51 int nparents = __clk_get_num_parents(hw->clk);
52 long best_rate = -EINVAL;
53 int i;
54
55 *best_parent_clk = NULL;
56
57 for (i = 0; i < nparents; i++) {
58 unsigned long parent_rate;
59 unsigned long tmp_rate;
60 struct clk *parent;
61 unsigned long div;
62 int shift;
63
64 parent = clk_get_parent_by_index(hw->clk, i);
65 parent_rate = __clk_get_rate(parent);
66 div = DIV_ROUND_UP(parent_rate, rate);
67
68 /*
69 * The AR100 clk contains 2 divisors:
70 * - one power of 2 divisor
71 * - one regular divisor
72 *
73 * First check if we can safely shift (or divide by a power
74 * of 2) without losing precision on the requested rate.
75 */
76 shift = ffs(div) - 1;
77 if (shift > SUN6I_AR100_SHIFT_MAX)
78 shift = SUN6I_AR100_SHIFT_MAX;
79
80 div >>= shift;
81
82 /*
83 * Then if the divisor is still bigger than what the HW
84 * actually supports, use a bigger shift (or power of 2
85 * divider) value and accept to lose some precision.
86 */
87 while (div > SUN6I_AR100_DIV_MAX) {
88 shift++;
89 div >>= 1;
90 if (shift > SUN6I_AR100_SHIFT_MAX)
91 break;
92 }
93
94 /*
95 * If the shift value (or power of 2 divider) is bigger
96 * than what the HW actually support, skip this parent.
97 */
98 if (shift > SUN6I_AR100_SHIFT_MAX)
99 continue;
100
101 tmp_rate = (parent_rate >> shift) / div;
102 if (!*best_parent_clk || tmp_rate > best_rate) {
103 *best_parent_clk = parent;
104 *best_parent_rate = parent_rate;
105 best_rate = tmp_rate;
106 }
107 }
108
109 return best_rate;
110}
111
112static int ar100_set_parent(struct clk_hw *hw, u8 index)
113{
114 struct ar100_clk *clk = to_ar100_clk(hw);
115 u32 val = readl(clk->reg);
116
117 if (index >= SUN6I_AR100_MAX_PARENTS)
118 return -EINVAL;
119
120 val &= ~(SUN6I_AR100_MUX_MASK << SUN6I_AR100_MUX_SHIFT);
121 val |= (index << SUN6I_AR100_MUX_SHIFT);
122 writel(val, clk->reg);
123
124 return 0;
125}
126
127static u8 ar100_get_parent(struct clk_hw *hw)
128{
129 struct ar100_clk *clk = to_ar100_clk(hw);
130 return (readl(clk->reg) >> SUN6I_AR100_MUX_SHIFT) &
131 SUN6I_AR100_MUX_MASK;
132}
133
134static int ar100_set_rate(struct clk_hw *hw, unsigned long rate,
135 unsigned long parent_rate)
136{
137 unsigned long div = parent_rate / rate;
138 struct ar100_clk *clk = to_ar100_clk(hw);
139 u32 val = readl(clk->reg);
140 int shift;
141
142 if (parent_rate % rate)
143 return -EINVAL;
144
145 shift = ffs(div) - 1;
146 if (shift > SUN6I_AR100_SHIFT_MAX)
147 shift = SUN6I_AR100_SHIFT_MAX;
148
149 div >>= shift;
150
151 if (div > SUN6I_AR100_DIV_MAX)
152 return -EINVAL;
153
154 val &= ~((SUN6I_AR100_SHIFT_MASK << SUN6I_AR100_SHIFT_SHIFT) |
155 (SUN6I_AR100_DIV_MASK << SUN6I_AR100_DIV_SHIFT));
156 val |= (shift << SUN6I_AR100_SHIFT_SHIFT) |
157 (div << SUN6I_AR100_DIV_SHIFT);
158 writel(val, clk->reg);
159
160 return 0;
161}
162
163struct clk_ops ar100_ops = {
164 .recalc_rate = ar100_recalc_rate,
165 .determine_rate = ar100_determine_rate,
166 .set_parent = ar100_set_parent,
167 .get_parent = ar100_get_parent,
168 .set_rate = ar100_set_rate,
169};
170
171static int sun6i_a31_ar100_clk_probe(struct platform_device *pdev)
172{
173 const char *parents[SUN6I_AR100_MAX_PARENTS];
174 struct device_node *np = pdev->dev.of_node;
175 const char *clk_name = np->name;
176 struct clk_init_data init;
177 struct ar100_clk *ar100;
178 struct resource *r;
179 struct clk *clk;
180 int nparents;
181 int i;
182
183 ar100 = devm_kzalloc(&pdev->dev, sizeof(*ar100), GFP_KERNEL);
184 if (!ar100)
185 return -ENOMEM;
186
187 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
188 ar100->reg = devm_ioremap_resource(&pdev->dev, r);
189 if (IS_ERR(ar100->reg))
190 return PTR_ERR(ar100->reg);
191
192 nparents = of_clk_get_parent_count(np);
193 if (nparents > SUN6I_AR100_MAX_PARENTS)
194 nparents = SUN6I_AR100_MAX_PARENTS;
195
196 for (i = 0; i < nparents; i++)
197 parents[i] = of_clk_get_parent_name(np, i);
198
199 of_property_read_string(np, "clock-output-names", &clk_name);
200
201 init.name = clk_name;
202 init.ops = &ar100_ops;
203 init.parent_names = parents;
204 init.num_parents = nparents;
205 init.flags = 0;
206
207 ar100->hw.init = &init;
208
209 clk = clk_register(&pdev->dev, &ar100->hw);
210 if (IS_ERR(clk))
211 return PTR_ERR(clk);
212
213 return of_clk_add_provider(np, of_clk_src_simple_get, clk);
214}
215
216const struct of_device_id sun6i_a31_ar100_clk_dt_ids[] = {
217 { .compatible = "allwinner,sun6i-a31-ar100-clk" },
218 { /* sentinel */ }
219};
220
221static struct platform_driver sun6i_a31_ar100_clk_driver = {
222 .driver = {
223 .name = "sun6i-a31-ar100-clk",
224 .owner = THIS_MODULE,
225 .of_match_table = sun6i_a31_ar100_clk_dt_ids,
226 },
227 .probe = sun6i_a31_ar100_clk_probe,
228};
229module_platform_driver(sun6i_a31_ar100_clk_driver);
230
231MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
232MODULE_DESCRIPTION("Allwinner A31 AR100 clock Driver");
233MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 426483422d3d..fb2ce8440f0e 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -28,63 +28,6 @@ static DEFINE_SPINLOCK(clk_lock);
28#define SUNXI_MAX_PARENTS 5 28#define SUNXI_MAX_PARENTS 5
29 29
30/** 30/**
31 * sun4i_osc_clk_setup() - Setup function for gatable oscillator
32 */
33
34#define SUNXI_OSC24M_GATE 0
35
36static void __init sun4i_osc_clk_setup(struct device_node *node)
37{
38 struct clk *clk;
39 struct clk_fixed_rate *fixed;
40 struct clk_gate *gate;
41 const char *clk_name = node->name;
42 u32 rate;
43
44 if (of_property_read_u32(node, "clock-frequency", &rate))
45 return;
46
47 /* allocate fixed-rate and gate clock structs */
48 fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
49 if (!fixed)
50 return;
51 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
52 if (!gate)
53 goto err_free_fixed;
54
55 of_property_read_string(node, "clock-output-names", &clk_name);
56
57 /* set up gate and fixed rate properties */
58 gate->reg = of_iomap(node, 0);
59 gate->bit_idx = SUNXI_OSC24M_GATE;
60 gate->lock = &clk_lock;
61 fixed->fixed_rate = rate;
62
63 clk = clk_register_composite(NULL, clk_name,
64 NULL, 0,
65 NULL, NULL,
66 &fixed->hw, &clk_fixed_rate_ops,
67 &gate->hw, &clk_gate_ops,
68 CLK_IS_ROOT);
69
70 if (IS_ERR(clk))
71 goto err_free_gate;
72
73 of_clk_add_provider(node, of_clk_src_simple_get, clk);
74 clk_register_clkdev(clk, clk_name, NULL);
75
76 return;
77
78err_free_gate:
79 kfree(gate);
80err_free_fixed:
81 kfree(fixed);
82}
83CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-a10-osc-clk", sun4i_osc_clk_setup);
84
85
86
87/**
88 * sun4i_get_pll1_factors() - calculates n, k, m, p factors for PLL1 31 * sun4i_get_pll1_factors() - calculates n, k, m, p factors for PLL1
89 * PLL1 rate is calculated as follows 32 * PLL1 rate is calculated as follows
90 * rate = (parent_rate * n * (k + 1) >> p) / (m + 1); 33 * rate = (parent_rate * n * (k + 1) >> p) / (m + 1);
@@ -408,104 +351,6 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
408 *p = calcp; 351 *p = calcp;
409} 352}
410 353
411
412
413/**
414 * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
415 *
416 * This clock looks something like this
417 * ________________________
418 * MII TX clock from PHY >-----|___________ _________|----> to GMAC core
419 * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
420 * Ext. 125MHz RGMII TX clk >--|__divider__/ |
421 * |________________________|
422 *
423 * The external 125 MHz reference is optional, i.e. GMAC can use its
424 * internal TX clock just fine. The A31 GMAC clock module does not have
425 * the divider controls for the external reference.
426 *
427 * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
428 * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
429 * select the appropriate source and gate/ungate the output to the PHY.
430 *
431 * Only the GMAC should use this clock. Altering the clock so that it doesn't
432 * match the GMAC's operation parameters will result in the GMAC not being
433 * able to send traffic out. The GMAC driver should set the clock rate and
434 * enable/disable this clock to configure the required state. The clock
435 * driver then responds by auto-reparenting the clock.
436 */
437
438#define SUN7I_A20_GMAC_GPIT 2
439#define SUN7I_A20_GMAC_MASK 0x3
440#define SUN7I_A20_GMAC_PARENTS 2
441
442static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
443{
444 struct clk *clk;
445 struct clk_mux *mux;
446 struct clk_gate *gate;
447 const char *clk_name = node->name;
448 const char *parents[SUN7I_A20_GMAC_PARENTS];
449 void *reg;
450
451 if (of_property_read_string(node, "clock-output-names", &clk_name))
452 return;
453
454 /* allocate mux and gate clock structs */
455 mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
456 if (!mux)
457 return;
458
459 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
460 if (!gate)
461 goto free_mux;
462
463 /* gmac clock requires exactly 2 parents */
464 parents[0] = of_clk_get_parent_name(node, 0);
465 parents[1] = of_clk_get_parent_name(node, 1);
466 if (!parents[0] || !parents[1])
467 goto free_gate;
468
469 reg = of_iomap(node, 0);
470 if (!reg)
471 goto free_gate;
472
473 /* set up gate and fixed rate properties */
474 gate->reg = reg;
475 gate->bit_idx = SUN7I_A20_GMAC_GPIT;
476 gate->lock = &clk_lock;
477 mux->reg = reg;
478 mux->mask = SUN7I_A20_GMAC_MASK;
479 mux->flags = CLK_MUX_INDEX_BIT;
480 mux->lock = &clk_lock;
481
482 clk = clk_register_composite(NULL, clk_name,
483 parents, SUN7I_A20_GMAC_PARENTS,
484 &mux->hw, &clk_mux_ops,
485 NULL, NULL,
486 &gate->hw, &clk_gate_ops,
487 0);
488
489 if (IS_ERR(clk))
490 goto iounmap_reg;
491
492 of_clk_add_provider(node, of_clk_src_simple_get, clk);
493 clk_register_clkdev(clk, clk_name, NULL);
494
495 return;
496
497iounmap_reg:
498 iounmap(reg);
499free_gate:
500 kfree(gate);
501free_mux:
502 kfree(mux);
503}
504CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
505 sun7i_a20_gmac_clk_setup);
506
507
508
509/** 354/**
510 * clk_sunxi_mmc_phase_control() - configures MMC clock phase control 355 * clk_sunxi_mmc_phase_control() - configures MMC clock phase control
511 */ 356 */
@@ -1009,6 +854,11 @@ static const struct gates_data sun5i_a13_usb_gates_data __initconst = {
1009 .reset_mask = 0x03, 854 .reset_mask = 0x03,
1010}; 855};
1011 856
857static const struct gates_data sun6i_a31_usb_gates_data __initconst = {
858 .mask = { BIT(18) | BIT(17) | BIT(16) | BIT(10) | BIT(9) | BIT(8) },
859 .reset_mask = BIT(2) | BIT(1) | BIT(0),
860};
861
1012static void __init sunxi_gates_clk_setup(struct device_node *node, 862static void __init sunxi_gates_clk_setup(struct device_node *node,
1013 struct gates_data *data) 863 struct gates_data *data)
1014{ 864{
@@ -1304,6 +1154,7 @@ static const struct of_device_id clk_gates_match[] __initconst = {
1304 {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, 1154 {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
1305 {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,}, 1155 {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
1306 {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,}, 1156 {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,},
1157 {.compatible = "allwinner,sun6i-a31-usb-clk", .data = &sun6i_a31_usb_gates_data,},
1307 {} 1158 {}
1308}; 1159};
1309 1160
@@ -1321,33 +1172,10 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat
1321 } 1172 }
1322} 1173}
1323 1174
1324/** 1175static void __init sunxi_init_clocks(const char *clocks[], int nclocks)
1325 * System clock protection
1326 *
1327 * By enabling these critical clocks, we prevent their accidental gating
1328 * by the framework
1329 */
1330static void __init sunxi_clock_protect(void)
1331{ 1176{
1332 struct clk *clk; 1177 unsigned int i;
1333
1334 /* memory bus clock - sun5i+ */
1335 clk = clk_get(NULL, "mbus");
1336 if (!IS_ERR(clk)) {
1337 clk_prepare_enable(clk);
1338 clk_put(clk);
1339 }
1340
1341 /* DDR clock - sun4i+ */
1342 clk = clk_get(NULL, "pll5_ddr");
1343 if (!IS_ERR(clk)) {
1344 clk_prepare_enable(clk);
1345 clk_put(clk);
1346 }
1347}
1348 1178
1349static void __init sunxi_init_clocks(struct device_node *np)
1350{
1351 /* Register factor clocks */ 1179 /* Register factor clocks */
1352 of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); 1180 of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup);
1353 1181
@@ -1363,11 +1191,48 @@ static void __init sunxi_init_clocks(struct device_node *np)
1363 /* Register gate clocks */ 1191 /* Register gate clocks */
1364 of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup); 1192 of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup);
1365 1193
1366 /* Enable core system clocks */ 1194 /* Protect the clocks that needs to stay on */
1367 sunxi_clock_protect(); 1195 for (i = 0; i < nclocks; i++) {
1196 struct clk *clk = clk_get(NULL, clocks[i]);
1197
1198 if (!IS_ERR(clk))
1199 clk_prepare_enable(clk);
1200 }
1201}
1202
1203static const char *sun4i_a10_critical_clocks[] __initdata = {
1204 "pll5_ddr",
1205};
1206
1207static void __init sun4i_a10_init_clocks(struct device_node *node)
1208{
1209 sunxi_init_clocks(sun4i_a10_critical_clocks,
1210 ARRAY_SIZE(sun4i_a10_critical_clocks));
1211}
1212CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks);
1213
1214static const char *sun5i_critical_clocks[] __initdata = {
1215 "mbus",
1216 "pll5_ddr",
1217};
1218
1219static void __init sun5i_init_clocks(struct device_node *node)
1220{
1221 sunxi_init_clocks(sun5i_critical_clocks,
1222 ARRAY_SIZE(sun5i_critical_clocks));
1223}
1224CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sun5i_init_clocks);
1225CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sun5i_init_clocks);
1226CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sun5i_init_clocks);
1227
1228static const char *sun6i_critical_clocks[] __initdata = {
1229 "cpu",
1230 "ahb1_sdram",
1231};
1232
1233static void __init sun6i_init_clocks(struct device_node *node)
1234{
1235 sunxi_init_clocks(sun6i_critical_clocks,
1236 ARRAY_SIZE(sun6i_critical_clocks));
1368} 1237}
1369CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sunxi_init_clocks); 1238CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks);
1370CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sunxi_init_clocks);
1371CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sunxi_init_clocks);
1372CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sunxi_init_clocks);
1373CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sunxi_init_clocks);
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index 4319d4031aa3..ed4d0aaf8916 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -3,9 +3,11 @@ obj-y += clk.o autoidle.o clockdomain.o
3clk-common = dpll.o composite.o divider.o gate.o \ 3clk-common = dpll.o composite.o divider.o gate.o \
4 fixed-factor.o mux.o apll.o 4 fixed-factor.o mux.o apll.o
5obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o 5obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o
6obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o
6obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o clk-3xxx.o 7obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o clk-3xxx.o
7obj-$(CONFIG_ARCH_OMAP4) += $(clk-common) clk-44xx.o 8obj-$(CONFIG_ARCH_OMAP4) += $(clk-common) clk-44xx.o
8obj-$(CONFIG_SOC_OMAP5) += $(clk-common) clk-54xx.o 9obj-$(CONFIG_SOC_OMAP5) += $(clk-common) clk-54xx.o
9obj-$(CONFIG_SOC_DRA7XX) += $(clk-common) clk-7xx.o 10obj-$(CONFIG_SOC_DRA7XX) += $(clk-common) clk-7xx.o \
11 clk-dra7-atl.o
10obj-$(CONFIG_SOC_AM43XX) += $(clk-common) clk-43xx.o 12obj-$(CONFIG_SOC_AM43XX) += $(clk-common) clk-43xx.o
11endif 13endif
diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c
index b986f61f5a77..5428c9c547cd 100644
--- a/drivers/clk/ti/apll.c
+++ b/drivers/clk/ti/apll.c
@@ -221,3 +221,184 @@ cleanup:
221 kfree(init); 221 kfree(init);
222} 222}
223CLK_OF_DECLARE(dra7_apll_clock, "ti,dra7-apll-clock", of_dra7_apll_setup); 223CLK_OF_DECLARE(dra7_apll_clock, "ti,dra7-apll-clock", of_dra7_apll_setup);
224
225#define OMAP2_EN_APLL_LOCKED 0x3
226#define OMAP2_EN_APLL_STOPPED 0x0
227
228static int omap2_apll_is_enabled(struct clk_hw *hw)
229{
230 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
231 struct dpll_data *ad = clk->dpll_data;
232 u32 v;
233
234 v = ti_clk_ll_ops->clk_readl(ad->control_reg);
235 v &= ad->enable_mask;
236
237 v >>= __ffs(ad->enable_mask);
238
239 return v == OMAP2_EN_APLL_LOCKED ? 1 : 0;
240}
241
242static unsigned long omap2_apll_recalc(struct clk_hw *hw,
243 unsigned long parent_rate)
244{
245 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
246
247 if (omap2_apll_is_enabled(hw))
248 return clk->fixed_rate;
249
250 return 0;
251}
252
253static int omap2_apll_enable(struct clk_hw *hw)
254{
255 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
256 struct dpll_data *ad = clk->dpll_data;
257 u32 v;
258 int i = 0;
259
260 v = ti_clk_ll_ops->clk_readl(ad->control_reg);
261 v &= ~ad->enable_mask;
262 v |= OMAP2_EN_APLL_LOCKED << __ffs(ad->enable_mask);
263 ti_clk_ll_ops->clk_writel(v, ad->control_reg);
264
265 while (1) {
266 v = ti_clk_ll_ops->clk_readl(ad->idlest_reg);
267 if (v & ad->idlest_mask)
268 break;
269 if (i > MAX_APLL_WAIT_TRIES)
270 break;
271 i++;
272 udelay(1);
273 }
274
275 if (i == MAX_APLL_WAIT_TRIES) {
276 pr_warn("%s failed to transition to locked\n",
277 __clk_get_name(clk->hw.clk));
278 return -EBUSY;
279 }
280
281 return 0;
282}
283
284static void omap2_apll_disable(struct clk_hw *hw)
285{
286 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
287 struct dpll_data *ad = clk->dpll_data;
288 u32 v;
289
290 v = ti_clk_ll_ops->clk_readl(ad->control_reg);
291 v &= ~ad->enable_mask;
292 v |= OMAP2_EN_APLL_STOPPED << __ffs(ad->enable_mask);
293 ti_clk_ll_ops->clk_writel(v, ad->control_reg);
294}
295
296static struct clk_ops omap2_apll_ops = {
297 .enable = &omap2_apll_enable,
298 .disable = &omap2_apll_disable,
299 .is_enabled = &omap2_apll_is_enabled,
300 .recalc_rate = &omap2_apll_recalc,
301};
302
303static void omap2_apll_set_autoidle(struct clk_hw_omap *clk, u32 val)
304{
305 struct dpll_data *ad = clk->dpll_data;
306 u32 v;
307
308 v = ti_clk_ll_ops->clk_readl(ad->autoidle_reg);
309 v &= ~ad->autoidle_mask;
310 v |= val << __ffs(ad->autoidle_mask);
311 ti_clk_ll_ops->clk_writel(v, ad->control_reg);
312}
313
314#define OMAP2_APLL_AUTOIDLE_LOW_POWER_STOP 0x3
315#define OMAP2_APLL_AUTOIDLE_DISABLE 0x0
316
317static void omap2_apll_allow_idle(struct clk_hw_omap *clk)
318{
319 omap2_apll_set_autoidle(clk, OMAP2_APLL_AUTOIDLE_LOW_POWER_STOP);
320}
321
322static void omap2_apll_deny_idle(struct clk_hw_omap *clk)
323{
324 omap2_apll_set_autoidle(clk, OMAP2_APLL_AUTOIDLE_DISABLE);
325}
326
327static struct clk_hw_omap_ops omap2_apll_hwops = {
328 .allow_idle = &omap2_apll_allow_idle,
329 .deny_idle = &omap2_apll_deny_idle,
330};
331
332static void __init of_omap2_apll_setup(struct device_node *node)
333{
334 struct dpll_data *ad = NULL;
335 struct clk_hw_omap *clk_hw = NULL;
336 struct clk_init_data *init = NULL;
337 struct clk *clk;
338 const char *parent_name;
339 u32 val;
340
341 ad = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
342 clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
343 init = kzalloc(sizeof(*init), GFP_KERNEL);
344
345 if (!ad || !clk_hw || !init)
346 goto cleanup;
347
348 clk_hw->dpll_data = ad;
349 clk_hw->hw.init = init;
350 init->ops = &omap2_apll_ops;
351 init->name = node->name;
352 clk_hw->ops = &omap2_apll_hwops;
353
354 init->num_parents = of_clk_get_parent_count(node);
355 if (init->num_parents != 1) {
356 pr_err("%s must have one parent\n", node->name);
357 goto cleanup;
358 }
359
360 parent_name = of_clk_get_parent_name(node, 0);
361 init->parent_names = &parent_name;
362
363 if (of_property_read_u32(node, "ti,clock-frequency", &val)) {
364 pr_err("%s missing clock-frequency\n", node->name);
365 goto cleanup;
366 }
367 clk_hw->fixed_rate = val;
368
369 if (of_property_read_u32(node, "ti,bit-shift", &val)) {
370 pr_err("%s missing bit-shift\n", node->name);
371 goto cleanup;
372 }
373
374 clk_hw->enable_bit = val;
375 ad->enable_mask = 0x3 << val;
376 ad->autoidle_mask = 0x3 << val;
377
378 if (of_property_read_u32(node, "ti,idlest-shift", &val)) {
379 pr_err("%s missing idlest-shift\n", node->name);
380 goto cleanup;
381 }
382
383 ad->idlest_mask = 1 << val;
384
385 ad->control_reg = ti_clk_get_reg_addr(node, 0);
386 ad->autoidle_reg = ti_clk_get_reg_addr(node, 1);
387 ad->idlest_reg = ti_clk_get_reg_addr(node, 2);
388
389 if (!ad->control_reg || !ad->autoidle_reg || !ad->idlest_reg)
390 goto cleanup;
391
392 clk = clk_register(NULL, &clk_hw->hw);
393 if (!IS_ERR(clk)) {
394 of_clk_add_provider(node, of_clk_src_simple_get, clk);
395 kfree(init);
396 return;
397 }
398cleanup:
399 kfree(ad);
400 kfree(clk_hw);
401 kfree(init);
402}
403CLK_OF_DECLARE(omap2_apll_clock, "ti,omap2-apll-clock",
404 of_omap2_apll_setup);
diff --git a/drivers/clk/ti/clk-2xxx.c b/drivers/clk/ti/clk-2xxx.c
new file mode 100644
index 000000000000..c808ab3d2bb2
--- /dev/null
+++ b/drivers/clk/ti/clk-2xxx.c
@@ -0,0 +1,256 @@
1/*
2 * OMAP2 Clock init
3 *
4 * Copyright (C) 2013 Texas Instruments, Inc
5 * Tero Kristo (t-kristo@ti.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation version 2.
10 *
11 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
12 * kind, whether express or implied; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/kernel.h>
18#include <linux/list.h>
19#include <linux/clk-provider.h>
20#include <linux/clk/ti.h>
21
22static struct ti_dt_clk omap2xxx_clks[] = {
23 DT_CLK(NULL, "func_32k_ck", "func_32k_ck"),
24 DT_CLK(NULL, "secure_32k_ck", "secure_32k_ck"),
25 DT_CLK(NULL, "virt_12m_ck", "virt_12m_ck"),
26 DT_CLK(NULL, "virt_13m_ck", "virt_13m_ck"),
27 DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"),
28 DT_CLK(NULL, "virt_26m_ck", "virt_26m_ck"),
29 DT_CLK(NULL, "aplls_clkin_ck", "aplls_clkin_ck"),
30 DT_CLK(NULL, "aplls_clkin_x2_ck", "aplls_clkin_x2_ck"),
31 DT_CLK(NULL, "osc_ck", "osc_ck"),
32 DT_CLK(NULL, "sys_ck", "sys_ck"),
33 DT_CLK(NULL, "alt_ck", "alt_ck"),
34 DT_CLK(NULL, "mcbsp_clks", "mcbsp_clks"),
35 DT_CLK(NULL, "dpll_ck", "dpll_ck"),
36 DT_CLK(NULL, "apll96_ck", "apll96_ck"),
37 DT_CLK(NULL, "apll54_ck", "apll54_ck"),
38 DT_CLK(NULL, "func_54m_ck", "func_54m_ck"),
39 DT_CLK(NULL, "core_ck", "core_ck"),
40 DT_CLK(NULL, "func_96m_ck", "func_96m_ck"),
41 DT_CLK(NULL, "func_48m_ck", "func_48m_ck"),
42 DT_CLK(NULL, "func_12m_ck", "func_12m_ck"),
43 DT_CLK(NULL, "sys_clkout_src", "sys_clkout_src"),
44 DT_CLK(NULL, "sys_clkout", "sys_clkout"),
45 DT_CLK(NULL, "emul_ck", "emul_ck"),
46 DT_CLK(NULL, "mpu_ck", "mpu_ck"),
47 DT_CLK(NULL, "dsp_fck", "dsp_fck"),
48 DT_CLK(NULL, "gfx_3d_fck", "gfx_3d_fck"),
49 DT_CLK(NULL, "gfx_2d_fck", "gfx_2d_fck"),
50 DT_CLK(NULL, "gfx_ick", "gfx_ick"),
51 DT_CLK("omapdss_dss", "ick", "dss_ick"),
52 DT_CLK(NULL, "dss_ick", "dss_ick"),
53 DT_CLK(NULL, "dss1_fck", "dss1_fck"),
54 DT_CLK(NULL, "dss2_fck", "dss2_fck"),
55 DT_CLK(NULL, "dss_54m_fck", "dss_54m_fck"),
56 DT_CLK(NULL, "core_l3_ck", "core_l3_ck"),
57 DT_CLK(NULL, "ssi_fck", "ssi_ssr_sst_fck"),
58 DT_CLK(NULL, "usb_l4_ick", "usb_l4_ick"),
59 DT_CLK(NULL, "l4_ck", "l4_ck"),
60 DT_CLK(NULL, "ssi_l4_ick", "ssi_l4_ick"),
61 DT_CLK(NULL, "gpt1_ick", "gpt1_ick"),
62 DT_CLK(NULL, "gpt1_fck", "gpt1_fck"),
63 DT_CLK(NULL, "gpt2_ick", "gpt2_ick"),
64 DT_CLK(NULL, "gpt2_fck", "gpt2_fck"),
65 DT_CLK(NULL, "gpt3_ick", "gpt3_ick"),
66 DT_CLK(NULL, "gpt3_fck", "gpt3_fck"),
67 DT_CLK(NULL, "gpt4_ick", "gpt4_ick"),
68 DT_CLK(NULL, "gpt4_fck", "gpt4_fck"),
69 DT_CLK(NULL, "gpt5_ick", "gpt5_ick"),
70 DT_CLK(NULL, "gpt5_fck", "gpt5_fck"),
71 DT_CLK(NULL, "gpt6_ick", "gpt6_ick"),
72 DT_CLK(NULL, "gpt6_fck", "gpt6_fck"),
73 DT_CLK(NULL, "gpt7_ick", "gpt7_ick"),
74 DT_CLK(NULL, "gpt7_fck", "gpt7_fck"),
75 DT_CLK(NULL, "gpt8_ick", "gpt8_ick"),
76 DT_CLK(NULL, "gpt8_fck", "gpt8_fck"),
77 DT_CLK(NULL, "gpt9_ick", "gpt9_ick"),
78 DT_CLK(NULL, "gpt9_fck", "gpt9_fck"),
79 DT_CLK(NULL, "gpt10_ick", "gpt10_ick"),
80 DT_CLK(NULL, "gpt10_fck", "gpt10_fck"),
81 DT_CLK(NULL, "gpt11_ick", "gpt11_ick"),
82 DT_CLK(NULL, "gpt11_fck", "gpt11_fck"),
83 DT_CLK(NULL, "gpt12_ick", "gpt12_ick"),
84 DT_CLK(NULL, "gpt12_fck", "gpt12_fck"),
85 DT_CLK("omap-mcbsp.1", "ick", "mcbsp1_ick"),
86 DT_CLK(NULL, "mcbsp1_ick", "mcbsp1_ick"),
87 DT_CLK(NULL, "mcbsp1_fck", "mcbsp1_fck"),
88 DT_CLK("omap-mcbsp.2", "ick", "mcbsp2_ick"),
89 DT_CLK(NULL, "mcbsp2_ick", "mcbsp2_ick"),
90 DT_CLK(NULL, "mcbsp2_fck", "mcbsp2_fck"),
91 DT_CLK("omap2_mcspi.1", "ick", "mcspi1_ick"),
92 DT_CLK(NULL, "mcspi1_ick", "mcspi1_ick"),
93 DT_CLK(NULL, "mcspi1_fck", "mcspi1_fck"),
94 DT_CLK("omap2_mcspi.2", "ick", "mcspi2_ick"),
95 DT_CLK(NULL, "mcspi2_ick", "mcspi2_ick"),
96 DT_CLK(NULL, "mcspi2_fck", "mcspi2_fck"),
97 DT_CLK(NULL, "uart1_ick", "uart1_ick"),
98 DT_CLK(NULL, "uart1_fck", "uart1_fck"),
99 DT_CLK(NULL, "uart2_ick", "uart2_ick"),
100 DT_CLK(NULL, "uart2_fck", "uart2_fck"),
101 DT_CLK(NULL, "uart3_ick", "uart3_ick"),
102 DT_CLK(NULL, "uart3_fck", "uart3_fck"),
103 DT_CLK(NULL, "gpios_ick", "gpios_ick"),
104 DT_CLK(NULL, "gpios_fck", "gpios_fck"),
105 DT_CLK("omap_wdt", "ick", "mpu_wdt_ick"),
106 DT_CLK(NULL, "mpu_wdt_ick", "mpu_wdt_ick"),
107 DT_CLK(NULL, "mpu_wdt_fck", "mpu_wdt_fck"),
108 DT_CLK(NULL, "sync_32k_ick", "sync_32k_ick"),
109 DT_CLK(NULL, "wdt1_ick", "wdt1_ick"),
110 DT_CLK(NULL, "omapctrl_ick", "omapctrl_ick"),
111 DT_CLK("omap24xxcam", "fck", "cam_fck"),
112 DT_CLK(NULL, "cam_fck", "cam_fck"),
113 DT_CLK("omap24xxcam", "ick", "cam_ick"),
114 DT_CLK(NULL, "cam_ick", "cam_ick"),
115 DT_CLK(NULL, "mailboxes_ick", "mailboxes_ick"),
116 DT_CLK(NULL, "wdt4_ick", "wdt4_ick"),
117 DT_CLK(NULL, "wdt4_fck", "wdt4_fck"),
118 DT_CLK(NULL, "mspro_ick", "mspro_ick"),
119 DT_CLK(NULL, "mspro_fck", "mspro_fck"),
120 DT_CLK(NULL, "fac_ick", "fac_ick"),
121 DT_CLK(NULL, "fac_fck", "fac_fck"),
122 DT_CLK("omap_hdq.0", "ick", "hdq_ick"),
123 DT_CLK(NULL, "hdq_ick", "hdq_ick"),
124 DT_CLK("omap_hdq.0", "fck", "hdq_fck"),
125 DT_CLK(NULL, "hdq_fck", "hdq_fck"),
126 DT_CLK("omap_i2c.1", "ick", "i2c1_ick"),
127 DT_CLK(NULL, "i2c1_ick", "i2c1_ick"),
128 DT_CLK("omap_i2c.2", "ick", "i2c2_ick"),
129 DT_CLK(NULL, "i2c2_ick", "i2c2_ick"),
130 DT_CLK(NULL, "gpmc_fck", "gpmc_fck"),
131 DT_CLK(NULL, "sdma_fck", "sdma_fck"),
132 DT_CLK(NULL, "sdma_ick", "sdma_ick"),
133 DT_CLK(NULL, "sdrc_ick", "sdrc_ick"),
134 DT_CLK(NULL, "des_ick", "des_ick"),
135 DT_CLK("omap-sham", "ick", "sha_ick"),
136 DT_CLK(NULL, "sha_ick", "sha_ick"),
137 DT_CLK("omap_rng", "ick", "rng_ick"),
138 DT_CLK(NULL, "rng_ick", "rng_ick"),
139 DT_CLK("omap-aes", "ick", "aes_ick"),
140 DT_CLK(NULL, "aes_ick", "aes_ick"),
141 DT_CLK(NULL, "pka_ick", "pka_ick"),
142 DT_CLK(NULL, "usb_fck", "usb_fck"),
143 DT_CLK(NULL, "timer_32k_ck", "func_32k_ck"),
144 DT_CLK(NULL, "timer_sys_ck", "sys_ck"),
145 DT_CLK(NULL, "timer_ext_ck", "alt_ck"),
146 { .node_name = NULL },
147};
148
149static struct ti_dt_clk omap2420_clks[] = {
150 DT_CLK(NULL, "sys_clkout2_src", "sys_clkout2_src"),
151 DT_CLK(NULL, "sys_clkout2", "sys_clkout2"),
152 DT_CLK(NULL, "dsp_ick", "dsp_ick"),
153 DT_CLK(NULL, "iva1_ifck", "iva1_ifck"),
154 DT_CLK(NULL, "iva1_mpu_int_ifck", "iva1_mpu_int_ifck"),
155 DT_CLK(NULL, "wdt3_ick", "wdt3_ick"),
156 DT_CLK(NULL, "wdt3_fck", "wdt3_fck"),
157 DT_CLK("mmci-omap.0", "ick", "mmc_ick"),
158 DT_CLK(NULL, "mmc_ick", "mmc_ick"),
159 DT_CLK("mmci-omap.0", "fck", "mmc_fck"),
160 DT_CLK(NULL, "mmc_fck", "mmc_fck"),
161 DT_CLK(NULL, "eac_ick", "eac_ick"),
162 DT_CLK(NULL, "eac_fck", "eac_fck"),
163 DT_CLK(NULL, "i2c1_fck", "i2c1_fck"),
164 DT_CLK(NULL, "i2c2_fck", "i2c2_fck"),
165 DT_CLK(NULL, "vlynq_ick", "vlynq_ick"),
166 DT_CLK(NULL, "vlynq_fck", "vlynq_fck"),
167 DT_CLK("musb-hdrc", "fck", "osc_ck"),
168 { .node_name = NULL },
169};
170
171static struct ti_dt_clk omap2430_clks[] = {
172 DT_CLK("twl", "fck", "osc_ck"),
173 DT_CLK(NULL, "iva2_1_ick", "iva2_1_ick"),
174 DT_CLK(NULL, "mdm_ick", "mdm_ick"),
175 DT_CLK(NULL, "mdm_osc_ck", "mdm_osc_ck"),
176 DT_CLK("omap-mcbsp.3", "ick", "mcbsp3_ick"),
177 DT_CLK(NULL, "mcbsp3_ick", "mcbsp3_ick"),
178 DT_CLK(NULL, "mcbsp3_fck", "mcbsp3_fck"),
179 DT_CLK("omap-mcbsp.4", "ick", "mcbsp4_ick"),
180 DT_CLK(NULL, "mcbsp4_ick", "mcbsp4_ick"),
181 DT_CLK(NULL, "mcbsp4_fck", "mcbsp4_fck"),
182 DT_CLK("omap-mcbsp.5", "ick", "mcbsp5_ick"),
183 DT_CLK(NULL, "mcbsp5_ick", "mcbsp5_ick"),
184 DT_CLK(NULL, "mcbsp5_fck", "mcbsp5_fck"),
185 DT_CLK("omap2_mcspi.3", "ick", "mcspi3_ick"),
186 DT_CLK(NULL, "mcspi3_ick", "mcspi3_ick"),
187 DT_CLK(NULL, "mcspi3_fck", "mcspi3_fck"),
188 DT_CLK(NULL, "icr_ick", "icr_ick"),
189 DT_CLK(NULL, "i2chs1_fck", "i2chs1_fck"),
190 DT_CLK(NULL, "i2chs2_fck", "i2chs2_fck"),
191 DT_CLK("musb-omap2430", "ick", "usbhs_ick"),
192 DT_CLK(NULL, "usbhs_ick", "usbhs_ick"),
193 DT_CLK("omap_hsmmc.0", "ick", "mmchs1_ick"),
194 DT_CLK(NULL, "mmchs1_ick", "mmchs1_ick"),
195 DT_CLK(NULL, "mmchs1_fck", "mmchs1_fck"),
196 DT_CLK("omap_hsmmc.1", "ick", "mmchs2_ick"),
197 DT_CLK(NULL, "mmchs2_ick", "mmchs2_ick"),
198 DT_CLK(NULL, "mmchs2_fck", "mmchs2_fck"),
199 DT_CLK(NULL, "gpio5_ick", "gpio5_ick"),
200 DT_CLK(NULL, "gpio5_fck", "gpio5_fck"),
201 DT_CLK(NULL, "mdm_intc_ick", "mdm_intc_ick"),
202 DT_CLK("omap_hsmmc.0", "mmchsdb_fck", "mmchsdb1_fck"),
203 DT_CLK(NULL, "mmchsdb1_fck", "mmchsdb1_fck"),
204 DT_CLK("omap_hsmmc.1", "mmchsdb_fck", "mmchsdb2_fck"),
205 DT_CLK(NULL, "mmchsdb2_fck", "mmchsdb2_fck"),
206 { .node_name = NULL },
207};
208
209static const char *enable_init_clks[] = {
210 "apll96_ck",
211 "apll54_ck",
212 "sync_32k_ick",
213 "omapctrl_ick",
214 "gpmc_fck",
215 "sdrc_ick",
216};
217
218enum {
219 OMAP2_SOC_OMAP2420,
220 OMAP2_SOC_OMAP2430,
221};
222
223static int __init omap2xxx_dt_clk_init(int soc_type)
224{
225 ti_dt_clocks_register(omap2xxx_clks);
226
227 if (soc_type == OMAP2_SOC_OMAP2420)
228 ti_dt_clocks_register(omap2420_clks);
229 else
230 ti_dt_clocks_register(omap2430_clks);
231
232 omap2xxx_clkt_vps_init();
233
234 omap2_clk_disable_autoidle_all();
235
236 omap2_clk_enable_init_clocks(enable_init_clks,
237 ARRAY_SIZE(enable_init_clks));
238
239 pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
240 (clk_get_rate(clk_get_sys(NULL, "sys_ck")) / 1000000),
241 (clk_get_rate(clk_get_sys(NULL, "sys_ck")) / 100000) % 10,
242 (clk_get_rate(clk_get_sys(NULL, "dpll_ck")) / 1000000),
243 (clk_get_rate(clk_get_sys(NULL, "mpu_ck")) / 1000000));
244
245 return 0;
246}
247
248int __init omap2420_dt_clk_init(void)
249{
250 return omap2xxx_dt_clk_init(OMAP2_SOC_OMAP2420);
251}
252
253int __init omap2430_dt_clk_init(void)
254{
255 return omap2xxx_dt_clk_init(OMAP2_SOC_OMAP2430);
256}
diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c
index 08f3d1b915b3..5e183993e3ec 100644
--- a/drivers/clk/ti/clk-54xx.c
+++ b/drivers/clk/ti/clk-54xx.c
@@ -240,6 +240,12 @@ int __init omap5xxx_dt_clk_init(void)
240 if (rc) 240 if (rc)
241 pr_err("%s: failed to configure ABE DPLL!\n", __func__); 241 pr_err("%s: failed to configure ABE DPLL!\n", __func__);
242 242
243 abe_dpll = clk_get_sys(NULL, "dpll_abe_m2x2_ck");
244 if (!rc)
245 rc = clk_set_rate(abe_dpll, OMAP5_DPLL_ABE_DEFFREQ * 2);
246 if (rc)
247 pr_err("%s: failed to configure ABE m2x2 DPLL!\n", __func__);
248
243 usb_dpll = clk_get_sys(NULL, "dpll_usb_ck"); 249 usb_dpll = clk_get_sys(NULL, "dpll_usb_ck");
244 rc = clk_set_rate(usb_dpll, OMAP5_DPLL_USB_DEFFREQ); 250 rc = clk_set_rate(usb_dpll, OMAP5_DPLL_USB_DEFFREQ);
245 if (rc) 251 if (rc)
diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c
index f7e40734c819..e1581335937d 100644
--- a/drivers/clk/ti/clk-7xx.c
+++ b/drivers/clk/ti/clk-7xx.c
@@ -24,7 +24,7 @@ static struct ti_dt_clk dra7xx_clks[] = {
24 DT_CLK(NULL, "atl_clkin0_ck", "atl_clkin0_ck"), 24 DT_CLK(NULL, "atl_clkin0_ck", "atl_clkin0_ck"),
25 DT_CLK(NULL, "atl_clkin1_ck", "atl_clkin1_ck"), 25 DT_CLK(NULL, "atl_clkin1_ck", "atl_clkin1_ck"),
26 DT_CLK(NULL, "atl_clkin2_ck", "atl_clkin2_ck"), 26 DT_CLK(NULL, "atl_clkin2_ck", "atl_clkin2_ck"),
27 DT_CLK(NULL, "atlclkin3_ck", "atlclkin3_ck"), 27 DT_CLK(NULL, "atl_clkin3_ck", "atl_clkin3_ck"),
28 DT_CLK(NULL, "hdmi_clkin_ck", "hdmi_clkin_ck"), 28 DT_CLK(NULL, "hdmi_clkin_ck", "hdmi_clkin_ck"),
29 DT_CLK(NULL, "mlb_clkin_ck", "mlb_clkin_ck"), 29 DT_CLK(NULL, "mlb_clkin_ck", "mlb_clkin_ck"),
30 DT_CLK(NULL, "mlbp_clkin_ck", "mlbp_clkin_ck"), 30 DT_CLK(NULL, "mlbp_clkin_ck", "mlbp_clkin_ck"),
diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
new file mode 100644
index 000000000000..4a65b410e4d5
--- /dev/null
+++ b/drivers/clk/ti/clk-dra7-atl.c
@@ -0,0 +1,312 @@
1/*
2 * DRA7 ATL (Audio Tracking Logic) clock driver
3 *
4 * Copyright (C) 2013 Texas Instruments, Inc.
5 *
6 * Peter Ujfalusi <peter.ujfalusi@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13 * kind, whether express or implied; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/clk-provider.h>
20#include <linux/slab.h>
21#include <linux/io.h>
22#include <linux/of.h>
23#include <linux/of_address.h>
24#include <linux/platform_device.h>
25#include <linux/pm_runtime.h>
26
27#define DRA7_ATL_INSTANCES 4
28
29#define DRA7_ATL_PPMR_REG(id) (0x200 + (id * 0x80))
30#define DRA7_ATL_BBSR_REG(id) (0x204 + (id * 0x80))
31#define DRA7_ATL_ATLCR_REG(id) (0x208 + (id * 0x80))
32#define DRA7_ATL_SWEN_REG(id) (0x210 + (id * 0x80))
33#define DRA7_ATL_BWSMUX_REG(id) (0x214 + (id * 0x80))
34#define DRA7_ATL_AWSMUX_REG(id) (0x218 + (id * 0x80))
35#define DRA7_ATL_PCLKMUX_REG(id) (0x21c + (id * 0x80))
36
37#define DRA7_ATL_SWEN BIT(0)
38#define DRA7_ATL_DIVIDER_MASK (0x1f)
39#define DRA7_ATL_PCLKMUX BIT(0)
40struct dra7_atl_clock_info;
41
42struct dra7_atl_desc {
43 struct clk *clk;
44 struct clk_hw hw;
45 struct dra7_atl_clock_info *cinfo;
46 int id;
47
48 bool probed; /* the driver for the IP has been loaded */
49 bool valid; /* configured */
50 bool enabled;
51 u32 bws; /* Baseband Word Select Mux */
52 u32 aws; /* Audio Word Select Mux */
53 u32 divider; /* Cached divider value */
54};
55
56struct dra7_atl_clock_info {
57 struct device *dev;
58 void __iomem *iobase;
59
60 struct dra7_atl_desc *cdesc;
61};
62
63#define to_atl_desc(_hw) container_of(_hw, struct dra7_atl_desc, hw)
64
65static inline void atl_write(struct dra7_atl_clock_info *cinfo, u32 reg,
66 u32 val)
67{
68 __raw_writel(val, cinfo->iobase + reg);
69}
70
71static inline int atl_read(struct dra7_atl_clock_info *cinfo, u32 reg)
72{
73 return __raw_readl(cinfo->iobase + reg);
74}
75
76static int atl_clk_enable(struct clk_hw *hw)
77{
78 struct dra7_atl_desc *cdesc = to_atl_desc(hw);
79
80 if (!cdesc->probed)
81 goto out;
82
83 if (unlikely(!cdesc->valid))
84 dev_warn(cdesc->cinfo->dev, "atl%d has not been configured\n",
85 cdesc->id);
86 pm_runtime_get_sync(cdesc->cinfo->dev);
87
88 atl_write(cdesc->cinfo, DRA7_ATL_ATLCR_REG(cdesc->id),
89 cdesc->divider - 1);
90 atl_write(cdesc->cinfo, DRA7_ATL_SWEN_REG(cdesc->id), DRA7_ATL_SWEN);
91
92out:
93 cdesc->enabled = true;
94
95 return 0;
96}
97
98static void atl_clk_disable(struct clk_hw *hw)
99{
100 struct dra7_atl_desc *cdesc = to_atl_desc(hw);
101
102 if (!cdesc->probed)
103 goto out;
104
105 atl_write(cdesc->cinfo, DRA7_ATL_SWEN_REG(cdesc->id), 0);
106 pm_runtime_put_sync(cdesc->cinfo->dev);
107
108out:
109 cdesc->enabled = false;
110}
111
112static int atl_clk_is_enabled(struct clk_hw *hw)
113{
114 struct dra7_atl_desc *cdesc = to_atl_desc(hw);
115
116 return cdesc->enabled;
117}
118
119static unsigned long atl_clk_recalc_rate(struct clk_hw *hw,
120 unsigned long parent_rate)
121{
122 struct dra7_atl_desc *cdesc = to_atl_desc(hw);
123
124 return parent_rate / cdesc->divider;
125}
126
127static long atl_clk_round_rate(struct clk_hw *hw, unsigned long rate,
128 unsigned long *parent_rate)
129{
130 unsigned divider;
131
132 divider = (*parent_rate + rate / 2) / rate;
133 if (divider > DRA7_ATL_DIVIDER_MASK + 1)
134 divider = DRA7_ATL_DIVIDER_MASK + 1;
135
136 return *parent_rate / divider;
137}
138
139static int atl_clk_set_rate(struct clk_hw *hw, unsigned long rate,
140 unsigned long parent_rate)
141{
142 struct dra7_atl_desc *cdesc = to_atl_desc(hw);
143 u32 divider;
144
145 divider = ((parent_rate + rate / 2) / rate) - 1;
146 if (divider > DRA7_ATL_DIVIDER_MASK)
147 divider = DRA7_ATL_DIVIDER_MASK;
148
149 cdesc->divider = divider + 1;
150
151 return 0;
152}
153
154const struct clk_ops atl_clk_ops = {
155 .enable = atl_clk_enable,
156 .disable = atl_clk_disable,
157 .is_enabled = atl_clk_is_enabled,
158 .recalc_rate = atl_clk_recalc_rate,
159 .round_rate = atl_clk_round_rate,
160 .set_rate = atl_clk_set_rate,
161};
162
163static void __init of_dra7_atl_clock_setup(struct device_node *node)
164{
165 struct dra7_atl_desc *clk_hw = NULL;
166 struct clk_init_data init = { 0 };
167 const char **parent_names = NULL;
168 struct clk *clk;
169
170 clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
171 if (!clk_hw) {
172 pr_err("%s: could not allocate dra7_atl_desc\n", __func__);
173 return;
174 }
175
176 clk_hw->hw.init = &init;
177 clk_hw->divider = 1;
178 init.name = node->name;
179 init.ops = &atl_clk_ops;
180 init.flags = CLK_IGNORE_UNUSED;
181 init.num_parents = of_clk_get_parent_count(node);
182
183 if (init.num_parents != 1) {
184 pr_err("%s: atl clock %s must have 1 parent\n", __func__,
185 node->name);
186 goto cleanup;
187 }
188
189 parent_names = kzalloc(sizeof(char *), GFP_KERNEL);
190
191 if (!parent_names)
192 goto cleanup;
193
194 parent_names[0] = of_clk_get_parent_name(node, 0);
195
196 init.parent_names = parent_names;
197
198 clk = clk_register(NULL, &clk_hw->hw);
199
200 if (!IS_ERR(clk)) {
201 of_clk_add_provider(node, of_clk_src_simple_get, clk);
202 return;
203 }
204cleanup:
205 kfree(parent_names);
206 kfree(clk_hw);
207}
208CLK_OF_DECLARE(dra7_atl_clock, "ti,dra7-atl-clock", of_dra7_atl_clock_setup);
209
210static int of_dra7_atl_clk_probe(struct platform_device *pdev)
211{
212 struct device_node *node = pdev->dev.of_node;
213 struct dra7_atl_clock_info *cinfo;
214 int i;
215 int ret = 0;
216
217 if (!node)
218 return -ENODEV;
219
220 cinfo = devm_kzalloc(&pdev->dev, sizeof(*cinfo), GFP_KERNEL);
221 if (!cinfo)
222 return -ENOMEM;
223
224 cinfo->iobase = of_iomap(node, 0);
225 cinfo->dev = &pdev->dev;
226 pm_runtime_enable(cinfo->dev);
227
228 pm_runtime_get_sync(cinfo->dev);
229 atl_write(cinfo, DRA7_ATL_PCLKMUX_REG(0), DRA7_ATL_PCLKMUX);
230
231 for (i = 0; i < DRA7_ATL_INSTANCES; i++) {
232 struct device_node *cfg_node;
233 char prop[5];
234 struct dra7_atl_desc *cdesc;
235 struct of_phandle_args clkspec;
236 struct clk *clk;
237 int rc;
238
239 rc = of_parse_phandle_with_args(node, "ti,provided-clocks",
240 NULL, i, &clkspec);
241
242 if (rc) {
243 pr_err("%s: failed to lookup atl clock %d\n", __func__,
244 i);
245 return -EINVAL;
246 }
247
248 clk = of_clk_get_from_provider(&clkspec);
249
250 cdesc = to_atl_desc(__clk_get_hw(clk));
251 cdesc->cinfo = cinfo;
252 cdesc->id = i;
253
254 /* Get configuration for the ATL instances */
255 snprintf(prop, sizeof(prop), "atl%u", i);
256 cfg_node = of_find_node_by_name(node, prop);
257 if (cfg_node) {
258 ret = of_property_read_u32(cfg_node, "bws",
259 &cdesc->bws);
260 ret |= of_property_read_u32(cfg_node, "aws",
261 &cdesc->aws);
262 if (!ret) {
263 cdesc->valid = true;
264 atl_write(cinfo, DRA7_ATL_BWSMUX_REG(i),
265 cdesc->bws);
266 atl_write(cinfo, DRA7_ATL_AWSMUX_REG(i),
267 cdesc->aws);
268 }
269 }
270
271 cdesc->probed = true;
272 /*
273 * Enable the clock if it has been asked prior to loading the
274 * hw driver
275 */
276 if (cdesc->enabled)
277 atl_clk_enable(__clk_get_hw(clk));
278 }
279 pm_runtime_put_sync(cinfo->dev);
280
281 return ret;
282}
283
284static int of_dra7_atl_clk_remove(struct platform_device *pdev)
285{
286 pm_runtime_disable(&pdev->dev);
287
288 return 0;
289}
290
291static struct of_device_id of_dra7_atl_clk_match_tbl[] = {
292 { .compatible = "ti,dra7-atl", },
293 {},
294};
295MODULE_DEVICE_TABLE(of, of_dra7_atl_clk_match_tbl);
296
297static struct platform_driver dra7_atl_clk_driver = {
298 .driver = {
299 .name = "dra7-atl",
300 .owner = THIS_MODULE,
301 .of_match_table = of_dra7_atl_clk_match_tbl,
302 },
303 .probe = of_dra7_atl_clk_probe,
304 .remove = of_dra7_atl_clk_remove,
305};
306
307module_platform_driver(dra7_atl_clk_driver);
308
309MODULE_DESCRIPTION("Clock driver for DRA7 Audio Tracking Logic");
310MODULE_ALIAS("platform:dra7-atl-clock");
311MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
312MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
index 7e498a44f97d..abd956d5f838 100644
--- a/drivers/clk/ti/dpll.c
+++ b/drivers/clk/ti/dpll.c
@@ -25,8 +25,6 @@
25#undef pr_fmt 25#undef pr_fmt
26#define pr_fmt(fmt) "%s: " fmt, __func__ 26#define pr_fmt(fmt) "%s: " fmt, __func__
27 27
28#define DPLL_HAS_AUTOIDLE 0x1
29
30#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \ 28#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
31 defined(CONFIG_SOC_DRA7XX) 29 defined(CONFIG_SOC_DRA7XX)
32static const struct clk_ops dpll_m4xen_ck_ops = { 30static const struct clk_ops dpll_m4xen_ck_ops = {
@@ -37,21 +35,18 @@ static const struct clk_ops dpll_m4xen_ck_ops = {
37 .set_rate = &omap3_noncore_dpll_set_rate, 35 .set_rate = &omap3_noncore_dpll_set_rate,
38 .get_parent = &omap2_init_dpll_parent, 36 .get_parent = &omap2_init_dpll_parent,
39}; 37};
38#else
39static const struct clk_ops dpll_m4xen_ck_ops = {};
40#endif 40#endif
41 41
42#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) || \
43 defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX) || \
44 defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX)
42static const struct clk_ops dpll_core_ck_ops = { 45static const struct clk_ops dpll_core_ck_ops = {
43 .recalc_rate = &omap3_dpll_recalc, 46 .recalc_rate = &omap3_dpll_recalc,
44 .get_parent = &omap2_init_dpll_parent, 47 .get_parent = &omap2_init_dpll_parent,
45}; 48};
46 49
47#ifdef CONFIG_ARCH_OMAP3
48static const struct clk_ops omap3_dpll_core_ck_ops = {
49 .get_parent = &omap2_init_dpll_parent,
50 .recalc_rate = &omap3_dpll_recalc,
51 .round_rate = &omap2_dpll_round_rate,
52};
53#endif
54
55static const struct clk_ops dpll_ck_ops = { 50static const struct clk_ops dpll_ck_ops = {
56 .enable = &omap3_noncore_dpll_enable, 51 .enable = &omap3_noncore_dpll_enable,
57 .disable = &omap3_noncore_dpll_disable, 52 .disable = &omap3_noncore_dpll_disable,
@@ -67,6 +62,33 @@ static const struct clk_ops dpll_no_gate_ck_ops = {
67 .round_rate = &omap2_dpll_round_rate, 62 .round_rate = &omap2_dpll_round_rate,
68 .set_rate = &omap3_noncore_dpll_set_rate, 63 .set_rate = &omap3_noncore_dpll_set_rate,
69}; 64};
65#else
66static const struct clk_ops dpll_core_ck_ops = {};
67static const struct clk_ops dpll_ck_ops = {};
68static const struct clk_ops dpll_no_gate_ck_ops = {};
69const struct clk_hw_omap_ops clkhwops_omap3_dpll = {};
70#endif
71
72#ifdef CONFIG_ARCH_OMAP2
73static const struct clk_ops omap2_dpll_core_ck_ops = {
74 .get_parent = &omap2_init_dpll_parent,
75 .recalc_rate = &omap2_dpllcore_recalc,
76 .round_rate = &omap2_dpll_round_rate,
77 .set_rate = &omap2_reprogram_dpllcore,
78};
79#else
80static const struct clk_ops omap2_dpll_core_ck_ops = {};
81#endif
82
83#ifdef CONFIG_ARCH_OMAP3
84static const struct clk_ops omap3_dpll_core_ck_ops = {
85 .get_parent = &omap2_init_dpll_parent,
86 .recalc_rate = &omap3_dpll_recalc,
87 .round_rate = &omap2_dpll_round_rate,
88};
89#else
90static const struct clk_ops omap3_dpll_core_ck_ops = {};
91#endif
70 92
71#ifdef CONFIG_ARCH_OMAP3 93#ifdef CONFIG_ARCH_OMAP3
72static const struct clk_ops omap3_dpll_ck_ops = { 94static const struct clk_ops omap3_dpll_ck_ops = {
@@ -193,14 +215,12 @@ static void ti_clk_register_dpll_x2(struct device_node *node,
193 * @node: device node containing the DPLL info 215 * @node: device node containing the DPLL info
194 * @ops: ops for the DPLL 216 * @ops: ops for the DPLL
195 * @ddt: DPLL data template to use 217 * @ddt: DPLL data template to use
196 * @init_flags: flags for controlling init types
197 * 218 *
198 * Initializes a DPLL clock from device tree data. 219 * Initializes a DPLL clock from device tree data.
199 */ 220 */
200static void __init of_ti_dpll_setup(struct device_node *node, 221static void __init of_ti_dpll_setup(struct device_node *node,
201 const struct clk_ops *ops, 222 const struct clk_ops *ops,
202 const struct dpll_data *ddt, 223 const struct dpll_data *ddt)
203 u8 init_flags)
204{ 224{
205 struct clk_hw_omap *clk_hw = NULL; 225 struct clk_hw_omap *clk_hw = NULL;
206 struct clk_init_data *init = NULL; 226 struct clk_init_data *init = NULL;
@@ -241,13 +261,30 @@ static void __init of_ti_dpll_setup(struct device_node *node,
241 init->parent_names = parent_names; 261 init->parent_names = parent_names;
242 262
243 dd->control_reg = ti_clk_get_reg_addr(node, 0); 263 dd->control_reg = ti_clk_get_reg_addr(node, 0);
244 dd->idlest_reg = ti_clk_get_reg_addr(node, 1);
245 dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2);
246 264
247 if (!dd->control_reg || !dd->idlest_reg || !dd->mult_div1_reg) 265 /*
266 * Special case for OMAP2 DPLL, register order is different due to
267 * missing idlest_reg, also clkhwops is different. Detected from
268 * missing idlest_mask.
269 */
270 if (!dd->idlest_mask) {
271 dd->mult_div1_reg = ti_clk_get_reg_addr(node, 1);
272#ifdef CONFIG_ARCH_OMAP2
273 clk_hw->ops = &clkhwops_omap2xxx_dpll;
274 omap2xxx_clkt_dpllcore_init(&clk_hw->hw);
275#endif
276 } else {
277 dd->idlest_reg = ti_clk_get_reg_addr(node, 1);
278 if (!dd->idlest_reg)
279 goto cleanup;
280
281 dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2);
282 }
283
284 if (!dd->control_reg || !dd->mult_div1_reg)
248 goto cleanup; 285 goto cleanup;
249 286
250 if (init_flags & DPLL_HAS_AUTOIDLE) { 287 if (dd->autoidle_mask) {
251 dd->autoidle_reg = ti_clk_get_reg_addr(node, 3); 288 dd->autoidle_reg = ti_clk_get_reg_addr(node, 3);
252 if (!dd->autoidle_reg) 289 if (!dd->autoidle_reg)
253 goto cleanup; 290 goto cleanup;
@@ -310,7 +347,7 @@ static void __init of_ti_omap3_dpll_setup(struct device_node *node)
310 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 347 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
311 }; 348 };
312 349
313 of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 350 of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd);
314} 351}
315CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock", 352CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock",
316 of_ti_omap3_dpll_setup); 353 of_ti_omap3_dpll_setup);
@@ -329,7 +366,7 @@ static void __init of_ti_omap3_core_dpll_setup(struct device_node *node)
329 .freqsel_mask = 0xf0, 366 .freqsel_mask = 0xf0,
330 }; 367 };
331 368
332 of_ti_dpll_setup(node, &omap3_dpll_core_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 369 of_ti_dpll_setup(node, &omap3_dpll_core_ck_ops, &dd);
333} 370}
334CLK_OF_DECLARE(ti_omap3_core_dpll_clock, "ti,omap3-dpll-core-clock", 371CLK_OF_DECLARE(ti_omap3_core_dpll_clock, "ti,omap3-dpll-core-clock",
335 of_ti_omap3_core_dpll_setup); 372 of_ti_omap3_core_dpll_setup);
@@ -349,7 +386,7 @@ static void __init of_ti_omap3_per_dpll_setup(struct device_node *node)
349 .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), 386 .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
350 }; 387 };
351 388
352 of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 389 of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd);
353} 390}
354CLK_OF_DECLARE(ti_omap3_per_dpll_clock, "ti,omap3-dpll-per-clock", 391CLK_OF_DECLARE(ti_omap3_per_dpll_clock, "ti,omap3-dpll-per-clock",
355 of_ti_omap3_per_dpll_setup); 392 of_ti_omap3_per_dpll_setup);
@@ -371,7 +408,7 @@ static void __init of_ti_omap3_per_jtype_dpll_setup(struct device_node *node)
371 .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), 408 .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
372 }; 409 };
373 410
374 of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 411 of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd);
375} 412}
376CLK_OF_DECLARE(ti_omap3_per_jtype_dpll_clock, "ti,omap3-dpll-per-j-type-clock", 413CLK_OF_DECLARE(ti_omap3_per_jtype_dpll_clock, "ti,omap3-dpll-per-j-type-clock",
377 of_ti_omap3_per_jtype_dpll_setup); 414 of_ti_omap3_per_jtype_dpll_setup);
@@ -391,11 +428,32 @@ static void __init of_ti_omap4_dpll_setup(struct device_node *node)
391 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 428 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
392 }; 429 };
393 430
394 of_ti_dpll_setup(node, &dpll_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 431 of_ti_dpll_setup(node, &dpll_ck_ops, &dd);
395} 432}
396CLK_OF_DECLARE(ti_omap4_dpll_clock, "ti,omap4-dpll-clock", 433CLK_OF_DECLARE(ti_omap4_dpll_clock, "ti,omap4-dpll-clock",
397 of_ti_omap4_dpll_setup); 434 of_ti_omap4_dpll_setup);
398 435
436static void __init of_ti_omap5_mpu_dpll_setup(struct device_node *node)
437{
438 const struct dpll_data dd = {
439 .idlest_mask = 0x1,
440 .enable_mask = 0x7,
441 .autoidle_mask = 0x7,
442 .mult_mask = 0x7ff << 8,
443 .div1_mask = 0x7f,
444 .max_multiplier = 2047,
445 .max_divider = 128,
446 .dcc_mask = BIT(22),
447 .dcc_rate = 1400000000, /* DCC beyond 1.4GHz */
448 .min_divider = 1,
449 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
450 };
451
452 of_ti_dpll_setup(node, &dpll_ck_ops, &dd);
453}
454CLK_OF_DECLARE(of_ti_omap5_mpu_dpll_clock, "ti,omap5-mpu-dpll-clock",
455 of_ti_omap5_mpu_dpll_setup);
456
399static void __init of_ti_omap4_core_dpll_setup(struct device_node *node) 457static void __init of_ti_omap4_core_dpll_setup(struct device_node *node)
400{ 458{
401 const struct dpll_data dd = { 459 const struct dpll_data dd = {
@@ -410,7 +468,7 @@ static void __init of_ti_omap4_core_dpll_setup(struct device_node *node)
410 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 468 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
411 }; 469 };
412 470
413 of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 471 of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd);
414} 472}
415CLK_OF_DECLARE(ti_omap4_core_dpll_clock, "ti,omap4-dpll-core-clock", 473CLK_OF_DECLARE(ti_omap4_core_dpll_clock, "ti,omap4-dpll-core-clock",
416 of_ti_omap4_core_dpll_setup); 474 of_ti_omap4_core_dpll_setup);
@@ -433,7 +491,7 @@ static void __init of_ti_omap4_m4xen_dpll_setup(struct device_node *node)
433 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 491 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
434 }; 492 };
435 493
436 of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 494 of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd);
437} 495}
438CLK_OF_DECLARE(ti_omap4_m4xen_dpll_clock, "ti,omap4-dpll-m4xen-clock", 496CLK_OF_DECLARE(ti_omap4_m4xen_dpll_clock, "ti,omap4-dpll-m4xen-clock",
439 of_ti_omap4_m4xen_dpll_setup); 497 of_ti_omap4_m4xen_dpll_setup);
@@ -454,7 +512,7 @@ static void __init of_ti_omap4_jtype_dpll_setup(struct device_node *node)
454 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 512 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
455 }; 513 };
456 514
457 of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd, DPLL_HAS_AUTOIDLE); 515 of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd);
458} 516}
459CLK_OF_DECLARE(ti_omap4_jtype_dpll_clock, "ti,omap4-dpll-j-type-clock", 517CLK_OF_DECLARE(ti_omap4_jtype_dpll_clock, "ti,omap4-dpll-j-type-clock",
460 of_ti_omap4_jtype_dpll_setup); 518 of_ti_omap4_jtype_dpll_setup);
@@ -465,7 +523,6 @@ static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node)
465 const struct dpll_data dd = { 523 const struct dpll_data dd = {
466 .idlest_mask = 0x1, 524 .idlest_mask = 0x1,
467 .enable_mask = 0x7, 525 .enable_mask = 0x7,
468 .autoidle_mask = 0x7,
469 .mult_mask = 0x7ff << 8, 526 .mult_mask = 0x7ff << 8,
470 .div1_mask = 0x7f, 527 .div1_mask = 0x7f,
471 .max_multiplier = 2047, 528 .max_multiplier = 2047,
@@ -474,7 +531,7 @@ static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node)
474 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 531 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
475 }; 532 };
476 533
477 of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd, 0); 534 of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd);
478} 535}
479CLK_OF_DECLARE(ti_am3_no_gate_dpll_clock, "ti,am3-dpll-no-gate-clock", 536CLK_OF_DECLARE(ti_am3_no_gate_dpll_clock, "ti,am3-dpll-no-gate-clock",
480 of_ti_am3_no_gate_dpll_setup); 537 of_ti_am3_no_gate_dpll_setup);
@@ -484,7 +541,6 @@ static void __init of_ti_am3_jtype_dpll_setup(struct device_node *node)
484 const struct dpll_data dd = { 541 const struct dpll_data dd = {
485 .idlest_mask = 0x1, 542 .idlest_mask = 0x1,
486 .enable_mask = 0x7, 543 .enable_mask = 0x7,
487 .autoidle_mask = 0x7,
488 .mult_mask = 0x7ff << 8, 544 .mult_mask = 0x7ff << 8,
489 .div1_mask = 0x7f, 545 .div1_mask = 0x7f,
490 .max_multiplier = 4095, 546 .max_multiplier = 4095,
@@ -494,7 +550,7 @@ static void __init of_ti_am3_jtype_dpll_setup(struct device_node *node)
494 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 550 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
495 }; 551 };
496 552
497 of_ti_dpll_setup(node, &dpll_ck_ops, &dd, 0); 553 of_ti_dpll_setup(node, &dpll_ck_ops, &dd);
498} 554}
499CLK_OF_DECLARE(ti_am3_jtype_dpll_clock, "ti,am3-dpll-j-type-clock", 555CLK_OF_DECLARE(ti_am3_jtype_dpll_clock, "ti,am3-dpll-j-type-clock",
500 of_ti_am3_jtype_dpll_setup); 556 of_ti_am3_jtype_dpll_setup);
@@ -504,7 +560,6 @@ static void __init of_ti_am3_no_gate_jtype_dpll_setup(struct device_node *node)
504 const struct dpll_data dd = { 560 const struct dpll_data dd = {
505 .idlest_mask = 0x1, 561 .idlest_mask = 0x1,
506 .enable_mask = 0x7, 562 .enable_mask = 0x7,
507 .autoidle_mask = 0x7,
508 .mult_mask = 0x7ff << 8, 563 .mult_mask = 0x7ff << 8,
509 .div1_mask = 0x7f, 564 .div1_mask = 0x7f,
510 .max_multiplier = 2047, 565 .max_multiplier = 2047,
@@ -514,7 +569,7 @@ static void __init of_ti_am3_no_gate_jtype_dpll_setup(struct device_node *node)
514 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 569 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
515 }; 570 };
516 571
517 of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd, 0); 572 of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd);
518} 573}
519CLK_OF_DECLARE(ti_am3_no_gate_jtype_dpll_clock, 574CLK_OF_DECLARE(ti_am3_no_gate_jtype_dpll_clock,
520 "ti,am3-dpll-no-gate-j-type-clock", 575 "ti,am3-dpll-no-gate-j-type-clock",
@@ -525,7 +580,6 @@ static void __init of_ti_am3_dpll_setup(struct device_node *node)
525 const struct dpll_data dd = { 580 const struct dpll_data dd = {
526 .idlest_mask = 0x1, 581 .idlest_mask = 0x1,
527 .enable_mask = 0x7, 582 .enable_mask = 0x7,
528 .autoidle_mask = 0x7,
529 .mult_mask = 0x7ff << 8, 583 .mult_mask = 0x7ff << 8,
530 .div1_mask = 0x7f, 584 .div1_mask = 0x7f,
531 .max_multiplier = 2047, 585 .max_multiplier = 2047,
@@ -534,7 +588,7 @@ static void __init of_ti_am3_dpll_setup(struct device_node *node)
534 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 588 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
535 }; 589 };
536 590
537 of_ti_dpll_setup(node, &dpll_ck_ops, &dd, 0); 591 of_ti_dpll_setup(node, &dpll_ck_ops, &dd);
538} 592}
539CLK_OF_DECLARE(ti_am3_dpll_clock, "ti,am3-dpll-clock", of_ti_am3_dpll_setup); 593CLK_OF_DECLARE(ti_am3_dpll_clock, "ti,am3-dpll-clock", of_ti_am3_dpll_setup);
540 594
@@ -543,7 +597,6 @@ static void __init of_ti_am3_core_dpll_setup(struct device_node *node)
543 const struct dpll_data dd = { 597 const struct dpll_data dd = {
544 .idlest_mask = 0x1, 598 .idlest_mask = 0x1,
545 .enable_mask = 0x7, 599 .enable_mask = 0x7,
546 .autoidle_mask = 0x7,
547 .mult_mask = 0x7ff << 8, 600 .mult_mask = 0x7ff << 8,
548 .div1_mask = 0x7f, 601 .div1_mask = 0x7f,
549 .max_multiplier = 2047, 602 .max_multiplier = 2047,
@@ -552,7 +605,22 @@ static void __init of_ti_am3_core_dpll_setup(struct device_node *node)
552 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), 605 .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
553 }; 606 };
554 607
555 of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd, 0); 608 of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd);
556} 609}
557CLK_OF_DECLARE(ti_am3_core_dpll_clock, "ti,am3-dpll-core-clock", 610CLK_OF_DECLARE(ti_am3_core_dpll_clock, "ti,am3-dpll-core-clock",
558 of_ti_am3_core_dpll_setup); 611 of_ti_am3_core_dpll_setup);
612
613static void __init of_ti_omap2_core_dpll_setup(struct device_node *node)
614{
615 const struct dpll_data dd = {
616 .enable_mask = 0x3,
617 .mult_mask = 0x3ff << 12,
618 .div1_mask = 0xf << 8,
619 .max_divider = 16,
620 .min_divider = 1,
621 };
622
623 of_ti_dpll_setup(node, &omap2_dpll_core_ck_ops, &dd);
624}
625CLK_OF_DECLARE(ti_omap2_core_dpll_clock, "ti,omap2-dpll-core-clock",
626 of_ti_omap2_core_dpll_setup);
diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c
index 58734817d502..b326d2797feb 100644
--- a/drivers/clk/ti/gate.c
+++ b/drivers/clk/ti/gate.c
@@ -185,7 +185,7 @@ of_ti_composite_no_wait_gate_clk_setup(struct device_node *node)
185CLK_OF_DECLARE(ti_composite_no_wait_gate_clk, "ti,composite-no-wait-gate-clock", 185CLK_OF_DECLARE(ti_composite_no_wait_gate_clk, "ti,composite-no-wait-gate-clock",
186 of_ti_composite_no_wait_gate_clk_setup); 186 of_ti_composite_no_wait_gate_clk_setup);
187 187
188#ifdef CONFIG_ARCH_OMAP3 188#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
189static void __init of_ti_composite_interface_clk_setup(struct device_node *node) 189static void __init of_ti_composite_interface_clk_setup(struct device_node *node)
190{ 190{
191 _of_ti_composite_gate_clk_setup(node, &clkhwops_iclk_wait); 191 _of_ti_composite_gate_clk_setup(node, &clkhwops_iclk_wait);
diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c
index 320a2b168bb2..9c3e8c4aaa40 100644
--- a/drivers/clk/ti/interface.c
+++ b/drivers/clk/ti/interface.c
@@ -94,6 +94,7 @@ static void __init of_ti_no_wait_interface_clk_setup(struct device_node *node)
94CLK_OF_DECLARE(ti_no_wait_interface_clk, "ti,omap3-no-wait-interface-clock", 94CLK_OF_DECLARE(ti_no_wait_interface_clk, "ti,omap3-no-wait-interface-clock",
95 of_ti_no_wait_interface_clk_setup); 95 of_ti_no_wait_interface_clk_setup);
96 96
97#ifdef CONFIG_ARCH_OMAP3
97static void __init of_ti_hsotgusb_interface_clk_setup(struct device_node *node) 98static void __init of_ti_hsotgusb_interface_clk_setup(struct device_node *node)
98{ 99{
99 _of_ti_interface_clk_setup(node, 100 _of_ti_interface_clk_setup(node,
@@ -123,3 +124,13 @@ static void __init of_ti_am35xx_interface_clk_setup(struct device_node *node)
123} 124}
124CLK_OF_DECLARE(ti_am35xx_interface_clk, "ti,am35xx-interface-clock", 125CLK_OF_DECLARE(ti_am35xx_interface_clk, "ti,am35xx-interface-clock",
125 of_ti_am35xx_interface_clk_setup); 126 of_ti_am35xx_interface_clk_setup);
127#endif
128
129#ifdef CONFIG_SOC_OMAP2430
130static void __init of_ti_omap2430_interface_clk_setup(struct device_node *node)
131{
132 _of_ti_interface_clk_setup(node, &clkhwops_omap2430_i2chs_wait);
133}
134CLK_OF_DECLARE(ti_omap2430_interface_clk, "ti,omap2430-interface-clock",
135 of_ti_omap2430_interface_clk_setup);
136#endif
diff --git a/include/dt-bindings/clk/ti-dra7-atl.h b/include/dt-bindings/clk/ti-dra7-atl.h
new file mode 100644
index 000000000000..42dd4164f6f4
--- /dev/null
+++ b/include/dt-bindings/clk/ti-dra7-atl.h
@@ -0,0 +1,40 @@
1/*
2 * This header provides constants for DRA7 ATL (Audio Tracking Logic)
3 *
4 * The constants defined in this header are used in dts files
5 *
6 * Copyright (C) 2013 Texas Instruments, Inc.
7 *
8 * Peter Ujfalusi <peter.ujfalusi@ti.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
15 * kind, whether express or implied; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#ifndef _DT_BINDINGS_CLK_DRA7_ATL_H
21#define _DT_BINDINGS_CLK_DRA7_ATL_H
22
23#define DRA7_ATL_WS_MCASP1_FSR 0
24#define DRA7_ATL_WS_MCASP1_FSX 1
25#define DRA7_ATL_WS_MCASP2_FSR 2
26#define DRA7_ATL_WS_MCASP2_FSX 3
27#define DRA7_ATL_WS_MCASP3_FSX 4
28#define DRA7_ATL_WS_MCASP4_FSX 5
29#define DRA7_ATL_WS_MCASP5_FSX 6
30#define DRA7_ATL_WS_MCASP6_FSX 7
31#define DRA7_ATL_WS_MCASP7_FSX 8
32#define DRA7_ATL_WS_MCASP8_FSX 9
33#define DRA7_ATL_WS_MCASP8_AHCLKX 10
34#define DRA7_ATL_WS_XREF_CLK3 11
35#define DRA7_ATL_WS_XREF_CLK0 12
36#define DRA7_ATL_WS_XREF_CLK1 13
37#define DRA7_ATL_WS_XREF_CLK2 14
38#define DRA7_ATL_WS_OSC1_X1 15
39
40#endif
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 4a21a872dbbd..e8d8a35034a5 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -41,6 +41,8 @@
41 * @idlest_reg: register containing the DPLL idle status bitfield 41 * @idlest_reg: register containing the DPLL idle status bitfield
42 * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg 42 * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg
43 * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg 43 * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg
44 * @dcc_mask: mask of the DPLL DCC correction bitfield @mult_div1_reg
45 * @dcc_rate: rate atleast which DCC @dcc_mask must be set
44 * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg 46 * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg
45 * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg 47 * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg
46 * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg 48 * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg
@@ -86,6 +88,8 @@ struct dpll_data {
86 u32 idlest_mask; 88 u32 idlest_mask;
87 u32 dco_mask; 89 u32 dco_mask;
88 u32 sddiv_mask; 90 u32 sddiv_mask;
91 u32 dcc_mask;
92 unsigned long dcc_rate;
89 u32 lpmode_mask; 93 u32 lpmode_mask;
90 u32 m4xen_mask; 94 u32 m4xen_mask;
91 u8 auto_recal_bit; 95 u8 auto_recal_bit;
@@ -94,7 +98,26 @@ struct dpll_data {
94 u8 flags; 98 u8 flags;
95}; 99};
96 100
97struct clk_hw_omap_ops; 101struct clk_hw_omap;
102
103/**
104 * struct clk_hw_omap_ops - OMAP clk ops
105 * @find_idlest: find idlest register information for a clock
106 * @find_companion: find companion clock register information for a clock,
107 * basically converts CM_ICLKEN* <-> CM_FCLKEN*
108 * @allow_idle: enables autoidle hardware functionality for a clock
109 * @deny_idle: prevent autoidle hardware functionality for a clock
110 */
111struct clk_hw_omap_ops {
112 void (*find_idlest)(struct clk_hw_omap *oclk,
113 void __iomem **idlest_reg,
114 u8 *idlest_bit, u8 *idlest_val);
115 void (*find_companion)(struct clk_hw_omap *oclk,
116 void __iomem **other_reg,
117 u8 *other_bit);
118 void (*allow_idle)(struct clk_hw_omap *oclk);
119 void (*deny_idle)(struct clk_hw_omap *oclk);
120};
98 121
99/** 122/**
100 * struct clk_hw_omap - OMAP struct clk 123 * struct clk_hw_omap - OMAP struct clk
@@ -259,6 +282,12 @@ int omap2_dflt_clk_enable(struct clk_hw *hw);
259void omap2_dflt_clk_disable(struct clk_hw *hw); 282void omap2_dflt_clk_disable(struct clk_hw *hw);
260int omap2_dflt_clk_is_enabled(struct clk_hw *hw); 283int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
261void omap3_clk_lock_dpll5(void); 284void omap3_clk_lock_dpll5(void);
285unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
286 unsigned long parent_rate);
287int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate,
288 unsigned long parent_rate);
289void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw);
290void omap2xxx_clkt_vps_init(void);
262 291
263void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index); 292void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
264void ti_dt_clocks_register(struct ti_dt_clk *oclks); 293void ti_dt_clocks_register(struct ti_dt_clk *oclks);
@@ -278,6 +307,8 @@ int omap5xxx_dt_clk_init(void);
278int dra7xx_dt_clk_init(void); 307int dra7xx_dt_clk_init(void);
279int am33xx_dt_clk_init(void); 308int am33xx_dt_clk_init(void);
280int am43xx_dt_clk_init(void); 309int am43xx_dt_clk_init(void);
310int omap2420_dt_clk_init(void);
311int omap2430_dt_clk_init(void);
281 312
282#ifdef CONFIG_OF 313#ifdef CONFIG_OF
283void of_ti_clk_allow_autoidle_all(void); 314void of_ti_clk_allow_autoidle_all(void);
@@ -287,6 +318,8 @@ static inline void of_ti_clk_allow_autoidle_all(void) { }
287static inline void of_ti_clk_deny_autoidle_all(void) { } 318static inline void of_ti_clk_deny_autoidle_all(void) { }
288#endif 319#endif
289 320
321extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
322extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
290extern const struct clk_hw_omap_ops clkhwops_omap3_dpll; 323extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
291extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx; 324extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
292extern const struct clk_hw_omap_ops clkhwops_wait; 325extern const struct clk_hw_omap_ops clkhwops_wait;