diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-05 21:39:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-05 21:39:18 -0400 |
commit | 19bc2eec3cbf9a282b592749a93ec9027d352bf2 (patch) | |
tree | bc7cff4dfebf2b256e62280bb006a494e967d4b2 | |
parent | 9712d3c377a9868355ea9a611aca3c54f88dc576 (diff) | |
parent | e44df332f30bf3040c60c1ed6674d1431fdb48b9 (diff) |
Merge tag 'clk-for-linus-3.15' of git://git.linaro.org/people/mike.turquette/linux
Pull clock framework changes from Mike Turquette:
"The clock framework changes for 3.15 look similar to past pull
requests. Mostly clock driver updates, more Device Tree support in
the form of common functions useful across platforms and a handful of
features and fixes to the framework core"
* tag 'clk-for-linus-3.15' of git://git.linaro.org/people/mike.turquette/linux: (86 commits)
clk: shmobile: fix setting paretn clock rate
clk: shmobile: rcar-gen2: fix lb/sd0/sd1/sdh clock parent to pll1
clk: Fix minor errors in of_clk_init() function comments
clk: reverse default clk provider initialization order in of_clk_init()
clk: sirf: update copyright years to 2014
clk: mmp: try to use closer one when do round rate
clk: mmp: fix the wrong calculation formula
clk: mmp: fix wrong mask when calculate denominator
clk: st: Adds quadfs clock binding
clk: st: Adds clockgen-vcc and clockgen-mux clock binding
clk: st: Adds clockgen clock binding
clk: st: Adds divmux and prediv clock binding
clk: st: Support for A9 MUX clocks
clk: st: Support for ClockGenA9/DDR/GPU
clk: st: Support for QUADFS inside ClockGenB/C/D/E/F
clk: st: Support for VCC-mux and MUX clocks
clk: st: Support for PLLs inside ClockGenA(s)
clk: st: Support for DIVMUX and PreDiv Clocks
clk: support hardware-specific debugfs entries
clk: s2mps11: Use of_get_child_by_name
...
74 files changed, 5882 insertions, 733 deletions
diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 699ef2a323b1..c9c399af7c08 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt | |||
@@ -255,3 +255,37 @@ are sorted out. | |||
255 | 255 | ||
256 | To bypass this disabling, include "clk_ignore_unused" in the bootargs to the | 256 | To bypass this disabling, include "clk_ignore_unused" in the bootargs to the |
257 | kernel. | 257 | kernel. |
258 | |||
259 | Part 7 - Locking | ||
260 | |||
261 | The common clock framework uses two global locks, the prepare lock and the | ||
262 | enable lock. | ||
263 | |||
264 | The enable lock is a spinlock and is held across calls to the .enable, | ||
265 | .disable and .is_enabled operations. Those operations are thus not allowed to | ||
266 | sleep, and calls to the clk_enable(), clk_disable() and clk_is_enabled() API | ||
267 | functions are allowed in atomic context. | ||
268 | |||
269 | The prepare lock is a mutex and is held across calls to all other operations. | ||
270 | All those operations are allowed to sleep, and calls to the corresponding API | ||
271 | functions are not allowed in atomic context. | ||
272 | |||
273 | This effectively divides operations in two groups from a locking perspective. | ||
274 | |||
275 | Drivers don't need to manually protect resources shared between the operations | ||
276 | of one group, regardless of whether those resources are shared by multiple | ||
277 | clocks or not. However, access to resources that are shared between operations | ||
278 | of the two groups needs to be protected by the drivers. An example of such a | ||
279 | resource would be a register that controls both the clock rate and the clock | ||
280 | enable/disable state. | ||
281 | |||
282 | The clock framework is reentrant, in that a driver is allowed to call clock | ||
283 | framework functions from within its implementation of clock operations. This | ||
284 | can for instance cause a .set_rate operation of one clock being called from | ||
285 | within the .set_rate operation of another clock. This case must be considered | ||
286 | in the driver implementations, but the code flow is usually controlled by the | ||
287 | driver in that case. | ||
288 | |||
289 | Note that locking must also be considered when code outside of the common | ||
290 | clock framework needs to access resources used by the clock operations. This | ||
291 | is considered out of scope of this document. | ||
diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt index 8c7a4653508d..df0a452b8526 100644 --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt | |||
@@ -30,3 +30,17 @@ Example: | |||
30 | resume-offset = <0x308>; | 30 | resume-offset = <0x308>; |
31 | reboot-offset = <0x4>; | 31 | reboot-offset = <0x4>; |
32 | }; | 32 | }; |
33 | |||
34 | PCTRL: Peripheral misc control register | ||
35 | |||
36 | Required Properties: | ||
37 | - compatible: "hisilicon,pctrl" | ||
38 | - reg: Address and size of pctrl. | ||
39 | |||
40 | Example: | ||
41 | |||
42 | /* for Hi3620 */ | ||
43 | pctrl: pctrl@fca09000 { | ||
44 | compatible = "hisilicon,pctrl"; | ||
45 | reg = <0xfca09000 0x1000>; | ||
46 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/altr_socfpga.txt b/Documentation/devicetree/bindings/clock/altr_socfpga.txt index 0045433eae1f..5dfd145d3ccf 100644 --- a/Documentation/devicetree/bindings/clock/altr_socfpga.txt +++ b/Documentation/devicetree/bindings/clock/altr_socfpga.txt | |||
@@ -23,3 +23,8 @@ Optional properties: | |||
23 | and the bit index. | 23 | and the bit index. |
24 | - div-reg : For "socfpga-gate-clk", div-reg contains the divider register, bit shift, | 24 | - div-reg : For "socfpga-gate-clk", div-reg contains the divider register, bit shift, |
25 | and width. | 25 | and width. |
26 | - clk-phase : For the sdmmc_clk, contains the value of the clock phase that controls | ||
27 | the SDMMC CIU clock. The first value is the clk_sample(smpsel), and the second | ||
28 | value is the cclk_in_drv(drvsel). The clk-phase is used to enable the correct | ||
29 | hold/delay times that is needed for the SD/MMC CIU clock. The values of both | ||
30 | can be 0-315 degrees, in 45 degree increments. | ||
diff --git a/Documentation/devicetree/bindings/clock/axi-clkgen.txt b/Documentation/devicetree/bindings/clock/axi-clkgen.txt index 028b493e97ff..20e1704e7df2 100644 --- a/Documentation/devicetree/bindings/clock/axi-clkgen.txt +++ b/Documentation/devicetree/bindings/clock/axi-clkgen.txt | |||
@@ -5,7 +5,7 @@ This binding uses the common clock binding[1]. | |||
5 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | 5 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt |
6 | 6 | ||
7 | Required properties: | 7 | Required properties: |
8 | - compatible : shall be "adi,axi-clkgen". | 8 | - compatible : shall be "adi,axi-clkgen-1.00.a" or "adi,axi-clkgen-2.00.a". |
9 | - #clock-cells : from common clock binding; Should always be set to 0. | 9 | - #clock-cells : from common clock binding; Should always be set to 0. |
10 | - reg : Address and length of the axi-clkgen register set. | 10 | - reg : Address and length of the axi-clkgen register set. |
11 | - clocks : Phandle and clock specifier for the parent clock. | 11 | - clocks : Phandle and clock specifier for the parent clock. |
diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt index 7c52c29d99fa..700e7aac3717 100644 --- a/Documentation/devicetree/bindings/clock/clock-bindings.txt +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt | |||
@@ -44,6 +44,23 @@ For example: | |||
44 | clocks by index. The names should reflect the clock output signal | 44 | clocks by index. The names should reflect the clock output signal |
45 | names for the device. | 45 | names for the device. |
46 | 46 | ||
47 | clock-indices: If the identifyng number for the clocks in the node | ||
48 | is not linear from zero, then the this mapping allows | ||
49 | the mapping of identifiers into the clock-output-names | ||
50 | array. | ||
51 | |||
52 | For example, if we have two clocks <&oscillator 1> and <&oscillator 3>: | ||
53 | |||
54 | oscillator { | ||
55 | compatible = "myclocktype"; | ||
56 | #clock-cells = <1>; | ||
57 | clock-indices = <1>, <3>; | ||
58 | clock-output-names = "clka", "clkb"; | ||
59 | } | ||
60 | |||
61 | This ensures we do not have any empty nodes in clock-output-names | ||
62 | |||
63 | |||
47 | ==Clock consumers== | 64 | ==Clock consumers== |
48 | 65 | ||
49 | Required properties: | 66 | Required properties: |
diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt b/Documentation/devicetree/bindings/clock/hi3620-clock.txt index 4b71ab41be53..dad6269f52c5 100644 --- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt +++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt | |||
@@ -7,6 +7,7 @@ Required Properties: | |||
7 | 7 | ||
8 | - compatible: should be one of the following. | 8 | - compatible: should be one of the following. |
9 | - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC. | 9 | - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC. |
10 | - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc. | ||
10 | 11 | ||
11 | - reg: physical base address of the controller and length of memory mapped | 12 | - reg: physical base address of the controller and length of memory mapped |
12 | region. | 13 | region. |
diff --git a/Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt b/Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt new file mode 100644 index 000000000000..fedea84314a1 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt | |||
@@ -0,0 +1,48 @@ | |||
1 | Device Tree Clock bindings for arch-moxart | ||
2 | |||
3 | This binding uses the common clock binding[1]. | ||
4 | |||
5 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
6 | |||
7 | MOXA ART SoCs allow to determine PLL output and APB frequencies | ||
8 | by reading registers holding multiplier and divisor information. | ||
9 | |||
10 | |||
11 | PLL: | ||
12 | |||
13 | Required properties: | ||
14 | - compatible : Must be "moxa,moxart-pll-clock" | ||
15 | - #clock-cells : Should be 0 | ||
16 | - reg : Should contain registers location and length | ||
17 | - clocks : Should contain phandle + clock-specifier for the parent clock | ||
18 | |||
19 | Optional properties: | ||
20 | - clock-output-names : Should contain clock name | ||
21 | |||
22 | |||
23 | APB: | ||
24 | |||
25 | Required properties: | ||
26 | - compatible : Must be "moxa,moxart-apb-clock" | ||
27 | - #clock-cells : Should be 0 | ||
28 | - reg : Should contain registers location and length | ||
29 | - clocks : Should contain phandle + clock-specifier for the parent clock | ||
30 | |||
31 | Optional properties: | ||
32 | - clock-output-names : Should contain clock name | ||
33 | |||
34 | |||
35 | For example: | ||
36 | |||
37 | clk_pll: clk_pll@98100000 { | ||
38 | compatible = "moxa,moxart-pll-clock"; | ||
39 | #clock-cells = <0>; | ||
40 | reg = <0x98100000 0x34>; | ||
41 | }; | ||
42 | |||
43 | clk_apb: clk_apb@98100000 { | ||
44 | compatible = "moxa,moxart-apb-clock"; | ||
45 | #clock-cells = <0>; | ||
46 | reg = <0x98100000 0x34>; | ||
47 | clocks = <&clk_pll>; | ||
48 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt index 1e662948661e..307a503c5db8 100644 --- a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt +++ b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt | |||
@@ -11,6 +11,18 @@ The following is a list of provided IDs and clock names on Armada 370/XP: | |||
11 | 3 = hclk (DRAM control clock) | 11 | 3 = hclk (DRAM control clock) |
12 | 4 = dramclk (DDR clock) | 12 | 4 = dramclk (DDR clock) |
13 | 13 | ||
14 | The following is a list of provided IDs and clock names on Armada 375: | ||
15 | 0 = tclk (Internal Bus clock) | ||
16 | 1 = cpuclk (CPU clock) | ||
17 | 2 = l2clk (L2 Cache clock) | ||
18 | 3 = ddrclk (DDR clock) | ||
19 | |||
20 | The following is a list of provided IDs and clock names on Armada 380/385: | ||
21 | 0 = tclk (Internal Bus clock) | ||
22 | 1 = cpuclk (CPU clock) | ||
23 | 2 = l2clk (L2 Cache clock) | ||
24 | 3 = ddrclk (DDR clock) | ||
25 | |||
14 | The following is a list of provided IDs and clock names on Kirkwood and Dove: | 26 | The following is a list of provided IDs and clock names on Kirkwood and Dove: |
15 | 0 = tclk (Internal Bus clock) | 27 | 0 = tclk (Internal Bus clock) |
16 | 1 = cpuclk (CPU0 clock) | 28 | 1 = cpuclk (CPU0 clock) |
@@ -20,6 +32,8 @@ The following is a list of provided IDs and clock names on Kirkwood and Dove: | |||
20 | Required properties: | 32 | Required properties: |
21 | - compatible : shall be one of the following: | 33 | - compatible : shall be one of the following: |
22 | "marvell,armada-370-core-clock" - For Armada 370 SoC core clocks | 34 | "marvell,armada-370-core-clock" - For Armada 370 SoC core clocks |
35 | "marvell,armada-375-core-clock" - For Armada 375 SoC core clocks | ||
36 | "marvell,armada-380-core-clock" - For Armada 380/385 SoC core clocks | ||
23 | "marvell,armada-xp-core-clock" - For Armada XP SoC core clocks | 37 | "marvell,armada-xp-core-clock" - For Armada XP SoC core clocks |
24 | "marvell,dove-core-clock" - for Dove SoC core clocks | 38 | "marvell,dove-core-clock" - for Dove SoC core clocks |
25 | "marvell,kirkwood-core-clock" - for Kirkwood SoC (except mv88f6180) | 39 | "marvell,kirkwood-core-clock" - for Kirkwood SoC (except mv88f6180) |
diff --git a/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt index c62391fc0e39..520562a7dc2a 100644 --- a/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt +++ b/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt | |||
@@ -4,7 +4,10 @@ The following is a list of provided IDs and clock names on Armada 370/XP: | |||
4 | 0 = nand (NAND clock) | 4 | 0 = nand (NAND clock) |
5 | 5 | ||
6 | Required properties: | 6 | Required properties: |
7 | - compatible : must be "marvell,armada-370-corediv-clock" | 7 | - compatible : must be "marvell,armada-370-corediv-clock", |
8 | "marvell,armada-375-corediv-clock", | ||
9 | "marvell,armada-380-corediv-clock", | ||
10 | |||
8 | - reg : must be the register address of Core Divider control register | 11 | - reg : must be the register address of Core Divider control register |
9 | - #clock-cells : from common clock binding; shall be set to 1 | 12 | - #clock-cells : from common clock binding; shall be set to 1 |
10 | - clocks : must be set to the parent's phandle | 13 | - clocks : must be set to the parent's phandle |
diff --git a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt index fc2910fa7e45..76477be742b2 100644 --- a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt +++ b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt | |||
@@ -1,9 +1,10 @@ | |||
1 | * Gated Clock bindings for Marvell EBU SoCs | 1 | * Gated Clock bindings for Marvell EBU SoCs |
2 | 2 | ||
3 | Marvell Armada 370/XP, Dove and Kirkwood allow some peripheral clocks to be | 3 | Marvell Armada 370/375/380/385/XP, Dove and Kirkwood allow some |
4 | gated to save some power. The clock consumer should specify the desired clock | 4 | peripheral clocks to be gated to save some power. The clock consumer |
5 | by having the clock ID in its "clocks" phandle cell. The clock ID is directly | 5 | should specify the desired clock by having the clock ID in its |
6 | mapped to the corresponding clock gating control bit in HW to ease manual clock | 6 | "clocks" phandle cell. The clock ID is directly mapped to the |
7 | corresponding clock gating control bit in HW to ease manual clock | ||
7 | lookup in datasheet. | 8 | lookup in datasheet. |
8 | 9 | ||
9 | The following is a list of provided IDs for Armada 370: | 10 | The following is a list of provided IDs for Armada 370: |
@@ -22,6 +23,60 @@ ID Clock Peripheral | |||
22 | 28 ddr DDR Cntrl | 23 | 28 ddr DDR Cntrl |
23 | 30 sata1 SATA Host 0 | 24 | 30 sata1 SATA Host 0 |
24 | 25 | ||
26 | The following is a list of provided IDs for Armada 375: | ||
27 | ID Clock Peripheral | ||
28 | ----------------------------------- | ||
29 | 2 mu Management Unit | ||
30 | 3 pp Packet Processor | ||
31 | 4 ptp PTP | ||
32 | 5 pex0 PCIe 0 Clock out | ||
33 | 6 pex1 PCIe 1 Clock out | ||
34 | 8 audio Audio Cntrl | ||
35 | 11 nd_clk Nand Flash Cntrl | ||
36 | 14 sata0_link SATA 0 Link | ||
37 | 15 sata0_core SATA 0 Core | ||
38 | 16 usb3 USB3 Host | ||
39 | 17 sdio SDHCI Host | ||
40 | 18 usb USB Host | ||
41 | 19 gop Gigabit Ethernet MAC | ||
42 | 20 sata1_link SATA 1 Link | ||
43 | 21 sata1_core SATA 1 Core | ||
44 | 22 xor0 XOR DMA 0 | ||
45 | 23 xor1 XOR DMA 0 | ||
46 | 24 copro Coprocessor | ||
47 | 25 tdm Time Division Mplx | ||
48 | 28 crypto0_enc Cryptographic Unit Port 0 Encryption | ||
49 | 29 crypto0_core Cryptographic Unit Port 0 Core | ||
50 | 30 crypto1_enc Cryptographic Unit Port 1 Encryption | ||
51 | 31 crypto1_core Cryptographic Unit Port 1 Core | ||
52 | |||
53 | The following is a list of provided IDs for Armada 380/385: | ||
54 | ID Clock Peripheral | ||
55 | ----------------------------------- | ||
56 | 0 audio Audio | ||
57 | 2 ge2 Gigabit Ethernet 2 | ||
58 | 3 ge1 Gigabit Ethernet 1 | ||
59 | 4 ge0 Gigabit Ethernet 0 | ||
60 | 5 pex1 PCIe 1 | ||
61 | 6 pex2 PCIe 2 | ||
62 | 7 pex3 PCIe 3 | ||
63 | 8 pex0 PCIe 0 | ||
64 | 9 usb3h0 USB3 Host 0 | ||
65 | 10 usb3h1 USB3 Host 1 | ||
66 | 11 usb3d USB3 Device | ||
67 | 13 bm Buffer Management | ||
68 | 14 crypto0z Cryptographic 0 Z | ||
69 | 15 sata0 SATA 0 | ||
70 | 16 crypto1z Cryptographic 1 Z | ||
71 | 17 sdio SDIO | ||
72 | 18 usb2 USB 2 | ||
73 | 21 crypto1 Cryptographic 1 | ||
74 | 22 xor0 XOR 0 | ||
75 | 23 crypto0 Cryptographic 0 | ||
76 | 25 tdm Time Division Multiplexing | ||
77 | 28 xor1 XOR 1 | ||
78 | 30 sata1 SATA 1 | ||
79 | |||
25 | The following is a list of provided IDs for Armada XP: | 80 | The following is a list of provided IDs for Armada XP: |
26 | ID Clock Peripheral | 81 | ID Clock Peripheral |
27 | ----------------------------------- | 82 | ----------------------------------- |
@@ -95,6 +150,8 @@ ID Clock Peripheral | |||
95 | Required properties: | 150 | Required properties: |
96 | - compatible : shall be one of the following: | 151 | - compatible : shall be one of the following: |
97 | "marvell,armada-370-gating-clock" - for Armada 370 SoC clock gating | 152 | "marvell,armada-370-gating-clock" - for Armada 370 SoC clock gating |
153 | "marvell,armada-375-gating-clock" - for Armada 375 SoC clock gating | ||
154 | "marvell,armada-380-gating-clock" - for Armada 380/385 SoC clock gating | ||
98 | "marvell,armada-xp-gating-clock" - for Armada XP SoC clock gating | 155 | "marvell,armada-xp-gating-clock" - for Armada XP SoC clock gating |
99 | "marvell,dove-gating-clock" - for Dove SoC clock gating | 156 | "marvell,dove-gating-clock" - for Dove SoC clock gating |
100 | "marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating | 157 | "marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating |
diff --git a/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt new file mode 100644 index 000000000000..98a257492522 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt | |||
@@ -0,0 +1,29 @@ | |||
1 | * Renesas RZ Clock Pulse Generator (CPG) | ||
2 | |||
3 | The CPG generates core clocks for the RZ SoCs. It includes the PLL, variable | ||
4 | CPU and GPU clocks, and several fixed ratio dividers. | ||
5 | |||
6 | Required Properties: | ||
7 | |||
8 | - compatible: Must be one of | ||
9 | - "renesas,r7s72100-cpg-clocks" for the r7s72100 CPG | ||
10 | - "renesas,rz-cpg-clocks" for the generic RZ CPG | ||
11 | - reg: Base address and length of the memory resource used by the CPG | ||
12 | - clocks: References to possible parent clocks. Order must match clock modes | ||
13 | in the datasheet. For the r7s72100, this is extal, usb_x1. | ||
14 | - #clock-cells: Must be 1 | ||
15 | - clock-output-names: The names of the clocks. Supported clocks are "pll", | ||
16 | "i", and "g" | ||
17 | |||
18 | |||
19 | Example | ||
20 | ------- | ||
21 | |||
22 | cpg_clocks: cpg_clocks@fcfe0000 { | ||
23 | #clock-cells = <1>; | ||
24 | compatible = "renesas,r7s72100-cpg-clocks", | ||
25 | "renesas,rz-cpg-clocks"; | ||
26 | reg = <0xfcfe0000 0x18>; | ||
27 | clocks = <&extal_clk>, <&usb_x1_clk>; | ||
28 | clock-output-names = "pll", "i", "g"; | ||
29 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt new file mode 100644 index 000000000000..ae56315fcec5 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt | |||
@@ -0,0 +1,49 @@ | |||
1 | Binding for a ST divider and multiplexer clock driver. | ||
2 | |||
3 | This binding uses the common clock binding[1]. | ||
4 | Base address is located to the parent node. See clock binding[2] | ||
5 | |||
6 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
7 | [2] Documentation/devicetree/bindings/clock/st/st,clkgen.txt | ||
8 | |||
9 | Required properties: | ||
10 | |||
11 | - compatible : shall be: | ||
12 | "st,clkgena-divmux-c65-hs", "st,clkgena-divmux" | ||
13 | "st,clkgena-divmux-c65-ls", "st,clkgena-divmux" | ||
14 | "st,clkgena-divmux-c32-odf0", "st,clkgena-divmux" | ||
15 | "st,clkgena-divmux-c32-odf1", "st,clkgena-divmux" | ||
16 | "st,clkgena-divmux-c32-odf2", "st,clkgena-divmux" | ||
17 | "st,clkgena-divmux-c32-odf3", "st,clkgena-divmux" | ||
18 | |||
19 | - #clock-cells : From common clock binding; shall be set to 1. | ||
20 | |||
21 | - clocks : From common clock binding | ||
22 | |||
23 | - clock-output-names : From common clock binding. | ||
24 | |||
25 | Example: | ||
26 | |||
27 | clockgenA@fd345000 { | ||
28 | reg = <0xfd345000 0xb50>; | ||
29 | |||
30 | CLK_M_A1_DIV1: CLK_M_A1_DIV1 { | ||
31 | #clock-cells = <1>; | ||
32 | compatible = "st,clkgena-divmux-c32-odf1", | ||
33 | "st,clkgena-divmux"; | ||
34 | |||
35 | clocks = <&CLK_M_A1_OSC_PREDIV>, | ||
36 | <&CLK_M_A1_PLL0 1>, /* PLL0 PHI1 */ | ||
37 | <&CLK_M_A1_PLL1 1>; /* PLL1 PHI1 */ | ||
38 | |||
39 | clock-output-names = "CLK_M_RX_ICN_TS", | ||
40 | "CLK_M_RX_ICN_VDP_0", | ||
41 | "", /* Unused */ | ||
42 | "CLK_M_PRV_T1_BUS", | ||
43 | "CLK_M_ICN_REG_12", | ||
44 | "CLK_M_ICN_REG_10", | ||
45 | "", /* Unused */ | ||
46 | "CLK_M_ICN_ST231"; | ||
47 | }; | ||
48 | }; | ||
49 | |||
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt new file mode 100644 index 000000000000..943e0808e212 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt | |||
@@ -0,0 +1,36 @@ | |||
1 | Binding for a ST multiplexed clock driver. | ||
2 | |||
3 | This binding supports only simple indexed multiplexers, it does not | ||
4 | support table based parent index to hardware value translations. | ||
5 | |||
6 | This binding uses the common clock binding[1]. | ||
7 | |||
8 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
9 | |||
10 | Required properties: | ||
11 | |||
12 | - compatible : shall be: | ||
13 | "st,stih416-clkgenc-vcc-hd", "st,clkgen-mux" | ||
14 | "st,stih416-clkgenf-vcc-fvdp", "st,clkgen-mux" | ||
15 | "st,stih416-clkgenf-vcc-hva", "st,clkgen-mux" | ||
16 | "st,stih416-clkgenf-vcc-hd", "st,clkgen-mux" | ||
17 | "st,stih416-clkgenf-vcc-sd", "st,clkgen-mux" | ||
18 | "st,stih415-clkgen-a9-mux", "st,clkgen-mux" | ||
19 | "st,stih416-clkgen-a9-mux", "st,clkgen-mux" | ||
20 | |||
21 | |||
22 | - #clock-cells : from common clock binding; shall be set to 0. | ||
23 | |||
24 | - reg : A Base address and length of the register set. | ||
25 | |||
26 | - clocks : from common clock binding | ||
27 | |||
28 | Example: | ||
29 | |||
30 | CLK_M_HVA: CLK_M_HVA { | ||
31 | #clock-cells = <0>; | ||
32 | compatible = "st,stih416-clkgenf-vcc-hva", "st,clkgen-mux"; | ||
33 | reg = <0xfd690868 4>; | ||
34 | |||
35 | clocks = <&CLOCKGEN_F 1>, <&CLK_M_A1_DIV0 3>; | ||
36 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt new file mode 100644 index 000000000000..81eb3855ab92 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt | |||
@@ -0,0 +1,48 @@ | |||
1 | Binding for a ST pll clock driver. | ||
2 | |||
3 | This binding uses the common clock binding[1]. | ||
4 | Base address is located to the parent node. See clock binding[2] | ||
5 | |||
6 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
7 | [2] Documentation/devicetree/bindings/clock/st/st,clkgen.txt | ||
8 | |||
9 | Required properties: | ||
10 | |||
11 | - compatible : shall be: | ||
12 | "st,clkgena-prediv-c65", "st,clkgena-prediv" | ||
13 | "st,clkgena-prediv-c32", "st,clkgena-prediv" | ||
14 | |||
15 | "st,clkgena-plls-c65" | ||
16 | "st,plls-c32-a1x-0", "st,clkgen-plls-c32" | ||
17 | "st,plls-c32-a1x-1", "st,clkgen-plls-c32" | ||
18 | "st,stih415-plls-c32-a9", "st,clkgen-plls-c32" | ||
19 | "st,stih415-plls-c32-ddr", "st,clkgen-plls-c32" | ||
20 | "st,stih416-plls-c32-a9", "st,clkgen-plls-c32" | ||
21 | "st,stih416-plls-c32-ddr", "st,clkgen-plls-c32" | ||
22 | |||
23 | "st,stih415-gpu-pll-c32", "st,clkgengpu-pll-c32" | ||
24 | "st,stih416-gpu-pll-c32", "st,clkgengpu-pll-c32" | ||
25 | |||
26 | |||
27 | - #clock-cells : From common clock binding; shall be set to 1. | ||
28 | |||
29 | - clocks : From common clock binding | ||
30 | |||
31 | - clock-output-names : From common clock binding. | ||
32 | |||
33 | Example: | ||
34 | |||
35 | clockgenA@fee62000 { | ||
36 | reg = <0xfee62000 0xb48>; | ||
37 | |||
38 | CLK_S_A0_PLL: CLK_S_A0_PLL { | ||
39 | #clock-cells = <1>; | ||
40 | compatible = "st,clkgena-plls-c65"; | ||
41 | |||
42 | clocks = <&CLK_SYSIN>; | ||
43 | |||
44 | clock-output-names = "CLK_S_A0_PLL0_HS", | ||
45 | "CLK_S_A0_PLL0_LS", | ||
46 | "CLK_S_A0_PLL1"; | ||
47 | }; | ||
48 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt new file mode 100644 index 000000000000..566c9d79ed32 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt | |||
@@ -0,0 +1,36 @@ | |||
1 | Binding for a ST pre-divider clock driver. | ||
2 | |||
3 | This binding uses the common clock binding[1]. | ||
4 | Base address is located to the parent node. See clock binding[2] | ||
5 | |||
6 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
7 | [2] Documentation/devicetree/bindings/clock/st/st,clkgen.txt | ||
8 | |||
9 | Required properties: | ||
10 | |||
11 | - compatible : shall be: | ||
12 | "st,clkgena-prediv-c65", "st,clkgena-prediv" | ||
13 | "st,clkgena-prediv-c32", "st,clkgena-prediv" | ||
14 | |||
15 | - #clock-cells : From common clock binding; shall be set to 0. | ||
16 | |||
17 | - clocks : From common clock binding | ||
18 | |||
19 | - clock-output-names : From common clock binding. | ||
20 | |||
21 | Example: | ||
22 | |||
23 | clockgenA@fd345000 { | ||
24 | reg = <0xfd345000 0xb50>; | ||
25 | |||
26 | CLK_M_A2_OSC_PREDIV: CLK_M_A2_OSC_PREDIV { | ||
27 | #clock-cells = <0>; | ||
28 | compatible = "st,clkgena-prediv-c32", | ||
29 | "st,clkgena-prediv"; | ||
30 | |||
31 | clocks = <&CLK_SYSIN>; | ||
32 | |||
33 | clock-output-names = "CLK_M_A2_OSC_PREDIV"; | ||
34 | }; | ||
35 | }; | ||
36 | |||
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt new file mode 100644 index 000000000000..4e3ff28b04c3 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt | |||
@@ -0,0 +1,53 @@ | |||
1 | Binding for a type of STMicroelectronics clock crossbar (VCC). | ||
2 | |||
3 | The crossbar can take up to 4 input clocks and control up to 16 | ||
4 | output clocks. Not all inputs or outputs have to be in use in a | ||
5 | particular instantiation. Each output can be individually enabled, | ||
6 | select any of the input clocks and apply a divide (by 1,2,4 or 8) to | ||
7 | that selected clock. | ||
8 | |||
9 | This binding uses the common clock binding[1]. | ||
10 | |||
11 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
12 | |||
13 | Required properties: | ||
14 | |||
15 | - compatible : shall be: | ||
16 | "st,stih416-clkgenc", "st,vcc" | ||
17 | "st,stih416-clkgenf", "st,vcc" | ||
18 | |||
19 | - #clock-cells : from common clock binding; shall be set to 1. | ||
20 | |||
21 | - reg : A Base address and length of the register set. | ||
22 | |||
23 | - clocks : from common clock binding | ||
24 | |||
25 | - clock-output-names : From common clock binding. The block has 16 | ||
26 | clock outputs but not all of them in a specific instance | ||
27 | have to be used in the SoC. If a clock name is left as | ||
28 | an empty string then no clock will be created for the | ||
29 | output associated with that string index. If fewer than | ||
30 | 16 strings are provided then no clocks will be created | ||
31 | for the remaining outputs. | ||
32 | |||
33 | Example: | ||
34 | |||
35 | CLOCKGEN_C_VCC: CLOCKGEN_C_VCC { | ||
36 | #clock-cells = <1>; | ||
37 | compatible = "st,stih416-clkgenc", "st,clkgen-vcc"; | ||
38 | reg = <0xfe8308ac 12>; | ||
39 | |||
40 | clocks = <&CLK_S_VCC_HD>, <&CLOCKGEN_C 1>, | ||
41 | <&CLK_S_TMDS_FROMPHY>, <&CLOCKGEN_C 2>; | ||
42 | |||
43 | clock-output-names = | ||
44 | "CLK_S_PIX_HDMI", "CLK_S_PIX_DVO", | ||
45 | "CLK_S_OUT_DVO", "CLK_S_PIX_HD", | ||
46 | "CLK_S_HDDAC", "CLK_S_DENC", | ||
47 | "CLK_S_SDDAC", "CLK_S_PIX_MAIN", | ||
48 | "CLK_S_PIX_AUX", "CLK_S_STFE_FRC_0", | ||
49 | "CLK_S_REF_MCRU", "CLK_S_SLAVE_MCRU", | ||
50 | "CLK_S_TMDS_HDMI", "CLK_S_HDMI_REJECT_PLL", | ||
51 | "CLK_S_THSENS"; | ||
52 | }; | ||
53 | |||
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt new file mode 100644 index 000000000000..49ec5ae18b5b --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt | |||
@@ -0,0 +1,83 @@ | |||
1 | Binding for a Clockgen hardware block found on | ||
2 | certain STMicroelectronics consumer electronics SoC devices. | ||
3 | |||
4 | A Clockgen node can contain pll, diviser or multiplexer nodes. | ||
5 | |||
6 | We will find only the base address of the Clockgen, this base | ||
7 | address is common of all subnode. | ||
8 | |||
9 | clockgen_node { | ||
10 | reg = <>; | ||
11 | |||
12 | pll_node { | ||
13 | ... | ||
14 | }; | ||
15 | |||
16 | prediv_node { | ||
17 | ... | ||
18 | }; | ||
19 | |||
20 | divmux_node { | ||
21 | ... | ||
22 | }; | ||
23 | |||
24 | quadfs_node { | ||
25 | ... | ||
26 | }; | ||
27 | ... | ||
28 | }; | ||
29 | |||
30 | This binding uses the common clock binding[1]. | ||
31 | Each subnode should use the binding discribe in [2]..[4] | ||
32 | |||
33 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
34 | [2] Documentation/devicetree/bindings/clock/st,quadfs.txt | ||
35 | [3] Documentation/devicetree/bindings/clock/st,quadfs.txt | ||
36 | [4] Documentation/devicetree/bindings/clock/st,quadfs.txt | ||
37 | |||
38 | Required properties: | ||
39 | - reg : A Base address and length of the register set. | ||
40 | |||
41 | Example: | ||
42 | |||
43 | clockgenA@fee62000 { | ||
44 | |||
45 | reg = <0xfee62000 0xb48>; | ||
46 | |||
47 | CLK_S_A0_PLL: CLK_S_A0_PLL { | ||
48 | #clock-cells = <1>; | ||
49 | compatible = "st,clkgena-plls-c65"; | ||
50 | |||
51 | clocks = <&CLK_SYSIN>; | ||
52 | |||
53 | clock-output-names = "CLK_S_A0_PLL0_HS", | ||
54 | "CLK_S_A0_PLL0_LS", | ||
55 | "CLK_S_A0_PLL1"; | ||
56 | }; | ||
57 | |||
58 | CLK_S_A0_OSC_PREDIV: CLK_S_A0_OSC_PREDIV { | ||
59 | #clock-cells = <0>; | ||
60 | compatible = "st,clkgena-prediv-c65", | ||
61 | "st,clkgena-prediv"; | ||
62 | |||
63 | clocks = <&CLK_SYSIN>; | ||
64 | |||
65 | clock-output-names = "CLK_S_A0_OSC_PREDIV"; | ||
66 | }; | ||
67 | |||
68 | CLK_S_A0_HS: CLK_S_A0_HS { | ||
69 | #clock-cells = <1>; | ||
70 | compatible = "st,clkgena-divmux-c65-hs", | ||
71 | "st,clkgena-divmux"; | ||
72 | |||
73 | clocks = <&CLK_S_A0_OSC_PREDIV>, | ||
74 | <&CLK_S_A0_PLL 0>, /* PLL0 HS */ | ||
75 | <&CLK_S_A0_PLL 2>; /* PLL1 */ | ||
76 | |||
77 | clock-output-names = "CLK_S_FDMA_0", | ||
78 | "CLK_S_FDMA_1", | ||
79 | ""; /* CLK_S_JIT_SENSE */ | ||
80 | /* Fourth output unused */ | ||
81 | }; | ||
82 | }; | ||
83 | |||
diff --git a/Documentation/devicetree/bindings/clock/st/st,quadfs.txt b/Documentation/devicetree/bindings/clock/st/st,quadfs.txt new file mode 100644 index 000000000000..ec86d62ca283 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st/st,quadfs.txt | |||
@@ -0,0 +1,45 @@ | |||
1 | Binding for a type of quad channel digital frequency synthesizer found on | ||
2 | certain STMicroelectronics consumer electronics SoC devices. | ||
3 | |||
4 | This version contains a programmable PLL which can generate up to 216, 432 | ||
5 | or 660MHz (from a 30MHz oscillator input) as the input to the digital | ||
6 | synthesizers. | ||
7 | |||
8 | This binding uses the common clock binding[1]. | ||
9 | |||
10 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
11 | |||
12 | Required properties: | ||
13 | - compatible : shall be: | ||
14 | "st,stih416-quadfs216", "st,quadfs" | ||
15 | "st,stih416-quadfs432", "st,quadfs" | ||
16 | "st,stih416-quadfs660-E", "st,quadfs" | ||
17 | "st,stih416-quadfs660-F", "st,quadfs" | ||
18 | |||
19 | - #clock-cells : from common clock binding; shall be set to 1. | ||
20 | |||
21 | - reg : A Base address and length of the register set. | ||
22 | |||
23 | - clocks : from common clock binding | ||
24 | |||
25 | - clock-output-names : From common clock binding. The block has 4 | ||
26 | clock outputs but not all of them in a specific instance | ||
27 | have to be used in the SoC. If a clock name is left as | ||
28 | an empty string then no clock will be created for the | ||
29 | output associated with that string index. If fewer than | ||
30 | 4 strings are provided then no clocks will be created | ||
31 | for the remaining outputs. | ||
32 | |||
33 | Example: | ||
34 | |||
35 | CLOCKGEN_E: CLOCKGEN_E { | ||
36 | #clock-cells = <1>; | ||
37 | compatible = "st,stih416-quadfs660-E", "st,quadfs"; | ||
38 | reg = <0xfd3208bc 0xB0>; | ||
39 | |||
40 | clocks = <&CLK_SYSIN>; | ||
41 | clock-output-names = "CLK_M_PIX_MDTP_0", | ||
42 | "CLK_M_PIX_MDTP_1", | ||
43 | "CLK_M_PIX_MDTP_2", | ||
44 | "CLK_M_MPELPC"; | ||
45 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index c2cb7621ad2d..a5160d8cbb5f 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt | |||
@@ -6,37 +6,41 @@ This binding uses the common clock binding[1]. | |||
6 | 6 | ||
7 | Required properties: | 7 | Required properties: |
8 | - compatible : shall be one of the following: | 8 | - compatible : shall be one of the following: |
9 | "allwinner,sun4i-osc-clk" - for a gatable oscillator | 9 | "allwinner,sun4i-a10-osc-clk" - for a gatable oscillator |
10 | "allwinner,sun4i-pll1-clk" - for the main PLL clock and PLL4 | 10 | "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4 |
11 | "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 | 11 | "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 |
12 | "allwinner,sun4i-pll5-clk" - for the PLL5 clock | 12 | "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock |
13 | "allwinner,sun4i-pll6-clk" - for the PLL6 clock | 13 | "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock |
14 | "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock | 14 | "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31 |
15 | "allwinner,sun4i-axi-clk" - for the AXI clock | 15 | "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock |
16 | "allwinner,sun4i-axi-gates-clk" - for the AXI gates | 16 | "allwinner,sun4i-a10-axi-clk" - for the AXI clock |
17 | "allwinner,sun4i-ahb-clk" - for the AHB clock | 17 | "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates |
18 | "allwinner,sun4i-ahb-gates-clk" - for the AHB gates on A10 | 18 | "allwinner,sun4i-a10-ahb-clk" - for the AHB clock |
19 | "allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10 | ||
19 | "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13 | 20 | "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13 |
20 | "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s | 21 | "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s |
21 | "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20 | 22 | "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20 |
22 | "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31 | 23 | "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31 |
23 | "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 | 24 | "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 |
24 | "allwinner,sun4i-apb0-clk" - for the APB0 clock | 25 | "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock |
25 | "allwinner,sun4i-apb0-gates-clk" - for the APB0 gates on A10 | 26 | "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10 |
26 | "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 | 27 | "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 |
27 | "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s | 28 | "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s |
28 | "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 | 29 | "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 |
29 | "allwinner,sun4i-apb1-clk" - for the APB1 clock | 30 | "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock |
30 | "allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing | 31 | "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing |
31 | "allwinner,sun4i-apb1-gates-clk" - for the APB1 gates on A10 | 32 | "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10 |
32 | "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13 | 33 | "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13 |
33 | "allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s | 34 | "allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s |
34 | "allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31 | 35 | "allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31 |
35 | "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20 | 36 | "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20 |
36 | "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31 | 37 | "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31 |
37 | "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 | 38 | "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 |
38 | "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks | 39 | "allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks |
39 | "allwinner,sun7i-a20-out-clk" - for the external output clocks | 40 | "allwinner,sun7i-a20-out-clk" - for the external output clocks |
41 | "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 | ||
42 | "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20 | ||
43 | "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13 | ||
40 | 44 | ||
41 | Required properties for all clocks: | 45 | Required properties for all clocks: |
42 | - reg : shall be the control register address for the clock. | 46 | - reg : shall be the control register address for the clock. |
@@ -44,10 +48,17 @@ Required properties for all clocks: | |||
44 | multiplexed clocks, the list order must match the hardware | 48 | multiplexed clocks, the list order must match the hardware |
45 | programming order. | 49 | programming order. |
46 | - #clock-cells : from common clock binding; shall be set to 0 except for | 50 | - #clock-cells : from common clock binding; shall be set to 0 except for |
47 | "allwinner,*-gates-clk" where it shall be set to 1 | 51 | "allwinner,*-gates-clk", "allwinner,sun4i-pll5-clk" and |
52 | "allwinner,sun4i-pll6-clk" where it shall be set to 1 | ||
53 | - clock-output-names : shall be the corresponding names of the outputs. | ||
54 | If the clock module only has one output, the name shall be the | ||
55 | module name. | ||
48 | 56 | ||
49 | Additionally, "allwinner,*-gates-clk" clocks require: | 57 | And "allwinner,*-usb-clk" clocks also require: |
50 | - clock-output-names : the corresponding gate names that the clock controls | 58 | - reset-cells : shall be set to 1 |
59 | |||
60 | For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate | ||
61 | dummy clocks at 25 MHz and 125 MHz, respectively. See example. | ||
51 | 62 | ||
52 | Clock consumers should specify the desired clocks they use with a | 63 | Clock consumers should specify the desired clocks they use with a |
53 | "clocks" phandle cell. Consumers that are using a gated clock should | 64 | "clocks" phandle cell. Consumers that are using a gated clock should |
@@ -56,23 +67,68 @@ offset of the bit controlling this particular gate in the register. | |||
56 | 67 | ||
57 | For example: | 68 | For example: |
58 | 69 | ||
59 | osc24M: osc24M@01c20050 { | 70 | osc24M: clk@01c20050 { |
60 | #clock-cells = <0>; | 71 | #clock-cells = <0>; |
61 | compatible = "allwinner,sun4i-osc-clk"; | 72 | compatible = "allwinner,sun4i-a10-osc-clk"; |
62 | reg = <0x01c20050 0x4>; | 73 | reg = <0x01c20050 0x4>; |
63 | clocks = <&osc24M_fixed>; | 74 | clocks = <&osc24M_fixed>; |
75 | clock-output-names = "osc24M"; | ||
64 | }; | 76 | }; |
65 | 77 | ||
66 | pll1: pll1@01c20000 { | 78 | pll1: clk@01c20000 { |
67 | #clock-cells = <0>; | 79 | #clock-cells = <0>; |
68 | compatible = "allwinner,sun4i-pll1-clk"; | 80 | compatible = "allwinner,sun4i-a10-pll1-clk"; |
69 | reg = <0x01c20000 0x4>; | 81 | reg = <0x01c20000 0x4>; |
70 | clocks = <&osc24M>; | 82 | clocks = <&osc24M>; |
83 | clock-output-names = "pll1"; | ||
84 | }; | ||
85 | |||
86 | pll5: clk@01c20020 { | ||
87 | #clock-cells = <1>; | ||
88 | compatible = "allwinner,sun4i-pll5-clk"; | ||
89 | reg = <0x01c20020 0x4>; | ||
90 | clocks = <&osc24M>; | ||
91 | clock-output-names = "pll5_ddr", "pll5_other"; | ||
71 | }; | 92 | }; |
72 | 93 | ||
73 | cpu: cpu@01c20054 { | 94 | cpu: cpu@01c20054 { |
74 | #clock-cells = <0>; | 95 | #clock-cells = <0>; |
75 | compatible = "allwinner,sun4i-cpu-clk"; | 96 | compatible = "allwinner,sun4i-a10-cpu-clk"; |
76 | reg = <0x01c20054 0x4>; | 97 | reg = <0x01c20054 0x4>; |
77 | clocks = <&osc32k>, <&osc24M>, <&pll1>; | 98 | clocks = <&osc32k>, <&osc24M>, <&pll1>; |
99 | clock-output-names = "cpu"; | ||
100 | }; | ||
101 | |||
102 | mmc0_clk: clk@01c20088 { | ||
103 | #clock-cells = <0>; | ||
104 | compatible = "allwinner,sun4i-mod0-clk"; | ||
105 | reg = <0x01c20088 0x4>; | ||
106 | clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; | ||
107 | clock-output-names = "mmc0"; | ||
108 | }; | ||
109 | |||
110 | mii_phy_tx_clk: clk@2 { | ||
111 | #clock-cells = <0>; | ||
112 | compatible = "fixed-clock"; | ||
113 | clock-frequency = <25000000>; | ||
114 | clock-output-names = "mii_phy_tx"; | ||
115 | }; | ||
116 | |||
117 | gmac_int_tx_clk: clk@3 { | ||
118 | #clock-cells = <0>; | ||
119 | compatible = "fixed-clock"; | ||
120 | clock-frequency = <125000000>; | ||
121 | clock-output-names = "gmac_int_tx"; | ||
122 | }; | ||
123 | |||
124 | gmac_clk: clk@01c20164 { | ||
125 | #clock-cells = <0>; | ||
126 | compatible = "allwinner,sun7i-a20-gmac-clk"; | ||
127 | reg = <0x01c20164 0x4>; | ||
128 | /* | ||
129 | * The first clock must be fixed at 25MHz; | ||
130 | * the second clock must be fixed at 125MHz | ||
131 | */ | ||
132 | clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>; | ||
133 | clock-output-names = "gmac"; | ||
78 | }; | 134 | }; |
diff --git a/MAINTAINERS b/MAINTAINERS index 2421c8d5ec5c..bfff89690c3a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -2318,7 +2318,7 @@ F: include/uapi/linux/coda*.h | |||
2318 | 2318 | ||
2319 | COMMON CLK FRAMEWORK | 2319 | COMMON CLK FRAMEWORK |
2320 | M: Mike Turquette <mturquette@linaro.org> | 2320 | M: Mike Turquette <mturquette@linaro.org> |
2321 | L: linux-arm-kernel@lists.infradead.org (same as CLK API & CLKDEV) | 2321 | L: linux-kernel@vger.kernel.org |
2322 | T: git git://git.linaro.org/people/mturquette/linux.git | 2322 | T: git git://git.linaro.org/people/mturquette/linux.git |
2323 | S: Maintained | 2323 | S: Maintained |
2324 | F: drivers/clk/ | 2324 | F: drivers/clk/ |
diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi index 4568c9869d44..56fc214e6d2c 100644 --- a/arch/arm/boot/dts/socfpga.dtsi +++ b/arch/arm/boot/dts/socfpga.dtsi | |||
@@ -424,6 +424,7 @@ | |||
424 | compatible = "altr,socfpga-gate-clk"; | 424 | compatible = "altr,socfpga-gate-clk"; |
425 | clocks = <&f2s_periph_ref_clk>, <&main_nand_sdmmc_clk>, <&per_nand_mmc_clk>; | 425 | clocks = <&f2s_periph_ref_clk>, <&main_nand_sdmmc_clk>, <&per_nand_mmc_clk>; |
426 | clk-gate = <0xa0 8>; | 426 | clk-gate = <0xa0 8>; |
427 | clk-phase = <0 135>; | ||
427 | }; | 428 | }; |
428 | 429 | ||
429 | nand_x_clk: nand_x_clk { | 430 | nand_x_clk: nand_x_clk { |
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c index dd0d49cdbe09..d86231e11b34 100644 --- a/arch/arm/mach-socfpga/socfpga.c +++ b/arch/arm/mach-socfpga/socfpga.c | |||
@@ -29,7 +29,6 @@ | |||
29 | void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE)); | 29 | void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE)); |
30 | void __iomem *sys_manager_base_addr; | 30 | void __iomem *sys_manager_base_addr; |
31 | void __iomem *rst_manager_base_addr; | 31 | void __iomem *rst_manager_base_addr; |
32 | void __iomem *clk_mgr_base_addr; | ||
33 | unsigned long cpu1start_addr; | 32 | unsigned long cpu1start_addr; |
34 | 33 | ||
35 | static struct map_desc scu_io_desc __initdata = { | 34 | static struct map_desc scu_io_desc __initdata = { |
@@ -78,9 +77,6 @@ void __init socfpga_sysmgr_init(void) | |||
78 | 77 | ||
79 | np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr"); | 78 | np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr"); |
80 | rst_manager_base_addr = of_iomap(np, 0); | 79 | rst_manager_base_addr = of_iomap(np, 0); |
81 | |||
82 | np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr"); | ||
83 | clk_mgr_base_addr = of_iomap(np, 0); | ||
84 | } | 80 | } |
85 | 81 | ||
86 | static void __init socfpga_init_irq(void) | 82 | static void __init socfpga_init_irq(void) |
@@ -106,7 +102,6 @@ static void __init socfpga_cyclone5_init(void) | |||
106 | { | 102 | { |
107 | l2x0_of_init(0, ~0UL); | 103 | l2x0_of_init(0, ~0UL); |
108 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); | 104 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); |
109 | socfpga_init_clocks(); | ||
110 | } | 105 | } |
111 | 106 | ||
112 | static const char *altera_dt_match[] = { | 107 | static const char *altera_dt_match[] = { |
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index f9f605695e40..6f56d3a4f010 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig | |||
@@ -65,10 +65,12 @@ config COMMON_CLK_SI570 | |||
65 | clock generators. | 65 | clock generators. |
66 | 66 | ||
67 | config COMMON_CLK_S2MPS11 | 67 | config COMMON_CLK_S2MPS11 |
68 | tristate "Clock driver for S2MPS11 MFD" | 68 | tristate "Clock driver for S2MPS11/S5M8767 MFD" |
69 | depends on MFD_SEC_CORE | 69 | depends on MFD_SEC_CORE |
70 | ---help--- | 70 | ---help--- |
71 | This driver supports S2MPS11 crystal oscillator clock. | 71 | This driver supports S2MPS11/S5M8767 crystal oscillator clock. These |
72 | multi-function devices have 3 fixed-rate oscillators, clocked at | ||
73 | 32KHz each. | ||
72 | 74 | ||
73 | config CLK_TWL6040 | 75 | config CLK_TWL6040 |
74 | tristate "External McPDM functional clock from twl6040" | 76 | tristate "External McPDM functional clock from twl6040" |
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 88af4a399d6c..5f8a28735c96 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile | |||
@@ -17,6 +17,7 @@ obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o | |||
17 | obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o | 17 | obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o |
18 | obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o | 18 | obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o |
19 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o | 19 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o |
20 | obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o | ||
20 | obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o | 21 | obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o |
21 | obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o | 22 | obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o |
22 | obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o | 23 | obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o |
@@ -31,6 +32,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o | |||
31 | obj-$(CONFIG_COMMON_CLK_AT91) += at91/ | 32 | obj-$(CONFIG_COMMON_CLK_AT91) += at91/ |
32 | obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm/ | 33 | obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm/ |
33 | obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/ | 34 | obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/ |
35 | obj-$(CONFIG_ARCH_HIP04) += hisilicon/ | ||
34 | obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ | 36 | obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ |
35 | ifeq ($(CONFIG_COMMON_CLK), y) | 37 | ifeq ($(CONFIG_COMMON_CLK), y) |
36 | obj-$(CONFIG_ARCH_MMP) += mmp/ | 38 | obj-$(CONFIG_ARCH_MMP) += mmp/ |
@@ -44,6 +46,7 @@ obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += shmobile/ | |||
44 | obj-$(CONFIG_ARCH_SIRF) += sirf/ | 46 | obj-$(CONFIG_ARCH_SIRF) += sirf/ |
45 | obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ | 47 | obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ |
46 | obj-$(CONFIG_PLAT_SPEAR) += spear/ | 48 | obj-$(CONFIG_PLAT_SPEAR) += spear/ |
49 | obj-$(CONFIG_ARCH_STI) += st/ | ||
47 | obj-$(CONFIG_ARCH_SUNXI) += sunxi/ | 50 | obj-$(CONFIG_ARCH_SUNXI) += sunxi/ |
48 | obj-$(CONFIG_ARCH_TEGRA) += tegra/ | 51 | obj-$(CONFIG_ARCH_TEGRA) += tegra/ |
49 | obj-$(CONFIG_ARCH_OMAP2PLUS) += ti/ | 52 | obj-$(CONFIG_ARCH_OMAP2PLUS) += ti/ |
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c index fd792b203eaf..62e2509f9df1 100644 --- a/drivers/clk/at91/clk-programmable.c +++ b/drivers/clk/at91/clk-programmable.c | |||
@@ -13,12 +13,9 @@ | |||
13 | #include <linux/clk/at91_pmc.h> | 13 | #include <linux/clk/at91_pmc.h> |
14 | #include <linux/of.h> | 14 | #include <linux/of.h> |
15 | #include <linux/of_address.h> | 15 | #include <linux/of_address.h> |
16 | #include <linux/of_irq.h> | ||
17 | #include <linux/io.h> | 16 | #include <linux/io.h> |
18 | #include <linux/wait.h> | 17 | #include <linux/wait.h> |
19 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/irq.h> | ||
22 | 19 | ||
23 | #include "pmc.h" | 20 | #include "pmc.h" |
24 | 21 | ||
@@ -38,104 +35,59 @@ struct clk_programmable_layout { | |||
38 | struct clk_programmable { | 35 | struct clk_programmable { |
39 | struct clk_hw hw; | 36 | struct clk_hw hw; |
40 | struct at91_pmc *pmc; | 37 | struct at91_pmc *pmc; |
41 | unsigned int irq; | ||
42 | wait_queue_head_t wait; | ||
43 | u8 id; | 38 | u8 id; |
44 | u8 css; | ||
45 | u8 pres; | ||
46 | u8 slckmck; | ||
47 | const struct clk_programmable_layout *layout; | 39 | const struct clk_programmable_layout *layout; |
48 | }; | 40 | }; |
49 | 41 | ||
50 | #define to_clk_programmable(hw) container_of(hw, struct clk_programmable, hw) | 42 | #define to_clk_programmable(hw) container_of(hw, struct clk_programmable, hw) |
51 | 43 | ||
52 | 44 | static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, | |
53 | static irqreturn_t clk_programmable_irq_handler(int irq, void *dev_id) | 45 | unsigned long parent_rate) |
54 | { | ||
55 | struct clk_programmable *prog = (struct clk_programmable *)dev_id; | ||
56 | |||
57 | wake_up(&prog->wait); | ||
58 | |||
59 | return IRQ_HANDLED; | ||
60 | } | ||
61 | |||
62 | static int clk_programmable_prepare(struct clk_hw *hw) | ||
63 | { | 46 | { |
64 | u32 tmp; | 47 | u32 pres; |
65 | struct clk_programmable *prog = to_clk_programmable(hw); | 48 | struct clk_programmable *prog = to_clk_programmable(hw); |
66 | struct at91_pmc *pmc = prog->pmc; | 49 | struct at91_pmc *pmc = prog->pmc; |
67 | const struct clk_programmable_layout *layout = prog->layout; | 50 | const struct clk_programmable_layout *layout = prog->layout; |
68 | u8 id = prog->id; | ||
69 | u32 mask = PROG_STATUS_MASK(id); | ||
70 | |||
71 | tmp = prog->css | (prog->pres << layout->pres_shift); | ||
72 | if (layout->have_slck_mck && prog->slckmck) | ||
73 | tmp |= AT91_PMC_CSSMCK_MCK; | ||
74 | |||
75 | pmc_write(pmc, AT91_PMC_PCKR(id), tmp); | ||
76 | |||
77 | while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) | ||
78 | wait_event(prog->wait, pmc_read(pmc, AT91_PMC_SR) & mask); | ||
79 | 51 | ||
80 | return 0; | 52 | pres = (pmc_read(pmc, AT91_PMC_PCKR(prog->id)) >> layout->pres_shift) & |
53 | PROG_PRES_MASK; | ||
54 | return parent_rate >> pres; | ||
81 | } | 55 | } |
82 | 56 | ||
83 | static int clk_programmable_is_ready(struct clk_hw *hw) | 57 | static long clk_programmable_determine_rate(struct clk_hw *hw, |
58 | unsigned long rate, | ||
59 | unsigned long *best_parent_rate, | ||
60 | struct clk **best_parent_clk) | ||
84 | { | 61 | { |
85 | struct clk_programmable *prog = to_clk_programmable(hw); | 62 | struct clk *parent = NULL; |
86 | struct at91_pmc *pmc = prog->pmc; | 63 | long best_rate = -EINVAL; |
87 | 64 | unsigned long parent_rate; | |
88 | return !!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_PCKR(prog->id)); | 65 | unsigned long tmp_rate; |
89 | } | 66 | int shift; |
67 | int i; | ||
90 | 68 | ||
91 | static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, | 69 | for (i = 0; i < __clk_get_num_parents(hw->clk); i++) { |
92 | unsigned long parent_rate) | 70 | parent = clk_get_parent_by_index(hw->clk, i); |
93 | { | 71 | if (!parent) |
94 | u32 tmp; | 72 | continue; |
95 | struct clk_programmable *prog = to_clk_programmable(hw); | ||
96 | struct at91_pmc *pmc = prog->pmc; | ||
97 | const struct clk_programmable_layout *layout = prog->layout; | ||
98 | 73 | ||
99 | tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)); | 74 | parent_rate = __clk_get_rate(parent); |
100 | prog->pres = (tmp >> layout->pres_shift) & PROG_PRES_MASK; | 75 | for (shift = 0; shift < PROG_PRES_MASK; shift++) { |
76 | tmp_rate = parent_rate >> shift; | ||
77 | if (tmp_rate <= rate) | ||
78 | break; | ||
79 | } | ||
101 | 80 | ||
102 | return parent_rate >> prog->pres; | 81 | if (tmp_rate > rate) |
103 | } | 82 | continue; |
104 | 83 | ||
105 | static long clk_programmable_round_rate(struct clk_hw *hw, unsigned long rate, | 84 | if (best_rate < 0 || (rate - tmp_rate) < (rate - best_rate)) { |
106 | unsigned long *parent_rate) | 85 | best_rate = tmp_rate; |
107 | { | 86 | *best_parent_rate = parent_rate; |
108 | unsigned long best_rate = *parent_rate; | 87 | *best_parent_clk = parent; |
109 | unsigned long best_diff; | ||
110 | unsigned long new_diff; | ||
111 | unsigned long cur_rate; | ||
112 | int shift = shift; | ||
113 | |||
114 | if (rate > *parent_rate) | ||
115 | return *parent_rate; | ||
116 | else | ||
117 | best_diff = *parent_rate - rate; | ||
118 | |||
119 | if (!best_diff) | ||
120 | return best_rate; | ||
121 | |||
122 | for (shift = 1; shift < PROG_PRES_MASK; shift++) { | ||
123 | cur_rate = *parent_rate >> shift; | ||
124 | |||
125 | if (cur_rate > rate) | ||
126 | new_diff = cur_rate - rate; | ||
127 | else | ||
128 | new_diff = rate - cur_rate; | ||
129 | |||
130 | if (!new_diff) | ||
131 | return cur_rate; | ||
132 | |||
133 | if (new_diff < best_diff) { | ||
134 | best_diff = new_diff; | ||
135 | best_rate = cur_rate; | ||
136 | } | 88 | } |
137 | 89 | ||
138 | if (rate > cur_rate) | 90 | if (!best_rate) |
139 | break; | 91 | break; |
140 | } | 92 | } |
141 | 93 | ||
@@ -146,17 +98,22 @@ static int clk_programmable_set_parent(struct clk_hw *hw, u8 index) | |||
146 | { | 98 | { |
147 | struct clk_programmable *prog = to_clk_programmable(hw); | 99 | struct clk_programmable *prog = to_clk_programmable(hw); |
148 | const struct clk_programmable_layout *layout = prog->layout; | 100 | const struct clk_programmable_layout *layout = prog->layout; |
101 | struct at91_pmc *pmc = prog->pmc; | ||
102 | u32 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)) & ~layout->css_mask; | ||
103 | |||
104 | if (layout->have_slck_mck) | ||
105 | tmp &= AT91_PMC_CSSMCK_MCK; | ||
106 | |||
149 | if (index > layout->css_mask) { | 107 | if (index > layout->css_mask) { |
150 | if (index > PROG_MAX_RM9200_CSS && layout->have_slck_mck) { | 108 | if (index > PROG_MAX_RM9200_CSS && layout->have_slck_mck) { |
151 | prog->css = 0; | 109 | tmp |= AT91_PMC_CSSMCK_MCK; |
152 | prog->slckmck = 1; | ||
153 | return 0; | 110 | return 0; |
154 | } else { | 111 | } else { |
155 | return -EINVAL; | 112 | return -EINVAL; |
156 | } | 113 | } |
157 | } | 114 | } |
158 | 115 | ||
159 | prog->css = index; | 116 | pmc_write(pmc, AT91_PMC_PCKR(prog->id), tmp | index); |
160 | return 0; | 117 | return 0; |
161 | } | 118 | } |
162 | 119 | ||
@@ -169,13 +126,9 @@ static u8 clk_programmable_get_parent(struct clk_hw *hw) | |||
169 | const struct clk_programmable_layout *layout = prog->layout; | 126 | const struct clk_programmable_layout *layout = prog->layout; |
170 | 127 | ||
171 | tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)); | 128 | tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)); |
172 | prog->css = tmp & layout->css_mask; | 129 | ret = tmp & layout->css_mask; |
173 | ret = prog->css; | 130 | if (layout->have_slck_mck && (tmp & AT91_PMC_CSSMCK_MCK) && !ret) |
174 | if (layout->have_slck_mck) { | 131 | ret = PROG_MAX_RM9200_CSS + 1; |
175 | prog->slckmck = !!(tmp & AT91_PMC_CSSMCK_MCK); | ||
176 | if (prog->slckmck && !ret) | ||
177 | ret = PROG_MAX_RM9200_CSS + 1; | ||
178 | } | ||
179 | 132 | ||
180 | return ret; | 133 | return ret; |
181 | } | 134 | } |
@@ -184,67 +137,47 @@ static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate, | |||
184 | unsigned long parent_rate) | 137 | unsigned long parent_rate) |
185 | { | 138 | { |
186 | struct clk_programmable *prog = to_clk_programmable(hw); | 139 | struct clk_programmable *prog = to_clk_programmable(hw); |
187 | unsigned long best_rate = parent_rate; | 140 | struct at91_pmc *pmc = prog->pmc; |
188 | unsigned long best_diff; | 141 | const struct clk_programmable_layout *layout = prog->layout; |
189 | unsigned long new_diff; | 142 | unsigned long div = parent_rate / rate; |
190 | unsigned long cur_rate; | ||
191 | int shift = 0; | 143 | int shift = 0; |
144 | u32 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)) & | ||
145 | ~(PROG_PRES_MASK << layout->pres_shift); | ||
192 | 146 | ||
193 | if (rate > parent_rate) | 147 | if (!div) |
194 | return parent_rate; | 148 | return -EINVAL; |
195 | else | ||
196 | best_diff = parent_rate - rate; | ||
197 | |||
198 | if (!best_diff) { | ||
199 | prog->pres = shift; | ||
200 | return 0; | ||
201 | } | ||
202 | 149 | ||
203 | for (shift = 1; shift < PROG_PRES_MASK; shift++) { | 150 | shift = fls(div) - 1; |
204 | cur_rate = parent_rate >> shift; | ||
205 | 151 | ||
206 | if (cur_rate > rate) | 152 | if (div != (1<<shift)) |
207 | new_diff = cur_rate - rate; | 153 | return -EINVAL; |
208 | else | ||
209 | new_diff = rate - cur_rate; | ||
210 | 154 | ||
211 | if (!new_diff) | 155 | if (shift >= PROG_PRES_MASK) |
212 | break; | 156 | return -EINVAL; |
213 | 157 | ||
214 | if (new_diff < best_diff) { | 158 | pmc_write(pmc, AT91_PMC_PCKR(prog->id), |
215 | best_diff = new_diff; | 159 | tmp | (shift << layout->pres_shift)); |
216 | best_rate = cur_rate; | ||
217 | } | ||
218 | 160 | ||
219 | if (rate > cur_rate) | ||
220 | break; | ||
221 | } | ||
222 | |||
223 | prog->pres = shift; | ||
224 | return 0; | 161 | return 0; |
225 | } | 162 | } |
226 | 163 | ||
227 | static const struct clk_ops programmable_ops = { | 164 | static const struct clk_ops programmable_ops = { |
228 | .prepare = clk_programmable_prepare, | ||
229 | .is_prepared = clk_programmable_is_ready, | ||
230 | .recalc_rate = clk_programmable_recalc_rate, | 165 | .recalc_rate = clk_programmable_recalc_rate, |
231 | .round_rate = clk_programmable_round_rate, | 166 | .determine_rate = clk_programmable_determine_rate, |
232 | .get_parent = clk_programmable_get_parent, | 167 | .get_parent = clk_programmable_get_parent, |
233 | .set_parent = clk_programmable_set_parent, | 168 | .set_parent = clk_programmable_set_parent, |
234 | .set_rate = clk_programmable_set_rate, | 169 | .set_rate = clk_programmable_set_rate, |
235 | }; | 170 | }; |
236 | 171 | ||
237 | static struct clk * __init | 172 | static struct clk * __init |
238 | at91_clk_register_programmable(struct at91_pmc *pmc, unsigned int irq, | 173 | at91_clk_register_programmable(struct at91_pmc *pmc, |
239 | const char *name, const char **parent_names, | 174 | const char *name, const char **parent_names, |
240 | u8 num_parents, u8 id, | 175 | u8 num_parents, u8 id, |
241 | const struct clk_programmable_layout *layout) | 176 | const struct clk_programmable_layout *layout) |
242 | { | 177 | { |
243 | int ret; | ||
244 | struct clk_programmable *prog; | 178 | struct clk_programmable *prog; |
245 | struct clk *clk = NULL; | 179 | struct clk *clk = NULL; |
246 | struct clk_init_data init; | 180 | struct clk_init_data init; |
247 | char irq_name[11]; | ||
248 | 181 | ||
249 | if (id > PROG_ID_MAX) | 182 | if (id > PROG_ID_MAX) |
250 | return ERR_PTR(-EINVAL); | 183 | return ERR_PTR(-EINVAL); |
@@ -263,14 +196,6 @@ at91_clk_register_programmable(struct at91_pmc *pmc, unsigned int irq, | |||
263 | prog->layout = layout; | 196 | prog->layout = layout; |
264 | prog->hw.init = &init; | 197 | prog->hw.init = &init; |
265 | prog->pmc = pmc; | 198 | prog->pmc = pmc; |
266 | prog->irq = irq; | ||
267 | init_waitqueue_head(&prog->wait); | ||
268 | irq_set_status_flags(prog->irq, IRQ_NOAUTOEN); | ||
269 | snprintf(irq_name, sizeof(irq_name), "clk-prog%d", id); | ||
270 | ret = request_irq(prog->irq, clk_programmable_irq_handler, | ||
271 | IRQF_TRIGGER_HIGH, irq_name, prog); | ||
272 | if (ret) | ||
273 | return ERR_PTR(ret); | ||
274 | 199 | ||
275 | clk = clk_register(NULL, &prog->hw); | 200 | clk = clk_register(NULL, &prog->hw); |
276 | if (IS_ERR(clk)) | 201 | if (IS_ERR(clk)) |
@@ -304,7 +229,6 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, | |||
304 | int num; | 229 | int num; |
305 | u32 id; | 230 | u32 id; |
306 | int i; | 231 | int i; |
307 | unsigned int irq; | ||
308 | struct clk *clk; | 232 | struct clk *clk; |
309 | int num_parents; | 233 | int num_parents; |
310 | const char *parent_names[PROG_SOURCE_MAX]; | 234 | const char *parent_names[PROG_SOURCE_MAX]; |
@@ -332,11 +256,7 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, | |||
332 | if (of_property_read_string(np, "clock-output-names", &name)) | 256 | if (of_property_read_string(np, "clock-output-names", &name)) |
333 | name = progclknp->name; | 257 | name = progclknp->name; |
334 | 258 | ||
335 | irq = irq_of_parse_and_map(progclknp, 0); | 259 | clk = at91_clk_register_programmable(pmc, name, |
336 | if (!irq) | ||
337 | continue; | ||
338 | |||
339 | clk = at91_clk_register_programmable(pmc, irq, name, | ||
340 | parent_names, num_parents, | 260 | parent_names, num_parents, |
341 | id, layout); | 261 | id, layout); |
342 | if (IS_ERR(clk)) | 262 | if (IS_ERR(clk)) |
diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c index 8f7c0434a09f..8c96307d7363 100644 --- a/drivers/clk/at91/clk-system.c +++ b/drivers/clk/at91/clk-system.c | |||
@@ -14,6 +14,11 @@ | |||
14 | #include <linux/of.h> | 14 | #include <linux/of.h> |
15 | #include <linux/of_address.h> | 15 | #include <linux/of_address.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/irq.h> | ||
18 | #include <linux/of_irq.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/wait.h> | ||
21 | #include <linux/sched.h> | ||
17 | 22 | ||
18 | #include "pmc.h" | 23 | #include "pmc.h" |
19 | 24 | ||
@@ -25,19 +30,48 @@ | |||
25 | struct clk_system { | 30 | struct clk_system { |
26 | struct clk_hw hw; | 31 | struct clk_hw hw; |
27 | struct at91_pmc *pmc; | 32 | struct at91_pmc *pmc; |
33 | unsigned int irq; | ||
34 | wait_queue_head_t wait; | ||
28 | u8 id; | 35 | u8 id; |
29 | }; | 36 | }; |
30 | 37 | ||
31 | static int clk_system_enable(struct clk_hw *hw) | 38 | static inline int is_pck(int id) |
39 | { | ||
40 | return (id >= 8) && (id <= 15); | ||
41 | } | ||
42 | static irqreturn_t clk_system_irq_handler(int irq, void *dev_id) | ||
43 | { | ||
44 | struct clk_system *sys = (struct clk_system *)dev_id; | ||
45 | |||
46 | wake_up(&sys->wait); | ||
47 | disable_irq_nosync(sys->irq); | ||
48 | |||
49 | return IRQ_HANDLED; | ||
50 | } | ||
51 | |||
52 | static int clk_system_prepare(struct clk_hw *hw) | ||
32 | { | 53 | { |
33 | struct clk_system *sys = to_clk_system(hw); | 54 | struct clk_system *sys = to_clk_system(hw); |
34 | struct at91_pmc *pmc = sys->pmc; | 55 | struct at91_pmc *pmc = sys->pmc; |
56 | u32 mask = 1 << sys->id; | ||
35 | 57 | ||
36 | pmc_write(pmc, AT91_PMC_SCER, 1 << sys->id); | 58 | pmc_write(pmc, AT91_PMC_SCER, mask); |
59 | |||
60 | if (!is_pck(sys->id)) | ||
61 | return 0; | ||
62 | |||
63 | while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) { | ||
64 | if (sys->irq) { | ||
65 | enable_irq(sys->irq); | ||
66 | wait_event(sys->wait, | ||
67 | pmc_read(pmc, AT91_PMC_SR) & mask); | ||
68 | } else | ||
69 | cpu_relax(); | ||
70 | } | ||
37 | return 0; | 71 | return 0; |
38 | } | 72 | } |
39 | 73 | ||
40 | static void clk_system_disable(struct clk_hw *hw) | 74 | static void clk_system_unprepare(struct clk_hw *hw) |
41 | { | 75 | { |
42 | struct clk_system *sys = to_clk_system(hw); | 76 | struct clk_system *sys = to_clk_system(hw); |
43 | struct at91_pmc *pmc = sys->pmc; | 77 | struct at91_pmc *pmc = sys->pmc; |
@@ -45,27 +79,34 @@ static void clk_system_disable(struct clk_hw *hw) | |||
45 | pmc_write(pmc, AT91_PMC_SCDR, 1 << sys->id); | 79 | pmc_write(pmc, AT91_PMC_SCDR, 1 << sys->id); |
46 | } | 80 | } |
47 | 81 | ||
48 | static int clk_system_is_enabled(struct clk_hw *hw) | 82 | static int clk_system_is_prepared(struct clk_hw *hw) |
49 | { | 83 | { |
50 | struct clk_system *sys = to_clk_system(hw); | 84 | struct clk_system *sys = to_clk_system(hw); |
51 | struct at91_pmc *pmc = sys->pmc; | 85 | struct at91_pmc *pmc = sys->pmc; |
52 | 86 | ||
53 | return !!(pmc_read(pmc, AT91_PMC_SCSR) & (1 << sys->id)); | 87 | if (!(pmc_read(pmc, AT91_PMC_SCSR) & (1 << sys->id))) |
88 | return 0; | ||
89 | |||
90 | if (!is_pck(sys->id)) | ||
91 | return 1; | ||
92 | |||
93 | return !!(pmc_read(pmc, AT91_PMC_SR) & (1 << sys->id)); | ||
54 | } | 94 | } |
55 | 95 | ||
56 | static const struct clk_ops system_ops = { | 96 | static const struct clk_ops system_ops = { |
57 | .enable = clk_system_enable, | 97 | .prepare = clk_system_prepare, |
58 | .disable = clk_system_disable, | 98 | .unprepare = clk_system_unprepare, |
59 | .is_enabled = clk_system_is_enabled, | 99 | .is_prepared = clk_system_is_prepared, |
60 | }; | 100 | }; |
61 | 101 | ||
62 | static struct clk * __init | 102 | static struct clk * __init |
63 | at91_clk_register_system(struct at91_pmc *pmc, const char *name, | 103 | at91_clk_register_system(struct at91_pmc *pmc, const char *name, |
64 | const char *parent_name, u8 id) | 104 | const char *parent_name, u8 id, int irq) |
65 | { | 105 | { |
66 | struct clk_system *sys; | 106 | struct clk_system *sys; |
67 | struct clk *clk = NULL; | 107 | struct clk *clk = NULL; |
68 | struct clk_init_data init; | 108 | struct clk_init_data init; |
109 | int ret; | ||
69 | 110 | ||
70 | if (!parent_name || id > SYSTEM_MAX_ID) | 111 | if (!parent_name || id > SYSTEM_MAX_ID) |
71 | return ERR_PTR(-EINVAL); | 112 | return ERR_PTR(-EINVAL); |
@@ -84,11 +125,20 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name, | |||
84 | * (see drivers/memory) which would request and enable the ddrck clock. | 125 | * (see drivers/memory) which would request and enable the ddrck clock. |
85 | * When this is done we will be able to remove CLK_IGNORE_UNUSED flag. | 126 | * When this is done we will be able to remove CLK_IGNORE_UNUSED flag. |
86 | */ | 127 | */ |
87 | init.flags = CLK_IGNORE_UNUSED; | 128 | init.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED; |
88 | 129 | ||
89 | sys->id = id; | 130 | sys->id = id; |
90 | sys->hw.init = &init; | 131 | sys->hw.init = &init; |
91 | sys->pmc = pmc; | 132 | sys->pmc = pmc; |
133 | sys->irq = irq; | ||
134 | if (irq) { | ||
135 | init_waitqueue_head(&sys->wait); | ||
136 | irq_set_status_flags(sys->irq, IRQ_NOAUTOEN); | ||
137 | ret = request_irq(sys->irq, clk_system_irq_handler, | ||
138 | IRQF_TRIGGER_HIGH, name, sys); | ||
139 | if (ret) | ||
140 | return ERR_PTR(ret); | ||
141 | } | ||
92 | 142 | ||
93 | clk = clk_register(NULL, &sys->hw); | 143 | clk = clk_register(NULL, &sys->hw); |
94 | if (IS_ERR(clk)) | 144 | if (IS_ERR(clk)) |
@@ -101,6 +151,7 @@ static void __init | |||
101 | of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc) | 151 | of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc) |
102 | { | 152 | { |
103 | int num; | 153 | int num; |
154 | int irq = 0; | ||
104 | u32 id; | 155 | u32 id; |
105 | struct clk *clk; | 156 | struct clk *clk; |
106 | const char *name; | 157 | const char *name; |
@@ -118,9 +169,12 @@ of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc) | |||
118 | if (of_property_read_string(np, "clock-output-names", &name)) | 169 | if (of_property_read_string(np, "clock-output-names", &name)) |
119 | name = sysclknp->name; | 170 | name = sysclknp->name; |
120 | 171 | ||
172 | if (is_pck(id)) | ||
173 | irq = irq_of_parse_and_map(sysclknp, 0); | ||
174 | |||
121 | parent_name = of_clk_get_parent_name(sysclknp, 0); | 175 | parent_name = of_clk_get_parent_name(sysclknp, 0); |
122 | 176 | ||
123 | clk = at91_clk_register_system(pmc, name, parent_name, id); | 177 | clk = at91_clk_register_system(pmc, name, parent_name, id, irq); |
124 | if (IS_ERR(clk)) | 178 | if (IS_ERR(clk)) |
125 | continue; | 179 | continue; |
126 | 180 | ||
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c index 8137327847c3..1127ee46b802 100644 --- a/drivers/clk/clk-axi-clkgen.c +++ b/drivers/clk/clk-axi-clkgen.c | |||
@@ -17,23 +17,75 @@ | |||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | 19 | ||
20 | #define AXI_CLKGEN_REG_UPDATE_ENABLE 0x04 | 20 | #define AXI_CLKGEN_V1_REG_UPDATE_ENABLE 0x04 |
21 | #define AXI_CLKGEN_REG_CLK_OUT1 0x08 | 21 | #define AXI_CLKGEN_V1_REG_CLK_OUT1 0x08 |
22 | #define AXI_CLKGEN_REG_CLK_OUT2 0x0c | 22 | #define AXI_CLKGEN_V1_REG_CLK_OUT2 0x0c |
23 | #define AXI_CLKGEN_REG_CLK_DIV 0x10 | 23 | #define AXI_CLKGEN_V1_REG_CLK_DIV 0x10 |
24 | #define AXI_CLKGEN_REG_CLK_FB1 0x14 | 24 | #define AXI_CLKGEN_V1_REG_CLK_FB1 0x14 |
25 | #define AXI_CLKGEN_REG_CLK_FB2 0x18 | 25 | #define AXI_CLKGEN_V1_REG_CLK_FB2 0x18 |
26 | #define AXI_CLKGEN_REG_LOCK1 0x1c | 26 | #define AXI_CLKGEN_V1_REG_LOCK1 0x1c |
27 | #define AXI_CLKGEN_REG_LOCK2 0x20 | 27 | #define AXI_CLKGEN_V1_REG_LOCK2 0x20 |
28 | #define AXI_CLKGEN_REG_LOCK3 0x24 | 28 | #define AXI_CLKGEN_V1_REG_LOCK3 0x24 |
29 | #define AXI_CLKGEN_REG_FILTER1 0x28 | 29 | #define AXI_CLKGEN_V1_REG_FILTER1 0x28 |
30 | #define AXI_CLKGEN_REG_FILTER2 0x2c | 30 | #define AXI_CLKGEN_V1_REG_FILTER2 0x2c |
31 | |||
32 | #define AXI_CLKGEN_V2_REG_RESET 0x40 | ||
33 | #define AXI_CLKGEN_V2_REG_DRP_CNTRL 0x70 | ||
34 | #define AXI_CLKGEN_V2_REG_DRP_STATUS 0x74 | ||
35 | |||
36 | #define AXI_CLKGEN_V2_RESET_MMCM_ENABLE BIT(1) | ||
37 | #define AXI_CLKGEN_V2_RESET_ENABLE BIT(0) | ||
38 | |||
39 | #define AXI_CLKGEN_V2_DRP_CNTRL_SEL BIT(29) | ||
40 | #define AXI_CLKGEN_V2_DRP_CNTRL_READ BIT(28) | ||
41 | |||
42 | #define AXI_CLKGEN_V2_DRP_STATUS_BUSY BIT(16) | ||
43 | |||
44 | #define MMCM_REG_CLKOUT0_1 0x08 | ||
45 | #define MMCM_REG_CLKOUT0_2 0x09 | ||
46 | #define MMCM_REG_CLK_FB1 0x14 | ||
47 | #define MMCM_REG_CLK_FB2 0x15 | ||
48 | #define MMCM_REG_CLK_DIV 0x16 | ||
49 | #define MMCM_REG_LOCK1 0x18 | ||
50 | #define MMCM_REG_LOCK2 0x19 | ||
51 | #define MMCM_REG_LOCK3 0x1a | ||
52 | #define MMCM_REG_FILTER1 0x4e | ||
53 | #define MMCM_REG_FILTER2 0x4f | ||
54 | |||
55 | struct axi_clkgen; | ||
56 | |||
57 | struct axi_clkgen_mmcm_ops { | ||
58 | void (*enable)(struct axi_clkgen *axi_clkgen, bool enable); | ||
59 | int (*write)(struct axi_clkgen *axi_clkgen, unsigned int reg, | ||
60 | unsigned int val, unsigned int mask); | ||
61 | int (*read)(struct axi_clkgen *axi_clkgen, unsigned int reg, | ||
62 | unsigned int *val); | ||
63 | }; | ||
31 | 64 | ||
32 | struct axi_clkgen { | 65 | struct axi_clkgen { |
33 | void __iomem *base; | 66 | void __iomem *base; |
67 | const struct axi_clkgen_mmcm_ops *mmcm_ops; | ||
34 | struct clk_hw clk_hw; | 68 | struct clk_hw clk_hw; |
35 | }; | 69 | }; |
36 | 70 | ||
71 | static void axi_clkgen_mmcm_enable(struct axi_clkgen *axi_clkgen, | ||
72 | bool enable) | ||
73 | { | ||
74 | axi_clkgen->mmcm_ops->enable(axi_clkgen, enable); | ||
75 | } | ||
76 | |||
77 | static int axi_clkgen_mmcm_write(struct axi_clkgen *axi_clkgen, | ||
78 | unsigned int reg, unsigned int val, unsigned int mask) | ||
79 | { | ||
80 | return axi_clkgen->mmcm_ops->write(axi_clkgen, reg, val, mask); | ||
81 | } | ||
82 | |||
83 | static int axi_clkgen_mmcm_read(struct axi_clkgen *axi_clkgen, | ||
84 | unsigned int reg, unsigned int *val) | ||
85 | { | ||
86 | return axi_clkgen->mmcm_ops->read(axi_clkgen, reg, val); | ||
87 | } | ||
88 | |||
37 | static uint32_t axi_clkgen_lookup_filter(unsigned int m) | 89 | static uint32_t axi_clkgen_lookup_filter(unsigned int m) |
38 | { | 90 | { |
39 | switch (m) { | 91 | switch (m) { |
@@ -156,6 +208,148 @@ static void axi_clkgen_read(struct axi_clkgen *axi_clkgen, | |||
156 | *val = readl(axi_clkgen->base + reg); | 208 | *val = readl(axi_clkgen->base + reg); |
157 | } | 209 | } |
158 | 210 | ||
211 | static unsigned int axi_clkgen_v1_map_mmcm_reg(unsigned int reg) | ||
212 | { | ||
213 | switch (reg) { | ||
214 | case MMCM_REG_CLKOUT0_1: | ||
215 | return AXI_CLKGEN_V1_REG_CLK_OUT1; | ||
216 | case MMCM_REG_CLKOUT0_2: | ||
217 | return AXI_CLKGEN_V1_REG_CLK_OUT2; | ||
218 | case MMCM_REG_CLK_FB1: | ||
219 | return AXI_CLKGEN_V1_REG_CLK_FB1; | ||
220 | case MMCM_REG_CLK_FB2: | ||
221 | return AXI_CLKGEN_V1_REG_CLK_FB2; | ||
222 | case MMCM_REG_CLK_DIV: | ||
223 | return AXI_CLKGEN_V1_REG_CLK_DIV; | ||
224 | case MMCM_REG_LOCK1: | ||
225 | return AXI_CLKGEN_V1_REG_LOCK1; | ||
226 | case MMCM_REG_LOCK2: | ||
227 | return AXI_CLKGEN_V1_REG_LOCK2; | ||
228 | case MMCM_REG_LOCK3: | ||
229 | return AXI_CLKGEN_V1_REG_LOCK3; | ||
230 | case MMCM_REG_FILTER1: | ||
231 | return AXI_CLKGEN_V1_REG_FILTER1; | ||
232 | case MMCM_REG_FILTER2: | ||
233 | return AXI_CLKGEN_V1_REG_FILTER2; | ||
234 | default: | ||
235 | return 0; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | static int axi_clkgen_v1_mmcm_write(struct axi_clkgen *axi_clkgen, | ||
240 | unsigned int reg, unsigned int val, unsigned int mask) | ||
241 | { | ||
242 | reg = axi_clkgen_v1_map_mmcm_reg(reg); | ||
243 | if (reg == 0) | ||
244 | return -EINVAL; | ||
245 | |||
246 | axi_clkgen_write(axi_clkgen, reg, val); | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static int axi_clkgen_v1_mmcm_read(struct axi_clkgen *axi_clkgen, | ||
252 | unsigned int reg, unsigned int *val) | ||
253 | { | ||
254 | reg = axi_clkgen_v1_map_mmcm_reg(reg); | ||
255 | if (reg == 0) | ||
256 | return -EINVAL; | ||
257 | |||
258 | axi_clkgen_read(axi_clkgen, reg, val); | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static void axi_clkgen_v1_mmcm_enable(struct axi_clkgen *axi_clkgen, | ||
264 | bool enable) | ||
265 | { | ||
266 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V1_REG_UPDATE_ENABLE, enable); | ||
267 | } | ||
268 | |||
269 | static const struct axi_clkgen_mmcm_ops axi_clkgen_v1_mmcm_ops = { | ||
270 | .write = axi_clkgen_v1_mmcm_write, | ||
271 | .read = axi_clkgen_v1_mmcm_read, | ||
272 | .enable = axi_clkgen_v1_mmcm_enable, | ||
273 | }; | ||
274 | |||
275 | static int axi_clkgen_wait_non_busy(struct axi_clkgen *axi_clkgen) | ||
276 | { | ||
277 | unsigned int timeout = 10000; | ||
278 | unsigned int val; | ||
279 | |||
280 | do { | ||
281 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_STATUS, &val); | ||
282 | } while ((val & AXI_CLKGEN_V2_DRP_STATUS_BUSY) && --timeout); | ||
283 | |||
284 | if (val & AXI_CLKGEN_V2_DRP_STATUS_BUSY) | ||
285 | return -EIO; | ||
286 | |||
287 | return val & 0xffff; | ||
288 | } | ||
289 | |||
290 | static int axi_clkgen_v2_mmcm_read(struct axi_clkgen *axi_clkgen, | ||
291 | unsigned int reg, unsigned int *val) | ||
292 | { | ||
293 | unsigned int reg_val; | ||
294 | int ret; | ||
295 | |||
296 | ret = axi_clkgen_wait_non_busy(axi_clkgen); | ||
297 | if (ret < 0) | ||
298 | return ret; | ||
299 | |||
300 | reg_val = AXI_CLKGEN_V2_DRP_CNTRL_SEL | AXI_CLKGEN_V2_DRP_CNTRL_READ; | ||
301 | reg_val |= (reg << 16); | ||
302 | |||
303 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val); | ||
304 | |||
305 | ret = axi_clkgen_wait_non_busy(axi_clkgen); | ||
306 | if (ret < 0) | ||
307 | return ret; | ||
308 | |||
309 | *val = ret; | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static int axi_clkgen_v2_mmcm_write(struct axi_clkgen *axi_clkgen, | ||
315 | unsigned int reg, unsigned int val, unsigned int mask) | ||
316 | { | ||
317 | unsigned int reg_val = 0; | ||
318 | int ret; | ||
319 | |||
320 | ret = axi_clkgen_wait_non_busy(axi_clkgen); | ||
321 | if (ret < 0) | ||
322 | return ret; | ||
323 | |||
324 | if (mask != 0xffff) { | ||
325 | axi_clkgen_v2_mmcm_read(axi_clkgen, reg, ®_val); | ||
326 | reg_val &= ~mask; | ||
327 | } | ||
328 | |||
329 | reg_val |= AXI_CLKGEN_V2_DRP_CNTRL_SEL | (reg << 16) | (val & mask); | ||
330 | |||
331 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_DRP_CNTRL, reg_val); | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static void axi_clkgen_v2_mmcm_enable(struct axi_clkgen *axi_clkgen, | ||
337 | bool enable) | ||
338 | { | ||
339 | unsigned int val = AXI_CLKGEN_V2_RESET_ENABLE; | ||
340 | |||
341 | if (enable) | ||
342 | val |= AXI_CLKGEN_V2_RESET_MMCM_ENABLE; | ||
343 | |||
344 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_V2_REG_RESET, val); | ||
345 | } | ||
346 | |||
347 | static const struct axi_clkgen_mmcm_ops axi_clkgen_v2_mmcm_ops = { | ||
348 | .write = axi_clkgen_v2_mmcm_write, | ||
349 | .read = axi_clkgen_v2_mmcm_read, | ||
350 | .enable = axi_clkgen_v2_mmcm_enable, | ||
351 | }; | ||
352 | |||
159 | static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw) | 353 | static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw) |
160 | { | 354 | { |
161 | return container_of(clk_hw, struct axi_clkgen, clk_hw); | 355 | return container_of(clk_hw, struct axi_clkgen, clk_hw); |
@@ -184,33 +378,29 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw, | |||
184 | filter = axi_clkgen_lookup_filter(m - 1); | 378 | filter = axi_clkgen_lookup_filter(m - 1); |
185 | lock = axi_clkgen_lookup_lock(m - 1); | 379 | lock = axi_clkgen_lookup_lock(m - 1); |
186 | 380 | ||
187 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 0); | ||
188 | |||
189 | axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount); | 381 | axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount); |
190 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, | 382 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_1, |
191 | (high << 6) | low); | 383 | (high << 6) | low, 0xefff); |
192 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT2, | 384 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_2, |
193 | (edge << 7) | (nocount << 6)); | 385 | (edge << 7) | (nocount << 6), 0x03ff); |
194 | 386 | ||
195 | axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount); | 387 | axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount); |
196 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, | 388 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_DIV, |
197 | (edge << 13) | (nocount << 12) | (high << 6) | low); | 389 | (edge << 13) | (nocount << 12) | (high << 6) | low, 0x3fff); |
198 | 390 | ||
199 | axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount); | 391 | axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount); |
200 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, | 392 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB1, |
201 | (high << 6) | low); | 393 | (high << 6) | low, 0xefff); |
202 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB2, | 394 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB2, |
203 | (edge << 7) | (nocount << 6)); | 395 | (edge << 7) | (nocount << 6), 0x03ff); |
204 | 396 | ||
205 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK1, lock & 0x3ff); | 397 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK1, lock & 0x3ff, 0x3ff); |
206 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK2, | 398 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK2, |
207 | (((lock >> 16) & 0x1f) << 10) | 0x1); | 399 | (((lock >> 16) & 0x1f) << 10) | 0x1, 0x7fff); |
208 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK3, | 400 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK3, |
209 | (((lock >> 24) & 0x1f) << 10) | 0x3e9); | 401 | (((lock >> 24) & 0x1f) << 10) | 0x3e9, 0x7fff); |
210 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER1, filter >> 16); | 402 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER1, filter >> 16, 0x9900); |
211 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER2, filter); | 403 | axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER2, filter, 0x9900); |
212 | |||
213 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 1); | ||
214 | 404 | ||
215 | return 0; | 405 | return 0; |
216 | } | 406 | } |
@@ -236,11 +426,11 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw, | |||
236 | unsigned int reg; | 426 | unsigned int reg; |
237 | unsigned long long tmp; | 427 | unsigned long long tmp; |
238 | 428 | ||
239 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, ®); | 429 | axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, ®); |
240 | dout = (reg & 0x3f) + ((reg >> 6) & 0x3f); | 430 | dout = (reg & 0x3f) + ((reg >> 6) & 0x3f); |
241 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, ®); | 431 | axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, ®); |
242 | d = (reg & 0x3f) + ((reg >> 6) & 0x3f); | 432 | d = (reg & 0x3f) + ((reg >> 6) & 0x3f); |
243 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, ®); | 433 | axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, ®); |
244 | m = (reg & 0x3f) + ((reg >> 6) & 0x3f); | 434 | m = (reg & 0x3f) + ((reg >> 6) & 0x3f); |
245 | 435 | ||
246 | if (d == 0 || dout == 0) | 436 | if (d == 0 || dout == 0) |
@@ -255,14 +445,45 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw, | |||
255 | return tmp; | 445 | return tmp; |
256 | } | 446 | } |
257 | 447 | ||
448 | static int axi_clkgen_enable(struct clk_hw *clk_hw) | ||
449 | { | ||
450 | struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); | ||
451 | |||
452 | axi_clkgen_mmcm_enable(axi_clkgen, true); | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static void axi_clkgen_disable(struct clk_hw *clk_hw) | ||
458 | { | ||
459 | struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); | ||
460 | |||
461 | axi_clkgen_mmcm_enable(axi_clkgen, false); | ||
462 | } | ||
463 | |||
258 | static const struct clk_ops axi_clkgen_ops = { | 464 | static const struct clk_ops axi_clkgen_ops = { |
259 | .recalc_rate = axi_clkgen_recalc_rate, | 465 | .recalc_rate = axi_clkgen_recalc_rate, |
260 | .round_rate = axi_clkgen_round_rate, | 466 | .round_rate = axi_clkgen_round_rate, |
261 | .set_rate = axi_clkgen_set_rate, | 467 | .set_rate = axi_clkgen_set_rate, |
468 | .enable = axi_clkgen_enable, | ||
469 | .disable = axi_clkgen_disable, | ||
262 | }; | 470 | }; |
263 | 471 | ||
472 | static const struct of_device_id axi_clkgen_ids[] = { | ||
473 | { | ||
474 | .compatible = "adi,axi-clkgen-1.00.a", | ||
475 | .data = &axi_clkgen_v1_mmcm_ops | ||
476 | }, { | ||
477 | .compatible = "adi,axi-clkgen-2.00.a", | ||
478 | .data = &axi_clkgen_v2_mmcm_ops, | ||
479 | }, | ||
480 | { }, | ||
481 | }; | ||
482 | MODULE_DEVICE_TABLE(of, axi_clkgen_ids); | ||
483 | |||
264 | static int axi_clkgen_probe(struct platform_device *pdev) | 484 | static int axi_clkgen_probe(struct platform_device *pdev) |
265 | { | 485 | { |
486 | const struct of_device_id *id; | ||
266 | struct axi_clkgen *axi_clkgen; | 487 | struct axi_clkgen *axi_clkgen; |
267 | struct clk_init_data init; | 488 | struct clk_init_data init; |
268 | const char *parent_name; | 489 | const char *parent_name; |
@@ -270,10 +491,19 @@ static int axi_clkgen_probe(struct platform_device *pdev) | |||
270 | struct resource *mem; | 491 | struct resource *mem; |
271 | struct clk *clk; | 492 | struct clk *clk; |
272 | 493 | ||
494 | if (!pdev->dev.of_node) | ||
495 | return -ENODEV; | ||
496 | |||
497 | id = of_match_node(axi_clkgen_ids, pdev->dev.of_node); | ||
498 | if (!id) | ||
499 | return -ENODEV; | ||
500 | |||
273 | axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL); | 501 | axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL); |
274 | if (!axi_clkgen) | 502 | if (!axi_clkgen) |
275 | return -ENOMEM; | 503 | return -ENOMEM; |
276 | 504 | ||
505 | axi_clkgen->mmcm_ops = id->data; | ||
506 | |||
277 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 507 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
278 | axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem); | 508 | axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem); |
279 | if (IS_ERR(axi_clkgen->base)) | 509 | if (IS_ERR(axi_clkgen->base)) |
@@ -289,10 +519,12 @@ static int axi_clkgen_probe(struct platform_device *pdev) | |||
289 | 519 | ||
290 | init.name = clk_name; | 520 | init.name = clk_name; |
291 | init.ops = &axi_clkgen_ops; | 521 | init.ops = &axi_clkgen_ops; |
292 | init.flags = 0; | 522 | init.flags = CLK_SET_RATE_GATE; |
293 | init.parent_names = &parent_name; | 523 | init.parent_names = &parent_name; |
294 | init.num_parents = 1; | 524 | init.num_parents = 1; |
295 | 525 | ||
526 | axi_clkgen_mmcm_enable(axi_clkgen, false); | ||
527 | |||
296 | axi_clkgen->clk_hw.init = &init; | 528 | axi_clkgen->clk_hw.init = &init; |
297 | clk = devm_clk_register(&pdev->dev, &axi_clkgen->clk_hw); | 529 | clk = devm_clk_register(&pdev->dev, &axi_clkgen->clk_hw); |
298 | if (IS_ERR(clk)) | 530 | if (IS_ERR(clk)) |
@@ -309,12 +541,6 @@ static int axi_clkgen_remove(struct platform_device *pdev) | |||
309 | return 0; | 541 | return 0; |
310 | } | 542 | } |
311 | 543 | ||
312 | static const struct of_device_id axi_clkgen_ids[] = { | ||
313 | { .compatible = "adi,axi-clkgen-1.00.a" }, | ||
314 | { }, | ||
315 | }; | ||
316 | MODULE_DEVICE_TABLE(of, axi_clkgen_ids); | ||
317 | |||
318 | static struct platform_driver axi_clkgen_driver = { | 544 | static struct platform_driver axi_clkgen_driver = { |
319 | .driver = { | 545 | .driver = { |
320 | .name = "adi-axi-clkgen", | 546 | .name = "adi-axi-clkgen", |
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 5543b7df8e16..ec22112e569f 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c | |||
@@ -24,7 +24,7 @@ | |||
24 | * Traits of this clock: | 24 | * Traits of this clock: |
25 | * prepare - clk_prepare only ensures that parents are prepared | 25 | * prepare - clk_prepare only ensures that parents are prepared |
26 | * enable - clk_enable only ensures that parents are enabled | 26 | * enable - clk_enable only ensures that parents are enabled |
27 | * rate - rate is adjustable. clk->rate = parent->rate / divisor | 27 | * rate - rate is adjustable. clk->rate = DIV_ROUND_UP(parent->rate / divisor) |
28 | * parent - fixed parent. No clk_set_parent support | 28 | * parent - fixed parent. No clk_set_parent support |
29 | */ | 29 | */ |
30 | 30 | ||
@@ -115,7 +115,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, | |||
115 | return parent_rate; | 115 | return parent_rate; |
116 | } | 116 | } |
117 | 117 | ||
118 | return parent_rate / div; | 118 | return DIV_ROUND_UP(parent_rate, div); |
119 | } | 119 | } |
120 | 120 | ||
121 | /* | 121 | /* |
@@ -185,7 +185,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, | |||
185 | } | 185 | } |
186 | parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), | 186 | parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), |
187 | MULT_ROUND_UP(rate, i)); | 187 | MULT_ROUND_UP(rate, i)); |
188 | now = parent_rate / i; | 188 | now = DIV_ROUND_UP(parent_rate, i); |
189 | if (now <= rate && now > best) { | 189 | if (now <= rate && now > best) { |
190 | bestdiv = i; | 190 | bestdiv = i; |
191 | best = now; | 191 | best = now; |
@@ -207,7 +207,7 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, | |||
207 | int div; | 207 | int div; |
208 | div = clk_divider_bestdiv(hw, rate, prate); | 208 | div = clk_divider_bestdiv(hw, rate, prate); |
209 | 209 | ||
210 | return *prate / div; | 210 | return DIV_ROUND_UP(*prate, div); |
211 | } | 211 | } |
212 | 212 | ||
213 | static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, | 213 | static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, |
@@ -218,7 +218,7 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, | |||
218 | unsigned long flags = 0; | 218 | unsigned long flags = 0; |
219 | u32 val; | 219 | u32 val; |
220 | 220 | ||
221 | div = parent_rate / rate; | 221 | div = DIV_ROUND_UP(parent_rate, rate); |
222 | value = _get_val(divider, div); | 222 | value = _get_val(divider, div); |
223 | 223 | ||
224 | if (value > div_mask(divider)) | 224 | if (value > div_mask(divider)) |
diff --git a/drivers/clk/clk-moxart.c b/drivers/clk/clk-moxart.c new file mode 100644 index 000000000000..30a3b6999e10 --- /dev/null +++ b/drivers/clk/clk-moxart.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * MOXA ART SoCs clock driver. | ||
3 | * | ||
4 | * Copyright (C) 2013 Jonas Jensen | ||
5 | * | ||
6 | * Jonas Jensen <jonas.jensen@gmail.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 | #include <linux/clk-provider.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/of_address.h> | ||
16 | #include <linux/clkdev.h> | ||
17 | |||
18 | void __init moxart_of_pll_clk_init(struct device_node *node) | ||
19 | { | ||
20 | static void __iomem *base; | ||
21 | struct clk *clk, *ref_clk; | ||
22 | unsigned int mul; | ||
23 | const char *name = node->name; | ||
24 | const char *parent_name; | ||
25 | |||
26 | of_property_read_string(node, "clock-output-names", &name); | ||
27 | parent_name = of_clk_get_parent_name(node, 0); | ||
28 | |||
29 | base = of_iomap(node, 0); | ||
30 | if (!base) { | ||
31 | pr_err("%s: of_iomap failed\n", node->full_name); | ||
32 | return; | ||
33 | } | ||
34 | |||
35 | mul = readl(base + 0x30) >> 3 & 0x3f; | ||
36 | iounmap(base); | ||
37 | |||
38 | ref_clk = of_clk_get(node, 0); | ||
39 | if (IS_ERR(ref_clk)) { | ||
40 | pr_err("%s: of_clk_get failed\n", node->full_name); | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mul, 1); | ||
45 | if (IS_ERR(clk)) { | ||
46 | pr_err("%s: failed to register clock\n", node->full_name); | ||
47 | return; | ||
48 | } | ||
49 | |||
50 | clk_register_clkdev(clk, NULL, name); | ||
51 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
52 | } | ||
53 | CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock", | ||
54 | moxart_of_pll_clk_init); | ||
55 | |||
56 | void __init moxart_of_apb_clk_init(struct device_node *node) | ||
57 | { | ||
58 | static void __iomem *base; | ||
59 | struct clk *clk, *pll_clk; | ||
60 | unsigned int div, val; | ||
61 | unsigned int div_idx[] = { 2, 3, 4, 6, 8}; | ||
62 | const char *name = node->name; | ||
63 | const char *parent_name; | ||
64 | |||
65 | of_property_read_string(node, "clock-output-names", &name); | ||
66 | parent_name = of_clk_get_parent_name(node, 0); | ||
67 | |||
68 | base = of_iomap(node, 0); | ||
69 | if (!base) { | ||
70 | pr_err("%s: of_iomap failed\n", node->full_name); | ||
71 | return; | ||
72 | } | ||
73 | |||
74 | val = readl(base + 0xc) >> 4 & 0x7; | ||
75 | iounmap(base); | ||
76 | |||
77 | if (val > 4) | ||
78 | val = 0; | ||
79 | div = div_idx[val] * 2; | ||
80 | |||
81 | pll_clk = of_clk_get(node, 0); | ||
82 | if (IS_ERR(pll_clk)) { | ||
83 | pr_err("%s: of_clk_get failed\n", node->full_name); | ||
84 | return; | ||
85 | } | ||
86 | |||
87 | clk = clk_register_fixed_factor(NULL, name, parent_name, 0, 1, div); | ||
88 | if (IS_ERR(clk)) { | ||
89 | pr_err("%s: failed to register clock\n", node->full_name); | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | clk_register_clkdev(clk, NULL, name); | ||
94 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
95 | } | ||
96 | CLK_OF_DECLARE(moxart_apb_clock, "moxa,moxart-apb-clock", | ||
97 | moxart_of_apb_clk_init); | ||
diff --git a/drivers/clk/clk-ppc-corenet.c b/drivers/clk/clk-ppc-corenet.c index c4f76ed914b0..8b284be4efa4 100644 --- a/drivers/clk/clk-ppc-corenet.c +++ b/drivers/clk/clk-ppc-corenet.c | |||
@@ -27,7 +27,6 @@ struct cmux_clk { | |||
27 | #define CLKSEL_ADJUST BIT(0) | 27 | #define CLKSEL_ADJUST BIT(0) |
28 | #define to_cmux_clk(p) container_of(p, struct cmux_clk, hw) | 28 | #define to_cmux_clk(p) container_of(p, struct cmux_clk, hw) |
29 | 29 | ||
30 | static void __iomem *base; | ||
31 | static unsigned int clocks_per_pll; | 30 | static unsigned int clocks_per_pll; |
32 | 31 | ||
33 | static int cmux_set_parent(struct clk_hw *hw, u8 idx) | 32 | static int cmux_set_parent(struct clk_hw *hw, u8 idx) |
@@ -100,7 +99,11 @@ static void __init core_mux_init(struct device_node *np) | |||
100 | pr_err("%s: could not allocate cmux_clk\n", __func__); | 99 | pr_err("%s: could not allocate cmux_clk\n", __func__); |
101 | goto err_name; | 100 | goto err_name; |
102 | } | 101 | } |
103 | cmux_clk->reg = base + offset; | 102 | cmux_clk->reg = of_iomap(np, 0); |
103 | if (!cmux_clk->reg) { | ||
104 | pr_err("%s: could not map register\n", __func__); | ||
105 | goto err_clk; | ||
106 | } | ||
104 | 107 | ||
105 | node = of_find_compatible_node(NULL, NULL, "fsl,p4080-clockgen"); | 108 | node = of_find_compatible_node(NULL, NULL, "fsl,p4080-clockgen"); |
106 | if (node && (offset >= 0x80)) | 109 | if (node && (offset >= 0x80)) |
@@ -143,38 +146,39 @@ err_name: | |||
143 | 146 | ||
144 | static void __init core_pll_init(struct device_node *np) | 147 | static void __init core_pll_init(struct device_node *np) |
145 | { | 148 | { |
146 | u32 offset, mult; | 149 | u32 mult; |
147 | int i, rc, count; | 150 | int i, rc, count; |
148 | const char *clk_name, *parent_name; | 151 | const char *clk_name, *parent_name; |
149 | struct clk_onecell_data *onecell_data; | 152 | struct clk_onecell_data *onecell_data; |
150 | struct clk **subclks; | 153 | struct clk **subclks; |
154 | void __iomem *base; | ||
151 | 155 | ||
152 | rc = of_property_read_u32(np, "reg", &offset); | 156 | base = of_iomap(np, 0); |
153 | if (rc) { | 157 | if (!base) { |
154 | pr_err("%s: could not get reg property\n", np->name); | 158 | pr_err("clk-ppc: iomap error\n"); |
155 | return; | 159 | return; |
156 | } | 160 | } |
157 | 161 | ||
158 | /* get the multiple of PLL */ | 162 | /* get the multiple of PLL */ |
159 | mult = ioread32be(base + offset); | 163 | mult = ioread32be(base); |
160 | 164 | ||
161 | /* check if this PLL is disabled */ | 165 | /* check if this PLL is disabled */ |
162 | if (mult & PLL_KILL) { | 166 | if (mult & PLL_KILL) { |
163 | pr_debug("PLL:%s is disabled\n", np->name); | 167 | pr_debug("PLL:%s is disabled\n", np->name); |
164 | return; | 168 | goto err_map; |
165 | } | 169 | } |
166 | mult = (mult >> 1) & 0x3f; | 170 | mult = (mult >> 1) & 0x3f; |
167 | 171 | ||
168 | parent_name = of_clk_get_parent_name(np, 0); | 172 | parent_name = of_clk_get_parent_name(np, 0); |
169 | if (!parent_name) { | 173 | if (!parent_name) { |
170 | pr_err("PLL: %s must have a parent\n", np->name); | 174 | pr_err("PLL: %s must have a parent\n", np->name); |
171 | return; | 175 | goto err_map; |
172 | } | 176 | } |
173 | 177 | ||
174 | count = of_property_count_strings(np, "clock-output-names"); | 178 | count = of_property_count_strings(np, "clock-output-names"); |
175 | if (count < 0 || count > 4) { | 179 | if (count < 0 || count > 4) { |
176 | pr_err("%s: clock is not supported\n", np->name); | 180 | pr_err("%s: clock is not supported\n", np->name); |
177 | return; | 181 | goto err_map; |
178 | } | 182 | } |
179 | 183 | ||
180 | /* output clock number per PLL */ | 184 | /* output clock number per PLL */ |
@@ -183,7 +187,7 @@ static void __init core_pll_init(struct device_node *np) | |||
183 | subclks = kzalloc(sizeof(struct clk *) * count, GFP_KERNEL); | 187 | subclks = kzalloc(sizeof(struct clk *) * count, GFP_KERNEL); |
184 | if (!subclks) { | 188 | if (!subclks) { |
185 | pr_err("%s: could not allocate subclks\n", __func__); | 189 | pr_err("%s: could not allocate subclks\n", __func__); |
186 | return; | 190 | goto err_map; |
187 | } | 191 | } |
188 | 192 | ||
189 | onecell_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL); | 193 | onecell_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL); |
@@ -230,30 +234,52 @@ static void __init core_pll_init(struct device_node *np) | |||
230 | goto err_cell; | 234 | goto err_cell; |
231 | } | 235 | } |
232 | 236 | ||
237 | iounmap(base); | ||
233 | return; | 238 | return; |
234 | err_cell: | 239 | err_cell: |
235 | kfree(onecell_data); | 240 | kfree(onecell_data); |
236 | err_clks: | 241 | err_clks: |
237 | kfree(subclks); | 242 | kfree(subclks); |
243 | err_map: | ||
244 | iounmap(base); | ||
245 | } | ||
246 | |||
247 | static void __init sysclk_init(struct device_node *node) | ||
248 | { | ||
249 | struct clk *clk; | ||
250 | const char *clk_name = node->name; | ||
251 | struct device_node *np = of_get_parent(node); | ||
252 | u32 rate; | ||
253 | |||
254 | if (!np) { | ||
255 | pr_err("ppc-clk: could not get parent node\n"); | ||
256 | return; | ||
257 | } | ||
258 | |||
259 | if (of_property_read_u32(np, "clock-frequency", &rate)) { | ||
260 | of_node_put(node); | ||
261 | return; | ||
262 | } | ||
263 | |||
264 | of_property_read_string(np, "clock-output-names", &clk_name); | ||
265 | |||
266 | clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate); | ||
267 | if (!IS_ERR(clk)) | ||
268 | of_clk_add_provider(np, of_clk_src_simple_get, clk); | ||
238 | } | 269 | } |
239 | 270 | ||
240 | static const struct of_device_id clk_match[] __initconst = { | 271 | static const struct of_device_id clk_match[] __initconst = { |
241 | { .compatible = "fixed-clock", .data = of_fixed_clk_setup, }, | 272 | { .compatible = "fsl,qoriq-sysclk-1.0", .data = sysclk_init, }, |
242 | { .compatible = "fsl,core-pll-clock", .data = core_pll_init, }, | 273 | { .compatible = "fsl,qoriq-sysclk-2.0", .data = sysclk_init, }, |
243 | { .compatible = "fsl,core-mux-clock", .data = core_mux_init, }, | 274 | { .compatible = "fsl,qoriq-core-pll-1.0", .data = core_pll_init, }, |
275 | { .compatible = "fsl,qoriq-core-pll-2.0", .data = core_pll_init, }, | ||
276 | { .compatible = "fsl,qoriq-core-mux-1.0", .data = core_mux_init, }, | ||
277 | { .compatible = "fsl,qoriq-core-mux-2.0", .data = core_mux_init, }, | ||
244 | {} | 278 | {} |
245 | }; | 279 | }; |
246 | 280 | ||
247 | static int __init ppc_corenet_clk_probe(struct platform_device *pdev) | 281 | static int __init ppc_corenet_clk_probe(struct platform_device *pdev) |
248 | { | 282 | { |
249 | struct device_node *np; | ||
250 | |||
251 | np = pdev->dev.of_node; | ||
252 | base = of_iomap(np, 0); | ||
253 | if (!base) { | ||
254 | dev_err(&pdev->dev, "iomap error\n"); | ||
255 | return -ENOMEM; | ||
256 | } | ||
257 | of_clk_init(clk_match); | 283 | of_clk_init(clk_match); |
258 | 284 | ||
259 | return 0; | 285 | return 0; |
diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c index 00a3abe103a5..f2f62a1bf61a 100644 --- a/drivers/clk/clk-s2mps11.c +++ b/drivers/clk/clk-s2mps11.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/clk-provider.h> | 27 | #include <linux/clk-provider.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/mfd/samsung/s2mps11.h> | 29 | #include <linux/mfd/samsung/s2mps11.h> |
30 | #include <linux/mfd/samsung/s5m8767.h> | ||
30 | #include <linux/mfd/samsung/core.h> | 31 | #include <linux/mfd/samsung/core.h> |
31 | 32 | ||
32 | #define s2mps11_name(a) (a->hw.init->name) | 33 | #define s2mps11_name(a) (a->hw.init->name) |
@@ -48,6 +49,7 @@ struct s2mps11_clk { | |||
48 | struct clk_lookup *lookup; | 49 | struct clk_lookup *lookup; |
49 | u32 mask; | 50 | u32 mask; |
50 | bool enabled; | 51 | bool enabled; |
52 | unsigned int reg; | ||
51 | }; | 53 | }; |
52 | 54 | ||
53 | static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw) | 55 | static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw) |
@@ -61,7 +63,7 @@ static int s2mps11_clk_prepare(struct clk_hw *hw) | |||
61 | int ret; | 63 | int ret; |
62 | 64 | ||
63 | ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, | 65 | ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, |
64 | S2MPS11_REG_RTC_CTRL, | 66 | s2mps11->reg, |
65 | s2mps11->mask, s2mps11->mask); | 67 | s2mps11->mask, s2mps11->mask); |
66 | if (!ret) | 68 | if (!ret) |
67 | s2mps11->enabled = true; | 69 | s2mps11->enabled = true; |
@@ -74,7 +76,7 @@ static void s2mps11_clk_unprepare(struct clk_hw *hw) | |||
74 | struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw); | 76 | struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw); |
75 | int ret; | 77 | int ret; |
76 | 78 | ||
77 | ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, S2MPS11_REG_RTC_CTRL, | 79 | ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, s2mps11->reg, |
78 | s2mps11->mask, ~s2mps11->mask); | 80 | s2mps11->mask, ~s2mps11->mask); |
79 | 81 | ||
80 | if (!ret) | 82 | if (!ret) |
@@ -130,9 +132,9 @@ static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev) | |||
130 | int i; | 132 | int i; |
131 | 133 | ||
132 | if (!iodev->dev->of_node) | 134 | if (!iodev->dev->of_node) |
133 | return NULL; | 135 | return ERR_PTR(-EINVAL); |
134 | 136 | ||
135 | clk_np = of_find_node_by_name(iodev->dev->of_node, "clocks"); | 137 | clk_np = of_get_child_by_name(iodev->dev->of_node, "clocks"); |
136 | if (!clk_np) { | 138 | if (!clk_np) { |
137 | dev_err(&pdev->dev, "could not find clock sub-node\n"); | 139 | dev_err(&pdev->dev, "could not find clock sub-node\n"); |
138 | return ERR_PTR(-EINVAL); | 140 | return ERR_PTR(-EINVAL); |
@@ -155,6 +157,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev) | |||
155 | struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); | 157 | struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); |
156 | struct s2mps11_clk *s2mps11_clks, *s2mps11_clk; | 158 | struct s2mps11_clk *s2mps11_clks, *s2mps11_clk; |
157 | struct device_node *clk_np = NULL; | 159 | struct device_node *clk_np = NULL; |
160 | unsigned int s2mps11_reg; | ||
158 | int i, ret = 0; | 161 | int i, ret = 0; |
159 | u32 val; | 162 | u32 val; |
160 | 163 | ||
@@ -169,13 +172,26 @@ static int s2mps11_clk_probe(struct platform_device *pdev) | |||
169 | if (IS_ERR(clk_np)) | 172 | if (IS_ERR(clk_np)) |
170 | return PTR_ERR(clk_np); | 173 | return PTR_ERR(clk_np); |
171 | 174 | ||
175 | switch(platform_get_device_id(pdev)->driver_data) { | ||
176 | case S2MPS11X: | ||
177 | s2mps11_reg = S2MPS11_REG_RTC_CTRL; | ||
178 | break; | ||
179 | case S5M8767X: | ||
180 | s2mps11_reg = S5M8767_REG_CTRL1; | ||
181 | break; | ||
182 | default: | ||
183 | dev_err(&pdev->dev, "Invalid device type\n"); | ||
184 | return -EINVAL; | ||
185 | }; | ||
186 | |||
172 | for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) { | 187 | for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) { |
173 | s2mps11_clk->iodev = iodev; | 188 | s2mps11_clk->iodev = iodev; |
174 | s2mps11_clk->hw.init = &s2mps11_clks_init[i]; | 189 | s2mps11_clk->hw.init = &s2mps11_clks_init[i]; |
175 | s2mps11_clk->mask = 1 << i; | 190 | s2mps11_clk->mask = 1 << i; |
191 | s2mps11_clk->reg = s2mps11_reg; | ||
176 | 192 | ||
177 | ret = regmap_read(s2mps11_clk->iodev->regmap_pmic, | 193 | ret = regmap_read(s2mps11_clk->iodev->regmap_pmic, |
178 | S2MPS11_REG_RTC_CTRL, &val); | 194 | s2mps11_clk->reg, &val); |
179 | if (ret < 0) | 195 | if (ret < 0) |
180 | goto err_reg; | 196 | goto err_reg; |
181 | 197 | ||
@@ -241,7 +257,8 @@ static int s2mps11_clk_remove(struct platform_device *pdev) | |||
241 | } | 257 | } |
242 | 258 | ||
243 | static const struct platform_device_id s2mps11_clk_id[] = { | 259 | static const struct platform_device_id s2mps11_clk_id[] = { |
244 | { "s2mps11-clk", 0}, | 260 | { "s2mps11-clk", S2MPS11X}, |
261 | { "s5m8767-clk", S5M8767X}, | ||
245 | { }, | 262 | { }, |
246 | }; | 263 | }; |
247 | MODULE_DEVICE_TABLE(platform, s2mps11_clk_id); | 264 | MODULE_DEVICE_TABLE(platform, s2mps11_clk_id); |
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index c42e608af6bb..dff0373f53c1 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
@@ -277,6 +277,10 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) | |||
277 | if (!d) | 277 | if (!d) |
278 | goto err_out; | 278 | goto err_out; |
279 | 279 | ||
280 | if (clk->ops->debug_init) | ||
281 | if (clk->ops->debug_init(clk->hw, clk->dentry)) | ||
282 | goto err_out; | ||
283 | |||
280 | ret = 0; | 284 | ret = 0; |
281 | goto out; | 285 | goto out; |
282 | 286 | ||
@@ -1339,8 +1343,11 @@ static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate) | |||
1339 | if (clk->notifier_count) | 1343 | if (clk->notifier_count) |
1340 | ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate); | 1344 | ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate); |
1341 | 1345 | ||
1342 | if (ret & NOTIFY_STOP_MASK) | 1346 | if (ret & NOTIFY_STOP_MASK) { |
1347 | pr_debug("%s: clk notifier callback for clock %s aborted with error %d\n", | ||
1348 | __func__, clk->name, ret); | ||
1343 | goto out; | 1349 | goto out; |
1350 | } | ||
1344 | 1351 | ||
1345 | hlist_for_each_entry(child, &clk->children, child_node) { | 1352 | hlist_for_each_entry(child, &clk->children, child_node) { |
1346 | ret = __clk_speculate_rates(child, new_rate); | 1353 | ret = __clk_speculate_rates(child, new_rate); |
@@ -1588,7 +1595,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
1588 | /* notify that we are about to change rates */ | 1595 | /* notify that we are about to change rates */ |
1589 | fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE); | 1596 | fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE); |
1590 | if (fail_clk) { | 1597 | if (fail_clk) { |
1591 | pr_warn("%s: failed to set %s rate\n", __func__, | 1598 | pr_debug("%s: failed to set %s rate\n", __func__, |
1592 | fail_clk->name); | 1599 | fail_clk->name); |
1593 | clk_propagate_rate_change(top, ABORT_RATE_CHANGE); | 1600 | clk_propagate_rate_change(top, ABORT_RATE_CHANGE); |
1594 | ret = -EBUSY; | 1601 | ret = -EBUSY; |
@@ -2260,20 +2267,11 @@ void __clk_put(struct clk *clk) | |||
2260 | * re-enter into the clk framework by calling any top-level clk APIs; | 2267 | * re-enter into the clk framework by calling any top-level clk APIs; |
2261 | * this will cause a nested prepare_lock mutex. | 2268 | * this will cause a nested prepare_lock mutex. |
2262 | * | 2269 | * |
2263 | * Pre-change notifier callbacks will be passed the current, pre-change | 2270 | * In all notification cases cases (pre, post and abort rate change) the |
2264 | * rate of the clk via struct clk_notifier_data.old_rate. The new, | 2271 | * original clock rate is passed to the callback via struct |
2265 | * post-change rate of the clk is passed via struct | 2272 | * clk_notifier_data.old_rate and the new frequency is passed via struct |
2266 | * clk_notifier_data.new_rate. | ||
2267 | * | ||
2268 | * Post-change notifiers will pass the now-current, post-change rate of | ||
2269 | * the clk in both struct clk_notifier_data.old_rate and struct | ||
2270 | * clk_notifier_data.new_rate. | 2273 | * clk_notifier_data.new_rate. |
2271 | * | 2274 | * |
2272 | * Abort-change notifiers are effectively the opposite of pre-change | ||
2273 | * notifiers: the original pre-change clk rate is passed in via struct | ||
2274 | * clk_notifier_data.new_rate and the failed post-change rate is passed | ||
2275 | * in via struct clk_notifier_data.old_rate. | ||
2276 | * | ||
2277 | * clk_notifier_register() must be called from non-atomic context. | 2275 | * clk_notifier_register() must be called from non-atomic context. |
2278 | * Returns -EINVAL if called with null arguments, -ENOMEM upon | 2276 | * Returns -EINVAL if called with null arguments, -ENOMEM upon |
2279 | * allocation failure; otherwise, passes along the return value of | 2277 | * allocation failure; otherwise, passes along the return value of |
@@ -2473,7 +2471,7 @@ EXPORT_SYMBOL_GPL(of_clk_del_provider); | |||
2473 | struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec) | 2471 | struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec) |
2474 | { | 2472 | { |
2475 | struct of_clk_provider *provider; | 2473 | struct of_clk_provider *provider; |
2476 | struct clk *clk = ERR_PTR(-ENOENT); | 2474 | struct clk *clk = ERR_PTR(-EPROBE_DEFER); |
2477 | 2475 | ||
2478 | /* Check if we have such a provider in our array */ | 2476 | /* Check if we have such a provider in our array */ |
2479 | list_for_each_entry(provider, &of_clk_providers, link) { | 2477 | list_for_each_entry(provider, &of_clk_providers, link) { |
@@ -2506,8 +2504,12 @@ EXPORT_SYMBOL_GPL(of_clk_get_parent_count); | |||
2506 | const char *of_clk_get_parent_name(struct device_node *np, int index) | 2504 | const char *of_clk_get_parent_name(struct device_node *np, int index) |
2507 | { | 2505 | { |
2508 | struct of_phandle_args clkspec; | 2506 | struct of_phandle_args clkspec; |
2507 | struct property *prop; | ||
2509 | const char *clk_name; | 2508 | const char *clk_name; |
2509 | const __be32 *vp; | ||
2510 | u32 pv; | ||
2510 | int rc; | 2511 | int rc; |
2512 | int count; | ||
2511 | 2513 | ||
2512 | if (index < 0) | 2514 | if (index < 0) |
2513 | return NULL; | 2515 | return NULL; |
@@ -2517,8 +2519,22 @@ const char *of_clk_get_parent_name(struct device_node *np, int index) | |||
2517 | if (rc) | 2519 | if (rc) |
2518 | return NULL; | 2520 | return NULL; |
2519 | 2521 | ||
2522 | index = clkspec.args_count ? clkspec.args[0] : 0; | ||
2523 | count = 0; | ||
2524 | |||
2525 | /* if there is an indices property, use it to transfer the index | ||
2526 | * specified into an array offset for the clock-output-names property. | ||
2527 | */ | ||
2528 | of_property_for_each_u32(clkspec.np, "clock-indices", prop, vp, pv) { | ||
2529 | if (index == pv) { | ||
2530 | index = count; | ||
2531 | break; | ||
2532 | } | ||
2533 | count++; | ||
2534 | } | ||
2535 | |||
2520 | if (of_property_read_string_index(clkspec.np, "clock-output-names", | 2536 | if (of_property_read_string_index(clkspec.np, "clock-output-names", |
2521 | clkspec.args_count ? clkspec.args[0] : 0, | 2537 | index, |
2522 | &clk_name) < 0) | 2538 | &clk_name) < 0) |
2523 | clk_name = clkspec.np->name; | 2539 | clk_name = clkspec.np->name; |
2524 | 2540 | ||
@@ -2527,24 +2543,99 @@ const char *of_clk_get_parent_name(struct device_node *np, int index) | |||
2527 | } | 2543 | } |
2528 | EXPORT_SYMBOL_GPL(of_clk_get_parent_name); | 2544 | EXPORT_SYMBOL_GPL(of_clk_get_parent_name); |
2529 | 2545 | ||
2546 | struct clock_provider { | ||
2547 | of_clk_init_cb_t clk_init_cb; | ||
2548 | struct device_node *np; | ||
2549 | struct list_head node; | ||
2550 | }; | ||
2551 | |||
2552 | static LIST_HEAD(clk_provider_list); | ||
2553 | |||
2554 | /* | ||
2555 | * This function looks for a parent clock. If there is one, then it | ||
2556 | * checks that the provider for this parent clock was initialized, in | ||
2557 | * this case the parent clock will be ready. | ||
2558 | */ | ||
2559 | static int parent_ready(struct device_node *np) | ||
2560 | { | ||
2561 | int i = 0; | ||
2562 | |||
2563 | while (true) { | ||
2564 | struct clk *clk = of_clk_get(np, i); | ||
2565 | |||
2566 | /* this parent is ready we can check the next one */ | ||
2567 | if (!IS_ERR(clk)) { | ||
2568 | clk_put(clk); | ||
2569 | i++; | ||
2570 | continue; | ||
2571 | } | ||
2572 | |||
2573 | /* at least one parent is not ready, we exit now */ | ||
2574 | if (PTR_ERR(clk) == -EPROBE_DEFER) | ||
2575 | return 0; | ||
2576 | |||
2577 | /* | ||
2578 | * Here we make assumption that the device tree is | ||
2579 | * written correctly. So an error means that there is | ||
2580 | * no more parent. As we didn't exit yet, then the | ||
2581 | * previous parent are ready. If there is no clock | ||
2582 | * parent, no need to wait for them, then we can | ||
2583 | * consider their absence as being ready | ||
2584 | */ | ||
2585 | return 1; | ||
2586 | } | ||
2587 | } | ||
2588 | |||
2530 | /** | 2589 | /** |
2531 | * of_clk_init() - Scan and init clock providers from the DT | 2590 | * of_clk_init() - Scan and init clock providers from the DT |
2532 | * @matches: array of compatible values and init functions for providers. | 2591 | * @matches: array of compatible values and init functions for providers. |
2533 | * | 2592 | * |
2534 | * This function scans the device tree for matching clock providers and | 2593 | * This function scans the device tree for matching clock providers |
2535 | * calls their initialization functions | 2594 | * and calls their initialization functions. It also does it by trying |
2595 | * to follow the dependencies. | ||
2536 | */ | 2596 | */ |
2537 | void __init of_clk_init(const struct of_device_id *matches) | 2597 | void __init of_clk_init(const struct of_device_id *matches) |
2538 | { | 2598 | { |
2539 | const struct of_device_id *match; | 2599 | const struct of_device_id *match; |
2540 | struct device_node *np; | 2600 | struct device_node *np; |
2601 | struct clock_provider *clk_provider, *next; | ||
2602 | bool is_init_done; | ||
2603 | bool force = false; | ||
2541 | 2604 | ||
2542 | if (!matches) | 2605 | if (!matches) |
2543 | matches = &__clk_of_table; | 2606 | matches = &__clk_of_table; |
2544 | 2607 | ||
2608 | /* First prepare the list of the clocks providers */ | ||
2545 | for_each_matching_node_and_match(np, matches, &match) { | 2609 | for_each_matching_node_and_match(np, matches, &match) { |
2546 | of_clk_init_cb_t clk_init_cb = match->data; | 2610 | struct clock_provider *parent = |
2547 | clk_init_cb(np); | 2611 | kzalloc(sizeof(struct clock_provider), GFP_KERNEL); |
2612 | |||
2613 | parent->clk_init_cb = match->data; | ||
2614 | parent->np = np; | ||
2615 | list_add_tail(&parent->node, &clk_provider_list); | ||
2616 | } | ||
2617 | |||
2618 | while (!list_empty(&clk_provider_list)) { | ||
2619 | is_init_done = false; | ||
2620 | list_for_each_entry_safe(clk_provider, next, | ||
2621 | &clk_provider_list, node) { | ||
2622 | if (force || parent_ready(clk_provider->np)) { | ||
2623 | clk_provider->clk_init_cb(clk_provider->np); | ||
2624 | list_del(&clk_provider->node); | ||
2625 | kfree(clk_provider); | ||
2626 | is_init_done = true; | ||
2627 | } | ||
2628 | } | ||
2629 | |||
2630 | /* | ||
2631 | * We didn't manage to initialize any of the | ||
2632 | * remaining providers during the last loop, so now we | ||
2633 | * initialize all the remaining ones unconditionally | ||
2634 | * in case the clock parent was not mandatory | ||
2635 | */ | ||
2636 | if (!is_init_done) | ||
2637 | force = true; | ||
2638 | |||
2548 | } | 2639 | } |
2549 | } | 2640 | } |
2550 | #endif | 2641 | #endif |
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index 48f67218247c..a360b2eca5cb 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c | |||
@@ -167,6 +167,8 @@ struct clk *clk_get(struct device *dev, const char *con_id) | |||
167 | clk = of_clk_get_by_name(dev->of_node, con_id); | 167 | clk = of_clk_get_by_name(dev->of_node, con_id); |
168 | if (!IS_ERR(clk)) | 168 | if (!IS_ERR(clk)) |
169 | return clk; | 169 | return clk; |
170 | if (PTR_ERR(clk) == -EPROBE_DEFER) | ||
171 | return clk; | ||
170 | } | 172 | } |
171 | 173 | ||
172 | return clk_get_sys(dev_id, con_id); | 174 | return clk_get_sys(dev_id, con_id); |
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile index a049108341fc..40b33c6a8257 100644 --- a/drivers/clk/hisilicon/Makefile +++ b/drivers/clk/hisilicon/Makefile | |||
@@ -2,4 +2,7 @@ | |||
2 | # Hisilicon Clock specific Makefile | 2 | # Hisilicon Clock specific Makefile |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += clk.o clkgate-separated.o clk-hi3620.o | 5 | obj-y += clk.o clkgate-separated.o |
6 | |||
7 | obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o | ||
8 | obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o | ||
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c index f24ad6a3a797..339945d2503b 100644 --- a/drivers/clk/hisilicon/clk-hi3620.c +++ b/drivers/clk/hisilicon/clk-hi3620.c | |||
@@ -210,33 +210,297 @@ static struct hisi_gate_clock hi3620_seperated_gate_clks[] __initdata = { | |||
210 | 210 | ||
211 | static void __init hi3620_clk_init(struct device_node *np) | 211 | static void __init hi3620_clk_init(struct device_node *np) |
212 | { | 212 | { |
213 | void __iomem *base; | 213 | struct hisi_clock_data *clk_data; |
214 | 214 | ||
215 | if (np) { | 215 | clk_data = hisi_clk_init(np, HI3620_NR_CLKS); |
216 | base = of_iomap(np, 0); | 216 | if (!clk_data) |
217 | if (!base) { | ||
218 | pr_err("failed to map Hi3620 clock registers\n"); | ||
219 | return; | ||
220 | } | ||
221 | } else { | ||
222 | pr_err("failed to find Hi3620 clock node in DTS\n"); | ||
223 | return; | 217 | return; |
224 | } | ||
225 | |||
226 | hisi_clk_init(np, HI3620_NR_CLKS); | ||
227 | 218 | ||
228 | hisi_clk_register_fixed_rate(hi3620_fixed_rate_clks, | 219 | hisi_clk_register_fixed_rate(hi3620_fixed_rate_clks, |
229 | ARRAY_SIZE(hi3620_fixed_rate_clks), | 220 | ARRAY_SIZE(hi3620_fixed_rate_clks), |
230 | base); | 221 | clk_data); |
231 | hisi_clk_register_fixed_factor(hi3620_fixed_factor_clks, | 222 | hisi_clk_register_fixed_factor(hi3620_fixed_factor_clks, |
232 | ARRAY_SIZE(hi3620_fixed_factor_clks), | 223 | ARRAY_SIZE(hi3620_fixed_factor_clks), |
233 | base); | 224 | clk_data); |
234 | hisi_clk_register_mux(hi3620_mux_clks, ARRAY_SIZE(hi3620_mux_clks), | 225 | hisi_clk_register_mux(hi3620_mux_clks, ARRAY_SIZE(hi3620_mux_clks), |
235 | base); | 226 | clk_data); |
236 | hisi_clk_register_divider(hi3620_div_clks, ARRAY_SIZE(hi3620_div_clks), | 227 | hisi_clk_register_divider(hi3620_div_clks, ARRAY_SIZE(hi3620_div_clks), |
237 | base); | 228 | clk_data); |
238 | hisi_clk_register_gate_sep(hi3620_seperated_gate_clks, | 229 | hisi_clk_register_gate_sep(hi3620_seperated_gate_clks, |
239 | ARRAY_SIZE(hi3620_seperated_gate_clks), | 230 | ARRAY_SIZE(hi3620_seperated_gate_clks), |
240 | base); | 231 | clk_data); |
241 | } | 232 | } |
242 | CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init); | 233 | CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init); |
234 | |||
235 | struct hisi_mmc_clock { | ||
236 | unsigned int id; | ||
237 | const char *name; | ||
238 | const char *parent_name; | ||
239 | unsigned long flags; | ||
240 | u32 clken_reg; | ||
241 | u32 clken_bit; | ||
242 | u32 div_reg; | ||
243 | u32 div_off; | ||
244 | u32 div_bits; | ||
245 | u32 drv_reg; | ||
246 | u32 drv_off; | ||
247 | u32 drv_bits; | ||
248 | u32 sam_reg; | ||
249 | u32 sam_off; | ||
250 | u32 sam_bits; | ||
251 | }; | ||
252 | |||
253 | struct clk_mmc { | ||
254 | struct clk_hw hw; | ||
255 | u32 id; | ||
256 | void __iomem *clken_reg; | ||
257 | u32 clken_bit; | ||
258 | void __iomem *div_reg; | ||
259 | u32 div_off; | ||
260 | u32 div_bits; | ||
261 | void __iomem *drv_reg; | ||
262 | u32 drv_off; | ||
263 | u32 drv_bits; | ||
264 | void __iomem *sam_reg; | ||
265 | u32 sam_off; | ||
266 | u32 sam_bits; | ||
267 | }; | ||
268 | |||
269 | #define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw) | ||
270 | |||
271 | static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = { | ||
272 | { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4}, | ||
273 | { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4}, | ||
274 | { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4}, | ||
275 | { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4}, | ||
276 | }; | ||
277 | |||
278 | static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw, | ||
279 | unsigned long parent_rate) | ||
280 | { | ||
281 | switch (parent_rate) { | ||
282 | case 26000000: | ||
283 | return 13000000; | ||
284 | case 180000000: | ||
285 | return 25000000; | ||
286 | case 360000000: | ||
287 | return 50000000; | ||
288 | case 720000000: | ||
289 | return 100000000; | ||
290 | case 1440000000: | ||
291 | return 180000000; | ||
292 | default: | ||
293 | return parent_rate; | ||
294 | } | ||
295 | } | ||
296 | |||
297 | static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate, | ||
298 | unsigned long *best_parent_rate, | ||
299 | struct clk **best_parent_p) | ||
300 | { | ||
301 | struct clk_mmc *mclk = to_mmc(hw); | ||
302 | unsigned long best = 0; | ||
303 | |||
304 | if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) { | ||
305 | rate = 13000000; | ||
306 | best = 26000000; | ||
307 | } else if (rate <= 26000000) { | ||
308 | rate = 25000000; | ||
309 | best = 180000000; | ||
310 | } else if (rate <= 52000000) { | ||
311 | rate = 50000000; | ||
312 | best = 360000000; | ||
313 | } else if (rate <= 100000000) { | ||
314 | rate = 100000000; | ||
315 | best = 720000000; | ||
316 | } else { | ||
317 | /* max is 180M */ | ||
318 | rate = 180000000; | ||
319 | best = 1440000000; | ||
320 | } | ||
321 | *best_parent_rate = best; | ||
322 | return rate; | ||
323 | } | ||
324 | |||
325 | static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len) | ||
326 | { | ||
327 | u32 i; | ||
328 | |||
329 | for (i = 0; i < len; i++) { | ||
330 | if (para % 2) | ||
331 | val |= 1 << (off + i); | ||
332 | else | ||
333 | val &= ~(1 << (off + i)); | ||
334 | para = para >> 1; | ||
335 | } | ||
336 | |||
337 | return val; | ||
338 | } | ||
339 | |||
340 | static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate) | ||
341 | { | ||
342 | struct clk_mmc *mclk = to_mmc(hw); | ||
343 | unsigned long flags; | ||
344 | u32 sam, drv, div, val; | ||
345 | static DEFINE_SPINLOCK(mmc_clk_lock); | ||
346 | |||
347 | switch (rate) { | ||
348 | case 13000000: | ||
349 | sam = 3; | ||
350 | drv = 1; | ||
351 | div = 1; | ||
352 | break; | ||
353 | case 25000000: | ||
354 | sam = 13; | ||
355 | drv = 6; | ||
356 | div = 6; | ||
357 | break; | ||
358 | case 50000000: | ||
359 | sam = 3; | ||
360 | drv = 6; | ||
361 | div = 6; | ||
362 | break; | ||
363 | case 100000000: | ||
364 | sam = 6; | ||
365 | drv = 4; | ||
366 | div = 6; | ||
367 | break; | ||
368 | case 180000000: | ||
369 | sam = 6; | ||
370 | drv = 4; | ||
371 | div = 7; | ||
372 | break; | ||
373 | default: | ||
374 | return -EINVAL; | ||
375 | } | ||
376 | |||
377 | spin_lock_irqsave(&mmc_clk_lock, flags); | ||
378 | |||
379 | val = readl_relaxed(mclk->clken_reg); | ||
380 | val &= ~(1 << mclk->clken_bit); | ||
381 | writel_relaxed(val, mclk->clken_reg); | ||
382 | |||
383 | val = readl_relaxed(mclk->sam_reg); | ||
384 | val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits); | ||
385 | writel_relaxed(val, mclk->sam_reg); | ||
386 | |||
387 | val = readl_relaxed(mclk->drv_reg); | ||
388 | val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits); | ||
389 | writel_relaxed(val, mclk->drv_reg); | ||
390 | |||
391 | val = readl_relaxed(mclk->div_reg); | ||
392 | val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits); | ||
393 | writel_relaxed(val, mclk->div_reg); | ||
394 | |||
395 | val = readl_relaxed(mclk->clken_reg); | ||
396 | val |= 1 << mclk->clken_bit; | ||
397 | writel_relaxed(val, mclk->clken_reg); | ||
398 | |||
399 | spin_unlock_irqrestore(&mmc_clk_lock, flags); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static int mmc_clk_prepare(struct clk_hw *hw) | ||
405 | { | ||
406 | struct clk_mmc *mclk = to_mmc(hw); | ||
407 | unsigned long rate; | ||
408 | |||
409 | if (mclk->id == HI3620_MMC_CIUCLK1) | ||
410 | rate = 13000000; | ||
411 | else | ||
412 | rate = 25000000; | ||
413 | |||
414 | return mmc_clk_set_timing(hw, rate); | ||
415 | } | ||
416 | |||
417 | static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate, | ||
418 | unsigned long parent_rate) | ||
419 | { | ||
420 | return mmc_clk_set_timing(hw, rate); | ||
421 | } | ||
422 | |||
423 | static struct clk_ops clk_mmc_ops = { | ||
424 | .prepare = mmc_clk_prepare, | ||
425 | .determine_rate = mmc_clk_determine_rate, | ||
426 | .set_rate = mmc_clk_set_rate, | ||
427 | .recalc_rate = mmc_clk_recalc_rate, | ||
428 | }; | ||
429 | |||
430 | static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk, | ||
431 | void __iomem *base, struct device_node *np) | ||
432 | { | ||
433 | struct clk_mmc *mclk; | ||
434 | struct clk *clk; | ||
435 | struct clk_init_data init; | ||
436 | |||
437 | mclk = kzalloc(sizeof(*mclk), GFP_KERNEL); | ||
438 | if (!mclk) { | ||
439 | pr_err("%s: fail to allocate mmc clk\n", __func__); | ||
440 | return ERR_PTR(-ENOMEM); | ||
441 | } | ||
442 | |||
443 | init.name = mmc_clk->name; | ||
444 | init.ops = &clk_mmc_ops; | ||
445 | init.flags = mmc_clk->flags | CLK_IS_BASIC; | ||
446 | init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL); | ||
447 | init.num_parents = (mmc_clk->parent_name ? 1 : 0); | ||
448 | mclk->hw.init = &init; | ||
449 | |||
450 | mclk->id = mmc_clk->id; | ||
451 | mclk->clken_reg = base + mmc_clk->clken_reg; | ||
452 | mclk->clken_bit = mmc_clk->clken_bit; | ||
453 | mclk->div_reg = base + mmc_clk->div_reg; | ||
454 | mclk->div_off = mmc_clk->div_off; | ||
455 | mclk->div_bits = mmc_clk->div_bits; | ||
456 | mclk->drv_reg = base + mmc_clk->drv_reg; | ||
457 | mclk->drv_off = mmc_clk->drv_off; | ||
458 | mclk->drv_bits = mmc_clk->drv_bits; | ||
459 | mclk->sam_reg = base + mmc_clk->sam_reg; | ||
460 | mclk->sam_off = mmc_clk->sam_off; | ||
461 | mclk->sam_bits = mmc_clk->sam_bits; | ||
462 | |||
463 | clk = clk_register(NULL, &mclk->hw); | ||
464 | if (WARN_ON(IS_ERR(clk))) | ||
465 | kfree(mclk); | ||
466 | return clk; | ||
467 | } | ||
468 | |||
469 | static void __init hi3620_mmc_clk_init(struct device_node *node) | ||
470 | { | ||
471 | void __iomem *base; | ||
472 | int i, num = ARRAY_SIZE(hi3620_mmc_clks); | ||
473 | struct clk_onecell_data *clk_data; | ||
474 | |||
475 | if (!node) { | ||
476 | pr_err("failed to find pctrl node in DTS\n"); | ||
477 | return; | ||
478 | } | ||
479 | |||
480 | base = of_iomap(node, 0); | ||
481 | if (!base) { | ||
482 | pr_err("failed to map pctrl\n"); | ||
483 | return; | ||
484 | } | ||
485 | |||
486 | clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); | ||
487 | if (WARN_ON(!clk_data)) | ||
488 | return; | ||
489 | |||
490 | clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL); | ||
491 | if (!clk_data->clks) { | ||
492 | pr_err("%s: fail to allocate mmc clk\n", __func__); | ||
493 | return; | ||
494 | } | ||
495 | |||
496 | for (i = 0; i < num; i++) { | ||
497 | struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i]; | ||
498 | clk_data->clks[mmc_clk->id] = | ||
499 | hisi_register_clk_mmc(mmc_clk, base, node); | ||
500 | } | ||
501 | |||
502 | clk_data->clk_num = num; | ||
503 | of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); | ||
504 | } | ||
505 | |||
506 | CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init); | ||
diff --git a/drivers/clk/hisilicon/clk-hip04.c b/drivers/clk/hisilicon/clk-hip04.c new file mode 100644 index 000000000000..132b57a0ce09 --- /dev/null +++ b/drivers/clk/hisilicon/clk-hip04.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Hisilicon HiP04 clock driver | ||
3 | * | ||
4 | * Copyright (c) 2013-2014 Hisilicon Limited. | ||
5 | * Copyright (c) 2013-2014 Linaro Limited. | ||
6 | * | ||
7 | * Author: Haojian Zhuang <haojian.zhuang@linaro.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/clk-provider.h> | ||
27 | #include <linux/clkdev.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/of.h> | ||
30 | #include <linux/of_address.h> | ||
31 | #include <linux/of_device.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/clk.h> | ||
34 | |||
35 | #include <dt-bindings/clock/hip04-clock.h> | ||
36 | |||
37 | #include "clk.h" | ||
38 | |||
39 | /* fixed rate clocks */ | ||
40 | static struct hisi_fixed_rate_clock hip04_fixed_rate_clks[] __initdata = { | ||
41 | { HIP04_OSC50M, "osc50m", NULL, CLK_IS_ROOT, 50000000, }, | ||
42 | { HIP04_CLK_50M, "clk50m", NULL, CLK_IS_ROOT, 50000000, }, | ||
43 | { HIP04_CLK_168M, "clk168m", NULL, CLK_IS_ROOT, 168750000, }, | ||
44 | }; | ||
45 | |||
46 | static void __init hip04_clk_init(struct device_node *np) | ||
47 | { | ||
48 | struct hisi_clock_data *clk_data; | ||
49 | |||
50 | clk_data = hisi_clk_init(np, HIP04_NR_CLKS); | ||
51 | if (!clk_data) | ||
52 | return; | ||
53 | |||
54 | hisi_clk_register_fixed_rate(hip04_fixed_rate_clks, | ||
55 | ARRAY_SIZE(hip04_fixed_rate_clks), | ||
56 | clk_data); | ||
57 | } | ||
58 | CLK_OF_DECLARE(hip04_clk, "hisilicon,hip04-clock", hip04_clk_init); | ||
diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c index a3a7152c92d9..276f672e7b1a 100644 --- a/drivers/clk/hisilicon/clk.c +++ b/drivers/clk/hisilicon/clk.c | |||
@@ -37,23 +37,49 @@ | |||
37 | #include "clk.h" | 37 | #include "clk.h" |
38 | 38 | ||
39 | static DEFINE_SPINLOCK(hisi_clk_lock); | 39 | static DEFINE_SPINLOCK(hisi_clk_lock); |
40 | static struct clk **clk_table; | ||
41 | static struct clk_onecell_data clk_data; | ||
42 | 40 | ||
43 | void __init hisi_clk_init(struct device_node *np, int nr_clks) | 41 | struct hisi_clock_data __init *hisi_clk_init(struct device_node *np, |
42 | int nr_clks) | ||
44 | { | 43 | { |
44 | struct hisi_clock_data *clk_data; | ||
45 | struct clk **clk_table; | ||
46 | void __iomem *base; | ||
47 | |||
48 | if (np) { | ||
49 | base = of_iomap(np, 0); | ||
50 | if (!base) { | ||
51 | pr_err("failed to map Hisilicon clock registers\n"); | ||
52 | goto err; | ||
53 | } | ||
54 | } else { | ||
55 | pr_err("failed to find Hisilicon clock node in DTS\n"); | ||
56 | goto err; | ||
57 | } | ||
58 | |||
59 | clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); | ||
60 | if (!clk_data) { | ||
61 | pr_err("%s: could not allocate clock data\n", __func__); | ||
62 | goto err; | ||
63 | } | ||
64 | clk_data->base = base; | ||
65 | |||
45 | clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL); | 66 | clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL); |
46 | if (!clk_table) { | 67 | if (!clk_table) { |
47 | pr_err("%s: could not allocate clock lookup table\n", __func__); | 68 | pr_err("%s: could not allocate clock lookup table\n", __func__); |
48 | return; | 69 | goto err_data; |
49 | } | 70 | } |
50 | clk_data.clks = clk_table; | 71 | clk_data->clk_data.clks = clk_table; |
51 | clk_data.clk_num = nr_clks; | 72 | clk_data->clk_data.clk_num = nr_clks; |
52 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | 73 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data); |
74 | return clk_data; | ||
75 | err_data: | ||
76 | kfree(clk_data); | ||
77 | err: | ||
78 | return NULL; | ||
53 | } | 79 | } |
54 | 80 | ||
55 | void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *clks, | 81 | void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *clks, |
56 | int nums, void __iomem *base) | 82 | int nums, struct hisi_clock_data *data) |
57 | { | 83 | { |
58 | struct clk *clk; | 84 | struct clk *clk; |
59 | int i; | 85 | int i; |
@@ -68,11 +94,13 @@ void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *clks, | |||
68 | __func__, clks[i].name); | 94 | __func__, clks[i].name); |
69 | continue; | 95 | continue; |
70 | } | 96 | } |
97 | data->clk_data.clks[clks[i].id] = clk; | ||
71 | } | 98 | } |
72 | } | 99 | } |
73 | 100 | ||
74 | void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *clks, | 101 | void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *clks, |
75 | int nums, void __iomem *base) | 102 | int nums, |
103 | struct hisi_clock_data *data) | ||
76 | { | 104 | { |
77 | struct clk *clk; | 105 | struct clk *clk; |
78 | int i; | 106 | int i; |
@@ -87,13 +115,15 @@ void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *clks, | |||
87 | __func__, clks[i].name); | 115 | __func__, clks[i].name); |
88 | continue; | 116 | continue; |
89 | } | 117 | } |
118 | data->clk_data.clks[clks[i].id] = clk; | ||
90 | } | 119 | } |
91 | } | 120 | } |
92 | 121 | ||
93 | void __init hisi_clk_register_mux(struct hisi_mux_clock *clks, | 122 | void __init hisi_clk_register_mux(struct hisi_mux_clock *clks, |
94 | int nums, void __iomem *base) | 123 | int nums, struct hisi_clock_data *data) |
95 | { | 124 | { |
96 | struct clk *clk; | 125 | struct clk *clk; |
126 | void __iomem *base = data->base; | ||
97 | int i; | 127 | int i; |
98 | 128 | ||
99 | for (i = 0; i < nums; i++) { | 129 | for (i = 0; i < nums; i++) { |
@@ -111,14 +141,15 @@ void __init hisi_clk_register_mux(struct hisi_mux_clock *clks, | |||
111 | if (clks[i].alias) | 141 | if (clks[i].alias) |
112 | clk_register_clkdev(clk, clks[i].alias, NULL); | 142 | clk_register_clkdev(clk, clks[i].alias, NULL); |
113 | 143 | ||
114 | clk_table[clks[i].id] = clk; | 144 | data->clk_data.clks[clks[i].id] = clk; |
115 | } | 145 | } |
116 | } | 146 | } |
117 | 147 | ||
118 | void __init hisi_clk_register_divider(struct hisi_divider_clock *clks, | 148 | void __init hisi_clk_register_divider(struct hisi_divider_clock *clks, |
119 | int nums, void __iomem *base) | 149 | int nums, struct hisi_clock_data *data) |
120 | { | 150 | { |
121 | struct clk *clk; | 151 | struct clk *clk; |
152 | void __iomem *base = data->base; | ||
122 | int i; | 153 | int i; |
123 | 154 | ||
124 | for (i = 0; i < nums; i++) { | 155 | for (i = 0; i < nums; i++) { |
@@ -139,14 +170,15 @@ void __init hisi_clk_register_divider(struct hisi_divider_clock *clks, | |||
139 | if (clks[i].alias) | 170 | if (clks[i].alias) |
140 | clk_register_clkdev(clk, clks[i].alias, NULL); | 171 | clk_register_clkdev(clk, clks[i].alias, NULL); |
141 | 172 | ||
142 | clk_table[clks[i].id] = clk; | 173 | data->clk_data.clks[clks[i].id] = clk; |
143 | } | 174 | } |
144 | } | 175 | } |
145 | 176 | ||
146 | void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks, | 177 | void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks, |
147 | int nums, void __iomem *base) | 178 | int nums, struct hisi_clock_data *data) |
148 | { | 179 | { |
149 | struct clk *clk; | 180 | struct clk *clk; |
181 | void __iomem *base = data->base; | ||
150 | int i; | 182 | int i; |
151 | 183 | ||
152 | for (i = 0; i < nums; i++) { | 184 | for (i = 0; i < nums; i++) { |
@@ -166,6 +198,6 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks, | |||
166 | if (clks[i].alias) | 198 | if (clks[i].alias) |
167 | clk_register_clkdev(clk, clks[i].alias, NULL); | 199 | clk_register_clkdev(clk, clks[i].alias, NULL); |
168 | 200 | ||
169 | clk_table[clks[i].id] = clk; | 201 | data->clk_data.clks[clks[i].id] = clk; |
170 | } | 202 | } |
171 | } | 203 | } |
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h index 4a6beebefb7a..43fa5da88f02 100644 --- a/drivers/clk/hisilicon/clk.h +++ b/drivers/clk/hisilicon/clk.h | |||
@@ -30,6 +30,11 @@ | |||
30 | #include <linux/io.h> | 30 | #include <linux/io.h> |
31 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
32 | 32 | ||
33 | struct hisi_clock_data { | ||
34 | struct clk_onecell_data clk_data; | ||
35 | void __iomem *base; | ||
36 | }; | ||
37 | |||
33 | struct hisi_fixed_rate_clock { | 38 | struct hisi_fixed_rate_clock { |
34 | unsigned int id; | 39 | unsigned int id; |
35 | char *name; | 40 | char *name; |
@@ -89,15 +94,15 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *, | |||
89 | void __iomem *, u8, | 94 | void __iomem *, u8, |
90 | u8, spinlock_t *); | 95 | u8, spinlock_t *); |
91 | 96 | ||
92 | void __init hisi_clk_init(struct device_node *, int); | 97 | struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int); |
93 | void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *, | 98 | void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *, |
94 | int, void __iomem *); | 99 | int, struct hisi_clock_data *); |
95 | void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *, | 100 | void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *, |
96 | int, void __iomem *); | 101 | int, struct hisi_clock_data *); |
97 | void __init hisi_clk_register_mux(struct hisi_mux_clock *, int, | 102 | void __init hisi_clk_register_mux(struct hisi_mux_clock *, int, |
98 | void __iomem *); | 103 | struct hisi_clock_data *); |
99 | void __init hisi_clk_register_divider(struct hisi_divider_clock *, | 104 | void __init hisi_clk_register_divider(struct hisi_divider_clock *, |
100 | int, void __iomem *); | 105 | int, struct hisi_clock_data *); |
101 | void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *, | 106 | void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *, |
102 | int, void __iomem *); | 107 | int, struct hisi_clock_data *); |
103 | #endif /* __HISI_CLK_H */ | 108 | #endif /* __HISI_CLK_H */ |
diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c index 80c1dd15d15c..23a56f561812 100644 --- a/drivers/clk/mmp/clk-frac.c +++ b/drivers/clk/mmp/clk-frac.c | |||
@@ -40,15 +40,19 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate, | |||
40 | 40 | ||
41 | for (i = 0; i < factor->ftbl_cnt; i++) { | 41 | for (i = 0; i < factor->ftbl_cnt; i++) { |
42 | prev_rate = rate; | 42 | prev_rate = rate; |
43 | rate = (((*prate / 10000) * factor->ftbl[i].num) / | 43 | rate = (((*prate / 10000) * factor->ftbl[i].den) / |
44 | (factor->ftbl[i].den * factor->masks->factor)) * 10000; | 44 | (factor->ftbl[i].num * factor->masks->factor)) * 10000; |
45 | if (rate > drate) | 45 | if (rate > drate) |
46 | break; | 46 | break; |
47 | } | 47 | } |
48 | if (i == 0) | 48 | if ((i == 0) || (i == factor->ftbl_cnt)) { |
49 | return rate; | 49 | return rate; |
50 | else | 50 | } else { |
51 | return prev_rate; | 51 | if ((drate - prev_rate) > (rate - drate)) |
52 | return rate; | ||
53 | else | ||
54 | return prev_rate; | ||
55 | } | ||
52 | } | 56 | } |
53 | 57 | ||
54 | static unsigned long clk_factor_recalc_rate(struct clk_hw *hw, | 58 | static unsigned long clk_factor_recalc_rate(struct clk_hw *hw, |
@@ -64,7 +68,7 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw, | |||
64 | num = (val >> masks->num_shift) & masks->num_mask; | 68 | num = (val >> masks->num_shift) & masks->num_mask; |
65 | 69 | ||
66 | /* calculate denominator */ | 70 | /* calculate denominator */ |
67 | den = (val >> masks->den_shift) & masks->num_mask; | 71 | den = (val >> masks->den_shift) & masks->den_mask; |
68 | 72 | ||
69 | if (!den) | 73 | if (!den) |
70 | return 0; | 74 | return 0; |
@@ -85,8 +89,8 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate, | |||
85 | 89 | ||
86 | for (i = 0; i < factor->ftbl_cnt; i++) { | 90 | for (i = 0; i < factor->ftbl_cnt; i++) { |
87 | prev_rate = rate; | 91 | prev_rate = rate; |
88 | rate = (((prate / 10000) * factor->ftbl[i].num) / | 92 | rate = (((prate / 10000) * factor->ftbl[i].den) / |
89 | (factor->ftbl[i].den * factor->masks->factor)) * 10000; | 93 | (factor->ftbl[i].num * factor->masks->factor)) * 10000; |
90 | if (rate > drate) | 94 | if (rate > drate) |
91 | break; | 95 | break; |
92 | } | 96 | } |
diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig index c339b829d3e3..693f7be129f1 100644 --- a/drivers/clk/mvebu/Kconfig +++ b/drivers/clk/mvebu/Kconfig | |||
@@ -13,6 +13,14 @@ config ARMADA_370_CLK | |||
13 | select MVEBU_CLK_CPU | 13 | select MVEBU_CLK_CPU |
14 | select MVEBU_CLK_COREDIV | 14 | select MVEBU_CLK_COREDIV |
15 | 15 | ||
16 | config ARMADA_375_CLK | ||
17 | bool | ||
18 | select MVEBU_CLK_COMMON | ||
19 | |||
20 | config ARMADA_38X_CLK | ||
21 | bool | ||
22 | select MVEBU_CLK_COMMON | ||
23 | |||
16 | config ARMADA_XP_CLK | 24 | config ARMADA_XP_CLK |
17 | bool | 25 | bool |
18 | select MVEBU_CLK_COMMON | 26 | select MVEBU_CLK_COMMON |
diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile index 21bbfb4a9f42..4c66162fb0b4 100644 --- a/drivers/clk/mvebu/Makefile +++ b/drivers/clk/mvebu/Makefile | |||
@@ -3,6 +3,8 @@ obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o | |||
3 | obj-$(CONFIG_MVEBU_CLK_COREDIV) += clk-corediv.o | 3 | obj-$(CONFIG_MVEBU_CLK_COREDIV) += clk-corediv.o |
4 | 4 | ||
5 | obj-$(CONFIG_ARMADA_370_CLK) += armada-370.o | 5 | obj-$(CONFIG_ARMADA_370_CLK) += armada-370.o |
6 | obj-$(CONFIG_ARMADA_375_CLK) += armada-375.o | ||
7 | obj-$(CONFIG_ARMADA_38X_CLK) += armada-38x.o | ||
6 | obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o | 8 | obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o |
7 | obj-$(CONFIG_DOVE_CLK) += dove.o | 9 | obj-$(CONFIG_DOVE_CLK) += dove.o |
8 | obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o | 10 | obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o |
diff --git a/drivers/clk/mvebu/armada-375.c b/drivers/clk/mvebu/armada-375.c new file mode 100644 index 000000000000..c991a4d95e10 --- /dev/null +++ b/drivers/clk/mvebu/armada-375.c | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | * Marvell Armada 375 SoC clocks | ||
3 | * | ||
4 | * Copyright (C) 2014 Marvell | ||
5 | * | ||
6 | * Gregory CLEMENT <gregory.clement@free-electrons.com> | ||
7 | * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
8 | * Andrew Lunn <andrew@lunn.ch> | ||
9 | * | ||
10 | * This file is licensed under the terms of the GNU General Public | ||
11 | * License version 2. This program is licensed "as is" without any | ||
12 | * warranty of any kind, whether express or implied. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/clk-provider.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/of.h> | ||
19 | #include "common.h" | ||
20 | |||
21 | /* | ||
22 | * Core Clocks | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | * For the Armada 375 SoCs, the CPU, DDR and L2 clocks frequencies are | ||
27 | * all modified at the same time, and not separately as for the Armada | ||
28 | * 370 or the Armada XP SoCs. | ||
29 | * | ||
30 | * SAR0[21:17] : CPU frequency DDR frequency L2 frequency | ||
31 | * 6 = 400 MHz 400 MHz 200 MHz | ||
32 | * 15 = 600 MHz 600 MHz 300 MHz | ||
33 | * 21 = 800 MHz 534 MHz 400 MHz | ||
34 | * 25 = 1000 MHz 500 MHz 500 MHz | ||
35 | * others reserved. | ||
36 | * | ||
37 | * SAR0[22] : TCLK frequency | ||
38 | * 0 = 166 MHz | ||
39 | * 1 = 200 MHz | ||
40 | */ | ||
41 | |||
42 | #define SAR1_A375_TCLK_FREQ_OPT 22 | ||
43 | #define SAR1_A375_TCLK_FREQ_OPT_MASK 0x1 | ||
44 | #define SAR1_A375_CPU_DDR_L2_FREQ_OPT 17 | ||
45 | #define SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK 0x1F | ||
46 | |||
47 | static const u32 armada_375_tclk_frequencies[] __initconst = { | ||
48 | 166000000, | ||
49 | 200000000, | ||
50 | }; | ||
51 | |||
52 | static u32 __init armada_375_get_tclk_freq(void __iomem *sar) | ||
53 | { | ||
54 | u8 tclk_freq_select; | ||
55 | |||
56 | tclk_freq_select = ((readl(sar) >> SAR1_A375_TCLK_FREQ_OPT) & | ||
57 | SAR1_A375_TCLK_FREQ_OPT_MASK); | ||
58 | return armada_375_tclk_frequencies[tclk_freq_select]; | ||
59 | } | ||
60 | |||
61 | |||
62 | static const u32 armada_375_cpu_frequencies[] __initconst = { | ||
63 | 0, 0, 0, 0, 0, 0, | ||
64 | 400000000, | ||
65 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
66 | 600000000, | ||
67 | 0, 0, 0, 0, 0, | ||
68 | 800000000, | ||
69 | 0, 0, 0, | ||
70 | 1000000000, | ||
71 | }; | ||
72 | |||
73 | static u32 __init armada_375_get_cpu_freq(void __iomem *sar) | ||
74 | { | ||
75 | u8 cpu_freq_select; | ||
76 | |||
77 | cpu_freq_select = ((readl(sar) >> SAR1_A375_CPU_DDR_L2_FREQ_OPT) & | ||
78 | SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK); | ||
79 | if (cpu_freq_select >= ARRAY_SIZE(armada_375_cpu_frequencies)) { | ||
80 | pr_err("Selected CPU frequency (%d) unsupported\n", | ||
81 | cpu_freq_select); | ||
82 | return 0; | ||
83 | } else | ||
84 | return armada_375_cpu_frequencies[cpu_freq_select]; | ||
85 | } | ||
86 | |||
87 | enum { A375_CPU_TO_DDR, A375_CPU_TO_L2 }; | ||
88 | |||
89 | static const struct coreclk_ratio armada_375_coreclk_ratios[] __initconst = { | ||
90 | { .id = A375_CPU_TO_L2, .name = "l2clk" }, | ||
91 | { .id = A375_CPU_TO_DDR, .name = "ddrclk" }, | ||
92 | }; | ||
93 | |||
94 | static const int armada_375_cpu_l2_ratios[32][2] __initconst = { | ||
95 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
96 | {0, 1}, {0, 1}, {1, 2}, {0, 1}, | ||
97 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
98 | {0, 1}, {0, 1}, {0, 1}, {1, 2}, | ||
99 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
100 | {0, 1}, {1, 2}, {0, 1}, {0, 1}, | ||
101 | {0, 1}, {1, 2}, {0, 1}, {0, 1}, | ||
102 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
103 | }; | ||
104 | |||
105 | static const int armada_375_cpu_ddr_ratios[32][2] __initconst = { | ||
106 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
107 | {0, 1}, {0, 1}, {1, 1}, {0, 1}, | ||
108 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
109 | {0, 1}, {0, 1}, {0, 1}, {2, 3}, | ||
110 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
111 | {0, 1}, {2, 3}, {0, 1}, {0, 1}, | ||
112 | {0, 1}, {1, 2}, {0, 1}, {0, 1}, | ||
113 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
114 | }; | ||
115 | |||
116 | static void __init armada_375_get_clk_ratio( | ||
117 | void __iomem *sar, int id, int *mult, int *div) | ||
118 | { | ||
119 | u32 opt = ((readl(sar) >> SAR1_A375_CPU_DDR_L2_FREQ_OPT) & | ||
120 | SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK); | ||
121 | |||
122 | switch (id) { | ||
123 | case A375_CPU_TO_L2: | ||
124 | *mult = armada_375_cpu_l2_ratios[opt][0]; | ||
125 | *div = armada_375_cpu_l2_ratios[opt][1]; | ||
126 | break; | ||
127 | case A375_CPU_TO_DDR: | ||
128 | *mult = armada_375_cpu_ddr_ratios[opt][0]; | ||
129 | *div = armada_375_cpu_ddr_ratios[opt][1]; | ||
130 | break; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static const struct coreclk_soc_desc armada_375_coreclks = { | ||
135 | .get_tclk_freq = armada_375_get_tclk_freq, | ||
136 | .get_cpu_freq = armada_375_get_cpu_freq, | ||
137 | .get_clk_ratio = armada_375_get_clk_ratio, | ||
138 | .ratios = armada_375_coreclk_ratios, | ||
139 | .num_ratios = ARRAY_SIZE(armada_375_coreclk_ratios), | ||
140 | }; | ||
141 | |||
142 | static void __init armada_375_coreclk_init(struct device_node *np) | ||
143 | { | ||
144 | mvebu_coreclk_setup(np, &armada_375_coreclks); | ||
145 | } | ||
146 | CLK_OF_DECLARE(armada_375_core_clk, "marvell,armada-375-core-clock", | ||
147 | armada_375_coreclk_init); | ||
148 | |||
149 | /* | ||
150 | * Clock Gating Control | ||
151 | */ | ||
152 | static const struct clk_gating_soc_desc armada_375_gating_desc[] __initconst = { | ||
153 | { "mu", NULL, 2 }, | ||
154 | { "pp", NULL, 3 }, | ||
155 | { "ptp", NULL, 4 }, | ||
156 | { "pex0", NULL, 5 }, | ||
157 | { "pex1", NULL, 6 }, | ||
158 | { "audio", NULL, 8 }, | ||
159 | { "nd_clk", "nand", 11 }, | ||
160 | { "sata0_link", "sata0_core", 14 }, | ||
161 | { "sata0_core", NULL, 15 }, | ||
162 | { "usb3", NULL, 16 }, | ||
163 | { "sdio", NULL, 17 }, | ||
164 | { "usb", NULL, 18 }, | ||
165 | { "gop", NULL, 19 }, | ||
166 | { "sata1_link", "sata1_core", 20 }, | ||
167 | { "sata1_core", NULL, 21 }, | ||
168 | { "xor0", NULL, 22 }, | ||
169 | { "xor1", NULL, 23 }, | ||
170 | { "copro", NULL, 24 }, | ||
171 | { "tdm", NULL, 25 }, | ||
172 | { "crypto0_enc", NULL, 28 }, | ||
173 | { "crypto0_core", NULL, 29 }, | ||
174 | { "crypto1_enc", NULL, 30 }, | ||
175 | { "crypto1_core", NULL, 31 }, | ||
176 | { } | ||
177 | }; | ||
178 | |||
179 | static void __init armada_375_clk_gating_init(struct device_node *np) | ||
180 | { | ||
181 | mvebu_clk_gating_setup(np, armada_375_gating_desc); | ||
182 | } | ||
183 | CLK_OF_DECLARE(armada_375_clk_gating, "marvell,armada-375-gating-clock", | ||
184 | armada_375_clk_gating_init); | ||
diff --git a/drivers/clk/mvebu/armada-38x.c b/drivers/clk/mvebu/armada-38x.c new file mode 100644 index 000000000000..8bccf4ecdab6 --- /dev/null +++ b/drivers/clk/mvebu/armada-38x.c | |||
@@ -0,0 +1,167 @@ | |||
1 | /* | ||
2 | * Marvell Armada 380/385 SoC clocks | ||
3 | * | ||
4 | * Copyright (C) 2014 Marvell | ||
5 | * | ||
6 | * Gregory CLEMENT <gregory.clement@free-electrons.com> | ||
7 | * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
8 | * Andrew Lunn <andrew@lunn.ch> | ||
9 | * | ||
10 | * This file is licensed under the terms of the GNU General Public | ||
11 | * License version 2. This program is licensed "as is" without any | ||
12 | * warranty of any kind, whether express or implied. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/clk-provider.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/of.h> | ||
19 | #include "common.h" | ||
20 | |||
21 | /* | ||
22 | * SAR[14:10] : Ratios between PCLK0, NBCLK, HCLK and DRAM clocks | ||
23 | * | ||
24 | * SAR[15] : TCLK frequency | ||
25 | * 0 = 250 MHz | ||
26 | * 1 = 200 MHz | ||
27 | */ | ||
28 | |||
29 | #define SAR_A380_TCLK_FREQ_OPT 15 | ||
30 | #define SAR_A380_TCLK_FREQ_OPT_MASK 0x1 | ||
31 | #define SAR_A380_CPU_DDR_L2_FREQ_OPT 10 | ||
32 | #define SAR_A380_CPU_DDR_L2_FREQ_OPT_MASK 0x1F | ||
33 | |||
34 | static const u32 armada_38x_tclk_frequencies[] __initconst = { | ||
35 | 250000000, | ||
36 | 200000000, | ||
37 | }; | ||
38 | |||
39 | static u32 __init armada_38x_get_tclk_freq(void __iomem *sar) | ||
40 | { | ||
41 | u8 tclk_freq_select; | ||
42 | |||
43 | tclk_freq_select = ((readl(sar) >> SAR_A380_TCLK_FREQ_OPT) & | ||
44 | SAR_A380_TCLK_FREQ_OPT_MASK); | ||
45 | return armada_38x_tclk_frequencies[tclk_freq_select]; | ||
46 | } | ||
47 | |||
48 | static const u32 armada_38x_cpu_frequencies[] __initconst = { | ||
49 | 0, 0, 0, 0, | ||
50 | 1066 * 1000 * 1000, 0, 0, 0, | ||
51 | 1332 * 1000 * 1000, 0, 0, 0, | ||
52 | 1600 * 1000 * 1000, | ||
53 | }; | ||
54 | |||
55 | static u32 __init armada_38x_get_cpu_freq(void __iomem *sar) | ||
56 | { | ||
57 | u8 cpu_freq_select; | ||
58 | |||
59 | cpu_freq_select = ((readl(sar) >> SAR_A380_CPU_DDR_L2_FREQ_OPT) & | ||
60 | SAR_A380_CPU_DDR_L2_FREQ_OPT_MASK); | ||
61 | if (cpu_freq_select >= ARRAY_SIZE(armada_38x_cpu_frequencies)) { | ||
62 | pr_err("Selected CPU frequency (%d) unsupported\n", | ||
63 | cpu_freq_select); | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | return armada_38x_cpu_frequencies[cpu_freq_select]; | ||
68 | } | ||
69 | |||
70 | enum { A380_CPU_TO_DDR, A380_CPU_TO_L2 }; | ||
71 | |||
72 | static const struct coreclk_ratio armada_38x_coreclk_ratios[] __initconst = { | ||
73 | { .id = A380_CPU_TO_L2, .name = "l2clk" }, | ||
74 | { .id = A380_CPU_TO_DDR, .name = "ddrclk" }, | ||
75 | }; | ||
76 | |||
77 | static const int armada_38x_cpu_l2_ratios[32][2] __initconst = { | ||
78 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
79 | {1, 2}, {0, 1}, {0, 1}, {0, 1}, | ||
80 | {1, 2}, {0, 1}, {0, 1}, {0, 1}, | ||
81 | {1, 2}, {0, 1}, {0, 1}, {0, 1}, | ||
82 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
83 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
84 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
85 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
86 | }; | ||
87 | |||
88 | static const int armada_38x_cpu_ddr_ratios[32][2] __initconst = { | ||
89 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
90 | {1, 2}, {0, 1}, {0, 1}, {0, 1}, | ||
91 | {1, 2}, {0, 1}, {0, 1}, {0, 1}, | ||
92 | {1, 2}, {0, 1}, {0, 1}, {0, 1}, | ||
93 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
94 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
95 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
96 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
97 | }; | ||
98 | |||
99 | static void __init armada_38x_get_clk_ratio( | ||
100 | void __iomem *sar, int id, int *mult, int *div) | ||
101 | { | ||
102 | u32 opt = ((readl(sar) >> SAR_A380_CPU_DDR_L2_FREQ_OPT) & | ||
103 | SAR_A380_CPU_DDR_L2_FREQ_OPT_MASK); | ||
104 | |||
105 | switch (id) { | ||
106 | case A380_CPU_TO_L2: | ||
107 | *mult = armada_38x_cpu_l2_ratios[opt][0]; | ||
108 | *div = armada_38x_cpu_l2_ratios[opt][1]; | ||
109 | break; | ||
110 | case A380_CPU_TO_DDR: | ||
111 | *mult = armada_38x_cpu_ddr_ratios[opt][0]; | ||
112 | *div = armada_38x_cpu_ddr_ratios[opt][1]; | ||
113 | break; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | static const struct coreclk_soc_desc armada_38x_coreclks = { | ||
118 | .get_tclk_freq = armada_38x_get_tclk_freq, | ||
119 | .get_cpu_freq = armada_38x_get_cpu_freq, | ||
120 | .get_clk_ratio = armada_38x_get_clk_ratio, | ||
121 | .ratios = armada_38x_coreclk_ratios, | ||
122 | .num_ratios = ARRAY_SIZE(armada_38x_coreclk_ratios), | ||
123 | }; | ||
124 | |||
125 | static void __init armada_38x_coreclk_init(struct device_node *np) | ||
126 | { | ||
127 | mvebu_coreclk_setup(np, &armada_38x_coreclks); | ||
128 | } | ||
129 | CLK_OF_DECLARE(armada_38x_core_clk, "marvell,armada-380-core-clock", | ||
130 | armada_38x_coreclk_init); | ||
131 | |||
132 | /* | ||
133 | * Clock Gating Control | ||
134 | */ | ||
135 | static const struct clk_gating_soc_desc armada_38x_gating_desc[] __initconst = { | ||
136 | { "audio", NULL, 0 }, | ||
137 | { "ge2", NULL, 2 }, | ||
138 | { "ge1", NULL, 3 }, | ||
139 | { "ge0", NULL, 4 }, | ||
140 | { "pex1", NULL, 5 }, | ||
141 | { "pex2", NULL, 6 }, | ||
142 | { "pex3", NULL, 7 }, | ||
143 | { "pex0", NULL, 8 }, | ||
144 | { "usb3h0", NULL, 9 }, | ||
145 | { "usb3h1", NULL, 10 }, | ||
146 | { "usb3d", NULL, 11 }, | ||
147 | { "bm", NULL, 13 }, | ||
148 | { "crypto0z", NULL, 14 }, | ||
149 | { "sata0", NULL, 15 }, | ||
150 | { "crypto1z", NULL, 16 }, | ||
151 | { "sdio", NULL, 17 }, | ||
152 | { "usb2", NULL, 18 }, | ||
153 | { "crypto1", NULL, 21 }, | ||
154 | { "xor0", NULL, 22 }, | ||
155 | { "crypto0", NULL, 23 }, | ||
156 | { "tdm", NULL, 25 }, | ||
157 | { "xor1", NULL, 28 }, | ||
158 | { "sata1", NULL, 30 }, | ||
159 | { } | ||
160 | }; | ||
161 | |||
162 | static void __init armada_38x_clk_gating_init(struct device_node *np) | ||
163 | { | ||
164 | mvebu_clk_gating_setup(np, armada_38x_gating_desc); | ||
165 | } | ||
166 | CLK_OF_DECLARE(armada_38x_clk_gating, "marvell,armada-380-gating-clock", | ||
167 | armada_38x_clk_gating_init); | ||
diff --git a/drivers/clk/mvebu/clk-corediv.c b/drivers/clk/mvebu/clk-corediv.c index 7162615bcdcd..d1e5863d3375 100644 --- a/drivers/clk/mvebu/clk-corediv.c +++ b/drivers/clk/mvebu/clk-corediv.c | |||
@@ -18,26 +18,56 @@ | |||
18 | #include "common.h" | 18 | #include "common.h" |
19 | 19 | ||
20 | #define CORE_CLK_DIV_RATIO_MASK 0xff | 20 | #define CORE_CLK_DIV_RATIO_MASK 0xff |
21 | #define CORE_CLK_DIV_RATIO_RELOAD BIT(8) | ||
22 | #define CORE_CLK_DIV_ENABLE_OFFSET 24 | ||
23 | #define CORE_CLK_DIV_RATIO_OFFSET 0x8 | ||
24 | 21 | ||
22 | /* | ||
23 | * This structure describes the hardware details (bit offset and mask) | ||
24 | * to configure one particular core divider clock. Those hardware | ||
25 | * details may differ from one SoC to another. This structure is | ||
26 | * therefore typically instantiated statically to describe the | ||
27 | * hardware details. | ||
28 | */ | ||
25 | struct clk_corediv_desc { | 29 | struct clk_corediv_desc { |
26 | unsigned int mask; | 30 | unsigned int mask; |
27 | unsigned int offset; | 31 | unsigned int offset; |
28 | unsigned int fieldbit; | 32 | unsigned int fieldbit; |
29 | }; | 33 | }; |
30 | 34 | ||
35 | /* | ||
36 | * This structure describes the hardware details to configure the core | ||
37 | * divider clocks on a given SoC. Amongst others, it points to the | ||
38 | * array of core divider clock descriptors for this SoC, as well as | ||
39 | * the corresponding operations to manipulate them. | ||
40 | */ | ||
41 | struct clk_corediv_soc_desc { | ||
42 | const struct clk_corediv_desc *descs; | ||
43 | unsigned int ndescs; | ||
44 | const struct clk_ops ops; | ||
45 | u32 ratio_reload; | ||
46 | u32 enable_bit_offset; | ||
47 | u32 ratio_offset; | ||
48 | }; | ||
49 | |||
50 | /* | ||
51 | * This structure represents one core divider clock for the clock | ||
52 | * framework, and is dynamically allocated for each core divider clock | ||
53 | * existing in the current SoC. | ||
54 | */ | ||
31 | struct clk_corediv { | 55 | struct clk_corediv { |
32 | struct clk_hw hw; | 56 | struct clk_hw hw; |
33 | void __iomem *reg; | 57 | void __iomem *reg; |
34 | struct clk_corediv_desc desc; | 58 | const struct clk_corediv_desc *desc; |
59 | const struct clk_corediv_soc_desc *soc_desc; | ||
35 | spinlock_t lock; | 60 | spinlock_t lock; |
36 | }; | 61 | }; |
37 | 62 | ||
38 | static struct clk_onecell_data clk_data; | 63 | static struct clk_onecell_data clk_data; |
39 | 64 | ||
40 | static const struct clk_corediv_desc mvebu_corediv_desc[] __initconst = { | 65 | /* |
66 | * Description of the core divider clocks available. For now, we | ||
67 | * support only NAND, and it is available at the same register | ||
68 | * locations regardless of the SoC. | ||
69 | */ | ||
70 | static const struct clk_corediv_desc mvebu_corediv_desc[] = { | ||
41 | { .mask = 0x3f, .offset = 8, .fieldbit = 1 }, /* NAND clock */ | 71 | { .mask = 0x3f, .offset = 8, .fieldbit = 1 }, /* NAND clock */ |
42 | }; | 72 | }; |
43 | 73 | ||
@@ -46,8 +76,9 @@ static const struct clk_corediv_desc mvebu_corediv_desc[] __initconst = { | |||
46 | static int clk_corediv_is_enabled(struct clk_hw *hwclk) | 76 | static int clk_corediv_is_enabled(struct clk_hw *hwclk) |
47 | { | 77 | { |
48 | struct clk_corediv *corediv = to_corediv_clk(hwclk); | 78 | struct clk_corediv *corediv = to_corediv_clk(hwclk); |
49 | struct clk_corediv_desc *desc = &corediv->desc; | 79 | const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; |
50 | u32 enable_mask = BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET; | 80 | const struct clk_corediv_desc *desc = corediv->desc; |
81 | u32 enable_mask = BIT(desc->fieldbit) << soc_desc->enable_bit_offset; | ||
51 | 82 | ||
52 | return !!(readl(corediv->reg) & enable_mask); | 83 | return !!(readl(corediv->reg) & enable_mask); |
53 | } | 84 | } |
@@ -55,14 +86,15 @@ static int clk_corediv_is_enabled(struct clk_hw *hwclk) | |||
55 | static int clk_corediv_enable(struct clk_hw *hwclk) | 86 | static int clk_corediv_enable(struct clk_hw *hwclk) |
56 | { | 87 | { |
57 | struct clk_corediv *corediv = to_corediv_clk(hwclk); | 88 | struct clk_corediv *corediv = to_corediv_clk(hwclk); |
58 | struct clk_corediv_desc *desc = &corediv->desc; | 89 | const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; |
90 | const struct clk_corediv_desc *desc = corediv->desc; | ||
59 | unsigned long flags = 0; | 91 | unsigned long flags = 0; |
60 | u32 reg; | 92 | u32 reg; |
61 | 93 | ||
62 | spin_lock_irqsave(&corediv->lock, flags); | 94 | spin_lock_irqsave(&corediv->lock, flags); |
63 | 95 | ||
64 | reg = readl(corediv->reg); | 96 | reg = readl(corediv->reg); |
65 | reg |= (BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET); | 97 | reg |= (BIT(desc->fieldbit) << soc_desc->enable_bit_offset); |
66 | writel(reg, corediv->reg); | 98 | writel(reg, corediv->reg); |
67 | 99 | ||
68 | spin_unlock_irqrestore(&corediv->lock, flags); | 100 | spin_unlock_irqrestore(&corediv->lock, flags); |
@@ -73,14 +105,15 @@ static int clk_corediv_enable(struct clk_hw *hwclk) | |||
73 | static void clk_corediv_disable(struct clk_hw *hwclk) | 105 | static void clk_corediv_disable(struct clk_hw *hwclk) |
74 | { | 106 | { |
75 | struct clk_corediv *corediv = to_corediv_clk(hwclk); | 107 | struct clk_corediv *corediv = to_corediv_clk(hwclk); |
76 | struct clk_corediv_desc *desc = &corediv->desc; | 108 | const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; |
109 | const struct clk_corediv_desc *desc = corediv->desc; | ||
77 | unsigned long flags = 0; | 110 | unsigned long flags = 0; |
78 | u32 reg; | 111 | u32 reg; |
79 | 112 | ||
80 | spin_lock_irqsave(&corediv->lock, flags); | 113 | spin_lock_irqsave(&corediv->lock, flags); |
81 | 114 | ||
82 | reg = readl(corediv->reg); | 115 | reg = readl(corediv->reg); |
83 | reg &= ~(BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET); | 116 | reg &= ~(BIT(desc->fieldbit) << soc_desc->enable_bit_offset); |
84 | writel(reg, corediv->reg); | 117 | writel(reg, corediv->reg); |
85 | 118 | ||
86 | spin_unlock_irqrestore(&corediv->lock, flags); | 119 | spin_unlock_irqrestore(&corediv->lock, flags); |
@@ -90,10 +123,11 @@ static unsigned long clk_corediv_recalc_rate(struct clk_hw *hwclk, | |||
90 | unsigned long parent_rate) | 123 | unsigned long parent_rate) |
91 | { | 124 | { |
92 | struct clk_corediv *corediv = to_corediv_clk(hwclk); | 125 | struct clk_corediv *corediv = to_corediv_clk(hwclk); |
93 | struct clk_corediv_desc *desc = &corediv->desc; | 126 | const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; |
127 | const struct clk_corediv_desc *desc = corediv->desc; | ||
94 | u32 reg, div; | 128 | u32 reg, div; |
95 | 129 | ||
96 | reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); | 130 | reg = readl(corediv->reg + soc_desc->ratio_offset); |
97 | div = (reg >> desc->offset) & desc->mask; | 131 | div = (reg >> desc->offset) & desc->mask; |
98 | return parent_rate / div; | 132 | return parent_rate / div; |
99 | } | 133 | } |
@@ -117,7 +151,8 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate, | |||
117 | unsigned long parent_rate) | 151 | unsigned long parent_rate) |
118 | { | 152 | { |
119 | struct clk_corediv *corediv = to_corediv_clk(hwclk); | 153 | struct clk_corediv *corediv = to_corediv_clk(hwclk); |
120 | struct clk_corediv_desc *desc = &corediv->desc; | 154 | const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; |
155 | const struct clk_corediv_desc *desc = corediv->desc; | ||
121 | unsigned long flags = 0; | 156 | unsigned long flags = 0; |
122 | u32 reg, div; | 157 | u32 reg, div; |
123 | 158 | ||
@@ -126,17 +161,17 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate, | |||
126 | spin_lock_irqsave(&corediv->lock, flags); | 161 | spin_lock_irqsave(&corediv->lock, flags); |
127 | 162 | ||
128 | /* Write new divider to the divider ratio register */ | 163 | /* Write new divider to the divider ratio register */ |
129 | reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); | 164 | reg = readl(corediv->reg + soc_desc->ratio_offset); |
130 | reg &= ~(desc->mask << desc->offset); | 165 | reg &= ~(desc->mask << desc->offset); |
131 | reg |= (div & desc->mask) << desc->offset; | 166 | reg |= (div & desc->mask) << desc->offset; |
132 | writel(reg, corediv->reg + CORE_CLK_DIV_RATIO_OFFSET); | 167 | writel(reg, corediv->reg + soc_desc->ratio_offset); |
133 | 168 | ||
134 | /* Set reload-force for this clock */ | 169 | /* Set reload-force for this clock */ |
135 | reg = readl(corediv->reg) | BIT(desc->fieldbit); | 170 | reg = readl(corediv->reg) | BIT(desc->fieldbit); |
136 | writel(reg, corediv->reg); | 171 | writel(reg, corediv->reg); |
137 | 172 | ||
138 | /* Now trigger the clock update */ | 173 | /* Now trigger the clock update */ |
139 | reg = readl(corediv->reg) | CORE_CLK_DIV_RATIO_RELOAD; | 174 | reg = readl(corediv->reg) | soc_desc->ratio_reload; |
140 | writel(reg, corediv->reg); | 175 | writel(reg, corediv->reg); |
141 | 176 | ||
142 | /* | 177 | /* |
@@ -144,7 +179,7 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate, | |||
144 | * ratios request and the reload request. | 179 | * ratios request and the reload request. |
145 | */ | 180 | */ |
146 | udelay(1000); | 181 | udelay(1000); |
147 | reg &= ~(CORE_CLK_DIV_RATIO_MASK | CORE_CLK_DIV_RATIO_RELOAD); | 182 | reg &= ~(CORE_CLK_DIV_RATIO_MASK | soc_desc->ratio_reload); |
148 | writel(reg, corediv->reg); | 183 | writel(reg, corediv->reg); |
149 | udelay(1000); | 184 | udelay(1000); |
150 | 185 | ||
@@ -153,16 +188,53 @@ static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate, | |||
153 | return 0; | 188 | return 0; |
154 | } | 189 | } |
155 | 190 | ||
156 | static const struct clk_ops corediv_ops = { | 191 | static const struct clk_corediv_soc_desc armada370_corediv_soc = { |
157 | .enable = clk_corediv_enable, | 192 | .descs = mvebu_corediv_desc, |
158 | .disable = clk_corediv_disable, | 193 | .ndescs = ARRAY_SIZE(mvebu_corediv_desc), |
159 | .is_enabled = clk_corediv_is_enabled, | 194 | .ops = { |
160 | .recalc_rate = clk_corediv_recalc_rate, | 195 | .enable = clk_corediv_enable, |
161 | .round_rate = clk_corediv_round_rate, | 196 | .disable = clk_corediv_disable, |
162 | .set_rate = clk_corediv_set_rate, | 197 | .is_enabled = clk_corediv_is_enabled, |
198 | .recalc_rate = clk_corediv_recalc_rate, | ||
199 | .round_rate = clk_corediv_round_rate, | ||
200 | .set_rate = clk_corediv_set_rate, | ||
201 | }, | ||
202 | .ratio_reload = BIT(8), | ||
203 | .enable_bit_offset = 24, | ||
204 | .ratio_offset = 0x8, | ||
205 | }; | ||
206 | |||
207 | static const struct clk_corediv_soc_desc armada380_corediv_soc = { | ||
208 | .descs = mvebu_corediv_desc, | ||
209 | .ndescs = ARRAY_SIZE(mvebu_corediv_desc), | ||
210 | .ops = { | ||
211 | .enable = clk_corediv_enable, | ||
212 | .disable = clk_corediv_disable, | ||
213 | .is_enabled = clk_corediv_is_enabled, | ||
214 | .recalc_rate = clk_corediv_recalc_rate, | ||
215 | .round_rate = clk_corediv_round_rate, | ||
216 | .set_rate = clk_corediv_set_rate, | ||
217 | }, | ||
218 | .ratio_reload = BIT(8), | ||
219 | .enable_bit_offset = 16, | ||
220 | .ratio_offset = 0x4, | ||
163 | }; | 221 | }; |
164 | 222 | ||
165 | static void __init mvebu_corediv_clk_init(struct device_node *node) | 223 | static const struct clk_corediv_soc_desc armada375_corediv_soc = { |
224 | .descs = mvebu_corediv_desc, | ||
225 | .ndescs = ARRAY_SIZE(mvebu_corediv_desc), | ||
226 | .ops = { | ||
227 | .recalc_rate = clk_corediv_recalc_rate, | ||
228 | .round_rate = clk_corediv_round_rate, | ||
229 | .set_rate = clk_corediv_set_rate, | ||
230 | }, | ||
231 | .ratio_reload = BIT(8), | ||
232 | .ratio_offset = 0x4, | ||
233 | }; | ||
234 | |||
235 | static void __init | ||
236 | mvebu_corediv_clk_init(struct device_node *node, | ||
237 | const struct clk_corediv_soc_desc *soc_desc) | ||
166 | { | 238 | { |
167 | struct clk_init_data init; | 239 | struct clk_init_data init; |
168 | struct clk_corediv *corediv; | 240 | struct clk_corediv *corediv; |
@@ -178,7 +250,7 @@ static void __init mvebu_corediv_clk_init(struct device_node *node) | |||
178 | 250 | ||
179 | parent_name = of_clk_get_parent_name(node, 0); | 251 | parent_name = of_clk_get_parent_name(node, 0); |
180 | 252 | ||
181 | clk_data.clk_num = ARRAY_SIZE(mvebu_corediv_desc); | 253 | clk_data.clk_num = soc_desc->ndescs; |
182 | 254 | ||
183 | /* clks holds the clock array */ | 255 | /* clks holds the clock array */ |
184 | clks = kcalloc(clk_data.clk_num, sizeof(struct clk *), | 256 | clks = kcalloc(clk_data.clk_num, sizeof(struct clk *), |
@@ -199,10 +271,11 @@ static void __init mvebu_corediv_clk_init(struct device_node *node) | |||
199 | init.num_parents = 1; | 271 | init.num_parents = 1; |
200 | init.parent_names = &parent_name; | 272 | init.parent_names = &parent_name; |
201 | init.name = clk_name; | 273 | init.name = clk_name; |
202 | init.ops = &corediv_ops; | 274 | init.ops = &soc_desc->ops; |
203 | init.flags = 0; | 275 | init.flags = 0; |
204 | 276 | ||
205 | corediv[i].desc = mvebu_corediv_desc[i]; | 277 | corediv[i].soc_desc = soc_desc; |
278 | corediv[i].desc = soc_desc->descs + i; | ||
206 | corediv[i].reg = base; | 279 | corediv[i].reg = base; |
207 | corediv[i].hw.init = &init; | 280 | corediv[i].hw.init = &init; |
208 | 281 | ||
@@ -219,5 +292,24 @@ err_free_clks: | |||
219 | err_unmap: | 292 | err_unmap: |
220 | iounmap(base); | 293 | iounmap(base); |
221 | } | 294 | } |
222 | CLK_OF_DECLARE(mvebu_corediv_clk, "marvell,armada-370-corediv-clock", | 295 | |
223 | mvebu_corediv_clk_init); | 296 | static void __init armada370_corediv_clk_init(struct device_node *node) |
297 | { | ||
298 | return mvebu_corediv_clk_init(node, &armada370_corediv_soc); | ||
299 | } | ||
300 | CLK_OF_DECLARE(armada370_corediv_clk, "marvell,armada-370-corediv-clock", | ||
301 | armada370_corediv_clk_init); | ||
302 | |||
303 | static void __init armada375_corediv_clk_init(struct device_node *node) | ||
304 | { | ||
305 | return mvebu_corediv_clk_init(node, &armada375_corediv_soc); | ||
306 | } | ||
307 | CLK_OF_DECLARE(armada375_corediv_clk, "marvell,armada-375-corediv-clock", | ||
308 | armada375_corediv_clk_init); | ||
309 | |||
310 | static void __init armada380_corediv_clk_init(struct device_node *node) | ||
311 | { | ||
312 | return mvebu_corediv_clk_init(node, &armada380_corediv_soc); | ||
313 | } | ||
314 | CLK_OF_DECLARE(armada380_corediv_clk, "marvell,armada-380-corediv-clock", | ||
315 | armada380_corediv_clk_init); | ||
diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile index 9ecef140dba7..5404cb931ebf 100644 --- a/drivers/clk/shmobile/Makefile +++ b/drivers/clk/shmobile/Makefile | |||
@@ -1,4 +1,5 @@ | |||
1 | obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o | 1 | obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o |
2 | obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o | ||
2 | obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o | 3 | obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o |
3 | obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o | 4 | obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o |
4 | obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o | 5 | obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o |
diff --git a/drivers/clk/shmobile/clk-div6.c b/drivers/clk/shmobile/clk-div6.c index aac4756ec52e..f065f694cb65 100644 --- a/drivers/clk/shmobile/clk-div6.c +++ b/drivers/clk/shmobile/clk-div6.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #define CPG_DIV6_DIV_MASK 0x3f | 23 | #define CPG_DIV6_DIV_MASK 0x3f |
24 | 24 | ||
25 | /** | 25 | /** |
26 | * struct div6_clock - MSTP gating clock | 26 | * struct div6_clock - CPG 6 bit divider clock |
27 | * @hw: handle between common and hardware-specific interfaces | 27 | * @hw: handle between common and hardware-specific interfaces |
28 | * @reg: IO-remapped register | 28 | * @reg: IO-remapped register |
29 | * @div: divisor value (1-64) | 29 | * @div: divisor value (1-64) |
diff --git a/drivers/clk/shmobile/clk-mstp.c b/drivers/clk/shmobile/clk-mstp.c index 42d5912b1d25..2e5810c88d11 100644 --- a/drivers/clk/shmobile/clk-mstp.c +++ b/drivers/clk/shmobile/clk-mstp.c | |||
@@ -137,7 +137,7 @@ cpg_mstp_clock_register(const char *name, const char *parent_name, | |||
137 | 137 | ||
138 | init.name = name; | 138 | init.name = name; |
139 | init.ops = &cpg_mstp_clock_ops; | 139 | init.ops = &cpg_mstp_clock_ops; |
140 | init.flags = CLK_IS_BASIC; | 140 | init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT; |
141 | init.parent_names = &parent_name; | 141 | init.parent_names = &parent_name; |
142 | init.num_parents = 1; | 142 | init.num_parents = 1; |
143 | 143 | ||
diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c index 99c27b1c625b..dff7f79a19b9 100644 --- a/drivers/clk/shmobile/clk-rcar-gen2.c +++ b/drivers/clk/shmobile/clk-rcar-gen2.c | |||
@@ -242,22 +242,22 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, | |||
242 | parent_name = "main"; | 242 | parent_name = "main"; |
243 | mult = config->pll3_mult; | 243 | mult = config->pll3_mult; |
244 | } else if (!strcmp(name, "lb")) { | 244 | } else if (!strcmp(name, "lb")) { |
245 | parent_name = "pll1_div2"; | 245 | parent_name = "pll1"; |
246 | div = cpg_mode & BIT(18) ? 36 : 24; | 246 | div = cpg_mode & BIT(18) ? 36 : 24; |
247 | } else if (!strcmp(name, "qspi")) { | 247 | } else if (!strcmp(name, "qspi")) { |
248 | parent_name = "pll1_div2"; | 248 | parent_name = "pll1_div2"; |
249 | div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) | 249 | div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) |
250 | ? 8 : 10; | 250 | ? 8 : 10; |
251 | } else if (!strcmp(name, "sdh")) { | 251 | } else if (!strcmp(name, "sdh")) { |
252 | parent_name = "pll1_div2"; | 252 | parent_name = "pll1"; |
253 | table = cpg_sdh_div_table; | 253 | table = cpg_sdh_div_table; |
254 | shift = 8; | 254 | shift = 8; |
255 | } else if (!strcmp(name, "sd0")) { | 255 | } else if (!strcmp(name, "sd0")) { |
256 | parent_name = "pll1_div2"; | 256 | parent_name = "pll1"; |
257 | table = cpg_sd01_div_table; | 257 | table = cpg_sd01_div_table; |
258 | shift = 4; | 258 | shift = 4; |
259 | } else if (!strcmp(name, "sd1")) { | 259 | } else if (!strcmp(name, "sd1")) { |
260 | parent_name = "pll1_div2"; | 260 | parent_name = "pll1"; |
261 | table = cpg_sd01_div_table; | 261 | table = cpg_sd01_div_table; |
262 | shift = 0; | 262 | shift = 0; |
263 | } else if (!strcmp(name, "z")) { | 263 | } else if (!strcmp(name, "z")) { |
diff --git a/drivers/clk/shmobile/clk-rz.c b/drivers/clk/shmobile/clk-rz.c new file mode 100644 index 000000000000..7e68e8630962 --- /dev/null +++ b/drivers/clk/shmobile/clk-rz.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * rz Core CPG Clocks | ||
3 | * | ||
4 | * Copyright (C) 2013 Ideas On Board SPRL | ||
5 | * Copyright (C) 2014 Wolfram Sang, Sang Engineering <wsa@sang-engineering.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk-provider.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/of_address.h> | ||
17 | #include <linux/slab.h> | ||
18 | |||
19 | struct rz_cpg { | ||
20 | struct clk_onecell_data data; | ||
21 | void __iomem *reg; | ||
22 | }; | ||
23 | |||
24 | #define CPG_FRQCR 0x10 | ||
25 | #define CPG_FRQCR2 0x14 | ||
26 | |||
27 | /* ----------------------------------------------------------------------------- | ||
28 | * Initialization | ||
29 | */ | ||
30 | |||
31 | static struct clk * __init | ||
32 | rz_cpg_register_clock(struct device_node *np, struct rz_cpg *cpg, const char *name) | ||
33 | { | ||
34 | u32 val; | ||
35 | unsigned mult; | ||
36 | static const unsigned frqcr_tab[4] = { 3, 2, 0, 1 }; | ||
37 | |||
38 | if (strcmp(name, "pll") == 0) { | ||
39 | /* FIXME: cpg_mode should be read from GPIO. But no GPIO support yet */ | ||
40 | unsigned cpg_mode = 0; /* hardcoded to EXTAL for now */ | ||
41 | const char *parent_name = of_clk_get_parent_name(np, cpg_mode); | ||
42 | |||
43 | mult = cpg_mode ? (32 / 4) : 30; | ||
44 | |||
45 | return clk_register_fixed_factor(NULL, name, parent_name, 0, mult, 1); | ||
46 | } | ||
47 | |||
48 | /* If mapping regs failed, skip non-pll clocks. System will boot anyhow */ | ||
49 | if (!cpg->reg) | ||
50 | return ERR_PTR(-ENXIO); | ||
51 | |||
52 | /* FIXME:"i" and "g" are variable clocks with non-integer dividers (e.g. 2/3) | ||
53 | * and the constraint that always g <= i. To get the rz platform started, | ||
54 | * let them run at fixed current speed and implement the details later. | ||
55 | */ | ||
56 | if (strcmp(name, "i") == 0) | ||
57 | val = (clk_readl(cpg->reg + CPG_FRQCR) >> 8) & 3; | ||
58 | else if (strcmp(name, "g") == 0) | ||
59 | val = clk_readl(cpg->reg + CPG_FRQCR2) & 3; | ||
60 | else | ||
61 | return ERR_PTR(-EINVAL); | ||
62 | |||
63 | mult = frqcr_tab[val]; | ||
64 | return clk_register_fixed_factor(NULL, name, "pll", 0, mult, 3); | ||
65 | } | ||
66 | |||
67 | static void __init rz_cpg_clocks_init(struct device_node *np) | ||
68 | { | ||
69 | struct rz_cpg *cpg; | ||
70 | struct clk **clks; | ||
71 | unsigned i; | ||
72 | int num_clks; | ||
73 | |||
74 | num_clks = of_property_count_strings(np, "clock-output-names"); | ||
75 | if (WARN(num_clks <= 0, "can't count CPG clocks\n")) | ||
76 | return; | ||
77 | |||
78 | cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); | ||
79 | clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL); | ||
80 | BUG_ON(!cpg || !clks); | ||
81 | |||
82 | cpg->data.clks = clks; | ||
83 | cpg->data.clk_num = num_clks; | ||
84 | |||
85 | cpg->reg = of_iomap(np, 0); | ||
86 | |||
87 | for (i = 0; i < num_clks; ++i) { | ||
88 | const char *name; | ||
89 | struct clk *clk; | ||
90 | |||
91 | of_property_read_string_index(np, "clock-output-names", i, &name); | ||
92 | |||
93 | clk = rz_cpg_register_clock(np, cpg, name); | ||
94 | if (IS_ERR(clk)) | ||
95 | pr_err("%s: failed to register %s %s clock (%ld)\n", | ||
96 | __func__, np->name, name, PTR_ERR(clk)); | ||
97 | else | ||
98 | cpg->data.clks[i] = clk; | ||
99 | } | ||
100 | |||
101 | of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); | ||
102 | } | ||
103 | CLK_OF_DECLARE(rz_cpg_clks, "renesas,rz-cpg-clocks", rz_cpg_clocks_init); | ||
diff --git a/drivers/clk/sirf/clk-atlas6.c b/drivers/clk/sirf/clk-atlas6.c index f9f4a15a64ab..d63b76ca60c3 100644 --- a/drivers/clk/sirf/clk-atlas6.c +++ b/drivers/clk/sirf/clk-atlas6.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Clock tree for CSR SiRFatlasVI | 2 | * Clock tree for CSR SiRFatlasVI |
3 | * | 3 | * |
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | 4 | * Copyright (c) 2011 - 2014 Cambridge Silicon Radio Limited, a CSR plc group |
5 | * company. | ||
5 | * | 6 | * |
6 | * Licensed under GPLv2 or later. | 7 | * Licensed under GPLv2 or later. |
7 | */ | 8 | */ |
diff --git a/drivers/clk/sirf/clk-common.c b/drivers/clk/sirf/clk-common.c index 7dde6a82f514..37af51c5f213 100644 --- a/drivers/clk/sirf/clk-common.c +++ b/drivers/clk/sirf/clk-common.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * common clks module for all SiRF SoCs | 2 | * common clks module for all SiRF SoCs |
3 | * | 3 | * |
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | 4 | * Copyright (c) 2011 - 2014 Cambridge Silicon Radio Limited, a CSR plc group |
5 | * company. | ||
5 | * | 6 | * |
6 | * Licensed under GPLv2 or later. | 7 | * Licensed under GPLv2 or later. |
7 | */ | 8 | */ |
diff --git a/drivers/clk/sirf/clk-prima2.c b/drivers/clk/sirf/clk-prima2.c index 7adc5c70c7ff..6968e2ebcd8a 100644 --- a/drivers/clk/sirf/clk-prima2.c +++ b/drivers/clk/sirf/clk-prima2.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Clock tree for CSR SiRFprimaII | 2 | * Clock tree for CSR SiRFprimaII |
3 | * | 3 | * |
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | 4 | * Copyright (c) 2011 - 2014 Cambridge Silicon Radio Limited, a CSR plc group |
5 | * company. | ||
5 | * | 6 | * |
6 | * Licensed under GPLv2 or later. | 7 | * Licensed under GPLv2 or later. |
7 | */ | 8 | */ |
diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile index 0303c0b99cd0..7e2d15a0c7b8 100644 --- a/drivers/clk/socfpga/Makefile +++ b/drivers/clk/socfpga/Makefile | |||
@@ -1 +1,4 @@ | |||
1 | obj-y += clk.o | 1 | obj-y += clk.o |
2 | obj-y += clk-gate.o | ||
3 | obj-y += clk-pll.o | ||
4 | obj-y += clk-periph.o | ||
diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c new file mode 100644 index 000000000000..501d513bf890 --- /dev/null +++ b/drivers/clk/socfpga/clk-gate.c | |||
@@ -0,0 +1,263 @@ | |||
1 | /* | ||
2 | * Copyright 2011-2012 Calxeda, Inc. | ||
3 | * Copyright (C) 2012-2013 Altera Corporation <www.altera.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * Based from clk-highbank.c | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/clkdev.h> | ||
20 | #include <linux/clk-provider.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/mfd/syscon.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/regmap.h> | ||
25 | |||
26 | #include "clk.h" | ||
27 | |||
28 | #define SOCFPGA_L4_MP_CLK "l4_mp_clk" | ||
29 | #define SOCFPGA_L4_SP_CLK "l4_sp_clk" | ||
30 | #define SOCFPGA_NAND_CLK "nand_clk" | ||
31 | #define SOCFPGA_NAND_X_CLK "nand_x_clk" | ||
32 | #define SOCFPGA_MMC_CLK "sdmmc_clk" | ||
33 | #define SOCFPGA_GPIO_DB_CLK_OFFSET 0xA8 | ||
34 | |||
35 | #define div_mask(width) ((1 << (width)) - 1) | ||
36 | #define streq(a, b) (strcmp((a), (b)) == 0) | ||
37 | |||
38 | #define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw) | ||
39 | |||
40 | /* SDMMC Group for System Manager defines */ | ||
41 | #define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x108 | ||
42 | #define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \ | ||
43 | ((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0)) | ||
44 | |||
45 | static u8 socfpga_clk_get_parent(struct clk_hw *hwclk) | ||
46 | { | ||
47 | u32 l4_src; | ||
48 | u32 perpll_src; | ||
49 | |||
50 | if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) { | ||
51 | l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
52 | return l4_src &= 0x1; | ||
53 | } | ||
54 | if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) { | ||
55 | l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
56 | return !!(l4_src & 2); | ||
57 | } | ||
58 | |||
59 | perpll_src = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC); | ||
60 | if (streq(hwclk->init->name, SOCFPGA_MMC_CLK)) | ||
61 | return perpll_src &= 0x3; | ||
62 | if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) || | ||
63 | streq(hwclk->init->name, SOCFPGA_NAND_X_CLK)) | ||
64 | return (perpll_src >> 2) & 3; | ||
65 | |||
66 | /* QSPI clock */ | ||
67 | return (perpll_src >> 4) & 3; | ||
68 | |||
69 | } | ||
70 | |||
71 | static int socfpga_clk_set_parent(struct clk_hw *hwclk, u8 parent) | ||
72 | { | ||
73 | u32 src_reg; | ||
74 | |||
75 | if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) { | ||
76 | src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
77 | src_reg &= ~0x1; | ||
78 | src_reg |= parent; | ||
79 | writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC); | ||
80 | } else if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) { | ||
81 | src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
82 | src_reg &= ~0x2; | ||
83 | src_reg |= (parent << 1); | ||
84 | writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC); | ||
85 | } else { | ||
86 | src_reg = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC); | ||
87 | if (streq(hwclk->init->name, SOCFPGA_MMC_CLK)) { | ||
88 | src_reg &= ~0x3; | ||
89 | src_reg |= parent; | ||
90 | } else if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) || | ||
91 | streq(hwclk->init->name, SOCFPGA_NAND_X_CLK)) { | ||
92 | src_reg &= ~0xC; | ||
93 | src_reg |= (parent << 2); | ||
94 | } else {/* QSPI clock */ | ||
95 | src_reg &= ~0x30; | ||
96 | src_reg |= (parent << 4); | ||
97 | } | ||
98 | writel(src_reg, clk_mgr_base_addr + CLKMGR_PERPLL_SRC); | ||
99 | } | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk, | ||
105 | unsigned long parent_rate) | ||
106 | { | ||
107 | struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk); | ||
108 | u32 div = 1, val; | ||
109 | |||
110 | if (socfpgaclk->fixed_div) | ||
111 | div = socfpgaclk->fixed_div; | ||
112 | else if (socfpgaclk->div_reg) { | ||
113 | val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift; | ||
114 | val &= div_mask(socfpgaclk->width); | ||
115 | /* Check for GPIO_DB_CLK by its offset */ | ||
116 | if ((int) socfpgaclk->div_reg & SOCFPGA_GPIO_DB_CLK_OFFSET) | ||
117 | div = val + 1; | ||
118 | else | ||
119 | div = (1 << val); | ||
120 | } | ||
121 | |||
122 | return parent_rate / div; | ||
123 | } | ||
124 | |||
125 | static int socfpga_clk_prepare(struct clk_hw *hwclk) | ||
126 | { | ||
127 | struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk); | ||
128 | struct regmap *sys_mgr_base_addr; | ||
129 | int i; | ||
130 | u32 hs_timing; | ||
131 | u32 clk_phase[2]; | ||
132 | |||
133 | if (socfpgaclk->clk_phase[0] || socfpgaclk->clk_phase[1]) { | ||
134 | sys_mgr_base_addr = syscon_regmap_lookup_by_compatible("altr,sys-mgr"); | ||
135 | if (IS_ERR(sys_mgr_base_addr)) { | ||
136 | pr_err("%s: failed to find altr,sys-mgr regmap!\n", __func__); | ||
137 | return -EINVAL; | ||
138 | } | ||
139 | |||
140 | for (i = 0; i < 2; i++) { | ||
141 | switch (socfpgaclk->clk_phase[i]) { | ||
142 | case 0: | ||
143 | clk_phase[i] = 0; | ||
144 | break; | ||
145 | case 45: | ||
146 | clk_phase[i] = 1; | ||
147 | break; | ||
148 | case 90: | ||
149 | clk_phase[i] = 2; | ||
150 | break; | ||
151 | case 135: | ||
152 | clk_phase[i] = 3; | ||
153 | break; | ||
154 | case 180: | ||
155 | clk_phase[i] = 4; | ||
156 | break; | ||
157 | case 225: | ||
158 | clk_phase[i] = 5; | ||
159 | break; | ||
160 | case 270: | ||
161 | clk_phase[i] = 6; | ||
162 | break; | ||
163 | case 315: | ||
164 | clk_phase[i] = 7; | ||
165 | break; | ||
166 | default: | ||
167 | clk_phase[i] = 0; | ||
168 | break; | ||
169 | } | ||
170 | } | ||
171 | hs_timing = SYSMGR_SDMMC_CTRL_SET(clk_phase[0], clk_phase[1]); | ||
172 | regmap_write(sys_mgr_base_addr, SYSMGR_SDMMCGRP_CTRL_OFFSET, | ||
173 | hs_timing); | ||
174 | } | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static struct clk_ops gateclk_ops = { | ||
179 | .prepare = socfpga_clk_prepare, | ||
180 | .recalc_rate = socfpga_clk_recalc_rate, | ||
181 | .get_parent = socfpga_clk_get_parent, | ||
182 | .set_parent = socfpga_clk_set_parent, | ||
183 | }; | ||
184 | |||
185 | static void __init __socfpga_gate_init(struct device_node *node, | ||
186 | const struct clk_ops *ops) | ||
187 | { | ||
188 | u32 clk_gate[2]; | ||
189 | u32 div_reg[3]; | ||
190 | u32 clk_phase[2]; | ||
191 | u32 fixed_div; | ||
192 | struct clk *clk; | ||
193 | struct socfpga_gate_clk *socfpga_clk; | ||
194 | const char *clk_name = node->name; | ||
195 | const char *parent_name[SOCFPGA_MAX_PARENTS]; | ||
196 | struct clk_init_data init; | ||
197 | int rc; | ||
198 | int i = 0; | ||
199 | |||
200 | socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL); | ||
201 | if (WARN_ON(!socfpga_clk)) | ||
202 | return; | ||
203 | |||
204 | rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2); | ||
205 | if (rc) | ||
206 | clk_gate[0] = 0; | ||
207 | |||
208 | if (clk_gate[0]) { | ||
209 | socfpga_clk->hw.reg = clk_mgr_base_addr + clk_gate[0]; | ||
210 | socfpga_clk->hw.bit_idx = clk_gate[1]; | ||
211 | |||
212 | gateclk_ops.enable = clk_gate_ops.enable; | ||
213 | gateclk_ops.disable = clk_gate_ops.disable; | ||
214 | } | ||
215 | |||
216 | rc = of_property_read_u32(node, "fixed-divider", &fixed_div); | ||
217 | if (rc) | ||
218 | socfpga_clk->fixed_div = 0; | ||
219 | else | ||
220 | socfpga_clk->fixed_div = fixed_div; | ||
221 | |||
222 | rc = of_property_read_u32_array(node, "div-reg", div_reg, 3); | ||
223 | if (!rc) { | ||
224 | socfpga_clk->div_reg = clk_mgr_base_addr + div_reg[0]; | ||
225 | socfpga_clk->shift = div_reg[1]; | ||
226 | socfpga_clk->width = div_reg[2]; | ||
227 | } else { | ||
228 | socfpga_clk->div_reg = 0; | ||
229 | } | ||
230 | |||
231 | rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2); | ||
232 | if (!rc) { | ||
233 | socfpga_clk->clk_phase[0] = clk_phase[0]; | ||
234 | socfpga_clk->clk_phase[1] = clk_phase[1]; | ||
235 | } | ||
236 | |||
237 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
238 | |||
239 | init.name = clk_name; | ||
240 | init.ops = ops; | ||
241 | init.flags = 0; | ||
242 | while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] = | ||
243 | of_clk_get_parent_name(node, i)) != NULL) | ||
244 | i++; | ||
245 | |||
246 | init.parent_names = parent_name; | ||
247 | init.num_parents = i; | ||
248 | socfpga_clk->hw.hw.init = &init; | ||
249 | |||
250 | clk = clk_register(NULL, &socfpga_clk->hw.hw); | ||
251 | if (WARN_ON(IS_ERR(clk))) { | ||
252 | kfree(socfpga_clk); | ||
253 | return; | ||
254 | } | ||
255 | rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
256 | if (WARN_ON(rc)) | ||
257 | return; | ||
258 | } | ||
259 | |||
260 | void __init socfpga_gate_init(struct device_node *node) | ||
261 | { | ||
262 | __socfpga_gate_init(node, &gateclk_ops); | ||
263 | } | ||
diff --git a/drivers/clk/socfpga/clk-periph.c b/drivers/clk/socfpga/clk-periph.c new file mode 100644 index 000000000000..81623a3736f9 --- /dev/null +++ b/drivers/clk/socfpga/clk-periph.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * Copyright 2011-2012 Calxeda, Inc. | ||
3 | * Copyright (C) 2012-2013 Altera Corporation <www.altera.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * Based from clk-highbank.c | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/clkdev.h> | ||
20 | #include <linux/clk-provider.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/of.h> | ||
23 | |||
24 | #include "clk.h" | ||
25 | |||
26 | #define to_socfpga_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw) | ||
27 | |||
28 | static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk, | ||
29 | unsigned long parent_rate) | ||
30 | { | ||
31 | struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk); | ||
32 | u32 div; | ||
33 | |||
34 | if (socfpgaclk->fixed_div) | ||
35 | div = socfpgaclk->fixed_div; | ||
36 | else | ||
37 | div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1); | ||
38 | |||
39 | return parent_rate / div; | ||
40 | } | ||
41 | |||
42 | static const struct clk_ops periclk_ops = { | ||
43 | .recalc_rate = clk_periclk_recalc_rate, | ||
44 | }; | ||
45 | |||
46 | static __init void __socfpga_periph_init(struct device_node *node, | ||
47 | const struct clk_ops *ops) | ||
48 | { | ||
49 | u32 reg; | ||
50 | struct clk *clk; | ||
51 | struct socfpga_periph_clk *periph_clk; | ||
52 | const char *clk_name = node->name; | ||
53 | const char *parent_name; | ||
54 | struct clk_init_data init; | ||
55 | int rc; | ||
56 | u32 fixed_div; | ||
57 | |||
58 | of_property_read_u32(node, "reg", ®); | ||
59 | |||
60 | periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL); | ||
61 | if (WARN_ON(!periph_clk)) | ||
62 | return; | ||
63 | |||
64 | periph_clk->hw.reg = clk_mgr_base_addr + reg; | ||
65 | |||
66 | rc = of_property_read_u32(node, "fixed-divider", &fixed_div); | ||
67 | if (rc) | ||
68 | periph_clk->fixed_div = 0; | ||
69 | else | ||
70 | periph_clk->fixed_div = fixed_div; | ||
71 | |||
72 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
73 | |||
74 | init.name = clk_name; | ||
75 | init.ops = ops; | ||
76 | init.flags = 0; | ||
77 | parent_name = of_clk_get_parent_name(node, 0); | ||
78 | init.parent_names = &parent_name; | ||
79 | init.num_parents = 1; | ||
80 | |||
81 | periph_clk->hw.hw.init = &init; | ||
82 | |||
83 | clk = clk_register(NULL, &periph_clk->hw.hw); | ||
84 | if (WARN_ON(IS_ERR(clk))) { | ||
85 | kfree(periph_clk); | ||
86 | return; | ||
87 | } | ||
88 | rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
89 | } | ||
90 | |||
91 | void __init socfpga_periph_init(struct device_node *node) | ||
92 | { | ||
93 | __socfpga_periph_init(node, &periclk_ops); | ||
94 | } | ||
diff --git a/drivers/clk/socfpga/clk-pll.c b/drivers/clk/socfpga/clk-pll.c new file mode 100644 index 000000000000..88dafb5e9627 --- /dev/null +++ b/drivers/clk/socfpga/clk-pll.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * Copyright 2011-2012 Calxeda, Inc. | ||
3 | * Copyright (C) 2012-2013 Altera Corporation <www.altera.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * Based from clk-highbank.c | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/clkdev.h> | ||
20 | #include <linux/clk-provider.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/of.h> | ||
23 | |||
24 | #include "clk.h" | ||
25 | |||
26 | /* Clock bypass bits */ | ||
27 | #define MAINPLL_BYPASS (1<<0) | ||
28 | #define SDRAMPLL_BYPASS (1<<1) | ||
29 | #define SDRAMPLL_SRC_BYPASS (1<<2) | ||
30 | #define PERPLL_BYPASS (1<<3) | ||
31 | #define PERPLL_SRC_BYPASS (1<<4) | ||
32 | |||
33 | #define SOCFPGA_PLL_BG_PWRDWN 0 | ||
34 | #define SOCFPGA_PLL_EXT_ENA 1 | ||
35 | #define SOCFPGA_PLL_PWR_DOWN 2 | ||
36 | #define SOCFPGA_PLL_DIVF_MASK 0x0000FFF8 | ||
37 | #define SOCFPGA_PLL_DIVF_SHIFT 3 | ||
38 | #define SOCFPGA_PLL_DIVQ_MASK 0x003F0000 | ||
39 | #define SOCFPGA_PLL_DIVQ_SHIFT 16 | ||
40 | |||
41 | #define CLK_MGR_PLL_CLK_SRC_SHIFT 22 | ||
42 | #define CLK_MGR_PLL_CLK_SRC_MASK 0x3 | ||
43 | |||
44 | #define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw) | ||
45 | |||
46 | static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk, | ||
47 | unsigned long parent_rate) | ||
48 | { | ||
49 | struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); | ||
50 | unsigned long divf, divq, reg; | ||
51 | unsigned long long vco_freq; | ||
52 | unsigned long bypass; | ||
53 | |||
54 | reg = readl(socfpgaclk->hw.reg); | ||
55 | bypass = readl(clk_mgr_base_addr + CLKMGR_BYPASS); | ||
56 | if (bypass & MAINPLL_BYPASS) | ||
57 | return parent_rate; | ||
58 | |||
59 | divf = (reg & SOCFPGA_PLL_DIVF_MASK) >> SOCFPGA_PLL_DIVF_SHIFT; | ||
60 | divq = (reg & SOCFPGA_PLL_DIVQ_MASK) >> SOCFPGA_PLL_DIVQ_SHIFT; | ||
61 | vco_freq = (unsigned long long)parent_rate * (divf + 1); | ||
62 | do_div(vco_freq, (1 + divq)); | ||
63 | return (unsigned long)vco_freq; | ||
64 | } | ||
65 | |||
66 | static u8 clk_pll_get_parent(struct clk_hw *hwclk) | ||
67 | { | ||
68 | u32 pll_src; | ||
69 | struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); | ||
70 | |||
71 | pll_src = readl(socfpgaclk->hw.reg); | ||
72 | return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) & | ||
73 | CLK_MGR_PLL_CLK_SRC_MASK; | ||
74 | } | ||
75 | |||
76 | static struct clk_ops clk_pll_ops = { | ||
77 | .recalc_rate = clk_pll_recalc_rate, | ||
78 | .get_parent = clk_pll_get_parent, | ||
79 | }; | ||
80 | |||
81 | static __init struct clk *__socfpga_pll_init(struct device_node *node, | ||
82 | const struct clk_ops *ops) | ||
83 | { | ||
84 | u32 reg; | ||
85 | struct clk *clk; | ||
86 | struct socfpga_pll *pll_clk; | ||
87 | const char *clk_name = node->name; | ||
88 | const char *parent_name[SOCFPGA_MAX_PARENTS]; | ||
89 | struct clk_init_data init; | ||
90 | int rc; | ||
91 | int i = 0; | ||
92 | |||
93 | of_property_read_u32(node, "reg", ®); | ||
94 | |||
95 | pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); | ||
96 | if (WARN_ON(!pll_clk)) | ||
97 | return NULL; | ||
98 | |||
99 | pll_clk->hw.reg = clk_mgr_base_addr + reg; | ||
100 | |||
101 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
102 | |||
103 | init.name = clk_name; | ||
104 | init.ops = ops; | ||
105 | init.flags = 0; | ||
106 | |||
107 | while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] = | ||
108 | of_clk_get_parent_name(node, i)) != NULL) | ||
109 | i++; | ||
110 | |||
111 | init.num_parents = i; | ||
112 | init.parent_names = parent_name; | ||
113 | pll_clk->hw.hw.init = &init; | ||
114 | |||
115 | pll_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA; | ||
116 | clk_pll_ops.enable = clk_gate_ops.enable; | ||
117 | clk_pll_ops.disable = clk_gate_ops.disable; | ||
118 | |||
119 | clk = clk_register(NULL, &pll_clk->hw.hw); | ||
120 | if (WARN_ON(IS_ERR(clk))) { | ||
121 | kfree(pll_clk); | ||
122 | return NULL; | ||
123 | } | ||
124 | rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
125 | return clk; | ||
126 | } | ||
127 | |||
128 | void __init socfpga_pll_init(struct device_node *node) | ||
129 | { | ||
130 | __socfpga_pll_init(node, &clk_pll_ops); | ||
131 | } | ||
diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c index 5983a26a8c5f..35a960a993f9 100644 --- a/drivers/clk/socfpga/clk.c +++ b/drivers/clk/socfpga/clk.c | |||
@@ -22,325 +22,23 @@ | |||
22 | #include <linux/clk-provider.h> | 22 | #include <linux/clk-provider.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/of_address.h> | ||
25 | 26 | ||
26 | /* Clock Manager offsets */ | 27 | #include "clk.h" |
27 | #define CLKMGR_CTRL 0x0 | ||
28 | #define CLKMGR_BYPASS 0x4 | ||
29 | #define CLKMGR_L4SRC 0x70 | ||
30 | #define CLKMGR_PERPLL_SRC 0xAC | ||
31 | 28 | ||
32 | /* Clock bypass bits */ | 29 | void __iomem *clk_mgr_base_addr; |
33 | #define MAINPLL_BYPASS (1<<0) | ||
34 | #define SDRAMPLL_BYPASS (1<<1) | ||
35 | #define SDRAMPLL_SRC_BYPASS (1<<2) | ||
36 | #define PERPLL_BYPASS (1<<3) | ||
37 | #define PERPLL_SRC_BYPASS (1<<4) | ||
38 | 30 | ||
39 | #define SOCFPGA_PLL_BG_PWRDWN 0 | 31 | static const struct of_device_id socfpga_child_clocks[] __initconst = { |
40 | #define SOCFPGA_PLL_EXT_ENA 1 | 32 | { .compatible = "altr,socfpga-pll-clock", socfpga_pll_init, }, |
41 | #define SOCFPGA_PLL_PWR_DOWN 2 | 33 | { .compatible = "altr,socfpga-perip-clk", socfpga_periph_init, }, |
42 | #define SOCFPGA_PLL_DIVF_MASK 0x0000FFF8 | 34 | { .compatible = "altr,socfpga-gate-clk", socfpga_gate_init, }, |
43 | #define SOCFPGA_PLL_DIVF_SHIFT 3 | 35 | {}, |
44 | #define SOCFPGA_PLL_DIVQ_MASK 0x003F0000 | ||
45 | #define SOCFPGA_PLL_DIVQ_SHIFT 16 | ||
46 | #define SOCFGPA_MAX_PARENTS 3 | ||
47 | |||
48 | #define SOCFPGA_L4_MP_CLK "l4_mp_clk" | ||
49 | #define SOCFPGA_L4_SP_CLK "l4_sp_clk" | ||
50 | #define SOCFPGA_NAND_CLK "nand_clk" | ||
51 | #define SOCFPGA_NAND_X_CLK "nand_x_clk" | ||
52 | #define SOCFPGA_MMC_CLK "sdmmc_clk" | ||
53 | #define SOCFPGA_DB_CLK "gpio_db_clk" | ||
54 | |||
55 | #define div_mask(width) ((1 << (width)) - 1) | ||
56 | #define streq(a, b) (strcmp((a), (b)) == 0) | ||
57 | |||
58 | extern void __iomem *clk_mgr_base_addr; | ||
59 | |||
60 | struct socfpga_clk { | ||
61 | struct clk_gate hw; | ||
62 | char *parent_name; | ||
63 | char *clk_name; | ||
64 | u32 fixed_div; | ||
65 | void __iomem *div_reg; | ||
66 | u32 width; /* only valid if div_reg != 0 */ | ||
67 | u32 shift; /* only valid if div_reg != 0 */ | ||
68 | }; | ||
69 | #define to_socfpga_clk(p) container_of(p, struct socfpga_clk, hw.hw) | ||
70 | |||
71 | static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk, | ||
72 | unsigned long parent_rate) | ||
73 | { | ||
74 | struct socfpga_clk *socfpgaclk = to_socfpga_clk(hwclk); | ||
75 | unsigned long divf, divq, vco_freq, reg; | ||
76 | unsigned long bypass; | ||
77 | |||
78 | reg = readl(socfpgaclk->hw.reg); | ||
79 | bypass = readl(clk_mgr_base_addr + CLKMGR_BYPASS); | ||
80 | if (bypass & MAINPLL_BYPASS) | ||
81 | return parent_rate; | ||
82 | |||
83 | divf = (reg & SOCFPGA_PLL_DIVF_MASK) >> SOCFPGA_PLL_DIVF_SHIFT; | ||
84 | divq = (reg & SOCFPGA_PLL_DIVQ_MASK) >> SOCFPGA_PLL_DIVQ_SHIFT; | ||
85 | vco_freq = parent_rate * (divf + 1); | ||
86 | return vco_freq / (1 + divq); | ||
87 | } | ||
88 | |||
89 | |||
90 | static struct clk_ops clk_pll_ops = { | ||
91 | .recalc_rate = clk_pll_recalc_rate, | ||
92 | }; | ||
93 | |||
94 | static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk, | ||
95 | unsigned long parent_rate) | ||
96 | { | ||
97 | struct socfpga_clk *socfpgaclk = to_socfpga_clk(hwclk); | ||
98 | u32 div; | ||
99 | |||
100 | if (socfpgaclk->fixed_div) | ||
101 | div = socfpgaclk->fixed_div; | ||
102 | else | ||
103 | div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1); | ||
104 | |||
105 | return parent_rate / div; | ||
106 | } | ||
107 | |||
108 | static const struct clk_ops periclk_ops = { | ||
109 | .recalc_rate = clk_periclk_recalc_rate, | ||
110 | }; | ||
111 | |||
112 | static __init struct clk *socfpga_clk_init(struct device_node *node, | ||
113 | const struct clk_ops *ops) | ||
114 | { | ||
115 | u32 reg; | ||
116 | struct clk *clk; | ||
117 | struct socfpga_clk *socfpga_clk; | ||
118 | const char *clk_name = node->name; | ||
119 | const char *parent_name; | ||
120 | struct clk_init_data init; | ||
121 | int rc; | ||
122 | u32 fixed_div; | ||
123 | |||
124 | of_property_read_u32(node, "reg", ®); | ||
125 | |||
126 | socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL); | ||
127 | if (WARN_ON(!socfpga_clk)) | ||
128 | return NULL; | ||
129 | |||
130 | socfpga_clk->hw.reg = clk_mgr_base_addr + reg; | ||
131 | |||
132 | rc = of_property_read_u32(node, "fixed-divider", &fixed_div); | ||
133 | if (rc) | ||
134 | socfpga_clk->fixed_div = 0; | ||
135 | else | ||
136 | socfpga_clk->fixed_div = fixed_div; | ||
137 | |||
138 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
139 | |||
140 | init.name = clk_name; | ||
141 | init.ops = ops; | ||
142 | init.flags = 0; | ||
143 | parent_name = of_clk_get_parent_name(node, 0); | ||
144 | init.parent_names = &parent_name; | ||
145 | init.num_parents = 1; | ||
146 | |||
147 | socfpga_clk->hw.hw.init = &init; | ||
148 | |||
149 | if (streq(clk_name, "main_pll") || | ||
150 | streq(clk_name, "periph_pll") || | ||
151 | streq(clk_name, "sdram_pll")) { | ||
152 | socfpga_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA; | ||
153 | clk_pll_ops.enable = clk_gate_ops.enable; | ||
154 | clk_pll_ops.disable = clk_gate_ops.disable; | ||
155 | } | ||
156 | |||
157 | clk = clk_register(NULL, &socfpga_clk->hw.hw); | ||
158 | if (WARN_ON(IS_ERR(clk))) { | ||
159 | kfree(socfpga_clk); | ||
160 | return NULL; | ||
161 | } | ||
162 | rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
163 | return clk; | ||
164 | } | ||
165 | |||
166 | static u8 socfpga_clk_get_parent(struct clk_hw *hwclk) | ||
167 | { | ||
168 | u32 l4_src; | ||
169 | u32 perpll_src; | ||
170 | |||
171 | if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) { | ||
172 | l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
173 | return l4_src &= 0x1; | ||
174 | } | ||
175 | if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) { | ||
176 | l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
177 | return !!(l4_src & 2); | ||
178 | } | ||
179 | |||
180 | perpll_src = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC); | ||
181 | if (streq(hwclk->init->name, SOCFPGA_MMC_CLK)) | ||
182 | return perpll_src &= 0x3; | ||
183 | if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) || | ||
184 | streq(hwclk->init->name, SOCFPGA_NAND_X_CLK)) | ||
185 | return (perpll_src >> 2) & 3; | ||
186 | |||
187 | /* QSPI clock */ | ||
188 | return (perpll_src >> 4) & 3; | ||
189 | |||
190 | } | ||
191 | |||
192 | static int socfpga_clk_set_parent(struct clk_hw *hwclk, u8 parent) | ||
193 | { | ||
194 | u32 src_reg; | ||
195 | |||
196 | if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) { | ||
197 | src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
198 | src_reg &= ~0x1; | ||
199 | src_reg |= parent; | ||
200 | writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC); | ||
201 | } else if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) { | ||
202 | src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC); | ||
203 | src_reg &= ~0x2; | ||
204 | src_reg |= (parent << 1); | ||
205 | writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC); | ||
206 | } else { | ||
207 | src_reg = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC); | ||
208 | if (streq(hwclk->init->name, SOCFPGA_MMC_CLK)) { | ||
209 | src_reg &= ~0x3; | ||
210 | src_reg |= parent; | ||
211 | } else if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) || | ||
212 | streq(hwclk->init->name, SOCFPGA_NAND_X_CLK)) { | ||
213 | src_reg &= ~0xC; | ||
214 | src_reg |= (parent << 2); | ||
215 | } else {/* QSPI clock */ | ||
216 | src_reg &= ~0x30; | ||
217 | src_reg |= (parent << 4); | ||
218 | } | ||
219 | writel(src_reg, clk_mgr_base_addr + CLKMGR_PERPLL_SRC); | ||
220 | } | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk, | ||
226 | unsigned long parent_rate) | ||
227 | { | ||
228 | struct socfpga_clk *socfpgaclk = to_socfpga_clk(hwclk); | ||
229 | u32 div = 1, val; | ||
230 | |||
231 | if (socfpgaclk->fixed_div) | ||
232 | div = socfpgaclk->fixed_div; | ||
233 | else if (socfpgaclk->div_reg) { | ||
234 | val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift; | ||
235 | val &= div_mask(socfpgaclk->width); | ||
236 | if (streq(hwclk->init->name, SOCFPGA_DB_CLK)) | ||
237 | div = val + 1; | ||
238 | else | ||
239 | div = (1 << val); | ||
240 | } | ||
241 | |||
242 | return parent_rate / div; | ||
243 | } | ||
244 | |||
245 | static struct clk_ops gateclk_ops = { | ||
246 | .recalc_rate = socfpga_clk_recalc_rate, | ||
247 | .get_parent = socfpga_clk_get_parent, | ||
248 | .set_parent = socfpga_clk_set_parent, | ||
249 | }; | 36 | }; |
250 | 37 | ||
251 | static void __init socfpga_gate_clk_init(struct device_node *node, | 38 | static void __init socfpga_clkmgr_init(struct device_node *node) |
252 | const struct clk_ops *ops) | ||
253 | { | ||
254 | u32 clk_gate[2]; | ||
255 | u32 div_reg[3]; | ||
256 | u32 fixed_div; | ||
257 | struct clk *clk; | ||
258 | struct socfpga_clk *socfpga_clk; | ||
259 | const char *clk_name = node->name; | ||
260 | const char *parent_name[SOCFGPA_MAX_PARENTS]; | ||
261 | struct clk_init_data init; | ||
262 | int rc; | ||
263 | int i = 0; | ||
264 | |||
265 | socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL); | ||
266 | if (WARN_ON(!socfpga_clk)) | ||
267 | return; | ||
268 | |||
269 | rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2); | ||
270 | if (rc) | ||
271 | clk_gate[0] = 0; | ||
272 | |||
273 | if (clk_gate[0]) { | ||
274 | socfpga_clk->hw.reg = clk_mgr_base_addr + clk_gate[0]; | ||
275 | socfpga_clk->hw.bit_idx = clk_gate[1]; | ||
276 | |||
277 | gateclk_ops.enable = clk_gate_ops.enable; | ||
278 | gateclk_ops.disable = clk_gate_ops.disable; | ||
279 | } | ||
280 | |||
281 | rc = of_property_read_u32(node, "fixed-divider", &fixed_div); | ||
282 | if (rc) | ||
283 | socfpga_clk->fixed_div = 0; | ||
284 | else | ||
285 | socfpga_clk->fixed_div = fixed_div; | ||
286 | |||
287 | rc = of_property_read_u32_array(node, "div-reg", div_reg, 3); | ||
288 | if (!rc) { | ||
289 | socfpga_clk->div_reg = clk_mgr_base_addr + div_reg[0]; | ||
290 | socfpga_clk->shift = div_reg[1]; | ||
291 | socfpga_clk->width = div_reg[2]; | ||
292 | } else { | ||
293 | socfpga_clk->div_reg = NULL; | ||
294 | } | ||
295 | |||
296 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
297 | |||
298 | init.name = clk_name; | ||
299 | init.ops = ops; | ||
300 | init.flags = 0; | ||
301 | while (i < SOCFGPA_MAX_PARENTS && (parent_name[i] = | ||
302 | of_clk_get_parent_name(node, i)) != NULL) | ||
303 | i++; | ||
304 | |||
305 | init.parent_names = parent_name; | ||
306 | init.num_parents = i; | ||
307 | socfpga_clk->hw.hw.init = &init; | ||
308 | |||
309 | clk = clk_register(NULL, &socfpga_clk->hw.hw); | ||
310 | if (WARN_ON(IS_ERR(clk))) { | ||
311 | kfree(socfpga_clk); | ||
312 | return; | ||
313 | } | ||
314 | rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
315 | if (WARN_ON(rc)) | ||
316 | return; | ||
317 | } | ||
318 | |||
319 | static void __init socfpga_pll_init(struct device_node *node) | ||
320 | { | 39 | { |
321 | socfpga_clk_init(node, &clk_pll_ops); | 40 | clk_mgr_base_addr = of_iomap(node, 0); |
41 | of_clk_init(socfpga_child_clocks); | ||
322 | } | 42 | } |
323 | CLK_OF_DECLARE(socfpga_pll, "altr,socfpga-pll-clock", socfpga_pll_init); | 43 | CLK_OF_DECLARE(socfpga_mgr, "altr,clk-mgr", socfpga_clkmgr_init); |
324 | 44 | ||
325 | static void __init socfpga_periph_init(struct device_node *node) | ||
326 | { | ||
327 | socfpga_clk_init(node, &periclk_ops); | ||
328 | } | ||
329 | CLK_OF_DECLARE(socfpga_periph, "altr,socfpga-perip-clk", socfpga_periph_init); | ||
330 | |||
331 | static void __init socfpga_gate_init(struct device_node *node) | ||
332 | { | ||
333 | socfpga_gate_clk_init(node, &gateclk_ops); | ||
334 | } | ||
335 | CLK_OF_DECLARE(socfpga_gate, "altr,socfpga-gate-clk", socfpga_gate_init); | ||
336 | |||
337 | void __init socfpga_init_clocks(void) | ||
338 | { | ||
339 | struct clk *clk; | ||
340 | int ret; | ||
341 | |||
342 | clk = clk_register_fixed_factor(NULL, "smp_twd", "mpuclk", 0, 1, 4); | ||
343 | ret = clk_register_clkdev(clk, NULL, "smp_twd"); | ||
344 | if (ret) | ||
345 | pr_err("smp_twd alias not registered\n"); | ||
346 | } | ||
diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h new file mode 100644 index 000000000000..d2e54019c94f --- /dev/null +++ b/drivers/clk/socfpga/clk.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013, Steffen Trumtrar <s.trumtrar@pengutronix.de> | ||
3 | * | ||
4 | * based on drivers/clk/tegra/clk.h | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __SOCFPGA_CLK_H | ||
18 | #define __SOCFPGA_CLK_H | ||
19 | |||
20 | #include <linux/clk-provider.h> | ||
21 | #include <linux/clkdev.h> | ||
22 | |||
23 | /* Clock Manager offsets */ | ||
24 | #define CLKMGR_CTRL 0x0 | ||
25 | #define CLKMGR_BYPASS 0x4 | ||
26 | #define CLKMGR_L4SRC 0x70 | ||
27 | #define CLKMGR_PERPLL_SRC 0xAC | ||
28 | |||
29 | #define SOCFPGA_MAX_PARENTS 3 | ||
30 | |||
31 | extern void __iomem *clk_mgr_base_addr; | ||
32 | |||
33 | void __init socfpga_pll_init(struct device_node *node); | ||
34 | void __init socfpga_periph_init(struct device_node *node); | ||
35 | void __init socfpga_gate_init(struct device_node *node); | ||
36 | |||
37 | struct socfpga_pll { | ||
38 | struct clk_gate hw; | ||
39 | }; | ||
40 | |||
41 | struct socfpga_gate_clk { | ||
42 | struct clk_gate hw; | ||
43 | char *parent_name; | ||
44 | u32 fixed_div; | ||
45 | void __iomem *div_reg; | ||
46 | u32 width; /* only valid if div_reg != 0 */ | ||
47 | u32 shift; /* only valid if div_reg != 0 */ | ||
48 | u32 clk_phase[2]; | ||
49 | }; | ||
50 | |||
51 | struct socfpga_periph_clk { | ||
52 | struct clk_gate hw; | ||
53 | char *parent_name; | ||
54 | u32 fixed_div; | ||
55 | }; | ||
56 | |||
57 | #endif /* SOCFPGA_CLK_H */ | ||
diff --git a/drivers/clk/st/Makefile b/drivers/clk/st/Makefile new file mode 100644 index 000000000000..c7455ffdbdf7 --- /dev/null +++ b/drivers/clk/st/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-y += clkgen-mux.o clkgen-pll.o clkgen-fsyn.o | |||
diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c new file mode 100644 index 000000000000..4f53ee0778d9 --- /dev/null +++ b/drivers/clk/st/clkgen-fsyn.c | |||
@@ -0,0 +1,1039 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 STMicroelectronics R&D Ltd | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Authors: | ||
12 | * Stephen Gallimore <stephen.gallimore@st.com>, | ||
13 | * Pankaj Dev <pankaj.dev@st.com>. | ||
14 | */ | ||
15 | |||
16 | #include <linux/slab.h> | ||
17 | #include <linux/of_address.h> | ||
18 | #include <linux/clk-provider.h> | ||
19 | |||
20 | #include "clkgen.h" | ||
21 | |||
22 | /* | ||
23 | * Maximum input clock to the PLL before we divide it down by 2 | ||
24 | * although in reality in actual systems this has never been seen to | ||
25 | * be used. | ||
26 | */ | ||
27 | #define QUADFS_NDIV_THRESHOLD 30000000 | ||
28 | |||
29 | #define PLL_BW_GOODREF (0L) | ||
30 | #define PLL_BW_VBADREF (1L) | ||
31 | #define PLL_BW_BADREF (2L) | ||
32 | #define PLL_BW_VGOODREF (3L) | ||
33 | |||
34 | #define QUADFS_MAX_CHAN 4 | ||
35 | |||
36 | struct stm_fs { | ||
37 | unsigned long ndiv; | ||
38 | unsigned long mdiv; | ||
39 | unsigned long pe; | ||
40 | unsigned long sdiv; | ||
41 | unsigned long nsdiv; | ||
42 | }; | ||
43 | |||
44 | static struct stm_fs fs216c65_rtbl[] = { | ||
45 | { .mdiv = 0x1f, .pe = 0x0, .sdiv = 0x7, .nsdiv = 0 }, /* 312.5 Khz */ | ||
46 | { .mdiv = 0x17, .pe = 0x25ed, .sdiv = 0x1, .nsdiv = 0 }, /* 27 MHz */ | ||
47 | { .mdiv = 0x1a, .pe = 0x7b36, .sdiv = 0x2, .nsdiv = 1 }, /* 36.87 MHz */ | ||
48 | { .mdiv = 0x13, .pe = 0x0, .sdiv = 0x2, .nsdiv = 1 }, /* 48 MHz */ | ||
49 | { .mdiv = 0x11, .pe = 0x1c72, .sdiv = 0x1, .nsdiv = 1 }, /* 108 MHz */ | ||
50 | }; | ||
51 | |||
52 | static struct stm_fs fs432c65_rtbl[] = { | ||
53 | { .mdiv = 0x1f, .pe = 0x0, .sdiv = 0x7, .nsdiv = 0 }, /* 625 Khz */ | ||
54 | { .mdiv = 0x11, .pe = 0x1c72, .sdiv = 0x2, .nsdiv = 1 }, /* 108 MHz */ | ||
55 | { .mdiv = 0x19, .pe = 0x121a, .sdiv = 0x0, .nsdiv = 1 }, /* 297 MHz */ | ||
56 | }; | ||
57 | |||
58 | static struct stm_fs fs660c32_rtbl[] = { | ||
59 | { .mdiv = 0x01, .pe = 0x2aaa, .sdiv = 0x8, .nsdiv = 0 }, /* 600 KHz */ | ||
60 | { .mdiv = 0x02, .pe = 0x3d33, .sdiv = 0x0, .nsdiv = 0 }, /* 148.5 Mhz */ | ||
61 | { .mdiv = 0x13, .pe = 0x5bcc, .sdiv = 0x0, .nsdiv = 1 }, /* 297 Mhz */ | ||
62 | { .mdiv = 0x0e, .pe = 0x1025, .sdiv = 0x0, .nsdiv = 1 }, /* 333 Mhz */ | ||
63 | { .mdiv = 0x0b, .pe = 0x715f, .sdiv = 0x0, .nsdiv = 1 }, /* 350 Mhz */ | ||
64 | }; | ||
65 | |||
66 | struct clkgen_quadfs_data { | ||
67 | bool reset_present; | ||
68 | bool bwfilter_present; | ||
69 | bool lockstatus_present; | ||
70 | bool nsdiv_present; | ||
71 | struct clkgen_field ndiv; | ||
72 | struct clkgen_field ref_bw; | ||
73 | struct clkgen_field nreset; | ||
74 | struct clkgen_field npda; | ||
75 | struct clkgen_field lock_status; | ||
76 | |||
77 | struct clkgen_field nsb[QUADFS_MAX_CHAN]; | ||
78 | struct clkgen_field en[QUADFS_MAX_CHAN]; | ||
79 | struct clkgen_field mdiv[QUADFS_MAX_CHAN]; | ||
80 | struct clkgen_field pe[QUADFS_MAX_CHAN]; | ||
81 | struct clkgen_field sdiv[QUADFS_MAX_CHAN]; | ||
82 | struct clkgen_field nsdiv[QUADFS_MAX_CHAN]; | ||
83 | |||
84 | const struct clk_ops *pll_ops; | ||
85 | struct stm_fs *rtbl; | ||
86 | u8 rtbl_cnt; | ||
87 | int (*get_rate)(unsigned long , struct stm_fs *, | ||
88 | unsigned long *); | ||
89 | }; | ||
90 | |||
91 | static const struct clk_ops st_quadfs_pll_c65_ops; | ||
92 | static const struct clk_ops st_quadfs_pll_c32_ops; | ||
93 | static const struct clk_ops st_quadfs_fs216c65_ops; | ||
94 | static const struct clk_ops st_quadfs_fs432c65_ops; | ||
95 | static const struct clk_ops st_quadfs_fs660c32_ops; | ||
96 | |||
97 | static int clk_fs216c65_get_rate(unsigned long, struct stm_fs *, | ||
98 | unsigned long *); | ||
99 | static int clk_fs432c65_get_rate(unsigned long, struct stm_fs *, | ||
100 | unsigned long *); | ||
101 | static int clk_fs660c32_dig_get_rate(unsigned long, struct stm_fs *, | ||
102 | unsigned long *); | ||
103 | /* | ||
104 | * Values for all of the standalone instances of this clock | ||
105 | * generator found in STiH415 and STiH416 SYSCFG register banks. Note | ||
106 | * that the individual channel standby control bits (nsb) are in the | ||
107 | * first register along with the PLL control bits. | ||
108 | */ | ||
109 | static struct clkgen_quadfs_data st_fs216c65_416 = { | ||
110 | /* 416 specific */ | ||
111 | .npda = CLKGEN_FIELD(0x0, 0x1, 14), | ||
112 | .nsb = { CLKGEN_FIELD(0x0, 0x1, 10), | ||
113 | CLKGEN_FIELD(0x0, 0x1, 11), | ||
114 | CLKGEN_FIELD(0x0, 0x1, 12), | ||
115 | CLKGEN_FIELD(0x0, 0x1, 13) }, | ||
116 | .nsdiv_present = true, | ||
117 | .nsdiv = { CLKGEN_FIELD(0x0, 0x1, 18), | ||
118 | CLKGEN_FIELD(0x0, 0x1, 19), | ||
119 | CLKGEN_FIELD(0x0, 0x1, 20), | ||
120 | CLKGEN_FIELD(0x0, 0x1, 21) }, | ||
121 | .mdiv = { CLKGEN_FIELD(0x4, 0x1f, 0), | ||
122 | CLKGEN_FIELD(0x14, 0x1f, 0), | ||
123 | CLKGEN_FIELD(0x24, 0x1f, 0), | ||
124 | CLKGEN_FIELD(0x34, 0x1f, 0) }, | ||
125 | .en = { CLKGEN_FIELD(0x10, 0x1, 0), | ||
126 | CLKGEN_FIELD(0x20, 0x1, 0), | ||
127 | CLKGEN_FIELD(0x30, 0x1, 0), | ||
128 | CLKGEN_FIELD(0x40, 0x1, 0) }, | ||
129 | .ndiv = CLKGEN_FIELD(0x0, 0x1, 15), | ||
130 | .bwfilter_present = true, | ||
131 | .ref_bw = CLKGEN_FIELD(0x0, 0x3, 16), | ||
132 | .pe = { CLKGEN_FIELD(0x8, 0xffff, 0), | ||
133 | CLKGEN_FIELD(0x18, 0xffff, 0), | ||
134 | CLKGEN_FIELD(0x28, 0xffff, 0), | ||
135 | CLKGEN_FIELD(0x38, 0xffff, 0) }, | ||
136 | .sdiv = { CLKGEN_FIELD(0xC, 0x7, 0), | ||
137 | CLKGEN_FIELD(0x1C, 0x7, 0), | ||
138 | CLKGEN_FIELD(0x2C, 0x7, 0), | ||
139 | CLKGEN_FIELD(0x3C, 0x7, 0) }, | ||
140 | .pll_ops = &st_quadfs_pll_c65_ops, | ||
141 | .rtbl = fs216c65_rtbl, | ||
142 | .rtbl_cnt = ARRAY_SIZE(fs216c65_rtbl), | ||
143 | .get_rate = clk_fs216c65_get_rate, | ||
144 | }; | ||
145 | |||
146 | static struct clkgen_quadfs_data st_fs432c65_416 = { | ||
147 | .npda = CLKGEN_FIELD(0x0, 0x1, 14), | ||
148 | .nsb = { CLKGEN_FIELD(0x0, 0x1, 10), | ||
149 | CLKGEN_FIELD(0x0, 0x1, 11), | ||
150 | CLKGEN_FIELD(0x0, 0x1, 12), | ||
151 | CLKGEN_FIELD(0x0, 0x1, 13) }, | ||
152 | .nsdiv_present = true, | ||
153 | .nsdiv = { CLKGEN_FIELD(0x0, 0x1, 18), | ||
154 | CLKGEN_FIELD(0x0, 0x1, 19), | ||
155 | CLKGEN_FIELD(0x0, 0x1, 20), | ||
156 | CLKGEN_FIELD(0x0, 0x1, 21) }, | ||
157 | .mdiv = { CLKGEN_FIELD(0x4, 0x1f, 0), | ||
158 | CLKGEN_FIELD(0x14, 0x1f, 0), | ||
159 | CLKGEN_FIELD(0x24, 0x1f, 0), | ||
160 | CLKGEN_FIELD(0x34, 0x1f, 0) }, | ||
161 | .en = { CLKGEN_FIELD(0x10, 0x1, 0), | ||
162 | CLKGEN_FIELD(0x20, 0x1, 0), | ||
163 | CLKGEN_FIELD(0x30, 0x1, 0), | ||
164 | CLKGEN_FIELD(0x40, 0x1, 0) }, | ||
165 | .ndiv = CLKGEN_FIELD(0x0, 0x1, 15), | ||
166 | .bwfilter_present = true, | ||
167 | .ref_bw = CLKGEN_FIELD(0x0, 0x3, 16), | ||
168 | .pe = { CLKGEN_FIELD(0x8, 0xffff, 0), | ||
169 | CLKGEN_FIELD(0x18, 0xffff, 0), | ||
170 | CLKGEN_FIELD(0x28, 0xffff, 0), | ||
171 | CLKGEN_FIELD(0x38, 0xffff, 0) }, | ||
172 | .sdiv = { CLKGEN_FIELD(0xC, 0x7, 0), | ||
173 | CLKGEN_FIELD(0x1C, 0x7, 0), | ||
174 | CLKGEN_FIELD(0x2C, 0x7, 0), | ||
175 | CLKGEN_FIELD(0x3C, 0x7, 0) }, | ||
176 | .pll_ops = &st_quadfs_pll_c65_ops, | ||
177 | .rtbl = fs432c65_rtbl, | ||
178 | .rtbl_cnt = ARRAY_SIZE(fs432c65_rtbl), | ||
179 | .get_rate = clk_fs432c65_get_rate, | ||
180 | }; | ||
181 | |||
182 | static struct clkgen_quadfs_data st_fs660c32_E_416 = { | ||
183 | .npda = CLKGEN_FIELD(0x0, 0x1, 14), | ||
184 | .nsb = { CLKGEN_FIELD(0x0, 0x1, 10), | ||
185 | CLKGEN_FIELD(0x0, 0x1, 11), | ||
186 | CLKGEN_FIELD(0x0, 0x1, 12), | ||
187 | CLKGEN_FIELD(0x0, 0x1, 13) }, | ||
188 | .nsdiv_present = true, | ||
189 | .nsdiv = { CLKGEN_FIELD(0x0, 0x1, 18), | ||
190 | CLKGEN_FIELD(0x0, 0x1, 19), | ||
191 | CLKGEN_FIELD(0x0, 0x1, 20), | ||
192 | CLKGEN_FIELD(0x0, 0x1, 21) }, | ||
193 | .mdiv = { CLKGEN_FIELD(0x4, 0x1f, 0), | ||
194 | CLKGEN_FIELD(0x14, 0x1f, 0), | ||
195 | CLKGEN_FIELD(0x24, 0x1f, 0), | ||
196 | CLKGEN_FIELD(0x34, 0x1f, 0) }, | ||
197 | .en = { CLKGEN_FIELD(0x10, 0x1, 0), | ||
198 | CLKGEN_FIELD(0x20, 0x1, 0), | ||
199 | CLKGEN_FIELD(0x30, 0x1, 0), | ||
200 | CLKGEN_FIELD(0x40, 0x1, 0) }, | ||
201 | .ndiv = CLKGEN_FIELD(0x0, 0x7, 15), | ||
202 | .pe = { CLKGEN_FIELD(0x8, 0x7fff, 0), | ||
203 | CLKGEN_FIELD(0x18, 0x7fff, 0), | ||
204 | CLKGEN_FIELD(0x28, 0x7fff, 0), | ||
205 | CLKGEN_FIELD(0x38, 0x7fff, 0) }, | ||
206 | .sdiv = { CLKGEN_FIELD(0xC, 0xf, 0), | ||
207 | CLKGEN_FIELD(0x1C, 0xf, 0), | ||
208 | CLKGEN_FIELD(0x2C, 0xf, 0), | ||
209 | CLKGEN_FIELD(0x3C, 0xf, 0) }, | ||
210 | .lockstatus_present = true, | ||
211 | .lock_status = CLKGEN_FIELD(0xAC, 0x1, 0), | ||
212 | .pll_ops = &st_quadfs_pll_c32_ops, | ||
213 | .rtbl = fs660c32_rtbl, | ||
214 | .rtbl_cnt = ARRAY_SIZE(fs660c32_rtbl), | ||
215 | .get_rate = clk_fs660c32_dig_get_rate, | ||
216 | }; | ||
217 | |||
218 | static struct clkgen_quadfs_data st_fs660c32_F_416 = { | ||
219 | .npda = CLKGEN_FIELD(0x0, 0x1, 14), | ||
220 | .nsb = { CLKGEN_FIELD(0x0, 0x1, 10), | ||
221 | CLKGEN_FIELD(0x0, 0x1, 11), | ||
222 | CLKGEN_FIELD(0x0, 0x1, 12), | ||
223 | CLKGEN_FIELD(0x0, 0x1, 13) }, | ||
224 | .nsdiv_present = true, | ||
225 | .nsdiv = { CLKGEN_FIELD(0x0, 0x1, 18), | ||
226 | CLKGEN_FIELD(0x0, 0x1, 19), | ||
227 | CLKGEN_FIELD(0x0, 0x1, 20), | ||
228 | CLKGEN_FIELD(0x0, 0x1, 21) }, | ||
229 | .mdiv = { CLKGEN_FIELD(0x4, 0x1f, 0), | ||
230 | CLKGEN_FIELD(0x14, 0x1f, 0), | ||
231 | CLKGEN_FIELD(0x24, 0x1f, 0), | ||
232 | CLKGEN_FIELD(0x34, 0x1f, 0) }, | ||
233 | .en = { CLKGEN_FIELD(0x10, 0x1, 0), | ||
234 | CLKGEN_FIELD(0x20, 0x1, 0), | ||
235 | CLKGEN_FIELD(0x30, 0x1, 0), | ||
236 | CLKGEN_FIELD(0x40, 0x1, 0) }, | ||
237 | .ndiv = CLKGEN_FIELD(0x0, 0x7, 15), | ||
238 | .pe = { CLKGEN_FIELD(0x8, 0x7fff, 0), | ||
239 | CLKGEN_FIELD(0x18, 0x7fff, 0), | ||
240 | CLKGEN_FIELD(0x28, 0x7fff, 0), | ||
241 | CLKGEN_FIELD(0x38, 0x7fff, 0) }, | ||
242 | .sdiv = { CLKGEN_FIELD(0xC, 0xf, 0), | ||
243 | CLKGEN_FIELD(0x1C, 0xf, 0), | ||
244 | CLKGEN_FIELD(0x2C, 0xf, 0), | ||
245 | CLKGEN_FIELD(0x3C, 0xf, 0) }, | ||
246 | .lockstatus_present = true, | ||
247 | .lock_status = CLKGEN_FIELD(0xEC, 0x1, 0), | ||
248 | .pll_ops = &st_quadfs_pll_c32_ops, | ||
249 | .rtbl = fs660c32_rtbl, | ||
250 | .rtbl_cnt = ARRAY_SIZE(fs660c32_rtbl), | ||
251 | .get_rate = clk_fs660c32_dig_get_rate, | ||
252 | }; | ||
253 | |||
254 | /** | ||
255 | * DOC: A Frequency Synthesizer that multiples its input clock by a fixed factor | ||
256 | * | ||
257 | * Traits of this clock: | ||
258 | * prepare - clk_(un)prepare only ensures parent is (un)prepared | ||
259 | * enable - clk_enable and clk_disable are functional & control the Fsyn | ||
260 | * rate - inherits rate from parent. set_rate/round_rate/recalc_rate | ||
261 | * parent - fixed parent. No clk_set_parent support | ||
262 | */ | ||
263 | |||
264 | /** | ||
265 | * struct st_clk_quadfs_pll - A pll which outputs a fixed multiplier of | ||
266 | * its parent clock, found inside a type of | ||
267 | * ST quad channel frequency synthesizer block | ||
268 | * | ||
269 | * @hw: handle between common and hardware-specific interfaces. | ||
270 | * @ndiv: regmap field for the ndiv control. | ||
271 | * @regs_base: base address of the configuration registers. | ||
272 | * @lock: spinlock. | ||
273 | * | ||
274 | */ | ||
275 | struct st_clk_quadfs_pll { | ||
276 | struct clk_hw hw; | ||
277 | void __iomem *regs_base; | ||
278 | spinlock_t *lock; | ||
279 | struct clkgen_quadfs_data *data; | ||
280 | u32 ndiv; | ||
281 | }; | ||
282 | |||
283 | #define to_quadfs_pll(_hw) container_of(_hw, struct st_clk_quadfs_pll, hw) | ||
284 | |||
285 | static int quadfs_pll_enable(struct clk_hw *hw) | ||
286 | { | ||
287 | struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw); | ||
288 | unsigned long flags = 0, timeout = jiffies + msecs_to_jiffies(10); | ||
289 | |||
290 | if (pll->lock) | ||
291 | spin_lock_irqsave(pll->lock, flags); | ||
292 | |||
293 | /* | ||
294 | * Bring block out of reset if we have reset control. | ||
295 | */ | ||
296 | if (pll->data->reset_present) | ||
297 | CLKGEN_WRITE(pll, nreset, 1); | ||
298 | |||
299 | /* | ||
300 | * Use a fixed input clock noise bandwidth filter for the moment | ||
301 | */ | ||
302 | if (pll->data->bwfilter_present) | ||
303 | CLKGEN_WRITE(pll, ref_bw, PLL_BW_GOODREF); | ||
304 | |||
305 | |||
306 | CLKGEN_WRITE(pll, ndiv, pll->ndiv); | ||
307 | |||
308 | /* | ||
309 | * Power up the PLL | ||
310 | */ | ||
311 | CLKGEN_WRITE(pll, npda, 1); | ||
312 | |||
313 | if (pll->lock) | ||
314 | spin_unlock_irqrestore(pll->lock, flags); | ||
315 | |||
316 | if (pll->data->lockstatus_present) | ||
317 | while (!CLKGEN_READ(pll, lock_status)) { | ||
318 | if (time_after(jiffies, timeout)) | ||
319 | return -ETIMEDOUT; | ||
320 | cpu_relax(); | ||
321 | } | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | static void quadfs_pll_disable(struct clk_hw *hw) | ||
327 | { | ||
328 | struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw); | ||
329 | unsigned long flags = 0; | ||
330 | |||
331 | if (pll->lock) | ||
332 | spin_lock_irqsave(pll->lock, flags); | ||
333 | |||
334 | /* | ||
335 | * Powerdown the PLL and then put block into soft reset if we have | ||
336 | * reset control. | ||
337 | */ | ||
338 | CLKGEN_WRITE(pll, npda, 0); | ||
339 | |||
340 | if (pll->data->reset_present) | ||
341 | CLKGEN_WRITE(pll, nreset, 0); | ||
342 | |||
343 | if (pll->lock) | ||
344 | spin_unlock_irqrestore(pll->lock, flags); | ||
345 | } | ||
346 | |||
347 | static int quadfs_pll_is_enabled(struct clk_hw *hw) | ||
348 | { | ||
349 | struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw); | ||
350 | u32 npda = CLKGEN_READ(pll, npda); | ||
351 | |||
352 | return !!npda; | ||
353 | } | ||
354 | |||
355 | int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs, | ||
356 | unsigned long *rate) | ||
357 | { | ||
358 | unsigned long nd = fs->ndiv + 16; /* ndiv value */ | ||
359 | |||
360 | *rate = input * nd; | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static unsigned long quadfs_pll_fs660c32_recalc_rate(struct clk_hw *hw, | ||
366 | unsigned long parent_rate) | ||
367 | { | ||
368 | struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw); | ||
369 | unsigned long rate = 0; | ||
370 | struct stm_fs params; | ||
371 | |||
372 | params.ndiv = CLKGEN_READ(pll, ndiv); | ||
373 | if (clk_fs660c32_vco_get_rate(parent_rate, ¶ms, &rate)) | ||
374 | pr_err("%s:%s error calculating rate\n", | ||
375 | __clk_get_name(hw->clk), __func__); | ||
376 | |||
377 | pll->ndiv = params.ndiv; | ||
378 | |||
379 | return rate; | ||
380 | } | ||
381 | |||
382 | int clk_fs660c32_vco_get_params(unsigned long input, | ||
383 | unsigned long output, struct stm_fs *fs) | ||
384 | { | ||
385 | /* Formula | ||
386 | VCO frequency = (fin x ndiv) / pdiv | ||
387 | ndiv = VCOfreq * pdiv / fin | ||
388 | */ | ||
389 | unsigned long pdiv = 1, n; | ||
390 | |||
391 | /* Output clock range: 384Mhz to 660Mhz */ | ||
392 | if (output < 384000000 || output > 660000000) | ||
393 | return -EINVAL; | ||
394 | |||
395 | if (input > 40000000) | ||
396 | /* This means that PDIV would be 2 instead of 1. | ||
397 | Not supported today. */ | ||
398 | return -EINVAL; | ||
399 | |||
400 | input /= 1000; | ||
401 | output /= 1000; | ||
402 | |||
403 | n = output * pdiv / input; | ||
404 | if (n < 16) | ||
405 | n = 16; | ||
406 | fs->ndiv = n - 16; /* Converting formula value to reg value */ | ||
407 | |||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | static long quadfs_pll_fs660c32_round_rate(struct clk_hw *hw, unsigned long rate | ||
412 | , unsigned long *prate) | ||
413 | { | ||
414 | struct stm_fs params; | ||
415 | |||
416 | if (!clk_fs660c32_vco_get_params(*prate, rate, ¶ms)) | ||
417 | clk_fs660c32_vco_get_rate(*prate, ¶ms, &rate); | ||
418 | |||
419 | pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n", | ||
420 | __func__, __clk_get_name(hw->clk), | ||
421 | rate, (unsigned int)params.sdiv, | ||
422 | (unsigned int)params.mdiv, | ||
423 | (unsigned int)params.pe, (unsigned int)params.nsdiv); | ||
424 | |||
425 | return rate; | ||
426 | } | ||
427 | |||
428 | static int quadfs_pll_fs660c32_set_rate(struct clk_hw *hw, unsigned long rate, | ||
429 | unsigned long parent_rate) | ||
430 | { | ||
431 | struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw); | ||
432 | struct stm_fs params; | ||
433 | long hwrate = 0; | ||
434 | unsigned long flags = 0; | ||
435 | |||
436 | if (!rate || !parent_rate) | ||
437 | return -EINVAL; | ||
438 | |||
439 | if (!clk_fs660c32_vco_get_params(parent_rate, rate, ¶ms)) | ||
440 | clk_fs660c32_vco_get_rate(parent_rate, ¶ms, &hwrate); | ||
441 | |||
442 | pr_debug("%s: %s new rate %ld [ndiv=0x%x]\n", | ||
443 | __func__, __clk_get_name(hw->clk), | ||
444 | hwrate, (unsigned int)params.ndiv); | ||
445 | |||
446 | if (!hwrate) | ||
447 | return -EINVAL; | ||
448 | |||
449 | pll->ndiv = params.ndiv; | ||
450 | |||
451 | if (pll->lock) | ||
452 | spin_lock_irqsave(pll->lock, flags); | ||
453 | |||
454 | CLKGEN_WRITE(pll, ndiv, pll->ndiv); | ||
455 | |||
456 | if (pll->lock) | ||
457 | spin_unlock_irqrestore(pll->lock, flags); | ||
458 | |||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | static const struct clk_ops st_quadfs_pll_c65_ops = { | ||
463 | .enable = quadfs_pll_enable, | ||
464 | .disable = quadfs_pll_disable, | ||
465 | .is_enabled = quadfs_pll_is_enabled, | ||
466 | }; | ||
467 | |||
468 | static const struct clk_ops st_quadfs_pll_c32_ops = { | ||
469 | .enable = quadfs_pll_enable, | ||
470 | .disable = quadfs_pll_disable, | ||
471 | .is_enabled = quadfs_pll_is_enabled, | ||
472 | .recalc_rate = quadfs_pll_fs660c32_recalc_rate, | ||
473 | .round_rate = quadfs_pll_fs660c32_round_rate, | ||
474 | .set_rate = quadfs_pll_fs660c32_set_rate, | ||
475 | }; | ||
476 | |||
477 | static struct clk * __init st_clk_register_quadfs_pll( | ||
478 | const char *name, const char *parent_name, | ||
479 | struct clkgen_quadfs_data *quadfs, void __iomem *reg, | ||
480 | spinlock_t *lock) | ||
481 | { | ||
482 | struct st_clk_quadfs_pll *pll; | ||
483 | struct clk *clk; | ||
484 | struct clk_init_data init; | ||
485 | |||
486 | /* | ||
487 | * Sanity check required pointers. | ||
488 | */ | ||
489 | if (WARN_ON(!name || !parent_name)) | ||
490 | return ERR_PTR(-EINVAL); | ||
491 | |||
492 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | ||
493 | if (!pll) | ||
494 | return ERR_PTR(-ENOMEM); | ||
495 | |||
496 | init.name = name; | ||
497 | init.ops = quadfs->pll_ops; | ||
498 | init.flags = CLK_IS_BASIC; | ||
499 | init.parent_names = &parent_name; | ||
500 | init.num_parents = 1; | ||
501 | |||
502 | pll->data = quadfs; | ||
503 | pll->regs_base = reg; | ||
504 | pll->lock = lock; | ||
505 | pll->hw.init = &init; | ||
506 | |||
507 | clk = clk_register(NULL, &pll->hw); | ||
508 | |||
509 | if (IS_ERR(clk)) | ||
510 | kfree(pll); | ||
511 | |||
512 | return clk; | ||
513 | } | ||
514 | |||
515 | /** | ||
516 | * DOC: A digital frequency synthesizer | ||
517 | * | ||
518 | * Traits of this clock: | ||
519 | * prepare - clk_(un)prepare only ensures parent is (un)prepared | ||
520 | * enable - clk_enable and clk_disable are functional | ||
521 | * rate - set rate is functional | ||
522 | * parent - fixed parent. No clk_set_parent support | ||
523 | */ | ||
524 | |||
525 | /** | ||
526 | * struct st_clk_quadfs_fsynth - One clock output from a four channel digital | ||
527 | * frequency synthesizer (fsynth) block. | ||
528 | * | ||
529 | * @hw: handle between common and hardware-specific interfaces | ||
530 | * | ||
531 | * @nsb: regmap field in the output control register for the digital | ||
532 | * standby of this fsynth channel. This control is active low so | ||
533 | * the channel is in standby when the control bit is cleared. | ||
534 | * | ||
535 | * @nsdiv: regmap field in the output control register for | ||
536 | * for the optional divide by 3 of this fsynth channel. This control | ||
537 | * is active low so the divide by 3 is active when the control bit is | ||
538 | * cleared and the divide is bypassed when the bit is set. | ||
539 | */ | ||
540 | struct st_clk_quadfs_fsynth { | ||
541 | struct clk_hw hw; | ||
542 | void __iomem *regs_base; | ||
543 | spinlock_t *lock; | ||
544 | struct clkgen_quadfs_data *data; | ||
545 | |||
546 | u32 chan; | ||
547 | /* | ||
548 | * Cached hardware values from set_rate so we can program the | ||
549 | * hardware in enable. There are two reasons for this: | ||
550 | * | ||
551 | * 1. The registers may not be writable until the parent has been | ||
552 | * enabled. | ||
553 | * | ||
554 | * 2. It restores the clock rate when a driver does an enable | ||
555 | * on PM restore, after a suspend to RAM has lost the hardware | ||
556 | * setup. | ||
557 | */ | ||
558 | u32 md; | ||
559 | u32 pe; | ||
560 | u32 sdiv; | ||
561 | u32 nsdiv; | ||
562 | }; | ||
563 | |||
564 | #define to_quadfs_fsynth(_hw) \ | ||
565 | container_of(_hw, struct st_clk_quadfs_fsynth, hw) | ||
566 | |||
567 | static void quadfs_fsynth_program_enable(struct st_clk_quadfs_fsynth *fs) | ||
568 | { | ||
569 | /* | ||
570 | * Pulse the program enable register lsb to make the hardware take | ||
571 | * notice of the new md/pe values with a glitchless transition. | ||
572 | */ | ||
573 | CLKGEN_WRITE(fs, en[fs->chan], 1); | ||
574 | CLKGEN_WRITE(fs, en[fs->chan], 0); | ||
575 | } | ||
576 | |||
577 | static void quadfs_fsynth_program_rate(struct st_clk_quadfs_fsynth *fs) | ||
578 | { | ||
579 | unsigned long flags = 0; | ||
580 | |||
581 | /* | ||
582 | * Ensure the md/pe parameters are ignored while we are | ||
583 | * reprogramming them so we can get a glitchless change | ||
584 | * when fine tuning the speed of a running clock. | ||
585 | */ | ||
586 | CLKGEN_WRITE(fs, en[fs->chan], 0); | ||
587 | |||
588 | CLKGEN_WRITE(fs, mdiv[fs->chan], fs->md); | ||
589 | CLKGEN_WRITE(fs, pe[fs->chan], fs->pe); | ||
590 | CLKGEN_WRITE(fs, sdiv[fs->chan], fs->sdiv); | ||
591 | |||
592 | if (fs->lock) | ||
593 | spin_lock_irqsave(fs->lock, flags); | ||
594 | |||
595 | if (fs->data->nsdiv_present) | ||
596 | CLKGEN_WRITE(fs, nsdiv[fs->chan], fs->nsdiv); | ||
597 | |||
598 | if (fs->lock) | ||
599 | spin_unlock_irqrestore(fs->lock, flags); | ||
600 | } | ||
601 | |||
602 | static int quadfs_fsynth_enable(struct clk_hw *hw) | ||
603 | { | ||
604 | struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw); | ||
605 | unsigned long flags = 0; | ||
606 | |||
607 | pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk)); | ||
608 | |||
609 | quadfs_fsynth_program_rate(fs); | ||
610 | |||
611 | if (fs->lock) | ||
612 | spin_lock_irqsave(fs->lock, flags); | ||
613 | |||
614 | CLKGEN_WRITE(fs, nsb[fs->chan], 1); | ||
615 | |||
616 | if (fs->lock) | ||
617 | spin_unlock_irqrestore(fs->lock, flags); | ||
618 | |||
619 | quadfs_fsynth_program_enable(fs); | ||
620 | |||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | static void quadfs_fsynth_disable(struct clk_hw *hw) | ||
625 | { | ||
626 | struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw); | ||
627 | unsigned long flags = 0; | ||
628 | |||
629 | pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk)); | ||
630 | |||
631 | if (fs->lock) | ||
632 | spin_lock_irqsave(fs->lock, flags); | ||
633 | |||
634 | CLKGEN_WRITE(fs, nsb[fs->chan], 0); | ||
635 | |||
636 | if (fs->lock) | ||
637 | spin_unlock_irqrestore(fs->lock, flags); | ||
638 | } | ||
639 | |||
640 | static int quadfs_fsynth_is_enabled(struct clk_hw *hw) | ||
641 | { | ||
642 | struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw); | ||
643 | u32 nsb = CLKGEN_READ(fs, nsb[fs->chan]); | ||
644 | |||
645 | pr_debug("%s: %s enable bit = 0x%x\n", | ||
646 | __func__, __clk_get_name(hw->clk), nsb); | ||
647 | |||
648 | return !!nsb; | ||
649 | } | ||
650 | |||
651 | #define P15 (uint64_t)(1 << 15) | ||
652 | |||
653 | static int clk_fs216c65_get_rate(unsigned long input, struct stm_fs *fs, | ||
654 | unsigned long *rate) | ||
655 | { | ||
656 | uint64_t res; | ||
657 | unsigned long ns; | ||
658 | unsigned long nd = 8; /* ndiv stuck at 0 => val = 8 */ | ||
659 | unsigned long s; | ||
660 | long m; | ||
661 | |||
662 | m = fs->mdiv - 32; | ||
663 | s = 1 << (fs->sdiv + 1); | ||
664 | ns = (fs->nsdiv ? 1 : 3); | ||
665 | |||
666 | res = (uint64_t)(s * ns * P15 * (uint64_t)(m + 33)); | ||
667 | res = res - (s * ns * fs->pe); | ||
668 | *rate = div64_u64(P15 * nd * input * 32, res); | ||
669 | |||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | static int clk_fs432c65_get_rate(unsigned long input, struct stm_fs *fs, | ||
674 | unsigned long *rate) | ||
675 | { | ||
676 | uint64_t res; | ||
677 | unsigned long nd = 16; /* ndiv value; stuck at 0 (30Mhz input) */ | ||
678 | long m; | ||
679 | unsigned long sd; | ||
680 | unsigned long ns; | ||
681 | |||
682 | m = fs->mdiv - 32; | ||
683 | sd = 1 << (fs->sdiv + 1); | ||
684 | ns = (fs->nsdiv ? 1 : 3); | ||
685 | |||
686 | res = (uint64_t)(sd * ns * P15 * (uint64_t)(m + 33)); | ||
687 | res = res - (sd * ns * fs->pe); | ||
688 | *rate = div64_u64(P15 * nd * input * 32, res); | ||
689 | |||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | #define P20 (uint64_t)(1 << 20) | ||
694 | |||
695 | static int clk_fs660c32_dig_get_rate(unsigned long input, | ||
696 | struct stm_fs *fs, unsigned long *rate) | ||
697 | { | ||
698 | unsigned long s = (1 << fs->sdiv); | ||
699 | unsigned long ns; | ||
700 | uint64_t res; | ||
701 | |||
702 | /* | ||
703 | * 'nsdiv' is a register value ('BIN') which is translated | ||
704 | * to a decimal value according to following rules. | ||
705 | * | ||
706 | * nsdiv ns.dec | ||
707 | * 0 3 | ||
708 | * 1 1 | ||
709 | */ | ||
710 | ns = (fs->nsdiv == 1) ? 1 : 3; | ||
711 | |||
712 | res = (P20 * (32 + fs->mdiv) + 32 * fs->pe) * s * ns; | ||
713 | *rate = (unsigned long)div64_u64(input * P20 * 32, res); | ||
714 | |||
715 | return 0; | ||
716 | } | ||
717 | |||
718 | static int quadfs_fsynt_get_hw_value_for_recalc(struct st_clk_quadfs_fsynth *fs, | ||
719 | struct stm_fs *params) | ||
720 | { | ||
721 | /* | ||
722 | * Get the initial hardware values for recalc_rate | ||
723 | */ | ||
724 | params->mdiv = CLKGEN_READ(fs, mdiv[fs->chan]); | ||
725 | params->pe = CLKGEN_READ(fs, pe[fs->chan]); | ||
726 | params->sdiv = CLKGEN_READ(fs, sdiv[fs->chan]); | ||
727 | |||
728 | if (fs->data->nsdiv_present) | ||
729 | params->nsdiv = CLKGEN_READ(fs, nsdiv[fs->chan]); | ||
730 | else | ||
731 | params->nsdiv = 1; | ||
732 | |||
733 | /* | ||
734 | * If All are NULL then assume no clock rate is programmed. | ||
735 | */ | ||
736 | if (!params->mdiv && !params->pe && !params->sdiv) | ||
737 | return 1; | ||
738 | |||
739 | fs->md = params->mdiv; | ||
740 | fs->pe = params->pe; | ||
741 | fs->sdiv = params->sdiv; | ||
742 | fs->nsdiv = params->nsdiv; | ||
743 | |||
744 | return 0; | ||
745 | } | ||
746 | |||
747 | static long quadfs_find_best_rate(struct clk_hw *hw, unsigned long drate, | ||
748 | unsigned long prate, struct stm_fs *params) | ||
749 | { | ||
750 | struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw); | ||
751 | int (*clk_fs_get_rate)(unsigned long , | ||
752 | struct stm_fs *, unsigned long *); | ||
753 | struct stm_fs prev_params; | ||
754 | unsigned long prev_rate, rate = 0; | ||
755 | unsigned long diff_rate, prev_diff_rate = ~0; | ||
756 | int index; | ||
757 | |||
758 | clk_fs_get_rate = fs->data->get_rate; | ||
759 | |||
760 | for (index = 0; index < fs->data->rtbl_cnt; index++) { | ||
761 | prev_rate = rate; | ||
762 | |||
763 | *params = fs->data->rtbl[index]; | ||
764 | prev_params = *params; | ||
765 | |||
766 | clk_fs_get_rate(prate, &fs->data->rtbl[index], &rate); | ||
767 | |||
768 | diff_rate = abs(drate - rate); | ||
769 | |||
770 | if (diff_rate > prev_diff_rate) { | ||
771 | rate = prev_rate; | ||
772 | *params = prev_params; | ||
773 | break; | ||
774 | } | ||
775 | |||
776 | prev_diff_rate = diff_rate; | ||
777 | |||
778 | if (drate == rate) | ||
779 | return rate; | ||
780 | } | ||
781 | |||
782 | |||
783 | if (index == fs->data->rtbl_cnt) | ||
784 | *params = prev_params; | ||
785 | |||
786 | return rate; | ||
787 | } | ||
788 | |||
789 | static unsigned long quadfs_recalc_rate(struct clk_hw *hw, | ||
790 | unsigned long parent_rate) | ||
791 | { | ||
792 | struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw); | ||
793 | unsigned long rate = 0; | ||
794 | struct stm_fs params; | ||
795 | int (*clk_fs_get_rate)(unsigned long , | ||
796 | struct stm_fs *, unsigned long *); | ||
797 | |||
798 | clk_fs_get_rate = fs->data->get_rate; | ||
799 | |||
800 | if (quadfs_fsynt_get_hw_value_for_recalc(fs, ¶ms)) | ||
801 | return 0; | ||
802 | |||
803 | if (clk_fs_get_rate(parent_rate, ¶ms, &rate)) { | ||
804 | pr_err("%s:%s error calculating rate\n", | ||
805 | __clk_get_name(hw->clk), __func__); | ||
806 | } | ||
807 | |||
808 | pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate); | ||
809 | |||
810 | return rate; | ||
811 | } | ||
812 | |||
813 | static long quadfs_round_rate(struct clk_hw *hw, unsigned long rate, | ||
814 | unsigned long *prate) | ||
815 | { | ||
816 | struct stm_fs params; | ||
817 | |||
818 | rate = quadfs_find_best_rate(hw, rate, *prate, ¶ms); | ||
819 | |||
820 | pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n", | ||
821 | __func__, __clk_get_name(hw->clk), | ||
822 | rate, (unsigned int)params.sdiv, (unsigned int)params.mdiv, | ||
823 | (unsigned int)params.pe, (unsigned int)params.nsdiv); | ||
824 | |||
825 | return rate; | ||
826 | } | ||
827 | |||
828 | |||
829 | static void quadfs_program_and_enable(struct st_clk_quadfs_fsynth *fs, | ||
830 | struct stm_fs *params) | ||
831 | { | ||
832 | fs->md = params->mdiv; | ||
833 | fs->pe = params->pe; | ||
834 | fs->sdiv = params->sdiv; | ||
835 | fs->nsdiv = params->nsdiv; | ||
836 | |||
837 | /* | ||
838 | * In some integrations you can only change the fsynth programming when | ||
839 | * the parent entity containing it is enabled. | ||
840 | */ | ||
841 | quadfs_fsynth_program_rate(fs); | ||
842 | quadfs_fsynth_program_enable(fs); | ||
843 | } | ||
844 | |||
845 | static int quadfs_set_rate(struct clk_hw *hw, unsigned long rate, | ||
846 | unsigned long parent_rate) | ||
847 | { | ||
848 | struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw); | ||
849 | struct stm_fs params; | ||
850 | long hwrate; | ||
851 | int uninitialized_var(i); | ||
852 | |||
853 | if (!rate || !parent_rate) | ||
854 | return -EINVAL; | ||
855 | |||
856 | memset(¶ms, 0, sizeof(struct stm_fs)); | ||
857 | |||
858 | hwrate = quadfs_find_best_rate(hw, rate, parent_rate, ¶ms); | ||
859 | if (!hwrate) | ||
860 | return -EINVAL; | ||
861 | |||
862 | quadfs_program_and_enable(fs, ¶ms); | ||
863 | |||
864 | return 0; | ||
865 | } | ||
866 | |||
867 | |||
868 | |||
869 | static const struct clk_ops st_quadfs_ops = { | ||
870 | .enable = quadfs_fsynth_enable, | ||
871 | .disable = quadfs_fsynth_disable, | ||
872 | .is_enabled = quadfs_fsynth_is_enabled, | ||
873 | .round_rate = quadfs_round_rate, | ||
874 | .set_rate = quadfs_set_rate, | ||
875 | .recalc_rate = quadfs_recalc_rate, | ||
876 | }; | ||
877 | |||
878 | static struct clk * __init st_clk_register_quadfs_fsynth( | ||
879 | const char *name, const char *parent_name, | ||
880 | struct clkgen_quadfs_data *quadfs, void __iomem *reg, u32 chan, | ||
881 | spinlock_t *lock) | ||
882 | { | ||
883 | struct st_clk_quadfs_fsynth *fs; | ||
884 | struct clk *clk; | ||
885 | struct clk_init_data init; | ||
886 | |||
887 | /* | ||
888 | * Sanity check required pointers, note that nsdiv3 is optional. | ||
889 | */ | ||
890 | if (WARN_ON(!name || !parent_name)) | ||
891 | return ERR_PTR(-EINVAL); | ||
892 | |||
893 | fs = kzalloc(sizeof(*fs), GFP_KERNEL); | ||
894 | if (!fs) | ||
895 | return ERR_PTR(-ENOMEM); | ||
896 | |||
897 | init.name = name; | ||
898 | init.ops = &st_quadfs_ops; | ||
899 | init.flags = CLK_GET_RATE_NOCACHE | CLK_IS_BASIC; | ||
900 | init.parent_names = &parent_name; | ||
901 | init.num_parents = 1; | ||
902 | |||
903 | fs->data = quadfs; | ||
904 | fs->regs_base = reg; | ||
905 | fs->chan = chan; | ||
906 | fs->lock = lock; | ||
907 | fs->hw.init = &init; | ||
908 | |||
909 | clk = clk_register(NULL, &fs->hw); | ||
910 | |||
911 | if (IS_ERR(clk)) | ||
912 | kfree(fs); | ||
913 | |||
914 | return clk; | ||
915 | } | ||
916 | |||
917 | static struct of_device_id quadfs_of_match[] = { | ||
918 | { | ||
919 | .compatible = "st,stih416-quadfs216", | ||
920 | .data = (void *)&st_fs216c65_416 | ||
921 | }, | ||
922 | { | ||
923 | .compatible = "st,stih416-quadfs432", | ||
924 | .data = (void *)&st_fs432c65_416 | ||
925 | }, | ||
926 | { | ||
927 | .compatible = "st,stih416-quadfs660-E", | ||
928 | .data = (void *)&st_fs660c32_E_416 | ||
929 | }, | ||
930 | { | ||
931 | .compatible = "st,stih416-quadfs660-F", | ||
932 | .data = (void *)&st_fs660c32_F_416 | ||
933 | }, | ||
934 | {} | ||
935 | }; | ||
936 | |||
937 | static void __init st_of_create_quadfs_fsynths( | ||
938 | struct device_node *np, const char *pll_name, | ||
939 | struct clkgen_quadfs_data *quadfs, void __iomem *reg, | ||
940 | spinlock_t *lock) | ||
941 | { | ||
942 | struct clk_onecell_data *clk_data; | ||
943 | int fschan; | ||
944 | |||
945 | clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); | ||
946 | if (!clk_data) | ||
947 | return; | ||
948 | |||
949 | clk_data->clk_num = QUADFS_MAX_CHAN; | ||
950 | clk_data->clks = kzalloc(QUADFS_MAX_CHAN * sizeof(struct clk *), | ||
951 | GFP_KERNEL); | ||
952 | |||
953 | if (!clk_data->clks) { | ||
954 | kfree(clk_data); | ||
955 | return; | ||
956 | } | ||
957 | |||
958 | for (fschan = 0; fschan < QUADFS_MAX_CHAN; fschan++) { | ||
959 | struct clk *clk; | ||
960 | const char *clk_name; | ||
961 | |||
962 | if (of_property_read_string_index(np, "clock-output-names", | ||
963 | fschan, &clk_name)) { | ||
964 | break; | ||
965 | } | ||
966 | |||
967 | /* | ||
968 | * If we read an empty clock name then the channel is unused | ||
969 | */ | ||
970 | if (*clk_name == '\0') | ||
971 | continue; | ||
972 | |||
973 | clk = st_clk_register_quadfs_fsynth(clk_name, pll_name, | ||
974 | quadfs, reg, fschan, lock); | ||
975 | |||
976 | /* | ||
977 | * If there was an error registering this clock output, clean | ||
978 | * up and move on to the next one. | ||
979 | */ | ||
980 | if (!IS_ERR(clk)) { | ||
981 | clk_data->clks[fschan] = clk; | ||
982 | pr_debug("%s: parent %s rate %u\n", | ||
983 | __clk_get_name(clk), | ||
984 | __clk_get_name(clk_get_parent(clk)), | ||
985 | (unsigned int)clk_get_rate(clk)); | ||
986 | } | ||
987 | } | ||
988 | |||
989 | of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); | ||
990 | } | ||
991 | |||
992 | static void __init st_of_quadfs_setup(struct device_node *np) | ||
993 | { | ||
994 | const struct of_device_id *match; | ||
995 | struct clk *clk; | ||
996 | const char *pll_name, *clk_parent_name; | ||
997 | void __iomem *reg; | ||
998 | spinlock_t *lock; | ||
999 | |||
1000 | match = of_match_node(quadfs_of_match, np); | ||
1001 | if (WARN_ON(!match)) | ||
1002 | return; | ||
1003 | |||
1004 | reg = of_iomap(np, 0); | ||
1005 | if (!reg) | ||
1006 | return; | ||
1007 | |||
1008 | clk_parent_name = of_clk_get_parent_name(np, 0); | ||
1009 | if (!clk_parent_name) | ||
1010 | return; | ||
1011 | |||
1012 | pll_name = kasprintf(GFP_KERNEL, "%s.pll", np->name); | ||
1013 | if (!pll_name) | ||
1014 | return; | ||
1015 | |||
1016 | lock = kzalloc(sizeof(*lock), GFP_KERNEL); | ||
1017 | if (!lock) | ||
1018 | goto err_exit; | ||
1019 | |||
1020 | spin_lock_init(lock); | ||
1021 | |||
1022 | clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, | ||
1023 | (struct clkgen_quadfs_data *) match->data, reg, lock); | ||
1024 | if (IS_ERR(clk)) | ||
1025 | goto err_exit; | ||
1026 | else | ||
1027 | pr_debug("%s: parent %s rate %u\n", | ||
1028 | __clk_get_name(clk), | ||
1029 | __clk_get_name(clk_get_parent(clk)), | ||
1030 | (unsigned int)clk_get_rate(clk)); | ||
1031 | |||
1032 | st_of_create_quadfs_fsynths(np, pll_name, | ||
1033 | (struct clkgen_quadfs_data *)match->data, | ||
1034 | reg, lock); | ||
1035 | |||
1036 | err_exit: | ||
1037 | kfree(pll_name); /* No longer need local copy of the PLL name */ | ||
1038 | } | ||
1039 | CLK_OF_DECLARE(quadfs, "st,quadfs", st_of_quadfs_setup); | ||
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c new file mode 100644 index 000000000000..a329906d1e81 --- /dev/null +++ b/drivers/clk/st/clkgen-mux.c | |||
@@ -0,0 +1,820 @@ | |||
1 | /* | ||
2 | * clkgen-mux.c: ST GEN-MUX Clock driver | ||
3 | * | ||
4 | * Copyright (C) 2014 STMicroelectronics (R&D) Limited | ||
5 | * | ||
6 | * Authors: Stephen Gallimore <stephen.gallimore@st.com> | ||
7 | * Pankaj Dev <pankaj.dev@st.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/slab.h> | ||
17 | #include <linux/of_address.h> | ||
18 | #include <linux/clk-provider.h> | ||
19 | |||
20 | static DEFINE_SPINLOCK(clkgena_divmux_lock); | ||
21 | static DEFINE_SPINLOCK(clkgenf_lock); | ||
22 | |||
23 | static const char ** __init clkgen_mux_get_parents(struct device_node *np, | ||
24 | int *num_parents) | ||
25 | { | ||
26 | const char **parents; | ||
27 | int nparents, i; | ||
28 | |||
29 | nparents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); | ||
30 | if (WARN_ON(nparents <= 0)) | ||
31 | return ERR_PTR(-EINVAL); | ||
32 | |||
33 | parents = kzalloc(nparents * sizeof(const char *), GFP_KERNEL); | ||
34 | if (!parents) | ||
35 | return ERR_PTR(-ENOMEM); | ||
36 | |||
37 | for (i = 0; i < nparents; i++) | ||
38 | parents[i] = of_clk_get_parent_name(np, i); | ||
39 | |||
40 | *num_parents = nparents; | ||
41 | return parents; | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * DOC: Clock mux with a programmable divider on each of its three inputs. | ||
46 | * The mux has an input setting which effectively gates its output. | ||
47 | * | ||
48 | * Traits of this clock: | ||
49 | * prepare - clk_(un)prepare only ensures parent is (un)prepared | ||
50 | * enable - clk_enable and clk_disable are functional & control gating | ||
51 | * rate - set rate is supported | ||
52 | * parent - set/get parent | ||
53 | */ | ||
54 | |||
55 | #define NUM_INPUTS 3 | ||
56 | |||
57 | struct clkgena_divmux { | ||
58 | struct clk_hw hw; | ||
59 | /* Subclassed mux and divider structures */ | ||
60 | struct clk_mux mux; | ||
61 | struct clk_divider div[NUM_INPUTS]; | ||
62 | /* Enable/running feedback register bits for each input */ | ||
63 | void __iomem *feedback_reg[NUM_INPUTS]; | ||
64 | int feedback_bit_idx; | ||
65 | |||
66 | u8 muxsel; | ||
67 | }; | ||
68 | |||
69 | #define to_clkgena_divmux(_hw) container_of(_hw, struct clkgena_divmux, hw) | ||
70 | |||
71 | struct clkgena_divmux_data { | ||
72 | int num_outputs; | ||
73 | int mux_offset; | ||
74 | int mux_offset2; | ||
75 | int mux_start_bit; | ||
76 | int div_offsets[NUM_INPUTS]; | ||
77 | int fb_offsets[NUM_INPUTS]; | ||
78 | int fb_start_bit_idx; | ||
79 | }; | ||
80 | |||
81 | #define CKGAX_CLKOPSRC_SWITCH_OFF 0x3 | ||
82 | |||
83 | static int clkgena_divmux_is_running(struct clkgena_divmux *mux) | ||
84 | { | ||
85 | u32 regval = readl(mux->feedback_reg[mux->muxsel]); | ||
86 | u32 running = regval & BIT(mux->feedback_bit_idx); | ||
87 | return !!running; | ||
88 | } | ||
89 | |||
90 | static int clkgena_divmux_enable(struct clk_hw *hw) | ||
91 | { | ||
92 | struct clkgena_divmux *genamux = to_clkgena_divmux(hw); | ||
93 | struct clk_hw *mux_hw = &genamux->mux.hw; | ||
94 | unsigned long timeout; | ||
95 | int ret = 0; | ||
96 | |||
97 | mux_hw->clk = hw->clk; | ||
98 | |||
99 | ret = clk_mux_ops.set_parent(mux_hw, genamux->muxsel); | ||
100 | if (ret) | ||
101 | return ret; | ||
102 | |||
103 | timeout = jiffies + msecs_to_jiffies(10); | ||
104 | |||
105 | while (!clkgena_divmux_is_running(genamux)) { | ||
106 | if (time_after(jiffies, timeout)) | ||
107 | return -ETIMEDOUT; | ||
108 | cpu_relax(); | ||
109 | } | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static void clkgena_divmux_disable(struct clk_hw *hw) | ||
115 | { | ||
116 | struct clkgena_divmux *genamux = to_clkgena_divmux(hw); | ||
117 | struct clk_hw *mux_hw = &genamux->mux.hw; | ||
118 | |||
119 | mux_hw->clk = hw->clk; | ||
120 | |||
121 | clk_mux_ops.set_parent(mux_hw, CKGAX_CLKOPSRC_SWITCH_OFF); | ||
122 | } | ||
123 | |||
124 | static int clkgena_divmux_is_enabled(struct clk_hw *hw) | ||
125 | { | ||
126 | struct clkgena_divmux *genamux = to_clkgena_divmux(hw); | ||
127 | struct clk_hw *mux_hw = &genamux->mux.hw; | ||
128 | |||
129 | mux_hw->clk = hw->clk; | ||
130 | |||
131 | return (s8)clk_mux_ops.get_parent(mux_hw) > 0; | ||
132 | } | ||
133 | |||
134 | u8 clkgena_divmux_get_parent(struct clk_hw *hw) | ||
135 | { | ||
136 | struct clkgena_divmux *genamux = to_clkgena_divmux(hw); | ||
137 | struct clk_hw *mux_hw = &genamux->mux.hw; | ||
138 | |||
139 | mux_hw->clk = hw->clk; | ||
140 | |||
141 | genamux->muxsel = clk_mux_ops.get_parent(mux_hw); | ||
142 | if ((s8)genamux->muxsel < 0) { | ||
143 | pr_debug("%s: %s: Invalid parent, setting to default.\n", | ||
144 | __func__, __clk_get_name(hw->clk)); | ||
145 | genamux->muxsel = 0; | ||
146 | } | ||
147 | |||
148 | return genamux->muxsel; | ||
149 | } | ||
150 | |||
151 | static int clkgena_divmux_set_parent(struct clk_hw *hw, u8 index) | ||
152 | { | ||
153 | struct clkgena_divmux *genamux = to_clkgena_divmux(hw); | ||
154 | |||
155 | if (index >= CKGAX_CLKOPSRC_SWITCH_OFF) | ||
156 | return -EINVAL; | ||
157 | |||
158 | genamux->muxsel = index; | ||
159 | |||
160 | /* | ||
161 | * If the mux is already enabled, call enable directly to set the | ||
162 | * new mux position and wait for it to start running again. Otherwise | ||
163 | * do nothing. | ||
164 | */ | ||
165 | if (clkgena_divmux_is_enabled(hw)) | ||
166 | clkgena_divmux_enable(hw); | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw, | ||
172 | unsigned long parent_rate) | ||
173 | { | ||
174 | struct clkgena_divmux *genamux = to_clkgena_divmux(hw); | ||
175 | struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw; | ||
176 | |||
177 | div_hw->clk = hw->clk; | ||
178 | |||
179 | return clk_divider_ops.recalc_rate(div_hw, parent_rate); | ||
180 | } | ||
181 | |||
182 | static int clkgena_divmux_set_rate(struct clk_hw *hw, unsigned long rate, | ||
183 | unsigned long parent_rate) | ||
184 | { | ||
185 | struct clkgena_divmux *genamux = to_clkgena_divmux(hw); | ||
186 | struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw; | ||
187 | |||
188 | div_hw->clk = hw->clk; | ||
189 | |||
190 | return clk_divider_ops.set_rate(div_hw, rate, parent_rate); | ||
191 | } | ||
192 | |||
193 | static long clkgena_divmux_round_rate(struct clk_hw *hw, unsigned long rate, | ||
194 | unsigned long *prate) | ||
195 | { | ||
196 | struct clkgena_divmux *genamux = to_clkgena_divmux(hw); | ||
197 | struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw; | ||
198 | |||
199 | div_hw->clk = hw->clk; | ||
200 | |||
201 | return clk_divider_ops.round_rate(div_hw, rate, prate); | ||
202 | } | ||
203 | |||
204 | static const struct clk_ops clkgena_divmux_ops = { | ||
205 | .enable = clkgena_divmux_enable, | ||
206 | .disable = clkgena_divmux_disable, | ||
207 | .is_enabled = clkgena_divmux_is_enabled, | ||
208 | .get_parent = clkgena_divmux_get_parent, | ||
209 | .set_parent = clkgena_divmux_set_parent, | ||
210 | .round_rate = clkgena_divmux_round_rate, | ||
211 | .recalc_rate = clkgena_divmux_recalc_rate, | ||
212 | .set_rate = clkgena_divmux_set_rate, | ||
213 | }; | ||
214 | |||
215 | /** | ||
216 | * clk_register_genamux - register a genamux clock with the clock framework | ||
217 | */ | ||
218 | struct clk *clk_register_genamux(const char *name, | ||
219 | const char **parent_names, u8 num_parents, | ||
220 | void __iomem *reg, | ||
221 | const struct clkgena_divmux_data *muxdata, | ||
222 | u32 idx) | ||
223 | { | ||
224 | /* | ||
225 | * Fixed constants across all ClockgenA variants | ||
226 | */ | ||
227 | const int mux_width = 2; | ||
228 | const int divider_width = 5; | ||
229 | struct clkgena_divmux *genamux; | ||
230 | struct clk *clk; | ||
231 | struct clk_init_data init; | ||
232 | int i; | ||
233 | |||
234 | genamux = kzalloc(sizeof(*genamux), GFP_KERNEL); | ||
235 | if (!genamux) | ||
236 | return ERR_PTR(-ENOMEM); | ||
237 | |||
238 | init.name = name; | ||
239 | init.ops = &clkgena_divmux_ops; | ||
240 | init.flags = CLK_IS_BASIC; | ||
241 | init.parent_names = parent_names; | ||
242 | init.num_parents = num_parents; | ||
243 | |||
244 | genamux->mux.lock = &clkgena_divmux_lock; | ||
245 | genamux->mux.mask = BIT(mux_width) - 1; | ||
246 | genamux->mux.shift = muxdata->mux_start_bit + (idx * mux_width); | ||
247 | if (genamux->mux.shift > 31) { | ||
248 | /* | ||
249 | * We have spilled into the second mux register so | ||
250 | * adjust the register address and the bit shift accordingly | ||
251 | */ | ||
252 | genamux->mux.reg = reg + muxdata->mux_offset2; | ||
253 | genamux->mux.shift -= 32; | ||
254 | } else { | ||
255 | genamux->mux.reg = reg + muxdata->mux_offset; | ||
256 | } | ||
257 | |||
258 | for (i = 0; i < NUM_INPUTS; i++) { | ||
259 | /* | ||
260 | * Divider config for each input | ||
261 | */ | ||
262 | void __iomem *divbase = reg + muxdata->div_offsets[i]; | ||
263 | genamux->div[i].width = divider_width; | ||
264 | genamux->div[i].reg = divbase + (idx * sizeof(u32)); | ||
265 | |||
266 | /* | ||
267 | * Mux enabled/running feedback register for each input. | ||
268 | */ | ||
269 | genamux->feedback_reg[i] = reg + muxdata->fb_offsets[i]; | ||
270 | } | ||
271 | |||
272 | genamux->feedback_bit_idx = muxdata->fb_start_bit_idx + idx; | ||
273 | genamux->hw.init = &init; | ||
274 | |||
275 | clk = clk_register(NULL, &genamux->hw); | ||
276 | if (IS_ERR(clk)) { | ||
277 | kfree(genamux); | ||
278 | goto err; | ||
279 | } | ||
280 | |||
281 | pr_debug("%s: parent %s rate %lu\n", | ||
282 | __clk_get_name(clk), | ||
283 | __clk_get_name(clk_get_parent(clk)), | ||
284 | clk_get_rate(clk)); | ||
285 | err: | ||
286 | return clk; | ||
287 | } | ||
288 | |||
289 | static struct clkgena_divmux_data st_divmux_c65hs = { | ||
290 | .num_outputs = 4, | ||
291 | .mux_offset = 0x14, | ||
292 | .mux_start_bit = 0, | ||
293 | .div_offsets = { 0x800, 0x900, 0xb00 }, | ||
294 | .fb_offsets = { 0x18, 0x1c, 0x20 }, | ||
295 | .fb_start_bit_idx = 0, | ||
296 | }; | ||
297 | |||
298 | static struct clkgena_divmux_data st_divmux_c65ls = { | ||
299 | .num_outputs = 14, | ||
300 | .mux_offset = 0x14, | ||
301 | .mux_offset2 = 0x24, | ||
302 | .mux_start_bit = 8, | ||
303 | .div_offsets = { 0x810, 0xa10, 0xb10 }, | ||
304 | .fb_offsets = { 0x18, 0x1c, 0x20 }, | ||
305 | .fb_start_bit_idx = 4, | ||
306 | }; | ||
307 | |||
308 | static struct clkgena_divmux_data st_divmux_c32odf0 = { | ||
309 | .num_outputs = 8, | ||
310 | .mux_offset = 0x1c, | ||
311 | .mux_start_bit = 0, | ||
312 | .div_offsets = { 0x800, 0x900, 0xa60 }, | ||
313 | .fb_offsets = { 0x2c, 0x24, 0x28 }, | ||
314 | .fb_start_bit_idx = 0, | ||
315 | }; | ||
316 | |||
317 | static struct clkgena_divmux_data st_divmux_c32odf1 = { | ||
318 | .num_outputs = 8, | ||
319 | .mux_offset = 0x1c, | ||
320 | .mux_start_bit = 16, | ||
321 | .div_offsets = { 0x820, 0x980, 0xa80 }, | ||
322 | .fb_offsets = { 0x2c, 0x24, 0x28 }, | ||
323 | .fb_start_bit_idx = 8, | ||
324 | }; | ||
325 | |||
326 | static struct clkgena_divmux_data st_divmux_c32odf2 = { | ||
327 | .num_outputs = 8, | ||
328 | .mux_offset = 0x20, | ||
329 | .mux_start_bit = 0, | ||
330 | .div_offsets = { 0x840, 0xa20, 0xb10 }, | ||
331 | .fb_offsets = { 0x2c, 0x24, 0x28 }, | ||
332 | .fb_start_bit_idx = 16, | ||
333 | }; | ||
334 | |||
335 | static struct clkgena_divmux_data st_divmux_c32odf3 = { | ||
336 | .num_outputs = 8, | ||
337 | .mux_offset = 0x20, | ||
338 | .mux_start_bit = 16, | ||
339 | .div_offsets = { 0x860, 0xa40, 0xb30 }, | ||
340 | .fb_offsets = { 0x2c, 0x24, 0x28 }, | ||
341 | .fb_start_bit_idx = 24, | ||
342 | }; | ||
343 | |||
344 | static struct of_device_id clkgena_divmux_of_match[] = { | ||
345 | { | ||
346 | .compatible = "st,clkgena-divmux-c65-hs", | ||
347 | .data = &st_divmux_c65hs, | ||
348 | }, | ||
349 | { | ||
350 | .compatible = "st,clkgena-divmux-c65-ls", | ||
351 | .data = &st_divmux_c65ls, | ||
352 | }, | ||
353 | { | ||
354 | .compatible = "st,clkgena-divmux-c32-odf0", | ||
355 | .data = &st_divmux_c32odf0, | ||
356 | }, | ||
357 | { | ||
358 | .compatible = "st,clkgena-divmux-c32-odf1", | ||
359 | .data = &st_divmux_c32odf1, | ||
360 | }, | ||
361 | { | ||
362 | .compatible = "st,clkgena-divmux-c32-odf2", | ||
363 | .data = &st_divmux_c32odf2, | ||
364 | }, | ||
365 | { | ||
366 | .compatible = "st,clkgena-divmux-c32-odf3", | ||
367 | .data = &st_divmux_c32odf3, | ||
368 | }, | ||
369 | {} | ||
370 | }; | ||
371 | |||
372 | static void __iomem * __init clkgen_get_register_base( | ||
373 | struct device_node *np) | ||
374 | { | ||
375 | struct device_node *pnode; | ||
376 | void __iomem *reg = NULL; | ||
377 | |||
378 | pnode = of_get_parent(np); | ||
379 | if (!pnode) | ||
380 | return NULL; | ||
381 | |||
382 | reg = of_iomap(pnode, 0); | ||
383 | |||
384 | of_node_put(pnode); | ||
385 | return reg; | ||
386 | } | ||
387 | |||
388 | void __init st_of_clkgena_divmux_setup(struct device_node *np) | ||
389 | { | ||
390 | const struct of_device_id *match; | ||
391 | const struct clkgena_divmux_data *data; | ||
392 | struct clk_onecell_data *clk_data; | ||
393 | void __iomem *reg; | ||
394 | const char **parents; | ||
395 | int num_parents = 0, i; | ||
396 | |||
397 | match = of_match_node(clkgena_divmux_of_match, np); | ||
398 | if (WARN_ON(!match)) | ||
399 | return; | ||
400 | |||
401 | data = (struct clkgena_divmux_data *)match->data; | ||
402 | |||
403 | reg = clkgen_get_register_base(np); | ||
404 | if (!reg) | ||
405 | return; | ||
406 | |||
407 | parents = clkgen_mux_get_parents(np, &num_parents); | ||
408 | if (IS_ERR(parents)) | ||
409 | return; | ||
410 | |||
411 | clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); | ||
412 | if (!clk_data) | ||
413 | goto err; | ||
414 | |||
415 | clk_data->clk_num = data->num_outputs; | ||
416 | clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *), | ||
417 | GFP_KERNEL); | ||
418 | |||
419 | if (!clk_data->clks) | ||
420 | goto err; | ||
421 | |||
422 | for (i = 0; i < clk_data->clk_num; i++) { | ||
423 | struct clk *clk; | ||
424 | const char *clk_name; | ||
425 | |||
426 | if (of_property_read_string_index(np, "clock-output-names", | ||
427 | i, &clk_name)) | ||
428 | break; | ||
429 | |||
430 | /* | ||
431 | * If we read an empty clock name then the output is unused | ||
432 | */ | ||
433 | if (*clk_name == '\0') | ||
434 | continue; | ||
435 | |||
436 | clk = clk_register_genamux(clk_name, parents, num_parents, | ||
437 | reg, data, i); | ||
438 | |||
439 | if (IS_ERR(clk)) | ||
440 | goto err; | ||
441 | |||
442 | clk_data->clks[i] = clk; | ||
443 | } | ||
444 | |||
445 | kfree(parents); | ||
446 | |||
447 | of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); | ||
448 | return; | ||
449 | err: | ||
450 | if (clk_data) | ||
451 | kfree(clk_data->clks); | ||
452 | |||
453 | kfree(clk_data); | ||
454 | kfree(parents); | ||
455 | } | ||
456 | CLK_OF_DECLARE(clkgenadivmux, "st,clkgena-divmux", st_of_clkgena_divmux_setup); | ||
457 | |||
458 | struct clkgena_prediv_data { | ||
459 | u32 offset; | ||
460 | u8 shift; | ||
461 | struct clk_div_table *table; | ||
462 | }; | ||
463 | |||
464 | static struct clk_div_table prediv_table16[] = { | ||
465 | { .val = 0, .div = 1 }, | ||
466 | { .val = 1, .div = 16 }, | ||
467 | { .div = 0 }, | ||
468 | }; | ||
469 | |||
470 | static struct clkgena_prediv_data prediv_c65_data = { | ||
471 | .offset = 0x4c, | ||
472 | .shift = 31, | ||
473 | .table = prediv_table16, | ||
474 | }; | ||
475 | |||
476 | static struct clkgena_prediv_data prediv_c32_data = { | ||
477 | .offset = 0x50, | ||
478 | .shift = 1, | ||
479 | .table = prediv_table16, | ||
480 | }; | ||
481 | |||
482 | static struct of_device_id clkgena_prediv_of_match[] = { | ||
483 | { .compatible = "st,clkgena-prediv-c65", .data = &prediv_c65_data }, | ||
484 | { .compatible = "st,clkgena-prediv-c32", .data = &prediv_c32_data }, | ||
485 | {} | ||
486 | }; | ||
487 | |||
488 | void __init st_of_clkgena_prediv_setup(struct device_node *np) | ||
489 | { | ||
490 | const struct of_device_id *match; | ||
491 | void __iomem *reg; | ||
492 | const char *parent_name, *clk_name; | ||
493 | struct clk *clk; | ||
494 | struct clkgena_prediv_data *data; | ||
495 | |||
496 | match = of_match_node(clkgena_prediv_of_match, np); | ||
497 | if (!match) { | ||
498 | pr_err("%s: No matching data\n", __func__); | ||
499 | return; | ||
500 | } | ||
501 | |||
502 | data = (struct clkgena_prediv_data *)match->data; | ||
503 | |||
504 | reg = clkgen_get_register_base(np); | ||
505 | if (!reg) | ||
506 | return; | ||
507 | |||
508 | parent_name = of_clk_get_parent_name(np, 0); | ||
509 | if (!parent_name) | ||
510 | return; | ||
511 | |||
512 | if (of_property_read_string_index(np, "clock-output-names", | ||
513 | 0, &clk_name)) | ||
514 | return; | ||
515 | |||
516 | clk = clk_register_divider_table(NULL, clk_name, parent_name, 0, | ||
517 | reg + data->offset, data->shift, 1, | ||
518 | 0, data->table, NULL); | ||
519 | if (IS_ERR(clk)) | ||
520 | return; | ||
521 | |||
522 | of_clk_add_provider(np, of_clk_src_simple_get, clk); | ||
523 | pr_debug("%s: parent %s rate %u\n", | ||
524 | __clk_get_name(clk), | ||
525 | __clk_get_name(clk_get_parent(clk)), | ||
526 | (unsigned int)clk_get_rate(clk)); | ||
527 | |||
528 | return; | ||
529 | } | ||
530 | CLK_OF_DECLARE(clkgenaprediv, "st,clkgena-prediv", st_of_clkgena_prediv_setup); | ||
531 | |||
532 | struct clkgen_mux_data { | ||
533 | u32 offset; | ||
534 | u8 shift; | ||
535 | u8 width; | ||
536 | spinlock_t *lock; | ||
537 | unsigned long clk_flags; | ||
538 | u8 mux_flags; | ||
539 | }; | ||
540 | |||
541 | static struct clkgen_mux_data clkgen_mux_c_vcc_hd_416 = { | ||
542 | .offset = 0, | ||
543 | .shift = 0, | ||
544 | .width = 1, | ||
545 | }; | ||
546 | |||
547 | static struct clkgen_mux_data clkgen_mux_f_vcc_fvdp_416 = { | ||
548 | .offset = 0, | ||
549 | .shift = 0, | ||
550 | .width = 1, | ||
551 | }; | ||
552 | |||
553 | static struct clkgen_mux_data clkgen_mux_f_vcc_hva_416 = { | ||
554 | .offset = 0, | ||
555 | .shift = 0, | ||
556 | .width = 1, | ||
557 | }; | ||
558 | |||
559 | static struct clkgen_mux_data clkgen_mux_f_vcc_hd_416 = { | ||
560 | .offset = 0, | ||
561 | .shift = 16, | ||
562 | .width = 1, | ||
563 | .lock = &clkgenf_lock, | ||
564 | }; | ||
565 | |||
566 | static struct clkgen_mux_data clkgen_mux_c_vcc_sd_416 = { | ||
567 | .offset = 0, | ||
568 | .shift = 17, | ||
569 | .width = 1, | ||
570 | .lock = &clkgenf_lock, | ||
571 | }; | ||
572 | |||
573 | static struct clkgen_mux_data stih415_a9_mux_data = { | ||
574 | .offset = 0, | ||
575 | .shift = 1, | ||
576 | .width = 2, | ||
577 | }; | ||
578 | static struct clkgen_mux_data stih416_a9_mux_data = { | ||
579 | .offset = 0, | ||
580 | .shift = 0, | ||
581 | .width = 2, | ||
582 | }; | ||
583 | |||
584 | static struct of_device_id mux_of_match[] = { | ||
585 | { | ||
586 | .compatible = "st,stih416-clkgenc-vcc-hd", | ||
587 | .data = &clkgen_mux_c_vcc_hd_416, | ||
588 | }, | ||
589 | { | ||
590 | .compatible = "st,stih416-clkgenf-vcc-fvdp", | ||
591 | .data = &clkgen_mux_f_vcc_fvdp_416, | ||
592 | }, | ||
593 | { | ||
594 | .compatible = "st,stih416-clkgenf-vcc-hva", | ||
595 | .data = &clkgen_mux_f_vcc_hva_416, | ||
596 | }, | ||
597 | { | ||
598 | .compatible = "st,stih416-clkgenf-vcc-hd", | ||
599 | .data = &clkgen_mux_f_vcc_hd_416, | ||
600 | }, | ||
601 | { | ||
602 | .compatible = "st,stih416-clkgenf-vcc-sd", | ||
603 | .data = &clkgen_mux_c_vcc_sd_416, | ||
604 | }, | ||
605 | { | ||
606 | .compatible = "st,stih415-clkgen-a9-mux", | ||
607 | .data = &stih415_a9_mux_data, | ||
608 | }, | ||
609 | { | ||
610 | .compatible = "st,stih416-clkgen-a9-mux", | ||
611 | .data = &stih416_a9_mux_data, | ||
612 | }, | ||
613 | {} | ||
614 | }; | ||
615 | |||
616 | void __init st_of_clkgen_mux_setup(struct device_node *np) | ||
617 | { | ||
618 | const struct of_device_id *match; | ||
619 | struct clk *clk; | ||
620 | void __iomem *reg; | ||
621 | const char **parents; | ||
622 | int num_parents; | ||
623 | struct clkgen_mux_data *data; | ||
624 | |||
625 | match = of_match_node(mux_of_match, np); | ||
626 | if (!match) { | ||
627 | pr_err("%s: No matching data\n", __func__); | ||
628 | return; | ||
629 | } | ||
630 | |||
631 | data = (struct clkgen_mux_data *)match->data; | ||
632 | |||
633 | reg = of_iomap(np, 0); | ||
634 | if (!reg) { | ||
635 | pr_err("%s: Failed to get base address\n", __func__); | ||
636 | return; | ||
637 | } | ||
638 | |||
639 | parents = clkgen_mux_get_parents(np, &num_parents); | ||
640 | if (IS_ERR(parents)) { | ||
641 | pr_err("%s: Failed to get parents (%ld)\n", | ||
642 | __func__, PTR_ERR(parents)); | ||
643 | return; | ||
644 | } | ||
645 | |||
646 | clk = clk_register_mux(NULL, np->name, parents, num_parents, | ||
647 | data->clk_flags | CLK_SET_RATE_PARENT, | ||
648 | reg + data->offset, | ||
649 | data->shift, data->width, data->mux_flags, | ||
650 | data->lock); | ||
651 | if (IS_ERR(clk)) | ||
652 | goto err; | ||
653 | |||
654 | pr_debug("%s: parent %s rate %u\n", | ||
655 | __clk_get_name(clk), | ||
656 | __clk_get_name(clk_get_parent(clk)), | ||
657 | (unsigned int)clk_get_rate(clk)); | ||
658 | |||
659 | of_clk_add_provider(np, of_clk_src_simple_get, clk); | ||
660 | |||
661 | err: | ||
662 | kfree(parents); | ||
663 | |||
664 | return; | ||
665 | } | ||
666 | CLK_OF_DECLARE(clkgen_mux, "st,clkgen-mux", st_of_clkgen_mux_setup); | ||
667 | |||
668 | #define VCC_MAX_CHANNELS 16 | ||
669 | |||
670 | #define VCC_GATE_OFFSET 0x0 | ||
671 | #define VCC_MUX_OFFSET 0x4 | ||
672 | #define VCC_DIV_OFFSET 0x8 | ||
673 | |||
674 | struct clkgen_vcc_data { | ||
675 | spinlock_t *lock; | ||
676 | unsigned long clk_flags; | ||
677 | }; | ||
678 | |||
679 | static struct clkgen_vcc_data st_clkgenc_vcc_416 = { | ||
680 | .clk_flags = CLK_SET_RATE_PARENT, | ||
681 | }; | ||
682 | |||
683 | static struct clkgen_vcc_data st_clkgenf_vcc_416 = { | ||
684 | .lock = &clkgenf_lock, | ||
685 | }; | ||
686 | |||
687 | static struct of_device_id vcc_of_match[] = { | ||
688 | { .compatible = "st,stih416-clkgenc", .data = &st_clkgenc_vcc_416 }, | ||
689 | { .compatible = "st,stih416-clkgenf", .data = &st_clkgenf_vcc_416 }, | ||
690 | {} | ||
691 | }; | ||
692 | |||
693 | void __init st_of_clkgen_vcc_setup(struct device_node *np) | ||
694 | { | ||
695 | const struct of_device_id *match; | ||
696 | void __iomem *reg; | ||
697 | const char **parents; | ||
698 | int num_parents, i; | ||
699 | struct clk_onecell_data *clk_data; | ||
700 | struct clkgen_vcc_data *data; | ||
701 | |||
702 | match = of_match_node(vcc_of_match, np); | ||
703 | if (WARN_ON(!match)) | ||
704 | return; | ||
705 | data = (struct clkgen_vcc_data *)match->data; | ||
706 | |||
707 | reg = of_iomap(np, 0); | ||
708 | if (!reg) | ||
709 | return; | ||
710 | |||
711 | parents = clkgen_mux_get_parents(np, &num_parents); | ||
712 | if (IS_ERR(parents)) | ||
713 | return; | ||
714 | |||
715 | clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); | ||
716 | if (!clk_data) | ||
717 | goto err; | ||
718 | |||
719 | clk_data->clk_num = VCC_MAX_CHANNELS; | ||
720 | clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *), | ||
721 | GFP_KERNEL); | ||
722 | |||
723 | if (!clk_data->clks) | ||
724 | goto err; | ||
725 | |||
726 | for (i = 0; i < clk_data->clk_num; i++) { | ||
727 | struct clk *clk; | ||
728 | const char *clk_name; | ||
729 | struct clk_gate *gate; | ||
730 | struct clk_divider *div; | ||
731 | struct clk_mux *mux; | ||
732 | |||
733 | if (of_property_read_string_index(np, "clock-output-names", | ||
734 | i, &clk_name)) | ||
735 | break; | ||
736 | |||
737 | /* | ||
738 | * If we read an empty clock name then the output is unused | ||
739 | */ | ||
740 | if (*clk_name == '\0') | ||
741 | continue; | ||
742 | |||
743 | gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); | ||
744 | if (!gate) | ||
745 | break; | ||
746 | |||
747 | div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL); | ||
748 | if (!div) { | ||
749 | kfree(gate); | ||
750 | break; | ||
751 | } | ||
752 | |||
753 | mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); | ||
754 | if (!mux) { | ||
755 | kfree(gate); | ||
756 | kfree(div); | ||
757 | break; | ||
758 | } | ||
759 | |||
760 | gate->reg = reg + VCC_GATE_OFFSET; | ||
761 | gate->bit_idx = i; | ||
762 | gate->flags = CLK_GATE_SET_TO_DISABLE; | ||
763 | gate->lock = data->lock; | ||
764 | |||
765 | div->reg = reg + VCC_DIV_OFFSET; | ||
766 | div->shift = 2 * i; | ||
767 | div->width = 2; | ||
768 | div->flags = CLK_DIVIDER_POWER_OF_TWO; | ||
769 | |||
770 | mux->reg = reg + VCC_MUX_OFFSET; | ||
771 | mux->shift = 2 * i; | ||
772 | mux->mask = 0x3; | ||
773 | |||
774 | clk = clk_register_composite(NULL, clk_name, parents, | ||
775 | num_parents, | ||
776 | &mux->hw, &clk_mux_ops, | ||
777 | &div->hw, &clk_divider_ops, | ||
778 | &gate->hw, &clk_gate_ops, | ||
779 | data->clk_flags); | ||
780 | if (IS_ERR(clk)) { | ||
781 | kfree(gate); | ||
782 | kfree(div); | ||
783 | kfree(mux); | ||
784 | goto err; | ||
785 | } | ||
786 | |||
787 | pr_debug("%s: parent %s rate %u\n", | ||
788 | __clk_get_name(clk), | ||
789 | __clk_get_name(clk_get_parent(clk)), | ||
790 | (unsigned int)clk_get_rate(clk)); | ||
791 | |||
792 | clk_data->clks[i] = clk; | ||
793 | } | ||
794 | |||
795 | kfree(parents); | ||
796 | |||
797 | of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); | ||
798 | return; | ||
799 | |||
800 | err: | ||
801 | for (i = 0; i < clk_data->clk_num; i++) { | ||
802 | struct clk_composite *composite; | ||
803 | |||
804 | if (!clk_data->clks[i]) | ||
805 | continue; | ||
806 | |||
807 | composite = container_of(__clk_get_hw(clk_data->clks[i]), | ||
808 | struct clk_composite, hw); | ||
809 | kfree(container_of(composite->gate_hw, struct clk_gate, hw)); | ||
810 | kfree(container_of(composite->rate_hw, struct clk_divider, hw)); | ||
811 | kfree(container_of(composite->mux_hw, struct clk_mux, hw)); | ||
812 | } | ||
813 | |||
814 | if (clk_data) | ||
815 | kfree(clk_data->clks); | ||
816 | |||
817 | kfree(clk_data); | ||
818 | kfree(parents); | ||
819 | } | ||
820 | CLK_OF_DECLARE(clkgen_vcc, "st,clkgen-vcc", st_of_clkgen_vcc_setup); | ||
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c new file mode 100644 index 000000000000..bca0a0badbfa --- /dev/null +++ b/drivers/clk/st/clkgen-pll.c | |||
@@ -0,0 +1,698 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 STMicroelectronics (R&D) Limited | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * Authors: | ||
13 | * Stephen Gallimore <stephen.gallimore@st.com>, | ||
14 | * Pankaj Dev <pankaj.dev@st.com>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/slab.h> | ||
18 | #include <linux/of_address.h> | ||
19 | #include <linux/clk-provider.h> | ||
20 | |||
21 | #include "clkgen.h" | ||
22 | |||
23 | static DEFINE_SPINLOCK(clkgena_c32_odf_lock); | ||
24 | |||
25 | /* | ||
26 | * Common PLL configuration register bits for PLL800 and PLL1600 C65 | ||
27 | */ | ||
28 | #define C65_MDIV_PLL800_MASK (0xff) | ||
29 | #define C65_MDIV_PLL1600_MASK (0x7) | ||
30 | #define C65_NDIV_MASK (0xff) | ||
31 | #define C65_PDIV_MASK (0x7) | ||
32 | |||
33 | /* | ||
34 | * PLL configuration register bits for PLL3200 C32 | ||
35 | */ | ||
36 | #define C32_NDIV_MASK (0xff) | ||
37 | #define C32_IDF_MASK (0x7) | ||
38 | #define C32_ODF_MASK (0x3f) | ||
39 | #define C32_LDF_MASK (0x7f) | ||
40 | |||
41 | #define C32_MAX_ODFS (4) | ||
42 | |||
43 | struct clkgen_pll_data { | ||
44 | struct clkgen_field pdn_status; | ||
45 | struct clkgen_field locked_status; | ||
46 | struct clkgen_field mdiv; | ||
47 | struct clkgen_field ndiv; | ||
48 | struct clkgen_field pdiv; | ||
49 | struct clkgen_field idf; | ||
50 | struct clkgen_field ldf; | ||
51 | unsigned int num_odfs; | ||
52 | struct clkgen_field odf[C32_MAX_ODFS]; | ||
53 | struct clkgen_field odf_gate[C32_MAX_ODFS]; | ||
54 | const struct clk_ops *ops; | ||
55 | }; | ||
56 | |||
57 | static const struct clk_ops st_pll1600c65_ops; | ||
58 | static const struct clk_ops st_pll800c65_ops; | ||
59 | static const struct clk_ops stm_pll3200c32_ops; | ||
60 | static const struct clk_ops st_pll1200c32_ops; | ||
61 | |||
62 | static struct clkgen_pll_data st_pll1600c65_ax = { | ||
63 | .pdn_status = CLKGEN_FIELD(0x0, 0x1, 19), | ||
64 | .locked_status = CLKGEN_FIELD(0x0, 0x1, 31), | ||
65 | .mdiv = CLKGEN_FIELD(0x0, C65_MDIV_PLL1600_MASK, 0), | ||
66 | .ndiv = CLKGEN_FIELD(0x0, C65_NDIV_MASK, 8), | ||
67 | .ops = &st_pll1600c65_ops | ||
68 | }; | ||
69 | |||
70 | static struct clkgen_pll_data st_pll800c65_ax = { | ||
71 | .pdn_status = CLKGEN_FIELD(0x0, 0x1, 19), | ||
72 | .locked_status = CLKGEN_FIELD(0x0, 0x1, 31), | ||
73 | .mdiv = CLKGEN_FIELD(0x0, C65_MDIV_PLL800_MASK, 0), | ||
74 | .ndiv = CLKGEN_FIELD(0x0, C65_NDIV_MASK, 8), | ||
75 | .pdiv = CLKGEN_FIELD(0x0, C65_PDIV_MASK, 16), | ||
76 | .ops = &st_pll800c65_ops | ||
77 | }; | ||
78 | |||
79 | static struct clkgen_pll_data st_pll3200c32_a1x_0 = { | ||
80 | .pdn_status = CLKGEN_FIELD(0x0, 0x1, 31), | ||
81 | .locked_status = CLKGEN_FIELD(0x4, 0x1, 31), | ||
82 | .ndiv = CLKGEN_FIELD(0x0, C32_NDIV_MASK, 0x0), | ||
83 | .idf = CLKGEN_FIELD(0x4, C32_IDF_MASK, 0x0), | ||
84 | .num_odfs = 4, | ||
85 | .odf = { CLKGEN_FIELD(0x54, C32_ODF_MASK, 4), | ||
86 | CLKGEN_FIELD(0x54, C32_ODF_MASK, 10), | ||
87 | CLKGEN_FIELD(0x54, C32_ODF_MASK, 16), | ||
88 | CLKGEN_FIELD(0x54, C32_ODF_MASK, 22) }, | ||
89 | .odf_gate = { CLKGEN_FIELD(0x54, 0x1, 0), | ||
90 | CLKGEN_FIELD(0x54, 0x1, 1), | ||
91 | CLKGEN_FIELD(0x54, 0x1, 2), | ||
92 | CLKGEN_FIELD(0x54, 0x1, 3) }, | ||
93 | .ops = &stm_pll3200c32_ops, | ||
94 | }; | ||
95 | |||
96 | static struct clkgen_pll_data st_pll3200c32_a1x_1 = { | ||
97 | .pdn_status = CLKGEN_FIELD(0xC, 0x1, 31), | ||
98 | .locked_status = CLKGEN_FIELD(0x10, 0x1, 31), | ||
99 | .ndiv = CLKGEN_FIELD(0xC, C32_NDIV_MASK, 0x0), | ||
100 | .idf = CLKGEN_FIELD(0x10, C32_IDF_MASK, 0x0), | ||
101 | .num_odfs = 4, | ||
102 | .odf = { CLKGEN_FIELD(0x58, C32_ODF_MASK, 4), | ||
103 | CLKGEN_FIELD(0x58, C32_ODF_MASK, 10), | ||
104 | CLKGEN_FIELD(0x58, C32_ODF_MASK, 16), | ||
105 | CLKGEN_FIELD(0x58, C32_ODF_MASK, 22) }, | ||
106 | .odf_gate = { CLKGEN_FIELD(0x58, 0x1, 0), | ||
107 | CLKGEN_FIELD(0x58, 0x1, 1), | ||
108 | CLKGEN_FIELD(0x58, 0x1, 2), | ||
109 | CLKGEN_FIELD(0x58, 0x1, 3) }, | ||
110 | .ops = &stm_pll3200c32_ops, | ||
111 | }; | ||
112 | |||
113 | /* 415 specific */ | ||
114 | static struct clkgen_pll_data st_pll3200c32_a9_415 = { | ||
115 | .pdn_status = CLKGEN_FIELD(0x0, 0x1, 0), | ||
116 | .locked_status = CLKGEN_FIELD(0x6C, 0x1, 0), | ||
117 | .ndiv = CLKGEN_FIELD(0x0, C32_NDIV_MASK, 9), | ||
118 | .idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 22), | ||
119 | .num_odfs = 1, | ||
120 | .odf = { CLKGEN_FIELD(0x0, C32_ODF_MASK, 3) }, | ||
121 | .odf_gate = { CLKGEN_FIELD(0x0, 0x1, 28) }, | ||
122 | .ops = &stm_pll3200c32_ops, | ||
123 | }; | ||
124 | |||
125 | static struct clkgen_pll_data st_pll3200c32_ddr_415 = { | ||
126 | .pdn_status = CLKGEN_FIELD(0x0, 0x1, 0), | ||
127 | .locked_status = CLKGEN_FIELD(0x100, 0x1, 0), | ||
128 | .ndiv = CLKGEN_FIELD(0x8, C32_NDIV_MASK, 0), | ||
129 | .idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 25), | ||
130 | .num_odfs = 2, | ||
131 | .odf = { CLKGEN_FIELD(0x8, C32_ODF_MASK, 8), | ||
132 | CLKGEN_FIELD(0x8, C32_ODF_MASK, 14) }, | ||
133 | .odf_gate = { CLKGEN_FIELD(0x4, 0x1, 28), | ||
134 | CLKGEN_FIELD(0x4, 0x1, 29) }, | ||
135 | .ops = &stm_pll3200c32_ops, | ||
136 | }; | ||
137 | |||
138 | static struct clkgen_pll_data st_pll1200c32_gpu_415 = { | ||
139 | .pdn_status = CLKGEN_FIELD(0x144, 0x1, 3), | ||
140 | .locked_status = CLKGEN_FIELD(0x168, 0x1, 0), | ||
141 | .ldf = CLKGEN_FIELD(0x0, C32_LDF_MASK, 3), | ||
142 | .idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 0), | ||
143 | .num_odfs = 0, | ||
144 | .odf = { CLKGEN_FIELD(0x0, C32_ODF_MASK, 10) }, | ||
145 | .ops = &st_pll1200c32_ops, | ||
146 | }; | ||
147 | |||
148 | /* 416 specific */ | ||
149 | static struct clkgen_pll_data st_pll3200c32_a9_416 = { | ||
150 | .pdn_status = CLKGEN_FIELD(0x0, 0x1, 0), | ||
151 | .locked_status = CLKGEN_FIELD(0x6C, 0x1, 0), | ||
152 | .ndiv = CLKGEN_FIELD(0x8, C32_NDIV_MASK, 0), | ||
153 | .idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 25), | ||
154 | .num_odfs = 1, | ||
155 | .odf = { CLKGEN_FIELD(0x8, C32_ODF_MASK, 8) }, | ||
156 | .odf_gate = { CLKGEN_FIELD(0x4, 0x1, 28) }, | ||
157 | .ops = &stm_pll3200c32_ops, | ||
158 | }; | ||
159 | |||
160 | static struct clkgen_pll_data st_pll3200c32_ddr_416 = { | ||
161 | .pdn_status = CLKGEN_FIELD(0x0, 0x1, 0), | ||
162 | .locked_status = CLKGEN_FIELD(0x10C, 0x1, 0), | ||
163 | .ndiv = CLKGEN_FIELD(0x8, C32_NDIV_MASK, 0), | ||
164 | .idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 25), | ||
165 | .num_odfs = 2, | ||
166 | .odf = { CLKGEN_FIELD(0x8, C32_ODF_MASK, 8), | ||
167 | CLKGEN_FIELD(0x8, C32_ODF_MASK, 14) }, | ||
168 | .odf_gate = { CLKGEN_FIELD(0x4, 0x1, 28), | ||
169 | CLKGEN_FIELD(0x4, 0x1, 29) }, | ||
170 | .ops = &stm_pll3200c32_ops, | ||
171 | }; | ||
172 | |||
173 | static struct clkgen_pll_data st_pll1200c32_gpu_416 = { | ||
174 | .pdn_status = CLKGEN_FIELD(0x8E4, 0x1, 3), | ||
175 | .locked_status = CLKGEN_FIELD(0x90C, 0x1, 0), | ||
176 | .ldf = CLKGEN_FIELD(0x0, C32_LDF_MASK, 3), | ||
177 | .idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 0), | ||
178 | .num_odfs = 0, | ||
179 | .odf = { CLKGEN_FIELD(0x0, C32_ODF_MASK, 10) }, | ||
180 | .ops = &st_pll1200c32_ops, | ||
181 | }; | ||
182 | |||
183 | /** | ||
184 | * DOC: Clock Generated by PLL, rate set and enabled by bootloader | ||
185 | * | ||
186 | * Traits of this clock: | ||
187 | * prepare - clk_(un)prepare only ensures parent is (un)prepared | ||
188 | * enable - clk_enable/disable only ensures parent is enabled | ||
189 | * rate - rate is fixed. No clk_set_rate support | ||
190 | * parent - fixed parent. No clk_set_parent support | ||
191 | */ | ||
192 | |||
193 | /** | ||
194 | * PLL clock that is integrated in the ClockGenA instances on the STiH415 | ||
195 | * and STiH416. | ||
196 | * | ||
197 | * @hw: handle between common and hardware-specific interfaces. | ||
198 | * @type: PLL instance type. | ||
199 | * @regs_base: base of the PLL configuration register(s). | ||
200 | * | ||
201 | */ | ||
202 | struct clkgen_pll { | ||
203 | struct clk_hw hw; | ||
204 | struct clkgen_pll_data *data; | ||
205 | void __iomem *regs_base; | ||
206 | }; | ||
207 | |||
208 | #define to_clkgen_pll(_hw) container_of(_hw, struct clkgen_pll, hw) | ||
209 | |||
210 | static int clkgen_pll_is_locked(struct clk_hw *hw) | ||
211 | { | ||
212 | struct clkgen_pll *pll = to_clkgen_pll(hw); | ||
213 | u32 locked = CLKGEN_READ(pll, locked_status); | ||
214 | |||
215 | return !!locked; | ||
216 | } | ||
217 | |||
218 | static int clkgen_pll_is_enabled(struct clk_hw *hw) | ||
219 | { | ||
220 | struct clkgen_pll *pll = to_clkgen_pll(hw); | ||
221 | u32 poweroff = CLKGEN_READ(pll, pdn_status); | ||
222 | return !poweroff; | ||
223 | } | ||
224 | |||
225 | unsigned long recalc_stm_pll800c65(struct clk_hw *hw, | ||
226 | unsigned long parent_rate) | ||
227 | { | ||
228 | struct clkgen_pll *pll = to_clkgen_pll(hw); | ||
229 | unsigned long mdiv, ndiv, pdiv; | ||
230 | unsigned long rate; | ||
231 | uint64_t res; | ||
232 | |||
233 | if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw)) | ||
234 | return 0; | ||
235 | |||
236 | pdiv = CLKGEN_READ(pll, pdiv); | ||
237 | mdiv = CLKGEN_READ(pll, mdiv); | ||
238 | ndiv = CLKGEN_READ(pll, ndiv); | ||
239 | |||
240 | if (!mdiv) | ||
241 | mdiv++; /* mdiv=0 or 1 => MDIV=1 */ | ||
242 | |||
243 | res = (uint64_t)2 * (uint64_t)parent_rate * (uint64_t)ndiv; | ||
244 | rate = (unsigned long)div64_u64(res, mdiv * (1 << pdiv)); | ||
245 | |||
246 | pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate); | ||
247 | |||
248 | return rate; | ||
249 | |||
250 | } | ||
251 | |||
252 | unsigned long recalc_stm_pll1600c65(struct clk_hw *hw, | ||
253 | unsigned long parent_rate) | ||
254 | { | ||
255 | struct clkgen_pll *pll = to_clkgen_pll(hw); | ||
256 | unsigned long mdiv, ndiv; | ||
257 | unsigned long rate; | ||
258 | |||
259 | if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw)) | ||
260 | return 0; | ||
261 | |||
262 | mdiv = CLKGEN_READ(pll, mdiv); | ||
263 | ndiv = CLKGEN_READ(pll, ndiv); | ||
264 | |||
265 | if (!mdiv) | ||
266 | mdiv = 1; | ||
267 | |||
268 | /* Note: input is divided by 1000 to avoid overflow */ | ||
269 | rate = ((2 * (parent_rate / 1000) * ndiv) / mdiv) * 1000; | ||
270 | |||
271 | pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate); | ||
272 | |||
273 | return rate; | ||
274 | } | ||
275 | |||
276 | unsigned long recalc_stm_pll3200c32(struct clk_hw *hw, | ||
277 | unsigned long parent_rate) | ||
278 | { | ||
279 | struct clkgen_pll *pll = to_clkgen_pll(hw); | ||
280 | unsigned long ndiv, idf; | ||
281 | unsigned long rate = 0; | ||
282 | |||
283 | if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw)) | ||
284 | return 0; | ||
285 | |||
286 | ndiv = CLKGEN_READ(pll, ndiv); | ||
287 | idf = CLKGEN_READ(pll, idf); | ||
288 | |||
289 | if (idf) | ||
290 | /* Note: input is divided to avoid overflow */ | ||
291 | rate = ((2 * (parent_rate/1000) * ndiv) / idf) * 1000; | ||
292 | |||
293 | pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate); | ||
294 | |||
295 | return rate; | ||
296 | } | ||
297 | |||
298 | unsigned long recalc_stm_pll1200c32(struct clk_hw *hw, | ||
299 | unsigned long parent_rate) | ||
300 | { | ||
301 | struct clkgen_pll *pll = to_clkgen_pll(hw); | ||
302 | unsigned long odf, ldf, idf; | ||
303 | unsigned long rate; | ||
304 | |||
305 | if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw)) | ||
306 | return 0; | ||
307 | |||
308 | odf = CLKGEN_READ(pll, odf[0]); | ||
309 | ldf = CLKGEN_READ(pll, ldf); | ||
310 | idf = CLKGEN_READ(pll, idf); | ||
311 | |||
312 | if (!idf) /* idf==0 means 1 */ | ||
313 | idf = 1; | ||
314 | if (!odf) /* odf==0 means 1 */ | ||
315 | odf = 1; | ||
316 | |||
317 | /* Note: input is divided by 1000 to avoid overflow */ | ||
318 | rate = (((parent_rate / 1000) * ldf) / (odf * idf)) * 1000; | ||
319 | |||
320 | pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate); | ||
321 | |||
322 | return rate; | ||
323 | } | ||
324 | |||
325 | static const struct clk_ops st_pll1600c65_ops = { | ||
326 | .is_enabled = clkgen_pll_is_enabled, | ||
327 | .recalc_rate = recalc_stm_pll1600c65, | ||
328 | }; | ||
329 | |||
330 | static const struct clk_ops st_pll800c65_ops = { | ||
331 | .is_enabled = clkgen_pll_is_enabled, | ||
332 | .recalc_rate = recalc_stm_pll800c65, | ||
333 | }; | ||
334 | |||
335 | static const struct clk_ops stm_pll3200c32_ops = { | ||
336 | .is_enabled = clkgen_pll_is_enabled, | ||
337 | .recalc_rate = recalc_stm_pll3200c32, | ||
338 | }; | ||
339 | |||
340 | static const struct clk_ops st_pll1200c32_ops = { | ||
341 | .is_enabled = clkgen_pll_is_enabled, | ||
342 | .recalc_rate = recalc_stm_pll1200c32, | ||
343 | }; | ||
344 | |||
345 | static struct clk * __init clkgen_pll_register(const char *parent_name, | ||
346 | struct clkgen_pll_data *pll_data, | ||
347 | void __iomem *reg, | ||
348 | const char *clk_name) | ||
349 | { | ||
350 | struct clkgen_pll *pll; | ||
351 | struct clk *clk; | ||
352 | struct clk_init_data init; | ||
353 | |||
354 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | ||
355 | if (!pll) | ||
356 | return ERR_PTR(-ENOMEM); | ||
357 | |||
358 | init.name = clk_name; | ||
359 | init.ops = pll_data->ops; | ||
360 | |||
361 | init.flags = CLK_IS_BASIC; | ||
362 | init.parent_names = &parent_name; | ||
363 | init.num_parents = 1; | ||
364 | |||
365 | pll->data = pll_data; | ||
366 | pll->regs_base = reg; | ||
367 | pll->hw.init = &init; | ||
368 | |||
369 | clk = clk_register(NULL, &pll->hw); | ||
370 | if (IS_ERR(clk)) { | ||
371 | kfree(pll); | ||
372 | return clk; | ||
373 | } | ||
374 | |||
375 | pr_debug("%s: parent %s rate %lu\n", | ||
376 | __clk_get_name(clk), | ||
377 | __clk_get_name(clk_get_parent(clk)), | ||
378 | clk_get_rate(clk)); | ||
379 | |||
380 | return clk; | ||
381 | } | ||
382 | |||
383 | static struct clk * __init clkgen_c65_lsdiv_register(const char *parent_name, | ||
384 | const char *clk_name) | ||
385 | { | ||
386 | struct clk *clk; | ||
387 | |||
388 | clk = clk_register_fixed_factor(NULL, clk_name, parent_name, 0, 1, 2); | ||
389 | if (IS_ERR(clk)) | ||
390 | return clk; | ||
391 | |||
392 | pr_debug("%s: parent %s rate %lu\n", | ||
393 | __clk_get_name(clk), | ||
394 | __clk_get_name(clk_get_parent(clk)), | ||
395 | clk_get_rate(clk)); | ||
396 | return clk; | ||
397 | } | ||
398 | |||
399 | static void __iomem * __init clkgen_get_register_base( | ||
400 | struct device_node *np) | ||
401 | { | ||
402 | struct device_node *pnode; | ||
403 | void __iomem *reg = NULL; | ||
404 | |||
405 | pnode = of_get_parent(np); | ||
406 | if (!pnode) | ||
407 | return NULL; | ||
408 | |||
409 | reg = of_iomap(pnode, 0); | ||
410 | |||
411 | of_node_put(pnode); | ||
412 | return reg; | ||
413 | } | ||
414 | |||
415 | #define CLKGENAx_PLL0_OFFSET 0x0 | ||
416 | #define CLKGENAx_PLL1_OFFSET 0x4 | ||
417 | |||
418 | static void __init clkgena_c65_pll_setup(struct device_node *np) | ||
419 | { | ||
420 | const int num_pll_outputs = 3; | ||
421 | struct clk_onecell_data *clk_data; | ||
422 | const char *parent_name; | ||
423 | void __iomem *reg; | ||
424 | const char *clk_name; | ||
425 | |||
426 | parent_name = of_clk_get_parent_name(np, 0); | ||
427 | if (!parent_name) | ||
428 | return; | ||
429 | |||
430 | reg = clkgen_get_register_base(np); | ||
431 | if (!reg) | ||
432 | return; | ||
433 | |||
434 | clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); | ||
435 | if (!clk_data) | ||
436 | return; | ||
437 | |||
438 | clk_data->clk_num = num_pll_outputs; | ||
439 | clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *), | ||
440 | GFP_KERNEL); | ||
441 | |||
442 | if (!clk_data->clks) | ||
443 | goto err; | ||
444 | |||
445 | if (of_property_read_string_index(np, "clock-output-names", | ||
446 | 0, &clk_name)) | ||
447 | goto err; | ||
448 | |||
449 | /* | ||
450 | * PLL0 HS (high speed) output | ||
451 | */ | ||
452 | clk_data->clks[0] = clkgen_pll_register(parent_name, | ||
453 | &st_pll1600c65_ax, | ||
454 | reg + CLKGENAx_PLL0_OFFSET, | ||
455 | clk_name); | ||
456 | |||
457 | if (IS_ERR(clk_data->clks[0])) | ||
458 | goto err; | ||
459 | |||
460 | if (of_property_read_string_index(np, "clock-output-names", | ||
461 | 1, &clk_name)) | ||
462 | goto err; | ||
463 | |||
464 | /* | ||
465 | * PLL0 LS (low speed) output, which is a fixed divide by 2 of the | ||
466 | * high speed output. | ||
467 | */ | ||
468 | clk_data->clks[1] = clkgen_c65_lsdiv_register(__clk_get_name | ||
469 | (clk_data->clks[0]), | ||
470 | clk_name); | ||
471 | |||
472 | if (IS_ERR(clk_data->clks[1])) | ||
473 | goto err; | ||
474 | |||
475 | if (of_property_read_string_index(np, "clock-output-names", | ||
476 | 2, &clk_name)) | ||
477 | goto err; | ||
478 | |||
479 | /* | ||
480 | * PLL1 output | ||
481 | */ | ||
482 | clk_data->clks[2] = clkgen_pll_register(parent_name, | ||
483 | &st_pll800c65_ax, | ||
484 | reg + CLKGENAx_PLL1_OFFSET, | ||
485 | clk_name); | ||
486 | |||
487 | if (IS_ERR(clk_data->clks[2])) | ||
488 | goto err; | ||
489 | |||
490 | of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); | ||
491 | return; | ||
492 | |||
493 | err: | ||
494 | kfree(clk_data->clks); | ||
495 | kfree(clk_data); | ||
496 | } | ||
497 | CLK_OF_DECLARE(clkgena_c65_plls, | ||
498 | "st,clkgena-plls-c65", clkgena_c65_pll_setup); | ||
499 | |||
500 | static struct clk * __init clkgen_odf_register(const char *parent_name, | ||
501 | void * __iomem reg, | ||
502 | struct clkgen_pll_data *pll_data, | ||
503 | int odf, | ||
504 | spinlock_t *odf_lock, | ||
505 | const char *odf_name) | ||
506 | { | ||
507 | struct clk *clk; | ||
508 | unsigned long flags; | ||
509 | struct clk_gate *gate; | ||
510 | struct clk_divider *div; | ||
511 | |||
512 | flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_GATE; | ||
513 | |||
514 | gate = kzalloc(sizeof(*gate), GFP_KERNEL); | ||
515 | if (!gate) | ||
516 | return ERR_PTR(-ENOMEM); | ||
517 | |||
518 | gate->flags = CLK_GATE_SET_TO_DISABLE; | ||
519 | gate->reg = reg + pll_data->odf_gate[odf].offset; | ||
520 | gate->bit_idx = pll_data->odf_gate[odf].shift; | ||
521 | gate->lock = odf_lock; | ||
522 | |||
523 | div = kzalloc(sizeof(*div), GFP_KERNEL); | ||
524 | if (!div) | ||
525 | return ERR_PTR(-ENOMEM); | ||
526 | |||
527 | div->flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO; | ||
528 | div->reg = reg + pll_data->odf[odf].offset; | ||
529 | div->shift = pll_data->odf[odf].shift; | ||
530 | div->width = fls(pll_data->odf[odf].mask); | ||
531 | div->lock = odf_lock; | ||
532 | |||
533 | clk = clk_register_composite(NULL, odf_name, &parent_name, 1, | ||
534 | NULL, NULL, | ||
535 | &div->hw, &clk_divider_ops, | ||
536 | &gate->hw, &clk_gate_ops, | ||
537 | flags); | ||
538 | if (IS_ERR(clk)) | ||
539 | return clk; | ||
540 | |||
541 | pr_debug("%s: parent %s rate %lu\n", | ||
542 | __clk_get_name(clk), | ||
543 | __clk_get_name(clk_get_parent(clk)), | ||
544 | clk_get_rate(clk)); | ||
545 | return clk; | ||
546 | } | ||
547 | |||
548 | static struct of_device_id c32_pll_of_match[] = { | ||
549 | { | ||
550 | .compatible = "st,plls-c32-a1x-0", | ||
551 | .data = &st_pll3200c32_a1x_0, | ||
552 | }, | ||
553 | { | ||
554 | .compatible = "st,plls-c32-a1x-1", | ||
555 | .data = &st_pll3200c32_a1x_1, | ||
556 | }, | ||
557 | { | ||
558 | .compatible = "st,stih415-plls-c32-a9", | ||
559 | .data = &st_pll3200c32_a9_415, | ||
560 | }, | ||
561 | { | ||
562 | .compatible = "st,stih415-plls-c32-ddr", | ||
563 | .data = &st_pll3200c32_ddr_415, | ||
564 | }, | ||
565 | { | ||
566 | .compatible = "st,stih416-plls-c32-a9", | ||
567 | .data = &st_pll3200c32_a9_416, | ||
568 | }, | ||
569 | { | ||
570 | .compatible = "st,stih416-plls-c32-ddr", | ||
571 | .data = &st_pll3200c32_ddr_416, | ||
572 | }, | ||
573 | {} | ||
574 | }; | ||
575 | |||
576 | static void __init clkgen_c32_pll_setup(struct device_node *np) | ||
577 | { | ||
578 | const struct of_device_id *match; | ||
579 | struct clk *clk; | ||
580 | const char *parent_name, *pll_name; | ||
581 | void __iomem *pll_base; | ||
582 | int num_odfs, odf; | ||
583 | struct clk_onecell_data *clk_data; | ||
584 | struct clkgen_pll_data *data; | ||
585 | |||
586 | match = of_match_node(c32_pll_of_match, np); | ||
587 | if (!match) { | ||
588 | pr_err("%s: No matching data\n", __func__); | ||
589 | return; | ||
590 | } | ||
591 | |||
592 | data = (struct clkgen_pll_data *) match->data; | ||
593 | |||
594 | parent_name = of_clk_get_parent_name(np, 0); | ||
595 | if (!parent_name) | ||
596 | return; | ||
597 | |||
598 | pll_base = clkgen_get_register_base(np); | ||
599 | if (!pll_base) | ||
600 | return; | ||
601 | |||
602 | clk = clkgen_pll_register(parent_name, data, pll_base, np->name); | ||
603 | if (IS_ERR(clk)) | ||
604 | return; | ||
605 | |||
606 | pll_name = __clk_get_name(clk); | ||
607 | |||
608 | num_odfs = data->num_odfs; | ||
609 | |||
610 | clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); | ||
611 | if (!clk_data) | ||
612 | return; | ||
613 | |||
614 | clk_data->clk_num = num_odfs; | ||
615 | clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *), | ||
616 | GFP_KERNEL); | ||
617 | |||
618 | if (!clk_data->clks) | ||
619 | goto err; | ||
620 | |||
621 | for (odf = 0; odf < num_odfs; odf++) { | ||
622 | struct clk *clk; | ||
623 | const char *clk_name; | ||
624 | |||
625 | if (of_property_read_string_index(np, "clock-output-names", | ||
626 | odf, &clk_name)) | ||
627 | return; | ||
628 | |||
629 | clk = clkgen_odf_register(pll_name, pll_base, data, | ||
630 | odf, &clkgena_c32_odf_lock, clk_name); | ||
631 | if (IS_ERR(clk)) | ||
632 | goto err; | ||
633 | |||
634 | clk_data->clks[odf] = clk; | ||
635 | } | ||
636 | |||
637 | of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); | ||
638 | return; | ||
639 | |||
640 | err: | ||
641 | kfree(pll_name); | ||
642 | kfree(clk_data->clks); | ||
643 | kfree(clk_data); | ||
644 | } | ||
645 | CLK_OF_DECLARE(clkgen_c32_pll, "st,clkgen-plls-c32", clkgen_c32_pll_setup); | ||
646 | |||
647 | static struct of_device_id c32_gpu_pll_of_match[] = { | ||
648 | { | ||
649 | .compatible = "st,stih415-gpu-pll-c32", | ||
650 | .data = &st_pll1200c32_gpu_415, | ||
651 | }, | ||
652 | { | ||
653 | .compatible = "st,stih416-gpu-pll-c32", | ||
654 | .data = &st_pll1200c32_gpu_416, | ||
655 | }, | ||
656 | }; | ||
657 | |||
658 | static void __init clkgengpu_c32_pll_setup(struct device_node *np) | ||
659 | { | ||
660 | const struct of_device_id *match; | ||
661 | struct clk *clk; | ||
662 | const char *parent_name; | ||
663 | void __iomem *reg; | ||
664 | const char *clk_name; | ||
665 | struct clkgen_pll_data *data; | ||
666 | |||
667 | match = of_match_node(c32_gpu_pll_of_match, np); | ||
668 | if (!match) { | ||
669 | pr_err("%s: No matching data\n", __func__); | ||
670 | return; | ||
671 | } | ||
672 | |||
673 | data = (struct clkgen_pll_data *)match->data; | ||
674 | |||
675 | parent_name = of_clk_get_parent_name(np, 0); | ||
676 | if (!parent_name) | ||
677 | return; | ||
678 | |||
679 | reg = clkgen_get_register_base(np); | ||
680 | if (!reg) | ||
681 | return; | ||
682 | |||
683 | if (of_property_read_string_index(np, "clock-output-names", | ||
684 | 0, &clk_name)) | ||
685 | return; | ||
686 | |||
687 | /* | ||
688 | * PLL 1200MHz output | ||
689 | */ | ||
690 | clk = clkgen_pll_register(parent_name, data, reg, clk_name); | ||
691 | |||
692 | if (!IS_ERR(clk)) | ||
693 | of_clk_add_provider(np, of_clk_src_simple_get, clk); | ||
694 | |||
695 | return; | ||
696 | } | ||
697 | CLK_OF_DECLARE(clkgengpu_c32_pll, | ||
698 | "st,clkgengpu-pll-c32", clkgengpu_c32_pll_setup); | ||
diff --git a/drivers/clk/st/clkgen.h b/drivers/clk/st/clkgen.h new file mode 100644 index 000000000000..35c863295268 --- /dev/null +++ b/drivers/clk/st/clkgen.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /************************************************************************ | ||
2 | File : Clock H/w specific Information | ||
3 | |||
4 | Author: Pankaj Dev <pankaj.dev@st.com> | ||
5 | |||
6 | Copyright (C) 2014 STMicroelectronics | ||
7 | ************************************************************************/ | ||
8 | |||
9 | #ifndef __CLKGEN_INFO_H | ||
10 | #define __CLKGEN_INFO_H | ||
11 | |||
12 | struct clkgen_field { | ||
13 | unsigned int offset; | ||
14 | unsigned int mask; | ||
15 | unsigned int shift; | ||
16 | }; | ||
17 | |||
18 | static inline unsigned long clkgen_read(void __iomem *base, | ||
19 | struct clkgen_field *field) | ||
20 | { | ||
21 | return (readl(base + field->offset) >> field->shift) & field->mask; | ||
22 | } | ||
23 | |||
24 | |||
25 | static inline void clkgen_write(void __iomem *base, struct clkgen_field *field, | ||
26 | unsigned long val) | ||
27 | { | ||
28 | writel((readl(base + field->offset) & | ||
29 | ~(field->mask << field->shift)) | (val << field->shift), | ||
30 | base + field->offset); | ||
31 | |||
32 | return; | ||
33 | } | ||
34 | |||
35 | #define CLKGEN_FIELD(_offset, _mask, _shift) { \ | ||
36 | .offset = _offset, \ | ||
37 | .mask = _mask, \ | ||
38 | .shift = _shift, \ | ||
39 | } | ||
40 | |||
41 | #define CLKGEN_READ(pll, field) clkgen_read(pll->regs_base, \ | ||
42 | &pll->data->field) | ||
43 | |||
44 | #define CLKGEN_WRITE(pll, field, val) clkgen_write(pll->regs_base, \ | ||
45 | &pll->data->field, val) | ||
46 | |||
47 | #endif /*__CLKGEN_INFO_H*/ | ||
48 | |||
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index abb6c5ac8a10..bd7dc733c1ca 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/clkdev.h> | 18 | #include <linux/clkdev.h> |
19 | #include <linux/of.h> | 19 | #include <linux/of.h> |
20 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
21 | #include <linux/reset-controller.h> | ||
21 | 22 | ||
22 | #include "clk-factors.h" | 23 | #include "clk-factors.h" |
23 | 24 | ||
@@ -51,6 +52,8 @@ static void __init sun4i_osc_clk_setup(struct device_node *node) | |||
51 | if (!gate) | 52 | if (!gate) |
52 | goto err_free_fixed; | 53 | goto err_free_fixed; |
53 | 54 | ||
55 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
56 | |||
54 | /* set up gate and fixed rate properties */ | 57 | /* set up gate and fixed rate properties */ |
55 | gate->reg = of_iomap(node, 0); | 58 | gate->reg = of_iomap(node, 0); |
56 | gate->bit_idx = SUNXI_OSC24M_GATE; | 59 | gate->bit_idx = SUNXI_OSC24M_GATE; |
@@ -77,7 +80,7 @@ err_free_gate: | |||
77 | err_free_fixed: | 80 | err_free_fixed: |
78 | kfree(fixed); | 81 | kfree(fixed); |
79 | } | 82 | } |
80 | CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-osc-clk", sun4i_osc_clk_setup); | 83 | CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-a10-osc-clk", sun4i_osc_clk_setup); |
81 | 84 | ||
82 | 85 | ||
83 | 86 | ||
@@ -249,7 +252,38 @@ static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate, | |||
249 | *n = DIV_ROUND_UP(div, (*k+1)); | 252 | *n = DIV_ROUND_UP(div, (*k+1)); |
250 | } | 253 | } |
251 | 254 | ||
255 | /** | ||
256 | * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6 | ||
257 | * PLL6 rate is calculated as follows | ||
258 | * rate = parent_rate * n * (k + 1) / 2 | ||
259 | * parent_rate is always 24Mhz | ||
260 | */ | ||
261 | |||
262 | static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate, | ||
263 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
264 | { | ||
265 | u8 div; | ||
266 | |||
267 | /* | ||
268 | * We always have 24MHz / 2, so we can just say that our | ||
269 | * parent clock is 12MHz. | ||
270 | */ | ||
271 | parent_rate = parent_rate / 2; | ||
252 | 272 | ||
273 | /* Normalize value to a parent_rate multiple (24M / 2) */ | ||
274 | div = *freq / parent_rate; | ||
275 | *freq = parent_rate * div; | ||
276 | |||
277 | /* we were called to round the frequency, we can now return */ | ||
278 | if (n == NULL) | ||
279 | return; | ||
280 | |||
281 | *k = div / 32; | ||
282 | if (*k > 3) | ||
283 | *k = 3; | ||
284 | |||
285 | *n = DIV_ROUND_UP(div, (*k+1)); | ||
286 | } | ||
253 | 287 | ||
254 | /** | 288 | /** |
255 | * sun4i_get_apb1_factors() - calculates m, p factors for APB1 | 289 | * sun4i_get_apb1_factors() - calculates m, p factors for APB1 |
@@ -265,7 +299,7 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate, | |||
265 | if (parent_rate < *freq) | 299 | if (parent_rate < *freq) |
266 | *freq = parent_rate; | 300 | *freq = parent_rate; |
267 | 301 | ||
268 | parent_rate = (parent_rate + (*freq - 1)) / *freq; | 302 | parent_rate = DIV_ROUND_UP(parent_rate, *freq); |
269 | 303 | ||
270 | /* Invalid rate! */ | 304 | /* Invalid rate! */ |
271 | if (parent_rate > 32) | 305 | if (parent_rate > 32) |
@@ -296,7 +330,7 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate, | |||
296 | 330 | ||
297 | /** | 331 | /** |
298 | * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks | 332 | * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks |
299 | * MMC rate is calculated as follows | 333 | * MOD0 rate is calculated as follows |
300 | * rate = (parent_rate >> p) / (m + 1); | 334 | * rate = (parent_rate >> p) / (m + 1); |
301 | */ | 335 | */ |
302 | 336 | ||
@@ -310,7 +344,7 @@ static void sun4i_get_mod0_factors(u32 *freq, u32 parent_rate, | |||
310 | if (*freq > parent_rate) | 344 | if (*freq > parent_rate) |
311 | *freq = parent_rate; | 345 | *freq = parent_rate; |
312 | 346 | ||
313 | div = parent_rate / *freq; | 347 | div = DIV_ROUND_UP(parent_rate, *freq); |
314 | 348 | ||
315 | if (div < 16) | 349 | if (div < 16) |
316 | calcp = 0; | 350 | calcp = 0; |
@@ -351,7 +385,7 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate, | |||
351 | if (*freq > parent_rate) | 385 | if (*freq > parent_rate) |
352 | *freq = parent_rate; | 386 | *freq = parent_rate; |
353 | 387 | ||
354 | div = parent_rate / *freq; | 388 | div = DIV_ROUND_UP(parent_rate, *freq); |
355 | 389 | ||
356 | if (div < 32) | 390 | if (div < 32) |
357 | calcp = 0; | 391 | calcp = 0; |
@@ -377,6 +411,102 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate, | |||
377 | 411 | ||
378 | 412 | ||
379 | /** | 413 | /** |
414 | * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module | ||
415 | * | ||
416 | * This clock looks something like this | ||
417 | * ________________________ | ||
418 | * MII TX clock from PHY >-----|___________ _________|----> to GMAC core | ||
419 | * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY | ||
420 | * Ext. 125MHz RGMII TX clk >--|__divider__/ | | ||
421 | * |________________________| | ||
422 | * | ||
423 | * The external 125 MHz reference is optional, i.e. GMAC can use its | ||
424 | * internal TX clock just fine. The A31 GMAC clock module does not have | ||
425 | * the divider controls for the external reference. | ||
426 | * | ||
427 | * To keep it simple, let the GMAC use either the MII TX clock for MII mode, | ||
428 | * and its internal TX clock for GMII and RGMII modes. The GMAC driver should | ||
429 | * select the appropriate source and gate/ungate the output to the PHY. | ||
430 | * | ||
431 | * Only the GMAC should use this clock. Altering the clock so that it doesn't | ||
432 | * match the GMAC's operation parameters will result in the GMAC not being | ||
433 | * able to send traffic out. The GMAC driver should set the clock rate and | ||
434 | * enable/disable this clock to configure the required state. The clock | ||
435 | * driver then responds by auto-reparenting the clock. | ||
436 | */ | ||
437 | |||
438 | #define SUN7I_A20_GMAC_GPIT 2 | ||
439 | #define SUN7I_A20_GMAC_MASK 0x3 | ||
440 | #define SUN7I_A20_GMAC_PARENTS 2 | ||
441 | |||
442 | static void __init sun7i_a20_gmac_clk_setup(struct device_node *node) | ||
443 | { | ||
444 | struct clk *clk; | ||
445 | struct clk_mux *mux; | ||
446 | struct clk_gate *gate; | ||
447 | const char *clk_name = node->name; | ||
448 | const char *parents[SUN7I_A20_GMAC_PARENTS]; | ||
449 | void *reg; | ||
450 | |||
451 | if (of_property_read_string(node, "clock-output-names", &clk_name)) | ||
452 | return; | ||
453 | |||
454 | /* allocate mux and gate clock structs */ | ||
455 | mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); | ||
456 | if (!mux) | ||
457 | return; | ||
458 | |||
459 | gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); | ||
460 | if (!gate) | ||
461 | goto free_mux; | ||
462 | |||
463 | /* gmac clock requires exactly 2 parents */ | ||
464 | parents[0] = of_clk_get_parent_name(node, 0); | ||
465 | parents[1] = of_clk_get_parent_name(node, 1); | ||
466 | if (!parents[0] || !parents[1]) | ||
467 | goto free_gate; | ||
468 | |||
469 | reg = of_iomap(node, 0); | ||
470 | if (!reg) | ||
471 | goto free_gate; | ||
472 | |||
473 | /* set up gate and fixed rate properties */ | ||
474 | gate->reg = reg; | ||
475 | gate->bit_idx = SUN7I_A20_GMAC_GPIT; | ||
476 | gate->lock = &clk_lock; | ||
477 | mux->reg = reg; | ||
478 | mux->mask = SUN7I_A20_GMAC_MASK; | ||
479 | mux->flags = CLK_MUX_INDEX_BIT; | ||
480 | mux->lock = &clk_lock; | ||
481 | |||
482 | clk = clk_register_composite(NULL, clk_name, | ||
483 | parents, SUN7I_A20_GMAC_PARENTS, | ||
484 | &mux->hw, &clk_mux_ops, | ||
485 | NULL, NULL, | ||
486 | &gate->hw, &clk_gate_ops, | ||
487 | 0); | ||
488 | |||
489 | if (IS_ERR(clk)) | ||
490 | goto iounmap_reg; | ||
491 | |||
492 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
493 | clk_register_clkdev(clk, clk_name, NULL); | ||
494 | |||
495 | return; | ||
496 | |||
497 | iounmap_reg: | ||
498 | iounmap(reg); | ||
499 | free_gate: | ||
500 | kfree(gate); | ||
501 | free_mux: | ||
502 | kfree(mux); | ||
503 | } | ||
504 | CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk", | ||
505 | sun7i_a20_gmac_clk_setup); | ||
506 | |||
507 | |||
508 | |||
509 | /** | ||
380 | * sunxi_factors_clk_setup() - Setup function for factor clocks | 510 | * sunxi_factors_clk_setup() - Setup function for factor clocks |
381 | */ | 511 | */ |
382 | 512 | ||
@@ -387,6 +517,7 @@ struct factors_data { | |||
387 | int mux; | 517 | int mux; |
388 | struct clk_factors_config *table; | 518 | struct clk_factors_config *table; |
389 | void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); | 519 | void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); |
520 | const char *name; | ||
390 | }; | 521 | }; |
391 | 522 | ||
392 | static struct clk_factors_config sun4i_pll1_config = { | 523 | static struct clk_factors_config sun4i_pll1_config = { |
@@ -416,6 +547,13 @@ static struct clk_factors_config sun4i_pll5_config = { | |||
416 | .kwidth = 2, | 547 | .kwidth = 2, |
417 | }; | 548 | }; |
418 | 549 | ||
550 | static struct clk_factors_config sun6i_a31_pll6_config = { | ||
551 | .nshift = 8, | ||
552 | .nwidth = 5, | ||
553 | .kshift = 4, | ||
554 | .kwidth = 2, | ||
555 | }; | ||
556 | |||
419 | static struct clk_factors_config sun4i_apb1_config = { | 557 | static struct clk_factors_config sun4i_apb1_config = { |
420 | .mshift = 0, | 558 | .mshift = 0, |
421 | .mwidth = 5, | 559 | .mwidth = 5, |
@@ -451,10 +589,30 @@ static const struct factors_data sun6i_a31_pll1_data __initconst = { | |||
451 | .getter = sun6i_a31_get_pll1_factors, | 589 | .getter = sun6i_a31_get_pll1_factors, |
452 | }; | 590 | }; |
453 | 591 | ||
592 | static const struct factors_data sun7i_a20_pll4_data __initconst = { | ||
593 | .enable = 31, | ||
594 | .table = &sun4i_pll5_config, | ||
595 | .getter = sun4i_get_pll5_factors, | ||
596 | }; | ||
597 | |||
454 | static const struct factors_data sun4i_pll5_data __initconst = { | 598 | static const struct factors_data sun4i_pll5_data __initconst = { |
455 | .enable = 31, | 599 | .enable = 31, |
456 | .table = &sun4i_pll5_config, | 600 | .table = &sun4i_pll5_config, |
457 | .getter = sun4i_get_pll5_factors, | 601 | .getter = sun4i_get_pll5_factors, |
602 | .name = "pll5", | ||
603 | }; | ||
604 | |||
605 | static const struct factors_data sun4i_pll6_data __initconst = { | ||
606 | .enable = 31, | ||
607 | .table = &sun4i_pll5_config, | ||
608 | .getter = sun4i_get_pll5_factors, | ||
609 | .name = "pll6", | ||
610 | }; | ||
611 | |||
612 | static const struct factors_data sun6i_a31_pll6_data __initconst = { | ||
613 | .enable = 31, | ||
614 | .table = &sun6i_a31_pll6_config, | ||
615 | .getter = sun6i_a31_get_pll6_factors, | ||
458 | }; | 616 | }; |
459 | 617 | ||
460 | static const struct factors_data sun4i_apb1_data __initconst = { | 618 | static const struct factors_data sun4i_apb1_data __initconst = { |
@@ -497,14 +655,14 @@ static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, | |||
497 | (parents[i] = of_clk_get_parent_name(node, i)) != NULL) | 655 | (parents[i] = of_clk_get_parent_name(node, i)) != NULL) |
498 | i++; | 656 | i++; |
499 | 657 | ||
500 | /* Nodes should be providing the name via clock-output-names | 658 | /* |
501 | * but originally our dts didn't, and so we used node->name. | 659 | * some factor clocks, such as pll5 and pll6, may have multiple |
502 | * The new, better nodes look like clk@deadbeef, so we pull the | 660 | * outputs, and have their name designated in factors_data |
503 | * name just in this case */ | 661 | */ |
504 | if (!strcmp("clk", clk_name)) { | 662 | if (data->name) |
505 | of_property_read_string_index(node, "clock-output-names", | 663 | clk_name = data->name; |
506 | 0, &clk_name); | 664 | else |
507 | } | 665 | of_property_read_string(node, "clock-output-names", &clk_name); |
508 | 666 | ||
509 | factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL); | 667 | factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL); |
510 | if (!factors) | 668 | if (!factors) |
@@ -601,6 +759,8 @@ static void __init sunxi_mux_clk_setup(struct device_node *node, | |||
601 | (parents[i] = of_clk_get_parent_name(node, i)) != NULL) | 759 | (parents[i] = of_clk_get_parent_name(node, i)) != NULL) |
602 | i++; | 760 | i++; |
603 | 761 | ||
762 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
763 | |||
604 | clk = clk_register_mux(NULL, clk_name, parents, i, | 764 | clk = clk_register_mux(NULL, clk_name, parents, i, |
605 | CLK_SET_RATE_NO_REPARENT, reg, | 765 | CLK_SET_RATE_NO_REPARENT, reg, |
606 | data->shift, SUNXI_MUX_GATE_WIDTH, | 766 | data->shift, SUNXI_MUX_GATE_WIDTH, |
@@ -660,6 +820,8 @@ static void __init sunxi_divider_clk_setup(struct device_node *node, | |||
660 | 820 | ||
661 | clk_parent = of_clk_get_parent_name(node, 0); | 821 | clk_parent = of_clk_get_parent_name(node, 0); |
662 | 822 | ||
823 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
824 | |||
663 | clk = clk_register_divider(NULL, clk_name, clk_parent, 0, | 825 | clk = clk_register_divider(NULL, clk_name, clk_parent, 0, |
664 | reg, data->shift, data->width, | 826 | reg, data->shift, data->width, |
665 | data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0, | 827 | data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0, |
@@ -673,6 +835,59 @@ static void __init sunxi_divider_clk_setup(struct device_node *node, | |||
673 | 835 | ||
674 | 836 | ||
675 | /** | 837 | /** |
838 | * sunxi_gates_reset... - reset bits in leaf gate clk registers handling | ||
839 | */ | ||
840 | |||
841 | struct gates_reset_data { | ||
842 | void __iomem *reg; | ||
843 | spinlock_t *lock; | ||
844 | struct reset_controller_dev rcdev; | ||
845 | }; | ||
846 | |||
847 | static int sunxi_gates_reset_assert(struct reset_controller_dev *rcdev, | ||
848 | unsigned long id) | ||
849 | { | ||
850 | struct gates_reset_data *data = container_of(rcdev, | ||
851 | struct gates_reset_data, | ||
852 | rcdev); | ||
853 | unsigned long flags; | ||
854 | u32 reg; | ||
855 | |||
856 | spin_lock_irqsave(data->lock, flags); | ||
857 | |||
858 | reg = readl(data->reg); | ||
859 | writel(reg & ~BIT(id), data->reg); | ||
860 | |||
861 | spin_unlock_irqrestore(data->lock, flags); | ||
862 | |||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | static int sunxi_gates_reset_deassert(struct reset_controller_dev *rcdev, | ||
867 | unsigned long id) | ||
868 | { | ||
869 | struct gates_reset_data *data = container_of(rcdev, | ||
870 | struct gates_reset_data, | ||
871 | rcdev); | ||
872 | unsigned long flags; | ||
873 | u32 reg; | ||
874 | |||
875 | spin_lock_irqsave(data->lock, flags); | ||
876 | |||
877 | reg = readl(data->reg); | ||
878 | writel(reg | BIT(id), data->reg); | ||
879 | |||
880 | spin_unlock_irqrestore(data->lock, flags); | ||
881 | |||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | static struct reset_control_ops sunxi_gates_reset_ops = { | ||
886 | .assert = sunxi_gates_reset_assert, | ||
887 | .deassert = sunxi_gates_reset_deassert, | ||
888 | }; | ||
889 | |||
890 | /** | ||
676 | * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks | 891 | * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks |
677 | */ | 892 | */ |
678 | 893 | ||
@@ -680,6 +895,7 @@ static void __init sunxi_divider_clk_setup(struct device_node *node, | |||
680 | 895 | ||
681 | struct gates_data { | 896 | struct gates_data { |
682 | DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE); | 897 | DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE); |
898 | u32 reset_mask; | ||
683 | }; | 899 | }; |
684 | 900 | ||
685 | static const struct gates_data sun4i_axi_gates_data __initconst = { | 901 | static const struct gates_data sun4i_axi_gates_data __initconst = { |
@@ -746,10 +962,21 @@ static const struct gates_data sun7i_a20_apb1_gates_data __initconst = { | |||
746 | .mask = { 0xff80ff }, | 962 | .mask = { 0xff80ff }, |
747 | }; | 963 | }; |
748 | 964 | ||
965 | static const struct gates_data sun4i_a10_usb_gates_data __initconst = { | ||
966 | .mask = {0x1C0}, | ||
967 | .reset_mask = 0x07, | ||
968 | }; | ||
969 | |||
970 | static const struct gates_data sun5i_a13_usb_gates_data __initconst = { | ||
971 | .mask = {0x140}, | ||
972 | .reset_mask = 0x03, | ||
973 | }; | ||
974 | |||
749 | static void __init sunxi_gates_clk_setup(struct device_node *node, | 975 | static void __init sunxi_gates_clk_setup(struct device_node *node, |
750 | struct gates_data *data) | 976 | struct gates_data *data) |
751 | { | 977 | { |
752 | struct clk_onecell_data *clk_data; | 978 | struct clk_onecell_data *clk_data; |
979 | struct gates_reset_data *reset_data; | ||
753 | const char *clk_parent; | 980 | const char *clk_parent; |
754 | const char *clk_name; | 981 | const char *clk_name; |
755 | void *reg; | 982 | void *reg; |
@@ -793,6 +1020,21 @@ static void __init sunxi_gates_clk_setup(struct device_node *node, | |||
793 | clk_data->clk_num = i; | 1020 | clk_data->clk_num = i; |
794 | 1021 | ||
795 | of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); | 1022 | of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); |
1023 | |||
1024 | /* Register a reset controler for gates with reset bits */ | ||
1025 | if (data->reset_mask == 0) | ||
1026 | return; | ||
1027 | |||
1028 | reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL); | ||
1029 | if (!reset_data) | ||
1030 | return; | ||
1031 | |||
1032 | reset_data->reg = reg; | ||
1033 | reset_data->lock = &clk_lock; | ||
1034 | reset_data->rcdev.nr_resets = __fls(data->reset_mask) + 1; | ||
1035 | reset_data->rcdev.ops = &sunxi_gates_reset_ops; | ||
1036 | reset_data->rcdev.of_node = node; | ||
1037 | reset_controller_register(&reset_data->rcdev); | ||
796 | } | 1038 | } |
797 | 1039 | ||
798 | 1040 | ||
@@ -832,7 +1074,7 @@ static const struct divs_data pll5_divs_data __initconst = { | |||
832 | }; | 1074 | }; |
833 | 1075 | ||
834 | static const struct divs_data pll6_divs_data __initconst = { | 1076 | static const struct divs_data pll6_divs_data __initconst = { |
835 | .factors = &sun4i_pll5_data, | 1077 | .factors = &sun4i_pll6_data, |
836 | .div = { | 1078 | .div = { |
837 | { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ | 1079 | { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ |
838 | { .fixed = 2 }, /* P, other */ | 1080 | { .fixed = 2 }, /* P, other */ |
@@ -854,7 +1096,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, | |||
854 | struct divs_data *data) | 1096 | struct divs_data *data) |
855 | { | 1097 | { |
856 | struct clk_onecell_data *clk_data; | 1098 | struct clk_onecell_data *clk_data; |
857 | const char *parent = node->name; | 1099 | const char *parent; |
858 | const char *clk_name; | 1100 | const char *clk_name; |
859 | struct clk **clks, *pclk; | 1101 | struct clk **clks, *pclk; |
860 | struct clk_hw *gate_hw, *rate_hw; | 1102 | struct clk_hw *gate_hw, *rate_hw; |
@@ -868,6 +1110,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, | |||
868 | 1110 | ||
869 | /* Set up factor clock that we will be dividing */ | 1111 | /* Set up factor clock that we will be dividing */ |
870 | pclk = sunxi_factors_clk_setup(node, data->factors); | 1112 | pclk = sunxi_factors_clk_setup(node, data->factors); |
1113 | parent = __clk_get_name(pclk); | ||
871 | 1114 | ||
872 | reg = of_iomap(node, 0); | 1115 | reg = of_iomap(node, 0); |
873 | 1116 | ||
@@ -970,56 +1213,60 @@ free_clkdata: | |||
970 | 1213 | ||
971 | /* Matches for factors clocks */ | 1214 | /* Matches for factors clocks */ |
972 | static const struct of_device_id clk_factors_match[] __initconst = { | 1215 | static const struct of_device_id clk_factors_match[] __initconst = { |
973 | {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,}, | 1216 | {.compatible = "allwinner,sun4i-a10-pll1-clk", .data = &sun4i_pll1_data,}, |
974 | {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, | 1217 | {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, |
975 | {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, | 1218 | {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,}, |
976 | {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,}, | 1219 | {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,}, |
1220 | {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,}, | ||
1221 | {.compatible = "allwinner,sun4i-a10-mod0-clk", .data = &sun4i_mod0_data,}, | ||
977 | {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, | 1222 | {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, |
978 | {} | 1223 | {} |
979 | }; | 1224 | }; |
980 | 1225 | ||
981 | /* Matches for divider clocks */ | 1226 | /* Matches for divider clocks */ |
982 | static const struct of_device_id clk_div_match[] __initconst = { | 1227 | static const struct of_device_id clk_div_match[] __initconst = { |
983 | {.compatible = "allwinner,sun4i-axi-clk", .data = &sun4i_axi_data,}, | 1228 | {.compatible = "allwinner,sun4i-a10-axi-clk", .data = &sun4i_axi_data,}, |
984 | {.compatible = "allwinner,sun4i-ahb-clk", .data = &sun4i_ahb_data,}, | 1229 | {.compatible = "allwinner,sun4i-a10-ahb-clk", .data = &sun4i_ahb_data,}, |
985 | {.compatible = "allwinner,sun4i-apb0-clk", .data = &sun4i_apb0_data,}, | 1230 | {.compatible = "allwinner,sun4i-a10-apb0-clk", .data = &sun4i_apb0_data,}, |
986 | {.compatible = "allwinner,sun6i-a31-apb2-div-clk", .data = &sun6i_a31_apb2_div_data,}, | 1231 | {.compatible = "allwinner,sun6i-a31-apb2-div-clk", .data = &sun6i_a31_apb2_div_data,}, |
987 | {} | 1232 | {} |
988 | }; | 1233 | }; |
989 | 1234 | ||
990 | /* Matches for divided outputs */ | 1235 | /* Matches for divided outputs */ |
991 | static const struct of_device_id clk_divs_match[] __initconst = { | 1236 | static const struct of_device_id clk_divs_match[] __initconst = { |
992 | {.compatible = "allwinner,sun4i-pll5-clk", .data = &pll5_divs_data,}, | 1237 | {.compatible = "allwinner,sun4i-a10-pll5-clk", .data = &pll5_divs_data,}, |
993 | {.compatible = "allwinner,sun4i-pll6-clk", .data = &pll6_divs_data,}, | 1238 | {.compatible = "allwinner,sun4i-a10-pll6-clk", .data = &pll6_divs_data,}, |
994 | {} | 1239 | {} |
995 | }; | 1240 | }; |
996 | 1241 | ||
997 | /* Matches for mux clocks */ | 1242 | /* Matches for mux clocks */ |
998 | static const struct of_device_id clk_mux_match[] __initconst = { | 1243 | static const struct of_device_id clk_mux_match[] __initconst = { |
999 | {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,}, | 1244 | {.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,}, |
1000 | {.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &sun4i_apb1_mux_data,}, | 1245 | {.compatible = "allwinner,sun4i-a10-apb1-mux-clk", .data = &sun4i_apb1_mux_data,}, |
1001 | {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,}, | 1246 | {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,}, |
1002 | {} | 1247 | {} |
1003 | }; | 1248 | }; |
1004 | 1249 | ||
1005 | /* Matches for gate clocks */ | 1250 | /* Matches for gate clocks */ |
1006 | static const struct of_device_id clk_gates_match[] __initconst = { | 1251 | static const struct of_device_id clk_gates_match[] __initconst = { |
1007 | {.compatible = "allwinner,sun4i-axi-gates-clk", .data = &sun4i_axi_gates_data,}, | 1252 | {.compatible = "allwinner,sun4i-a10-axi-gates-clk", .data = &sun4i_axi_gates_data,}, |
1008 | {.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,}, | 1253 | {.compatible = "allwinner,sun4i-a10-ahb-gates-clk", .data = &sun4i_ahb_gates_data,}, |
1009 | {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,}, | 1254 | {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,}, |
1010 | {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,}, | 1255 | {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,}, |
1011 | {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,}, | 1256 | {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,}, |
1012 | {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,}, | 1257 | {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,}, |
1013 | {.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &sun4i_apb0_gates_data,}, | 1258 | {.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,}, |
1014 | {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,}, | 1259 | {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,}, |
1015 | {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,}, | 1260 | {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,}, |
1016 | {.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,}, | 1261 | {.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,}, |
1017 | {.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &sun4i_apb1_gates_data,}, | 1262 | {.compatible = "allwinner,sun4i-a10-apb1-gates-clk", .data = &sun4i_apb1_gates_data,}, |
1018 | {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,}, | 1263 | {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,}, |
1019 | {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,}, | 1264 | {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,}, |
1020 | {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,}, | 1265 | {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,}, |
1021 | {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,}, | 1266 | {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,}, |
1022 | {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, | 1267 | {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, |
1268 | {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,}, | ||
1269 | {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,}, | ||
1023 | {} | 1270 | {} |
1024 | }; | 1271 | }; |
1025 | 1272 | ||
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index 356e9b804421..9e899c18af86 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c | |||
@@ -130,7 +130,7 @@ static const struct clk_ops tegra_clk_periph_nodiv_ops = { | |||
130 | .disable = clk_periph_disable, | 130 | .disable = clk_periph_disable, |
131 | }; | 131 | }; |
132 | 132 | ||
133 | const struct clk_ops tegra_clk_periph_no_gate_ops = { | 133 | static const struct clk_ops tegra_clk_periph_no_gate_ops = { |
134 | .get_parent = clk_periph_get_parent, | 134 | .get_parent = clk_periph_get_parent, |
135 | .set_parent = clk_periph_set_parent, | 135 | .set_parent = clk_periph_set_parent, |
136 | .recalc_rate = clk_periph_recalc_rate, | 136 | .recalc_rate = clk_periph_recalc_rate, |
diff --git a/drivers/clk/ti/clk-33xx.c b/drivers/clk/ti/clk-33xx.c index 776ee4594bd4..028b33783d38 100644 --- a/drivers/clk/ti/clk-33xx.c +++ b/drivers/clk/ti/clk-33xx.c | |||
@@ -34,7 +34,6 @@ static struct ti_dt_clk am33xx_clks[] = { | |||
34 | DT_CLK(NULL, "dpll_core_m5_ck", "dpll_core_m5_ck"), | 34 | DT_CLK(NULL, "dpll_core_m5_ck", "dpll_core_m5_ck"), |
35 | DT_CLK(NULL, "dpll_core_m6_ck", "dpll_core_m6_ck"), | 35 | DT_CLK(NULL, "dpll_core_m6_ck", "dpll_core_m6_ck"), |
36 | DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"), | 36 | DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"), |
37 | DT_CLK("cpu0", NULL, "dpll_mpu_ck"), | ||
38 | DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"), | 37 | DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"), |
39 | DT_CLK(NULL, "dpll_ddr_ck", "dpll_ddr_ck"), | 38 | DT_CLK(NULL, "dpll_ddr_ck", "dpll_ddr_ck"), |
40 | DT_CLK(NULL, "dpll_ddr_m2_ck", "dpll_ddr_m2_ck"), | 39 | DT_CLK(NULL, "dpll_ddr_m2_ck", "dpll_ddr_m2_ck"), |
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index a15e445570b2..e6aa10db7bba 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c | |||
@@ -112,7 +112,7 @@ static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw, | |||
112 | return parent_rate; | 112 | return parent_rate; |
113 | } | 113 | } |
114 | 114 | ||
115 | return parent_rate / div; | 115 | return DIV_ROUND_UP(parent_rate, div); |
116 | } | 116 | } |
117 | 117 | ||
118 | /* | 118 | /* |
@@ -182,7 +182,7 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, | |||
182 | } | 182 | } |
183 | parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), | 183 | parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), |
184 | MULT_ROUND_UP(rate, i)); | 184 | MULT_ROUND_UP(rate, i)); |
185 | now = parent_rate / i; | 185 | now = DIV_ROUND_UP(parent_rate, i); |
186 | if (now <= rate && now > best) { | 186 | if (now <= rate && now > best) { |
187 | bestdiv = i; | 187 | bestdiv = i; |
188 | best = now; | 188 | best = now; |
@@ -205,7 +205,7 @@ static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, | |||
205 | int div; | 205 | int div; |
206 | div = ti_clk_divider_bestdiv(hw, rate, prate); | 206 | div = ti_clk_divider_bestdiv(hw, rate, prate); |
207 | 207 | ||
208 | return *prate / div; | 208 | return DIV_ROUND_UP(*prate, div); |
209 | } | 209 | } |
210 | 210 | ||
211 | static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, | 211 | static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, |
@@ -216,7 +216,7 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, | |||
216 | unsigned long flags = 0; | 216 | unsigned long flags = 0; |
217 | u32 val; | 217 | u32 val; |
218 | 218 | ||
219 | div = parent_rate / rate; | 219 | div = DIV_ROUND_UP(parent_rate, rate); |
220 | value = _get_val(divider, div); | 220 | value = _get_val(divider, div); |
221 | 221 | ||
222 | if (value > div_mask(divider)) | 222 | if (value > div_mask(divider)) |
diff --git a/drivers/clk/ux500/u8500_of_clk.c b/drivers/clk/ux500/u8500_of_clk.c index cdeff299de26..7b55ef89baa5 100644 --- a/drivers/clk/ux500/u8500_of_clk.c +++ b/drivers/clk/ux500/u8500_of_clk.c | |||
@@ -29,7 +29,8 @@ static struct clk *prcc_kclk[(PRCC_NUM_PERIPH_CLUSTERS + 1) * PRCC_PERIPHS_PER_C | |||
29 | #define PRCC_KCLK_STORE(clk, base, bit) \ | 29 | #define PRCC_KCLK_STORE(clk, base, bit) \ |
30 | prcc_kclk[(base * PRCC_PERIPHS_PER_CLUSTER) + bit] = clk | 30 | prcc_kclk[(base * PRCC_PERIPHS_PER_CLUSTER) + bit] = clk |
31 | 31 | ||
32 | struct clk *ux500_twocell_get(struct of_phandle_args *clkspec, void *data) | 32 | static struct clk *ux500_twocell_get(struct of_phandle_args *clkspec, |
33 | void *data) | ||
33 | { | 34 | { |
34 | struct clk **clk_data = data; | 35 | struct clk **clk_data = data; |
35 | unsigned int base, bit; | 36 | unsigned int base, bit; |
diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c index c812b93a52b2..52c09afdcfb7 100644 --- a/drivers/clk/zynq/clkc.c +++ b/drivers/clk/zynq/clkc.c | |||
@@ -149,7 +149,7 @@ static void __init zynq_clk_register_fclk(enum zynq_clk fclk, | |||
149 | clks[fclk] = clk_register_gate(NULL, clk_name, | 149 | clks[fclk] = clk_register_gate(NULL, clk_name, |
150 | div1_name, CLK_SET_RATE_PARENT, fclk_gate_reg, | 150 | div1_name, CLK_SET_RATE_PARENT, fclk_gate_reg, |
151 | 0, CLK_GATE_SET_TO_DISABLE, fclk_gate_lock); | 151 | 0, CLK_GATE_SET_TO_DISABLE, fclk_gate_lock); |
152 | enable_reg = readl(fclk_gate_reg) & 1; | 152 | enable_reg = clk_readl(fclk_gate_reg) & 1; |
153 | if (enable && !enable_reg) { | 153 | if (enable && !enable_reg) { |
154 | if (clk_prepare_enable(clks[fclk])) | 154 | if (clk_prepare_enable(clks[fclk])) |
155 | pr_warn("%s: FCLK%u enable failed\n", __func__, | 155 | pr_warn("%s: FCLK%u enable failed\n", __func__, |
@@ -278,7 +278,7 @@ static void __init zynq_clk_setup(struct device_node *np) | |||
278 | SLCR_IOPLL_CTRL, 4, 1, 0, &iopll_lock); | 278 | SLCR_IOPLL_CTRL, 4, 1, 0, &iopll_lock); |
279 | 279 | ||
280 | /* CPU clocks */ | 280 | /* CPU clocks */ |
281 | tmp = readl(SLCR_621_TRUE) & 1; | 281 | tmp = clk_readl(SLCR_621_TRUE) & 1; |
282 | clk = clk_register_mux(NULL, "cpu_mux", cpu_parents, 4, | 282 | clk = clk_register_mux(NULL, "cpu_mux", cpu_parents, 4, |
283 | CLK_SET_RATE_NO_REPARENT, SLCR_ARM_CLK_CTRL, 4, 2, 0, | 283 | CLK_SET_RATE_NO_REPARENT, SLCR_ARM_CLK_CTRL, 4, 2, 0, |
284 | &armclk_lock); | 284 | &armclk_lock); |
diff --git a/drivers/clk/zynq/pll.c b/drivers/clk/zynq/pll.c index 3226f54fa595..cec97596fe65 100644 --- a/drivers/clk/zynq/pll.c +++ b/drivers/clk/zynq/pll.c | |||
@@ -90,7 +90,7 @@ static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw, | |||
90 | * makes probably sense to redundantly save fbdiv in the struct | 90 | * makes probably sense to redundantly save fbdiv in the struct |
91 | * zynq_pll to save the IO access. | 91 | * zynq_pll to save the IO access. |
92 | */ | 92 | */ |
93 | fbdiv = (readl(clk->pll_ctrl) & PLLCTRL_FBDIV_MASK) >> | 93 | fbdiv = (clk_readl(clk->pll_ctrl) & PLLCTRL_FBDIV_MASK) >> |
94 | PLLCTRL_FBDIV_SHIFT; | 94 | PLLCTRL_FBDIV_SHIFT; |
95 | 95 | ||
96 | return parent_rate * fbdiv; | 96 | return parent_rate * fbdiv; |
@@ -112,7 +112,7 @@ static int zynq_pll_is_enabled(struct clk_hw *hw) | |||
112 | 112 | ||
113 | spin_lock_irqsave(clk->lock, flags); | 113 | spin_lock_irqsave(clk->lock, flags); |
114 | 114 | ||
115 | reg = readl(clk->pll_ctrl); | 115 | reg = clk_readl(clk->pll_ctrl); |
116 | 116 | ||
117 | spin_unlock_irqrestore(clk->lock, flags); | 117 | spin_unlock_irqrestore(clk->lock, flags); |
118 | 118 | ||
@@ -138,10 +138,10 @@ static int zynq_pll_enable(struct clk_hw *hw) | |||
138 | /* Power up PLL and wait for lock */ | 138 | /* Power up PLL and wait for lock */ |
139 | spin_lock_irqsave(clk->lock, flags); | 139 | spin_lock_irqsave(clk->lock, flags); |
140 | 140 | ||
141 | reg = readl(clk->pll_ctrl); | 141 | reg = clk_readl(clk->pll_ctrl); |
142 | reg &= ~(PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK); | 142 | reg &= ~(PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK); |
143 | writel(reg, clk->pll_ctrl); | 143 | clk_writel(reg, clk->pll_ctrl); |
144 | while (!(readl(clk->pll_status) & (1 << clk->lockbit))) | 144 | while (!(clk_readl(clk->pll_status) & (1 << clk->lockbit))) |
145 | ; | 145 | ; |
146 | 146 | ||
147 | spin_unlock_irqrestore(clk->lock, flags); | 147 | spin_unlock_irqrestore(clk->lock, flags); |
@@ -168,9 +168,9 @@ static void zynq_pll_disable(struct clk_hw *hw) | |||
168 | /* shut down PLL */ | 168 | /* shut down PLL */ |
169 | spin_lock_irqsave(clk->lock, flags); | 169 | spin_lock_irqsave(clk->lock, flags); |
170 | 170 | ||
171 | reg = readl(clk->pll_ctrl); | 171 | reg = clk_readl(clk->pll_ctrl); |
172 | reg |= PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK; | 172 | reg |= PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK; |
173 | writel(reg, clk->pll_ctrl); | 173 | clk_writel(reg, clk->pll_ctrl); |
174 | 174 | ||
175 | spin_unlock_irqrestore(clk->lock, flags); | 175 | spin_unlock_irqrestore(clk->lock, flags); |
176 | } | 176 | } |
@@ -225,9 +225,9 @@ struct clk *clk_register_zynq_pll(const char *name, const char *parent, | |||
225 | 225 | ||
226 | spin_lock_irqsave(pll->lock, flags); | 226 | spin_lock_irqsave(pll->lock, flags); |
227 | 227 | ||
228 | reg = readl(pll->pll_ctrl); | 228 | reg = clk_readl(pll->pll_ctrl); |
229 | reg &= ~PLLCTRL_BPQUAL_MASK; | 229 | reg &= ~PLLCTRL_BPQUAL_MASK; |
230 | writel(reg, pll->pll_ctrl); | 230 | clk_writel(reg, pll->pll_ctrl); |
231 | 231 | ||
232 | spin_unlock_irqrestore(pll->lock, flags); | 232 | spin_unlock_irqrestore(pll->lock, flags); |
233 | 233 | ||
diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h index 6eaa6a45e110..21b9d0e2eb0c 100644 --- a/include/dt-bindings/clock/hi3620-clock.h +++ b/include/dt-bindings/clock/hi3620-clock.h | |||
@@ -147,6 +147,11 @@ | |||
147 | #define HI3620_MMC_CLK3 217 | 147 | #define HI3620_MMC_CLK3 217 |
148 | #define HI3620_MCU_CLK 218 | 148 | #define HI3620_MCU_CLK 218 |
149 | 149 | ||
150 | #define HI3620_SD_CIUCLK 0 | ||
151 | #define HI3620_MMC_CIUCLK1 1 | ||
152 | #define HI3620_MMC_CIUCLK2 2 | ||
153 | #define HI3620_MMC_CIUCLK3 3 | ||
154 | |||
150 | #define HI3620_NR_CLKS 219 | 155 | #define HI3620_NR_CLKS 219 |
151 | 156 | ||
152 | #endif /* __DTS_HI3620_CLOCK_H */ | 157 | #endif /* __DTS_HI3620_CLOCK_H */ |
diff --git a/include/dt-bindings/clock/hip04-clock.h b/include/dt-bindings/clock/hip04-clock.h new file mode 100644 index 000000000000..695e61cd1523 --- /dev/null +++ b/include/dt-bindings/clock/hip04-clock.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013-2014 Hisilicon Limited. | ||
3 | * Copyright (c) 2013-2014 Linaro Limited. | ||
4 | * | ||
5 | * Author: Haojian Zhuang <haojian.zhuang@linaro.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #ifndef __DTS_HIP04_CLOCK_H | ||
24 | #define __DTS_HIP04_CLOCK_H | ||
25 | |||
26 | #define HIP04_NONE_CLOCK 0 | ||
27 | |||
28 | /* fixed rate & fixed factor clocks */ | ||
29 | #define HIP04_OSC50M 1 | ||
30 | #define HIP04_CLK_50M 2 | ||
31 | #define HIP04_CLK_168M 3 | ||
32 | |||
33 | #define HIP04_NR_CLKS 64 | ||
34 | |||
35 | #endif /* __DTS_HIP04_CLOCK_H */ | ||
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 939533da93a7..511917416fb0 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */ | 32 | #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */ |
33 | 33 | ||
34 | struct clk_hw; | 34 | struct clk_hw; |
35 | struct dentry; | ||
35 | 36 | ||
36 | /** | 37 | /** |
37 | * struct clk_ops - Callback operations for hardware clocks; these are to | 38 | * struct clk_ops - Callback operations for hardware clocks; these are to |
@@ -127,6 +128,12 @@ struct clk_hw; | |||
127 | * separately via calls to .set_parent and .set_rate. | 128 | * separately via calls to .set_parent and .set_rate. |
128 | * Returns 0 on success, -EERROR otherwise. | 129 | * Returns 0 on success, -EERROR otherwise. |
129 | * | 130 | * |
131 | * @debug_init: Set up type-specific debugfs entries for this clock. This | ||
132 | * is called once, after the debugfs directory entry for this | ||
133 | * clock has been created. The dentry pointer representing that | ||
134 | * directory is provided as an argument. Called with | ||
135 | * prepare_lock held. Returns 0 on success, -EERROR otherwise. | ||
136 | * | ||
130 | * | 137 | * |
131 | * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow | 138 | * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow |
132 | * implementations to split any work between atomic (enable) and sleepable | 139 | * implementations to split any work between atomic (enable) and sleepable |
@@ -165,6 +172,7 @@ struct clk_ops { | |||
165 | unsigned long (*recalc_accuracy)(struct clk_hw *hw, | 172 | unsigned long (*recalc_accuracy)(struct clk_hw *hw, |
166 | unsigned long parent_accuracy); | 173 | unsigned long parent_accuracy); |
167 | void (*init)(struct clk_hw *hw); | 174 | void (*init)(struct clk_hw *hw); |
175 | int (*debug_init)(struct clk_hw *hw, struct dentry *dentry); | ||
168 | }; | 176 | }; |
169 | 177 | ||
170 | /** | 178 | /** |
diff --git a/include/linux/clk.h b/include/linux/clk.h index 0dd91148165e..fb5e097d8f72 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h | |||
@@ -78,8 +78,22 @@ struct clk_notifier_data { | |||
78 | unsigned long new_rate; | 78 | unsigned long new_rate; |
79 | }; | 79 | }; |
80 | 80 | ||
81 | /** | ||
82 | * clk_notifier_register: register a clock rate-change notifier callback | ||
83 | * @clk: clock whose rate we are interested in | ||
84 | * @nb: notifier block with callback function pointer | ||
85 | * | ||
86 | * ProTip: debugging across notifier chains can be frustrating. Make sure that | ||
87 | * your notifier callback function prints a nice big warning in case of | ||
88 | * failure. | ||
89 | */ | ||
81 | int clk_notifier_register(struct clk *clk, struct notifier_block *nb); | 90 | int clk_notifier_register(struct clk *clk, struct notifier_block *nb); |
82 | 91 | ||
92 | /** | ||
93 | * clk_notifier_unregister: unregister a clock rate-change notifier callback | ||
94 | * @clk: clock whose rate we are no longer interested in | ||
95 | * @nb: notifier block which will be unregistered | ||
96 | */ | ||
83 | int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb); | 97 | int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb); |
84 | 98 | ||
85 | /** | 99 | /** |