aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2012-11-20 17:06:52 -0500
committerThomas Petazzoni <thomas.petazzoni@free-electrons.com>2012-11-20 17:06:52 -0500
commitae24db86d4ab06e2b859c202c81837a06a24fe09 (patch)
treed8fdd2f1f9b7df6b6e3543af6435b7d11f5da45e
parentf4a75d2eb7b1e2206094b901be09adb31ba63681 (diff)
parent1611f872513735ac7105535689c0dd668fbf1c04 (diff)
Merge tag 'marvell-mvebu-clk-3.8' of github.com:MISL-EBU-System-SW/mainline-public into test-the-merge
Marvell MVEBU clk support, for 3.8
-rw-r--r--Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt1
-rw-r--r--Documentation/devicetree/bindings/clock/mvebu-core-clock.txt47
-rw-r--r--Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt21
-rw-r--r--Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt119
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/boot/dts/armada-370-db.dts4
-rw-r--r--arch/arm/boot/dts/armada-370-xp.dtsi1
-rw-r--r--arch/arm/boot/dts/armada-370.dtsi15
-rw-r--r--arch/arm/boot/dts/armada-xp-mv78230.dtsi12
-rw-r--r--arch/arm/boot/dts/armada-xp-mv78260.dtsi19
-rw-r--r--arch/arm/boot/dts/armada-xp-mv78460.dtsi34
-rw-r--r--arch/arm/boot/dts/armada-xp.dtsi20
-rw-r--r--arch/arm/boot/dts/dove.dtsi20
-rw-r--r--arch/arm/boot/dts/kirkwood.dtsi22
-rw-r--r--arch/arm/mach-dove/Kconfig2
-rw-r--r--arch/arm/mach-dove/common.c63
-rw-r--r--arch/arm/mach-kirkwood/Kconfig2
-rw-r--r--arch/arm/mach-kirkwood/board-dt.c71
-rw-r--r--arch/arm/mach-mvebu/Kconfig4
-rw-r--r--arch/arm/mach-mvebu/armada-370-xp.c9
-rw-r--r--arch/arm/plat-orion/include/plat/common.h1
-rw-r--r--drivers/clk/Kconfig2
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/mvebu/Kconfig8
-rw-r--r--drivers/clk/mvebu/Makefile3
-rw-r--r--drivers/clk/mvebu/clk-core.c675
-rw-r--r--drivers/clk/mvebu/clk-core.h18
-rw-r--r--drivers/clk/mvebu/clk-cpu.c186
-rw-r--r--drivers/clk/mvebu/clk-cpu.h22
-rw-r--r--drivers/clk/mvebu/clk-gating-ctrl.c249
-rw-r--r--drivers/clk/mvebu/clk-gating-ctrl.h22
-rw-r--r--drivers/clk/mvebu/clk.c27
-rw-r--r--drivers/clocksource/time-armada-370-xp.c11
-rw-r--r--include/linux/clk/mvebu.h22
34 files changed, 1696 insertions, 38 deletions
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt
index 8b6ea2267c94..64830118b013 100644
--- a/Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt
+++ b/Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt
@@ -5,6 +5,7 @@ Required properties:
5- compatible: Should be "marvell,armada-370-xp-timer" 5- compatible: Should be "marvell,armada-370-xp-timer"
6- interrupts: Should contain the list of Global Timer interrupts 6- interrupts: Should contain the list of Global Timer interrupts
7- reg: Should contain the base address of the Global Timer registers 7- reg: Should contain the base address of the Global Timer registers
8- clocks: clock driving the timer hardware
8 9
9Optional properties: 10Optional properties:
10- marvell,timer-25Mhz: Tells whether the Global timer supports the 25 11- marvell,timer-25Mhz: Tells whether the Global timer supports the 25
diff --git a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
new file mode 100644
index 000000000000..1e662948661e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
@@ -0,0 +1,47 @@
1* Core Clock bindings for Marvell MVEBU SoCs
2
3Marvell MVEBU SoCs usually allow to determine core clock frequencies by
4reading the Sample-At-Reset (SAR) register. The core clock consumer should
5specify the desired clock by having the clock ID in its "clocks" phandle cell.
6
7The following is a list of provided IDs and clock names on Armada 370/XP:
8 0 = tclk (Internal Bus clock)
9 1 = cpuclk (CPU clock)
10 2 = nbclk (L2 Cache clock)
11 3 = hclk (DRAM control clock)
12 4 = dramclk (DDR clock)
13
14The following is a list of provided IDs and clock names on Kirkwood and Dove:
15 0 = tclk (Internal Bus clock)
16 1 = cpuclk (CPU0 clock)
17 2 = l2clk (L2 Cache clock derived from CPU0 clock)
18 3 = ddrclk (DDR controller clock derived from CPU0 clock)
19
20Required properties:
21- compatible : shall be one of the following:
22 "marvell,armada-370-core-clock" - For Armada 370 SoC core clocks
23 "marvell,armada-xp-core-clock" - For Armada XP SoC core clocks
24 "marvell,dove-core-clock" - for Dove SoC core clocks
25 "marvell,kirkwood-core-clock" - for Kirkwood SoC (except mv88f6180)
26 "marvell,mv88f6180-core-clock" - for Kirkwood MV88f6180 SoC
27- reg : shall be the register address of the Sample-At-Reset (SAR) register
28- #clock-cells : from common clock binding; shall be set to 1
29
30Optional properties:
31- clock-output-names : from common clock binding; allows overwrite default clock
32 output names ("tclk", "cpuclk", "l2clk", "ddrclk")
33
34Example:
35
36core_clk: core-clocks@d0214 {
37 compatible = "marvell,dove-core-clock";
38 reg = <0xd0214 0x4>;
39 #clock-cells = <1>;
40};
41
42spi0: spi@10600 {
43 compatible = "marvell,orion-spi";
44 /* ... */
45 /* get tclk from core clock provider */
46 clocks = <&core_clk 0>;
47};
diff --git a/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt
new file mode 100644
index 000000000000..feb830130714
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt
@@ -0,0 +1,21 @@
1Device Tree Clock bindings for cpu clock of Marvell EBU platforms
2
3Required properties:
4- compatible : shall be one of the following:
5 "marvell,armada-xp-cpu-clock" - cpu clocks for Armada XP
6- reg : Address and length of the clock complex register set
7- #clock-cells : should be set to 1.
8- clocks : shall be the input parent clock phandle for the clock.
9
10cpuclk: clock-complex@d0018700 {
11 #clock-cells = <1>;
12 compatible = "marvell,armada-xp-cpu-clock";
13 reg = <0xd0018700 0xA0>;
14 clocks = <&coreclk 1>;
15}
16
17cpu@0 {
18 compatible = "marvell,sheeva-v7";
19 reg = <0>;
20 clocks = <&cpuclk 0>;
21};
diff --git a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
new file mode 100644
index 000000000000..7337005ef5e1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
@@ -0,0 +1,119 @@
1* Gated Clock bindings for Marvell Orion SoCs
2
3Marvell Dove and Kirkwood allow some peripheral clocks to be gated to save
4some power. The clock consumer should specify the desired clock by having
5the clock ID in its "clocks" phandle cell. The clock ID is directly mapped to
6the corresponding clock gating control bit in HW to ease manual clock lookup
7in datasheet.
8
9The following is a list of provided IDs for Armada 370:
10ID Clock Peripheral
11-----------------------------------
120 Audio AC97 Cntrl
131 pex0_en PCIe 0 Clock out
142 pex1_en PCIe 1 Clock out
153 ge1 Gigabit Ethernet 1
164 ge0 Gigabit Ethernet 0
175 pex0 PCIe Cntrl 0
189 pex1 PCIe Cntrl 1
1915 sata0 SATA Host 0
2017 sdio SDHCI Host
2125 tdm Time Division Mplx
2228 ddr DDR Cntrl
2330 sata1 SATA Host 0
24
25The following is a list of provided IDs for Armada XP:
26ID Clock Peripheral
27-----------------------------------
280 audio Audio Cntrl
291 ge3 Gigabit Ethernet 3
302 ge2 Gigabit Ethernet 2
313 ge1 Gigabit Ethernet 1
324 ge0 Gigabit Ethernet 0
335 pex0 PCIe Cntrl 0
346 pex1 PCIe Cntrl 1
357 pex2 PCIe Cntrl 2
368 pex3 PCIe Cntrl 3
3713 bp
3814 sata0lnk
3915 sata0 SATA Host 0
4016 lcd LCD Cntrl
4117 sdio SDHCI Host
4218 usb0 USB Host 0
4319 usb1 USB Host 1
4420 usb2 USB Host 2
4522 xor0 XOR DMA 0
4623 crypto CESA engine
4725 tdm Time Division Mplx
4828 xor1 XOR DMA 1
4929 sata1lnk
5030 sata1 SATA Host 0
51
52The following is a list of provided IDs for Dove:
53ID Clock Peripheral
54-----------------------------------
550 usb0 USB Host 0
561 usb1 USB Host 1
572 ge Gigabit Ethernet
583 sata SATA Host
594 pex0 PCIe Cntrl 0
605 pex1 PCIe Cntrl 1
618 sdio0 SDHCI Host 0
629 sdio1 SDHCI Host 1
6310 nand NAND Cntrl
6411 camera Camera Cntrl
6512 i2s0 I2S Cntrl 0
6613 i2s1 I2S Cntrl 1
6715 crypto CESA engine
6821 ac97 AC97 Cntrl
6922 pdma Peripheral DMA
7023 xor0 XOR DMA 0
7124 xor1 XOR DMA 1
7230 gephy Gigabit Ethernel PHY
73Note: gephy(30) is implemented as a parent clock of ge(2)
74
75The following is a list of provided IDs for Kirkwood:
76ID Clock Peripheral
77-----------------------------------
780 ge0 Gigabit Ethernet 0
792 pex0 PCIe Cntrl 0
803 usb0 USB Host 0
814 sdio SDIO Cntrl
825 tsu Transp. Stream Unit
836 dunit SDRAM Cntrl
847 runit Runit
858 xor0 XOR DMA 0
869 audio I2S Cntrl 0
8714 sata0 SATA Host 0
8815 sata1 SATA Host 1
8916 xor1 XOR DMA 1
9017 crypto CESA engine
9118 pex1 PCIe Cntrl 1
9219 ge1 Gigabit Ethernet 0
9320 tdm Time Division Mplx
94
95Required properties:
96- compatible : shall be one of the following:
97 "marvell,dove-gating-clock" - for Dove SoC clock gating
98 "marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating
99- reg : shall be the register address of the Clock Gating Control register
100- #clock-cells : from common clock binding; shall be set to 1
101
102Optional properties:
103- clocks : default parent clock phandle (e.g. tclk)
104
105Example:
106
107gate_clk: clock-gating-control@d0038 {
108 compatible = "marvell,dove-gating-clock";
109 reg = <0xd0038 0x4>;
110 /* default parent clock is tclk */
111 clocks = <&core_clk 0>;
112 #clock-cells = <1>;
113};
114
115sdio0: sdio@92000 {
116 compatible = "marvell,dove-sdhci";
117 /* get clk gate bit 8 (sdio0) */
118 clocks = <&gate_clk 8>;
119};
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ade7e924bef5..05900997af90 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -533,6 +533,7 @@ config ARCH_IXP4XX
533config ARCH_DOVE 533config ARCH_DOVE
534 bool "Marvell Dove" 534 bool "Marvell Dove"
535 select ARCH_REQUIRE_GPIOLIB 535 select ARCH_REQUIRE_GPIOLIB
536 select COMMON_CLK_DOVE
536 select CPU_V7 537 select CPU_V7
537 select GENERIC_CLOCKEVENTS 538 select GENERIC_CLOCKEVENTS
538 select MIGHT_HAVE_PCI 539 select MIGHT_HAVE_PCI
diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts
index fffd5c2a3041..4a31b0396623 100644
--- a/arch/arm/boot/dts/armada-370-db.dts
+++ b/arch/arm/boot/dts/armada-370-db.dts
@@ -34,9 +34,5 @@
34 clock-frequency = <200000000>; 34 clock-frequency = <200000000>;
35 status = "okay"; 35 status = "okay";
36 }; 36 };
37 timer@d0020300 {
38 clock-frequency = <600000000>;
39 status = "okay";
40 };
41 }; 37 };
42}; 38};
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index 16cc82cdaa81..94b4b9e03571 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -62,6 +62,7 @@
62 compatible = "marvell,armada-370-xp-timer"; 62 compatible = "marvell,armada-370-xp-timer";
63 reg = <0xd0020300 0x30>; 63 reg = <0xd0020300 0x30>;
64 interrupts = <37>, <38>, <39>, <40>; 64 interrupts = <37>, <38>, <39>, <40>;
65 clocks = <&coreclk 2>;
65 }; 66 };
66 67
67 addr-decoding@d0020000 { 68 addr-decoding@d0020000 {
diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
index 2069151afe01..175df2887076 100644
--- a/arch/arm/boot/dts/armada-370.dtsi
+++ b/arch/arm/boot/dts/armada-370.dtsi
@@ -75,5 +75,20 @@
75 #interrupts-cells = <2>; 75 #interrupts-cells = <2>;
76 interrupts = <91>; 76 interrupts = <91>;
77 }; 77 };
78
79 coreclk: mvebu-sar@d0018230 {
80 compatible = "marvell,armada-370-core-clock";
81 reg = <0xd0018230 0x08>;
82 #clock-cells = <1>;
83 };
84
85 gateclk: clock-gating-control@d0018220 {
86 compatible = "marvell,armada-370-gating-clock";
87 reg = <0xd0018220 0x4>;
88 clocks = <&coreclk 0>;
89 #clock-cells = <1>;
90 };
91
92
78 }; 93 };
79}; 94};
diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
index ea355192be6f..c45c7b4dc352 100644
--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
@@ -24,6 +24,18 @@
24 gpio1 = &gpio1; 24 gpio1 = &gpio1;
25 }; 25 };
26 26
27 cpus {
28 #address-cells = <1>;
29 #size-cells = <0>;
30
31 cpu@0 {
32 device_type = "cpu";
33 compatible = "marvell,sheeva-v7";
34 reg = <0>;
35 clocks = <&cpuclk 0>;
36 };
37 }
38
27 soc { 39 soc {
28 pinctrl { 40 pinctrl {
29 compatible = "marvell,mv78230-pinctrl"; 41 compatible = "marvell,mv78230-pinctrl";
diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
index 2057863f3dfa..a2aee5707377 100644
--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
@@ -25,6 +25,25 @@
25 gpio2 = &gpio2; 25 gpio2 = &gpio2;
26 }; 26 };
27 27
28 cpus {
29 #address-cells = <1>;
30 #size-cells = <0>;
31
32 cpu@0 {
33 device_type = "cpu";
34 compatible = "marvell,sheeva-v7";
35 reg = <0>;
36 clocks = <&cpuclk 0>;
37 };
38
39 cpu@1 {
40 device_type = "cpu";
41 compatible = "marvell,sheeva-v7";
42 reg = <1>;
43 clocks = <&cpuclk 1>;
44 };
45 };
46
28 soc { 47 soc {
29 pinctrl { 48 pinctrl {
30 compatible = "marvell,mv78260-pinctrl"; 49 compatible = "marvell,mv78260-pinctrl";
diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
index ffac98373792..da03a129243a 100644
--- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
@@ -25,6 +25,40 @@
25 gpio2 = &gpio2; 25 gpio2 = &gpio2;
26 }; 26 };
27 27
28
29 cpus {
30 #address-cells = <1>;
31 #size-cells = <0>;
32
33 cpu@0 {
34 device_type = "cpu";
35 compatible = "marvell,sheeva-v7";
36 reg = <0>;
37 clocks = <&cpuclk 0>;
38 };
39
40 cpu@1 {
41 device_type = "cpu";
42 compatible = "marvell,sheeva-v7";
43 reg = <1>;
44 clocks = <&cpuclk 1>;
45 };
46
47 cpu@2 {
48 device_type = "cpu";
49 compatible = "marvell,sheeva-v7";
50 reg = <2>;
51 clocks = <&cpuclk 2>;
52 };
53
54 cpu@3 {
55 device_type = "cpu";
56 compatible = "marvell,sheeva-v7";
57 reg = <3>;
58 clocks = <&cpuclk 3>;
59 };
60 };
61
28 soc { 62 soc {
29 pinctrl { 63 pinctrl {
30 compatible = "marvell,mv78460-pinctrl"; 64 compatible = "marvell,mv78460-pinctrl";
diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi
index 71d6b5d0daf1..f51554e80009 100644
--- a/arch/arm/boot/dts/armada-xp.dtsi
+++ b/arch/arm/boot/dts/armada-xp.dtsi
@@ -47,6 +47,26 @@
47 marvell,timer-25Mhz; 47 marvell,timer-25Mhz;
48 }; 48 };
49 49
50 coreclk: mvebu-sar@d0018230 {
51 compatible = "marvell,armada-xp-core-clock";
52 reg = <0xd0018230 0x08>;
53 #clock-cells = <1>;
54 };
55
56 cpuclk: clock-complex@d0018700 {
57 #clock-cells = <1>;
58 compatible = "marvell,armada-xp-cpu-clock";
59 reg = <0xd0018700 0xA0>;
60 clocks = <&coreclk 1>;
61 };
62
63 gateclk: clock-gating-control@d0018220 {
64 compatible = "marvell,armada-xp-gating-clock";
65 reg = <0xd0018220 0x4>;
66 clocks = <&coreclk 0>;
67 #clock-cells = <1>;
68 };
69
50 system-controller@d0018200 { 70 system-controller@d0018200 {
51 compatible = "marvell,armada-370-xp-system-controller"; 71 compatible = "marvell,armada-370-xp-system-controller";
52 reg = <0xd0018200 0x500>; 72 reg = <0xd0018200 0x500>;
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
index 5a00022383e7..b524ee377f83 100644
--- a/arch/arm/boot/dts/dove.dtsi
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -31,6 +31,19 @@
31 reg = <0x20204 0x04>, <0x20214 0x04>; 31 reg = <0x20204 0x04>, <0x20214 0x04>;
32 }; 32 };
33 33
34 core_clk: core-clocks@d0214 {
35 compatible = "marvell,dove-core-clock";
36 reg = <0xd0214 0x4>;
37 #clock-cells = <1>;
38 };
39
40 gate_clk: clock-gating-control@d0038 {
41 compatible = "marvell,dove-gating-clock";
42 reg = <0xd0038 0x4>;
43 clocks = <&core_clk 0>;
44 #clock-cells = <1>;
45 };
46
34 uart0: serial@12000 { 47 uart0: serial@12000 {
35 compatible = "ns16550a"; 48 compatible = "ns16550a";
36 reg = <0x12000 0x100>; 49 reg = <0x12000 0x100>;
@@ -100,6 +113,7 @@
100 cell-index = <0>; 113 cell-index = <0>;
101 interrupts = <6>; 114 interrupts = <6>;
102 reg = <0x10600 0x28>; 115 reg = <0x10600 0x28>;
116 clocks = <&core_clk 0>;
103 status = "disabled"; 117 status = "disabled";
104 }; 118 };
105 119
@@ -110,6 +124,7 @@
110 cell-index = <1>; 124 cell-index = <1>;
111 interrupts = <5>; 125 interrupts = <5>;
112 reg = <0x14600 0x28>; 126 reg = <0x14600 0x28>;
127 clocks = <&core_clk 0>;
113 status = "disabled"; 128 status = "disabled";
114 }; 129 };
115 130
@@ -121,6 +136,7 @@
121 interrupts = <11>; 136 interrupts = <11>;
122 clock-frequency = <400000>; 137 clock-frequency = <400000>;
123 timeout-ms = <1000>; 138 timeout-ms = <1000>;
139 clocks = <&core_clk 0>;
124 status = "disabled"; 140 status = "disabled";
125 }; 141 };
126 142
@@ -128,6 +144,7 @@
128 compatible = "marvell,dove-sdhci"; 144 compatible = "marvell,dove-sdhci";
129 reg = <0x92000 0x100>; 145 reg = <0x92000 0x100>;
130 interrupts = <35>, <37>; 146 interrupts = <35>, <37>;
147 clocks = <&gate_clk 8>;
131 status = "disabled"; 148 status = "disabled";
132 }; 149 };
133 150
@@ -135,6 +152,7 @@
135 compatible = "marvell,dove-sdhci"; 152 compatible = "marvell,dove-sdhci";
136 reg = <0x90000 0x100>; 153 reg = <0x90000 0x100>;
137 interrupts = <36>, <38>; 154 interrupts = <36>, <38>;
155 clocks = <&gate_clk 9>;
138 status = "disabled"; 156 status = "disabled";
139 }; 157 };
140 158
@@ -142,6 +160,7 @@
142 compatible = "marvell,orion-sata"; 160 compatible = "marvell,orion-sata";
143 reg = <0xa0000 0x2400>; 161 reg = <0xa0000 0x2400>;
144 interrupts = <62>; 162 interrupts = <62>;
163 clocks = <&gate_clk 3>;
145 nr-ports = <1>; 164 nr-ports = <1>;
146 status = "disabled"; 165 status = "disabled";
147 }; 166 };
@@ -152,6 +171,7 @@
152 <0xc8000000 0x800>; 171 <0xc8000000 0x800>;
153 reg-names = "regs", "sram"; 172 reg-names = "regs", "sram";
154 interrupts = <31>; 173 interrupts = <31>;
174 clocks = <&gate_clk 15>;
155 status = "okay"; 175 status = "okay";
156 }; 176 };
157 }; 177 };
diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi
index 4e5b8154a5be..7a9fac0d4251 100644
--- a/arch/arm/boot/dts/kirkwood.dtsi
+++ b/arch/arm/boot/dts/kirkwood.dtsi
@@ -19,6 +19,12 @@
19 #address-cells = <1>; 19 #address-cells = <1>;
20 #size-cells = <1>; 20 #size-cells = <1>;
21 21
22 core_clk: core-clocks@10030 {
23 compatible = "marvell,kirkwood-core-clock";
24 reg = <0x10030 0x4>;
25 #clock-cells = <1>;
26 };
27
22 gpio0: gpio@10100 { 28 gpio0: gpio@10100 {
23 compatible = "marvell,orion-gpio"; 29 compatible = "marvell,orion-gpio";
24 #gpio-cells = <2>; 30 #gpio-cells = <2>;
@@ -42,6 +48,7 @@
42 reg = <0x12000 0x100>; 48 reg = <0x12000 0x100>;
43 reg-shift = <2>; 49 reg-shift = <2>;
44 interrupts = <33>; 50 interrupts = <33>;
51 clocks = <&gate_clk 7>;
45 /* set clock-frequency in board dts */ 52 /* set clock-frequency in board dts */
46 status = "disabled"; 53 status = "disabled";
47 }; 54 };
@@ -51,6 +58,7 @@
51 reg = <0x12100 0x100>; 58 reg = <0x12100 0x100>;
52 reg-shift = <2>; 59 reg-shift = <2>;
53 interrupts = <34>; 60 interrupts = <34>;
61 clocks = <&gate_clk 7>;
54 /* set clock-frequency in board dts */ 62 /* set clock-frequency in board dts */
55 status = "disabled"; 63 status = "disabled";
56 }; 64 };
@@ -68,12 +76,21 @@
68 cell-index = <0>; 76 cell-index = <0>;
69 interrupts = <23>; 77 interrupts = <23>;
70 reg = <0x10600 0x28>; 78 reg = <0x10600 0x28>;
79 clocks = <&gate_clk 7>;
71 status = "disabled"; 80 status = "disabled";
72 }; 81 };
73 82
83 gate_clk: clock-gating-control@2011c {
84 compatible = "marvell,kirkwood-gating-clock";
85 reg = <0x2011c 0x4>;
86 clocks = <&core_clk 0>;
87 #clock-cells = <1>;
88 };
89
74 wdt@20300 { 90 wdt@20300 {
75 compatible = "marvell,orion-wdt"; 91 compatible = "marvell,orion-wdt";
76 reg = <0x20300 0x28>; 92 reg = <0x20300 0x28>;
93 clocks = <&gate_clk 7>;
77 status = "okay"; 94 status = "okay";
78 }; 95 };
79 96
@@ -81,6 +98,8 @@
81 compatible = "marvell,orion-sata"; 98 compatible = "marvell,orion-sata";
82 reg = <0x80000 0x5000>; 99 reg = <0x80000 0x5000>;
83 interrupts = <21>; 100 interrupts = <21>;
101 clocks = <&gate_clk 14>, <&gate_clk 15>;
102 clock-names = "0", "1";
84 status = "disabled"; 103 status = "disabled";
85 }; 104 };
86 105
@@ -94,6 +113,7 @@
94 reg = <0x3000000 0x400>; 113 reg = <0x3000000 0x400>;
95 chip-delay = <25>; 114 chip-delay = <25>;
96 /* set partition map and/or chip-delay in board dts */ 115 /* set partition map and/or chip-delay in board dts */
116 clocks = <&gate_clk 7>;
97 status = "disabled"; 117 status = "disabled";
98 }; 118 };
99 119
@@ -104,6 +124,7 @@
104 #size-cells = <0>; 124 #size-cells = <0>;
105 interrupts = <29>; 125 interrupts = <29>;
106 clock-frequency = <100000>; 126 clock-frequency = <100000>;
127 clocks = <&gate_clk 7>;
107 status = "disabled"; 128 status = "disabled";
108 }; 129 };
109 130
@@ -113,6 +134,7 @@
113 <0xf5000000 0x800>; 134 <0xf5000000 0x800>;
114 reg-names = "regs", "sram"; 135 reg-names = "regs", "sram";
115 interrupts = <22>; 136 interrupts = <22>;
137 clocks = <&gate_clk 17>;
116 status = "okay"; 138 status = "okay";
117 }; 139 };
118 }; 140 };
diff --git a/arch/arm/mach-dove/Kconfig b/arch/arm/mach-dove/Kconfig
index 00154e74ce6b..603c5fd99e8a 100644
--- a/arch/arm/mach-dove/Kconfig
+++ b/arch/arm/mach-dove/Kconfig
@@ -17,6 +17,8 @@ config MACH_CM_A510
17 17
18config MACH_DOVE_DT 18config MACH_DOVE_DT
19 bool "Marvell Dove Flattened Device Tree" 19 bool "Marvell Dove Flattened Device Tree"
20 select MVEBU_CLK_CORE
21 select MVEBU_CLK_GATING
20 select USE_OF 22 select USE_OF
21 help 23 help
22 Say 'Y' here if you want your kernel to support the 24 Say 'Y' here if you want your kernel to support the
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index f723fe13d0f0..6a2c4dc413a8 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -14,6 +14,7 @@
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/pci.h> 15#include <linux/pci.h>
16#include <linux/clk-provider.h> 16#include <linux/clk-provider.h>
17#include <linux/clk/mvebu.h>
17#include <linux/ata_platform.h> 18#include <linux/ata_platform.h>
18#include <linux/gpio.h> 19#include <linux/gpio.h>
19#include <linux/of.h> 20#include <linux/of.h>
@@ -376,19 +377,52 @@ void dove_restart(char mode, const char *cmd)
376 377
377#if defined(CONFIG_MACH_DOVE_DT) 378#if defined(CONFIG_MACH_DOVE_DT)
378/* 379/*
379 * Auxdata required until real OF clock provider 380 * There are still devices that doesn't even know about DT,
381 * get clock gates here and add a clock lookup.
380 */ 382 */
381struct of_dev_auxdata dove_auxdata_lookup[] __initdata = { 383static void __init dove_legacy_clk_init(void)
382 OF_DEV_AUXDATA("marvell,orion-spi", 0xf1010600, "orion_spi.0", NULL), 384{
383 OF_DEV_AUXDATA("marvell,orion-spi", 0xf1014600, "orion_spi.1", NULL), 385 struct device_node *np = of_find_compatible_node(NULL, NULL,
384 OF_DEV_AUXDATA("marvell,orion-wdt", 0xf1020300, "orion_wdt", NULL), 386 "marvell,dove-gating-clock");
385 OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011000, "mv64xxx_i2c.0", 387 struct of_phandle_args clkspec;
386 NULL), 388
387 OF_DEV_AUXDATA("marvell,orion-sata", 0xf10a0000, "sata_mv.0", NULL), 389 clkspec.np = np;
388 OF_DEV_AUXDATA("marvell,dove-sdhci", 0xf1092000, "sdhci-dove.0", NULL), 390 clkspec.args_count = 1;
389 OF_DEV_AUXDATA("marvell,dove-sdhci", 0xf1090000, "sdhci-dove.1", NULL), 391
390 {}, 392 clkspec.args[0] = CLOCK_GATING_BIT_USB0;
391}; 393 orion_clkdev_add(NULL, "orion-ehci.0",
394 of_clk_get_from_provider(&clkspec));
395
396 clkspec.args[0] = CLOCK_GATING_BIT_USB1;
397 orion_clkdev_add(NULL, "orion-ehci.1",
398 of_clk_get_from_provider(&clkspec));
399
400 clkspec.args[0] = CLOCK_GATING_BIT_GBE;
401 orion_clkdev_add(NULL, "mv643xx_eth_port.0",
402 of_clk_get_from_provider(&clkspec));
403
404 clkspec.args[0] = CLOCK_GATING_BIT_PCIE0;
405 orion_clkdev_add("0", "pcie",
406 of_clk_get_from_provider(&clkspec));
407
408 clkspec.args[0] = CLOCK_GATING_BIT_PCIE1;
409 orion_clkdev_add("1", "pcie",
410 of_clk_get_from_provider(&clkspec));
411
412 clkspec.args[0] = CLOCK_GATING_BIT_XOR0;
413 orion_clkdev_add(NULL, "mv_xor_shared.0",
414 of_clk_get_from_provider(&clkspec));
415
416 clkspec.args[0] = CLOCK_GATING_BIT_XOR1;
417 orion_clkdev_add(NULL, "mv_xor_shared.1",
418 of_clk_get_from_provider(&clkspec));
419}
420
421static void __init dove_of_clk_init(void)
422{
423 mvebu_clocks_init();
424 dove_legacy_clk_init();
425}
392 426
393static struct mv643xx_eth_platform_data dove_dt_ge00_data = { 427static struct mv643xx_eth_platform_data dove_dt_ge00_data = {
394 .phy_addr = MV643XX_ETH_PHY_ADDR_DEFAULT, 428 .phy_addr = MV643XX_ETH_PHY_ADDR_DEFAULT,
@@ -405,7 +439,7 @@ static void __init dove_dt_init(void)
405 dove_setup_cpu_mbus(); 439 dove_setup_cpu_mbus();
406 440
407 /* Setup root of clk tree */ 441 /* Setup root of clk tree */
408 dove_clk_init(); 442 dove_of_clk_init();
409 443
410 /* Internal devices not ported to DT yet */ 444 /* Internal devices not ported to DT yet */
411 dove_rtc_init(); 445 dove_rtc_init();
@@ -417,8 +451,7 @@ static void __init dove_dt_init(void)
417 dove_ehci1_init(); 451 dove_ehci1_init();
418 dove_pcie_init(1, 1); 452 dove_pcie_init(1, 1);
419 453
420 of_platform_populate(NULL, of_default_bus_match_table, 454 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
421 dove_auxdata_lookup, NULL);
422} 455}
423 456
424static const char * const dove_dt_board_compat[] = { 457static const char * const dove_dt_board_compat[] = {
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index 50bca5032b7e..2833492eb273 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -46,6 +46,8 @@ config MACH_GURUPLUG
46 46
47config ARCH_KIRKWOOD_DT 47config ARCH_KIRKWOOD_DT
48 bool "Marvell Kirkwood Flattened Device Tree" 48 bool "Marvell Kirkwood Flattened Device Tree"
49 select MVEBU_CLK_CORE
50 select MVEBU_CLK_GATING
49 select USE_OF 51 select USE_OF
50 help 52 help
51 Say 'Y' here if you want your kernel to support the 53 Say 'Y' here if you want your kernel to support the
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
index d94872fed8c0..8bdfaa4db091 100644
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ b/arch/arm/mach-kirkwood/board-dt.c
@@ -14,11 +14,15 @@
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/of.h> 15#include <linux/of.h>
16#include <linux/of_platform.h> 16#include <linux/of_platform.h>
17#include <linux/clk-provider.h>
18#include <linux/clk/mvebu.h>
17#include <linux/kexec.h> 19#include <linux/kexec.h>
18#include <asm/mach/arch.h> 20#include <asm/mach/arch.h>
19#include <asm/mach/map.h> 21#include <asm/mach/map.h>
20#include <mach/bridge-regs.h> 22#include <mach/bridge-regs.h>
23#include <linux/platform_data/usb-ehci-orion.h>
21#include <plat/irq.h> 24#include <plat/irq.h>
25#include <plat/common.h>
22#include "common.h" 26#include "common.h"
23 27
24static struct of_device_id kirkwood_dt_match_table[] __initdata = { 28static struct of_device_id kirkwood_dt_match_table[] __initdata = {
@@ -26,16 +30,58 @@ static struct of_device_id kirkwood_dt_match_table[] __initdata = {
26 { } 30 { }
27}; 31};
28 32
29struct of_dev_auxdata kirkwood_auxdata_lookup[] __initdata = { 33/*
30 OF_DEV_AUXDATA("marvell,orion-spi", 0xf1010600, "orion_spi.0", NULL), 34 * There are still devices that doesn't know about DT yet. Get clock
31 OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011000, "mv64xxx_i2c.0", 35 * gates here and add a clock lookup alias, so that old platform
32 NULL), 36 * devices still work.
33 OF_DEV_AUXDATA("marvell,orion-wdt", 0xf1020300, "orion_wdt", NULL), 37*/
34 OF_DEV_AUXDATA("marvell,orion-sata", 0xf1080000, "sata_mv.0", NULL), 38
35 OF_DEV_AUXDATA("marvell,orion-nand", 0xf4000000, "orion_nand", NULL), 39static void __init kirkwood_legacy_clk_init(void)
36 OF_DEV_AUXDATA("marvell,orion-crypto", 0xf1030000, "mv_crypto", NULL), 40{
37 {}, 41
38}; 42 struct device_node *np = of_find_compatible_node(
43 NULL, NULL, "marvell,kirkwood-gating-clock");
44
45 struct of_phandle_args clkspec;
46
47 clkspec.np = np;
48 clkspec.args_count = 1;
49
50 clkspec.args[0] = CGC_BIT_GE0;
51 orion_clkdev_add(NULL, "mv643xx_eth_port.0",
52 of_clk_get_from_provider(&clkspec));
53
54 clkspec.args[0] = CGC_BIT_PEX0;
55 orion_clkdev_add("0", "pcie",
56 of_clk_get_from_provider(&clkspec));
57
58 clkspec.args[0] = CGC_BIT_USB0;
59 orion_clkdev_add(NULL, "orion-ehci.0",
60 of_clk_get_from_provider(&clkspec));
61
62 clkspec.args[0] = CGC_BIT_XOR0;
63 orion_clkdev_add(NULL, "mv_xor_shared.0",
64 of_clk_get_from_provider(&clkspec));
65
66 clkspec.args[0] = CGC_BIT_XOR1;
67 orion_clkdev_add(NULL, "mv_xor_shared.1",
68 of_clk_get_from_provider(&clkspec));
69
70 clkspec.args[0] = CGC_BIT_PEX1;
71 orion_clkdev_add("1", "pcie",
72 of_clk_get_from_provider(&clkspec));
73
74 clkspec.args[0] = CGC_BIT_GE1;
75 orion_clkdev_add(NULL, "mv643xx_eth_port.1",
76 of_clk_get_from_provider(&clkspec));
77
78}
79
80static void __init kirkwood_of_clk_init(void)
81{
82 mvebu_clocks_init();
83 kirkwood_legacy_clk_init();
84}
39 85
40static void __init kirkwood_dt_init(void) 86static void __init kirkwood_dt_init(void)
41{ 87{
@@ -54,7 +100,7 @@ static void __init kirkwood_dt_init(void)
54 kirkwood_l2_init(); 100 kirkwood_l2_init();
55 101
56 /* Setup root of clk tree */ 102 /* Setup root of clk tree */
57 kirkwood_clk_init(); 103 kirkwood_of_clk_init();
58 104
59 /* internal devices that every board has */ 105 /* internal devices that every board has */
60 kirkwood_xor0_init(); 106 kirkwood_xor0_init();
@@ -94,8 +140,7 @@ static void __init kirkwood_dt_init(void)
94 if (of_machine_is_compatible("keymile,km_kirkwood")) 140 if (of_machine_is_compatible("keymile,km_kirkwood"))
95 km_kirkwood_init(); 141 km_kirkwood_init();
96 142
97 of_platform_populate(NULL, kirkwood_dt_match_table, 143 of_platform_populate(NULL, kirkwood_dt_match_table, NULL, NULL);
98 kirkwood_auxdata_lookup, NULL);
99} 144}
100 145
101static const char *kirkwood_dt_board_compat[] = { 146static const char *kirkwood_dt_board_compat[] = {
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 416d46ef7ebd..79299cd94f0f 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -9,6 +9,10 @@ config ARCH_MVEBU
9 select PINCTRL 9 select PINCTRL
10 select PLAT_ORION 10 select PLAT_ORION
11 select SPARSE_IRQ 11 select SPARSE_IRQ
12 select CLKDEV_LOOKUP
13 select MVEBU_CLK_CORE
14 select MVEBU_CLK_CPU
15 select MVEBU_CLK_GATING
12 16
13if ARCH_MVEBU 17if ARCH_MVEBU
14 18
diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
index 49d791548ad6..3292d6da5dc7 100644
--- a/arch/arm/mach-mvebu/armada-370-xp.c
+++ b/arch/arm/mach-mvebu/armada-370-xp.c
@@ -17,6 +17,7 @@
17#include <linux/of_platform.h> 17#include <linux/of_platform.h>
18#include <linux/io.h> 18#include <linux/io.h>
19#include <linux/time-armada-370-xp.h> 19#include <linux/time-armada-370-xp.h>
20#include <linux/clk/mvebu.h>
20#include <asm/mach/arch.h> 21#include <asm/mach/arch.h>
21#include <asm/mach/map.h> 22#include <asm/mach/map.h>
22#include <asm/mach/time.h> 23#include <asm/mach/time.h>
@@ -37,8 +38,14 @@ void __init armada_370_xp_map_io(void)
37 iotable_init(armada_370_xp_io_desc, ARRAY_SIZE(armada_370_xp_io_desc)); 38 iotable_init(armada_370_xp_io_desc, ARRAY_SIZE(armada_370_xp_io_desc));
38} 39}
39 40
41void __init armada_370_xp_timer_and_clk_init(void)
42{
43 mvebu_clocks_init();
44 armada_370_xp_timer_init();
45}
46
40struct sys_timer armada_370_xp_timer = { 47struct sys_timer armada_370_xp_timer = {
41 .init = armada_370_xp_timer_init, 48 .init = armada_370_xp_timer_and_clk_init,
42}; 49};
43 50
44static void __init armada_370_xp_dt_init(void) 51static void __init armada_370_xp_dt_init(void)
diff --git a/arch/arm/plat-orion/include/plat/common.h b/arch/arm/plat-orion/include/plat/common.h
index 6bbc3fe5f58e..e06fc5fefa14 100644
--- a/arch/arm/plat-orion/include/plat/common.h
+++ b/arch/arm/plat-orion/include/plat/common.h
@@ -12,6 +12,7 @@
12#include <linux/mv643xx_eth.h> 12#include <linux/mv643xx_eth.h>
13 13
14struct dsa_platform_data; 14struct dsa_platform_data;
15struct mv_sata_platform_data;
15 16
16void __init orion_uart0_init(void __iomem *membase, 17void __init orion_uart0_init(void __iomem *membase,
17 resource_size_t mapbase, 18 resource_size_t mapbase,
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index bace9e98f75d..60427c0d23e6 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -54,3 +54,5 @@ config COMMON_CLK_MAX77686
54 This driver supports Maxim 77686 crystal oscillator clock. 54 This driver supports Maxim 77686 crystal oscillator clock.
55 55
56endmenu 56endmenu
57
58source "drivers/clk/mvebu/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 71a25b91de00..d0a14ae8d49c 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_PLAT_SPEAR) += spear/
13obj-$(CONFIG_ARCH_U300) += clk-u300.o 13obj-$(CONFIG_ARCH_U300) += clk-u300.o
14obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/ 14obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/
15obj-$(CONFIG_ARCH_PRIMA2) += clk-prima2.o 15obj-$(CONFIG_ARCH_PRIMA2) += clk-prima2.o
16obj-$(CONFIG_PLAT_ORION) += mvebu/
16ifeq ($(CONFIG_COMMON_CLK), y) 17ifeq ($(CONFIG_COMMON_CLK), y)
17obj-$(CONFIG_ARCH_MMP) += mmp/ 18obj-$(CONFIG_ARCH_MMP) += mmp/
18endif 19endif
diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig
new file mode 100644
index 000000000000..57323fd15ec9
--- /dev/null
+++ b/drivers/clk/mvebu/Kconfig
@@ -0,0 +1,8 @@
1config MVEBU_CLK_CORE
2 bool
3
4config MVEBU_CLK_CPU
5 bool
6
7config MVEBU_CLK_GATING
8 bool
diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile
new file mode 100644
index 000000000000..58df3dc49363
--- /dev/null
+++ b/drivers/clk/mvebu/Makefile
@@ -0,0 +1,3 @@
1obj-$(CONFIG_MVEBU_CLK_CORE) += clk.o clk-core.o
2obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o
3obj-$(CONFIG_MVEBU_CLK_GATING) += clk-gating-ctrl.o
diff --git a/drivers/clk/mvebu/clk-core.c b/drivers/clk/mvebu/clk-core.c
new file mode 100644
index 000000000000..69056a7479e8
--- /dev/null
+++ b/drivers/clk/mvebu/clk-core.c
@@ -0,0 +1,675 @@
1/*
2 * Marvell EBU clock core handling defined at reset
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Gregory CLEMENT <gregory.clement@free-electrons.com>
7 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13#include <linux/kernel.h>
14#include <linux/clk.h>
15#include <linux/clkdev.h>
16#include <linux/clk-provider.h>
17#include <linux/of_address.h>
18#include <linux/io.h>
19#include <linux/of.h>
20#include "clk-core.h"
21
22struct core_ratio {
23 int id;
24 const char *name;
25};
26
27struct core_clocks {
28 u32 (*get_tclk_freq)(void __iomem *sar);
29 u32 (*get_cpu_freq)(void __iomem *sar);
30 void (*get_clk_ratio)(void __iomem *sar, int id, int *mult, int *div);
31 const struct core_ratio *ratios;
32 int num_ratios;
33};
34
35static struct clk_onecell_data clk_data;
36
37static void __init mvebu_clk_core_setup(struct device_node *np,
38 struct core_clocks *coreclk)
39{
40 const char *tclk_name = "tclk";
41 const char *cpuclk_name = "cpuclk";
42 void __iomem *base;
43 unsigned long rate;
44 int n;
45
46 base = of_iomap(np, 0);
47 if (WARN_ON(!base))
48 return;
49
50 /*
51 * Allocate struct for TCLK, cpu clk, and core ratio clocks
52 */
53 clk_data.clk_num = 2 + coreclk->num_ratios;
54 clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *),
55 GFP_KERNEL);
56 if (WARN_ON(!clk_data.clks))
57 return;
58
59 /*
60 * Register TCLK
61 */
62 of_property_read_string_index(np, "clock-output-names", 0,
63 &tclk_name);
64 rate = coreclk->get_tclk_freq(base);
65 clk_data.clks[0] = clk_register_fixed_rate(NULL, tclk_name, NULL,
66 CLK_IS_ROOT, rate);
67 WARN_ON(IS_ERR(clk_data.clks[0]));
68
69 /*
70 * Register CPU clock
71 */
72 of_property_read_string_index(np, "clock-output-names", 1,
73 &cpuclk_name);
74 rate = coreclk->get_cpu_freq(base);
75 clk_data.clks[1] = clk_register_fixed_rate(NULL, cpuclk_name, NULL,
76 CLK_IS_ROOT, rate);
77 WARN_ON(IS_ERR(clk_data.clks[1]));
78
79 /*
80 * Register fixed-factor clocks derived from CPU clock
81 */
82 for (n = 0; n < coreclk->num_ratios; n++) {
83 const char *rclk_name = coreclk->ratios[n].name;
84 int mult, div;
85
86 of_property_read_string_index(np, "clock-output-names",
87 2+n, &rclk_name);
88 coreclk->get_clk_ratio(base, coreclk->ratios[n].id,
89 &mult, &div);
90 clk_data.clks[2+n] = clk_register_fixed_factor(NULL, rclk_name,
91 cpuclk_name, 0, mult, div);
92 WARN_ON(IS_ERR(clk_data.clks[2+n]));
93 };
94
95 /*
96 * SAR register isn't needed anymore
97 */
98 iounmap(base);
99
100 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
101}
102
103#ifdef CONFIG_MACH_ARMADA_370_XP
104/*
105 * Armada 370/XP Sample At Reset is a 64 bit bitfiled split in two
106 * register of 32 bits
107 */
108
109#define SARL 0 /* Low part [0:31] */
110#define SARL_AXP_PCLK_FREQ_OPT 21
111#define SARL_AXP_PCLK_FREQ_OPT_MASK 0x7
112#define SARL_A370_PCLK_FREQ_OPT 11
113#define SARL_A370_PCLK_FREQ_OPT_MASK 0xF
114#define SARL_AXP_FAB_FREQ_OPT 24
115#define SARL_AXP_FAB_FREQ_OPT_MASK 0xF
116#define SARL_A370_FAB_FREQ_OPT 15
117#define SARL_A370_FAB_FREQ_OPT_MASK 0x1F
118#define SARL_A370_TCLK_FREQ_OPT 20
119#define SARL_A370_TCLK_FREQ_OPT_MASK 0x1
120#define SARH 4 /* High part [32:63] */
121#define SARH_AXP_PCLK_FREQ_OPT (52-32)
122#define SARH_AXP_PCLK_FREQ_OPT_MASK 0x1
123#define SARH_AXP_PCLK_FREQ_OPT_SHIFT 3
124#define SARH_AXP_FAB_FREQ_OPT (51-32)
125#define SARH_AXP_FAB_FREQ_OPT_MASK 0x1
126#define SARH_AXP_FAB_FREQ_OPT_SHIFT 4
127
128static const u32 __initconst armada_370_tclk_frequencies[] = {
129 16600000,
130 20000000,
131};
132
133static u32 __init armada_370_get_tclk_freq(void __iomem *sar)
134{
135 u8 tclk_freq_select = 0;
136
137 tclk_freq_select = ((readl(sar) >> SARL_A370_TCLK_FREQ_OPT) &
138 SARL_A370_TCLK_FREQ_OPT_MASK);
139 return armada_370_tclk_frequencies[tclk_freq_select];
140}
141
142static const u32 __initconst armada_370_cpu_frequencies[] = {
143 400000000,
144 533000000,
145 667000000,
146 800000000,
147 1000000000,
148 1067000000,
149 1200000000,
150};
151
152static u32 __init armada_370_get_cpu_freq(void __iomem *sar)
153{
154 u32 cpu_freq;
155 u8 cpu_freq_select = 0;
156
157 cpu_freq_select = ((readl(sar) >> SARL_A370_PCLK_FREQ_OPT) &
158 SARL_A370_PCLK_FREQ_OPT_MASK);
159 if (cpu_freq_select > ARRAY_SIZE(armada_370_cpu_frequencies)) {
160 pr_err("CPU freq select unsuported %d\n", cpu_freq_select);
161 cpu_freq = 0;
162 } else
163 cpu_freq = armada_370_cpu_frequencies[cpu_freq_select];
164
165 return cpu_freq;
166}
167
168enum { A370_XP_NBCLK, A370_XP_HCLK, A370_XP_DRAMCLK };
169
170static const struct core_ratio __initconst armada_370_xp_core_ratios[] = {
171 { .id = A370_XP_NBCLK, .name = "nbclk" },
172 { .id = A370_XP_HCLK, .name = "hclk" },
173 { .id = A370_XP_DRAMCLK, .name = "dramclk" },
174};
175
176static const int __initconst armada_370_xp_nbclk_ratios[32][2] = {
177 {0, 1}, {1, 2}, {2, 2}, {2, 2},
178 {1, 2}, {1, 2}, {1, 1}, {2, 3},
179 {0, 1}, {1, 2}, {2, 4}, {0, 1},
180 {1, 2}, {0, 1}, {0, 1}, {2, 2},
181 {0, 1}, {0, 1}, {0, 1}, {1, 1},
182 {2, 3}, {0, 1}, {0, 1}, {0, 1},
183 {0, 1}, {0, 1}, {0, 1}, {1, 1},
184 {0, 1}, {0, 1}, {0, 1}, {0, 1},
185};
186
187static const int __initconst armada_370_xp_hclk_ratios[32][2] = {
188 {0, 1}, {1, 2}, {2, 6}, {2, 3},
189 {1, 3}, {1, 4}, {1, 2}, {2, 6},
190 {0, 1}, {1, 6}, {2, 10}, {0, 1},
191 {1, 4}, {0, 1}, {0, 1}, {2, 5},
192 {0, 1}, {0, 1}, {0, 1}, {1, 2},
193 {2, 6}, {0, 1}, {0, 1}, {0, 1},
194 {0, 1}, {0, 1}, {0, 1}, {1, 1},
195 {0, 1}, {0, 1}, {0, 1}, {0, 1},
196};
197
198static const int __initconst armada_370_xp_dramclk_ratios[32][2] = {
199 {0, 1}, {1, 2}, {2, 3}, {2, 3},
200 {1, 3}, {1, 2}, {1, 2}, {2, 6},
201 {0, 1}, {1, 3}, {2, 5}, {0, 1},
202 {1, 4}, {0, 1}, {0, 1}, {2, 5},
203 {0, 1}, {0, 1}, {0, 1}, {1, 1},
204 {2, 3}, {0, 1}, {0, 1}, {0, 1},
205 {0, 1}, {0, 1}, {0, 1}, {1, 1},
206 {0, 1}, {0, 1}, {0, 1}, {0, 1},
207};
208
209static void __init armada_370_xp_get_clk_ratio(u32 opt,
210 void __iomem *sar, int id, int *mult, int *div)
211{
212 switch (id) {
213 case A370_XP_NBCLK:
214 *mult = armada_370_xp_nbclk_ratios[opt][0];
215 *div = armada_370_xp_nbclk_ratios[opt][1];
216 break;
217 case A370_XP_HCLK:
218 *mult = armada_370_xp_hclk_ratios[opt][0];
219 *div = armada_370_xp_hclk_ratios[opt][1];
220 break;
221 case A370_XP_DRAMCLK:
222 *mult = armada_370_xp_dramclk_ratios[opt][0];
223 *div = armada_370_xp_dramclk_ratios[opt][1];
224 break;
225 }
226}
227
228static void __init armada_370_get_clk_ratio(
229 void __iomem *sar, int id, int *mult, int *div)
230{
231 u32 opt = ((readl(sar) >> SARL_A370_FAB_FREQ_OPT) &
232 SARL_A370_FAB_FREQ_OPT_MASK);
233
234 armada_370_xp_get_clk_ratio(opt, sar, id, mult, div);
235}
236
237
238static const struct core_clocks armada_370_core_clocks = {
239 .get_tclk_freq = armada_370_get_tclk_freq,
240 .get_cpu_freq = armada_370_get_cpu_freq,
241 .get_clk_ratio = armada_370_get_clk_ratio,
242 .ratios = armada_370_xp_core_ratios,
243 .num_ratios = ARRAY_SIZE(armada_370_xp_core_ratios),
244};
245
246static const u32 __initconst armada_xp_cpu_frequencies[] = {
247 1000000000,
248 1066000000,
249 1200000000,
250 1333000000,
251 1500000000,
252 1666000000,
253 1800000000,
254 2000000000,
255 667000000,
256 0,
257 800000000,
258 1600000000,
259};
260
261/* For Armada XP TCLK frequency is fix: 250MHz */
262static u32 __init armada_xp_get_tclk_freq(void __iomem *sar)
263{
264 return 250 * 1000 * 1000;
265}
266
267static u32 __init armada_xp_get_cpu_freq(void __iomem *sar)
268{
269 u32 cpu_freq;
270 u8 cpu_freq_select = 0;
271
272 cpu_freq_select = ((readl(sar) >> SARL_AXP_PCLK_FREQ_OPT) &
273 SARL_AXP_PCLK_FREQ_OPT_MASK);
274 /*
275 * The upper bit is not contiguous to the other ones and
276 * located in the high part of the SAR registers
277 */
278 cpu_freq_select |= (((readl(sar+4) >> SARH_AXP_PCLK_FREQ_OPT) &
279 SARH_AXP_PCLK_FREQ_OPT_MASK)
280 << SARH_AXP_PCLK_FREQ_OPT_SHIFT);
281 if (cpu_freq_select > ARRAY_SIZE(armada_xp_cpu_frequencies)) {
282 pr_err("CPU freq select unsuported: %d\n", cpu_freq_select);
283 cpu_freq = 0;
284 } else
285 cpu_freq = armada_xp_cpu_frequencies[cpu_freq_select];
286
287 return cpu_freq;
288}
289
290static void __init armada_xp_get_clk_ratio(
291 void __iomem *sar, int id, int *mult, int *div)
292{
293
294 u32 opt = ((readl(sar) >> SARL_AXP_FAB_FREQ_OPT) &
295 SARL_AXP_FAB_FREQ_OPT_MASK);
296 /*
297 * The upper bit is not contiguous to the other ones and
298 * located in the high part of the SAR registers
299 */
300 opt |= (((readl(sar+4) >> SARH_AXP_FAB_FREQ_OPT) &
301 SARH_AXP_FAB_FREQ_OPT_MASK)
302 << SARH_AXP_FAB_FREQ_OPT_SHIFT);
303
304 armada_370_xp_get_clk_ratio(opt, sar, id, mult, div);
305}
306
307static const struct core_clocks armada_xp_core_clocks = {
308 .get_tclk_freq = armada_xp_get_tclk_freq,
309 .get_cpu_freq = armada_xp_get_cpu_freq,
310 .get_clk_ratio = armada_xp_get_clk_ratio,
311 .ratios = armada_370_xp_core_ratios,
312 .num_ratios = ARRAY_SIZE(armada_370_xp_core_ratios),
313};
314
315#endif /* CONFIG_MACH_ARMADA_370_XP */
316
317/*
318 * Dove PLL sample-at-reset configuration
319 *
320 * SAR0[8:5] : CPU frequency
321 * 5 = 1000 MHz
322 * 6 = 933 MHz
323 * 7 = 933 MHz
324 * 8 = 800 MHz
325 * 9 = 800 MHz
326 * 10 = 800 MHz
327 * 11 = 1067 MHz
328 * 12 = 667 MHz
329 * 13 = 533 MHz
330 * 14 = 400 MHz
331 * 15 = 333 MHz
332 * others reserved.
333 *
334 * SAR0[11:9] : CPU to L2 Clock divider ratio
335 * 0 = (1/1) * CPU
336 * 2 = (1/2) * CPU
337 * 4 = (1/3) * CPU
338 * 6 = (1/4) * CPU
339 * others reserved.
340 *
341 * SAR0[15:12] : CPU to DDR DRAM Clock divider ratio
342 * 0 = (1/1) * CPU
343 * 2 = (1/2) * CPU
344 * 3 = (2/5) * CPU
345 * 4 = (1/3) * CPU
346 * 6 = (1/4) * CPU
347 * 8 = (1/5) * CPU
348 * 10 = (1/6) * CPU
349 * 12 = (1/7) * CPU
350 * 14 = (1/8) * CPU
351 * 15 = (1/10) * CPU
352 * others reserved.
353 *
354 * SAR0[24:23] : TCLK frequency
355 * 0 = 166 MHz
356 * 1 = 125 MHz
357 * others reserved.
358 */
359#ifdef CONFIG_ARCH_DOVE
360#define SAR_DOVE_CPU_FREQ 5
361#define SAR_DOVE_CPU_FREQ_MASK 0xf
362#define SAR_DOVE_L2_RATIO 9
363#define SAR_DOVE_L2_RATIO_MASK 0x7
364#define SAR_DOVE_DDR_RATIO 12
365#define SAR_DOVE_DDR_RATIO_MASK 0xf
366#define SAR_DOVE_TCLK_FREQ 23
367#define SAR_DOVE_TCLK_FREQ_MASK 0x3
368
369static const u32 __initconst dove_tclk_frequencies[] = {
370 166666667,
371 125000000,
372 0, 0
373};
374
375static u32 __init dove_get_tclk_freq(void __iomem *sar)
376{
377 u32 opt = (readl(sar) >> SAR_DOVE_TCLK_FREQ) &
378 SAR_DOVE_TCLK_FREQ_MASK;
379 return dove_tclk_frequencies[opt];
380}
381
382static const u32 __initconst dove_cpu_frequencies[] = {
383 0, 0, 0, 0, 0,
384 1000000000,
385 933333333, 933333333,
386 800000000, 800000000, 800000000,
387 1066666667,
388 666666667,
389 533333333,
390 400000000,
391 333333333
392};
393
394static u32 __init dove_get_cpu_freq(void __iomem *sar)
395{
396 u32 opt = (readl(sar) >> SAR_DOVE_CPU_FREQ) &
397 SAR_DOVE_CPU_FREQ_MASK;
398 return dove_cpu_frequencies[opt];
399}
400
401enum { DOVE_CPU_TO_L2, DOVE_CPU_TO_DDR };
402
403static const struct core_ratio __initconst dove_core_ratios[] = {
404 { .id = DOVE_CPU_TO_L2, .name = "l2clk", },
405 { .id = DOVE_CPU_TO_DDR, .name = "ddrclk", }
406};
407
408static const int __initconst dove_cpu_l2_ratios[8][2] = {
409 { 1, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
410 { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 }
411};
412
413static const int __initconst dove_cpu_ddr_ratios[16][2] = {
414 { 1, 1 }, { 0, 1 }, { 1, 2 }, { 2, 5 },
415 { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 },
416 { 1, 5 }, { 0, 1 }, { 1, 6 }, { 0, 1 },
417 { 1, 7 }, { 0, 1 }, { 1, 8 }, { 1, 10 }
418};
419
420static void __init dove_get_clk_ratio(
421 void __iomem *sar, int id, int *mult, int *div)
422{
423 switch (id) {
424 case DOVE_CPU_TO_L2:
425 {
426 u32 opt = (readl(sar) >> SAR_DOVE_L2_RATIO) &
427 SAR_DOVE_L2_RATIO_MASK;
428 *mult = dove_cpu_l2_ratios[opt][0];
429 *div = dove_cpu_l2_ratios[opt][1];
430 break;
431 }
432 case DOVE_CPU_TO_DDR:
433 {
434 u32 opt = (readl(sar) >> SAR_DOVE_DDR_RATIO) &
435 SAR_DOVE_DDR_RATIO_MASK;
436 *mult = dove_cpu_ddr_ratios[opt][0];
437 *div = dove_cpu_ddr_ratios[opt][1];
438 break;
439 }
440 }
441}
442
443static const struct core_clocks dove_core_clocks = {
444 .get_tclk_freq = dove_get_tclk_freq,
445 .get_cpu_freq = dove_get_cpu_freq,
446 .get_clk_ratio = dove_get_clk_ratio,
447 .ratios = dove_core_ratios,
448 .num_ratios = ARRAY_SIZE(dove_core_ratios),
449};
450#endif /* CONFIG_ARCH_DOVE */
451
452/*
453 * Kirkwood PLL sample-at-reset configuration
454 * (6180 has different SAR layout than other Kirkwood SoCs)
455 *
456 * SAR0[4:3,22,1] : CPU frequency (6281,6292,6282)
457 * 4 = 600 MHz
458 * 6 = 800 MHz
459 * 7 = 1000 MHz
460 * 9 = 1200 MHz
461 * 12 = 1500 MHz
462 * 13 = 1600 MHz
463 * 14 = 1800 MHz
464 * 15 = 2000 MHz
465 * others reserved.
466 *
467 * SAR0[19,10:9] : CPU to L2 Clock divider ratio (6281,6292,6282)
468 * 1 = (1/2) * CPU
469 * 3 = (1/3) * CPU
470 * 5 = (1/4) * CPU
471 * others reserved.
472 *
473 * SAR0[8:5] : CPU to DDR DRAM Clock divider ratio (6281,6292,6282)
474 * 2 = (1/2) * CPU
475 * 4 = (1/3) * CPU
476 * 6 = (1/4) * CPU
477 * 7 = (2/9) * CPU
478 * 8 = (1/5) * CPU
479 * 9 = (1/6) * CPU
480 * others reserved.
481 *
482 * SAR0[4:2] : Kirkwood 6180 cpu/l2/ddr clock configuration (6180 only)
483 * 5 = [CPU = 600 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/3) * CPU]
484 * 6 = [CPU = 800 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/4) * CPU]
485 * 7 = [CPU = 1000 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/5) * CPU]
486 * others reserved.
487 *
488 * SAR0[21] : TCLK frequency
489 * 0 = 200 MHz
490 * 1 = 166 MHz
491 * others reserved.
492 */
493#ifdef CONFIG_ARCH_KIRKWOOD
494#define SAR_KIRKWOOD_CPU_FREQ(x) \
495 (((x & (1 << 1)) >> 1) | \
496 ((x & (1 << 22)) >> 21) | \
497 ((x & (3 << 3)) >> 1))
498#define SAR_KIRKWOOD_L2_RATIO(x) \
499 (((x & (3 << 9)) >> 9) | \
500 (((x & (1 << 19)) >> 17)))
501#define SAR_KIRKWOOD_DDR_RATIO 5
502#define SAR_KIRKWOOD_DDR_RATIO_MASK 0xf
503#define SAR_MV88F6180_CLK 2
504#define SAR_MV88F6180_CLK_MASK 0x7
505#define SAR_KIRKWOOD_TCLK_FREQ 21
506#define SAR_KIRKWOOD_TCLK_FREQ_MASK 0x1
507
508enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR };
509
510static const struct core_ratio __initconst kirkwood_core_ratios[] = {
511 { .id = KIRKWOOD_CPU_TO_L2, .name = "l2clk", },
512 { .id = KIRKWOOD_CPU_TO_DDR, .name = "ddrclk", }
513};
514
515static u32 __init kirkwood_get_tclk_freq(void __iomem *sar)
516{
517 u32 opt = (readl(sar) >> SAR_KIRKWOOD_TCLK_FREQ) &
518 SAR_KIRKWOOD_TCLK_FREQ_MASK;
519 return (opt) ? 166666667 : 200000000;
520}
521
522static const u32 __initconst kirkwood_cpu_frequencies[] = {
523 0, 0, 0, 0,
524 600000000,
525 0,
526 800000000,
527 1000000000,
528 0,
529 1200000000,
530 0, 0,
531 1500000000,
532 1600000000,
533 1800000000,
534 2000000000
535};
536
537static u32 __init kirkwood_get_cpu_freq(void __iomem *sar)
538{
539 u32 opt = SAR_KIRKWOOD_CPU_FREQ(readl(sar));
540 return kirkwood_cpu_frequencies[opt];
541}
542
543static const int __initconst kirkwood_cpu_l2_ratios[8][2] = {
544 { 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 },
545 { 0, 1 }, { 1, 4 }, { 0, 1 }, { 0, 1 }
546};
547
548static const int __initconst kirkwood_cpu_ddr_ratios[16][2] = {
549 { 0, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
550 { 1, 3 }, { 0, 1 }, { 1, 4 }, { 2, 9 },
551 { 1, 5 }, { 1, 6 }, { 0, 1 }, { 0, 1 },
552 { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }
553};
554
555static void __init kirkwood_get_clk_ratio(
556 void __iomem *sar, int id, int *mult, int *div)
557{
558 switch (id) {
559 case KIRKWOOD_CPU_TO_L2:
560 {
561 u32 opt = SAR_KIRKWOOD_L2_RATIO(readl(sar));
562 *mult = kirkwood_cpu_l2_ratios[opt][0];
563 *div = kirkwood_cpu_l2_ratios[opt][1];
564 break;
565 }
566 case KIRKWOOD_CPU_TO_DDR:
567 {
568 u32 opt = (readl(sar) >> SAR_KIRKWOOD_DDR_RATIO) &
569 SAR_KIRKWOOD_DDR_RATIO_MASK;
570 *mult = kirkwood_cpu_ddr_ratios[opt][0];
571 *div = kirkwood_cpu_ddr_ratios[opt][1];
572 break;
573 }
574 }
575}
576
577static const struct core_clocks kirkwood_core_clocks = {
578 .get_tclk_freq = kirkwood_get_tclk_freq,
579 .get_cpu_freq = kirkwood_get_cpu_freq,
580 .get_clk_ratio = kirkwood_get_clk_ratio,
581 .ratios = kirkwood_core_ratios,
582 .num_ratios = ARRAY_SIZE(kirkwood_core_ratios),
583};
584
585static const u32 __initconst mv88f6180_cpu_frequencies[] = {
586 0, 0, 0, 0, 0,
587 600000000,
588 800000000,
589 1000000000
590};
591
592static u32 __init mv88f6180_get_cpu_freq(void __iomem *sar)
593{
594 u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) & SAR_MV88F6180_CLK_MASK;
595 return mv88f6180_cpu_frequencies[opt];
596}
597
598static const int __initconst mv88f6180_cpu_ddr_ratios[8][2] = {
599 { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 },
600 { 0, 1 }, { 1, 3 }, { 1, 4 }, { 1, 5 }
601};
602
603static void __init mv88f6180_get_clk_ratio(
604 void __iomem *sar, int id, int *mult, int *div)
605{
606 switch (id) {
607 case KIRKWOOD_CPU_TO_L2:
608 {
609 /* mv88f6180 has a fixed 1:2 CPU-to-L2 ratio */
610 *mult = 1;
611 *div = 2;
612 break;
613 }
614 case KIRKWOOD_CPU_TO_DDR:
615 {
616 u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) &
617 SAR_MV88F6180_CLK_MASK;
618 *mult = mv88f6180_cpu_ddr_ratios[opt][0];
619 *div = mv88f6180_cpu_ddr_ratios[opt][1];
620 break;
621 }
622 }
623}
624
625static const struct core_clocks mv88f6180_core_clocks = {
626 .get_tclk_freq = kirkwood_get_tclk_freq,
627 .get_cpu_freq = mv88f6180_get_cpu_freq,
628 .get_clk_ratio = mv88f6180_get_clk_ratio,
629 .ratios = kirkwood_core_ratios,
630 .num_ratios = ARRAY_SIZE(kirkwood_core_ratios),
631};
632#endif /* CONFIG_ARCH_KIRKWOOD */
633
634static const __initdata struct of_device_id clk_core_match[] = {
635#ifdef CONFIG_MACH_ARMADA_370_XP
636 {
637 .compatible = "marvell,armada-370-core-clock",
638 .data = &armada_370_core_clocks,
639 },
640 {
641 .compatible = "marvell,armada-xp-core-clock",
642 .data = &armada_xp_core_clocks,
643 },
644#endif
645#ifdef CONFIG_ARCH_DOVE
646 {
647 .compatible = "marvell,dove-core-clock",
648 .data = &dove_core_clocks,
649 },
650#endif
651
652#ifdef CONFIG_ARCH_KIRKWOOD
653 {
654 .compatible = "marvell,kirkwood-core-clock",
655 .data = &kirkwood_core_clocks,
656 },
657 {
658 .compatible = "marvell,mv88f6180-core-clock",
659 .data = &mv88f6180_core_clocks,
660 },
661#endif
662
663 { }
664};
665
666void __init mvebu_core_clk_init(void)
667{
668 struct device_node *np;
669
670 for_each_matching_node(np, clk_core_match) {
671 const struct of_device_id *match =
672 of_match_node(clk_core_match, np);
673 mvebu_clk_core_setup(np, (struct core_clocks *)match->data);
674 }
675}
diff --git a/drivers/clk/mvebu/clk-core.h b/drivers/clk/mvebu/clk-core.h
new file mode 100644
index 000000000000..28b5e02e9885
--- /dev/null
+++ b/drivers/clk/mvebu/clk-core.h
@@ -0,0 +1,18 @@
1/*
2 * * Marvell EBU clock core handling defined at reset
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Gregory CLEMENT <gregory.clement@free-electrons.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#ifndef __MVEBU_CLK_CORE_H
14#define __MVEBU_CLK_CORE_H
15
16void __init mvebu_core_clk_init(void);
17
18#endif
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
new file mode 100644
index 000000000000..ff004578a119
--- /dev/null
+++ b/drivers/clk/mvebu/clk-cpu.c
@@ -0,0 +1,186 @@
1/*
2 * Marvell MVEBU CPU clock handling.
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Gregory CLEMENT <gregory.clement@free-electrons.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12#include <linux/kernel.h>
13#include <linux/clkdev.h>
14#include <linux/clk-provider.h>
15#include <linux/of_address.h>
16#include <linux/io.h>
17#include <linux/of.h>
18#include <linux/delay.h>
19#include "clk-cpu.h"
20
21#define SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET 0x0
22#define SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET 0xC
23#define SYS_CTRL_CLK_DIVIDER_MASK 0x3F
24
25#define MAX_CPU 4
26struct cpu_clk {
27 struct clk_hw hw;
28 int cpu;
29 const char *clk_name;
30 const char *parent_name;
31 void __iomem *reg_base;
32};
33
34static struct clk **clks;
35
36static struct clk_onecell_data clk_data;
37
38#define to_cpu_clk(p) container_of(p, struct cpu_clk, hw)
39
40static unsigned long clk_cpu_recalc_rate(struct clk_hw *hwclk,
41 unsigned long parent_rate)
42{
43 struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
44 u32 reg, div;
45
46 reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET);
47 div = (reg >> (cpuclk->cpu * 8)) & SYS_CTRL_CLK_DIVIDER_MASK;
48 return parent_rate / div;
49}
50
51static long clk_cpu_round_rate(struct clk_hw *hwclk, unsigned long rate,
52 unsigned long *parent_rate)
53{
54 /* Valid ratio are 1:1, 1:2 and 1:3 */
55 u32 div;
56
57 div = *parent_rate / rate;
58 if (div == 0)
59 div = 1;
60 else if (div > 3)
61 div = 3;
62
63 return *parent_rate / div;
64}
65
66static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate,
67 unsigned long parent_rate)
68{
69 struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
70 u32 reg, div;
71 u32 reload_mask;
72
73 div = parent_rate / rate;
74 reg = (readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET)
75 & (~(SYS_CTRL_CLK_DIVIDER_MASK << (cpuclk->cpu * 8))))
76 | (div << (cpuclk->cpu * 8));
77 writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET);
78 /* Set clock divider reload smooth bit mask */
79 reload_mask = 1 << (20 + cpuclk->cpu);
80
81 reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET)
82 | reload_mask;
83 writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
84
85 /* Now trigger the clock update */
86 reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET)
87 | 1 << 24;
88 writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
89
90 /* Wait for clocks to settle down then clear reload request */
91 udelay(1000);
92 reg &= ~(reload_mask | 1 << 24);
93 writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
94 udelay(1000);
95
96 return 0;
97}
98
99static const struct clk_ops cpu_ops = {
100 .recalc_rate = clk_cpu_recalc_rate,
101 .round_rate = clk_cpu_round_rate,
102 .set_rate = clk_cpu_set_rate,
103};
104
105void __init of_cpu_clk_setup(struct device_node *node)
106{
107 struct cpu_clk *cpuclk;
108 void __iomem *clock_complex_base = of_iomap(node, 0);
109 int ncpus = 0;
110 struct device_node *dn;
111
112 if (clock_complex_base == NULL) {
113 pr_err("%s: clock-complex base register not set\n",
114 __func__);
115 return;
116 }
117
118 for_each_node_by_type(dn, "cpu")
119 ncpus++;
120
121 cpuclk = kzalloc(ncpus * sizeof(*cpuclk), GFP_KERNEL);
122 if (WARN_ON(!cpuclk))
123 return;
124
125 clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL);
126 if (WARN_ON(!clks))
127 return;
128
129 for_each_node_by_type(dn, "cpu") {
130 struct clk_init_data init;
131 struct clk *clk;
132 struct clk *parent_clk;
133 char *clk_name = kzalloc(5, GFP_KERNEL);
134 int cpu, err;
135
136 if (WARN_ON(!clk_name))
137 return;
138
139 err = of_property_read_u32(dn, "reg", &cpu);
140 if (WARN_ON(err))
141 return;
142
143 sprintf(clk_name, "cpu%d", cpu);
144 parent_clk = of_clk_get(node, 0);
145
146 cpuclk[cpu].parent_name = __clk_get_name(parent_clk);
147 cpuclk[cpu].clk_name = clk_name;
148 cpuclk[cpu].cpu = cpu;
149 cpuclk[cpu].reg_base = clock_complex_base;
150 cpuclk[cpu].hw.init = &init;
151
152 init.name = cpuclk[cpu].clk_name;
153 init.ops = &cpu_ops;
154 init.flags = 0;
155 init.parent_names = &cpuclk[cpu].parent_name;
156 init.num_parents = 1;
157
158 clk = clk_register(NULL, &cpuclk[cpu].hw);
159 if (WARN_ON(IS_ERR(clk)))
160 goto bail_out;
161 clks[cpu] = clk;
162 }
163 clk_data.clk_num = MAX_CPU;
164 clk_data.clks = clks;
165 of_clk_add_provider(node, of_clk_src_onecell_get, &clk_data);
166
167 return;
168bail_out:
169 kfree(clks);
170 kfree(cpuclk);
171}
172
173static const __initconst struct of_device_id clk_cpu_match[] = {
174 {
175 .compatible = "marvell,armada-xp-cpu-clock",
176 .data = of_cpu_clk_setup,
177 },
178 {
179 /* sentinel */
180 },
181};
182
183void __init mvebu_cpu_clk_init(void)
184{
185 of_clk_init(clk_cpu_match);
186}
diff --git a/drivers/clk/mvebu/clk-cpu.h b/drivers/clk/mvebu/clk-cpu.h
new file mode 100644
index 000000000000..08e2affba4e6
--- /dev/null
+++ b/drivers/clk/mvebu/clk-cpu.h
@@ -0,0 +1,22 @@
1/*
2 * Marvell MVEBU CPU clock handling.
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Gregory CLEMENT <gregory.clement@free-electrons.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#ifndef __MVEBU_CLK_CPU_H
14#define __MVEBU_CLK_CPU_H
15
16#ifdef CONFIG_MVEBU_CLK_CPU
17void __init mvebu_cpu_clk_init(void);
18#else
19static inline void mvebu_cpu_clk_init(void) {}
20#endif
21
22#endif
diff --git a/drivers/clk/mvebu/clk-gating-ctrl.c b/drivers/clk/mvebu/clk-gating-ctrl.c
new file mode 100644
index 000000000000..c6d3c263b070
--- /dev/null
+++ b/drivers/clk/mvebu/clk-gating-ctrl.c
@@ -0,0 +1,249 @@
1/*
2 * Marvell MVEBU clock gating control.
3 *
4 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
5 * Andrew Lunn <andrew@lunn.ch>
6 *
7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any
9 * warranty of any kind, whether express or implied.
10 */
11#include <linux/kernel.h>
12#include <linux/bitops.h>
13#include <linux/io.h>
14#include <linux/clk.h>
15#include <linux/clkdev.h>
16#include <linux/clk-provider.h>
17#include <linux/clk/mvebu.h>
18#include <linux/of.h>
19#include <linux/of_address.h>
20
21struct mvebu_gating_ctrl {
22 spinlock_t lock;
23 struct clk **gates;
24 int num_gates;
25};
26
27struct mvebu_soc_descr {
28 const char *name;
29 const char *parent;
30 int bit_idx;
31};
32
33#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
34
35static struct clk __init *mvebu_clk_gating_get_src(
36 struct of_phandle_args *clkspec, void *data)
37{
38 struct mvebu_gating_ctrl *ctrl = (struct mvebu_gating_ctrl *)data;
39 int n;
40
41 if (clkspec->args_count < 1)
42 return ERR_PTR(-EINVAL);
43
44 for (n = 0; n < ctrl->num_gates; n++) {
45 struct clk_gate *gate =
46 to_clk_gate(__clk_get_hw(ctrl->gates[n]));
47 if (clkspec->args[0] == gate->bit_idx)
48 return ctrl->gates[n];
49 }
50 return ERR_PTR(-ENODEV);
51}
52
53static void __init mvebu_clk_gating_setup(
54 struct device_node *np, const struct mvebu_soc_descr *descr)
55{
56 struct mvebu_gating_ctrl *ctrl;
57 struct clk *clk;
58 void __iomem *base;
59 const char *default_parent = NULL;
60 int n;
61
62 base = of_iomap(np, 0);
63
64 clk = of_clk_get(np, 0);
65 if (!IS_ERR(clk)) {
66 default_parent = __clk_get_name(clk);
67 clk_put(clk);
68 }
69
70 ctrl = kzalloc(sizeof(struct mvebu_gating_ctrl), GFP_KERNEL);
71 if (WARN_ON(!ctrl))
72 return;
73
74 spin_lock_init(&ctrl->lock);
75
76 /*
77 * Count, allocate, and register clock gates
78 */
79 for (n = 0; descr[n].name;)
80 n++;
81
82 ctrl->num_gates = n;
83 ctrl->gates = kzalloc(ctrl->num_gates * sizeof(struct clk *),
84 GFP_KERNEL);
85 if (WARN_ON(!ctrl->gates)) {
86 kfree(ctrl);
87 return;
88 }
89
90 for (n = 0; n < ctrl->num_gates; n++) {
91 u8 flags = 0;
92 const char *parent =
93 (descr[n].parent) ? descr[n].parent : default_parent;
94
95 /*
96 * On Armada 370, the DDR clock is a special case: it
97 * isn't taken by any driver, but should anyway be
98 * kept enabled, so we mark it as IGNORE_UNUSED for
99 * now.
100 */
101 if (!strcmp(descr[n].name, "ddr"))
102 flags |= CLK_IGNORE_UNUSED;
103
104 ctrl->gates[n] = clk_register_gate(NULL, descr[n].name, parent,
105 flags, base, descr[n].bit_idx, 0, &ctrl->lock);
106 WARN_ON(IS_ERR(ctrl->gates[n]));
107 }
108 of_clk_add_provider(np, mvebu_clk_gating_get_src, ctrl);
109}
110
111/*
112 * SoC specific clock gating control
113 */
114
115#ifdef CONFIG_MACH_ARMADA_370
116static const struct mvebu_soc_descr __initconst armada_370_gating_descr[] = {
117 { "audio", NULL, 0 },
118 { "pex0_en", NULL, 1 },
119 { "pex1_en", NULL, 2 },
120 { "ge1", NULL, 3 },
121 { "ge0", NULL, 4 },
122 { "pex0", NULL, 5 },
123 { "pex1", NULL, 9 },
124 { "sata0", NULL, 15 },
125 { "sdio", NULL, 17 },
126 { "tdm", NULL, 25 },
127 { "ddr", NULL, 28 },
128 { "sata1", NULL, 30 },
129 { }
130};
131#endif
132
133#ifdef CONFIG_MACH_ARMADA_XP
134static const struct mvebu_soc_descr __initconst armada_xp_gating_descr[] = {
135 { "audio", NULL, 0 },
136 { "ge3", NULL, 1 },
137 { "ge2", NULL, 2 },
138 { "ge1", NULL, 3 },
139 { "ge0", NULL, 4 },
140 { "pex0", NULL, 5 },
141 { "pex1", NULL, 6 },
142 { "pex2", NULL, 7 },
143 { "pex3", NULL, 8 },
144 { "bp", NULL, 13 },
145 { "sata0lnk", NULL, 14 },
146 { "sata0", "sata0lnk", 15 },
147 { "lcd", NULL, 16 },
148 { "sdio", NULL, 17 },
149 { "usb0", NULL, 18 },
150 { "usb1", NULL, 19 },
151 { "usb2", NULL, 20 },
152 { "xor0", NULL, 22 },
153 { "crypto", NULL, 23 },
154 { "tdm", NULL, 25 },
155 { "xor1", NULL, 28 },
156 { "sata1lnk", NULL, 29 },
157 { "sata1", "sata1lnk", 30 },
158 { }
159};
160#endif
161
162#ifdef CONFIG_ARCH_DOVE
163static const struct mvebu_soc_descr __initconst dove_gating_descr[] = {
164 { "usb0", NULL, 0 },
165 { "usb1", NULL, 1 },
166 { "ge", "gephy", 2 },
167 { "sata", NULL, 3 },
168 { "pex0", NULL, 4 },
169 { "pex1", NULL, 5 },
170 { "sdio0", NULL, 8 },
171 { "sdio1", NULL, 9 },
172 { "nand", NULL, 10 },
173 { "camera", NULL, 11 },
174 { "i2s0", NULL, 12 },
175 { "i2s1", NULL, 13 },
176 { "crypto", NULL, 15 },
177 { "ac97", NULL, 21 },
178 { "pdma", NULL, 22 },
179 { "xor0", NULL, 23 },
180 { "xor1", NULL, 24 },
181 { "gephy", NULL, 30 },
182 { }
183};
184#endif
185
186#ifdef CONFIG_ARCH_KIRKWOOD
187static const struct mvebu_soc_descr __initconst kirkwood_gating_descr[] = {
188 { "ge0", NULL, 0 },
189 { "pex0", NULL, 2 },
190 { "usb0", NULL, 3 },
191 { "sdio", NULL, 4 },
192 { "tsu", NULL, 5 },
193 { "runit", NULL, 7 },
194 { "xor0", NULL, 8 },
195 { "audio", NULL, 9 },
196 { "sata0", NULL, 14 },
197 { "sata1", NULL, 15 },
198 { "xor1", NULL, 16 },
199 { "crypto", NULL, 17 },
200 { "pex1", NULL, 18 },
201 { "ge1", NULL, 19 },
202 { "tdm", NULL, 20 },
203 { }
204};
205#endif
206
207static const __initdata struct of_device_id clk_gating_match[] = {
208#ifdef CONFIG_MACH_ARMADA_370
209 {
210 .compatible = "marvell,armada-370-gating-clock",
211 .data = armada_370_gating_descr,
212 },
213#endif
214
215#ifdef CONFIG_MACH_ARMADA_XP
216 {
217 .compatible = "marvell,armada-xp-gating-clock",
218 .data = armada_xp_gating_descr,
219 },
220#endif
221
222#ifdef CONFIG_ARCH_DOVE
223 {
224 .compatible = "marvell,dove-gating-clock",
225 .data = dove_gating_descr,
226 },
227#endif
228
229#ifdef CONFIG_ARCH_KIRKWOOD
230 {
231 .compatible = "marvell,kirkwood-gating-clock",
232 .data = kirkwood_gating_descr,
233 },
234#endif
235
236 { }
237};
238
239void __init mvebu_gating_clk_init(void)
240{
241 struct device_node *np;
242
243 for_each_matching_node(np, clk_gating_match) {
244 const struct of_device_id *match =
245 of_match_node(clk_gating_match, np);
246 mvebu_clk_gating_setup(np,
247 (const struct mvebu_soc_descr *)match->data);
248 }
249}
diff --git a/drivers/clk/mvebu/clk-gating-ctrl.h b/drivers/clk/mvebu/clk-gating-ctrl.h
new file mode 100644
index 000000000000..9275d1e51f1b
--- /dev/null
+++ b/drivers/clk/mvebu/clk-gating-ctrl.h
@@ -0,0 +1,22 @@
1/*
2 * Marvell EBU gating clock handling
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#ifndef __MVEBU_CLK_GATING_H
14#define __MVEBU_CLK_GATING_H
15
16#ifdef CONFIG_MVEBU_CLK_GATING
17void __init mvebu_gating_clk_init(void);
18#else
19void mvebu_gating_clk_init(void) {}
20#endif
21
22#endif
diff --git a/drivers/clk/mvebu/clk.c b/drivers/clk/mvebu/clk.c
new file mode 100644
index 000000000000..855681b8a9dc
--- /dev/null
+++ b/drivers/clk/mvebu/clk.c
@@ -0,0 +1,27 @@
1/*
2 * Marvell EBU SoC clock handling.
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Gregory CLEMENT <gregory.clement@free-electrons.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12#include <linux/kernel.h>
13#include <linux/clk.h>
14#include <linux/clk-provider.h>
15#include <linux/of_address.h>
16#include <linux/clk/mvebu.h>
17#include <linux/of.h>
18#include "clk-core.h"
19#include "clk-cpu.h"
20#include "clk-gating-ctrl.h"
21
22void __init mvebu_clocks_init(void)
23{
24 mvebu_core_clk_init();
25 mvebu_gating_clk_init();
26 mvebu_cpu_clk_init();
27}
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
index 4674f94957cd..a4605fd7e303 100644
--- a/drivers/clocksource/time-armada-370-xp.c
+++ b/drivers/clocksource/time-armada-370-xp.c
@@ -18,6 +18,7 @@
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/clk.h>
21#include <linux/timer.h> 22#include <linux/timer.h>
22#include <linux/clockchips.h> 23#include <linux/clockchips.h>
23#include <linux/interrupt.h> 24#include <linux/interrupt.h>
@@ -167,7 +168,6 @@ void __init armada_370_xp_timer_init(void)
167 u32 u; 168 u32 u;
168 struct device_node *np; 169 struct device_node *np;
169 unsigned int timer_clk; 170 unsigned int timer_clk;
170 int ret;
171 np = of_find_compatible_node(NULL, NULL, "marvell,armada-370-xp-timer"); 171 np = of_find_compatible_node(NULL, NULL, "marvell,armada-370-xp-timer");
172 timer_base = of_iomap(np, 0); 172 timer_base = of_iomap(np, 0);
173 WARN_ON(!timer_base); 173 WARN_ON(!timer_base);
@@ -179,13 +179,14 @@ void __init armada_370_xp_timer_init(void)
179 timer_base + TIMER_CTRL_OFF); 179 timer_base + TIMER_CTRL_OFF);
180 timer_clk = 25000000; 180 timer_clk = 25000000;
181 } else { 181 } else {
182 u32 clk = 0; 182 unsigned long rate = 0;
183 ret = of_property_read_u32(np, "clock-frequency", &clk); 183 struct clk *clk = of_clk_get(np, 0);
184 WARN_ON(!clk || ret < 0); 184 WARN_ON(IS_ERR(clk));
185 rate = clk_get_rate(clk);
185 u = readl(timer_base + TIMER_CTRL_OFF); 186 u = readl(timer_base + TIMER_CTRL_OFF);
186 writel(u & ~(TIMER0_25MHZ | TIMER1_25MHZ), 187 writel(u & ~(TIMER0_25MHZ | TIMER1_25MHZ),
187 timer_base + TIMER_CTRL_OFF); 188 timer_base + TIMER_CTRL_OFF);
188 timer_clk = clk / TIMER_DIVIDER; 189 timer_clk = rate / TIMER_DIVIDER;
189 } 190 }
190 191
191 /* We use timer 0 as clocksource, and timer 1 for 192 /* We use timer 0 as clocksource, and timer 1 for
diff --git a/include/linux/clk/mvebu.h b/include/linux/clk/mvebu.h
new file mode 100644
index 000000000000..8c4ae713b063
--- /dev/null
+++ b/include/linux/clk/mvebu.h
@@ -0,0 +1,22 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 */
16
17#ifndef __CLK_MVEBU_H_
18#define __CLK_MVEBU_H_
19
20void __init mvebu_clocks_init(void);
21
22#endif