diff options
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 | ||
| 9 | Optional properties: | 10 | Optional 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 | |||
| 3 | Marvell MVEBU SoCs usually allow to determine core clock frequencies by | ||
| 4 | reading the Sample-At-Reset (SAR) register. The core clock consumer should | ||
| 5 | specify the desired clock by having the clock ID in its "clocks" phandle cell. | ||
| 6 | |||
| 7 | The 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 | |||
| 14 | The 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 | |||
| 20 | Required 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 | |||
| 30 | Optional properties: | ||
| 31 | - clock-output-names : from common clock binding; allows overwrite default clock | ||
| 32 | output names ("tclk", "cpuclk", "l2clk", "ddrclk") | ||
| 33 | |||
| 34 | Example: | ||
| 35 | |||
| 36 | core_clk: core-clocks@d0214 { | ||
| 37 | compatible = "marvell,dove-core-clock"; | ||
| 38 | reg = <0xd0214 0x4>; | ||
| 39 | #clock-cells = <1>; | ||
| 40 | }; | ||
| 41 | |||
| 42 | spi0: 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 @@ | |||
| 1 | Device Tree Clock bindings for cpu clock of Marvell EBU platforms | ||
| 2 | |||
| 3 | Required 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 | |||
| 10 | cpuclk: clock-complex@d0018700 { | ||
| 11 | #clock-cells = <1>; | ||
| 12 | compatible = "marvell,armada-xp-cpu-clock"; | ||
| 13 | reg = <0xd0018700 0xA0>; | ||
| 14 | clocks = <&coreclk 1>; | ||
| 15 | } | ||
| 16 | |||
| 17 | cpu@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 | |||
| 3 | Marvell Dove and Kirkwood allow some peripheral clocks to be gated to save | ||
| 4 | some power. The clock consumer should specify the desired clock by having | ||
| 5 | the clock ID in its "clocks" phandle cell. The clock ID is directly mapped to | ||
| 6 | the corresponding clock gating control bit in HW to ease manual clock lookup | ||
| 7 | in datasheet. | ||
| 8 | |||
| 9 | The following is a list of provided IDs for Armada 370: | ||
| 10 | ID Clock Peripheral | ||
| 11 | ----------------------------------- | ||
| 12 | 0 Audio AC97 Cntrl | ||
| 13 | 1 pex0_en PCIe 0 Clock out | ||
| 14 | 2 pex1_en PCIe 1 Clock out | ||
| 15 | 3 ge1 Gigabit Ethernet 1 | ||
| 16 | 4 ge0 Gigabit Ethernet 0 | ||
| 17 | 5 pex0 PCIe Cntrl 0 | ||
| 18 | 9 pex1 PCIe Cntrl 1 | ||
| 19 | 15 sata0 SATA Host 0 | ||
| 20 | 17 sdio SDHCI Host | ||
| 21 | 25 tdm Time Division Mplx | ||
| 22 | 28 ddr DDR Cntrl | ||
| 23 | 30 sata1 SATA Host 0 | ||
| 24 | |||
| 25 | The following is a list of provided IDs for Armada XP: | ||
| 26 | ID Clock Peripheral | ||
| 27 | ----------------------------------- | ||
| 28 | 0 audio Audio Cntrl | ||
| 29 | 1 ge3 Gigabit Ethernet 3 | ||
| 30 | 2 ge2 Gigabit Ethernet 2 | ||
| 31 | 3 ge1 Gigabit Ethernet 1 | ||
| 32 | 4 ge0 Gigabit Ethernet 0 | ||
| 33 | 5 pex0 PCIe Cntrl 0 | ||
| 34 | 6 pex1 PCIe Cntrl 1 | ||
| 35 | 7 pex2 PCIe Cntrl 2 | ||
| 36 | 8 pex3 PCIe Cntrl 3 | ||
| 37 | 13 bp | ||
| 38 | 14 sata0lnk | ||
| 39 | 15 sata0 SATA Host 0 | ||
| 40 | 16 lcd LCD Cntrl | ||
| 41 | 17 sdio SDHCI Host | ||
| 42 | 18 usb0 USB Host 0 | ||
| 43 | 19 usb1 USB Host 1 | ||
| 44 | 20 usb2 USB Host 2 | ||
| 45 | 22 xor0 XOR DMA 0 | ||
| 46 | 23 crypto CESA engine | ||
| 47 | 25 tdm Time Division Mplx | ||
| 48 | 28 xor1 XOR DMA 1 | ||
| 49 | 29 sata1lnk | ||
| 50 | 30 sata1 SATA Host 0 | ||
| 51 | |||
| 52 | The following is a list of provided IDs for Dove: | ||
| 53 | ID Clock Peripheral | ||
| 54 | ----------------------------------- | ||
| 55 | 0 usb0 USB Host 0 | ||
| 56 | 1 usb1 USB Host 1 | ||
| 57 | 2 ge Gigabit Ethernet | ||
| 58 | 3 sata SATA Host | ||
| 59 | 4 pex0 PCIe Cntrl 0 | ||
| 60 | 5 pex1 PCIe Cntrl 1 | ||
| 61 | 8 sdio0 SDHCI Host 0 | ||
| 62 | 9 sdio1 SDHCI Host 1 | ||
| 63 | 10 nand NAND Cntrl | ||
| 64 | 11 camera Camera Cntrl | ||
| 65 | 12 i2s0 I2S Cntrl 0 | ||
| 66 | 13 i2s1 I2S Cntrl 1 | ||
| 67 | 15 crypto CESA engine | ||
| 68 | 21 ac97 AC97 Cntrl | ||
| 69 | 22 pdma Peripheral DMA | ||
| 70 | 23 xor0 XOR DMA 0 | ||
| 71 | 24 xor1 XOR DMA 1 | ||
| 72 | 30 gephy Gigabit Ethernel PHY | ||
| 73 | Note: gephy(30) is implemented as a parent clock of ge(2) | ||
| 74 | |||
| 75 | The following is a list of provided IDs for Kirkwood: | ||
| 76 | ID Clock Peripheral | ||
| 77 | ----------------------------------- | ||
| 78 | 0 ge0 Gigabit Ethernet 0 | ||
| 79 | 2 pex0 PCIe Cntrl 0 | ||
| 80 | 3 usb0 USB Host 0 | ||
| 81 | 4 sdio SDIO Cntrl | ||
| 82 | 5 tsu Transp. Stream Unit | ||
| 83 | 6 dunit SDRAM Cntrl | ||
| 84 | 7 runit Runit | ||
| 85 | 8 xor0 XOR DMA 0 | ||
| 86 | 9 audio I2S Cntrl 0 | ||
| 87 | 14 sata0 SATA Host 0 | ||
| 88 | 15 sata1 SATA Host 1 | ||
| 89 | 16 xor1 XOR DMA 1 | ||
| 90 | 17 crypto CESA engine | ||
| 91 | 18 pex1 PCIe Cntrl 1 | ||
| 92 | 19 ge1 Gigabit Ethernet 0 | ||
| 93 | 20 tdm Time Division Mplx | ||
| 94 | |||
| 95 | Required 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 | |||
| 102 | Optional properties: | ||
| 103 | - clocks : default parent clock phandle (e.g. tclk) | ||
| 104 | |||
| 105 | Example: | ||
| 106 | |||
| 107 | gate_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 | |||
| 115 | sdio0: 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 | |||
| 533 | config ARCH_DOVE | 533 | config 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 | ||
| 18 | config MACH_DOVE_DT | 18 | config 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 | */ |
| 381 | struct of_dev_auxdata dove_auxdata_lookup[] __initdata = { | 383 | static 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 | |||
| 421 | static void __init dove_of_clk_init(void) | ||
| 422 | { | ||
| 423 | mvebu_clocks_init(); | ||
| 424 | dove_legacy_clk_init(); | ||
| 425 | } | ||
| 392 | 426 | ||
| 393 | static struct mv643xx_eth_platform_data dove_dt_ge00_data = { | 427 | static 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 | ||
| 424 | static const char * const dove_dt_board_compat[] = { | 457 | static 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 | ||
| 47 | config ARCH_KIRKWOOD_DT | 47 | config 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 | ||
| 24 | static struct of_device_id kirkwood_dt_match_table[] __initdata = { | 28 | static 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 | ||
| 29 | struct 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), | 39 | static 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 | |||
| 80 | static void __init kirkwood_of_clk_init(void) | ||
| 81 | { | ||
| 82 | mvebu_clocks_init(); | ||
| 83 | kirkwood_legacy_clk_init(); | ||
| 84 | } | ||
| 39 | 85 | ||
| 40 | static void __init kirkwood_dt_init(void) | 86 | static 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 | ||
| 101 | static const char *kirkwood_dt_board_compat[] = { | 146 | static 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 | ||
| 13 | if ARCH_MVEBU | 17 | if 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 | ||
| 41 | void __init armada_370_xp_timer_and_clk_init(void) | ||
| 42 | { | ||
| 43 | mvebu_clocks_init(); | ||
| 44 | armada_370_xp_timer_init(); | ||
| 45 | } | ||
| 46 | |||
| 40 | struct sys_timer armada_370_xp_timer = { | 47 | struct 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 | ||
| 44 | static void __init armada_370_xp_dt_init(void) | 51 | static 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 | ||
| 14 | struct dsa_platform_data; | 14 | struct dsa_platform_data; |
| 15 | struct mv_sata_platform_data; | ||
| 15 | 16 | ||
| 16 | void __init orion_uart0_init(void __iomem *membase, | 17 | void __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 | ||
| 56 | endmenu | 56 | endmenu |
| 57 | |||
| 58 | source "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/ | |||
| 13 | obj-$(CONFIG_ARCH_U300) += clk-u300.o | 13 | obj-$(CONFIG_ARCH_U300) += clk-u300.o |
| 14 | obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/ | 14 | obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/ |
| 15 | obj-$(CONFIG_ARCH_PRIMA2) += clk-prima2.o | 15 | obj-$(CONFIG_ARCH_PRIMA2) += clk-prima2.o |
| 16 | obj-$(CONFIG_PLAT_ORION) += mvebu/ | ||
| 16 | ifeq ($(CONFIG_COMMON_CLK), y) | 17 | ifeq ($(CONFIG_COMMON_CLK), y) |
| 17 | obj-$(CONFIG_ARCH_MMP) += mmp/ | 18 | obj-$(CONFIG_ARCH_MMP) += mmp/ |
| 18 | endif | 19 | endif |
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 @@ | |||
| 1 | config MVEBU_CLK_CORE | ||
| 2 | bool | ||
| 3 | |||
| 4 | config MVEBU_CLK_CPU | ||
| 5 | bool | ||
| 6 | |||
| 7 | config 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 @@ | |||
| 1 | obj-$(CONFIG_MVEBU_CLK_CORE) += clk.o clk-core.o | ||
| 2 | obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o | ||
| 3 | obj-$(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 | |||
| 22 | struct core_ratio { | ||
| 23 | int id; | ||
| 24 | const char *name; | ||
| 25 | }; | ||
| 26 | |||
| 27 | struct 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 | |||
| 35 | static struct clk_onecell_data clk_data; | ||
| 36 | |||
| 37 | static 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 | |||
| 128 | static const u32 __initconst armada_370_tclk_frequencies[] = { | ||
| 129 | 16600000, | ||
| 130 | 20000000, | ||
| 131 | }; | ||
| 132 | |||
| 133 | static 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 | |||
| 142 | static const u32 __initconst armada_370_cpu_frequencies[] = { | ||
| 143 | 400000000, | ||
| 144 | 533000000, | ||
| 145 | 667000000, | ||
| 146 | 800000000, | ||
| 147 | 1000000000, | ||
| 148 | 1067000000, | ||
| 149 | 1200000000, | ||
| 150 | }; | ||
| 151 | |||
| 152 | static 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 | |||
| 168 | enum { A370_XP_NBCLK, A370_XP_HCLK, A370_XP_DRAMCLK }; | ||
| 169 | |||
| 170 | static 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 | |||
| 176 | static 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 | |||
| 187 | static 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 | |||
| 198 | static 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 | |||
| 209 | static 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 | |||
| 228 | static 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 | |||
| 238 | static 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 | |||
| 246 | static 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 */ | ||
| 262 | static u32 __init armada_xp_get_tclk_freq(void __iomem *sar) | ||
| 263 | { | ||
| 264 | return 250 * 1000 * 1000; | ||
| 265 | } | ||
| 266 | |||
| 267 | static 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 | |||
| 290 | static 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 | |||
| 307 | static 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 | |||
| 369 | static const u32 __initconst dove_tclk_frequencies[] = { | ||
| 370 | 166666667, | ||
| 371 | 125000000, | ||
| 372 | 0, 0 | ||
| 373 | }; | ||
| 374 | |||
| 375 | static 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 | |||
| 382 | static 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 | |||
| 394 | static 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 | |||
| 401 | enum { DOVE_CPU_TO_L2, DOVE_CPU_TO_DDR }; | ||
| 402 | |||
| 403 | static 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 | |||
| 408 | static 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 | |||
| 413 | static 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 | |||
| 420 | static 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 | |||
| 443 | static 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 | |||
| 508 | enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR }; | ||
| 509 | |||
| 510 | static 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 | |||
| 515 | static 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 | |||
| 522 | static 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 | |||
| 537 | static 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 | |||
| 543 | static 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 | |||
| 548 | static 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 | |||
| 555 | static 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 | |||
| 577 | static 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 | |||
| 585 | static const u32 __initconst mv88f6180_cpu_frequencies[] = { | ||
| 586 | 0, 0, 0, 0, 0, | ||
| 587 | 600000000, | ||
| 588 | 800000000, | ||
| 589 | 1000000000 | ||
| 590 | }; | ||
| 591 | |||
| 592 | static 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 | |||
| 598 | static 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 | |||
| 603 | static 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 | |||
| 625 | static 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 | |||
| 634 | static 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 | |||
| 666 | void __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 | |||
| 16 | void __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 | ||
| 26 | struct 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 | |||
| 34 | static struct clk **clks; | ||
| 35 | |||
| 36 | static struct clk_onecell_data clk_data; | ||
| 37 | |||
| 38 | #define to_cpu_clk(p) container_of(p, struct cpu_clk, hw) | ||
| 39 | |||
| 40 | static 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 | |||
| 51 | static 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 | |||
| 66 | static 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 | |||
| 99 | static 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 | |||
| 105 | void __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; | ||
| 168 | bail_out: | ||
| 169 | kfree(clks); | ||
| 170 | kfree(cpuclk); | ||
| 171 | } | ||
| 172 | |||
| 173 | static 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 | |||
| 183 | void __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 | ||
| 17 | void __init mvebu_cpu_clk_init(void); | ||
| 18 | #else | ||
| 19 | static 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 | |||
| 21 | struct mvebu_gating_ctrl { | ||
| 22 | spinlock_t lock; | ||
| 23 | struct clk **gates; | ||
| 24 | int num_gates; | ||
| 25 | }; | ||
| 26 | |||
| 27 | struct 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 | |||
| 35 | static 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 | |||
| 53 | static 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 | ||
| 116 | static 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 | ||
| 134 | static 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 | ||
| 163 | static 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 | ||
| 187 | static 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 | |||
| 207 | static 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 | |||
| 239 | void __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 | ||
| 17 | void __init mvebu_gating_clk_init(void); | ||
| 18 | #else | ||
| 19 | void 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 | |||
| 22 | void __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 | |||
| 20 | void __init mvebu_clocks_init(void); | ||
| 21 | |||
| 22 | #endif | ||
