diff options
author | Arnd Bergmann <arnd@arndb.de> | 2013-04-09 11:09:35 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2013-04-09 11:09:35 -0400 |
commit | 5790c58b133913f92fd737c03efce9db7a1d2d4d (patch) | |
tree | deef8f070b4de7fcff62d496d09842ff91ed83d0 | |
parent | 1194b152cd4eff475652785ce366b20afe82dfcf (diff) | |
parent | 533ddeb1e86f506129ee388a6cc13796dcf31311 (diff) |
Merge branch 'depends/clk' into next/drivers
This is a snapshot of the stable clk branch at
git://git.linaro.org/people/mturquette/linux.git clk-for-3.10
which is a dependency for the tegra clock changes.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
25 files changed, 1622 insertions, 130 deletions
diff --git a/Documentation/arm/sunxi/clocks.txt b/Documentation/arm/sunxi/clocks.txt new file mode 100644 index 000000000000..e09a88aa3136 --- /dev/null +++ b/Documentation/arm/sunxi/clocks.txt | |||
@@ -0,0 +1,56 @@ | |||
1 | Frequently asked questions about the sunxi clock system | ||
2 | ======================================================= | ||
3 | |||
4 | This document contains useful bits of information that people tend to ask | ||
5 | about the sunxi clock system, as well as accompanying ASCII art when adequate. | ||
6 | |||
7 | Q: Why is the main 24MHz oscillator gatable? Wouldn't that break the | ||
8 | system? | ||
9 | |||
10 | A: The 24MHz oscillator allows gating to save power. Indeed, if gated | ||
11 | carelessly the system would stop functioning, but with the right | ||
12 | steps, one can gate it and keep the system running. Consider this | ||
13 | simplified suspend example: | ||
14 | |||
15 | While the system is operational, you would see something like | ||
16 | |||
17 | 24MHz 32kHz | ||
18 | | | ||
19 | PLL1 | ||
20 | \ | ||
21 | \_ CPU Mux | ||
22 | | | ||
23 | [CPU] | ||
24 | |||
25 | When you are about to suspend, you switch the CPU Mux to the 32kHz | ||
26 | oscillator: | ||
27 | |||
28 | 24Mhz 32kHz | ||
29 | | | | ||
30 | PLL1 | | ||
31 | / | ||
32 | CPU Mux _/ | ||
33 | | | ||
34 | [CPU] | ||
35 | |||
36 | Finally you can gate the main oscillator | ||
37 | |||
38 | 32kHz | ||
39 | | | ||
40 | | | ||
41 | / | ||
42 | CPU Mux _/ | ||
43 | | | ||
44 | [CPU] | ||
45 | |||
46 | Q: Were can I learn more about the sunxi clocks? | ||
47 | |||
48 | A: The linux-sunxi wiki contains a page documenting the clock registers, | ||
49 | you can find it at | ||
50 | |||
51 | http://linux-sunxi.org/A10/CCM | ||
52 | |||
53 | The authoritative source for information at this time is the ccmu driver | ||
54 | released by Allwinner, you can find it at | ||
55 | |||
56 | https://github.com/linux-sunxi/linux-sunxi/tree/sunxi-3.0/arch/arm/mach-sun4i/clock/ccmu | ||
diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 1943fae014fd..4274a546eb57 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt | |||
@@ -174,9 +174,9 @@ int clk_foo_enable(struct clk_hw *hw) | |||
174 | }; | 174 | }; |
175 | 175 | ||
176 | Below is a matrix detailing which clk_ops are mandatory based upon the | 176 | Below is a matrix detailing which clk_ops are mandatory based upon the |
177 | hardware capbilities of that clock. A cell marked as "y" means | 177 | hardware capabilities of that clock. A cell marked as "y" means |
178 | mandatory, a cell marked as "n" implies that either including that | 178 | mandatory, a cell marked as "n" implies that either including that |
179 | callback is invalid or otherwise uneccesary. Empty cells are either | 179 | callback is invalid or otherwise unnecessary. Empty cells are either |
180 | optional or must be evaluated on a case-by-case basis. | 180 | optional or must be evaluated on a case-by-case basis. |
181 | 181 | ||
182 | clock hardware characteristics | 182 | clock hardware characteristics |
diff --git a/Documentation/devicetree/bindings/clock/axi-clkgen.txt b/Documentation/devicetree/bindings/clock/axi-clkgen.txt new file mode 100644 index 000000000000..028b493e97ff --- /dev/null +++ b/Documentation/devicetree/bindings/clock/axi-clkgen.txt | |||
@@ -0,0 +1,22 @@ | |||
1 | Binding for the axi-clkgen clock generator | ||
2 | |||
3 | This binding uses the common clock binding[1]. | ||
4 | |||
5 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
6 | |||
7 | Required properties: | ||
8 | - compatible : shall be "adi,axi-clkgen". | ||
9 | - #clock-cells : from common clock binding; Should always be set to 0. | ||
10 | - reg : Address and length of the axi-clkgen register set. | ||
11 | - clocks : Phandle and clock specifier for the parent clock. | ||
12 | |||
13 | Optional properties: | ||
14 | - clock-output-names : From common clock binding. | ||
15 | |||
16 | Example: | ||
17 | clock@0xff000000 { | ||
18 | compatible = "adi,axi-clkgen"; | ||
19 | #clock-cells = <0>; | ||
20 | reg = <0xff000000 0x1000>; | ||
21 | clocks = <&osc 1>; | ||
22 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt new file mode 100644 index 000000000000..20b8479c2760 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sunxi.txt | |||
@@ -0,0 +1,44 @@ | |||
1 | Device Tree Clock bindings for arch-sunxi | ||
2 | |||
3 | This binding uses the common clock binding[1]. | ||
4 | |||
5 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
6 | |||
7 | Required properties: | ||
8 | - compatible : shall be one of the following: | ||
9 | "allwinner,sun4i-osc-clk" - for a gatable oscillator | ||
10 | "allwinner,sun4i-pll1-clk" - for the main PLL clock | ||
11 | "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock | ||
12 | "allwinner,sun4i-axi-clk" - for the AXI clock | ||
13 | "allwinner,sun4i-ahb-clk" - for the AHB clock | ||
14 | "allwinner,sun4i-apb0-clk" - for the APB0 clock | ||
15 | "allwinner,sun4i-apb1-clk" - for the APB1 clock | ||
16 | "allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing | ||
17 | |||
18 | Required properties for all clocks: | ||
19 | - reg : shall be the control register address for the clock. | ||
20 | - clocks : shall be the input parent clock(s) phandle for the clock | ||
21 | - #clock-cells : from common clock binding; shall be set to 0. | ||
22 | |||
23 | For example: | ||
24 | |||
25 | osc24M: osc24M@01c20050 { | ||
26 | #clock-cells = <0>; | ||
27 | compatible = "allwinner,sun4i-osc-clk"; | ||
28 | reg = <0x01c20050 0x4>; | ||
29 | clocks = <&osc24M_fixed>; | ||
30 | }; | ||
31 | |||
32 | pll1: pll1@01c20000 { | ||
33 | #clock-cells = <0>; | ||
34 | compatible = "allwinner,sun4i-pll1-clk"; | ||
35 | reg = <0x01c20000 0x4>; | ||
36 | clocks = <&osc24M>; | ||
37 | }; | ||
38 | |||
39 | cpu: cpu@01c20054 { | ||
40 | #clock-cells = <0>; | ||
41 | compatible = "allwinner,sun4i-cpu-clk"; | ||
42 | reg = <0x01c20054 0x4>; | ||
43 | clocks = <&osc32k>, <&osc24M>, <&pll1>; | ||
44 | }; | ||
diff --git a/arch/arm/mach-imx/clk-busy.c b/arch/arm/mach-imx/clk-busy.c index 1ab91b5209e6..85b728cc27ab 100644 --- a/arch/arm/mach-imx/clk-busy.c +++ b/arch/arm/mach-imx/clk-busy.c | |||
@@ -169,7 +169,7 @@ struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift, | |||
169 | 169 | ||
170 | busy->mux.reg = reg; | 170 | busy->mux.reg = reg; |
171 | busy->mux.shift = shift; | 171 | busy->mux.shift = shift; |
172 | busy->mux.width = width; | 172 | busy->mux.mask = BIT(width) - 1; |
173 | busy->mux.lock = &imx_ccm_lock; | 173 | busy->mux.lock = &imx_ccm_lock; |
174 | busy->mux_ops = &clk_mux_ops; | 174 | busy->mux_ops = &clk_mux_ops; |
175 | 175 | ||
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index a47e6ee98b8c..a64caefdba12 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig | |||
@@ -63,6 +63,14 @@ config CLK_TWL6040 | |||
63 | McPDM. McPDM module is using the external bit clock on the McPDM bus | 63 | McPDM. McPDM module is using the external bit clock on the McPDM bus |
64 | as functional clock. | 64 | as functional clock. |
65 | 65 | ||
66 | config COMMON_CLK_AXI_CLKGEN | ||
67 | tristate "AXI clkgen driver" | ||
68 | depends on ARCH_ZYNQ || MICROBLAZE | ||
69 | help | ||
70 | ---help--- | ||
71 | Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx | ||
72 | FPGAs. It is commonly used in Analog Devices' reference designs. | ||
73 | |||
66 | endmenu | 74 | endmenu |
67 | 75 | ||
68 | source "drivers/clk/mvebu/Kconfig" | 76 | source "drivers/clk/mvebu/Kconfig" |
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 300d4775d926..79e98e416724 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile | |||
@@ -7,6 +7,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o | |||
7 | obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o | 7 | obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o |
8 | obj-$(CONFIG_COMMON_CLK) += clk-gate.o | 8 | obj-$(CONFIG_COMMON_CLK) += clk-gate.o |
9 | obj-$(CONFIG_COMMON_CLK) += clk-mux.o | 9 | obj-$(CONFIG_COMMON_CLK) += clk-mux.o |
10 | obj-$(CONFIG_COMMON_CLK) += clk-composite.o | ||
10 | 11 | ||
11 | # SoCs specific | 12 | # SoCs specific |
12 | obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o | 13 | obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o |
@@ -23,6 +24,7 @@ ifeq ($(CONFIG_COMMON_CLK), y) | |||
23 | obj-$(CONFIG_ARCH_MMP) += mmp/ | 24 | obj-$(CONFIG_ARCH_MMP) += mmp/ |
24 | endif | 25 | endif |
25 | obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o | 26 | obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o |
27 | obj-$(CONFIG_ARCH_SUNXI) += sunxi/ | ||
26 | obj-$(CONFIG_ARCH_U8500) += ux500/ | 28 | obj-$(CONFIG_ARCH_U8500) += ux500/ |
27 | obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o | 29 | obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o |
28 | obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o | 30 | obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o |
@@ -31,6 +33,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/ | |||
31 | obj-$(CONFIG_X86) += x86/ | 33 | obj-$(CONFIG_X86) += x86/ |
32 | 34 | ||
33 | # Chip specific | 35 | # Chip specific |
36 | obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o | ||
34 | obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o | 37 | obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o |
35 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o | 38 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o |
36 | obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o | 39 | obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o |
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c new file mode 100644 index 000000000000..8137327847c3 --- /dev/null +++ b/drivers/clk/clk-axi-clkgen.c | |||
@@ -0,0 +1,331 @@ | |||
1 | /* | ||
2 | * AXI clkgen driver | ||
3 | * | ||
4 | * Copyright 2012-2013 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/clk-provider.h> | ||
13 | #include <linux/clk.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/of.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/err.h> | ||
19 | |||
20 | #define AXI_CLKGEN_REG_UPDATE_ENABLE 0x04 | ||
21 | #define AXI_CLKGEN_REG_CLK_OUT1 0x08 | ||
22 | #define AXI_CLKGEN_REG_CLK_OUT2 0x0c | ||
23 | #define AXI_CLKGEN_REG_CLK_DIV 0x10 | ||
24 | #define AXI_CLKGEN_REG_CLK_FB1 0x14 | ||
25 | #define AXI_CLKGEN_REG_CLK_FB2 0x18 | ||
26 | #define AXI_CLKGEN_REG_LOCK1 0x1c | ||
27 | #define AXI_CLKGEN_REG_LOCK2 0x20 | ||
28 | #define AXI_CLKGEN_REG_LOCK3 0x24 | ||
29 | #define AXI_CLKGEN_REG_FILTER1 0x28 | ||
30 | #define AXI_CLKGEN_REG_FILTER2 0x2c | ||
31 | |||
32 | struct axi_clkgen { | ||
33 | void __iomem *base; | ||
34 | struct clk_hw clk_hw; | ||
35 | }; | ||
36 | |||
37 | static uint32_t axi_clkgen_lookup_filter(unsigned int m) | ||
38 | { | ||
39 | switch (m) { | ||
40 | case 0: | ||
41 | return 0x01001990; | ||
42 | case 1: | ||
43 | return 0x01001190; | ||
44 | case 2: | ||
45 | return 0x01009890; | ||
46 | case 3: | ||
47 | return 0x01001890; | ||
48 | case 4: | ||
49 | return 0x01008890; | ||
50 | case 5 ... 8: | ||
51 | return 0x01009090; | ||
52 | case 9 ... 11: | ||
53 | return 0x01000890; | ||
54 | case 12: | ||
55 | return 0x08009090; | ||
56 | case 13 ... 22: | ||
57 | return 0x01001090; | ||
58 | case 23 ... 36: | ||
59 | return 0x01008090; | ||
60 | case 37 ... 46: | ||
61 | return 0x08001090; | ||
62 | default: | ||
63 | return 0x08008090; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | static const uint32_t axi_clkgen_lock_table[] = { | ||
68 | 0x060603e8, 0x060603e8, 0x080803e8, 0x0b0b03e8, | ||
69 | 0x0e0e03e8, 0x111103e8, 0x131303e8, 0x161603e8, | ||
70 | 0x191903e8, 0x1c1c03e8, 0x1f1f0384, 0x1f1f0339, | ||
71 | 0x1f1f02ee, 0x1f1f02bc, 0x1f1f028a, 0x1f1f0271, | ||
72 | 0x1f1f023f, 0x1f1f0226, 0x1f1f020d, 0x1f1f01f4, | ||
73 | 0x1f1f01db, 0x1f1f01c2, 0x1f1f01a9, 0x1f1f0190, | ||
74 | 0x1f1f0190, 0x1f1f0177, 0x1f1f015e, 0x1f1f015e, | ||
75 | 0x1f1f0145, 0x1f1f0145, 0x1f1f012c, 0x1f1f012c, | ||
76 | 0x1f1f012c, 0x1f1f0113, 0x1f1f0113, 0x1f1f0113, | ||
77 | }; | ||
78 | |||
79 | static uint32_t axi_clkgen_lookup_lock(unsigned int m) | ||
80 | { | ||
81 | if (m < ARRAY_SIZE(axi_clkgen_lock_table)) | ||
82 | return axi_clkgen_lock_table[m]; | ||
83 | return 0x1f1f00fa; | ||
84 | } | ||
85 | |||
86 | static const unsigned int fpfd_min = 10000; | ||
87 | static const unsigned int fpfd_max = 300000; | ||
88 | static const unsigned int fvco_min = 600000; | ||
89 | static const unsigned int fvco_max = 1200000; | ||
90 | |||
91 | static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout, | ||
92 | unsigned int *best_d, unsigned int *best_m, unsigned int *best_dout) | ||
93 | { | ||
94 | unsigned long d, d_min, d_max, _d_min, _d_max; | ||
95 | unsigned long m, m_min, m_max; | ||
96 | unsigned long f, dout, best_f, fvco; | ||
97 | |||
98 | fin /= 1000; | ||
99 | fout /= 1000; | ||
100 | |||
101 | best_f = ULONG_MAX; | ||
102 | *best_d = 0; | ||
103 | *best_m = 0; | ||
104 | *best_dout = 0; | ||
105 | |||
106 | d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1); | ||
107 | d_max = min_t(unsigned long, fin / fpfd_min, 80); | ||
108 | |||
109 | m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min, fin) * d_min, 1); | ||
110 | m_max = min_t(unsigned long, fvco_max * d_max / fin, 64); | ||
111 | |||
112 | for (m = m_min; m <= m_max; m++) { | ||
113 | _d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max)); | ||
114 | _d_max = min(d_max, fin * m / fvco_min); | ||
115 | |||
116 | for (d = _d_min; d <= _d_max; d++) { | ||
117 | fvco = fin * m / d; | ||
118 | |||
119 | dout = DIV_ROUND_CLOSEST(fvco, fout); | ||
120 | dout = clamp_t(unsigned long, dout, 1, 128); | ||
121 | f = fvco / dout; | ||
122 | if (abs(f - fout) < abs(best_f - fout)) { | ||
123 | best_f = f; | ||
124 | *best_d = d; | ||
125 | *best_m = m; | ||
126 | *best_dout = dout; | ||
127 | if (best_f == fout) | ||
128 | return; | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static void axi_clkgen_calc_clk_params(unsigned int divider, unsigned int *low, | ||
135 | unsigned int *high, unsigned int *edge, unsigned int *nocount) | ||
136 | { | ||
137 | if (divider == 1) | ||
138 | *nocount = 1; | ||
139 | else | ||
140 | *nocount = 0; | ||
141 | |||
142 | *high = divider / 2; | ||
143 | *edge = divider % 2; | ||
144 | *low = divider - *high; | ||
145 | } | ||
146 | |||
147 | static void axi_clkgen_write(struct axi_clkgen *axi_clkgen, | ||
148 | unsigned int reg, unsigned int val) | ||
149 | { | ||
150 | writel(val, axi_clkgen->base + reg); | ||
151 | } | ||
152 | |||
153 | static void axi_clkgen_read(struct axi_clkgen *axi_clkgen, | ||
154 | unsigned int reg, unsigned int *val) | ||
155 | { | ||
156 | *val = readl(axi_clkgen->base + reg); | ||
157 | } | ||
158 | |||
159 | static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw) | ||
160 | { | ||
161 | return container_of(clk_hw, struct axi_clkgen, clk_hw); | ||
162 | } | ||
163 | |||
164 | static int axi_clkgen_set_rate(struct clk_hw *clk_hw, | ||
165 | unsigned long rate, unsigned long parent_rate) | ||
166 | { | ||
167 | struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); | ||
168 | unsigned int d, m, dout; | ||
169 | unsigned int nocount; | ||
170 | unsigned int high; | ||
171 | unsigned int edge; | ||
172 | unsigned int low; | ||
173 | uint32_t filter; | ||
174 | uint32_t lock; | ||
175 | |||
176 | if (parent_rate == 0 || rate == 0) | ||
177 | return -EINVAL; | ||
178 | |||
179 | axi_clkgen_calc_params(parent_rate, rate, &d, &m, &dout); | ||
180 | |||
181 | if (d == 0 || dout == 0 || m == 0) | ||
182 | return -EINVAL; | ||
183 | |||
184 | filter = axi_clkgen_lookup_filter(m - 1); | ||
185 | lock = axi_clkgen_lookup_lock(m - 1); | ||
186 | |||
187 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 0); | ||
188 | |||
189 | axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount); | ||
190 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, | ||
191 | (high << 6) | low); | ||
192 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT2, | ||
193 | (edge << 7) | (nocount << 6)); | ||
194 | |||
195 | axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount); | ||
196 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, | ||
197 | (edge << 13) | (nocount << 12) | (high << 6) | low); | ||
198 | |||
199 | axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount); | ||
200 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, | ||
201 | (high << 6) | low); | ||
202 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB2, | ||
203 | (edge << 7) | (nocount << 6)); | ||
204 | |||
205 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK1, lock & 0x3ff); | ||
206 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK2, | ||
207 | (((lock >> 16) & 0x1f) << 10) | 0x1); | ||
208 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK3, | ||
209 | (((lock >> 24) & 0x1f) << 10) | 0x3e9); | ||
210 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER1, filter >> 16); | ||
211 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER2, filter); | ||
212 | |||
213 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 1); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate, | ||
219 | unsigned long *parent_rate) | ||
220 | { | ||
221 | unsigned int d, m, dout; | ||
222 | |||
223 | axi_clkgen_calc_params(*parent_rate, rate, &d, &m, &dout); | ||
224 | |||
225 | if (d == 0 || dout == 0 || m == 0) | ||
226 | return -EINVAL; | ||
227 | |||
228 | return *parent_rate / d * m / dout; | ||
229 | } | ||
230 | |||
231 | static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw, | ||
232 | unsigned long parent_rate) | ||
233 | { | ||
234 | struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); | ||
235 | unsigned int d, m, dout; | ||
236 | unsigned int reg; | ||
237 | unsigned long long tmp; | ||
238 | |||
239 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, ®); | ||
240 | dout = (reg & 0x3f) + ((reg >> 6) & 0x3f); | ||
241 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, ®); | ||
242 | d = (reg & 0x3f) + ((reg >> 6) & 0x3f); | ||
243 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, ®); | ||
244 | m = (reg & 0x3f) + ((reg >> 6) & 0x3f); | ||
245 | |||
246 | if (d == 0 || dout == 0) | ||
247 | return 0; | ||
248 | |||
249 | tmp = (unsigned long long)(parent_rate / d) * m; | ||
250 | do_div(tmp, dout); | ||
251 | |||
252 | if (tmp > ULONG_MAX) | ||
253 | return ULONG_MAX; | ||
254 | |||
255 | return tmp; | ||
256 | } | ||
257 | |||
258 | static const struct clk_ops axi_clkgen_ops = { | ||
259 | .recalc_rate = axi_clkgen_recalc_rate, | ||
260 | .round_rate = axi_clkgen_round_rate, | ||
261 | .set_rate = axi_clkgen_set_rate, | ||
262 | }; | ||
263 | |||
264 | static int axi_clkgen_probe(struct platform_device *pdev) | ||
265 | { | ||
266 | struct axi_clkgen *axi_clkgen; | ||
267 | struct clk_init_data init; | ||
268 | const char *parent_name; | ||
269 | const char *clk_name; | ||
270 | struct resource *mem; | ||
271 | struct clk *clk; | ||
272 | |||
273 | axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL); | ||
274 | if (!axi_clkgen) | ||
275 | return -ENOMEM; | ||
276 | |||
277 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
278 | axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem); | ||
279 | if (IS_ERR(axi_clkgen->base)) | ||
280 | return PTR_ERR(axi_clkgen->base); | ||
281 | |||
282 | parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0); | ||
283 | if (!parent_name) | ||
284 | return -EINVAL; | ||
285 | |||
286 | clk_name = pdev->dev.of_node->name; | ||
287 | of_property_read_string(pdev->dev.of_node, "clock-output-names", | ||
288 | &clk_name); | ||
289 | |||
290 | init.name = clk_name; | ||
291 | init.ops = &axi_clkgen_ops; | ||
292 | init.flags = 0; | ||
293 | init.parent_names = &parent_name; | ||
294 | init.num_parents = 1; | ||
295 | |||
296 | axi_clkgen->clk_hw.init = &init; | ||
297 | clk = devm_clk_register(&pdev->dev, &axi_clkgen->clk_hw); | ||
298 | if (IS_ERR(clk)) | ||
299 | return PTR_ERR(clk); | ||
300 | |||
301 | return of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, | ||
302 | clk); | ||
303 | } | ||
304 | |||
305 | static int axi_clkgen_remove(struct platform_device *pdev) | ||
306 | { | ||
307 | of_clk_del_provider(pdev->dev.of_node); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
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 = { | ||
319 | .driver = { | ||
320 | .name = "adi-axi-clkgen", | ||
321 | .owner = THIS_MODULE, | ||
322 | .of_match_table = axi_clkgen_ids, | ||
323 | }, | ||
324 | .probe = axi_clkgen_probe, | ||
325 | .remove = axi_clkgen_remove, | ||
326 | }; | ||
327 | module_platform_driver(axi_clkgen_driver); | ||
328 | |||
329 | MODULE_LICENSE("GPL v2"); | ||
330 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
331 | MODULE_DESCRIPTION("Driver for the Analog Devices' AXI clkgen pcore clock generator"); | ||
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c new file mode 100644 index 000000000000..097dee4fd209 --- /dev/null +++ b/drivers/clk/clk-composite.c | |||
@@ -0,0 +1,201 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/clk.h> | ||
18 | #include <linux/clk-provider.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw) | ||
23 | |||
24 | static u8 clk_composite_get_parent(struct clk_hw *hw) | ||
25 | { | ||
26 | struct clk_composite *composite = to_clk_composite(hw); | ||
27 | const struct clk_ops *mux_ops = composite->mux_ops; | ||
28 | struct clk_hw *mux_hw = composite->mux_hw; | ||
29 | |||
30 | mux_hw->clk = hw->clk; | ||
31 | |||
32 | return mux_ops->get_parent(mux_hw); | ||
33 | } | ||
34 | |||
35 | static int clk_composite_set_parent(struct clk_hw *hw, u8 index) | ||
36 | { | ||
37 | struct clk_composite *composite = to_clk_composite(hw); | ||
38 | const struct clk_ops *mux_ops = composite->mux_ops; | ||
39 | struct clk_hw *mux_hw = composite->mux_hw; | ||
40 | |||
41 | mux_hw->clk = hw->clk; | ||
42 | |||
43 | return mux_ops->set_parent(mux_hw, index); | ||
44 | } | ||
45 | |||
46 | static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, | ||
47 | unsigned long parent_rate) | ||
48 | { | ||
49 | struct clk_composite *composite = to_clk_composite(hw); | ||
50 | const struct clk_ops *div_ops = composite->div_ops; | ||
51 | struct clk_hw *div_hw = composite->div_hw; | ||
52 | |||
53 | div_hw->clk = hw->clk; | ||
54 | |||
55 | return div_ops->recalc_rate(div_hw, parent_rate); | ||
56 | } | ||
57 | |||
58 | static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate, | ||
59 | unsigned long *prate) | ||
60 | { | ||
61 | struct clk_composite *composite = to_clk_composite(hw); | ||
62 | const struct clk_ops *div_ops = composite->div_ops; | ||
63 | struct clk_hw *div_hw = composite->div_hw; | ||
64 | |||
65 | div_hw->clk = hw->clk; | ||
66 | |||
67 | return div_ops->round_rate(div_hw, rate, prate); | ||
68 | } | ||
69 | |||
70 | static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate, | ||
71 | unsigned long parent_rate) | ||
72 | { | ||
73 | struct clk_composite *composite = to_clk_composite(hw); | ||
74 | const struct clk_ops *div_ops = composite->div_ops; | ||
75 | struct clk_hw *div_hw = composite->div_hw; | ||
76 | |||
77 | div_hw->clk = hw->clk; | ||
78 | |||
79 | return div_ops->set_rate(div_hw, rate, parent_rate); | ||
80 | } | ||
81 | |||
82 | static int clk_composite_is_enabled(struct clk_hw *hw) | ||
83 | { | ||
84 | struct clk_composite *composite = to_clk_composite(hw); | ||
85 | const struct clk_ops *gate_ops = composite->gate_ops; | ||
86 | struct clk_hw *gate_hw = composite->gate_hw; | ||
87 | |||
88 | gate_hw->clk = hw->clk; | ||
89 | |||
90 | return gate_ops->is_enabled(gate_hw); | ||
91 | } | ||
92 | |||
93 | static int clk_composite_enable(struct clk_hw *hw) | ||
94 | { | ||
95 | struct clk_composite *composite = to_clk_composite(hw); | ||
96 | const struct clk_ops *gate_ops = composite->gate_ops; | ||
97 | struct clk_hw *gate_hw = composite->gate_hw; | ||
98 | |||
99 | gate_hw->clk = hw->clk; | ||
100 | |||
101 | return gate_ops->enable(gate_hw); | ||
102 | } | ||
103 | |||
104 | static void clk_composite_disable(struct clk_hw *hw) | ||
105 | { | ||
106 | struct clk_composite *composite = to_clk_composite(hw); | ||
107 | const struct clk_ops *gate_ops = composite->gate_ops; | ||
108 | struct clk_hw *gate_hw = composite->gate_hw; | ||
109 | |||
110 | gate_hw->clk = hw->clk; | ||
111 | |||
112 | gate_ops->disable(gate_hw); | ||
113 | } | ||
114 | |||
115 | struct clk *clk_register_composite(struct device *dev, const char *name, | ||
116 | const char **parent_names, int num_parents, | ||
117 | struct clk_hw *mux_hw, const struct clk_ops *mux_ops, | ||
118 | struct clk_hw *div_hw, const struct clk_ops *div_ops, | ||
119 | struct clk_hw *gate_hw, const struct clk_ops *gate_ops, | ||
120 | unsigned long flags) | ||
121 | { | ||
122 | struct clk *clk; | ||
123 | struct clk_init_data init; | ||
124 | struct clk_composite *composite; | ||
125 | struct clk_ops *clk_composite_ops; | ||
126 | |||
127 | composite = kzalloc(sizeof(*composite), GFP_KERNEL); | ||
128 | if (!composite) { | ||
129 | pr_err("%s: could not allocate composite clk\n", __func__); | ||
130 | return ERR_PTR(-ENOMEM); | ||
131 | } | ||
132 | |||
133 | init.name = name; | ||
134 | init.flags = flags | CLK_IS_BASIC; | ||
135 | init.parent_names = parent_names; | ||
136 | init.num_parents = num_parents; | ||
137 | |||
138 | clk_composite_ops = &composite->ops; | ||
139 | |||
140 | if (mux_hw && mux_ops) { | ||
141 | if (!mux_ops->get_parent || !mux_ops->set_parent) { | ||
142 | clk = ERR_PTR(-EINVAL); | ||
143 | goto err; | ||
144 | } | ||
145 | |||
146 | composite->mux_hw = mux_hw; | ||
147 | composite->mux_ops = mux_ops; | ||
148 | clk_composite_ops->get_parent = clk_composite_get_parent; | ||
149 | clk_composite_ops->set_parent = clk_composite_set_parent; | ||
150 | } | ||
151 | |||
152 | if (div_hw && div_ops) { | ||
153 | if (!div_ops->recalc_rate || !div_ops->round_rate || | ||
154 | !div_ops->set_rate) { | ||
155 | clk = ERR_PTR(-EINVAL); | ||
156 | goto err; | ||
157 | } | ||
158 | |||
159 | composite->div_hw = div_hw; | ||
160 | composite->div_ops = div_ops; | ||
161 | clk_composite_ops->recalc_rate = clk_composite_recalc_rate; | ||
162 | clk_composite_ops->round_rate = clk_composite_round_rate; | ||
163 | clk_composite_ops->set_rate = clk_composite_set_rate; | ||
164 | } | ||
165 | |||
166 | if (gate_hw && gate_ops) { | ||
167 | if (!gate_ops->is_enabled || !gate_ops->enable || | ||
168 | !gate_ops->disable) { | ||
169 | clk = ERR_PTR(-EINVAL); | ||
170 | goto err; | ||
171 | } | ||
172 | |||
173 | composite->gate_hw = gate_hw; | ||
174 | composite->gate_ops = gate_ops; | ||
175 | clk_composite_ops->is_enabled = clk_composite_is_enabled; | ||
176 | clk_composite_ops->enable = clk_composite_enable; | ||
177 | clk_composite_ops->disable = clk_composite_disable; | ||
178 | } | ||
179 | |||
180 | init.ops = clk_composite_ops; | ||
181 | composite->hw.init = &init; | ||
182 | |||
183 | clk = clk_register(dev, &composite->hw); | ||
184 | if (IS_ERR(clk)) | ||
185 | goto err; | ||
186 | |||
187 | if (composite->mux_hw) | ||
188 | composite->mux_hw->clk = clk; | ||
189 | |||
190 | if (composite->div_hw) | ||
191 | composite->div_hw->clk = clk; | ||
192 | |||
193 | if (composite->gate_hw) | ||
194 | composite->gate_hw->clk = clk; | ||
195 | |||
196 | return clk; | ||
197 | |||
198 | err: | ||
199 | kfree(composite); | ||
200 | return clk; | ||
201 | } | ||
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 508c032edce4..25b1734560d0 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c | |||
@@ -32,6 +32,7 @@ | |||
32 | static u8 clk_mux_get_parent(struct clk_hw *hw) | 32 | static u8 clk_mux_get_parent(struct clk_hw *hw) |
33 | { | 33 | { |
34 | struct clk_mux *mux = to_clk_mux(hw); | 34 | struct clk_mux *mux = to_clk_mux(hw); |
35 | int num_parents = __clk_get_num_parents(hw->clk); | ||
35 | u32 val; | 36 | u32 val; |
36 | 37 | ||
37 | /* | 38 | /* |
@@ -42,7 +43,16 @@ static u8 clk_mux_get_parent(struct clk_hw *hw) | |||
42 | * val = 0x4 really means "bit 2, index starts at bit 0" | 43 | * val = 0x4 really means "bit 2, index starts at bit 0" |
43 | */ | 44 | */ |
44 | val = readl(mux->reg) >> mux->shift; | 45 | val = readl(mux->reg) >> mux->shift; |
45 | val &= (1 << mux->width) - 1; | 46 | val &= mux->mask; |
47 | |||
48 | if (mux->table) { | ||
49 | int i; | ||
50 | |||
51 | for (i = 0; i < num_parents; i++) | ||
52 | if (mux->table[i] == val) | ||
53 | return i; | ||
54 | return -EINVAL; | ||
55 | } | ||
46 | 56 | ||
47 | if (val && (mux->flags & CLK_MUX_INDEX_BIT)) | 57 | if (val && (mux->flags & CLK_MUX_INDEX_BIT)) |
48 | val = ffs(val) - 1; | 58 | val = ffs(val) - 1; |
@@ -50,7 +60,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw) | |||
50 | if (val && (mux->flags & CLK_MUX_INDEX_ONE)) | 60 | if (val && (mux->flags & CLK_MUX_INDEX_ONE)) |
51 | val--; | 61 | val--; |
52 | 62 | ||
53 | if (val >= __clk_get_num_parents(hw->clk)) | 63 | if (val >= num_parents) |
54 | return -EINVAL; | 64 | return -EINVAL; |
55 | 65 | ||
56 | return val; | 66 | return val; |
@@ -62,17 +72,22 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index) | |||
62 | u32 val; | 72 | u32 val; |
63 | unsigned long flags = 0; | 73 | unsigned long flags = 0; |
64 | 74 | ||
65 | if (mux->flags & CLK_MUX_INDEX_BIT) | 75 | if (mux->table) |
66 | index = (1 << ffs(index)); | 76 | index = mux->table[index]; |
67 | 77 | ||
68 | if (mux->flags & CLK_MUX_INDEX_ONE) | 78 | else { |
69 | index++; | 79 | if (mux->flags & CLK_MUX_INDEX_BIT) |
80 | index = (1 << ffs(index)); | ||
81 | |||
82 | if (mux->flags & CLK_MUX_INDEX_ONE) | ||
83 | index++; | ||
84 | } | ||
70 | 85 | ||
71 | if (mux->lock) | 86 | if (mux->lock) |
72 | spin_lock_irqsave(mux->lock, flags); | 87 | spin_lock_irqsave(mux->lock, flags); |
73 | 88 | ||
74 | val = readl(mux->reg); | 89 | val = readl(mux->reg); |
75 | val &= ~(((1 << mux->width) - 1) << mux->shift); | 90 | val &= ~(mux->mask << mux->shift); |
76 | val |= index << mux->shift; | 91 | val |= index << mux->shift; |
77 | writel(val, mux->reg); | 92 | writel(val, mux->reg); |
78 | 93 | ||
@@ -88,10 +103,10 @@ const struct clk_ops clk_mux_ops = { | |||
88 | }; | 103 | }; |
89 | EXPORT_SYMBOL_GPL(clk_mux_ops); | 104 | EXPORT_SYMBOL_GPL(clk_mux_ops); |
90 | 105 | ||
91 | struct clk *clk_register_mux(struct device *dev, const char *name, | 106 | struct clk *clk_register_mux_table(struct device *dev, const char *name, |
92 | const char **parent_names, u8 num_parents, unsigned long flags, | 107 | const char **parent_names, u8 num_parents, unsigned long flags, |
93 | void __iomem *reg, u8 shift, u8 width, | 108 | void __iomem *reg, u8 shift, u32 mask, |
94 | u8 clk_mux_flags, spinlock_t *lock) | 109 | u8 clk_mux_flags, u32 *table, spinlock_t *lock) |
95 | { | 110 | { |
96 | struct clk_mux *mux; | 111 | struct clk_mux *mux; |
97 | struct clk *clk; | 112 | struct clk *clk; |
@@ -113,9 +128,10 @@ struct clk *clk_register_mux(struct device *dev, const char *name, | |||
113 | /* struct clk_mux assignments */ | 128 | /* struct clk_mux assignments */ |
114 | mux->reg = reg; | 129 | mux->reg = reg; |
115 | mux->shift = shift; | 130 | mux->shift = shift; |
116 | mux->width = width; | 131 | mux->mask = mask; |
117 | mux->flags = clk_mux_flags; | 132 | mux->flags = clk_mux_flags; |
118 | mux->lock = lock; | 133 | mux->lock = lock; |
134 | mux->table = table; | ||
119 | mux->hw.init = &init; | 135 | mux->hw.init = &init; |
120 | 136 | ||
121 | clk = clk_register(dev, &mux->hw); | 137 | clk = clk_register(dev, &mux->hw); |
@@ -125,3 +141,15 @@ struct clk *clk_register_mux(struct device *dev, const char *name, | |||
125 | 141 | ||
126 | return clk; | 142 | return clk; |
127 | } | 143 | } |
144 | |||
145 | struct clk *clk_register_mux(struct device *dev, const char *name, | ||
146 | const char **parent_names, u8 num_parents, unsigned long flags, | ||
147 | void __iomem *reg, u8 shift, u8 width, | ||
148 | u8 clk_mux_flags, spinlock_t *lock) | ||
149 | { | ||
150 | u32 mask = BIT(width) - 1; | ||
151 | |||
152 | return clk_register_mux_table(dev, name, parent_names, num_parents, | ||
153 | flags, reg, shift, mask, clk_mux_flags, | ||
154 | NULL, lock); | ||
155 | } | ||
diff --git a/drivers/clk/clk-prima2.c b/drivers/clk/clk-prima2.c index f8e9d0c27be2..643ca653fef0 100644 --- a/drivers/clk/clk-prima2.c +++ b/drivers/clk/clk-prima2.c | |||
@@ -1113,7 +1113,7 @@ void __init sirfsoc_of_clk_init(void) | |||
1113 | 1113 | ||
1114 | for (i = pll1; i < maxclk; i++) { | 1114 | for (i = pll1; i < maxclk; i++) { |
1115 | prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]); | 1115 | prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]); |
1116 | BUG_ON(!prima2_clks[i]); | 1116 | BUG_ON(IS_ERR(prima2_clks[i])); |
1117 | } | 1117 | } |
1118 | clk_register_clkdev(prima2_clks[cpu], NULL, "cpu"); | 1118 | clk_register_clkdev(prima2_clks[cpu], NULL, "cpu"); |
1119 | clk_register_clkdev(prima2_clks[io], NULL, "io"); | 1119 | clk_register_clkdev(prima2_clks[io], NULL, "io"); |
diff --git a/drivers/clk/clk-zynq.c b/drivers/clk/clk-zynq.c index b14a25f39255..32062977f453 100644 --- a/drivers/clk/clk-zynq.c +++ b/drivers/clk/clk-zynq.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/clk-provider.h> | 22 | #include <linux/clk-provider.h> |
23 | #include <linux/clk/zynq.h> | ||
23 | 24 | ||
24 | static void __iomem *slcr_base; | 25 | static void __iomem *slcr_base; |
25 | 26 | ||
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index ed87b2405806..0230c9d95975 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
@@ -19,14 +19,77 @@ | |||
19 | #include <linux/of.h> | 19 | #include <linux/of.h> |
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/sched.h> | ||
22 | 23 | ||
23 | static DEFINE_SPINLOCK(enable_lock); | 24 | static DEFINE_SPINLOCK(enable_lock); |
24 | static DEFINE_MUTEX(prepare_lock); | 25 | static DEFINE_MUTEX(prepare_lock); |
25 | 26 | ||
27 | static struct task_struct *prepare_owner; | ||
28 | static struct task_struct *enable_owner; | ||
29 | |||
30 | static int prepare_refcnt; | ||
31 | static int enable_refcnt; | ||
32 | |||
26 | static HLIST_HEAD(clk_root_list); | 33 | static HLIST_HEAD(clk_root_list); |
27 | static HLIST_HEAD(clk_orphan_list); | 34 | static HLIST_HEAD(clk_orphan_list); |
28 | static LIST_HEAD(clk_notifier_list); | 35 | static LIST_HEAD(clk_notifier_list); |
29 | 36 | ||
37 | /*** locking ***/ | ||
38 | static void clk_prepare_lock(void) | ||
39 | { | ||
40 | if (!mutex_trylock(&prepare_lock)) { | ||
41 | if (prepare_owner == current) { | ||
42 | prepare_refcnt++; | ||
43 | return; | ||
44 | } | ||
45 | mutex_lock(&prepare_lock); | ||
46 | } | ||
47 | WARN_ON_ONCE(prepare_owner != NULL); | ||
48 | WARN_ON_ONCE(prepare_refcnt != 0); | ||
49 | prepare_owner = current; | ||
50 | prepare_refcnt = 1; | ||
51 | } | ||
52 | |||
53 | static void clk_prepare_unlock(void) | ||
54 | { | ||
55 | WARN_ON_ONCE(prepare_owner != current); | ||
56 | WARN_ON_ONCE(prepare_refcnt == 0); | ||
57 | |||
58 | if (--prepare_refcnt) | ||
59 | return; | ||
60 | prepare_owner = NULL; | ||
61 | mutex_unlock(&prepare_lock); | ||
62 | } | ||
63 | |||
64 | static unsigned long clk_enable_lock(void) | ||
65 | { | ||
66 | unsigned long flags; | ||
67 | |||
68 | if (!spin_trylock_irqsave(&enable_lock, flags)) { | ||
69 | if (enable_owner == current) { | ||
70 | enable_refcnt++; | ||
71 | return flags; | ||
72 | } | ||
73 | spin_lock_irqsave(&enable_lock, flags); | ||
74 | } | ||
75 | WARN_ON_ONCE(enable_owner != NULL); | ||
76 | WARN_ON_ONCE(enable_refcnt != 0); | ||
77 | enable_owner = current; | ||
78 | enable_refcnt = 1; | ||
79 | return flags; | ||
80 | } | ||
81 | |||
82 | static void clk_enable_unlock(unsigned long flags) | ||
83 | { | ||
84 | WARN_ON_ONCE(enable_owner != current); | ||
85 | WARN_ON_ONCE(enable_refcnt == 0); | ||
86 | |||
87 | if (--enable_refcnt) | ||
88 | return; | ||
89 | enable_owner = NULL; | ||
90 | spin_unlock_irqrestore(&enable_lock, flags); | ||
91 | } | ||
92 | |||
30 | /*** debugfs support ***/ | 93 | /*** debugfs support ***/ |
31 | 94 | ||
32 | #ifdef CONFIG_COMMON_CLK_DEBUG | 95 | #ifdef CONFIG_COMMON_CLK_DEBUG |
@@ -69,7 +132,7 @@ static int clk_summary_show(struct seq_file *s, void *data) | |||
69 | seq_printf(s, " clock enable_cnt prepare_cnt rate\n"); | 132 | seq_printf(s, " clock enable_cnt prepare_cnt rate\n"); |
70 | seq_printf(s, "---------------------------------------------------------------------\n"); | 133 | seq_printf(s, "---------------------------------------------------------------------\n"); |
71 | 134 | ||
72 | mutex_lock(&prepare_lock); | 135 | clk_prepare_lock(); |
73 | 136 | ||
74 | hlist_for_each_entry(c, &clk_root_list, child_node) | 137 | hlist_for_each_entry(c, &clk_root_list, child_node) |
75 | clk_summary_show_subtree(s, c, 0); | 138 | clk_summary_show_subtree(s, c, 0); |
@@ -77,7 +140,7 @@ static int clk_summary_show(struct seq_file *s, void *data) | |||
77 | hlist_for_each_entry(c, &clk_orphan_list, child_node) | 140 | hlist_for_each_entry(c, &clk_orphan_list, child_node) |
78 | clk_summary_show_subtree(s, c, 0); | 141 | clk_summary_show_subtree(s, c, 0); |
79 | 142 | ||
80 | mutex_unlock(&prepare_lock); | 143 | clk_prepare_unlock(); |
81 | 144 | ||
82 | return 0; | 145 | return 0; |
83 | } | 146 | } |
@@ -130,7 +193,7 @@ static int clk_dump(struct seq_file *s, void *data) | |||
130 | 193 | ||
131 | seq_printf(s, "{"); | 194 | seq_printf(s, "{"); |
132 | 195 | ||
133 | mutex_lock(&prepare_lock); | 196 | clk_prepare_lock(); |
134 | 197 | ||
135 | hlist_for_each_entry(c, &clk_root_list, child_node) { | 198 | hlist_for_each_entry(c, &clk_root_list, child_node) { |
136 | if (!first_node) | 199 | if (!first_node) |
@@ -144,7 +207,7 @@ static int clk_dump(struct seq_file *s, void *data) | |||
144 | clk_dump_subtree(s, c, 0); | 207 | clk_dump_subtree(s, c, 0); |
145 | } | 208 | } |
146 | 209 | ||
147 | mutex_unlock(&prepare_lock); | 210 | clk_prepare_unlock(); |
148 | 211 | ||
149 | seq_printf(s, "}"); | 212 | seq_printf(s, "}"); |
150 | return 0; | 213 | return 0; |
@@ -316,7 +379,7 @@ static int __init clk_debug_init(void) | |||
316 | if (!orphandir) | 379 | if (!orphandir) |
317 | return -ENOMEM; | 380 | return -ENOMEM; |
318 | 381 | ||
319 | mutex_lock(&prepare_lock); | 382 | clk_prepare_lock(); |
320 | 383 | ||
321 | hlist_for_each_entry(clk, &clk_root_list, child_node) | 384 | hlist_for_each_entry(clk, &clk_root_list, child_node) |
322 | clk_debug_create_subtree(clk, rootdir); | 385 | clk_debug_create_subtree(clk, rootdir); |
@@ -326,7 +389,7 @@ static int __init clk_debug_init(void) | |||
326 | 389 | ||
327 | inited = 1; | 390 | inited = 1; |
328 | 391 | ||
329 | mutex_unlock(&prepare_lock); | 392 | clk_prepare_unlock(); |
330 | 393 | ||
331 | return 0; | 394 | return 0; |
332 | } | 395 | } |
@@ -336,6 +399,31 @@ static inline int clk_debug_register(struct clk *clk) { return 0; } | |||
336 | #endif | 399 | #endif |
337 | 400 | ||
338 | /* caller must hold prepare_lock */ | 401 | /* caller must hold prepare_lock */ |
402 | static void clk_unprepare_unused_subtree(struct clk *clk) | ||
403 | { | ||
404 | struct clk *child; | ||
405 | |||
406 | if (!clk) | ||
407 | return; | ||
408 | |||
409 | hlist_for_each_entry(child, &clk->children, child_node) | ||
410 | clk_unprepare_unused_subtree(child); | ||
411 | |||
412 | if (clk->prepare_count) | ||
413 | return; | ||
414 | |||
415 | if (clk->flags & CLK_IGNORE_UNUSED) | ||
416 | return; | ||
417 | |||
418 | if (__clk_is_prepared(clk)) { | ||
419 | if (clk->ops->unprepare_unused) | ||
420 | clk->ops->unprepare_unused(clk->hw); | ||
421 | else if (clk->ops->unprepare) | ||
422 | clk->ops->unprepare(clk->hw); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | /* caller must hold prepare_lock */ | ||
339 | static void clk_disable_unused_subtree(struct clk *clk) | 427 | static void clk_disable_unused_subtree(struct clk *clk) |
340 | { | 428 | { |
341 | struct clk *child; | 429 | struct clk *child; |
@@ -347,7 +435,7 @@ static void clk_disable_unused_subtree(struct clk *clk) | |||
347 | hlist_for_each_entry(child, &clk->children, child_node) | 435 | hlist_for_each_entry(child, &clk->children, child_node) |
348 | clk_disable_unused_subtree(child); | 436 | clk_disable_unused_subtree(child); |
349 | 437 | ||
350 | spin_lock_irqsave(&enable_lock, flags); | 438 | flags = clk_enable_lock(); |
351 | 439 | ||
352 | if (clk->enable_count) | 440 | if (clk->enable_count) |
353 | goto unlock_out; | 441 | goto unlock_out; |
@@ -368,7 +456,7 @@ static void clk_disable_unused_subtree(struct clk *clk) | |||
368 | } | 456 | } |
369 | 457 | ||
370 | unlock_out: | 458 | unlock_out: |
371 | spin_unlock_irqrestore(&enable_lock, flags); | 459 | clk_enable_unlock(flags); |
372 | 460 | ||
373 | out: | 461 | out: |
374 | return; | 462 | return; |
@@ -378,7 +466,7 @@ static int clk_disable_unused(void) | |||
378 | { | 466 | { |
379 | struct clk *clk; | 467 | struct clk *clk; |
380 | 468 | ||
381 | mutex_lock(&prepare_lock); | 469 | clk_prepare_lock(); |
382 | 470 | ||
383 | hlist_for_each_entry(clk, &clk_root_list, child_node) | 471 | hlist_for_each_entry(clk, &clk_root_list, child_node) |
384 | clk_disable_unused_subtree(clk); | 472 | clk_disable_unused_subtree(clk); |
@@ -386,7 +474,13 @@ static int clk_disable_unused(void) | |||
386 | hlist_for_each_entry(clk, &clk_orphan_list, child_node) | 474 | hlist_for_each_entry(clk, &clk_orphan_list, child_node) |
387 | clk_disable_unused_subtree(clk); | 475 | clk_disable_unused_subtree(clk); |
388 | 476 | ||
389 | mutex_unlock(&prepare_lock); | 477 | hlist_for_each_entry(clk, &clk_root_list, child_node) |
478 | clk_unprepare_unused_subtree(clk); | ||
479 | |||
480 | hlist_for_each_entry(clk, &clk_orphan_list, child_node) | ||
481 | clk_unprepare_unused_subtree(clk); | ||
482 | |||
483 | clk_prepare_unlock(); | ||
390 | 484 | ||
391 | return 0; | 485 | return 0; |
392 | } | 486 | } |
@@ -451,6 +545,27 @@ unsigned long __clk_get_flags(struct clk *clk) | |||
451 | return !clk ? 0 : clk->flags; | 545 | return !clk ? 0 : clk->flags; |
452 | } | 546 | } |
453 | 547 | ||
548 | bool __clk_is_prepared(struct clk *clk) | ||
549 | { | ||
550 | int ret; | ||
551 | |||
552 | if (!clk) | ||
553 | return false; | ||
554 | |||
555 | /* | ||
556 | * .is_prepared is optional for clocks that can prepare | ||
557 | * fall back to software usage counter if it is missing | ||
558 | */ | ||
559 | if (!clk->ops->is_prepared) { | ||
560 | ret = clk->prepare_count ? 1 : 0; | ||
561 | goto out; | ||
562 | } | ||
563 | |||
564 | ret = clk->ops->is_prepared(clk->hw); | ||
565 | out: | ||
566 | return !!ret; | ||
567 | } | ||
568 | |||
454 | bool __clk_is_enabled(struct clk *clk) | 569 | bool __clk_is_enabled(struct clk *clk) |
455 | { | 570 | { |
456 | int ret; | 571 | int ret; |
@@ -548,9 +663,9 @@ void __clk_unprepare(struct clk *clk) | |||
548 | */ | 663 | */ |
549 | void clk_unprepare(struct clk *clk) | 664 | void clk_unprepare(struct clk *clk) |
550 | { | 665 | { |
551 | mutex_lock(&prepare_lock); | 666 | clk_prepare_lock(); |
552 | __clk_unprepare(clk); | 667 | __clk_unprepare(clk); |
553 | mutex_unlock(&prepare_lock); | 668 | clk_prepare_unlock(); |
554 | } | 669 | } |
555 | EXPORT_SYMBOL_GPL(clk_unprepare); | 670 | EXPORT_SYMBOL_GPL(clk_unprepare); |
556 | 671 | ||
@@ -596,9 +711,9 @@ int clk_prepare(struct clk *clk) | |||
596 | { | 711 | { |
597 | int ret; | 712 | int ret; |
598 | 713 | ||
599 | mutex_lock(&prepare_lock); | 714 | clk_prepare_lock(); |
600 | ret = __clk_prepare(clk); | 715 | ret = __clk_prepare(clk); |
601 | mutex_unlock(&prepare_lock); | 716 | clk_prepare_unlock(); |
602 | 717 | ||
603 | return ret; | 718 | return ret; |
604 | } | 719 | } |
@@ -640,9 +755,9 @@ void clk_disable(struct clk *clk) | |||
640 | { | 755 | { |
641 | unsigned long flags; | 756 | unsigned long flags; |
642 | 757 | ||
643 | spin_lock_irqsave(&enable_lock, flags); | 758 | flags = clk_enable_lock(); |
644 | __clk_disable(clk); | 759 | __clk_disable(clk); |
645 | spin_unlock_irqrestore(&enable_lock, flags); | 760 | clk_enable_unlock(flags); |
646 | } | 761 | } |
647 | EXPORT_SYMBOL_GPL(clk_disable); | 762 | EXPORT_SYMBOL_GPL(clk_disable); |
648 | 763 | ||
@@ -693,9 +808,9 @@ int clk_enable(struct clk *clk) | |||
693 | unsigned long flags; | 808 | unsigned long flags; |
694 | int ret; | 809 | int ret; |
695 | 810 | ||
696 | spin_lock_irqsave(&enable_lock, flags); | 811 | flags = clk_enable_lock(); |
697 | ret = __clk_enable(clk); | 812 | ret = __clk_enable(clk); |
698 | spin_unlock_irqrestore(&enable_lock, flags); | 813 | clk_enable_unlock(flags); |
699 | 814 | ||
700 | return ret; | 815 | return ret; |
701 | } | 816 | } |
@@ -740,9 +855,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate) | |||
740 | { | 855 | { |
741 | unsigned long ret; | 856 | unsigned long ret; |
742 | 857 | ||
743 | mutex_lock(&prepare_lock); | 858 | clk_prepare_lock(); |
744 | ret = __clk_round_rate(clk, rate); | 859 | ret = __clk_round_rate(clk, rate); |
745 | mutex_unlock(&prepare_lock); | 860 | clk_prepare_unlock(); |
746 | 861 | ||
747 | return ret; | 862 | return ret; |
748 | } | 863 | } |
@@ -837,13 +952,13 @@ unsigned long clk_get_rate(struct clk *clk) | |||
837 | { | 952 | { |
838 | unsigned long rate; | 953 | unsigned long rate; |
839 | 954 | ||
840 | mutex_lock(&prepare_lock); | 955 | clk_prepare_lock(); |
841 | 956 | ||
842 | if (clk && (clk->flags & CLK_GET_RATE_NOCACHE)) | 957 | if (clk && (clk->flags & CLK_GET_RATE_NOCACHE)) |
843 | __clk_recalc_rates(clk, 0); | 958 | __clk_recalc_rates(clk, 0); |
844 | 959 | ||
845 | rate = __clk_get_rate(clk); | 960 | rate = __clk_get_rate(clk); |
846 | mutex_unlock(&prepare_lock); | 961 | clk_prepare_unlock(); |
847 | 962 | ||
848 | return rate; | 963 | return rate; |
849 | } | 964 | } |
@@ -974,7 +1089,7 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even | |||
974 | int ret = NOTIFY_DONE; | 1089 | int ret = NOTIFY_DONE; |
975 | 1090 | ||
976 | if (clk->rate == clk->new_rate) | 1091 | if (clk->rate == clk->new_rate) |
977 | return 0; | 1092 | return NULL; |
978 | 1093 | ||
979 | if (clk->notifier_count) { | 1094 | if (clk->notifier_count) { |
980 | ret = __clk_notify(clk, event, clk->rate, clk->new_rate); | 1095 | ret = __clk_notify(clk, event, clk->rate, clk->new_rate); |
@@ -1048,7 +1163,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
1048 | int ret = 0; | 1163 | int ret = 0; |
1049 | 1164 | ||
1050 | /* prevent racing with updates to the clock topology */ | 1165 | /* prevent racing with updates to the clock topology */ |
1051 | mutex_lock(&prepare_lock); | 1166 | clk_prepare_lock(); |
1052 | 1167 | ||
1053 | /* bail early if nothing to do */ | 1168 | /* bail early if nothing to do */ |
1054 | if (rate == clk->rate) | 1169 | if (rate == clk->rate) |
@@ -1080,7 +1195,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
1080 | clk_change_rate(top); | 1195 | clk_change_rate(top); |
1081 | 1196 | ||
1082 | out: | 1197 | out: |
1083 | mutex_unlock(&prepare_lock); | 1198 | clk_prepare_unlock(); |
1084 | 1199 | ||
1085 | return ret; | 1200 | return ret; |
1086 | } | 1201 | } |
@@ -1096,9 +1211,9 @@ struct clk *clk_get_parent(struct clk *clk) | |||
1096 | { | 1211 | { |
1097 | struct clk *parent; | 1212 | struct clk *parent; |
1098 | 1213 | ||
1099 | mutex_lock(&prepare_lock); | 1214 | clk_prepare_lock(); |
1100 | parent = __clk_get_parent(clk); | 1215 | parent = __clk_get_parent(clk); |
1101 | mutex_unlock(&prepare_lock); | 1216 | clk_prepare_unlock(); |
1102 | 1217 | ||
1103 | return parent; | 1218 | return parent; |
1104 | } | 1219 | } |
@@ -1242,19 +1357,19 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent) | |||
1242 | __clk_prepare(parent); | 1357 | __clk_prepare(parent); |
1243 | 1358 | ||
1244 | /* FIXME replace with clk_is_enabled(clk) someday */ | 1359 | /* FIXME replace with clk_is_enabled(clk) someday */ |
1245 | spin_lock_irqsave(&enable_lock, flags); | 1360 | flags = clk_enable_lock(); |
1246 | if (clk->enable_count) | 1361 | if (clk->enable_count) |
1247 | __clk_enable(parent); | 1362 | __clk_enable(parent); |
1248 | spin_unlock_irqrestore(&enable_lock, flags); | 1363 | clk_enable_unlock(flags); |
1249 | 1364 | ||
1250 | /* change clock input source */ | 1365 | /* change clock input source */ |
1251 | ret = clk->ops->set_parent(clk->hw, i); | 1366 | ret = clk->ops->set_parent(clk->hw, i); |
1252 | 1367 | ||
1253 | /* clean up old prepare and enable */ | 1368 | /* clean up old prepare and enable */ |
1254 | spin_lock_irqsave(&enable_lock, flags); | 1369 | flags = clk_enable_lock(); |
1255 | if (clk->enable_count) | 1370 | if (clk->enable_count) |
1256 | __clk_disable(old_parent); | 1371 | __clk_disable(old_parent); |
1257 | spin_unlock_irqrestore(&enable_lock, flags); | 1372 | clk_enable_unlock(flags); |
1258 | 1373 | ||
1259 | if (clk->prepare_count) | 1374 | if (clk->prepare_count) |
1260 | __clk_unprepare(old_parent); | 1375 | __clk_unprepare(old_parent); |
@@ -1286,7 +1401,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent) | |||
1286 | return -ENOSYS; | 1401 | return -ENOSYS; |
1287 | 1402 | ||
1288 | /* prevent racing with updates to the clock topology */ | 1403 | /* prevent racing with updates to the clock topology */ |
1289 | mutex_lock(&prepare_lock); | 1404 | clk_prepare_lock(); |
1290 | 1405 | ||
1291 | if (clk->parent == parent) | 1406 | if (clk->parent == parent) |
1292 | goto out; | 1407 | goto out; |
@@ -1315,7 +1430,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent) | |||
1315 | __clk_reparent(clk, parent); | 1430 | __clk_reparent(clk, parent); |
1316 | 1431 | ||
1317 | out: | 1432 | out: |
1318 | mutex_unlock(&prepare_lock); | 1433 | clk_prepare_unlock(); |
1319 | 1434 | ||
1320 | return ret; | 1435 | return ret; |
1321 | } | 1436 | } |
@@ -1338,7 +1453,7 @@ int __clk_init(struct device *dev, struct clk *clk) | |||
1338 | if (!clk) | 1453 | if (!clk) |
1339 | return -EINVAL; | 1454 | return -EINVAL; |
1340 | 1455 | ||
1341 | mutex_lock(&prepare_lock); | 1456 | clk_prepare_lock(); |
1342 | 1457 | ||
1343 | /* check to see if a clock with this name is already registered */ | 1458 | /* check to see if a clock with this name is already registered */ |
1344 | if (__clk_lookup(clk->name)) { | 1459 | if (__clk_lookup(clk->name)) { |
@@ -1462,7 +1577,7 @@ int __clk_init(struct device *dev, struct clk *clk) | |||
1462 | clk_debug_register(clk); | 1577 | clk_debug_register(clk); |
1463 | 1578 | ||
1464 | out: | 1579 | out: |
1465 | mutex_unlock(&prepare_lock); | 1580 | clk_prepare_unlock(); |
1466 | 1581 | ||
1467 | return ret; | 1582 | return ret; |
1468 | } | 1583 | } |
@@ -1696,7 +1811,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb) | |||
1696 | if (!clk || !nb) | 1811 | if (!clk || !nb) |
1697 | return -EINVAL; | 1812 | return -EINVAL; |
1698 | 1813 | ||
1699 | mutex_lock(&prepare_lock); | 1814 | clk_prepare_lock(); |
1700 | 1815 | ||
1701 | /* search the list of notifiers for this clk */ | 1816 | /* search the list of notifiers for this clk */ |
1702 | list_for_each_entry(cn, &clk_notifier_list, node) | 1817 | list_for_each_entry(cn, &clk_notifier_list, node) |
@@ -1720,7 +1835,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb) | |||
1720 | clk->notifier_count++; | 1835 | clk->notifier_count++; |
1721 | 1836 | ||
1722 | out: | 1837 | out: |
1723 | mutex_unlock(&prepare_lock); | 1838 | clk_prepare_unlock(); |
1724 | 1839 | ||
1725 | return ret; | 1840 | return ret; |
1726 | } | 1841 | } |
@@ -1745,7 +1860,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) | |||
1745 | if (!clk || !nb) | 1860 | if (!clk || !nb) |
1746 | return -EINVAL; | 1861 | return -EINVAL; |
1747 | 1862 | ||
1748 | mutex_lock(&prepare_lock); | 1863 | clk_prepare_lock(); |
1749 | 1864 | ||
1750 | list_for_each_entry(cn, &clk_notifier_list, node) | 1865 | list_for_each_entry(cn, &clk_notifier_list, node) |
1751 | if (cn->clk == clk) | 1866 | if (cn->clk == clk) |
@@ -1766,7 +1881,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) | |||
1766 | ret = -ENOENT; | 1881 | ret = -ENOENT; |
1767 | } | 1882 | } |
1768 | 1883 | ||
1769 | mutex_unlock(&prepare_lock); | 1884 | clk_prepare_unlock(); |
1770 | 1885 | ||
1771 | return ret; | 1886 | return ret; |
1772 | } | 1887 | } |
diff --git a/drivers/clk/mxs/clk.c b/drivers/clk/mxs/clk.c index b24d56067c80..5301bce8957b 100644 --- a/drivers/clk/mxs/clk.c +++ b/drivers/clk/mxs/clk.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/io.h> | 13 | #include <linux/io.h> |
14 | #include <linux/jiffies.h> | 14 | #include <linux/jiffies.h> |
15 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
16 | #include "clk.h" | ||
16 | 17 | ||
17 | DEFINE_SPINLOCK(mxs_lock); | 18 | DEFINE_SPINLOCK(mxs_lock); |
18 | 19 | ||
diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c index 82abea366b78..35e7e2698e10 100644 --- a/drivers/clk/spear/spear1340_clock.c +++ b/drivers/clk/spear/spear1340_clock.c | |||
@@ -960,47 +960,47 @@ void __init spear1340_clk_init(void) | |||
960 | SPEAR1340_SPDIF_IN_CLK_ENB, 0, &_lock); | 960 | SPEAR1340_SPDIF_IN_CLK_ENB, 0, &_lock); |
961 | clk_register_clkdev(clk, NULL, "d0100000.spdif-in"); | 961 | clk_register_clkdev(clk, NULL, "d0100000.spdif-in"); |
962 | 962 | ||
963 | clk = clk_register_gate(NULL, "acp_clk", "acp_mclk", 0, | 963 | clk = clk_register_gate(NULL, "acp_clk", "ahb_clk", 0, |
964 | SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_ACP_CLK_ENB, 0, | 964 | SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_ACP_CLK_ENB, 0, |
965 | &_lock); | 965 | &_lock); |
966 | clk_register_clkdev(clk, NULL, "acp_clk"); | 966 | clk_register_clkdev(clk, NULL, "acp_clk"); |
967 | 967 | ||
968 | clk = clk_register_gate(NULL, "plgpio_clk", "plgpio_mclk", 0, | 968 | clk = clk_register_gate(NULL, "plgpio_clk", "ahb_clk", 0, |
969 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PLGPIO_CLK_ENB, 0, | 969 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PLGPIO_CLK_ENB, 0, |
970 | &_lock); | 970 | &_lock); |
971 | clk_register_clkdev(clk, NULL, "e2800000.gpio"); | 971 | clk_register_clkdev(clk, NULL, "e2800000.gpio"); |
972 | 972 | ||
973 | clk = clk_register_gate(NULL, "video_dec_clk", "video_dec_mclk", 0, | 973 | clk = clk_register_gate(NULL, "video_dec_clk", "ahb_clk", 0, |
974 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_DEC_CLK_ENB, | 974 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_DEC_CLK_ENB, |
975 | 0, &_lock); | 975 | 0, &_lock); |
976 | clk_register_clkdev(clk, NULL, "video_dec"); | 976 | clk_register_clkdev(clk, NULL, "video_dec"); |
977 | 977 | ||
978 | clk = clk_register_gate(NULL, "video_enc_clk", "video_enc_mclk", 0, | 978 | clk = clk_register_gate(NULL, "video_enc_clk", "ahb_clk", 0, |
979 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_ENC_CLK_ENB, | 979 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_ENC_CLK_ENB, |
980 | 0, &_lock); | 980 | 0, &_lock); |
981 | clk_register_clkdev(clk, NULL, "video_enc"); | 981 | clk_register_clkdev(clk, NULL, "video_enc"); |
982 | 982 | ||
983 | clk = clk_register_gate(NULL, "video_in_clk", "video_in_mclk", 0, | 983 | clk = clk_register_gate(NULL, "video_in_clk", "ahb_clk", 0, |
984 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_IN_CLK_ENB, 0, | 984 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_IN_CLK_ENB, 0, |
985 | &_lock); | 985 | &_lock); |
986 | clk_register_clkdev(clk, NULL, "spear_vip"); | 986 | clk_register_clkdev(clk, NULL, "spear_vip"); |
987 | 987 | ||
988 | clk = clk_register_gate(NULL, "cam0_clk", "cam0_mclk", 0, | 988 | clk = clk_register_gate(NULL, "cam0_clk", "ahb_clk", 0, |
989 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM0_CLK_ENB, 0, | 989 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM0_CLK_ENB, 0, |
990 | &_lock); | 990 | &_lock); |
991 | clk_register_clkdev(clk, NULL, "d0200000.cam0"); | 991 | clk_register_clkdev(clk, NULL, "d0200000.cam0"); |
992 | 992 | ||
993 | clk = clk_register_gate(NULL, "cam1_clk", "cam1_mclk", 0, | 993 | clk = clk_register_gate(NULL, "cam1_clk", "ahb_clk", 0, |
994 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM1_CLK_ENB, 0, | 994 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM1_CLK_ENB, 0, |
995 | &_lock); | 995 | &_lock); |
996 | clk_register_clkdev(clk, NULL, "d0300000.cam1"); | 996 | clk_register_clkdev(clk, NULL, "d0300000.cam1"); |
997 | 997 | ||
998 | clk = clk_register_gate(NULL, "cam2_clk", "cam2_mclk", 0, | 998 | clk = clk_register_gate(NULL, "cam2_clk", "ahb_clk", 0, |
999 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM2_CLK_ENB, 0, | 999 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM2_CLK_ENB, 0, |
1000 | &_lock); | 1000 | &_lock); |
1001 | clk_register_clkdev(clk, NULL, "d0400000.cam2"); | 1001 | clk_register_clkdev(clk, NULL, "d0400000.cam2"); |
1002 | 1002 | ||
1003 | clk = clk_register_gate(NULL, "cam3_clk", "cam3_mclk", 0, | 1003 | clk = clk_register_gate(NULL, "cam3_clk", "ahb_clk", 0, |
1004 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM3_CLK_ENB, 0, | 1004 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM3_CLK_ENB, 0, |
1005 | &_lock); | 1005 | &_lock); |
1006 | clk_register_clkdev(clk, NULL, "d0500000.cam3"); | 1006 | clk_register_clkdev(clk, NULL, "d0500000.cam3"); |
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile new file mode 100644 index 000000000000..b5bac917612c --- /dev/null +++ b/drivers/clk/sunxi/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # | ||
2 | # Makefile for sunxi specific clk | ||
3 | # | ||
4 | |||
5 | obj-y += clk-sunxi.o clk-factors.o | ||
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c new file mode 100644 index 000000000000..88523f91d9b7 --- /dev/null +++ b/drivers/clk/sunxi/clk-factors.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Emilio López <emilio@elopez.com.ar> | ||
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 | * Adjustable factor-based clock implementation | ||
9 | */ | ||
10 | |||
11 | #include <linux/clk-provider.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/string.h> | ||
17 | |||
18 | #include <linux/delay.h> | ||
19 | |||
20 | #include "clk-factors.h" | ||
21 | |||
22 | /* | ||
23 | * DOC: basic adjustable factor-based clock that cannot gate | ||
24 | * | ||
25 | * Traits of this clock: | ||
26 | * prepare - clk_prepare only ensures that parents are prepared | ||
27 | * enable - clk_enable only ensures that parents are enabled | ||
28 | * rate - rate is adjustable. | ||
29 | * clk->rate = (parent->rate * N * (K + 1) >> P) / (M + 1) | ||
30 | * parent - fixed parent. No clk_set_parent support | ||
31 | */ | ||
32 | |||
33 | struct clk_factors { | ||
34 | struct clk_hw hw; | ||
35 | void __iomem *reg; | ||
36 | struct clk_factors_config *config; | ||
37 | void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p); | ||
38 | spinlock_t *lock; | ||
39 | }; | ||
40 | |||
41 | #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) | ||
42 | |||
43 | #define SETMASK(len, pos) (((-1U) >> (31-len)) << (pos)) | ||
44 | #define CLRMASK(len, pos) (~(SETMASK(len, pos))) | ||
45 | #define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit)) | ||
46 | |||
47 | #define FACTOR_SET(bit, len, reg, val) \ | ||
48 | (((reg) & CLRMASK(len, bit)) | (val << (bit))) | ||
49 | |||
50 | static unsigned long clk_factors_recalc_rate(struct clk_hw *hw, | ||
51 | unsigned long parent_rate) | ||
52 | { | ||
53 | u8 n = 1, k = 0, p = 0, m = 0; | ||
54 | u32 reg; | ||
55 | unsigned long rate; | ||
56 | struct clk_factors *factors = to_clk_factors(hw); | ||
57 | struct clk_factors_config *config = factors->config; | ||
58 | |||
59 | /* Fetch the register value */ | ||
60 | reg = readl(factors->reg); | ||
61 | |||
62 | /* Get each individual factor if applicable */ | ||
63 | if (config->nwidth != SUNXI_FACTORS_NOT_APPLICABLE) | ||
64 | n = FACTOR_GET(config->nshift, config->nwidth, reg); | ||
65 | if (config->kwidth != SUNXI_FACTORS_NOT_APPLICABLE) | ||
66 | k = FACTOR_GET(config->kshift, config->kwidth, reg); | ||
67 | if (config->mwidth != SUNXI_FACTORS_NOT_APPLICABLE) | ||
68 | m = FACTOR_GET(config->mshift, config->mwidth, reg); | ||
69 | if (config->pwidth != SUNXI_FACTORS_NOT_APPLICABLE) | ||
70 | p = FACTOR_GET(config->pshift, config->pwidth, reg); | ||
71 | |||
72 | /* Calculate the rate */ | ||
73 | rate = (parent_rate * n * (k + 1) >> p) / (m + 1); | ||
74 | |||
75 | return rate; | ||
76 | } | ||
77 | |||
78 | static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, | ||
79 | unsigned long *parent_rate) | ||
80 | { | ||
81 | struct clk_factors *factors = to_clk_factors(hw); | ||
82 | factors->get_factors((u32 *)&rate, (u32)*parent_rate, | ||
83 | NULL, NULL, NULL, NULL); | ||
84 | |||
85 | return rate; | ||
86 | } | ||
87 | |||
88 | static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, | ||
89 | unsigned long parent_rate) | ||
90 | { | ||
91 | u8 n, k, m, p; | ||
92 | u32 reg; | ||
93 | struct clk_factors *factors = to_clk_factors(hw); | ||
94 | struct clk_factors_config *config = factors->config; | ||
95 | unsigned long flags = 0; | ||
96 | |||
97 | factors->get_factors((u32 *)&rate, (u32)parent_rate, &n, &k, &m, &p); | ||
98 | |||
99 | if (factors->lock) | ||
100 | spin_lock_irqsave(factors->lock, flags); | ||
101 | |||
102 | /* Fetch the register value */ | ||
103 | reg = readl(factors->reg); | ||
104 | |||
105 | /* Set up the new factors - macros do not do anything if width is 0 */ | ||
106 | reg = FACTOR_SET(config->nshift, config->nwidth, reg, n); | ||
107 | reg = FACTOR_SET(config->kshift, config->kwidth, reg, k); | ||
108 | reg = FACTOR_SET(config->mshift, config->mwidth, reg, m); | ||
109 | reg = FACTOR_SET(config->pshift, config->pwidth, reg, p); | ||
110 | |||
111 | /* Apply them now */ | ||
112 | writel(reg, factors->reg); | ||
113 | |||
114 | /* delay 500us so pll stabilizes */ | ||
115 | __delay((rate >> 20) * 500 / 2); | ||
116 | |||
117 | if (factors->lock) | ||
118 | spin_unlock_irqrestore(factors->lock, flags); | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static const struct clk_ops clk_factors_ops = { | ||
124 | .recalc_rate = clk_factors_recalc_rate, | ||
125 | .round_rate = clk_factors_round_rate, | ||
126 | .set_rate = clk_factors_set_rate, | ||
127 | }; | ||
128 | |||
129 | /** | ||
130 | * clk_register_factors - register a factors clock with | ||
131 | * the clock framework | ||
132 | * @dev: device registering this clock | ||
133 | * @name: name of this clock | ||
134 | * @parent_name: name of clock's parent | ||
135 | * @flags: framework-specific flags | ||
136 | * @reg: register address to adjust factors | ||
137 | * @config: shift and width of factors n, k, m and p | ||
138 | * @get_factors: function to calculate the factors for a given frequency | ||
139 | * @lock: shared register lock for this clock | ||
140 | */ | ||
141 | struct clk *clk_register_factors(struct device *dev, const char *name, | ||
142 | const char *parent_name, | ||
143 | unsigned long flags, void __iomem *reg, | ||
144 | struct clk_factors_config *config, | ||
145 | void (*get_factors)(u32 *rate, u32 parent, | ||
146 | u8 *n, u8 *k, u8 *m, u8 *p), | ||
147 | spinlock_t *lock) | ||
148 | { | ||
149 | struct clk_factors *factors; | ||
150 | struct clk *clk; | ||
151 | struct clk_init_data init; | ||
152 | |||
153 | /* allocate the factors */ | ||
154 | factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL); | ||
155 | if (!factors) { | ||
156 | pr_err("%s: could not allocate factors clk\n", __func__); | ||
157 | return ERR_PTR(-ENOMEM); | ||
158 | } | ||
159 | |||
160 | init.name = name; | ||
161 | init.ops = &clk_factors_ops; | ||
162 | init.flags = flags; | ||
163 | init.parent_names = (parent_name ? &parent_name : NULL); | ||
164 | init.num_parents = (parent_name ? 1 : 0); | ||
165 | |||
166 | /* struct clk_factors assignments */ | ||
167 | factors->reg = reg; | ||
168 | factors->config = config; | ||
169 | factors->lock = lock; | ||
170 | factors->hw.init = &init; | ||
171 | factors->get_factors = get_factors; | ||
172 | |||
173 | /* register the clock */ | ||
174 | clk = clk_register(dev, &factors->hw); | ||
175 | |||
176 | if (IS_ERR(clk)) | ||
177 | kfree(factors); | ||
178 | |||
179 | return clk; | ||
180 | } | ||
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h new file mode 100644 index 000000000000..f49851cc4380 --- /dev/null +++ b/drivers/clk/sunxi/clk-factors.h | |||
@@ -0,0 +1,27 @@ | |||
1 | #ifndef __MACH_SUNXI_CLK_FACTORS_H | ||
2 | #define __MACH_SUNXI_CLK_FACTORS_H | ||
3 | |||
4 | #include <linux/clk-provider.h> | ||
5 | #include <linux/clkdev.h> | ||
6 | |||
7 | #define SUNXI_FACTORS_NOT_APPLICABLE (0) | ||
8 | |||
9 | struct clk_factors_config { | ||
10 | u8 nshift; | ||
11 | u8 nwidth; | ||
12 | u8 kshift; | ||
13 | u8 kwidth; | ||
14 | u8 mshift; | ||
15 | u8 mwidth; | ||
16 | u8 pshift; | ||
17 | u8 pwidth; | ||
18 | }; | ||
19 | |||
20 | struct clk *clk_register_factors(struct device *dev, const char *name, | ||
21 | const char *parent_name, | ||
22 | unsigned long flags, void __iomem *reg, | ||
23 | struct clk_factors_config *config, | ||
24 | void (*get_factors) (u32 *rate, u32 parent_rate, | ||
25 | u8 *n, u8 *k, u8 *m, u8 *p), | ||
26 | spinlock_t *lock); | ||
27 | #endif | ||
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c new file mode 100644 index 000000000000..d528a2496690 --- /dev/null +++ b/drivers/clk/sunxi/clk-sunxi.c | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | * Copyright 2013 Emilio López | ||
3 | * | ||
4 | * Emilio López <emilio@elopez.com.ar> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/clk-provider.h> | ||
18 | #include <linux/clkdev.h> | ||
19 | #include <linux/clk/sunxi.h> | ||
20 | #include <linux/of.h> | ||
21 | #include <linux/of_address.h> | ||
22 | |||
23 | #include "clk-factors.h" | ||
24 | |||
25 | static DEFINE_SPINLOCK(clk_lock); | ||
26 | |||
27 | /** | ||
28 | * sunxi_osc_clk_setup() - Setup function for gatable oscillator | ||
29 | */ | ||
30 | |||
31 | #define SUNXI_OSC24M_GATE 0 | ||
32 | |||
33 | static void __init sunxi_osc_clk_setup(struct device_node *node) | ||
34 | { | ||
35 | struct clk *clk; | ||
36 | const char *clk_name = node->name; | ||
37 | const char *parent; | ||
38 | void *reg; | ||
39 | |||
40 | reg = of_iomap(node, 0); | ||
41 | |||
42 | parent = of_clk_get_parent_name(node, 0); | ||
43 | |||
44 | clk = clk_register_gate(NULL, clk_name, parent, CLK_IGNORE_UNUSED, | ||
45 | reg, SUNXI_OSC24M_GATE, 0, &clk_lock); | ||
46 | |||
47 | if (clk) { | ||
48 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
49 | clk_register_clkdev(clk, clk_name, NULL); | ||
50 | } | ||
51 | } | ||
52 | |||
53 | |||
54 | |||
55 | /** | ||
56 | * sunxi_get_pll1_factors() - calculates n, k, m, p factors for PLL1 | ||
57 | * PLL1 rate is calculated as follows | ||
58 | * rate = (parent_rate * n * (k + 1) >> p) / (m + 1); | ||
59 | * parent_rate is always 24Mhz | ||
60 | */ | ||
61 | |||
62 | static void sunxi_get_pll1_factors(u32 *freq, u32 parent_rate, | ||
63 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
64 | { | ||
65 | u8 div; | ||
66 | |||
67 | /* Normalize value to a 6M multiple */ | ||
68 | div = *freq / 6000000; | ||
69 | *freq = 6000000 * div; | ||
70 | |||
71 | /* we were called to round the frequency, we can now return */ | ||
72 | if (n == NULL) | ||
73 | return; | ||
74 | |||
75 | /* m is always zero for pll1 */ | ||
76 | *m = 0; | ||
77 | |||
78 | /* k is 1 only on these cases */ | ||
79 | if (*freq >= 768000000 || *freq == 42000000 || *freq == 54000000) | ||
80 | *k = 1; | ||
81 | else | ||
82 | *k = 0; | ||
83 | |||
84 | /* p will be 3 for divs under 10 */ | ||
85 | if (div < 10) | ||
86 | *p = 3; | ||
87 | |||
88 | /* p will be 2 for divs between 10 - 20 and odd divs under 32 */ | ||
89 | else if (div < 20 || (div < 32 && (div & 1))) | ||
90 | *p = 2; | ||
91 | |||
92 | /* p will be 1 for even divs under 32, divs under 40 and odd pairs | ||
93 | * of divs between 40-62 */ | ||
94 | else if (div < 40 || (div < 64 && (div & 2))) | ||
95 | *p = 1; | ||
96 | |||
97 | /* any other entries have p = 0 */ | ||
98 | else | ||
99 | *p = 0; | ||
100 | |||
101 | /* calculate a suitable n based on k and p */ | ||
102 | div <<= *p; | ||
103 | div /= (*k + 1); | ||
104 | *n = div / 4; | ||
105 | } | ||
106 | |||
107 | |||
108 | |||
109 | /** | ||
110 | * sunxi_get_apb1_factors() - calculates m, p factors for APB1 | ||
111 | * APB1 rate is calculated as follows | ||
112 | * rate = (parent_rate >> p) / (m + 1); | ||
113 | */ | ||
114 | |||
115 | static void sunxi_get_apb1_factors(u32 *freq, u32 parent_rate, | ||
116 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
117 | { | ||
118 | u8 calcm, calcp; | ||
119 | |||
120 | if (parent_rate < *freq) | ||
121 | *freq = parent_rate; | ||
122 | |||
123 | parent_rate = (parent_rate + (*freq - 1)) / *freq; | ||
124 | |||
125 | /* Invalid rate! */ | ||
126 | if (parent_rate > 32) | ||
127 | return; | ||
128 | |||
129 | if (parent_rate <= 4) | ||
130 | calcp = 0; | ||
131 | else if (parent_rate <= 8) | ||
132 | calcp = 1; | ||
133 | else if (parent_rate <= 16) | ||
134 | calcp = 2; | ||
135 | else | ||
136 | calcp = 3; | ||
137 | |||
138 | calcm = (parent_rate >> calcp) - 1; | ||
139 | |||
140 | *freq = (parent_rate >> calcp) / (calcm + 1); | ||
141 | |||
142 | /* we were called to round the frequency, we can now return */ | ||
143 | if (n == NULL) | ||
144 | return; | ||
145 | |||
146 | *m = calcm; | ||
147 | *p = calcp; | ||
148 | } | ||
149 | |||
150 | |||
151 | |||
152 | /** | ||
153 | * sunxi_factors_clk_setup() - Setup function for factor clocks | ||
154 | */ | ||
155 | |||
156 | struct factors_data { | ||
157 | struct clk_factors_config *table; | ||
158 | void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); | ||
159 | }; | ||
160 | |||
161 | static struct clk_factors_config pll1_config = { | ||
162 | .nshift = 8, | ||
163 | .nwidth = 5, | ||
164 | .kshift = 4, | ||
165 | .kwidth = 2, | ||
166 | .mshift = 0, | ||
167 | .mwidth = 2, | ||
168 | .pshift = 16, | ||
169 | .pwidth = 2, | ||
170 | }; | ||
171 | |||
172 | static struct clk_factors_config apb1_config = { | ||
173 | .mshift = 0, | ||
174 | .mwidth = 5, | ||
175 | .pshift = 16, | ||
176 | .pwidth = 2, | ||
177 | }; | ||
178 | |||
179 | static const __initconst struct factors_data pll1_data = { | ||
180 | .table = &pll1_config, | ||
181 | .getter = sunxi_get_pll1_factors, | ||
182 | }; | ||
183 | |||
184 | static const __initconst struct factors_data apb1_data = { | ||
185 | .table = &apb1_config, | ||
186 | .getter = sunxi_get_apb1_factors, | ||
187 | }; | ||
188 | |||
189 | static void __init sunxi_factors_clk_setup(struct device_node *node, | ||
190 | struct factors_data *data) | ||
191 | { | ||
192 | struct clk *clk; | ||
193 | const char *clk_name = node->name; | ||
194 | const char *parent; | ||
195 | void *reg; | ||
196 | |||
197 | reg = of_iomap(node, 0); | ||
198 | |||
199 | parent = of_clk_get_parent_name(node, 0); | ||
200 | |||
201 | clk = clk_register_factors(NULL, clk_name, parent, CLK_IGNORE_UNUSED, | ||
202 | reg, data->table, data->getter, &clk_lock); | ||
203 | |||
204 | if (clk) { | ||
205 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
206 | clk_register_clkdev(clk, clk_name, NULL); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | |||
211 | |||
212 | /** | ||
213 | * sunxi_mux_clk_setup() - Setup function for muxes | ||
214 | */ | ||
215 | |||
216 | #define SUNXI_MUX_GATE_WIDTH 2 | ||
217 | |||
218 | struct mux_data { | ||
219 | u8 shift; | ||
220 | }; | ||
221 | |||
222 | static const __initconst struct mux_data cpu_data = { | ||
223 | .shift = 16, | ||
224 | }; | ||
225 | |||
226 | static const __initconst struct mux_data apb1_mux_data = { | ||
227 | .shift = 24, | ||
228 | }; | ||
229 | |||
230 | static void __init sunxi_mux_clk_setup(struct device_node *node, | ||
231 | struct mux_data *data) | ||
232 | { | ||
233 | struct clk *clk; | ||
234 | const char *clk_name = node->name; | ||
235 | const char **parents = kmalloc(sizeof(char *) * 5, GFP_KERNEL); | ||
236 | void *reg; | ||
237 | int i = 0; | ||
238 | |||
239 | reg = of_iomap(node, 0); | ||
240 | |||
241 | while (i < 5 && (parents[i] = of_clk_get_parent_name(node, i)) != NULL) | ||
242 | i++; | ||
243 | |||
244 | clk = clk_register_mux(NULL, clk_name, parents, i, 0, reg, | ||
245 | data->shift, SUNXI_MUX_GATE_WIDTH, | ||
246 | 0, &clk_lock); | ||
247 | |||
248 | if (clk) { | ||
249 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
250 | clk_register_clkdev(clk, clk_name, NULL); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | |||
255 | |||
256 | /** | ||
257 | * sunxi_divider_clk_setup() - Setup function for simple divider clocks | ||
258 | */ | ||
259 | |||
260 | #define SUNXI_DIVISOR_WIDTH 2 | ||
261 | |||
262 | struct div_data { | ||
263 | u8 shift; | ||
264 | u8 pow; | ||
265 | }; | ||
266 | |||
267 | static const __initconst struct div_data axi_data = { | ||
268 | .shift = 0, | ||
269 | .pow = 0, | ||
270 | }; | ||
271 | |||
272 | static const __initconst struct div_data ahb_data = { | ||
273 | .shift = 4, | ||
274 | .pow = 1, | ||
275 | }; | ||
276 | |||
277 | static const __initconst struct div_data apb0_data = { | ||
278 | .shift = 8, | ||
279 | .pow = 1, | ||
280 | }; | ||
281 | |||
282 | static void __init sunxi_divider_clk_setup(struct device_node *node, | ||
283 | struct div_data *data) | ||
284 | { | ||
285 | struct clk *clk; | ||
286 | const char *clk_name = node->name; | ||
287 | const char *clk_parent; | ||
288 | void *reg; | ||
289 | |||
290 | reg = of_iomap(node, 0); | ||
291 | |||
292 | clk_parent = of_clk_get_parent_name(node, 0); | ||
293 | |||
294 | clk = clk_register_divider(NULL, clk_name, clk_parent, 0, | ||
295 | reg, data->shift, SUNXI_DIVISOR_WIDTH, | ||
296 | data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0, | ||
297 | &clk_lock); | ||
298 | if (clk) { | ||
299 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
300 | clk_register_clkdev(clk, clk_name, NULL); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | |||
305 | /* Matches for of_clk_init */ | ||
306 | static const __initconst struct of_device_id clk_match[] = { | ||
307 | {.compatible = "fixed-clock", .data = of_fixed_clk_setup,}, | ||
308 | {.compatible = "allwinner,sun4i-osc-clk", .data = sunxi_osc_clk_setup,}, | ||
309 | {} | ||
310 | }; | ||
311 | |||
312 | /* Matches for factors clocks */ | ||
313 | static const __initconst struct of_device_id clk_factors_match[] = { | ||
314 | {.compatible = "allwinner,sun4i-pll1-clk", .data = &pll1_data,}, | ||
315 | {.compatible = "allwinner,sun4i-apb1-clk", .data = &apb1_data,}, | ||
316 | {} | ||
317 | }; | ||
318 | |||
319 | /* Matches for divider clocks */ | ||
320 | static const __initconst struct of_device_id clk_div_match[] = { | ||
321 | {.compatible = "allwinner,sun4i-axi-clk", .data = &axi_data,}, | ||
322 | {.compatible = "allwinner,sun4i-ahb-clk", .data = &ahb_data,}, | ||
323 | {.compatible = "allwinner,sun4i-apb0-clk", .data = &apb0_data,}, | ||
324 | {} | ||
325 | }; | ||
326 | |||
327 | /* Matches for mux clocks */ | ||
328 | static const __initconst struct of_device_id clk_mux_match[] = { | ||
329 | {.compatible = "allwinner,sun4i-cpu-clk", .data = &cpu_data,}, | ||
330 | {.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &apb1_mux_data,}, | ||
331 | {} | ||
332 | }; | ||
333 | |||
334 | static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_match, | ||
335 | void *function) | ||
336 | { | ||
337 | struct device_node *np; | ||
338 | const struct div_data *data; | ||
339 | const struct of_device_id *match; | ||
340 | void (*setup_function)(struct device_node *, const void *) = function; | ||
341 | |||
342 | for_each_matching_node(np, clk_match) { | ||
343 | match = of_match_node(clk_match, np); | ||
344 | data = match->data; | ||
345 | setup_function(np, data); | ||
346 | } | ||
347 | } | ||
348 | |||
349 | void __init sunxi_init_clocks(void) | ||
350 | { | ||
351 | /* Register all the simple sunxi clocks on DT */ | ||
352 | of_clk_init(clk_match); | ||
353 | |||
354 | /* Register factor clocks */ | ||
355 | of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); | ||
356 | |||
357 | /* Register divider clocks */ | ||
358 | of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup); | ||
359 | |||
360 | /* Register mux clocks */ | ||
361 | of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup); | ||
362 | } | ||
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 0744731c6229..a09d7dcaf183 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h | |||
@@ -355,15 +355,16 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name, | |||
355 | struct tegra_clk_periph *periph, void __iomem *clk_base, | 355 | struct tegra_clk_periph *periph, void __iomem *clk_base, |
356 | u32 offset); | 356 | u32 offset); |
357 | 357 | ||
358 | #define TEGRA_CLK_PERIPH(_mux_shift, _mux_width, _mux_flags, \ | 358 | #define TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, _mux_flags, \ |
359 | _div_shift, _div_width, _div_frac_width, \ | 359 | _div_shift, _div_width, _div_frac_width, \ |
360 | _div_flags, _clk_num, _enb_refcnt, _regs, \ | 360 | _div_flags, _clk_num, _enb_refcnt, _regs, \ |
361 | _gate_flags) \ | 361 | _gate_flags, _table) \ |
362 | { \ | 362 | { \ |
363 | .mux = { \ | 363 | .mux = { \ |
364 | .flags = _mux_flags, \ | 364 | .flags = _mux_flags, \ |
365 | .shift = _mux_shift, \ | 365 | .shift = _mux_shift, \ |
366 | .width = _mux_width, \ | 366 | .mask = _mux_mask, \ |
367 | .table = _table, \ | ||
367 | }, \ | 368 | }, \ |
368 | .divider = { \ | 369 | .divider = { \ |
369 | .flags = _div_flags, \ | 370 | .flags = _div_flags, \ |
@@ -393,26 +394,36 @@ struct tegra_periph_init_data { | |||
393 | const char *dev_id; | 394 | const char *dev_id; |
394 | }; | 395 | }; |
395 | 396 | ||
396 | #define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset, \ | 397 | #define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\ |
397 | _mux_shift, _mux_width, _mux_flags, _div_shift, \ | 398 | _mux_shift, _mux_mask, _mux_flags, _div_shift, \ |
398 | _div_width, _div_frac_width, _div_flags, _regs, \ | 399 | _div_width, _div_frac_width, _div_flags, _regs, \ |
399 | _clk_num, _enb_refcnt, _gate_flags, _clk_id) \ | 400 | _clk_num, _enb_refcnt, _gate_flags, _clk_id, _table) \ |
400 | { \ | 401 | { \ |
401 | .name = _name, \ | 402 | .name = _name, \ |
402 | .clk_id = _clk_id, \ | 403 | .clk_id = _clk_id, \ |
403 | .parent_names = _parent_names, \ | 404 | .parent_names = _parent_names, \ |
404 | .num_parents = ARRAY_SIZE(_parent_names), \ | 405 | .num_parents = ARRAY_SIZE(_parent_names), \ |
405 | .periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_width, \ | 406 | .periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, \ |
406 | _mux_flags, _div_shift, \ | 407 | _mux_flags, _div_shift, \ |
407 | _div_width, _div_frac_width, \ | 408 | _div_width, _div_frac_width, \ |
408 | _div_flags, _clk_num, \ | 409 | _div_flags, _clk_num, \ |
409 | _enb_refcnt, _regs, \ | 410 | _enb_refcnt, _regs, \ |
410 | _gate_flags), \ | 411 | _gate_flags, _table), \ |
411 | .offset = _offset, \ | 412 | .offset = _offset, \ |
412 | .con_id = _con_id, \ | 413 | .con_id = _con_id, \ |
413 | .dev_id = _dev_id, \ | 414 | .dev_id = _dev_id, \ |
414 | } | 415 | } |
415 | 416 | ||
417 | #define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\ | ||
418 | _mux_shift, _mux_width, _mux_flags, _div_shift, \ | ||
419 | _div_width, _div_frac_width, _div_flags, _regs, \ | ||
420 | _clk_num, _enb_refcnt, _gate_flags, _clk_id) \ | ||
421 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\ | ||
422 | _mux_shift, BIT(_mux_width) - 1, _mux_flags, \ | ||
423 | _div_shift, _div_width, _div_frac_width, _div_flags, \ | ||
424 | _regs, _clk_num, _enb_refcnt, _gate_flags, _clk_id,\ | ||
425 | NULL) | ||
426 | |||
416 | /** | 427 | /** |
417 | * struct clk_super_mux - super clock | 428 | * struct clk_super_mux - super clock |
418 | * | 429 | * |
diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c index 74faa7e3cf59..293a28854417 100644 --- a/drivers/clk/ux500/clk-prcmu.c +++ b/drivers/clk/ux500/clk-prcmu.c | |||
@@ -20,15 +20,23 @@ | |||
20 | struct clk_prcmu { | 20 | struct clk_prcmu { |
21 | struct clk_hw hw; | 21 | struct clk_hw hw; |
22 | u8 cg_sel; | 22 | u8 cg_sel; |
23 | int is_prepared; | ||
23 | int is_enabled; | 24 | int is_enabled; |
25 | int opp_requested; | ||
24 | }; | 26 | }; |
25 | 27 | ||
26 | /* PRCMU clock operations. */ | 28 | /* PRCMU clock operations. */ |
27 | 29 | ||
28 | static int clk_prcmu_prepare(struct clk_hw *hw) | 30 | static int clk_prcmu_prepare(struct clk_hw *hw) |
29 | { | 31 | { |
32 | int ret; | ||
30 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 33 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
31 | return prcmu_request_clock(clk->cg_sel, true); | 34 | |
35 | ret = prcmu_request_clock(clk->cg_sel, true); | ||
36 | if (!ret) | ||
37 | clk->is_prepared = 1; | ||
38 | |||
39 | return ret;; | ||
32 | } | 40 | } |
33 | 41 | ||
34 | static void clk_prcmu_unprepare(struct clk_hw *hw) | 42 | static void clk_prcmu_unprepare(struct clk_hw *hw) |
@@ -36,7 +44,15 @@ static void clk_prcmu_unprepare(struct clk_hw *hw) | |||
36 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 44 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
37 | if (prcmu_request_clock(clk->cg_sel, false)) | 45 | if (prcmu_request_clock(clk->cg_sel, false)) |
38 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, | 46 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, |
39 | hw->init->name); | 47 | __clk_get_name(hw->clk)); |
48 | else | ||
49 | clk->is_prepared = 0; | ||
50 | } | ||
51 | |||
52 | static int clk_prcmu_is_prepared(struct clk_hw *hw) | ||
53 | { | ||
54 | struct clk_prcmu *clk = to_clk_prcmu(hw); | ||
55 | return clk->is_prepared; | ||
40 | } | 56 | } |
41 | 57 | ||
42 | static int clk_prcmu_enable(struct clk_hw *hw) | 58 | static int clk_prcmu_enable(struct clk_hw *hw) |
@@ -79,58 +95,52 @@ static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate, | |||
79 | return prcmu_set_clock_rate(clk->cg_sel, rate); | 95 | return prcmu_set_clock_rate(clk->cg_sel, rate); |
80 | } | 96 | } |
81 | 97 | ||
82 | static int request_ape_opp100(bool enable) | ||
83 | { | ||
84 | static int reqs; | ||
85 | int err = 0; | ||
86 | |||
87 | if (enable) { | ||
88 | if (!reqs) | ||
89 | err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, | ||
90 | "clock", 100); | ||
91 | if (!err) | ||
92 | reqs++; | ||
93 | } else { | ||
94 | reqs--; | ||
95 | if (!reqs) | ||
96 | prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, | ||
97 | "clock"); | ||
98 | } | ||
99 | return err; | ||
100 | } | ||
101 | |||
102 | static int clk_prcmu_opp_prepare(struct clk_hw *hw) | 98 | static int clk_prcmu_opp_prepare(struct clk_hw *hw) |
103 | { | 99 | { |
104 | int err; | 100 | int err; |
105 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 101 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
106 | 102 | ||
107 | err = request_ape_opp100(true); | 103 | if (!clk->opp_requested) { |
108 | if (err) { | 104 | err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, |
109 | pr_err("clk_prcmu: %s failed to request APE OPP100 for %s.\n", | 105 | (char *)__clk_get_name(hw->clk), |
110 | __func__, hw->init->name); | 106 | 100); |
111 | return err; | 107 | if (err) { |
108 | pr_err("clk_prcmu: %s fail req APE OPP for %s.\n", | ||
109 | __func__, __clk_get_name(hw->clk)); | ||
110 | return err; | ||
111 | } | ||
112 | clk->opp_requested = 1; | ||
112 | } | 113 | } |
113 | 114 | ||
114 | err = prcmu_request_clock(clk->cg_sel, true); | 115 | err = prcmu_request_clock(clk->cg_sel, true); |
115 | if (err) | 116 | if (err) { |
116 | request_ape_opp100(false); | 117 | prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, |
118 | (char *)__clk_get_name(hw->clk)); | ||
119 | clk->opp_requested = 0; | ||
120 | return err; | ||
121 | } | ||
117 | 122 | ||
118 | return err; | 123 | clk->is_prepared = 1; |
124 | return 0; | ||
119 | } | 125 | } |
120 | 126 | ||
121 | static void clk_prcmu_opp_unprepare(struct clk_hw *hw) | 127 | static void clk_prcmu_opp_unprepare(struct clk_hw *hw) |
122 | { | 128 | { |
123 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 129 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
124 | 130 | ||
125 | if (prcmu_request_clock(clk->cg_sel, false)) | 131 | if (prcmu_request_clock(clk->cg_sel, false)) { |
126 | goto out_error; | 132 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, |
127 | if (request_ape_opp100(false)) | 133 | __clk_get_name(hw->clk)); |
128 | goto out_error; | 134 | return; |
129 | return; | 135 | } |
130 | 136 | ||
131 | out_error: | 137 | if (clk->opp_requested) { |
132 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, | 138 | prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, |
133 | hw->init->name); | 139 | (char *)__clk_get_name(hw->clk)); |
140 | clk->opp_requested = 0; | ||
141 | } | ||
142 | |||
143 | clk->is_prepared = 0; | ||
134 | } | 144 | } |
135 | 145 | ||
136 | static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw) | 146 | static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw) |
@@ -138,38 +148,49 @@ static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw) | |||
138 | int err; | 148 | int err; |
139 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 149 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
140 | 150 | ||
141 | err = prcmu_request_ape_opp_100_voltage(true); | 151 | if (!clk->opp_requested) { |
142 | if (err) { | 152 | err = prcmu_request_ape_opp_100_voltage(true); |
143 | pr_err("clk_prcmu: %s failed to request APE OPP VOLT for %s.\n", | 153 | if (err) { |
144 | __func__, hw->init->name); | 154 | pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n", |
145 | return err; | 155 | __func__, __clk_get_name(hw->clk)); |
156 | return err; | ||
157 | } | ||
158 | clk->opp_requested = 1; | ||
146 | } | 159 | } |
147 | 160 | ||
148 | err = prcmu_request_clock(clk->cg_sel, true); | 161 | err = prcmu_request_clock(clk->cg_sel, true); |
149 | if (err) | 162 | if (err) { |
150 | prcmu_request_ape_opp_100_voltage(false); | 163 | prcmu_request_ape_opp_100_voltage(false); |
164 | clk->opp_requested = 0; | ||
165 | return err; | ||
166 | } | ||
151 | 167 | ||
152 | return err; | 168 | clk->is_prepared = 1; |
169 | return 0; | ||
153 | } | 170 | } |
154 | 171 | ||
155 | static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw) | 172 | static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw) |
156 | { | 173 | { |
157 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 174 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
158 | 175 | ||
159 | if (prcmu_request_clock(clk->cg_sel, false)) | 176 | if (prcmu_request_clock(clk->cg_sel, false)) { |
160 | goto out_error; | 177 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, |
161 | if (prcmu_request_ape_opp_100_voltage(false)) | 178 | __clk_get_name(hw->clk)); |
162 | goto out_error; | 179 | return; |
163 | return; | 180 | } |
164 | 181 | ||
165 | out_error: | 182 | if (clk->opp_requested) { |
166 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, | 183 | prcmu_request_ape_opp_100_voltage(false); |
167 | hw->init->name); | 184 | clk->opp_requested = 0; |
185 | } | ||
186 | |||
187 | clk->is_prepared = 0; | ||
168 | } | 188 | } |
169 | 189 | ||
170 | static struct clk_ops clk_prcmu_scalable_ops = { | 190 | static struct clk_ops clk_prcmu_scalable_ops = { |
171 | .prepare = clk_prcmu_prepare, | 191 | .prepare = clk_prcmu_prepare, |
172 | .unprepare = clk_prcmu_unprepare, | 192 | .unprepare = clk_prcmu_unprepare, |
193 | .is_prepared = clk_prcmu_is_prepared, | ||
173 | .enable = clk_prcmu_enable, | 194 | .enable = clk_prcmu_enable, |
174 | .disable = clk_prcmu_disable, | 195 | .disable = clk_prcmu_disable, |
175 | .is_enabled = clk_prcmu_is_enabled, | 196 | .is_enabled = clk_prcmu_is_enabled, |
@@ -181,6 +202,7 @@ static struct clk_ops clk_prcmu_scalable_ops = { | |||
181 | static struct clk_ops clk_prcmu_gate_ops = { | 202 | static struct clk_ops clk_prcmu_gate_ops = { |
182 | .prepare = clk_prcmu_prepare, | 203 | .prepare = clk_prcmu_prepare, |
183 | .unprepare = clk_prcmu_unprepare, | 204 | .unprepare = clk_prcmu_unprepare, |
205 | .is_prepared = clk_prcmu_is_prepared, | ||
184 | .enable = clk_prcmu_enable, | 206 | .enable = clk_prcmu_enable, |
185 | .disable = clk_prcmu_disable, | 207 | .disable = clk_prcmu_disable, |
186 | .is_enabled = clk_prcmu_is_enabled, | 208 | .is_enabled = clk_prcmu_is_enabled, |
@@ -202,6 +224,7 @@ static struct clk_ops clk_prcmu_rate_ops = { | |||
202 | static struct clk_ops clk_prcmu_opp_gate_ops = { | 224 | static struct clk_ops clk_prcmu_opp_gate_ops = { |
203 | .prepare = clk_prcmu_opp_prepare, | 225 | .prepare = clk_prcmu_opp_prepare, |
204 | .unprepare = clk_prcmu_opp_unprepare, | 226 | .unprepare = clk_prcmu_opp_unprepare, |
227 | .is_prepared = clk_prcmu_is_prepared, | ||
205 | .enable = clk_prcmu_enable, | 228 | .enable = clk_prcmu_enable, |
206 | .disable = clk_prcmu_disable, | 229 | .disable = clk_prcmu_disable, |
207 | .is_enabled = clk_prcmu_is_enabled, | 230 | .is_enabled = clk_prcmu_is_enabled, |
@@ -211,6 +234,7 @@ static struct clk_ops clk_prcmu_opp_gate_ops = { | |||
211 | static struct clk_ops clk_prcmu_opp_volt_scalable_ops = { | 234 | static struct clk_ops clk_prcmu_opp_volt_scalable_ops = { |
212 | .prepare = clk_prcmu_opp_volt_prepare, | 235 | .prepare = clk_prcmu_opp_volt_prepare, |
213 | .unprepare = clk_prcmu_opp_volt_unprepare, | 236 | .unprepare = clk_prcmu_opp_volt_unprepare, |
237 | .is_prepared = clk_prcmu_is_prepared, | ||
214 | .enable = clk_prcmu_enable, | 238 | .enable = clk_prcmu_enable, |
215 | .disable = clk_prcmu_disable, | 239 | .disable = clk_prcmu_disable, |
216 | .is_enabled = clk_prcmu_is_enabled, | 240 | .is_enabled = clk_prcmu_is_enabled, |
@@ -242,7 +266,9 @@ static struct clk *clk_reg_prcmu(const char *name, | |||
242 | } | 266 | } |
243 | 267 | ||
244 | clk->cg_sel = cg_sel; | 268 | clk->cg_sel = cg_sel; |
269 | clk->is_prepared = 1; | ||
245 | clk->is_enabled = 1; | 270 | clk->is_enabled = 1; |
271 | clk->opp_requested = 0; | ||
246 | /* "rate" can be used for changing the initial frequency */ | 272 | /* "rate" can be used for changing the initial frequency */ |
247 | if (rate) | 273 | if (rate) |
248 | prcmu_set_clock_rate(cg_sel, rate); | 274 | prcmu_set_clock_rate(cg_sel, rate); |
diff --git a/drivers/clocksource/sunxi_timer.c b/drivers/clocksource/sunxi_timer.c index 4086b9167159..0ce85e29769b 100644 --- a/drivers/clocksource/sunxi_timer.c +++ b/drivers/clocksource/sunxi_timer.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/of_address.h> | 23 | #include <linux/of_address.h> |
24 | #include <linux/of_irq.h> | 24 | #include <linux/of_irq.h> |
25 | #include <linux/sunxi_timer.h> | 25 | #include <linux/sunxi_timer.h> |
26 | #include <linux/clk-provider.h> | 26 | #include <linux/clk/sunxi.h> |
27 | 27 | ||
28 | #define TIMER_CTL_REG 0x00 | 28 | #define TIMER_CTL_REG 0x00 |
29 | #define TIMER_CTL_ENABLE (1 << 0) | 29 | #define TIMER_CTL_ENABLE (1 << 0) |
@@ -123,7 +123,7 @@ void __init sunxi_timer_init(void) | |||
123 | if (irq <= 0) | 123 | if (irq <= 0) |
124 | panic("Can't parse IRQ"); | 124 | panic("Can't parse IRQ"); |
125 | 125 | ||
126 | of_clk_init(NULL); | 126 | sunxi_init_clocks(); |
127 | 127 | ||
128 | clk = of_clk_get(node, 0); | 128 | clk = of_clk_get(node, 0); |
129 | if (IS_ERR(clk)) | 129 | if (IS_ERR(clk)) |
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h index 9c7f5807824b..dd7adff76e81 100644 --- a/include/linux/clk-private.h +++ b/include/linux/clk-private.h | |||
@@ -152,7 +152,7 @@ struct clk { | |||
152 | }, \ | 152 | }, \ |
153 | .reg = _reg, \ | 153 | .reg = _reg, \ |
154 | .shift = _shift, \ | 154 | .shift = _shift, \ |
155 | .width = _width, \ | 155 | .mask = BIT(_width) - 1, \ |
156 | .flags = _mux_flags, \ | 156 | .flags = _mux_flags, \ |
157 | .lock = _lock, \ | 157 | .lock = _lock, \ |
158 | }; \ | 158 | }; \ |
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 7f197d7addb0..1f0352802794 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h | |||
@@ -45,6 +45,14 @@ struct clk_hw; | |||
45 | * undo any work done in the @prepare callback. Called with | 45 | * undo any work done in the @prepare callback. Called with |
46 | * prepare_lock held. | 46 | * prepare_lock held. |
47 | * | 47 | * |
48 | * @is_prepared: Queries the hardware to determine if the clock is prepared. | ||
49 | * This function is allowed to sleep. Optional, if this op is not | ||
50 | * set then the prepare count will be used. | ||
51 | * | ||
52 | * @unprepare_unused: Unprepare the clock atomically. Only called from | ||
53 | * clk_disable_unused for prepare clocks with special needs. | ||
54 | * Called with prepare mutex held. This function may sleep. | ||
55 | * | ||
48 | * @enable: Enable the clock atomically. This must not return until the | 56 | * @enable: Enable the clock atomically. This must not return until the |
49 | * clock is generating a valid clock signal, usable by consumer | 57 | * clock is generating a valid clock signal, usable by consumer |
50 | * devices. Called with enable_lock held. This function must not | 58 | * devices. Called with enable_lock held. This function must not |
@@ -108,6 +116,8 @@ struct clk_hw; | |||
108 | struct clk_ops { | 116 | struct clk_ops { |
109 | int (*prepare)(struct clk_hw *hw); | 117 | int (*prepare)(struct clk_hw *hw); |
110 | void (*unprepare)(struct clk_hw *hw); | 118 | void (*unprepare)(struct clk_hw *hw); |
119 | int (*is_prepared)(struct clk_hw *hw); | ||
120 | void (*unprepare_unused)(struct clk_hw *hw); | ||
111 | int (*enable)(struct clk_hw *hw); | 121 | int (*enable)(struct clk_hw *hw); |
112 | void (*disable)(struct clk_hw *hw); | 122 | void (*disable)(struct clk_hw *hw); |
113 | int (*is_enabled)(struct clk_hw *hw); | 123 | int (*is_enabled)(struct clk_hw *hw); |
@@ -287,8 +297,9 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name, | |||
287 | struct clk_mux { | 297 | struct clk_mux { |
288 | struct clk_hw hw; | 298 | struct clk_hw hw; |
289 | void __iomem *reg; | 299 | void __iomem *reg; |
300 | u32 *table; | ||
301 | u32 mask; | ||
290 | u8 shift; | 302 | u8 shift; |
291 | u8 width; | ||
292 | u8 flags; | 303 | u8 flags; |
293 | spinlock_t *lock; | 304 | spinlock_t *lock; |
294 | }; | 305 | }; |
@@ -297,11 +308,17 @@ struct clk_mux { | |||
297 | #define CLK_MUX_INDEX_BIT BIT(1) | 308 | #define CLK_MUX_INDEX_BIT BIT(1) |
298 | 309 | ||
299 | extern const struct clk_ops clk_mux_ops; | 310 | extern const struct clk_ops clk_mux_ops; |
311 | |||
300 | struct clk *clk_register_mux(struct device *dev, const char *name, | 312 | struct clk *clk_register_mux(struct device *dev, const char *name, |
301 | const char **parent_names, u8 num_parents, unsigned long flags, | 313 | const char **parent_names, u8 num_parents, unsigned long flags, |
302 | void __iomem *reg, u8 shift, u8 width, | 314 | void __iomem *reg, u8 shift, u8 width, |
303 | u8 clk_mux_flags, spinlock_t *lock); | 315 | u8 clk_mux_flags, spinlock_t *lock); |
304 | 316 | ||
317 | struct clk *clk_register_mux_table(struct device *dev, const char *name, | ||
318 | const char **parent_names, u8 num_parents, unsigned long flags, | ||
319 | void __iomem *reg, u8 shift, u32 mask, | ||
320 | u8 clk_mux_flags, u32 *table, spinlock_t *lock); | ||
321 | |||
305 | /** | 322 | /** |
306 | * struct clk_fixed_factor - fixed multiplier and divider clock | 323 | * struct clk_fixed_factor - fixed multiplier and divider clock |
307 | * | 324 | * |
@@ -325,6 +342,37 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name, | |||
325 | const char *parent_name, unsigned long flags, | 342 | const char *parent_name, unsigned long flags, |
326 | unsigned int mult, unsigned int div); | 343 | unsigned int mult, unsigned int div); |
327 | 344 | ||
345 | /*** | ||
346 | * struct clk_composite - aggregate clock of mux, divider and gate clocks | ||
347 | * | ||
348 | * @hw: handle between common and hardware-specific interfaces | ||
349 | * @mux_hw: handle between composite and hardware-specifix mux clock | ||
350 | * @div_hw: handle between composite and hardware-specifix divider clock | ||
351 | * @gate_hw: handle between composite and hardware-specifix gate clock | ||
352 | * @mux_ops: clock ops for mux | ||
353 | * @div_ops: clock ops for divider | ||
354 | * @gate_ops: clock ops for gate | ||
355 | */ | ||
356 | struct clk_composite { | ||
357 | struct clk_hw hw; | ||
358 | struct clk_ops ops; | ||
359 | |||
360 | struct clk_hw *mux_hw; | ||
361 | struct clk_hw *div_hw; | ||
362 | struct clk_hw *gate_hw; | ||
363 | |||
364 | const struct clk_ops *mux_ops; | ||
365 | const struct clk_ops *div_ops; | ||
366 | const struct clk_ops *gate_ops; | ||
367 | }; | ||
368 | |||
369 | struct clk *clk_register_composite(struct device *dev, const char *name, | ||
370 | const char **parent_names, int num_parents, | ||
371 | struct clk_hw *mux_hw, const struct clk_ops *mux_ops, | ||
372 | struct clk_hw *div_hw, const struct clk_ops *div_ops, | ||
373 | struct clk_hw *gate_hw, const struct clk_ops *gate_ops, | ||
374 | unsigned long flags); | ||
375 | |||
328 | /** | 376 | /** |
329 | * clk_register - allocate a new clock, register it and return an opaque cookie | 377 | * clk_register - allocate a new clock, register it and return an opaque cookie |
330 | * @dev: device that is registering this clock | 378 | * @dev: device that is registering this clock |
@@ -351,6 +399,7 @@ unsigned int __clk_get_enable_count(struct clk *clk); | |||
351 | unsigned int __clk_get_prepare_count(struct clk *clk); | 399 | unsigned int __clk_get_prepare_count(struct clk *clk); |
352 | unsigned long __clk_get_rate(struct clk *clk); | 400 | unsigned long __clk_get_rate(struct clk *clk); |
353 | unsigned long __clk_get_flags(struct clk *clk); | 401 | unsigned long __clk_get_flags(struct clk *clk); |
402 | bool __clk_is_prepared(struct clk *clk); | ||
354 | bool __clk_is_enabled(struct clk *clk); | 403 | bool __clk_is_enabled(struct clk *clk); |
355 | struct clk *__clk_lookup(const char *name); | 404 | struct clk *__clk_lookup(const char *name); |
356 | 405 | ||
diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h new file mode 100644 index 000000000000..e074fdd5a236 --- /dev/null +++ b/include/linux/clk/sunxi.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Maxime Ripard | ||
3 | * | ||
4 | * Maxime Ripard <maxime.ripard@free-electrons.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #ifndef __LINUX_CLK_SUNXI_H_ | ||
18 | #define __LINUX_CLK_SUNXI_H_ | ||
19 | |||
20 | void __init sunxi_init_clocks(void); | ||
21 | |||
22 | #endif | ||