aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2014-11-20 08:42:02 -0500
committerJiri Kosina <jkosina@suse.cz>2014-11-20 08:42:02 -0500
commita02001086bbfb4da35d1228bebc2f1b442db455f (patch)
tree62ab47936cef06fd08657ca5b6cd1df98c19be57 /drivers/clk
parenteff264efeeb0898408e8c9df72d8a32621035bed (diff)
parentfc14f9c1272f62c3e8d01300f52467c0d9af50f9 (diff)
Merge Linus' tree to be be to apply submitted patches to newer code than
current trivial.git base
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/Kconfig25
-rw-r--r--drivers/clk/Makefile5
-rw-r--r--drivers/clk/at91/Makefile1
-rw-r--r--drivers/clk/at91/clk-h32mx.c123
-rw-r--r--drivers/clk/at91/clk-pll.c160
-rw-r--r--drivers/clk/at91/clk-slow.c2
-rw-r--r--drivers/clk/at91/clk-system.c8
-rw-r--r--drivers/clk/at91/clk-usb.c20
-rw-r--r--drivers/clk/at91/pmc.c6
-rw-r--r--drivers/clk/at91/pmc.h5
-rw-r--r--drivers/clk/clk-axi-clkgen.c1
-rw-r--r--drivers/clk/clk-efm32gg.c6
-rw-r--r--drivers/clk/clk-fractional-divider.c2
-rw-r--r--drivers/clk/clk-gate.c2
-rw-r--r--drivers/clk/clk-gpio-gate.c205
-rw-r--r--drivers/clk/clk-max-gen.c192
-rw-r--r--drivers/clk/clk-max-gen.h32
-rw-r--r--drivers/clk/clk-max77686.c184
-rw-r--r--drivers/clk/clk-max77802.c97
-rw-r--r--drivers/clk/clk-palmas.c1
-rw-r--r--drivers/clk/clk-rk808.c170
-rw-r--r--drivers/clk/clk-twl6040.c1
-rw-r--r--drivers/clk/clk-wm831x.c1
-rw-r--r--drivers/clk/clk.c175
-rw-r--r--drivers/clk/hisilicon/clk-hix5hd2.c232
-rw-r--r--drivers/clk/mvebu/armada-370.c8
-rw-r--r--drivers/clk/mvebu/armada-375.c4
-rw-r--r--drivers/clk/mvebu/clk-cpu.c80
-rw-r--r--drivers/clk/mvebu/common.c91
-rw-r--r--drivers/clk/mvebu/common.h9
-rw-r--r--drivers/clk/mvebu/kirkwood.c102
-rw-r--r--drivers/clk/pxa/Makefile2
-rw-r--r--drivers/clk/pxa/clk-pxa.c97
-rw-r--r--drivers/clk/pxa/clk-pxa.h107
-rw-r--r--drivers/clk/pxa/clk-pxa27x.c370
-rw-r--r--drivers/clk/qcom/clk-pll.c68
-rw-r--r--drivers/clk/qcom/clk-pll.h20
-rw-r--r--drivers/clk/qcom/clk-rcg.c115
-rw-r--r--drivers/clk/qcom/clk-rcg.h6
-rw-r--r--drivers/clk/qcom/clk-rcg2.c19
-rw-r--r--drivers/clk/qcom/common.c16
-rw-r--r--drivers/clk/qcom/common.h4
-rw-r--r--drivers/clk/qcom/gcc-ipq806x.c33
-rw-r--r--drivers/clk/qcom/mmcc-apq8084.c1
-rw-r--r--drivers/clk/qcom/mmcc-msm8960.c29
-rw-r--r--drivers/clk/qcom/mmcc-msm8974.c1
-rw-r--r--drivers/clk/rockchip/Makefile1
-rw-r--r--drivers/clk/rockchip/clk-cpu.c329
-rw-r--r--drivers/clk/rockchip/clk-pll.c63
-rw-r--r--drivers/clk/rockchip/clk-rk3188.c171
-rw-r--r--drivers/clk/rockchip/clk-rk3288.c207
-rw-r--r--drivers/clk/rockchip/clk.c119
-rw-r--r--drivers/clk/rockchip/clk.h39
-rw-r--r--drivers/clk/samsung/Makefile1
-rw-r--r--drivers/clk/samsung/clk-exynos3250.c202
-rw-r--r--drivers/clk/samsung/clk-exynos4.c18
-rw-r--r--drivers/clk/samsung/clk-exynos5260.c2
-rw-r--r--drivers/clk/samsung/clk-s3c2410-dclk.c1
-rw-r--r--drivers/clk/samsung/clk-s3c2412.c29
-rw-r--r--drivers/clk/samsung/clk-s3c2443.c19
-rw-r--r--drivers/clk/samsung/clk-s5pv210-audss.c241
-rw-r--r--drivers/clk/samsung/clk-s5pv210.c856
-rw-r--r--drivers/clk/shmobile/Makefile3
-rw-r--r--drivers/clk/shmobile/clk-rcar-gen2.c1
-rw-r--r--drivers/clk/sunxi/Makefile2
-rw-r--r--drivers/clk/sunxi/clk-factors.c101
-rw-r--r--drivers/clk/sunxi/clk-factors.h16
-rw-r--r--drivers/clk/sunxi/clk-mod0.c283
-rw-r--r--drivers/clk/sunxi/clk-sun6i-apb0-gates.c1
-rw-r--r--drivers/clk/sunxi/clk-sun6i-apb0.c1
-rw-r--r--drivers/clk/sunxi/clk-sun6i-ar100.c1
-rw-r--r--drivers/clk/sunxi/clk-sun8i-apb0.c1
-rw-r--r--drivers/clk/sunxi/clk-sun8i-mbus.c78
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c161
-rw-r--r--drivers/clk/tegra/clk-periph-gate.c3
-rw-r--r--drivers/clk/tegra/clk-tegra124.c8
-rw-r--r--drivers/clk/tegra/clk-tegra30.c5
-rw-r--r--drivers/clk/tegra/clk.c12
-rw-r--r--drivers/clk/ti/clk-dra7-atl.c9
-rw-r--r--drivers/clk/ti/clk.c68
-rw-r--r--drivers/clk/ti/clockdomain.c5
-rw-r--r--drivers/clk/ti/divider.c11
-rw-r--r--drivers/clk/versatile/Makefile3
-rw-r--r--drivers/clk/versatile/clk-versatile.c (renamed from drivers/clk/versatile/clk-integrator.c)38
-rw-r--r--drivers/clk/zynq/clkc.c30
-rw-r--r--drivers/clk/zynq/pll.c4
86 files changed, 5185 insertions, 796 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 01abbbe49bab..3f44f292d066 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -32,12 +32,32 @@ config COMMON_CLK_WM831X
32 32
33source "drivers/clk/versatile/Kconfig" 33source "drivers/clk/versatile/Kconfig"
34 34
35config COMMON_CLK_MAX_GEN
36 bool
37
35config COMMON_CLK_MAX77686 38config COMMON_CLK_MAX77686
36 tristate "Clock driver for Maxim 77686 MFD" 39 tristate "Clock driver for Maxim 77686 MFD"
37 depends on MFD_MAX77686 40 depends on MFD_MAX77686
41 select COMMON_CLK_MAX_GEN
38 ---help--- 42 ---help---
39 This driver supports Maxim 77686 crystal oscillator clock. 43 This driver supports Maxim 77686 crystal oscillator clock.
40 44
45config COMMON_CLK_MAX77802
46 tristate "Clock driver for Maxim 77802 PMIC"
47 depends on MFD_MAX77686
48 select COMMON_CLK_MAX_GEN
49 ---help---
50 This driver supports Maxim 77802 crystal oscillator clock.
51
52config COMMON_CLK_RK808
53 tristate "Clock driver for RK808"
54 depends on MFD_RK808
55 ---help---
56 This driver supports RK808 crystal oscillator clock. These
57 multi-function devices have two fixed-rate oscillators,
58 clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
59 by control register.
60
41config COMMON_CLK_SI5351 61config COMMON_CLK_SI5351
42 tristate "Clock driver for SiLabs 5351A/B/C" 62 tristate "Clock driver for SiLabs 5351A/B/C"
43 depends on I2C 63 depends on I2C
@@ -109,6 +129,11 @@ config COMMON_CLK_PALMAS
109 This driver supports TI Palmas devices 32KHz output KG and KG_AUDIO 129 This driver supports TI Palmas devices 32KHz output KG and KG_AUDIO
110 using common clock framework. 130 using common clock framework.
111 131
132config COMMON_CLK_PXA
133 def_bool COMMON_CLK && ARCH_PXA
134 ---help---
135 Sypport for the Marvell PXA SoC.
136
112source "drivers/clk/qcom/Kconfig" 137source "drivers/clk/qcom/Kconfig"
113 138
114endmenu 139endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index f537a0b1f798..d5fba5bc6e1b 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-gate.o
9obj-$(CONFIG_COMMON_CLK) += clk-mux.o 9obj-$(CONFIG_COMMON_CLK) += clk-mux.o
10obj-$(CONFIG_COMMON_CLK) += clk-composite.o 10obj-$(CONFIG_COMMON_CLK) += clk-composite.o
11obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o 11obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o
12obj-$(CONFIG_COMMON_CLK) += clk-gpio-gate.o
12ifeq ($(CONFIG_OF), y) 13ifeq ($(CONFIG_OF), y)
13obj-$(CONFIG_COMMON_CLK) += clk-conf.o 14obj-$(CONFIG_COMMON_CLK) += clk-conf.o
14endif 15endif
@@ -22,12 +23,15 @@ obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
22obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o 23obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
23obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o 24obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
24obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o 25obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
26obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o
25obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o 27obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
28obj-$(CONFIG_COMMON_CLK_MAX77802) += clk-max77802.o
26obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o 29obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o
27obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o 30obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
28obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o 31obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o
29obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o 32obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o
30obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o 33obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o
34obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o
31obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o 35obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
32obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o 36obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
33obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o 37obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
@@ -48,6 +52,7 @@ obj-$(CONFIG_ARCH_MMP) += mmp/
48endif 52endif
49obj-$(CONFIG_PLAT_ORION) += mvebu/ 53obj-$(CONFIG_PLAT_ORION) += mvebu/
50obj-$(CONFIG_ARCH_MXS) += mxs/ 54obj-$(CONFIG_ARCH_MXS) += mxs/
55obj-$(CONFIG_COMMON_CLK_PXA) += pxa/
51obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ 56obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/
52obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ 57obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
53obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ 58obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile
index 4998aee59267..89a48a7bd5df 100644
--- a/drivers/clk/at91/Makefile
+++ b/drivers/clk/at91/Makefile
@@ -9,3 +9,4 @@ obj-y += clk-system.o clk-peripheral.o clk-programmable.o
9obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o 9obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o
10obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o 10obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o
11obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o 11obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o
12obj-$(CONFIG_HAVE_AT91_H32MX) += clk-h32mx.o
diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c
new file mode 100644
index 000000000000..152dcb3f7b5f
--- /dev/null
+++ b/drivers/clk/at91/clk-h32mx.c
@@ -0,0 +1,123 @@
1/*
2 * clk-h32mx.c
3 *
4 * Copyright (C) 2014 Atmel
5 *
6 * Alexandre Belloni <alexandre.belloni@free-electrons.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 */
14
15#include <linux/clk-provider.h>
16#include <linux/clkdev.h>
17#include <linux/clk/at91_pmc.h>
18#include <linux/delay.h>
19#include <linux/of.h>
20#include <linux/of_address.h>
21#include <linux/of_irq.h>
22#include <linux/io.h>
23#include <linux/interrupt.h>
24#include <linux/irq.h>
25#include <linux/sched.h>
26#include <linux/wait.h>
27
28#include "pmc.h"
29
30#define H32MX_MAX_FREQ 90000000
31
32struct clk_sama5d4_h32mx {
33 struct clk_hw hw;
34 struct at91_pmc *pmc;
35};
36
37#define to_clk_sama5d4_h32mx(hw) container_of(hw, struct clk_sama5d4_h32mx, hw)
38
39static unsigned long clk_sama5d4_h32mx_recalc_rate(struct clk_hw *hw,
40 unsigned long parent_rate)
41{
42 struct clk_sama5d4_h32mx *h32mxclk = to_clk_sama5d4_h32mx(hw);
43
44 if (pmc_read(h32mxclk->pmc, AT91_PMC_MCKR) & AT91_PMC_H32MXDIV)
45 return parent_rate / 2;
46
47 if (parent_rate > H32MX_MAX_FREQ)
48 pr_warn("H32MX clock is too fast\n");
49 return parent_rate;
50}
51
52static long clk_sama5d4_h32mx_round_rate(struct clk_hw *hw, unsigned long rate,
53 unsigned long *parent_rate)
54{
55 unsigned long div;
56
57 if (rate > *parent_rate)
58 return *parent_rate;
59 div = *parent_rate / 2;
60 if (rate < div)
61 return div;
62
63 if (rate - div < *parent_rate - rate)
64 return div;
65
66 return *parent_rate;
67}
68
69static int clk_sama5d4_h32mx_set_rate(struct clk_hw *hw, unsigned long rate,
70 unsigned long parent_rate)
71{
72 struct clk_sama5d4_h32mx *h32mxclk = to_clk_sama5d4_h32mx(hw);
73 struct at91_pmc *pmc = h32mxclk->pmc;
74 u32 tmp;
75
76 if (parent_rate != rate && (parent_rate / 2) != rate)
77 return -EINVAL;
78
79 pmc_lock(pmc);
80 tmp = pmc_read(pmc, AT91_PMC_MCKR) & ~AT91_PMC_H32MXDIV;
81 if ((parent_rate / 2) == rate)
82 tmp |= AT91_PMC_H32MXDIV;
83 pmc_write(pmc, AT91_PMC_MCKR, tmp);
84 pmc_unlock(pmc);
85
86 return 0;
87}
88
89static const struct clk_ops h32mx_ops = {
90 .recalc_rate = clk_sama5d4_h32mx_recalc_rate,
91 .round_rate = clk_sama5d4_h32mx_round_rate,
92 .set_rate = clk_sama5d4_h32mx_set_rate,
93};
94
95void __init of_sama5d4_clk_h32mx_setup(struct device_node *np,
96 struct at91_pmc *pmc)
97{
98 struct clk_sama5d4_h32mx *h32mxclk;
99 struct clk_init_data init;
100 const char *parent_name;
101 struct clk *clk;
102
103 h32mxclk = kzalloc(sizeof(*h32mxclk), GFP_KERNEL);
104 if (!h32mxclk)
105 return;
106
107 parent_name = of_clk_get_parent_name(np, 0);
108
109 init.name = np->name;
110 init.ops = &h32mx_ops;
111 init.parent_names = parent_name ? &parent_name : NULL;
112 init.num_parents = parent_name ? 1 : 0;
113 init.flags = CLK_SET_RATE_GATE;
114
115 h32mxclk->hw.init = &init;
116 h32mxclk->pmc = pmc;
117
118 clk = clk_register(NULL, &h32mxclk->hw);
119 if (!clk)
120 return;
121
122 of_clk_add_provider(np, of_clk_src_simple_get, clk);
123}
diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c
index cf6ed023504c..6ec79dbc0840 100644
--- a/drivers/clk/at91/clk-pll.c
+++ b/drivers/clk/at91/clk-pll.c
@@ -15,6 +15,7 @@
15#include <linux/of_address.h> 15#include <linux/of_address.h>
16#include <linux/of_irq.h> 16#include <linux/of_irq.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/kernel.h>
18#include <linux/wait.h> 19#include <linux/wait.h>
19#include <linux/sched.h> 20#include <linux/sched.h>
20#include <linux/interrupt.h> 21#include <linux/interrupt.h>
@@ -29,9 +30,12 @@
29#define PLL_DIV(reg) ((reg) & PLL_DIV_MASK) 30#define PLL_DIV(reg) ((reg) & PLL_DIV_MASK)
30#define PLL_MUL(reg, layout) (((reg) >> (layout)->mul_shift) & \ 31#define PLL_MUL(reg, layout) (((reg) >> (layout)->mul_shift) & \
31 (layout)->mul_mask) 32 (layout)->mul_mask)
33#define PLL_MUL_MIN 2
34#define PLL_MUL_MASK(layout) ((layout)->mul_mask)
35#define PLL_MUL_MAX(layout) (PLL_MUL_MASK(layout) + 1)
32#define PLL_ICPR_SHIFT(id) ((id) * 16) 36#define PLL_ICPR_SHIFT(id) ((id) * 16)
33#define PLL_ICPR_MASK(id) (0xffff << PLL_ICPR_SHIFT(id)) 37#define PLL_ICPR_MASK(id) (0xffff << PLL_ICPR_SHIFT(id))
34#define PLL_MAX_COUNT 0x3ff 38#define PLL_MAX_COUNT 0x3f
35#define PLL_COUNT_SHIFT 8 39#define PLL_COUNT_SHIFT 8
36#define PLL_OUT_SHIFT 14 40#define PLL_OUT_SHIFT 14
37#define PLL_MAX_ID 1 41#define PLL_MAX_ID 1
@@ -147,115 +151,113 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
147 unsigned long parent_rate) 151 unsigned long parent_rate)
148{ 152{
149 struct clk_pll *pll = to_clk_pll(hw); 153 struct clk_pll *pll = to_clk_pll(hw);
150 const struct clk_pll_layout *layout = pll->layout; 154
151 struct at91_pmc *pmc = pll->pmc; 155 if (!pll->div || !pll->mul)
152 int offset = PLL_REG(pll->id);
153 u32 tmp = pmc_read(pmc, offset) & layout->pllr_mask;
154 u8 div = PLL_DIV(tmp);
155 u16 mul = PLL_MUL(tmp, layout);
156 if (!div || !mul)
157 return 0; 156 return 0;
158 157
159 return (parent_rate * (mul + 1)) / div; 158 return (parent_rate / pll->div) * (pll->mul + 1);
160} 159}
161 160
162static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate, 161static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate,
163 unsigned long parent_rate, 162 unsigned long parent_rate,
164 u32 *div, u32 *mul, 163 u32 *div, u32 *mul,
165 u32 *index) { 164 u32 *index) {
166 unsigned long maxrate;
167 unsigned long minrate;
168 unsigned long divrate;
169 unsigned long bestdiv = 1;
170 unsigned long bestmul;
171 unsigned long tmpdiv;
172 unsigned long roundup;
173 unsigned long rounddown;
174 unsigned long remainder;
175 unsigned long bestremainder;
176 unsigned long maxmul;
177 unsigned long maxdiv;
178 unsigned long mindiv;
179 int i = 0;
180 const struct clk_pll_layout *layout = pll->layout; 165 const struct clk_pll_layout *layout = pll->layout;
181 const struct clk_pll_characteristics *characteristics = 166 const struct clk_pll_characteristics *characteristics =
182 pll->characteristics; 167 pll->characteristics;
168 unsigned long bestremainder = ULONG_MAX;
169 unsigned long maxdiv, mindiv, tmpdiv;
170 long bestrate = -ERANGE;
171 unsigned long bestdiv;
172 unsigned long bestmul;
173 int i = 0;
183 174
184 /* Minimum divider = 1 */ 175 /* Check if parent_rate is a valid input rate */
185 /* Maximum multiplier = max_mul */
186 maxmul = layout->mul_mask + 1;
187 maxrate = (parent_rate * maxmul) / 1;
188
189 /* Maximum divider = max_div */
190 /* Minimum multiplier = 2 */
191 maxdiv = PLL_DIV_MAX;
192 minrate = (parent_rate * 2) / maxdiv;
193
194 if (parent_rate < characteristics->input.min || 176 if (parent_rate < characteristics->input.min ||
195 parent_rate < characteristics->input.max) 177 parent_rate > characteristics->input.max)
196 return -ERANGE;
197
198 if (parent_rate < minrate || parent_rate > maxrate)
199 return -ERANGE; 178 return -ERANGE;
200 179
201 for (i = 0; i < characteristics->num_output; i++) { 180 /*
202 if (parent_rate >= characteristics->output[i].min && 181 * Calculate minimum divider based on the minimum multiplier, the
203 parent_rate <= characteristics->output[i].max) 182 * parent_rate and the requested rate.
204 break; 183 * Should always be 2 according to the input and output characteristics
205 } 184 * of the PLL blocks.
206 185 */
207 if (i >= characteristics->num_output) 186 mindiv = (parent_rate * PLL_MUL_MIN) / rate;
208 return -ERANGE; 187 if (!mindiv)
209 188 mindiv = 1;
210 bestmul = rate / parent_rate; 189
211 rounddown = parent_rate % rate; 190 /*
212 roundup = rate - rounddown; 191 * Calculate the maximum divider which is limited by PLL register
213 bestremainder = roundup < rounddown ? roundup : rounddown; 192 * layout (limited by the MUL or DIV field size).
214 193 */
215 if (!bestremainder) { 194 maxdiv = DIV_ROUND_UP(parent_rate * PLL_MUL_MAX(layout), rate);
216 if (div) 195 if (maxdiv > PLL_DIV_MAX)
217 *div = bestdiv; 196 maxdiv = PLL_DIV_MAX;
218 if (mul) 197
219 *mul = bestmul; 198 /*
220 if (index) 199 * Iterate over the acceptable divider values to find the best
221 *index = i; 200 * divider/multiplier pair (the one that generates the closest
222 return rate; 201 * rate to the requested one).
223 } 202 */
224 203 for (tmpdiv = mindiv; tmpdiv <= maxdiv; tmpdiv++) {
225 maxdiv = 255 / (bestmul + 1); 204 unsigned long remainder;
226 if (parent_rate / maxdiv < characteristics->input.min) 205 unsigned long tmprate;
227 maxdiv = parent_rate / characteristics->input.min; 206 unsigned long tmpmul;
228 mindiv = parent_rate / characteristics->input.max; 207
229 if (parent_rate % characteristics->input.max) 208 /*
230 mindiv++; 209 * Calculate the multiplier associated with the current
231 210 * divider that provide the closest rate to the requested one.
232 for (tmpdiv = mindiv; tmpdiv < maxdiv; tmpdiv++) { 211 */
233 divrate = parent_rate / tmpdiv; 212 tmpmul = DIV_ROUND_CLOSEST(rate, parent_rate / tmpdiv);
234 213 tmprate = (parent_rate / tmpdiv) * tmpmul;
235 rounddown = rate % divrate; 214 if (tmprate > rate)
236 roundup = divrate - rounddown; 215 remainder = tmprate - rate;
237 remainder = roundup < rounddown ? roundup : rounddown; 216 else
238 217 remainder = rate - tmprate;
218
219 /*
220 * Compare the remainder with the best remainder found until
221 * now and elect a new best multiplier/divider pair if the
222 * current remainder is smaller than the best one.
223 */
239 if (remainder < bestremainder) { 224 if (remainder < bestremainder) {
240 bestremainder = remainder; 225 bestremainder = remainder;
241 bestmul = rate / divrate;
242 bestdiv = tmpdiv; 226 bestdiv = tmpdiv;
227 bestmul = tmpmul;
228 bestrate = tmprate;
243 } 229 }
244 230
231 /*
232 * We've found a perfect match!
233 * Stop searching now and use this multiplier/divider pair.
234 */
245 if (!remainder) 235 if (!remainder)
246 break; 236 break;
247 } 237 }
248 238
249 rate = (parent_rate / bestdiv) * bestmul; 239 /* We haven't found any multiplier/divider pair => return -ERANGE */
240 if (bestrate < 0)
241 return bestrate;
242
243 /* Check if bestrate is a valid output rate */
244 for (i = 0; i < characteristics->num_output; i++) {
245 if (bestrate >= characteristics->output[i].min &&
246 bestrate <= characteristics->output[i].max)
247 break;
248 }
249
250 if (i >= characteristics->num_output)
251 return -ERANGE;
250 252
251 if (div) 253 if (div)
252 *div = bestdiv; 254 *div = bestdiv;
253 if (mul) 255 if (mul)
254 *mul = bestmul; 256 *mul = bestmul - 1;
255 if (index) 257 if (index)
256 *index = i; 258 *index = i;
257 259
258 return rate; 260 return bestrate;
259} 261}
260 262
261static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, 263static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c
index 0300c46ee247..32f7c1b36204 100644
--- a/drivers/clk/at91/clk-slow.c
+++ b/drivers/clk/at91/clk-slow.c
@@ -447,7 +447,7 @@ void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
447 int i; 447 int i;
448 448
449 num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); 449 num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
450 if (num_parents <= 0 || num_parents > 1) 450 if (num_parents != 2)
451 return; 451 return;
452 452
453 for (i = 0; i < num_parents; ++i) { 453 for (i = 0; i < num_parents; ++i) {
diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c
index 8c96307d7363..a76d03fd577b 100644
--- a/drivers/clk/at91/clk-system.c
+++ b/drivers/clk/at91/clk-system.c
@@ -119,13 +119,7 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name,
119 init.ops = &system_ops; 119 init.ops = &system_ops;
120 init.parent_names = &parent_name; 120 init.parent_names = &parent_name;
121 init.num_parents = 1; 121 init.num_parents = 1;
122 /* 122 init.flags = CLK_SET_RATE_PARENT;
123 * CLK_IGNORE_UNUSED is used to avoid ddrck switch off.
124 * TODO : we should implement a driver supporting at91 ddr controller
125 * (see drivers/memory) which would request and enable the ddrck clock.
126 * When this is done we will be able to remove CLK_IGNORE_UNUSED flag.
127 */
128 init.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED;
129 123
130 sys->id = id; 124 sys->id = id;
131 sys->hw.init = &init; 125 sys->hw.init = &init;
diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c
index 7d1d26a4bd04..24b5b020753a 100644
--- a/drivers/clk/at91/clk-usb.c
+++ b/drivers/clk/at91/clk-usb.c
@@ -238,16 +238,22 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
238 unsigned long *parent_rate) 238 unsigned long *parent_rate)
239{ 239{
240 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); 240 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
241 struct clk *parent = __clk_get_parent(hw->clk);
241 unsigned long bestrate = 0; 242 unsigned long bestrate = 0;
242 int bestdiff = -1; 243 int bestdiff = -1;
243 unsigned long tmprate; 244 unsigned long tmprate;
244 int tmpdiff; 245 int tmpdiff;
245 int i = 0; 246 int i = 0;
246 247
247 for (i = 0; i < 4; i++) { 248 for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) {
249 unsigned long tmp_parent_rate;
250
248 if (!usb->divisors[i]) 251 if (!usb->divisors[i])
249 continue; 252 continue;
250 tmprate = *parent_rate / usb->divisors[i]; 253
254 tmp_parent_rate = rate * usb->divisors[i];
255 tmp_parent_rate = __clk_round_rate(parent, tmp_parent_rate);
256 tmprate = tmp_parent_rate / usb->divisors[i];
251 if (tmprate < rate) 257 if (tmprate < rate)
252 tmpdiff = rate - tmprate; 258 tmpdiff = rate - tmprate;
253 else 259 else
@@ -256,6 +262,7 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
256 if (bestdiff < 0 || bestdiff > tmpdiff) { 262 if (bestdiff < 0 || bestdiff > tmpdiff) {
257 bestrate = tmprate; 263 bestrate = tmprate;
258 bestdiff = tmpdiff; 264 bestdiff = tmpdiff;
265 *parent_rate = tmp_parent_rate;
259 } 266 }
260 267
261 if (!bestdiff) 268 if (!bestdiff)
@@ -272,10 +279,13 @@ static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
272 int i; 279 int i;
273 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); 280 struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
274 struct at91_pmc *pmc = usb->pmc; 281 struct at91_pmc *pmc = usb->pmc;
275 unsigned long div = parent_rate / rate; 282 unsigned long div;
276 283
277 if (parent_rate % rate) 284 if (!rate || parent_rate % rate)
278 return -EINVAL; 285 return -EINVAL;
286
287 div = parent_rate / rate;
288
279 for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) { 289 for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) {
280 if (usb->divisors[i] == div) { 290 if (usb->divisors[i] == div) {
281 tmp = pmc_read(pmc, AT91_CKGR_PLLBR) & 291 tmp = pmc_read(pmc, AT91_CKGR_PLLBR) &
@@ -311,7 +321,7 @@ at91rm9200_clk_register_usb(struct at91_pmc *pmc, const char *name,
311 init.ops = &at91rm9200_usb_ops; 321 init.ops = &at91rm9200_usb_ops;
312 init.parent_names = &parent_name; 322 init.parent_names = &parent_name;
313 init.num_parents = 1; 323 init.num_parents = 1;
314 init.flags = 0; 324 init.flags = CLK_SET_RATE_PARENT;
315 325
316 usb->hw.init = &init; 326 usb->hw.init = &init;
317 usb->pmc = pmc; 327 usb->pmc = pmc;
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 524196bb35a5..386999b4f8eb 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -337,6 +337,12 @@ static const struct of_device_id pmc_clk_ids[] __initconst = {
337 .data = of_at91sam9x5_clk_smd_setup, 337 .data = of_at91sam9x5_clk_smd_setup,
338 }, 338 },
339#endif 339#endif
340#if defined(CONFIG_HAVE_AT91_H32MX)
341 {
342 .compatible = "atmel,sama5d4-clk-h32mx",
343 .data = of_sama5d4_clk_h32mx_setup,
344 },
345#endif
340 { /*sentinel*/ } 346 { /*sentinel*/ }
341}; 347};
342 348
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
index 6c7625976113..52d2041fa3f6 100644
--- a/drivers/clk/at91/pmc.h
+++ b/drivers/clk/at91/pmc.h
@@ -120,4 +120,9 @@ extern void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
120 struct at91_pmc *pmc); 120 struct at91_pmc *pmc);
121#endif 121#endif
122 122
123#if defined(CONFIG_HAVE_AT91_SMD)
124extern void __init of_sama5d4_clk_h32mx_setup(struct device_node *np,
125 struct at91_pmc *pmc);
126#endif
127
123#endif /* __PMC_H_ */ 128#endif /* __PMC_H_ */
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index 1127ee46b802..e619285c6def 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -544,7 +544,6 @@ static int axi_clkgen_remove(struct platform_device *pdev)
544static struct platform_driver axi_clkgen_driver = { 544static struct platform_driver axi_clkgen_driver = {
545 .driver = { 545 .driver = {
546 .name = "adi-axi-clkgen", 546 .name = "adi-axi-clkgen",
547 .owner = THIS_MODULE,
548 .of_match_table = axi_clkgen_ids, 547 .of_match_table = axi_clkgen_ids,
549 }, 548 },
550 .probe = axi_clkgen_probe, 549 .probe = axi_clkgen_probe,
diff --git a/drivers/clk/clk-efm32gg.c b/drivers/clk/clk-efm32gg.c
index bac2ddf49d02..73a8d0ff530c 100644
--- a/drivers/clk/clk-efm32gg.c
+++ b/drivers/clk/clk-efm32gg.c
@@ -22,7 +22,7 @@ static struct clk_onecell_data clk_data = {
22 .clk_num = ARRAY_SIZE(clk), 22 .clk_num = ARRAY_SIZE(clk),
23}; 23};
24 24
25static int __init efm32gg_cmu_init(struct device_node *np) 25static void __init efm32gg_cmu_init(struct device_node *np)
26{ 26{
27 int i; 27 int i;
28 void __iomem *base; 28 void __iomem *base;
@@ -33,7 +33,7 @@ static int __init efm32gg_cmu_init(struct device_node *np)
33 base = of_iomap(np, 0); 33 base = of_iomap(np, 0);
34 if (!base) { 34 if (!base) {
35 pr_warn("Failed to map address range for efm32gg,cmu node\n"); 35 pr_warn("Failed to map address range for efm32gg,cmu node\n");
36 return -EADDRNOTAVAIL; 36 return;
37 } 37 }
38 38
39 clk[clk_HFXO] = clk_register_fixed_rate(NULL, "HFXO", NULL, 39 clk[clk_HFXO] = clk_register_fixed_rate(NULL, "HFXO", NULL,
@@ -76,6 +76,6 @@ static int __init efm32gg_cmu_init(struct device_node *np)
76 clk[clk_HFPERCLKDAC0] = clk_register_gate(NULL, "HFPERCLK.DAC0", 76 clk[clk_HFPERCLKDAC0] = clk_register_gate(NULL, "HFPERCLK.DAC0",
77 "HFXO", 0, base + CMU_HFPERCLKEN0, 17, 0, NULL); 77 "HFXO", 0, base + CMU_HFPERCLKEN0, 17, 0, NULL);
78 78
79 return of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); 79 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
80} 80}
81CLK_OF_DECLARE(efm32ggcmu, "efm32gg,cmu", efm32gg_cmu_init); 81CLK_OF_DECLARE(efm32ggcmu, "efm32gg,cmu", efm32gg_cmu_init);
diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c
index ede685ca0d20..82a59d0086cc 100644
--- a/drivers/clk/clk-fractional-divider.c
+++ b/drivers/clk/clk-fractional-divider.c
@@ -36,7 +36,7 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
36 m = (val & fd->mmask) >> fd->mshift; 36 m = (val & fd->mmask) >> fd->mshift;
37 n = (val & fd->nmask) >> fd->nshift; 37 n = (val & fd->nmask) >> fd->nshift;
38 38
39 ret = parent_rate * m; 39 ret = (u64)parent_rate * m;
40 do_div(ret, n); 40 do_div(ret, n);
41 41
42 return ret; 42 return ret;
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 4a58c55255bd..51fd87fb7ba6 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -45,7 +45,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
45{ 45{
46 struct clk_gate *gate = to_clk_gate(hw); 46 struct clk_gate *gate = to_clk_gate(hw);
47 int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; 47 int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
48 unsigned long flags = 0; 48 unsigned long uninitialized_var(flags);
49 u32 reg; 49 u32 reg;
50 50
51 set ^= enable; 51 set ^= enable;
diff --git a/drivers/clk/clk-gpio-gate.c b/drivers/clk/clk-gpio-gate.c
new file mode 100644
index 000000000000..08e43224fd52
--- /dev/null
+++ b/drivers/clk/clk-gpio-gate.c
@@ -0,0 +1,205 @@
1/*
2 * Copyright (C) 2013 - 2014 Texas Instruments Incorporated - http://www.ti.com
3 * Author: Jyri Sarha <jsarha@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Gpio gated clock implementation
10 */
11
12#include <linux/clk-provider.h>
13#include <linux/module.h>
14#include <linux/slab.h>
15#include <linux/gpio.h>
16#include <linux/gpio/consumer.h>
17#include <linux/of_gpio.h>
18#include <linux/err.h>
19#include <linux/device.h>
20
21/**
22 * DOC: basic gpio gated clock which can be enabled and disabled
23 * with gpio output
24 * Traits of this clock:
25 * prepare - clk_(un)prepare only ensures parent is (un)prepared
26 * enable - clk_enable and clk_disable are functional & control gpio
27 * rate - inherits rate from parent. No clk_set_rate support
28 * parent - fixed parent. No clk_set_parent support
29 */
30
31#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw)
32
33static int clk_gpio_gate_enable(struct clk_hw *hw)
34{
35 struct clk_gpio *clk = to_clk_gpio(hw);
36
37 gpiod_set_value(clk->gpiod, 1);
38
39 return 0;
40}
41
42static void clk_gpio_gate_disable(struct clk_hw *hw)
43{
44 struct clk_gpio *clk = to_clk_gpio(hw);
45
46 gpiod_set_value(clk->gpiod, 0);
47}
48
49static int clk_gpio_gate_is_enabled(struct clk_hw *hw)
50{
51 struct clk_gpio *clk = to_clk_gpio(hw);
52
53 return gpiod_get_value(clk->gpiod);
54}
55
56const struct clk_ops clk_gpio_gate_ops = {
57 .enable = clk_gpio_gate_enable,
58 .disable = clk_gpio_gate_disable,
59 .is_enabled = clk_gpio_gate_is_enabled,
60};
61EXPORT_SYMBOL_GPL(clk_gpio_gate_ops);
62
63/**
64 * clk_register_gpio - register a gpip clock with the clock framework
65 * @dev: device that is registering this clock
66 * @name: name of this clock
67 * @parent_name: name of this clock's parent
68 * @gpiod: gpio descriptor to gate this clock
69 */
70struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
71 const char *parent_name, struct gpio_desc *gpiod,
72 unsigned long flags)
73{
74 struct clk_gpio *clk_gpio = NULL;
75 struct clk *clk = ERR_PTR(-EINVAL);
76 struct clk_init_data init = { NULL };
77 unsigned long gpio_flags;
78 int err;
79
80 if (gpiod_is_active_low(gpiod))
81 gpio_flags = GPIOF_OUT_INIT_HIGH;
82 else
83 gpio_flags = GPIOF_OUT_INIT_LOW;
84
85 if (dev)
86 err = devm_gpio_request_one(dev, desc_to_gpio(gpiod),
87 gpio_flags, name);
88 else
89 err = gpio_request_one(desc_to_gpio(gpiod), gpio_flags, name);
90
91 if (err) {
92 pr_err("%s: %s: Error requesting clock control gpio %u\n",
93 __func__, name, desc_to_gpio(gpiod));
94 return ERR_PTR(err);
95 }
96
97 if (dev)
98 clk_gpio = devm_kzalloc(dev, sizeof(struct clk_gpio),
99 GFP_KERNEL);
100 else
101 clk_gpio = kzalloc(sizeof(struct clk_gpio), GFP_KERNEL);
102
103 if (!clk_gpio) {
104 clk = ERR_PTR(-ENOMEM);
105 goto clk_register_gpio_gate_err;
106 }
107
108 init.name = name;
109 init.ops = &clk_gpio_gate_ops;
110 init.flags = flags | CLK_IS_BASIC;
111 init.parent_names = (parent_name ? &parent_name : NULL);
112 init.num_parents = (parent_name ? 1 : 0);
113
114 clk_gpio->gpiod = gpiod;
115 clk_gpio->hw.init = &init;
116
117 clk = clk_register(dev, &clk_gpio->hw);
118
119 if (!IS_ERR(clk))
120 return clk;
121
122 if (!dev)
123 kfree(clk_gpio);
124
125clk_register_gpio_gate_err:
126 gpiod_put(gpiod);
127
128 return clk;
129}
130EXPORT_SYMBOL_GPL(clk_register_gpio_gate);
131
132#ifdef CONFIG_OF
133/**
134 * The clk_register_gpio_gate has to be delayed, because the EPROBE_DEFER
135 * can not be handled properly at of_clk_init() call time.
136 */
137
138struct clk_gpio_gate_delayed_register_data {
139 struct device_node *node;
140 struct mutex lock;
141 struct clk *clk;
142};
143
144static struct clk *of_clk_gpio_gate_delayed_register_get(
145 struct of_phandle_args *clkspec,
146 void *_data)
147{
148 struct clk_gpio_gate_delayed_register_data *data = _data;
149 struct clk *clk;
150 const char *clk_name = data->node->name;
151 const char *parent_name;
152 struct gpio_desc *gpiod;
153 int gpio;
154
155 mutex_lock(&data->lock);
156
157 if (data->clk) {
158 mutex_unlock(&data->lock);
159 return data->clk;
160 }
161
162 gpio = of_get_named_gpio_flags(data->node, "enable-gpios", 0, NULL);
163 if (gpio < 0) {
164 mutex_unlock(&data->lock);
165 if (gpio != -EPROBE_DEFER)
166 pr_err("%s: %s: Can't get 'enable-gpios' DT property\n",
167 __func__, clk_name);
168 return ERR_PTR(gpio);
169 }
170 gpiod = gpio_to_desc(gpio);
171
172 parent_name = of_clk_get_parent_name(data->node, 0);
173
174 clk = clk_register_gpio_gate(NULL, clk_name, parent_name, gpiod, 0);
175 if (IS_ERR(clk)) {
176 mutex_unlock(&data->lock);
177 return clk;
178 }
179
180 data->clk = clk;
181 mutex_unlock(&data->lock);
182
183 return clk;
184}
185
186/**
187 * of_gpio_gate_clk_setup() - Setup function for gpio controlled clock
188 */
189void __init of_gpio_gate_clk_setup(struct device_node *node)
190{
191 struct clk_gpio_gate_delayed_register_data *data;
192
193 data = kzalloc(sizeof(struct clk_gpio_gate_delayed_register_data),
194 GFP_KERNEL);
195 if (!data)
196 return;
197
198 data->node = node;
199 mutex_init(&data->lock);
200
201 of_clk_add_provider(node, of_clk_gpio_gate_delayed_register_get, data);
202}
203EXPORT_SYMBOL_GPL(of_gpio_gate_clk_setup);
204CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup);
205#endif
diff --git a/drivers/clk/clk-max-gen.c b/drivers/clk/clk-max-gen.c
new file mode 100644
index 000000000000..6505049d50f1
--- /dev/null
+++ b/drivers/clk/clk-max-gen.c
@@ -0,0 +1,192 @@
1/*
2 * clk-max-gen.c - Generic clock driver for Maxim PMICs clocks
3 *
4 * Copyright (C) 2014 Google, Inc
5 *
6 * Copyright (C) 2012 Samsung Electornics
7 * Jonghwa Lee <jonghwa3.lee@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * This driver is based on clk-max77686.c
20 *
21 */
22
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/err.h>
26#include <linux/regmap.h>
27#include <linux/platform_device.h>
28#include <linux/clk-provider.h>
29#include <linux/mutex.h>
30#include <linux/clkdev.h>
31#include <linux/of.h>
32#include <linux/export.h>
33
34struct max_gen_clk {
35 struct regmap *regmap;
36 u32 mask;
37 u32 reg;
38 struct clk_hw hw;
39};
40
41static struct max_gen_clk *to_max_gen_clk(struct clk_hw *hw)
42{
43 return container_of(hw, struct max_gen_clk, hw);
44}
45
46static int max_gen_clk_prepare(struct clk_hw *hw)
47{
48 struct max_gen_clk *max_gen = to_max_gen_clk(hw);
49
50 return regmap_update_bits(max_gen->regmap, max_gen->reg,
51 max_gen->mask, max_gen->mask);
52}
53
54static void max_gen_clk_unprepare(struct clk_hw *hw)
55{
56 struct max_gen_clk *max_gen = to_max_gen_clk(hw);
57
58 regmap_update_bits(max_gen->regmap, max_gen->reg,
59 max_gen->mask, ~max_gen->mask);
60}
61
62static int max_gen_clk_is_prepared(struct clk_hw *hw)
63{
64 struct max_gen_clk *max_gen = to_max_gen_clk(hw);
65 int ret;
66 u32 val;
67
68 ret = regmap_read(max_gen->regmap, max_gen->reg, &val);
69
70 if (ret < 0)
71 return -EINVAL;
72
73 return val & max_gen->mask;
74}
75
76static unsigned long max_gen_recalc_rate(struct clk_hw *hw,
77 unsigned long parent_rate)
78{
79 return 32768;
80}
81
82struct clk_ops max_gen_clk_ops = {
83 .prepare = max_gen_clk_prepare,
84 .unprepare = max_gen_clk_unprepare,
85 .is_prepared = max_gen_clk_is_prepared,
86 .recalc_rate = max_gen_recalc_rate,
87};
88EXPORT_SYMBOL_GPL(max_gen_clk_ops);
89
90static struct clk *max_gen_clk_register(struct device *dev,
91 struct max_gen_clk *max_gen)
92{
93 struct clk *clk;
94 struct clk_hw *hw = &max_gen->hw;
95 int ret;
96
97 clk = devm_clk_register(dev, hw);
98 if (IS_ERR(clk))
99 return clk;
100
101 ret = clk_register_clkdev(clk, hw->init->name, NULL);
102
103 if (ret)
104 return ERR_PTR(ret);
105
106 return clk;
107}
108
109int max_gen_clk_probe(struct platform_device *pdev, struct regmap *regmap,
110 u32 reg, struct clk_init_data *clks_init, int num_init)
111{
112 int i, ret;
113 struct max_gen_clk *max_gen_clks;
114 struct clk **clocks;
115 struct device *dev = pdev->dev.parent;
116 const char *clk_name;
117 struct clk_init_data *init;
118
119 clocks = devm_kzalloc(dev, sizeof(struct clk *) * num_init, GFP_KERNEL);
120 if (!clocks)
121 return -ENOMEM;
122
123 max_gen_clks = devm_kzalloc(dev, sizeof(struct max_gen_clk)
124 * num_init, GFP_KERNEL);
125 if (!max_gen_clks)
126 return -ENOMEM;
127
128 for (i = 0; i < num_init; i++) {
129 max_gen_clks[i].regmap = regmap;
130 max_gen_clks[i].mask = 1 << i;
131 max_gen_clks[i].reg = reg;
132
133 init = devm_kzalloc(dev, sizeof(*init), GFP_KERNEL);
134 if (!init)
135 return -ENOMEM;
136
137 if (dev->of_node &&
138 !of_property_read_string_index(dev->of_node,
139 "clock-output-names",
140 i, &clk_name))
141 init->name = clk_name;
142 else
143 init->name = clks_init[i].name;
144
145 init->ops = clks_init[i].ops;
146 init->flags = clks_init[i].flags;
147
148 max_gen_clks[i].hw.init = init;
149
150 clocks[i] = max_gen_clk_register(dev, &max_gen_clks[i]);
151 if (IS_ERR(clocks[i])) {
152 ret = PTR_ERR(clocks[i]);
153 dev_err(dev, "failed to register %s\n",
154 max_gen_clks[i].hw.init->name);
155 return ret;
156 }
157 }
158
159 platform_set_drvdata(pdev, clocks);
160
161 if (dev->of_node) {
162 struct clk_onecell_data *of_data;
163
164 of_data = devm_kzalloc(dev, sizeof(*of_data), GFP_KERNEL);
165 if (!of_data)
166 return -ENOMEM;
167
168 of_data->clks = clocks;
169 of_data->clk_num = num_init;
170 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
171 of_data);
172
173 if (ret) {
174 dev_err(dev, "failed to register OF clock provider\n");
175 return ret;
176 }
177 }
178
179 return 0;
180}
181EXPORT_SYMBOL_GPL(max_gen_clk_probe);
182
183int max_gen_clk_remove(struct platform_device *pdev, int num_init)
184{
185 struct device *dev = pdev->dev.parent;
186
187 if (dev->of_node)
188 of_clk_del_provider(dev->of_node);
189
190 return 0;
191}
192EXPORT_SYMBOL_GPL(max_gen_clk_remove);
diff --git a/drivers/clk/clk-max-gen.h b/drivers/clk/clk-max-gen.h
new file mode 100644
index 000000000000..997e86fc3f4d
--- /dev/null
+++ b/drivers/clk/clk-max-gen.h
@@ -0,0 +1,32 @@
1/*
2 * clk-max-gen.h - Generic clock driver for Maxim PMICs clocks
3 *
4 * Copyright (C) 2014 Google, Inc
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * 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
18#ifndef __CLK_MAX_GEN_H__
19#define __CLK_MAX_GEN_H__
20
21#include <linux/types.h>
22#include <linux/device.h>
23#include <linux/clkdev.h>
24#include <linux/regmap.h>
25#include <linux/platform_device.h>
26
27int max_gen_clk_probe(struct platform_device *pdev, struct regmap *regmap,
28 u32 reg, struct clk_init_data *clks_init, int num_init);
29int max_gen_clk_remove(struct platform_device *pdev, int num_init);
30extern struct clk_ops max_gen_clk_ops;
31
32#endif /* __CLK_MAX_GEN_H__ */
diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c
index 3d7e8dd8fd58..86cdb3a28629 100644
--- a/drivers/clk/clk-max77686.c
+++ b/drivers/clk/clk-max77686.c
@@ -30,193 +30,38 @@
30#include <linux/mutex.h> 30#include <linux/mutex.h>
31#include <linux/clkdev.h> 31#include <linux/clkdev.h>
32 32
33enum { 33#include <dt-bindings/clock/maxim,max77686.h>
34 MAX77686_CLK_AP = 0, 34#include "clk-max-gen.h"
35 MAX77686_CLK_CP,
36 MAX77686_CLK_PMIC,
37 MAX77686_CLKS_NUM,
38};
39
40struct max77686_clk {
41 struct max77686_dev *iodev;
42 u32 mask;
43 struct clk_hw hw;
44 struct clk_lookup *lookup;
45};
46
47static struct max77686_clk *to_max77686_clk(struct clk_hw *hw)
48{
49 return container_of(hw, struct max77686_clk, hw);
50}
51
52static int max77686_clk_prepare(struct clk_hw *hw)
53{
54 struct max77686_clk *max77686 = to_max77686_clk(hw);
55
56 return regmap_update_bits(max77686->iodev->regmap,
57 MAX77686_REG_32KHZ, max77686->mask,
58 max77686->mask);
59}
60
61static void max77686_clk_unprepare(struct clk_hw *hw)
62{
63 struct max77686_clk *max77686 = to_max77686_clk(hw);
64
65 regmap_update_bits(max77686->iodev->regmap,
66 MAX77686_REG_32KHZ, max77686->mask, ~max77686->mask);
67}
68
69static int max77686_clk_is_prepared(struct clk_hw *hw)
70{
71 struct max77686_clk *max77686 = to_max77686_clk(hw);
72 int ret;
73 u32 val;
74
75 ret = regmap_read(max77686->iodev->regmap,
76 MAX77686_REG_32KHZ, &val);
77
78 if (ret < 0)
79 return -EINVAL;
80
81 return val & max77686->mask;
82}
83
84static unsigned long max77686_recalc_rate(struct clk_hw *hw,
85 unsigned long parent_rate)
86{
87 return 32768;
88}
89
90static struct clk_ops max77686_clk_ops = {
91 .prepare = max77686_clk_prepare,
92 .unprepare = max77686_clk_unprepare,
93 .is_prepared = max77686_clk_is_prepared,
94 .recalc_rate = max77686_recalc_rate,
95};
96 35
97static struct clk_init_data max77686_clks_init[MAX77686_CLKS_NUM] = { 36static struct clk_init_data max77686_clks_init[MAX77686_CLKS_NUM] = {
98 [MAX77686_CLK_AP] = { 37 [MAX77686_CLK_AP] = {
99 .name = "32khz_ap", 38 .name = "32khz_ap",
100 .ops = &max77686_clk_ops, 39 .ops = &max_gen_clk_ops,
101 .flags = CLK_IS_ROOT, 40 .flags = CLK_IS_ROOT,
102 }, 41 },
103 [MAX77686_CLK_CP] = { 42 [MAX77686_CLK_CP] = {
104 .name = "32khz_cp", 43 .name = "32khz_cp",
105 .ops = &max77686_clk_ops, 44 .ops = &max_gen_clk_ops,
106 .flags = CLK_IS_ROOT, 45 .flags = CLK_IS_ROOT,
107 }, 46 },
108 [MAX77686_CLK_PMIC] = { 47 [MAX77686_CLK_PMIC] = {
109 .name = "32khz_pmic", 48 .name = "32khz_pmic",
110 .ops = &max77686_clk_ops, 49 .ops = &max_gen_clk_ops,
111 .flags = CLK_IS_ROOT, 50 .flags = CLK_IS_ROOT,
112 }, 51 },
113}; 52};
114 53
115static struct clk *max77686_clk_register(struct device *dev,
116 struct max77686_clk *max77686)
117{
118 struct clk *clk;
119 struct clk_hw *hw = &max77686->hw;
120
121 clk = clk_register(dev, hw);
122 if (IS_ERR(clk))
123 return clk;
124
125 max77686->lookup = kzalloc(sizeof(struct clk_lookup), GFP_KERNEL);
126 if (!max77686->lookup)
127 return ERR_PTR(-ENOMEM);
128
129 max77686->lookup->con_id = hw->init->name;
130 max77686->lookup->clk = clk;
131
132 clkdev_add(max77686->lookup);
133
134 return clk;
135}
136
137static int max77686_clk_probe(struct platform_device *pdev) 54static int max77686_clk_probe(struct platform_device *pdev)
138{ 55{
139 struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); 56 struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
140 struct max77686_clk *max77686_clks[MAX77686_CLKS_NUM];
141 struct clk **clocks;
142 int i, ret;
143
144 clocks = devm_kzalloc(&pdev->dev, sizeof(struct clk *)
145 * MAX77686_CLKS_NUM, GFP_KERNEL);
146 if (!clocks)
147 return -ENOMEM;
148
149 for (i = 0; i < MAX77686_CLKS_NUM; i++) {
150 max77686_clks[i] = devm_kzalloc(&pdev->dev,
151 sizeof(struct max77686_clk), GFP_KERNEL);
152 if (!max77686_clks[i])
153 return -ENOMEM;
154 }
155
156 for (i = 0; i < MAX77686_CLKS_NUM; i++) {
157 max77686_clks[i]->iodev = iodev;
158 max77686_clks[i]->mask = 1 << i;
159 max77686_clks[i]->hw.init = &max77686_clks_init[i];
160
161 clocks[i] = max77686_clk_register(&pdev->dev, max77686_clks[i]);
162 if (IS_ERR(clocks[i])) {
163 ret = PTR_ERR(clocks[i]);
164 dev_err(&pdev->dev, "failed to register %s\n",
165 max77686_clks[i]->hw.init->name);
166 goto err_clocks;
167 }
168 }
169
170 platform_set_drvdata(pdev, clocks);
171
172 if (iodev->dev->of_node) {
173 struct clk_onecell_data *of_data;
174 57
175 of_data = devm_kzalloc(&pdev->dev, 58 return max_gen_clk_probe(pdev, iodev->regmap, MAX77686_REG_32KHZ,
176 sizeof(*of_data), GFP_KERNEL); 59 max77686_clks_init, MAX77686_CLKS_NUM);
177 if (!of_data) {
178 ret = -ENOMEM;
179 goto err_clocks;
180 }
181
182 of_data->clks = clocks;
183 of_data->clk_num = MAX77686_CLKS_NUM;
184 ret = of_clk_add_provider(iodev->dev->of_node,
185 of_clk_src_onecell_get, of_data);
186 if (ret) {
187 dev_err(&pdev->dev, "failed to register OF clock provider\n");
188 goto err_clocks;
189 }
190 }
191
192 return 0;
193
194err_clocks:
195 for (--i; i >= 0; --i) {
196 clkdev_drop(max77686_clks[i]->lookup);
197 clk_unregister(max77686_clks[i]->hw.clk);
198 }
199
200 return ret;
201} 60}
202 61
203static int max77686_clk_remove(struct platform_device *pdev) 62static int max77686_clk_remove(struct platform_device *pdev)
204{ 63{
205 struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); 64 return max_gen_clk_remove(pdev, MAX77686_CLKS_NUM);
206 struct clk **clocks = platform_get_drvdata(pdev);
207 int i;
208
209 if (iodev->dev->of_node)
210 of_clk_del_provider(iodev->dev->of_node);
211
212 for (i = 0; i < MAX77686_CLKS_NUM; i++) {
213 struct clk_hw *hw = __clk_get_hw(clocks[i]);
214 struct max77686_clk *max77686 = to_max77686_clk(hw);
215
216 clkdev_drop(max77686->lookup);
217 clk_unregister(clocks[i]);
218 }
219 return 0;
220} 65}
221 66
222static const struct platform_device_id max77686_clk_id[] = { 67static const struct platform_device_id max77686_clk_id[] = {
@@ -228,24 +73,13 @@ MODULE_DEVICE_TABLE(platform, max77686_clk_id);
228static struct platform_driver max77686_clk_driver = { 73static struct platform_driver max77686_clk_driver = {
229 .driver = { 74 .driver = {
230 .name = "max77686-clk", 75 .name = "max77686-clk",
231 .owner = THIS_MODULE,
232 }, 76 },
233 .probe = max77686_clk_probe, 77 .probe = max77686_clk_probe,
234 .remove = max77686_clk_remove, 78 .remove = max77686_clk_remove,
235 .id_table = max77686_clk_id, 79 .id_table = max77686_clk_id,
236}; 80};
237 81
238static int __init max77686_clk_init(void) 82module_platform_driver(max77686_clk_driver);
239{
240 return platform_driver_register(&max77686_clk_driver);
241}
242subsys_initcall(max77686_clk_init);
243
244static void __init max77686_clk_cleanup(void)
245{
246 platform_driver_unregister(&max77686_clk_driver);
247}
248module_exit(max77686_clk_cleanup);
249 83
250MODULE_DESCRIPTION("MAXIM 77686 Clock Driver"); 84MODULE_DESCRIPTION("MAXIM 77686 Clock Driver");
251MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>"); 85MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>");
diff --git a/drivers/clk/clk-max77802.c b/drivers/clk/clk-max77802.c
new file mode 100644
index 000000000000..0729dc723a8f
--- /dev/null
+++ b/drivers/clk/clk-max77802.c
@@ -0,0 +1,97 @@
1/*
2 * clk-max77802.c - Clock driver for Maxim 77802
3 *
4 * Copyright (C) 2014 Google, Inc
5 *
6 * Copyright (C) 2012 Samsung Electornics
7 * Jonghwa Lee <jonghwa3.lee@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * This driver is based on clk-max77686.c
20 */
21
22#include <linux/kernel.h>
23#include <linux/slab.h>
24#include <linux/err.h>
25#include <linux/platform_device.h>
26#include <linux/mfd/max77686-private.h>
27#include <linux/clk-provider.h>
28#include <linux/mutex.h>
29#include <linux/clkdev.h>
30
31#include <dt-bindings/clock/maxim,max77802.h>
32#include "clk-max-gen.h"
33
34#define MAX77802_CLOCK_OPMODE_MASK 0x1
35#define MAX77802_CLOCK_LOW_JITTER_SHIFT 0x3
36
37static struct clk_init_data max77802_clks_init[MAX77802_CLKS_NUM] = {
38 [MAX77802_CLK_32K_AP] = {
39 .name = "32khz_ap",
40 .ops = &max_gen_clk_ops,
41 .flags = CLK_IS_ROOT,
42 },
43 [MAX77802_CLK_32K_CP] = {
44 .name = "32khz_cp",
45 .ops = &max_gen_clk_ops,
46 .flags = CLK_IS_ROOT,
47 },
48};
49
50static int max77802_clk_probe(struct platform_device *pdev)
51{
52 struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
53 int ret;
54
55 ret = max_gen_clk_probe(pdev, iodev->regmap, MAX77802_REG_32KHZ,
56 max77802_clks_init, MAX77802_CLKS_NUM);
57
58 if (ret) {
59 dev_err(&pdev->dev, "generic probe failed %d\n", ret);
60 return ret;
61 }
62
63 /* Enable low-jitter mode on the 32khz clocks. */
64 ret = regmap_update_bits(iodev->regmap, MAX77802_REG_32KHZ,
65 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT,
66 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT);
67 if (ret < 0)
68 dev_err(&pdev->dev, "failed to enable low-jitter mode\n");
69
70 return ret;
71}
72
73static int max77802_clk_remove(struct platform_device *pdev)
74{
75 return max_gen_clk_remove(pdev, MAX77802_CLKS_NUM);
76}
77
78static const struct platform_device_id max77802_clk_id[] = {
79 { "max77802-clk", 0},
80 { },
81};
82MODULE_DEVICE_TABLE(platform, max77802_clk_id);
83
84static struct platform_driver max77802_clk_driver = {
85 .driver = {
86 .name = "max77802-clk",
87 },
88 .probe = max77802_clk_probe,
89 .remove = max77802_clk_remove,
90 .id_table = max77802_clk_id,
91};
92
93module_platform_driver(max77802_clk_driver);
94
95MODULE_DESCRIPTION("MAXIM 77802 Clock Driver");
96MODULE_AUTHOR("Javier Martinez Canillas <javier.martinez@collabora.co.uk>");
97MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-palmas.c b/drivers/clk/clk-palmas.c
index 781630e1372b..8d459923a15f 100644
--- a/drivers/clk/clk-palmas.c
+++ b/drivers/clk/clk-palmas.c
@@ -292,7 +292,6 @@ static int palmas_clks_remove(struct platform_device *pdev)
292static struct platform_driver palmas_clks_driver = { 292static struct platform_driver palmas_clks_driver = {
293 .driver = { 293 .driver = {
294 .name = "palmas-clk", 294 .name = "palmas-clk",
295 .owner = THIS_MODULE,
296 .of_match_table = palmas_clks_of_match, 295 .of_match_table = palmas_clks_of_match,
297 }, 296 },
298 .probe = palmas_clks_probe, 297 .probe = palmas_clks_probe,
diff --git a/drivers/clk/clk-rk808.c b/drivers/clk/clk-rk808.c
new file mode 100644
index 000000000000..83902b9cd49e
--- /dev/null
+++ b/drivers/clk/clk-rk808.c
@@ -0,0 +1,170 @@
1/*
2 * Clkout driver for Rockchip RK808
3 *
4 * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
5 *
6 * Author:Chris Zhong <zyw@rock-chips.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 */
17
18#include <linux/clk.h>
19#include <linux/clk-provider.h>
20#include <linux/module.h>
21#include <linux/slab.h>
22#include <linux/platform_device.h>
23#include <linux/mfd/rk808.h>
24#include <linux/i2c.h>
25
26#define RK808_NR_OUTPUT 2
27
28struct rk808_clkout {
29 struct rk808 *rk808;
30 struct clk_onecell_data clk_data;
31 struct clk_hw clkout1_hw;
32 struct clk_hw clkout2_hw;
33};
34
35static unsigned long rk808_clkout_recalc_rate(struct clk_hw *hw,
36 unsigned long parent_rate)
37{
38 return 32768;
39}
40
41static int rk808_clkout2_enable(struct clk_hw *hw, bool enable)
42{
43 struct rk808_clkout *rk808_clkout = container_of(hw,
44 struct rk808_clkout,
45 clkout2_hw);
46 struct rk808 *rk808 = rk808_clkout->rk808;
47
48 return regmap_update_bits(rk808->regmap, RK808_CLK32OUT_REG,
49 CLK32KOUT2_EN, enable ? CLK32KOUT2_EN : 0);
50}
51
52static int rk808_clkout2_prepare(struct clk_hw *hw)
53{
54 return rk808_clkout2_enable(hw, true);
55}
56
57static void rk808_clkout2_unprepare(struct clk_hw *hw)
58{
59 rk808_clkout2_enable(hw, false);
60}
61
62static int rk808_clkout2_is_prepared(struct clk_hw *hw)
63{
64 struct rk808_clkout *rk808_clkout = container_of(hw,
65 struct rk808_clkout,
66 clkout2_hw);
67 struct rk808 *rk808 = rk808_clkout->rk808;
68 uint32_t val;
69
70 int ret = regmap_read(rk808->regmap, RK808_CLK32OUT_REG, &val);
71
72 if (ret < 0)
73 return ret;
74
75 return (val & CLK32KOUT2_EN) ? 1 : 0;
76}
77
78static const struct clk_ops rk808_clkout1_ops = {
79 .recalc_rate = rk808_clkout_recalc_rate,
80};
81
82static const struct clk_ops rk808_clkout2_ops = {
83 .prepare = rk808_clkout2_prepare,
84 .unprepare = rk808_clkout2_unprepare,
85 .is_prepared = rk808_clkout2_is_prepared,
86 .recalc_rate = rk808_clkout_recalc_rate,
87};
88
89static int rk808_clkout_probe(struct platform_device *pdev)
90{
91 struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
92 struct i2c_client *client = rk808->i2c;
93 struct device_node *node = client->dev.of_node;
94 struct clk_init_data init = {};
95 struct clk **clk_table;
96 struct rk808_clkout *rk808_clkout;
97
98 rk808_clkout = devm_kzalloc(&client->dev,
99 sizeof(*rk808_clkout), GFP_KERNEL);
100 if (!rk808_clkout)
101 return -ENOMEM;
102
103 rk808_clkout->rk808 = rk808;
104
105 clk_table = devm_kcalloc(&client->dev, RK808_NR_OUTPUT,
106 sizeof(struct clk *), GFP_KERNEL);
107 if (!clk_table)
108 return -ENOMEM;
109
110 init.flags = CLK_IS_ROOT;
111 init.parent_names = NULL;
112 init.num_parents = 0;
113 init.name = "rk808-clkout1";
114 init.ops = &rk808_clkout1_ops;
115 rk808_clkout->clkout1_hw.init = &init;
116
117 /* optional override of the clockname */
118 of_property_read_string_index(node, "clock-output-names",
119 0, &init.name);
120
121 clk_table[0] = devm_clk_register(&client->dev,
122 &rk808_clkout->clkout1_hw);
123 if (IS_ERR(clk_table[0]))
124 return PTR_ERR(clk_table[0]);
125
126 init.name = "rk808-clkout2";
127 init.ops = &rk808_clkout2_ops;
128 rk808_clkout->clkout2_hw.init = &init;
129
130 /* optional override of the clockname */
131 of_property_read_string_index(node, "clock-output-names",
132 1, &init.name);
133
134 clk_table[1] = devm_clk_register(&client->dev,
135 &rk808_clkout->clkout2_hw);
136 if (IS_ERR(clk_table[1]))
137 return PTR_ERR(clk_table[1]);
138
139 rk808_clkout->clk_data.clks = clk_table;
140 rk808_clkout->clk_data.clk_num = RK808_NR_OUTPUT;
141
142 return of_clk_add_provider(node, of_clk_src_onecell_get,
143 &rk808_clkout->clk_data);
144}
145
146static int rk808_clkout_remove(struct platform_device *pdev)
147{
148 struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
149 struct i2c_client *client = rk808->i2c;
150 struct device_node *node = client->dev.of_node;
151
152 of_clk_del_provider(node);
153
154 return 0;
155}
156
157static struct platform_driver rk808_clkout_driver = {
158 .probe = rk808_clkout_probe,
159 .remove = rk808_clkout_remove,
160 .driver = {
161 .name = "rk808-clkout",
162 },
163};
164
165module_platform_driver(rk808_clkout_driver);
166
167MODULE_DESCRIPTION("Clkout driver for the rk808 series PMICs");
168MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
169MODULE_LICENSE("GPL");
170MODULE_ALIAS("platform:rk808-clkout");
diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c
index 1ada79a28052..4a755135bcd3 100644
--- a/drivers/clk/clk-twl6040.c
+++ b/drivers/clk/clk-twl6040.c
@@ -112,7 +112,6 @@ static int twl6040_clk_remove(struct platform_device *pdev)
112static struct platform_driver twl6040_clk_driver = { 112static struct platform_driver twl6040_clk_driver = {
113 .driver = { 113 .driver = {
114 .name = "twl6040-clk", 114 .name = "twl6040-clk",
115 .owner = THIS_MODULE,
116 }, 115 },
117 .probe = twl6040_clk_probe, 116 .probe = twl6040_clk_probe,
118 .remove = twl6040_clk_remove, 117 .remove = twl6040_clk_remove,
diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
index b131041c8f48..ef67719f4e52 100644
--- a/drivers/clk/clk-wm831x.c
+++ b/drivers/clk/clk-wm831x.c
@@ -395,7 +395,6 @@ static struct platform_driver wm831x_clk_driver = {
395 .probe = wm831x_clk_probe, 395 .probe = wm831x_clk_probe,
396 .driver = { 396 .driver = {
397 .name = "wm831x-clk", 397 .name = "wm831x-clk",
398 .owner = THIS_MODULE,
399 }, 398 },
400}; 399};
401 400
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index b76fa69b44cb..4896ae9e23da 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -100,6 +100,8 @@ static void clk_enable_unlock(unsigned long flags)
100 100
101static struct dentry *rootdir; 101static struct dentry *rootdir;
102static int inited = 0; 102static int inited = 0;
103static DEFINE_MUTEX(clk_debug_lock);
104static HLIST_HEAD(clk_debug_list);
103 105
104static struct hlist_head *all_lists[] = { 106static struct hlist_head *all_lists[] = {
105 &clk_root_list, 107 &clk_root_list,
@@ -117,11 +119,11 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
117 if (!c) 119 if (!c)
118 return; 120 return;
119 121
120 seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu\n", 122 seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
121 level * 3 + 1, "", 123 level * 3 + 1, "",
122 30 - level * 3, c->name, 124 30 - level * 3, c->name,
123 c->enable_count, c->prepare_count, clk_get_rate(c), 125 c->enable_count, c->prepare_count, clk_get_rate(c),
124 clk_get_accuracy(c)); 126 clk_get_accuracy(c), clk_get_phase(c));
125} 127}
126 128
127static void clk_summary_show_subtree(struct seq_file *s, struct clk *c, 129static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
@@ -143,8 +145,8 @@ static int clk_summary_show(struct seq_file *s, void *data)
143 struct clk *c; 145 struct clk *c;
144 struct hlist_head **lists = (struct hlist_head **)s->private; 146 struct hlist_head **lists = (struct hlist_head **)s->private;
145 147
146 seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy\n"); 148 seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy phase\n");
147 seq_puts(s, "--------------------------------------------------------------------------------\n"); 149 seq_puts(s, "----------------------------------------------------------------------------------------\n");
148 150
149 clk_prepare_lock(); 151 clk_prepare_lock();
150 152
@@ -180,6 +182,7 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
180 seq_printf(s, "\"prepare_count\": %d,", c->prepare_count); 182 seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
181 seq_printf(s, "\"rate\": %lu", clk_get_rate(c)); 183 seq_printf(s, "\"rate\": %lu", clk_get_rate(c));
182 seq_printf(s, "\"accuracy\": %lu", clk_get_accuracy(c)); 184 seq_printf(s, "\"accuracy\": %lu", clk_get_accuracy(c));
185 seq_printf(s, "\"phase\": %d", clk_get_phase(c));
183} 186}
184 187
185static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level) 188static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
@@ -264,6 +267,11 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
264 if (!d) 267 if (!d)
265 goto err_out; 268 goto err_out;
266 269
270 d = debugfs_create_u32("clk_phase", S_IRUGO, clk->dentry,
271 (u32 *)&clk->phase);
272 if (!d)
273 goto err_out;
274
267 d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry, 275 d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
268 (u32 *)&clk->flags); 276 (u32 *)&clk->flags);
269 if (!d) 277 if (!d)
@@ -300,28 +308,6 @@ out:
300 return ret; 308 return ret;
301} 309}
302 310
303/* caller must hold prepare_lock */
304static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
305{
306 struct clk *child;
307 int ret = -EINVAL;;
308
309 if (!clk || !pdentry)
310 goto out;
311
312 ret = clk_debug_create_one(clk, pdentry);
313
314 if (ret)
315 goto out;
316
317 hlist_for_each_entry(child, &clk->children, child_node)
318 clk_debug_create_subtree(child, pdentry);
319
320 ret = 0;
321out:
322 return ret;
323}
324
325/** 311/**
326 * clk_debug_register - add a clk node to the debugfs clk tree 312 * clk_debug_register - add a clk node to the debugfs clk tree
327 * @clk: the clk being added to the debugfs clk tree 313 * @clk: the clk being added to the debugfs clk tree
@@ -329,20 +315,21 @@ out:
329 * Dynamically adds a clk to the debugfs clk tree if debugfs has been 315 * Dynamically adds a clk to the debugfs clk tree if debugfs has been
330 * initialized. Otherwise it bails out early since the debugfs clk tree 316 * initialized. Otherwise it bails out early since the debugfs clk tree
331 * will be created lazily by clk_debug_init as part of a late_initcall. 317 * will be created lazily by clk_debug_init as part of a late_initcall.
332 *
333 * Caller must hold prepare_lock. Only clk_init calls this function (so
334 * far) so this is taken care.
335 */ 318 */
336static int clk_debug_register(struct clk *clk) 319static int clk_debug_register(struct clk *clk)
337{ 320{
338 int ret = 0; 321 int ret = 0;
339 322
323 mutex_lock(&clk_debug_lock);
324 hlist_add_head(&clk->debug_node, &clk_debug_list);
325
340 if (!inited) 326 if (!inited)
341 goto out; 327 goto unlock;
342 328
343 ret = clk_debug_create_subtree(clk, rootdir); 329 ret = clk_debug_create_one(clk, rootdir);
330unlock:
331 mutex_unlock(&clk_debug_lock);
344 332
345out:
346 return ret; 333 return ret;
347} 334}
348 335
@@ -353,12 +340,18 @@ out:
353 * Dynamically removes a clk and all it's children clk nodes from the 340 * Dynamically removes a clk and all it's children clk nodes from the
354 * debugfs clk tree if clk->dentry points to debugfs created by 341 * debugfs clk tree if clk->dentry points to debugfs created by
355 * clk_debug_register in __clk_init. 342 * clk_debug_register in __clk_init.
356 *
357 * Caller must hold prepare_lock.
358 */ 343 */
359static void clk_debug_unregister(struct clk *clk) 344static void clk_debug_unregister(struct clk *clk)
360{ 345{
346 mutex_lock(&clk_debug_lock);
347 if (!clk->dentry)
348 goto out;
349
350 hlist_del_init(&clk->debug_node);
361 debugfs_remove_recursive(clk->dentry); 351 debugfs_remove_recursive(clk->dentry);
352 clk->dentry = NULL;
353out:
354 mutex_unlock(&clk_debug_lock);
362} 355}
363 356
364struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode, 357struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode,
@@ -415,17 +408,12 @@ static int __init clk_debug_init(void)
415 if (!d) 408 if (!d)
416 return -ENOMEM; 409 return -ENOMEM;
417 410
418 clk_prepare_lock(); 411 mutex_lock(&clk_debug_lock);
419 412 hlist_for_each_entry(clk, &clk_debug_list, debug_node)
420 hlist_for_each_entry(clk, &clk_root_list, child_node) 413 clk_debug_create_one(clk, rootdir);
421 clk_debug_create_subtree(clk, rootdir);
422
423 hlist_for_each_entry(clk, &clk_orphan_list, child_node)
424 clk_debug_create_subtree(clk, rootdir);
425 414
426 inited = 1; 415 inited = 1;
427 416 mutex_unlock(&clk_debug_lock);
428 clk_prepare_unlock();
429 417
430 return 0; 418 return 0;
431} 419}
@@ -1467,6 +1455,7 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even
1467static void clk_change_rate(struct clk *clk) 1455static void clk_change_rate(struct clk *clk)
1468{ 1456{
1469 struct clk *child; 1457 struct clk *child;
1458 struct hlist_node *tmp;
1470 unsigned long old_rate; 1459 unsigned long old_rate;
1471 unsigned long best_parent_rate = 0; 1460 unsigned long best_parent_rate = 0;
1472 bool skip_set_rate = false; 1461 bool skip_set_rate = false;
@@ -1502,7 +1491,11 @@ static void clk_change_rate(struct clk *clk)
1502 if (clk->notifier_count && old_rate != clk->rate) 1491 if (clk->notifier_count && old_rate != clk->rate)
1503 __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); 1492 __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
1504 1493
1505 hlist_for_each_entry(child, &clk->children, child_node) { 1494 /*
1495 * Use safe iteration, as change_rate can actually swap parents
1496 * for certain clock types.
1497 */
1498 hlist_for_each_entry_safe(child, tmp, &clk->children, child_node) {
1506 /* Skip children who will be reparented to another clock */ 1499 /* Skip children who will be reparented to another clock */
1507 if (child->new_parent && child->new_parent != clk) 1500 if (child->new_parent && child->new_parent != clk)
1508 continue; 1501 continue;
@@ -1739,6 +1732,77 @@ out:
1739EXPORT_SYMBOL_GPL(clk_set_parent); 1732EXPORT_SYMBOL_GPL(clk_set_parent);
1740 1733
1741/** 1734/**
1735 * clk_set_phase - adjust the phase shift of a clock signal
1736 * @clk: clock signal source
1737 * @degrees: number of degrees the signal is shifted
1738 *
1739 * Shifts the phase of a clock signal by the specified
1740 * degrees. Returns 0 on success, -EERROR otherwise.
1741 *
1742 * This function makes no distinction about the input or reference
1743 * signal that we adjust the clock signal phase against. For example
1744 * phase locked-loop clock signal generators we may shift phase with
1745 * respect to feedback clock signal input, but for other cases the
1746 * clock phase may be shifted with respect to some other, unspecified
1747 * signal.
1748 *
1749 * Additionally the concept of phase shift does not propagate through
1750 * the clock tree hierarchy, which sets it apart from clock rates and
1751 * clock accuracy. A parent clock phase attribute does not have an
1752 * impact on the phase attribute of a child clock.
1753 */
1754int clk_set_phase(struct clk *clk, int degrees)
1755{
1756 int ret = 0;
1757
1758 if (!clk)
1759 goto out;
1760
1761 /* sanity check degrees */
1762 degrees %= 360;
1763 if (degrees < 0)
1764 degrees += 360;
1765
1766 clk_prepare_lock();
1767
1768 if (!clk->ops->set_phase)
1769 goto out_unlock;
1770
1771 ret = clk->ops->set_phase(clk->hw, degrees);
1772
1773 if (!ret)
1774 clk->phase = degrees;
1775
1776out_unlock:
1777 clk_prepare_unlock();
1778
1779out:
1780 return ret;
1781}
1782
1783/**
1784 * clk_get_phase - return the phase shift of a clock signal
1785 * @clk: clock signal source
1786 *
1787 * Returns the phase shift of a clock node in degrees, otherwise returns
1788 * -EERROR.
1789 */
1790int clk_get_phase(struct clk *clk)
1791{
1792 int ret = 0;
1793
1794 if (!clk)
1795 goto out;
1796
1797 clk_prepare_lock();
1798 ret = clk->phase;
1799 clk_prepare_unlock();
1800
1801out:
1802 return ret;
1803}
1804
1805/**
1742 * __clk_init - initialize the data structures in a struct clk 1806 * __clk_init - initialize the data structures in a struct clk
1743 * @dev: device initializing this clk, placeholder for now 1807 * @dev: device initializing this clk, placeholder for now
1744 * @clk: clk being initialized 1808 * @clk: clk being initialized
@@ -1857,6 +1921,16 @@ int __clk_init(struct device *dev, struct clk *clk)
1857 clk->accuracy = 0; 1921 clk->accuracy = 0;
1858 1922
1859 /* 1923 /*
1924 * Set clk's phase.
1925 * Since a phase is by definition relative to its parent, just
1926 * query the current clock phase, or just assume it's in phase.
1927 */
1928 if (clk->ops->get_phase)
1929 clk->phase = clk->ops->get_phase(clk->hw);
1930 else
1931 clk->phase = 0;
1932
1933 /*
1860 * Set clk's rate. The preferred method is to use .recalc_rate. For 1934 * Set clk's rate. The preferred method is to use .recalc_rate. For
1861 * simple clocks and lazy developers the default fallback is to use the 1935 * simple clocks and lazy developers the default fallback is to use the
1862 * parent's rate. If a clock doesn't have a parent (or is orphaned) 1936 * parent's rate. If a clock doesn't have a parent (or is orphaned)
@@ -2087,14 +2161,16 @@ void clk_unregister(struct clk *clk)
2087{ 2161{
2088 unsigned long flags; 2162 unsigned long flags;
2089 2163
2090 if (!clk || WARN_ON_ONCE(IS_ERR(clk))) 2164 if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
2091 return; 2165 return;
2166
2167 clk_debug_unregister(clk);
2092 2168
2093 clk_prepare_lock(); 2169 clk_prepare_lock();
2094 2170
2095 if (clk->ops == &clk_nodrv_ops) { 2171 if (clk->ops == &clk_nodrv_ops) {
2096 pr_err("%s: unregistered clock: %s\n", __func__, clk->name); 2172 pr_err("%s: unregistered clock: %s\n", __func__, clk->name);
2097 goto out; 2173 return;
2098 } 2174 }
2099 /* 2175 /*
2100 * Assign empty clock ops for consumers that might still hold 2176 * Assign empty clock ops for consumers that might still hold
@@ -2113,16 +2189,13 @@ void clk_unregister(struct clk *clk)
2113 clk_set_parent(child, NULL); 2189 clk_set_parent(child, NULL);
2114 } 2190 }
2115 2191
2116 clk_debug_unregister(clk);
2117
2118 hlist_del_init(&clk->child_node); 2192 hlist_del_init(&clk->child_node);
2119 2193
2120 if (clk->prepare_count) 2194 if (clk->prepare_count)
2121 pr_warn("%s: unregistering prepared clock: %s\n", 2195 pr_warn("%s: unregistering prepared clock: %s\n",
2122 __func__, clk->name); 2196 __func__, clk->name);
2123
2124 kref_put(&clk->ref, __clk_release); 2197 kref_put(&clk->ref, __clk_release);
2125out: 2198
2126 clk_prepare_unlock(); 2199 clk_prepare_unlock();
2127} 2200}
2128EXPORT_SYMBOL_GPL(clk_unregister); 2201EXPORT_SYMBOL_GPL(clk_unregister);
diff --git a/drivers/clk/hisilicon/clk-hix5hd2.c b/drivers/clk/hisilicon/clk-hix5hd2.c
index e5fcfb4e32ef..3f369c60fe56 100644
--- a/drivers/clk/hisilicon/clk-hix5hd2.c
+++ b/drivers/clk/hisilicon/clk-hix5hd2.c
@@ -9,6 +9,8 @@
9 9
10#include <linux/of_address.h> 10#include <linux/of_address.h>
11#include <dt-bindings/clock/hix5hd2-clock.h> 11#include <dt-bindings/clock/hix5hd2-clock.h>
12#include <linux/slab.h>
13#include <linux/delay.h>
12#include "clk.h" 14#include "clk.h"
13 15
14static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] __initdata = { 16static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] __initdata = {
@@ -48,9 +50,9 @@ static const char *sfc_mux_p[] __initconst = {
48 "24m", "150m", "200m", "100m", "75m", }; 50 "24m", "150m", "200m", "100m", "75m", };
49static u32 sfc_mux_table[] = {0, 4, 5, 6, 7}; 51static u32 sfc_mux_table[] = {0, 4, 5, 6, 7};
50 52
51static const char *sdio1_mux_p[] __initconst = { 53static const char *sdio_mux_p[] __initconst = {
52 "75m", "100m", "50m", "15m", }; 54 "75m", "100m", "50m", "15m", };
53static u32 sdio1_mux_table[] = {0, 1, 2, 3}; 55static u32 sdio_mux_table[] = {0, 1, 2, 3};
54 56
55static const char *fephy_mux_p[] __initconst = { "25m", "125m"}; 57static const char *fephy_mux_p[] __initconst = { "25m", "125m"};
56static u32 fephy_mux_table[] = {0, 1}; 58static u32 fephy_mux_table[] = {0, 1};
@@ -59,28 +61,243 @@ static u32 fephy_mux_table[] = {0, 1};
59static struct hisi_mux_clock hix5hd2_mux_clks[] __initdata = { 61static struct hisi_mux_clock hix5hd2_mux_clks[] __initdata = {
60 { HIX5HD2_SFC_MUX, "sfc_mux", sfc_mux_p, ARRAY_SIZE(sfc_mux_p), 62 { HIX5HD2_SFC_MUX, "sfc_mux", sfc_mux_p, ARRAY_SIZE(sfc_mux_p),
61 CLK_SET_RATE_PARENT, 0x5c, 8, 3, 0, sfc_mux_table, }, 63 CLK_SET_RATE_PARENT, 0x5c, 8, 3, 0, sfc_mux_table, },
62 { HIX5HD2_MMC_MUX, "mmc_mux", sdio1_mux_p, ARRAY_SIZE(sdio1_mux_p), 64 { HIX5HD2_MMC_MUX, "mmc_mux", sdio_mux_p, ARRAY_SIZE(sdio_mux_p),
63 CLK_SET_RATE_PARENT, 0xa0, 8, 2, 0, sdio1_mux_table, }, 65 CLK_SET_RATE_PARENT, 0xa0, 8, 2, 0, sdio_mux_table, },
66 { HIX5HD2_SD_MUX, "sd_mux", sdio_mux_p, ARRAY_SIZE(sdio_mux_p),
67 CLK_SET_RATE_PARENT, 0x9c, 8, 2, 0, sdio_mux_table, },
64 { HIX5HD2_FEPHY_MUX, "fephy_mux", 68 { HIX5HD2_FEPHY_MUX, "fephy_mux",
65 fephy_mux_p, ARRAY_SIZE(fephy_mux_p), 69 fephy_mux_p, ARRAY_SIZE(fephy_mux_p),
66 CLK_SET_RATE_PARENT, 0x120, 8, 2, 0, fephy_mux_table, }, 70 CLK_SET_RATE_PARENT, 0x120, 8, 2, 0, fephy_mux_table, },
67}; 71};
68 72
69static struct hisi_gate_clock hix5hd2_gate_clks[] __initdata = { 73static struct hisi_gate_clock hix5hd2_gate_clks[] __initdata = {
70 /*sfc*/ 74 /* sfc */
71 { HIX5HD2_SFC_CLK, "clk_sfc", "sfc_mux", 75 { HIX5HD2_SFC_CLK, "clk_sfc", "sfc_mux",
72 CLK_SET_RATE_PARENT, 0x5c, 0, 0, }, 76 CLK_SET_RATE_PARENT, 0x5c, 0, 0, },
73 { HIX5HD2_SFC_RST, "rst_sfc", "clk_sfc", 77 { HIX5HD2_SFC_RST, "rst_sfc", "clk_sfc",
74 CLK_SET_RATE_PARENT, 0x5c, 4, CLK_GATE_SET_TO_DISABLE, }, 78 CLK_SET_RATE_PARENT, 0x5c, 4, CLK_GATE_SET_TO_DISABLE, },
75 /*sdio1*/ 79 /* sdio0 */
80 { HIX5HD2_SD_BIU_CLK, "clk_sd_biu", "200m",
81 CLK_SET_RATE_PARENT, 0x9c, 0, 0, },
82 { HIX5HD2_SD_CIU_CLK, "clk_sd_ciu", "sd_mux",
83 CLK_SET_RATE_PARENT, 0x9c, 1, 0, },
84 { HIX5HD2_SD_CIU_RST, "rst_sd_ciu", "clk_sd_ciu",
85 CLK_SET_RATE_PARENT, 0x9c, 4, CLK_GATE_SET_TO_DISABLE, },
86 /* sdio1 */
76 { HIX5HD2_MMC_BIU_CLK, "clk_mmc_biu", "200m", 87 { HIX5HD2_MMC_BIU_CLK, "clk_mmc_biu", "200m",
77 CLK_SET_RATE_PARENT, 0xa0, 0, 0, }, 88 CLK_SET_RATE_PARENT, 0xa0, 0, 0, },
78 { HIX5HD2_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux", 89 { HIX5HD2_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux",
79 CLK_SET_RATE_PARENT, 0xa0, 1, 0, }, 90 CLK_SET_RATE_PARENT, 0xa0, 1, 0, },
80 { HIX5HD2_MMC_CIU_RST, "rst_mmc_ciu", "clk_mmc_ciu", 91 { HIX5HD2_MMC_CIU_RST, "rst_mmc_ciu", "clk_mmc_ciu",
81 CLK_SET_RATE_PARENT, 0xa0, 4, CLK_GATE_SET_TO_DISABLE, }, 92 CLK_SET_RATE_PARENT, 0xa0, 4, CLK_GATE_SET_TO_DISABLE, },
93 /* gsf */
94 { HIX5HD2_FWD_BUS_CLK, "clk_fwd_bus", NULL, 0, 0xcc, 0, 0, },
95 { HIX5HD2_FWD_SYS_CLK, "clk_fwd_sys", "clk_fwd_bus", 0, 0xcc, 5, 0, },
96 { HIX5HD2_MAC0_PHY_CLK, "clk_fephy", "clk_fwd_sys",
97 CLK_SET_RATE_PARENT, 0x120, 0, 0, },
98 /* wdg0 */
99 { HIX5HD2_WDG0_CLK, "clk_wdg0", "24m",
100 CLK_SET_RATE_PARENT, 0x178, 0, 0, },
101 { HIX5HD2_WDG0_RST, "rst_wdg0", "clk_wdg0",
102 CLK_SET_RATE_PARENT, 0x178, 4, CLK_GATE_SET_TO_DISABLE, },
103 /* I2C */
104 {HIX5HD2_I2C0_CLK, "clk_i2c0", "100m",
105 CLK_SET_RATE_PARENT, 0x06c, 4, 0, },
106 {HIX5HD2_I2C0_RST, "rst_i2c0", "clk_i2c0",
107 CLK_SET_RATE_PARENT, 0x06c, 5, CLK_GATE_SET_TO_DISABLE, },
108 {HIX5HD2_I2C1_CLK, "clk_i2c1", "100m",
109 CLK_SET_RATE_PARENT, 0x06c, 8, 0, },
110 {HIX5HD2_I2C1_RST, "rst_i2c1", "clk_i2c1",
111 CLK_SET_RATE_PARENT, 0x06c, 9, CLK_GATE_SET_TO_DISABLE, },
112 {HIX5HD2_I2C2_CLK, "clk_i2c2", "100m",
113 CLK_SET_RATE_PARENT, 0x06c, 12, 0, },
114 {HIX5HD2_I2C2_RST, "rst_i2c2", "clk_i2c2",
115 CLK_SET_RATE_PARENT, 0x06c, 13, CLK_GATE_SET_TO_DISABLE, },
116 {HIX5HD2_I2C3_CLK, "clk_i2c3", "100m",
117 CLK_SET_RATE_PARENT, 0x06c, 16, 0, },
118 {HIX5HD2_I2C3_RST, "rst_i2c3", "clk_i2c3",
119 CLK_SET_RATE_PARENT, 0x06c, 17, CLK_GATE_SET_TO_DISABLE, },
120 {HIX5HD2_I2C4_CLK, "clk_i2c4", "100m",
121 CLK_SET_RATE_PARENT, 0x06c, 20, 0, },
122 {HIX5HD2_I2C4_RST, "rst_i2c4", "clk_i2c4",
123 CLK_SET_RATE_PARENT, 0x06c, 21, CLK_GATE_SET_TO_DISABLE, },
124 {HIX5HD2_I2C5_CLK, "clk_i2c5", "100m",
125 CLK_SET_RATE_PARENT, 0x06c, 0, 0, },
126 {HIX5HD2_I2C5_RST, "rst_i2c5", "clk_i2c5",
127 CLK_SET_RATE_PARENT, 0x06c, 1, CLK_GATE_SET_TO_DISABLE, },
82}; 128};
83 129
130enum hix5hd2_clk_type {
131 TYPE_COMPLEX,
132 TYPE_ETHER,
133};
134
135struct hix5hd2_complex_clock {
136 const char *name;
137 const char *parent_name;
138 u32 id;
139 u32 ctrl_reg;
140 u32 ctrl_clk_mask;
141 u32 ctrl_rst_mask;
142 u32 phy_reg;
143 u32 phy_clk_mask;
144 u32 phy_rst_mask;
145 enum hix5hd2_clk_type type;
146};
147
148struct hix5hd2_clk_complex {
149 struct clk_hw hw;
150 u32 id;
151 void __iomem *ctrl_reg;
152 u32 ctrl_clk_mask;
153 u32 ctrl_rst_mask;
154 void __iomem *phy_reg;
155 u32 phy_clk_mask;
156 u32 phy_rst_mask;
157};
158
159static struct hix5hd2_complex_clock hix5hd2_complex_clks[] __initdata = {
160 {"clk_mac0", "clk_fephy", HIX5HD2_MAC0_CLK,
161 0xcc, 0xa, 0x500, 0x120, 0, 0x10, TYPE_ETHER},
162 {"clk_mac1", "clk_fwd_sys", HIX5HD2_MAC1_CLK,
163 0xcc, 0x14, 0xa00, 0x168, 0x2, 0, TYPE_ETHER},
164 {"clk_sata", NULL, HIX5HD2_SATA_CLK,
165 0xa8, 0x1f, 0x300, 0xac, 0x1, 0x0, TYPE_COMPLEX},
166 {"clk_usb", NULL, HIX5HD2_USB_CLK,
167 0xb8, 0xff, 0x3f000, 0xbc, 0x7, 0x3f00, TYPE_COMPLEX},
168};
169
170#define to_complex_clk(_hw) container_of(_hw, struct hix5hd2_clk_complex, hw)
171
172static int clk_ether_prepare(struct clk_hw *hw)
173{
174 struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
175 u32 val;
176
177 val = readl_relaxed(clk->ctrl_reg);
178 val |= clk->ctrl_clk_mask | clk->ctrl_rst_mask;
179 writel_relaxed(val, clk->ctrl_reg);
180 val &= ~(clk->ctrl_rst_mask);
181 writel_relaxed(val, clk->ctrl_reg);
182
183 val = readl_relaxed(clk->phy_reg);
184 val |= clk->phy_clk_mask;
185 val &= ~(clk->phy_rst_mask);
186 writel_relaxed(val, clk->phy_reg);
187 mdelay(10);
188
189 val &= ~(clk->phy_clk_mask);
190 val |= clk->phy_rst_mask;
191 writel_relaxed(val, clk->phy_reg);
192 mdelay(10);
193
194 val |= clk->phy_clk_mask;
195 val &= ~(clk->phy_rst_mask);
196 writel_relaxed(val, clk->phy_reg);
197 mdelay(30);
198 return 0;
199}
200
201static void clk_ether_unprepare(struct clk_hw *hw)
202{
203 struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
204 u32 val;
205
206 val = readl_relaxed(clk->ctrl_reg);
207 val &= ~(clk->ctrl_clk_mask);
208 writel_relaxed(val, clk->ctrl_reg);
209}
210
211static struct clk_ops clk_ether_ops = {
212 .prepare = clk_ether_prepare,
213 .unprepare = clk_ether_unprepare,
214};
215
216static int clk_complex_enable(struct clk_hw *hw)
217{
218 struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
219 u32 val;
220
221 val = readl_relaxed(clk->ctrl_reg);
222 val |= clk->ctrl_clk_mask;
223 val &= ~(clk->ctrl_rst_mask);
224 writel_relaxed(val, clk->ctrl_reg);
225
226 val = readl_relaxed(clk->phy_reg);
227 val |= clk->phy_clk_mask;
228 val &= ~(clk->phy_rst_mask);
229 writel_relaxed(val, clk->phy_reg);
230
231 return 0;
232}
233
234static void clk_complex_disable(struct clk_hw *hw)
235{
236 struct hix5hd2_clk_complex *clk = to_complex_clk(hw);
237 u32 val;
238
239 val = readl_relaxed(clk->ctrl_reg);
240 val |= clk->ctrl_rst_mask;
241 val &= ~(clk->ctrl_clk_mask);
242 writel_relaxed(val, clk->ctrl_reg);
243
244 val = readl_relaxed(clk->phy_reg);
245 val |= clk->phy_rst_mask;
246 val &= ~(clk->phy_clk_mask);
247 writel_relaxed(val, clk->phy_reg);
248}
249
250static struct clk_ops clk_complex_ops = {
251 .enable = clk_complex_enable,
252 .disable = clk_complex_disable,
253};
254
255void __init hix5hd2_clk_register_complex(struct hix5hd2_complex_clock *clks,
256 int nums, struct hisi_clock_data *data)
257{
258 void __iomem *base = data->base;
259 int i;
260
261 for (i = 0; i < nums; i++) {
262 struct hix5hd2_clk_complex *p_clk;
263 struct clk *clk;
264 struct clk_init_data init;
265
266 p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL);
267 if (!p_clk)
268 return;
269
270 init.name = clks[i].name;
271 if (clks[i].type == TYPE_ETHER)
272 init.ops = &clk_ether_ops;
273 else
274 init.ops = &clk_complex_ops;
275
276 init.flags = CLK_IS_BASIC;
277 init.parent_names =
278 (clks[i].parent_name ? &clks[i].parent_name : NULL);
279 init.num_parents = (clks[i].parent_name ? 1 : 0);
280
281 p_clk->ctrl_reg = base + clks[i].ctrl_reg;
282 p_clk->ctrl_clk_mask = clks[i].ctrl_clk_mask;
283 p_clk->ctrl_rst_mask = clks[i].ctrl_rst_mask;
284 p_clk->phy_reg = base + clks[i].phy_reg;
285 p_clk->phy_clk_mask = clks[i].phy_clk_mask;
286 p_clk->phy_rst_mask = clks[i].phy_rst_mask;
287 p_clk->hw.init = &init;
288
289 clk = clk_register(NULL, &p_clk->hw);
290 if (IS_ERR(clk)) {
291 kfree(p_clk);
292 pr_err("%s: failed to register clock %s\n",
293 __func__, clks[i].name);
294 continue;
295 }
296
297 data->clk_data.clks[clks[i].id] = clk;
298 }
299}
300
84static void __init hix5hd2_clk_init(struct device_node *np) 301static void __init hix5hd2_clk_init(struct device_node *np)
85{ 302{
86 struct hisi_clock_data *clk_data; 303 struct hisi_clock_data *clk_data;
@@ -96,6 +313,9 @@ static void __init hix5hd2_clk_init(struct device_node *np)
96 clk_data); 313 clk_data);
97 hisi_clk_register_gate(hix5hd2_gate_clks, 314 hisi_clk_register_gate(hix5hd2_gate_clks,
98 ARRAY_SIZE(hix5hd2_gate_clks), clk_data); 315 ARRAY_SIZE(hix5hd2_gate_clks), clk_data);
316 hix5hd2_clk_register_complex(hix5hd2_complex_clks,
317 ARRAY_SIZE(hix5hd2_complex_clks),
318 clk_data);
99} 319}
100 320
101CLK_OF_DECLARE(hix5hd2_clk, "hisilicon,hix5hd2-clock", hix5hd2_clk_init); 321CLK_OF_DECLARE(hix5hd2_clk, "hisilicon,hix5hd2-clock", hix5hd2_clk_init);
diff --git a/drivers/clk/mvebu/armada-370.c b/drivers/clk/mvebu/armada-370.c
index bef198a83863..756f0f39d6a3 100644
--- a/drivers/clk/mvebu/armada-370.c
+++ b/drivers/clk/mvebu/armada-370.c
@@ -23,6 +23,7 @@
23 */ 23 */
24 24
25#define SARL 0 /* Low part [0:31] */ 25#define SARL 0 /* Low part [0:31] */
26#define SARL_A370_SSCG_ENABLE BIT(10)
26#define SARL_A370_PCLK_FREQ_OPT 11 27#define SARL_A370_PCLK_FREQ_OPT 11
27#define SARL_A370_PCLK_FREQ_OPT_MASK 0xF 28#define SARL_A370_PCLK_FREQ_OPT_MASK 0xF
28#define SARL_A370_FAB_FREQ_OPT 15 29#define SARL_A370_FAB_FREQ_OPT 15
@@ -133,10 +134,17 @@ static void __init a370_get_clk_ratio(
133 } 134 }
134} 135}
135 136
137static bool a370_is_sscg_enabled(void __iomem *sar)
138{
139 return !(readl(sar) & SARL_A370_SSCG_ENABLE);
140}
141
136static const struct coreclk_soc_desc a370_coreclks = { 142static const struct coreclk_soc_desc a370_coreclks = {
137 .get_tclk_freq = a370_get_tclk_freq, 143 .get_tclk_freq = a370_get_tclk_freq,
138 .get_cpu_freq = a370_get_cpu_freq, 144 .get_cpu_freq = a370_get_cpu_freq,
139 .get_clk_ratio = a370_get_clk_ratio, 145 .get_clk_ratio = a370_get_clk_ratio,
146 .is_sscg_enabled = a370_is_sscg_enabled,
147 .fix_sscg_deviation = kirkwood_fix_sscg_deviation,
140 .ratios = a370_coreclk_ratios, 148 .ratios = a370_coreclk_ratios,
141 .num_ratios = ARRAY_SIZE(a370_coreclk_ratios), 149 .num_ratios = ARRAY_SIZE(a370_coreclk_ratios),
142}; 150};
diff --git a/drivers/clk/mvebu/armada-375.c b/drivers/clk/mvebu/armada-375.c
index c991a4d95e10..c7af2242b796 100644
--- a/drivers/clk/mvebu/armada-375.c
+++ b/drivers/clk/mvebu/armada-375.c
@@ -27,14 +27,14 @@
27 * all modified at the same time, and not separately as for the Armada 27 * all modified at the same time, and not separately as for the Armada
28 * 370 or the Armada XP SoCs. 28 * 370 or the Armada XP SoCs.
29 * 29 *
30 * SAR0[21:17] : CPU frequency DDR frequency L2 frequency 30 * SAR1[21:17] : CPU frequency DDR frequency L2 frequency
31 * 6 = 400 MHz 400 MHz 200 MHz 31 * 6 = 400 MHz 400 MHz 200 MHz
32 * 15 = 600 MHz 600 MHz 300 MHz 32 * 15 = 600 MHz 600 MHz 300 MHz
33 * 21 = 800 MHz 534 MHz 400 MHz 33 * 21 = 800 MHz 534 MHz 400 MHz
34 * 25 = 1000 MHz 500 MHz 500 MHz 34 * 25 = 1000 MHz 500 MHz 500 MHz
35 * others reserved. 35 * others reserved.
36 * 36 *
37 * SAR0[22] : TCLK frequency 37 * SAR1[22] : TCLK frequency
38 * 0 = 166 MHz 38 * 0 = 166 MHz
39 * 1 = 200 MHz 39 * 1 = 200 MHz
40 */ 40 */
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
index 8ebf757d29e2..3821a88077ea 100644
--- a/drivers/clk/mvebu/clk-cpu.c
+++ b/drivers/clk/mvebu/clk-cpu.c
@@ -16,10 +16,19 @@
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/of.h> 17#include <linux/of.h>
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/mvebu-pmsu.h>
20#include <asm/smp_plat.h>
19 21
20#define SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET 0x0 22#define SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET 0x0
21#define SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET 0xC 23#define SYS_CTRL_CLK_DIVIDER_CTRL_RESET_ALL 0xff
22#define SYS_CTRL_CLK_DIVIDER_MASK 0x3F 24#define SYS_CTRL_CLK_DIVIDER_CTRL_RESET_SHIFT 8
25#define SYS_CTRL_CLK_DIVIDER_CTRL2_OFFSET 0x8
26#define SYS_CTRL_CLK_DIVIDER_CTRL2_NBCLK_RATIO_SHIFT 16
27#define SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET 0xC
28#define SYS_CTRL_CLK_DIVIDER_MASK 0x3F
29
30#define PMU_DFS_RATIO_SHIFT 16
31#define PMU_DFS_RATIO_MASK 0x3F
23 32
24#define MAX_CPU 4 33#define MAX_CPU 4
25struct cpu_clk { 34struct cpu_clk {
@@ -28,6 +37,7 @@ struct cpu_clk {
28 const char *clk_name; 37 const char *clk_name;
29 const char *parent_name; 38 const char *parent_name;
30 void __iomem *reg_base; 39 void __iomem *reg_base;
40 void __iomem *pmu_dfs;
31}; 41};
32 42
33static struct clk **clks; 43static struct clk **clks;
@@ -62,8 +72,9 @@ static long clk_cpu_round_rate(struct clk_hw *hwclk, unsigned long rate,
62 return *parent_rate / div; 72 return *parent_rate / div;
63} 73}
64 74
65static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate, 75static int clk_cpu_off_set_rate(struct clk_hw *hwclk, unsigned long rate,
66 unsigned long parent_rate) 76 unsigned long parent_rate)
77
67{ 78{
68 struct cpu_clk *cpuclk = to_cpu_clk(hwclk); 79 struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
69 u32 reg, div; 80 u32 reg, div;
@@ -95,6 +106,58 @@ static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate,
95 return 0; 106 return 0;
96} 107}
97 108
109static int clk_cpu_on_set_rate(struct clk_hw *hwclk, unsigned long rate,
110 unsigned long parent_rate)
111{
112 u32 reg;
113 unsigned long fabric_div, target_div, cur_rate;
114 struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
115
116 /*
117 * PMU DFS registers are not mapped, Device Tree does not
118 * describes them. We cannot change the frequency dynamically.
119 */
120 if (!cpuclk->pmu_dfs)
121 return -ENODEV;
122
123 cur_rate = __clk_get_rate(hwclk->clk);
124
125 reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL2_OFFSET);
126 fabric_div = (reg >> SYS_CTRL_CLK_DIVIDER_CTRL2_NBCLK_RATIO_SHIFT) &
127 SYS_CTRL_CLK_DIVIDER_MASK;
128
129 /* Frequency is going up */
130 if (rate == 2 * cur_rate)
131 target_div = fabric_div / 2;
132 /* Frequency is going down */
133 else
134 target_div = fabric_div;
135
136 if (target_div == 0)
137 target_div = 1;
138
139 reg = readl(cpuclk->pmu_dfs);
140 reg &= ~(PMU_DFS_RATIO_MASK << PMU_DFS_RATIO_SHIFT);
141 reg |= (target_div << PMU_DFS_RATIO_SHIFT);
142 writel(reg, cpuclk->pmu_dfs);
143
144 reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
145 reg |= (SYS_CTRL_CLK_DIVIDER_CTRL_RESET_ALL <<
146 SYS_CTRL_CLK_DIVIDER_CTRL_RESET_SHIFT);
147 writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
148
149 return mvebu_pmsu_dfs_request(cpuclk->cpu);
150}
151
152static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate,
153 unsigned long parent_rate)
154{
155 if (__clk_is_enabled(hwclk->clk))
156 return clk_cpu_on_set_rate(hwclk, rate, parent_rate);
157 else
158 return clk_cpu_off_set_rate(hwclk, rate, parent_rate);
159}
160
98static const struct clk_ops cpu_ops = { 161static const struct clk_ops cpu_ops = {
99 .recalc_rate = clk_cpu_recalc_rate, 162 .recalc_rate = clk_cpu_recalc_rate,
100 .round_rate = clk_cpu_round_rate, 163 .round_rate = clk_cpu_round_rate,
@@ -105,6 +168,7 @@ static void __init of_cpu_clk_setup(struct device_node *node)
105{ 168{
106 struct cpu_clk *cpuclk; 169 struct cpu_clk *cpuclk;
107 void __iomem *clock_complex_base = of_iomap(node, 0); 170 void __iomem *clock_complex_base = of_iomap(node, 0);
171 void __iomem *pmu_dfs_base = of_iomap(node, 1);
108 int ncpus = 0; 172 int ncpus = 0;
109 struct device_node *dn; 173 struct device_node *dn;
110 174
@@ -114,6 +178,10 @@ static void __init of_cpu_clk_setup(struct device_node *node)
114 return; 178 return;
115 } 179 }
116 180
181 if (pmu_dfs_base == NULL)
182 pr_warn("%s: pmu-dfs base register not set, dynamic frequency scaling not available\n",
183 __func__);
184
117 for_each_node_by_type(dn, "cpu") 185 for_each_node_by_type(dn, "cpu")
118 ncpus++; 186 ncpus++;
119 187
@@ -146,6 +214,8 @@ static void __init of_cpu_clk_setup(struct device_node *node)
146 cpuclk[cpu].clk_name = clk_name; 214 cpuclk[cpu].clk_name = clk_name;
147 cpuclk[cpu].cpu = cpu; 215 cpuclk[cpu].cpu = cpu;
148 cpuclk[cpu].reg_base = clock_complex_base; 216 cpuclk[cpu].reg_base = clock_complex_base;
217 if (pmu_dfs_base)
218 cpuclk[cpu].pmu_dfs = pmu_dfs_base + 4 * cpu;
149 cpuclk[cpu].hw.init = &init; 219 cpuclk[cpu].hw.init = &init;
150 220
151 init.name = cpuclk[cpu].clk_name; 221 init.name = cpuclk[cpu].clk_name;
diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c
index 25ceccf939ad..b7fcb469c87a 100644
--- a/drivers/clk/mvebu/common.c
+++ b/drivers/clk/mvebu/common.c
@@ -26,8 +26,85 @@
26 * Core Clocks 26 * Core Clocks
27 */ 27 */
28 28
29#define SSCG_CONF_MODE(reg) (((reg) >> 16) & 0x3)
30#define SSCG_SPREAD_DOWN 0x0
31#define SSCG_SPREAD_UP 0x1
32#define SSCG_SPREAD_CENTRAL 0x2
33#define SSCG_CONF_LOW(reg) (((reg) >> 8) & 0xFF)
34#define SSCG_CONF_HIGH(reg) ((reg) & 0xFF)
35
29static struct clk_onecell_data clk_data; 36static struct clk_onecell_data clk_data;
30 37
38/*
39 * This function can be used by the Kirkwood, the Armada 370, the
40 * Armada XP and the Armada 375 SoC. The name of the function was
41 * chosen following the dt convention: using the first known SoC
42 * compatible with it.
43 */
44u32 kirkwood_fix_sscg_deviation(u32 system_clk)
45{
46 struct device_node *sscg_np = NULL;
47 void __iomem *sscg_map;
48 u32 sscg_reg;
49 s32 low_bound, high_bound;
50 u64 freq_swing_half;
51
52 sscg_np = of_find_node_by_name(NULL, "sscg");
53 if (sscg_np == NULL) {
54 pr_err("cannot get SSCG register node\n");
55 return system_clk;
56 }
57
58 sscg_map = of_iomap(sscg_np, 0);
59 if (sscg_map == NULL) {
60 pr_err("cannot map SSCG register\n");
61 goto out;
62 }
63
64 sscg_reg = readl(sscg_map);
65 high_bound = SSCG_CONF_HIGH(sscg_reg);
66 low_bound = SSCG_CONF_LOW(sscg_reg);
67
68 if ((high_bound - low_bound) <= 0)
69 goto out;
70 /*
71 * From Marvell engineer we got the following formula (when
72 * this code was written, the datasheet was erroneous)
73 * Spread percentage = 1/96 * (H - L) / H
74 * H = SSCG_High_Boundary
75 * L = SSCG_Low_Boundary
76 *
77 * As the deviation is half of spread then it lead to the
78 * following formula in the code.
79 *
80 * To avoid an overflow and not lose any significant digit in
81 * the same time we have to use a 64 bit integer.
82 */
83
84 freq_swing_half = (((u64)high_bound - (u64)low_bound)
85 * (u64)system_clk);
86 do_div(freq_swing_half, (2 * 96 * high_bound));
87
88 switch (SSCG_CONF_MODE(sscg_reg)) {
89 case SSCG_SPREAD_DOWN:
90 system_clk -= freq_swing_half;
91 break;
92 case SSCG_SPREAD_UP:
93 system_clk += freq_swing_half;
94 break;
95 case SSCG_SPREAD_CENTRAL:
96 default:
97 break;
98 }
99
100 iounmap(sscg_map);
101
102out:
103 of_node_put(sscg_np);
104
105 return system_clk;
106}
107
31void __init mvebu_coreclk_setup(struct device_node *np, 108void __init mvebu_coreclk_setup(struct device_node *np,
32 const struct coreclk_soc_desc *desc) 109 const struct coreclk_soc_desc *desc)
33{ 110{
@@ -62,6 +139,11 @@ void __init mvebu_coreclk_setup(struct device_node *np,
62 of_property_read_string_index(np, "clock-output-names", 1, 139 of_property_read_string_index(np, "clock-output-names", 1,
63 &cpuclk_name); 140 &cpuclk_name);
64 rate = desc->get_cpu_freq(base); 141 rate = desc->get_cpu_freq(base);
142
143 if (desc->is_sscg_enabled && desc->fix_sscg_deviation
144 && desc->is_sscg_enabled(base))
145 rate = desc->fix_sscg_deviation(rate);
146
65 clk_data.clks[1] = clk_register_fixed_rate(NULL, cpuclk_name, NULL, 147 clk_data.clks[1] = clk_register_fixed_rate(NULL, cpuclk_name, NULL,
66 CLK_IS_ROOT, rate); 148 CLK_IS_ROOT, rate);
67 WARN_ON(IS_ERR(clk_data.clks[1])); 149 WARN_ON(IS_ERR(clk_data.clks[1]));
@@ -89,8 +171,10 @@ void __init mvebu_coreclk_setup(struct device_node *np,
89 * Clock Gating Control 171 * Clock Gating Control
90 */ 172 */
91 173
174DEFINE_SPINLOCK(ctrl_gating_lock);
175
92struct clk_gating_ctrl { 176struct clk_gating_ctrl {
93 spinlock_t lock; 177 spinlock_t *lock;
94 struct clk **gates; 178 struct clk **gates;
95 int num_gates; 179 int num_gates;
96}; 180};
@@ -138,7 +222,8 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
138 if (WARN_ON(!ctrl)) 222 if (WARN_ON(!ctrl))
139 goto ctrl_out; 223 goto ctrl_out;
140 224
141 spin_lock_init(&ctrl->lock); 225 /* lock must already be initialized */
226 ctrl->lock = &ctrl_gating_lock;
142 227
143 /* Count, allocate, and register clock gates */ 228 /* Count, allocate, and register clock gates */
144 for (n = 0; desc[n].name;) 229 for (n = 0; desc[n].name;)
@@ -155,7 +240,7 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
155 (desc[n].parent) ? desc[n].parent : default_parent; 240 (desc[n].parent) ? desc[n].parent : default_parent;
156 ctrl->gates[n] = clk_register_gate(NULL, desc[n].name, parent, 241 ctrl->gates[n] = clk_register_gate(NULL, desc[n].name, parent,
157 desc[n].flags, base, desc[n].bit_idx, 242 desc[n].flags, base, desc[n].bit_idx,
158 0, &ctrl->lock); 243 0, ctrl->lock);
159 WARN_ON(IS_ERR(ctrl->gates[n])); 244 WARN_ON(IS_ERR(ctrl->gates[n]));
160 } 245 }
161 246
diff --git a/drivers/clk/mvebu/common.h b/drivers/clk/mvebu/common.h
index f968b4d9df92..783b5631a453 100644
--- a/drivers/clk/mvebu/common.h
+++ b/drivers/clk/mvebu/common.h
@@ -17,6 +17,8 @@
17 17
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19 19
20extern spinlock_t ctrl_gating_lock;
21
20struct device_node; 22struct device_node;
21 23
22struct coreclk_ratio { 24struct coreclk_ratio {
@@ -28,6 +30,8 @@ struct coreclk_soc_desc {
28 u32 (*get_tclk_freq)(void __iomem *sar); 30 u32 (*get_tclk_freq)(void __iomem *sar);
29 u32 (*get_cpu_freq)(void __iomem *sar); 31 u32 (*get_cpu_freq)(void __iomem *sar);
30 void (*get_clk_ratio)(void __iomem *sar, int id, int *mult, int *div); 32 void (*get_clk_ratio)(void __iomem *sar, int id, int *mult, int *div);
33 bool (*is_sscg_enabled)(void __iomem *sar);
34 u32 (*fix_sscg_deviation)(u32 system_clk);
31 const struct coreclk_ratio *ratios; 35 const struct coreclk_ratio *ratios;
32 int num_ratios; 36 int num_ratios;
33}; 37};
@@ -45,4 +49,9 @@ void __init mvebu_coreclk_setup(struct device_node *np,
45void __init mvebu_clk_gating_setup(struct device_node *np, 49void __init mvebu_clk_gating_setup(struct device_node *np,
46 const struct clk_gating_soc_desc *desc); 50 const struct clk_gating_soc_desc *desc);
47 51
52/*
53 * This function is shared among the Kirkwood, Armada 370, Armada XP
54 * and Armada 375 SoC
55 */
56u32 kirkwood_fix_sscg_deviation(u32 system_clk);
48#endif 57#endif
diff --git a/drivers/clk/mvebu/kirkwood.c b/drivers/clk/mvebu/kirkwood.c
index ddb666a86500..99550f25975e 100644
--- a/drivers/clk/mvebu/kirkwood.c
+++ b/drivers/clk/mvebu/kirkwood.c
@@ -13,9 +13,11 @@
13 */ 13 */
14 14
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/slab.h>
16#include <linux/clk-provider.h> 17#include <linux/clk-provider.h>
17#include <linux/io.h> 18#include <linux/io.h>
18#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/of_address.h>
19#include "common.h" 21#include "common.h"
20 22
21/* 23/*
@@ -214,7 +216,6 @@ static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = {
214 { "runit", NULL, 7, 0 }, 216 { "runit", NULL, 7, 0 },
215 { "xor0", NULL, 8, 0 }, 217 { "xor0", NULL, 8, 0 },
216 { "audio", NULL, 9, 0 }, 218 { "audio", NULL, 9, 0 },
217 { "powersave", "cpuclk", 11, 0 },
218 { "sata0", NULL, 14, 0 }, 219 { "sata0", NULL, 14, 0 },
219 { "sata1", NULL, 15, 0 }, 220 { "sata1", NULL, 15, 0 },
220 { "xor1", NULL, 16, 0 }, 221 { "xor1", NULL, 16, 0 },
@@ -225,6 +226,101 @@ static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = {
225 { } 226 { }
226}; 227};
227 228
229
230/*
231 * Clock Muxing Control
232 */
233
234struct clk_muxing_soc_desc {
235 const char *name;
236 const char **parents;
237 int num_parents;
238 int shift;
239 int width;
240 unsigned long flags;
241};
242
243struct clk_muxing_ctrl {
244 spinlock_t *lock;
245 struct clk **muxes;
246 int num_muxes;
247};
248
249static const char *powersave_parents[] = {
250 "cpuclk",
251 "ddrclk",
252};
253
254static const struct clk_muxing_soc_desc kirkwood_mux_desc[] __initconst = {
255 { "powersave", powersave_parents, ARRAY_SIZE(powersave_parents),
256 11, 1, 0 },
257};
258
259#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
260
261static struct clk *clk_muxing_get_src(
262 struct of_phandle_args *clkspec, void *data)
263{
264 struct clk_muxing_ctrl *ctrl = (struct clk_muxing_ctrl *)data;
265 int n;
266
267 if (clkspec->args_count < 1)
268 return ERR_PTR(-EINVAL);
269
270 for (n = 0; n < ctrl->num_muxes; n++) {
271 struct clk_mux *mux =
272 to_clk_mux(__clk_get_hw(ctrl->muxes[n]));
273 if (clkspec->args[0] == mux->shift)
274 return ctrl->muxes[n];
275 }
276 return ERR_PTR(-ENODEV);
277}
278
279static void __init kirkwood_clk_muxing_setup(struct device_node *np,
280 const struct clk_muxing_soc_desc *desc)
281{
282 struct clk_muxing_ctrl *ctrl;
283 void __iomem *base;
284 int n;
285
286 base = of_iomap(np, 0);
287 if (WARN_ON(!base))
288 return;
289
290 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
291 if (WARN_ON(!ctrl))
292 goto ctrl_out;
293
294 /* lock must already be initialized */
295 ctrl->lock = &ctrl_gating_lock;
296
297 /* Count, allocate, and register clock muxes */
298 for (n = 0; desc[n].name;)
299 n++;
300
301 ctrl->num_muxes = n;
302 ctrl->muxes = kcalloc(ctrl->num_muxes, sizeof(struct clk *),
303 GFP_KERNEL);
304 if (WARN_ON(!ctrl->muxes))
305 goto muxes_out;
306
307 for (n = 0; n < ctrl->num_muxes; n++) {
308 ctrl->muxes[n] = clk_register_mux(NULL, desc[n].name,
309 desc[n].parents, desc[n].num_parents,
310 desc[n].flags, base, desc[n].shift,
311 desc[n].width, desc[n].flags, ctrl->lock);
312 WARN_ON(IS_ERR(ctrl->muxes[n]));
313 }
314
315 of_clk_add_provider(np, clk_muxing_get_src, ctrl);
316
317 return;
318muxes_out:
319 kfree(ctrl);
320ctrl_out:
321 iounmap(base);
322}
323
228static void __init kirkwood_clk_init(struct device_node *np) 324static void __init kirkwood_clk_init(struct device_node *np)
229{ 325{
230 struct device_node *cgnp = 326 struct device_node *cgnp =
@@ -236,8 +332,10 @@ static void __init kirkwood_clk_init(struct device_node *np)
236 else 332 else
237 mvebu_coreclk_setup(np, &kirkwood_coreclks); 333 mvebu_coreclk_setup(np, &kirkwood_coreclks);
238 334
239 if (cgnp) 335 if (cgnp) {
240 mvebu_clk_gating_setup(cgnp, kirkwood_gating_desc); 336 mvebu_clk_gating_setup(cgnp, kirkwood_gating_desc);
337 kirkwood_clk_muxing_setup(cgnp, kirkwood_mux_desc);
338 }
241} 339}
242CLK_OF_DECLARE(kirkwood_clk, "marvell,kirkwood-core-clock", 340CLK_OF_DECLARE(kirkwood_clk, "marvell,kirkwood-core-clock",
243 kirkwood_clk_init); 341 kirkwood_clk_init);
diff --git a/drivers/clk/pxa/Makefile b/drivers/clk/pxa/Makefile
new file mode 100644
index 000000000000..4ff2abcd500b
--- /dev/null
+++ b/drivers/clk/pxa/Makefile
@@ -0,0 +1,2 @@
1obj-y += clk-pxa.o
2obj-$(CONFIG_PXA27x) += clk-pxa27x.o
diff --git a/drivers/clk/pxa/clk-pxa.c b/drivers/clk/pxa/clk-pxa.c
new file mode 100644
index 000000000000..ef3c05389c0a
--- /dev/null
+++ b/drivers/clk/pxa/clk-pxa.c
@@ -0,0 +1,97 @@
1/*
2 * Marvell PXA family clocks
3 *
4 * Copyright (C) 2014 Robert Jarzmik
5 *
6 * Common clock code for PXA clocks ("CKEN" type clocks + DT)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 */
13#include <linux/clk.h>
14#include <linux/clk-provider.h>
15#include <linux/clkdev.h>
16#include <linux/of.h>
17
18#include <dt-bindings/clock/pxa-clock.h>
19#include "clk-pxa.h"
20
21DEFINE_SPINLOCK(lock);
22
23static struct clk *pxa_clocks[CLK_MAX];
24static struct clk_onecell_data onecell_data = {
25 .clks = pxa_clocks,
26 .clk_num = CLK_MAX,
27};
28
29#define to_pxa_clk(_hw) container_of(_hw, struct pxa_clk_cken, hw)
30
31static unsigned long cken_recalc_rate(struct clk_hw *hw,
32 unsigned long parent_rate)
33{
34 struct pxa_clk_cken *pclk = to_pxa_clk(hw);
35 struct clk_fixed_factor *fix;
36
37 if (!pclk->is_in_low_power || pclk->is_in_low_power())
38 fix = &pclk->lp;
39 else
40 fix = &pclk->hp;
41 fix->hw.clk = hw->clk;
42 return clk_fixed_factor_ops.recalc_rate(&fix->hw, parent_rate);
43}
44
45static struct clk_ops cken_rate_ops = {
46 .recalc_rate = cken_recalc_rate,
47};
48
49static u8 cken_get_parent(struct clk_hw *hw)
50{
51 struct pxa_clk_cken *pclk = to_pxa_clk(hw);
52
53 if (!pclk->is_in_low_power)
54 return 0;
55 return pclk->is_in_low_power() ? 0 : 1;
56}
57
58static struct clk_ops cken_mux_ops = {
59 .get_parent = cken_get_parent,
60 .set_parent = dummy_clk_set_parent,
61};
62
63void __init clkdev_pxa_register(int ckid, const char *con_id,
64 const char *dev_id, struct clk *clk)
65{
66 if (!IS_ERR(clk) && (ckid != CLK_NONE))
67 pxa_clocks[ckid] = clk;
68 if (!IS_ERR(clk))
69 clk_register_clkdev(clk, con_id, dev_id);
70}
71
72int __init clk_pxa_cken_init(struct pxa_clk_cken *clks, int nb_clks)
73{
74 int i;
75 struct pxa_clk_cken *pclk;
76 struct clk *clk;
77
78 for (i = 0; i < nb_clks; i++) {
79 pclk = clks + i;
80 pclk->gate.lock = &lock;
81 clk = clk_register_composite(NULL, pclk->name,
82 pclk->parent_names, 2,
83 &pclk->hw, &cken_mux_ops,
84 &pclk->hw, &cken_rate_ops,
85 &pclk->gate.hw, &clk_gate_ops,
86 pclk->flags);
87 clkdev_pxa_register(pclk->ckid, pclk->con_id, pclk->dev_id,
88 clk);
89 }
90 return 0;
91}
92
93static void __init pxa_dt_clocks_init(struct device_node *np)
94{
95 of_clk_add_provider(np, of_clk_src_onecell_get, &onecell_data);
96}
97CLK_OF_DECLARE(pxa_clks, "marvell,pxa-clocks", pxa_dt_clocks_init);
diff --git a/drivers/clk/pxa/clk-pxa.h b/drivers/clk/pxa/clk-pxa.h
new file mode 100644
index 000000000000..5fe219d06b49
--- /dev/null
+++ b/drivers/clk/pxa/clk-pxa.h
@@ -0,0 +1,107 @@
1/*
2 * Marvell PXA family clocks
3 *
4 * Copyright (C) 2014 Robert Jarzmik
5 *
6 * Common clock code for PXA clocks ("CKEN" type clocks + DT)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 */
13#ifndef _CLK_PXA_
14#define _CLK_PXA_
15
16#define PARENTS(name) \
17 static const char *name ## _parents[] __initconst
18#define MUX_RO_RATE_RO_OPS(name, clk_name) \
19 static struct clk_hw name ## _mux_hw; \
20 static struct clk_hw name ## _rate_hw; \
21 static struct clk_ops name ## _mux_ops = { \
22 .get_parent = name ## _get_parent, \
23 .set_parent = dummy_clk_set_parent, \
24 }; \
25 static struct clk_ops name ## _rate_ops = { \
26 .recalc_rate = name ## _get_rate, \
27 }; \
28 static struct clk *clk_register_ ## name(void) \
29 { \
30 return clk_register_composite(NULL, clk_name, \
31 name ## _parents, \
32 ARRAY_SIZE(name ## _parents), \
33 &name ## _mux_hw, &name ## _mux_ops, \
34 &name ## _rate_hw, &name ## _rate_ops, \
35 NULL, NULL, CLK_GET_RATE_NOCACHE); \
36 }
37
38#define RATE_RO_OPS(name, clk_name) \
39 static struct clk_hw name ## _rate_hw; \
40 static struct clk_ops name ## _rate_ops = { \
41 .recalc_rate = name ## _get_rate, \
42 }; \
43 static struct clk *clk_register_ ## name(void) \
44 { \
45 return clk_register_composite(NULL, clk_name, \
46 name ## _parents, \
47 ARRAY_SIZE(name ## _parents), \
48 NULL, NULL, \
49 &name ## _rate_hw, &name ## _rate_ops, \
50 NULL, NULL, CLK_GET_RATE_NOCACHE); \
51 }
52
53/*
54 * CKEN clock type
55 * This clock takes it source from 2 possible parents :
56 * - a low power parent
57 * - a normal parent
58 *
59 * +------------+ +-----------+
60 * | Low Power | --- | x mult_lp |
61 * | Clock | | / div_lp |\
62 * +------------+ +-----------+ \+-----+ +-----------+
63 * | Mux |---| CKEN gate |
64 * +------------+ +-----------+ /+-----+ +-----------+
65 * | High Power | | x mult_hp |/
66 * | Clock | --- | / div_hp |
67 * +------------+ +-----------+
68 */
69struct pxa_clk_cken {
70 struct clk_hw hw;
71 int ckid;
72 const char *name;
73 const char *dev_id;
74 const char *con_id;
75 const char **parent_names;
76 struct clk_fixed_factor lp;
77 struct clk_fixed_factor hp;
78 struct clk_gate gate;
79 bool (*is_in_low_power)(void);
80 const unsigned long flags;
81};
82
83#define PXA_CKEN(_dev_id, _con_id, _name, parents, _mult_lp, _div_lp, \
84 _mult_hp, _div_hp, is_lp, _cken_reg, _cken_bit, flag) \
85 { .ckid = CLK_ ## _name, .name = #_name, \
86 .dev_id = _dev_id, .con_id = _con_id, .parent_names = parents,\
87 .lp = { .mult = _mult_lp, .div = _div_lp }, \
88 .hp = { .mult = _mult_hp, .div = _div_hp }, \
89 .is_in_low_power = is_lp, \
90 .gate = { .reg = (void __iomem *)_cken_reg, .bit_idx = _cken_bit }, \
91 .flags = flag, \
92 }
93#define PXA_CKEN_1RATE(dev_id, con_id, name, parents, cken_reg, \
94 cken_bit, flag) \
95 PXA_CKEN(dev_id, con_id, name, parents, 1, 1, 1, 1, \
96 NULL, cken_reg, cken_bit, flag)
97
98static int dummy_clk_set_parent(struct clk_hw *hw, u8 index)
99{
100 return 0;
101}
102
103extern void clkdev_pxa_register(int ckid, const char *con_id,
104 const char *dev_id, struct clk *clk);
105extern int clk_pxa_cken_init(struct pxa_clk_cken *clks, int nb_clks);
106
107#endif
diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c
new file mode 100644
index 000000000000..b345cc791e5d
--- /dev/null
+++ b/drivers/clk/pxa/clk-pxa27x.c
@@ -0,0 +1,370 @@
1/*
2 * Marvell PXA27x family clocks
3 *
4 * Copyright (C) 2014 Robert Jarzmik
5 *
6 * Heavily inspired from former arch/arm/mach-pxa/clock.c.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 */
13#include <linux/clk-provider.h>
14#include <mach/pxa2xx-regs.h>
15#include <linux/io.h>
16#include <linux/clk.h>
17#include <linux/clkdev.h>
18#include <linux/of.h>
19
20#include <dt-bindings/clock/pxa-clock.h>
21#include "clk-pxa.h"
22
23#define KHz 1000
24#define MHz (1000 * 1000)
25
26enum {
27 PXA_CORE_13Mhz = 0,
28 PXA_CORE_RUN,
29 PXA_CORE_TURBO,
30};
31
32enum {
33 PXA_BUS_13Mhz = 0,
34 PXA_BUS_RUN,
35};
36
37enum {
38 PXA_LCD_13Mhz = 0,
39 PXA_LCD_RUN,
40};
41
42enum {
43 PXA_MEM_13Mhz = 0,
44 PXA_MEM_SYSTEM_BUS,
45 PXA_MEM_RUN,
46};
47
48static const char * const get_freq_khz[] = {
49 "core", "run", "cpll", "memory",
50 "system_bus"
51};
52
53/*
54 * Get the clock frequency as reflected by CCSR and the turbo flag.
55 * We assume these values have been applied via a fcs.
56 * If info is not 0 we also display the current settings.
57 */
58unsigned int pxa27x_get_clk_frequency_khz(int info)
59{
60 struct clk *clk;
61 unsigned long clks[5];
62 int i;
63
64 for (i = 0; i < 5; i++) {
65 clk = clk_get(NULL, get_freq_khz[i]);
66 if (IS_ERR(clk)) {
67 clks[i] = 0;
68 } else {
69 clks[i] = clk_get_rate(clk);
70 clk_put(clk);
71 }
72 }
73 if (info) {
74 pr_info("Run Mode clock: %ld.%02ldMHz\n",
75 clks[1] / 1000000, (clks[1] % 1000000) / 10000);
76 pr_info("Turbo Mode clock: %ld.%02ldMHz\n",
77 clks[2] / 1000000, (clks[2] % 1000000) / 10000);
78 pr_info("Memory clock: %ld.%02ldMHz\n",
79 clks[3] / 1000000, (clks[3] % 1000000) / 10000);
80 pr_info("System bus clock: %ld.%02ldMHz\n",
81 clks[4] / 1000000, (clks[4] % 1000000) / 10000);
82 }
83 return (unsigned int)clks[0];
84}
85
86bool pxa27x_is_ppll_disabled(void)
87{
88 unsigned long ccsr = CCSR;
89
90 return ccsr & (1 << CCCR_PPDIS_BIT);
91}
92
93#define PXA27X_CKEN(dev_id, con_id, parents, mult_hp, div_hp, \
94 bit, is_lp, flags) \
95 PXA_CKEN(dev_id, con_id, bit, parents, 1, 1, mult_hp, div_hp, \
96 is_lp, &CKEN, CKEN_ ## bit, flags)
97#define PXA27X_PBUS_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay) \
98 PXA27X_CKEN(dev_id, con_id, pxa27x_pbus_parents, mult_hp, \
99 div_hp, bit, pxa27x_is_ppll_disabled, 0)
100
101PARENTS(pxa27x_pbus) = { "osc_13mhz", "ppll_312mhz" };
102PARENTS(pxa27x_sbus) = { "system_bus", "system_bus" };
103PARENTS(pxa27x_32Mhz_bus) = { "osc_32_768khz", "osc_32_768khz" };
104PARENTS(pxa27x_lcd_bus) = { "lcd_base", "lcd_base" };
105PARENTS(pxa27x_membus) = { "lcd_base", "lcd_base" };
106
107#define PXA27X_CKEN_1RATE(dev_id, con_id, bit, parents, delay) \
108 PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \
109 &CKEN, CKEN_ ## bit, 0)
110#define PXA27X_CKEN_1RATE_AO(dev_id, con_id, bit, parents, delay) \
111 PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \
112 &CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED)
113
114static struct pxa_clk_cken pxa27x_clocks[] = {
115 PXA27X_PBUS_CKEN("pxa2xx-uart.0", NULL, FFUART, 2, 42, 1),
116 PXA27X_PBUS_CKEN("pxa2xx-uart.1", NULL, BTUART, 2, 42, 1),
117 PXA27X_PBUS_CKEN("pxa2xx-uart.2", NULL, STUART, 2, 42, 1),
118 PXA27X_PBUS_CKEN("pxa2xx-i2s", NULL, I2S, 2, 51, 0),
119 PXA27X_PBUS_CKEN("pxa2xx-i2c.0", NULL, I2C, 2, 19, 0),
120 PXA27X_PBUS_CKEN("pxa27x-udc", NULL, USB, 2, 13, 5),
121 PXA27X_PBUS_CKEN("pxa2xx-mci.0", NULL, MMC, 2, 32, 0),
122 PXA27X_PBUS_CKEN("pxa2xx-ir", "FICPCLK", FICP, 2, 13, 0),
123 PXA27X_PBUS_CKEN("pxa27x-ohci", NULL, USBHOST, 2, 13, 0),
124 PXA27X_PBUS_CKEN("pxa2xx-i2c.1", NULL, PWRI2C, 1, 24, 0),
125 PXA27X_PBUS_CKEN("pxa27x-ssp.0", NULL, SSP1, 1, 24, 0),
126 PXA27X_PBUS_CKEN("pxa27x-ssp.1", NULL, SSP2, 1, 24, 0),
127 PXA27X_PBUS_CKEN("pxa27x-ssp.2", NULL, SSP3, 1, 24, 0),
128 PXA27X_PBUS_CKEN("pxa27x-pwm.0", NULL, PWM0, 1, 24, 0),
129 PXA27X_PBUS_CKEN("pxa27x-pwm.1", NULL, PWM1, 1, 24, 0),
130 PXA27X_PBUS_CKEN(NULL, "MSLCLK", MSL, 2, 13, 0),
131 PXA27X_PBUS_CKEN(NULL, "USIMCLK", USIM, 2, 13, 0),
132 PXA27X_PBUS_CKEN(NULL, "MSTKCLK", MEMSTK, 2, 32, 0),
133 PXA27X_PBUS_CKEN(NULL, "AC97CLK", AC97, 1, 1, 0),
134 PXA27X_PBUS_CKEN(NULL, "AC97CONFCLK", AC97CONF, 1, 1, 0),
135 PXA27X_PBUS_CKEN(NULL, "OSTIMER0", OSTIMER, 1, 96, 0),
136
137 PXA27X_CKEN_1RATE("pxa27x-keypad", NULL, KEYPAD,
138 pxa27x_32Mhz_bus_parents, 0),
139 PXA27X_CKEN_1RATE(NULL, "IMCLK", IM, pxa27x_sbus_parents, 0),
140 PXA27X_CKEN_1RATE("pxa2xx-fb", NULL, LCD, pxa27x_lcd_bus_parents, 0),
141 PXA27X_CKEN_1RATE("pxa27x-camera.0", NULL, CAMERA,
142 pxa27x_lcd_bus_parents, 0),
143 PXA27X_CKEN_1RATE_AO("pxa2xx-pcmcia", NULL, MEMC,
144 pxa27x_membus_parents, 0),
145
146};
147
148static unsigned long clk_pxa27x_cpll_get_rate(struct clk_hw *hw,
149 unsigned long parent_rate)
150{
151 unsigned long clkcfg;
152 unsigned int t, ht;
153 unsigned int l, L, n2, N;
154 unsigned long ccsr = CCSR;
155
156 asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
157 t = clkcfg & (1 << 0);
158 ht = clkcfg & (1 << 2);
159
160 l = ccsr & CCSR_L_MASK;
161 n2 = (ccsr & CCSR_N2_MASK) >> CCSR_N2_SHIFT;
162 L = l * parent_rate;
163 N = (L * n2) / 2;
164
165 return t ? N : L;
166}
167PARENTS(clk_pxa27x_cpll) = { "osc_13mhz" };
168RATE_RO_OPS(clk_pxa27x_cpll, "cpll");
169
170static unsigned long clk_pxa27x_lcd_base_get_rate(struct clk_hw *hw,
171 unsigned long parent_rate)
172{
173 unsigned int l, osc_forced;
174 unsigned long ccsr = CCSR;
175 unsigned long cccr = CCCR;
176
177 l = ccsr & CCSR_L_MASK;
178 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
179 if (osc_forced) {
180 if (cccr & (1 << CCCR_LCD_26_BIT))
181 return parent_rate * 2;
182 else
183 return parent_rate;
184 }
185
186 if (l <= 7)
187 return parent_rate;
188 if (l <= 16)
189 return parent_rate / 2;
190 return parent_rate / 4;
191}
192
193static u8 clk_pxa27x_lcd_base_get_parent(struct clk_hw *hw)
194{
195 unsigned int osc_forced;
196 unsigned long ccsr = CCSR;
197
198 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
199 if (osc_forced)
200 return PXA_LCD_13Mhz;
201 else
202 return PXA_LCD_RUN;
203}
204
205PARENTS(clk_pxa27x_lcd_base) = { "osc_13mhz", "run" };
206MUX_RO_RATE_RO_OPS(clk_pxa27x_lcd_base, "lcd_base");
207
208static void __init pxa27x_register_plls(void)
209{
210 clk_register_fixed_rate(NULL, "osc_13mhz", NULL,
211 CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
212 13 * MHz);
213 clk_register_fixed_rate(NULL, "osc_32_768khz", NULL,
214 CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
215 32768 * KHz);
216 clk_register_fixed_rate(NULL, "clk_dummy", NULL, CLK_IS_ROOT, 0);
217 clk_register_fixed_factor(NULL, "ppll_312mhz", "osc_13mhz", 0, 24, 1);
218}
219
220static unsigned long clk_pxa27x_core_get_rate(struct clk_hw *hw,
221 unsigned long parent_rate)
222{
223 unsigned long clkcfg;
224 unsigned int t, ht, b, osc_forced;
225 unsigned long ccsr = CCSR;
226
227 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
228 asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
229 t = clkcfg & (1 << 0);
230 ht = clkcfg & (1 << 2);
231 b = clkcfg & (1 << 3);
232
233 if (osc_forced)
234 return parent_rate;
235 if (ht)
236 return parent_rate / 2;
237 else
238 return parent_rate;
239}
240
241static u8 clk_pxa27x_core_get_parent(struct clk_hw *hw)
242{
243 unsigned long clkcfg;
244 unsigned int t, ht, b, osc_forced;
245 unsigned long ccsr = CCSR;
246
247 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
248 if (osc_forced)
249 return PXA_CORE_13Mhz;
250
251 asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
252 t = clkcfg & (1 << 0);
253 ht = clkcfg & (1 << 2);
254 b = clkcfg & (1 << 3);
255
256 if (ht || t)
257 return PXA_CORE_TURBO;
258 return PXA_CORE_RUN;
259}
260PARENTS(clk_pxa27x_core) = { "osc_13mhz", "run", "cpll" };
261MUX_RO_RATE_RO_OPS(clk_pxa27x_core, "core");
262
263static unsigned long clk_pxa27x_run_get_rate(struct clk_hw *hw,
264 unsigned long parent_rate)
265{
266 unsigned long ccsr = CCSR;
267 unsigned int n2 = (ccsr & CCSR_N2_MASK) >> CCSR_N2_SHIFT;
268
269 return (parent_rate / n2) * 2;
270}
271PARENTS(clk_pxa27x_run) = { "cpll" };
272RATE_RO_OPS(clk_pxa27x_run, "run");
273
274static void __init pxa27x_register_core(void)
275{
276 clk_register_clk_pxa27x_cpll();
277 clk_register_clk_pxa27x_run();
278
279 clkdev_pxa_register(CLK_CORE, "core", NULL,
280 clk_register_clk_pxa27x_core());
281}
282
283static unsigned long clk_pxa27x_system_bus_get_rate(struct clk_hw *hw,
284 unsigned long parent_rate)
285{
286 unsigned long clkcfg;
287 unsigned int b, osc_forced;
288 unsigned long ccsr = CCSR;
289
290 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
291 asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
292 b = clkcfg & (1 << 3);
293
294 if (osc_forced)
295 return parent_rate;
296 if (b)
297 return parent_rate / 2;
298 else
299 return parent_rate;
300}
301
302static u8 clk_pxa27x_system_bus_get_parent(struct clk_hw *hw)
303{
304 unsigned int osc_forced;
305 unsigned long ccsr = CCSR;
306
307 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
308 if (osc_forced)
309 return PXA_BUS_13Mhz;
310 else
311 return PXA_BUS_RUN;
312}
313
314PARENTS(clk_pxa27x_system_bus) = { "osc_13mhz", "run" };
315MUX_RO_RATE_RO_OPS(clk_pxa27x_system_bus, "system_bus");
316
317static unsigned long clk_pxa27x_memory_get_rate(struct clk_hw *hw,
318 unsigned long parent_rate)
319{
320 unsigned int a, l, osc_forced;
321 unsigned long cccr = CCCR;
322 unsigned long ccsr = CCSR;
323
324 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
325 a = cccr & CCCR_A_BIT;
326 l = ccsr & CCSR_L_MASK;
327
328 if (osc_forced || a)
329 return parent_rate;
330 if (l <= 10)
331 return parent_rate;
332 if (l <= 20)
333 return parent_rate / 2;
334 return parent_rate / 4;
335}
336
337static u8 clk_pxa27x_memory_get_parent(struct clk_hw *hw)
338{
339 unsigned int osc_forced, a;
340 unsigned long cccr = CCCR;
341 unsigned long ccsr = CCSR;
342
343 osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
344 a = cccr & CCCR_A_BIT;
345 if (osc_forced)
346 return PXA_MEM_13Mhz;
347 if (a)
348 return PXA_MEM_SYSTEM_BUS;
349 else
350 return PXA_MEM_RUN;
351}
352
353PARENTS(clk_pxa27x_memory) = { "osc_13mhz", "system_bus", "run" };
354MUX_RO_RATE_RO_OPS(clk_pxa27x_memory, "memory");
355
356static void __init pxa27x_base_clocks_init(void)
357{
358 pxa27x_register_plls();
359 pxa27x_register_core();
360 clk_register_clk_pxa27x_system_bus();
361 clk_register_clk_pxa27x_memory();
362 clk_register_clk_pxa27x_lcd_base();
363}
364
365static int __init pxa27x_clocks_init(void)
366{
367 pxa27x_base_clocks_init();
368 return clk_pxa_cken_init(pxa27x_clocks, ARRAY_SIZE(pxa27x_clocks));
369}
370postcore_initcall(pxa27x_clocks_init);
diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c
index 9db03d3b1657..b823bc3b6250 100644
--- a/drivers/clk/qcom/clk-pll.c
+++ b/drivers/clk/qcom/clk-pll.c
@@ -97,7 +97,7 @@ static unsigned long
97clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) 97clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
98{ 98{
99 struct clk_pll *pll = to_clk_pll(hw); 99 struct clk_pll *pll = to_clk_pll(hw);
100 u32 l, m, n; 100 u32 l, m, n, config;
101 unsigned long rate; 101 unsigned long rate;
102 u64 tmp; 102 u64 tmp;
103 103
@@ -116,13 +116,79 @@ clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
116 do_div(tmp, n); 116 do_div(tmp, n);
117 rate += tmp; 117 rate += tmp;
118 } 118 }
119 if (pll->post_div_width) {
120 regmap_read(pll->clkr.regmap, pll->config_reg, &config);
121 config >>= pll->post_div_shift;
122 config &= BIT(pll->post_div_width) - 1;
123 rate /= config + 1;
124 }
125
119 return rate; 126 return rate;
120} 127}
121 128
129static const
130struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate)
131{
132 if (!f)
133 return NULL;
134
135 for (; f->freq; f++)
136 if (rate <= f->freq)
137 return f;
138
139 return NULL;
140}
141
142static long
143clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate,
144 unsigned long *p_rate, struct clk **p)
145{
146 struct clk_pll *pll = to_clk_pll(hw);
147 const struct pll_freq_tbl *f;
148
149 f = find_freq(pll->freq_tbl, rate);
150 if (!f)
151 return clk_pll_recalc_rate(hw, *p_rate);
152
153 return f->freq;
154}
155
156static int
157clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate)
158{
159 struct clk_pll *pll = to_clk_pll(hw);
160 const struct pll_freq_tbl *f;
161 bool enabled;
162 u32 mode;
163 u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N;
164
165 f = find_freq(pll->freq_tbl, rate);
166 if (!f)
167 return -EINVAL;
168
169 regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
170 enabled = (mode & enable_mask) == enable_mask;
171
172 if (enabled)
173 clk_pll_disable(hw);
174
175 regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l);
176 regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m);
177 regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n);
178 regmap_write(pll->clkr.regmap, pll->config_reg, f->ibits);
179
180 if (enabled)
181 clk_pll_enable(hw);
182
183 return 0;
184}
185
122const struct clk_ops clk_pll_ops = { 186const struct clk_ops clk_pll_ops = {
123 .enable = clk_pll_enable, 187 .enable = clk_pll_enable,
124 .disable = clk_pll_disable, 188 .disable = clk_pll_disable,
125 .recalc_rate = clk_pll_recalc_rate, 189 .recalc_rate = clk_pll_recalc_rate,
190 .determine_rate = clk_pll_determine_rate,
191 .set_rate = clk_pll_set_rate,
126}; 192};
127EXPORT_SYMBOL_GPL(clk_pll_ops); 193EXPORT_SYMBOL_GPL(clk_pll_ops);
128 194
diff --git a/drivers/clk/qcom/clk-pll.h b/drivers/clk/qcom/clk-pll.h
index 3003e9962472..c9c0cda306d0 100644
--- a/drivers/clk/qcom/clk-pll.h
+++ b/drivers/clk/qcom/clk-pll.h
@@ -18,6 +18,21 @@
18#include "clk-regmap.h" 18#include "clk-regmap.h"
19 19
20/** 20/**
21 * struct pll_freq_tbl - PLL frequency table
22 * @l: L value
23 * @m: M value
24 * @n: N value
25 * @ibits: internal values
26 */
27struct pll_freq_tbl {
28 unsigned long freq;
29 u16 l;
30 u16 m;
31 u16 n;
32 u32 ibits;
33};
34
35/**
21 * struct clk_pll - phase locked loop (PLL) 36 * struct clk_pll - phase locked loop (PLL)
22 * @l_reg: L register 37 * @l_reg: L register
23 * @m_reg: M register 38 * @m_reg: M register
@@ -26,6 +41,7 @@
26 * @mode_reg: mode register 41 * @mode_reg: mode register
27 * @status_reg: status register 42 * @status_reg: status register
28 * @status_bit: ANDed with @status_reg to determine if PLL is enabled 43 * @status_bit: ANDed with @status_reg to determine if PLL is enabled
44 * @freq_tbl: PLL frequency table
29 * @hw: handle between common and hardware-specific interfaces 45 * @hw: handle between common and hardware-specific interfaces
30 */ 46 */
31struct clk_pll { 47struct clk_pll {
@@ -36,6 +52,10 @@ struct clk_pll {
36 u32 mode_reg; 52 u32 mode_reg;
37 u32 status_reg; 53 u32 status_reg;
38 u8 status_bit; 54 u8 status_bit;
55 u8 post_div_width;
56 u8 post_div_shift;
57
58 const struct pll_freq_tbl *freq_tbl;
39 59
40 struct clk_regmap clkr; 60 struct clk_regmap clkr;
41}; 61};
diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c
index b638c5846dbf..b6e6959e89aa 100644
--- a/drivers/clk/qcom/clk-rcg.c
+++ b/drivers/clk/qcom/clk-rcg.c
@@ -21,6 +21,7 @@
21#include <asm/div64.h> 21#include <asm/div64.h>
22 22
23#include "clk-rcg.h" 23#include "clk-rcg.h"
24#include "common.h"
24 25
25static u32 ns_to_src(struct src_sel *s, u32 ns) 26static u32 ns_to_src(struct src_sel *s, u32 ns)
26{ 27{
@@ -67,16 +68,16 @@ static u8 clk_dyn_rcg_get_parent(struct clk_hw *hw)
67{ 68{
68 struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); 69 struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
69 int num_parents = __clk_get_num_parents(hw->clk); 70 int num_parents = __clk_get_num_parents(hw->clk);
70 u32 ns, ctl; 71 u32 ns, reg;
71 int bank; 72 int bank;
72 int i; 73 int i;
73 struct src_sel *s; 74 struct src_sel *s;
74 75
75 regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); 76 regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
76 bank = reg_to_bank(rcg, ctl); 77 bank = reg_to_bank(rcg, reg);
77 s = &rcg->s[bank]; 78 s = &rcg->s[bank];
78 79
79 regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 80 regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns);
80 ns = ns_to_src(s, ns); 81 ns = ns_to_src(s, ns);
81 82
82 for (i = 0; i < num_parents; i++) 83 for (i = 0; i < num_parents; i++)
@@ -192,90 +193,93 @@ static u32 mn_to_reg(struct mn *mn, u32 m, u32 n, u32 val)
192 193
193static void configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f) 194static void configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f)
194{ 195{
195 u32 ns, md, ctl, *regp; 196 u32 ns, md, reg;
196 int bank, new_bank; 197 int bank, new_bank;
197 struct mn *mn; 198 struct mn *mn;
198 struct pre_div *p; 199 struct pre_div *p;
199 struct src_sel *s; 200 struct src_sel *s;
200 bool enabled; 201 bool enabled;
201 u32 md_reg; 202 u32 md_reg, ns_reg;
202 u32 bank_reg;
203 bool banked_mn = !!rcg->mn[1].width; 203 bool banked_mn = !!rcg->mn[1].width;
204 bool banked_p = !!rcg->p[1].pre_div_width;
204 struct clk_hw *hw = &rcg->clkr.hw; 205 struct clk_hw *hw = &rcg->clkr.hw;
205 206
206 enabled = __clk_is_enabled(hw->clk); 207 enabled = __clk_is_enabled(hw->clk);
207 208
208 regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 209 regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
209 regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); 210 bank = reg_to_bank(rcg, reg);
210
211 if (banked_mn) {
212 regp = &ctl;
213 bank_reg = rcg->clkr.enable_reg;
214 } else {
215 regp = &ns;
216 bank_reg = rcg->ns_reg;
217 }
218
219 bank = reg_to_bank(rcg, *regp);
220 new_bank = enabled ? !bank : bank; 211 new_bank = enabled ? !bank : bank;
221 212
213 ns_reg = rcg->ns_reg[new_bank];
214 regmap_read(rcg->clkr.regmap, ns_reg, &ns);
215
222 if (banked_mn) { 216 if (banked_mn) {
223 mn = &rcg->mn[new_bank]; 217 mn = &rcg->mn[new_bank];
224 md_reg = rcg->md_reg[new_bank]; 218 md_reg = rcg->md_reg[new_bank];
225 219
226 ns |= BIT(mn->mnctr_reset_bit); 220 ns |= BIT(mn->mnctr_reset_bit);
227 regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); 221 regmap_write(rcg->clkr.regmap, ns_reg, ns);
228 222
229 regmap_read(rcg->clkr.regmap, md_reg, &md); 223 regmap_read(rcg->clkr.regmap, md_reg, &md);
230 md = mn_to_md(mn, f->m, f->n, md); 224 md = mn_to_md(mn, f->m, f->n, md);
231 regmap_write(rcg->clkr.regmap, md_reg, md); 225 regmap_write(rcg->clkr.regmap, md_reg, md);
232 226
233 ns = mn_to_ns(mn, f->m, f->n, ns); 227 ns = mn_to_ns(mn, f->m, f->n, ns);
234 regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); 228 regmap_write(rcg->clkr.regmap, ns_reg, ns);
235 229
236 ctl = mn_to_reg(mn, f->m, f->n, ctl); 230 /* Two NS registers means mode control is in NS register */
237 regmap_write(rcg->clkr.regmap, rcg->clkr.enable_reg, ctl); 231 if (rcg->ns_reg[0] != rcg->ns_reg[1]) {
232 ns = mn_to_reg(mn, f->m, f->n, ns);
233 regmap_write(rcg->clkr.regmap, ns_reg, ns);
234 } else {
235 reg = mn_to_reg(mn, f->m, f->n, reg);
236 regmap_write(rcg->clkr.regmap, rcg->bank_reg, reg);
237 }
238 238
239 ns &= ~BIT(mn->mnctr_reset_bit); 239 ns &= ~BIT(mn->mnctr_reset_bit);
240 regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); 240 regmap_write(rcg->clkr.regmap, ns_reg, ns);
241 } else { 241 }
242
243 if (banked_p) {
242 p = &rcg->p[new_bank]; 244 p = &rcg->p[new_bank];
243 ns = pre_div_to_ns(p, f->pre_div - 1, ns); 245 ns = pre_div_to_ns(p, f->pre_div - 1, ns);
244 } 246 }
245 247
246 s = &rcg->s[new_bank]; 248 s = &rcg->s[new_bank];
247 ns = src_to_ns(s, s->parent_map[f->src], ns); 249 ns = src_to_ns(s, s->parent_map[f->src], ns);
248 regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); 250 regmap_write(rcg->clkr.regmap, ns_reg, ns);
249 251
250 if (enabled) { 252 if (enabled) {
251 *regp ^= BIT(rcg->mux_sel_bit); 253 regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
252 regmap_write(rcg->clkr.regmap, bank_reg, *regp); 254 reg ^= BIT(rcg->mux_sel_bit);
255 regmap_write(rcg->clkr.regmap, rcg->bank_reg, reg);
253 } 256 }
254} 257}
255 258
256static int clk_dyn_rcg_set_parent(struct clk_hw *hw, u8 index) 259static int clk_dyn_rcg_set_parent(struct clk_hw *hw, u8 index)
257{ 260{
258 struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); 261 struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
259 u32 ns, ctl, md, reg; 262 u32 ns, md, reg;
260 int bank; 263 int bank;
261 struct freq_tbl f = { 0 }; 264 struct freq_tbl f = { 0 };
262 bool banked_mn = !!rcg->mn[1].width; 265 bool banked_mn = !!rcg->mn[1].width;
266 bool banked_p = !!rcg->p[1].pre_div_width;
263 267
264 regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 268 regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
265 regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl);
266 reg = banked_mn ? ctl : ns;
267
268 bank = reg_to_bank(rcg, reg); 269 bank = reg_to_bank(rcg, reg);
269 270
271 regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns);
272
270 if (banked_mn) { 273 if (banked_mn) {
271 regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md); 274 regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md);
272 f.m = md_to_m(&rcg->mn[bank], md); 275 f.m = md_to_m(&rcg->mn[bank], md);
273 f.n = ns_m_to_n(&rcg->mn[bank], ns, f.m); 276 f.n = ns_m_to_n(&rcg->mn[bank], ns, f.m);
274 } else {
275 f.pre_div = ns_to_pre_div(&rcg->p[bank], ns) + 1;
276 } 277 }
277 f.src = index;
278 278
279 if (banked_p)
280 f.pre_div = ns_to_pre_div(&rcg->p[bank], ns) + 1;
281
282 f.src = index;
279 configure_bank(rcg, &f); 283 configure_bank(rcg, &f);
280 284
281 return 0; 285 return 0;
@@ -336,41 +340,30 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
336 u32 m, n, pre_div, ns, md, mode, reg; 340 u32 m, n, pre_div, ns, md, mode, reg;
337 int bank; 341 int bank;
338 struct mn *mn; 342 struct mn *mn;
343 bool banked_p = !!rcg->p[1].pre_div_width;
339 bool banked_mn = !!rcg->mn[1].width; 344 bool banked_mn = !!rcg->mn[1].width;
340 345
341 regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 346 regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
342
343 if (banked_mn)
344 regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &reg);
345 else
346 reg = ns;
347
348 bank = reg_to_bank(rcg, reg); 347 bank = reg_to_bank(rcg, reg);
349 348
349 regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns);
350 m = n = pre_div = mode = 0;
351
350 if (banked_mn) { 352 if (banked_mn) {
351 mn = &rcg->mn[bank]; 353 mn = &rcg->mn[bank];
352 regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md); 354 regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md);
353 m = md_to_m(mn, md); 355 m = md_to_m(mn, md);
354 n = ns_m_to_n(mn, ns, m); 356 n = ns_m_to_n(mn, ns, m);
357 /* Two NS registers means mode control is in NS register */
358 if (rcg->ns_reg[0] != rcg->ns_reg[1])
359 reg = ns;
355 mode = reg_to_mnctr_mode(mn, reg); 360 mode = reg_to_mnctr_mode(mn, reg);
356 return calc_rate(parent_rate, m, n, mode, 0);
357 } else {
358 pre_div = ns_to_pre_div(&rcg->p[bank], ns);
359 return calc_rate(parent_rate, 0, 0, 0, pre_div);
360 } 361 }
361}
362 362
363static const 363 if (banked_p)
364struct freq_tbl *find_freq(const struct freq_tbl *f, unsigned long rate) 364 pre_div = ns_to_pre_div(&rcg->p[bank], ns);
365{
366 if (!f)
367 return NULL;
368
369 for (; f->freq; f++)
370 if (rate <= f->freq)
371 return f;
372 365
373 return NULL; 366 return calc_rate(parent_rate, m, n, mode, pre_div);
374} 367}
375 368
376static long _freq_tbl_determine_rate(struct clk_hw *hw, 369static long _freq_tbl_determine_rate(struct clk_hw *hw,
@@ -379,7 +372,7 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
379{ 372{
380 unsigned long clk_flags; 373 unsigned long clk_flags;
381 374
382 f = find_freq(f, rate); 375 f = qcom_find_freq(f, rate);
383 if (!f) 376 if (!f)
384 return -EINVAL; 377 return -EINVAL;
385 378
@@ -477,7 +470,7 @@ static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
477 struct clk_rcg *rcg = to_clk_rcg(hw); 470 struct clk_rcg *rcg = to_clk_rcg(hw);
478 const struct freq_tbl *f; 471 const struct freq_tbl *f;
479 472
480 f = find_freq(rcg->freq_tbl, rate); 473 f = qcom_find_freq(rcg->freq_tbl, rate);
481 if (!f) 474 if (!f)
482 return -EINVAL; 475 return -EINVAL;
483 476
@@ -497,7 +490,7 @@ static int __clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate)
497 struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); 490 struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
498 const struct freq_tbl *f; 491 const struct freq_tbl *f;
499 492
500 f = find_freq(rcg->freq_tbl, rate); 493 f = qcom_find_freq(rcg->freq_tbl, rate);
501 if (!f) 494 if (!f)
502 return -EINVAL; 495 return -EINVAL;
503 496
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index ba0523cefd2e..687e41f91d7c 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -103,8 +103,9 @@ extern const struct clk_ops clk_rcg_bypass_ops;
103 * struct clk_dyn_rcg - root clock generator with glitch free mux 103 * struct clk_dyn_rcg - root clock generator with glitch free mux
104 * 104 *
105 * @mux_sel_bit: bit to switch glitch free mux 105 * @mux_sel_bit: bit to switch glitch free mux
106 * @ns_reg: NS register 106 * @ns_reg: NS0 and NS1 register
107 * @md_reg: MD0 and MD1 register 107 * @md_reg: MD0 and MD1 register
108 * @bank_reg: register to XOR @mux_sel_bit into to switch glitch free mux
108 * @mn: mn counter (banked) 109 * @mn: mn counter (banked)
109 * @s: source selector (banked) 110 * @s: source selector (banked)
110 * @freq_tbl: frequency table 111 * @freq_tbl: frequency table
@@ -113,8 +114,9 @@ extern const struct clk_ops clk_rcg_bypass_ops;
113 * 114 *
114 */ 115 */
115struct clk_dyn_rcg { 116struct clk_dyn_rcg {
116 u32 ns_reg; 117 u32 ns_reg[2];
117 u32 md_reg[2]; 118 u32 md_reg[2];
119 u32 bank_reg;
118 120
119 u8 mux_sel_bit; 121 u8 mux_sel_bit;
120 122
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index cd185d5cc67a..cfa9eb4fe9ca 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -24,6 +24,7 @@
24#include <asm/div64.h> 24#include <asm/div64.h>
25 25
26#include "clk-rcg.h" 26#include "clk-rcg.h"
27#include "common.h"
27 28
28#define CMD_REG 0x0 29#define CMD_REG 0x0
29#define CMD_UPDATE BIT(0) 30#define CMD_UPDATE BIT(0)
@@ -172,27 +173,13 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
172 return calc_rate(parent_rate, m, n, mode, hid_div); 173 return calc_rate(parent_rate, m, n, mode, hid_div);
173} 174}
174 175
175static const
176struct freq_tbl *find_freq(const struct freq_tbl *f, unsigned long rate)
177{
178 if (!f)
179 return NULL;
180
181 for (; f->freq; f++)
182 if (rate <= f->freq)
183 return f;
184
185 /* Default to our fastest rate */
186 return f - 1;
187}
188
189static long _freq_tbl_determine_rate(struct clk_hw *hw, 176static long _freq_tbl_determine_rate(struct clk_hw *hw,
190 const struct freq_tbl *f, unsigned long rate, 177 const struct freq_tbl *f, unsigned long rate,
191 unsigned long *p_rate, struct clk **p) 178 unsigned long *p_rate, struct clk **p)
192{ 179{
193 unsigned long clk_flags; 180 unsigned long clk_flags;
194 181
195 f = find_freq(f, rate); 182 f = qcom_find_freq(f, rate);
196 if (!f) 183 if (!f)
197 return -EINVAL; 184 return -EINVAL;
198 185
@@ -268,7 +255,7 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
268 struct clk_rcg2 *rcg = to_clk_rcg2(hw); 255 struct clk_rcg2 *rcg = to_clk_rcg2(hw);
269 const struct freq_tbl *f; 256 const struct freq_tbl *f;
270 257
271 f = find_freq(rcg->freq_tbl, rate); 258 f = qcom_find_freq(rcg->freq_tbl, rate);
272 if (!f) 259 if (!f)
273 return -EINVAL; 260 return -EINVAL;
274 261
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index eeb3eea01f4c..e20d947db3e5 100644
--- a/drivers/clk/qcom/common.c
+++ b/drivers/clk/qcom/common.c
@@ -18,6 +18,7 @@
18#include <linux/reset-controller.h> 18#include <linux/reset-controller.h>
19 19
20#include "common.h" 20#include "common.h"
21#include "clk-rcg.h"
21#include "clk-regmap.h" 22#include "clk-regmap.h"
22#include "reset.h" 23#include "reset.h"
23 24
@@ -27,6 +28,21 @@ struct qcom_cc {
27 struct clk *clks[]; 28 struct clk *clks[];
28}; 29};
29 30
31const
32struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate)
33{
34 if (!f)
35 return NULL;
36
37 for (; f->freq; f++)
38 if (rate <= f->freq)
39 return f;
40
41 /* Default to our fastest rate */
42 return f - 1;
43}
44EXPORT_SYMBOL_GPL(qcom_find_freq);
45
30struct regmap * 46struct regmap *
31qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc) 47qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc)
32{ 48{
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index 2765e9d3da97..f519322acdf3 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -18,6 +18,7 @@ struct regmap_config;
18struct clk_regmap; 18struct clk_regmap;
19struct qcom_reset_map; 19struct qcom_reset_map;
20struct regmap; 20struct regmap;
21struct freq_tbl;
21 22
22struct qcom_cc_desc { 23struct qcom_cc_desc {
23 const struct regmap_config *config; 24 const struct regmap_config *config;
@@ -27,6 +28,9 @@ struct qcom_cc_desc {
27 size_t num_resets; 28 size_t num_resets;
28}; 29};
29 30
31extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
32 unsigned long rate);
33
30extern struct regmap *qcom_cc_map(struct platform_device *pdev, 34extern struct regmap *qcom_cc_map(struct platform_device *pdev,
31 const struct qcom_cc_desc *desc); 35 const struct qcom_cc_desc *desc);
32extern int qcom_cc_really_probe(struct platform_device *pdev, 36extern int qcom_cc_really_probe(struct platform_device *pdev,
diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c
index 4032e510d9aa..5cd62a709ac7 100644
--- a/drivers/clk/qcom/gcc-ipq806x.c
+++ b/drivers/clk/qcom/gcc-ipq806x.c
@@ -32,6 +32,33 @@
32#include "clk-branch.h" 32#include "clk-branch.h"
33#include "reset.h" 33#include "reset.h"
34 34
35static struct clk_pll pll0 = {
36 .l_reg = 0x30c4,
37 .m_reg = 0x30c8,
38 .n_reg = 0x30cc,
39 .config_reg = 0x30d4,
40 .mode_reg = 0x30c0,
41 .status_reg = 0x30d8,
42 .status_bit = 16,
43 .clkr.hw.init = &(struct clk_init_data){
44 .name = "pll0",
45 .parent_names = (const char *[]){ "pxo" },
46 .num_parents = 1,
47 .ops = &clk_pll_ops,
48 },
49};
50
51static struct clk_regmap pll0_vote = {
52 .enable_reg = 0x34c0,
53 .enable_mask = BIT(0),
54 .hw.init = &(struct clk_init_data){
55 .name = "pll0_vote",
56 .parent_names = (const char *[]){ "pll0" },
57 .num_parents = 1,
58 .ops = &clk_pll_vote_ops,
59 },
60};
61
35static struct clk_pll pll3 = { 62static struct clk_pll pll3 = {
36 .l_reg = 0x3164, 63 .l_reg = 0x3164,
37 .m_reg = 0x3168, 64 .m_reg = 0x3168,
@@ -154,7 +181,7 @@ static const u8 gcc_pxo_pll8_pll0[] = {
154static const char *gcc_pxo_pll8_pll0_map[] = { 181static const char *gcc_pxo_pll8_pll0_map[] = {
155 "pxo", 182 "pxo",
156 "pll8_vote", 183 "pll8_vote",
157 "pll0", 184 "pll0_vote",
158}; 185};
159 186
160static struct freq_tbl clk_tbl_gsbi_uart[] = { 187static struct freq_tbl clk_tbl_gsbi_uart[] = {
@@ -1095,7 +1122,7 @@ static struct clk_branch prng_clk = {
1095}; 1122};
1096 1123
1097static const struct freq_tbl clk_tbl_sdc[] = { 1124static const struct freq_tbl clk_tbl_sdc[] = {
1098 { 144000, P_PXO, 5, 18,625 }, 1125 { 200000, P_PXO, 2, 2, 125 },
1099 { 400000, P_PLL8, 4, 1, 240 }, 1126 { 400000, P_PLL8, 4, 1, 240 },
1100 { 16000000, P_PLL8, 4, 1, 6 }, 1127 { 16000000, P_PLL8, 4, 1, 6 },
1101 { 17070000, P_PLL8, 1, 2, 45 }, 1128 { 17070000, P_PLL8, 1, 2, 45 },
@@ -2133,6 +2160,8 @@ static struct clk_branch usb_fs1_h_clk = {
2133}; 2160};
2134 2161
2135static struct clk_regmap *gcc_ipq806x_clks[] = { 2162static struct clk_regmap *gcc_ipq806x_clks[] = {
2163 [PLL0] = &pll0.clkr,
2164 [PLL0_VOTE] = &pll0_vote,
2136 [PLL3] = &pll3.clkr, 2165 [PLL3] = &pll3.clkr,
2137 [PLL8] = &pll8.clkr, 2166 [PLL8] = &pll8.clkr,
2138 [PLL8_VOTE] = &pll8_vote, 2167 [PLL8_VOTE] = &pll8_vote,
diff --git a/drivers/clk/qcom/mmcc-apq8084.c b/drivers/clk/qcom/mmcc-apq8084.c
index 751eea376a2b..dab988ab8cf1 100644
--- a/drivers/clk/qcom/mmcc-apq8084.c
+++ b/drivers/clk/qcom/mmcc-apq8084.c
@@ -3341,7 +3341,6 @@ static struct platform_driver mmcc_apq8084_driver = {
3341 .remove = mmcc_apq8084_remove, 3341 .remove = mmcc_apq8084_remove,
3342 .driver = { 3342 .driver = {
3343 .name = "mmcc-apq8084", 3343 .name = "mmcc-apq8084",
3344 .owner = THIS_MODULE,
3345 .of_match_table = mmcc_apq8084_match_table, 3344 .of_match_table = mmcc_apq8084_match_table,
3346 }, 3345 },
3347}; 3346};
diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c
index 2e80a219b8ea..e8b33bbc362f 100644
--- a/drivers/clk/qcom/mmcc-msm8960.c
+++ b/drivers/clk/qcom/mmcc-msm8960.c
@@ -773,9 +773,11 @@ static struct freq_tbl clk_tbl_gfx2d[] = {
773}; 773};
774 774
775static struct clk_dyn_rcg gfx2d0_src = { 775static struct clk_dyn_rcg gfx2d0_src = {
776 .ns_reg = 0x0070, 776 .ns_reg[0] = 0x0070,
777 .ns_reg[1] = 0x0070,
777 .md_reg[0] = 0x0064, 778 .md_reg[0] = 0x0064,
778 .md_reg[1] = 0x0068, 779 .md_reg[1] = 0x0068,
780 .bank_reg = 0x0060,
779 .mn[0] = { 781 .mn[0] = {
780 .mnctr_en_bit = 8, 782 .mnctr_en_bit = 8,
781 .mnctr_reset_bit = 25, 783 .mnctr_reset_bit = 25,
@@ -831,9 +833,11 @@ static struct clk_branch gfx2d0_clk = {
831}; 833};
832 834
833static struct clk_dyn_rcg gfx2d1_src = { 835static struct clk_dyn_rcg gfx2d1_src = {
834 .ns_reg = 0x007c, 836 .ns_reg[0] = 0x007c,
837 .ns_reg[1] = 0x007c,
835 .md_reg[0] = 0x0078, 838 .md_reg[0] = 0x0078,
836 .md_reg[1] = 0x006c, 839 .md_reg[1] = 0x006c,
840 .bank_reg = 0x0074,
837 .mn[0] = { 841 .mn[0] = {
838 .mnctr_en_bit = 8, 842 .mnctr_en_bit = 8,
839 .mnctr_reset_bit = 25, 843 .mnctr_reset_bit = 25,
@@ -930,9 +934,11 @@ static struct freq_tbl clk_tbl_gfx3d_8064[] = {
930}; 934};
931 935
932static struct clk_dyn_rcg gfx3d_src = { 936static struct clk_dyn_rcg gfx3d_src = {
933 .ns_reg = 0x008c, 937 .ns_reg[0] = 0x008c,
938 .ns_reg[1] = 0x008c,
934 .md_reg[0] = 0x0084, 939 .md_reg[0] = 0x0084,
935 .md_reg[1] = 0x0088, 940 .md_reg[1] = 0x0088,
941 .bank_reg = 0x0080,
936 .mn[0] = { 942 .mn[0] = {
937 .mnctr_en_bit = 8, 943 .mnctr_en_bit = 8,
938 .mnctr_reset_bit = 25, 944 .mnctr_reset_bit = 25,
@@ -1006,9 +1012,11 @@ static struct freq_tbl clk_tbl_vcap[] = {
1006}; 1012};
1007 1013
1008static struct clk_dyn_rcg vcap_src = { 1014static struct clk_dyn_rcg vcap_src = {
1009 .ns_reg = 0x021c, 1015 .ns_reg[0] = 0x021c,
1016 .ns_reg[1] = 0x021c,
1010 .md_reg[0] = 0x01ec, 1017 .md_reg[0] = 0x01ec,
1011 .md_reg[1] = 0x0218, 1018 .md_reg[1] = 0x0218,
1019 .bank_reg = 0x0178,
1012 .mn[0] = { 1020 .mn[0] = {
1013 .mnctr_en_bit = 8, 1021 .mnctr_en_bit = 8,
1014 .mnctr_reset_bit = 23, 1022 .mnctr_reset_bit = 23,
@@ -1211,9 +1219,11 @@ static struct freq_tbl clk_tbl_mdp[] = {
1211}; 1219};
1212 1220
1213static struct clk_dyn_rcg mdp_src = { 1221static struct clk_dyn_rcg mdp_src = {
1214 .ns_reg = 0x00d0, 1222 .ns_reg[0] = 0x00d0,
1223 .ns_reg[1] = 0x00d0,
1215 .md_reg[0] = 0x00c4, 1224 .md_reg[0] = 0x00c4,
1216 .md_reg[1] = 0x00c8, 1225 .md_reg[1] = 0x00c8,
1226 .bank_reg = 0x00c0,
1217 .mn[0] = { 1227 .mn[0] = {
1218 .mnctr_en_bit = 8, 1228 .mnctr_en_bit = 8,
1219 .mnctr_reset_bit = 31, 1229 .mnctr_reset_bit = 31,
@@ -1318,7 +1328,9 @@ static struct freq_tbl clk_tbl_rot[] = {
1318}; 1328};
1319 1329
1320static struct clk_dyn_rcg rot_src = { 1330static struct clk_dyn_rcg rot_src = {
1321 .ns_reg = 0x00e8, 1331 .ns_reg[0] = 0x00e8,
1332 .ns_reg[1] = 0x00e8,
1333 .bank_reg = 0x00e8,
1322 .p[0] = { 1334 .p[0] = {
1323 .pre_div_shift = 22, 1335 .pre_div_shift = 22,
1324 .pre_div_width = 4, 1336 .pre_div_width = 4,
@@ -1542,9 +1554,11 @@ static struct freq_tbl clk_tbl_vcodec[] = {
1542}; 1554};
1543 1555
1544static struct clk_dyn_rcg vcodec_src = { 1556static struct clk_dyn_rcg vcodec_src = {
1545 .ns_reg = 0x0100, 1557 .ns_reg[0] = 0x0100,
1558 .ns_reg[1] = 0x0100,
1546 .md_reg[0] = 0x00fc, 1559 .md_reg[0] = 0x00fc,
1547 .md_reg[1] = 0x0128, 1560 .md_reg[1] = 0x0128,
1561 .bank_reg = 0x00f8,
1548 .mn[0] = { 1562 .mn[0] = {
1549 .mnctr_en_bit = 5, 1563 .mnctr_en_bit = 5,
1550 .mnctr_reset_bit = 31, 1564 .mnctr_reset_bit = 31,
@@ -2679,7 +2693,6 @@ static struct platform_driver mmcc_msm8960_driver = {
2679 .remove = mmcc_msm8960_remove, 2693 .remove = mmcc_msm8960_remove,
2680 .driver = { 2694 .driver = {
2681 .name = "mmcc-msm8960", 2695 .name = "mmcc-msm8960",
2682 .owner = THIS_MODULE,
2683 .of_match_table = mmcc_msm8960_match_table, 2696 .of_match_table = mmcc_msm8960_match_table,
2684 }, 2697 },
2685}; 2698};
diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c
index bc8f519c47aa..be94c54a9a4f 100644
--- a/drivers/clk/qcom/mmcc-msm8974.c
+++ b/drivers/clk/qcom/mmcc-msm8974.c
@@ -2570,7 +2570,6 @@ static struct platform_driver mmcc_msm8974_driver = {
2570 .remove = mmcc_msm8974_remove, 2570 .remove = mmcc_msm8974_remove,
2571 .driver = { 2571 .driver = {
2572 .name = "mmcc-msm8974", 2572 .name = "mmcc-msm8974",
2573 .owner = THIS_MODULE,
2574 .of_match_table = mmcc_msm8974_match_table, 2573 .of_match_table = mmcc_msm8974_match_table,
2575 }, 2574 },
2576}; 2575};
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index ee6b077381e1..bd8514d63634 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -5,6 +5,7 @@
5obj-y += clk-rockchip.o 5obj-y += clk-rockchip.o
6obj-y += clk.o 6obj-y += clk.o
7obj-y += clk-pll.o 7obj-y += clk-pll.o
8obj-y += clk-cpu.o
8obj-$(CONFIG_RESET_CONTROLLER) += softrst.o 9obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
9 10
10obj-y += clk-rk3188.o 11obj-y += clk-rk3188.o
diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c
new file mode 100644
index 000000000000..75c8c45ef728
--- /dev/null
+++ b/drivers/clk/rockchip/clk-cpu.c
@@ -0,0 +1,329 @@
1/*
2 * Copyright (c) 2014 MundoReader S.L.
3 * Author: Heiko Stuebner <heiko@sntech.de>
4 *
5 * based on clk/samsung/clk-cpu.c
6 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
7 * Author: Thomas Abraham <thomas.ab@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * A CPU clock is defined as a clock supplied to a CPU or a group of CPUs.
14 * The CPU clock is typically derived from a hierarchy of clock
15 * blocks which includes mux and divider blocks. There are a number of other
16 * auxiliary clocks supplied to the CPU domain such as the debug blocks and AXI
17 * clock for CPU domain. The rates of these auxiliary clocks are related to the
18 * CPU clock rate and this relation is usually specified in the hardware manual
19 * of the SoC or supplied after the SoC characterization.
20 *
21 * The below implementation of the CPU clock allows the rate changes of the CPU
22 * clock and the corresponding rate changes of the auxillary clocks of the CPU
23 * domain. The platform clock driver provides a clock register configuration
24 * for each configurable rate which is then used to program the clock hardware
25 * registers to acheive a fast co-oridinated rate change for all the CPU domain
26 * clocks.
27 *
28 * On a rate change request for the CPU clock, the rate change is propagated
29 * upto the PLL supplying the clock to the CPU domain clock blocks. While the
30 * CPU domain PLL is reconfigured, the CPU domain clocks are driven using an
31 * alternate clock source. If required, the alternate clock source is divided
32 * down in order to keep the output clock rate within the previous OPP limits.
33 */
34
35#include <linux/of.h>
36#include <linux/slab.h>
37#include <linux/io.h>
38#include <linux/clk-provider.h>
39#include "clk.h"
40
41/**
42 * struct rockchip_cpuclk: information about clock supplied to a CPU core.
43 * @hw: handle between ccf and cpu clock.
44 * @alt_parent: alternate parent clock to use when switching the speed
45 * of the primary parent clock.
46 * @reg_base: base register for cpu-clock values.
47 * @clk_nb: clock notifier registered for changes in clock speed of the
48 * primary parent clock.
49 * @rate_count: number of rates in the rate_table
50 * @rate_table: pll-rates and their associated dividers
51 * @reg_data: cpu-specific register settings
52 * @lock: clock lock
53 */
54struct rockchip_cpuclk {
55 struct clk_hw hw;
56
57 struct clk_mux cpu_mux;
58 const struct clk_ops *cpu_mux_ops;
59
60 struct clk *alt_parent;
61 void __iomem *reg_base;
62 struct notifier_block clk_nb;
63 unsigned int rate_count;
64 struct rockchip_cpuclk_rate_table *rate_table;
65 const struct rockchip_cpuclk_reg_data *reg_data;
66 spinlock_t *lock;
67};
68
69#define to_rockchip_cpuclk_hw(hw) container_of(hw, struct rockchip_cpuclk, hw)
70#define to_rockchip_cpuclk_nb(nb) \
71 container_of(nb, struct rockchip_cpuclk, clk_nb)
72
73static const struct rockchip_cpuclk_rate_table *rockchip_get_cpuclk_settings(
74 struct rockchip_cpuclk *cpuclk, unsigned long rate)
75{
76 const struct rockchip_cpuclk_rate_table *rate_table =
77 cpuclk->rate_table;
78 int i;
79
80 for (i = 0; i < cpuclk->rate_count; i++) {
81 if (rate == rate_table[i].prate)
82 return &rate_table[i];
83 }
84
85 return NULL;
86}
87
88static unsigned long rockchip_cpuclk_recalc_rate(struct clk_hw *hw,
89 unsigned long parent_rate)
90{
91 struct rockchip_cpuclk *cpuclk = to_rockchip_cpuclk_hw(hw);
92 const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
93 u32 clksel0 = readl_relaxed(cpuclk->reg_base + reg_data->core_reg);
94
95 clksel0 >>= reg_data->div_core_shift;
96 clksel0 &= reg_data->div_core_mask;
97 return parent_rate / (clksel0 + 1);
98}
99
100static const struct clk_ops rockchip_cpuclk_ops = {
101 .recalc_rate = rockchip_cpuclk_recalc_rate,
102};
103
104static void rockchip_cpuclk_set_dividers(struct rockchip_cpuclk *cpuclk,
105 const struct rockchip_cpuclk_rate_table *rate)
106{
107 int i;
108
109 /* alternate parent is active now. set the dividers */
110 for (i = 0; i < ARRAY_SIZE(rate->divs); i++) {
111 const struct rockchip_cpuclk_clksel *clksel = &rate->divs[i];
112
113 if (!clksel->reg)
114 continue;
115
116 pr_debug("%s: setting reg 0x%x to 0x%x\n",
117 __func__, clksel->reg, clksel->val);
118 writel(clksel->val , cpuclk->reg_base + clksel->reg);
119 }
120}
121
122static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
123 struct clk_notifier_data *ndata)
124{
125 const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
126 unsigned long alt_prate, alt_div;
127
128 alt_prate = clk_get_rate(cpuclk->alt_parent);
129
130 spin_lock(cpuclk->lock);
131
132 /*
133 * If the old parent clock speed is less than the clock speed
134 * of the alternate parent, then it should be ensured that at no point
135 * the armclk speed is more than the old_rate until the dividers are
136 * set.
137 */
138 if (alt_prate > ndata->old_rate) {
139 /* calculate dividers */
140 alt_div = DIV_ROUND_UP(alt_prate, ndata->old_rate) - 1;
141 if (alt_div > reg_data->div_core_mask) {
142 pr_warn("%s: limiting alt-divider %lu to %d\n",
143 __func__, alt_div, reg_data->div_core_mask);
144 alt_div = reg_data->div_core_mask;
145 }
146
147 /*
148 * Change parents and add dividers in a single transaction.
149 *
150 * NOTE: we do this in a single transaction so we're never
151 * dividing the primary parent by the extra dividers that were
152 * needed for the alt.
153 */
154 pr_debug("%s: setting div %lu as alt-rate %lu > old-rate %lu\n",
155 __func__, alt_div, alt_prate, ndata->old_rate);
156
157 writel(HIWORD_UPDATE(alt_div, reg_data->div_core_mask,
158 reg_data->div_core_shift) |
159 HIWORD_UPDATE(1, 1, reg_data->mux_core_shift),
160 cpuclk->reg_base + reg_data->core_reg);
161 } else {
162 /* select alternate parent */
163 writel(HIWORD_UPDATE(1, 1, reg_data->mux_core_shift),
164 cpuclk->reg_base + reg_data->core_reg);
165 }
166
167 spin_unlock(cpuclk->lock);
168 return 0;
169}
170
171static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk,
172 struct clk_notifier_data *ndata)
173{
174 const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
175 const struct rockchip_cpuclk_rate_table *rate;
176
177 rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate);
178 if (!rate) {
179 pr_err("%s: Invalid rate : %lu for cpuclk\n",
180 __func__, ndata->new_rate);
181 return -EINVAL;
182 }
183
184 spin_lock(cpuclk->lock);
185
186 if (ndata->old_rate < ndata->new_rate)
187 rockchip_cpuclk_set_dividers(cpuclk, rate);
188
189 /*
190 * post-rate change event, re-mux to primary parent and remove dividers.
191 *
192 * NOTE: we do this in a single transaction so we're never dividing the
193 * primary parent by the extra dividers that were needed for the alt.
194 */
195
196 writel(HIWORD_UPDATE(0, reg_data->div_core_mask,
197 reg_data->div_core_shift) |
198 HIWORD_UPDATE(0, 1, reg_data->mux_core_shift),
199 cpuclk->reg_base + reg_data->core_reg);
200
201 if (ndata->old_rate > ndata->new_rate)
202 rockchip_cpuclk_set_dividers(cpuclk, rate);
203
204 spin_unlock(cpuclk->lock);
205 return 0;
206}
207
208/*
209 * This clock notifier is called when the frequency of the parent clock
210 * of cpuclk is to be changed. This notifier handles the setting up all
211 * the divider clocks, remux to temporary parent and handling the safe
212 * frequency levels when using temporary parent.
213 */
214static int rockchip_cpuclk_notifier_cb(struct notifier_block *nb,
215 unsigned long event, void *data)
216{
217 struct clk_notifier_data *ndata = data;
218 struct rockchip_cpuclk *cpuclk = to_rockchip_cpuclk_nb(nb);
219 int ret = 0;
220
221 pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n",
222 __func__, event, ndata->old_rate, ndata->new_rate);
223 if (event == PRE_RATE_CHANGE)
224 ret = rockchip_cpuclk_pre_rate_change(cpuclk, ndata);
225 else if (event == POST_RATE_CHANGE)
226 ret = rockchip_cpuclk_post_rate_change(cpuclk, ndata);
227
228 return notifier_from_errno(ret);
229}
230
231struct clk *rockchip_clk_register_cpuclk(const char *name,
232 const char **parent_names, u8 num_parents,
233 const struct rockchip_cpuclk_reg_data *reg_data,
234 const struct rockchip_cpuclk_rate_table *rates,
235 int nrates, void __iomem *reg_base, spinlock_t *lock)
236{
237 struct rockchip_cpuclk *cpuclk;
238 struct clk_init_data init;
239 struct clk *clk, *cclk;
240 int ret;
241
242 if (num_parents != 2) {
243 pr_err("%s: needs two parent clocks\n", __func__);
244 return ERR_PTR(-EINVAL);
245 }
246
247 cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
248 if (!cpuclk)
249 return ERR_PTR(-ENOMEM);
250
251 init.name = name;
252 init.parent_names = &parent_names[0];
253 init.num_parents = 1;
254 init.ops = &rockchip_cpuclk_ops;
255
256 /* only allow rate changes when we have a rate table */
257 init.flags = (nrates > 0) ? CLK_SET_RATE_PARENT : 0;
258
259 /* disallow automatic parent changes by ccf */
260 init.flags |= CLK_SET_RATE_NO_REPARENT;
261
262 init.flags |= CLK_GET_RATE_NOCACHE;
263
264 cpuclk->reg_base = reg_base;
265 cpuclk->lock = lock;
266 cpuclk->reg_data = reg_data;
267 cpuclk->clk_nb.notifier_call = rockchip_cpuclk_notifier_cb;
268 cpuclk->hw.init = &init;
269
270 cpuclk->alt_parent = __clk_lookup(parent_names[1]);
271 if (!cpuclk->alt_parent) {
272 pr_err("%s: could not lookup alternate parent\n",
273 __func__);
274 ret = -EINVAL;
275 goto free_cpuclk;
276 }
277
278 ret = clk_prepare_enable(cpuclk->alt_parent);
279 if (ret) {
280 pr_err("%s: could not enable alternate parent\n",
281 __func__);
282 goto free_cpuclk;
283 }
284
285 clk = __clk_lookup(parent_names[0]);
286 if (!clk) {
287 pr_err("%s: could not lookup parent clock %s\n",
288 __func__, parent_names[0]);
289 ret = -EINVAL;
290 goto free_cpuclk;
291 }
292
293 ret = clk_notifier_register(clk, &cpuclk->clk_nb);
294 if (ret) {
295 pr_err("%s: failed to register clock notifier for %s\n",
296 __func__, name);
297 goto free_cpuclk;
298 }
299
300 if (nrates > 0) {
301 cpuclk->rate_count = nrates;
302 cpuclk->rate_table = kmemdup(rates,
303 sizeof(*rates) * nrates,
304 GFP_KERNEL);
305 if (!cpuclk->rate_table) {
306 pr_err("%s: could not allocate memory for cpuclk rates\n",
307 __func__);
308 ret = -ENOMEM;
309 goto unregister_notifier;
310 }
311 }
312
313 cclk = clk_register(NULL, &cpuclk->hw);
314 if (IS_ERR(clk)) {
315 pr_err("%s: could not register cpuclk %s\n", __func__, name);
316 ret = PTR_ERR(clk);
317 goto free_rate_table;
318 }
319
320 return cclk;
321
322free_rate_table:
323 kfree(cpuclk->rate_table);
324unregister_notifier:
325 clk_notifier_unregister(clk, &cpuclk->clk_nb);
326free_cpuclk:
327 kfree(cpuclk);
328 return ERR_PTR(ret);
329}
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index f2a1c7abf4d9..a3e886a38480 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -34,7 +34,6 @@ struct rockchip_clk_pll {
34 const struct clk_ops *pll_mux_ops; 34 const struct clk_ops *pll_mux_ops;
35 35
36 struct notifier_block clk_nb; 36 struct notifier_block clk_nb;
37 bool rate_change_remuxed;
38 37
39 void __iomem *reg_base; 38 void __iomem *reg_base;
40 int lock_offset; 39 int lock_offset;
@@ -109,38 +108,6 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
109} 108}
110 109
111/** 110/**
112 * Set pll mux when changing the pll rate.
113 * This makes sure to move the pll mux away from the actual pll before
114 * changing its rate and back to the original parent after the change.
115 */
116static int rockchip_pll_notifier_cb(struct notifier_block *nb,
117 unsigned long event, void *data)
118{
119 struct rockchip_clk_pll *pll = to_rockchip_clk_pll_nb(nb);
120 struct clk_mux *pll_mux = &pll->pll_mux;
121 const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
122 int cur_parent;
123
124 switch (event) {
125 case PRE_RATE_CHANGE:
126 cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
127 if (cur_parent == PLL_MODE_NORM) {
128 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
129 pll->rate_change_remuxed = 1;
130 }
131 break;
132 case POST_RATE_CHANGE:
133 if (pll->rate_change_remuxed) {
134 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
135 pll->rate_change_remuxed = 0;
136 }
137 break;
138 }
139
140 return NOTIFY_OK;
141}
142
143/**
144 * PLL used in RK3066, RK3188 and RK3288 111 * PLL used in RK3066, RK3188 and RK3288
145 */ 112 */
146 113
@@ -194,6 +161,10 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
194 const struct rockchip_pll_rate_table *rate; 161 const struct rockchip_pll_rate_table *rate;
195 unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate); 162 unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate);
196 struct regmap *grf = rockchip_clk_get_grf(); 163 struct regmap *grf = rockchip_clk_get_grf();
164 struct clk_mux *pll_mux = &pll->pll_mux;
165 const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
166 int rate_change_remuxed = 0;
167 int cur_parent;
197 int ret; 168 int ret;
198 169
199 if (IS_ERR(grf)) { 170 if (IS_ERR(grf)) {
@@ -216,6 +187,12 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
216 pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n", 187 pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n",
217 __func__, rate->rate, rate->nr, rate->no, rate->nf); 188 __func__, rate->rate, rate->nr, rate->no, rate->nf);
218 189
190 cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
191 if (cur_parent == PLL_MODE_NORM) {
192 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
193 rate_change_remuxed = 1;
194 }
195
219 /* enter reset mode */ 196 /* enter reset mode */
220 writel(HIWORD_UPDATE(RK3066_PLLCON3_RESET, RK3066_PLLCON3_RESET, 0), 197 writel(HIWORD_UPDATE(RK3066_PLLCON3_RESET, RK3066_PLLCON3_RESET, 0),
221 pll->reg_base + RK3066_PLLCON(3)); 198 pll->reg_base + RK3066_PLLCON(3));
@@ -247,6 +224,9 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
247 rockchip_rk3066_pll_set_rate(hw, old_rate, prate); 224 rockchip_rk3066_pll_set_rate(hw, old_rate, prate);
248 } 225 }
249 226
227 if (rate_change_remuxed)
228 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
229
250 return ret; 230 return ret;
251} 231}
252 232
@@ -310,7 +290,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
310 struct clk_mux *pll_mux; 290 struct clk_mux *pll_mux;
311 struct clk *pll_clk, *mux_clk; 291 struct clk *pll_clk, *mux_clk;
312 char pll_name[20]; 292 char pll_name[20];
313 int ret;
314 293
315 if (num_parents != 2) { 294 if (num_parents != 2) {
316 pr_err("%s: needs two parent clocks\n", __func__); 295 pr_err("%s: needs two parent clocks\n", __func__);
@@ -367,7 +346,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
367 pll->lock_offset = grf_lock_offset; 346 pll->lock_offset = grf_lock_offset;
368 pll->lock_shift = lock_shift; 347 pll->lock_shift = lock_shift;
369 pll->lock = lock; 348 pll->lock = lock;
370 pll->clk_nb.notifier_call = rockchip_pll_notifier_cb;
371 349
372 pll_clk = clk_register(NULL, &pll->hw); 350 pll_clk = clk_register(NULL, &pll->hw);
373 if (IS_ERR(pll_clk)) { 351 if (IS_ERR(pll_clk)) {
@@ -377,14 +355,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
377 goto err_pll; 355 goto err_pll;
378 } 356 }
379 357
380 ret = clk_notifier_register(pll_clk, &pll->clk_nb);
381 if (ret) {
382 pr_err("%s: failed to register clock notifier for %s : %d\n",
383 __func__, name, ret);
384 mux_clk = ERR_PTR(ret);
385 goto err_pll_notifier;
386 }
387
388 /* create the mux on top of the real pll */ 358 /* create the mux on top of the real pll */
389 pll->pll_mux_ops = &clk_mux_ops; 359 pll->pll_mux_ops = &clk_mux_ops;
390 pll_mux = &pll->pll_mux; 360 pll_mux = &pll->pll_mux;
@@ -417,13 +387,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
417 return mux_clk; 387 return mux_clk;
418 388
419err_mux: 389err_mux:
420 ret = clk_notifier_unregister(pll_clk, &pll->clk_nb);
421 if (ret) {
422 pr_err("%s: could not unregister clock notifier in error path : %d\n",
423 __func__, ret);
424 return mux_clk;
425 }
426err_pll_notifier:
427 clk_unregister(pll_clk); 390 clk_unregister(pll_clk);
428err_pll: 391err_pll:
429 kfree(pll); 392 kfree(pll);
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index a83a6d8d0fb6..beed49c79126 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -19,6 +19,7 @@
19#include <dt-bindings/clock/rk3188-cru-common.h> 19#include <dt-bindings/clock/rk3188-cru-common.h>
20#include "clk.h" 20#include "clk.h"
21 21
22#define RK3066_GRF_SOC_STATUS 0x15c
22#define RK3188_GRF_SOC_STATUS 0xac 23#define RK3188_GRF_SOC_STATUS 0xac
23 24
24enum rk3188_plls { 25enum rk3188_plls {
@@ -100,6 +101,98 @@ struct rockchip_pll_rate_table rk3188_pll_rates[] = {
100 { /* sentinel */ }, 101 { /* sentinel */ },
101}; 102};
102 103
104#define RK3066_DIV_CORE_PERIPH_MASK 0x3
105#define RK3066_DIV_CORE_PERIPH_SHIFT 6
106#define RK3066_DIV_ACLK_CORE_MASK 0x7
107#define RK3066_DIV_ACLK_CORE_SHIFT 0
108#define RK3066_DIV_ACLK_HCLK_MASK 0x3
109#define RK3066_DIV_ACLK_HCLK_SHIFT 8
110#define RK3066_DIV_ACLK_PCLK_MASK 0x3
111#define RK3066_DIV_ACLK_PCLK_SHIFT 12
112#define RK3066_DIV_AHB2APB_MASK 0x3
113#define RK3066_DIV_AHB2APB_SHIFT 14
114
115#define RK3066_CLKSEL0(_core_peri) \
116 { \
117 .reg = RK2928_CLKSEL_CON(0), \
118 .val = HIWORD_UPDATE(_core_peri, RK3066_DIV_CORE_PERIPH_MASK, \
119 RK3066_DIV_CORE_PERIPH_SHIFT) \
120 }
121#define RK3066_CLKSEL1(_aclk_core, _aclk_hclk, _aclk_pclk, _ahb2apb) \
122 { \
123 .reg = RK2928_CLKSEL_CON(1), \
124 .val = HIWORD_UPDATE(_aclk_core, RK3066_DIV_ACLK_CORE_MASK, \
125 RK3066_DIV_ACLK_CORE_SHIFT) | \
126 HIWORD_UPDATE(_aclk_hclk, RK3066_DIV_ACLK_HCLK_MASK, \
127 RK3066_DIV_ACLK_HCLK_SHIFT) | \
128 HIWORD_UPDATE(_aclk_pclk, RK3066_DIV_ACLK_PCLK_MASK, \
129 RK3066_DIV_ACLK_PCLK_SHIFT) | \
130 HIWORD_UPDATE(_ahb2apb, RK3066_DIV_AHB2APB_MASK, \
131 RK3066_DIV_AHB2APB_SHIFT), \
132 }
133
134#define RK3066_CPUCLK_RATE(_prate, _core_peri, _acore, _ahclk, _apclk, _h2p) \
135 { \
136 .prate = _prate, \
137 .divs = { \
138 RK3066_CLKSEL0(_core_peri), \
139 RK3066_CLKSEL1(_acore, _ahclk, _apclk, _h2p), \
140 }, \
141 }
142
143static struct rockchip_cpuclk_rate_table rk3066_cpuclk_rates[] __initdata = {
144 RK3066_CPUCLK_RATE(1416000000, 2, 3, 1, 2, 1),
145 RK3066_CPUCLK_RATE(1200000000, 2, 3, 1, 2, 1),
146 RK3066_CPUCLK_RATE(1008000000, 2, 2, 1, 2, 1),
147 RK3066_CPUCLK_RATE( 816000000, 2, 2, 1, 2, 1),
148 RK3066_CPUCLK_RATE( 600000000, 1, 2, 1, 2, 1),
149 RK3066_CPUCLK_RATE( 504000000, 1, 1, 1, 2, 1),
150 RK3066_CPUCLK_RATE( 312000000, 0, 1, 1, 1, 0),
151};
152
153static const struct rockchip_cpuclk_reg_data rk3066_cpuclk_data = {
154 .core_reg = RK2928_CLKSEL_CON(0),
155 .div_core_shift = 0,
156 .div_core_mask = 0x1f,
157 .mux_core_shift = 8,
158};
159
160#define RK3188_DIV_ACLK_CORE_MASK 0x7
161#define RK3188_DIV_ACLK_CORE_SHIFT 3
162
163#define RK3188_CLKSEL1(_aclk_core) \
164 { \
165 .reg = RK2928_CLKSEL_CON(1), \
166 .val = HIWORD_UPDATE(_aclk_core, RK3188_DIV_ACLK_CORE_MASK,\
167 RK3188_DIV_ACLK_CORE_SHIFT) \
168 }
169#define RK3188_CPUCLK_RATE(_prate, _core_peri, _aclk_core) \
170 { \
171 .prate = _prate, \
172 .divs = { \
173 RK3066_CLKSEL0(_core_peri), \
174 RK3188_CLKSEL1(_aclk_core), \
175 }, \
176 }
177
178static struct rockchip_cpuclk_rate_table rk3188_cpuclk_rates[] __initdata = {
179 RK3188_CPUCLK_RATE(1608000000, 2, 3),
180 RK3188_CPUCLK_RATE(1416000000, 2, 3),
181 RK3188_CPUCLK_RATE(1200000000, 2, 3),
182 RK3188_CPUCLK_RATE(1008000000, 2, 3),
183 RK3188_CPUCLK_RATE( 816000000, 2, 3),
184 RK3188_CPUCLK_RATE( 600000000, 1, 3),
185 RK3188_CPUCLK_RATE( 504000000, 1, 3),
186 RK3188_CPUCLK_RATE( 312000000, 0, 1),
187};
188
189static const struct rockchip_cpuclk_reg_data rk3188_cpuclk_data = {
190 .core_reg = RK2928_CLKSEL_CON(0),
191 .div_core_shift = 9,
192 .div_core_mask = 0x1f,
193 .mux_core_shift = 8,
194};
195
103PNAME(mux_pll_p) = { "xin24m", "xin32k" }; 196PNAME(mux_pll_p) = { "xin24m", "xin32k" };
104PNAME(mux_armclk_p) = { "apll", "gpll_armclk" }; 197PNAME(mux_armclk_p) = { "apll", "gpll_armclk" };
105PNAME(mux_ddrphy_p) = { "dpll", "gpll_ddr" }; 198PNAME(mux_ddrphy_p) = { "dpll", "gpll_ddr" };
@@ -173,17 +266,10 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
173 GATE(0, "aclk_cpu", "aclk_cpu_pre", 0, 266 GATE(0, "aclk_cpu", "aclk_cpu_pre", 0,
174 RK2928_CLKGATE_CON(0), 3, GFLAGS), 267 RK2928_CLKGATE_CON(0), 3, GFLAGS),
175 268
176 DIV(0, "pclk_cpu_pre", "aclk_cpu_pre", 0,
177 RK2928_CLKSEL_CON(1), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
178 GATE(0, "atclk_cpu", "pclk_cpu_pre", 0, 269 GATE(0, "atclk_cpu", "pclk_cpu_pre", 0,
179 RK2928_CLKGATE_CON(0), 6, GFLAGS), 270 RK2928_CLKGATE_CON(0), 6, GFLAGS),
180 GATE(0, "pclk_cpu", "pclk_cpu_pre", 0, 271 GATE(0, "pclk_cpu", "pclk_cpu_pre", 0,
181 RK2928_CLKGATE_CON(0), 5, GFLAGS), 272 RK2928_CLKGATE_CON(0), 5, GFLAGS),
182 DIV(0, "hclk_cpu_pre", "aclk_cpu_pre", 0,
183 RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
184 COMPOSITE_NOMUX(0, "hclk_ahb2apb", "hclk_cpu_pre", 0,
185 RK2928_CLKSEL_CON(1), 14, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
186 RK2928_CLKGATE_CON(4), 9, GFLAGS),
187 GATE(0, "hclk_cpu", "hclk_cpu_pre", 0, 273 GATE(0, "hclk_cpu", "hclk_cpu_pre", 0,
188 RK2928_CLKGATE_CON(0), 4, GFLAGS), 274 RK2928_CLKGATE_CON(0), 4, GFLAGS),
189 275
@@ -412,10 +498,18 @@ static struct clk_div_table div_aclk_cpu_t[] = {
412}; 498};
413 499
414static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = { 500static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
415 COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0,
416 RK2928_CLKSEL_CON(0), 8, 1, MFLAGS, 0, 5, DFLAGS),
417 DIVTBL(0, "aclk_cpu_pre", "armclk", 0, 501 DIVTBL(0, "aclk_cpu_pre", "armclk", 0,
418 RK2928_CLKSEL_CON(1), 0, 3, DFLAGS, div_aclk_cpu_t), 502 RK2928_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, div_aclk_cpu_t),
503 DIV(0, "pclk_cpu_pre", "aclk_cpu_pre", 0,
504 RK2928_CLKSEL_CON(1), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO
505 | CLK_DIVIDER_READ_ONLY),
506 DIV(0, "hclk_cpu_pre", "aclk_cpu_pre", 0,
507 RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO
508 | CLK_DIVIDER_READ_ONLY),
509 COMPOSITE_NOMUX(0, "hclk_ahb2apb", "hclk_cpu_pre", 0,
510 RK2928_CLKSEL_CON(1), 14, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO
511 | CLK_DIVIDER_READ_ONLY,
512 RK2928_CLKGATE_CON(4), 9, GFLAGS),
419 513
420 GATE(CORE_L2C, "core_l2c", "aclk_cpu", 0, 514 GATE(CORE_L2C, "core_l2c", "aclk_cpu", 0,
421 RK2928_CLKGATE_CON(9), 4, GFLAGS), 515 RK2928_CLKGATE_CON(9), 4, GFLAGS),
@@ -524,8 +618,6 @@ PNAME(mux_hsicphy_p) = { "sclk_otgphy0", "sclk_otgphy1",
524 "gpll", "cpll" }; 618 "gpll", "cpll" };
525 619
526static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = { 620static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
527 COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0,
528 RK2928_CLKSEL_CON(0), 8, 1, MFLAGS, 9, 5, DFLAGS),
529 COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", 0, 621 COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", 0,
530 RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, 622 RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
531 div_rk3188_aclk_core_t, RK2928_CLKGATE_CON(0), 7, GFLAGS), 623 div_rk3188_aclk_core_t, RK2928_CLKGATE_CON(0), 7, GFLAGS),
@@ -533,6 +625,13 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
533 /* do not source aclk_cpu_pre from the apll, to keep complexity down */ 625 /* do not source aclk_cpu_pre from the apll, to keep complexity down */
534 COMPOSITE_NOGATE(0, "aclk_cpu_pre", mux_aclk_cpu_p, CLK_SET_RATE_NO_REPARENT, 626 COMPOSITE_NOGATE(0, "aclk_cpu_pre", mux_aclk_cpu_p, CLK_SET_RATE_NO_REPARENT,
535 RK2928_CLKSEL_CON(0), 5, 1, MFLAGS, 0, 5, DFLAGS), 627 RK2928_CLKSEL_CON(0), 5, 1, MFLAGS, 0, 5, DFLAGS),
628 DIV(0, "pclk_cpu_pre", "aclk_cpu_pre", 0,
629 RK2928_CLKSEL_CON(1), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
630 DIV(0, "hclk_cpu_pre", "aclk_cpu_pre", 0,
631 RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
632 COMPOSITE_NOMUX(0, "hclk_ahb2apb", "hclk_cpu_pre", 0,
633 RK2928_CLKSEL_CON(1), 14, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
634 RK2928_CLKGATE_CON(4), 9, GFLAGS),
536 635
537 GATE(CORE_L2C, "core_l2c", "armclk", 0, 636 GATE(CORE_L2C, "core_l2c", "armclk", 0,
538 RK2928_CLKGATE_CON(9), 4, GFLAGS), 637 RK2928_CLKGATE_CON(9), 4, GFLAGS),
@@ -599,6 +698,12 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
599 GATE(ACLK_GPS, "aclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS), 698 GATE(ACLK_GPS, "aclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS),
600}; 699};
601 700
701static const char *rk3188_critical_clocks[] __initconst = {
702 "aclk_cpu",
703 "aclk_peri",
704 "hclk_peri",
705};
706
602static void __init rk3188_common_clk_init(struct device_node *np) 707static void __init rk3188_common_clk_init(struct device_node *np)
603{ 708{
604 void __iomem *reg_base; 709 void __iomem *reg_base;
@@ -623,29 +728,65 @@ static void __init rk3188_common_clk_init(struct device_node *np)
623 pr_warn("%s: could not register clock usb480m: %ld\n", 728 pr_warn("%s: could not register clock usb480m: %ld\n",
624 __func__, PTR_ERR(clk)); 729 __func__, PTR_ERR(clk));
625 730
626 rockchip_clk_register_plls(rk3188_pll_clks,
627 ARRAY_SIZE(rk3188_pll_clks),
628 RK3188_GRF_SOC_STATUS);
629 rockchip_clk_register_branches(common_clk_branches, 731 rockchip_clk_register_branches(common_clk_branches,
630 ARRAY_SIZE(common_clk_branches)); 732 ARRAY_SIZE(common_clk_branches));
733 rockchip_clk_protect_critical(rk3188_critical_clocks,
734 ARRAY_SIZE(rk3188_critical_clocks));
631 735
632 rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), 736 rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
633 ROCKCHIP_SOFTRST_HIWORD_MASK); 737 ROCKCHIP_SOFTRST_HIWORD_MASK);
738
739 rockchip_register_restart_notifier(RK2928_GLB_SRST_FST);
634} 740}
635 741
636static void __init rk3066a_clk_init(struct device_node *np) 742static void __init rk3066a_clk_init(struct device_node *np)
637{ 743{
638 rk3188_common_clk_init(np); 744 rk3188_common_clk_init(np);
745 rockchip_clk_register_plls(rk3188_pll_clks,
746 ARRAY_SIZE(rk3188_pll_clks),
747 RK3066_GRF_SOC_STATUS);
639 rockchip_clk_register_branches(rk3066a_clk_branches, 748 rockchip_clk_register_branches(rk3066a_clk_branches,
640 ARRAY_SIZE(rk3066a_clk_branches)); 749 ARRAY_SIZE(rk3066a_clk_branches));
750 rockchip_clk_register_armclk(ARMCLK, "armclk",
751 mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
752 &rk3066_cpuclk_data, rk3066_cpuclk_rates,
753 ARRAY_SIZE(rk3066_cpuclk_rates));
641} 754}
642CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init); 755CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init);
643 756
644static void __init rk3188a_clk_init(struct device_node *np) 757static void __init rk3188a_clk_init(struct device_node *np)
645{ 758{
759 struct clk *clk1, *clk2;
760 unsigned long rate;
761 int ret;
762
646 rk3188_common_clk_init(np); 763 rk3188_common_clk_init(np);
764 rockchip_clk_register_plls(rk3188_pll_clks,
765 ARRAY_SIZE(rk3188_pll_clks),
766 RK3188_GRF_SOC_STATUS);
647 rockchip_clk_register_branches(rk3188_clk_branches, 767 rockchip_clk_register_branches(rk3188_clk_branches,
648 ARRAY_SIZE(rk3188_clk_branches)); 768 ARRAY_SIZE(rk3188_clk_branches));
769 rockchip_clk_register_armclk(ARMCLK, "armclk",
770 mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
771 &rk3188_cpuclk_data, rk3188_cpuclk_rates,
772 ARRAY_SIZE(rk3188_cpuclk_rates));
773
774 /* reparent aclk_cpu_pre from apll */
775 clk1 = __clk_lookup("aclk_cpu_pre");
776 clk2 = __clk_lookup("gpll");
777 if (clk1 && clk2) {
778 rate = clk_get_rate(clk1);
779
780 ret = clk_set_parent(clk1, clk2);
781 if (ret < 0)
782 pr_warn("%s: could not reparent aclk_cpu_pre to gpll\n",
783 __func__);
784
785 clk_set_rate(clk1, rate);
786 } else {
787 pr_warn("%s: missing clocks to reparent aclk_cpu_pre to gpll\n",
788 __func__);
789 }
649} 790}
650CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init); 791CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init);
651 792
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index 0d8c6c59a75e..23278291da44 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -20,7 +20,7 @@
20#include "clk.h" 20#include "clk.h"
21 21
22#define RK3288_GRF_SOC_CON(x) (0x244 + x * 4) 22#define RK3288_GRF_SOC_CON(x) (0x244 + x * 4)
23#define RK3288_GRF_SOC_STATUS 0x280 23#define RK3288_GRF_SOC_STATUS1 0x284
24 24
25enum rk3288_plls { 25enum rk3288_plls {
26 apll, dpll, cpll, gpll, npll, 26 apll, dpll, cpll, gpll, npll,
@@ -101,6 +101,70 @@ struct rockchip_pll_rate_table rk3288_pll_rates[] = {
101 { /* sentinel */ }, 101 { /* sentinel */ },
102}; 102};
103 103
104#define RK3288_DIV_ACLK_CORE_M0_MASK 0xf
105#define RK3288_DIV_ACLK_CORE_M0_SHIFT 0
106#define RK3288_DIV_ACLK_CORE_MP_MASK 0xf
107#define RK3288_DIV_ACLK_CORE_MP_SHIFT 4
108#define RK3288_DIV_L2RAM_MASK 0x7
109#define RK3288_DIV_L2RAM_SHIFT 0
110#define RK3288_DIV_ATCLK_MASK 0x1f
111#define RK3288_DIV_ATCLK_SHIFT 4
112#define RK3288_DIV_PCLK_DBGPRE_MASK 0x1f
113#define RK3288_DIV_PCLK_DBGPRE_SHIFT 9
114
115#define RK3288_CLKSEL0(_core_m0, _core_mp) \
116 { \
117 .reg = RK3288_CLKSEL_CON(0), \
118 .val = HIWORD_UPDATE(_core_m0, RK3288_DIV_ACLK_CORE_M0_MASK, \
119 RK3288_DIV_ACLK_CORE_M0_SHIFT) | \
120 HIWORD_UPDATE(_core_mp, RK3288_DIV_ACLK_CORE_MP_MASK, \
121 RK3288_DIV_ACLK_CORE_MP_SHIFT), \
122 }
123#define RK3288_CLKSEL37(_l2ram, _atclk, _pclk_dbg_pre) \
124 { \
125 .reg = RK3288_CLKSEL_CON(37), \
126 .val = HIWORD_UPDATE(_l2ram, RK3288_DIV_L2RAM_MASK, \
127 RK3288_DIV_L2RAM_SHIFT) | \
128 HIWORD_UPDATE(_atclk, RK3288_DIV_ATCLK_MASK, \
129 RK3288_DIV_ATCLK_SHIFT) | \
130 HIWORD_UPDATE(_pclk_dbg_pre, \
131 RK3288_DIV_PCLK_DBGPRE_MASK, \
132 RK3288_DIV_PCLK_DBGPRE_SHIFT), \
133 }
134
135#define RK3288_CPUCLK_RATE(_prate, _core_m0, _core_mp, _l2ram, _atclk, _pdbg) \
136 { \
137 .prate = _prate, \
138 .divs = { \
139 RK3288_CLKSEL0(_core_m0, _core_mp), \
140 RK3288_CLKSEL37(_l2ram, _atclk, _pdbg), \
141 }, \
142 }
143
144static struct rockchip_cpuclk_rate_table rk3288_cpuclk_rates[] __initdata = {
145 RK3288_CPUCLK_RATE(1800000000, 2, 4, 2, 4, 4),
146 RK3288_CPUCLK_RATE(1704000000, 2, 4, 2, 4, 4),
147 RK3288_CPUCLK_RATE(1608000000, 2, 4, 2, 4, 4),
148 RK3288_CPUCLK_RATE(1512000000, 2, 4, 2, 4, 4),
149 RK3288_CPUCLK_RATE(1416000000, 2, 4, 2, 4, 4),
150 RK3288_CPUCLK_RATE(1200000000, 2, 4, 2, 4, 4),
151 RK3288_CPUCLK_RATE(1008000000, 2, 4, 2, 4, 4),
152 RK3288_CPUCLK_RATE( 816000000, 2, 4, 2, 4, 4),
153 RK3288_CPUCLK_RATE( 696000000, 2, 4, 2, 4, 4),
154 RK3288_CPUCLK_RATE( 600000000, 2, 4, 2, 4, 4),
155 RK3288_CPUCLK_RATE( 408000000, 2, 4, 2, 4, 4),
156 RK3288_CPUCLK_RATE( 312000000, 2, 4, 2, 4, 4),
157 RK3288_CPUCLK_RATE( 216000000, 2, 4, 2, 4, 4),
158 RK3288_CPUCLK_RATE( 126000000, 2, 4, 2, 4, 4),
159};
160
161static const struct rockchip_cpuclk_reg_data rk3288_cpuclk_data = {
162 .core_reg = RK3288_CLKSEL_CON(0),
163 .div_core_shift = 8,
164 .div_core_mask = 0x1f,
165 .mux_core_shift = 15,
166};
167
104PNAME(mux_pll_p) = { "xin24m", "xin32k" }; 168PNAME(mux_pll_p) = { "xin24m", "xin32k" };
105PNAME(mux_armclk_p) = { "apll_core", "gpll_core" }; 169PNAME(mux_armclk_p) = { "apll_core", "gpll_core" };
106PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr" }; 170PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr" };
@@ -143,7 +207,7 @@ static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = {
143 [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), 207 [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12),
144 RK3288_MODE_CON, 12, 8, rk3288_pll_rates), 208 RK3288_MODE_CON, 12, 8, rk3288_pll_rates),
145 [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), 209 [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16),
146 RK3288_MODE_CON, 14, 9, NULL), 210 RK3288_MODE_CON, 14, 9, rk3288_pll_rates),
147}; 211};
148 212
149static struct clk_div_table div_hclk_cpu_t[] = { 213static struct clk_div_table div_hclk_cpu_t[] = {
@@ -166,35 +230,33 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
166 RK3288_CLKGATE_CON(0), 1, GFLAGS), 230 RK3288_CLKGATE_CON(0), 1, GFLAGS),
167 GATE(0, "gpll_core", "gpll", 0, 231 GATE(0, "gpll_core", "gpll", 0,
168 RK3288_CLKGATE_CON(0), 2, GFLAGS), 232 RK3288_CLKGATE_CON(0), 2, GFLAGS),
169 COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0,
170 RK3288_CLKSEL_CON(0), 15, 1, MFLAGS, 8, 5, DFLAGS),
171 233
172 COMPOSITE_NOMUX(0, "armcore0", "armclk", 0, 234 COMPOSITE_NOMUX(0, "armcore0", "armclk", 0,
173 RK3288_CLKSEL_CON(36), 0, 3, DFLAGS, 235 RK3288_CLKSEL_CON(36), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
174 RK3288_CLKGATE_CON(12), 0, GFLAGS), 236 RK3288_CLKGATE_CON(12), 0, GFLAGS),
175 COMPOSITE_NOMUX(0, "armcore1", "armclk", 0, 237 COMPOSITE_NOMUX(0, "armcore1", "armclk", 0,
176 RK3288_CLKSEL_CON(36), 4, 3, DFLAGS, 238 RK3288_CLKSEL_CON(36), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
177 RK3288_CLKGATE_CON(12), 1, GFLAGS), 239 RK3288_CLKGATE_CON(12), 1, GFLAGS),
178 COMPOSITE_NOMUX(0, "armcore2", "armclk", 0, 240 COMPOSITE_NOMUX(0, "armcore2", "armclk", 0,
179 RK3288_CLKSEL_CON(36), 8, 3, DFLAGS, 241 RK3288_CLKSEL_CON(36), 8, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
180 RK3288_CLKGATE_CON(12), 2, GFLAGS), 242 RK3288_CLKGATE_CON(12), 2, GFLAGS),
181 COMPOSITE_NOMUX(0, "armcore3", "armclk", 0, 243 COMPOSITE_NOMUX(0, "armcore3", "armclk", 0,
182 RK3288_CLKSEL_CON(36), 12, 3, DFLAGS, 244 RK3288_CLKSEL_CON(36), 12, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
183 RK3288_CLKGATE_CON(12), 3, GFLAGS), 245 RK3288_CLKGATE_CON(12), 3, GFLAGS),
184 COMPOSITE_NOMUX(0, "l2ram", "armclk", 0, 246 COMPOSITE_NOMUX(0, "l2ram", "armclk", 0,
185 RK3288_CLKSEL_CON(37), 0, 3, DFLAGS, 247 RK3288_CLKSEL_CON(37), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
186 RK3288_CLKGATE_CON(12), 4, GFLAGS), 248 RK3288_CLKGATE_CON(12), 4, GFLAGS),
187 COMPOSITE_NOMUX(0, "aclk_core_m0", "armclk", 0, 249 COMPOSITE_NOMUX(0, "aclk_core_m0", "armclk", 0,
188 RK3288_CLKSEL_CON(0), 0, 4, DFLAGS, 250 RK3288_CLKSEL_CON(0), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
189 RK3288_CLKGATE_CON(12), 5, GFLAGS), 251 RK3288_CLKGATE_CON(12), 5, GFLAGS),
190 COMPOSITE_NOMUX(0, "aclk_core_mp", "armclk", 0, 252 COMPOSITE_NOMUX(0, "aclk_core_mp", "armclk", 0,
191 RK3288_CLKSEL_CON(0), 4, 4, DFLAGS, 253 RK3288_CLKSEL_CON(0), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
192 RK3288_CLKGATE_CON(12), 6, GFLAGS), 254 RK3288_CLKGATE_CON(12), 6, GFLAGS),
193 COMPOSITE_NOMUX(0, "atclk", "armclk", 0, 255 COMPOSITE_NOMUX(0, "atclk", "armclk", 0,
194 RK3288_CLKSEL_CON(37), 4, 5, DFLAGS, 256 RK3288_CLKSEL_CON(37), 4, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
195 RK3288_CLKGATE_CON(12), 7, GFLAGS), 257 RK3288_CLKGATE_CON(12), 7, GFLAGS),
196 COMPOSITE_NOMUX(0, "pclk_dbg_pre", "armclk", 0, 258 COMPOSITE_NOMUX(0, "pclk_dbg_pre", "armclk", 0,
197 RK3288_CLKSEL_CON(37), 9, 5, DFLAGS, 259 RK3288_CLKSEL_CON(37), 9, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
198 RK3288_CLKGATE_CON(12), 8, GFLAGS), 260 RK3288_CLKGATE_CON(12), 8, GFLAGS),
199 GATE(0, "pclk_dbg", "pclk_dbg_pre", 0, 261 GATE(0, "pclk_dbg", "pclk_dbg_pre", 0,
200 RK3288_CLKGATE_CON(12), 9, GFLAGS), 262 RK3288_CLKGATE_CON(12), 9, GFLAGS),
@@ -219,12 +281,12 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
219 RK3288_CLKSEL_CON(1), 15, 1, MFLAGS, 3, 5, DFLAGS), 281 RK3288_CLKSEL_CON(1), 15, 1, MFLAGS, 3, 5, DFLAGS),
220 DIV(0, "aclk_cpu_pre", "aclk_cpu_src", 0, 282 DIV(0, "aclk_cpu_pre", "aclk_cpu_src", 0,
221 RK3288_CLKSEL_CON(1), 0, 3, DFLAGS), 283 RK3288_CLKSEL_CON(1), 0, 3, DFLAGS),
222 GATE(0, "aclk_cpu", "aclk_cpu_pre", 0, 284 GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_pre", 0,
223 RK3288_CLKGATE_CON(0), 3, GFLAGS), 285 RK3288_CLKGATE_CON(0), 3, GFLAGS),
224 COMPOSITE_NOMUX(0, "pclk_cpu", "aclk_cpu_pre", 0, 286 COMPOSITE_NOMUX(PCLK_CPU, "pclk_cpu", "aclk_cpu_pre", 0,
225 RK3288_CLKSEL_CON(1), 12, 3, DFLAGS, 287 RK3288_CLKSEL_CON(1), 12, 3, DFLAGS,
226 RK3288_CLKGATE_CON(0), 5, GFLAGS), 288 RK3288_CLKGATE_CON(0), 5, GFLAGS),
227 COMPOSITE_NOMUX_DIVTBL(0, "hclk_cpu", "aclk_cpu_pre", 0, 289 COMPOSITE_NOMUX_DIVTBL(HCLK_CPU, "hclk_cpu", "aclk_cpu_pre", 0,
228 RK3288_CLKSEL_CON(1), 8, 2, DFLAGS, div_hclk_cpu_t, 290 RK3288_CLKSEL_CON(1), 8, 2, DFLAGS, div_hclk_cpu_t,
229 RK3288_CLKGATE_CON(0), 4, GFLAGS), 291 RK3288_CLKGATE_CON(0), 4, GFLAGS),
230 GATE(0, "c2c_host", "aclk_cpu_src", 0, 292 GATE(0, "c2c_host", "aclk_cpu_src", 0,
@@ -238,15 +300,15 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
238 COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0, 300 COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0,
239 RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS, 301 RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS,
240 RK3288_CLKGATE_CON(4), 1, GFLAGS), 302 RK3288_CLKGATE_CON(4), 1, GFLAGS),
241 COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", 0, 303 COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
242 RK3288_CLKSEL_CON(8), 0, 304 RK3288_CLKSEL_CON(8), 0,
243 RK3288_CLKGATE_CON(4), 2, GFLAGS), 305 RK3288_CLKGATE_CON(4), 2, GFLAGS),
244 MUX(0, "i2s_pre", mux_i2s_pre_p, 0, 306 MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
245 RK3288_CLKSEL_CON(4), 8, 2, MFLAGS), 307 RK3288_CLKSEL_CON(4), 8, 2, MFLAGS),
246 COMPOSITE_NODIV(0, "i2s0_clkout", mux_i2s_clkout_p, 0, 308 COMPOSITE_NODIV(0, "i2s0_clkout", mux_i2s_clkout_p, CLK_SET_RATE_PARENT,
247 RK3288_CLKSEL_CON(4), 12, 1, MFLAGS, 309 RK3288_CLKSEL_CON(4), 12, 1, MFLAGS,
248 RK3288_CLKGATE_CON(4), 0, GFLAGS), 310 RK3288_CLKGATE_CON(4), 0, GFLAGS),
249 GATE(SCLK_I2S0, "sclk_i2s0", "i2s_pre", 0, 311 GATE(SCLK_I2S0, "sclk_i2s0", "i2s_pre", CLK_SET_RATE_PARENT,
250 RK3288_CLKGATE_CON(4), 3, GFLAGS), 312 RK3288_CLKGATE_CON(4), 3, GFLAGS),
251 313
252 MUX(0, "spdif_src", mux_pll_src_cpll_gpll_p, 0, 314 MUX(0, "spdif_src", mux_pll_src_cpll_gpll_p, 0,
@@ -296,6 +358,20 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
296 COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb480m_p, 0, 358 COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb480m_p, 0,
297 RK3288_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS, 359 RK3288_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
298 RK3288_CLKGATE_CON(3), 11, GFLAGS), 360 RK3288_CLKGATE_CON(3), 11, GFLAGS),
361 /*
362 * We use aclk_vdpu by default GRF_SOC_CON0[7] setting in system,
363 * so we ignore the mux and make clocks nodes as following,
364 */
365 GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vdpu", 0,
366 RK3288_CLKGATE_CON(9), 0, GFLAGS),
367 /*
368 * We introduce a virtul node of hclk_vodec_pre_v to split one clock
369 * struct with a gate and a fix divider into two node in software.
370 */
371 GATE(0, "hclk_vcodec_pre_v", "aclk_vdpu", 0,
372 RK3288_CLKGATE_CON(3), 10, GFLAGS),
373 GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", 0,
374 RK3288_CLKGATE_CON(9), 1, GFLAGS),
299 375
300 COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, 0, 376 COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, 0,
301 RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS, 377 RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS,
@@ -309,7 +385,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
309 COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_usb480m_p, 0, 385 COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_usb480m_p, 0,
310 RK3288_CLKSEL_CON(30), 6, 2, MFLAGS, 0, 5, DFLAGS, 386 RK3288_CLKSEL_CON(30), 6, 2, MFLAGS, 0, 5, DFLAGS,
311 RK3288_CLKGATE_CON(3), 5, GFLAGS), 387 RK3288_CLKGATE_CON(3), 5, GFLAGS),
312 COMPOSITE(0, "sclk_rga", mux_pll_src_cpll_gpll_usb480m_p, 0, 388 COMPOSITE(SCLK_RGA, "sclk_rga", mux_pll_src_cpll_gpll_usb480m_p, 0,
313 RK3288_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS, 389 RK3288_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS,
314 RK3288_CLKGATE_CON(3), 4, GFLAGS), 390 RK3288_CLKGATE_CON(3), 4, GFLAGS),
315 391
@@ -320,35 +396,35 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
320 RK3288_CLKSEL_CON(29), 6, 2, MFLAGS, 8, 8, DFLAGS, 396 RK3288_CLKSEL_CON(29), 6, 2, MFLAGS, 8, 8, DFLAGS,
321 RK3288_CLKGATE_CON(3), 3, GFLAGS), 397 RK3288_CLKGATE_CON(3), 3, GFLAGS),
322 398
323 COMPOSITE_NODIV(0, "sclk_edp_24m", mux_edp_24m_p, 0, 399 COMPOSITE_NODIV(SCLK_EDP_24M, "sclk_edp_24m", mux_edp_24m_p, 0,
324 RK3288_CLKSEL_CON(28), 15, 1, MFLAGS, 400 RK3288_CLKSEL_CON(28), 15, 1, MFLAGS,
325 RK3288_CLKGATE_CON(3), 12, GFLAGS), 401 RK3288_CLKGATE_CON(3), 12, GFLAGS),
326 COMPOSITE(0, "sclk_edp", mux_pll_src_cpll_gpll_npll_p, 0, 402 COMPOSITE(SCLK_EDP, "sclk_edp", mux_pll_src_cpll_gpll_npll_p, 0,
327 RK3288_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 6, DFLAGS, 403 RK3288_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 6, DFLAGS,
328 RK3288_CLKGATE_CON(3), 13, GFLAGS), 404 RK3288_CLKGATE_CON(3), 13, GFLAGS),
329 405
330 COMPOSITE(0, "sclk_isp", mux_pll_src_cpll_gpll_npll_p, 0, 406 COMPOSITE(SCLK_ISP, "sclk_isp", mux_pll_src_cpll_gpll_npll_p, 0,
331 RK3288_CLKSEL_CON(6), 6, 2, MFLAGS, 0, 6, DFLAGS, 407 RK3288_CLKSEL_CON(6), 6, 2, MFLAGS, 0, 6, DFLAGS,
332 RK3288_CLKGATE_CON(3), 14, GFLAGS), 408 RK3288_CLKGATE_CON(3), 14, GFLAGS),
333 COMPOSITE(0, "sclk_isp_jpe", mux_pll_src_cpll_gpll_npll_p, 0, 409 COMPOSITE(SCLK_ISP_JPE, "sclk_isp_jpe", mux_pll_src_cpll_gpll_npll_p, 0,
334 RK3288_CLKSEL_CON(6), 14, 2, MFLAGS, 8, 6, DFLAGS, 410 RK3288_CLKSEL_CON(6), 14, 2, MFLAGS, 8, 6, DFLAGS,
335 RK3288_CLKGATE_CON(3), 15, GFLAGS), 411 RK3288_CLKGATE_CON(3), 15, GFLAGS),
336 412
337 GATE(0, "sclk_hdmi_hdcp", "xin24m", 0, 413 GATE(SCLK_HDMI_HDCP, "sclk_hdmi_hdcp", "xin24m", 0,
338 RK3288_CLKGATE_CON(5), 12, GFLAGS), 414 RK3288_CLKGATE_CON(5), 12, GFLAGS),
339 GATE(0, "sclk_hdmi_cec", "xin32k", 0, 415 GATE(SCLK_HDMI_CEC, "sclk_hdmi_cec", "xin32k", 0,
340 RK3288_CLKGATE_CON(5), 11, GFLAGS), 416 RK3288_CLKGATE_CON(5), 11, GFLAGS),
341 417
342 COMPOSITE(0, "aclk_hevc", mux_pll_src_cpll_gpll_npll_p, 0, 418 COMPOSITE(ACLK_HEVC, "aclk_hevc", mux_pll_src_cpll_gpll_npll_p, 0,
343 RK3288_CLKSEL_CON(39), 14, 2, MFLAGS, 8, 5, DFLAGS, 419 RK3288_CLKSEL_CON(39), 14, 2, MFLAGS, 8, 5, DFLAGS,
344 RK3288_CLKGATE_CON(13), 13, GFLAGS), 420 RK3288_CLKGATE_CON(13), 13, GFLAGS),
345 DIV(0, "hclk_hevc", "aclk_hevc", 0, 421 DIV(HCLK_HEVC, "hclk_hevc", "aclk_hevc", 0,
346 RK3288_CLKSEL_CON(40), 12, 2, DFLAGS), 422 RK3288_CLKSEL_CON(40), 12, 2, DFLAGS),
347 423
348 COMPOSITE(0, "sclk_hevc_cabac", mux_pll_src_cpll_gpll_npll_p, 0, 424 COMPOSITE(SCLK_HEVC_CABAC, "sclk_hevc_cabac", mux_pll_src_cpll_gpll_npll_p, 0,
349 RK3288_CLKSEL_CON(42), 6, 2, MFLAGS, 0, 5, DFLAGS, 425 RK3288_CLKSEL_CON(42), 6, 2, MFLAGS, 0, 5, DFLAGS,
350 RK3288_CLKGATE_CON(13), 14, GFLAGS), 426 RK3288_CLKGATE_CON(13), 14, GFLAGS),
351 COMPOSITE(0, "sclk_hevc_core", mux_pll_src_cpll_gpll_npll_p, 0, 427 COMPOSITE(SCLK_HEVC_CORE, "sclk_hevc_core", mux_pll_src_cpll_gpll_npll_p, 0,
352 RK3288_CLKSEL_CON(42), 14, 2, MFLAGS, 8, 5, DFLAGS, 428 RK3288_CLKSEL_CON(42), 14, 2, MFLAGS, 8, 5, DFLAGS,
353 RK3288_CLKGATE_CON(13), 15, GFLAGS), 429 RK3288_CLKGATE_CON(13), 15, GFLAGS),
354 430
@@ -371,13 +447,13 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
371 COMPOSITE(0, "aclk_peri_src", mux_pll_src_cpll_gpll_p, 0, 447 COMPOSITE(0, "aclk_peri_src", mux_pll_src_cpll_gpll_p, 0,
372 RK3288_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS, 448 RK3288_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS,
373 RK3288_CLKGATE_CON(2), 0, GFLAGS), 449 RK3288_CLKGATE_CON(2), 0, GFLAGS),
374 COMPOSITE_NOMUX(0, "pclk_peri", "aclk_peri_src", 0, 450 COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0,
375 RK3288_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, 451 RK3288_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
376 RK3288_CLKGATE_CON(2), 3, GFLAGS), 452 RK3288_CLKGATE_CON(2), 3, GFLAGS),
377 COMPOSITE_NOMUX(0, "hclk_peri", "aclk_peri_src", 0, 453 COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_src", 0,
378 RK3288_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, 454 RK3288_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
379 RK3288_CLKGATE_CON(2), 2, GFLAGS), 455 RK3288_CLKGATE_CON(2), 2, GFLAGS),
380 GATE(0, "aclk_peri", "aclk_peri_src", 0, 456 GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", 0,
381 RK3288_CLKGATE_CON(2), 1, GFLAGS), 457 RK3288_CLKGATE_CON(2), 1, GFLAGS),
382 458
383 /* 459 /*
@@ -545,7 +621,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
545 GATE(PCLK_PWM, "pclk_pwm", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 0, GFLAGS), 621 GATE(PCLK_PWM, "pclk_pwm", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 0, GFLAGS),
546 GATE(PCLK_TIMER, "pclk_timer", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 1, GFLAGS), 622 GATE(PCLK_TIMER, "pclk_timer", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 1, GFLAGS),
547 GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 2, GFLAGS), 623 GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 2, GFLAGS),
548 GATE(PCLK_I2C1, "pclk_i2c1", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 3, GFLAGS), 624 GATE(PCLK_I2C2, "pclk_i2c2", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 3, GFLAGS),
549 GATE(0, "pclk_ddrupctl0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 14, GFLAGS), 625 GATE(0, "pclk_ddrupctl0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 14, GFLAGS),
550 GATE(0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS), 626 GATE(0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS),
551 GATE(0, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS), 627 GATE(0, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS),
@@ -603,7 +679,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
603 GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 15, GFLAGS), 679 GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 15, GFLAGS),
604 GATE(PCLK_UART3, "pclk_uart3", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 11, GFLAGS), 680 GATE(PCLK_UART3, "pclk_uart3", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 11, GFLAGS),
605 GATE(PCLK_UART4, "pclk_uart4", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 12, GFLAGS), 681 GATE(PCLK_UART4, "pclk_uart4", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 12, GFLAGS),
606 GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 13, GFLAGS), 682 GATE(PCLK_I2C1, "pclk_i2c1", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 13, GFLAGS),
607 GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 14, GFLAGS), 683 GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 14, GFLAGS),
608 GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 1, GFLAGS), 684 GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 1, GFLAGS),
609 GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 2, GFLAGS), 685 GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 2, GFLAGS),
@@ -643,34 +719,34 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
643 GATE(HCLK_RGA, "hclk_rga", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 1, GFLAGS), 719 GATE(HCLK_RGA, "hclk_rga", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 1, GFLAGS),
644 GATE(HCLK_VOP0, "hclk_vop0", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 6, GFLAGS), 720 GATE(HCLK_VOP0, "hclk_vop0", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 6, GFLAGS),
645 GATE(HCLK_VOP1, "hclk_vop1", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 8, GFLAGS), 721 GATE(HCLK_VOP1, "hclk_vop1", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 8, GFLAGS),
646 GATE(0, "hclk_vio_ahb_arbi", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 9, GFLAGS), 722 GATE(HCLK_VIO_AHB_ARBI, "hclk_vio_ahb_arbi", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 9, GFLAGS),
647 GATE(0, "hclk_vio_niu", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 10, GFLAGS), 723 GATE(HCLK_VIO_NIU, "hclk_vio_niu", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 10, GFLAGS),
648 GATE(0, "hclk_vip", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 15, GFLAGS), 724 GATE(HCLK_VIP, "hclk_vip", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 15, GFLAGS),
649 GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 3, GFLAGS), 725 GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 3, GFLAGS),
650 GATE(HCLK_ISP, "hclk_isp", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 1, GFLAGS), 726 GATE(HCLK_ISP, "hclk_isp", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 1, GFLAGS),
651 GATE(0, "hclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 10, GFLAGS), 727 GATE(HCLK_VIO2_H2P, "hclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 10, GFLAGS),
652 GATE(0, "pclk_mipi_dsi0", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 4, GFLAGS), 728 GATE(PCLK_MIPI_DSI0, "pclk_mipi_dsi0", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 4, GFLAGS),
653 GATE(0, "pclk_mipi_dsi1", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 5, GFLAGS), 729 GATE(PCLK_MIPI_DSI1, "pclk_mipi_dsi1", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 5, GFLAGS),
654 GATE(0, "pclk_mipi_csi", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 6, GFLAGS), 730 GATE(PCLK_MIPI_CSI, "pclk_mipi_csi", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 6, GFLAGS),
655 GATE(0, "pclk_lvds_phy", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 7, GFLAGS), 731 GATE(PCLK_LVDS_PHY, "pclk_lvds_phy", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 7, GFLAGS),
656 GATE(0, "pclk_edp_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 8, GFLAGS), 732 GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 8, GFLAGS),
657 GATE(0, "pclk_hdmi_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 9, GFLAGS), 733 GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 9, GFLAGS),
658 GATE(0, "pclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 11, GFLAGS), 734 GATE(PCLK_VIO2_H2P, "pclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 11, GFLAGS),
659 735
660 /* aclk_vio0 gates */ 736 /* aclk_vio0 gates */
661 GATE(ACLK_VOP0, "aclk_vop0", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 5, GFLAGS), 737 GATE(ACLK_VOP0, "aclk_vop0", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 5, GFLAGS),
662 GATE(0, "aclk_iep", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 2, GFLAGS), 738 GATE(ACLK_IEP, "aclk_iep", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 2, GFLAGS),
663 GATE(0, "aclk_vio0_niu", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 11, GFLAGS), 739 GATE(ACLK_VIO0_NIU, "aclk_vio0_niu", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 11, GFLAGS),
664 GATE(0, "aclk_vip", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 14, GFLAGS), 740 GATE(ACLK_VIP, "aclk_vip", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 14, GFLAGS),
665 741
666 /* aclk_vio1 gates */ 742 /* aclk_vio1 gates */
667 GATE(ACLK_VOP1, "aclk_vop1", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 7, GFLAGS), 743 GATE(ACLK_VOP1, "aclk_vop1", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 7, GFLAGS),
668 GATE(0, "aclk_isp", "aclk_vio1", 0, RK3288_CLKGATE_CON(16), 2, GFLAGS), 744 GATE(ACLK_ISP, "aclk_isp", "aclk_vio1", 0, RK3288_CLKGATE_CON(16), 2, GFLAGS),
669 GATE(0, "aclk_vio1_niu", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 12, GFLAGS), 745 GATE(ACLK_VIO1_NIU, "aclk_vio1_niu", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 12, GFLAGS),
670 746
671 /* aclk_rga_pre gates */ 747 /* aclk_rga_pre gates */
672 GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 0, GFLAGS), 748 GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 0, GFLAGS),
673 GATE(0, "aclk_rga_niu", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 13, GFLAGS), 749 GATE(ACLK_RGA_NIU, "aclk_rga_niu", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 13, GFLAGS),
674 750
675 /* 751 /*
676 * Other ungrouped clocks. 752 * Other ungrouped clocks.
@@ -680,6 +756,12 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
680 GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS), 756 GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS),
681}; 757};
682 758
759static const char *rk3288_critical_clocks[] __initconst = {
760 "aclk_cpu",
761 "aclk_peri",
762 "hclk_peri",
763};
764
683static void __init rk3288_clk_init(struct device_node *np) 765static void __init rk3288_clk_init(struct device_node *np)
684{ 766{
685 void __iomem *reg_base; 767 void __iomem *reg_base;
@@ -705,13 +787,28 @@ static void __init rk3288_clk_init(struct device_node *np)
705 pr_warn("%s: could not register clock usb480m: %ld\n", 787 pr_warn("%s: could not register clock usb480m: %ld\n",
706 __func__, PTR_ERR(clk)); 788 __func__, PTR_ERR(clk));
707 789
790 clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
791 "hclk_vcodec_pre_v", 0, 1, 4);
792 if (IS_ERR(clk))
793 pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
794 __func__, PTR_ERR(clk));
795
708 rockchip_clk_register_plls(rk3288_pll_clks, 796 rockchip_clk_register_plls(rk3288_pll_clks,
709 ARRAY_SIZE(rk3288_pll_clks), 797 ARRAY_SIZE(rk3288_pll_clks),
710 RK3288_GRF_SOC_STATUS); 798 RK3288_GRF_SOC_STATUS1);
711 rockchip_clk_register_branches(rk3288_clk_branches, 799 rockchip_clk_register_branches(rk3288_clk_branches,
712 ARRAY_SIZE(rk3288_clk_branches)); 800 ARRAY_SIZE(rk3288_clk_branches));
801 rockchip_clk_protect_critical(rk3288_critical_clocks,
802 ARRAY_SIZE(rk3288_critical_clocks));
713 803
714 rockchip_register_softrst(np, 9, reg_base + RK3288_SOFTRST_CON(0), 804 rockchip_clk_register_armclk(ARMCLK, "armclk",
805 mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
806 &rk3288_cpuclk_data, rk3288_cpuclk_rates,
807 ARRAY_SIZE(rk3288_cpuclk_rates));
808
809 rockchip_register_softrst(np, 12, reg_base + RK3288_SOFTRST_CON(0),
715 ROCKCHIP_SOFTRST_HIWORD_MASK); 810 ROCKCHIP_SOFTRST_HIWORD_MASK);
811
812 rockchip_register_restart_notifier(RK3288_GLB_SRST_FST);
716} 813}
717CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); 814CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init);
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 278cf9dd1e23..1e68bff481b8 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -25,6 +25,7 @@
25#include <linux/clk-provider.h> 25#include <linux/clk-provider.h>
26#include <linux/mfd/syscon.h> 26#include <linux/mfd/syscon.h>
27#include <linux/regmap.h> 27#include <linux/regmap.h>
28#include <linux/reboot.h>
28#include "clk.h" 29#include "clk.h"
29 30
30/** 31/**
@@ -37,7 +38,7 @@
37 * 38 *
38 * sometimes without one of those components. 39 * sometimes without one of those components.
39 */ 40 */
40struct clk *rockchip_clk_register_branch(const char *name, 41static struct clk *rockchip_clk_register_branch(const char *name,
41 const char **parent_names, u8 num_parents, void __iomem *base, 42 const char **parent_names, u8 num_parents, void __iomem *base,
42 int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags, 43 int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
43 u8 div_shift, u8 div_width, u8 div_flags, 44 u8 div_shift, u8 div_width, u8 div_flags,
@@ -103,6 +104,54 @@ struct clk *rockchip_clk_register_branch(const char *name,
103 return clk; 104 return clk;
104} 105}
105 106
107static struct clk *rockchip_clk_register_frac_branch(const char *name,
108 const char **parent_names, u8 num_parents, void __iomem *base,
109 int muxdiv_offset, u8 div_flags,
110 int gate_offset, u8 gate_shift, u8 gate_flags,
111 unsigned long flags, spinlock_t *lock)
112{
113 struct clk *clk;
114 struct clk_gate *gate = NULL;
115 struct clk_fractional_divider *div = NULL;
116 const struct clk_ops *div_ops = NULL, *gate_ops = NULL;
117
118 if (gate_offset >= 0) {
119 gate = kzalloc(sizeof(*gate), GFP_KERNEL);
120 if (!gate)
121 return ERR_PTR(-ENOMEM);
122
123 gate->flags = gate_flags;
124 gate->reg = base + gate_offset;
125 gate->bit_idx = gate_shift;
126 gate->lock = lock;
127 gate_ops = &clk_gate_ops;
128 }
129
130 if (muxdiv_offset < 0)
131 return ERR_PTR(-EINVAL);
132
133 div = kzalloc(sizeof(*div), GFP_KERNEL);
134 if (!div)
135 return ERR_PTR(-ENOMEM);
136
137 div->flags = div_flags;
138 div->reg = base + muxdiv_offset;
139 div->mshift = 16;
140 div->mmask = 0xffff0000;
141 div->nshift = 0;
142 div->nmask = 0xffff;
143 div->lock = lock;
144 div_ops = &clk_fractional_divider_ops;
145
146 clk = clk_register_composite(NULL, name, parent_names, num_parents,
147 NULL, NULL,
148 &div->hw, div_ops,
149 gate ? &gate->hw : NULL, gate_ops,
150 flags);
151
152 return clk;
153}
154
106static DEFINE_SPINLOCK(clk_lock); 155static DEFINE_SPINLOCK(clk_lock);
107static struct clk **clk_table; 156static struct clk **clk_table;
108static void __iomem *reg_base; 157static void __iomem *reg_base;
@@ -197,8 +246,14 @@ void __init rockchip_clk_register_branches(
197 list->div_flags, &clk_lock); 246 list->div_flags, &clk_lock);
198 break; 247 break;
199 case branch_fraction_divider: 248 case branch_fraction_divider:
200 /* unimplemented */ 249 /* keep all gates untouched for now */
201 continue; 250 flags |= CLK_IGNORE_UNUSED;
251
252 clk = rockchip_clk_register_frac_branch(list->name,
253 list->parent_names, list->num_parents,
254 reg_base, list->muxdiv_offset, list->div_flags,
255 list->gate_offset, list->gate_shift,
256 list->gate_flags, flags, &clk_lock);
202 break; 257 break;
203 case branch_gate: 258 case branch_gate:
204 flags |= CLK_SET_RATE_PARENT; 259 flags |= CLK_SET_RATE_PARENT;
@@ -242,3 +297,61 @@ void __init rockchip_clk_register_branches(
242 rockchip_clk_add_lookup(clk, list->id); 297 rockchip_clk_add_lookup(clk, list->id);
243 } 298 }
244} 299}
300
301void __init rockchip_clk_register_armclk(unsigned int lookup_id,
302 const char *name, const char **parent_names,
303 u8 num_parents,
304 const struct rockchip_cpuclk_reg_data *reg_data,
305 const struct rockchip_cpuclk_rate_table *rates,
306 int nrates)
307{
308 struct clk *clk;
309
310 clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents,
311 reg_data, rates, nrates, reg_base,
312 &clk_lock);
313 if (IS_ERR(clk)) {
314 pr_err("%s: failed to register clock %s: %ld\n",
315 __func__, name, PTR_ERR(clk));
316 return;
317 }
318
319 rockchip_clk_add_lookup(clk, lookup_id);
320}
321
322void __init rockchip_clk_protect_critical(const char *clocks[], int nclocks)
323{
324 int i;
325
326 /* Protect the clocks that needs to stay on */
327 for (i = 0; i < nclocks; i++) {
328 struct clk *clk = __clk_lookup(clocks[i]);
329
330 if (clk)
331 clk_prepare_enable(clk);
332 }
333}
334
335static unsigned int reg_restart;
336static int rockchip_restart_notify(struct notifier_block *this,
337 unsigned long mode, void *cmd)
338{
339 writel(0xfdb9, reg_base + reg_restart);
340 return NOTIFY_DONE;
341}
342
343static struct notifier_block rockchip_restart_handler = {
344 .notifier_call = rockchip_restart_notify,
345 .priority = 128,
346};
347
348void __init rockchip_register_restart_notifier(unsigned int reg)
349{
350 int ret;
351
352 reg_restart = reg;
353 ret = register_restart_handler(&rockchip_restart_handler);
354 if (ret)
355 pr_err("%s: cannot register restart handler, %d\n",
356 __func__, ret);
357}
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 887cbdeca2aa..ca009ab0a33a 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -120,6 +120,38 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
120 struct rockchip_pll_rate_table *rate_table, 120 struct rockchip_pll_rate_table *rate_table,
121 spinlock_t *lock); 121 spinlock_t *lock);
122 122
123struct rockchip_cpuclk_clksel {
124 int reg;
125 u32 val;
126};
127
128#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2
129struct rockchip_cpuclk_rate_table {
130 unsigned long prate;
131 struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
132};
133
134/**
135 * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock
136 * @core_reg: register offset of the core settings register
137 * @div_core_shift: core divider offset used to divide the pll value
138 * @div_core_mask: core divider mask
139 * @mux_core_shift: offset of the core multiplexer
140 */
141struct rockchip_cpuclk_reg_data {
142 int core_reg;
143 u8 div_core_shift;
144 u32 div_core_mask;
145 int mux_core_reg;
146 u8 mux_core_shift;
147};
148
149struct clk *rockchip_clk_register_cpuclk(const char *name,
150 const char **parent_names, u8 num_parents,
151 const struct rockchip_cpuclk_reg_data *reg_data,
152 const struct rockchip_cpuclk_rate_table *rates,
153 int nrates, void __iomem *reg_base, spinlock_t *lock);
154
123#define PNAME(x) static const char *x[] __initconst 155#define PNAME(x) static const char *x[] __initconst
124 156
125enum rockchip_clk_branch_type { 157enum rockchip_clk_branch_type {
@@ -329,6 +361,13 @@ void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
329 unsigned int nr_clk); 361 unsigned int nr_clk);
330void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list, 362void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
331 unsigned int nr_pll, int grf_lock_offset); 363 unsigned int nr_pll, int grf_lock_offset);
364void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
365 const char **parent_names, u8 num_parents,
366 const struct rockchip_cpuclk_reg_data *reg_data,
367 const struct rockchip_cpuclk_rate_table *rates,
368 int nrates);
369void rockchip_clk_protect_critical(const char *clocks[], int nclocks);
370void rockchip_register_restart_notifier(unsigned int reg);
332 371
333#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) 372#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0)
334 373
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 2949a556af8f..6fb4bc602e8a 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
17obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o 17obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
18obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o 18obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o
19obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o 19obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o
20obj-$(CONFIG_ARCH_S5PV210) += clk-s5pv210.o clk-s5pv210-audss.o
diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index dc85f8e7a2d7..6e6cca392082 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -110,7 +110,14 @@ enum exynos3250_plls {
110 nr_plls 110 nr_plls
111}; 111};
112 112
113/* list of PLLs in DMC block to be registered */
114enum exynos3250_dmc_plls {
115 bpll, epll,
116 nr_dmc_plls
117};
118
113static void __iomem *reg_base; 119static void __iomem *reg_base;
120static void __iomem *dmc_reg_base;
114 121
115/* 122/*
116 * Support for CMU save/restore across system suspends 123 * Support for CMU save/restore across system suspends
@@ -266,6 +273,7 @@ PNAME(group_sclk_cam_blk_p) = { "xxti", "xusbxti",
266 "none", "none", "none", 273 "none", "none", "none",
267 "none", "div_mpll_pre", 274 "none", "div_mpll_pre",
268 "mout_epll_user", "mout_vpll", 275 "mout_epll_user", "mout_vpll",
276 "none", "none", "none",
269 "div_cam_blk_320", }; 277 "div_cam_blk_320", };
270PNAME(group_sclk_fimd0_p) = { "xxti", "xusbxti", 278PNAME(group_sclk_fimd0_p) = { "xxti", "xusbxti",
271 "m_bitclkhsdiv4_2l", "none", 279 "m_bitclkhsdiv4_2l", "none",
@@ -353,8 +361,8 @@ static struct samsung_mux_clock mux_clks[] __initdata = {
353 361
354 /* SRC_FSYS */ 362 /* SRC_FSYS */
355 MUX(CLK_MOUT_TSADC, "mout_tsadc", group_sclk_p, SRC_FSYS, 28, 4), 363 MUX(CLK_MOUT_TSADC, "mout_tsadc", group_sclk_p, SRC_FSYS, 28, 4),
356 MUX(CLK_MOUT_MMC1, "mout_mmc1", group_sclk_p, SRC_FSYS, 4, 3), 364 MUX(CLK_MOUT_MMC1, "mout_mmc1", group_sclk_p, SRC_FSYS, 4, 4),
357 MUX(CLK_MOUT_MMC0, "mout_mmc0", group_sclk_p, SRC_FSYS, 0, 3), 365 MUX(CLK_MOUT_MMC0, "mout_mmc0", group_sclk_p, SRC_FSYS, 0, 4),
358 366
359 /* SRC_PERIL0 */ 367 /* SRC_PERIL0 */
360 MUX(CLK_MOUT_UART1, "mout_uart1", group_sclk_p, SRC_PERIL0, 4, 4), 368 MUX(CLK_MOUT_UART1, "mout_uart1", group_sclk_p, SRC_PERIL0, 4, 4),
@@ -423,7 +431,7 @@ static struct samsung_div_clock div_clks[] __initdata = {
423 DIV(CLK_DIV_SPI1_ISP, "div_spi1_isp", "mout_spi1_isp", DIV_ISP, 16, 4), 431 DIV(CLK_DIV_SPI1_ISP, "div_spi1_isp", "mout_spi1_isp", DIV_ISP, 16, 4),
424 DIV_F(CLK_DIV_SPI0_ISP_PRE, "div_spi0_isp_pre", "div_spi0_isp", 432 DIV_F(CLK_DIV_SPI0_ISP_PRE, "div_spi0_isp_pre", "div_spi0_isp",
425 DIV_ISP, 8, 8, CLK_SET_RATE_PARENT, 0), 433 DIV_ISP, 8, 8, CLK_SET_RATE_PARENT, 0),
426 DIV(CLK_DIV_SPI0_ISP, "div_spi0_isp", "mout_spi0_isp", DIV_ISP, 0, 4), 434 DIV(CLK_DIV_SPI0_ISP, "div_spi0_isp", "mout_spi0_isp", DIV_ISP, 4, 4),
427 435
428 /* DIV_FSYS0 */ 436 /* DIV_FSYS0 */
429 DIV_F(CLK_DIV_TSADC_PRE, "div_tsadc_pre", "div_tsadc", DIV_FSYS0, 8, 8, 437 DIV_F(CLK_DIV_TSADC_PRE, "div_tsadc_pre", "div_tsadc", DIV_FSYS0, 8, 8,
@@ -724,6 +732,25 @@ static struct samsung_pll_rate_table exynos3250_pll_rates[] = {
724 { /* sentinel */ } 732 { /* sentinel */ }
725}; 733};
726 734
735/* EPLL */
736static struct samsung_pll_rate_table exynos3250_epll_rates[] = {
737 PLL_36XX_RATE(800000000, 200, 3, 1, 0),
738 PLL_36XX_RATE(288000000, 96, 2, 2, 0),
739 PLL_36XX_RATE(192000000, 128, 2, 3, 0),
740 PLL_36XX_RATE(144000000, 96, 2, 3, 0),
741 PLL_36XX_RATE( 96000000, 128, 2, 4, 0),
742 PLL_36XX_RATE( 84000000, 112, 2, 4, 0),
743 PLL_36XX_RATE( 80000004, 106, 2, 4, 43691),
744 PLL_36XX_RATE( 73728000, 98, 2, 4, 19923),
745 PLL_36XX_RATE( 67737598, 270, 3, 5, 62285),
746 PLL_36XX_RATE( 65535999, 174, 2, 5, 49982),
747 PLL_36XX_RATE( 50000000, 200, 3, 5, 0),
748 PLL_36XX_RATE( 49152002, 131, 2, 5, 4719),
749 PLL_36XX_RATE( 48000000, 128, 2, 5, 0),
750 PLL_36XX_RATE( 45158401, 180, 3, 5, 41524),
751 { /* sentinel */ }
752};
753
727/* VPLL */ 754/* VPLL */
728static struct samsung_pll_rate_table exynos3250_vpll_rates[] = { 755static struct samsung_pll_rate_table exynos3250_vpll_rates[] = {
729 PLL_36XX_RATE(600000000, 100, 2, 1, 0), 756 PLL_36XX_RATE(600000000, 100, 2, 1, 0),
@@ -821,3 +848,172 @@ static void __init exynos3250_cmu_init(struct device_node *np)
821 samsung_clk_of_add_provider(np, ctx); 848 samsung_clk_of_add_provider(np, ctx);
822} 849}
823CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init); 850CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init);
851
852/*
853 * CMU DMC
854 */
855
856#define BPLL_LOCK 0x0118
857#define BPLL_CON0 0x0218
858#define BPLL_CON1 0x021c
859#define BPLL_CON2 0x0220
860#define SRC_DMC 0x0300
861#define DIV_DMC1 0x0504
862#define GATE_BUS_DMC0 0x0700
863#define GATE_BUS_DMC1 0x0704
864#define GATE_BUS_DMC2 0x0708
865#define GATE_BUS_DMC3 0x070c
866#define GATE_SCLK_DMC 0x0800
867#define GATE_IP_DMC0 0x0900
868#define GATE_IP_DMC1 0x0904
869#define EPLL_LOCK 0x1110
870#define EPLL_CON0 0x1114
871#define EPLL_CON1 0x1118
872#define EPLL_CON2 0x111c
873#define SRC_EPLL 0x1120
874
875/*
876 * Support for CMU save/restore across system suspends
877 */
878#ifdef CONFIG_PM_SLEEP
879static struct samsung_clk_reg_dump *exynos3250_dmc_clk_regs;
880
881static unsigned long exynos3250_cmu_dmc_clk_regs[] __initdata = {
882 BPLL_LOCK,
883 BPLL_CON0,
884 BPLL_CON1,
885 BPLL_CON2,
886 SRC_DMC,
887 DIV_DMC1,
888 GATE_BUS_DMC0,
889 GATE_BUS_DMC1,
890 GATE_BUS_DMC2,
891 GATE_BUS_DMC3,
892 GATE_SCLK_DMC,
893 GATE_IP_DMC0,
894 GATE_IP_DMC1,
895 EPLL_LOCK,
896 EPLL_CON0,
897 EPLL_CON1,
898 EPLL_CON2,
899 SRC_EPLL,
900};
901
902static int exynos3250_dmc_clk_suspend(void)
903{
904 samsung_clk_save(dmc_reg_base, exynos3250_dmc_clk_regs,
905 ARRAY_SIZE(exynos3250_cmu_dmc_clk_regs));
906 return 0;
907}
908
909static void exynos3250_dmc_clk_resume(void)
910{
911 samsung_clk_restore(dmc_reg_base, exynos3250_dmc_clk_regs,
912 ARRAY_SIZE(exynos3250_cmu_dmc_clk_regs));
913}
914
915static struct syscore_ops exynos3250_dmc_clk_syscore_ops = {
916 .suspend = exynos3250_dmc_clk_suspend,
917 .resume = exynos3250_dmc_clk_resume,
918};
919
920static void exynos3250_dmc_clk_sleep_init(void)
921{
922 exynos3250_dmc_clk_regs =
923 samsung_clk_alloc_reg_dump(exynos3250_cmu_dmc_clk_regs,
924 ARRAY_SIZE(exynos3250_cmu_dmc_clk_regs));
925 if (!exynos3250_dmc_clk_regs) {
926 pr_warn("%s: Failed to allocate sleep save data\n", __func__);
927 goto err;
928 }
929
930 register_syscore_ops(&exynos3250_dmc_clk_syscore_ops);
931 return;
932err:
933 kfree(exynos3250_dmc_clk_regs);
934}
935#else
936static inline void exynos3250_dmc_clk_sleep_init(void) { }
937#endif
938
939PNAME(mout_epll_p) = { "fin_pll", "fout_epll", };
940PNAME(mout_bpll_p) = { "fin_pll", "fout_bpll", };
941PNAME(mout_mpll_mif_p) = { "fin_pll", "sclk_mpll_mif", };
942PNAME(mout_dphy_p) = { "mout_mpll_mif", "mout_bpll", };
943
944static struct samsung_mux_clock dmc_mux_clks[] __initdata = {
945 /*
946 * NOTE: Following table is sorted by register address in ascending
947 * order and then bitfield shift in descending order, as it is done
948 * in the User's Manual. When adding new entries, please make sure
949 * that the order is preserved, to avoid merge conflicts and make
950 * further work with defined data easier.
951 */
952
953 /* SRC_DMC */
954 MUX(CLK_MOUT_MPLL_MIF, "mout_mpll_mif", mout_mpll_mif_p, SRC_DMC, 12, 1),
955 MUX(CLK_MOUT_BPLL, "mout_bpll", mout_bpll_p, SRC_DMC, 10, 1),
956 MUX(CLK_MOUT_DPHY, "mout_dphy", mout_dphy_p, SRC_DMC, 8, 1),
957 MUX(CLK_MOUT_DMC_BUS, "mout_dmc_bus", mout_dphy_p, SRC_DMC, 4, 1),
958
959 /* SRC_EPLL */
960 MUX(CLK_MOUT_EPLL, "mout_epll", mout_epll_p, SRC_EPLL, 4, 1),
961};
962
963static struct samsung_div_clock dmc_div_clks[] __initdata = {
964 /*
965 * NOTE: Following table is sorted by register address in ascending
966 * order and then bitfield shift in descending order, as it is done
967 * in the User's Manual. When adding new entries, please make sure
968 * that the order is preserved, to avoid merge conflicts and make
969 * further work with defined data easier.
970 */
971
972 /* DIV_DMC1 */
973 DIV(CLK_DIV_DMC, "div_dmc", "div_dmc_pre", DIV_DMC1, 27, 3),
974 DIV(CLK_DIV_DPHY, "div_dphy", "mout_dphy", DIV_DMC1, 23, 3),
975 DIV(CLK_DIV_DMC_PRE, "div_dmc_pre", "mout_dmc_bus", DIV_DMC1, 19, 2),
976 DIV(CLK_DIV_DMCP, "div_dmcp", "div_dmcd", DIV_DMC1, 15, 3),
977 DIV(CLK_DIV_DMCD, "div_dmcd", "div_dmc", DIV_DMC1, 11, 3),
978};
979
980static struct samsung_pll_clock exynos3250_dmc_plls[nr_dmc_plls] __initdata = {
981 [bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll",
982 BPLL_LOCK, BPLL_CON0, NULL),
983 [epll] = PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
984 EPLL_LOCK, EPLL_CON0, NULL),
985};
986
987static void __init exynos3250_cmu_dmc_init(struct device_node *np)
988{
989 struct samsung_clk_provider *ctx;
990
991 dmc_reg_base = of_iomap(np, 0);
992 if (!dmc_reg_base)
993 panic("%s: failed to map registers\n", __func__);
994
995 ctx = samsung_clk_init(np, dmc_reg_base, NR_CLKS_DMC);
996 if (!ctx)
997 panic("%s: unable to allocate context.\n", __func__);
998
999 exynos3250_dmc_plls[bpll].rate_table = exynos3250_pll_rates;
1000 exynos3250_dmc_plls[epll].rate_table = exynos3250_epll_rates;
1001
1002 pr_err("CLK registering epll bpll: %d, %d, %d, %d\n",
1003 exynos3250_dmc_plls[bpll].rate_table[0].rate,
1004 exynos3250_dmc_plls[bpll].rate_table[0].mdiv,
1005 exynos3250_dmc_plls[bpll].rate_table[0].pdiv,
1006 exynos3250_dmc_plls[bpll].rate_table[0].sdiv
1007 );
1008 samsung_clk_register_pll(ctx, exynos3250_dmc_plls,
1009 ARRAY_SIZE(exynos3250_dmc_plls), dmc_reg_base);
1010
1011 samsung_clk_register_mux(ctx, dmc_mux_clks, ARRAY_SIZE(dmc_mux_clks));
1012 samsung_clk_register_div(ctx, dmc_div_clks, ARRAY_SIZE(dmc_div_clks));
1013
1014 exynos3250_dmc_clk_sleep_init();
1015
1016 samsung_clk_of_add_provider(np, ctx);
1017}
1018CLK_OF_DECLARE(exynos3250_cmu_dmc, "samsung,exynos3250-cmu-dmc",
1019 exynos3250_cmu_dmc_init);
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index ac163d7f5bc3..940f02837b82 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -517,7 +517,7 @@ static struct samsung_fixed_factor_clock exynos4_fixed_factor_clks[] __initdata
517 FFACTOR(0, "sclk_apll_div_2", "sclk_apll", 1, 2, 0), 517 FFACTOR(0, "sclk_apll_div_2", "sclk_apll", 1, 2, 0),
518 FFACTOR(0, "fout_mpll_div_2", "fout_mpll", 1, 2, 0), 518 FFACTOR(0, "fout_mpll_div_2", "fout_mpll", 1, 2, 0),
519 FFACTOR(0, "fout_apll_div_2", "fout_apll", 1, 2, 0), 519 FFACTOR(0, "fout_apll_div_2", "fout_apll", 1, 2, 0),
520 FFACTOR(0, "arm_clk_div_2", "arm_clk", 1, 2, 0), 520 FFACTOR(0, "arm_clk_div_2", "div_core2", 1, 2, 0),
521}; 521};
522 522
523static struct samsung_fixed_factor_clock exynos4210_fixed_factor_clks[] __initdata = { 523static struct samsung_fixed_factor_clock exynos4210_fixed_factor_clks[] __initdata = {
@@ -535,7 +535,7 @@ static struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initda
535static struct samsung_mux_clock exynos4_mux_clks[] __initdata = { 535static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
536 MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, 536 MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
537 CLK_SET_RATE_PARENT, 0, "mout_apll"), 537 CLK_SET_RATE_PARENT, 0, "mout_apll"),
538 MUX(0, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1), 538 MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1),
539 MUX(0, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1), 539 MUX(0, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1),
540 MUX(0, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1), 540 MUX(0, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1),
541 MUX_F(CLK_MOUT_G3D1, "mout_g3d1", sclk_evpll_p, SRC_G3D, 4, 1, 541 MUX_F(CLK_MOUT_G3D1, "mout_g3d1", sclk_evpll_p, SRC_G3D, 4, 1,
@@ -569,7 +569,7 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
569 MUX(0, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1), 569 MUX(0, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1),
570 MUX(0, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1), 570 MUX(0, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1),
571 MUX(0, "mout_aclk133", sclk_ampll_p4210, SRC_TOP0, 24, 1), 571 MUX(0, "mout_aclk133", sclk_ampll_p4210, SRC_TOP0, 24, 1),
572 MUX(0, "mout_mixer", mout_mixer_p4210, SRC_TV, 4, 1), 572 MUX(CLK_MOUT_MIXER, "mout_mixer", mout_mixer_p4210, SRC_TV, 4, 1),
573 MUX(0, "mout_dac", mout_dac_p4210, SRC_TV, 8, 1), 573 MUX(0, "mout_dac", mout_dac_p4210, SRC_TV, 8, 1),
574 MUX(0, "mout_g2d0", sclk_ampll_p4210, E4210_SRC_IMAGE, 0, 1), 574 MUX(0, "mout_g2d0", sclk_ampll_p4210, E4210_SRC_IMAGE, 0, 1),
575 MUX(0, "mout_g2d1", sclk_evpll_p, E4210_SRC_IMAGE, 4, 1), 575 MUX(0, "mout_g2d1", sclk_evpll_p, E4210_SRC_IMAGE, 4, 1),
@@ -719,7 +719,7 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
719 DIV(0, "div_periph", "div_core2", DIV_CPU0, 12, 3), 719 DIV(0, "div_periph", "div_core2", DIV_CPU0, 12, 3),
720 DIV(0, "div_atb", "mout_core", DIV_CPU0, 16, 3), 720 DIV(0, "div_atb", "mout_core", DIV_CPU0, 16, 3),
721 DIV(0, "div_pclk_dbg", "div_atb", DIV_CPU0, 20, 3), 721 DIV(0, "div_pclk_dbg", "div_atb", DIV_CPU0, 20, 3),
722 DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3), 722 DIV(CLK_ARM_CLK, "div_core2", "div_core", DIV_CPU0, 28, 3),
723 DIV(0, "div_copy", "mout_hpm", DIV_CPU1, 0, 3), 723 DIV(0, "div_copy", "mout_hpm", DIV_CPU1, 0, 3),
724 DIV(0, "div_hpm", "div_copy", DIV_CPU1, 4, 3), 724 DIV(0, "div_hpm", "div_copy", DIV_CPU1, 4, 3),
725 DIV(0, "div_clkout_cpu", "mout_clkout_cpu", CLKOUT_CMU_CPU, 8, 6), 725 DIV(0, "div_clkout_cpu", "mout_clkout_cpu", CLKOUT_CMU_CPU, 8, 6),
@@ -733,8 +733,7 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
733 DIV(0, "div_csis0", "mout_csis0", DIV_CAM, 24, 4), 733 DIV(0, "div_csis0", "mout_csis0", DIV_CAM, 24, 4),
734 DIV(0, "div_csis1", "mout_csis1", DIV_CAM, 28, 4), 734 DIV(0, "div_csis1", "mout_csis1", DIV_CAM, 28, 4),
735 DIV(CLK_SCLK_MFC, "sclk_mfc", "mout_mfc", DIV_MFC, 0, 4), 735 DIV(CLK_SCLK_MFC, "sclk_mfc", "mout_mfc", DIV_MFC, 0, 4),
736 DIV_F(0, "div_g3d", "mout_g3d", DIV_G3D, 0, 4, 736 DIV(CLK_SCLK_G3D, "sclk_g3d", "mout_g3d", DIV_G3D, 0, 4),
737 CLK_SET_RATE_PARENT, 0),
738 DIV(0, "div_fimd0", "mout_fimd0", DIV_LCD0, 0, 4), 737 DIV(0, "div_fimd0", "mout_fimd0", DIV_LCD0, 0, 4),
739 DIV(0, "div_mipi0", "mout_mipi0", DIV_LCD0, 16, 4), 738 DIV(0, "div_mipi0", "mout_mipi0", DIV_LCD0, 16, 4),
740 DIV(0, "div_audio0", "mout_audio0", DIV_MAUDIO, 0, 4), 739 DIV(0, "div_audio0", "mout_audio0", DIV_MAUDIO, 0, 4),
@@ -769,7 +768,6 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
769 DIV(0, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8), 768 DIV(0, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8),
770 DIV(0, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4), 769 DIV(0, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4),
771 DIV(0, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4), 770 DIV(0, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4),
772 DIV(CLK_ARM_CLK, "arm_clk", "div_core2", DIV_CPU0, 28, 3),
773 DIV(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3), 771 DIV(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
774 DIV_F(0, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4, 772 DIV_F(0, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
775 CLK_SET_RATE_PARENT, 0), 773 CLK_SET_RATE_PARENT, 0),
@@ -857,8 +855,7 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
857 0), 855 0),
858 GATE(CLK_TSI, "tsi", "aclk133", GATE_IP_FSYS, 4, 0, 0), 856 GATE(CLK_TSI, "tsi", "aclk133", GATE_IP_FSYS, 4, 0, 0),
859 GATE(CLK_SROMC, "sromc", "aclk133", GATE_IP_FSYS, 11, 0, 0), 857 GATE(CLK_SROMC, "sromc", "aclk133", GATE_IP_FSYS, 11, 0, 0),
860 GATE(CLK_SCLK_G3D, "sclk_g3d", "div_g3d", GATE_IP_G3D, 0, 858 GATE(CLK_G3D, "g3d", "aclk200", GATE_IP_G3D, 0, 0, 0),
861 CLK_SET_RATE_PARENT, 0),
862 GATE(CLK_PPMUG3D, "ppmug3d", "aclk200", GATE_IP_G3D, 1, 0, 0), 859 GATE(CLK_PPMUG3D, "ppmug3d", "aclk200", GATE_IP_G3D, 1, 0, 0),
863 GATE(CLK_USB_DEVICE, "usb_device", "aclk133", GATE_IP_FSYS, 13, 0, 0), 860 GATE(CLK_USB_DEVICE, "usb_device", "aclk133", GATE_IP_FSYS, 13, 0, 0),
864 GATE(CLK_ONENAND, "onenand", "aclk133", GATE_IP_FSYS, 15, 0, 0), 861 GATE(CLK_ONENAND, "onenand", "aclk133", GATE_IP_FSYS, 15, 0, 0),
@@ -1183,6 +1180,7 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
1183 GATE(CLK_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13, 1180 GATE(CLK_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
1184 CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), 1181 CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
1185 GATE(CLK_G2D, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0), 1182 GATE(CLK_G2D, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0),
1183 GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", GATE_IP_DMC, 24, 0, 0),
1186 GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0, 1184 GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0,
1187 0), 1185 0),
1188}; 1186};
@@ -1486,7 +1484,7 @@ static void __init exynos4_clk_init(struct device_node *np,
1486 exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12", 1484 exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
1487 _get_rate("sclk_apll"), _get_rate("sclk_mpll"), 1485 _get_rate("sclk_apll"), _get_rate("sclk_mpll"),
1488 _get_rate("sclk_epll"), _get_rate("sclk_vpll"), 1486 _get_rate("sclk_epll"), _get_rate("sclk_vpll"),
1489 _get_rate("arm_clk")); 1487 _get_rate("div_core2"));
1490} 1488}
1491 1489
1492 1490
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
index ce3de97e5f11..2527e39aadcf 100644
--- a/drivers/clk/samsung/clk-exynos5260.c
+++ b/drivers/clk/samsung/clk-exynos5260.c
@@ -1581,7 +1581,7 @@ struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = {
1581 FRATE(PHYCLK_HDMI_LINK_O_TMDS_CLKHI, "phyclk_hdmi_link_o_tmds_clkhi", 1581 FRATE(PHYCLK_HDMI_LINK_O_TMDS_CLKHI, "phyclk_hdmi_link_o_tmds_clkhi",
1582 NULL, CLK_IS_ROOT, 125000000), 1582 NULL, CLK_IS_ROOT, 125000000),
1583 FRATE(PHYCLK_MIPI_DPHY_4L_M_TXBYTECLKHS, 1583 FRATE(PHYCLK_MIPI_DPHY_4L_M_TXBYTECLKHS,
1584 "phyclk_mipi_dphy_4l_m_txbyteclkhs" , NULL, 1584 "phyclk_mipi_dphy_4l_m_txbyte_clkhs" , NULL,
1585 CLK_IS_ROOT, 187500000), 1585 CLK_IS_ROOT, 187500000),
1586 FRATE(PHYCLK_DPTX_PHY_O_REF_CLK_24M, "phyclk_dptx_phy_o_ref_clk_24m", 1586 FRATE(PHYCLK_DPTX_PHY_O_REF_CLK_24M, "phyclk_dptx_phy_o_ref_clk_24m",
1587 NULL, CLK_IS_ROOT, 24000000), 1587 NULL, CLK_IS_ROOT, 24000000),
diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c
index 0449cc0458ed..f4f29ed6bd25 100644
--- a/drivers/clk/samsung/clk-s3c2410-dclk.c
+++ b/drivers/clk/samsung/clk-s3c2410-dclk.c
@@ -426,7 +426,6 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_dclk_driver_ids);
426static struct platform_driver s3c24xx_dclk_driver = { 426static struct platform_driver s3c24xx_dclk_driver = {
427 .driver = { 427 .driver = {
428 .name = "s3c24xx-dclk", 428 .name = "s3c24xx-dclk",
429 .owner = THIS_MODULE,
430 .pm = &s3c24xx_dclk_pm_ops, 429 .pm = &s3c24xx_dclk_pm_ops,
431 }, 430 },
432 .probe = s3c24xx_dclk_probe, 431 .probe = s3c24xx_dclk_probe,
diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c
index 34af09f6a155..2ceedaf8ce18 100644
--- a/drivers/clk/samsung/clk-s3c2412.c
+++ b/drivers/clk/samsung/clk-s3c2412.c
@@ -14,6 +14,7 @@
14#include <linux/of.h> 14#include <linux/of.h>
15#include <linux/of_address.h> 15#include <linux/of_address.h>
16#include <linux/syscore_ops.h> 16#include <linux/syscore_ops.h>
17#include <linux/reboot.h>
17 18
18#include <dt-bindings/clock/s3c2412.h> 19#include <dt-bindings/clock/s3c2412.h>
19 20
@@ -26,6 +27,7 @@
26#define CLKCON 0x0c 27#define CLKCON 0x0c
27#define CLKDIVN 0x14 28#define CLKDIVN 0x14
28#define CLKSRC 0x1c 29#define CLKSRC 0x1c
30#define SWRST 0x30
29 31
30/* list of PLLs to be registered */ 32/* list of PLLs to be registered */
31enum s3c2412_plls { 33enum s3c2412_plls {
@@ -204,6 +206,28 @@ struct samsung_clock_alias s3c2412_aliases[] __initdata = {
204 ALIAS(MSYSCLK, NULL, "fclk"), 206 ALIAS(MSYSCLK, NULL, "fclk"),
205}; 207};
206 208
209static int s3c2412_restart(struct notifier_block *this,
210 unsigned long mode, void *cmd)
211{
212 /* errata "Watch-dog/Software Reset Problem" specifies that
213 * this reset must be done with the SYSCLK sourced from
214 * EXTCLK instead of FOUT to avoid a glitch in the reset
215 * mechanism.
216 *
217 * See the watchdog section of the S3C2412 manual for more
218 * information on this fix.
219 */
220
221 __raw_writel(0x00, reg_base + CLKSRC);
222 __raw_writel(0x533C2412, reg_base + SWRST);
223 return NOTIFY_DONE;
224}
225
226static struct notifier_block s3c2412_restart_handler = {
227 .notifier_call = s3c2412_restart,
228 .priority = 129,
229};
230
207/* 231/*
208 * fixed rate clocks generated outside the soc 232 * fixed rate clocks generated outside the soc
209 * Only necessary until the devicetree-move is complete 233 * Only necessary until the devicetree-move is complete
@@ -233,6 +257,7 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
233 unsigned long ext_f, void __iomem *base) 257 unsigned long ext_f, void __iomem *base)
234{ 258{
235 struct samsung_clk_provider *ctx; 259 struct samsung_clk_provider *ctx;
260 int ret;
236 reg_base = base; 261 reg_base = base;
237 262
238 if (np) { 263 if (np) {
@@ -267,6 +292,10 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
267 s3c2412_clk_sleep_init(); 292 s3c2412_clk_sleep_init();
268 293
269 samsung_clk_of_add_provider(np, ctx); 294 samsung_clk_of_add_provider(np, ctx);
295
296 ret = register_restart_handler(&s3c2412_restart_handler);
297 if (ret)
298 pr_warn("cannot register restart handler, %d\n", ret);
270} 299}
271 300
272static void __init s3c2412_clk_init(struct device_node *np) 301static void __init s3c2412_clk_init(struct device_node *np)
diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c
index c92f853fca9f..0c3c182b902a 100644
--- a/drivers/clk/samsung/clk-s3c2443.c
+++ b/drivers/clk/samsung/clk-s3c2443.c
@@ -14,6 +14,7 @@
14#include <linux/of.h> 14#include <linux/of.h>
15#include <linux/of_address.h> 15#include <linux/of_address.h>
16#include <linux/syscore_ops.h> 16#include <linux/syscore_ops.h>
17#include <linux/reboot.h>
17 18
18#include <dt-bindings/clock/s3c2443.h> 19#include <dt-bindings/clock/s3c2443.h>
19 20
@@ -33,6 +34,7 @@
33#define HCLKCON 0x30 34#define HCLKCON 0x30
34#define PCLKCON 0x34 35#define PCLKCON 0x34
35#define SCLKCON 0x38 36#define SCLKCON 0x38
37#define SWRST 0x44
36 38
37/* the soc types */ 39/* the soc types */
38enum supported_socs { 40enum supported_socs {
@@ -354,6 +356,18 @@ struct samsung_clock_alias s3c2450_aliases[] __initdata = {
354 ALIAS(PCLK_I2C1, "s3c2410-i2c.1", "i2c"), 356 ALIAS(PCLK_I2C1, "s3c2410-i2c.1", "i2c"),
355}; 357};
356 358
359static int s3c2443_restart(struct notifier_block *this,
360 unsigned long mode, void *cmd)
361{
362 __raw_writel(0x533c2443, reg_base + SWRST);
363 return NOTIFY_DONE;
364}
365
366static struct notifier_block s3c2443_restart_handler = {
367 .notifier_call = s3c2443_restart,
368 .priority = 129,
369};
370
357/* 371/*
358 * fixed rate clocks generated outside the soc 372 * fixed rate clocks generated outside the soc
359 * Only necessary until the devicetree-move is complete 373 * Only necessary until the devicetree-move is complete
@@ -378,6 +392,7 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
378 void __iomem *base) 392 void __iomem *base)
379{ 393{
380 struct samsung_clk_provider *ctx; 394 struct samsung_clk_provider *ctx;
395 int ret;
381 reg_base = base; 396 reg_base = base;
382 397
383 if (np) { 398 if (np) {
@@ -447,6 +462,10 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
447 s3c2443_clk_sleep_init(); 462 s3c2443_clk_sleep_init();
448 463
449 samsung_clk_of_add_provider(np, ctx); 464 samsung_clk_of_add_provider(np, ctx);
465
466 ret = register_restart_handler(&s3c2443_restart_handler);
467 if (ret)
468 pr_warn("cannot register restart handler, %d\n", ret);
450} 469}
451 470
452static void __init s3c2416_clk_init(struct device_node *np) 471static void __init s3c2416_clk_init(struct device_node *np)
diff --git a/drivers/clk/samsung/clk-s5pv210-audss.c b/drivers/clk/samsung/clk-s5pv210-audss.c
new file mode 100644
index 000000000000..a8053b4aca56
--- /dev/null
+++ b/drivers/clk/samsung/clk-s5pv210-audss.c
@@ -0,0 +1,241 @@
1/*
2 * Copyright (c) 2014 Tomasz Figa <t.figa@samsung.com>
3 *
4 * Based on Exynos Audio Subsystem Clock Controller driver:
5 *
6 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
7 * Author: Padmavathi Venna <padma.v@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * Driver for Audio Subsystem Clock Controller of S5PV210-compatible SoCs.
14*/
15
16#include <linux/clkdev.h>
17#include <linux/io.h>
18#include <linux/clk-provider.h>
19#include <linux/of_address.h>
20#include <linux/syscore_ops.h>
21#include <linux/module.h>
22#include <linux/platform_device.h>
23
24#include <dt-bindings/clock/s5pv210-audss.h>
25
26static DEFINE_SPINLOCK(lock);
27static struct clk **clk_table;
28static void __iomem *reg_base;
29static struct clk_onecell_data clk_data;
30
31#define ASS_CLK_SRC 0x0
32#define ASS_CLK_DIV 0x4
33#define ASS_CLK_GATE 0x8
34
35#ifdef CONFIG_PM_SLEEP
36static unsigned long reg_save[][2] = {
37 {ASS_CLK_SRC, 0},
38 {ASS_CLK_DIV, 0},
39 {ASS_CLK_GATE, 0},
40};
41
42static int s5pv210_audss_clk_suspend(void)
43{
44 int i;
45
46 for (i = 0; i < ARRAY_SIZE(reg_save); i++)
47 reg_save[i][1] = readl(reg_base + reg_save[i][0]);
48
49 return 0;
50}
51
52static void s5pv210_audss_clk_resume(void)
53{
54 int i;
55
56 for (i = 0; i < ARRAY_SIZE(reg_save); i++)
57 writel(reg_save[i][1], reg_base + reg_save[i][0]);
58}
59
60static struct syscore_ops s5pv210_audss_clk_syscore_ops = {
61 .suspend = s5pv210_audss_clk_suspend,
62 .resume = s5pv210_audss_clk_resume,
63};
64#endif /* CONFIG_PM_SLEEP */
65
66/* register s5pv210_audss clocks */
67static int s5pv210_audss_clk_probe(struct platform_device *pdev)
68{
69 int i, ret = 0;
70 struct resource *res;
71 const char *mout_audss_p[2];
72 const char *mout_i2s_p[3];
73 const char *hclk_p;
74 struct clk *hclk, *pll_ref, *pll_in, *cdclk, *sclk_audio;
75
76 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
77 reg_base = devm_ioremap_resource(&pdev->dev, res);
78 if (IS_ERR(reg_base)) {
79 dev_err(&pdev->dev, "failed to map audss registers\n");
80 return PTR_ERR(reg_base);
81 }
82
83 clk_table = devm_kzalloc(&pdev->dev,
84 sizeof(struct clk *) * AUDSS_MAX_CLKS,
85 GFP_KERNEL);
86 if (!clk_table)
87 return -ENOMEM;
88
89 clk_data.clks = clk_table;
90 clk_data.clk_num = AUDSS_MAX_CLKS;
91
92 hclk = devm_clk_get(&pdev->dev, "hclk");
93 if (IS_ERR(hclk)) {
94 dev_err(&pdev->dev, "failed to get hclk clock\n");
95 return PTR_ERR(hclk);
96 }
97
98 pll_in = devm_clk_get(&pdev->dev, "fout_epll");
99 if (IS_ERR(pll_in)) {
100 dev_err(&pdev->dev, "failed to get fout_epll clock\n");
101 return PTR_ERR(pll_in);
102 }
103
104 sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio0");
105 if (IS_ERR(sclk_audio)) {
106 dev_err(&pdev->dev, "failed to get sclk_audio0 clock\n");
107 return PTR_ERR(sclk_audio);
108 }
109
110 /* iiscdclk0 is an optional external I2S codec clock */
111 cdclk = devm_clk_get(&pdev->dev, "iiscdclk0");
112 pll_ref = devm_clk_get(&pdev->dev, "xxti");
113
114 if (!IS_ERR(pll_ref))
115 mout_audss_p[0] = __clk_get_name(pll_ref);
116 else
117 mout_audss_p[0] = "xxti";
118 mout_audss_p[1] = __clk_get_name(pll_in);
119 clk_table[CLK_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
120 mout_audss_p, ARRAY_SIZE(mout_audss_p),
121 CLK_SET_RATE_NO_REPARENT,
122 reg_base + ASS_CLK_SRC, 0, 1, 0, &lock);
123
124 mout_i2s_p[0] = "mout_audss";
125 if (!IS_ERR(cdclk))
126 mout_i2s_p[1] = __clk_get_name(cdclk);
127 else
128 mout_i2s_p[1] = "iiscdclk0";
129 mout_i2s_p[2] = __clk_get_name(sclk_audio);
130 clk_table[CLK_MOUT_I2S_A] = clk_register_mux(NULL, "mout_i2s_audss",
131 mout_i2s_p, ARRAY_SIZE(mout_i2s_p),
132 CLK_SET_RATE_NO_REPARENT,
133 reg_base + ASS_CLK_SRC, 2, 2, 0, &lock);
134
135 clk_table[CLK_DOUT_AUD_BUS] = clk_register_divider(NULL,
136 "dout_aud_bus", "mout_audss", 0,
137 reg_base + ASS_CLK_DIV, 0, 4, 0, &lock);
138 clk_table[CLK_DOUT_I2S_A] = clk_register_divider(NULL, "dout_i2s_audss",
139 "mout_i2s_audss", 0, reg_base + ASS_CLK_DIV,
140 4, 4, 0, &lock);
141
142 clk_table[CLK_I2S] = clk_register_gate(NULL, "i2s_audss",
143 "dout_i2s_audss", CLK_SET_RATE_PARENT,
144 reg_base + ASS_CLK_GATE, 6, 0, &lock);
145
146 hclk_p = __clk_get_name(hclk);
147
148 clk_table[CLK_HCLK_I2S] = clk_register_gate(NULL, "hclk_i2s_audss",
149 hclk_p, CLK_IGNORE_UNUSED,
150 reg_base + ASS_CLK_GATE, 5, 0, &lock);
151 clk_table[CLK_HCLK_UART] = clk_register_gate(NULL, "hclk_uart_audss",
152 hclk_p, CLK_IGNORE_UNUSED,
153 reg_base + ASS_CLK_GATE, 4, 0, &lock);
154 clk_table[CLK_HCLK_HWA] = clk_register_gate(NULL, "hclk_hwa_audss",
155 hclk_p, CLK_IGNORE_UNUSED,
156 reg_base + ASS_CLK_GATE, 3, 0, &lock);
157 clk_table[CLK_HCLK_DMA] = clk_register_gate(NULL, "hclk_dma_audss",
158 hclk_p, CLK_IGNORE_UNUSED,
159 reg_base + ASS_CLK_GATE, 2, 0, &lock);
160 clk_table[CLK_HCLK_BUF] = clk_register_gate(NULL, "hclk_buf_audss",
161 hclk_p, CLK_IGNORE_UNUSED,
162 reg_base + ASS_CLK_GATE, 1, 0, &lock);
163 clk_table[CLK_HCLK_RP] = clk_register_gate(NULL, "hclk_rp_audss",
164 hclk_p, CLK_IGNORE_UNUSED,
165 reg_base + ASS_CLK_GATE, 0, 0, &lock);
166
167 for (i = 0; i < clk_data.clk_num; i++) {
168 if (IS_ERR(clk_table[i])) {
169 dev_err(&pdev->dev, "failed to register clock %d\n", i);
170 ret = PTR_ERR(clk_table[i]);
171 goto unregister;
172 }
173 }
174
175 ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
176 &clk_data);
177 if (ret) {
178 dev_err(&pdev->dev, "failed to add clock provider\n");
179 goto unregister;
180 }
181
182#ifdef CONFIG_PM_SLEEP
183 register_syscore_ops(&s5pv210_audss_clk_syscore_ops);
184#endif
185
186 return 0;
187
188unregister:
189 for (i = 0; i < clk_data.clk_num; i++) {
190 if (!IS_ERR(clk_table[i]))
191 clk_unregister(clk_table[i]);
192 }
193
194 return ret;
195}
196
197static int s5pv210_audss_clk_remove(struct platform_device *pdev)
198{
199 int i;
200
201 of_clk_del_provider(pdev->dev.of_node);
202
203 for (i = 0; i < clk_data.clk_num; i++) {
204 if (!IS_ERR(clk_table[i]))
205 clk_unregister(clk_table[i]);
206 }
207
208 return 0;
209}
210
211static const struct of_device_id s5pv210_audss_clk_of_match[] = {
212 { .compatible = "samsung,s5pv210-audss-clock", },
213 {},
214};
215
216static struct platform_driver s5pv210_audss_clk_driver = {
217 .driver = {
218 .name = "s5pv210-audss-clk",
219 .owner = THIS_MODULE,
220 .of_match_table = s5pv210_audss_clk_of_match,
221 },
222 .probe = s5pv210_audss_clk_probe,
223 .remove = s5pv210_audss_clk_remove,
224};
225
226static int __init s5pv210_audss_clk_init(void)
227{
228 return platform_driver_register(&s5pv210_audss_clk_driver);
229}
230core_initcall(s5pv210_audss_clk_init);
231
232static void __exit s5pv210_audss_clk_exit(void)
233{
234 platform_driver_unregister(&s5pv210_audss_clk_driver);
235}
236module_exit(s5pv210_audss_clk_exit);
237
238MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
239MODULE_DESCRIPTION("S5PV210 Audio Subsystem Clock Controller");
240MODULE_LICENSE("GPL v2");
241MODULE_ALIAS("platform:s5pv210-audss-clk");
diff --git a/drivers/clk/samsung/clk-s5pv210.c b/drivers/clk/samsung/clk-s5pv210.c
new file mode 100644
index 000000000000..d270a2084644
--- /dev/null
+++ b/drivers/clk/samsung/clk-s5pv210.c
@@ -0,0 +1,856 @@
1/*
2 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
3 * Author: Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
4 *
5 * Based on clock drivers for S3C64xx and Exynos4 SoCs.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Common Clock Framework support for all S5PC110/S5PV210 SoCs.
12 */
13
14#include <linux/clk.h>
15#include <linux/clkdev.h>
16#include <linux/clk-provider.h>
17#include <linux/of.h>
18#include <linux/of_address.h>
19#include <linux/syscore_ops.h>
20
21#include "clk.h"
22#include "clk-pll.h"
23
24#include <dt-bindings/clock/s5pv210.h>
25
26/* S5PC110/S5PV210 clock controller register offsets */
27#define APLL_LOCK 0x0000
28#define MPLL_LOCK 0x0008
29#define EPLL_LOCK 0x0010
30#define VPLL_LOCK 0x0020
31#define APLL_CON0 0x0100
32#define APLL_CON1 0x0104
33#define MPLL_CON 0x0108
34#define EPLL_CON0 0x0110
35#define EPLL_CON1 0x0114
36#define VPLL_CON 0x0120
37#define CLK_SRC0 0x0200
38#define CLK_SRC1 0x0204
39#define CLK_SRC2 0x0208
40#define CLK_SRC3 0x020c
41#define CLK_SRC4 0x0210
42#define CLK_SRC5 0x0214
43#define CLK_SRC6 0x0218
44#define CLK_SRC_MASK0 0x0280
45#define CLK_SRC_MASK1 0x0284
46#define CLK_DIV0 0x0300
47#define CLK_DIV1 0x0304
48#define CLK_DIV2 0x0308
49#define CLK_DIV3 0x030c
50#define CLK_DIV4 0x0310
51#define CLK_DIV5 0x0314
52#define CLK_DIV6 0x0318
53#define CLK_DIV7 0x031c
54#define CLK_GATE_MAIN0 0x0400
55#define CLK_GATE_MAIN1 0x0404
56#define CLK_GATE_MAIN2 0x0408
57#define CLK_GATE_PERI0 0x0420
58#define CLK_GATE_PERI1 0x0424
59#define CLK_GATE_SCLK0 0x0440
60#define CLK_GATE_SCLK1 0x0444
61#define CLK_GATE_IP0 0x0460
62#define CLK_GATE_IP1 0x0464
63#define CLK_GATE_IP2 0x0468
64#define CLK_GATE_IP3 0x046c
65#define CLK_GATE_IP4 0x0470
66#define CLK_GATE_BLOCK 0x0480
67#define CLK_GATE_IP5 0x0484
68#define CLK_OUT 0x0500
69#define MISC 0xe000
70#define OM_STAT 0xe100
71
72/* IDs of PLLs available on S5PV210/S5P6442 SoCs */
73enum {
74 apll,
75 mpll,
76 epll,
77 vpll,
78};
79
80/* IDs of external clocks (used for legacy boards) */
81enum {
82 xxti,
83 xusbxti,
84};
85
86static void __iomem *reg_base;
87
88#ifdef CONFIG_PM_SLEEP
89static struct samsung_clk_reg_dump *s5pv210_clk_dump;
90
91/* List of registers that need to be preserved across suspend/resume. */
92static unsigned long s5pv210_clk_regs[] __initdata = {
93 CLK_SRC0,
94 CLK_SRC1,
95 CLK_SRC2,
96 CLK_SRC3,
97 CLK_SRC4,
98 CLK_SRC5,
99 CLK_SRC6,
100 CLK_SRC_MASK0,
101 CLK_SRC_MASK1,
102 CLK_DIV0,
103 CLK_DIV1,
104 CLK_DIV2,
105 CLK_DIV3,
106 CLK_DIV4,
107 CLK_DIV5,
108 CLK_DIV6,
109 CLK_DIV7,
110 CLK_GATE_MAIN0,
111 CLK_GATE_MAIN1,
112 CLK_GATE_MAIN2,
113 CLK_GATE_PERI0,
114 CLK_GATE_PERI1,
115 CLK_GATE_SCLK0,
116 CLK_GATE_SCLK1,
117 CLK_GATE_IP0,
118 CLK_GATE_IP1,
119 CLK_GATE_IP2,
120 CLK_GATE_IP3,
121 CLK_GATE_IP4,
122 CLK_GATE_IP5,
123 CLK_GATE_BLOCK,
124 APLL_LOCK,
125 MPLL_LOCK,
126 EPLL_LOCK,
127 VPLL_LOCK,
128 APLL_CON0,
129 APLL_CON1,
130 MPLL_CON,
131 EPLL_CON0,
132 EPLL_CON1,
133 VPLL_CON,
134 CLK_OUT,
135};
136
137static int s5pv210_clk_suspend(void)
138{
139 samsung_clk_save(reg_base, s5pv210_clk_dump,
140 ARRAY_SIZE(s5pv210_clk_regs));
141 return 0;
142}
143
144static void s5pv210_clk_resume(void)
145{
146 samsung_clk_restore(reg_base, s5pv210_clk_dump,
147 ARRAY_SIZE(s5pv210_clk_regs));
148}
149
150static struct syscore_ops s5pv210_clk_syscore_ops = {
151 .suspend = s5pv210_clk_suspend,
152 .resume = s5pv210_clk_resume,
153};
154
155static void s5pv210_clk_sleep_init(void)
156{
157 s5pv210_clk_dump =
158 samsung_clk_alloc_reg_dump(s5pv210_clk_regs,
159 ARRAY_SIZE(s5pv210_clk_regs));
160 if (!s5pv210_clk_dump) {
161 pr_warn("%s: Failed to allocate sleep save data\n", __func__);
162 return;
163 }
164
165 register_syscore_ops(&s5pv210_clk_syscore_ops);
166}
167#else
168static inline void s5pv210_clk_sleep_init(void) { }
169#endif
170
171/* Mux parent lists. */
172static const char *fin_pll_p[] __initconst = {
173 "xxti",
174 "xusbxti"
175};
176
177static const char *mout_apll_p[] __initconst = {
178 "fin_pll",
179 "fout_apll"
180};
181
182static const char *mout_mpll_p[] __initconst = {
183 "fin_pll",
184 "fout_mpll"
185};
186
187static const char *mout_epll_p[] __initconst = {
188 "fin_pll",
189 "fout_epll"
190};
191
192static const char *mout_vpllsrc_p[] __initconst = {
193 "fin_pll",
194 "sclk_hdmi27m"
195};
196
197static const char *mout_vpll_p[] __initconst = {
198 "mout_vpllsrc",
199 "fout_vpll"
200};
201
202static const char *mout_group1_p[] __initconst = {
203 "dout_a2m",
204 "mout_mpll",
205 "mout_epll",
206 "mout_vpll"
207};
208
209static const char *mout_group2_p[] __initconst = {
210 "xxti",
211 "xusbxti",
212 "sclk_hdmi27m",
213 "sclk_usbphy0",
214 "sclk_usbphy1",
215 "sclk_hdmiphy",
216 "mout_mpll",
217 "mout_epll",
218 "mout_vpll",
219};
220
221static const char *mout_audio0_p[] __initconst = {
222 "xxti",
223 "pcmcdclk0",
224 "sclk_hdmi27m",
225 "sclk_usbphy0",
226 "sclk_usbphy1",
227 "sclk_hdmiphy",
228 "mout_mpll",
229 "mout_epll",
230 "mout_vpll",
231};
232
233static const char *mout_audio1_p[] __initconst = {
234 "i2scdclk1",
235 "pcmcdclk1",
236 "sclk_hdmi27m",
237 "sclk_usbphy0",
238 "sclk_usbphy1",
239 "sclk_hdmiphy",
240 "mout_mpll",
241 "mout_epll",
242 "mout_vpll",
243};
244
245static const char *mout_audio2_p[] __initconst = {
246 "i2scdclk2",
247 "pcmcdclk2",
248 "sclk_hdmi27m",
249 "sclk_usbphy0",
250 "sclk_usbphy1",
251 "sclk_hdmiphy",
252 "mout_mpll",
253 "mout_epll",
254 "mout_vpll",
255};
256
257static const char *mout_spdif_p[] __initconst = {
258 "dout_audio0",
259 "dout_audio1",
260 "dout_audio3",
261};
262
263static const char *mout_group3_p[] __initconst = {
264 "mout_apll",
265 "mout_mpll"
266};
267
268static const char *mout_group4_p[] __initconst = {
269 "mout_mpll",
270 "dout_a2m"
271};
272
273static const char *mout_flash_p[] __initconst = {
274 "dout_hclkd",
275 "dout_hclkp"
276};
277
278static const char *mout_dac_p[] __initconst = {
279 "mout_vpll",
280 "sclk_hdmiphy"
281};
282
283static const char *mout_hdmi_p[] __initconst = {
284 "sclk_hdmiphy",
285 "dout_tblk"
286};
287
288static const char *mout_mixer_p[] __initconst = {
289 "mout_dac",
290 "mout_hdmi"
291};
292
293static const char *mout_vpll_6442_p[] __initconst = {
294 "fin_pll",
295 "fout_vpll"
296};
297
298static const char *mout_mixer_6442_p[] __initconst = {
299 "mout_vpll",
300 "dout_mixer"
301};
302
303static const char *mout_d0sync_6442_p[] __initconst = {
304 "mout_dsys",
305 "div_apll"
306};
307
308static const char *mout_d1sync_6442_p[] __initconst = {
309 "mout_psys",
310 "div_apll"
311};
312
313static const char *mout_group2_6442_p[] __initconst = {
314 "fin_pll",
315 "none",
316 "none",
317 "sclk_usbphy0",
318 "none",
319 "none",
320 "mout_mpll",
321 "mout_epll",
322 "mout_vpll",
323};
324
325static const char *mout_audio0_6442_p[] __initconst = {
326 "fin_pll",
327 "pcmcdclk0",
328 "none",
329 "sclk_usbphy0",
330 "none",
331 "none",
332 "mout_mpll",
333 "mout_epll",
334 "mout_vpll",
335};
336
337static const char *mout_audio1_6442_p[] __initconst = {
338 "i2scdclk1",
339 "pcmcdclk1",
340 "none",
341 "sclk_usbphy0",
342 "none",
343 "none",
344 "mout_mpll",
345 "mout_epll",
346 "mout_vpll",
347 "fin_pll",
348};
349
350static const char *mout_clksel_p[] __initconst = {
351 "fout_apll_clkout",
352 "fout_mpll_clkout",
353 "fout_epll",
354 "fout_vpll",
355 "sclk_usbphy0",
356 "sclk_usbphy1",
357 "sclk_hdmiphy",
358 "rtc",
359 "rtc_tick",
360 "dout_hclkm",
361 "dout_pclkm",
362 "dout_hclkd",
363 "dout_pclkd",
364 "dout_hclkp",
365 "dout_pclkp",
366 "dout_apll_clkout",
367 "dout_hpm",
368 "xxti",
369 "xusbxti",
370 "div_dclk"
371};
372
373static const char *mout_clksel_6442_p[] __initconst = {
374 "fout_apll_clkout",
375 "fout_mpll_clkout",
376 "fout_epll",
377 "fout_vpll",
378 "sclk_usbphy0",
379 "none",
380 "none",
381 "rtc",
382 "rtc_tick",
383 "none",
384 "none",
385 "dout_hclkd",
386 "dout_pclkd",
387 "dout_hclkp",
388 "dout_pclkp",
389 "dout_apll_clkout",
390 "none",
391 "fin_pll",
392 "none",
393 "div_dclk"
394};
395
396static const char *mout_clkout_p[] __initconst = {
397 "dout_clkout",
398 "none",
399 "xxti",
400 "xusbxti"
401};
402
403/* Common fixed factor clocks. */
404static struct samsung_fixed_factor_clock ffactor_clks[] __initdata = {
405 FFACTOR(FOUT_APLL_CLKOUT, "fout_apll_clkout", "fout_apll", 1, 4, 0),
406 FFACTOR(FOUT_MPLL_CLKOUT, "fout_mpll_clkout", "fout_mpll", 1, 2, 0),
407 FFACTOR(DOUT_APLL_CLKOUT, "dout_apll_clkout", "dout_apll", 1, 4, 0),
408};
409
410/* PLL input mux (fin_pll), which needs to be registered before PLLs. */
411static struct samsung_mux_clock early_mux_clks[] __initdata = {
412 MUX_F(FIN_PLL, "fin_pll", fin_pll_p, OM_STAT, 0, 1,
413 CLK_MUX_READ_ONLY, 0),
414};
415
416/* Common clock muxes. */
417static struct samsung_mux_clock mux_clks[] __initdata = {
418 MUX(MOUT_FLASH, "mout_flash", mout_flash_p, CLK_SRC0, 28, 1),
419 MUX(MOUT_PSYS, "mout_psys", mout_group4_p, CLK_SRC0, 24, 1),
420 MUX(MOUT_DSYS, "mout_dsys", mout_group4_p, CLK_SRC0, 20, 1),
421 MUX(MOUT_MSYS, "mout_msys", mout_group3_p, CLK_SRC0, 16, 1),
422 MUX(MOUT_EPLL, "mout_epll", mout_epll_p, CLK_SRC0, 8, 1),
423 MUX(MOUT_MPLL, "mout_mpll", mout_mpll_p, CLK_SRC0, 4, 1),
424 MUX(MOUT_APLL, "mout_apll", mout_apll_p, CLK_SRC0, 0, 1),
425
426 MUX(MOUT_CLKOUT, "mout_clkout", mout_clkout_p, MISC, 8, 2),
427};
428
429/* S5PV210-specific clock muxes. */
430static struct samsung_mux_clock s5pv210_mux_clks[] __initdata = {
431 MUX(MOUT_VPLL, "mout_vpll", mout_vpll_p, CLK_SRC0, 12, 1),
432
433 MUX(MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, CLK_SRC1, 28, 1),
434 MUX(MOUT_CSIS, "mout_csis", mout_group2_p, CLK_SRC1, 24, 4),
435 MUX(MOUT_FIMD, "mout_fimd", mout_group2_p, CLK_SRC1, 20, 4),
436 MUX(MOUT_CAM1, "mout_cam1", mout_group2_p, CLK_SRC1, 16, 4),
437 MUX(MOUT_CAM0, "mout_cam0", mout_group2_p, CLK_SRC1, 12, 4),
438 MUX(MOUT_DAC, "mout_dac", mout_dac_p, CLK_SRC1, 8, 1),
439 MUX(MOUT_MIXER, "mout_mixer", mout_mixer_p, CLK_SRC1, 4, 1),
440 MUX(MOUT_HDMI, "mout_hdmi", mout_hdmi_p, CLK_SRC1, 0, 1),
441
442 MUX(MOUT_G2D, "mout_g2d", mout_group1_p, CLK_SRC2, 8, 2),
443 MUX(MOUT_MFC, "mout_mfc", mout_group1_p, CLK_SRC2, 4, 2),
444 MUX(MOUT_G3D, "mout_g3d", mout_group1_p, CLK_SRC2, 0, 2),
445
446 MUX(MOUT_FIMC2, "mout_fimc2", mout_group2_p, CLK_SRC3, 20, 4),
447 MUX(MOUT_FIMC1, "mout_fimc1", mout_group2_p, CLK_SRC3, 16, 4),
448 MUX(MOUT_FIMC0, "mout_fimc0", mout_group2_p, CLK_SRC3, 12, 4),
449
450 MUX(MOUT_UART3, "mout_uart3", mout_group2_p, CLK_SRC4, 28, 4),
451 MUX(MOUT_UART2, "mout_uart2", mout_group2_p, CLK_SRC4, 24, 4),
452 MUX(MOUT_UART1, "mout_uart1", mout_group2_p, CLK_SRC4, 20, 4),
453 MUX(MOUT_UART0, "mout_uart0", mout_group2_p, CLK_SRC4, 16, 4),
454 MUX(MOUT_MMC3, "mout_mmc3", mout_group2_p, CLK_SRC4, 12, 4),
455 MUX(MOUT_MMC2, "mout_mmc2", mout_group2_p, CLK_SRC4, 8, 4),
456 MUX(MOUT_MMC1, "mout_mmc1", mout_group2_p, CLK_SRC4, 4, 4),
457 MUX(MOUT_MMC0, "mout_mmc0", mout_group2_p, CLK_SRC4, 0, 4),
458
459 MUX(MOUT_PWM, "mout_pwm", mout_group2_p, CLK_SRC5, 12, 4),
460 MUX(MOUT_SPI1, "mout_spi1", mout_group2_p, CLK_SRC5, 4, 4),
461 MUX(MOUT_SPI0, "mout_spi0", mout_group2_p, CLK_SRC5, 0, 4),
462
463 MUX(MOUT_DMC0, "mout_dmc0", mout_group1_p, CLK_SRC6, 24, 2),
464 MUX(MOUT_PWI, "mout_pwi", mout_group2_p, CLK_SRC6, 20, 4),
465 MUX(MOUT_HPM, "mout_hpm", mout_group3_p, CLK_SRC6, 16, 1),
466 MUX(MOUT_SPDIF, "mout_spdif", mout_spdif_p, CLK_SRC6, 12, 2),
467 MUX(MOUT_AUDIO2, "mout_audio2", mout_audio2_p, CLK_SRC6, 8, 4),
468 MUX(MOUT_AUDIO1, "mout_audio1", mout_audio1_p, CLK_SRC6, 4, 4),
469 MUX(MOUT_AUDIO0, "mout_audio0", mout_audio0_p, CLK_SRC6, 0, 4),
470
471 MUX(MOUT_CLKSEL, "mout_clksel", mout_clksel_p, CLK_OUT, 12, 5),
472};
473
474/* S5P6442-specific clock muxes. */
475static struct samsung_mux_clock s5p6442_mux_clks[] __initdata = {
476 MUX(MOUT_VPLL, "mout_vpll", mout_vpll_6442_p, CLK_SRC0, 12, 1),
477
478 MUX(MOUT_FIMD, "mout_fimd", mout_group2_6442_p, CLK_SRC1, 20, 4),
479 MUX(MOUT_CAM1, "mout_cam1", mout_group2_6442_p, CLK_SRC1, 16, 4),
480 MUX(MOUT_CAM0, "mout_cam0", mout_group2_6442_p, CLK_SRC1, 12, 4),
481 MUX(MOUT_MIXER, "mout_mixer", mout_mixer_6442_p, CLK_SRC1, 4, 1),
482
483 MUX(MOUT_D0SYNC, "mout_d0sync", mout_d0sync_6442_p, CLK_SRC2, 28, 1),
484 MUX(MOUT_D1SYNC, "mout_d1sync", mout_d1sync_6442_p, CLK_SRC2, 24, 1),
485
486 MUX(MOUT_FIMC2, "mout_fimc2", mout_group2_6442_p, CLK_SRC3, 20, 4),
487 MUX(MOUT_FIMC1, "mout_fimc1", mout_group2_6442_p, CLK_SRC3, 16, 4),
488 MUX(MOUT_FIMC0, "mout_fimc0", mout_group2_6442_p, CLK_SRC3, 12, 4),
489
490 MUX(MOUT_UART2, "mout_uart2", mout_group2_6442_p, CLK_SRC4, 24, 4),
491 MUX(MOUT_UART1, "mout_uart1", mout_group2_6442_p, CLK_SRC4, 20, 4),
492 MUX(MOUT_UART0, "mout_uart0", mout_group2_6442_p, CLK_SRC4, 16, 4),
493 MUX(MOUT_MMC2, "mout_mmc2", mout_group2_6442_p, CLK_SRC4, 8, 4),
494 MUX(MOUT_MMC1, "mout_mmc1", mout_group2_6442_p, CLK_SRC4, 4, 4),
495 MUX(MOUT_MMC0, "mout_mmc0", mout_group2_6442_p, CLK_SRC4, 0, 4),
496
497 MUX(MOUT_PWM, "mout_pwm", mout_group2_6442_p, CLK_SRC5, 12, 4),
498 MUX(MOUT_SPI0, "mout_spi0", mout_group2_6442_p, CLK_SRC5, 0, 4),
499
500 MUX(MOUT_AUDIO1, "mout_audio1", mout_audio1_6442_p, CLK_SRC6, 4, 4),
501 MUX(MOUT_AUDIO0, "mout_audio0", mout_audio0_6442_p, CLK_SRC6, 0, 4),
502
503 MUX(MOUT_CLKSEL, "mout_clksel", mout_clksel_6442_p, CLK_OUT, 12, 5),
504};
505
506/* S5PV210-specific fixed rate clocks generated inside the SoC. */
507static struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initdata = {
508 FRATE(SCLK_HDMI27M, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
509 FRATE(SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
510 FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
511 FRATE(SCLK_USBPHY1, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
512};
513
514/* S5P6442-specific fixed rate clocks generated inside the SoC. */
515static struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initdata = {
516 FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 30000000),
517};
518
519/* Common clock dividers. */
520static struct samsung_div_clock div_clks[] __initdata = {
521 DIV(DOUT_PCLKP, "dout_pclkp", "dout_hclkp", CLK_DIV0, 28, 3),
522 DIV(DOUT_PCLKD, "dout_pclkd", "dout_hclkd", CLK_DIV0, 20, 3),
523 DIV(DOUT_A2M, "dout_a2m", "mout_apll", CLK_DIV0, 4, 3),
524 DIV(DOUT_APLL, "dout_apll", "mout_msys", CLK_DIV0, 0, 3),
525
526 DIV(DOUT_FIMD, "dout_fimd", "mout_fimd", CLK_DIV1, 20, 4),
527 DIV(DOUT_CAM1, "dout_cam1", "mout_cam1", CLK_DIV1, 16, 4),
528 DIV(DOUT_CAM0, "dout_cam0", "mout_cam0", CLK_DIV1, 12, 4),
529
530 DIV(DOUT_FIMC2, "dout_fimc2", "mout_fimc2", CLK_DIV3, 20, 4),
531 DIV(DOUT_FIMC1, "dout_fimc1", "mout_fimc1", CLK_DIV3, 16, 4),
532 DIV(DOUT_FIMC0, "dout_fimc0", "mout_fimc0", CLK_DIV3, 12, 4),
533
534 DIV(DOUT_UART2, "dout_uart2", "mout_uart2", CLK_DIV4, 24, 4),
535 DIV(DOUT_UART1, "dout_uart1", "mout_uart1", CLK_DIV4, 20, 4),
536 DIV(DOUT_UART0, "dout_uart0", "mout_uart0", CLK_DIV4, 16, 4),
537 DIV(DOUT_MMC2, "dout_mmc2", "mout_mmc2", CLK_DIV4, 8, 4),
538 DIV(DOUT_MMC1, "dout_mmc1", "mout_mmc1", CLK_DIV4, 4, 4),
539 DIV(DOUT_MMC0, "dout_mmc0", "mout_mmc0", CLK_DIV4, 0, 4),
540
541 DIV(DOUT_PWM, "dout_pwm", "mout_pwm", CLK_DIV5, 12, 4),
542 DIV(DOUT_SPI0, "dout_spi0", "mout_spi0", CLK_DIV5, 0, 4),
543
544 DIV(DOUT_FLASH, "dout_flash", "mout_flash", CLK_DIV6, 12, 3),
545 DIV(DOUT_AUDIO1, "dout_audio1", "mout_audio1", CLK_DIV6, 4, 4),
546 DIV(DOUT_AUDIO0, "dout_audio0", "mout_audio0", CLK_DIV6, 0, 4),
547
548 DIV(DOUT_CLKOUT, "dout_clkout", "mout_clksel", CLK_OUT, 20, 4),
549};
550
551/* S5PV210-specific clock dividers. */
552static struct samsung_div_clock s5pv210_div_clks[] __initdata = {
553 DIV(DOUT_HCLKP, "dout_hclkp", "mout_psys", CLK_DIV0, 24, 4),
554 DIV(DOUT_HCLKD, "dout_hclkd", "mout_dsys", CLK_DIV0, 16, 4),
555 DIV(DOUT_PCLKM, "dout_pclkm", "dout_hclkm", CLK_DIV0, 12, 3),
556 DIV(DOUT_HCLKM, "dout_hclkm", "dout_apll", CLK_DIV0, 8, 3),
557
558 DIV(DOUT_CSIS, "dout_csis", "mout_csis", CLK_DIV1, 28, 4),
559 DIV(DOUT_TBLK, "dout_tblk", "mout_vpll", CLK_DIV1, 0, 4),
560
561 DIV(DOUT_G2D, "dout_g2d", "mout_g2d", CLK_DIV2, 8, 4),
562 DIV(DOUT_MFC, "dout_mfc", "mout_mfc", CLK_DIV2, 4, 4),
563 DIV(DOUT_G3D, "dout_g3d", "mout_g3d", CLK_DIV2, 0, 4),
564
565 DIV(DOUT_UART3, "dout_uart3", "mout_uart3", CLK_DIV4, 28, 4),
566 DIV(DOUT_MMC3, "dout_mmc3", "mout_mmc3", CLK_DIV4, 12, 4),
567
568 DIV(DOUT_SPI1, "dout_spi1", "mout_spi1", CLK_DIV5, 4, 4),
569
570 DIV(DOUT_DMC0, "dout_dmc0", "mout_dmc0", CLK_DIV6, 28, 4),
571 DIV(DOUT_PWI, "dout_pwi", "mout_pwi", CLK_DIV6, 24, 4),
572 DIV(DOUT_HPM, "dout_hpm", "dout_copy", CLK_DIV6, 20, 3),
573 DIV(DOUT_COPY, "dout_copy", "mout_hpm", CLK_DIV6, 16, 3),
574 DIV(DOUT_AUDIO2, "dout_audio2", "mout_audio2", CLK_DIV6, 8, 4),
575
576 DIV(DOUT_DPM, "dout_dpm", "dout_pclkp", CLK_DIV7, 8, 7),
577 DIV(DOUT_DVSEM, "dout_dvsem", "dout_pclkp", CLK_DIV7, 0, 7),
578};
579
580/* S5P6442-specific clock dividers. */
581static struct samsung_div_clock s5p6442_div_clks[] __initdata = {
582 DIV(DOUT_HCLKP, "dout_hclkp", "mout_d1sync", CLK_DIV0, 24, 4),
583 DIV(DOUT_HCLKD, "dout_hclkd", "mout_d0sync", CLK_DIV0, 16, 4),
584
585 DIV(DOUT_MIXER, "dout_mixer", "mout_vpll", CLK_DIV1, 0, 4),
586};
587
588/* Common clock gates. */
589static struct samsung_gate_clock gate_clks[] __initdata = {
590 GATE(CLK_ROTATOR, "rotator", "dout_hclkd", CLK_GATE_IP0, 29, 0, 0),
591 GATE(CLK_FIMC2, "fimc2", "dout_hclkd", CLK_GATE_IP0, 26, 0, 0),
592 GATE(CLK_FIMC1, "fimc1", "dout_hclkd", CLK_GATE_IP0, 25, 0, 0),
593 GATE(CLK_FIMC0, "fimc0", "dout_hclkd", CLK_GATE_IP0, 24, 0, 0),
594 GATE(CLK_PDMA0, "pdma0", "dout_hclkp", CLK_GATE_IP0, 3, 0, 0),
595 GATE(CLK_MDMA, "mdma", "dout_hclkd", CLK_GATE_IP0, 2, 0, 0),
596
597 GATE(CLK_SROMC, "sromc", "dout_hclkp", CLK_GATE_IP1, 26, 0, 0),
598 GATE(CLK_NANDXL, "nandxl", "dout_hclkp", CLK_GATE_IP1, 24, 0, 0),
599 GATE(CLK_USB_OTG, "usb_otg", "dout_hclkp", CLK_GATE_IP1, 16, 0, 0),
600 GATE(CLK_TVENC, "tvenc", "dout_hclkd", CLK_GATE_IP1, 10, 0, 0),
601 GATE(CLK_MIXER, "mixer", "dout_hclkd", CLK_GATE_IP1, 9, 0, 0),
602 GATE(CLK_VP, "vp", "dout_hclkd", CLK_GATE_IP1, 8, 0, 0),
603 GATE(CLK_FIMD, "fimd", "dout_hclkd", CLK_GATE_IP1, 0, 0, 0),
604
605 GATE(CLK_HSMMC2, "hsmmc2", "dout_hclkp", CLK_GATE_IP2, 18, 0, 0),
606 GATE(CLK_HSMMC1, "hsmmc1", "dout_hclkp", CLK_GATE_IP2, 17, 0, 0),
607 GATE(CLK_HSMMC0, "hsmmc0", "dout_hclkp", CLK_GATE_IP2, 16, 0, 0),
608 GATE(CLK_MODEMIF, "modemif", "dout_hclkp", CLK_GATE_IP2, 9, 0, 0),
609 GATE(CLK_SECSS, "secss", "dout_hclkp", CLK_GATE_IP2, 0, 0, 0),
610
611 GATE(CLK_PCM1, "pcm1", "dout_pclkp", CLK_GATE_IP3, 29, 0, 0),
612 GATE(CLK_PCM0, "pcm0", "dout_pclkp", CLK_GATE_IP3, 28, 0, 0),
613 GATE(CLK_TSADC, "tsadc", "dout_pclkp", CLK_GATE_IP3, 24, 0, 0),
614 GATE(CLK_PWM, "pwm", "dout_pclkp", CLK_GATE_IP3, 23, 0, 0),
615 GATE(CLK_WDT, "watchdog", "dout_pclkp", CLK_GATE_IP3, 22, 0, 0),
616 GATE(CLK_KEYIF, "keyif", "dout_pclkp", CLK_GATE_IP3, 21, 0, 0),
617 GATE(CLK_UART2, "uart2", "dout_pclkp", CLK_GATE_IP3, 19, 0, 0),
618 GATE(CLK_UART1, "uart1", "dout_pclkp", CLK_GATE_IP3, 18, 0, 0),
619 GATE(CLK_UART0, "uart0", "dout_pclkp", CLK_GATE_IP3, 17, 0, 0),
620 GATE(CLK_SYSTIMER, "systimer", "dout_pclkp", CLK_GATE_IP3, 16, 0, 0),
621 GATE(CLK_RTC, "rtc", "dout_pclkp", CLK_GATE_IP3, 15, 0, 0),
622 GATE(CLK_SPI0, "spi0", "dout_pclkp", CLK_GATE_IP3, 12, 0, 0),
623 GATE(CLK_I2C2, "i2c2", "dout_pclkp", CLK_GATE_IP3, 9, 0, 0),
624 GATE(CLK_I2C0, "i2c0", "dout_pclkp", CLK_GATE_IP3, 7, 0, 0),
625 GATE(CLK_I2S1, "i2s1", "dout_pclkp", CLK_GATE_IP3, 5, 0, 0),
626 GATE(CLK_I2S0, "i2s0", "dout_pclkp", CLK_GATE_IP3, 4, 0, 0),
627
628 GATE(CLK_SECKEY, "seckey", "dout_pclkp", CLK_GATE_IP4, 3, 0, 0),
629 GATE(CLK_CHIPID, "chipid", "dout_pclkp", CLK_GATE_IP4, 0, 0, 0),
630
631 GATE(SCLK_AUDIO1, "sclk_audio1", "dout_audio1", CLK_SRC_MASK0, 25,
632 CLK_SET_RATE_PARENT, 0),
633 GATE(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", CLK_SRC_MASK0, 24,
634 CLK_SET_RATE_PARENT, 0),
635 GATE(SCLK_PWM, "sclk_pwm", "dout_pwm", CLK_SRC_MASK0, 19,
636 CLK_SET_RATE_PARENT, 0),
637 GATE(SCLK_SPI0, "sclk_spi0", "dout_spi0", CLK_SRC_MASK0, 16,
638 CLK_SET_RATE_PARENT, 0),
639 GATE(SCLK_UART2, "sclk_uart2", "dout_uart2", CLK_SRC_MASK0, 14,
640 CLK_SET_RATE_PARENT, 0),
641 GATE(SCLK_UART1, "sclk_uart1", "dout_uart1", CLK_SRC_MASK0, 13,
642 CLK_SET_RATE_PARENT, 0),
643 GATE(SCLK_UART0, "sclk_uart0", "dout_uart0", CLK_SRC_MASK0, 12,
644 CLK_SET_RATE_PARENT, 0),
645 GATE(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", CLK_SRC_MASK0, 10,
646 CLK_SET_RATE_PARENT, 0),
647 GATE(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", CLK_SRC_MASK0, 9,
648 CLK_SET_RATE_PARENT, 0),
649 GATE(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", CLK_SRC_MASK0, 8,
650 CLK_SET_RATE_PARENT, 0),
651 GATE(SCLK_FIMD, "sclk_fimd", "dout_fimd", CLK_SRC_MASK0, 5,
652 CLK_SET_RATE_PARENT, 0),
653 GATE(SCLK_CAM1, "sclk_cam1", "dout_cam1", CLK_SRC_MASK0, 4,
654 CLK_SET_RATE_PARENT, 0),
655 GATE(SCLK_CAM0, "sclk_cam0", "dout_cam0", CLK_SRC_MASK0, 3,
656 CLK_SET_RATE_PARENT, 0),
657 GATE(SCLK_MIXER, "sclk_mixer", "mout_mixer", CLK_SRC_MASK0, 1,
658 CLK_SET_RATE_PARENT, 0),
659
660 GATE(SCLK_FIMC2, "sclk_fimc2", "dout_fimc2", CLK_SRC_MASK1, 4,
661 CLK_SET_RATE_PARENT, 0),
662 GATE(SCLK_FIMC1, "sclk_fimc1", "dout_fimc1", CLK_SRC_MASK1, 3,
663 CLK_SET_RATE_PARENT, 0),
664 GATE(SCLK_FIMC0, "sclk_fimc0", "dout_fimc0", CLK_SRC_MASK1, 2,
665 CLK_SET_RATE_PARENT, 0),
666};
667
668/* S5PV210-specific clock gates. */
669static struct samsung_gate_clock s5pv210_gate_clks[] __initdata = {
670 GATE(CLK_CSIS, "clk_csis", "dout_hclkd", CLK_GATE_IP0, 31, 0, 0),
671 GATE(CLK_MFC, "mfc", "dout_hclkm", CLK_GATE_IP0, 16, 0, 0),
672 GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
673 GATE(CLK_G3D, "g3d", "dout_hclkm", CLK_GATE_IP0, 8, 0, 0),
674 GATE(CLK_IMEM, "imem", "dout_hclkm", CLK_GATE_IP0, 5, 0, 0),
675 GATE(CLK_PDMA1, "pdma1", "dout_hclkp", CLK_GATE_IP0, 4, 0, 0),
676
677 GATE(CLK_NFCON, "nfcon", "dout_hclkp", CLK_GATE_IP1, 28, 0, 0),
678 GATE(CLK_CFCON, "cfcon", "dout_hclkp", CLK_GATE_IP1, 25, 0, 0),
679 GATE(CLK_USB_HOST, "usb_host", "dout_hclkp", CLK_GATE_IP1, 17, 0, 0),
680 GATE(CLK_HDMI, "hdmi", "dout_hclkd", CLK_GATE_IP1, 11, 0, 0),
681 GATE(CLK_DSIM, "dsim", "dout_pclkd", CLK_GATE_IP1, 2, 0, 0),
682
683 GATE(CLK_TZIC3, "tzic3", "dout_hclkm", CLK_GATE_IP2, 31, 0, 0),
684 GATE(CLK_TZIC2, "tzic2", "dout_hclkm", CLK_GATE_IP2, 30, 0, 0),
685 GATE(CLK_TZIC1, "tzic1", "dout_hclkm", CLK_GATE_IP2, 29, 0, 0),
686 GATE(CLK_TZIC0, "tzic0", "dout_hclkm", CLK_GATE_IP2, 28, 0, 0),
687 GATE(CLK_TSI, "tsi", "dout_hclkd", CLK_GATE_IP2, 20, 0, 0),
688 GATE(CLK_HSMMC3, "hsmmc3", "dout_hclkp", CLK_GATE_IP2, 19, 0, 0),
689 GATE(CLK_JTAG, "jtag", "dout_hclkp", CLK_GATE_IP2, 11, 0, 0),
690 GATE(CLK_CORESIGHT, "coresight", "dout_pclkp", CLK_GATE_IP2, 8, 0, 0),
691 GATE(CLK_SDM, "sdm", "dout_pclkm", CLK_GATE_IP2, 1, 0, 0),
692
693 GATE(CLK_PCM2, "pcm2", "dout_pclkp", CLK_GATE_IP3, 30, 0, 0),
694 GATE(CLK_UART3, "uart3", "dout_pclkp", CLK_GATE_IP3, 20, 0, 0),
695 GATE(CLK_SPI1, "spi1", "dout_pclkp", CLK_GATE_IP3, 13, 0, 0),
696 GATE(CLK_I2C_HDMI_PHY, "i2c_hdmi_phy", "dout_pclkd",
697 CLK_GATE_IP3, 11, 0, 0),
698 GATE(CLK_I2C1, "i2c1", "dout_pclkd", CLK_GATE_IP3, 10, 0, 0),
699 GATE(CLK_I2S2, "i2s2", "dout_pclkp", CLK_GATE_IP3, 6, 0, 0),
700 GATE(CLK_AC97, "ac97", "dout_pclkp", CLK_GATE_IP3, 1, 0, 0),
701 GATE(CLK_SPDIF, "spdif", "dout_pclkp", CLK_GATE_IP3, 0, 0, 0),
702
703 GATE(CLK_TZPC3, "tzpc.3", "dout_pclkd", CLK_GATE_IP4, 8, 0, 0),
704 GATE(CLK_TZPC2, "tzpc.2", "dout_pclkd", CLK_GATE_IP4, 7, 0, 0),
705 GATE(CLK_TZPC1, "tzpc.1", "dout_pclkp", CLK_GATE_IP4, 6, 0, 0),
706 GATE(CLK_TZPC0, "tzpc.0", "dout_pclkm", CLK_GATE_IP4, 5, 0, 0),
707 GATE(CLK_IEM_APC, "iem_apc", "dout_pclkp", CLK_GATE_IP4, 2, 0, 0),
708 GATE(CLK_IEM_IEC, "iem_iec", "dout_pclkp", CLK_GATE_IP4, 1, 0, 0),
709
710 GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP5, 29, 0, 0),
711
712 GATE(SCLK_SPDIF, "sclk_spdif", "mout_spdif", CLK_SRC_MASK0, 27,
713 CLK_SET_RATE_PARENT, 0),
714 GATE(SCLK_AUDIO2, "sclk_audio2", "dout_audio2", CLK_SRC_MASK0, 26,
715 CLK_SET_RATE_PARENT, 0),
716 GATE(SCLK_SPI1, "sclk_spi1", "dout_spi1", CLK_SRC_MASK0, 17,
717 CLK_SET_RATE_PARENT, 0),
718 GATE(SCLK_UART3, "sclk_uart3", "dout_uart3", CLK_SRC_MASK0, 15,
719 CLK_SET_RATE_PARENT, 0),
720 GATE(SCLK_MMC3, "sclk_mmc3", "dout_mmc3", CLK_SRC_MASK0, 11,
721 CLK_SET_RATE_PARENT, 0),
722 GATE(SCLK_CSIS, "sclk_csis", "dout_csis", CLK_SRC_MASK0, 6,
723 CLK_SET_RATE_PARENT, 0),
724 GATE(SCLK_DAC, "sclk_dac", "mout_dac", CLK_SRC_MASK0, 2,
725 CLK_SET_RATE_PARENT, 0),
726 GATE(SCLK_HDMI, "sclk_hdmi", "mout_hdmi", CLK_SRC_MASK0, 0,
727 CLK_SET_RATE_PARENT, 0),
728};
729
730/* S5P6442-specific clock gates. */
731static struct samsung_gate_clock s5p6442_gate_clks[] __initdata = {
732 GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP0, 28, 0, 0),
733 GATE(CLK_MFC, "mfc", "dout_hclkd", CLK_GATE_IP0, 16, 0, 0),
734 GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
735 GATE(CLK_G3D, "g3d", "dout_hclkd", CLK_GATE_IP0, 8, 0, 0),
736 GATE(CLK_IMEM, "imem", "dout_hclkd", CLK_GATE_IP0, 5, 0, 0),
737
738 GATE(CLK_ETB, "etb", "dout_hclkd", CLK_GATE_IP1, 31, 0, 0),
739 GATE(CLK_ETM, "etm", "dout_hclkd", CLK_GATE_IP1, 30, 0, 0),
740
741 GATE(CLK_I2C1, "i2c1", "dout_pclkp", CLK_GATE_IP3, 8, 0, 0),
742
743 GATE(SCLK_DAC, "sclk_dac", "mout_vpll", CLK_SRC_MASK0, 2,
744 CLK_SET_RATE_PARENT, 0),
745};
746
747/*
748 * Clock aliases for legacy clkdev look-up.
749 * NOTE: Needed only to support legacy board files.
750 */
751static struct samsung_clock_alias s5pv210_aliases[] = {
752 ALIAS(DOUT_APLL, NULL, "armclk"),
753 ALIAS(DOUT_HCLKM, NULL, "hclk_msys"),
754 ALIAS(MOUT_DMC0, NULL, "sclk_dmc0"),
755};
756
757/* S5PV210-specific PLLs. */
758static struct samsung_pll_clock s5pv210_pll_clks[] __initdata = {
759 [apll] = PLL(pll_4508, FOUT_APLL, "fout_apll", "fin_pll",
760 APLL_LOCK, APLL_CON0, NULL),
761 [mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
762 MPLL_LOCK, MPLL_CON, NULL),
763 [epll] = PLL(pll_4600, FOUT_EPLL, "fout_epll", "fin_pll",
764 EPLL_LOCK, EPLL_CON0, NULL),
765 [vpll] = PLL(pll_4502, FOUT_VPLL, "fout_vpll", "mout_vpllsrc",
766 VPLL_LOCK, VPLL_CON, NULL),
767};
768
769/* S5P6442-specific PLLs. */
770static struct samsung_pll_clock s5p6442_pll_clks[] __initdata = {
771 [apll] = PLL(pll_4502, FOUT_APLL, "fout_apll", "fin_pll",
772 APLL_LOCK, APLL_CON0, NULL),
773 [mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
774 MPLL_LOCK, MPLL_CON, NULL),
775 [epll] = PLL(pll_4500, FOUT_EPLL, "fout_epll", "fin_pll",
776 EPLL_LOCK, EPLL_CON0, NULL),
777 [vpll] = PLL(pll_4500, FOUT_VPLL, "fout_vpll", "fin_pll",
778 VPLL_LOCK, VPLL_CON, NULL),
779};
780
781static void __init __s5pv210_clk_init(struct device_node *np,
782 unsigned long xxti_f,
783 unsigned long xusbxti_f,
784 bool is_s5p6442)
785{
786 struct samsung_clk_provider *ctx;
787
788 ctx = samsung_clk_init(np, reg_base, NR_CLKS);
789 if (!ctx)
790 panic("%s: unable to allocate context.\n", __func__);
791
792 samsung_clk_register_mux(ctx, early_mux_clks,
793 ARRAY_SIZE(early_mux_clks));
794
795 if (is_s5p6442) {
796 samsung_clk_register_fixed_rate(ctx, s5p6442_frate_clks,
797 ARRAY_SIZE(s5p6442_frate_clks));
798 samsung_clk_register_pll(ctx, s5p6442_pll_clks,
799 ARRAY_SIZE(s5p6442_pll_clks), reg_base);
800 samsung_clk_register_mux(ctx, s5p6442_mux_clks,
801 ARRAY_SIZE(s5p6442_mux_clks));
802 samsung_clk_register_div(ctx, s5p6442_div_clks,
803 ARRAY_SIZE(s5p6442_div_clks));
804 samsung_clk_register_gate(ctx, s5p6442_gate_clks,
805 ARRAY_SIZE(s5p6442_gate_clks));
806 } else {
807 samsung_clk_register_fixed_rate(ctx, s5pv210_frate_clks,
808 ARRAY_SIZE(s5pv210_frate_clks));
809 samsung_clk_register_pll(ctx, s5pv210_pll_clks,
810 ARRAY_SIZE(s5pv210_pll_clks), reg_base);
811 samsung_clk_register_mux(ctx, s5pv210_mux_clks,
812 ARRAY_SIZE(s5pv210_mux_clks));
813 samsung_clk_register_div(ctx, s5pv210_div_clks,
814 ARRAY_SIZE(s5pv210_div_clks));
815 samsung_clk_register_gate(ctx, s5pv210_gate_clks,
816 ARRAY_SIZE(s5pv210_gate_clks));
817 }
818
819 samsung_clk_register_mux(ctx, mux_clks, ARRAY_SIZE(mux_clks));
820 samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks));
821 samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks));
822
823 samsung_clk_register_fixed_factor(ctx, ffactor_clks,
824 ARRAY_SIZE(ffactor_clks));
825
826 samsung_clk_register_alias(ctx, s5pv210_aliases,
827 ARRAY_SIZE(s5pv210_aliases));
828
829 s5pv210_clk_sleep_init();
830
831 pr_info("%s clocks: mout_apll = %ld, mout_mpll = %ld\n"
832 "\tmout_epll = %ld, mout_vpll = %ld\n",
833 is_s5p6442 ? "S5P6442" : "S5PV210",
834 _get_rate("mout_apll"), _get_rate("mout_mpll"),
835 _get_rate("mout_epll"), _get_rate("mout_vpll"));
836}
837
838static void __init s5pv210_clk_dt_init(struct device_node *np)
839{
840 reg_base = of_iomap(np, 0);
841 if (!reg_base)
842 panic("%s: failed to map registers\n", __func__);
843
844 __s5pv210_clk_init(np, 0, 0, false);
845}
846CLK_OF_DECLARE(s5pv210_clk, "samsung,s5pv210-clock", s5pv210_clk_dt_init);
847
848static void __init s5p6442_clk_dt_init(struct device_node *np)
849{
850 reg_base = of_iomap(np, 0);
851 if (!reg_base)
852 panic("%s: failed to map registers\n", __func__);
853
854 __s5pv210_clk_init(np, 0, 0, true);
855}
856CLK_OF_DECLARE(s5p6442_clk, "samsung,s5p6442-clock", s5p6442_clk_dt_init);
diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile
index e0029237827a..960bf22d42ae 100644
--- a/drivers/clk/shmobile/Makefile
+++ b/drivers/clk/shmobile/Makefile
@@ -4,7 +4,6 @@ obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o
4obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o 4obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o
5obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o 5obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o
6obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o 6obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o
7obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o
7obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o 8obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o
8obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-mstp.o 9obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-mstp.o
9# for emply built-in.o
10obj-n := dummy
diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c
index dff7f79a19b9..e996425d06a9 100644
--- a/drivers/clk/shmobile/clk-rcar-gen2.c
+++ b/drivers/clk/shmobile/clk-rcar-gen2.c
@@ -202,6 +202,7 @@ static const struct clk_div_table cpg_sdh_div_table[] = {
202}; 202};
203 203
204static const struct clk_div_table cpg_sd01_div_table[] = { 204static const struct clk_div_table cpg_sd01_div_table[] = {
205 { 4, 8 },
205 { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 }, 206 { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 },
206 { 10, 36 }, { 11, 48 }, { 12, 10 }, { 0, 0 }, 207 { 10, 36 }, { 11, 48 }, { 12, 10 }, { 0, 0 },
207}; 208};
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 6850cba35871..7ddc2b553846 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -5,6 +5,8 @@
5obj-y += clk-sunxi.o clk-factors.o 5obj-y += clk-sunxi.o clk-factors.o
6obj-y += clk-a10-hosc.o 6obj-y += clk-a10-hosc.o
7obj-y += clk-a20-gmac.o 7obj-y += clk-a20-gmac.o
8obj-y += clk-mod0.o
9obj-y += clk-sun8i-mbus.o
8 10
9obj-$(CONFIG_MFD_SUN6I_PRCM) += \ 11obj-$(CONFIG_MFD_SUN6I_PRCM) += \
10 clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \ 12 clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 2057c8ac648f..f83ba097126c 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -9,18 +9,18 @@
9 */ 9 */
10 10
11#include <linux/clk-provider.h> 11#include <linux/clk-provider.h>
12#include <linux/delay.h>
13#include <linux/err.h>
14#include <linux/io.h>
12#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/of_address.h>
13#include <linux/slab.h> 17#include <linux/slab.h>
14#include <linux/io.h>
15#include <linux/err.h>
16#include <linux/string.h> 18#include <linux/string.h>
17 19
18#include <linux/delay.h>
19
20#include "clk-factors.h" 20#include "clk-factors.h"
21 21
22/* 22/*
23 * DOC: basic adjustable factor-based clock that cannot gate 23 * DOC: basic adjustable factor-based clock
24 * 24 *
25 * Traits of this clock: 25 * Traits of this clock:
26 * prepare - clk_prepare only ensures that parents are prepared 26 * prepare - clk_prepare only ensures that parents are prepared
@@ -32,6 +32,8 @@
32 32
33#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) 33#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
34 34
35#define FACTORS_MAX_PARENTS 5
36
35#define SETMASK(len, pos) (((1U << (len)) - 1) << (pos)) 37#define SETMASK(len, pos) (((1U << (len)) - 1) << (pos))
36#define CLRMASK(len, pos) (~(SETMASK(len, pos))) 38#define CLRMASK(len, pos) (~(SETMASK(len, pos)))
37#define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit)) 39#define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit))
@@ -147,9 +149,96 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
147 return 0; 149 return 0;
148} 150}
149 151
150const struct clk_ops clk_factors_ops = { 152static const struct clk_ops clk_factors_ops = {
151 .determine_rate = clk_factors_determine_rate, 153 .determine_rate = clk_factors_determine_rate,
152 .recalc_rate = clk_factors_recalc_rate, 154 .recalc_rate = clk_factors_recalc_rate,
153 .round_rate = clk_factors_round_rate, 155 .round_rate = clk_factors_round_rate,
154 .set_rate = clk_factors_set_rate, 156 .set_rate = clk_factors_set_rate,
155}; 157};
158
159struct clk * __init sunxi_factors_register(struct device_node *node,
160 const struct factors_data *data,
161 spinlock_t *lock)
162{
163 struct clk *clk;
164 struct clk_factors *factors;
165 struct clk_gate *gate = NULL;
166 struct clk_mux *mux = NULL;
167 struct clk_hw *gate_hw = NULL;
168 struct clk_hw *mux_hw = NULL;
169 const char *clk_name = node->name;
170 const char *parents[FACTORS_MAX_PARENTS];
171 void __iomem *reg;
172 int i = 0;
173
174 reg = of_iomap(node, 0);
175
176 /* if we have a mux, we will have >1 parents */
177 while (i < FACTORS_MAX_PARENTS &&
178 (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
179 i++;
180
181 /*
182 * some factor clocks, such as pll5 and pll6, may have multiple
183 * outputs, and have their name designated in factors_data
184 */
185 if (data->name)
186 clk_name = data->name;
187 else
188 of_property_read_string(node, "clock-output-names", &clk_name);
189
190 factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
191 if (!factors)
192 return NULL;
193
194 /* set up factors properties */
195 factors->reg = reg;
196 factors->config = data->table;
197 factors->get_factors = data->getter;
198 factors->lock = lock;
199
200 /* Add a gate if this factor clock can be gated */
201 if (data->enable) {
202 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
203 if (!gate) {
204 kfree(factors);
205 return NULL;
206 }
207
208 /* set up gate properties */
209 gate->reg = reg;
210 gate->bit_idx = data->enable;
211 gate->lock = factors->lock;
212 gate_hw = &gate->hw;
213 }
214
215 /* Add a mux if this factor clock can be muxed */
216 if (data->mux) {
217 mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
218 if (!mux) {
219 kfree(factors);
220 kfree(gate);
221 return NULL;
222 }
223
224 /* set up gate properties */
225 mux->reg = reg;
226 mux->shift = data->mux;
227 mux->mask = SUNXI_FACTORS_MUX_MASK;
228 mux->lock = factors->lock;
229 mux_hw = &mux->hw;
230 }
231
232 clk = clk_register_composite(NULL, clk_name,
233 parents, i,
234 mux_hw, &clk_mux_ops,
235 &factors->hw, &clk_factors_ops,
236 gate_hw, &clk_gate_ops, 0);
237
238 if (!IS_ERR(clk)) {
239 of_clk_add_provider(node, of_clk_src_simple_get, clk);
240 clk_register_clkdev(clk, clk_name, NULL);
241 }
242
243 return clk;
244}
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
index d2d0efa39379..9913840018d3 100644
--- a/drivers/clk/sunxi/clk-factors.h
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -3,9 +3,12 @@
3 3
4#include <linux/clk-provider.h> 4#include <linux/clk-provider.h>
5#include <linux/clkdev.h> 5#include <linux/clkdev.h>
6#include <linux/spinlock.h>
6 7
7#define SUNXI_FACTORS_NOT_APPLICABLE (0) 8#define SUNXI_FACTORS_NOT_APPLICABLE (0)
8 9
10#define SUNXI_FACTORS_MUX_MASK 0x3
11
9struct clk_factors_config { 12struct clk_factors_config {
10 u8 nshift; 13 u8 nshift;
11 u8 nwidth; 14 u8 nwidth;
@@ -18,6 +21,14 @@ struct clk_factors_config {
18 u8 n_start; 21 u8 n_start;
19}; 22};
20 23
24struct factors_data {
25 int enable;
26 int mux;
27 struct clk_factors_config *table;
28 void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
29 const char *name;
30};
31
21struct clk_factors { 32struct clk_factors {
22 struct clk_hw hw; 33 struct clk_hw hw;
23 void __iomem *reg; 34 void __iomem *reg;
@@ -26,5 +37,8 @@ struct clk_factors {
26 spinlock_t *lock; 37 spinlock_t *lock;
27}; 38};
28 39
29extern const struct clk_ops clk_factors_ops; 40struct clk * __init sunxi_factors_register(struct device_node *node,
41 const struct factors_data *data,
42 spinlock_t *lock);
43
30#endif 44#endif
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
new file mode 100644
index 000000000000..4a563850ee6e
--- /dev/null
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -0,0 +1,283 @@
1/*
2 * Copyright 2013 Emilio López
3 *
4 * Emilio López <emilio@elopez.com.ar>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/clk-provider.h>
18#include <linux/clkdev.h>
19#include <linux/of_address.h>
20
21#include "clk-factors.h"
22
23/**
24 * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
25 * MOD0 rate is calculated as follows
26 * rate = (parent_rate >> p) / (m + 1);
27 */
28
29static void sun4i_a10_get_mod0_factors(u32 *freq, u32 parent_rate,
30 u8 *n, u8 *k, u8 *m, u8 *p)
31{
32 u8 div, calcm, calcp;
33
34 /* These clocks can only divide, so we will never be able to achieve
35 * frequencies higher than the parent frequency */
36 if (*freq > parent_rate)
37 *freq = parent_rate;
38
39 div = DIV_ROUND_UP(parent_rate, *freq);
40
41 if (div < 16)
42 calcp = 0;
43 else if (div / 2 < 16)
44 calcp = 1;
45 else if (div / 4 < 16)
46 calcp = 2;
47 else
48 calcp = 3;
49
50 calcm = DIV_ROUND_UP(div, 1 << calcp);
51
52 *freq = (parent_rate >> calcp) / calcm;
53
54 /* we were called to round the frequency, we can now return */
55 if (n == NULL)
56 return;
57
58 *m = calcm - 1;
59 *p = calcp;
60}
61
62/* user manual says "n" but it's really "p" */
63static struct clk_factors_config sun4i_a10_mod0_config = {
64 .mshift = 0,
65 .mwidth = 4,
66 .pshift = 16,
67 .pwidth = 2,
68};
69
70static const struct factors_data sun4i_a10_mod0_data __initconst = {
71 .enable = 31,
72 .mux = 24,
73 .table = &sun4i_a10_mod0_config,
74 .getter = sun4i_a10_get_mod0_factors,
75};
76
77static DEFINE_SPINLOCK(sun4i_a10_mod0_lock);
78
79static void __init sun4i_a10_mod0_setup(struct device_node *node)
80{
81 sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun4i_a10_mod0_lock);
82}
83CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup);
84
85static DEFINE_SPINLOCK(sun5i_a13_mbus_lock);
86
87static void __init sun5i_a13_mbus_setup(struct device_node *node)
88{
89 struct clk *mbus = sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun5i_a13_mbus_lock);
90
91 /* The MBUS clocks needs to be always enabled */
92 __clk_get(mbus);
93 clk_prepare_enable(mbus);
94}
95CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup);
96
97struct mmc_phase_data {
98 u8 offset;
99};
100
101struct mmc_phase {
102 struct clk_hw hw;
103 void __iomem *reg;
104 struct mmc_phase_data *data;
105 spinlock_t *lock;
106};
107
108#define to_mmc_phase(_hw) container_of(_hw, struct mmc_phase, hw)
109
110static int mmc_get_phase(struct clk_hw *hw)
111{
112 struct clk *mmc, *mmc_parent, *clk = hw->clk;
113 struct mmc_phase *phase = to_mmc_phase(hw);
114 unsigned int mmc_rate, mmc_parent_rate;
115 u16 step, mmc_div;
116 u32 value;
117 u8 delay;
118
119 value = readl(phase->reg);
120 delay = (value >> phase->data->offset) & 0x3;
121
122 if (!delay)
123 return 180;
124
125 /* Get the main MMC clock */
126 mmc = clk_get_parent(clk);
127 if (!mmc)
128 return -EINVAL;
129
130 /* And its rate */
131 mmc_rate = clk_get_rate(mmc);
132 if (!mmc_rate)
133 return -EINVAL;
134
135 /* Now, get the MMC parent (most likely some PLL) */
136 mmc_parent = clk_get_parent(mmc);
137 if (!mmc_parent)
138 return -EINVAL;
139
140 /* And its rate */
141 mmc_parent_rate = clk_get_rate(mmc_parent);
142 if (!mmc_parent_rate)
143 return -EINVAL;
144
145 /* Get MMC clock divider */
146 mmc_div = mmc_parent_rate / mmc_rate;
147
148 step = DIV_ROUND_CLOSEST(360, mmc_div);
149 return delay * step;
150}
151
152static int mmc_set_phase(struct clk_hw *hw, int degrees)
153{
154 struct clk *mmc, *mmc_parent, *clk = hw->clk;
155 struct mmc_phase *phase = to_mmc_phase(hw);
156 unsigned int mmc_rate, mmc_parent_rate;
157 unsigned long flags;
158 u32 value;
159 u8 delay;
160
161 /* Get the main MMC clock */
162 mmc = clk_get_parent(clk);
163 if (!mmc)
164 return -EINVAL;
165
166 /* And its rate */
167 mmc_rate = clk_get_rate(mmc);
168 if (!mmc_rate)
169 return -EINVAL;
170
171 /* Now, get the MMC parent (most likely some PLL) */
172 mmc_parent = clk_get_parent(mmc);
173 if (!mmc_parent)
174 return -EINVAL;
175
176 /* And its rate */
177 mmc_parent_rate = clk_get_rate(mmc_parent);
178 if (!mmc_parent_rate)
179 return -EINVAL;
180
181 if (degrees != 180) {
182 u16 step, mmc_div;
183
184 /* Get MMC clock divider */
185 mmc_div = mmc_parent_rate / mmc_rate;
186
187 /*
188 * We can only outphase the clocks by multiple of the
189 * PLL's period.
190 *
191 * Since the MMC clock in only a divider, and the
192 * formula to get the outphasing in degrees is deg =
193 * 360 * delta / period
194 *
195 * If we simplify this formula, we can see that the
196 * only thing that we're concerned about is the number
197 * of period we want to outphase our clock from, and
198 * the divider set by the MMC clock.
199 */
200 step = DIV_ROUND_CLOSEST(360, mmc_div);
201 delay = DIV_ROUND_CLOSEST(degrees, step);
202 } else {
203 delay = 0;
204 }
205
206 spin_lock_irqsave(phase->lock, flags);
207 value = readl(phase->reg);
208 value &= ~GENMASK(phase->data->offset + 3, phase->data->offset);
209 value |= delay << phase->data->offset;
210 writel(value, phase->reg);
211 spin_unlock_irqrestore(phase->lock, flags);
212
213 return 0;
214}
215
216static const struct clk_ops mmc_clk_ops = {
217 .get_phase = mmc_get_phase,
218 .set_phase = mmc_set_phase,
219};
220
221static void __init sun4i_a10_mmc_phase_setup(struct device_node *node,
222 struct mmc_phase_data *data)
223{
224 const char *parent_names[1] = { of_clk_get_parent_name(node, 0) };
225 struct clk_init_data init = {
226 .num_parents = 1,
227 .parent_names = parent_names,
228 .ops = &mmc_clk_ops,
229 };
230
231 struct mmc_phase *phase;
232 struct clk *clk;
233
234 phase = kmalloc(sizeof(*phase), GFP_KERNEL);
235 if (!phase)
236 return;
237
238 phase->hw.init = &init;
239
240 phase->reg = of_iomap(node, 0);
241 if (!phase->reg)
242 goto err_free;
243
244 phase->data = data;
245 phase->lock = &sun4i_a10_mod0_lock;
246
247 if (of_property_read_string(node, "clock-output-names", &init.name))
248 init.name = node->name;
249
250 clk = clk_register(NULL, &phase->hw);
251 if (IS_ERR(clk))
252 goto err_unmap;
253
254 of_clk_add_provider(node, of_clk_src_simple_get, clk);
255
256 return;
257
258err_unmap:
259 iounmap(phase->reg);
260err_free:
261 kfree(phase);
262}
263
264
265static struct mmc_phase_data mmc_output_clk = {
266 .offset = 8,
267};
268
269static struct mmc_phase_data mmc_sample_clk = {
270 .offset = 20,
271};
272
273static void __init sun4i_a10_mmc_output_setup(struct device_node *node)
274{
275 sun4i_a10_mmc_phase_setup(node, &mmc_output_clk);
276}
277CLK_OF_DECLARE(sun4i_a10_mmc_output, "allwinner,sun4i-a10-mmc-output-clk", sun4i_a10_mmc_output_setup);
278
279static void __init sun4i_a10_mmc_sample_setup(struct device_node *node)
280{
281 sun4i_a10_mmc_phase_setup(node, &mmc_sample_clk);
282}
283CLK_OF_DECLARE(sun4i_a10_mmc_sample, "allwinner,sun4i-a10-mmc-sample-clk", sun4i_a10_mmc_sample_setup);
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
index e10d0521ec76..64f3e46d383c 100644
--- a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
+++ b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
@@ -99,7 +99,6 @@ static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev)
99static struct platform_driver sun6i_a31_apb0_gates_clk_driver = { 99static struct platform_driver sun6i_a31_apb0_gates_clk_driver = {
100 .driver = { 100 .driver = {
101 .name = "sun6i-a31-apb0-gates-clk", 101 .name = "sun6i-a31-apb0-gates-clk",
102 .owner = THIS_MODULE,
103 .of_match_table = sun6i_a31_apb0_gates_clk_dt_ids, 102 .of_match_table = sun6i_a31_apb0_gates_clk_dt_ids,
104 }, 103 },
105 .probe = sun6i_a31_apb0_gates_clk_probe, 104 .probe = sun6i_a31_apb0_gates_clk_probe,
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0.c b/drivers/clk/sunxi/clk-sun6i-apb0.c
index 1fa23371c8c6..70763600aeae 100644
--- a/drivers/clk/sunxi/clk-sun6i-apb0.c
+++ b/drivers/clk/sunxi/clk-sun6i-apb0.c
@@ -65,7 +65,6 @@ static const struct of_device_id sun6i_a31_apb0_clk_dt_ids[] = {
65static struct platform_driver sun6i_a31_apb0_clk_driver = { 65static struct platform_driver sun6i_a31_apb0_clk_driver = {
66 .driver = { 66 .driver = {
67 .name = "sun6i-a31-apb0-clk", 67 .name = "sun6i-a31-apb0-clk",
68 .owner = THIS_MODULE,
69 .of_match_table = sun6i_a31_apb0_clk_dt_ids, 68 .of_match_table = sun6i_a31_apb0_clk_dt_ids,
70 }, 69 },
71 .probe = sun6i_a31_apb0_clk_probe, 70 .probe = sun6i_a31_apb0_clk_probe,
diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c
index eca8ca025b6a..acca53290be2 100644
--- a/drivers/clk/sunxi/clk-sun6i-ar100.c
+++ b/drivers/clk/sunxi/clk-sun6i-ar100.c
@@ -221,7 +221,6 @@ static const struct of_device_id sun6i_a31_ar100_clk_dt_ids[] = {
221static struct platform_driver sun6i_a31_ar100_clk_driver = { 221static struct platform_driver sun6i_a31_ar100_clk_driver = {
222 .driver = { 222 .driver = {
223 .name = "sun6i-a31-ar100-clk", 223 .name = "sun6i-a31-ar100-clk",
224 .owner = THIS_MODULE,
225 .of_match_table = sun6i_a31_ar100_clk_dt_ids, 224 .of_match_table = sun6i_a31_ar100_clk_dt_ids,
226 }, 225 },
227 .probe = sun6i_a31_ar100_clk_probe, 226 .probe = sun6i_a31_ar100_clk_probe,
diff --git a/drivers/clk/sunxi/clk-sun8i-apb0.c b/drivers/clk/sunxi/clk-sun8i-apb0.c
index 1f5ba9b4b8cd..155d0022194f 100644
--- a/drivers/clk/sunxi/clk-sun8i-apb0.c
+++ b/drivers/clk/sunxi/clk-sun8i-apb0.c
@@ -56,7 +56,6 @@ static const struct of_device_id sun8i_a23_apb0_clk_dt_ids[] = {
56static struct platform_driver sun8i_a23_apb0_clk_driver = { 56static struct platform_driver sun8i_a23_apb0_clk_driver = {
57 .driver = { 57 .driver = {
58 .name = "sun8i-a23-apb0-clk", 58 .name = "sun8i-a23-apb0-clk",
59 .owner = THIS_MODULE,
60 .of_match_table = sun8i_a23_apb0_clk_dt_ids, 59 .of_match_table = sun8i_a23_apb0_clk_dt_ids,
61 }, 60 },
62 .probe = sun8i_a23_apb0_clk_probe, 61 .probe = sun8i_a23_apb0_clk_probe,
diff --git a/drivers/clk/sunxi/clk-sun8i-mbus.c b/drivers/clk/sunxi/clk-sun8i-mbus.c
new file mode 100644
index 000000000000..8e49b44cee41
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun8i-mbus.c
@@ -0,0 +1,78 @@
1/*
2 * Copyright 2014 Chen-Yu Tsai
3 *
4 * Chen-Yu Tsai <wens@csie.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/clk-provider.h>
18#include <linux/clkdev.h>
19#include <linux/of_address.h>
20
21#include "clk-factors.h"
22
23/**
24 * sun8i_a23_get_mbus_factors() - calculates m factor for MBUS clocks
25 * MBUS rate is calculated as follows
26 * rate = parent_rate / (m + 1);
27 */
28
29static void sun8i_a23_get_mbus_factors(u32 *freq, u32 parent_rate,
30 u8 *n, u8 *k, u8 *m, u8 *p)
31{
32 u8 div;
33
34 /*
35 * These clocks can only divide, so we will never be able to
36 * achieve frequencies higher than the parent frequency
37 */
38 if (*freq > parent_rate)
39 *freq = parent_rate;
40
41 div = DIV_ROUND_UP(parent_rate, *freq);
42
43 if (div > 8)
44 div = 8;
45
46 *freq = parent_rate / div;
47
48 /* we were called to round the frequency, we can now return */
49 if (m == NULL)
50 return;
51
52 *m = div - 1;
53}
54
55static struct clk_factors_config sun8i_a23_mbus_config = {
56 .mshift = 0,
57 .mwidth = 3,
58};
59
60static const struct factors_data sun8i_a23_mbus_data __initconst = {
61 .enable = 31,
62 .mux = 24,
63 .table = &sun8i_a23_mbus_config,
64 .getter = sun8i_a23_get_mbus_factors,
65};
66
67static DEFINE_SPINLOCK(sun8i_a23_mbus_lock);
68
69static void __init sun8i_a23_mbus_setup(struct device_node *node)
70{
71 struct clk *mbus = sunxi_factors_register(node, &sun8i_a23_mbus_data,
72 &sun8i_a23_mbus_lock);
73
74 /* The MBUS clocks needs to be always enabled */
75 __clk_get(mbus);
76 clk_prepare_enable(mbus);
77}
78CLK_OF_DECLARE(sun8i_a23_mbus, "allwinner,sun8i-a23-mbus-clk", sun8i_a23_mbus_setup);
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index b654b7b1d137..d5dc951264ca 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -19,6 +19,7 @@
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/of_address.h> 20#include <linux/of_address.h>
21#include <linux/reset-controller.h> 21#include <linux/reset-controller.h>
22#include <linux/spinlock.h>
22 23
23#include "clk-factors.h" 24#include "clk-factors.h"
24 25
@@ -319,46 +320,6 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate,
319 320
320 321
321 322
322/**
323 * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
324 * MOD0 rate is calculated as follows
325 * rate = (parent_rate >> p) / (m + 1);
326 */
327
328static void sun4i_get_mod0_factors(u32 *freq, u32 parent_rate,
329 u8 *n, u8 *k, u8 *m, u8 *p)
330{
331 u8 div, calcm, calcp;
332
333 /* These clocks can only divide, so we will never be able to achieve
334 * frequencies higher than the parent frequency */
335 if (*freq > parent_rate)
336 *freq = parent_rate;
337
338 div = DIV_ROUND_UP(parent_rate, *freq);
339
340 if (div < 16)
341 calcp = 0;
342 else if (div / 2 < 16)
343 calcp = 1;
344 else if (div / 4 < 16)
345 calcp = 2;
346 else
347 calcp = 3;
348
349 calcm = DIV_ROUND_UP(div, 1 << calcp);
350
351 *freq = (parent_rate >> calcp) / calcm;
352
353 /* we were called to round the frequency, we can now return */
354 if (n == NULL)
355 return;
356
357 *m = calcm - 1;
358 *p = calcp;
359}
360
361
362 323
363/** 324/**
364 * sun7i_a20_get_out_factors() - calculates m, p factors for CLK_OUT_A/B 325 * sun7i_a20_get_out_factors() - calculates m, p factors for CLK_OUT_A/B
@@ -440,16 +401,6 @@ EXPORT_SYMBOL(clk_sunxi_mmc_phase_control);
440 * sunxi_factors_clk_setup() - Setup function for factor clocks 401 * sunxi_factors_clk_setup() - Setup function for factor clocks
441 */ 402 */
442 403
443#define SUNXI_FACTORS_MUX_MASK 0x3
444
445struct factors_data {
446 int enable;
447 int mux;
448 struct clk_factors_config *table;
449 void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
450 const char *name;
451};
452
453static struct clk_factors_config sun4i_pll1_config = { 404static struct clk_factors_config sun4i_pll1_config = {
454 .nshift = 8, 405 .nshift = 8,
455 .nwidth = 5, 406 .nwidth = 5,
@@ -504,14 +455,6 @@ static struct clk_factors_config sun4i_apb1_config = {
504}; 455};
505 456
506/* user manual says "n" but it's really "p" */ 457/* user manual says "n" but it's really "p" */
507static struct clk_factors_config sun4i_mod0_config = {
508 .mshift = 0,
509 .mwidth = 4,
510 .pshift = 16,
511 .pwidth = 2,
512};
513
514/* user manual says "n" but it's really "p" */
515static struct clk_factors_config sun7i_a20_out_config = { 458static struct clk_factors_config sun7i_a20_out_config = {
516 .mshift = 8, 459 .mshift = 8,
517 .mwidth = 5, 460 .mwidth = 5,
@@ -568,13 +511,6 @@ static const struct factors_data sun4i_apb1_data __initconst = {
568 .getter = sun4i_get_apb1_factors, 511 .getter = sun4i_get_apb1_factors,
569}; 512};
570 513
571static const struct factors_data sun4i_mod0_data __initconst = {
572 .enable = 31,
573 .mux = 24,
574 .table = &sun4i_mod0_config,
575 .getter = sun4i_get_mod0_factors,
576};
577
578static const struct factors_data sun7i_a20_out_data __initconst = { 514static const struct factors_data sun7i_a20_out_data __initconst = {
579 .enable = 31, 515 .enable = 31,
580 .mux = 24, 516 .mux = 24,
@@ -583,89 +519,9 @@ static const struct factors_data sun7i_a20_out_data __initconst = {
583}; 519};
584 520
585static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, 521static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
586 const struct factors_data *data) 522 const struct factors_data *data)
587{ 523{
588 struct clk *clk; 524 return sunxi_factors_register(node, data, &clk_lock);
589 struct clk_factors *factors;
590 struct clk_gate *gate = NULL;
591 struct clk_mux *mux = NULL;
592 struct clk_hw *gate_hw = NULL;
593 struct clk_hw *mux_hw = NULL;
594 const char *clk_name = node->name;
595 const char *parents[SUNXI_MAX_PARENTS];
596 void __iomem *reg;
597 int i = 0;
598
599 reg = of_iomap(node, 0);
600
601 /* if we have a mux, we will have >1 parents */
602 while (i < SUNXI_MAX_PARENTS &&
603 (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
604 i++;
605
606 /*
607 * some factor clocks, such as pll5 and pll6, may have multiple
608 * outputs, and have their name designated in factors_data
609 */
610 if (data->name)
611 clk_name = data->name;
612 else
613 of_property_read_string(node, "clock-output-names", &clk_name);
614
615 factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
616 if (!factors)
617 return NULL;
618
619 /* Add a gate if this factor clock can be gated */
620 if (data->enable) {
621 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
622 if (!gate) {
623 kfree(factors);
624 return NULL;
625 }
626
627 /* set up gate properties */
628 gate->reg = reg;
629 gate->bit_idx = data->enable;
630 gate->lock = &clk_lock;
631 gate_hw = &gate->hw;
632 }
633
634 /* Add a mux if this factor clock can be muxed */
635 if (data->mux) {
636 mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
637 if (!mux) {
638 kfree(factors);
639 kfree(gate);
640 return NULL;
641 }
642
643 /* set up gate properties */
644 mux->reg = reg;
645 mux->shift = data->mux;
646 mux->mask = SUNXI_FACTORS_MUX_MASK;
647 mux->lock = &clk_lock;
648 mux_hw = &mux->hw;
649 }
650
651 /* set up factors properties */
652 factors->reg = reg;
653 factors->config = data->table;
654 factors->get_factors = data->getter;
655 factors->lock = &clk_lock;
656
657 clk = clk_register_composite(NULL, clk_name,
658 parents, i,
659 mux_hw, &clk_mux_ops,
660 &factors->hw, &clk_factors_ops,
661 gate_hw, &clk_gate_ops, 0);
662
663 if (!IS_ERR(clk)) {
664 of_clk_add_provider(node, of_clk_src_simple_get, clk);
665 clk_register_clkdev(clk, clk_name, NULL);
666 }
667
668 return clk;
669} 525}
670 526
671 527
@@ -762,10 +618,19 @@ static const struct div_data sun4i_ahb_data __initconst = {
762 .width = 2, 618 .width = 2,
763}; 619};
764 620
621static const struct clk_div_table sun4i_apb0_table[] __initconst = {
622 { .val = 0, .div = 2 },
623 { .val = 1, .div = 2 },
624 { .val = 2, .div = 4 },
625 { .val = 3, .div = 8 },
626 { } /* sentinel */
627};
628
765static const struct div_data sun4i_apb0_data __initconst = { 629static const struct div_data sun4i_apb0_data __initconst = {
766 .shift = 8, 630 .shift = 8,
767 .pow = 1, 631 .pow = 1,
768 .width = 2, 632 .width = 2,
633 .table = sun4i_apb0_table,
769}; 634};
770 635
771static const struct div_data sun6i_a31_apb2_div_data __initconst = { 636static const struct div_data sun6i_a31_apb2_div_data __initconst = {
@@ -1199,7 +1064,6 @@ static const struct of_device_id clk_factors_match[] __initconst = {
1199 {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,}, 1064 {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,},
1200 {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,}, 1065 {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
1201 {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,}, 1066 {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
1202 {.compatible = "allwinner,sun4i-a10-mod0-clk", .data = &sun4i_mod0_data,},
1203 {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, 1067 {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
1204 {} 1068 {}
1205}; 1069};
@@ -1311,7 +1175,6 @@ static void __init sun4i_a10_init_clocks(struct device_node *node)
1311CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks); 1175CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks);
1312 1176
1313static const char *sun5i_critical_clocks[] __initdata = { 1177static const char *sun5i_critical_clocks[] __initdata = {
1314 "mbus",
1315 "pll5_ddr", 1178 "pll5_ddr",
1316 "ahb_sdram", 1179 "ahb_sdram",
1317}; 1180};
diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c
index 507015314827..0aa8830ae7cc 100644
--- a/drivers/clk/tegra/clk-periph-gate.c
+++ b/drivers/clk/tegra/clk-periph-gate.c
@@ -20,7 +20,8 @@
20#include <linux/io.h> 20#include <linux/io.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/err.h> 22#include <linux/err.h>
23#include <linux/tegra-soc.h> 23
24#include <soc/tegra/fuse.h>
24 25
25#include "clk.h" 26#include "clk.h"
26 27
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index 9525c684d149..e3a85842ce0c 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -1166,6 +1166,12 @@ static void __init tegra124_pll_init(void __iomem *clk_base,
1166 clk_register_clkdev(clk, "pll_c_out1", NULL); 1166 clk_register_clkdev(clk, "pll_c_out1", NULL);
1167 clks[TEGRA124_CLK_PLL_C_OUT1] = clk; 1167 clks[TEGRA124_CLK_PLL_C_OUT1] = clk;
1168 1168
1169 /* PLLC_UD */
1170 clk = clk_register_fixed_factor(NULL, "pll_c_ud", "pll_c",
1171 CLK_SET_RATE_PARENT, 1, 1);
1172 clk_register_clkdev(clk, "pll_c_ud", NULL);
1173 clks[TEGRA124_CLK_PLL_C_UD] = clk;
1174
1169 /* PLLC2 */ 1175 /* PLLC2 */
1170 clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, 1176 clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0,
1171 &pll_c2_params, NULL); 1177 &pll_c2_params, NULL);
@@ -1198,6 +1204,8 @@ static void __init tegra124_pll_init(void __iomem *clk_base,
1198 /* PLLM_UD */ 1204 /* PLLM_UD */
1199 clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m", 1205 clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m",
1200 CLK_SET_RATE_PARENT, 1, 1); 1206 CLK_SET_RATE_PARENT, 1, 1);
1207 clk_register_clkdev(clk, "pll_m_ud", NULL);
1208 clks[TEGRA124_CLK_PLL_M_UD] = clk;
1201 1209
1202 /* PLLU */ 1210 /* PLLU */
1203 val = readl(clk_base + pll_u_params.base_reg); 1211 val = readl(clk_base + pll_u_params.base_reg);
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index 8b10c38b6e3c..5bbacd01094f 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -22,8 +22,11 @@
22#include <linux/of.h> 22#include <linux/of.h>
23#include <linux/of_address.h> 23#include <linux/of_address.h>
24#include <linux/clk/tegra.h> 24#include <linux/clk/tegra.h>
25#include <linux/tegra-powergate.h> 25
26#include <soc/tegra/pmc.h>
27
26#include <dt-bindings/clock/tegra30-car.h> 28#include <dt-bindings/clock/tegra30-car.h>
29
27#include "clk.h" 30#include "clk.h"
28#include "clk-id.h" 31#include "clk-id.h"
29 32
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index bf452b62beb8..97dc8595c3cd 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -19,7 +19,8 @@
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/clk/tegra.h> 20#include <linux/clk/tegra.h>
21#include <linux/reset-controller.h> 21#include <linux/reset-controller.h>
22#include <linux/tegra-soc.h> 22
23#include <soc/tegra/fuse.h>
23 24
24#include "clk.h" 25#include "clk.h"
25 26
@@ -206,8 +207,13 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl,
206 207
207 for (; tbl->clk_id < clk_max; tbl++) { 208 for (; tbl->clk_id < clk_max; tbl++) {
208 clk = clks[tbl->clk_id]; 209 clk = clks[tbl->clk_id];
209 if (IS_ERR_OR_NULL(clk)) 210 if (IS_ERR_OR_NULL(clk)) {
210 return; 211 pr_err("%s: invalid entry %ld in clks array for id %d\n",
212 __func__, PTR_ERR(clk), tbl->clk_id);
213 WARN_ON(1);
214
215 continue;
216 }
211 217
212 if (tbl->parent_id < clk_max) { 218 if (tbl->parent_id < clk_max) {
213 struct clk *parent = clks[tbl->parent_id]; 219 struct clk *parent = clks[tbl->parent_id];
diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
index 4a65b410e4d5..59bb4b39d12e 100644
--- a/drivers/clk/ti/clk-dra7-atl.c
+++ b/drivers/clk/ti/clk-dra7-atl.c
@@ -139,9 +139,13 @@ static long atl_clk_round_rate(struct clk_hw *hw, unsigned long rate,
139static int atl_clk_set_rate(struct clk_hw *hw, unsigned long rate, 139static int atl_clk_set_rate(struct clk_hw *hw, unsigned long rate,
140 unsigned long parent_rate) 140 unsigned long parent_rate)
141{ 141{
142 struct dra7_atl_desc *cdesc = to_atl_desc(hw); 142 struct dra7_atl_desc *cdesc;
143 u32 divider; 143 u32 divider;
144 144
145 if (!hw || !rate)
146 return -EINVAL;
147
148 cdesc = to_atl_desc(hw);
145 divider = ((parent_rate + rate / 2) / rate) - 1; 149 divider = ((parent_rate + rate / 2) / rate) - 1;
146 if (divider > DRA7_ATL_DIVIDER_MASK) 150 if (divider > DRA7_ATL_DIVIDER_MASK)
147 divider = DRA7_ATL_DIVIDER_MASK; 151 divider = DRA7_ATL_DIVIDER_MASK;
@@ -199,6 +203,7 @@ static void __init of_dra7_atl_clock_setup(struct device_node *node)
199 203
200 if (!IS_ERR(clk)) { 204 if (!IS_ERR(clk)) {
201 of_clk_add_provider(node, of_clk_src_simple_get, clk); 205 of_clk_add_provider(node, of_clk_src_simple_get, clk);
206 kfree(parent_names);
202 return; 207 return;
203 } 208 }
204cleanup: 209cleanup:
@@ -224,6 +229,7 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev)
224 cinfo->iobase = of_iomap(node, 0); 229 cinfo->iobase = of_iomap(node, 0);
225 cinfo->dev = &pdev->dev; 230 cinfo->dev = &pdev->dev;
226 pm_runtime_enable(cinfo->dev); 231 pm_runtime_enable(cinfo->dev);
232 pm_runtime_irq_safe(cinfo->dev);
227 233
228 pm_runtime_get_sync(cinfo->dev); 234 pm_runtime_get_sync(cinfo->dev);
229 atl_write(cinfo, DRA7_ATL_PCLKMUX_REG(0), DRA7_ATL_PCLKMUX); 235 atl_write(cinfo, DRA7_ATL_PCLKMUX_REG(0), DRA7_ATL_PCLKMUX);
@@ -297,7 +303,6 @@ MODULE_DEVICE_TABLE(of, of_dra7_atl_clk_match_tbl);
297static struct platform_driver dra7_atl_clk_driver = { 303static struct platform_driver dra7_atl_clk_driver = {
298 .driver = { 304 .driver = {
299 .name = "dra7-atl", 305 .name = "dra7-atl",
300 .owner = THIS_MODULE,
301 .of_match_table = of_dra7_atl_clk_match_tbl, 306 .of_match_table = of_dra7_atl_clk_match_tbl,
302 }, 307 },
303 .probe = of_dra7_atl_clk_probe, 308 .probe = of_dra7_atl_clk_probe,
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index b1a6f7144f3f..337abe5909e1 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -25,8 +25,8 @@
25#undef pr_fmt 25#undef pr_fmt
26#define pr_fmt(fmt) "%s: " fmt, __func__ 26#define pr_fmt(fmt) "%s: " fmt, __func__
27 27
28static int ti_dt_clk_memmap_index;
29struct ti_clk_ll_ops *ti_clk_ll_ops; 28struct ti_clk_ll_ops *ti_clk_ll_ops;
29static struct device_node *clocks_node_ptr[CLK_MAX_MEMMAPS];
30 30
31/** 31/**
32 * ti_dt_clocks_register - register DT alias clocks during boot 32 * ti_dt_clocks_register - register DT alias clocks during boot
@@ -108,9 +108,21 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
108 struct clk_omap_reg *reg; 108 struct clk_omap_reg *reg;
109 u32 val; 109 u32 val;
110 u32 tmp; 110 u32 tmp;
111 int i;
111 112
112 reg = (struct clk_omap_reg *)&tmp; 113 reg = (struct clk_omap_reg *)&tmp;
113 reg->index = ti_dt_clk_memmap_index; 114
115 for (i = 0; i < CLK_MAX_MEMMAPS; i++) {
116 if (clocks_node_ptr[i] == node->parent)
117 break;
118 }
119
120 if (i == CLK_MAX_MEMMAPS) {
121 pr_err("clk-provider not found for %s!\n", node->name);
122 return NULL;
123 }
124
125 reg->index = i;
114 126
115 if (of_property_read_u32_index(node, "reg", index, &val)) { 127 if (of_property_read_u32_index(node, "reg", index, &val)) {
116 pr_err("%s must have reg[%d]!\n", node->name, index); 128 pr_err("%s must have reg[%d]!\n", node->name, index);
@@ -127,20 +139,14 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
127 * @parent: master node 139 * @parent: master node
128 * @index: internal index for clk_reg_ops 140 * @index: internal index for clk_reg_ops
129 * 141 *
130 * Initializes a master clock IP block and its child clock nodes. 142 * Initializes a master clock IP block. This basically sets up the
131 * Regmap is provided for accessing the register space for the 143 * mapping from clocks node to the memory map index. All the clocks
132 * IP block and all the clocks under it. 144 * are then initialized through the common of_clk_init call, and the
145 * clocks will access their memory maps based on the node layout.
133 */ 146 */
134void ti_dt_clk_init_provider(struct device_node *parent, int index) 147void ti_dt_clk_init_provider(struct device_node *parent, int index)
135{ 148{
136 const struct of_device_id *match;
137 struct device_node *np;
138 struct device_node *clocks; 149 struct device_node *clocks;
139 of_clk_init_cb_t clk_init_cb;
140 struct clk_init_item *retry;
141 struct clk_init_item *tmp;
142
143 ti_dt_clk_memmap_index = index;
144 150
145 /* get clocks for this parent */ 151 /* get clocks for this parent */
146 clocks = of_get_child_by_name(parent, "clocks"); 152 clocks = of_get_child_by_name(parent, "clocks");
@@ -149,19 +155,31 @@ void ti_dt_clk_init_provider(struct device_node *parent, int index)
149 return; 155 return;
150 } 156 }
151 157
152 for_each_child_of_node(clocks, np) { 158 /* add clocks node info */
153 match = of_match_node(&__clk_of_table, np); 159 clocks_node_ptr[index] = clocks;
154 if (!match) 160}
155 continue;
156 clk_init_cb = (of_clk_init_cb_t)match->data;
157 pr_debug("%s: initializing: %s\n", __func__, np->name);
158 clk_init_cb(np);
159 }
160 161
161 list_for_each_entry_safe(retry, tmp, &retry_list, link) { 162/**
162 pr_debug("retry-init: %s\n", retry->node->name); 163 * ti_dt_clk_init_retry_clks - init clocks from the retry list
163 retry->func(retry->hw, retry->node); 164 *
164 list_del(&retry->link); 165 * Initializes any clocks that have failed to initialize before,
165 kfree(retry); 166 * reasons being missing parent node(s) during earlier init. This
167 * typically happens only for DPLLs which need to have both of their
168 * parent clocks ready during init.
169 */
170void ti_dt_clk_init_retry_clks(void)
171{
172 struct clk_init_item *retry;
173 struct clk_init_item *tmp;
174 int retries = 5;
175
176 while (!list_empty(&retry_list) && retries) {
177 list_for_each_entry_safe(retry, tmp, &retry_list, link) {
178 pr_debug("retry-init: %s\n", retry->node->name);
179 retry->func(retry->hw, retry->node);
180 list_del(&retry->link);
181 kfree(retry);
182 }
183 retries--;
166 } 184 }
167} 185}
diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c
index f1e0038d76ac..b4c5faccaece 100644
--- a/drivers/clk/ti/clockdomain.c
+++ b/drivers/clk/ti/clockdomain.c
@@ -36,6 +36,11 @@ static void __init of_ti_clockdomain_setup(struct device_node *node)
36 36
37 for (i = 0; i < num_clks; i++) { 37 for (i = 0; i < num_clks; i++) {
38 clk = of_clk_get(node, i); 38 clk = of_clk_get(node, i);
39 if (IS_ERR(clk)) {
40 pr_err("%s: Failed get %s' clock nr %d (%ld)\n",
41 __func__, node->full_name, i, PTR_ERR(clk));
42 continue;
43 }
39 if (__clk_get_flags(clk) & CLK_IS_BASIC) { 44 if (__clk_get_flags(clk) & CLK_IS_BASIC) {
40 pr_warn("can't setup clkdm for basic clk %s\n", 45 pr_warn("can't setup clkdm for basic clk %s\n",
41 __clk_get_name(clk)); 46 __clk_get_name(clk));
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
index e6aa10db7bba..bff2b5b8ff59 100644
--- a/drivers/clk/ti/divider.c
+++ b/drivers/clk/ti/divider.c
@@ -211,11 +211,16 @@ static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
211static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, 211static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
212 unsigned long parent_rate) 212 unsigned long parent_rate)
213{ 213{
214 struct clk_divider *divider = to_clk_divider(hw); 214 struct clk_divider *divider;
215 unsigned int div, value; 215 unsigned int div, value;
216 unsigned long flags = 0; 216 unsigned long flags = 0;
217 u32 val; 217 u32 val;
218 218
219 if (!hw || !rate)
220 return -EINVAL;
221
222 divider = to_clk_divider(hw);
223
219 div = DIV_ROUND_UP(parent_rate, rate); 224 div = DIV_ROUND_UP(parent_rate, rate);
220 value = _get_val(divider, div); 225 value = _get_val(divider, div);
221 226
@@ -295,8 +300,8 @@ static struct clk *_register_divider(struct device *dev, const char *name,
295 return clk; 300 return clk;
296} 301}
297 302
298static struct clk_div_table 303static struct clk_div_table *
299__init *ti_clk_get_div_table(struct device_node *node) 304__init ti_clk_get_div_table(struct device_node *node)
300{ 305{
301 struct clk_div_table *table; 306 struct clk_div_table *table;
302 const __be32 *divspec; 307 const __be32 *divspec;
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
index fd449f9b006d..162e519cb0f9 100644
--- a/drivers/clk/versatile/Makefile
+++ b/drivers/clk/versatile/Makefile
@@ -1,6 +1,5 @@
1# Makefile for Versatile-specific clocks 1# Makefile for Versatile-specific clocks
2obj-$(CONFIG_ICST) += clk-icst.o 2obj-$(CONFIG_ICST) += clk-icst.o clk-versatile.o
3obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o
4obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o 3obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o
5obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o 4obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o
6obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o 5obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o
diff --git a/drivers/clk/versatile/clk-integrator.c b/drivers/clk/versatile/clk-versatile.c
index 734c4b8fe6ab..a76981e88cb6 100644
--- a/drivers/clk/versatile/clk-integrator.c
+++ b/drivers/clk/versatile/clk-versatile.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Clock driver for the ARM Integrator/AP and Integrator/CP boards 2 * Clock driver for the ARM Integrator/AP, Integrator/CP, Versatile AB and
3 * Versatile PB boards.
3 * Copyright (C) 2012 Linus Walleij 4 * Copyright (C) 2012 Linus Walleij
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
@@ -17,6 +18,9 @@
17 18
18#define INTEGRATOR_HDR_LOCK_OFFSET 0x14 19#define INTEGRATOR_HDR_LOCK_OFFSET 0x14
19 20
21#define VERSATILE_SYS_OSCCLCD_OFFSET 0x1c
22#define VERSATILE_SYS_LOCK_OFFSET 0x20
23
20/* Base offset for the core module */ 24/* Base offset for the core module */
21static void __iomem *cm_base; 25static void __iomem *cm_base;
22 26
@@ -37,11 +41,27 @@ static const struct clk_icst_desc __initdata cm_auxosc_desc = {
37 .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET, 41 .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET,
38}; 42};
39 43
40static void __init of_integrator_cm_osc_setup(struct device_node *np) 44static const struct icst_params versatile_auxosc_params = {
45 .vco_max = ICST307_VCO_MAX,
46 .vco_min = ICST307_VCO_MIN,
47 .vd_min = 4 + 8,
48 .vd_max = 511 + 8,
49 .rd_min = 1 + 2,
50 .rd_max = 127 + 2,
51 .s2div = icst307_s2div,
52 .idx2s = icst307_idx2s,
53};
54
55static const struct clk_icst_desc versatile_auxosc_desc __initconst = {
56 .params = &versatile_auxosc_params,
57 .vco_offset = VERSATILE_SYS_OSCCLCD_OFFSET,
58 .lock_offset = VERSATILE_SYS_LOCK_OFFSET,
59};
60static void __init cm_osc_setup(struct device_node *np,
61 const struct clk_icst_desc *desc)
41{ 62{
42 struct clk *clk = ERR_PTR(-EINVAL); 63 struct clk *clk = ERR_PTR(-EINVAL);
43 const char *clk_name = np->name; 64 const char *clk_name = np->name;
44 const struct clk_icst_desc *desc = &cm_auxosc_desc;
45 const char *parent_name; 65 const char *parent_name;
46 66
47 if (!cm_base) { 67 if (!cm_base) {
@@ -65,5 +85,17 @@ static void __init of_integrator_cm_osc_setup(struct device_node *np)
65 if (!IS_ERR(clk)) 85 if (!IS_ERR(clk))
66 of_clk_add_provider(np, of_clk_src_simple_get, clk); 86 of_clk_add_provider(np, of_clk_src_simple_get, clk);
67} 87}
88
89static void __init of_integrator_cm_osc_setup(struct device_node *np)
90{
91 cm_osc_setup(np, &cm_auxosc_desc);
92}
68CLK_OF_DECLARE(integrator_cm_auxosc_clk, 93CLK_OF_DECLARE(integrator_cm_auxosc_clk,
69 "arm,integrator-cm-auxosc", of_integrator_cm_osc_setup); 94 "arm,integrator-cm-auxosc", of_integrator_cm_osc_setup);
95
96static void __init of_versatile_cm_osc_setup(struct device_node *np)
97{
98 cm_osc_setup(np, &versatile_auxosc_desc);
99}
100CLK_OF_DECLARE(versatile_cm_auxosc_clk,
101 "arm,versatile-cm-auxosc", of_versatile_cm_osc_setup);
diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c
index 246cf1226eaa..9037bebd69f7 100644
--- a/drivers/clk/zynq/clkc.c
+++ b/drivers/clk/zynq/clkc.c
@@ -85,24 +85,22 @@ static DEFINE_SPINLOCK(canmioclk_lock);
85static DEFINE_SPINLOCK(dbgclk_lock); 85static DEFINE_SPINLOCK(dbgclk_lock);
86static DEFINE_SPINLOCK(aperclk_lock); 86static DEFINE_SPINLOCK(aperclk_lock);
87 87
88static const char dummy_nm[] __initconst = "dummy_name"; 88static const char *armpll_parents[] __initconst = {"armpll_int", "ps_clk"};
89 89static const char *ddrpll_parents[] __initconst = {"ddrpll_int", "ps_clk"};
90static const char *armpll_parents[] __initdata = {"armpll_int", "ps_clk"}; 90static const char *iopll_parents[] __initconst = {"iopll_int", "ps_clk"};
91static const char *ddrpll_parents[] __initdata = {"ddrpll_int", "ps_clk"}; 91static const char *gem0_mux_parents[] __initconst = {"gem0_div1", "dummy_name"};
92static const char *iopll_parents[] __initdata = {"iopll_int", "ps_clk"}; 92static const char *gem1_mux_parents[] __initconst = {"gem1_div1", "dummy_name"};
93static const char *gem0_mux_parents[] __initdata = {"gem0_div1", dummy_nm}; 93static const char *can0_mio_mux2_parents[] __initconst = {"can0_gate",
94static const char *gem1_mux_parents[] __initdata = {"gem1_div1", dummy_nm};
95static const char *can0_mio_mux2_parents[] __initdata = {"can0_gate",
96 "can0_mio_mux"}; 94 "can0_mio_mux"};
97static const char *can1_mio_mux2_parents[] __initdata = {"can1_gate", 95static const char *can1_mio_mux2_parents[] __initconst = {"can1_gate",
98 "can1_mio_mux"}; 96 "can1_mio_mux"};
99static const char *dbg_emio_mux_parents[] __initdata = {"dbg_div", 97static const char *dbg_emio_mux_parents[] __initconst = {"dbg_div",
100 dummy_nm}; 98 "dummy_name"};
101 99
102static const char *dbgtrc_emio_input_names[] __initdata = {"trace_emio_clk"}; 100static const char *dbgtrc_emio_input_names[] __initconst = {"trace_emio_clk"};
103static const char *gem0_emio_input_names[] __initdata = {"gem0_emio_clk"}; 101static const char *gem0_emio_input_names[] __initconst = {"gem0_emio_clk"};
104static const char *gem1_emio_input_names[] __initdata = {"gem1_emio_clk"}; 102static const char *gem1_emio_input_names[] __initconst = {"gem1_emio_clk"};
105static const char *swdt_ext_clk_input_names[] __initdata = {"swdt_ext_clk"}; 103static const char *swdt_ext_clk_input_names[] __initconst = {"swdt_ext_clk"};
106 104
107static void __init zynq_clk_register_fclk(enum zynq_clk fclk, 105static void __init zynq_clk_register_fclk(enum zynq_clk fclk,
108 const char *clk_name, void __iomem *fclk_ctrl_reg, 106 const char *clk_name, void __iomem *fclk_ctrl_reg,
@@ -230,6 +228,7 @@ static void __init zynq_clk_setup(struct device_node *np)
230 const char *periph_parents[4]; 228 const char *periph_parents[4];
231 const char *swdt_ext_clk_mux_parents[2]; 229 const char *swdt_ext_clk_mux_parents[2];
232 const char *can_mio_mux_parents[NUM_MIO_PINS]; 230 const char *can_mio_mux_parents[NUM_MIO_PINS];
231 const char *dummy_nm = "dummy_name";
233 232
234 pr_info("Zynq clock init\n"); 233 pr_info("Zynq clock init\n");
235 234
@@ -619,5 +618,4 @@ void __init zynq_clock_init(void)
619np_err: 618np_err:
620 of_node_put(np); 619 of_node_put(np);
621 BUG(); 620 BUG();
622 return;
623} 621}
diff --git a/drivers/clk/zynq/pll.c b/drivers/clk/zynq/pll.c
index cec97596fe65..00d72fb5c036 100644
--- a/drivers/clk/zynq/pll.c
+++ b/drivers/clk/zynq/pll.c
@@ -211,10 +211,8 @@ struct clk *clk_register_zynq_pll(const char *name, const char *parent,
211 }; 211 };
212 212
213 pll = kmalloc(sizeof(*pll), GFP_KERNEL); 213 pll = kmalloc(sizeof(*pll), GFP_KERNEL);
214 if (!pll) { 214 if (!pll)
215 pr_err("%s: Could not allocate Zynq PLL clk.\n", __func__);
216 return ERR_PTR(-ENOMEM); 215 return ERR_PTR(-ENOMEM);
217 }
218 216
219 /* Populate the struct */ 217 /* Populate the struct */
220 pll->hw.init = &initd; 218 pll->hw.init = &initd;