aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/Kconfig19
-rw-r--r--drivers/clk/Makefile6
-rw-r--r--drivers/clk/at91/Makefile4
-rw-r--r--drivers/clk/at91/clk-main.c577
-rw-r--r--drivers/clk/at91/clk-slow.c467
-rw-r--r--drivers/clk/at91/pmc.c17
-rw-r--r--drivers/clk/at91/pmc.h9
-rw-r--r--drivers/clk/at91/sckc.c57
-rw-r--r--drivers/clk/at91/sckc.h22
-rw-r--r--drivers/clk/bcm/Kconfig2
-rw-r--r--drivers/clk/bcm/Makefile1
-rw-r--r--drivers/clk/bcm/clk-bcm21664.c290
-rw-r--r--drivers/clk/bcm/clk-bcm281xx.c231
-rw-r--r--drivers/clk/bcm/clk-kona-setup.c229
-rw-r--r--drivers/clk/bcm/clk-kona.c266
-rw-r--r--drivers/clk/bcm/clk-kona.h160
-rw-r--r--drivers/clk/berlin/Makefile4
-rw-r--r--drivers/clk/berlin/berlin2-avpll.c393
-rw-r--r--drivers/clk/berlin/berlin2-avpll.h36
-rw-r--r--drivers/clk/berlin/berlin2-div.c265
-rw-r--r--drivers/clk/berlin/berlin2-div.h89
-rw-r--r--drivers/clk/berlin/berlin2-pll.c117
-rw-r--r--drivers/clk/berlin/berlin2-pll.h37
-rw-r--r--drivers/clk/berlin/bg2.c691
-rw-r--r--drivers/clk/berlin/bg2q.c389
-rw-r--r--drivers/clk/berlin/common.h29
-rw-r--r--drivers/clk/clk-axm5516.c615
-rw-r--r--drivers/clk/clk-divider.c93
-rw-r--r--drivers/clk/clk-fractional-divider.c135
-rw-r--r--drivers/clk/clk-s2mps11.c88
-rw-r--r--drivers/clk/clk-si570.c2
-rw-r--r--drivers/clk/clk-u300.c1
-rw-r--r--drivers/clk/clk.c47
-rw-r--r--drivers/clk/clk.h1
-rw-r--r--drivers/clk/clkdev.c34
-rw-r--r--drivers/clk/hisilicon/Makefile1
-rw-r--r--drivers/clk/hisilicon/clk-hix5hd2.c101
-rw-r--r--drivers/clk/hisilicon/clk.c41
-rw-r--r--drivers/clk/hisilicon/clk.h3
-rw-r--r--drivers/clk/mvebu/Kconfig4
-rw-r--r--drivers/clk/mvebu/Makefile1
-rw-r--r--drivers/clk/mvebu/orion.c210
-rw-r--r--drivers/clk/qcom/Kconfig4
-rw-r--r--drivers/clk/qcom/Makefile1
-rw-r--r--drivers/clk/qcom/clk-rcg.h3
-rw-r--r--drivers/clk/qcom/clk-rcg2.c304
-rw-r--r--drivers/clk/qcom/common.c101
-rw-r--r--drivers/clk/qcom/common.h34
-rw-r--r--drivers/clk/qcom/gcc-msm8660.c77
-rw-r--r--drivers/clk/qcom/gcc-msm8960.c109
-rw-r--r--drivers/clk/qcom/gcc-msm8974.c207
-rw-r--r--drivers/clk/qcom/mmcc-msm8960.c78
-rw-r--r--drivers/clk/qcom/mmcc-msm8974.c198
-rw-r--r--drivers/clk/rockchip/clk-rockchip.c3
-rw-r--r--drivers/clk/samsung/Kconfig26
-rw-r--r--drivers/clk/samsung/Makefile7
-rw-r--r--drivers/clk/samsung/clk-exynos3250.c780
-rw-r--r--drivers/clk/samsung/clk-exynos4.c55
-rw-r--r--drivers/clk/samsung/clk-exynos5250.c118
-rw-r--r--drivers/clk/samsung/clk-exynos5260.c1980
-rw-r--r--drivers/clk/samsung/clk-exynos5260.h459
-rw-r--r--drivers/clk/samsung/clk-exynos5410.c209
-rw-r--r--drivers/clk/samsung/clk-exynos5420.c1127
-rw-r--r--drivers/clk/samsung/clk-exynos5440.c18
-rw-r--r--drivers/clk/samsung/clk-pll.c489
-rw-r--r--drivers/clk/samsung/clk-pll.h8
-rw-r--r--drivers/clk/samsung/clk-s3c2410-dclk.c440
-rw-r--r--drivers/clk/samsung/clk-s3c2410.c482
-rw-r--r--drivers/clk/samsung/clk-s3c2412.c274
-rw-r--r--drivers/clk/samsung/clk-s3c2443.c466
-rw-r--r--drivers/clk/samsung/clk-s3c64xx.c44
-rw-r--r--drivers/clk/samsung/clk.c123
-rw-r--r--drivers/clk/samsung/clk.h72
-rw-r--r--drivers/clk/shmobile/Makefile2
-rw-r--r--drivers/clk/shmobile/clk-mstp.c2
-rw-r--r--drivers/clk/shmobile/clk-r8a7740.c199
-rw-r--r--drivers/clk/shmobile/clk-r8a7779.c180
-rw-r--r--drivers/clk/socfpga/clk-gate.c1
-rw-r--r--drivers/clk/socfpga/clk-periph.c22
-rw-r--r--drivers/clk/socfpga/clk.h4
-rw-r--r--drivers/clk/st/clkgen-pll.c1
-rw-r--r--drivers/clk/sunxi/clk-factors.c36
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c42
-rw-r--r--drivers/clk/tegra/clk-id.h1
-rw-r--r--drivers/clk/tegra/clk-pll.c33
-rw-r--r--drivers/clk/tegra/clk-tegra-periph.c10
-rw-r--r--drivers/clk/tegra/clk-tegra114.c22
-rw-r--r--drivers/clk/tegra/clk-tegra124.c21
-rw-r--r--drivers/clk/ti/clk-43xx.c6
-rw-r--r--drivers/clk/ti/gate.c2
-rw-r--r--drivers/clk/versatile/Kconfig26
-rw-r--r--drivers/clk/versatile/Makefile5
-rw-r--r--drivers/clk/versatile/clk-icst.c2
-rw-r--r--drivers/clk/versatile/clk-impd1.c38
-rw-r--r--drivers/clk/versatile/clk-vexpress-osc.c96
-rw-r--r--drivers/clk/zynq/clkc.c12
96 files changed, 13457 insertions, 1386 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 6f56d3a4f010..9f9c5ae5359b 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -30,14 +30,7 @@ config COMMON_CLK_WM831X
30 Supports the clocking subsystem of the WM831x/2x series of 30 Supports the clocking subsystem of the WM831x/2x series of
31 PMICs from Wolfson Microlectronics. 31 PMICs from Wolfson Microlectronics.
32 32
33config COMMON_CLK_VERSATILE 33source "drivers/clk/versatile/Kconfig"
34 bool "Clock driver for ARM Reference designs"
35 depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64
36 ---help---
37 Supports clocking on ARM Reference designs:
38 - Integrator/AP and Integrator/CP
39 - RealView PB1176, EB, PB11MP and PBX
40 - Versatile Express
41 34
42config COMMON_CLK_MAX77686 35config COMMON_CLK_MAX77686
43 tristate "Clock driver for Maxim 77686 MFD" 36 tristate "Clock driver for Maxim 77686 MFD"
@@ -65,12 +58,12 @@ config COMMON_CLK_SI570
65 clock generators. 58 clock generators.
66 59
67config COMMON_CLK_S2MPS11 60config COMMON_CLK_S2MPS11
68 tristate "Clock driver for S2MPS11/S5M8767 MFD" 61 tristate "Clock driver for S2MPS1X/S5M8767 MFD"
69 depends on MFD_SEC_CORE 62 depends on MFD_SEC_CORE
70 ---help--- 63 ---help---
71 This driver supports S2MPS11/S5M8767 crystal oscillator clock. These 64 This driver supports S2MPS11/S2MPS14/S5M8767 crystal oscillator
72 multi-function devices have 3 fixed-rate oscillators, clocked at 65 clock. These multi-function devices have two (S2MPS14) or three
73 32KHz each. 66 (S2MPS11, S5M8767) fixed-rate oscillators, clocked at 32KHz each.
74 67
75config CLK_TWL6040 68config CLK_TWL6040
76 tristate "External McPDM functional clock from twl6040" 69 tristate "External McPDM functional clock from twl6040"
@@ -115,3 +108,5 @@ endmenu
115 108
116source "drivers/clk/bcm/Kconfig" 109source "drivers/clk/bcm/Kconfig"
117source "drivers/clk/mvebu/Kconfig" 110source "drivers/clk/mvebu/Kconfig"
111
112source "drivers/clk/samsung/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 5f8a28735c96..567f10259029 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -8,10 +8,12 @@ obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o
8obj-$(CONFIG_COMMON_CLK) += clk-gate.o 8obj-$(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
11 12
12# hardware specific clock types 13# hardware specific clock types
13# please keep this section sorted lexicographically by file/directory path name 14# please keep this section sorted lexicographically by file/directory path name
14obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o 15obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
16obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o
15obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o 17obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
16obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o 18obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
17obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o 19obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
@@ -31,8 +33,10 @@ obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
31obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o 33obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o
32obj-$(CONFIG_COMMON_CLK_AT91) += at91/ 34obj-$(CONFIG_COMMON_CLK_AT91) += at91/
33obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm/ 35obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm/
36obj-$(CONFIG_ARCH_BERLIN) += berlin/
34obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/ 37obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/
35obj-$(CONFIG_ARCH_HIP04) += hisilicon/ 38obj-$(CONFIG_ARCH_HIP04) += hisilicon/
39obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/
36obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ 40obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/
37ifeq ($(CONFIG_COMMON_CLK), y) 41ifeq ($(CONFIG_COMMON_CLK), y)
38obj-$(CONFIG_ARCH_MMP) += mmp/ 42obj-$(CONFIG_ARCH_MMP) += mmp/
@@ -41,7 +45,7 @@ obj-$(CONFIG_PLAT_ORION) += mvebu/
41obj-$(CONFIG_ARCH_MXS) += mxs/ 45obj-$(CONFIG_ARCH_MXS) += mxs/
42obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ 46obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/
43obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ 47obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
44obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ 48obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
45obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += shmobile/ 49obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += shmobile/
46obj-$(CONFIG_ARCH_SIRF) += sirf/ 50obj-$(CONFIG_ARCH_SIRF) += sirf/
47obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ 51obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile
index 46c1d3d0d66b..4998aee59267 100644
--- a/drivers/clk/at91/Makefile
+++ b/drivers/clk/at91/Makefile
@@ -2,8 +2,8 @@
2# Makefile for at91 specific clk 2# Makefile for at91 specific clk
3# 3#
4 4
5obj-y += pmc.o 5obj-y += pmc.o sckc.o
6obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o 6obj-y += clk-slow.o clk-main.o clk-pll.o clk-plldiv.o clk-master.o
7obj-y += clk-system.o clk-peripheral.o clk-programmable.o 7obj-y += clk-system.o clk-peripheral.o clk-programmable.o
8 8
9obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o 9obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o
diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c
index 8e9e8cc0412d..733306131b99 100644
--- a/drivers/clk/at91/clk-main.c
+++ b/drivers/clk/at91/clk-main.c
@@ -30,99 +30,546 @@
30#define MAINF_LOOP_MIN_WAIT (USEC_PER_SEC / SLOW_CLOCK_FREQ) 30#define MAINF_LOOP_MIN_WAIT (USEC_PER_SEC / SLOW_CLOCK_FREQ)
31#define MAINF_LOOP_MAX_WAIT MAINFRDY_TIMEOUT 31#define MAINF_LOOP_MAX_WAIT MAINFRDY_TIMEOUT
32 32
33struct clk_main { 33#define MOR_KEY_MASK (0xff << 16)
34
35struct clk_main_osc {
34 struct clk_hw hw; 36 struct clk_hw hw;
35 struct at91_pmc *pmc; 37 struct at91_pmc *pmc;
36 unsigned long rate;
37 unsigned int irq; 38 unsigned int irq;
38 wait_queue_head_t wait; 39 wait_queue_head_t wait;
39}; 40};
40 41
41#define to_clk_main(hw) container_of(hw, struct clk_main, hw) 42#define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw)
43
44struct clk_main_rc_osc {
45 struct clk_hw hw;
46 struct at91_pmc *pmc;
47 unsigned int irq;
48 wait_queue_head_t wait;
49 unsigned long frequency;
50 unsigned long accuracy;
51};
52
53#define to_clk_main_rc_osc(hw) container_of(hw, struct clk_main_rc_osc, hw)
54
55struct clk_rm9200_main {
56 struct clk_hw hw;
57 struct at91_pmc *pmc;
58};
59
60#define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw)
42 61
43static irqreturn_t clk_main_irq_handler(int irq, void *dev_id) 62struct clk_sam9x5_main {
63 struct clk_hw hw;
64 struct at91_pmc *pmc;
65 unsigned int irq;
66 wait_queue_head_t wait;
67 u8 parent;
68};
69
70#define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw)
71
72static irqreturn_t clk_main_osc_irq_handler(int irq, void *dev_id)
44{ 73{
45 struct clk_main *clkmain = (struct clk_main *)dev_id; 74 struct clk_main_osc *osc = dev_id;
46 75
47 wake_up(&clkmain->wait); 76 wake_up(&osc->wait);
48 disable_irq_nosync(clkmain->irq); 77 disable_irq_nosync(osc->irq);
49 78
50 return IRQ_HANDLED; 79 return IRQ_HANDLED;
51} 80}
52 81
53static int clk_main_prepare(struct clk_hw *hw) 82static int clk_main_osc_prepare(struct clk_hw *hw)
54{ 83{
55 struct clk_main *clkmain = to_clk_main(hw); 84 struct clk_main_osc *osc = to_clk_main_osc(hw);
56 struct at91_pmc *pmc = clkmain->pmc; 85 struct at91_pmc *pmc = osc->pmc;
57 unsigned long halt_time, timeout;
58 u32 tmp; 86 u32 tmp;
59 87
88 tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
89 if (tmp & AT91_PMC_OSCBYPASS)
90 return 0;
91
92 if (!(tmp & AT91_PMC_MOSCEN)) {
93 tmp |= AT91_PMC_MOSCEN | AT91_PMC_KEY;
94 pmc_write(pmc, AT91_CKGR_MOR, tmp);
95 }
96
60 while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS)) { 97 while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS)) {
61 enable_irq(clkmain->irq); 98 enable_irq(osc->irq);
62 wait_event(clkmain->wait, 99 wait_event(osc->wait,
63 pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS); 100 pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS);
64 } 101 }
65 102
66 if (clkmain->rate) 103 return 0;
67 return 0; 104}
105
106static void clk_main_osc_unprepare(struct clk_hw *hw)
107{
108 struct clk_main_osc *osc = to_clk_main_osc(hw);
109 struct at91_pmc *pmc = osc->pmc;
110 u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
111
112 if (tmp & AT91_PMC_OSCBYPASS)
113 return;
114
115 if (!(tmp & AT91_PMC_MOSCEN))
116 return;
117
118 tmp &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN);
119 pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
120}
121
122static int clk_main_osc_is_prepared(struct clk_hw *hw)
123{
124 struct clk_main_osc *osc = to_clk_main_osc(hw);
125 struct at91_pmc *pmc = osc->pmc;
126 u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
127
128 if (tmp & AT91_PMC_OSCBYPASS)
129 return 1;
130
131 return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS) &&
132 (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN));
133}
134
135static const struct clk_ops main_osc_ops = {
136 .prepare = clk_main_osc_prepare,
137 .unprepare = clk_main_osc_unprepare,
138 .is_prepared = clk_main_osc_is_prepared,
139};
140
141static struct clk * __init
142at91_clk_register_main_osc(struct at91_pmc *pmc,
143 unsigned int irq,
144 const char *name,
145 const char *parent_name,
146 bool bypass)
147{
148 int ret;
149 struct clk_main_osc *osc;
150 struct clk *clk = NULL;
151 struct clk_init_data init;
152
153 if (!pmc || !irq || !name || !parent_name)
154 return ERR_PTR(-EINVAL);
155
156 osc = kzalloc(sizeof(*osc), GFP_KERNEL);
157 if (!osc)
158 return ERR_PTR(-ENOMEM);
159
160 init.name = name;
161 init.ops = &main_osc_ops;
162 init.parent_names = &parent_name;
163 init.num_parents = 1;
164 init.flags = CLK_IGNORE_UNUSED;
165
166 osc->hw.init = &init;
167 osc->pmc = pmc;
168 osc->irq = irq;
169
170 init_waitqueue_head(&osc->wait);
171 irq_set_status_flags(osc->irq, IRQ_NOAUTOEN);
172 ret = request_irq(osc->irq, clk_main_osc_irq_handler,
173 IRQF_TRIGGER_HIGH, name, osc);
174 if (ret)
175 return ERR_PTR(ret);
176
177 if (bypass)
178 pmc_write(pmc, AT91_CKGR_MOR,
179 (pmc_read(pmc, AT91_CKGR_MOR) &
180 ~(MOR_KEY_MASK | AT91_PMC_MOSCEN)) |
181 AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
182
183 clk = clk_register(NULL, &osc->hw);
184 if (IS_ERR(clk)) {
185 free_irq(irq, osc);
186 kfree(osc);
187 }
188
189 return clk;
190}
191
192void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np,
193 struct at91_pmc *pmc)
194{
195 struct clk *clk;
196 unsigned int irq;
197 const char *name = np->name;
198 const char *parent_name;
199 bool bypass;
200
201 of_property_read_string(np, "clock-output-names", &name);
202 bypass = of_property_read_bool(np, "atmel,osc-bypass");
203 parent_name = of_clk_get_parent_name(np, 0);
204
205 irq = irq_of_parse_and_map(np, 0);
206 if (!irq)
207 return;
208
209 clk = at91_clk_register_main_osc(pmc, irq, name, parent_name, bypass);
210 if (IS_ERR(clk))
211 return;
212
213 of_clk_add_provider(np, of_clk_src_simple_get, clk);
214}
215
216static irqreturn_t clk_main_rc_osc_irq_handler(int irq, void *dev_id)
217{
218 struct clk_main_rc_osc *osc = dev_id;
219
220 wake_up(&osc->wait);
221 disable_irq_nosync(osc->irq);
222
223 return IRQ_HANDLED;
224}
225
226static int clk_main_rc_osc_prepare(struct clk_hw *hw)
227{
228 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
229 struct at91_pmc *pmc = osc->pmc;
230 u32 tmp;
231
232 tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
233
234 if (!(tmp & AT91_PMC_MOSCRCEN)) {
235 tmp |= AT91_PMC_MOSCRCEN | AT91_PMC_KEY;
236 pmc_write(pmc, AT91_CKGR_MOR, tmp);
237 }
238
239 while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS)) {
240 enable_irq(osc->irq);
241 wait_event(osc->wait,
242 pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS);
243 }
244
245 return 0;
246}
247
248static void clk_main_rc_osc_unprepare(struct clk_hw *hw)
249{
250 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
251 struct at91_pmc *pmc = osc->pmc;
252 u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
253
254 if (!(tmp & AT91_PMC_MOSCRCEN))
255 return;
256
257 tmp &= ~(MOR_KEY_MASK | AT91_PMC_MOSCRCEN);
258 pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
259}
260
261static int clk_main_rc_osc_is_prepared(struct clk_hw *hw)
262{
263 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
264 struct at91_pmc *pmc = osc->pmc;
265
266 return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS) &&
267 (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCRCEN));
268}
269
270static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw,
271 unsigned long parent_rate)
272{
273 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
274
275 return osc->frequency;
276}
277
278static unsigned long clk_main_rc_osc_recalc_accuracy(struct clk_hw *hw,
279 unsigned long parent_acc)
280{
281 struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
282
283 return osc->accuracy;
284}
285
286static const struct clk_ops main_rc_osc_ops = {
287 .prepare = clk_main_rc_osc_prepare,
288 .unprepare = clk_main_rc_osc_unprepare,
289 .is_prepared = clk_main_rc_osc_is_prepared,
290 .recalc_rate = clk_main_rc_osc_recalc_rate,
291 .recalc_accuracy = clk_main_rc_osc_recalc_accuracy,
292};
293
294static struct clk * __init
295at91_clk_register_main_rc_osc(struct at91_pmc *pmc,
296 unsigned int irq,
297 const char *name,
298 u32 frequency, u32 accuracy)
299{
300 int ret;
301 struct clk_main_rc_osc *osc;
302 struct clk *clk = NULL;
303 struct clk_init_data init;
304
305 if (!pmc || !irq || !name || !frequency)
306 return ERR_PTR(-EINVAL);
307
308 osc = kzalloc(sizeof(*osc), GFP_KERNEL);
309 if (!osc)
310 return ERR_PTR(-ENOMEM);
311
312 init.name = name;
313 init.ops = &main_rc_osc_ops;
314 init.parent_names = NULL;
315 init.num_parents = 0;
316 init.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED;
317
318 osc->hw.init = &init;
319 osc->pmc = pmc;
320 osc->irq = irq;
321 osc->frequency = frequency;
322 osc->accuracy = accuracy;
323
324 init_waitqueue_head(&osc->wait);
325 irq_set_status_flags(osc->irq, IRQ_NOAUTOEN);
326 ret = request_irq(osc->irq, clk_main_rc_osc_irq_handler,
327 IRQF_TRIGGER_HIGH, name, osc);
328 if (ret)
329 return ERR_PTR(ret);
330
331 clk = clk_register(NULL, &osc->hw);
332 if (IS_ERR(clk)) {
333 free_irq(irq, osc);
334 kfree(osc);
335 }
336
337 return clk;
338}
339
340void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
341 struct at91_pmc *pmc)
342{
343 struct clk *clk;
344 unsigned int irq;
345 u32 frequency = 0;
346 u32 accuracy = 0;
347 const char *name = np->name;
348
349 of_property_read_string(np, "clock-output-names", &name);
350 of_property_read_u32(np, "clock-frequency", &frequency);
351 of_property_read_u32(np, "clock-accuracy", &accuracy);
352
353 irq = irq_of_parse_and_map(np, 0);
354 if (!irq)
355 return;
356
357 clk = at91_clk_register_main_rc_osc(pmc, irq, name, frequency,
358 accuracy);
359 if (IS_ERR(clk))
360 return;
361
362 of_clk_add_provider(np, of_clk_src_simple_get, clk);
363}
364
365
366static int clk_main_probe_frequency(struct at91_pmc *pmc)
367{
368 unsigned long prep_time, timeout;
369 u32 tmp;
68 370
69 timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT); 371 timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT);
70 do { 372 do {
71 halt_time = jiffies; 373 prep_time = jiffies;
72 tmp = pmc_read(pmc, AT91_CKGR_MCFR); 374 tmp = pmc_read(pmc, AT91_CKGR_MCFR);
73 if (tmp & AT91_PMC_MAINRDY) 375 if (tmp & AT91_PMC_MAINRDY)
74 return 0; 376 return 0;
75 usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT); 377 usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT);
76 } while (time_before(halt_time, timeout)); 378 } while (time_before(prep_time, timeout));
77 379
78 return 0; 380 return -ETIMEDOUT;
79} 381}
80 382
81static int clk_main_is_prepared(struct clk_hw *hw) 383static unsigned long clk_main_recalc_rate(struct at91_pmc *pmc,
384 unsigned long parent_rate)
82{ 385{
83 struct clk_main *clkmain = to_clk_main(hw); 386 u32 tmp;
387
388 if (parent_rate)
389 return parent_rate;
390
391 tmp = pmc_read(pmc, AT91_CKGR_MCFR);
392 if (!(tmp & AT91_PMC_MAINRDY))
393 return 0;
84 394
85 return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCS); 395 return ((tmp & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV;
86} 396}
87 397
88static unsigned long clk_main_recalc_rate(struct clk_hw *hw, 398static int clk_rm9200_main_prepare(struct clk_hw *hw)
89 unsigned long parent_rate)
90{ 399{
91 u32 tmp; 400 struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
92 struct clk_main *clkmain = to_clk_main(hw); 401
402 return clk_main_probe_frequency(clkmain->pmc);
403}
404
405static int clk_rm9200_main_is_prepared(struct clk_hw *hw)
406{
407 struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
408
409 return !!(pmc_read(clkmain->pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINRDY);
410}
411
412static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw,
413 unsigned long parent_rate)
414{
415 struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
416
417 return clk_main_recalc_rate(clkmain->pmc, parent_rate);
418}
419
420static const struct clk_ops rm9200_main_ops = {
421 .prepare = clk_rm9200_main_prepare,
422 .is_prepared = clk_rm9200_main_is_prepared,
423 .recalc_rate = clk_rm9200_main_recalc_rate,
424};
425
426static struct clk * __init
427at91_clk_register_rm9200_main(struct at91_pmc *pmc,
428 const char *name,
429 const char *parent_name)
430{
431 struct clk_rm9200_main *clkmain;
432 struct clk *clk = NULL;
433 struct clk_init_data init;
434
435 if (!pmc || !name)
436 return ERR_PTR(-EINVAL);
437
438 if (!parent_name)
439 return ERR_PTR(-EINVAL);
440
441 clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
442 if (!clkmain)
443 return ERR_PTR(-ENOMEM);
444
445 init.name = name;
446 init.ops = &rm9200_main_ops;
447 init.parent_names = &parent_name;
448 init.num_parents = 1;
449 init.flags = 0;
450
451 clkmain->hw.init = &init;
452 clkmain->pmc = pmc;
453
454 clk = clk_register(NULL, &clkmain->hw);
455 if (IS_ERR(clk))
456 kfree(clkmain);
457
458 return clk;
459}
460
461void __init of_at91rm9200_clk_main_setup(struct device_node *np,
462 struct at91_pmc *pmc)
463{
464 struct clk *clk;
465 const char *parent_name;
466 const char *name = np->name;
467
468 parent_name = of_clk_get_parent_name(np, 0);
469 of_property_read_string(np, "clock-output-names", &name);
470
471 clk = at91_clk_register_rm9200_main(pmc, name, parent_name);
472 if (IS_ERR(clk))
473 return;
474
475 of_clk_add_provider(np, of_clk_src_simple_get, clk);
476}
477
478static irqreturn_t clk_sam9x5_main_irq_handler(int irq, void *dev_id)
479{
480 struct clk_sam9x5_main *clkmain = dev_id;
481
482 wake_up(&clkmain->wait);
483 disable_irq_nosync(clkmain->irq);
484
485 return IRQ_HANDLED;
486}
487
488static int clk_sam9x5_main_prepare(struct clk_hw *hw)
489{
490 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
93 struct at91_pmc *pmc = clkmain->pmc; 491 struct at91_pmc *pmc = clkmain->pmc;
94 492
95 if (clkmain->rate) 493 while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) {
96 return clkmain->rate; 494 enable_irq(clkmain->irq);
495 wait_event(clkmain->wait,
496 pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
497 }
498
499 return clk_main_probe_frequency(pmc);
500}
97 501
98 tmp = pmc_read(pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINF; 502static int clk_sam9x5_main_is_prepared(struct clk_hw *hw)
99 clkmain->rate = (tmp * parent_rate) / MAINF_DIV; 503{
504 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
100 505
101 return clkmain->rate; 506 return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
102} 507}
103 508
104static const struct clk_ops main_ops = { 509static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw,
105 .prepare = clk_main_prepare, 510 unsigned long parent_rate)
106 .is_prepared = clk_main_is_prepared, 511{
107 .recalc_rate = clk_main_recalc_rate, 512 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
513
514 return clk_main_recalc_rate(clkmain->pmc, parent_rate);
515}
516
517static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index)
518{
519 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
520 struct at91_pmc *pmc = clkmain->pmc;
521 u32 tmp;
522
523 if (index > 1)
524 return -EINVAL;
525
526 tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
527
528 if (index && !(tmp & AT91_PMC_MOSCSEL))
529 pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL);
530 else if (!index && (tmp & AT91_PMC_MOSCSEL))
531 pmc_write(pmc, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL);
532
533 while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) {
534 enable_irq(clkmain->irq);
535 wait_event(clkmain->wait,
536 pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
537 }
538
539 return 0;
540}
541
542static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw)
543{
544 struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
545
546 return !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN);
547}
548
549static const struct clk_ops sam9x5_main_ops = {
550 .prepare = clk_sam9x5_main_prepare,
551 .is_prepared = clk_sam9x5_main_is_prepared,
552 .recalc_rate = clk_sam9x5_main_recalc_rate,
553 .set_parent = clk_sam9x5_main_set_parent,
554 .get_parent = clk_sam9x5_main_get_parent,
108}; 555};
109 556
110static struct clk * __init 557static struct clk * __init
111at91_clk_register_main(struct at91_pmc *pmc, 558at91_clk_register_sam9x5_main(struct at91_pmc *pmc,
112 unsigned int irq, 559 unsigned int irq,
113 const char *name, 560 const char *name,
114 const char *parent_name, 561 const char **parent_names,
115 unsigned long rate) 562 int num_parents)
116{ 563{
117 int ret; 564 int ret;
118 struct clk_main *clkmain; 565 struct clk_sam9x5_main *clkmain;
119 struct clk *clk = NULL; 566 struct clk *clk = NULL;
120 struct clk_init_data init; 567 struct clk_init_data init;
121 568
122 if (!pmc || !irq || !name) 569 if (!pmc || !irq || !name)
123 return ERR_PTR(-EINVAL); 570 return ERR_PTR(-EINVAL);
124 571
125 if (!rate && !parent_name) 572 if (!parent_names || !num_parents)
126 return ERR_PTR(-EINVAL); 573 return ERR_PTR(-EINVAL);
127 574
128 clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL); 575 clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
@@ -130,19 +577,20 @@ at91_clk_register_main(struct at91_pmc *pmc,
130 return ERR_PTR(-ENOMEM); 577 return ERR_PTR(-ENOMEM);
131 578
132 init.name = name; 579 init.name = name;
133 init.ops = &main_ops; 580 init.ops = &sam9x5_main_ops;
134 init.parent_names = parent_name ? &parent_name : NULL; 581 init.parent_names = parent_names;
135 init.num_parents = parent_name ? 1 : 0; 582 init.num_parents = num_parents;
136 init.flags = parent_name ? 0 : CLK_IS_ROOT; 583 init.flags = CLK_SET_PARENT_GATE;
137 584
138 clkmain->hw.init = &init; 585 clkmain->hw.init = &init;
139 clkmain->rate = rate;
140 clkmain->pmc = pmc; 586 clkmain->pmc = pmc;
141 clkmain->irq = irq; 587 clkmain->irq = irq;
588 clkmain->parent = !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) &
589 AT91_PMC_MOSCEN);
142 init_waitqueue_head(&clkmain->wait); 590 init_waitqueue_head(&clkmain->wait);
143 irq_set_status_flags(clkmain->irq, IRQ_NOAUTOEN); 591 irq_set_status_flags(clkmain->irq, IRQ_NOAUTOEN);
144 ret = request_irq(clkmain->irq, clk_main_irq_handler, 592 ret = request_irq(clkmain->irq, clk_sam9x5_main_irq_handler,
145 IRQF_TRIGGER_HIGH, "clk-main", clkmain); 593 IRQF_TRIGGER_HIGH, name, clkmain);
146 if (ret) 594 if (ret)
147 return ERR_PTR(ret); 595 return ERR_PTR(ret);
148 596
@@ -155,33 +603,36 @@ at91_clk_register_main(struct at91_pmc *pmc,
155 return clk; 603 return clk;
156} 604}
157 605
158 606void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
159 607 struct at91_pmc *pmc)
160static void __init
161of_at91_clk_main_setup(struct device_node *np, struct at91_pmc *pmc)
162{ 608{
163 struct clk *clk; 609 struct clk *clk;
610 const char *parent_names[2];
611 int num_parents;
164 unsigned int irq; 612 unsigned int irq;
165 const char *parent_name;
166 const char *name = np->name; 613 const char *name = np->name;
167 u32 rate = 0; 614 int i;
615
616 num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
617 if (num_parents <= 0 || num_parents > 2)
618 return;
619
620 for (i = 0; i < num_parents; ++i) {
621 parent_names[i] = of_clk_get_parent_name(np, i);
622 if (!parent_names[i])
623 return;
624 }
168 625
169 parent_name = of_clk_get_parent_name(np, 0);
170 of_property_read_string(np, "clock-output-names", &name); 626 of_property_read_string(np, "clock-output-names", &name);
171 of_property_read_u32(np, "clock-frequency", &rate); 627
172 irq = irq_of_parse_and_map(np, 0); 628 irq = irq_of_parse_and_map(np, 0);
173 if (!irq) 629 if (!irq)
174 return; 630 return;
175 631
176 clk = at91_clk_register_main(pmc, irq, name, parent_name, rate); 632 clk = at91_clk_register_sam9x5_main(pmc, irq, name, parent_names,
633 num_parents);
177 if (IS_ERR(clk)) 634 if (IS_ERR(clk))
178 return; 635 return;
179 636
180 of_clk_add_provider(np, of_clk_src_simple_get, clk); 637 of_clk_add_provider(np, of_clk_src_simple_get, clk);
181} 638}
182
183void __init of_at91rm9200_clk_main_setup(struct device_node *np,
184 struct at91_pmc *pmc)
185{
186 of_at91_clk_main_setup(np, pmc);
187}
diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c
new file mode 100644
index 000000000000..0300c46ee247
--- /dev/null
+++ b/drivers/clk/at91/clk-slow.c
@@ -0,0 +1,467 @@
1/*
2 * drivers/clk/at91/clk-slow.c
3 *
4 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 */
12
13#include <linux/clk-provider.h>
14#include <linux/clkdev.h>
15#include <linux/clk/at91_pmc.h>
16#include <linux/delay.h>
17#include <linux/of.h>
18#include <linux/of_address.h>
19#include <linux/of_irq.h>
20#include <linux/io.h>
21#include <linux/interrupt.h>
22#include <linux/irq.h>
23#include <linux/sched.h>
24#include <linux/wait.h>
25
26#include "pmc.h"
27#include "sckc.h"
28
29#define SLOW_CLOCK_FREQ 32768
30#define SLOWCK_SW_CYCLES 5
31#define SLOWCK_SW_TIME_USEC ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \
32 SLOW_CLOCK_FREQ)
33
34#define AT91_SCKC_CR 0x00
35#define AT91_SCKC_RCEN (1 << 0)
36#define AT91_SCKC_OSC32EN (1 << 1)
37#define AT91_SCKC_OSC32BYP (1 << 2)
38#define AT91_SCKC_OSCSEL (1 << 3)
39
40struct clk_slow_osc {
41 struct clk_hw hw;
42 void __iomem *sckcr;
43 unsigned long startup_usec;
44};
45
46#define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw)
47
48struct clk_slow_rc_osc {
49 struct clk_hw hw;
50 void __iomem *sckcr;
51 unsigned long frequency;
52 unsigned long accuracy;
53 unsigned long startup_usec;
54};
55
56#define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw)
57
58struct clk_sam9260_slow {
59 struct clk_hw hw;
60 struct at91_pmc *pmc;
61};
62
63#define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw)
64
65struct clk_sam9x5_slow {
66 struct clk_hw hw;
67 void __iomem *sckcr;
68 u8 parent;
69};
70
71#define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw)
72
73
74static int clk_slow_osc_prepare(struct clk_hw *hw)
75{
76 struct clk_slow_osc *osc = to_clk_slow_osc(hw);
77 void __iomem *sckcr = osc->sckcr;
78 u32 tmp = readl(sckcr);
79
80 if (tmp & AT91_SCKC_OSC32BYP)
81 return 0;
82
83 writel(tmp | AT91_SCKC_OSC32EN, sckcr);
84
85 usleep_range(osc->startup_usec, osc->startup_usec + 1);
86
87 return 0;
88}
89
90static void clk_slow_osc_unprepare(struct clk_hw *hw)
91{
92 struct clk_slow_osc *osc = to_clk_slow_osc(hw);
93 void __iomem *sckcr = osc->sckcr;
94 u32 tmp = readl(sckcr);
95
96 if (tmp & AT91_SCKC_OSC32BYP)
97 return;
98
99 writel(tmp & ~AT91_SCKC_OSC32EN, sckcr);
100}
101
102static int clk_slow_osc_is_prepared(struct clk_hw *hw)
103{
104 struct clk_slow_osc *osc = to_clk_slow_osc(hw);
105 void __iomem *sckcr = osc->sckcr;
106 u32 tmp = readl(sckcr);
107
108 if (tmp & AT91_SCKC_OSC32BYP)
109 return 1;
110
111 return !!(tmp & AT91_SCKC_OSC32EN);
112}
113
114static const struct clk_ops slow_osc_ops = {
115 .prepare = clk_slow_osc_prepare,
116 .unprepare = clk_slow_osc_unprepare,
117 .is_prepared = clk_slow_osc_is_prepared,
118};
119
120static struct clk * __init
121at91_clk_register_slow_osc(void __iomem *sckcr,
122 const char *name,
123 const char *parent_name,
124 unsigned long startup,
125 bool bypass)
126{
127 struct clk_slow_osc *osc;
128 struct clk *clk = NULL;
129 struct clk_init_data init;
130
131 if (!sckcr || !name || !parent_name)
132 return ERR_PTR(-EINVAL);
133
134 osc = kzalloc(sizeof(*osc), GFP_KERNEL);
135 if (!osc)
136 return ERR_PTR(-ENOMEM);
137
138 init.name = name;
139 init.ops = &slow_osc_ops;
140 init.parent_names = &parent_name;
141 init.num_parents = 1;
142 init.flags = CLK_IGNORE_UNUSED;
143
144 osc->hw.init = &init;
145 osc->sckcr = sckcr;
146 osc->startup_usec = startup;
147
148 if (bypass)
149 writel((readl(sckcr) & ~AT91_SCKC_OSC32EN) | AT91_SCKC_OSC32BYP,
150 sckcr);
151
152 clk = clk_register(NULL, &osc->hw);
153 if (IS_ERR(clk))
154 kfree(osc);
155
156 return clk;
157}
158
159void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np,
160 void __iomem *sckcr)
161{
162 struct clk *clk;
163 const char *parent_name;
164 const char *name = np->name;
165 u32 startup;
166 bool bypass;
167
168 parent_name = of_clk_get_parent_name(np, 0);
169 of_property_read_string(np, "clock-output-names", &name);
170 of_property_read_u32(np, "atmel,startup-time-usec", &startup);
171 bypass = of_property_read_bool(np, "atmel,osc-bypass");
172
173 clk = at91_clk_register_slow_osc(sckcr, name, parent_name, startup,
174 bypass);
175 if (IS_ERR(clk))
176 return;
177
178 of_clk_add_provider(np, of_clk_src_simple_get, clk);
179}
180
181static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw,
182 unsigned long parent_rate)
183{
184 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
185
186 return osc->frequency;
187}
188
189static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw *hw,
190 unsigned long parent_acc)
191{
192 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
193
194 return osc->accuracy;
195}
196
197static int clk_slow_rc_osc_prepare(struct clk_hw *hw)
198{
199 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
200 void __iomem *sckcr = osc->sckcr;
201
202 writel(readl(sckcr) | AT91_SCKC_RCEN, sckcr);
203
204 usleep_range(osc->startup_usec, osc->startup_usec + 1);
205
206 return 0;
207}
208
209static void clk_slow_rc_osc_unprepare(struct clk_hw *hw)
210{
211 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
212 void __iomem *sckcr = osc->sckcr;
213
214 writel(readl(sckcr) & ~AT91_SCKC_RCEN, sckcr);
215}
216
217static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw)
218{
219 struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
220
221 return !!(readl(osc->sckcr) & AT91_SCKC_RCEN);
222}
223
224static const struct clk_ops slow_rc_osc_ops = {
225 .prepare = clk_slow_rc_osc_prepare,
226 .unprepare = clk_slow_rc_osc_unprepare,
227 .is_prepared = clk_slow_rc_osc_is_prepared,
228 .recalc_rate = clk_slow_rc_osc_recalc_rate,
229 .recalc_accuracy = clk_slow_rc_osc_recalc_accuracy,
230};
231
232static struct clk * __init
233at91_clk_register_slow_rc_osc(void __iomem *sckcr,
234 const char *name,
235 unsigned long frequency,
236 unsigned long accuracy,
237 unsigned long startup)
238{
239 struct clk_slow_rc_osc *osc;
240 struct clk *clk = NULL;
241 struct clk_init_data init;
242
243 if (!sckcr || !name)
244 return ERR_PTR(-EINVAL);
245
246 osc = kzalloc(sizeof(*osc), GFP_KERNEL);
247 if (!osc)
248 return ERR_PTR(-ENOMEM);
249
250 init.name = name;
251 init.ops = &slow_rc_osc_ops;
252 init.parent_names = NULL;
253 init.num_parents = 0;
254 init.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED;
255
256 osc->hw.init = &init;
257 osc->sckcr = sckcr;
258 osc->frequency = frequency;
259 osc->accuracy = accuracy;
260 osc->startup_usec = startup;
261
262 clk = clk_register(NULL, &osc->hw);
263 if (IS_ERR(clk))
264 kfree(osc);
265
266 return clk;
267}
268
269void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np,
270 void __iomem *sckcr)
271{
272 struct clk *clk;
273 u32 frequency = 0;
274 u32 accuracy = 0;
275 u32 startup = 0;
276 const char *name = np->name;
277
278 of_property_read_string(np, "clock-output-names", &name);
279 of_property_read_u32(np, "clock-frequency", &frequency);
280 of_property_read_u32(np, "clock-accuracy", &accuracy);
281 of_property_read_u32(np, "atmel,startup-time-usec", &startup);
282
283 clk = at91_clk_register_slow_rc_osc(sckcr, name, frequency, accuracy,
284 startup);
285 if (IS_ERR(clk))
286 return;
287
288 of_clk_add_provider(np, of_clk_src_simple_get, clk);
289}
290
291static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index)
292{
293 struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
294 void __iomem *sckcr = slowck->sckcr;
295 u32 tmp;
296
297 if (index > 1)
298 return -EINVAL;
299
300 tmp = readl(sckcr);
301
302 if ((!index && !(tmp & AT91_SCKC_OSCSEL)) ||
303 (index && (tmp & AT91_SCKC_OSCSEL)))
304 return 0;
305
306 if (index)
307 tmp |= AT91_SCKC_OSCSEL;
308 else
309 tmp &= ~AT91_SCKC_OSCSEL;
310
311 writel(tmp, sckcr);
312
313 usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1);
314
315 return 0;
316}
317
318static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw)
319{
320 struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
321
322 return !!(readl(slowck->sckcr) & AT91_SCKC_OSCSEL);
323}
324
325static const struct clk_ops sam9x5_slow_ops = {
326 .set_parent = clk_sam9x5_slow_set_parent,
327 .get_parent = clk_sam9x5_slow_get_parent,
328};
329
330static struct clk * __init
331at91_clk_register_sam9x5_slow(void __iomem *sckcr,
332 const char *name,
333 const char **parent_names,
334 int num_parents)
335{
336 struct clk_sam9x5_slow *slowck;
337 struct clk *clk = NULL;
338 struct clk_init_data init;
339
340 if (!sckcr || !name || !parent_names || !num_parents)
341 return ERR_PTR(-EINVAL);
342
343 slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
344 if (!slowck)
345 return ERR_PTR(-ENOMEM);
346
347 init.name = name;
348 init.ops = &sam9x5_slow_ops;
349 init.parent_names = parent_names;
350 init.num_parents = num_parents;
351 init.flags = 0;
352
353 slowck->hw.init = &init;
354 slowck->sckcr = sckcr;
355 slowck->parent = !!(readl(sckcr) & AT91_SCKC_OSCSEL);
356
357 clk = clk_register(NULL, &slowck->hw);
358 if (IS_ERR(clk))
359 kfree(slowck);
360
361 return clk;
362}
363
364void __init of_at91sam9x5_clk_slow_setup(struct device_node *np,
365 void __iomem *sckcr)
366{
367 struct clk *clk;
368 const char *parent_names[2];
369 int num_parents;
370 const char *name = np->name;
371 int i;
372
373 num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
374 if (num_parents <= 0 || num_parents > 2)
375 return;
376
377 for (i = 0; i < num_parents; ++i) {
378 parent_names[i] = of_clk_get_parent_name(np, i);
379 if (!parent_names[i])
380 return;
381 }
382
383 of_property_read_string(np, "clock-output-names", &name);
384
385 clk = at91_clk_register_sam9x5_slow(sckcr, name, parent_names,
386 num_parents);
387 if (IS_ERR(clk))
388 return;
389
390 of_clk_add_provider(np, of_clk_src_simple_get, clk);
391}
392
393static u8 clk_sam9260_slow_get_parent(struct clk_hw *hw)
394{
395 struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw);
396
397 return !!(pmc_read(slowck->pmc, AT91_PMC_SR) & AT91_PMC_OSCSEL);
398}
399
400static const struct clk_ops sam9260_slow_ops = {
401 .get_parent = clk_sam9260_slow_get_parent,
402};
403
404static struct clk * __init
405at91_clk_register_sam9260_slow(struct at91_pmc *pmc,
406 const char *name,
407 const char **parent_names,
408 int num_parents)
409{
410 struct clk_sam9260_slow *slowck;
411 struct clk *clk = NULL;
412 struct clk_init_data init;
413
414 if (!pmc || !name)
415 return ERR_PTR(-EINVAL);
416
417 if (!parent_names || !num_parents)
418 return ERR_PTR(-EINVAL);
419
420 slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
421 if (!slowck)
422 return ERR_PTR(-ENOMEM);
423
424 init.name = name;
425 init.ops = &sam9260_slow_ops;
426 init.parent_names = parent_names;
427 init.num_parents = num_parents;
428 init.flags = 0;
429
430 slowck->hw.init = &init;
431 slowck->pmc = pmc;
432
433 clk = clk_register(NULL, &slowck->hw);
434 if (IS_ERR(clk))
435 kfree(slowck);
436
437 return clk;
438}
439
440void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
441 struct at91_pmc *pmc)
442{
443 struct clk *clk;
444 const char *parent_names[2];
445 int num_parents;
446 const char *name = np->name;
447 int i;
448
449 num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
450 if (num_parents <= 0 || num_parents > 1)
451 return;
452
453 for (i = 0; i < num_parents; ++i) {
454 parent_names[i] = of_clk_get_parent_name(np, i);
455 if (!parent_names[i])
456 return;
457 }
458
459 of_property_read_string(np, "clock-output-names", &name);
460
461 clk = at91_clk_register_sam9260_slow(pmc, name, parent_names,
462 num_parents);
463 if (IS_ERR(clk))
464 return;
465
466 of_clk_add_provider(np, of_clk_src_simple_get, clk);
467}
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 6a61477a57e0..524196bb35a5 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -229,11 +229,28 @@ out_free_pmc:
229} 229}
230 230
231static const struct of_device_id pmc_clk_ids[] __initconst = { 231static const struct of_device_id pmc_clk_ids[] __initconst = {
232 /* Slow oscillator */
233 {
234 .compatible = "atmel,at91sam9260-clk-slow",
235 .data = of_at91sam9260_clk_slow_setup,
236 },
232 /* Main clock */ 237 /* Main clock */
233 { 238 {
239 .compatible = "atmel,at91rm9200-clk-main-osc",
240 .data = of_at91rm9200_clk_main_osc_setup,
241 },
242 {
243 .compatible = "atmel,at91sam9x5-clk-main-rc-osc",
244 .data = of_at91sam9x5_clk_main_rc_osc_setup,
245 },
246 {
234 .compatible = "atmel,at91rm9200-clk-main", 247 .compatible = "atmel,at91rm9200-clk-main",
235 .data = of_at91rm9200_clk_main_setup, 248 .data = of_at91rm9200_clk_main_setup,
236 }, 249 },
250 {
251 .compatible = "atmel,at91sam9x5-clk-main",
252 .data = of_at91sam9x5_clk_main_setup,
253 },
237 /* PLL clocks */ 254 /* PLL clocks */
238 { 255 {
239 .compatible = "atmel,at91rm9200-clk-pll", 256 .compatible = "atmel,at91rm9200-clk-pll",
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
index 441350983ccb..6c7625976113 100644
--- a/drivers/clk/at91/pmc.h
+++ b/drivers/clk/at91/pmc.h
@@ -58,8 +58,17 @@ static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value)
58int of_at91_get_clk_range(struct device_node *np, const char *propname, 58int of_at91_get_clk_range(struct device_node *np, const char *propname,
59 struct clk_range *range); 59 struct clk_range *range);
60 60
61extern void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
62 struct at91_pmc *pmc);
63
64extern void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np,
65 struct at91_pmc *pmc);
66extern void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
67 struct at91_pmc *pmc);
61extern void __init of_at91rm9200_clk_main_setup(struct device_node *np, 68extern void __init of_at91rm9200_clk_main_setup(struct device_node *np,
62 struct at91_pmc *pmc); 69 struct at91_pmc *pmc);
70extern void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
71 struct at91_pmc *pmc);
63 72
64extern void __init of_at91rm9200_clk_pll_setup(struct device_node *np, 73extern void __init of_at91rm9200_clk_pll_setup(struct device_node *np,
65 struct at91_pmc *pmc); 74 struct at91_pmc *pmc);
diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c
new file mode 100644
index 000000000000..1184d76a7ab7
--- /dev/null
+++ b/drivers/clk/at91/sckc.c
@@ -0,0 +1,57 @@
1/*
2 * drivers/clk/at91/sckc.c
3 *
4 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 */
12
13#include <linux/clk-provider.h>
14#include <linux/clkdev.h>
15#include <linux/of.h>
16#include <linux/of_address.h>
17#include <linux/io.h>
18
19#include "sckc.h"
20
21static const struct of_device_id sckc_clk_ids[] __initconst = {
22 /* Slow clock */
23 {
24 .compatible = "atmel,at91sam9x5-clk-slow-osc",
25 .data = of_at91sam9x5_clk_slow_osc_setup,
26 },
27 {
28 .compatible = "atmel,at91sam9x5-clk-slow-rc-osc",
29 .data = of_at91sam9x5_clk_slow_rc_osc_setup,
30 },
31 {
32 .compatible = "atmel,at91sam9x5-clk-slow",
33 .data = of_at91sam9x5_clk_slow_setup,
34 },
35 { /*sentinel*/ }
36};
37
38static void __init of_at91sam9x5_sckc_setup(struct device_node *np)
39{
40 struct device_node *childnp;
41 void (*clk_setup)(struct device_node *, void __iomem *);
42 const struct of_device_id *clk_id;
43 void __iomem *regbase = of_iomap(np, 0);
44
45 if (!regbase)
46 return;
47
48 for_each_child_of_node(np, childnp) {
49 clk_id = of_match_node(sckc_clk_ids, childnp);
50 if (!clk_id)
51 continue;
52 clk_setup = clk_id->data;
53 clk_setup(childnp, regbase);
54 }
55}
56CLK_OF_DECLARE(at91sam9x5_clk_sckc, "atmel,at91sam9x5-sckc",
57 of_at91sam9x5_sckc_setup);
diff --git a/drivers/clk/at91/sckc.h b/drivers/clk/at91/sckc.h
new file mode 100644
index 000000000000..836fcf59820f
--- /dev/null
+++ b/drivers/clk/at91/sckc.h
@@ -0,0 +1,22 @@
1/*
2 * drivers/clk/at91/sckc.h
3 *
4 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef __AT91_SCKC_H_
13#define __AT91_SCKC_H_
14
15extern void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np,
16 void __iomem *sckcr);
17extern void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np,
18 void __iomem *sckcr);
19extern void __init of_at91sam9x5_clk_slow_setup(struct device_node *np,
20 void __iomem *sckcr);
21
22#endif /* __AT91_SCKC_H_ */
diff --git a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig
index a7262fb8ce55..75506e53075b 100644
--- a/drivers/clk/bcm/Kconfig
+++ b/drivers/clk/bcm/Kconfig
@@ -6,4 +6,4 @@ config CLK_BCM_KONA
6 help 6 help
7 Enable common clock framework support for Broadcom SoCs 7 Enable common clock framework support for Broadcom SoCs
8 using "Kona" style clock control units, including those 8 using "Kona" style clock control units, including those
9 in the BCM281xx family. 9 in the BCM281xx and BCM21664 families.
diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile
index cf93359aa862..6297d05a9a10 100644
--- a/drivers/clk/bcm/Makefile
+++ b/drivers/clk/bcm/Makefile
@@ -1,3 +1,4 @@
1obj-$(CONFIG_CLK_BCM_KONA) += clk-kona.o 1obj-$(CONFIG_CLK_BCM_KONA) += clk-kona.o
2obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o 2obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o
3obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o 3obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o
4obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o
diff --git a/drivers/clk/bcm/clk-bcm21664.c b/drivers/clk/bcm/clk-bcm21664.c
new file mode 100644
index 000000000000..eeae4cad2281
--- /dev/null
+++ b/drivers/clk/bcm/clk-bcm21664.c
@@ -0,0 +1,290 @@
1/*
2 * Copyright (C) 2014 Broadcom Corporation
3 * Copyright 2014 Linaro Limited
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation version 2.
8 *
9 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
10 * kind, whether express or implied; without even the implied warranty
11 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include "clk-kona.h"
16#include "dt-bindings/clock/bcm21664.h"
17
18#define BCM21664_CCU_COMMON(_name, _capname) \
19 KONA_CCU_COMMON(BCM21664, _name, _capname)
20
21/* Root CCU */
22
23static struct peri_clk_data frac_1m_data = {
24 .gate = HW_SW_GATE(0x214, 16, 0, 1),
25 .clocks = CLOCKS("ref_crystal"),
26};
27
28static struct ccu_data root_ccu_data = {
29 BCM21664_CCU_COMMON(root, ROOT),
30 /* no policy control */
31 .kona_clks = {
32 [BCM21664_ROOT_CCU_FRAC_1M] =
33 KONA_CLK(root, frac_1m, peri),
34 [BCM21664_ROOT_CCU_CLOCK_COUNT] = LAST_KONA_CLK,
35 },
36};
37
38/* AON CCU */
39
40static struct peri_clk_data hub_timer_data = {
41 .gate = HW_SW_GATE(0x0414, 16, 0, 1),
42 .hyst = HYST(0x0414, 8, 9),
43 .clocks = CLOCKS("bbl_32k",
44 "frac_1m",
45 "dft_19_5m"),
46 .sel = SELECTOR(0x0a10, 0, 2),
47 .trig = TRIGGER(0x0a40, 4),
48};
49
50static struct ccu_data aon_ccu_data = {
51 BCM21664_CCU_COMMON(aon, AON),
52 .policy = {
53 .enable = CCU_LVM_EN(0x0034, 0),
54 .control = CCU_POLICY_CTL(0x000c, 0, 1, 2),
55 },
56 .kona_clks = {
57 [BCM21664_AON_CCU_HUB_TIMER] =
58 KONA_CLK(aon, hub_timer, peri),
59 [BCM21664_AON_CCU_CLOCK_COUNT] = LAST_KONA_CLK,
60 },
61};
62
63/* Master CCU */
64
65static struct peri_clk_data sdio1_data = {
66 .gate = HW_SW_GATE(0x0358, 18, 2, 3),
67 .clocks = CLOCKS("ref_crystal",
68 "var_52m",
69 "ref_52m",
70 "var_96m",
71 "ref_96m"),
72 .sel = SELECTOR(0x0a28, 0, 3),
73 .div = DIVIDER(0x0a28, 4, 14),
74 .trig = TRIGGER(0x0afc, 9),
75};
76
77static struct peri_clk_data sdio2_data = {
78 .gate = HW_SW_GATE(0x035c, 18, 2, 3),
79 .clocks = CLOCKS("ref_crystal",
80 "var_52m",
81 "ref_52m",
82 "var_96m",
83 "ref_96m"),
84 .sel = SELECTOR(0x0a2c, 0, 3),
85 .div = DIVIDER(0x0a2c, 4, 14),
86 .trig = TRIGGER(0x0afc, 10),
87};
88
89static struct peri_clk_data sdio3_data = {
90 .gate = HW_SW_GATE(0x0364, 18, 2, 3),
91 .clocks = CLOCKS("ref_crystal",
92 "var_52m",
93 "ref_52m",
94 "var_96m",
95 "ref_96m"),
96 .sel = SELECTOR(0x0a34, 0, 3),
97 .div = DIVIDER(0x0a34, 4, 14),
98 .trig = TRIGGER(0x0afc, 12),
99};
100
101static struct peri_clk_data sdio4_data = {
102 .gate = HW_SW_GATE(0x0360, 18, 2, 3),
103 .clocks = CLOCKS("ref_crystal",
104 "var_52m",
105 "ref_52m",
106 "var_96m",
107 "ref_96m"),
108 .sel = SELECTOR(0x0a30, 0, 3),
109 .div = DIVIDER(0x0a30, 4, 14),
110 .trig = TRIGGER(0x0afc, 11),
111};
112
113static struct peri_clk_data sdio1_sleep_data = {
114 .clocks = CLOCKS("ref_32k"), /* Verify */
115 .gate = HW_SW_GATE(0x0358, 18, 2, 3),
116};
117
118static struct peri_clk_data sdio2_sleep_data = {
119 .clocks = CLOCKS("ref_32k"), /* Verify */
120 .gate = HW_SW_GATE(0x035c, 18, 2, 3),
121};
122
123static struct peri_clk_data sdio3_sleep_data = {
124 .clocks = CLOCKS("ref_32k"), /* Verify */
125 .gate = HW_SW_GATE(0x0364, 18, 2, 3),
126};
127
128static struct peri_clk_data sdio4_sleep_data = {
129 .clocks = CLOCKS("ref_32k"), /* Verify */
130 .gate = HW_SW_GATE(0x0360, 18, 2, 3),
131};
132
133static struct ccu_data master_ccu_data = {
134 BCM21664_CCU_COMMON(master, MASTER),
135 .policy = {
136 .enable = CCU_LVM_EN(0x0034, 0),
137 .control = CCU_POLICY_CTL(0x000c, 0, 1, 2),
138 },
139 .kona_clks = {
140 [BCM21664_MASTER_CCU_SDIO1] =
141 KONA_CLK(master, sdio1, peri),
142 [BCM21664_MASTER_CCU_SDIO2] =
143 KONA_CLK(master, sdio2, peri),
144 [BCM21664_MASTER_CCU_SDIO3] =
145 KONA_CLK(master, sdio3, peri),
146 [BCM21664_MASTER_CCU_SDIO4] =
147 KONA_CLK(master, sdio4, peri),
148 [BCM21664_MASTER_CCU_SDIO1_SLEEP] =
149 KONA_CLK(master, sdio1_sleep, peri),
150 [BCM21664_MASTER_CCU_SDIO2_SLEEP] =
151 KONA_CLK(master, sdio2_sleep, peri),
152 [BCM21664_MASTER_CCU_SDIO3_SLEEP] =
153 KONA_CLK(master, sdio3_sleep, peri),
154 [BCM21664_MASTER_CCU_SDIO4_SLEEP] =
155 KONA_CLK(master, sdio4_sleep, peri),
156 [BCM21664_MASTER_CCU_CLOCK_COUNT] = LAST_KONA_CLK,
157 },
158};
159
160/* Slave CCU */
161
162static struct peri_clk_data uartb_data = {
163 .gate = HW_SW_GATE(0x0400, 18, 2, 3),
164 .clocks = CLOCKS("ref_crystal",
165 "var_156m",
166 "ref_156m"),
167 .sel = SELECTOR(0x0a10, 0, 2),
168 .div = FRAC_DIVIDER(0x0a10, 4, 12, 8),
169 .trig = TRIGGER(0x0afc, 2),
170};
171
172static struct peri_clk_data uartb2_data = {
173 .gate = HW_SW_GATE(0x0404, 18, 2, 3),
174 .clocks = CLOCKS("ref_crystal",
175 "var_156m",
176 "ref_156m"),
177 .sel = SELECTOR(0x0a14, 0, 2),
178 .div = FRAC_DIVIDER(0x0a14, 4, 12, 8),
179 .trig = TRIGGER(0x0afc, 3),
180};
181
182static struct peri_clk_data uartb3_data = {
183 .gate = HW_SW_GATE(0x0408, 18, 2, 3),
184 .clocks = CLOCKS("ref_crystal",
185 "var_156m",
186 "ref_156m"),
187 .sel = SELECTOR(0x0a18, 0, 2),
188 .div = FRAC_DIVIDER(0x0a18, 4, 12, 8),
189 .trig = TRIGGER(0x0afc, 4),
190};
191
192static struct peri_clk_data bsc1_data = {
193 .gate = HW_SW_GATE(0x0458, 18, 2, 3),
194 .clocks = CLOCKS("ref_crystal",
195 "var_104m",
196 "ref_104m",
197 "var_13m",
198 "ref_13m"),
199 .sel = SELECTOR(0x0a64, 0, 3),
200 .trig = TRIGGER(0x0afc, 23),
201};
202
203static struct peri_clk_data bsc2_data = {
204 .gate = HW_SW_GATE(0x045c, 18, 2, 3),
205 .clocks = CLOCKS("ref_crystal",
206 "var_104m",
207 "ref_104m",
208 "var_13m",
209 "ref_13m"),
210 .sel = SELECTOR(0x0a68, 0, 3),
211 .trig = TRIGGER(0x0afc, 24),
212};
213
214static struct peri_clk_data bsc3_data = {
215 .gate = HW_SW_GATE(0x0470, 18, 2, 3),
216 .clocks = CLOCKS("ref_crystal",
217 "var_104m",
218 "ref_104m",
219 "var_13m",
220 "ref_13m"),
221 .sel = SELECTOR(0x0a7c, 0, 3),
222 .trig = TRIGGER(0x0afc, 18),
223};
224
225static struct peri_clk_data bsc4_data = {
226 .gate = HW_SW_GATE(0x0474, 18, 2, 3),
227 .clocks = CLOCKS("ref_crystal",
228 "var_104m",
229 "ref_104m",
230 "var_13m",
231 "ref_13m"),
232 .sel = SELECTOR(0x0a80, 0, 3),
233 .trig = TRIGGER(0x0afc, 19),
234};
235
236static struct ccu_data slave_ccu_data = {
237 BCM21664_CCU_COMMON(slave, SLAVE),
238 .policy = {
239 .enable = CCU_LVM_EN(0x0034, 0),
240 .control = CCU_POLICY_CTL(0x000c, 0, 1, 2),
241 },
242 .kona_clks = {
243 [BCM21664_SLAVE_CCU_UARTB] =
244 KONA_CLK(slave, uartb, peri),
245 [BCM21664_SLAVE_CCU_UARTB2] =
246 KONA_CLK(slave, uartb2, peri),
247 [BCM21664_SLAVE_CCU_UARTB3] =
248 KONA_CLK(slave, uartb3, peri),
249 [BCM21664_SLAVE_CCU_BSC1] =
250 KONA_CLK(slave, bsc1, peri),
251 [BCM21664_SLAVE_CCU_BSC2] =
252 KONA_CLK(slave, bsc2, peri),
253 [BCM21664_SLAVE_CCU_BSC3] =
254 KONA_CLK(slave, bsc3, peri),
255 [BCM21664_SLAVE_CCU_BSC4] =
256 KONA_CLK(slave, bsc4, peri),
257 [BCM21664_SLAVE_CCU_CLOCK_COUNT] = LAST_KONA_CLK,
258 },
259};
260
261/* Device tree match table callback functions */
262
263static void __init kona_dt_root_ccu_setup(struct device_node *node)
264{
265 kona_dt_ccu_setup(&root_ccu_data, node);
266}
267
268static void __init kona_dt_aon_ccu_setup(struct device_node *node)
269{
270 kona_dt_ccu_setup(&aon_ccu_data, node);
271}
272
273static void __init kona_dt_master_ccu_setup(struct device_node *node)
274{
275 kona_dt_ccu_setup(&master_ccu_data, node);
276}
277
278static void __init kona_dt_slave_ccu_setup(struct device_node *node)
279{
280 kona_dt_ccu_setup(&slave_ccu_data, node);
281}
282
283CLK_OF_DECLARE(bcm21664_root_ccu, BCM21664_DT_ROOT_CCU_COMPAT,
284 kona_dt_root_ccu_setup);
285CLK_OF_DECLARE(bcm21664_aon_ccu, BCM21664_DT_AON_CCU_COMPAT,
286 kona_dt_aon_ccu_setup);
287CLK_OF_DECLARE(bcm21664_master_ccu, BCM21664_DT_MASTER_CCU_COMPAT,
288 kona_dt_master_ccu_setup);
289CLK_OF_DECLARE(bcm21664_slave_ccu, BCM21664_DT_SLAVE_CCU_COMPAT,
290 kona_dt_slave_ccu_setup);
diff --git a/drivers/clk/bcm/clk-bcm281xx.c b/drivers/clk/bcm/clk-bcm281xx.c
index 3c66de696aeb..502a487d62c5 100644
--- a/drivers/clk/bcm/clk-bcm281xx.c
+++ b/drivers/clk/bcm/clk-bcm281xx.c
@@ -15,14 +15,10 @@
15#include "clk-kona.h" 15#include "clk-kona.h"
16#include "dt-bindings/clock/bcm281xx.h" 16#include "dt-bindings/clock/bcm281xx.h"
17 17
18/* bcm11351 CCU device tree "compatible" strings */ 18#define BCM281XX_CCU_COMMON(_name, _ucase_name) \
19#define BCM11351_DT_ROOT_CCU_COMPAT "brcm,bcm11351-root-ccu" 19 KONA_CCU_COMMON(BCM281XX, _name, _ucase_name)
20#define BCM11351_DT_AON_CCU_COMPAT "brcm,bcm11351-aon-ccu"
21#define BCM11351_DT_HUB_CCU_COMPAT "brcm,bcm11351-hub-ccu"
22#define BCM11351_DT_MASTER_CCU_COMPAT "brcm,bcm11351-master-ccu"
23#define BCM11351_DT_SLAVE_CCU_COMPAT "brcm,bcm11351-slave-ccu"
24 20
25/* Root CCU clocks */ 21/* Root CCU */
26 22
27static struct peri_clk_data frac_1m_data = { 23static struct peri_clk_data frac_1m_data = {
28 .gate = HW_SW_GATE(0x214, 16, 0, 1), 24 .gate = HW_SW_GATE(0x214, 16, 0, 1),
@@ -31,7 +27,16 @@ static struct peri_clk_data frac_1m_data = {
31 .clocks = CLOCKS("ref_crystal"), 27 .clocks = CLOCKS("ref_crystal"),
32}; 28};
33 29
34/* AON CCU clocks */ 30static struct ccu_data root_ccu_data = {
31 BCM281XX_CCU_COMMON(root, ROOT),
32 .kona_clks = {
33 [BCM281XX_ROOT_CCU_FRAC_1M] =
34 KONA_CLK(root, frac_1m, peri),
35 [BCM281XX_ROOT_CCU_CLOCK_COUNT] = LAST_KONA_CLK,
36 },
37};
38
39/* AON CCU */
35 40
36static struct peri_clk_data hub_timer_data = { 41static struct peri_clk_data hub_timer_data = {
37 .gate = HW_SW_GATE(0x0414, 16, 0, 1), 42 .gate = HW_SW_GATE(0x0414, 16, 0, 1),
@@ -60,7 +65,20 @@ static struct peri_clk_data pmu_bsc_var_data = {
60 .trig = TRIGGER(0x0a40, 2), 65 .trig = TRIGGER(0x0a40, 2),
61}; 66};
62 67
63/* Hub CCU clocks */ 68static struct ccu_data aon_ccu_data = {
69 BCM281XX_CCU_COMMON(aon, AON),
70 .kona_clks = {
71 [BCM281XX_AON_CCU_HUB_TIMER] =
72 KONA_CLK(aon, hub_timer, peri),
73 [BCM281XX_AON_CCU_PMU_BSC] =
74 KONA_CLK(aon, pmu_bsc, peri),
75 [BCM281XX_AON_CCU_PMU_BSC_VAR] =
76 KONA_CLK(aon, pmu_bsc_var, peri),
77 [BCM281XX_AON_CCU_CLOCK_COUNT] = LAST_KONA_CLK,
78 },
79};
80
81/* Hub CCU */
64 82
65static struct peri_clk_data tmon_1m_data = { 83static struct peri_clk_data tmon_1m_data = {
66 .gate = HW_SW_GATE(0x04a4, 18, 2, 3), 84 .gate = HW_SW_GATE(0x04a4, 18, 2, 3),
@@ -70,7 +88,16 @@ static struct peri_clk_data tmon_1m_data = {
70 .trig = TRIGGER(0x0e84, 1), 88 .trig = TRIGGER(0x0e84, 1),
71}; 89};
72 90
73/* Master CCU clocks */ 91static struct ccu_data hub_ccu_data = {
92 BCM281XX_CCU_COMMON(hub, HUB),
93 .kona_clks = {
94 [BCM281XX_HUB_CCU_TMON_1M] =
95 KONA_CLK(hub, tmon_1m, peri),
96 [BCM281XX_HUB_CCU_CLOCK_COUNT] = LAST_KONA_CLK,
97 },
98};
99
100/* Master CCU */
74 101
75static struct peri_clk_data sdio1_data = { 102static struct peri_clk_data sdio1_data = {
76 .gate = HW_SW_GATE(0x0358, 18, 2, 3), 103 .gate = HW_SW_GATE(0x0358, 18, 2, 3),
@@ -153,7 +180,28 @@ static struct peri_clk_data hsic2_12m_data = {
153 .trig = TRIGGER(0x0afc, 5), 180 .trig = TRIGGER(0x0afc, 5),
154}; 181};
155 182
156/* Slave CCU clocks */ 183static struct ccu_data master_ccu_data = {
184 BCM281XX_CCU_COMMON(master, MASTER),
185 .kona_clks = {
186 [BCM281XX_MASTER_CCU_SDIO1] =
187 KONA_CLK(master, sdio1, peri),
188 [BCM281XX_MASTER_CCU_SDIO2] =
189 KONA_CLK(master, sdio2, peri),
190 [BCM281XX_MASTER_CCU_SDIO3] =
191 KONA_CLK(master, sdio3, peri),
192 [BCM281XX_MASTER_CCU_SDIO4] =
193 KONA_CLK(master, sdio4, peri),
194 [BCM281XX_MASTER_CCU_USB_IC] =
195 KONA_CLK(master, usb_ic, peri),
196 [BCM281XX_MASTER_CCU_HSIC2_48M] =
197 KONA_CLK(master, hsic2_48m, peri),
198 [BCM281XX_MASTER_CCU_HSIC2_12M] =
199 KONA_CLK(master, hsic2_12m, peri),
200 [BCM281XX_MASTER_CCU_CLOCK_COUNT] = LAST_KONA_CLK,
201 },
202};
203
204/* Slave CCU */
157 205
158static struct peri_clk_data uartb_data = { 206static struct peri_clk_data uartb_data = {
159 .gate = HW_SW_GATE(0x0400, 18, 2, 3), 207 .gate = HW_SW_GATE(0x0400, 18, 2, 3),
@@ -261,156 +309,67 @@ static struct peri_clk_data pwm_data = {
261 .trig = TRIGGER(0x0afc, 15), 309 .trig = TRIGGER(0x0afc, 15),
262}; 310};
263 311
264/* 312static struct ccu_data slave_ccu_data = {
265 * CCU setup routines 313 BCM281XX_CCU_COMMON(slave, SLAVE),
266 * 314 .kona_clks = {
267 * These are called from kona_dt_ccu_setup() to initialize the array 315 [BCM281XX_SLAVE_CCU_UARTB] =
268 * of clocks provided by the CCU. Once allocated, the entries in 316 KONA_CLK(slave, uartb, peri),
269 * the array are initialized by calling kona_clk_setup() with the 317 [BCM281XX_SLAVE_CCU_UARTB2] =
270 * initialization data for each clock. They return 0 if successful 318 KONA_CLK(slave, uartb2, peri),
271 * or an error code otherwise. 319 [BCM281XX_SLAVE_CCU_UARTB3] =
272 */ 320 KONA_CLK(slave, uartb3, peri),
273static int __init bcm281xx_root_ccu_clks_setup(struct ccu_data *ccu) 321 [BCM281XX_SLAVE_CCU_UARTB4] =
274{ 322 KONA_CLK(slave, uartb4, peri),
275 struct clk **clks; 323 [BCM281XX_SLAVE_CCU_SSP0] =
276 size_t count = BCM281XX_ROOT_CCU_CLOCK_COUNT; 324 KONA_CLK(slave, ssp0, peri),
277 325 [BCM281XX_SLAVE_CCU_SSP2] =
278 clks = kzalloc(count * sizeof(*clks), GFP_KERNEL); 326 KONA_CLK(slave, ssp2, peri),
279 if (!clks) { 327 [BCM281XX_SLAVE_CCU_BSC1] =
280 pr_err("%s: failed to allocate root clocks\n", __func__); 328 KONA_CLK(slave, bsc1, peri),
281 return -ENOMEM; 329 [BCM281XX_SLAVE_CCU_BSC2] =
282 } 330 KONA_CLK(slave, bsc2, peri),
283 ccu->data.clks = clks; 331 [BCM281XX_SLAVE_CCU_BSC3] =
284 ccu->data.clk_num = count; 332 KONA_CLK(slave, bsc3, peri),
285 333 [BCM281XX_SLAVE_CCU_PWM] =
286 PERI_CLK_SETUP(clks, ccu, BCM281XX_ROOT_CCU_FRAC_1M, frac_1m); 334 KONA_CLK(slave, pwm, peri),
287 335 [BCM281XX_SLAVE_CCU_CLOCK_COUNT] = LAST_KONA_CLK,
288 return 0; 336 },
289} 337};
290
291static int __init bcm281xx_aon_ccu_clks_setup(struct ccu_data *ccu)
292{
293 struct clk **clks;
294 size_t count = BCM281XX_AON_CCU_CLOCK_COUNT;
295
296 clks = kzalloc(count * sizeof(*clks), GFP_KERNEL);
297 if (!clks) {
298 pr_err("%s: failed to allocate aon clocks\n", __func__);
299 return -ENOMEM;
300 }
301 ccu->data.clks = clks;
302 ccu->data.clk_num = count;
303
304 PERI_CLK_SETUP(clks, ccu, BCM281XX_AON_CCU_HUB_TIMER, hub_timer);
305 PERI_CLK_SETUP(clks, ccu, BCM281XX_AON_CCU_PMU_BSC, pmu_bsc);
306 PERI_CLK_SETUP(clks, ccu, BCM281XX_AON_CCU_PMU_BSC_VAR, pmu_bsc_var);
307
308 return 0;
309}
310
311static int __init bcm281xx_hub_ccu_clks_setup(struct ccu_data *ccu)
312{
313 struct clk **clks;
314 size_t count = BCM281XX_HUB_CCU_CLOCK_COUNT;
315
316 clks = kzalloc(count * sizeof(*clks), GFP_KERNEL);
317 if (!clks) {
318 pr_err("%s: failed to allocate hub clocks\n", __func__);
319 return -ENOMEM;
320 }
321 ccu->data.clks = clks;
322 ccu->data.clk_num = count;
323
324 PERI_CLK_SETUP(clks, ccu, BCM281XX_HUB_CCU_TMON_1M, tmon_1m);
325
326 return 0;
327}
328
329static int __init bcm281xx_master_ccu_clks_setup(struct ccu_data *ccu)
330{
331 struct clk **clks;
332 size_t count = BCM281XX_MASTER_CCU_CLOCK_COUNT;
333
334 clks = kzalloc(count * sizeof(*clks), GFP_KERNEL);
335 if (!clks) {
336 pr_err("%s: failed to allocate master clocks\n", __func__);
337 return -ENOMEM;
338 }
339 ccu->data.clks = clks;
340 ccu->data.clk_num = count;
341
342 PERI_CLK_SETUP(clks, ccu, BCM281XX_MASTER_CCU_SDIO1, sdio1);
343 PERI_CLK_SETUP(clks, ccu, BCM281XX_MASTER_CCU_SDIO2, sdio2);
344 PERI_CLK_SETUP(clks, ccu, BCM281XX_MASTER_CCU_SDIO3, sdio3);
345 PERI_CLK_SETUP(clks, ccu, BCM281XX_MASTER_CCU_SDIO4, sdio4);
346 PERI_CLK_SETUP(clks, ccu, BCM281XX_MASTER_CCU_USB_IC, usb_ic);
347 PERI_CLK_SETUP(clks, ccu, BCM281XX_MASTER_CCU_HSIC2_48M, hsic2_48m);
348 PERI_CLK_SETUP(clks, ccu, BCM281XX_MASTER_CCU_HSIC2_12M, hsic2_12m);
349
350 return 0;
351}
352
353static int __init bcm281xx_slave_ccu_clks_setup(struct ccu_data *ccu)
354{
355 struct clk **clks;
356 size_t count = BCM281XX_SLAVE_CCU_CLOCK_COUNT;
357
358 clks = kzalloc(count * sizeof(*clks), GFP_KERNEL);
359 if (!clks) {
360 pr_err("%s: failed to allocate slave clocks\n", __func__);
361 return -ENOMEM;
362 }
363 ccu->data.clks = clks;
364 ccu->data.clk_num = count;
365
366 PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_UARTB, uartb);
367 PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_UARTB2, uartb2);
368 PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_UARTB3, uartb3);
369 PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_UARTB4, uartb4);
370 PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_SSP0, ssp0);
371 PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_SSP2, ssp2);
372 PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_BSC1, bsc1);
373 PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_BSC2, bsc2);
374 PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_BSC3, bsc3);
375 PERI_CLK_SETUP(clks, ccu, BCM281XX_SLAVE_CCU_PWM, pwm);
376
377 return 0;
378}
379 338
380/* Device tree match table callback functions */ 339/* Device tree match table callback functions */
381 340
382static void __init kona_dt_root_ccu_setup(struct device_node *node) 341static void __init kona_dt_root_ccu_setup(struct device_node *node)
383{ 342{
384 kona_dt_ccu_setup(node, bcm281xx_root_ccu_clks_setup); 343 kona_dt_ccu_setup(&root_ccu_data, node);
385} 344}
386 345
387static void __init kona_dt_aon_ccu_setup(struct device_node *node) 346static void __init kona_dt_aon_ccu_setup(struct device_node *node)
388{ 347{
389 kona_dt_ccu_setup(node, bcm281xx_aon_ccu_clks_setup); 348 kona_dt_ccu_setup(&aon_ccu_data, node);
390} 349}
391 350
392static void __init kona_dt_hub_ccu_setup(struct device_node *node) 351static void __init kona_dt_hub_ccu_setup(struct device_node *node)
393{ 352{
394 kona_dt_ccu_setup(node, bcm281xx_hub_ccu_clks_setup); 353 kona_dt_ccu_setup(&hub_ccu_data, node);
395} 354}
396 355
397static void __init kona_dt_master_ccu_setup(struct device_node *node) 356static void __init kona_dt_master_ccu_setup(struct device_node *node)
398{ 357{
399 kona_dt_ccu_setup(node, bcm281xx_master_ccu_clks_setup); 358 kona_dt_ccu_setup(&master_ccu_data, node);
400} 359}
401 360
402static void __init kona_dt_slave_ccu_setup(struct device_node *node) 361static void __init kona_dt_slave_ccu_setup(struct device_node *node)
403{ 362{
404 kona_dt_ccu_setup(node, bcm281xx_slave_ccu_clks_setup); 363 kona_dt_ccu_setup(&slave_ccu_data, node);
405} 364}
406 365
407CLK_OF_DECLARE(bcm11351_root_ccu, BCM11351_DT_ROOT_CCU_COMPAT, 366CLK_OF_DECLARE(bcm281xx_root_ccu, BCM281XX_DT_ROOT_CCU_COMPAT,
408 kona_dt_root_ccu_setup); 367 kona_dt_root_ccu_setup);
409CLK_OF_DECLARE(bcm11351_aon_ccu, BCM11351_DT_AON_CCU_COMPAT, 368CLK_OF_DECLARE(bcm281xx_aon_ccu, BCM281XX_DT_AON_CCU_COMPAT,
410 kona_dt_aon_ccu_setup); 369 kona_dt_aon_ccu_setup);
411CLK_OF_DECLARE(bcm11351_hub_ccu, BCM11351_DT_HUB_CCU_COMPAT, 370CLK_OF_DECLARE(bcm281xx_hub_ccu, BCM281XX_DT_HUB_CCU_COMPAT,
412 kona_dt_hub_ccu_setup); 371 kona_dt_hub_ccu_setup);
413CLK_OF_DECLARE(bcm11351_master_ccu, BCM11351_DT_MASTER_CCU_COMPAT, 372CLK_OF_DECLARE(bcm281xx_master_ccu, BCM281XX_DT_MASTER_CCU_COMPAT,
414 kona_dt_master_ccu_setup); 373 kona_dt_master_ccu_setup);
415CLK_OF_DECLARE(bcm11351_slave_ccu, BCM11351_DT_SLAVE_CCU_COMPAT, 374CLK_OF_DECLARE(bcm281xx_slave_ccu, BCM281XX_DT_SLAVE_CCU_COMPAT,
416 kona_dt_slave_ccu_setup); 375 kona_dt_slave_ccu_setup);
diff --git a/drivers/clk/bcm/clk-kona-setup.c b/drivers/clk/bcm/clk-kona-setup.c
index 54a06526f64f..e5aededdd322 100644
--- a/drivers/clk/bcm/clk-kona-setup.c
+++ b/drivers/clk/bcm/clk-kona-setup.c
@@ -25,6 +25,31 @@ LIST_HEAD(ccu_list); /* The list of set up CCUs */
25 25
26/* Validity checking */ 26/* Validity checking */
27 27
28static bool ccu_data_offsets_valid(struct ccu_data *ccu)
29{
30 struct ccu_policy *ccu_policy = &ccu->policy;
31 u32 limit;
32
33 limit = ccu->range - sizeof(u32);
34 limit = round_down(limit, sizeof(u32));
35 if (ccu_policy_exists(ccu_policy)) {
36 if (ccu_policy->enable.offset > limit) {
37 pr_err("%s: bad policy enable offset for %s "
38 "(%u > %u)\n", __func__,
39 ccu->name, ccu_policy->enable.offset, limit);
40 return false;
41 }
42 if (ccu_policy->control.offset > limit) {
43 pr_err("%s: bad policy control offset for %s "
44 "(%u > %u)\n", __func__,
45 ccu->name, ccu_policy->control.offset, limit);
46 return false;
47 }
48 }
49
50 return true;
51}
52
28static bool clk_requires_trigger(struct kona_clk *bcm_clk) 53static bool clk_requires_trigger(struct kona_clk *bcm_clk)
29{ 54{
30 struct peri_clk_data *peri = bcm_clk->u.peri; 55 struct peri_clk_data *peri = bcm_clk->u.peri;
@@ -54,7 +79,9 @@ static bool clk_requires_trigger(struct kona_clk *bcm_clk)
54static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk) 79static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk)
55{ 80{
56 struct peri_clk_data *peri; 81 struct peri_clk_data *peri;
82 struct bcm_clk_policy *policy;
57 struct bcm_clk_gate *gate; 83 struct bcm_clk_gate *gate;
84 struct bcm_clk_hyst *hyst;
58 struct bcm_clk_div *div; 85 struct bcm_clk_div *div;
59 struct bcm_clk_sel *sel; 86 struct bcm_clk_sel *sel;
60 struct bcm_clk_trig *trig; 87 struct bcm_clk_trig *trig;
@@ -64,19 +91,41 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk)
64 91
65 BUG_ON(bcm_clk->type != bcm_clk_peri); 92 BUG_ON(bcm_clk->type != bcm_clk_peri);
66 peri = bcm_clk->u.peri; 93 peri = bcm_clk->u.peri;
67 name = bcm_clk->name; 94 name = bcm_clk->init_data.name;
68 range = bcm_clk->ccu->range; 95 range = bcm_clk->ccu->range;
69 96
70 limit = range - sizeof(u32); 97 limit = range - sizeof(u32);
71 limit = round_down(limit, sizeof(u32)); 98 limit = round_down(limit, sizeof(u32));
72 99
100 policy = &peri->policy;
101 if (policy_exists(policy)) {
102 if (policy->offset > limit) {
103 pr_err("%s: bad policy offset for %s (%u > %u)\n",
104 __func__, name, policy->offset, limit);
105 return false;
106 }
107 }
108
73 gate = &peri->gate; 109 gate = &peri->gate;
110 hyst = &peri->hyst;
74 if (gate_exists(gate)) { 111 if (gate_exists(gate)) {
75 if (gate->offset > limit) { 112 if (gate->offset > limit) {
76 pr_err("%s: bad gate offset for %s (%u > %u)\n", 113 pr_err("%s: bad gate offset for %s (%u > %u)\n",
77 __func__, name, gate->offset, limit); 114 __func__, name, gate->offset, limit);
78 return false; 115 return false;
79 } 116 }
117
118 if (hyst_exists(hyst)) {
119 if (hyst->offset > limit) {
120 pr_err("%s: bad hysteresis offset for %s "
121 "(%u > %u)\n", __func__,
122 name, hyst->offset, limit);
123 return false;
124 }
125 }
126 } else if (hyst_exists(hyst)) {
127 pr_err("%s: hysteresis but no gate for %s\n", __func__, name);
128 return false;
80 } 129 }
81 130
82 div = &peri->div; 131 div = &peri->div;
@@ -167,6 +216,36 @@ static bool bitfield_valid(u32 shift, u32 width, const char *field_name,
167 return true; 216 return true;
168} 217}
169 218
219static bool
220ccu_policy_valid(struct ccu_policy *ccu_policy, const char *ccu_name)
221{
222 struct bcm_lvm_en *enable = &ccu_policy->enable;
223 struct bcm_policy_ctl *control;
224
225 if (!bit_posn_valid(enable->bit, "policy enable", ccu_name))
226 return false;
227
228 control = &ccu_policy->control;
229 if (!bit_posn_valid(control->go_bit, "policy control GO", ccu_name))
230 return false;
231
232 if (!bit_posn_valid(control->atl_bit, "policy control ATL", ccu_name))
233 return false;
234
235 if (!bit_posn_valid(control->ac_bit, "policy control AC", ccu_name))
236 return false;
237
238 return true;
239}
240
241static bool policy_valid(struct bcm_clk_policy *policy, const char *clock_name)
242{
243 if (!bit_posn_valid(policy->bit, "policy", clock_name))
244 return false;
245
246 return true;
247}
248
170/* 249/*
171 * All gates, if defined, have a status bit, and for hardware-only 250 * All gates, if defined, have a status bit, and for hardware-only
172 * gates, that's it. Gates that can be software controlled also 251 * gates, that's it. Gates that can be software controlled also
@@ -196,6 +275,17 @@ static bool gate_valid(struct bcm_clk_gate *gate, const char *field_name,
196 return true; 275 return true;
197} 276}
198 277
278static bool hyst_valid(struct bcm_clk_hyst *hyst, const char *clock_name)
279{
280 if (!bit_posn_valid(hyst->en_bit, "hysteresis enable", clock_name))
281 return false;
282
283 if (!bit_posn_valid(hyst->val_bit, "hysteresis value", clock_name))
284 return false;
285
286 return true;
287}
288
199/* 289/*
200 * A selector bitfield must be valid. Its parent_sel array must 290 * A selector bitfield must be valid. Its parent_sel array must
201 * also be reasonable for the field. 291 * also be reasonable for the field.
@@ -312,7 +402,9 @@ static bool
312peri_clk_data_valid(struct kona_clk *bcm_clk) 402peri_clk_data_valid(struct kona_clk *bcm_clk)
313{ 403{
314 struct peri_clk_data *peri; 404 struct peri_clk_data *peri;
405 struct bcm_clk_policy *policy;
315 struct bcm_clk_gate *gate; 406 struct bcm_clk_gate *gate;
407 struct bcm_clk_hyst *hyst;
316 struct bcm_clk_sel *sel; 408 struct bcm_clk_sel *sel;
317 struct bcm_clk_div *div; 409 struct bcm_clk_div *div;
318 struct bcm_clk_div *pre_div; 410 struct bcm_clk_div *pre_div;
@@ -330,11 +422,20 @@ peri_clk_data_valid(struct kona_clk *bcm_clk)
330 return false; 422 return false;
331 423
332 peri = bcm_clk->u.peri; 424 peri = bcm_clk->u.peri;
333 name = bcm_clk->name; 425 name = bcm_clk->init_data.name;
426
427 policy = &peri->policy;
428 if (policy_exists(policy) && !policy_valid(policy, name))
429 return false;
430
334 gate = &peri->gate; 431 gate = &peri->gate;
335 if (gate_exists(gate) && !gate_valid(gate, "gate", name)) 432 if (gate_exists(gate) && !gate_valid(gate, "gate", name))
336 return false; 433 return false;
337 434
435 hyst = &peri->hyst;
436 if (hyst_exists(hyst) && !hyst_valid(hyst, name))
437 return false;
438
338 sel = &peri->sel; 439 sel = &peri->sel;
339 if (selector_exists(sel)) { 440 if (selector_exists(sel)) {
340 if (!sel_valid(sel, "selector", name)) 441 if (!sel_valid(sel, "selector", name))
@@ -567,7 +668,6 @@ static void peri_clk_teardown(struct peri_clk_data *data,
567 struct clk_init_data *init_data) 668 struct clk_init_data *init_data)
568{ 669{
569 clk_sel_teardown(&data->sel, init_data); 670 clk_sel_teardown(&data->sel, init_data);
570 init_data->ops = NULL;
571} 671}
572 672
573/* 673/*
@@ -576,10 +676,9 @@ static void peri_clk_teardown(struct peri_clk_data *data,
576 * that can be assigned if the clock has one or more parent clocks 676 * that can be assigned if the clock has one or more parent clocks
577 * associated with it. 677 * associated with it.
578 */ 678 */
579static int peri_clk_setup(struct ccu_data *ccu, struct peri_clk_data *data, 679static int
580 struct clk_init_data *init_data) 680peri_clk_setup(struct peri_clk_data *data, struct clk_init_data *init_data)
581{ 681{
582 init_data->ops = &kona_peri_clk_ops;
583 init_data->flags = CLK_IGNORE_UNUSED; 682 init_data->flags = CLK_IGNORE_UNUSED;
584 683
585 return clk_sel_setup(data->clocks, &data->sel, init_data); 684 return clk_sel_setup(data->clocks, &data->sel, init_data);
@@ -617,39 +716,26 @@ static void kona_clk_teardown(struct clk *clk)
617 bcm_clk_teardown(bcm_clk); 716 bcm_clk_teardown(bcm_clk);
618} 717}
619 718
620struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name, 719struct clk *kona_clk_setup(struct kona_clk *bcm_clk)
621 enum bcm_clk_type type, void *data)
622{ 720{
623 struct kona_clk *bcm_clk; 721 struct clk_init_data *init_data = &bcm_clk->init_data;
624 struct clk_init_data *init_data;
625 struct clk *clk = NULL; 722 struct clk *clk = NULL;
626 723
627 bcm_clk = kzalloc(sizeof(*bcm_clk), GFP_KERNEL); 724 switch (bcm_clk->type) {
628 if (!bcm_clk) {
629 pr_err("%s: failed to allocate bcm_clk for %s\n", __func__,
630 name);
631 return NULL;
632 }
633 bcm_clk->ccu = ccu;
634 bcm_clk->name = name;
635
636 init_data = &bcm_clk->init_data;
637 init_data->name = name;
638 switch (type) {
639 case bcm_clk_peri: 725 case bcm_clk_peri:
640 if (peri_clk_setup(ccu, data, init_data)) 726 if (peri_clk_setup(bcm_clk->u.data, init_data))
641 goto out_free; 727 return NULL;
642 break; 728 break;
643 default: 729 default:
644 data = NULL; 730 pr_err("%s: clock type %d invalid for %s\n", __func__,
645 break; 731 (int)bcm_clk->type, init_data->name);
732 return NULL;
646 } 733 }
647 bcm_clk->type = type;
648 bcm_clk->u.data = data;
649 734
650 /* Make sure everything makes sense before we set it up */ 735 /* Make sure everything makes sense before we set it up */
651 if (!kona_clk_valid(bcm_clk)) { 736 if (!kona_clk_valid(bcm_clk)) {
652 pr_err("%s: clock data invalid for %s\n", __func__, name); 737 pr_err("%s: clock data invalid for %s\n", __func__,
738 init_data->name);
653 goto out_teardown; 739 goto out_teardown;
654 } 740 }
655 741
@@ -657,7 +743,7 @@ struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name,
657 clk = clk_register(NULL, &bcm_clk->hw); 743 clk = clk_register(NULL, &bcm_clk->hw);
658 if (IS_ERR(clk)) { 744 if (IS_ERR(clk)) {
659 pr_err("%s: error registering clock %s (%ld)\n", __func__, 745 pr_err("%s: error registering clock %s (%ld)\n", __func__,
660 name, PTR_ERR(clk)); 746 init_data->name, PTR_ERR(clk));
661 goto out_teardown; 747 goto out_teardown;
662 } 748 }
663 BUG_ON(!clk); 749 BUG_ON(!clk);
@@ -665,8 +751,6 @@ struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name,
665 return clk; 751 return clk;
666out_teardown: 752out_teardown:
667 bcm_clk_teardown(bcm_clk); 753 bcm_clk_teardown(bcm_clk);
668out_free:
669 kfree(bcm_clk);
670 754
671 return NULL; 755 return NULL;
672} 756}
@@ -675,50 +759,64 @@ static void ccu_clks_teardown(struct ccu_data *ccu)
675{ 759{
676 u32 i; 760 u32 i;
677 761
678 for (i = 0; i < ccu->data.clk_num; i++) 762 for (i = 0; i < ccu->clk_data.clk_num; i++)
679 kona_clk_teardown(ccu->data.clks[i]); 763 kona_clk_teardown(ccu->clk_data.clks[i]);
680 kfree(ccu->data.clks); 764 kfree(ccu->clk_data.clks);
681} 765}
682 766
683static void kona_ccu_teardown(struct ccu_data *ccu) 767static void kona_ccu_teardown(struct ccu_data *ccu)
684{ 768{
685 if (!ccu) 769 kfree(ccu->clk_data.clks);
686 return; 770 ccu->clk_data.clks = NULL;
687
688 if (!ccu->base) 771 if (!ccu->base)
689 goto done; 772 return;
690 773
691 of_clk_del_provider(ccu->node); /* safe if never added */ 774 of_clk_del_provider(ccu->node); /* safe if never added */
692 ccu_clks_teardown(ccu); 775 ccu_clks_teardown(ccu);
693 list_del(&ccu->links); 776 list_del(&ccu->links);
694 of_node_put(ccu->node); 777 of_node_put(ccu->node);
778 ccu->node = NULL;
695 iounmap(ccu->base); 779 iounmap(ccu->base);
696done: 780 ccu->base = NULL;
697 kfree(ccu->name); 781}
698 kfree(ccu); 782
783static bool ccu_data_valid(struct ccu_data *ccu)
784{
785 struct ccu_policy *ccu_policy;
786
787 if (!ccu_data_offsets_valid(ccu))
788 return false;
789
790 ccu_policy = &ccu->policy;
791 if (ccu_policy_exists(ccu_policy))
792 if (!ccu_policy_valid(ccu_policy, ccu->name))
793 return false;
794
795 return true;
699} 796}
700 797
701/* 798/*
702 * Set up a CCU. Call the provided ccu_clks_setup callback to 799 * Set up a CCU. Call the provided ccu_clks_setup callback to
703 * initialize the array of clocks provided by the CCU. 800 * initialize the array of clocks provided by the CCU.
704 */ 801 */
705void __init kona_dt_ccu_setup(struct device_node *node, 802void __init kona_dt_ccu_setup(struct ccu_data *ccu,
706 int (*ccu_clks_setup)(struct ccu_data *)) 803 struct device_node *node)
707{ 804{
708 struct ccu_data *ccu;
709 struct resource res = { 0 }; 805 struct resource res = { 0 };
710 resource_size_t range; 806 resource_size_t range;
807 unsigned int i;
711 int ret; 808 int ret;
712 809
713 ccu = kzalloc(sizeof(*ccu), GFP_KERNEL); 810 if (ccu->clk_data.clk_num) {
714 if (ccu) 811 size_t size;
715 ccu->name = kstrdup(node->name, GFP_KERNEL);
716 if (!ccu || !ccu->name) {
717 pr_err("%s: unable to allocate CCU struct for %s\n",
718 __func__, node->name);
719 kfree(ccu);
720 812
721 return; 813 size = ccu->clk_data.clk_num * sizeof(*ccu->clk_data.clks);
814 ccu->clk_data.clks = kzalloc(size, GFP_KERNEL);
815 if (!ccu->clk_data.clks) {
816 pr_err("%s: unable to allocate %u clocks for %s\n",
817 __func__, ccu->clk_data.clk_num, node->name);
818 return;
819 }
722 } 820 }
723 821
724 ret = of_address_to_resource(node, 0, &res); 822 ret = of_address_to_resource(node, 0, &res);
@@ -736,24 +834,33 @@ void __init kona_dt_ccu_setup(struct device_node *node,
736 } 834 }
737 835
738 ccu->range = (u32)range; 836 ccu->range = (u32)range;
837
838 if (!ccu_data_valid(ccu)) {
839 pr_err("%s: ccu data not valid for %s\n", __func__, node->name);
840 goto out_err;
841 }
842
739 ccu->base = ioremap(res.start, ccu->range); 843 ccu->base = ioremap(res.start, ccu->range);
740 if (!ccu->base) { 844 if (!ccu->base) {
741 pr_err("%s: unable to map CCU registers for %s\n", __func__, 845 pr_err("%s: unable to map CCU registers for %s\n", __func__,
742 node->name); 846 node->name);
743 goto out_err; 847 goto out_err;
744 } 848 }
745
746 spin_lock_init(&ccu->lock);
747 INIT_LIST_HEAD(&ccu->links);
748 ccu->node = of_node_get(node); 849 ccu->node = of_node_get(node);
749
750 list_add_tail(&ccu->links, &ccu_list); 850 list_add_tail(&ccu->links, &ccu_list);
751 851
752 /* Set up clocks array (in ccu->data) */ 852 /*
753 if (ccu_clks_setup(ccu)) 853 * Set up each defined kona clock and save the result in
754 goto out_err; 854 * the clock framework clock array (in ccu->data). Then
855 * register as a provider for these clocks.
856 */
857 for (i = 0; i < ccu->clk_data.clk_num; i++) {
858 if (!ccu->kona_clks[i].ccu)
859 continue;
860 ccu->clk_data.clks[i] = kona_clk_setup(&ccu->kona_clks[i]);
861 }
755 862
756 ret = of_clk_add_provider(node, of_clk_src_onecell_get, &ccu->data); 863 ret = of_clk_add_provider(node, of_clk_src_onecell_get, &ccu->clk_data);
757 if (ret) { 864 if (ret) {
758 pr_err("%s: error adding ccu %s as provider (%d)\n", __func__, 865 pr_err("%s: error adding ccu %s as provider (%d)\n", __func__,
759 node->name, ret); 866 node->name, ret);
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c
index db11a87449f2..95af2e665dd3 100644
--- a/drivers/clk/bcm/clk-kona.c
+++ b/drivers/clk/bcm/clk-kona.c
@@ -16,6 +16,14 @@
16 16
17#include <linux/delay.h> 17#include <linux/delay.h>
18 18
19/*
20 * "Policies" affect the frequencies of bus clocks provided by a
21 * CCU. (I believe these polices are named "Deep Sleep", "Economy",
22 * "Normal", and "Turbo".) A lower policy number has lower power
23 * consumption, and policy 2 is the default.
24 */
25#define CCU_POLICY_COUNT 4
26
19#define CCU_ACCESS_PASSWORD 0xA5A500 27#define CCU_ACCESS_PASSWORD 0xA5A500
20#define CLK_GATE_DELAY_LOOP 2000 28#define CLK_GATE_DELAY_LOOP 2000
21 29
@@ -207,9 +215,154 @@ __ccu_wait_bit(struct ccu_data *ccu, u32 reg_offset, u32 bit, bool want)
207 return true; 215 return true;
208 udelay(1); 216 udelay(1);
209 } 217 }
218 pr_warn("%s: %s/0x%04x bit %u was never %s\n", __func__,
219 ccu->name, reg_offset, bit, want ? "set" : "clear");
220
210 return false; 221 return false;
211} 222}
212 223
224/* Policy operations */
225
226static bool __ccu_policy_engine_start(struct ccu_data *ccu, bool sync)
227{
228 struct bcm_policy_ctl *control = &ccu->policy.control;
229 u32 offset;
230 u32 go_bit;
231 u32 mask;
232 bool ret;
233
234 /* If we don't need to control policy for this CCU, we're done. */
235 if (!policy_ctl_exists(control))
236 return true;
237
238 offset = control->offset;
239 go_bit = control->go_bit;
240
241 /* Ensure we're not busy before we start */
242 ret = __ccu_wait_bit(ccu, offset, go_bit, false);
243 if (!ret) {
244 pr_err("%s: ccu %s policy engine wouldn't go idle\n",
245 __func__, ccu->name);
246 return false;
247 }
248
249 /*
250 * If it's a synchronous request, we'll wait for the voltage
251 * and frequency of the active load to stabilize before
252 * returning. To do this we select the active load by
253 * setting the ATL bit.
254 *
255 * An asynchronous request instead ramps the voltage in the
256 * background, and when that process stabilizes, the target
257 * load is copied to the active load and the CCU frequency
258 * is switched. We do this by selecting the target load
259 * (ATL bit clear) and setting the request auto-copy (AC bit
260 * set).
261 *
262 * Note, we do NOT read-modify-write this register.
263 */
264 mask = (u32)1 << go_bit;
265 if (sync)
266 mask |= 1 << control->atl_bit;
267 else
268 mask |= 1 << control->ac_bit;
269 __ccu_write(ccu, offset, mask);
270
271 /* Wait for indication that operation is complete. */
272 ret = __ccu_wait_bit(ccu, offset, go_bit, false);
273 if (!ret)
274 pr_err("%s: ccu %s policy engine never started\n",
275 __func__, ccu->name);
276
277 return ret;
278}
279
280static bool __ccu_policy_engine_stop(struct ccu_data *ccu)
281{
282 struct bcm_lvm_en *enable = &ccu->policy.enable;
283 u32 offset;
284 u32 enable_bit;
285 bool ret;
286
287 /* If we don't need to control policy for this CCU, we're done. */
288 if (!policy_lvm_en_exists(enable))
289 return true;
290
291 /* Ensure we're not busy before we start */
292 offset = enable->offset;
293 enable_bit = enable->bit;
294 ret = __ccu_wait_bit(ccu, offset, enable_bit, false);
295 if (!ret) {
296 pr_err("%s: ccu %s policy engine already stopped\n",
297 __func__, ccu->name);
298 return false;
299 }
300
301 /* Now set the bit to stop the engine (NO read-modify-write) */
302 __ccu_write(ccu, offset, (u32)1 << enable_bit);
303
304 /* Wait for indication that it has stopped. */
305 ret = __ccu_wait_bit(ccu, offset, enable_bit, false);
306 if (!ret)
307 pr_err("%s: ccu %s policy engine never stopped\n",
308 __func__, ccu->name);
309
310 return ret;
311}
312
313/*
314 * A CCU has four operating conditions ("policies"), and some clocks
315 * can be disabled or enabled based on which policy is currently in
316 * effect. Such clocks have a bit in a "policy mask" register for
317 * each policy indicating whether the clock is enabled for that
318 * policy or not. The bit position for a clock is the same for all
319 * four registers, and the 32-bit registers are at consecutive
320 * addresses.
321 */
322static bool policy_init(struct ccu_data *ccu, struct bcm_clk_policy *policy)
323{
324 u32 offset;
325 u32 mask;
326 int i;
327 bool ret;
328
329 if (!policy_exists(policy))
330 return true;
331
332 /*
333 * We need to stop the CCU policy engine to allow update
334 * of our policy bits.
335 */
336 if (!__ccu_policy_engine_stop(ccu)) {
337 pr_err("%s: unable to stop CCU %s policy engine\n",
338 __func__, ccu->name);
339 return false;
340 }
341
342 /*
343 * For now, if a clock defines its policy bit we just mark
344 * it "enabled" for all four policies.
345 */
346 offset = policy->offset;
347 mask = (u32)1 << policy->bit;
348 for (i = 0; i < CCU_POLICY_COUNT; i++) {
349 u32 reg_val;
350
351 reg_val = __ccu_read(ccu, offset);
352 reg_val |= mask;
353 __ccu_write(ccu, offset, reg_val);
354 offset += sizeof(u32);
355 }
356
357 /* We're done updating; fire up the policy engine again. */
358 ret = __ccu_policy_engine_start(ccu, true);
359 if (!ret)
360 pr_err("%s: unable to restart CCU %s policy engine\n",
361 __func__, ccu->name);
362
363 return ret;
364}
365
213/* Gate operations */ 366/* Gate operations */
214 367
215/* Determine whether a clock is gated. CCU lock must be held. */ 368/* Determine whether a clock is gated. CCU lock must be held. */
@@ -374,6 +527,35 @@ static int clk_gate(struct ccu_data *ccu, const char *name,
374 return -EIO; 527 return -EIO;
375} 528}
376 529
530/* Hysteresis operations */
531
532/*
533 * If a clock gate requires a turn-off delay it will have
534 * "hysteresis" register bits defined. The first, if set, enables
535 * the delay; and if enabled, the second bit determines whether the
536 * delay is "low" or "high" (1 means high). For now, if it's
537 * defined for a clock, we set it.
538 */
539static bool hyst_init(struct ccu_data *ccu, struct bcm_clk_hyst *hyst)
540{
541 u32 offset;
542 u32 reg_val;
543 u32 mask;
544
545 if (!hyst_exists(hyst))
546 return true;
547
548 offset = hyst->offset;
549 mask = (u32)1 << hyst->en_bit;
550 mask |= (u32)1 << hyst->val_bit;
551
552 reg_val = __ccu_read(ccu, offset);
553 reg_val |= mask;
554 __ccu_write(ccu, offset, reg_val);
555
556 return true;
557}
558
377/* Trigger operations */ 559/* Trigger operations */
378 560
379/* 561/*
@@ -806,7 +988,7 @@ static int kona_peri_clk_enable(struct clk_hw *hw)
806 struct kona_clk *bcm_clk = to_kona_clk(hw); 988 struct kona_clk *bcm_clk = to_kona_clk(hw);
807 struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate; 989 struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate;
808 990
809 return clk_gate(bcm_clk->ccu, bcm_clk->name, gate, true); 991 return clk_gate(bcm_clk->ccu, bcm_clk->init_data.name, gate, true);
810} 992}
811 993
812static void kona_peri_clk_disable(struct clk_hw *hw) 994static void kona_peri_clk_disable(struct clk_hw *hw)
@@ -814,7 +996,7 @@ static void kona_peri_clk_disable(struct clk_hw *hw)
814 struct kona_clk *bcm_clk = to_kona_clk(hw); 996 struct kona_clk *bcm_clk = to_kona_clk(hw);
815 struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate; 997 struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate;
816 998
817 (void)clk_gate(bcm_clk->ccu, bcm_clk->name, gate, false); 999 (void)clk_gate(bcm_clk->ccu, bcm_clk->init_data.name, gate, false);
818} 1000}
819 1001
820static int kona_peri_clk_is_enabled(struct clk_hw *hw) 1002static int kona_peri_clk_is_enabled(struct clk_hw *hw)
@@ -849,6 +1031,58 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
849 rate ? rate : 1, *parent_rate, NULL); 1031 rate ? rate : 1, *parent_rate, NULL);
850} 1032}
851 1033
1034static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
1035 unsigned long *best_parent_rate, struct clk **best_parent)
1036{
1037 struct kona_clk *bcm_clk = to_kona_clk(hw);
1038 struct clk *clk = hw->clk;
1039 struct clk *current_parent;
1040 unsigned long parent_rate;
1041 unsigned long best_delta;
1042 unsigned long best_rate;
1043 u32 parent_count;
1044 u32 which;
1045
1046 /*
1047 * If there is no other parent to choose, use the current one.
1048 * Note: We don't honor (or use) CLK_SET_RATE_NO_REPARENT.
1049 */
1050 WARN_ON_ONCE(bcm_clk->init_data.flags & CLK_SET_RATE_NO_REPARENT);
1051 parent_count = (u32)bcm_clk->init_data.num_parents;
1052 if (parent_count < 2)
1053 return kona_peri_clk_round_rate(hw, rate, best_parent_rate);
1054
1055 /* Unless we can do better, stick with current parent */
1056 current_parent = clk_get_parent(clk);
1057 parent_rate = __clk_get_rate(current_parent);
1058 best_rate = kona_peri_clk_round_rate(hw, rate, &parent_rate);
1059 best_delta = abs(best_rate - rate);
1060
1061 /* Check whether any other parent clock can produce a better result */
1062 for (which = 0; which < parent_count; which++) {
1063 struct clk *parent = clk_get_parent_by_index(clk, which);
1064 unsigned long delta;
1065 unsigned long other_rate;
1066
1067 BUG_ON(!parent);
1068 if (parent == current_parent)
1069 continue;
1070
1071 /* We don't support CLK_SET_RATE_PARENT */
1072 parent_rate = __clk_get_rate(parent);
1073 other_rate = kona_peri_clk_round_rate(hw, rate, &parent_rate);
1074 delta = abs(other_rate - rate);
1075 if (delta < best_delta) {
1076 best_delta = delta;
1077 best_rate = other_rate;
1078 *best_parent = parent;
1079 *best_parent_rate = parent_rate;
1080 }
1081 }
1082
1083 return best_rate;
1084}
1085
852static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index) 1086static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
853{ 1087{
854 struct kona_clk *bcm_clk = to_kona_clk(hw); 1088 struct kona_clk *bcm_clk = to_kona_clk(hw);
@@ -872,12 +1106,13 @@ static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
872 1106
873 ret = selector_write(bcm_clk->ccu, &data->gate, sel, trig, index); 1107 ret = selector_write(bcm_clk->ccu, &data->gate, sel, trig, index);
874 if (ret == -ENXIO) { 1108 if (ret == -ENXIO) {
875 pr_err("%s: gating failure for %s\n", __func__, bcm_clk->name); 1109 pr_err("%s: gating failure for %s\n", __func__,
1110 bcm_clk->init_data.name);
876 ret = -EIO; /* Don't proliferate weird errors */ 1111 ret = -EIO; /* Don't proliferate weird errors */
877 } else if (ret == -EIO) { 1112 } else if (ret == -EIO) {
878 pr_err("%s: %strigger failed for %s\n", __func__, 1113 pr_err("%s: %strigger failed for %s\n", __func__,
879 trig == &data->pre_trig ? "pre-" : "", 1114 trig == &data->pre_trig ? "pre-" : "",
880 bcm_clk->name); 1115 bcm_clk->init_data.name);
881 } 1116 }
882 1117
883 return ret; 1118 return ret;
@@ -936,10 +1171,12 @@ static int kona_peri_clk_set_rate(struct clk_hw *hw, unsigned long rate,
936 ret = divider_write(bcm_clk->ccu, &data->gate, &data->div, 1171 ret = divider_write(bcm_clk->ccu, &data->gate, &data->div,
937 &data->trig, scaled_div); 1172 &data->trig, scaled_div);
938 if (ret == -ENXIO) { 1173 if (ret == -ENXIO) {
939 pr_err("%s: gating failure for %s\n", __func__, bcm_clk->name); 1174 pr_err("%s: gating failure for %s\n", __func__,
1175 bcm_clk->init_data.name);
940 ret = -EIO; /* Don't proliferate weird errors */ 1176 ret = -EIO; /* Don't proliferate weird errors */
941 } else if (ret == -EIO) { 1177 } else if (ret == -EIO) {
942 pr_err("%s: trigger failed for %s\n", __func__, bcm_clk->name); 1178 pr_err("%s: trigger failed for %s\n", __func__,
1179 bcm_clk->init_data.name);
943 } 1180 }
944 1181
945 return ret; 1182 return ret;
@@ -950,7 +1187,7 @@ struct clk_ops kona_peri_clk_ops = {
950 .disable = kona_peri_clk_disable, 1187 .disable = kona_peri_clk_disable,
951 .is_enabled = kona_peri_clk_is_enabled, 1188 .is_enabled = kona_peri_clk_is_enabled,
952 .recalc_rate = kona_peri_clk_recalc_rate, 1189 .recalc_rate = kona_peri_clk_recalc_rate,
953 .round_rate = kona_peri_clk_round_rate, 1190 .determine_rate = kona_peri_clk_determine_rate,
954 .set_parent = kona_peri_clk_set_parent, 1191 .set_parent = kona_peri_clk_set_parent,
955 .get_parent = kona_peri_clk_get_parent, 1192 .get_parent = kona_peri_clk_get_parent,
956 .set_rate = kona_peri_clk_set_rate, 1193 .set_rate = kona_peri_clk_set_rate,
@@ -961,15 +1198,24 @@ static bool __peri_clk_init(struct kona_clk *bcm_clk)
961{ 1198{
962 struct ccu_data *ccu = bcm_clk->ccu; 1199 struct ccu_data *ccu = bcm_clk->ccu;
963 struct peri_clk_data *peri = bcm_clk->u.peri; 1200 struct peri_clk_data *peri = bcm_clk->u.peri;
964 const char *name = bcm_clk->name; 1201 const char *name = bcm_clk->init_data.name;
965 struct bcm_clk_trig *trig; 1202 struct bcm_clk_trig *trig;
966 1203
967 BUG_ON(bcm_clk->type != bcm_clk_peri); 1204 BUG_ON(bcm_clk->type != bcm_clk_peri);
968 1205
1206 if (!policy_init(ccu, &peri->policy)) {
1207 pr_err("%s: error initializing policy for %s\n",
1208 __func__, name);
1209 return false;
1210 }
969 if (!gate_init(ccu, &peri->gate)) { 1211 if (!gate_init(ccu, &peri->gate)) {
970 pr_err("%s: error initializing gate for %s\n", __func__, name); 1212 pr_err("%s: error initializing gate for %s\n", __func__, name);
971 return false; 1213 return false;
972 } 1214 }
1215 if (!hyst_init(ccu, &peri->hyst)) {
1216 pr_err("%s: error initializing hyst for %s\n", __func__, name);
1217 return false;
1218 }
973 if (!div_init(ccu, &peri->gate, &peri->div, &peri->trig)) { 1219 if (!div_init(ccu, &peri->gate, &peri->div, &peri->trig)) {
974 pr_err("%s: error initializing divider for %s\n", __func__, 1220 pr_err("%s: error initializing divider for %s\n", __func__,
975 name); 1221 name);
@@ -1014,13 +1260,13 @@ bool __init kona_ccu_init(struct ccu_data *ccu)
1014{ 1260{
1015 unsigned long flags; 1261 unsigned long flags;
1016 unsigned int which; 1262 unsigned int which;
1017 struct clk **clks = ccu->data.clks; 1263 struct clk **clks = ccu->clk_data.clks;
1018 bool success = true; 1264 bool success = true;
1019 1265
1020 flags = ccu_lock(ccu); 1266 flags = ccu_lock(ccu);
1021 __ccu_write_enable(ccu); 1267 __ccu_write_enable(ccu);
1022 1268
1023 for (which = 0; which < ccu->data.clk_num; which++) { 1269 for (which = 0; which < ccu->clk_data.clk_num; which++) {
1024 struct kona_clk *bcm_clk; 1270 struct kona_clk *bcm_clk;
1025 1271
1026 if (!clks[which]) 1272 if (!clks[which])
diff --git a/drivers/clk/bcm/clk-kona.h b/drivers/clk/bcm/clk-kona.h
index dee690951bb6..2537b3072910 100644
--- a/drivers/clk/bcm/clk-kona.h
+++ b/drivers/clk/bcm/clk-kona.h
@@ -43,8 +43,14 @@
43#define FLAG_FLIP(obj, type, flag) ((obj)->flags ^= FLAG(type, flag)) 43#define FLAG_FLIP(obj, type, flag) ((obj)->flags ^= FLAG(type, flag))
44#define FLAG_TEST(obj, type, flag) (!!((obj)->flags & FLAG(type, flag))) 44#define FLAG_TEST(obj, type, flag) (!!((obj)->flags & FLAG(type, flag)))
45 45
46/* CCU field state tests */
47
48#define ccu_policy_exists(ccu_policy) ((ccu_policy)->enable.offset != 0)
49
46/* Clock field state tests */ 50/* Clock field state tests */
47 51
52#define policy_exists(policy) ((policy)->offset != 0)
53
48#define gate_exists(gate) FLAG_TEST(gate, GATE, EXISTS) 54#define gate_exists(gate) FLAG_TEST(gate, GATE, EXISTS)
49#define gate_is_enabled(gate) FLAG_TEST(gate, GATE, ENABLED) 55#define gate_is_enabled(gate) FLAG_TEST(gate, GATE, ENABLED)
50#define gate_is_hw_controllable(gate) FLAG_TEST(gate, GATE, HW) 56#define gate_is_hw_controllable(gate) FLAG_TEST(gate, GATE, HW)
@@ -54,6 +60,8 @@
54 60
55#define gate_flip_enabled(gate) FLAG_FLIP(gate, GATE, ENABLED) 61#define gate_flip_enabled(gate) FLAG_FLIP(gate, GATE, ENABLED)
56 62
63#define hyst_exists(hyst) ((hyst)->offset != 0)
64
57#define divider_exists(div) FLAG_TEST(div, DIV, EXISTS) 65#define divider_exists(div) FLAG_TEST(div, DIV, EXISTS)
58#define divider_is_fixed(div) FLAG_TEST(div, DIV, FIXED) 66#define divider_is_fixed(div) FLAG_TEST(div, DIV, FIXED)
59#define divider_has_fraction(div) (!divider_is_fixed(div) && \ 67#define divider_has_fraction(div) (!divider_is_fixed(div) && \
@@ -62,6 +70,9 @@
62#define selector_exists(sel) ((sel)->width != 0) 70#define selector_exists(sel) ((sel)->width != 0)
63#define trigger_exists(trig) FLAG_TEST(trig, TRIG, EXISTS) 71#define trigger_exists(trig) FLAG_TEST(trig, TRIG, EXISTS)
64 72
73#define policy_lvm_en_exists(enable) ((enable)->offset != 0)
74#define policy_ctl_exists(control) ((control)->offset != 0)
75
65/* Clock type, used to tell common block what it's part of */ 76/* Clock type, used to tell common block what it's part of */
66enum bcm_clk_type { 77enum bcm_clk_type {
67 bcm_clk_none, /* undefined clock type */ 78 bcm_clk_none, /* undefined clock type */
@@ -71,25 +82,26 @@ enum bcm_clk_type {
71}; 82};
72 83
73/* 84/*
74 * Each CCU defines a mapped area of memory containing registers 85 * CCU policy control for clocks. Clocks can be enabled or disabled
75 * used to manage clocks implemented by the CCU. Access to memory 86 * based on the CCU policy in effect. One bit in each policy mask
76 * within the CCU's space is serialized by a spinlock. Before any 87 * register (one per CCU policy) represents whether the clock is
77 * (other) address can be written, a special access "password" value 88 * enabled when that policy is effect or not. The CCU policy engine
78 * must be written to its WR_ACCESS register (located at the base 89 * must be stopped to update these bits, and must be restarted again
79 * address of the range). We keep track of the name of each CCU as 90 * afterward.
80 * it is set up, and maintain them in a list.
81 */ 91 */
82struct ccu_data { 92struct bcm_clk_policy {
83 void __iomem *base; /* base of mapped address space */ 93 u32 offset; /* first policy mask register offset */
84 spinlock_t lock; /* serialization lock */ 94 u32 bit; /* bit used in all mask registers */
85 bool write_enabled; /* write access is currently enabled */
86 struct list_head links; /* for ccu_list */
87 struct device_node *node;
88 struct clk_onecell_data data;
89 const char *name;
90 u32 range; /* byte range of address space */
91}; 95};
92 96
97/* Policy initialization macro */
98
99#define POLICY(_offset, _bit) \
100 { \
101 .offset = (_offset), \
102 .bit = (_bit), \
103 }
104
93/* 105/*
94 * Gating control and status is managed by a 32-bit gate register. 106 * Gating control and status is managed by a 32-bit gate register.
95 * 107 *
@@ -195,6 +207,22 @@ struct bcm_clk_gate {
195 .flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS), \ 207 .flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS), \
196 } 208 }
197 209
210/* Gate hysteresis for clocks */
211struct bcm_clk_hyst {
212 u32 offset; /* hyst register offset (normally CLKGATE) */
213 u32 en_bit; /* bit used to enable hysteresis */
214 u32 val_bit; /* if enabled: 0 = low delay; 1 = high delay */
215};
216
217/* Hysteresis initialization macro */
218
219#define HYST(_offset, _en_bit, _val_bit) \
220 { \
221 .offset = (_offset), \
222 .en_bit = (_en_bit), \
223 .val_bit = (_val_bit), \
224 }
225
198/* 226/*
199 * Each clock can have zero, one, or two dividers which change the 227 * Each clock can have zero, one, or two dividers which change the
200 * output rate of the clock. Each divider can be either fixed or 228 * output rate of the clock. Each divider can be either fixed or
@@ -360,7 +388,9 @@ struct bcm_clk_trig {
360 } 388 }
361 389
362struct peri_clk_data { 390struct peri_clk_data {
391 struct bcm_clk_policy policy;
363 struct bcm_clk_gate gate; 392 struct bcm_clk_gate gate;
393 struct bcm_clk_hyst hyst;
364 struct bcm_clk_trig pre_trig; 394 struct bcm_clk_trig pre_trig;
365 struct bcm_clk_div pre_div; 395 struct bcm_clk_div pre_div;
366 struct bcm_clk_trig trig; 396 struct bcm_clk_trig trig;
@@ -373,8 +403,7 @@ struct peri_clk_data {
373 403
374struct kona_clk { 404struct kona_clk {
375 struct clk_hw hw; 405 struct clk_hw hw;
376 struct clk_init_data init_data; 406 struct clk_init_data init_data; /* includes name of this clock */
377 const char *name; /* name of this clock */
378 struct ccu_data *ccu; /* ccu this clock is associated with */ 407 struct ccu_data *ccu; /* ccu this clock is associated with */
379 enum bcm_clk_type type; 408 enum bcm_clk_type type;
380 union { 409 union {
@@ -385,14 +414,92 @@ struct kona_clk {
385#define to_kona_clk(_hw) \ 414#define to_kona_clk(_hw) \
386 container_of(_hw, struct kona_clk, hw) 415 container_of(_hw, struct kona_clk, hw)
387 416
388/* Exported globals */ 417/* Initialization macro for an entry in a CCU's kona_clks[] array. */
418#define KONA_CLK(_ccu_name, _clk_name, _type) \
419 { \
420 .init_data = { \
421 .name = #_clk_name, \
422 .ops = &kona_ ## _type ## _clk_ops, \
423 }, \
424 .ccu = &_ccu_name ## _ccu_data, \
425 .type = bcm_clk_ ## _type, \
426 .u.data = &_clk_name ## _data, \
427 }
428#define LAST_KONA_CLK { .type = bcm_clk_none }
389 429
390extern struct clk_ops kona_peri_clk_ops; 430/*
431 * CCU policy control. To enable software update of the policy
432 * tables the CCU policy engine must be stopped by setting the
433 * software update enable bit (LVM_EN). After an update the engine
434 * is restarted using the GO bit and either the GO_ATL or GO_AC bit.
435 */
436struct bcm_lvm_en {
437 u32 offset; /* LVM_EN register offset */
438 u32 bit; /* POLICY_CONFIG_EN bit in register */
439};
440
441/* Policy enable initialization macro */
442#define CCU_LVM_EN(_offset, _bit) \
443 { \
444 .offset = (_offset), \
445 .bit = (_bit), \
446 }
447
448struct bcm_policy_ctl {
449 u32 offset; /* POLICY_CTL register offset */
450 u32 go_bit;
451 u32 atl_bit; /* GO, GO_ATL, and GO_AC bits */
452 u32 ac_bit;
453};
454
455/* Policy control initialization macro */
456#define CCU_POLICY_CTL(_offset, _go_bit, _ac_bit, _atl_bit) \
457 { \
458 .offset = (_offset), \
459 .go_bit = (_go_bit), \
460 .ac_bit = (_ac_bit), \
461 .atl_bit = (_atl_bit), \
462 }
463
464struct ccu_policy {
465 struct bcm_lvm_en enable;
466 struct bcm_policy_ctl control;
467};
468
469/*
470 * Each CCU defines a mapped area of memory containing registers
471 * used to manage clocks implemented by the CCU. Access to memory
472 * within the CCU's space is serialized by a spinlock. Before any
473 * (other) address can be written, a special access "password" value
474 * must be written to its WR_ACCESS register (located at the base
475 * address of the range). We keep track of the name of each CCU as
476 * it is set up, and maintain them in a list.
477 */
478struct ccu_data {
479 void __iomem *base; /* base of mapped address space */
480 spinlock_t lock; /* serialization lock */
481 bool write_enabled; /* write access is currently enabled */
482 struct ccu_policy policy;
483 struct list_head links; /* for ccu_list */
484 struct device_node *node;
485 struct clk_onecell_data clk_data;
486 const char *name;
487 u32 range; /* byte range of address space */
488 struct kona_clk kona_clks[]; /* must be last */
489};
391 490
392/* Help functions */ 491/* Initialization for common fields in a Kona ccu_data structure */
492#define KONA_CCU_COMMON(_prefix, _name, _ccuname) \
493 .name = #_name "_ccu", \
494 .lock = __SPIN_LOCK_UNLOCKED(_name ## _ccu_data.lock), \
495 .links = LIST_HEAD_INIT(_name ## _ccu_data.links), \
496 .clk_data = { \
497 .clk_num = _prefix ## _ ## _ccuname ## _CCU_CLOCK_COUNT, \
498 }
499
500/* Exported globals */
393 501
394#define PERI_CLK_SETUP(clks, ccu, id, name) \ 502extern struct clk_ops kona_peri_clk_ops;
395 clks[id] = kona_clk_setup(ccu, #name, bcm_clk_peri, &name ## _data)
396 503
397/* Externally visible functions */ 504/* Externally visible functions */
398 505
@@ -401,10 +508,9 @@ extern u64 scaled_div_max(struct bcm_clk_div *div);
401extern u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, 508extern u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value,
402 u32 billionths); 509 u32 billionths);
403 510
404extern struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name, 511extern struct clk *kona_clk_setup(struct kona_clk *bcm_clk);
405 enum bcm_clk_type type, void *data); 512extern void __init kona_dt_ccu_setup(struct ccu_data *ccu,
406extern void __init kona_dt_ccu_setup(struct device_node *node, 513 struct device_node *node);
407 int (*ccu_clks_setup)(struct ccu_data *));
408extern bool __init kona_ccu_init(struct ccu_data *ccu); 514extern bool __init kona_ccu_init(struct ccu_data *ccu);
409 515
410#endif /* _CLK_KONA_H */ 516#endif /* _CLK_KONA_H */
diff --git a/drivers/clk/berlin/Makefile b/drivers/clk/berlin/Makefile
new file mode 100644
index 000000000000..2a36ab710a07
--- /dev/null
+++ b/drivers/clk/berlin/Makefile
@@ -0,0 +1,4 @@
1obj-y += berlin2-avpll.o berlin2-pll.o berlin2-div.o
2obj-$(CONFIG_MACH_BERLIN_BG2) += bg2.o
3obj-$(CONFIG_MACH_BERLIN_BG2CD) += bg2.o
4obj-$(CONFIG_MACH_BERLIN_BG2Q) += bg2q.o
diff --git a/drivers/clk/berlin/berlin2-avpll.c b/drivers/clk/berlin/berlin2-avpll.c
new file mode 100644
index 000000000000..fd0f26c38465
--- /dev/null
+++ b/drivers/clk/berlin/berlin2-avpll.c
@@ -0,0 +1,393 @@
1/*
2 * Copyright (c) 2014 Marvell Technology Group Ltd.
3 *
4 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
5 * Alexandre Belloni <alexandre.belloni@free-electrons.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#include <linux/clk-provider.h>
20#include <linux/io.h>
21#include <linux/kernel.h>
22#include <linux/of.h>
23#include <linux/of_address.h>
24#include <linux/slab.h>
25
26#include "berlin2-avpll.h"
27
28/*
29 * Berlin2 SoCs comprise up to two PLLs called AVPLL built upon a
30 * VCO with 8 channels each, channel 8 is the odd-one-out and does
31 * not provide mul/div.
32 *
33 * Unfortunately, its registers are not named but just numbered. To
34 * get in at least some kind of structure, we split each AVPLL into
35 * the VCOs and each channel into separate clock drivers.
36 *
37 * Also, here and there the VCO registers are a bit different with
38 * respect to bit shifts. Make sure to add a comment for those.
39 */
40#define NUM_CHANNELS 8
41
42#define AVPLL_CTRL(x) ((x) * 0x4)
43
44#define VCO_CTRL0 AVPLL_CTRL(0)
45/* BG2/BG2CDs VCO_B has an additional shift of 4 for its VCO_CTRL0 reg */
46#define VCO_RESET BIT(0)
47#define VCO_POWERUP BIT(1)
48#define VCO_INTERPOL_SHIFT 2
49#define VCO_INTERPOL_MASK (0xf << VCO_INTERPOL_SHIFT)
50#define VCO_REG1V45_SEL_SHIFT 6
51#define VCO_REG1V45_SEL(x) ((x) << VCO_REG1V45_SEL_SHIFT)
52#define VCO_REG1V45_SEL_1V40 VCO_REG1V45_SEL(0)
53#define VCO_REG1V45_SEL_1V45 VCO_REG1V45_SEL(1)
54#define VCO_REG1V45_SEL_1V50 VCO_REG1V45_SEL(2)
55#define VCO_REG1V45_SEL_1V55 VCO_REG1V45_SEL(3)
56#define VCO_REG1V45_SEL_MASK VCO_REG1V45_SEL(3)
57#define VCO_REG0V9_SEL_SHIFT 8
58#define VCO_REG0V9_SEL_MASK (0xf << VCO_REG0V9_SEL_SHIFT)
59#define VCO_VTHCAL_SHIFT 12
60#define VCO_VTHCAL(x) ((x) << VCO_VTHCAL_SHIFT)
61#define VCO_VTHCAL_0V90 VCO_VTHCAL(0)
62#define VCO_VTHCAL_0V95 VCO_VTHCAL(1)
63#define VCO_VTHCAL_1V00 VCO_VTHCAL(2)
64#define VCO_VTHCAL_1V05 VCO_VTHCAL(3)
65#define VCO_VTHCAL_MASK VCO_VTHCAL(3)
66#define VCO_KVCOEXT_SHIFT 14
67#define VCO_KVCOEXT_MASK (0x3 << VCO_KVCOEXT_SHIFT)
68#define VCO_KVCOEXT_ENABLE BIT(17)
69#define VCO_V2IEXT_SHIFT 18
70#define VCO_V2IEXT_MASK (0xf << VCO_V2IEXT_SHIFT)
71#define VCO_V2IEXT_ENABLE BIT(22)
72#define VCO_SPEED_SHIFT 23
73#define VCO_SPEED(x) ((x) << VCO_SPEED_SHIFT)
74#define VCO_SPEED_1G08_1G21 VCO_SPEED(0)
75#define VCO_SPEED_1G21_1G40 VCO_SPEED(1)
76#define VCO_SPEED_1G40_1G61 VCO_SPEED(2)
77#define VCO_SPEED_1G61_1G86 VCO_SPEED(3)
78#define VCO_SPEED_1G86_2G00 VCO_SPEED(4)
79#define VCO_SPEED_2G00_2G22 VCO_SPEED(5)
80#define VCO_SPEED_2G22 VCO_SPEED(6)
81#define VCO_SPEED_MASK VCO_SPEED(0x7)
82#define VCO_CLKDET_ENABLE BIT(26)
83#define VCO_CTRL1 AVPLL_CTRL(1)
84#define VCO_REFDIV_SHIFT 0
85#define VCO_REFDIV(x) ((x) << VCO_REFDIV_SHIFT)
86#define VCO_REFDIV_1 VCO_REFDIV(0)
87#define VCO_REFDIV_2 VCO_REFDIV(1)
88#define VCO_REFDIV_4 VCO_REFDIV(2)
89#define VCO_REFDIV_3 VCO_REFDIV(3)
90#define VCO_REFDIV_MASK VCO_REFDIV(0x3f)
91#define VCO_FBDIV_SHIFT 6
92#define VCO_FBDIV(x) ((x) << VCO_FBDIV_SHIFT)
93#define VCO_FBDIV_MASK VCO_FBDIV(0xff)
94#define VCO_ICP_SHIFT 14
95/* PLL Charge Pump Current = 10uA * (x + 1) */
96#define VCO_ICP(x) ((x) << VCO_ICP_SHIFT)
97#define VCO_ICP_MASK VCO_ICP(0xf)
98#define VCO_LOAD_CAP BIT(18)
99#define VCO_CALIBRATION_START BIT(19)
100#define VCO_FREQOFFSETn(x) AVPLL_CTRL(3 + (x))
101#define VCO_FREQOFFSET_MASK 0x7ffff
102#define VCO_CTRL10 AVPLL_CTRL(10)
103#define VCO_POWERUP_CH1 BIT(20)
104#define VCO_CTRL11 AVPLL_CTRL(11)
105#define VCO_CTRL12 AVPLL_CTRL(12)
106#define VCO_CTRL13 AVPLL_CTRL(13)
107#define VCO_CTRL14 AVPLL_CTRL(14)
108#define VCO_CTRL15 AVPLL_CTRL(15)
109#define VCO_SYNC1n(x) AVPLL_CTRL(15 + (x))
110#define VCO_SYNC1_MASK 0x1ffff
111#define VCO_SYNC2n(x) AVPLL_CTRL(23 + (x))
112#define VCO_SYNC2_MASK 0x1ffff
113#define VCO_CTRL30 AVPLL_CTRL(30)
114#define VCO_DPLL_CH1_ENABLE BIT(17)
115
116struct berlin2_avpll_vco {
117 struct clk_hw hw;
118 void __iomem *base;
119 u8 flags;
120};
121
122#define to_avpll_vco(hw) container_of(hw, struct berlin2_avpll_vco, hw)
123
124static int berlin2_avpll_vco_is_enabled(struct clk_hw *hw)
125{
126 struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
127 u32 reg;
128
129 reg = readl_relaxed(vco->base + VCO_CTRL0);
130 if (vco->flags & BERLIN2_AVPLL_BIT_QUIRK)
131 reg >>= 4;
132
133 return !!(reg & VCO_POWERUP);
134}
135
136static int berlin2_avpll_vco_enable(struct clk_hw *hw)
137{
138 struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
139 u32 reg;
140
141 reg = readl_relaxed(vco->base + VCO_CTRL0);
142 if (vco->flags & BERLIN2_AVPLL_BIT_QUIRK)
143 reg |= VCO_POWERUP << 4;
144 else
145 reg |= VCO_POWERUP;
146 writel_relaxed(reg, vco->base + VCO_CTRL0);
147
148 return 0;
149}
150
151static void berlin2_avpll_vco_disable(struct clk_hw *hw)
152{
153 struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
154 u32 reg;
155
156 reg = readl_relaxed(vco->base + VCO_CTRL0);
157 if (vco->flags & BERLIN2_AVPLL_BIT_QUIRK)
158 reg &= ~(VCO_POWERUP << 4);
159 else
160 reg &= ~VCO_POWERUP;
161 writel_relaxed(reg, vco->base + VCO_CTRL0);
162}
163
164static u8 vco_refdiv[] = { 1, 2, 4, 3 };
165
166static unsigned long
167berlin2_avpll_vco_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
168{
169 struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
170 u32 reg, refdiv, fbdiv;
171 u64 freq = parent_rate;
172
173 /* AVPLL VCO frequency: Fvco = (Fref / refdiv) * fbdiv */
174 reg = readl_relaxed(vco->base + VCO_CTRL1);
175 refdiv = (reg & VCO_REFDIV_MASK) >> VCO_REFDIV_SHIFT;
176 refdiv = vco_refdiv[refdiv];
177 fbdiv = (reg & VCO_FBDIV_MASK) >> VCO_FBDIV_SHIFT;
178 freq *= fbdiv;
179 do_div(freq, refdiv);
180
181 return (unsigned long)freq;
182}
183
184static const struct clk_ops berlin2_avpll_vco_ops = {
185 .is_enabled = berlin2_avpll_vco_is_enabled,
186 .enable = berlin2_avpll_vco_enable,
187 .disable = berlin2_avpll_vco_disable,
188 .recalc_rate = berlin2_avpll_vco_recalc_rate,
189};
190
191struct clk * __init berlin2_avpll_vco_register(void __iomem *base,
192 const char *name, const char *parent_name,
193 u8 vco_flags, unsigned long flags)
194{
195 struct berlin2_avpll_vco *vco;
196 struct clk_init_data init;
197
198 vco = kzalloc(sizeof(*vco), GFP_KERNEL);
199 if (!vco)
200 return ERR_PTR(-ENOMEM);
201
202 vco->base = base;
203 vco->flags = vco_flags;
204 vco->hw.init = &init;
205 init.name = name;
206 init.ops = &berlin2_avpll_vco_ops;
207 init.parent_names = &parent_name;
208 init.num_parents = 1;
209 init.flags = flags;
210
211 return clk_register(NULL, &vco->hw);
212}
213
214struct berlin2_avpll_channel {
215 struct clk_hw hw;
216 void __iomem *base;
217 u8 flags;
218 u8 index;
219};
220
221#define to_avpll_channel(hw) container_of(hw, struct berlin2_avpll_channel, hw)
222
223static int berlin2_avpll_channel_is_enabled(struct clk_hw *hw)
224{
225 struct berlin2_avpll_channel *ch = to_avpll_channel(hw);
226 u32 reg;
227
228 if (ch->index == 7)
229 return 1;
230
231 reg = readl_relaxed(ch->base + VCO_CTRL10);
232 reg &= VCO_POWERUP_CH1 << ch->index;
233
234 return !!reg;
235}
236
237static int berlin2_avpll_channel_enable(struct clk_hw *hw)
238{
239 struct berlin2_avpll_channel *ch = to_avpll_channel(hw);
240 u32 reg;
241
242 reg = readl_relaxed(ch->base + VCO_CTRL10);
243 reg |= VCO_POWERUP_CH1 << ch->index;
244 writel_relaxed(reg, ch->base + VCO_CTRL10);
245
246 return 0;
247}
248
249static void berlin2_avpll_channel_disable(struct clk_hw *hw)
250{
251 struct berlin2_avpll_channel *ch = to_avpll_channel(hw);
252 u32 reg;
253
254 reg = readl_relaxed(ch->base + VCO_CTRL10);
255 reg &= ~(VCO_POWERUP_CH1 << ch->index);
256 writel_relaxed(reg, ch->base + VCO_CTRL10);
257}
258
259static const u8 div_hdmi[] = { 1, 2, 4, 6 };
260static const u8 div_av1[] = { 1, 2, 5, 5 };
261
262static unsigned long
263berlin2_avpll_channel_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
264{
265 struct berlin2_avpll_channel *ch = to_avpll_channel(hw);
266 u32 reg, div_av2, div_av3, divider = 1;
267 u64 freq = parent_rate;
268
269 reg = readl_relaxed(ch->base + VCO_CTRL30);
270 if ((reg & (VCO_DPLL_CH1_ENABLE << ch->index)) == 0)
271 goto skip_div;
272
273 /*
274 * Fch = (Fref * sync2) /
275 * (sync1 * div_hdmi * div_av1 * div_av2 * div_av3)
276 */
277
278 reg = readl_relaxed(ch->base + VCO_SYNC1n(ch->index));
279 /* BG2/BG2CDs SYNC1 reg on AVPLL_B channel 1 is shifted by 4 */
280 if (ch->flags & BERLIN2_AVPLL_BIT_QUIRK && ch->index == 0)
281 reg >>= 4;
282 divider = reg & VCO_SYNC1_MASK;
283
284 reg = readl_relaxed(ch->base + VCO_SYNC2n(ch->index));
285 freq *= reg & VCO_SYNC2_MASK;
286
287 /* Channel 8 has no dividers */
288 if (ch->index == 7)
289 goto skip_div;
290
291 /*
292 * HDMI divider start at VCO_CTRL11, bit 7; MSB is enable, lower 2 bit
293 * determine divider.
294 */
295 reg = readl_relaxed(ch->base + VCO_CTRL11) >> 7;
296 reg = (reg >> (ch->index * 3));
297 if (reg & BIT(2))
298 divider *= div_hdmi[reg & 0x3];
299
300 /*
301 * AV1 divider start at VCO_CTRL11, bit 28; MSB is enable, lower 2 bit
302 * determine divider.
303 */
304 if (ch->index == 0) {
305 reg = readl_relaxed(ch->base + VCO_CTRL11);
306 reg >>= 28;
307 } else {
308 reg = readl_relaxed(ch->base + VCO_CTRL12);
309 reg >>= (ch->index-1) * 3;
310 }
311 if (reg & BIT(2))
312 divider *= div_av1[reg & 0x3];
313
314 /*
315 * AV2 divider start at VCO_CTRL12, bit 18; each 7 bits wide,
316 * zero is not a valid value.
317 */
318 if (ch->index < 2) {
319 reg = readl_relaxed(ch->base + VCO_CTRL12);
320 reg >>= 18 + (ch->index * 7);
321 } else if (ch->index < 7) {
322 reg = readl_relaxed(ch->base + VCO_CTRL13);
323 reg >>= (ch->index - 2) * 7;
324 } else {
325 reg = readl_relaxed(ch->base + VCO_CTRL14);
326 }
327 div_av2 = reg & 0x7f;
328 if (div_av2)
329 divider *= div_av2;
330
331 /*
332 * AV3 divider start at VCO_CTRL14, bit 7; each 4 bits wide.
333 * AV2/AV3 form a fractional divider, where only specfic values for AV3
334 * are allowed. AV3 != 0 divides by AV2/2, AV3=0 is bypass.
335 */
336 if (ch->index < 6) {
337 reg = readl_relaxed(ch->base + VCO_CTRL14);
338 reg >>= 7 + (ch->index * 4);
339 } else {
340 reg = readl_relaxed(ch->base + VCO_CTRL15);
341 }
342 div_av3 = reg & 0xf;
343 if (div_av2 && div_av3)
344 freq *= 2;
345
346skip_div:
347 do_div(freq, divider);
348 return (unsigned long)freq;
349}
350
351static const struct clk_ops berlin2_avpll_channel_ops = {
352 .is_enabled = berlin2_avpll_channel_is_enabled,
353 .enable = berlin2_avpll_channel_enable,
354 .disable = berlin2_avpll_channel_disable,
355 .recalc_rate = berlin2_avpll_channel_recalc_rate,
356};
357
358/*
359 * Another nice quirk:
360 * On some production SoCs, AVPLL channels are scrambled with respect
361 * to the channel numbering in the registers but still referenced by
362 * their original channel numbers. We deal with it by having a flag
363 * and a translation table for the index.
364 */
365static const u8 quirk_index[] __initconst = { 0, 6, 5, 4, 3, 2, 1, 7 };
366
367struct clk * __init berlin2_avpll_channel_register(void __iomem *base,
368 const char *name, u8 index, const char *parent_name,
369 u8 ch_flags, unsigned long flags)
370{
371 struct berlin2_avpll_channel *ch;
372 struct clk_init_data init;
373
374 ch = kzalloc(sizeof(*ch), GFP_KERNEL);
375 if (!ch)
376 return ERR_PTR(-ENOMEM);
377
378 ch->base = base;
379 if (ch_flags & BERLIN2_AVPLL_SCRAMBLE_QUIRK)
380 ch->index = quirk_index[index];
381 else
382 ch->index = index;
383
384 ch->flags = ch_flags;
385 ch->hw.init = &init;
386 init.name = name;
387 init.ops = &berlin2_avpll_channel_ops;
388 init.parent_names = &parent_name;
389 init.num_parents = 1;
390 init.flags = flags;
391
392 return clk_register(NULL, &ch->hw);
393}
diff --git a/drivers/clk/berlin/berlin2-avpll.h b/drivers/clk/berlin/berlin2-avpll.h
new file mode 100644
index 000000000000..a37f5068d299
--- /dev/null
+++ b/drivers/clk/berlin/berlin2-avpll.h
@@ -0,0 +1,36 @@
1/*
2 * Copyright (c) 2014 Marvell Technology Group Ltd.
3 *
4 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
5 * Alexandre Belloni <alexandre.belloni@free-electrons.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef __BERLIN2_AVPLL_H
20#define __BERLIN2_AVPLL_H
21
22struct clk;
23
24#define BERLIN2_AVPLL_BIT_QUIRK BIT(0)
25#define BERLIN2_AVPLL_SCRAMBLE_QUIRK BIT(1)
26
27struct clk * __init
28berlin2_avpll_vco_register(void __iomem *base, const char *name,
29 const char *parent_name, u8 vco_flags, unsigned long flags);
30
31struct clk * __init
32berlin2_avpll_channel_register(void __iomem *base, const char *name,
33 u8 index, const char *parent_name, u8 ch_flags,
34 unsigned long flags);
35
36#endif /* __BERLIN2_AVPLL_H */
diff --git a/drivers/clk/berlin/berlin2-div.c b/drivers/clk/berlin/berlin2-div.c
new file mode 100644
index 000000000000..81ff97f8aa0b
--- /dev/null
+++ b/drivers/clk/berlin/berlin2-div.c
@@ -0,0 +1,265 @@
1/*
2 * Copyright (c) 2014 Marvell Technology Group Ltd.
3 *
4 * Alexandre Belloni <alexandre.belloni@free-electrons.com>
5 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#include <linux/bitops.h>
20#include <linux/clk-provider.h>
21#include <linux/of.h>
22#include <linux/of_address.h>
23#include <linux/slab.h>
24#include <linux/spinlock.h>
25
26#include "berlin2-div.h"
27
28/*
29 * Clock dividers in Berlin2 SoCs comprise a complex cell to select
30 * input pll and divider. The virtual structure as it is used in Marvell
31 * BSP code can be seen as:
32 *
33 * +---+
34 * pll0 --------------->| 0 | +---+
35 * +---+ |(B)|--+--------------->| 0 | +---+
36 * pll1.0 -->| 0 | +-->| 1 | | +--------+ |(E)|----->| 0 | +---+
37 * pll1.1 -->| 1 | | +---+ +-->|(C) 1:M |-->| 1 | |(F)|-->|(G)|->
38 * ... -->|(A)|--+ | +--------+ +---+ +-->| 1 | +---+
39 * ... -->| | +-->|(D) 1:3 |----------+ +---+
40 * pll1.N -->| N | +---------
41 * +---+
42 *
43 * (A) input pll clock mux controlled by <PllSelect[1:n]>
44 * (B) input pll bypass mux controlled by <PllSwitch>
45 * (C) programmable clock divider controlled by <Select[1:n]>
46 * (D) constant div-by-3 clock divider
47 * (E) programmable clock divider bypass controlled by <Switch>
48 * (F) constant div-by-3 clock mux controlled by <D3Switch>
49 * (G) clock gate controlled by <Enable>
50 *
51 * For whatever reason, above control signals come in two flavors:
52 * - single register dividers with all bits in one register
53 * - shared register dividers with bits spread over multiple registers
54 * (including signals for the same cell spread over consecutive registers)
55 *
56 * Also, clock gate and pll mux is not available on every div cell, so
57 * we have to deal with those, too. We reuse common clock composite driver
58 * for it.
59 */
60
61#define PLL_SELECT_MASK 0x7
62#define DIV_SELECT_MASK 0x7
63
64struct berlin2_div {
65 struct clk_hw hw;
66 void __iomem *base;
67 struct berlin2_div_map map;
68 spinlock_t *lock;
69};
70
71#define to_berlin2_div(hw) container_of(hw, struct berlin2_div, hw)
72
73static u8 clk_div[] = { 1, 2, 4, 6, 8, 12, 1, 1 };
74
75static int berlin2_div_is_enabled(struct clk_hw *hw)
76{
77 struct berlin2_div *div = to_berlin2_div(hw);
78 struct berlin2_div_map *map = &div->map;
79 u32 reg;
80
81 if (div->lock)
82 spin_lock(div->lock);
83
84 reg = readl_relaxed(div->base + map->gate_offs);
85 reg >>= map->gate_shift;
86
87 if (div->lock)
88 spin_unlock(div->lock);
89
90 return (reg & 0x1);
91}
92
93static int berlin2_div_enable(struct clk_hw *hw)
94{
95 struct berlin2_div *div = to_berlin2_div(hw);
96 struct berlin2_div_map *map = &div->map;
97 u32 reg;
98
99 if (div->lock)
100 spin_lock(div->lock);
101
102 reg = readl_relaxed(div->base + map->gate_offs);
103 reg |= BIT(map->gate_shift);
104 writel_relaxed(reg, div->base + map->gate_offs);
105
106 if (div->lock)
107 spin_unlock(div->lock);
108
109 return 0;
110}
111
112static void berlin2_div_disable(struct clk_hw *hw)
113{
114 struct berlin2_div *div = to_berlin2_div(hw);
115 struct berlin2_div_map *map = &div->map;
116 u32 reg;
117
118 if (div->lock)
119 spin_lock(div->lock);
120
121 reg = readl_relaxed(div->base + map->gate_offs);
122 reg &= ~BIT(map->gate_shift);
123 writel_relaxed(reg, div->base + map->gate_offs);
124
125 if (div->lock)
126 spin_unlock(div->lock);
127}
128
129static int berlin2_div_set_parent(struct clk_hw *hw, u8 index)
130{
131 struct berlin2_div *div = to_berlin2_div(hw);
132 struct berlin2_div_map *map = &div->map;
133 u32 reg;
134
135 if (div->lock)
136 spin_lock(div->lock);
137
138 /* index == 0 is PLL_SWITCH */
139 reg = readl_relaxed(div->base + map->pll_switch_offs);
140 if (index == 0)
141 reg &= ~BIT(map->pll_switch_shift);
142 else
143 reg |= BIT(map->pll_switch_shift);
144 writel_relaxed(reg, div->base + map->pll_switch_offs);
145
146 /* index > 0 is PLL_SELECT */
147 if (index > 0) {
148 reg = readl_relaxed(div->base + map->pll_select_offs);
149 reg &= ~(PLL_SELECT_MASK << map->pll_select_shift);
150 reg |= (index - 1) << map->pll_select_shift;
151 writel_relaxed(reg, div->base + map->pll_select_offs);
152 }
153
154 if (div->lock)
155 spin_unlock(div->lock);
156
157 return 0;
158}
159
160static u8 berlin2_div_get_parent(struct clk_hw *hw)
161{
162 struct berlin2_div *div = to_berlin2_div(hw);
163 struct berlin2_div_map *map = &div->map;
164 u32 reg;
165 u8 index = 0;
166
167 if (div->lock)
168 spin_lock(div->lock);
169
170 /* PLL_SWITCH == 0 is index 0 */
171 reg = readl_relaxed(div->base + map->pll_switch_offs);
172 reg &= BIT(map->pll_switch_shift);
173 if (reg) {
174 reg = readl_relaxed(div->base + map->pll_select_offs);
175 reg >>= map->pll_select_shift;
176 reg &= PLL_SELECT_MASK;
177 index = 1 + reg;
178 }
179
180 if (div->lock)
181 spin_unlock(div->lock);
182
183 return index;
184}
185
186static unsigned long berlin2_div_recalc_rate(struct clk_hw *hw,
187 unsigned long parent_rate)
188{
189 struct berlin2_div *div = to_berlin2_div(hw);
190 struct berlin2_div_map *map = &div->map;
191 u32 divsw, div3sw, divider = 1;
192
193 if (div->lock)
194 spin_lock(div->lock);
195
196 divsw = readl_relaxed(div->base + map->div_switch_offs) &
197 (1 << map->div_switch_shift);
198 div3sw = readl_relaxed(div->base + map->div3_switch_offs) &
199 (1 << map->div3_switch_shift);
200
201 /* constant divide-by-3 (dominant) */
202 if (div3sw != 0) {
203 divider = 3;
204 /* divider can be bypassed with DIV_SWITCH == 0 */
205 } else if (divsw == 0) {
206 divider = 1;
207 /* clock divider determined by DIV_SELECT */
208 } else {
209 u32 reg;
210 reg = readl_relaxed(div->base + map->div_select_offs);
211 reg >>= map->div_select_shift;
212 reg &= DIV_SELECT_MASK;
213 divider = clk_div[reg];
214 }
215
216 if (div->lock)
217 spin_unlock(div->lock);
218
219 return parent_rate / divider;
220}
221
222static const struct clk_ops berlin2_div_rate_ops = {
223 .recalc_rate = berlin2_div_recalc_rate,
224};
225
226static const struct clk_ops berlin2_div_gate_ops = {
227 .is_enabled = berlin2_div_is_enabled,
228 .enable = berlin2_div_enable,
229 .disable = berlin2_div_disable,
230};
231
232static const struct clk_ops berlin2_div_mux_ops = {
233 .set_parent = berlin2_div_set_parent,
234 .get_parent = berlin2_div_get_parent,
235};
236
237struct clk * __init
238berlin2_div_register(const struct berlin2_div_map *map,
239 void __iomem *base, const char *name, u8 div_flags,
240 const char **parent_names, int num_parents,
241 unsigned long flags, spinlock_t *lock)
242{
243 const struct clk_ops *mux_ops = &berlin2_div_mux_ops;
244 const struct clk_ops *rate_ops = &berlin2_div_rate_ops;
245 const struct clk_ops *gate_ops = &berlin2_div_gate_ops;
246 struct berlin2_div *div;
247
248 div = kzalloc(sizeof(*div), GFP_KERNEL);
249 if (!div)
250 return ERR_PTR(-ENOMEM);
251
252 /* copy div_map to allow __initconst */
253 memcpy(&div->map, map, sizeof(*map));
254 div->base = base;
255 div->lock = lock;
256
257 if ((div_flags & BERLIN2_DIV_HAS_GATE) == 0)
258 gate_ops = NULL;
259 if ((div_flags & BERLIN2_DIV_HAS_MUX) == 0)
260 mux_ops = NULL;
261
262 return clk_register_composite(NULL, name, parent_names, num_parents,
263 &div->hw, mux_ops, &div->hw, rate_ops,
264 &div->hw, gate_ops, flags);
265}
diff --git a/drivers/clk/berlin/berlin2-div.h b/drivers/clk/berlin/berlin2-div.h
new file mode 100644
index 000000000000..15e3384f3116
--- /dev/null
+++ b/drivers/clk/berlin/berlin2-div.h
@@ -0,0 +1,89 @@
1/*
2 * Copyright (c) 2014 Marvell Technology Group Ltd.
3 *
4 * Alexandre Belloni <alexandre.belloni@free-electrons.com>
5 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef __BERLIN2_DIV_H
20#define __BERLIN2_DIV_H
21
22struct clk;
23
24#define BERLIN2_DIV_HAS_GATE BIT(0)
25#define BERLIN2_DIV_HAS_MUX BIT(1)
26
27#define BERLIN2_PLL_SELECT(_off, _sh) \
28 .pll_select_offs = _off, \
29 .pll_select_shift = _sh
30
31#define BERLIN2_PLL_SWITCH(_off, _sh) \
32 .pll_switch_offs = _off, \
33 .pll_switch_shift = _sh
34
35#define BERLIN2_DIV_SELECT(_off, _sh) \
36 .div_select_offs = _off, \
37 .div_select_shift = _sh
38
39#define BERLIN2_DIV_SWITCH(_off, _sh) \
40 .div_switch_offs = _off, \
41 .div_switch_shift = _sh
42
43#define BERLIN2_DIV_D3SWITCH(_off, _sh) \
44 .div3_switch_offs = _off, \
45 .div3_switch_shift = _sh
46
47#define BERLIN2_DIV_GATE(_off, _sh) \
48 .gate_offs = _off, \
49 .gate_shift = _sh
50
51#define BERLIN2_SINGLE_DIV(_off) \
52 BERLIN2_DIV_GATE(_off, 0), \
53 BERLIN2_PLL_SELECT(_off, 1), \
54 BERLIN2_PLL_SWITCH(_off, 4), \
55 BERLIN2_DIV_SWITCH(_off, 5), \
56 BERLIN2_DIV_D3SWITCH(_off, 6), \
57 BERLIN2_DIV_SELECT(_off, 7)
58
59struct berlin2_div_map {
60 u16 pll_select_offs;
61 u16 pll_switch_offs;
62 u16 div_select_offs;
63 u16 div_switch_offs;
64 u16 div3_switch_offs;
65 u16 gate_offs;
66 u8 pll_select_shift;
67 u8 pll_switch_shift;
68 u8 div_select_shift;
69 u8 div_switch_shift;
70 u8 div3_switch_shift;
71 u8 gate_shift;
72};
73
74struct berlin2_div_data {
75 const char *name;
76 const u8 *parent_ids;
77 int num_parents;
78 unsigned long flags;
79 struct berlin2_div_map map;
80 u8 div_flags;
81};
82
83struct clk * __init
84berlin2_div_register(const struct berlin2_div_map *map,
85 void __iomem *base, const char *name, u8 div_flags,
86 const char **parent_names, int num_parents,
87 unsigned long flags, spinlock_t *lock);
88
89#endif /* __BERLIN2_DIV_H */
diff --git a/drivers/clk/berlin/berlin2-pll.c b/drivers/clk/berlin/berlin2-pll.c
new file mode 100644
index 000000000000..bdc506b03824
--- /dev/null
+++ b/drivers/clk/berlin/berlin2-pll.c
@@ -0,0 +1,117 @@
1/*
2 * Copyright (c) 2014 Marvell Technology Group Ltd.
3 *
4 * Alexandre Belloni <alexandre.belloni@free-electrons.com>
5 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#include <linux/clk-provider.h>
20#include <linux/io.h>
21#include <linux/kernel.h>
22#include <linux/of.h>
23#include <linux/of_address.h>
24#include <linux/slab.h>
25#include <asm/div64.h>
26
27#include "berlin2-div.h"
28
29struct berlin2_pll_map {
30 const u8 vcodiv[16];
31 u8 mult;
32 u8 fbdiv_shift;
33 u8 rfdiv_shift;
34 u8 divsel_shift;
35};
36
37struct berlin2_pll {
38 struct clk_hw hw;
39 void __iomem *base;
40 struct berlin2_pll_map map;
41};
42
43#define to_berlin2_pll(hw) container_of(hw, struct berlin2_pll, hw)
44
45#define SPLL_CTRL0 0x00
46#define SPLL_CTRL1 0x04
47#define SPLL_CTRL2 0x08
48#define SPLL_CTRL3 0x0c
49#define SPLL_CTRL4 0x10
50
51#define FBDIV_MASK 0x1ff
52#define RFDIV_MASK 0x1f
53#define DIVSEL_MASK 0xf
54
55/*
56 * The output frequency formula for the pll is:
57 * clkout = fbdiv / refdiv * parent / vcodiv
58 */
59static unsigned long
60berlin2_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
61{
62 struct berlin2_pll *pll = to_berlin2_pll(hw);
63 struct berlin2_pll_map *map = &pll->map;
64 u32 val, fbdiv, rfdiv, vcodivsel, vcodiv;
65 u64 rate = parent_rate;
66
67 val = readl_relaxed(pll->base + SPLL_CTRL0);
68 fbdiv = (val >> map->fbdiv_shift) & FBDIV_MASK;
69 rfdiv = (val >> map->rfdiv_shift) & RFDIV_MASK;
70 if (rfdiv == 0) {
71 pr_warn("%s has zero rfdiv\n", __clk_get_name(hw->clk));
72 rfdiv = 1;
73 }
74
75 val = readl_relaxed(pll->base + SPLL_CTRL1);
76 vcodivsel = (val >> map->divsel_shift) & DIVSEL_MASK;
77 vcodiv = map->vcodiv[vcodivsel];
78 if (vcodiv == 0) {
79 pr_warn("%s has zero vcodiv (index %d)\n",
80 __clk_get_name(hw->clk), vcodivsel);
81 vcodiv = 1;
82 }
83
84 rate *= fbdiv * map->mult;
85 do_div(rate, rfdiv * vcodiv);
86
87 return (unsigned long)rate;
88}
89
90static const struct clk_ops berlin2_pll_ops = {
91 .recalc_rate = berlin2_pll_recalc_rate,
92};
93
94struct clk * __init
95berlin2_pll_register(const struct berlin2_pll_map *map,
96 void __iomem *base, const char *name,
97 const char *parent_name, unsigned long flags)
98{
99 struct clk_init_data init;
100 struct berlin2_pll *pll;
101
102 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
103 if (!pll)
104 return ERR_PTR(-ENOMEM);
105
106 /* copy pll_map to allow __initconst */
107 memcpy(&pll->map, map, sizeof(*map));
108 pll->base = base;
109 pll->hw.init = &init;
110 init.name = name;
111 init.ops = &berlin2_pll_ops;
112 init.parent_names = &parent_name;
113 init.num_parents = 1;
114 init.flags = flags;
115
116 return clk_register(NULL, &pll->hw);
117}
diff --git a/drivers/clk/berlin/berlin2-pll.h b/drivers/clk/berlin/berlin2-pll.h
new file mode 100644
index 000000000000..8831ce27ac1e
--- /dev/null
+++ b/drivers/clk/berlin/berlin2-pll.h
@@ -0,0 +1,37 @@
1/*
2 * Copyright (c) 2014 Marvell Technology Group Ltd.
3 *
4 * Alexandre Belloni <alexandre.belloni@free-electrons.com>
5 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef __BERLIN2_PLL_H
20#define __BERLIN2_PLL_H
21
22struct clk;
23
24struct berlin2_pll_map {
25 const u8 vcodiv[16];
26 u8 mult;
27 u8 fbdiv_shift;
28 u8 rfdiv_shift;
29 u8 divsel_shift;
30};
31
32struct clk * __init
33berlin2_pll_register(const struct berlin2_pll_map *map,
34 void __iomem *base, const char *name,
35 const char *parent_name, unsigned long flags);
36
37#endif /* __BERLIN2_PLL_H */
diff --git a/drivers/clk/berlin/bg2.c b/drivers/clk/berlin/bg2.c
new file mode 100644
index 000000000000..515fb133495c
--- /dev/null
+++ b/drivers/clk/berlin/bg2.c
@@ -0,0 +1,691 @@
1/*
2 * Copyright (c) 2014 Marvell Technology Group Ltd.
3 *
4 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
5 * Alexandre Belloni <alexandre.belloni@free-electrons.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/clk.h>
21#include <linux/clk-provider.h>
22#include <linux/kernel.h>
23#include <linux/of.h>
24#include <linux/of_address.h>
25#include <linux/slab.h>
26
27#include <dt-bindings/clock/berlin2.h>
28
29#include "berlin2-avpll.h"
30#include "berlin2-div.h"
31#include "berlin2-pll.h"
32#include "common.h"
33
34#define REG_PINMUX0 0x0000
35#define REG_PINMUX1 0x0004
36#define REG_SYSPLLCTL0 0x0014
37#define REG_SYSPLLCTL4 0x0024
38#define REG_MEMPLLCTL0 0x0028
39#define REG_MEMPLLCTL4 0x0038
40#define REG_CPUPLLCTL0 0x003c
41#define REG_CPUPLLCTL4 0x004c
42#define REG_AVPLLCTL0 0x0050
43#define REG_AVPLLCTL31 0x00cc
44#define REG_AVPLLCTL62 0x0148
45#define REG_PLLSTATUS 0x014c
46#define REG_CLKENABLE 0x0150
47#define REG_CLKSELECT0 0x0154
48#define REG_CLKSELECT1 0x0158
49#define REG_CLKSELECT2 0x015c
50#define REG_CLKSELECT3 0x0160
51#define REG_CLKSWITCH0 0x0164
52#define REG_CLKSWITCH1 0x0168
53#define REG_RESET_TRIGGER 0x0178
54#define REG_RESET_STATUS0 0x017c
55#define REG_RESET_STATUS1 0x0180
56#define REG_SW_GENERIC0 0x0184
57#define REG_SW_GENERIC3 0x0190
58#define REG_PRODUCTID 0x01cc
59#define REG_PRODUCTID_EXT 0x01d0
60#define REG_GFX3DCORE_CLKCTL 0x022c
61#define REG_GFX3DSYS_CLKCTL 0x0230
62#define REG_ARC_CLKCTL 0x0234
63#define REG_VIP_CLKCTL 0x0238
64#define REG_SDIO0XIN_CLKCTL 0x023c
65#define REG_SDIO1XIN_CLKCTL 0x0240
66#define REG_GFX3DEXTRA_CLKCTL 0x0244
67#define REG_GFX3D_RESET 0x0248
68#define REG_GC360_CLKCTL 0x024c
69#define REG_SDIO_DLLMST_CLKCTL 0x0250
70
71/*
72 * BG2/BG2CD SoCs have the following audio/video I/O units:
73 *
74 * audiohd: HDMI TX audio
75 * audio0: 7.1ch TX
76 * audio1: 2ch TX
77 * audio2: 2ch RX
78 * audio3: SPDIF TX
79 * video0: HDMI video
80 * video1: Secondary video
81 * video2: SD auxiliary video
82 *
83 * There are no external audio clocks (ACLKI0, ACLKI1) and
84 * only one external video clock (VCLKI0).
85 *
86 * Currently missing bits and pieces:
87 * - audio_fast_pll is unknown
88 * - audiohd_pll is unknown
89 * - video0_pll is unknown
90 * - audio[023], audiohd parent pll is assumed to be audio_fast_pll
91 *
92 */
93
94#define MAX_CLKS 41
95static struct clk *clks[MAX_CLKS];
96static struct clk_onecell_data clk_data;
97static DEFINE_SPINLOCK(lock);
98static void __iomem *gbase;
99
100enum {
101 REFCLK, VIDEO_EXT0,
102 SYSPLL, MEMPLL, CPUPLL,
103 AVPLL_A1, AVPLL_A2, AVPLL_A3, AVPLL_A4,
104 AVPLL_A5, AVPLL_A6, AVPLL_A7, AVPLL_A8,
105 AVPLL_B1, AVPLL_B2, AVPLL_B3, AVPLL_B4,
106 AVPLL_B5, AVPLL_B6, AVPLL_B7, AVPLL_B8,
107 AUDIO1_PLL, AUDIO_FAST_PLL,
108 VIDEO0_PLL, VIDEO0_IN,
109 VIDEO1_PLL, VIDEO1_IN,
110 VIDEO2_PLL, VIDEO2_IN,
111};
112
113static const char *clk_names[] = {
114 [REFCLK] = "refclk",
115 [VIDEO_EXT0] = "video_ext0",
116 [SYSPLL] = "syspll",
117 [MEMPLL] = "mempll",
118 [CPUPLL] = "cpupll",
119 [AVPLL_A1] = "avpll_a1",
120 [AVPLL_A2] = "avpll_a2",
121 [AVPLL_A3] = "avpll_a3",
122 [AVPLL_A4] = "avpll_a4",
123 [AVPLL_A5] = "avpll_a5",
124 [AVPLL_A6] = "avpll_a6",
125 [AVPLL_A7] = "avpll_a7",
126 [AVPLL_A8] = "avpll_a8",
127 [AVPLL_B1] = "avpll_b1",
128 [AVPLL_B2] = "avpll_b2",
129 [AVPLL_B3] = "avpll_b3",
130 [AVPLL_B4] = "avpll_b4",
131 [AVPLL_B5] = "avpll_b5",
132 [AVPLL_B6] = "avpll_b6",
133 [AVPLL_B7] = "avpll_b7",
134 [AVPLL_B8] = "avpll_b8",
135 [AUDIO1_PLL] = "audio1_pll",
136 [AUDIO_FAST_PLL] = "audio_fast_pll",
137 [VIDEO0_PLL] = "video0_pll",
138 [VIDEO0_IN] = "video0_in",
139 [VIDEO1_PLL] = "video1_pll",
140 [VIDEO1_IN] = "video1_in",
141 [VIDEO2_PLL] = "video2_pll",
142 [VIDEO2_IN] = "video2_in",
143};
144
145static const struct berlin2_pll_map bg2_pll_map __initconst = {
146 .vcodiv = {10, 15, 20, 25, 30, 40, 50, 60, 80},
147 .mult = 10,
148 .fbdiv_shift = 6,
149 .rfdiv_shift = 1,
150 .divsel_shift = 7,
151};
152
153static const u8 default_parent_ids[] = {
154 SYSPLL, AVPLL_B4, AVPLL_A5, AVPLL_B6, AVPLL_B7, SYSPLL
155};
156
157static const struct berlin2_div_data bg2_divs[] __initconst = {
158 {
159 .name = "sys",
160 .parent_ids = (const u8 []){
161 SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL
162 },
163 .num_parents = 6,
164 .map = {
165 BERLIN2_DIV_GATE(REG_CLKENABLE, 0),
166 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 0),
167 BERLIN2_DIV_SELECT(REG_CLKSELECT0, 3),
168 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 3),
169 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 4),
170 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 5),
171 },
172 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
173 .flags = CLK_IGNORE_UNUSED,
174 },
175 {
176 .name = "cpu",
177 .parent_ids = (const u8 []){
178 CPUPLL, MEMPLL, MEMPLL, MEMPLL, MEMPLL
179 },
180 .num_parents = 5,
181 .map = {
182 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 6),
183 BERLIN2_DIV_SELECT(REG_CLKSELECT0, 9),
184 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 6),
185 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 7),
186 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 8),
187 },
188 .div_flags = BERLIN2_DIV_HAS_MUX,
189 .flags = 0,
190 },
191 {
192 .name = "drmfigo",
193 .parent_ids = default_parent_ids,
194 .num_parents = ARRAY_SIZE(default_parent_ids),
195 .map = {
196 BERLIN2_DIV_GATE(REG_CLKENABLE, 16),
197 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 17),
198 BERLIN2_DIV_SELECT(REG_CLKSELECT0, 20),
199 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 12),
200 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 13),
201 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 14),
202 },
203 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
204 .flags = 0,
205 },
206 {
207 .name = "cfg",
208 .parent_ids = default_parent_ids,
209 .num_parents = ARRAY_SIZE(default_parent_ids),
210 .map = {
211 BERLIN2_DIV_GATE(REG_CLKENABLE, 1),
212 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 23),
213 BERLIN2_DIV_SELECT(REG_CLKSELECT0, 26),
214 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 15),
215 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 16),
216 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 17),
217 },
218 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
219 .flags = 0,
220 },
221 {
222 .name = "gfx",
223 .parent_ids = default_parent_ids,
224 .num_parents = ARRAY_SIZE(default_parent_ids),
225 .map = {
226 BERLIN2_DIV_GATE(REG_CLKENABLE, 4),
227 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 29),
228 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 0),
229 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 18),
230 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 19),
231 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 20),
232 },
233 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
234 .flags = 0,
235 },
236 {
237 .name = "zsp",
238 .parent_ids = default_parent_ids,
239 .num_parents = ARRAY_SIZE(default_parent_ids),
240 .map = {
241 BERLIN2_DIV_GATE(REG_CLKENABLE, 5),
242 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 3),
243 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 6),
244 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 21),
245 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 22),
246 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 23),
247 },
248 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
249 .flags = 0,
250 },
251 {
252 .name = "perif",
253 .parent_ids = default_parent_ids,
254 .num_parents = ARRAY_SIZE(default_parent_ids),
255 .map = {
256 BERLIN2_DIV_GATE(REG_CLKENABLE, 6),
257 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 9),
258 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 12),
259 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 24),
260 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 25),
261 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 26),
262 },
263 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
264 .flags = CLK_IGNORE_UNUSED,
265 },
266 {
267 .name = "pcube",
268 .parent_ids = default_parent_ids,
269 .num_parents = ARRAY_SIZE(default_parent_ids),
270 .map = {
271 BERLIN2_DIV_GATE(REG_CLKENABLE, 2),
272 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 15),
273 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 18),
274 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 27),
275 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 28),
276 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 29),
277 },
278 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
279 .flags = 0,
280 },
281 {
282 .name = "vscope",
283 .parent_ids = default_parent_ids,
284 .num_parents = ARRAY_SIZE(default_parent_ids),
285 .map = {
286 BERLIN2_DIV_GATE(REG_CLKENABLE, 3),
287 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 21),
288 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 24),
289 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 30),
290 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 31),
291 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 0),
292 },
293 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
294 .flags = 0,
295 },
296 {
297 .name = "nfc_ecc",
298 .parent_ids = default_parent_ids,
299 .num_parents = ARRAY_SIZE(default_parent_ids),
300 .map = {
301 BERLIN2_DIV_GATE(REG_CLKENABLE, 18),
302 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 27),
303 BERLIN2_DIV_SELECT(REG_CLKSELECT2, 0),
304 BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 1),
305 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 2),
306 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 3),
307 },
308 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
309 .flags = 0,
310 },
311 {
312 .name = "vpp",
313 .parent_ids = default_parent_ids,
314 .num_parents = ARRAY_SIZE(default_parent_ids),
315 .map = {
316 BERLIN2_DIV_GATE(REG_CLKENABLE, 21),
317 BERLIN2_PLL_SELECT(REG_CLKSELECT2, 3),
318 BERLIN2_DIV_SELECT(REG_CLKSELECT2, 6),
319 BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 4),
320 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 5),
321 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 6),
322 },
323 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
324 .flags = 0,
325 },
326 {
327 .name = "app",
328 .parent_ids = default_parent_ids,
329 .num_parents = ARRAY_SIZE(default_parent_ids),
330 .map = {
331 BERLIN2_DIV_GATE(REG_CLKENABLE, 20),
332 BERLIN2_PLL_SELECT(REG_CLKSELECT2, 9),
333 BERLIN2_DIV_SELECT(REG_CLKSELECT2, 12),
334 BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 7),
335 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 8),
336 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 9),
337 },
338 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
339 .flags = 0,
340 },
341 {
342 .name = "audio0",
343 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
344 .num_parents = 1,
345 .map = {
346 BERLIN2_DIV_GATE(REG_CLKENABLE, 22),
347 BERLIN2_DIV_SELECT(REG_CLKSELECT2, 17),
348 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 10),
349 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 11),
350 },
351 .div_flags = BERLIN2_DIV_HAS_GATE,
352 .flags = 0,
353 },
354 {
355 .name = "audio2",
356 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
357 .num_parents = 1,
358 .map = {
359 BERLIN2_DIV_GATE(REG_CLKENABLE, 24),
360 BERLIN2_DIV_SELECT(REG_CLKSELECT2, 20),
361 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 14),
362 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 15),
363 },
364 .div_flags = BERLIN2_DIV_HAS_GATE,
365 .flags = 0,
366 },
367 {
368 .name = "audio3",
369 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
370 .num_parents = 1,
371 .map = {
372 BERLIN2_DIV_GATE(REG_CLKENABLE, 25),
373 BERLIN2_DIV_SELECT(REG_CLKSELECT2, 23),
374 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 16),
375 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 17),
376 },
377 .div_flags = BERLIN2_DIV_HAS_GATE,
378 .flags = 0,
379 },
380 {
381 .name = "audio1",
382 .parent_ids = (const u8 []){ AUDIO1_PLL },
383 .num_parents = 1,
384 .map = {
385 BERLIN2_DIV_GATE(REG_CLKENABLE, 23),
386 BERLIN2_DIV_SELECT(REG_CLKSELECT3, 0),
387 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 12),
388 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 13),
389 },
390 .div_flags = BERLIN2_DIV_HAS_GATE,
391 .flags = 0,
392 },
393 {
394 .name = "gfx3d_core",
395 .parent_ids = default_parent_ids,
396 .num_parents = ARRAY_SIZE(default_parent_ids),
397 .map = {
398 BERLIN2_SINGLE_DIV(REG_GFX3DCORE_CLKCTL),
399 },
400 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
401 .flags = 0,
402 },
403 {
404 .name = "gfx3d_sys",
405 .parent_ids = default_parent_ids,
406 .num_parents = ARRAY_SIZE(default_parent_ids),
407 .map = {
408 BERLIN2_SINGLE_DIV(REG_GFX3DSYS_CLKCTL),
409 },
410 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
411 .flags = 0,
412 },
413 {
414 .name = "arc",
415 .parent_ids = default_parent_ids,
416 .num_parents = ARRAY_SIZE(default_parent_ids),
417 .map = {
418 BERLIN2_SINGLE_DIV(REG_ARC_CLKCTL),
419 },
420 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
421 .flags = 0,
422 },
423 {
424 .name = "vip",
425 .parent_ids = default_parent_ids,
426 .num_parents = ARRAY_SIZE(default_parent_ids),
427 .map = {
428 BERLIN2_SINGLE_DIV(REG_VIP_CLKCTL),
429 },
430 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
431 .flags = 0,
432 },
433 {
434 .name = "sdio0xin",
435 .parent_ids = default_parent_ids,
436 .num_parents = ARRAY_SIZE(default_parent_ids),
437 .map = {
438 BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL),
439 },
440 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
441 .flags = 0,
442 },
443 {
444 .name = "sdio1xin",
445 .parent_ids = default_parent_ids,
446 .num_parents = ARRAY_SIZE(default_parent_ids),
447 .map = {
448 BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL),
449 },
450 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
451 .flags = 0,
452 },
453 {
454 .name = "gfx3d_extra",
455 .parent_ids = default_parent_ids,
456 .num_parents = ARRAY_SIZE(default_parent_ids),
457 .map = {
458 BERLIN2_SINGLE_DIV(REG_GFX3DEXTRA_CLKCTL),
459 },
460 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
461 .flags = 0,
462 },
463 {
464 .name = "gc360",
465 .parent_ids = default_parent_ids,
466 .num_parents = ARRAY_SIZE(default_parent_ids),
467 .map = {
468 BERLIN2_SINGLE_DIV(REG_GC360_CLKCTL),
469 },
470 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
471 .flags = 0,
472 },
473 {
474 .name = "sdio_dllmst",
475 .parent_ids = default_parent_ids,
476 .num_parents = ARRAY_SIZE(default_parent_ids),
477 .map = {
478 BERLIN2_SINGLE_DIV(REG_SDIO_DLLMST_CLKCTL),
479 },
480 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
481 .flags = 0,
482 },
483};
484
485static const struct berlin2_gate_data bg2_gates[] __initconst = {
486 { "geth0", "perif", 7 },
487 { "geth1", "perif", 8 },
488 { "sata", "perif", 9 },
489 { "ahbapb", "perif", 10, CLK_IGNORE_UNUSED },
490 { "usb0", "perif", 11 },
491 { "usb1", "perif", 12 },
492 { "pbridge", "perif", 13, CLK_IGNORE_UNUSED },
493 { "sdio0", "perif", 14, CLK_IGNORE_UNUSED },
494 { "sdio1", "perif", 15, CLK_IGNORE_UNUSED },
495 { "nfc", "perif", 17 },
496 { "smemc", "perif", 19 },
497 { "audiohd", "audiohd_pll", 26 },
498 { "video0", "video0_in", 27 },
499 { "video1", "video1_in", 28 },
500 { "video2", "video2_in", 29 },
501};
502
503static void __init berlin2_clock_setup(struct device_node *np)
504{
505 const char *parent_names[9];
506 struct clk *clk;
507 u8 avpll_flags = 0;
508 int n;
509
510 gbase = of_iomap(np, 0);
511 if (!gbase)
512 return;
513
514 /* overwrite default clock names with DT provided ones */
515 clk = of_clk_get_by_name(np, clk_names[REFCLK]);
516 if (!IS_ERR(clk)) {
517 clk_names[REFCLK] = __clk_get_name(clk);
518 clk_put(clk);
519 }
520
521 clk = of_clk_get_by_name(np, clk_names[VIDEO_EXT0]);
522 if (!IS_ERR(clk)) {
523 clk_names[VIDEO_EXT0] = __clk_get_name(clk);
524 clk_put(clk);
525 }
526
527 /* simple register PLLs */
528 clk = berlin2_pll_register(&bg2_pll_map, gbase + REG_SYSPLLCTL0,
529 clk_names[SYSPLL], clk_names[REFCLK], 0);
530 if (IS_ERR(clk))
531 goto bg2_fail;
532
533 clk = berlin2_pll_register(&bg2_pll_map, gbase + REG_MEMPLLCTL0,
534 clk_names[MEMPLL], clk_names[REFCLK], 0);
535 if (IS_ERR(clk))
536 goto bg2_fail;
537
538 clk = berlin2_pll_register(&bg2_pll_map, gbase + REG_CPUPLLCTL0,
539 clk_names[CPUPLL], clk_names[REFCLK], 0);
540 if (IS_ERR(clk))
541 goto bg2_fail;
542
543 if (of_device_is_compatible(np, "marvell,berlin2-global-register"))
544 avpll_flags |= BERLIN2_AVPLL_SCRAMBLE_QUIRK;
545
546 /* audio/video VCOs */
547 clk = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL0, "avpll_vcoA",
548 clk_names[REFCLK], avpll_flags, 0);
549 if (IS_ERR(clk))
550 goto bg2_fail;
551
552 for (n = 0; n < 8; n++) {
553 clk = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL0,
554 clk_names[AVPLL_A1 + n], n, "avpll_vcoA",
555 avpll_flags, 0);
556 if (IS_ERR(clk))
557 goto bg2_fail;
558 }
559
560 clk = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL31, "avpll_vcoB",
561 clk_names[REFCLK], BERLIN2_AVPLL_BIT_QUIRK |
562 avpll_flags, 0);
563 if (IS_ERR(clk))
564 goto bg2_fail;
565
566 for (n = 0; n < 8; n++) {
567 clk = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL31,
568 clk_names[AVPLL_B1 + n], n, "avpll_vcoB",
569 BERLIN2_AVPLL_BIT_QUIRK | avpll_flags, 0);
570 if (IS_ERR(clk))
571 goto bg2_fail;
572 }
573
574 /* reference clock bypass switches */
575 parent_names[0] = clk_names[SYSPLL];
576 parent_names[1] = clk_names[REFCLK];
577 clk = clk_register_mux(NULL, "syspll_byp", parent_names, 2,
578 0, gbase + REG_CLKSWITCH0, 0, 1, 0, &lock);
579 if (IS_ERR(clk))
580 goto bg2_fail;
581 clk_names[SYSPLL] = __clk_get_name(clk);
582
583 parent_names[0] = clk_names[MEMPLL];
584 parent_names[1] = clk_names[REFCLK];
585 clk = clk_register_mux(NULL, "mempll_byp", parent_names, 2,
586 0, gbase + REG_CLKSWITCH0, 1, 1, 0, &lock);
587 if (IS_ERR(clk))
588 goto bg2_fail;
589 clk_names[MEMPLL] = __clk_get_name(clk);
590
591 parent_names[0] = clk_names[CPUPLL];
592 parent_names[1] = clk_names[REFCLK];
593 clk = clk_register_mux(NULL, "cpupll_byp", parent_names, 2,
594 0, gbase + REG_CLKSWITCH0, 2, 1, 0, &lock);
595 if (IS_ERR(clk))
596 goto bg2_fail;
597 clk_names[CPUPLL] = __clk_get_name(clk);
598
599 /* clock muxes */
600 parent_names[0] = clk_names[AVPLL_B3];
601 parent_names[1] = clk_names[AVPLL_A3];
602 clk = clk_register_mux(NULL, clk_names[AUDIO1_PLL], parent_names, 2,
603 0, gbase + REG_CLKSELECT2, 29, 1, 0, &lock);
604 if (IS_ERR(clk))
605 goto bg2_fail;
606
607 parent_names[0] = clk_names[VIDEO0_PLL];
608 parent_names[1] = clk_names[VIDEO_EXT0];
609 clk = clk_register_mux(NULL, clk_names[VIDEO0_IN], parent_names, 2,
610 0, gbase + REG_CLKSELECT3, 4, 1, 0, &lock);
611 if (IS_ERR(clk))
612 goto bg2_fail;
613
614 parent_names[0] = clk_names[VIDEO1_PLL];
615 parent_names[1] = clk_names[VIDEO_EXT0];
616 clk = clk_register_mux(NULL, clk_names[VIDEO1_IN], parent_names, 2,
617 0, gbase + REG_CLKSELECT3, 6, 1, 0, &lock);
618 if (IS_ERR(clk))
619 goto bg2_fail;
620
621 parent_names[0] = clk_names[AVPLL_A2];
622 parent_names[1] = clk_names[AVPLL_B2];
623 clk = clk_register_mux(NULL, clk_names[VIDEO1_PLL], parent_names, 2,
624 0, gbase + REG_CLKSELECT3, 7, 1, 0, &lock);
625 if (IS_ERR(clk))
626 goto bg2_fail;
627
628 parent_names[0] = clk_names[VIDEO2_PLL];
629 parent_names[1] = clk_names[VIDEO_EXT0];
630 clk = clk_register_mux(NULL, clk_names[VIDEO2_IN], parent_names, 2,
631 0, gbase + REG_CLKSELECT3, 9, 1, 0, &lock);
632 if (IS_ERR(clk))
633 goto bg2_fail;
634
635 parent_names[0] = clk_names[AVPLL_B1];
636 parent_names[1] = clk_names[AVPLL_A5];
637 clk = clk_register_mux(NULL, clk_names[VIDEO2_PLL], parent_names, 2,
638 0, gbase + REG_CLKSELECT3, 10, 1, 0, &lock);
639 if (IS_ERR(clk))
640 goto bg2_fail;
641
642 /* clock divider cells */
643 for (n = 0; n < ARRAY_SIZE(bg2_divs); n++) {
644 const struct berlin2_div_data *dd = &bg2_divs[n];
645 int k;
646
647 for (k = 0; k < dd->num_parents; k++)
648 parent_names[k] = clk_names[dd->parent_ids[k]];
649
650 clks[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
651 dd->name, dd->div_flags, parent_names,
652 dd->num_parents, dd->flags, &lock);
653 }
654
655 /* clock gate cells */
656 for (n = 0; n < ARRAY_SIZE(bg2_gates); n++) {
657 const struct berlin2_gate_data *gd = &bg2_gates[n];
658
659 clks[CLKID_GETH0 + n] = clk_register_gate(NULL, gd->name,
660 gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
661 gd->bit_idx, 0, &lock);
662 }
663
664 /* twdclk is derived from cpu/3 */
665 clks[CLKID_TWD] =
666 clk_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
667
668 /* check for errors on leaf clocks */
669 for (n = 0; n < MAX_CLKS; n++) {
670 if (!IS_ERR(clks[n]))
671 continue;
672
673 pr_err("%s: Unable to register leaf clock %d\n",
674 np->full_name, n);
675 goto bg2_fail;
676 }
677
678 /* register clk-provider */
679 clk_data.clks = clks;
680 clk_data.clk_num = MAX_CLKS;
681 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
682
683 return;
684
685bg2_fail:
686 iounmap(gbase);
687}
688CLK_OF_DECLARE(berlin2_clock, "marvell,berlin2-chip-ctrl",
689 berlin2_clock_setup);
690CLK_OF_DECLARE(berlin2cd_clock, "marvell,berlin2cd-chip-ctrl",
691 berlin2_clock_setup);
diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c
new file mode 100644
index 000000000000..21784e4eb3f0
--- /dev/null
+++ b/drivers/clk/berlin/bg2q.c
@@ -0,0 +1,389 @@
1/*
2 * Copyright (c) 2014 Marvell Technology Group Ltd.
3 *
4 * Alexandre Belloni <alexandre.belloni@free-electrons.com>
5 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/clk.h>
21#include <linux/clk-provider.h>
22#include <linux/kernel.h>
23#include <linux/of.h>
24#include <linux/of_address.h>
25#include <linux/slab.h>
26
27#include <dt-bindings/clock/berlin2q.h>
28
29#include "berlin2-div.h"
30#include "berlin2-pll.h"
31#include "common.h"
32
33#define REG_PINMUX0 0x0018
34#define REG_PINMUX5 0x002c
35#define REG_SYSPLLCTL0 0x0030
36#define REG_SYSPLLCTL4 0x0040
37#define REG_CLKENABLE 0x00e8
38#define REG_CLKSELECT0 0x00ec
39#define REG_CLKSELECT1 0x00f0
40#define REG_CLKSELECT2 0x00f4
41#define REG_CLKSWITCH0 0x00f8
42#define REG_CLKSWITCH1 0x00fc
43#define REG_SW_GENERIC0 0x0110
44#define REG_SW_GENERIC3 0x011c
45#define REG_SDIO0XIN_CLKCTL 0x0158
46#define REG_SDIO1XIN_CLKCTL 0x015c
47
48#define MAX_CLKS 27
49static struct clk *clks[MAX_CLKS];
50static struct clk_onecell_data clk_data;
51static DEFINE_SPINLOCK(lock);
52static void __iomem *gbase;
53static void __iomem *cpupll_base;
54
55enum {
56 REFCLK,
57 SYSPLL, CPUPLL,
58 AVPLL_B1, AVPLL_B2, AVPLL_B3, AVPLL_B4,
59 AVPLL_B5, AVPLL_B6, AVPLL_B7, AVPLL_B8,
60};
61
62static const char *clk_names[] = {
63 [REFCLK] = "refclk",
64 [SYSPLL] = "syspll",
65 [CPUPLL] = "cpupll",
66 [AVPLL_B1] = "avpll_b1",
67 [AVPLL_B2] = "avpll_b2",
68 [AVPLL_B3] = "avpll_b3",
69 [AVPLL_B4] = "avpll_b4",
70 [AVPLL_B5] = "avpll_b5",
71 [AVPLL_B6] = "avpll_b6",
72 [AVPLL_B7] = "avpll_b7",
73 [AVPLL_B8] = "avpll_b8",
74};
75
76static const struct berlin2_pll_map bg2q_pll_map __initconst = {
77 .vcodiv = {1, 0, 2, 0, 3, 4, 0, 6, 8},
78 .mult = 1,
79 .fbdiv_shift = 7,
80 .rfdiv_shift = 2,
81 .divsel_shift = 9,
82};
83
84static const u8 default_parent_ids[] = {
85 SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL
86};
87
88static const struct berlin2_div_data bg2q_divs[] __initconst = {
89 {
90 .name = "sys",
91 .parent_ids = default_parent_ids,
92 .num_parents = ARRAY_SIZE(default_parent_ids),
93 .map = {
94 BERLIN2_DIV_GATE(REG_CLKENABLE, 0),
95 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 0),
96 BERLIN2_DIV_SELECT(REG_CLKSELECT0, 3),
97 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 3),
98 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 4),
99 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 5),
100 },
101 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
102 .flags = CLK_IGNORE_UNUSED,
103 },
104 {
105 .name = "drmfigo",
106 .parent_ids = default_parent_ids,
107 .num_parents = ARRAY_SIZE(default_parent_ids),
108 .map = {
109 BERLIN2_DIV_GATE(REG_CLKENABLE, 17),
110 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 6),
111 BERLIN2_DIV_SELECT(REG_CLKSELECT0, 9),
112 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 6),
113 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 7),
114 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 8),
115 },
116 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
117 .flags = 0,
118 },
119 {
120 .name = "cfg",
121 .parent_ids = default_parent_ids,
122 .num_parents = ARRAY_SIZE(default_parent_ids),
123 .map = {
124 BERLIN2_DIV_GATE(REG_CLKENABLE, 1),
125 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 12),
126 BERLIN2_DIV_SELECT(REG_CLKSELECT0, 15),
127 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 9),
128 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 10),
129 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 11),
130 },
131 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
132 .flags = 0,
133 },
134 {
135 .name = "gfx2d",
136 .parent_ids = default_parent_ids,
137 .num_parents = ARRAY_SIZE(default_parent_ids),
138 .map = {
139 BERLIN2_DIV_GATE(REG_CLKENABLE, 4),
140 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 18),
141 BERLIN2_DIV_SELECT(REG_CLKSELECT0, 21),
142 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 12),
143 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 13),
144 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 14),
145 },
146 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
147 .flags = 0,
148 },
149 {
150 .name = "zsp",
151 .parent_ids = default_parent_ids,
152 .num_parents = ARRAY_SIZE(default_parent_ids),
153 .map = {
154 BERLIN2_DIV_GATE(REG_CLKENABLE, 6),
155 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 24),
156 BERLIN2_DIV_SELECT(REG_CLKSELECT0, 27),
157 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 15),
158 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 16),
159 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 17),
160 },
161 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
162 .flags = 0,
163 },
164 {
165 .name = "perif",
166 .parent_ids = default_parent_ids,
167 .num_parents = ARRAY_SIZE(default_parent_ids),
168 .map = {
169 BERLIN2_DIV_GATE(REG_CLKENABLE, 7),
170 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 0),
171 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 3),
172 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 18),
173 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 19),
174 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 20),
175 },
176 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
177 .flags = CLK_IGNORE_UNUSED,
178 },
179 {
180 .name = "pcube",
181 .parent_ids = default_parent_ids,
182 .num_parents = ARRAY_SIZE(default_parent_ids),
183 .map = {
184 BERLIN2_DIV_GATE(REG_CLKENABLE, 2),
185 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 6),
186 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 9),
187 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 21),
188 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 22),
189 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 23),
190 },
191 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
192 .flags = 0,
193 },
194 {
195 .name = "vscope",
196 .parent_ids = default_parent_ids,
197 .num_parents = ARRAY_SIZE(default_parent_ids),
198 .map = {
199 BERLIN2_DIV_GATE(REG_CLKENABLE, 3),
200 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 12),
201 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 15),
202 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 24),
203 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 25),
204 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 26),
205 },
206 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
207 .flags = 0,
208 },
209 {
210 .name = "nfc_ecc",
211 .parent_ids = default_parent_ids,
212 .num_parents = ARRAY_SIZE(default_parent_ids),
213 .map = {
214 BERLIN2_DIV_GATE(REG_CLKENABLE, 19),
215 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 18),
216 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 21),
217 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 27),
218 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 28),
219 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 29),
220 },
221 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
222 .flags = 0,
223 },
224 {
225 .name = "vpp",
226 .parent_ids = default_parent_ids,
227 .num_parents = ARRAY_SIZE(default_parent_ids),
228 .map = {
229 BERLIN2_DIV_GATE(REG_CLKENABLE, 21),
230 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 24),
231 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 27),
232 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 30),
233 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 31),
234 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 0),
235 },
236 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
237 .flags = 0,
238 },
239 {
240 .name = "app",
241 .parent_ids = default_parent_ids,
242 .num_parents = ARRAY_SIZE(default_parent_ids),
243 .map = {
244 BERLIN2_DIV_GATE(REG_CLKENABLE, 20),
245 BERLIN2_PLL_SELECT(REG_CLKSELECT2, 0),
246 BERLIN2_DIV_SELECT(REG_CLKSELECT2, 3),
247 BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 1),
248 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 2),
249 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 3),
250 },
251 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
252 .flags = 0,
253 },
254 {
255 .name = "sdio0xin",
256 .parent_ids = default_parent_ids,
257 .num_parents = ARRAY_SIZE(default_parent_ids),
258 .map = {
259 BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL),
260 },
261 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
262 .flags = 0,
263 },
264 {
265 .name = "sdio1xin",
266 .parent_ids = default_parent_ids,
267 .num_parents = ARRAY_SIZE(default_parent_ids),
268 .map = {
269 BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL),
270 },
271 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
272 .flags = 0,
273 },
274};
275
276static const struct berlin2_gate_data bg2q_gates[] __initconst = {
277 { "gfx2daxi", "perif", 5 },
278 { "geth0", "perif", 8 },
279 { "sata", "perif", 9 },
280 { "ahbapb", "perif", 10, CLK_IGNORE_UNUSED },
281 { "usb0", "perif", 11 },
282 { "usb1", "perif", 12 },
283 { "usb2", "perif", 13 },
284 { "usb3", "perif", 14 },
285 { "pbridge", "perif", 15, CLK_IGNORE_UNUSED },
286 { "sdio", "perif", 16, CLK_IGNORE_UNUSED },
287 { "nfc", "perif", 18 },
288 { "smemc", "perif", 19 },
289 { "pcie", "perif", 22 },
290};
291
292static void __init berlin2q_clock_setup(struct device_node *np)
293{
294 const char *parent_names[9];
295 struct clk *clk;
296 int n;
297
298 gbase = of_iomap(np, 0);
299 if (!gbase) {
300 pr_err("%s: Unable to map global base\n", np->full_name);
301 return;
302 }
303
304 /* BG2Q CPU PLL is not part of global registers */
305 cpupll_base = of_iomap(np, 1);
306 if (!cpupll_base) {
307 pr_err("%s: Unable to map cpupll base\n", np->full_name);
308 iounmap(gbase);
309 return;
310 }
311
312 /* overwrite default clock names with DT provided ones */
313 clk = of_clk_get_by_name(np, clk_names[REFCLK]);
314 if (!IS_ERR(clk)) {
315 clk_names[REFCLK] = __clk_get_name(clk);
316 clk_put(clk);
317 }
318
319 /* simple register PLLs */
320 clk = berlin2_pll_register(&bg2q_pll_map, gbase + REG_SYSPLLCTL0,
321 clk_names[SYSPLL], clk_names[REFCLK], 0);
322 if (IS_ERR(clk))
323 goto bg2q_fail;
324
325 clk = berlin2_pll_register(&bg2q_pll_map, cpupll_base,
326 clk_names[CPUPLL], clk_names[REFCLK], 0);
327 if (IS_ERR(clk))
328 goto bg2q_fail;
329
330 /* TODO: add BG2Q AVPLL */
331
332 /*
333 * TODO: add reference clock bypass switches:
334 * memPLLSWBypass, cpuPLLSWBypass, and sysPLLSWBypass
335 */
336
337 /* clock divider cells */
338 for (n = 0; n < ARRAY_SIZE(bg2q_divs); n++) {
339 const struct berlin2_div_data *dd = &bg2q_divs[n];
340 int k;
341
342 for (k = 0; k < dd->num_parents; k++)
343 parent_names[k] = clk_names[dd->parent_ids[k]];
344
345 clks[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
346 dd->name, dd->div_flags, parent_names,
347 dd->num_parents, dd->flags, &lock);
348 }
349
350 /* clock gate cells */
351 for (n = 0; n < ARRAY_SIZE(bg2q_gates); n++) {
352 const struct berlin2_gate_data *gd = &bg2q_gates[n];
353
354 clks[CLKID_GFX2DAXI + n] = clk_register_gate(NULL, gd->name,
355 gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
356 gd->bit_idx, 0, &lock);
357 }
358
359 /*
360 * twdclk is derived from cpu/3
361 * TODO: use cpupll until cpuclk is not available
362 */
363 clks[CLKID_TWD] =
364 clk_register_fixed_factor(NULL, "twd", clk_names[CPUPLL],
365 0, 1, 3);
366
367 /* check for errors on leaf clocks */
368 for (n = 0; n < MAX_CLKS; n++) {
369 if (!IS_ERR(clks[n]))
370 continue;
371
372 pr_err("%s: Unable to register leaf clock %d\n",
373 np->full_name, n);
374 goto bg2q_fail;
375 }
376
377 /* register clk-provider */
378 clk_data.clks = clks;
379 clk_data.clk_num = MAX_CLKS;
380 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
381
382 return;
383
384bg2q_fail:
385 iounmap(cpupll_base);
386 iounmap(gbase);
387}
388CLK_OF_DECLARE(berlin2q_clock, "marvell,berlin2q-chip-ctrl",
389 berlin2q_clock_setup);
diff --git a/drivers/clk/berlin/common.h b/drivers/clk/berlin/common.h
new file mode 100644
index 000000000000..bc68a14c4550
--- /dev/null
+++ b/drivers/clk/berlin/common.h
@@ -0,0 +1,29 @@
1/*
2 * Copyright (c) 2014 Marvell Technology Group Ltd.
3 *
4 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
5 * Alexandre Belloni <alexandre.belloni@free-electrons.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef __BERLIN2_COMMON_H
20#define __BERLIN2_COMMON_H
21
22struct berlin2_gate_data {
23 const char *name;
24 const char *parent_name;
25 u8 bit_idx;
26 unsigned long flags;
27};
28
29#endif /* BERLIN2_COMMON_H */
diff --git a/drivers/clk/clk-axm5516.c b/drivers/clk/clk-axm5516.c
new file mode 100644
index 000000000000..d2f1e119b450
--- /dev/null
+++ b/drivers/clk/clk-axm5516.c
@@ -0,0 +1,615 @@
1/*
2 * drivers/clk/clk-axm5516.c
3 *
4 * Provides clock implementations for three different types of clock devices on
5 * the Axxia device: PLL clock, a clock divider and a clock mux.
6 *
7 * Copyright (C) 2014 LSI Corporation
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 version 2 as published by
11 * the Free Software Foundation.
12 */
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/slab.h>
16#include <linux/platform_device.h>
17#include <linux/of.h>
18#include <linux/of_address.h>
19#include <linux/clk-provider.h>
20#include <linux/regmap.h>
21#include <dt-bindings/clock/lsi,axm5516-clks.h>
22
23
24/**
25 * struct axxia_clk - Common struct to all Axxia clocks.
26 * @hw: clk_hw for the common clk framework
27 * @regmap: Regmap for the clock control registers
28 */
29struct axxia_clk {
30 struct clk_hw hw;
31 struct regmap *regmap;
32};
33#define to_axxia_clk(_hw) container_of(_hw, struct axxia_clk, hw)
34
35/**
36 * struct axxia_pllclk - Axxia PLL generated clock.
37 * @aclk: Common struct
38 * @reg: Offset into regmap for PLL control register
39 */
40struct axxia_pllclk {
41 struct axxia_clk aclk;
42 u32 reg;
43};
44#define to_axxia_pllclk(_aclk) container_of(_aclk, struct axxia_pllclk, aclk)
45
46/**
47 * axxia_pllclk_recalc - Calculate the PLL generated clock rate given the
48 * parent clock rate.
49 */
50static unsigned long
51axxia_pllclk_recalc(struct clk_hw *hw, unsigned long parent_rate)
52{
53 struct axxia_clk *aclk = to_axxia_clk(hw);
54 struct axxia_pllclk *pll = to_axxia_pllclk(aclk);
55 unsigned long rate, fbdiv, refdiv, postdiv;
56 u32 control;
57
58 regmap_read(aclk->regmap, pll->reg, &control);
59 postdiv = ((control >> 0) & 0xf) + 1;
60 fbdiv = ((control >> 4) & 0xfff) + 3;
61 refdiv = ((control >> 16) & 0x1f) + 1;
62 rate = (parent_rate / (refdiv * postdiv)) * fbdiv;
63
64 return rate;
65}
66
67static const struct clk_ops axxia_pllclk_ops = {
68 .recalc_rate = axxia_pllclk_recalc,
69};
70
71/**
72 * struct axxia_divclk - Axxia clock divider
73 * @aclk: Common struct
74 * @reg: Offset into regmap for PLL control register
75 * @shift: Bit position for divider value
76 * @width: Number of bits in divider value
77 */
78struct axxia_divclk {
79 struct axxia_clk aclk;
80 u32 reg;
81 u32 shift;
82 u32 width;
83};
84#define to_axxia_divclk(_aclk) container_of(_aclk, struct axxia_divclk, aclk)
85
86/**
87 * axxia_divclk_recalc_rate - Calculate clock divider output rage
88 */
89static unsigned long
90axxia_divclk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
91{
92 struct axxia_clk *aclk = to_axxia_clk(hw);
93 struct axxia_divclk *divclk = to_axxia_divclk(aclk);
94 u32 ctrl, div;
95
96 regmap_read(aclk->regmap, divclk->reg, &ctrl);
97 div = 1 + ((ctrl >> divclk->shift) & ((1 << divclk->width)-1));
98
99 return parent_rate / div;
100}
101
102static const struct clk_ops axxia_divclk_ops = {
103 .recalc_rate = axxia_divclk_recalc_rate,
104};
105
106/**
107 * struct axxia_clkmux - Axxia clock mux
108 * @aclk: Common struct
109 * @reg: Offset into regmap for PLL control register
110 * @shift: Bit position for selection value
111 * @width: Number of bits in selection value
112 */
113struct axxia_clkmux {
114 struct axxia_clk aclk;
115 u32 reg;
116 u32 shift;
117 u32 width;
118};
119#define to_axxia_clkmux(_aclk) container_of(_aclk, struct axxia_clkmux, aclk)
120
121/**
122 * axxia_clkmux_get_parent - Return the index of selected parent clock
123 */
124static u8 axxia_clkmux_get_parent(struct clk_hw *hw)
125{
126 struct axxia_clk *aclk = to_axxia_clk(hw);
127 struct axxia_clkmux *mux = to_axxia_clkmux(aclk);
128 u32 ctrl, parent;
129
130 regmap_read(aclk->regmap, mux->reg, &ctrl);
131 parent = (ctrl >> mux->shift) & ((1 << mux->width) - 1);
132
133 return (u8) parent;
134}
135
136static const struct clk_ops axxia_clkmux_ops = {
137 .get_parent = axxia_clkmux_get_parent,
138};
139
140
141/*
142 * PLLs
143 */
144
145static struct axxia_pllclk clk_fab_pll = {
146 .aclk.hw.init = &(struct clk_init_data){
147 .name = "clk_fab_pll",
148 .parent_names = (const char *[]){
149 "clk_ref0"
150 },
151 .num_parents = 1,
152 .ops = &axxia_pllclk_ops,
153 },
154 .reg = 0x01800,
155};
156
157static struct axxia_pllclk clk_cpu_pll = {
158 .aclk.hw.init = &(struct clk_init_data){
159 .name = "clk_cpu_pll",
160 .parent_names = (const char *[]){
161 "clk_ref0"
162 },
163 .num_parents = 1,
164 .ops = &axxia_pllclk_ops,
165 },
166 .reg = 0x02000,
167};
168
169static struct axxia_pllclk clk_sys_pll = {
170 .aclk.hw.init = &(struct clk_init_data){
171 .name = "clk_sys_pll",
172 .parent_names = (const char *[]){
173 "clk_ref0"
174 },
175 .num_parents = 1,
176 .ops = &axxia_pllclk_ops,
177 },
178 .reg = 0x02800,
179};
180
181static struct axxia_pllclk clk_sm0_pll = {
182 .aclk.hw.init = &(struct clk_init_data){
183 .name = "clk_sm0_pll",
184 .parent_names = (const char *[]){
185 "clk_ref2"
186 },
187 .num_parents = 1,
188 .ops = &axxia_pllclk_ops,
189 },
190 .reg = 0x03000,
191};
192
193static struct axxia_pllclk clk_sm1_pll = {
194 .aclk.hw.init = &(struct clk_init_data){
195 .name = "clk_sm1_pll",
196 .parent_names = (const char *[]){
197 "clk_ref1"
198 },
199 .num_parents = 1,
200 .ops = &axxia_pllclk_ops,
201 },
202 .reg = 0x03800,
203};
204
205/*
206 * Clock dividers
207 */
208
209static struct axxia_divclk clk_cpu0_div = {
210 .aclk.hw.init = &(struct clk_init_data){
211 .name = "clk_cpu0_div",
212 .parent_names = (const char *[]){
213 "clk_cpu_pll"
214 },
215 .num_parents = 1,
216 .ops = &axxia_divclk_ops,
217 },
218 .reg = 0x10008,
219 .shift = 0,
220 .width = 4,
221};
222
223static struct axxia_divclk clk_cpu1_div = {
224 .aclk.hw.init = &(struct clk_init_data){
225 .name = "clk_cpu1_div",
226 .parent_names = (const char *[]){
227 "clk_cpu_pll"
228 },
229 .num_parents = 1,
230 .ops = &axxia_divclk_ops,
231 },
232 .reg = 0x10008,
233 .shift = 4,
234 .width = 4,
235};
236
237static struct axxia_divclk clk_cpu2_div = {
238 .aclk.hw.init = &(struct clk_init_data){
239 .name = "clk_cpu2_div",
240 .parent_names = (const char *[]){
241 "clk_cpu_pll"
242 },
243 .num_parents = 1,
244 .ops = &axxia_divclk_ops,
245 },
246 .reg = 0x10008,
247 .shift = 8,
248 .width = 4,
249};
250
251static struct axxia_divclk clk_cpu3_div = {
252 .aclk.hw.init = &(struct clk_init_data){
253 .name = "clk_cpu3_div",
254 .parent_names = (const char *[]){
255 "clk_cpu_pll"
256 },
257 .num_parents = 1,
258 .ops = &axxia_divclk_ops,
259 },
260 .reg = 0x10008,
261 .shift = 12,
262 .width = 4,
263};
264
265static struct axxia_divclk clk_nrcp_div = {
266 .aclk.hw.init = &(struct clk_init_data){
267 .name = "clk_nrcp_div",
268 .parent_names = (const char *[]){
269 "clk_sys_pll"
270 },
271 .num_parents = 1,
272 .ops = &axxia_divclk_ops,
273 },
274 .reg = 0x1000c,
275 .shift = 0,
276 .width = 4,
277};
278
279static struct axxia_divclk clk_sys_div = {
280 .aclk.hw.init = &(struct clk_init_data){
281 .name = "clk_sys_div",
282 .parent_names = (const char *[]){
283 "clk_sys_pll"
284 },
285 .num_parents = 1,
286 .ops = &axxia_divclk_ops,
287 },
288 .reg = 0x1000c,
289 .shift = 4,
290 .width = 4,
291};
292
293static struct axxia_divclk clk_fab_div = {
294 .aclk.hw.init = &(struct clk_init_data){
295 .name = "clk_fab_div",
296 .parent_names = (const char *[]){
297 "clk_fab_pll"
298 },
299 .num_parents = 1,
300 .ops = &axxia_divclk_ops,
301 },
302 .reg = 0x1000c,
303 .shift = 8,
304 .width = 4,
305};
306
307static struct axxia_divclk clk_per_div = {
308 .aclk.hw.init = &(struct clk_init_data){
309 .name = "clk_per_div",
310 .parent_names = (const char *[]){
311 "clk_sm1_pll"
312 },
313 .num_parents = 1,
314 .flags = CLK_IS_BASIC,
315 .ops = &axxia_divclk_ops,
316 },
317 .reg = 0x1000c,
318 .shift = 12,
319 .width = 4,
320};
321
322static struct axxia_divclk clk_mmc_div = {
323 .aclk.hw.init = &(struct clk_init_data){
324 .name = "clk_mmc_div",
325 .parent_names = (const char *[]){
326 "clk_sm1_pll"
327 },
328 .num_parents = 1,
329 .flags = CLK_IS_BASIC,
330 .ops = &axxia_divclk_ops,
331 },
332 .reg = 0x1000c,
333 .shift = 16,
334 .width = 4,
335};
336
337/*
338 * Clock MUXes
339 */
340
341static struct axxia_clkmux clk_cpu0_mux = {
342 .aclk.hw.init = &(struct clk_init_data){
343 .name = "clk_cpu0",
344 .parent_names = (const char *[]){
345 "clk_ref0",
346 "clk_cpu_pll",
347 "clk_cpu0_div",
348 "clk_cpu0_div"
349 },
350 .num_parents = 4,
351 .ops = &axxia_clkmux_ops,
352 },
353 .reg = 0x10000,
354 .shift = 0,
355 .width = 2,
356};
357
358static struct axxia_clkmux clk_cpu1_mux = {
359 .aclk.hw.init = &(struct clk_init_data){
360 .name = "clk_cpu1",
361 .parent_names = (const char *[]){
362 "clk_ref0",
363 "clk_cpu_pll",
364 "clk_cpu1_div",
365 "clk_cpu1_div"
366 },
367 .num_parents = 4,
368 .ops = &axxia_clkmux_ops,
369 },
370 .reg = 0x10000,
371 .shift = 2,
372 .width = 2,
373};
374
375static struct axxia_clkmux clk_cpu2_mux = {
376 .aclk.hw.init = &(struct clk_init_data){
377 .name = "clk_cpu2",
378 .parent_names = (const char *[]){
379 "clk_ref0",
380 "clk_cpu_pll",
381 "clk_cpu2_div",
382 "clk_cpu2_div"
383 },
384 .num_parents = 4,
385 .ops = &axxia_clkmux_ops,
386 },
387 .reg = 0x10000,
388 .shift = 4,
389 .width = 2,
390};
391
392static struct axxia_clkmux clk_cpu3_mux = {
393 .aclk.hw.init = &(struct clk_init_data){
394 .name = "clk_cpu3",
395 .parent_names = (const char *[]){
396 "clk_ref0",
397 "clk_cpu_pll",
398 "clk_cpu3_div",
399 "clk_cpu3_div"
400 },
401 .num_parents = 4,
402 .ops = &axxia_clkmux_ops,
403 },
404 .reg = 0x10000,
405 .shift = 6,
406 .width = 2,
407};
408
409static struct axxia_clkmux clk_nrcp_mux = {
410 .aclk.hw.init = &(struct clk_init_data){
411 .name = "clk_nrcp",
412 .parent_names = (const char *[]){
413 "clk_ref0",
414 "clk_sys_pll",
415 "clk_nrcp_div",
416 "clk_nrcp_div"
417 },
418 .num_parents = 4,
419 .ops = &axxia_clkmux_ops,
420 },
421 .reg = 0x10004,
422 .shift = 0,
423 .width = 2,
424};
425
426static struct axxia_clkmux clk_sys_mux = {
427 .aclk.hw.init = &(struct clk_init_data){
428 .name = "clk_sys",
429 .parent_names = (const char *[]){
430 "clk_ref0",
431 "clk_sys_pll",
432 "clk_sys_div",
433 "clk_sys_div"
434 },
435 .num_parents = 4,
436 .ops = &axxia_clkmux_ops,
437 },
438 .reg = 0x10004,
439 .shift = 2,
440 .width = 2,
441};
442
443static struct axxia_clkmux clk_fab_mux = {
444 .aclk.hw.init = &(struct clk_init_data){
445 .name = "clk_fab",
446 .parent_names = (const char *[]){
447 "clk_ref0",
448 "clk_fab_pll",
449 "clk_fab_div",
450 "clk_fab_div"
451 },
452 .num_parents = 4,
453 .ops = &axxia_clkmux_ops,
454 },
455 .reg = 0x10004,
456 .shift = 4,
457 .width = 2,
458};
459
460static struct axxia_clkmux clk_per_mux = {
461 .aclk.hw.init = &(struct clk_init_data){
462 .name = "clk_per",
463 .parent_names = (const char *[]){
464 "clk_ref1",
465 "clk_per_div"
466 },
467 .num_parents = 2,
468 .ops = &axxia_clkmux_ops,
469 },
470 .reg = 0x10004,
471 .shift = 6,
472 .width = 1,
473};
474
475static struct axxia_clkmux clk_mmc_mux = {
476 .aclk.hw.init = &(struct clk_init_data){
477 .name = "clk_mmc",
478 .parent_names = (const char *[]){
479 "clk_ref1",
480 "clk_mmc_div"
481 },
482 .num_parents = 2,
483 .ops = &axxia_clkmux_ops,
484 },
485 .reg = 0x10004,
486 .shift = 9,
487 .width = 1,
488};
489
490/* Table of all supported clocks indexed by the clock identifiers from the
491 * device tree binding
492 */
493static struct axxia_clk *axmclk_clocks[] = {
494 [AXXIA_CLK_FAB_PLL] = &clk_fab_pll.aclk,
495 [AXXIA_CLK_CPU_PLL] = &clk_cpu_pll.aclk,
496 [AXXIA_CLK_SYS_PLL] = &clk_sys_pll.aclk,
497 [AXXIA_CLK_SM0_PLL] = &clk_sm0_pll.aclk,
498 [AXXIA_CLK_SM1_PLL] = &clk_sm1_pll.aclk,
499 [AXXIA_CLK_FAB_DIV] = &clk_fab_div.aclk,
500 [AXXIA_CLK_SYS_DIV] = &clk_sys_div.aclk,
501 [AXXIA_CLK_NRCP_DIV] = &clk_nrcp_div.aclk,
502 [AXXIA_CLK_CPU0_DIV] = &clk_cpu0_div.aclk,
503 [AXXIA_CLK_CPU1_DIV] = &clk_cpu1_div.aclk,
504 [AXXIA_CLK_CPU2_DIV] = &clk_cpu2_div.aclk,
505 [AXXIA_CLK_CPU3_DIV] = &clk_cpu3_div.aclk,
506 [AXXIA_CLK_PER_DIV] = &clk_per_div.aclk,
507 [AXXIA_CLK_MMC_DIV] = &clk_mmc_div.aclk,
508 [AXXIA_CLK_FAB] = &clk_fab_mux.aclk,
509 [AXXIA_CLK_SYS] = &clk_sys_mux.aclk,
510 [AXXIA_CLK_NRCP] = &clk_nrcp_mux.aclk,
511 [AXXIA_CLK_CPU0] = &clk_cpu0_mux.aclk,
512 [AXXIA_CLK_CPU1] = &clk_cpu1_mux.aclk,
513 [AXXIA_CLK_CPU2] = &clk_cpu2_mux.aclk,
514 [AXXIA_CLK_CPU3] = &clk_cpu3_mux.aclk,
515 [AXXIA_CLK_PER] = &clk_per_mux.aclk,
516 [AXXIA_CLK_MMC] = &clk_mmc_mux.aclk,
517};
518
519static const struct regmap_config axmclk_regmap_config = {
520 .reg_bits = 32,
521 .reg_stride = 4,
522 .val_bits = 32,
523 .max_register = 0x1fffc,
524 .fast_io = true,
525};
526
527static const struct of_device_id axmclk_match_table[] = {
528 { .compatible = "lsi,axm5516-clks" },
529 { }
530};
531MODULE_DEVICE_TABLE(of, axmclk_match_table);
532
533struct axmclk_priv {
534 struct clk_onecell_data onecell;
535 struct clk *clks[];
536};
537
538static int axmclk_probe(struct platform_device *pdev)
539{
540 void __iomem *base;
541 struct resource *res;
542 int i, ret;
543 struct device *dev = &pdev->dev;
544 struct clk *clk;
545 struct regmap *regmap;
546 size_t num_clks;
547 struct axmclk_priv *priv;
548
549 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
550 base = devm_ioremap_resource(dev, res);
551 if (IS_ERR(base))
552 return PTR_ERR(base);
553
554 regmap = devm_regmap_init_mmio(dev, base, &axmclk_regmap_config);
555 if (IS_ERR(regmap))
556 return PTR_ERR(regmap);
557
558 num_clks = ARRAY_SIZE(axmclk_clocks);
559 pr_info("axmclk: supporting %u clocks\n", num_clks);
560 priv = devm_kzalloc(dev, sizeof(*priv) + sizeof(*priv->clks) * num_clks,
561 GFP_KERNEL);
562 if (!priv)
563 return -ENOMEM;
564
565 priv->onecell.clks = priv->clks;
566 priv->onecell.clk_num = num_clks;
567
568 /* Update each entry with the allocated regmap and register the clock
569 * with the common clock framework
570 */
571 for (i = 0; i < num_clks; i++) {
572 axmclk_clocks[i]->regmap = regmap;
573 clk = devm_clk_register(dev, &axmclk_clocks[i]->hw);
574 if (IS_ERR(clk))
575 return PTR_ERR(clk);
576 priv->clks[i] = clk;
577 }
578
579 ret = of_clk_add_provider(dev->of_node,
580 of_clk_src_onecell_get, &priv->onecell);
581
582 return ret;
583}
584
585static int axmclk_remove(struct platform_device *pdev)
586{
587 of_clk_del_provider(pdev->dev.of_node);
588 return 0;
589}
590
591static struct platform_driver axmclk_driver = {
592 .probe = axmclk_probe,
593 .remove = axmclk_remove,
594 .driver = {
595 .name = "clk-axm5516",
596 .owner = THIS_MODULE,
597 .of_match_table = axmclk_match_table,
598 },
599};
600
601static int __init axmclk_init(void)
602{
603 return platform_driver_register(&axmclk_driver);
604}
605core_initcall(axmclk_init);
606
607static void __exit axmclk_exit(void)
608{
609 platform_driver_unregister(&axmclk_driver);
610}
611module_exit(axmclk_exit);
612
613MODULE_DESCRIPTION("AXM5516 clock driver");
614MODULE_LICENSE("GPL v2");
615MODULE_ALIAS("platform:clk-axm5516");
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 3fbee4540228..18a9de29df0e 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -43,6 +43,17 @@ static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
43 return maxdiv; 43 return maxdiv;
44} 44}
45 45
46static unsigned int _get_table_mindiv(const struct clk_div_table *table)
47{
48 unsigned int mindiv = UINT_MAX;
49 const struct clk_div_table *clkt;
50
51 for (clkt = table; clkt->div; clkt++)
52 if (clkt->div < mindiv)
53 mindiv = clkt->div;
54 return mindiv;
55}
56
46static unsigned int _get_maxdiv(struct clk_divider *divider) 57static unsigned int _get_maxdiv(struct clk_divider *divider)
47{ 58{
48 if (divider->flags & CLK_DIVIDER_ONE_BASED) 59 if (divider->flags & CLK_DIVIDER_ONE_BASED)
@@ -162,6 +173,24 @@ static int _round_up_table(const struct clk_div_table *table, int div)
162 return up; 173 return up;
163} 174}
164 175
176static int _round_down_table(const struct clk_div_table *table, int div)
177{
178 const struct clk_div_table *clkt;
179 int down = _get_table_mindiv(table);
180
181 for (clkt = table; clkt->div; clkt++) {
182 if (clkt->div == div)
183 return clkt->div;
184 else if (clkt->div > div)
185 continue;
186
187 if ((div - clkt->div) < (div - down))
188 down = clkt->div;
189 }
190
191 return down;
192}
193
165static int _div_round_up(struct clk_divider *divider, 194static int _div_round_up(struct clk_divider *divider,
166 unsigned long parent_rate, unsigned long rate) 195 unsigned long parent_rate, unsigned long rate)
167{ 196{
@@ -175,6 +204,54 @@ static int _div_round_up(struct clk_divider *divider,
175 return div; 204 return div;
176} 205}
177 206
207static int _div_round_closest(struct clk_divider *divider,
208 unsigned long parent_rate, unsigned long rate)
209{
210 int up, down, div;
211
212 up = down = div = DIV_ROUND_CLOSEST(parent_rate, rate);
213
214 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) {
215 up = __roundup_pow_of_two(div);
216 down = __rounddown_pow_of_two(div);
217 } else if (divider->table) {
218 up = _round_up_table(divider->table, div);
219 down = _round_down_table(divider->table, div);
220 }
221
222 return (up - div) <= (div - down) ? up : down;
223}
224
225static int _div_round(struct clk_divider *divider, unsigned long parent_rate,
226 unsigned long rate)
227{
228 if (divider->flags & CLK_DIVIDER_ROUND_CLOSEST)
229 return _div_round_closest(divider, parent_rate, rate);
230
231 return _div_round_up(divider, parent_rate, rate);
232}
233
234static bool _is_best_div(struct clk_divider *divider,
235 unsigned long rate, unsigned long now, unsigned long best)
236{
237 if (divider->flags & CLK_DIVIDER_ROUND_CLOSEST)
238 return abs(rate - now) < abs(rate - best);
239
240 return now <= rate && now > best;
241}
242
243static int _next_div(struct clk_divider *divider, int div)
244{
245 div++;
246
247 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
248 return __roundup_pow_of_two(div);
249 if (divider->table)
250 return _round_up_table(divider->table, div);
251
252 return div;
253}
254
178static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, 255static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
179 unsigned long *best_parent_rate) 256 unsigned long *best_parent_rate)
180{ 257{
@@ -190,7 +267,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
190 267
191 if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) { 268 if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
192 parent_rate = *best_parent_rate; 269 parent_rate = *best_parent_rate;
193 bestdiv = _div_round_up(divider, parent_rate, rate); 270 bestdiv = _div_round(divider, parent_rate, rate);
194 bestdiv = bestdiv == 0 ? 1 : bestdiv; 271 bestdiv = bestdiv == 0 ? 1 : bestdiv;
195 bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv; 272 bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
196 return bestdiv; 273 return bestdiv;
@@ -202,7 +279,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
202 */ 279 */
203 maxdiv = min(ULONG_MAX / rate, maxdiv); 280 maxdiv = min(ULONG_MAX / rate, maxdiv);
204 281
205 for (i = 1; i <= maxdiv; i++) { 282 for (i = 1; i <= maxdiv; i = _next_div(divider, i)) {
206 if (!_is_valid_div(divider, i)) 283 if (!_is_valid_div(divider, i))
207 continue; 284 continue;
208 if (rate * i == parent_rate_saved) { 285 if (rate * i == parent_rate_saved) {
@@ -217,7 +294,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
217 parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 294 parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
218 MULT_ROUND_UP(rate, i)); 295 MULT_ROUND_UP(rate, i));
219 now = DIV_ROUND_UP(parent_rate, i); 296 now = DIV_ROUND_UP(parent_rate, i);
220 if (now <= rate && now > best) { 297 if (_is_best_div(divider, rate, now, best)) {
221 bestdiv = i; 298 bestdiv = i;
222 best = now; 299 best = now;
223 *best_parent_rate = parent_rate; 300 *best_parent_rate = parent_rate;
@@ -284,6 +361,11 @@ const struct clk_ops clk_divider_ops = {
284}; 361};
285EXPORT_SYMBOL_GPL(clk_divider_ops); 362EXPORT_SYMBOL_GPL(clk_divider_ops);
286 363
364const struct clk_ops clk_divider_ro_ops = {
365 .recalc_rate = clk_divider_recalc_rate,
366};
367EXPORT_SYMBOL_GPL(clk_divider_ro_ops);
368
287static struct clk *_register_divider(struct device *dev, const char *name, 369static struct clk *_register_divider(struct device *dev, const char *name,
288 const char *parent_name, unsigned long flags, 370 const char *parent_name, unsigned long flags,
289 void __iomem *reg, u8 shift, u8 width, 371 void __iomem *reg, u8 shift, u8 width,
@@ -309,7 +391,10 @@ static struct clk *_register_divider(struct device *dev, const char *name,
309 } 391 }
310 392
311 init.name = name; 393 init.name = name;
312 init.ops = &clk_divider_ops; 394 if (clk_divider_flags & CLK_DIVIDER_READ_ONLY)
395 init.ops = &clk_divider_ro_ops;
396 else
397 init.ops = &clk_divider_ops;
313 init.flags = flags | CLK_IS_BASIC; 398 init.flags = flags | CLK_IS_BASIC;
314 init.parent_names = (parent_name ? &parent_name: NULL); 399 init.parent_names = (parent_name ? &parent_name: NULL);
315 init.num_parents = (parent_name ? 1 : 0); 400 init.num_parents = (parent_name ? 1 : 0);
diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c
new file mode 100644
index 000000000000..ede685ca0d20
--- /dev/null
+++ b/drivers/clk/clk-fractional-divider.c
@@ -0,0 +1,135 @@
1/*
2 * Copyright (C) 2014 Intel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Adjustable fractional divider clock implementation.
9 * Output rate = (m / n) * parent_rate.
10 */
11
12#include <linux/clk-provider.h>
13#include <linux/module.h>
14#include <linux/device.h>
15#include <linux/slab.h>
16#include <linux/gcd.h>
17
18#define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, hw)
19
20static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
21 unsigned long parent_rate)
22{
23 struct clk_fractional_divider *fd = to_clk_fd(hw);
24 unsigned long flags = 0;
25 u32 val, m, n;
26 u64 ret;
27
28 if (fd->lock)
29 spin_lock_irqsave(fd->lock, flags);
30
31 val = clk_readl(fd->reg);
32
33 if (fd->lock)
34 spin_unlock_irqrestore(fd->lock, flags);
35
36 m = (val & fd->mmask) >> fd->mshift;
37 n = (val & fd->nmask) >> fd->nshift;
38
39 ret = parent_rate * m;
40 do_div(ret, n);
41
42 return ret;
43}
44
45static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
46 unsigned long *prate)
47{
48 struct clk_fractional_divider *fd = to_clk_fd(hw);
49 unsigned maxn = (fd->nmask >> fd->nshift) + 1;
50 unsigned div;
51
52 if (!rate || rate >= *prate)
53 return *prate;
54
55 div = gcd(*prate, rate);
56
57 while ((*prate / div) > maxn) {
58 div <<= 1;
59 rate <<= 1;
60 }
61
62 return rate;
63}
64
65static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
66 unsigned long parent_rate)
67{
68 struct clk_fractional_divider *fd = to_clk_fd(hw);
69 unsigned long flags = 0;
70 unsigned long div;
71 unsigned n, m;
72 u32 val;
73
74 div = gcd(parent_rate, rate);
75 m = rate / div;
76 n = parent_rate / div;
77
78 if (fd->lock)
79 spin_lock_irqsave(fd->lock, flags);
80
81 val = clk_readl(fd->reg);
82 val &= ~(fd->mmask | fd->nmask);
83 val |= (m << fd->mshift) | (n << fd->nshift);
84 clk_writel(val, fd->reg);
85
86 if (fd->lock)
87 spin_unlock_irqrestore(fd->lock, flags);
88
89 return 0;
90}
91
92const struct clk_ops clk_fractional_divider_ops = {
93 .recalc_rate = clk_fd_recalc_rate,
94 .round_rate = clk_fd_round_rate,
95 .set_rate = clk_fd_set_rate,
96};
97EXPORT_SYMBOL_GPL(clk_fractional_divider_ops);
98
99struct clk *clk_register_fractional_divider(struct device *dev,
100 const char *name, const char *parent_name, unsigned long flags,
101 void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
102 u8 clk_divider_flags, spinlock_t *lock)
103{
104 struct clk_fractional_divider *fd;
105 struct clk_init_data init;
106 struct clk *clk;
107
108 fd = kzalloc(sizeof(*fd), GFP_KERNEL);
109 if (!fd) {
110 dev_err(dev, "could not allocate fractional divider clk\n");
111 return ERR_PTR(-ENOMEM);
112 }
113
114 init.name = name;
115 init.ops = &clk_fractional_divider_ops;
116 init.flags = flags | CLK_IS_BASIC;
117 init.parent_names = parent_name ? &parent_name : NULL;
118 init.num_parents = parent_name ? 1 : 0;
119
120 fd->reg = reg;
121 fd->mshift = mshift;
122 fd->mmask = (BIT(mwidth) - 1) << mshift;
123 fd->nshift = nshift;
124 fd->nmask = (BIT(nwidth) - 1) << nshift;
125 fd->flags = clk_divider_flags;
126 fd->lock = lock;
127 fd->hw.init = &init;
128
129 clk = clk_register(dev, &fd->hw);
130 if (IS_ERR(clk))
131 kfree(fd);
132
133 return clk;
134}
135EXPORT_SYMBOL_GPL(clk_register_fractional_divider);
diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
index f2f62a1bf61a..9b7b5859a420 100644
--- a/drivers/clk/clk-s2mps11.c
+++ b/drivers/clk/clk-s2mps11.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * clk-s2mps11.c - Clock driver for S2MPS11. 2 * clk-s2mps11.c - Clock driver for S2MPS11.
3 * 3 *
4 * Copyright (C) 2013 Samsung Electornics 4 * Copyright (C) 2013,2014 Samsung Electornics
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 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 7 * under the terms of the GNU General Public License as published by the
@@ -13,10 +13,6 @@
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */ 16 */
21 17
22#include <linux/module.h> 18#include <linux/module.h>
@@ -27,6 +23,7 @@
27#include <linux/clk-provider.h> 23#include <linux/clk-provider.h>
28#include <linux/platform_device.h> 24#include <linux/platform_device.h>
29#include <linux/mfd/samsung/s2mps11.h> 25#include <linux/mfd/samsung/s2mps11.h>
26#include <linux/mfd/samsung/s2mps14.h>
30#include <linux/mfd/samsung/s5m8767.h> 27#include <linux/mfd/samsung/s5m8767.h>
31#include <linux/mfd/samsung/core.h> 28#include <linux/mfd/samsung/core.h>
32 29
@@ -44,6 +41,7 @@ enum {
44 41
45struct s2mps11_clk { 42struct s2mps11_clk {
46 struct sec_pmic_dev *iodev; 43 struct sec_pmic_dev *iodev;
44 struct device_node *clk_np;
47 struct clk_hw hw; 45 struct clk_hw hw;
48 struct clk *clk; 46 struct clk *clk;
49 struct clk_lookup *lookup; 47 struct clk_lookup *lookup;
@@ -125,7 +123,21 @@ static struct clk_init_data s2mps11_clks_init[S2MPS11_CLKS_NUM] = {
125 }, 123 },
126}; 124};
127 125
128static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev) 126static struct clk_init_data s2mps14_clks_init[S2MPS11_CLKS_NUM] = {
127 [S2MPS11_CLK_AP] = {
128 .name = "s2mps14_ap",
129 .ops = &s2mps11_clk_ops,
130 .flags = CLK_IS_ROOT,
131 },
132 [S2MPS11_CLK_BT] = {
133 .name = "s2mps14_bt",
134 .ops = &s2mps11_clk_ops,
135 .flags = CLK_IS_ROOT,
136 },
137};
138
139static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev,
140 struct clk_init_data *clks_init)
129{ 141{
130 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); 142 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
131 struct device_node *clk_np; 143 struct device_node *clk_np;
@@ -140,14 +152,12 @@ static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev)
140 return ERR_PTR(-EINVAL); 152 return ERR_PTR(-EINVAL);
141 } 153 }
142 154
143 clk_table = devm_kzalloc(&pdev->dev, sizeof(struct clk *) * 155 for (i = 0; i < S2MPS11_CLKS_NUM; i++) {
144 S2MPS11_CLKS_NUM, GFP_KERNEL); 156 if (!clks_init[i].name)
145 if (!clk_table) 157 continue; /* Skip clocks not present in some devices */
146 return ERR_PTR(-ENOMEM);
147
148 for (i = 0; i < S2MPS11_CLKS_NUM; i++)
149 of_property_read_string_index(clk_np, "clock-output-names", i, 158 of_property_read_string_index(clk_np, "clock-output-names", i,
150 &s2mps11_clks_init[i].name); 159 &clks_init[i].name);
160 }
151 161
152 return clk_np; 162 return clk_np;
153} 163}
@@ -156,8 +166,8 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
156{ 166{
157 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); 167 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
158 struct s2mps11_clk *s2mps11_clks, *s2mps11_clk; 168 struct s2mps11_clk *s2mps11_clks, *s2mps11_clk;
159 struct device_node *clk_np = NULL;
160 unsigned int s2mps11_reg; 169 unsigned int s2mps11_reg;
170 struct clk_init_data *clks_init;
161 int i, ret = 0; 171 int i, ret = 0;
162 u32 val; 172 u32 val;
163 173
@@ -168,25 +178,39 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
168 178
169 s2mps11_clk = s2mps11_clks; 179 s2mps11_clk = s2mps11_clks;
170 180
171 clk_np = s2mps11_clk_parse_dt(pdev); 181 clk_table = devm_kzalloc(&pdev->dev, sizeof(struct clk *) *
172 if (IS_ERR(clk_np)) 182 S2MPS11_CLKS_NUM, GFP_KERNEL);
173 return PTR_ERR(clk_np); 183 if (!clk_table)
184 return -ENOMEM;
174 185
175 switch(platform_get_device_id(pdev)->driver_data) { 186 switch(platform_get_device_id(pdev)->driver_data) {
176 case S2MPS11X: 187 case S2MPS11X:
177 s2mps11_reg = S2MPS11_REG_RTC_CTRL; 188 s2mps11_reg = S2MPS11_REG_RTC_CTRL;
189 clks_init = s2mps11_clks_init;
190 break;
191 case S2MPS14X:
192 s2mps11_reg = S2MPS14_REG_RTCCTRL;
193 clks_init = s2mps14_clks_init;
178 break; 194 break;
179 case S5M8767X: 195 case S5M8767X:
180 s2mps11_reg = S5M8767_REG_CTRL1; 196 s2mps11_reg = S5M8767_REG_CTRL1;
197 clks_init = s2mps11_clks_init;
181 break; 198 break;
182 default: 199 default:
183 dev_err(&pdev->dev, "Invalid device type\n"); 200 dev_err(&pdev->dev, "Invalid device type\n");
184 return -EINVAL; 201 return -EINVAL;
185 }; 202 };
186 203
204 /* Store clocks of_node in first element of s2mps11_clks array */
205 s2mps11_clks->clk_np = s2mps11_clk_parse_dt(pdev, clks_init);
206 if (IS_ERR(s2mps11_clks->clk_np))
207 return PTR_ERR(s2mps11_clks->clk_np);
208
187 for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) { 209 for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) {
210 if (!clks_init[i].name)
211 continue; /* Skip clocks not present in some devices */
188 s2mps11_clk->iodev = iodev; 212 s2mps11_clk->iodev = iodev;
189 s2mps11_clk->hw.init = &s2mps11_clks_init[i]; 213 s2mps11_clk->hw.init = &clks_init[i];
190 s2mps11_clk->mask = 1 << i; 214 s2mps11_clk->mask = 1 << i;
191 s2mps11_clk->reg = s2mps11_reg; 215 s2mps11_clk->reg = s2mps11_reg;
192 216
@@ -219,15 +243,18 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
219 clkdev_add(s2mps11_clk->lookup); 243 clkdev_add(s2mps11_clk->lookup);
220 } 244 }
221 245
222 if (clk_table) { 246 for (i = 0; i < S2MPS11_CLKS_NUM; i++) {
223 for (i = 0; i < S2MPS11_CLKS_NUM; i++) 247 /* Skip clocks not present on S2MPS14 */
224 clk_table[i] = s2mps11_clks[i].clk; 248 if (!clks_init[i].name)
225 249 continue;
226 clk_data.clks = clk_table; 250 clk_table[i] = s2mps11_clks[i].clk;
227 clk_data.clk_num = S2MPS11_CLKS_NUM;
228 of_clk_add_provider(clk_np, of_clk_src_onecell_get, &clk_data);
229 } 251 }
230 252
253 clk_data.clks = clk_table;
254 clk_data.clk_num = S2MPS11_CLKS_NUM;
255 of_clk_add_provider(s2mps11_clks->clk_np, of_clk_src_onecell_get,
256 &clk_data);
257
231 platform_set_drvdata(pdev, s2mps11_clks); 258 platform_set_drvdata(pdev, s2mps11_clks);
232 259
233 return ret; 260 return ret;
@@ -250,14 +277,23 @@ static int s2mps11_clk_remove(struct platform_device *pdev)
250 struct s2mps11_clk *s2mps11_clks = platform_get_drvdata(pdev); 277 struct s2mps11_clk *s2mps11_clks = platform_get_drvdata(pdev);
251 int i; 278 int i;
252 279
253 for (i = 0; i < S2MPS11_CLKS_NUM; i++) 280 of_clk_del_provider(s2mps11_clks[0].clk_np);
281 /* Drop the reference obtained in s2mps11_clk_parse_dt */
282 of_node_put(s2mps11_clks[0].clk_np);
283
284 for (i = 0; i < S2MPS11_CLKS_NUM; i++) {
285 /* Skip clocks not present on S2MPS14 */
286 if (!s2mps11_clks[i].lookup)
287 continue;
254 clkdev_drop(s2mps11_clks[i].lookup); 288 clkdev_drop(s2mps11_clks[i].lookup);
289 }
255 290
256 return 0; 291 return 0;
257} 292}
258 293
259static const struct platform_device_id s2mps11_clk_id[] = { 294static const struct platform_device_id s2mps11_clk_id[] = {
260 { "s2mps11-clk", S2MPS11X}, 295 { "s2mps11-clk", S2MPS11X},
296 { "s2mps14-clk", S2MPS14X},
261 { "s5m8767-clk", S5M8767X}, 297 { "s5m8767-clk", S5M8767X},
262 { }, 298 { },
263}; 299};
diff --git a/drivers/clk/clk-si570.c b/drivers/clk/clk-si570.c
index 4bbbe32585ec..fc167b3f8919 100644
--- a/drivers/clk/clk-si570.c
+++ b/drivers/clk/clk-si570.c
@@ -526,6 +526,6 @@ static struct i2c_driver si570_driver = {
526module_i2c_driver(si570_driver); 526module_i2c_driver(si570_driver);
527 527
528MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>"); 528MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
529MODULE_AUTHOR("Soeren Brinkmann <soren.brinkmann@xilinx.com"); 529MODULE_AUTHOR("Soeren Brinkmann <soren.brinkmann@xilinx.com>");
530MODULE_DESCRIPTION("Si570 driver"); 530MODULE_DESCRIPTION("Si570 driver");
531MODULE_LICENSE("GPL"); 531MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c
index 3efbdd078d14..406bfc1375b2 100644
--- a/drivers/clk/clk-u300.c
+++ b/drivers/clk/clk-u300.c
@@ -1168,6 +1168,7 @@ static const struct of_device_id u300_clk_match[] __initconst = {
1168 .compatible = "stericsson,u300-syscon-mclk", 1168 .compatible = "stericsson,u300-syscon-mclk",
1169 .data = of_u300_syscon_mclk_init, 1169 .data = of_u300_syscon_mclk_init,
1170 }, 1170 },
1171 {}
1171}; 1172};
1172 1173
1173 1174
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 7cf2c093cc54..8b73edef151d 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -106,12 +106,11 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
106 if (!c) 106 if (!c)
107 return; 107 return;
108 108
109 seq_printf(s, "%*s%-*s %-11d %-12d %-10lu %-11lu", 109 seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu\n",
110 level * 3 + 1, "", 110 level * 3 + 1, "",
111 30 - level * 3, c->name, 111 30 - level * 3, c->name,
112 c->enable_count, c->prepare_count, clk_get_rate(c), 112 c->enable_count, c->prepare_count, clk_get_rate(c),
113 clk_get_accuracy(c)); 113 clk_get_accuracy(c));
114 seq_printf(s, "\n");
115} 114}
116 115
117static void clk_summary_show_subtree(struct seq_file *s, struct clk *c, 116static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
@@ -132,8 +131,8 @@ static int clk_summary_show(struct seq_file *s, void *data)
132{ 131{
133 struct clk *c; 132 struct clk *c;
134 133
135 seq_printf(s, " clock enable_cnt prepare_cnt rate accuracy\n"); 134 seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy\n");
136 seq_printf(s, "---------------------------------------------------------------------------------\n"); 135 seq_puts(s, "--------------------------------------------------------------------------------\n");
137 136
138 clk_prepare_lock(); 137 clk_prepare_lock();
139 138
@@ -822,6 +821,9 @@ void __clk_unprepare(struct clk *clk)
822 */ 821 */
823void clk_unprepare(struct clk *clk) 822void clk_unprepare(struct clk *clk)
824{ 823{
824 if (IS_ERR_OR_NULL(clk))
825 return;
826
825 clk_prepare_lock(); 827 clk_prepare_lock();
826 __clk_unprepare(clk); 828 __clk_unprepare(clk);
827 clk_prepare_unlock(); 829 clk_prepare_unlock();
@@ -883,9 +885,6 @@ static void __clk_disable(struct clk *clk)
883 if (!clk) 885 if (!clk)
884 return; 886 return;
885 887
886 if (WARN_ON(IS_ERR(clk)))
887 return;
888
889 if (WARN_ON(clk->enable_count == 0)) 888 if (WARN_ON(clk->enable_count == 0))
890 return; 889 return;
891 890
@@ -914,6 +913,9 @@ void clk_disable(struct clk *clk)
914{ 913{
915 unsigned long flags; 914 unsigned long flags;
916 915
916 if (IS_ERR_OR_NULL(clk))
917 return;
918
917 flags = clk_enable_lock(); 919 flags = clk_enable_lock();
918 __clk_disable(clk); 920 __clk_disable(clk);
919 clk_enable_unlock(flags); 921 clk_enable_unlock(flags);
@@ -1004,6 +1006,7 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
1004 else 1006 else
1005 return clk->rate; 1007 return clk->rate;
1006} 1008}
1009EXPORT_SYMBOL_GPL(__clk_round_rate);
1007 1010
1008/** 1011/**
1009 * clk_round_rate - round the given rate for a clk 1012 * clk_round_rate - round the given rate for a clk
@@ -1115,6 +1118,13 @@ long clk_get_accuracy(struct clk *clk)
1115} 1118}
1116EXPORT_SYMBOL_GPL(clk_get_accuracy); 1119EXPORT_SYMBOL_GPL(clk_get_accuracy);
1117 1120
1121static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
1122{
1123 if (clk->ops->recalc_rate)
1124 return clk->ops->recalc_rate(clk->hw, parent_rate);
1125 return parent_rate;
1126}
1127
1118/** 1128/**
1119 * __clk_recalc_rates 1129 * __clk_recalc_rates
1120 * @clk: first clk in the subtree 1130 * @clk: first clk in the subtree
@@ -1140,10 +1150,7 @@ static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
1140 if (clk->parent) 1150 if (clk->parent)
1141 parent_rate = clk->parent->rate; 1151 parent_rate = clk->parent->rate;
1142 1152
1143 if (clk->ops->recalc_rate) 1153 clk->rate = clk_recalc(clk, parent_rate);
1144 clk->rate = clk->ops->recalc_rate(clk->hw, parent_rate);
1145 else
1146 clk->rate = parent_rate;
1147 1154
1148 /* 1155 /*
1149 * ignore NOTIFY_STOP and NOTIFY_BAD return values for POST_RATE_CHANGE 1156 * ignore NOTIFY_STOP and NOTIFY_BAD return values for POST_RATE_CHANGE
@@ -1334,10 +1341,7 @@ static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)
1334 unsigned long new_rate; 1341 unsigned long new_rate;
1335 int ret = NOTIFY_DONE; 1342 int ret = NOTIFY_DONE;
1336 1343
1337 if (clk->ops->recalc_rate) 1344 new_rate = clk_recalc(clk, parent_rate);
1338 new_rate = clk->ops->recalc_rate(clk->hw, parent_rate);
1339 else
1340 new_rate = parent_rate;
1341 1345
1342 /* abort rate change if a driver returns NOTIFY_BAD or NOTIFY_STOP */ 1346 /* abort rate change if a driver returns NOTIFY_BAD or NOTIFY_STOP */
1343 if (clk->notifier_count) 1347 if (clk->notifier_count)
@@ -1373,10 +1377,7 @@ static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
1373 new_parent->new_child = clk; 1377 new_parent->new_child = clk;
1374 1378
1375 hlist_for_each_entry(child, &clk->children, child_node) { 1379 hlist_for_each_entry(child, &clk->children, child_node) {
1376 if (child->ops->recalc_rate) 1380 child->new_rate = clk_recalc(child, new_rate);
1377 child->new_rate = child->ops->recalc_rate(child->hw, new_rate);
1378 else
1379 child->new_rate = new_rate;
1380 clk_calc_subtree(child, child->new_rate, NULL, 0); 1381 clk_calc_subtree(child, child->new_rate, NULL, 0);
1381 } 1382 }
1382} 1383}
@@ -1524,10 +1525,7 @@ static void clk_change_rate(struct clk *clk)
1524 if (!skip_set_rate && clk->ops->set_rate) 1525 if (!skip_set_rate && clk->ops->set_rate)
1525 clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate); 1526 clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate);
1526 1527
1527 if (clk->ops->recalc_rate) 1528 clk->rate = clk_recalc(clk, best_parent_rate);
1528 clk->rate = clk->ops->recalc_rate(clk->hw, best_parent_rate);
1529 else
1530 clk->rate = best_parent_rate;
1531 1529
1532 if (clk->notifier_count && old_rate != clk->rate) 1530 if (clk->notifier_count && old_rate != clk->rate)
1533 __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); 1531 __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
@@ -1716,9 +1714,6 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
1716 if (!clk) 1714 if (!clk)
1717 return 0; 1715 return 0;
1718 1716
1719 if (!clk->ops)
1720 return -EINVAL;
1721
1722 /* verify ops for for multi-parent clks */ 1717 /* verify ops for for multi-parent clks */
1723 if ((clk->num_parents > 1) && (!clk->ops->set_parent)) 1718 if ((clk->num_parents > 1) && (!clk->ops->set_parent))
1724 return -ENOSYS; 1719 return -ENOSYS;
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index 795cc9f0dac0..c798138f023f 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -10,6 +10,7 @@
10 */ 10 */
11 11
12#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) 12#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
13struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec);
13struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec); 14struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec);
14void of_clk_lock(void); 15void of_clk_lock(void);
15void of_clk_unlock(void); 16void of_clk_unlock(void);
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index a360b2eca5cb..f890b901c6bc 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -27,6 +27,32 @@ static LIST_HEAD(clocks);
27static DEFINE_MUTEX(clocks_mutex); 27static DEFINE_MUTEX(clocks_mutex);
28 28
29#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) 29#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
30
31/**
32 * of_clk_get_by_clkspec() - Lookup a clock form a clock provider
33 * @clkspec: pointer to a clock specifier data structure
34 *
35 * This function looks up a struct clk from the registered list of clock
36 * providers, an input is a clock specifier data structure as returned
37 * from the of_parse_phandle_with_args() function call.
38 */
39struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
40{
41 struct clk *clk;
42
43 if (!clkspec)
44 return ERR_PTR(-EINVAL);
45
46 of_clk_lock();
47 clk = __of_clk_get_from_provider(clkspec);
48
49 if (!IS_ERR(clk) && !__clk_get(clk))
50 clk = ERR_PTR(-ENOENT);
51
52 of_clk_unlock();
53 return clk;
54}
55
30struct clk *of_clk_get(struct device_node *np, int index) 56struct clk *of_clk_get(struct device_node *np, int index)
31{ 57{
32 struct of_phandle_args clkspec; 58 struct of_phandle_args clkspec;
@@ -41,13 +67,7 @@ struct clk *of_clk_get(struct device_node *np, int index)
41 if (rc) 67 if (rc)
42 return ERR_PTR(rc); 68 return ERR_PTR(rc);
43 69
44 of_clk_lock(); 70 clk = of_clk_get_by_clkspec(&clkspec);
45 clk = __of_clk_get_from_provider(&clkspec);
46
47 if (!IS_ERR(clk) && !__clk_get(clk))
48 clk = ERR_PTR(-ENOENT);
49
50 of_clk_unlock();
51 of_node_put(clkspec.np); 71 of_node_put(clkspec.np);
52 return clk; 72 return clk;
53} 73}
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
index 40b33c6a8257..038c02f4d0e7 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -6,3 +6,4 @@ obj-y += clk.o clkgate-separated.o
6 6
7obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o 7obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o
8obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o 8obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o
9obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o
diff --git a/drivers/clk/hisilicon/clk-hix5hd2.c b/drivers/clk/hisilicon/clk-hix5hd2.c
new file mode 100644
index 000000000000..e5fcfb4e32ef
--- /dev/null
+++ b/drivers/clk/hisilicon/clk-hix5hd2.c
@@ -0,0 +1,101 @@
1/*
2 * Copyright (c) 2014 Linaro Ltd.
3 * Copyright (c) 2014 Hisilicon Limited.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 */
9
10#include <linux/of_address.h>
11#include <dt-bindings/clock/hix5hd2-clock.h>
12#include "clk.h"
13
14static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] __initdata = {
15 { HIX5HD2_FIXED_1200M, "1200m", NULL, CLK_IS_ROOT, 1200000000, },
16 { HIX5HD2_FIXED_400M, "400m", NULL, CLK_IS_ROOT, 400000000, },
17 { HIX5HD2_FIXED_48M, "48m", NULL, CLK_IS_ROOT, 48000000, },
18 { HIX5HD2_FIXED_24M, "24m", NULL, CLK_IS_ROOT, 24000000, },
19 { HIX5HD2_FIXED_600M, "600m", NULL, CLK_IS_ROOT, 600000000, },
20 { HIX5HD2_FIXED_300M, "300m", NULL, CLK_IS_ROOT, 300000000, },
21 { HIX5HD2_FIXED_75M, "75m", NULL, CLK_IS_ROOT, 75000000, },
22 { HIX5HD2_FIXED_200M, "200m", NULL, CLK_IS_ROOT, 200000000, },
23 { HIX5HD2_FIXED_100M, "100m", NULL, CLK_IS_ROOT, 100000000, },
24 { HIX5HD2_FIXED_40M, "40m", NULL, CLK_IS_ROOT, 40000000, },
25 { HIX5HD2_FIXED_150M, "150m", NULL, CLK_IS_ROOT, 150000000, },
26 { HIX5HD2_FIXED_1728M, "1728m", NULL, CLK_IS_ROOT, 1728000000, },
27 { HIX5HD2_FIXED_28P8M, "28p8m", NULL, CLK_IS_ROOT, 28000000, },
28 { HIX5HD2_FIXED_432M, "432m", NULL, CLK_IS_ROOT, 432000000, },
29 { HIX5HD2_FIXED_345P6M, "345p6m", NULL, CLK_IS_ROOT, 345000000, },
30 { HIX5HD2_FIXED_288M, "288m", NULL, CLK_IS_ROOT, 288000000, },
31 { HIX5HD2_FIXED_60M, "60m", NULL, CLK_IS_ROOT, 60000000, },
32 { HIX5HD2_FIXED_750M, "750m", NULL, CLK_IS_ROOT, 750000000, },
33 { HIX5HD2_FIXED_500M, "500m", NULL, CLK_IS_ROOT, 500000000, },
34 { HIX5HD2_FIXED_54M, "54m", NULL, CLK_IS_ROOT, 54000000, },
35 { HIX5HD2_FIXED_27M, "27m", NULL, CLK_IS_ROOT, 27000000, },
36 { HIX5HD2_FIXED_1500M, "1500m", NULL, CLK_IS_ROOT, 1500000000, },
37 { HIX5HD2_FIXED_375M, "375m", NULL, CLK_IS_ROOT, 375000000, },
38 { HIX5HD2_FIXED_187M, "187m", NULL, CLK_IS_ROOT, 187000000, },
39 { HIX5HD2_FIXED_250M, "250m", NULL, CLK_IS_ROOT, 250000000, },
40 { HIX5HD2_FIXED_125M, "125m", NULL, CLK_IS_ROOT, 125000000, },
41 { HIX5HD2_FIXED_2P02M, "2m", NULL, CLK_IS_ROOT, 2000000, },
42 { HIX5HD2_FIXED_50M, "50m", NULL, CLK_IS_ROOT, 50000000, },
43 { HIX5HD2_FIXED_25M, "25m", NULL, CLK_IS_ROOT, 25000000, },
44 { HIX5HD2_FIXED_83M, "83m", NULL, CLK_IS_ROOT, 83333333, },
45};
46
47static const char *sfc_mux_p[] __initconst = {
48 "24m", "150m", "200m", "100m", "75m", };
49static u32 sfc_mux_table[] = {0, 4, 5, 6, 7};
50
51static const char *sdio1_mux_p[] __initconst = {
52 "75m", "100m", "50m", "15m", };
53static u32 sdio1_mux_table[] = {0, 1, 2, 3};
54
55static const char *fephy_mux_p[] __initconst = { "25m", "125m"};
56static u32 fephy_mux_table[] = {0, 1};
57
58
59static struct hisi_mux_clock hix5hd2_mux_clks[] __initdata = {
60 { 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, },
62 { HIX5HD2_MMC_MUX, "mmc_mux", sdio1_mux_p, ARRAY_SIZE(sdio1_mux_p),
63 CLK_SET_RATE_PARENT, 0xa0, 8, 2, 0, sdio1_mux_table, },
64 { HIX5HD2_FEPHY_MUX, "fephy_mux",
65 fephy_mux_p, ARRAY_SIZE(fephy_mux_p),
66 CLK_SET_RATE_PARENT, 0x120, 8, 2, 0, fephy_mux_table, },
67};
68
69static struct hisi_gate_clock hix5hd2_gate_clks[] __initdata = {
70 /*sfc*/
71 { HIX5HD2_SFC_CLK, "clk_sfc", "sfc_mux",
72 CLK_SET_RATE_PARENT, 0x5c, 0, 0, },
73 { HIX5HD2_SFC_RST, "rst_sfc", "clk_sfc",
74 CLK_SET_RATE_PARENT, 0x5c, 4, CLK_GATE_SET_TO_DISABLE, },
75 /*sdio1*/
76 { HIX5HD2_MMC_BIU_CLK, "clk_mmc_biu", "200m",
77 CLK_SET_RATE_PARENT, 0xa0, 0, 0, },
78 { HIX5HD2_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux",
79 CLK_SET_RATE_PARENT, 0xa0, 1, 0, },
80 { HIX5HD2_MMC_CIU_RST, "rst_mmc_ciu", "clk_mmc_ciu",
81 CLK_SET_RATE_PARENT, 0xa0, 4, CLK_GATE_SET_TO_DISABLE, },
82};
83
84static void __init hix5hd2_clk_init(struct device_node *np)
85{
86 struct hisi_clock_data *clk_data;
87
88 clk_data = hisi_clk_init(np, HIX5HD2_NR_CLKS);
89 if (!clk_data)
90 return;
91
92 hisi_clk_register_fixed_rate(hix5hd2_fixed_rate_clks,
93 ARRAY_SIZE(hix5hd2_fixed_rate_clks),
94 clk_data);
95 hisi_clk_register_mux(hix5hd2_mux_clks, ARRAY_SIZE(hix5hd2_mux_clks),
96 clk_data);
97 hisi_clk_register_gate(hix5hd2_gate_clks,
98 ARRAY_SIZE(hix5hd2_gate_clks), clk_data);
99}
100
101CLK_OF_DECLARE(hix5hd2_clk, "hisilicon,hix5hd2-clock", hix5hd2_clk_init);
diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
index 276f672e7b1a..a078e84f7b05 100644
--- a/drivers/clk/hisilicon/clk.c
+++ b/drivers/clk/hisilicon/clk.c
@@ -127,11 +127,14 @@ void __init hisi_clk_register_mux(struct hisi_mux_clock *clks,
127 int i; 127 int i;
128 128
129 for (i = 0; i < nums; i++) { 129 for (i = 0; i < nums; i++) {
130 clk = clk_register_mux(NULL, clks[i].name, clks[i].parent_names, 130 u32 mask = BIT(clks[i].width) - 1;
131 clks[i].num_parents, clks[i].flags, 131
132 base + clks[i].offset, clks[i].shift, 132 clk = clk_register_mux_table(NULL, clks[i].name,
133 clks[i].width, clks[i].mux_flags, 133 clks[i].parent_names,
134 &hisi_clk_lock); 134 clks[i].num_parents, clks[i].flags,
135 base + clks[i].offset, clks[i].shift,
136 mask, clks[i].mux_flags,
137 clks[i].table, &hisi_clk_lock);
135 if (IS_ERR(clk)) { 138 if (IS_ERR(clk)) {
136 pr_err("%s: failed to register clock %s\n", 139 pr_err("%s: failed to register clock %s\n",
137 __func__, clks[i].name); 140 __func__, clks[i].name);
@@ -174,6 +177,34 @@ void __init hisi_clk_register_divider(struct hisi_divider_clock *clks,
174 } 177 }
175} 178}
176 179
180void __init hisi_clk_register_gate(struct hisi_gate_clock *clks,
181 int nums, struct hisi_clock_data *data)
182{
183 struct clk *clk;
184 void __iomem *base = data->base;
185 int i;
186
187 for (i = 0; i < nums; i++) {
188 clk = clk_register_gate(NULL, clks[i].name,
189 clks[i].parent_name,
190 clks[i].flags,
191 base + clks[i].offset,
192 clks[i].bit_idx,
193 clks[i].gate_flags,
194 &hisi_clk_lock);
195 if (IS_ERR(clk)) {
196 pr_err("%s: failed to register clock %s\n",
197 __func__, clks[i].name);
198 continue;
199 }
200
201 if (clks[i].alias)
202 clk_register_clkdev(clk, clks[i].alias, NULL);
203
204 data->clk_data.clks[clks[i].id] = clk;
205 }
206}
207
177void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks, 208void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
178 int nums, struct hisi_clock_data *data) 209 int nums, struct hisi_clock_data *data)
179{ 210{
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index 43fa5da88f02..31083ffc0650 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -62,6 +62,7 @@ struct hisi_mux_clock {
62 u8 shift; 62 u8 shift;
63 u8 width; 63 u8 width;
64 u8 mux_flags; 64 u8 mux_flags;
65 u32 *table;
65 const char *alias; 66 const char *alias;
66}; 67};
67 68
@@ -103,6 +104,8 @@ void __init hisi_clk_register_mux(struct hisi_mux_clock *, int,
103 struct hisi_clock_data *); 104 struct hisi_clock_data *);
104void __init hisi_clk_register_divider(struct hisi_divider_clock *, 105void __init hisi_clk_register_divider(struct hisi_divider_clock *,
105 int, struct hisi_clock_data *); 106 int, struct hisi_clock_data *);
107void __init hisi_clk_register_gate(struct hisi_gate_clock *,
108 int, struct hisi_clock_data *);
106void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *, 109void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
107 int, struct hisi_clock_data *); 110 int, struct hisi_clock_data *);
108#endif /* __HISI_CLK_H */ 111#endif /* __HISI_CLK_H */
diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig
index 693f7be129f1..3b34dba9178d 100644
--- a/drivers/clk/mvebu/Kconfig
+++ b/drivers/clk/mvebu/Kconfig
@@ -34,3 +34,7 @@ config DOVE_CLK
34config KIRKWOOD_CLK 34config KIRKWOOD_CLK
35 bool 35 bool
36 select MVEBU_CLK_COMMON 36 select MVEBU_CLK_COMMON
37
38config ORION_CLK
39 bool
40 select MVEBU_CLK_COMMON
diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile
index 4c66162fb0b4..a9a56fc01901 100644
--- a/drivers/clk/mvebu/Makefile
+++ b/drivers/clk/mvebu/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_ARMADA_38X_CLK) += armada-38x.o
8obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o 8obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o
9obj-$(CONFIG_DOVE_CLK) += dove.o 9obj-$(CONFIG_DOVE_CLK) += dove.o
10obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o 10obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o
11obj-$(CONFIG_ORION_CLK) += orion.o
diff --git a/drivers/clk/mvebu/orion.c b/drivers/clk/mvebu/orion.c
new file mode 100644
index 000000000000..fd129566c1ce
--- /dev/null
+++ b/drivers/clk/mvebu/orion.c
@@ -0,0 +1,210 @@
1/*
2 * Marvell Orion SoC clocks
3 *
4 * Copyright (C) 2014 Thomas Petazzoni
5 *
6 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/kernel.h>
14#include <linux/clk-provider.h>
15#include <linux/io.h>
16#include <linux/of.h>
17#include "common.h"
18
19static const struct coreclk_ratio orion_coreclk_ratios[] __initconst = {
20 { .id = 0, .name = "ddrclk", }
21};
22
23/*
24 * Orion 5182
25 */
26
27#define SAR_MV88F5182_TCLK_FREQ 8
28#define SAR_MV88F5182_TCLK_FREQ_MASK 0x3
29
30static u32 __init mv88f5182_get_tclk_freq(void __iomem *sar)
31{
32 u32 opt = (readl(sar) >> SAR_MV88F5182_TCLK_FREQ) &
33 SAR_MV88F5182_TCLK_FREQ_MASK;
34 if (opt == 1)
35 return 150000000;
36 else if (opt == 2)
37 return 166666667;
38 else
39 return 0;
40}
41
42#define SAR_MV88F5182_CPU_FREQ 4
43#define SAR_MV88F5182_CPU_FREQ_MASK 0xf
44
45static u32 __init mv88f5182_get_cpu_freq(void __iomem *sar)
46{
47 u32 opt = (readl(sar) >> SAR_MV88F5182_CPU_FREQ) &
48 SAR_MV88F5182_CPU_FREQ_MASK;
49 if (opt == 0)
50 return 333333333;
51 else if (opt == 1 || opt == 2)
52 return 400000000;
53 else if (opt == 3)
54 return 500000000;
55 else
56 return 0;
57}
58
59static void __init mv88f5182_get_clk_ratio(void __iomem *sar, int id,
60 int *mult, int *div)
61{
62 u32 opt = (readl(sar) >> SAR_MV88F5182_CPU_FREQ) &
63 SAR_MV88F5182_CPU_FREQ_MASK;
64 if (opt == 0 || opt == 1) {
65 *mult = 1;
66 *div = 2;
67 } else if (opt == 2 || opt == 3) {
68 *mult = 1;
69 *div = 3;
70 } else {
71 *mult = 0;
72 *div = 1;
73 }
74}
75
76static const struct coreclk_soc_desc mv88f5182_coreclks = {
77 .get_tclk_freq = mv88f5182_get_tclk_freq,
78 .get_cpu_freq = mv88f5182_get_cpu_freq,
79 .get_clk_ratio = mv88f5182_get_clk_ratio,
80 .ratios = orion_coreclk_ratios,
81 .num_ratios = ARRAY_SIZE(orion_coreclk_ratios),
82};
83
84static void __init mv88f5182_clk_init(struct device_node *np)
85{
86 return mvebu_coreclk_setup(np, &mv88f5182_coreclks);
87}
88
89CLK_OF_DECLARE(mv88f5182_clk, "marvell,mv88f5182-core-clock", mv88f5182_clk_init);
90
91/*
92 * Orion 5281
93 */
94
95static u32 __init mv88f5281_get_tclk_freq(void __iomem *sar)
96{
97 /* On 5281, tclk is always 166 Mhz */
98 return 166666667;
99}
100
101#define SAR_MV88F5281_CPU_FREQ 4
102#define SAR_MV88F5281_CPU_FREQ_MASK 0xf
103
104static u32 __init mv88f5281_get_cpu_freq(void __iomem *sar)
105{
106 u32 opt = (readl(sar) >> SAR_MV88F5281_CPU_FREQ) &
107 SAR_MV88F5281_CPU_FREQ_MASK;
108 if (opt == 1 || opt == 2)
109 return 400000000;
110 else if (opt == 3)
111 return 500000000;
112 else
113 return 0;
114}
115
116static void __init mv88f5281_get_clk_ratio(void __iomem *sar, int id,
117 int *mult, int *div)
118{
119 u32 opt = (readl(sar) >> SAR_MV88F5281_CPU_FREQ) &
120 SAR_MV88F5281_CPU_FREQ_MASK;
121 if (opt == 1) {
122 *mult = 1;
123 *div = 2;
124 } else if (opt == 2 || opt == 3) {
125 *mult = 1;
126 *div = 3;
127 } else {
128 *mult = 0;
129 *div = 1;
130 }
131}
132
133static const struct coreclk_soc_desc mv88f5281_coreclks = {
134 .get_tclk_freq = mv88f5281_get_tclk_freq,
135 .get_cpu_freq = mv88f5281_get_cpu_freq,
136 .get_clk_ratio = mv88f5281_get_clk_ratio,
137 .ratios = orion_coreclk_ratios,
138 .num_ratios = ARRAY_SIZE(orion_coreclk_ratios),
139};
140
141static void __init mv88f5281_clk_init(struct device_node *np)
142{
143 return mvebu_coreclk_setup(np, &mv88f5281_coreclks);
144}
145
146CLK_OF_DECLARE(mv88f5281_clk, "marvell,mv88f5281-core-clock", mv88f5281_clk_init);
147
148/*
149 * Orion 6183
150 */
151
152#define SAR_MV88F6183_TCLK_FREQ 9
153#define SAR_MV88F6183_TCLK_FREQ_MASK 0x1
154
155static u32 __init mv88f6183_get_tclk_freq(void __iomem *sar)
156{
157 u32 opt = (readl(sar) >> SAR_MV88F6183_TCLK_FREQ) &
158 SAR_MV88F6183_TCLK_FREQ_MASK;
159 if (opt == 0)
160 return 133333333;
161 else if (opt == 1)
162 return 166666667;
163 else
164 return 0;
165}
166
167#define SAR_MV88F6183_CPU_FREQ 1
168#define SAR_MV88F6183_CPU_FREQ_MASK 0x3f
169
170static u32 __init mv88f6183_get_cpu_freq(void __iomem *sar)
171{
172 u32 opt = (readl(sar) >> SAR_MV88F6183_CPU_FREQ) &
173 SAR_MV88F6183_CPU_FREQ_MASK;
174 if (opt == 9)
175 return 333333333;
176 else if (opt == 17)
177 return 400000000;
178 else
179 return 0;
180}
181
182static void __init mv88f6183_get_clk_ratio(void __iomem *sar, int id,
183 int *mult, int *div)
184{
185 u32 opt = (readl(sar) >> SAR_MV88F6183_CPU_FREQ) &
186 SAR_MV88F6183_CPU_FREQ_MASK;
187 if (opt == 9 || opt == 17) {
188 *mult = 1;
189 *div = 2;
190 } else {
191 *mult = 0;
192 *div = 1;
193 }
194}
195
196static const struct coreclk_soc_desc mv88f6183_coreclks = {
197 .get_tclk_freq = mv88f6183_get_tclk_freq,
198 .get_cpu_freq = mv88f6183_get_cpu_freq,
199 .get_clk_ratio = mv88f6183_get_clk_ratio,
200 .ratios = orion_coreclk_ratios,
201 .num_ratios = ARRAY_SIZE(orion_coreclk_ratios),
202};
203
204
205static void __init mv88f6183_clk_init(struct device_node *np)
206{
207 return mvebu_coreclk_setup(np, &mv88f6183_coreclks);
208}
209
210CLK_OF_DECLARE(mv88f6183_clk, "marvell,mv88f6183-core-clock", mv88f6183_clk_init);
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 995bcfa021a4..7f696b7d4422 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -13,10 +13,10 @@ config MSM_GCC_8660
13 i2c, USB, SD/eMMC, etc. 13 i2c, USB, SD/eMMC, etc.
14 14
15config MSM_GCC_8960 15config MSM_GCC_8960
16 tristate "MSM8960 Global Clock Controller" 16 tristate "APQ8064/MSM8960 Global Clock Controller"
17 depends on COMMON_CLK_QCOM 17 depends on COMMON_CLK_QCOM
18 help 18 help
19 Support for the global clock controller on msm8960 devices. 19 Support for the global clock controller on apq8064/msm8960 devices.
20 Say Y if you want to use peripheral devices such as UART, SPI, 20 Say Y if you want to use peripheral devices such as UART, SPI,
21 i2c, USB, SD/eMMC, SATA, PCIe, etc. 21 i2c, USB, SD/eMMC, SATA, PCIe, etc.
22 22
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index f60db2ef1aee..689e05bf4f95 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -1,5 +1,6 @@
1obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o 1obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o
2 2
3clk-qcom-y += common.o
3clk-qcom-y += clk-regmap.o 4clk-qcom-y += clk-regmap.o
4clk-qcom-y += clk-pll.o 5clk-qcom-y += clk-pll.o
5clk-qcom-y += clk-rcg.o 6clk-qcom-y += clk-rcg.o
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index 1d6b6dece328..b9ec11dfd1b4 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -155,5 +155,8 @@ struct clk_rcg2 {
155#define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr) 155#define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
156 156
157extern const struct clk_ops clk_rcg2_ops; 157extern const struct clk_ops clk_rcg2_ops;
158extern const struct clk_ops clk_edp_pixel_ops;
159extern const struct clk_ops clk_byte_ops;
160extern const struct clk_ops clk_pixel_ops;
158 161
159#endif 162#endif
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 00f878a04d3f..cd185d5cc67a 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -19,6 +19,7 @@
19#include <linux/clk-provider.h> 19#include <linux/clk-provider.h>
20#include <linux/delay.h> 20#include <linux/delay.h>
21#include <linux/regmap.h> 21#include <linux/regmap.h>
22#include <linux/math64.h>
22 23
23#include <asm/div64.h> 24#include <asm/div64.h>
24 25
@@ -55,7 +56,7 @@ static int clk_rcg2_is_enabled(struct clk_hw *hw)
55 if (ret) 56 if (ret)
56 return ret; 57 return ret;
57 58
58 return (cmd & CMD_ROOT_OFF) != 0; 59 return (cmd & CMD_ROOT_OFF) == 0;
59} 60}
60 61
61static u8 clk_rcg2_get_parent(struct clk_hw *hw) 62static u8 clk_rcg2_get_parent(struct clk_hw *hw)
@@ -181,7 +182,8 @@ struct freq_tbl *find_freq(const struct freq_tbl *f, unsigned long rate)
181 if (rate <= f->freq) 182 if (rate <= f->freq)
182 return f; 183 return f;
183 184
184 return NULL; 185 /* Default to our fastest rate */
186 return f - 1;
185} 187}
186 188
187static long _freq_tbl_determine_rate(struct clk_hw *hw, 189static long _freq_tbl_determine_rate(struct clk_hw *hw,
@@ -224,31 +226,25 @@ static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
224 return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p); 226 return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
225} 227}
226 228
227static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate) 229static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
228{ 230{
229 struct clk_rcg2 *rcg = to_clk_rcg2(hw);
230 const struct freq_tbl *f;
231 u32 cfg, mask; 231 u32 cfg, mask;
232 int ret; 232 int ret;
233 233
234 f = find_freq(rcg->freq_tbl, rate);
235 if (!f)
236 return -EINVAL;
237
238 if (rcg->mnd_width && f->n) { 234 if (rcg->mnd_width && f->n) {
239 mask = BIT(rcg->mnd_width) - 1; 235 mask = BIT(rcg->mnd_width) - 1;
240 ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + M_REG, 236 ret = regmap_update_bits(rcg->clkr.regmap,
241 mask, f->m); 237 rcg->cmd_rcgr + M_REG, mask, f->m);
242 if (ret) 238 if (ret)
243 return ret; 239 return ret;
244 240
245 ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + N_REG, 241 ret = regmap_update_bits(rcg->clkr.regmap,
246 mask, ~(f->n - f->m)); 242 rcg->cmd_rcgr + N_REG, mask, ~(f->n - f->m));
247 if (ret) 243 if (ret)
248 return ret; 244 return ret;
249 245
250 ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + D_REG, 246 ret = regmap_update_bits(rcg->clkr.regmap,
251 mask, ~f->n); 247 rcg->cmd_rcgr + D_REG, mask, ~f->n);
252 if (ret) 248 if (ret)
253 return ret; 249 return ret;
254 } 250 }
@@ -259,14 +255,26 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
259 cfg |= rcg->parent_map[f->src] << CFG_SRC_SEL_SHIFT; 255 cfg |= rcg->parent_map[f->src] << CFG_SRC_SEL_SHIFT;
260 if (rcg->mnd_width && f->n) 256 if (rcg->mnd_width && f->n)
261 cfg |= CFG_MODE_DUAL_EDGE; 257 cfg |= CFG_MODE_DUAL_EDGE;
262 ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, mask, 258 ret = regmap_update_bits(rcg->clkr.regmap,
263 cfg); 259 rcg->cmd_rcgr + CFG_REG, mask, cfg);
264 if (ret) 260 if (ret)
265 return ret; 261 return ret;
266 262
267 return update_config(rcg); 263 return update_config(rcg);
268} 264}
269 265
266static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
267{
268 struct clk_rcg2 *rcg = to_clk_rcg2(hw);
269 const struct freq_tbl *f;
270
271 f = find_freq(rcg->freq_tbl, rate);
272 if (!f)
273 return -EINVAL;
274
275 return clk_rcg2_configure(rcg, f);
276}
277
270static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, 278static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
271 unsigned long parent_rate) 279 unsigned long parent_rate)
272{ 280{
@@ -289,3 +297,265 @@ const struct clk_ops clk_rcg2_ops = {
289 .set_rate_and_parent = clk_rcg2_set_rate_and_parent, 297 .set_rate_and_parent = clk_rcg2_set_rate_and_parent,
290}; 298};
291EXPORT_SYMBOL_GPL(clk_rcg2_ops); 299EXPORT_SYMBOL_GPL(clk_rcg2_ops);
300
301struct frac_entry {
302 int num;
303 int den;
304};
305
306static const struct frac_entry frac_table_675m[] = { /* link rate of 270M */
307 { 52, 295 }, /* 119 M */
308 { 11, 57 }, /* 130.25 M */
309 { 63, 307 }, /* 138.50 M */
310 { 11, 50 }, /* 148.50 M */
311 { 47, 206 }, /* 154 M */
312 { 31, 100 }, /* 205.25 M */
313 { 107, 269 }, /* 268.50 M */
314 { },
315};
316
317static struct frac_entry frac_table_810m[] = { /* Link rate of 162M */
318 { 31, 211 }, /* 119 M */
319 { 32, 199 }, /* 130.25 M */
320 { 63, 307 }, /* 138.50 M */
321 { 11, 60 }, /* 148.50 M */
322 { 50, 263 }, /* 154 M */
323 { 31, 120 }, /* 205.25 M */
324 { 119, 359 }, /* 268.50 M */
325 { },
326};
327
328static int clk_edp_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
329 unsigned long parent_rate)
330{
331 struct clk_rcg2 *rcg = to_clk_rcg2(hw);
332 struct freq_tbl f = *rcg->freq_tbl;
333 const struct frac_entry *frac;
334 int delta = 100000;
335 s64 src_rate = parent_rate;
336 s64 request;
337 u32 mask = BIT(rcg->hid_width) - 1;
338 u32 hid_div;
339
340 if (src_rate == 810000000)
341 frac = frac_table_810m;
342 else
343 frac = frac_table_675m;
344
345 for (; frac->num; frac++) {
346 request = rate;
347 request *= frac->den;
348 request = div_s64(request, frac->num);
349 if ((src_rate < (request - delta)) ||
350 (src_rate > (request + delta)))
351 continue;
352
353 regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
354 &hid_div);
355 f.pre_div = hid_div;
356 f.pre_div >>= CFG_SRC_DIV_SHIFT;
357 f.pre_div &= mask;
358 f.m = frac->num;
359 f.n = frac->den;
360
361 return clk_rcg2_configure(rcg, &f);
362 }
363
364 return -EINVAL;
365}
366
367static int clk_edp_pixel_set_rate_and_parent(struct clk_hw *hw,
368 unsigned long rate, unsigned long parent_rate, u8 index)
369{
370 /* Parent index is set statically in frequency table */
371 return clk_edp_pixel_set_rate(hw, rate, parent_rate);
372}
373
374static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
375 unsigned long *p_rate, struct clk **p)
376{
377 struct clk_rcg2 *rcg = to_clk_rcg2(hw);
378 const struct freq_tbl *f = rcg->freq_tbl;
379 const struct frac_entry *frac;
380 int delta = 100000;
381 s64 src_rate = *p_rate;
382 s64 request;
383 u32 mask = BIT(rcg->hid_width) - 1;
384 u32 hid_div;
385
386 /* Force the correct parent */
387 *p = clk_get_parent_by_index(hw->clk, f->src);
388
389 if (src_rate == 810000000)
390 frac = frac_table_810m;
391 else
392 frac = frac_table_675m;
393
394 for (; frac->num; frac++) {
395 request = rate;
396 request *= frac->den;
397 request = div_s64(request, frac->num);
398 if ((src_rate < (request - delta)) ||
399 (src_rate > (request + delta)))
400 continue;
401
402 regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
403 &hid_div);
404 hid_div >>= CFG_SRC_DIV_SHIFT;
405 hid_div &= mask;
406
407 return calc_rate(src_rate, frac->num, frac->den, !!frac->den,
408 hid_div);
409 }
410
411 return -EINVAL;
412}
413
414const struct clk_ops clk_edp_pixel_ops = {
415 .is_enabled = clk_rcg2_is_enabled,
416 .get_parent = clk_rcg2_get_parent,
417 .set_parent = clk_rcg2_set_parent,
418 .recalc_rate = clk_rcg2_recalc_rate,
419 .set_rate = clk_edp_pixel_set_rate,
420 .set_rate_and_parent = clk_edp_pixel_set_rate_and_parent,
421 .determine_rate = clk_edp_pixel_determine_rate,
422};
423EXPORT_SYMBOL_GPL(clk_edp_pixel_ops);
424
425static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
426 unsigned long *p_rate, struct clk **p)
427{
428 struct clk_rcg2 *rcg = to_clk_rcg2(hw);
429 const struct freq_tbl *f = rcg->freq_tbl;
430 unsigned long parent_rate, div;
431 u32 mask = BIT(rcg->hid_width) - 1;
432
433 if (rate == 0)
434 return -EINVAL;
435
436 *p = clk_get_parent_by_index(hw->clk, f->src);
437 *p_rate = parent_rate = __clk_round_rate(*p, rate);
438
439 div = DIV_ROUND_UP((2 * parent_rate), rate) - 1;
440 div = min_t(u32, div, mask);
441
442 return calc_rate(parent_rate, 0, 0, 0, div);
443}
444
445static int clk_byte_set_rate(struct clk_hw *hw, unsigned long rate,
446 unsigned long parent_rate)
447{
448 struct clk_rcg2 *rcg = to_clk_rcg2(hw);
449 struct freq_tbl f = *rcg->freq_tbl;
450 unsigned long div;
451 u32 mask = BIT(rcg->hid_width) - 1;
452
453 div = DIV_ROUND_UP((2 * parent_rate), rate) - 1;
454 div = min_t(u32, div, mask);
455
456 f.pre_div = div;
457
458 return clk_rcg2_configure(rcg, &f);
459}
460
461static int clk_byte_set_rate_and_parent(struct clk_hw *hw,
462 unsigned long rate, unsigned long parent_rate, u8 index)
463{
464 /* Parent index is set statically in frequency table */
465 return clk_byte_set_rate(hw, rate, parent_rate);
466}
467
468const struct clk_ops clk_byte_ops = {
469 .is_enabled = clk_rcg2_is_enabled,
470 .get_parent = clk_rcg2_get_parent,
471 .set_parent = clk_rcg2_set_parent,
472 .recalc_rate = clk_rcg2_recalc_rate,
473 .set_rate = clk_byte_set_rate,
474 .set_rate_and_parent = clk_byte_set_rate_and_parent,
475 .determine_rate = clk_byte_determine_rate,
476};
477EXPORT_SYMBOL_GPL(clk_byte_ops);
478
479static const struct frac_entry frac_table_pixel[] = {
480 { 3, 8 },
481 { 2, 9 },
482 { 4, 9 },
483 { 1, 1 },
484 { }
485};
486
487static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
488 unsigned long *p_rate, struct clk **p)
489{
490 struct clk_rcg2 *rcg = to_clk_rcg2(hw);
491 unsigned long request, src_rate;
492 int delta = 100000;
493 const struct freq_tbl *f = rcg->freq_tbl;
494 const struct frac_entry *frac = frac_table_pixel;
495 struct clk *parent = *p = clk_get_parent_by_index(hw->clk, f->src);
496
497 for (; frac->num; frac++) {
498 request = (rate * frac->den) / frac->num;
499
500 src_rate = __clk_round_rate(parent, request);
501 if ((src_rate < (request - delta)) ||
502 (src_rate > (request + delta)))
503 continue;
504
505 *p_rate = src_rate;
506 return (src_rate * frac->num) / frac->den;
507 }
508
509 return -EINVAL;
510}
511
512static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
513 unsigned long parent_rate)
514{
515 struct clk_rcg2 *rcg = to_clk_rcg2(hw);
516 struct freq_tbl f = *rcg->freq_tbl;
517 const struct frac_entry *frac = frac_table_pixel;
518 unsigned long request, src_rate;
519 int delta = 100000;
520 u32 mask = BIT(rcg->hid_width) - 1;
521 u32 hid_div;
522 struct clk *parent = clk_get_parent_by_index(hw->clk, f.src);
523
524 for (; frac->num; frac++) {
525 request = (rate * frac->den) / frac->num;
526
527 src_rate = __clk_round_rate(parent, request);
528 if ((src_rate < (request - delta)) ||
529 (src_rate > (request + delta)))
530 continue;
531
532 regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
533 &hid_div);
534 f.pre_div = hid_div;
535 f.pre_div >>= CFG_SRC_DIV_SHIFT;
536 f.pre_div &= mask;
537 f.m = frac->num;
538 f.n = frac->den;
539
540 return clk_rcg2_configure(rcg, &f);
541 }
542 return -EINVAL;
543}
544
545static int clk_pixel_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
546 unsigned long parent_rate, u8 index)
547{
548 /* Parent index is set statically in frequency table */
549 return clk_pixel_set_rate(hw, rate, parent_rate);
550}
551
552const struct clk_ops clk_pixel_ops = {
553 .is_enabled = clk_rcg2_is_enabled,
554 .get_parent = clk_rcg2_get_parent,
555 .set_parent = clk_rcg2_set_parent,
556 .recalc_rate = clk_rcg2_recalc_rate,
557 .set_rate = clk_pixel_set_rate,
558 .set_rate_and_parent = clk_pixel_set_rate_and_parent,
559 .determine_rate = clk_pixel_determine_rate,
560};
561EXPORT_SYMBOL_GPL(clk_pixel_ops);
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
new file mode 100644
index 000000000000..9b5a1cfc6b91
--- /dev/null
+++ b/drivers/clk/qcom/common.c
@@ -0,0 +1,101 @@
1/*
2 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/export.h>
15#include <linux/regmap.h>
16#include <linux/platform_device.h>
17#include <linux/clk-provider.h>
18#include <linux/reset-controller.h>
19
20#include "common.h"
21#include "clk-regmap.h"
22#include "reset.h"
23
24struct qcom_cc {
25 struct qcom_reset_controller reset;
26 struct clk_onecell_data data;
27 struct clk *clks[];
28};
29
30int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc)
31{
32 void __iomem *base;
33 struct resource *res;
34 int i, ret;
35 struct device *dev = &pdev->dev;
36 struct clk *clk;
37 struct clk_onecell_data *data;
38 struct clk **clks;
39 struct regmap *regmap;
40 struct qcom_reset_controller *reset;
41 struct qcom_cc *cc;
42 size_t num_clks = desc->num_clks;
43 struct clk_regmap **rclks = desc->clks;
44
45 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
46 base = devm_ioremap_resource(dev, res);
47 if (IS_ERR(base))
48 return PTR_ERR(base);
49
50 regmap = devm_regmap_init_mmio(dev, base, desc->config);
51 if (IS_ERR(regmap))
52 return PTR_ERR(regmap);
53
54 cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
55 GFP_KERNEL);
56 if (!cc)
57 return -ENOMEM;
58
59 clks = cc->clks;
60 data = &cc->data;
61 data->clks = clks;
62 data->clk_num = num_clks;
63
64 for (i = 0; i < num_clks; i++) {
65 if (!rclks[i]) {
66 clks[i] = ERR_PTR(-ENOENT);
67 continue;
68 }
69 clk = devm_clk_register_regmap(dev, rclks[i]);
70 if (IS_ERR(clk))
71 return PTR_ERR(clk);
72 clks[i] = clk;
73 }
74
75 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
76 if (ret)
77 return ret;
78
79 reset = &cc->reset;
80 reset->rcdev.of_node = dev->of_node;
81 reset->rcdev.ops = &qcom_reset_ops;
82 reset->rcdev.owner = dev->driver->owner;
83 reset->rcdev.nr_resets = desc->num_resets;
84 reset->regmap = regmap;
85 reset->reset_map = desc->resets;
86 platform_set_drvdata(pdev, &reset->rcdev);
87
88 ret = reset_controller_register(&reset->rcdev);
89 if (ret)
90 of_clk_del_provider(dev->of_node);
91
92 return ret;
93}
94EXPORT_SYMBOL_GPL(qcom_cc_probe);
95
96void qcom_cc_remove(struct platform_device *pdev)
97{
98 of_clk_del_provider(pdev->dev.of_node);
99 reset_controller_unregister(platform_get_drvdata(pdev));
100}
101EXPORT_SYMBOL_GPL(qcom_cc_remove);
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
new file mode 100644
index 000000000000..2c3cfc860348
--- /dev/null
+++ b/drivers/clk/qcom/common.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13#ifndef __QCOM_CLK_COMMON_H__
14#define __QCOM_CLK_COMMON_H__
15
16struct platform_device;
17struct regmap_config;
18struct clk_regmap;
19struct qcom_reset_map;
20
21struct qcom_cc_desc {
22 const struct regmap_config *config;
23 struct clk_regmap **clks;
24 size_t num_clks;
25 const struct qcom_reset_map *resets;
26 size_t num_resets;
27};
28
29extern int qcom_cc_probe(struct platform_device *pdev,
30 const struct qcom_cc_desc *desc);
31
32extern void qcom_cc_remove(struct platform_device *pdev);
33
34#endif
diff --git a/drivers/clk/qcom/gcc-msm8660.c b/drivers/clk/qcom/gcc-msm8660.c
index bc0b7f1fcfbe..0c4b727ae429 100644
--- a/drivers/clk/qcom/gcc-msm8660.c
+++ b/drivers/clk/qcom/gcc-msm8660.c
@@ -25,6 +25,7 @@
25#include <dt-bindings/clock/qcom,gcc-msm8660.h> 25#include <dt-bindings/clock/qcom,gcc-msm8660.h>
26#include <dt-bindings/reset/qcom,gcc-msm8660.h> 26#include <dt-bindings/reset/qcom,gcc-msm8660.h>
27 27
28#include "common.h"
28#include "clk-regmap.h" 29#include "clk-regmap.h"
29#include "clk-pll.h" 30#include "clk-pll.h"
30#include "clk-rcg.h" 31#include "clk-rcg.h"
@@ -2701,51 +2702,24 @@ static const struct regmap_config gcc_msm8660_regmap_config = {
2701 .fast_io = true, 2702 .fast_io = true,
2702}; 2703};
2703 2704
2705static const struct qcom_cc_desc gcc_msm8660_desc = {
2706 .config = &gcc_msm8660_regmap_config,
2707 .clks = gcc_msm8660_clks,
2708 .num_clks = ARRAY_SIZE(gcc_msm8660_clks),
2709 .resets = gcc_msm8660_resets,
2710 .num_resets = ARRAY_SIZE(gcc_msm8660_resets),
2711};
2712
2704static const struct of_device_id gcc_msm8660_match_table[] = { 2713static const struct of_device_id gcc_msm8660_match_table[] = {
2705 { .compatible = "qcom,gcc-msm8660" }, 2714 { .compatible = "qcom,gcc-msm8660" },
2706 { } 2715 { }
2707}; 2716};
2708MODULE_DEVICE_TABLE(of, gcc_msm8660_match_table); 2717MODULE_DEVICE_TABLE(of, gcc_msm8660_match_table);
2709 2718
2710struct qcom_cc {
2711 struct qcom_reset_controller reset;
2712 struct clk_onecell_data data;
2713 struct clk *clks[];
2714};
2715
2716static int gcc_msm8660_probe(struct platform_device *pdev) 2719static int gcc_msm8660_probe(struct platform_device *pdev)
2717{ 2720{
2718 void __iomem *base;
2719 struct resource *res;
2720 int i, ret;
2721 struct device *dev = &pdev->dev;
2722 struct clk *clk; 2721 struct clk *clk;
2723 struct clk_onecell_data *data; 2722 struct device *dev = &pdev->dev;
2724 struct clk **clks;
2725 struct regmap *regmap;
2726 size_t num_clks;
2727 struct qcom_reset_controller *reset;
2728 struct qcom_cc *cc;
2729
2730 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2731 base = devm_ioremap_resource(dev, res);
2732 if (IS_ERR(base))
2733 return PTR_ERR(base);
2734
2735 regmap = devm_regmap_init_mmio(dev, base, &gcc_msm8660_regmap_config);
2736 if (IS_ERR(regmap))
2737 return PTR_ERR(regmap);
2738
2739 num_clks = ARRAY_SIZE(gcc_msm8660_clks);
2740 cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
2741 GFP_KERNEL);
2742 if (!cc)
2743 return -ENOMEM;
2744
2745 clks = cc->clks;
2746 data = &cc->data;
2747 data->clks = clks;
2748 data->clk_num = num_clks;
2749 2723
2750 /* Temporary until RPM clocks supported */ 2724 /* Temporary until RPM clocks supported */
2751 clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000); 2725 clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000);
@@ -2756,39 +2730,12 @@ static int gcc_msm8660_probe(struct platform_device *pdev)
2756 if (IS_ERR(clk)) 2730 if (IS_ERR(clk))
2757 return PTR_ERR(clk); 2731 return PTR_ERR(clk);
2758 2732
2759 for (i = 0; i < num_clks; i++) { 2733 return qcom_cc_probe(pdev, &gcc_msm8660_desc);
2760 if (!gcc_msm8660_clks[i])
2761 continue;
2762 clk = devm_clk_register_regmap(dev, gcc_msm8660_clks[i]);
2763 if (IS_ERR(clk))
2764 return PTR_ERR(clk);
2765 clks[i] = clk;
2766 }
2767
2768 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
2769 if (ret)
2770 return ret;
2771
2772 reset = &cc->reset;
2773 reset->rcdev.of_node = dev->of_node;
2774 reset->rcdev.ops = &qcom_reset_ops,
2775 reset->rcdev.owner = THIS_MODULE,
2776 reset->rcdev.nr_resets = ARRAY_SIZE(gcc_msm8660_resets),
2777 reset->regmap = regmap;
2778 reset->reset_map = gcc_msm8660_resets,
2779 platform_set_drvdata(pdev, &reset->rcdev);
2780
2781 ret = reset_controller_register(&reset->rcdev);
2782 if (ret)
2783 of_clk_del_provider(dev->of_node);
2784
2785 return ret;
2786} 2734}
2787 2735
2788static int gcc_msm8660_remove(struct platform_device *pdev) 2736static int gcc_msm8660_remove(struct platform_device *pdev)
2789{ 2737{
2790 of_clk_del_provider(pdev->dev.of_node); 2738 qcom_cc_remove(pdev);
2791 reset_controller_unregister(platform_get_drvdata(pdev));
2792 return 0; 2739 return 0;
2793} 2740}
2794 2741
diff --git a/drivers/clk/qcom/gcc-msm8960.c b/drivers/clk/qcom/gcc-msm8960.c
index fd446ab2fd98..f4ffd91901f8 100644
--- a/drivers/clk/qcom/gcc-msm8960.c
+++ b/drivers/clk/qcom/gcc-msm8960.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2013, The Linux Foundation. All rights reserved. 2 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
3 * 3 *
4 * This software is licensed under the terms of the GNU General Public 4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and 5 * License version 2, as published by the Free Software Foundation, and
@@ -25,6 +25,7 @@
25#include <dt-bindings/clock/qcom,gcc-msm8960.h> 25#include <dt-bindings/clock/qcom,gcc-msm8960.h>
26#include <dt-bindings/reset/qcom,gcc-msm8960.h> 26#include <dt-bindings/reset/qcom,gcc-msm8960.h>
27 27
28#include "common.h"
28#include "clk-regmap.h" 29#include "clk-regmap.h"
29#include "clk-pll.h" 30#include "clk-pll.h"
30#include "clk-rcg.h" 31#include "clk-rcg.h"
@@ -2809,7 +2810,7 @@ static const struct qcom_reset_map gcc_msm8960_resets[] = {
2809 [PPSS_PROC_RESET] = { 0x2594, 1 }, 2810 [PPSS_PROC_RESET] = { 0x2594, 1 },
2810 [PPSS_RESET] = { 0x2594}, 2811 [PPSS_RESET] = { 0x2594},
2811 [DMA_BAM_RESET] = { 0x25c0, 7 }, 2812 [DMA_BAM_RESET] = { 0x25c0, 7 },
2812 [SIC_TIC_RESET] = { 0x2600, 7 }, 2813 [SPS_TIC_H_RESET] = { 0x2600, 7 },
2813 [SLIMBUS_H_RESET] = { 0x2620, 7 }, 2814 [SLIMBUS_H_RESET] = { 0x2620, 7 },
2814 [SFAB_CFPB_M_RESET] = { 0x2680, 7 }, 2815 [SFAB_CFPB_M_RESET] = { 0x2680, 7 },
2815 [SFAB_CFPB_S_RESET] = { 0x26c0, 7 }, 2816 [SFAB_CFPB_S_RESET] = { 0x26c0, 7 },
@@ -2822,7 +2823,7 @@ static const struct qcom_reset_map gcc_msm8960_resets[] = {
2822 [SFAB_SFPB_M_RESET] = { 0x2780, 7 }, 2823 [SFAB_SFPB_M_RESET] = { 0x2780, 7 },
2823 [SFAB_SFPB_S_RESET] = { 0x27a0, 7 }, 2824 [SFAB_SFPB_S_RESET] = { 0x27a0, 7 },
2824 [RPM_PROC_RESET] = { 0x27c0, 7 }, 2825 [RPM_PROC_RESET] = { 0x27c0, 7 },
2825 [PMIC_SSBI2_RESET] = { 0x270c, 12 }, 2826 [PMIC_SSBI2_RESET] = { 0x280c, 12 },
2826 [SDC1_RESET] = { 0x2830 }, 2827 [SDC1_RESET] = { 0x2830 },
2827 [SDC2_RESET] = { 0x2850 }, 2828 [SDC2_RESET] = { 0x2850 },
2828 [SDC3_RESET] = { 0x2870 }, 2829 [SDC3_RESET] = { 0x2870 },
@@ -2867,6 +2868,16 @@ static const struct qcom_reset_map gcc_msm8960_resets[] = {
2867 [RIVA_RESET] = { 0x35e0 }, 2868 [RIVA_RESET] = { 0x35e0 },
2868}; 2869};
2869 2870
2871static struct clk_regmap *gcc_apq8064_clks[] = {
2872 [PLL8] = &pll8.clkr,
2873 [PLL8_VOTE] = &pll8_vote,
2874 [GSBI7_UART_SRC] = &gsbi7_uart_src.clkr,
2875 [GSBI7_UART_CLK] = &gsbi7_uart_clk.clkr,
2876 [GSBI7_QUP_SRC] = &gsbi7_qup_src.clkr,
2877 [GSBI7_QUP_CLK] = &gsbi7_qup_clk.clkr,
2878 [GSBI7_H_CLK] = &gsbi7_h_clk.clkr,
2879};
2880
2870static const struct regmap_config gcc_msm8960_regmap_config = { 2881static const struct regmap_config gcc_msm8960_regmap_config = {
2871 .reg_bits = 32, 2882 .reg_bits = 32,
2872 .reg_stride = 4, 2883 .reg_stride = 4,
@@ -2875,51 +2886,38 @@ static const struct regmap_config gcc_msm8960_regmap_config = {
2875 .fast_io = true, 2886 .fast_io = true,
2876}; 2887};
2877 2888
2889static const struct qcom_cc_desc gcc_msm8960_desc = {
2890 .config = &gcc_msm8960_regmap_config,
2891 .clks = gcc_msm8960_clks,
2892 .num_clks = ARRAY_SIZE(gcc_msm8960_clks),
2893 .resets = gcc_msm8960_resets,
2894 .num_resets = ARRAY_SIZE(gcc_msm8960_resets),
2895};
2896
2897static const struct qcom_cc_desc gcc_apq8064_desc = {
2898 .config = &gcc_msm8960_regmap_config,
2899 .clks = gcc_apq8064_clks,
2900 .num_clks = ARRAY_SIZE(gcc_apq8064_clks),
2901 .resets = gcc_msm8960_resets,
2902 .num_resets = ARRAY_SIZE(gcc_msm8960_resets),
2903};
2904
2878static const struct of_device_id gcc_msm8960_match_table[] = { 2905static const struct of_device_id gcc_msm8960_match_table[] = {
2879 { .compatible = "qcom,gcc-msm8960" }, 2906 { .compatible = "qcom,gcc-msm8960", .data = &gcc_msm8960_desc },
2907 { .compatible = "qcom,gcc-apq8064", .data = &gcc_apq8064_desc },
2880 { } 2908 { }
2881}; 2909};
2882MODULE_DEVICE_TABLE(of, gcc_msm8960_match_table); 2910MODULE_DEVICE_TABLE(of, gcc_msm8960_match_table);
2883 2911
2884struct qcom_cc {
2885 struct qcom_reset_controller reset;
2886 struct clk_onecell_data data;
2887 struct clk *clks[];
2888};
2889
2890static int gcc_msm8960_probe(struct platform_device *pdev) 2912static int gcc_msm8960_probe(struct platform_device *pdev)
2891{ 2913{
2892 void __iomem *base;
2893 struct resource *res;
2894 int i, ret;
2895 struct device *dev = &pdev->dev;
2896 struct clk *clk; 2914 struct clk *clk;
2897 struct clk_onecell_data *data; 2915 struct device *dev = &pdev->dev;
2898 struct clk **clks; 2916 const struct of_device_id *match;
2899 struct regmap *regmap; 2917
2900 size_t num_clks; 2918 match = of_match_device(gcc_msm8960_match_table, &pdev->dev);
2901 struct qcom_reset_controller *reset; 2919 if (!match)
2902 struct qcom_cc *cc; 2920 return -EINVAL;
2903
2904 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2905 base = devm_ioremap_resource(dev, res);
2906 if (IS_ERR(base))
2907 return PTR_ERR(base);
2908
2909 regmap = devm_regmap_init_mmio(dev, base, &gcc_msm8960_regmap_config);
2910 if (IS_ERR(regmap))
2911 return PTR_ERR(regmap);
2912
2913 num_clks = ARRAY_SIZE(gcc_msm8960_clks);
2914 cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
2915 GFP_KERNEL);
2916 if (!cc)
2917 return -ENOMEM;
2918
2919 clks = cc->clks;
2920 data = &cc->data;
2921 data->clks = clks;
2922 data->clk_num = num_clks;
2923 2921
2924 /* Temporary until RPM clocks supported */ 2922 /* Temporary until RPM clocks supported */
2925 clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000); 2923 clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000);
@@ -2930,39 +2928,12 @@ static int gcc_msm8960_probe(struct platform_device *pdev)
2930 if (IS_ERR(clk)) 2928 if (IS_ERR(clk))
2931 return PTR_ERR(clk); 2929 return PTR_ERR(clk);
2932 2930
2933 for (i = 0; i < num_clks; i++) { 2931 return qcom_cc_probe(pdev, match->data);
2934 if (!gcc_msm8960_clks[i])
2935 continue;
2936 clk = devm_clk_register_regmap(dev, gcc_msm8960_clks[i]);
2937 if (IS_ERR(clk))
2938 return PTR_ERR(clk);
2939 clks[i] = clk;
2940 }
2941
2942 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
2943 if (ret)
2944 return ret;
2945
2946 reset = &cc->reset;
2947 reset->rcdev.of_node = dev->of_node;
2948 reset->rcdev.ops = &qcom_reset_ops,
2949 reset->rcdev.owner = THIS_MODULE,
2950 reset->rcdev.nr_resets = ARRAY_SIZE(gcc_msm8960_resets),
2951 reset->regmap = regmap;
2952 reset->reset_map = gcc_msm8960_resets,
2953 platform_set_drvdata(pdev, &reset->rcdev);
2954
2955 ret = reset_controller_register(&reset->rcdev);
2956 if (ret)
2957 of_clk_del_provider(dev->of_node);
2958
2959 return ret;
2960} 2932}
2961 2933
2962static int gcc_msm8960_remove(struct platform_device *pdev) 2934static int gcc_msm8960_remove(struct platform_device *pdev)
2963{ 2935{
2964 of_clk_del_provider(pdev->dev.of_node); 2936 qcom_cc_remove(pdev);
2965 reset_controller_unregister(platform_get_drvdata(pdev));
2966 return 0; 2937 return 0;
2967} 2938}
2968 2939
diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c
index 51d457e2b959..7af7c18d2144 100644
--- a/drivers/clk/qcom/gcc-msm8974.c
+++ b/drivers/clk/qcom/gcc-msm8974.c
@@ -25,6 +25,7 @@
25#include <dt-bindings/clock/qcom,gcc-msm8974.h> 25#include <dt-bindings/clock/qcom,gcc-msm8974.h>
26#include <dt-bindings/reset/qcom,gcc-msm8974.h> 26#include <dt-bindings/reset/qcom,gcc-msm8974.h>
27 27
28#include "common.h"
28#include "clk-regmap.h" 29#include "clk-regmap.h"
29#include "clk-pll.h" 30#include "clk-pll.h"
30#include "clk-rcg.h" 31#include "clk-rcg.h"
@@ -34,6 +35,7 @@
34#define P_XO 0 35#define P_XO 0
35#define P_GPLL0 1 36#define P_GPLL0 1
36#define P_GPLL1 1 37#define P_GPLL1 1
38#define P_GPLL4 2
37 39
38static const u8 gcc_xo_gpll0_map[] = { 40static const u8 gcc_xo_gpll0_map[] = {
39 [P_XO] = 0, 41 [P_XO] = 0,
@@ -45,6 +47,18 @@ static const char *gcc_xo_gpll0[] = {
45 "gpll0_vote", 47 "gpll0_vote",
46}; 48};
47 49
50static const u8 gcc_xo_gpll0_gpll4_map[] = {
51 [P_XO] = 0,
52 [P_GPLL0] = 1,
53 [P_GPLL4] = 5,
54};
55
56static const char *gcc_xo_gpll0_gpll4[] = {
57 "xo",
58 "gpll0_vote",
59 "gpll4_vote",
60};
61
48#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } 62#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
49 63
50static struct clk_pll gpll0 = { 64static struct clk_pll gpll0 = {
@@ -137,6 +151,33 @@ static struct clk_regmap gpll1_vote = {
137 }, 151 },
138}; 152};
139 153
154static struct clk_pll gpll4 = {
155 .l_reg = 0x1dc4,
156 .m_reg = 0x1dc8,
157 .n_reg = 0x1dcc,
158 .config_reg = 0x1dd4,
159 .mode_reg = 0x1dc0,
160 .status_reg = 0x1ddc,
161 .status_bit = 17,
162 .clkr.hw.init = &(struct clk_init_data){
163 .name = "gpll4",
164 .parent_names = (const char *[]){ "xo" },
165 .num_parents = 1,
166 .ops = &clk_pll_ops,
167 },
168};
169
170static struct clk_regmap gpll4_vote = {
171 .enable_reg = 0x1480,
172 .enable_mask = BIT(4),
173 .hw.init = &(struct clk_init_data){
174 .name = "gpll4_vote",
175 .parent_names = (const char *[]){ "gpll4" },
176 .num_parents = 1,
177 .ops = &clk_pll_vote_ops,
178 },
179};
180
140static const struct freq_tbl ftbl_gcc_usb30_master_clk[] = { 181static const struct freq_tbl ftbl_gcc_usb30_master_clk[] = {
141 F(125000000, P_GPLL0, 1, 5, 24), 182 F(125000000, P_GPLL0, 1, 5, 24),
142 { } 183 { }
@@ -811,18 +852,33 @@ static const struct freq_tbl ftbl_gcc_sdcc1_4_apps_clk[] = {
811 { } 852 { }
812}; 853};
813 854
855static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_pro[] = {
856 F(144000, P_XO, 16, 3, 25),
857 F(400000, P_XO, 12, 1, 4),
858 F(20000000, P_GPLL0, 15, 1, 2),
859 F(25000000, P_GPLL0, 12, 1, 2),
860 F(50000000, P_GPLL0, 12, 0, 0),
861 F(100000000, P_GPLL0, 6, 0, 0),
862 F(192000000, P_GPLL4, 4, 0, 0),
863 F(200000000, P_GPLL0, 3, 0, 0),
864 F(384000000, P_GPLL4, 2, 0, 0),
865 { }
866};
867
868static struct clk_init_data sdcc1_apps_clk_src_init = {
869 .name = "sdcc1_apps_clk_src",
870 .parent_names = gcc_xo_gpll0,
871 .num_parents = 2,
872 .ops = &clk_rcg2_ops,
873};
874
814static struct clk_rcg2 sdcc1_apps_clk_src = { 875static struct clk_rcg2 sdcc1_apps_clk_src = {
815 .cmd_rcgr = 0x04d0, 876 .cmd_rcgr = 0x04d0,
816 .mnd_width = 8, 877 .mnd_width = 8,
817 .hid_width = 5, 878 .hid_width = 5,
818 .parent_map = gcc_xo_gpll0_map, 879 .parent_map = gcc_xo_gpll0_map,
819 .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk, 880 .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
820 .clkr.hw.init = &(struct clk_init_data){ 881 .clkr.hw.init = &sdcc1_apps_clk_src_init,
821 .name = "sdcc1_apps_clk_src",
822 .parent_names = gcc_xo_gpll0,
823 .num_parents = 2,
824 .ops = &clk_rcg2_ops,
825 },
826}; 882};
827 883
828static struct clk_rcg2 sdcc2_apps_clk_src = { 884static struct clk_rcg2 sdcc2_apps_clk_src = {
@@ -1340,7 +1396,7 @@ static struct clk_branch gcc_blsp1_uart6_apps_clk = {
1340}; 1396};
1341 1397
1342static struct clk_branch gcc_blsp2_ahb_clk = { 1398static struct clk_branch gcc_blsp2_ahb_clk = {
1343 .halt_reg = 0x05c4, 1399 .halt_reg = 0x0944,
1344 .halt_check = BRANCH_HALT_VOTED, 1400 .halt_check = BRANCH_HALT_VOTED,
1345 .clkr = { 1401 .clkr = {
1346 .enable_reg = 0x1484, 1402 .enable_reg = 0x1484,
@@ -1994,6 +2050,38 @@ static struct clk_branch gcc_sdcc1_apps_clk = {
1994 }, 2050 },
1995}; 2051};
1996 2052
2053static struct clk_branch gcc_sdcc1_cdccal_ff_clk = {
2054 .halt_reg = 0x04e8,
2055 .clkr = {
2056 .enable_reg = 0x04e8,
2057 .enable_mask = BIT(0),
2058 .hw.init = &(struct clk_init_data){
2059 .name = "gcc_sdcc1_cdccal_ff_clk",
2060 .parent_names = (const char *[]){
2061 "xo"
2062 },
2063 .num_parents = 1,
2064 .ops = &clk_branch2_ops,
2065 },
2066 },
2067};
2068
2069static struct clk_branch gcc_sdcc1_cdccal_sleep_clk = {
2070 .halt_reg = 0x04e4,
2071 .clkr = {
2072 .enable_reg = 0x04e4,
2073 .enable_mask = BIT(0),
2074 .hw.init = &(struct clk_init_data){
2075 .name = "gcc_sdcc1_cdccal_sleep_clk",
2076 .parent_names = (const char *[]){
2077 "sleep_clk_src"
2078 },
2079 .num_parents = 1,
2080 .ops = &clk_branch2_ops,
2081 },
2082 },
2083};
2084
1997static struct clk_branch gcc_sdcc2_ahb_clk = { 2085static struct clk_branch gcc_sdcc2_ahb_clk = {
1998 .halt_reg = 0x0508, 2086 .halt_reg = 0x0508,
1999 .clkr = { 2087 .clkr = {
@@ -2483,6 +2571,10 @@ static struct clk_regmap *gcc_msm8974_clocks[] = {
2483 [GCC_USB_HSIC_IO_CAL_SLEEP_CLK] = &gcc_usb_hsic_io_cal_sleep_clk.clkr, 2571 [GCC_USB_HSIC_IO_CAL_SLEEP_CLK] = &gcc_usb_hsic_io_cal_sleep_clk.clkr,
2484 [GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.clkr, 2572 [GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.clkr,
2485 [GCC_MMSS_GPLL0_CLK_SRC] = &gcc_mmss_gpll0_clk_src, 2573 [GCC_MMSS_GPLL0_CLK_SRC] = &gcc_mmss_gpll0_clk_src,
2574 [GPLL4] = NULL,
2575 [GPLL4_VOTE] = NULL,
2576 [GCC_SDCC1_CDCCAL_SLEEP_CLK] = NULL,
2577 [GCC_SDCC1_CDCCAL_FF_CLK] = NULL,
2486}; 2578};
2487 2579
2488static const struct qcom_reset_map gcc_msm8974_resets[] = { 2580static const struct qcom_reset_map gcc_msm8974_resets[] = {
@@ -2574,51 +2666,51 @@ static const struct regmap_config gcc_msm8974_regmap_config = {
2574 .fast_io = true, 2666 .fast_io = true,
2575}; 2667};
2576 2668
2669static const struct qcom_cc_desc gcc_msm8974_desc = {
2670 .config = &gcc_msm8974_regmap_config,
2671 .clks = gcc_msm8974_clocks,
2672 .num_clks = ARRAY_SIZE(gcc_msm8974_clocks),
2673 .resets = gcc_msm8974_resets,
2674 .num_resets = ARRAY_SIZE(gcc_msm8974_resets),
2675};
2676
2577static const struct of_device_id gcc_msm8974_match_table[] = { 2677static const struct of_device_id gcc_msm8974_match_table[] = {
2578 { .compatible = "qcom,gcc-msm8974" }, 2678 { .compatible = "qcom,gcc-msm8974" },
2679 { .compatible = "qcom,gcc-msm8974pro" , .data = (void *)1UL },
2680 { .compatible = "qcom,gcc-msm8974pro-ac", .data = (void *)1UL },
2579 { } 2681 { }
2580}; 2682};
2581MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table); 2683MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table);
2582 2684
2583struct qcom_cc { 2685static void msm8974_pro_clock_override(void)
2584 struct qcom_reset_controller reset; 2686{
2585 struct clk_onecell_data data; 2687 sdcc1_apps_clk_src_init.parent_names = gcc_xo_gpll0_gpll4;
2586 struct clk *clks[]; 2688 sdcc1_apps_clk_src_init.num_parents = 3;
2587}; 2689 sdcc1_apps_clk_src.freq_tbl = ftbl_gcc_sdcc1_apps_clk_pro;
2690 sdcc1_apps_clk_src.parent_map = gcc_xo_gpll0_gpll4_map;
2691
2692 gcc_msm8974_clocks[GPLL4] = &gpll4.clkr;
2693 gcc_msm8974_clocks[GPLL4_VOTE] = &gpll4_vote;
2694 gcc_msm8974_clocks[GCC_SDCC1_CDCCAL_SLEEP_CLK] =
2695 &gcc_sdcc1_cdccal_sleep_clk.clkr;
2696 gcc_msm8974_clocks[GCC_SDCC1_CDCCAL_FF_CLK] =
2697 &gcc_sdcc1_cdccal_ff_clk.clkr;
2698}
2588 2699
2589static int gcc_msm8974_probe(struct platform_device *pdev) 2700static int gcc_msm8974_probe(struct platform_device *pdev)
2590{ 2701{
2591 void __iomem *base;
2592 struct resource *res;
2593 int i, ret;
2594 struct device *dev = &pdev->dev;
2595 struct clk *clk; 2702 struct clk *clk;
2596 struct clk_onecell_data *data; 2703 struct device *dev = &pdev->dev;
2597 struct clk **clks; 2704 bool pro;
2598 struct regmap *regmap; 2705 const struct of_device_id *id;
2599 size_t num_clks; 2706
2600 struct qcom_reset_controller *reset; 2707 id = of_match_device(gcc_msm8974_match_table, dev);
2601 struct qcom_cc *cc; 2708 if (!id)
2602 2709 return -ENODEV;
2603 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2710 pro = !!(id->data);
2604 base = devm_ioremap_resource(dev, res); 2711
2605 if (IS_ERR(base)) 2712 if (pro)
2606 return PTR_ERR(base); 2713 msm8974_pro_clock_override();
2607
2608 regmap = devm_regmap_init_mmio(dev, base, &gcc_msm8974_regmap_config);
2609 if (IS_ERR(regmap))
2610 return PTR_ERR(regmap);
2611
2612 num_clks = ARRAY_SIZE(gcc_msm8974_clocks);
2613 cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
2614 GFP_KERNEL);
2615 if (!cc)
2616 return -ENOMEM;
2617
2618 clks = cc->clks;
2619 data = &cc->data;
2620 data->clks = clks;
2621 data->clk_num = num_clks;
2622 2714
2623 /* Temporary until RPM clocks supported */ 2715 /* Temporary until RPM clocks supported */
2624 clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000); 2716 clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000);
@@ -2631,39 +2723,12 @@ static int gcc_msm8974_probe(struct platform_device *pdev)
2631 if (IS_ERR(clk)) 2723 if (IS_ERR(clk))
2632 return PTR_ERR(clk); 2724 return PTR_ERR(clk);
2633 2725
2634 for (i = 0; i < num_clks; i++) { 2726 return qcom_cc_probe(pdev, &gcc_msm8974_desc);
2635 if (!gcc_msm8974_clocks[i])
2636 continue;
2637 clk = devm_clk_register_regmap(dev, gcc_msm8974_clocks[i]);
2638 if (IS_ERR(clk))
2639 return PTR_ERR(clk);
2640 clks[i] = clk;
2641 }
2642
2643 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
2644 if (ret)
2645 return ret;
2646
2647 reset = &cc->reset;
2648 reset->rcdev.of_node = dev->of_node;
2649 reset->rcdev.ops = &qcom_reset_ops,
2650 reset->rcdev.owner = THIS_MODULE,
2651 reset->rcdev.nr_resets = ARRAY_SIZE(gcc_msm8974_resets),
2652 reset->regmap = regmap;
2653 reset->reset_map = gcc_msm8974_resets,
2654 platform_set_drvdata(pdev, &reset->rcdev);
2655
2656 ret = reset_controller_register(&reset->rcdev);
2657 if (ret)
2658 of_clk_del_provider(dev->of_node);
2659
2660 return ret;
2661} 2727}
2662 2728
2663static int gcc_msm8974_remove(struct platform_device *pdev) 2729static int gcc_msm8974_remove(struct platform_device *pdev)
2664{ 2730{
2665 of_clk_del_provider(pdev->dev.of_node); 2731 qcom_cc_remove(pdev);
2666 reset_controller_unregister(platform_get_drvdata(pdev));
2667 return 0; 2732 return 0;
2668} 2733}
2669 2734
diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c
index f9b59c7e48e9..12f3c0b64fcd 100644
--- a/drivers/clk/qcom/mmcc-msm8960.c
+++ b/drivers/clk/qcom/mmcc-msm8960.c
@@ -26,6 +26,7 @@
26#include <dt-bindings/clock/qcom,mmcc-msm8960.h> 26#include <dt-bindings/clock/qcom,mmcc-msm8960.h>
27#include <dt-bindings/reset/qcom,mmcc-msm8960.h> 27#include <dt-bindings/reset/qcom,mmcc-msm8960.h>
28 28
29#include "common.h"
29#include "clk-regmap.h" 30#include "clk-regmap.h"
30#include "clk-pll.h" 31#include "clk-pll.h"
31#include "clk-rcg.h" 32#include "clk-rcg.h"
@@ -2222,85 +2223,28 @@ static const struct regmap_config mmcc_msm8960_regmap_config = {
2222 .fast_io = true, 2223 .fast_io = true,
2223}; 2224};
2224 2225
2226static const struct qcom_cc_desc mmcc_msm8960_desc = {
2227 .config = &mmcc_msm8960_regmap_config,
2228 .clks = mmcc_msm8960_clks,
2229 .num_clks = ARRAY_SIZE(mmcc_msm8960_clks),
2230 .resets = mmcc_msm8960_resets,
2231 .num_resets = ARRAY_SIZE(mmcc_msm8960_resets),
2232};
2233
2225static const struct of_device_id mmcc_msm8960_match_table[] = { 2234static const struct of_device_id mmcc_msm8960_match_table[] = {
2226 { .compatible = "qcom,mmcc-msm8960" }, 2235 { .compatible = "qcom,mmcc-msm8960" },
2227 { } 2236 { }
2228}; 2237};
2229MODULE_DEVICE_TABLE(of, mmcc_msm8960_match_table); 2238MODULE_DEVICE_TABLE(of, mmcc_msm8960_match_table);
2230 2239
2231struct qcom_cc {
2232 struct qcom_reset_controller reset;
2233 struct clk_onecell_data data;
2234 struct clk *clks[];
2235};
2236
2237static int mmcc_msm8960_probe(struct platform_device *pdev) 2240static int mmcc_msm8960_probe(struct platform_device *pdev)
2238{ 2241{
2239 void __iomem *base; 2242 return qcom_cc_probe(pdev, &mmcc_msm8960_desc);
2240 struct resource *res;
2241 int i, ret;
2242 struct device *dev = &pdev->dev;
2243 struct clk *clk;
2244 struct clk_onecell_data *data;
2245 struct clk **clks;
2246 struct regmap *regmap;
2247 size_t num_clks;
2248 struct qcom_reset_controller *reset;
2249 struct qcom_cc *cc;
2250
2251 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2252 base = devm_ioremap_resource(dev, res);
2253 if (IS_ERR(base))
2254 return PTR_ERR(base);
2255
2256 regmap = devm_regmap_init_mmio(dev, base, &mmcc_msm8960_regmap_config);
2257 if (IS_ERR(regmap))
2258 return PTR_ERR(regmap);
2259
2260 num_clks = ARRAY_SIZE(mmcc_msm8960_clks);
2261 cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
2262 GFP_KERNEL);
2263 if (!cc)
2264 return -ENOMEM;
2265
2266 clks = cc->clks;
2267 data = &cc->data;
2268 data->clks = clks;
2269 data->clk_num = num_clks;
2270
2271 for (i = 0; i < num_clks; i++) {
2272 if (!mmcc_msm8960_clks[i])
2273 continue;
2274 clk = devm_clk_register_regmap(dev, mmcc_msm8960_clks[i]);
2275 if (IS_ERR(clk))
2276 return PTR_ERR(clk);
2277 clks[i] = clk;
2278 }
2279
2280 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
2281 if (ret)
2282 return ret;
2283
2284 reset = &cc->reset;
2285 reset->rcdev.of_node = dev->of_node;
2286 reset->rcdev.ops = &qcom_reset_ops,
2287 reset->rcdev.owner = THIS_MODULE,
2288 reset->rcdev.nr_resets = ARRAY_SIZE(mmcc_msm8960_resets),
2289 reset->regmap = regmap;
2290 reset->reset_map = mmcc_msm8960_resets,
2291 platform_set_drvdata(pdev, &reset->rcdev);
2292
2293 ret = reset_controller_register(&reset->rcdev);
2294 if (ret)
2295 of_clk_del_provider(dev->of_node);
2296
2297 return ret;
2298} 2243}
2299 2244
2300static int mmcc_msm8960_remove(struct platform_device *pdev) 2245static int mmcc_msm8960_remove(struct platform_device *pdev)
2301{ 2246{
2302 of_clk_del_provider(pdev->dev.of_node); 2247 qcom_cc_remove(pdev);
2303 reset_controller_unregister(platform_get_drvdata(pdev));
2304 return 0; 2248 return 0;
2305} 2249}
2306 2250
diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c
index c95774514b81..c65b90515872 100644
--- a/drivers/clk/qcom/mmcc-msm8974.c
+++ b/drivers/clk/qcom/mmcc-msm8974.c
@@ -25,6 +25,7 @@
25#include <dt-bindings/clock/qcom,mmcc-msm8974.h> 25#include <dt-bindings/clock/qcom,mmcc-msm8974.h>
26#include <dt-bindings/reset/qcom,mmcc-msm8974.h> 26#include <dt-bindings/reset/qcom,mmcc-msm8974.h>
27 27
28#include "common.h"
28#include "clk-regmap.h" 29#include "clk-regmap.h"
29#include "clk-pll.h" 30#include "clk-pll.h"
30#include "clk-rcg.h" 31#include "clk-rcg.h"
@@ -40,9 +41,11 @@
40#define P_EDPVCO 3 41#define P_EDPVCO 3
41#define P_GPLL1 4 42#define P_GPLL1 4
42#define P_DSI0PLL 4 43#define P_DSI0PLL 4
44#define P_DSI0PLL_BYTE 4
43#define P_MMPLL2 4 45#define P_MMPLL2 4
44#define P_MMPLL3 4 46#define P_MMPLL3 4
45#define P_DSI1PLL 5 47#define P_DSI1PLL 5
48#define P_DSI1PLL_BYTE 5
46 49
47static const u8 mmcc_xo_mmpll0_mmpll1_gpll0_map[] = { 50static const u8 mmcc_xo_mmpll0_mmpll1_gpll0_map[] = {
48 [P_XO] = 0, 51 [P_XO] = 0,
@@ -160,6 +163,24 @@ static const char *mmcc_xo_dsi_hdmi_edp_gpll0[] = {
160 "dsi1pll", 163 "dsi1pll",
161}; 164};
162 165
166static const u8 mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = {
167 [P_XO] = 0,
168 [P_EDPLINK] = 4,
169 [P_HDMIPLL] = 3,
170 [P_GPLL0] = 5,
171 [P_DSI0PLL_BYTE] = 1,
172 [P_DSI1PLL_BYTE] = 2,
173};
174
175static const char *mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
176 "xo",
177 "edp_link_clk",
178 "hdmipll",
179 "gpll0_vote",
180 "dsi0pllbyte",
181 "dsi1pllbyte",
182};
183
163#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } 184#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
164 185
165static struct clk_pll mmpll0 = { 186static struct clk_pll mmpll0 = {
@@ -169,6 +190,7 @@ static struct clk_pll mmpll0 = {
169 .config_reg = 0x0014, 190 .config_reg = 0x0014,
170 .mode_reg = 0x0000, 191 .mode_reg = 0x0000,
171 .status_reg = 0x001c, 192 .status_reg = 0x001c,
193 .status_bit = 17,
172 .clkr.hw.init = &(struct clk_init_data){ 194 .clkr.hw.init = &(struct clk_init_data){
173 .name = "mmpll0", 195 .name = "mmpll0",
174 .parent_names = (const char *[]){ "xo" }, 196 .parent_names = (const char *[]){ "xo" },
@@ -192,9 +214,10 @@ static struct clk_pll mmpll1 = {
192 .l_reg = 0x0044, 214 .l_reg = 0x0044,
193 .m_reg = 0x0048, 215 .m_reg = 0x0048,
194 .n_reg = 0x004c, 216 .n_reg = 0x004c,
195 .config_reg = 0x0054, 217 .config_reg = 0x0050,
196 .mode_reg = 0x0040, 218 .mode_reg = 0x0040,
197 .status_reg = 0x005c, 219 .status_reg = 0x005c,
220 .status_bit = 17,
198 .clkr.hw.init = &(struct clk_init_data){ 221 .clkr.hw.init = &(struct clk_init_data){
199 .name = "mmpll1", 222 .name = "mmpll1",
200 .parent_names = (const char *[]){ "xo" }, 223 .parent_names = (const char *[]){ "xo" },
@@ -218,7 +241,7 @@ static struct clk_pll mmpll2 = {
218 .l_reg = 0x4104, 241 .l_reg = 0x4104,
219 .m_reg = 0x4108, 242 .m_reg = 0x4108,
220 .n_reg = 0x410c, 243 .n_reg = 0x410c,
221 .config_reg = 0x4114, 244 .config_reg = 0x4110,
222 .mode_reg = 0x4100, 245 .mode_reg = 0x4100,
223 .status_reg = 0x411c, 246 .status_reg = 0x411c,
224 .clkr.hw.init = &(struct clk_init_data){ 247 .clkr.hw.init = &(struct clk_init_data){
@@ -233,9 +256,10 @@ static struct clk_pll mmpll3 = {
233 .l_reg = 0x0084, 256 .l_reg = 0x0084,
234 .m_reg = 0x0088, 257 .m_reg = 0x0088,
235 .n_reg = 0x008c, 258 .n_reg = 0x008c,
236 .config_reg = 0x0094, 259 .config_reg = 0x0090,
237 .mode_reg = 0x0080, 260 .mode_reg = 0x0080,
238 .status_reg = 0x009c, 261 .status_reg = 0x009c,
262 .status_bit = 17,
239 .clkr.hw.init = &(struct clk_init_data){ 263 .clkr.hw.init = &(struct clk_init_data){
240 .name = "mmpll3", 264 .name = "mmpll3",
241 .parent_names = (const char *[]){ "xo" }, 265 .parent_names = (const char *[]){ "xo" },
@@ -496,15 +520,8 @@ static struct clk_rcg2 jpeg2_clk_src = {
496 }, 520 },
497}; 521};
498 522
499static struct freq_tbl ftbl_mdss_pclk0_clk[] = { 523static struct freq_tbl pixel_freq_tbl[] = {
500 F(125000000, P_DSI0PLL, 2, 0, 0), 524 { .src = P_DSI0PLL },
501 F(250000000, P_DSI0PLL, 1, 0, 0),
502 { }
503};
504
505static struct freq_tbl ftbl_mdss_pclk1_clk[] = {
506 F(125000000, P_DSI1PLL, 2, 0, 0),
507 F(250000000, P_DSI1PLL, 1, 0, 0),
508 { } 525 { }
509}; 526};
510 527
@@ -513,12 +530,13 @@ static struct clk_rcg2 pclk0_clk_src = {
513 .mnd_width = 8, 530 .mnd_width = 8,
514 .hid_width = 5, 531 .hid_width = 5,
515 .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, 532 .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
516 .freq_tbl = ftbl_mdss_pclk0_clk, 533 .freq_tbl = pixel_freq_tbl,
517 .clkr.hw.init = &(struct clk_init_data){ 534 .clkr.hw.init = &(struct clk_init_data){
518 .name = "pclk0_clk_src", 535 .name = "pclk0_clk_src",
519 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, 536 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
520 .num_parents = 6, 537 .num_parents = 6,
521 .ops = &clk_rcg2_ops, 538 .ops = &clk_pixel_ops,
539 .flags = CLK_SET_RATE_PARENT,
522 }, 540 },
523}; 541};
524 542
@@ -527,12 +545,13 @@ static struct clk_rcg2 pclk1_clk_src = {
527 .mnd_width = 8, 545 .mnd_width = 8,
528 .hid_width = 5, 546 .hid_width = 5,
529 .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, 547 .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
530 .freq_tbl = ftbl_mdss_pclk1_clk, 548 .freq_tbl = pixel_freq_tbl,
531 .clkr.hw.init = &(struct clk_init_data){ 549 .clkr.hw.init = &(struct clk_init_data){
532 .name = "pclk1_clk_src", 550 .name = "pclk1_clk_src",
533 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, 551 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
534 .num_parents = 6, 552 .num_parents = 6,
535 .ops = &clk_rcg2_ops, 553 .ops = &clk_pixel_ops,
554 .flags = CLK_SET_RATE_PARENT,
536 }, 555 },
537}; 556};
538 557
@@ -750,41 +769,36 @@ static struct clk_rcg2 cpp_clk_src = {
750 }, 769 },
751}; 770};
752 771
753static struct freq_tbl ftbl_mdss_byte0_clk[] = { 772static struct freq_tbl byte_freq_tbl[] = {
754 F(93750000, P_DSI0PLL, 8, 0, 0), 773 { .src = P_DSI0PLL_BYTE },
755 F(187500000, P_DSI0PLL, 4, 0, 0),
756 { }
757};
758
759static struct freq_tbl ftbl_mdss_byte1_clk[] = {
760 F(93750000, P_DSI1PLL, 8, 0, 0),
761 F(187500000, P_DSI1PLL, 4, 0, 0),
762 { } 774 { }
763}; 775};
764 776
765static struct clk_rcg2 byte0_clk_src = { 777static struct clk_rcg2 byte0_clk_src = {
766 .cmd_rcgr = 0x2120, 778 .cmd_rcgr = 0x2120,
767 .hid_width = 5, 779 .hid_width = 5,
768 .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, 780 .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
769 .freq_tbl = ftbl_mdss_byte0_clk, 781 .freq_tbl = byte_freq_tbl,
770 .clkr.hw.init = &(struct clk_init_data){ 782 .clkr.hw.init = &(struct clk_init_data){
771 .name = "byte0_clk_src", 783 .name = "byte0_clk_src",
772 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, 784 .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
773 .num_parents = 6, 785 .num_parents = 6,
774 .ops = &clk_rcg2_ops, 786 .ops = &clk_byte_ops,
787 .flags = CLK_SET_RATE_PARENT,
775 }, 788 },
776}; 789};
777 790
778static struct clk_rcg2 byte1_clk_src = { 791static struct clk_rcg2 byte1_clk_src = {
779 .cmd_rcgr = 0x2140, 792 .cmd_rcgr = 0x2140,
780 .hid_width = 5, 793 .hid_width = 5,
781 .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, 794 .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
782 .freq_tbl = ftbl_mdss_byte1_clk, 795 .freq_tbl = byte_freq_tbl,
783 .clkr.hw.init = &(struct clk_init_data){ 796 .clkr.hw.init = &(struct clk_init_data){
784 .name = "byte1_clk_src", 797 .name = "byte1_clk_src",
785 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, 798 .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
786 .num_parents = 6, 799 .num_parents = 6,
787 .ops = &clk_rcg2_ops, 800 .ops = &clk_byte_ops,
801 .flags = CLK_SET_RATE_PARENT,
788 }, 802 },
789}; 803};
790 804
@@ -822,12 +836,12 @@ static struct clk_rcg2 edplink_clk_src = {
822 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, 836 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
823 .num_parents = 6, 837 .num_parents = 6,
824 .ops = &clk_rcg2_ops, 838 .ops = &clk_rcg2_ops,
839 .flags = CLK_SET_RATE_PARENT,
825 }, 840 },
826}; 841};
827 842
828static struct freq_tbl ftbl_mdss_edppixel_clk[] = { 843static struct freq_tbl edp_pixel_freq_tbl[] = {
829 F(175000000, P_EDPVCO, 2, 0, 0), 844 { .src = P_EDPVCO },
830 F(350000000, P_EDPVCO, 11, 0, 0),
831 { } 845 { }
832}; 846};
833 847
@@ -836,12 +850,12 @@ static struct clk_rcg2 edppixel_clk_src = {
836 .mnd_width = 8, 850 .mnd_width = 8,
837 .hid_width = 5, 851 .hid_width = 5,
838 .parent_map = mmcc_xo_dsi_hdmi_edp_map, 852 .parent_map = mmcc_xo_dsi_hdmi_edp_map,
839 .freq_tbl = ftbl_mdss_edppixel_clk, 853 .freq_tbl = edp_pixel_freq_tbl,
840 .clkr.hw.init = &(struct clk_init_data){ 854 .clkr.hw.init = &(struct clk_init_data){
841 .name = "edppixel_clk_src", 855 .name = "edppixel_clk_src",
842 .parent_names = mmcc_xo_dsi_hdmi_edp, 856 .parent_names = mmcc_xo_dsi_hdmi_edp,
843 .num_parents = 6, 857 .num_parents = 6,
844 .ops = &clk_rcg2_ops, 858 .ops = &clk_edp_pixel_ops,
845 }, 859 },
846}; 860};
847 861
@@ -853,11 +867,11 @@ static struct freq_tbl ftbl_mdss_esc0_1_clk[] = {
853static struct clk_rcg2 esc0_clk_src = { 867static struct clk_rcg2 esc0_clk_src = {
854 .cmd_rcgr = 0x2160, 868 .cmd_rcgr = 0x2160,
855 .hid_width = 5, 869 .hid_width = 5,
856 .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, 870 .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
857 .freq_tbl = ftbl_mdss_esc0_1_clk, 871 .freq_tbl = ftbl_mdss_esc0_1_clk,
858 .clkr.hw.init = &(struct clk_init_data){ 872 .clkr.hw.init = &(struct clk_init_data){
859 .name = "esc0_clk_src", 873 .name = "esc0_clk_src",
860 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, 874 .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
861 .num_parents = 6, 875 .num_parents = 6,
862 .ops = &clk_rcg2_ops, 876 .ops = &clk_rcg2_ops,
863 }, 877 },
@@ -866,26 +880,18 @@ static struct clk_rcg2 esc0_clk_src = {
866static struct clk_rcg2 esc1_clk_src = { 880static struct clk_rcg2 esc1_clk_src = {
867 .cmd_rcgr = 0x2180, 881 .cmd_rcgr = 0x2180,
868 .hid_width = 5, 882 .hid_width = 5,
869 .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, 883 .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
870 .freq_tbl = ftbl_mdss_esc0_1_clk, 884 .freq_tbl = ftbl_mdss_esc0_1_clk,
871 .clkr.hw.init = &(struct clk_init_data){ 885 .clkr.hw.init = &(struct clk_init_data){
872 .name = "esc1_clk_src", 886 .name = "esc1_clk_src",
873 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, 887 .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
874 .num_parents = 6, 888 .num_parents = 6,
875 .ops = &clk_rcg2_ops, 889 .ops = &clk_rcg2_ops,
876 }, 890 },
877}; 891};
878 892
879static struct freq_tbl ftbl_mdss_extpclk_clk[] = { 893static struct freq_tbl extpclk_freq_tbl[] = {
880 F(25200000, P_HDMIPLL, 1, 0, 0), 894 { .src = P_HDMIPLL },
881 F(27000000, P_HDMIPLL, 1, 0, 0),
882 F(27030000, P_HDMIPLL, 1, 0, 0),
883 F(65000000, P_HDMIPLL, 1, 0, 0),
884 F(74250000, P_HDMIPLL, 1, 0, 0),
885 F(108000000, P_HDMIPLL, 1, 0, 0),
886 F(148500000, P_HDMIPLL, 1, 0, 0),
887 F(268500000, P_HDMIPLL, 1, 0, 0),
888 F(297000000, P_HDMIPLL, 1, 0, 0),
889 { } 895 { }
890}; 896};
891 897
@@ -893,12 +899,13 @@ static struct clk_rcg2 extpclk_clk_src = {
893 .cmd_rcgr = 0x2060, 899 .cmd_rcgr = 0x2060,
894 .hid_width = 5, 900 .hid_width = 5,
895 .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, 901 .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
896 .freq_tbl = ftbl_mdss_extpclk_clk, 902 .freq_tbl = extpclk_freq_tbl,
897 .clkr.hw.init = &(struct clk_init_data){ 903 .clkr.hw.init = &(struct clk_init_data){
898 .name = "extpclk_clk_src", 904 .name = "extpclk_clk_src",
899 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, 905 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
900 .num_parents = 6, 906 .num_parents = 6,
901 .ops = &clk_rcg2_ops, 907 .ops = &clk_byte_ops,
908 .flags = CLK_SET_RATE_PARENT,
902 }, 909 },
903}; 910};
904 911
@@ -2318,7 +2325,7 @@ static const struct pll_config mmpll1_config = {
2318 .vco_val = 0x0, 2325 .vco_val = 0x0,
2319 .vco_mask = 0x3 << 20, 2326 .vco_mask = 0x3 << 20,
2320 .pre_div_val = 0x0, 2327 .pre_div_val = 0x0,
2321 .pre_div_mask = 0x3 << 12, 2328 .pre_div_mask = 0x7 << 12,
2322 .post_div_val = 0x0, 2329 .post_div_val = 0x0,
2323 .post_div_mask = 0x3 << 8, 2330 .post_div_mask = 0x3 << 8,
2324 .mn_ena_mask = BIT(24), 2331 .mn_ena_mask = BIT(24),
@@ -2332,7 +2339,7 @@ static struct pll_config mmpll3_config = {
2332 .vco_val = 0x0, 2339 .vco_val = 0x0,
2333 .vco_mask = 0x3 << 20, 2340 .vco_mask = 0x3 << 20,
2334 .pre_div_val = 0x0, 2341 .pre_div_val = 0x0,
2335 .pre_div_mask = 0x3 << 12, 2342 .pre_div_mask = 0x7 << 12,
2336 .post_div_val = 0x0, 2343 .post_div_val = 0x0,
2337 .post_div_mask = 0x3 << 8, 2344 .post_div_mask = 0x3 << 8,
2338 .mn_ena_mask = BIT(24), 2345 .mn_ena_mask = BIT(24),
@@ -2524,88 +2531,39 @@ static const struct regmap_config mmcc_msm8974_regmap_config = {
2524 .fast_io = true, 2531 .fast_io = true,
2525}; 2532};
2526 2533
2534static const struct qcom_cc_desc mmcc_msm8974_desc = {
2535 .config = &mmcc_msm8974_regmap_config,
2536 .clks = mmcc_msm8974_clocks,
2537 .num_clks = ARRAY_SIZE(mmcc_msm8974_clocks),
2538 .resets = mmcc_msm8974_resets,
2539 .num_resets = ARRAY_SIZE(mmcc_msm8974_resets),
2540};
2541
2527static const struct of_device_id mmcc_msm8974_match_table[] = { 2542static const struct of_device_id mmcc_msm8974_match_table[] = {
2528 { .compatible = "qcom,mmcc-msm8974" }, 2543 { .compatible = "qcom,mmcc-msm8974" },
2529 { } 2544 { }
2530}; 2545};
2531MODULE_DEVICE_TABLE(of, mmcc_msm8974_match_table); 2546MODULE_DEVICE_TABLE(of, mmcc_msm8974_match_table);
2532 2547
2533struct qcom_cc {
2534 struct qcom_reset_controller reset;
2535 struct clk_onecell_data data;
2536 struct clk *clks[];
2537};
2538
2539static int mmcc_msm8974_probe(struct platform_device *pdev) 2548static int mmcc_msm8974_probe(struct platform_device *pdev)
2540{ 2549{
2541 void __iomem *base; 2550 int ret;
2542 struct resource *res;
2543 int i, ret;
2544 struct device *dev = &pdev->dev;
2545 struct clk *clk;
2546 struct clk_onecell_data *data;
2547 struct clk **clks;
2548 struct regmap *regmap; 2551 struct regmap *regmap;
2549 size_t num_clks;
2550 struct qcom_reset_controller *reset;
2551 struct qcom_cc *cc;
2552
2553 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2554 base = devm_ioremap_resource(dev, res);
2555 if (IS_ERR(base))
2556 return PTR_ERR(base);
2557
2558 regmap = devm_regmap_init_mmio(dev, base, &mmcc_msm8974_regmap_config);
2559 if (IS_ERR(regmap))
2560 return PTR_ERR(regmap);
2561
2562 num_clks = ARRAY_SIZE(mmcc_msm8974_clocks);
2563 cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
2564 GFP_KERNEL);
2565 if (!cc)
2566 return -ENOMEM;
2567
2568 clks = cc->clks;
2569 data = &cc->data;
2570 data->clks = clks;
2571 data->clk_num = num_clks;
2572
2573 clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true);
2574 clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false);
2575
2576 for (i = 0; i < num_clks; i++) {
2577 if (!mmcc_msm8974_clocks[i])
2578 continue;
2579 clk = devm_clk_register_regmap(dev, mmcc_msm8974_clocks[i]);
2580 if (IS_ERR(clk))
2581 return PTR_ERR(clk);
2582 clks[i] = clk;
2583 }
2584 2552
2585 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data); 2553 ret = qcom_cc_probe(pdev, &mmcc_msm8974_desc);
2586 if (ret) 2554 if (ret)
2587 return ret; 2555 return ret;
2588 2556
2589 reset = &cc->reset; 2557 regmap = dev_get_regmap(&pdev->dev, NULL);
2590 reset->rcdev.of_node = dev->of_node; 2558 clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true);
2591 reset->rcdev.ops = &qcom_reset_ops, 2559 clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false);
2592 reset->rcdev.owner = THIS_MODULE,
2593 reset->rcdev.nr_resets = ARRAY_SIZE(mmcc_msm8974_resets),
2594 reset->regmap = regmap;
2595 reset->reset_map = mmcc_msm8974_resets,
2596 platform_set_drvdata(pdev, &reset->rcdev);
2597
2598 ret = reset_controller_register(&reset->rcdev);
2599 if (ret)
2600 of_clk_del_provider(dev->of_node);
2601 2560
2602 return ret; 2561 return 0;
2603} 2562}
2604 2563
2605static int mmcc_msm8974_remove(struct platform_device *pdev) 2564static int mmcc_msm8974_remove(struct platform_device *pdev)
2606{ 2565{
2607 of_clk_del_provider(pdev->dev.of_node); 2566 qcom_cc_remove(pdev);
2608 reset_controller_unregister(platform_get_drvdata(pdev));
2609 return 0; 2567 return 0;
2610} 2568}
2611 2569
diff --git a/drivers/clk/rockchip/clk-rockchip.c b/drivers/clk/rockchip/clk-rockchip.c
index 967c141b1a20..4cf838d52ef6 100644
--- a/drivers/clk/rockchip/clk-rockchip.c
+++ b/drivers/clk/rockchip/clk-rockchip.c
@@ -24,8 +24,7 @@ static DEFINE_SPINLOCK(clk_lock);
24 * Gate clocks 24 * Gate clocks
25 */ 25 */
26 26
27static void __init rk2928_gate_clk_init(struct device_node *node, 27static void __init rk2928_gate_clk_init(struct device_node *node)
28 void *data)
29{ 28{
30 struct clk_onecell_data *clk_data; 29 struct clk_onecell_data *clk_data;
31 const char *clk_parent; 30 const char *clk_parent;
diff --git a/drivers/clk/samsung/Kconfig b/drivers/clk/samsung/Kconfig
new file mode 100644
index 000000000000..84196ecdaa12
--- /dev/null
+++ b/drivers/clk/samsung/Kconfig
@@ -0,0 +1,26 @@
1config COMMON_CLK_SAMSUNG
2 bool
3 select COMMON_CLK
4
5config S3C2410_COMMON_CLK
6 bool
7 select COMMON_CLK_SAMSUNG
8 help
9 Build the s3c2410 clock driver based on the common clock framework.
10
11config S3C2410_COMMON_DCLK
12 bool
13 select COMMON_CLK_SAMSUNG
14 select REGMAP_MMIO
15 help
16 Temporary symbol to build the dclk driver based on the common clock
17 framework.
18
19config S3C2412_COMMON_CLK
20 bool
21 select COMMON_CLK_SAMSUNG
22
23config S3C2443_COMMON_CLK
24 bool
25 select COMMON_CLK_SAMSUNG
26
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 8eb4799237f0..69e81773164e 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -3,9 +3,16 @@
3# 3#
4 4
5obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o 5obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o
6obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o
6obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o 7obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
7obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o 8obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o
9obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o
10obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o
8obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o 11obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
9obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o 12obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o
10obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o 13obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o
14obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
15obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
16obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
17obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o
11obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o 18obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o
diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
new file mode 100644
index 000000000000..7a17bd40d1dd
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -0,0 +1,780 @@
1/*
2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Common Clock Framework support for Exynos3250 SoC.
9 */
10
11#include <linux/clk.h>
12#include <linux/clkdev.h>
13#include <linux/clk-provider.h>
14#include <linux/of.h>
15#include <linux/of_address.h>
16#include <linux/platform_device.h>
17#include <linux/syscore_ops.h>
18
19#include <dt-bindings/clock/exynos3250.h>
20
21#include "clk.h"
22#include "clk-pll.h"
23
24#define SRC_LEFTBUS 0x4200
25#define DIV_LEFTBUS 0x4500
26#define GATE_IP_LEFTBUS 0x4800
27#define SRC_RIGHTBUS 0x8200
28#define DIV_RIGHTBUS 0x8500
29#define GATE_IP_RIGHTBUS 0x8800
30#define GATE_IP_PERIR 0x8960
31#define MPLL_LOCK 0xc010
32#define MPLL_CON0 0xc110
33#define VPLL_LOCK 0xc020
34#define VPLL_CON0 0xc120
35#define UPLL_LOCK 0xc030
36#define UPLL_CON0 0xc130
37#define SRC_TOP0 0xc210
38#define SRC_TOP1 0xc214
39#define SRC_CAM 0xc220
40#define SRC_MFC 0xc228
41#define SRC_G3D 0xc22c
42#define SRC_LCD 0xc234
43#define SRC_ISP 0xc238
44#define SRC_FSYS 0xc240
45#define SRC_PERIL0 0xc250
46#define SRC_PERIL1 0xc254
47#define SRC_MASK_TOP 0xc310
48#define SRC_MASK_CAM 0xc320
49#define SRC_MASK_LCD 0xc334
50#define SRC_MASK_ISP 0xc338
51#define SRC_MASK_FSYS 0xc340
52#define SRC_MASK_PERIL0 0xc350
53#define SRC_MASK_PERIL1 0xc354
54#define DIV_TOP 0xc510
55#define DIV_CAM 0xc520
56#define DIV_MFC 0xc528
57#define DIV_G3D 0xc52c
58#define DIV_LCD 0xc534
59#define DIV_ISP 0xc538
60#define DIV_FSYS0 0xc540
61#define DIV_FSYS1 0xc544
62#define DIV_FSYS2 0xc548
63#define DIV_PERIL0 0xc550
64#define DIV_PERIL1 0xc554
65#define DIV_PERIL3 0xc55c
66#define DIV_PERIL4 0xc560
67#define DIV_PERIL5 0xc564
68#define DIV_CAM1 0xc568
69#define CLKDIV2_RATIO 0xc580
70#define GATE_SCLK_CAM 0xc820
71#define GATE_SCLK_MFC 0xc828
72#define GATE_SCLK_G3D 0xc82c
73#define GATE_SCLK_LCD 0xc834
74#define GATE_SCLK_ISP_TOP 0xc838
75#define GATE_SCLK_FSYS 0xc840
76#define GATE_SCLK_PERIL 0xc850
77#define GATE_IP_CAM 0xc920
78#define GATE_IP_MFC 0xc928
79#define GATE_IP_G3D 0xc92c
80#define GATE_IP_LCD 0xc934
81#define GATE_IP_ISP 0xc938
82#define GATE_IP_FSYS 0xc940
83#define GATE_IP_PERIL 0xc950
84#define GATE_BLOCK 0xc970
85#define APLL_LOCK 0x14000
86#define APLL_CON0 0x14100
87#define SRC_CPU 0x14200
88#define DIV_CPU0 0x14500
89#define DIV_CPU1 0x14504
90
91/* list of PLLs to be registered */
92enum exynos3250_plls {
93 apll, mpll, vpll, upll,
94 nr_plls
95};
96
97static void __iomem *reg_base;
98
99/*
100 * Support for CMU save/restore across system suspends
101 */
102#ifdef CONFIG_PM_SLEEP
103static struct samsung_clk_reg_dump *exynos3250_clk_regs;
104
105static unsigned long exynos3250_cmu_clk_regs[] __initdata = {
106 SRC_LEFTBUS,
107 DIV_LEFTBUS,
108 GATE_IP_LEFTBUS,
109 SRC_RIGHTBUS,
110 DIV_RIGHTBUS,
111 GATE_IP_RIGHTBUS,
112 GATE_IP_PERIR,
113 MPLL_LOCK,
114 MPLL_CON0,
115 VPLL_LOCK,
116 VPLL_CON0,
117 UPLL_LOCK,
118 UPLL_CON0,
119 SRC_TOP0,
120 SRC_TOP1,
121 SRC_CAM,
122 SRC_MFC,
123 SRC_G3D,
124 SRC_LCD,
125 SRC_ISP,
126 SRC_FSYS,
127 SRC_PERIL0,
128 SRC_PERIL1,
129 SRC_MASK_TOP,
130 SRC_MASK_CAM,
131 SRC_MASK_LCD,
132 SRC_MASK_ISP,
133 SRC_MASK_FSYS,
134 SRC_MASK_PERIL0,
135 SRC_MASK_PERIL1,
136 DIV_TOP,
137 DIV_CAM,
138 DIV_MFC,
139 DIV_G3D,
140 DIV_LCD,
141 DIV_ISP,
142 DIV_FSYS0,
143 DIV_FSYS1,
144 DIV_FSYS2,
145 DIV_PERIL0,
146 DIV_PERIL1,
147 DIV_PERIL3,
148 DIV_PERIL4,
149 DIV_PERIL5,
150 DIV_CAM1,
151 CLKDIV2_RATIO,
152 GATE_SCLK_CAM,
153 GATE_SCLK_MFC,
154 GATE_SCLK_G3D,
155 GATE_SCLK_LCD,
156 GATE_SCLK_ISP_TOP,
157 GATE_SCLK_FSYS,
158 GATE_SCLK_PERIL,
159 GATE_IP_CAM,
160 GATE_IP_MFC,
161 GATE_IP_G3D,
162 GATE_IP_LCD,
163 GATE_IP_ISP,
164 GATE_IP_FSYS,
165 GATE_IP_PERIL,
166 GATE_BLOCK,
167 APLL_LOCK,
168 SRC_CPU,
169 DIV_CPU0,
170 DIV_CPU1,
171};
172
173static int exynos3250_clk_suspend(void)
174{
175 samsung_clk_save(reg_base, exynos3250_clk_regs,
176 ARRAY_SIZE(exynos3250_cmu_clk_regs));
177 return 0;
178}
179
180static void exynos3250_clk_resume(void)
181{
182 samsung_clk_restore(reg_base, exynos3250_clk_regs,
183 ARRAY_SIZE(exynos3250_cmu_clk_regs));
184}
185
186static struct syscore_ops exynos3250_clk_syscore_ops = {
187 .suspend = exynos3250_clk_suspend,
188 .resume = exynos3250_clk_resume,
189};
190
191static void exynos3250_clk_sleep_init(void)
192{
193 exynos3250_clk_regs =
194 samsung_clk_alloc_reg_dump(exynos3250_cmu_clk_regs,
195 ARRAY_SIZE(exynos3250_cmu_clk_regs));
196 if (!exynos3250_clk_regs) {
197 pr_warn("%s: Failed to allocate sleep save data\n", __func__);
198 goto err;
199 }
200
201 register_syscore_ops(&exynos3250_clk_syscore_ops);
202 return;
203err:
204 kfree(exynos3250_clk_regs);
205}
206#else
207static inline void exynos3250_clk_sleep_init(void) { }
208#endif
209
210/* list of all parent clock list */
211PNAME(mout_vpllsrc_p) = { "fin_pll", };
212
213PNAME(mout_apll_p) = { "fin_pll", "fout_apll", };
214PNAME(mout_mpll_p) = { "fin_pll", "fout_mpll", };
215PNAME(mout_vpll_p) = { "fin_pll", "fout_vpll", };
216PNAME(mout_upll_p) = { "fin_pll", "fout_upll", };
217
218PNAME(mout_mpll_user_p) = { "fin_pll", "div_mpll_pre", };
219PNAME(mout_epll_user_p) = { "fin_pll", "mout_epll", };
220PNAME(mout_core_p) = { "mout_apll", "mout_mpll_user_c", };
221PNAME(mout_hpm_p) = { "mout_apll", "mout_mpll_user_c", };
222
223PNAME(mout_ebi_p) = { "div_aclk_200", "div_aclk_160", };
224PNAME(mout_ebi_1_p) = { "mout_ebi", "mout_vpll", };
225
226PNAME(mout_gdl_p) = { "mout_mpll_user_l", };
227PNAME(mout_gdr_p) = { "mout_mpll_user_r", };
228
229PNAME(mout_aclk_400_mcuisp_sub_p)
230 = { "fin_pll", "div_aclk_400_mcuisp", };
231PNAME(mout_aclk_266_0_p) = { "div_mpll_pre", "mout_vpll", };
232PNAME(mout_aclk_266_1_p) = { "mout_epll_user", };
233PNAME(mout_aclk_266_p) = { "mout_aclk_266_0", "mout_aclk_266_1", };
234PNAME(mout_aclk_266_sub_p) = { "fin_pll", "div_aclk_266", };
235
236PNAME(group_div_mpll_pre_p) = { "div_mpll_pre", };
237PNAME(group_epll_vpll_p) = { "mout_epll_user", "mout_vpll" };
238PNAME(group_sclk_p) = { "xxti", "xusbxti",
239 "none", "none",
240 "none", "none", "div_mpll_pre",
241 "mout_epll_user", "mout_vpll", };
242PNAME(group_sclk_audio_p) = { "audiocdclk", "none",
243 "none", "none",
244 "xxti", "xusbxti",
245 "div_mpll_pre", "mout_epll_user",
246 "mout_vpll", };
247PNAME(group_sclk_cam_blk_p) = { "xxti", "xusbxti",
248 "none", "none", "none",
249 "none", "div_mpll_pre",
250 "mout_epll_user", "mout_vpll",
251 "div_cam_blk_320", };
252PNAME(group_sclk_fimd0_p) = { "xxti", "xusbxti",
253 "m_bitclkhsdiv4_2l", "none",
254 "none", "none", "div_mpll_pre",
255 "mout_epll_user", "mout_vpll",
256 "none", "none", "none",
257 "div_lcd_blk_145", };
258
259PNAME(mout_mfc_p) = { "mout_mfc_0", "mout_mfc_1" };
260PNAME(mout_g3d_p) = { "mout_g3d_0", "mout_g3d_1" };
261
262static struct samsung_fixed_factor_clock fixed_factor_clks[] __initdata = {
263 FFACTOR(0, "sclk_mpll_1600", "mout_mpll", 1, 1, 0),
264 FFACTOR(0, "sclk_mpll_mif", "mout_mpll", 1, 2, 0),
265 FFACTOR(0, "sclk_bpll", "fout_bpll", 1, 2, 0),
266 FFACTOR(0, "div_cam_blk_320", "sclk_mpll_1600", 1, 5, 0),
267 FFACTOR(0, "div_lcd_blk_145", "sclk_mpll_1600", 1, 11, 0),
268
269 /* HACK: fin_pll hardcoded to xusbxti until detection is implemented. */
270 FFACTOR(CLK_FIN_PLL, "fin_pll", "xusbxti", 1, 1, 0),
271};
272
273static struct samsung_mux_clock mux_clks[] __initdata = {
274 /*
275 * NOTE: Following table is sorted by register address in ascending
276 * order and then bitfield shift in descending order, as it is done
277 * in the User's Manual. When adding new entries, please make sure
278 * that the order is preserved, to avoid merge conflicts and make
279 * further work with defined data easier.
280 */
281
282 /* SRC_LEFTBUS */
283 MUX(CLK_MOUT_MPLL_USER_L, "mout_mpll_user_l", mout_mpll_user_p,
284 SRC_LEFTBUS, 4, 1),
285 MUX(CLK_MOUT_GDL, "mout_gdl", mout_gdl_p, SRC_LEFTBUS, 0, 1),
286
287 /* SRC_RIGHTBUS */
288 MUX(CLK_MOUT_MPLL_USER_R, "mout_mpll_user_r", mout_mpll_user_p,
289 SRC_RIGHTBUS, 4, 1),
290 MUX(CLK_MOUT_GDR, "mout_gdr", mout_gdr_p, SRC_RIGHTBUS, 0, 1),
291
292 /* SRC_TOP0 */
293 MUX(CLK_MOUT_EBI, "mout_ebi", mout_ebi_p, SRC_TOP0, 28, 1),
294 MUX(CLK_MOUT_ACLK_200, "mout_aclk_200", group_div_mpll_pre_p,SRC_TOP0, 24, 1),
295 MUX(CLK_MOUT_ACLK_160, "mout_aclk_160", group_div_mpll_pre_p, SRC_TOP0, 20, 1),
296 MUX(CLK_MOUT_ACLK_100, "mout_aclk_100", group_div_mpll_pre_p, SRC_TOP0, 16, 1),
297 MUX(CLK_MOUT_ACLK_266_1, "mout_aclk_266_1", mout_aclk_266_1_p, SRC_TOP0, 14, 1),
298 MUX(CLK_MOUT_ACLK_266_0, "mout_aclk_266_0", mout_aclk_266_0_p, SRC_TOP0, 13, 1),
299 MUX(CLK_MOUT_ACLK_266, "mout_aclk_266", mout_aclk_266_p, SRC_TOP0, 12, 1),
300 MUX(CLK_MOUT_VPLL, "mout_vpll", mout_vpll_p, SRC_TOP0, 8, 1),
301 MUX(CLK_MOUT_EPLL_USER, "mout_epll_user", mout_epll_user_p, SRC_TOP0, 4, 1),
302 MUX(CLK_MOUT_EBI_1, "mout_ebi_1", mout_ebi_1_p, SRC_TOP0, 0, 1),
303
304 /* SRC_TOP1 */
305 MUX(CLK_MOUT_UPLL, "mout_upll", mout_upll_p, SRC_TOP1, 28, 1),
306 MUX(CLK_MOUT_ACLK_400_MCUISP_SUB, "mout_aclk_400_mcuisp_sub", mout_aclk_400_mcuisp_sub_p,
307 SRC_TOP1, 24, 1),
308 MUX(CLK_MOUT_ACLK_266_SUB, "mout_aclk_266_sub", mout_aclk_266_sub_p, SRC_TOP1, 20, 1),
309 MUX(CLK_MOUT_MPLL, "mout_mpll", mout_mpll_p, SRC_TOP1, 12, 1),
310 MUX(CLK_MOUT_ACLK_400_MCUISP, "mout_aclk_400_mcuisp", group_div_mpll_pre_p, SRC_TOP1, 8, 1),
311 MUX(CLK_MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1),
312
313 /* SRC_CAM */
314 MUX(CLK_MOUT_CAM1, "mout_cam1", group_sclk_p, SRC_CAM, 20, 4),
315 MUX(CLK_MOUT_CAM_BLK, "mout_cam_blk", group_sclk_cam_blk_p, SRC_CAM, 0, 4),
316
317 /* SRC_MFC */
318 MUX(CLK_MOUT_MFC, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1),
319 MUX(CLK_MOUT_MFC_1, "mout_mfc_1", group_epll_vpll_p, SRC_MFC, 4, 1),
320 MUX(CLK_MOUT_MFC_0, "mout_mfc_0", group_div_mpll_pre_p, SRC_MFC, 0, 1),
321
322 /* SRC_G3D */
323 MUX(CLK_MOUT_G3D, "mout_g3d", mout_g3d_p, SRC_G3D, 8, 1),
324 MUX(CLK_MOUT_G3D_1, "mout_g3d_1", group_epll_vpll_p, SRC_G3D, 4, 1),
325 MUX(CLK_MOUT_G3D_0, "mout_g3d_0", group_div_mpll_pre_p, SRC_G3D, 0, 1),
326
327 /* SRC_LCD */
328 MUX(CLK_MOUT_MIPI0, "mout_mipi0", group_sclk_p, SRC_LCD, 12, 4),
329 MUX(CLK_MOUT_FIMD0, "mout_fimd0", group_sclk_fimd0_p, SRC_LCD, 0, 4),
330
331 /* SRC_ISP */
332 MUX(CLK_MOUT_UART_ISP, "mout_uart_isp", group_sclk_p, SRC_ISP, 12, 4),
333 MUX(CLK_MOUT_SPI1_ISP, "mout_spi1_isp", group_sclk_p, SRC_ISP, 8, 4),
334 MUX(CLK_MOUT_SPI0_ISP, "mout_spi0_isp", group_sclk_p, SRC_ISP, 4, 4),
335
336 /* SRC_FSYS */
337 MUX(CLK_MOUT_TSADC, "mout_tsadc", group_sclk_p, SRC_FSYS, 28, 4),
338 MUX(CLK_MOUT_MMC1, "mout_mmc1", group_sclk_p, SRC_FSYS, 4, 3),
339 MUX(CLK_MOUT_MMC0, "mout_mmc0", group_sclk_p, SRC_FSYS, 0, 3),
340
341 /* SRC_PERIL0 */
342 MUX(CLK_MOUT_UART1, "mout_uart1", group_sclk_p, SRC_PERIL0, 4, 4),
343 MUX(CLK_MOUT_UART0, "mout_uart0", group_sclk_p, SRC_PERIL0, 0, 4),
344
345 /* SRC_PERIL1 */
346 MUX(CLK_MOUT_SPI1, "mout_spi1", group_sclk_p, SRC_PERIL1, 20, 4),
347 MUX(CLK_MOUT_SPI0, "mout_spi0", group_sclk_p, SRC_PERIL1, 16, 4),
348 MUX(CLK_MOUT_AUDIO, "mout_audio", group_sclk_audio_p, SRC_PERIL1, 4, 4),
349
350 /* SRC_CPU */
351 MUX(CLK_MOUT_MPLL_USER_C, "mout_mpll_user_c", mout_mpll_user_p,
352 SRC_CPU, 24, 1),
353 MUX(CLK_MOUT_HPM, "mout_hpm", mout_hpm_p, SRC_CPU, 20, 1),
354 MUX(CLK_MOUT_CORE, "mout_core", mout_core_p, SRC_CPU, 16, 1),
355 MUX(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1),
356};
357
358static struct samsung_div_clock div_clks[] __initdata = {
359 /*
360 * NOTE: Following table is sorted by register address in ascending
361 * order and then bitfield shift in descending order, as it is done
362 * in the User's Manual. When adding new entries, please make sure
363 * that the order is preserved, to avoid merge conflicts and make
364 * further work with defined data easier.
365 */
366
367 /* DIV_LEFTBUS */
368 DIV(CLK_DIV_GPL, "div_gpl", "div_gdl", DIV_LEFTBUS, 4, 3),
369 DIV(CLK_DIV_GDL, "div_gdl", "mout_gdl", DIV_LEFTBUS, 0, 4),
370
371 /* DIV_RIGHTBUS */
372 DIV(CLK_DIV_GPR, "div_gpr", "div_gdr", DIV_RIGHTBUS, 4, 3),
373 DIV(CLK_DIV_GDR, "div_gdr", "mout_gdr", DIV_RIGHTBUS, 0, 4),
374
375 /* DIV_TOP */
376 DIV(CLK_DIV_MPLL_PRE, "div_mpll_pre", "sclk_mpll_mif", DIV_TOP, 28, 2),
377 DIV(CLK_DIV_ACLK_400_MCUISP, "div_aclk_400_mcuisp",
378 "mout_aclk_400_mcuisp", DIV_TOP, 24, 3),
379 DIV(CLK_DIV_EBI, "div_ebi", "mout_ebi_1", DIV_TOP, 16, 3),
380 DIV(CLK_DIV_ACLK_200, "div_aclk_200", "mout_aclk_200", DIV_TOP, 12, 3),
381 DIV(CLK_DIV_ACLK_160, "div_aclk_160", "mout_aclk_160", DIV_TOP, 8, 3),
382 DIV(CLK_DIV_ACLK_100, "div_aclk_100", "mout_aclk_100", DIV_TOP, 4, 4),
383 DIV(CLK_DIV_ACLK_266, "div_aclk_266", "mout_aclk_266", DIV_TOP, 0, 3),
384
385 /* DIV_CAM */
386 DIV(CLK_DIV_CAM1, "div_cam1", "mout_cam1", DIV_CAM, 20, 4),
387 DIV(CLK_DIV_CAM_BLK, "div_cam_blk", "mout_cam_blk", DIV_CAM, 0, 4),
388
389 /* DIV_MFC */
390 DIV(CLK_DIV_MFC, "div_mfc", "mout_mfc", DIV_MFC, 0, 4),
391
392 /* DIV_G3D */
393 DIV(CLK_DIV_G3D, "div_g3d", "mout_g3d", DIV_G3D, 0, 4),
394
395 /* DIV_LCD */
396 DIV_F(CLK_DIV_MIPI0_PRE, "div_mipi0_pre", "div_mipi0", DIV_LCD, 20, 4,
397 CLK_SET_RATE_PARENT, 0),
398 DIV(CLK_DIV_MIPI0, "div_mipi0", "mout_mipi0", DIV_LCD, 16, 4),
399 DIV(CLK_DIV_FIMD0, "div_fimd0", "mout_fimd0", DIV_LCD, 0, 4),
400
401 /* DIV_ISP */
402 DIV(CLK_DIV_UART_ISP, "div_uart_isp", "mout_uart_isp", DIV_ISP, 28, 4),
403 DIV_F(CLK_DIV_SPI1_ISP_PRE, "div_spi1_isp_pre", "div_spi1_isp",
404 DIV_ISP, 20, 8, CLK_SET_RATE_PARENT, 0),
405 DIV(CLK_DIV_SPI1_ISP, "div_spi1_isp", "mout_spi1_isp", DIV_ISP, 16, 4),
406 DIV_F(CLK_DIV_SPI0_ISP_PRE, "div_spi0_isp_pre", "div_spi0_isp",
407 DIV_ISP, 8, 8, CLK_SET_RATE_PARENT, 0),
408 DIV(CLK_DIV_SPI0_ISP, "div_spi0_isp", "mout_spi0_isp", DIV_ISP, 0, 4),
409
410 /* DIV_FSYS0 */
411 DIV_F(CLK_DIV_TSADC_PRE, "div_tsadc_pre", "div_tsadc", DIV_FSYS0, 8, 8,
412 CLK_SET_RATE_PARENT, 0),
413 DIV(CLK_DIV_TSADC, "div_tsadc", "mout_tsadc", DIV_FSYS0, 0, 4),
414
415 /* DIV_FSYS1 */
416 DIV_F(CLK_DIV_MMC1_PRE, "div_mmc1_pre", "div_mmc1", DIV_FSYS1, 24, 8,
417 CLK_SET_RATE_PARENT, 0),
418 DIV(CLK_DIV_MMC1, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
419 DIV_F(CLK_DIV_MMC0_PRE, "div_mmc0_pre", "div_mmc0", DIV_FSYS1, 8, 8,
420 CLK_SET_RATE_PARENT, 0),
421 DIV(CLK_DIV_MMC0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
422
423 /* DIV_PERIL0 */
424 DIV(CLK_DIV_UART1, "div_uart1", "mout_uart1", DIV_PERIL0, 4, 4),
425 DIV(CLK_DIV_UART0, "div_uart0", "mout_uart0", DIV_PERIL0, 0, 4),
426
427 /* DIV_PERIL1 */
428 DIV_F(CLK_DIV_SPI1_PRE, "div_spi1_pre", "div_spi1", DIV_PERIL1, 24, 8,
429 CLK_SET_RATE_PARENT, 0),
430 DIV(CLK_DIV_SPI1, "div_spi1", "mout_spi1", DIV_PERIL1, 16, 4),
431 DIV_F(CLK_DIV_SPI0_PRE, "div_spi0_pre", "div_spi0", DIV_PERIL1, 8, 8,
432 CLK_SET_RATE_PARENT, 0),
433 DIV(CLK_DIV_SPI0, "div_spi0", "mout_spi0", DIV_PERIL1, 0, 4),
434
435 /* DIV_PERIL4 */
436 DIV(CLK_DIV_PCM, "div_pcm", "div_audio", DIV_PERIL4, 20, 8),
437 DIV(CLK_DIV_AUDIO, "div_audio", "mout_audio", DIV_PERIL4, 16, 4),
438
439 /* DIV_PERIL5 */
440 DIV(CLK_DIV_I2S, "div_i2s", "div_audio", DIV_PERIL5, 8, 6),
441
442 /* DIV_CPU0 */
443 DIV(CLK_DIV_CORE2, "div_core2", "div_core", DIV_CPU0, 28, 3),
444 DIV(CLK_DIV_APLL, "div_apll", "mout_apll", DIV_CPU0, 24, 3),
445 DIV(CLK_DIV_PCLK_DBG, "div_pclk_dbg", "div_core2", DIV_CPU0, 20, 3),
446 DIV(CLK_DIV_ATB, "div_atb", "div_core2", DIV_CPU0, 16, 3),
447 DIV(CLK_DIV_COREM, "div_corem", "div_core2", DIV_CPU0, 4, 3),
448 DIV(CLK_DIV_CORE, "div_core", "mout_core", DIV_CPU0, 0, 3),
449
450 /* DIV_CPU1 */
451 DIV(CLK_DIV_HPM, "div_hpm", "div_copy", DIV_CPU1, 4, 3),
452 DIV(CLK_DIV_COPY, "div_copy", "mout_hpm", DIV_CPU1, 0, 3),
453};
454
455static struct samsung_gate_clock gate_clks[] __initdata = {
456 /*
457 * NOTE: Following table is sorted by register address in ascending
458 * order and then bitfield shift in descending order, as it is done
459 * in the User's Manual. When adding new entries, please make sure
460 * that the order is preserved, to avoid merge conflicts and make
461 * further work with defined data easier.
462 */
463
464 /* GATE_IP_LEFTBUS */
465 GATE(CLK_ASYNC_G3D, "async_g3d", "div_aclk_100", GATE_IP_LEFTBUS, 6,
466 CLK_IGNORE_UNUSED, 0),
467 GATE(CLK_ASYNC_MFCL, "async_mfcl", "div_aclk_100", GATE_IP_LEFTBUS, 4,
468 CLK_IGNORE_UNUSED, 0),
469 GATE(CLK_PPMULEFT, "ppmuleft", "div_aclk_100", GATE_IP_LEFTBUS, 1,
470 CLK_IGNORE_UNUSED, 0),
471 GATE(CLK_GPIO_LEFT, "gpio_left", "div_aclk_100", GATE_IP_LEFTBUS, 0,
472 CLK_IGNORE_UNUSED, 0),
473
474 /* GATE_IP_RIGHTBUS */
475 GATE(CLK_ASYNC_ISPMX, "async_ispmx", "div_aclk_100",
476 GATE_IP_RIGHTBUS, 9, CLK_IGNORE_UNUSED, 0),
477 GATE(CLK_ASYNC_FSYSD, "async_fsysd", "div_aclk_100",
478 GATE_IP_RIGHTBUS, 5, CLK_IGNORE_UNUSED, 0),
479 GATE(CLK_ASYNC_LCD0X, "async_lcd0x", "div_aclk_100",
480 GATE_IP_RIGHTBUS, 3, CLK_IGNORE_UNUSED, 0),
481 GATE(CLK_ASYNC_CAMX, "async_camx", "div_aclk_100", GATE_IP_RIGHTBUS, 2,
482 CLK_IGNORE_UNUSED, 0),
483 GATE(CLK_PPMURIGHT, "ppmuright", "div_aclk_100", GATE_IP_RIGHTBUS, 1,
484 CLK_IGNORE_UNUSED, 0),
485 GATE(CLK_GPIO_RIGHT, "gpio_right", "div_aclk_100", GATE_IP_RIGHTBUS, 0,
486 CLK_IGNORE_UNUSED, 0),
487
488 /* GATE_IP_PERIR */
489 GATE(CLK_MONOCNT, "monocnt", "div_aclk_100", GATE_IP_PERIR, 22,
490 CLK_IGNORE_UNUSED, 0),
491 GATE(CLK_TZPC6, "tzpc6", "div_aclk_100", GATE_IP_PERIR, 21,
492 CLK_IGNORE_UNUSED, 0),
493 GATE(CLK_PROVISIONKEY1, "provisionkey1", "div_aclk_100",
494 GATE_IP_PERIR, 20, CLK_IGNORE_UNUSED, 0),
495 GATE(CLK_PROVISIONKEY0, "provisionkey0", "div_aclk_100",
496 GATE_IP_PERIR, 19, CLK_IGNORE_UNUSED, 0),
497 GATE(CLK_CMU_ISPPART, "cmu_isppart", "div_aclk_100", GATE_IP_PERIR, 18,
498 CLK_IGNORE_UNUSED, 0),
499 GATE(CLK_TMU_APBIF, "tmu_apbif", "div_aclk_100",
500 GATE_IP_PERIR, 17, 0, 0),
501 GATE(CLK_KEYIF, "keyif", "div_aclk_100", GATE_IP_PERIR, 16, 0, 0),
502 GATE(CLK_RTC, "rtc", "div_aclk_100", GATE_IP_PERIR, 15, 0, 0),
503 GATE(CLK_WDT, "wdt", "div_aclk_100", GATE_IP_PERIR, 14, 0, 0),
504 GATE(CLK_MCT, "mct", "div_aclk_100", GATE_IP_PERIR, 13, 0, 0),
505 GATE(CLK_SECKEY, "seckey", "div_aclk_100", GATE_IP_PERIR, 12,
506 CLK_IGNORE_UNUSED, 0),
507 GATE(CLK_TZPC5, "tzpc5", "div_aclk_100", GATE_IP_PERIR, 10,
508 CLK_IGNORE_UNUSED, 0),
509 GATE(CLK_TZPC4, "tzpc4", "div_aclk_100", GATE_IP_PERIR, 9,
510 CLK_IGNORE_UNUSED, 0),
511 GATE(CLK_TZPC3, "tzpc3", "div_aclk_100", GATE_IP_PERIR, 8,
512 CLK_IGNORE_UNUSED, 0),
513 GATE(CLK_TZPC2, "tzpc2", "div_aclk_100", GATE_IP_PERIR, 7,
514 CLK_IGNORE_UNUSED, 0),
515 GATE(CLK_TZPC1, "tzpc1", "div_aclk_100", GATE_IP_PERIR, 6,
516 CLK_IGNORE_UNUSED, 0),
517 GATE(CLK_TZPC0, "tzpc0", "div_aclk_100", GATE_IP_PERIR, 5,
518 CLK_IGNORE_UNUSED, 0),
519 GATE(CLK_CMU_COREPART, "cmu_corepart", "div_aclk_100", GATE_IP_PERIR, 4,
520 CLK_IGNORE_UNUSED, 0),
521 GATE(CLK_CMU_TOPPART, "cmu_toppart", "div_aclk_100", GATE_IP_PERIR, 3,
522 CLK_IGNORE_UNUSED, 0),
523 GATE(CLK_PMU_APBIF, "pmu_apbif", "div_aclk_100", GATE_IP_PERIR, 2,
524 CLK_IGNORE_UNUSED, 0),
525 GATE(CLK_SYSREG, "sysreg", "div_aclk_100", GATE_IP_PERIR, 1,
526 CLK_IGNORE_UNUSED, 0),
527 GATE(CLK_CHIP_ID, "chip_id", "div_aclk_100", GATE_IP_PERIR, 0,
528 CLK_IGNORE_UNUSED, 0),
529
530 /* GATE_SCLK_CAM */
531 GATE(CLK_SCLK_JPEG, "sclk_jpeg", "div_cam_blk",
532 GATE_SCLK_CAM, 8, CLK_SET_RATE_PARENT, 0),
533 GATE(CLK_SCLK_M2MSCALER, "sclk_m2mscaler", "div_cam_blk",
534 GATE_SCLK_CAM, 2, CLK_SET_RATE_PARENT, 0),
535 GATE(CLK_SCLK_GSCALER1, "sclk_gscaler1", "div_cam_blk",
536 GATE_SCLK_CAM, 1, CLK_SET_RATE_PARENT, 0),
537 GATE(CLK_SCLK_GSCALER0, "sclk_gscaler0", "div_cam_blk",
538 GATE_SCLK_CAM, 0, CLK_SET_RATE_PARENT, 0),
539
540 /* GATE_SCLK_MFC */
541 GATE(CLK_SCLK_MFC, "sclk_mfc", "div_mfc",
542 GATE_SCLK_MFC, 0, CLK_SET_RATE_PARENT, 0),
543
544 /* GATE_SCLK_G3D */
545 GATE(CLK_SCLK_G3D, "sclk_g3d", "div_g3d",
546 GATE_SCLK_G3D, 0, CLK_SET_RATE_PARENT, 0),
547
548 /* GATE_SCLK_LCD */
549 GATE(CLK_SCLK_MIPIDPHY2L, "sclk_mipidphy2l", "div_mipi0",
550 GATE_SCLK_LCD, 4, CLK_SET_RATE_PARENT, 0),
551 GATE(CLK_SCLK_MIPI0, "sclk_mipi0", "div_mipi0_pre",
552 GATE_SCLK_LCD, 3, CLK_SET_RATE_PARENT, 0),
553 GATE(CLK_SCLK_FIMD0, "sclk_fimd0", "div_fimd0",
554 GATE_SCLK_LCD, 0, CLK_SET_RATE_PARENT, 0),
555
556 /* GATE_SCLK_ISP_TOP */
557 GATE(CLK_SCLK_CAM1, "sclk_cam1", "div_cam1",
558 GATE_SCLK_ISP_TOP, 4, CLK_SET_RATE_PARENT, 0),
559 GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "div_uart_isp",
560 GATE_SCLK_ISP_TOP, 3, CLK_SET_RATE_PARENT, 0),
561 GATE(CLK_SCLK_SPI1_ISP, "sclk_spi1_isp", "div_spi1_isp",
562 GATE_SCLK_ISP_TOP, 2, CLK_SET_RATE_PARENT, 0),
563 GATE(CLK_SCLK_SPI0_ISP, "sclk_spi0_isp", "div_spi0_isp",
564 GATE_SCLK_ISP_TOP, 1, CLK_SET_RATE_PARENT, 0),
565
566 /* GATE_SCLK_FSYS */
567 GATE(CLK_SCLK_UPLL, "sclk_upll", "mout_upll", GATE_SCLK_FSYS, 10, 0, 0),
568 GATE(CLK_SCLK_TSADC, "sclk_tsadc", "div_tsadc_pre",
569 GATE_SCLK_FSYS, 9, CLK_SET_RATE_PARENT, 0),
570 GATE(CLK_SCLK_EBI, "sclk_ebi", "div_ebi",
571 GATE_SCLK_FSYS, 6, CLK_SET_RATE_PARENT, 0),
572 GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc1_pre",
573 GATE_SCLK_FSYS, 1, CLK_SET_RATE_PARENT, 0),
574 GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc0_pre",
575 GATE_SCLK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
576
577 /* GATE_SCLK_PERIL */
578 GATE(CLK_SCLK_I2S, "sclk_i2s", "div_i2s",
579 GATE_SCLK_PERIL, 18, CLK_SET_RATE_PARENT, 0),
580 GATE(CLK_SCLK_PCM, "sclk_pcm", "div_pcm",
581 GATE_SCLK_PERIL, 16, CLK_SET_RATE_PARENT, 0),
582 GATE(CLK_SCLK_SPI1, "sclk_spi1", "div_spi1_pre",
583 GATE_SCLK_PERIL, 7, CLK_SET_RATE_PARENT, 0),
584 GATE(CLK_SCLK_SPI0, "sclk_spi0", "div_spi0_pre",
585 GATE_SCLK_PERIL, 6, CLK_SET_RATE_PARENT, 0),
586 GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1",
587 GATE_SCLK_PERIL, 1, CLK_SET_RATE_PARENT, 0),
588 GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
589 GATE_SCLK_PERIL, 0, CLK_SET_RATE_PARENT, 0),
590
591 /* GATE_IP_CAM */
592 GATE(CLK_QEJPEG, "qejpeg", "div_cam_blk_320", GATE_IP_CAM, 19,
593 CLK_IGNORE_UNUSED, 0),
594 GATE(CLK_PIXELASYNCM1, "pixelasyncm1", "div_cam_blk_320",
595 GATE_IP_CAM, 18, CLK_IGNORE_UNUSED, 0),
596 GATE(CLK_PIXELASYNCM0, "pixelasyncm0", "div_cam_blk_320",
597 GATE_IP_CAM, 17, CLK_IGNORE_UNUSED, 0),
598 GATE(CLK_PPMUCAMIF, "ppmucamif", "div_cam_blk_320",
599 GATE_IP_CAM, 16, CLK_IGNORE_UNUSED, 0),
600 GATE(CLK_QEM2MSCALER, "qem2mscaler", "div_cam_blk_320",
601 GATE_IP_CAM, 14, CLK_IGNORE_UNUSED, 0),
602 GATE(CLK_QEGSCALER1, "qegscaler1", "div_cam_blk_320",
603 GATE_IP_CAM, 13, CLK_IGNORE_UNUSED, 0),
604 GATE(CLK_QEGSCALER0, "qegscaler0", "div_cam_blk_320",
605 GATE_IP_CAM, 12, CLK_IGNORE_UNUSED, 0),
606 GATE(CLK_SMMUJPEG, "smmujpeg", "div_cam_blk_320",
607 GATE_IP_CAM, 11, 0, 0),
608 GATE(CLK_SMMUM2M2SCALER, "smmum2m2scaler", "div_cam_blk_320",
609 GATE_IP_CAM, 9, 0, 0),
610 GATE(CLK_SMMUGSCALER1, "smmugscaler1", "div_cam_blk_320",
611 GATE_IP_CAM, 8, 0, 0),
612 GATE(CLK_SMMUGSCALER0, "smmugscaler0", "div_cam_blk_320",
613 GATE_IP_CAM, 7, 0, 0),
614 GATE(CLK_JPEG, "jpeg", "div_cam_blk_320", GATE_IP_CAM, 6, 0, 0),
615 GATE(CLK_M2MSCALER, "m2mscaler", "div_cam_blk_320",
616 GATE_IP_CAM, 2, 0, 0),
617 GATE(CLK_GSCALER1, "gscaler1", "div_cam_blk_320", GATE_IP_CAM, 1, 0, 0),
618 GATE(CLK_GSCALER0, "gscaler0", "div_cam_blk_320", GATE_IP_CAM, 0, 0, 0),
619
620 /* GATE_IP_MFC */
621 GATE(CLK_QEMFC, "qemfc", "div_aclk_200", GATE_IP_MFC, 5,
622 CLK_IGNORE_UNUSED, 0),
623 GATE(CLK_PPMUMFC_L, "ppmumfc_l", "div_aclk_200", GATE_IP_MFC, 3,
624 CLK_IGNORE_UNUSED, 0),
625 GATE(CLK_SMMUMFC_L, "smmumfc_l", "div_aclk_200", GATE_IP_MFC, 1, 0, 0),
626 GATE(CLK_MFC, "mfc", "div_aclk_200", GATE_IP_MFC, 0, 0, 0),
627
628 /* GATE_IP_G3D */
629 GATE(CLK_SMMUG3D, "smmug3d", "div_aclk_200", GATE_IP_G3D, 3, 0, 0),
630 GATE(CLK_QEG3D, "qeg3d", "div_aclk_200", GATE_IP_G3D, 2,
631 CLK_IGNORE_UNUSED, 0),
632 GATE(CLK_PPMUG3D, "ppmug3d", "div_aclk_200", GATE_IP_G3D, 1,
633 CLK_IGNORE_UNUSED, 0),
634 GATE(CLK_G3D, "g3d", "div_aclk_200", GATE_IP_G3D, 0, 0, 0),
635
636 /* GATE_IP_LCD */
637 GATE(CLK_QE_CH1_LCD, "qe_ch1_lcd", "div_aclk_160", GATE_IP_LCD, 7,
638 CLK_IGNORE_UNUSED, 0),
639 GATE(CLK_QE_CH0_LCD, "qe_ch0_lcd", "div_aclk_160", GATE_IP_LCD, 6,
640 CLK_IGNORE_UNUSED, 0),
641 GATE(CLK_PPMULCD0, "ppmulcd0", "div_aclk_160", GATE_IP_LCD, 5,
642 CLK_IGNORE_UNUSED, 0),
643 GATE(CLK_SMMUFIMD0, "smmufimd0", "div_aclk_160", GATE_IP_LCD, 4, 0, 0),
644 GATE(CLK_DSIM0, "dsim0", "div_aclk_160", GATE_IP_LCD, 3, 0, 0),
645 GATE(CLK_SMIES, "smies", "div_aclk_160", GATE_IP_LCD, 2, 0, 0),
646 GATE(CLK_FIMD0, "fimd0", "div_aclk_160", GATE_IP_LCD, 0, 0, 0),
647
648 /* GATE_IP_ISP */
649 GATE(CLK_CAM1, "cam1", "mout_aclk_266_sub", GATE_IP_ISP, 5, 0, 0),
650 GATE(CLK_UART_ISP_TOP, "uart_isp_top", "mout_aclk_266_sub",
651 GATE_IP_ISP, 3, 0, 0),
652 GATE(CLK_SPI1_ISP_TOP, "spi1_isp_top", "mout_aclk_266_sub",
653 GATE_IP_ISP, 2, 0, 0),
654 GATE(CLK_SPI0_ISP_TOP, "spi0_isp_top", "mout_aclk_266_sub",
655 GATE_IP_ISP, 1, 0, 0),
656
657 /* GATE_IP_FSYS */
658 GATE(CLK_TSADC, "tsadc", "div_aclk_200", GATE_IP_FSYS, 20, 0, 0),
659 GATE(CLK_PPMUFILE, "ppmufile", "div_aclk_200", GATE_IP_FSYS, 17,
660 CLK_IGNORE_UNUSED, 0),
661 GATE(CLK_USBOTG, "usbotg", "div_aclk_200", GATE_IP_FSYS, 13, 0, 0),
662 GATE(CLK_USBHOST, "usbhost", "div_aclk_200", GATE_IP_FSYS, 12, 0, 0),
663 GATE(CLK_SROMC, "sromc", "div_aclk_200", GATE_IP_FSYS, 11, 0, 0),
664 GATE(CLK_SDMMC1, "sdmmc1", "div_aclk_200", GATE_IP_FSYS, 6, 0, 0),
665 GATE(CLK_SDMMC0, "sdmmc0", "div_aclk_200", GATE_IP_FSYS, 5, 0, 0),
666 GATE(CLK_PDMA1, "pdma1", "div_aclk_200", GATE_IP_FSYS, 1, 0, 0),
667 GATE(CLK_PDMA0, "pdma0", "div_aclk_200", GATE_IP_FSYS, 0, 0, 0),
668
669 /* GATE_IP_PERIL */
670 GATE(CLK_PWM, "pwm", "div_aclk_100", GATE_IP_PERIL, 24, 0, 0),
671 GATE(CLK_PCM, "pcm", "div_aclk_100", GATE_IP_PERIL, 23, 0, 0),
672 GATE(CLK_I2S, "i2s", "div_aclk_100", GATE_IP_PERIL, 21, 0, 0),
673 GATE(CLK_SPI1, "spi1", "div_aclk_100", GATE_IP_PERIL, 17, 0, 0),
674 GATE(CLK_SPI0, "spi0", "div_aclk_100", GATE_IP_PERIL, 16, 0, 0),
675 GATE(CLK_I2C7, "i2c7", "div_aclk_100", GATE_IP_PERIL, 13, 0, 0),
676 GATE(CLK_I2C6, "i2c6", "div_aclk_100", GATE_IP_PERIL, 12, 0, 0),
677 GATE(CLK_I2C5, "i2c5", "div_aclk_100", GATE_IP_PERIL, 11, 0, 0),
678 GATE(CLK_I2C4, "i2c4", "div_aclk_100", GATE_IP_PERIL, 10, 0, 0),
679 GATE(CLK_I2C3, "i2c3", "div_aclk_100", GATE_IP_PERIL, 9, 0, 0),
680 GATE(CLK_I2C2, "i2c2", "div_aclk_100", GATE_IP_PERIL, 8, 0, 0),
681 GATE(CLK_I2C1, "i2c1", "div_aclk_100", GATE_IP_PERIL, 7, 0, 0),
682 GATE(CLK_I2C0, "i2c0", "div_aclk_100", GATE_IP_PERIL, 6, 0, 0),
683 GATE(CLK_UART1, "uart1", "div_aclk_100", GATE_IP_PERIL, 1, 0, 0),
684 GATE(CLK_UART0, "uart0", "div_aclk_100", GATE_IP_PERIL, 0, 0, 0),
685};
686
687/* APLL & MPLL & BPLL & UPLL */
688static struct samsung_pll_rate_table exynos3250_pll_rates[] = {
689 PLL_35XX_RATE(1200000000, 400, 4, 1),
690 PLL_35XX_RATE(1100000000, 275, 3, 1),
691 PLL_35XX_RATE(1066000000, 533, 6, 1),
692 PLL_35XX_RATE(1000000000, 250, 3, 1),
693 PLL_35XX_RATE( 960000000, 320, 4, 1),
694 PLL_35XX_RATE( 900000000, 300, 4, 1),
695 PLL_35XX_RATE( 850000000, 425, 6, 1),
696 PLL_35XX_RATE( 800000000, 200, 3, 1),
697 PLL_35XX_RATE( 700000000, 175, 3, 1),
698 PLL_35XX_RATE( 667000000, 667, 12, 1),
699 PLL_35XX_RATE( 600000000, 400, 4, 2),
700 PLL_35XX_RATE( 533000000, 533, 6, 2),
701 PLL_35XX_RATE( 520000000, 260, 3, 2),
702 PLL_35XX_RATE( 500000000, 250, 3, 2),
703 PLL_35XX_RATE( 400000000, 200, 3, 2),
704 PLL_35XX_RATE( 200000000, 200, 3, 3),
705 PLL_35XX_RATE( 100000000, 200, 3, 4),
706 { /* sentinel */ }
707};
708
709/* VPLL */
710static struct samsung_pll_rate_table exynos3250_vpll_rates[] = {
711 PLL_36XX_RATE(600000000, 100, 2, 1, 0),
712 PLL_36XX_RATE(533000000, 266, 3, 2, 32768),
713 PLL_36XX_RATE(519230987, 173, 2, 2, 5046),
714 PLL_36XX_RATE(500000000, 250, 3, 2, 0),
715 PLL_36XX_RATE(445500000, 148, 2, 2, 32768),
716 PLL_36XX_RATE(445055007, 148, 2, 2, 23047),
717 PLL_36XX_RATE(400000000, 200, 3, 2, 0),
718 PLL_36XX_RATE(371250000, 123, 2, 2, 49152),
719 PLL_36XX_RATE(370878997, 185, 3, 2, 28803),
720 PLL_36XX_RATE(340000000, 170, 3, 2, 0),
721 PLL_36XX_RATE(335000015, 111, 2, 2, 43691),
722 PLL_36XX_RATE(333000000, 111, 2, 2, 0),
723 PLL_36XX_RATE(330000000, 110, 2, 2, 0),
724 PLL_36XX_RATE(320000015, 106, 2, 2, 43691),
725 PLL_36XX_RATE(300000000, 100, 2, 2, 0),
726 PLL_36XX_RATE(275000000, 275, 3, 3, 0),
727 PLL_36XX_RATE(222750000, 148, 2, 3, 32768),
728 PLL_36XX_RATE(222528007, 148, 2, 3, 23069),
729 PLL_36XX_RATE(160000000, 160, 3, 3, 0),
730 PLL_36XX_RATE(148500000, 99, 2, 3, 0),
731 PLL_36XX_RATE(148352005, 98, 2, 3, 59070),
732 PLL_36XX_RATE(108000000, 144, 2, 4, 0),
733 PLL_36XX_RATE( 74250000, 99, 2, 4, 0),
734 PLL_36XX_RATE( 74176002, 98, 3, 4, 59070),
735 PLL_36XX_RATE( 54054000, 216, 3, 5, 14156),
736 PLL_36XX_RATE( 54000000, 144, 2, 5, 0),
737 { /* sentinel */ }
738};
739
740static struct samsung_pll_clock exynos3250_plls[nr_plls] __initdata = {
741 [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll",
742 APLL_LOCK, APLL_CON0, NULL),
743 [mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll",
744 MPLL_LOCK, MPLL_CON0, NULL),
745 [vpll] = PLL(pll_36xx, CLK_FOUT_VPLL, "fout_vpll", "fin_pll",
746 VPLL_LOCK, VPLL_CON0, NULL),
747 [upll] = PLL(pll_35xx, CLK_FOUT_UPLL, "fout_upll", "fin_pll",
748 UPLL_LOCK, UPLL_CON0, NULL),
749};
750
751static void __init exynos3250_cmu_init(struct device_node *np)
752{
753 struct samsung_clk_provider *ctx;
754
755 reg_base = of_iomap(np, 0);
756 if (!reg_base)
757 panic("%s: failed to map registers\n", __func__);
758
759 ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
760 if (!ctx)
761 panic("%s: unable to allocate context.\n", __func__);
762
763 samsung_clk_register_fixed_factor(ctx, fixed_factor_clks,
764 ARRAY_SIZE(fixed_factor_clks));
765
766 exynos3250_plls[apll].rate_table = exynos3250_pll_rates;
767 exynos3250_plls[mpll].rate_table = exynos3250_pll_rates;
768 exynos3250_plls[vpll].rate_table = exynos3250_vpll_rates;
769 exynos3250_plls[upll].rate_table = exynos3250_pll_rates;
770
771 samsung_clk_register_pll(ctx, exynos3250_plls,
772 ARRAY_SIZE(exynos3250_plls), reg_base);
773
774 samsung_clk_register_mux(ctx, mux_clks, ARRAY_SIZE(mux_clks));
775 samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks));
776 samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks));
777
778 exynos3250_clk_sleep_init();
779}
780CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init);
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index b4f967210175..4f150c9dd38c 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -324,7 +324,7 @@ static struct syscore_ops exynos4_clk_syscore_ops = {
324 .resume = exynos4_clk_resume, 324 .resume = exynos4_clk_resume,
325}; 325};
326 326
327static void exynos4_clk_sleep_init(void) 327static void __init exynos4_clk_sleep_init(void)
328{ 328{
329 exynos4_save_common = samsung_clk_alloc_reg_dump(exynos4_clk_regs, 329 exynos4_save_common = samsung_clk_alloc_reg_dump(exynos4_clk_regs,
330 ARRAY_SIZE(exynos4_clk_regs)); 330 ARRAY_SIZE(exynos4_clk_regs));
@@ -359,7 +359,7 @@ err_warn:
359 __func__); 359 __func__);
360} 360}
361#else 361#else
362static void exynos4_clk_sleep_init(void) {} 362static void __init exynos4_clk_sleep_init(void) {}
363#endif 363#endif
364 364
365/* list of all parent clock list */ 365/* list of all parent clock list */
@@ -428,7 +428,7 @@ static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata
428/* fixed rate clocks generated inside the soc */ 428/* fixed rate clocks generated inside the soc */
429static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = { 429static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = {
430 FRATE(0, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000), 430 FRATE(0, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
431 FRATE(0, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000), 431 FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
432 FRATE(0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000), 432 FRATE(0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
433}; 433};
434 434
@@ -903,7 +903,7 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
903 GATE(CLK_AUDSS, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0), 903 GATE(CLK_AUDSS, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0),
904 GATE(CLK_MDNIE0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0), 904 GATE(CLK_MDNIE0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0),
905 GATE(CLK_ROTATOR, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0), 905 GATE(CLK_ROTATOR, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0),
906 GATE(CLK_MDMA2, "mdma2", "aclk200", E4X12_GATE_IP_IMAGE, 2, 0, 0), 906 GATE(CLK_MDMA, "mdma", "aclk200", E4X12_GATE_IP_IMAGE, 2, 0, 0),
907 GATE(CLK_SMMU_MDMA, "smmu_mdma", "aclk200", E4X12_GATE_IP_IMAGE, 5, 0, 907 GATE(CLK_SMMU_MDMA, "smmu_mdma", "aclk200", E4X12_GATE_IP_IMAGE, 5, 0,
908 0), 908 0),
909 GATE(CLK_MIPI_HSI, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0), 909 GATE(CLK_MIPI_HSI, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0),
@@ -1043,7 +1043,7 @@ static unsigned long exynos4_get_xom(void)
1043 return xom; 1043 return xom;
1044} 1044}
1045 1045
1046static void __init exynos4_clk_register_finpll(void) 1046static void __init exynos4_clk_register_finpll(struct samsung_clk_provider *ctx)
1047{ 1047{
1048 struct samsung_fixed_rate_clock fclk; 1048 struct samsung_fixed_rate_clock fclk;
1049 struct clk *clk; 1049 struct clk *clk;
@@ -1066,7 +1066,7 @@ static void __init exynos4_clk_register_finpll(void)
1066 fclk.parent_name = NULL; 1066 fclk.parent_name = NULL;
1067 fclk.flags = CLK_IS_ROOT; 1067 fclk.flags = CLK_IS_ROOT;
1068 fclk.fixed_rate = finpll_f; 1068 fclk.fixed_rate = finpll_f;
1069 samsung_clk_register_fixed_rate(&fclk, 1); 1069 samsung_clk_register_fixed_rate(ctx, &fclk, 1);
1070 1070
1071} 1071}
1072 1072
@@ -1176,22 +1176,25 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
1176static void __init exynos4_clk_init(struct device_node *np, 1176static void __init exynos4_clk_init(struct device_node *np,
1177 enum exynos4_soc soc) 1177 enum exynos4_soc soc)
1178{ 1178{
1179 struct samsung_clk_provider *ctx;
1179 exynos4_soc = soc; 1180 exynos4_soc = soc;
1180 1181
1181 reg_base = of_iomap(np, 0); 1182 reg_base = of_iomap(np, 0);
1182 if (!reg_base) 1183 if (!reg_base)
1183 panic("%s: failed to map registers\n", __func__); 1184 panic("%s: failed to map registers\n", __func__);
1184 1185
1185 samsung_clk_init(np, reg_base, CLK_NR_CLKS); 1186 ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
1187 if (!ctx)
1188 panic("%s: unable to allocate context.\n", __func__);
1186 1189
1187 samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks, 1190 samsung_clk_of_register_fixed_ext(ctx, exynos4_fixed_rate_ext_clks,
1188 ARRAY_SIZE(exynos4_fixed_rate_ext_clks), 1191 ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
1189 ext_clk_match); 1192 ext_clk_match);
1190 1193
1191 exynos4_clk_register_finpll(); 1194 exynos4_clk_register_finpll(ctx);
1192 1195
1193 if (exynos4_soc == EXYNOS4210) { 1196 if (exynos4_soc == EXYNOS4210) {
1194 samsung_clk_register_mux(exynos4210_mux_early, 1197 samsung_clk_register_mux(ctx, exynos4210_mux_early,
1195 ARRAY_SIZE(exynos4210_mux_early)); 1198 ARRAY_SIZE(exynos4210_mux_early));
1196 1199
1197 if (_get_rate("fin_pll") == 24000000) { 1200 if (_get_rate("fin_pll") == 24000000) {
@@ -1205,7 +1208,7 @@ static void __init exynos4_clk_init(struct device_node *np,
1205 exynos4210_plls[vpll].rate_table = 1208 exynos4210_plls[vpll].rate_table =
1206 exynos4210_vpll_rates; 1209 exynos4210_vpll_rates;
1207 1210
1208 samsung_clk_register_pll(exynos4210_plls, 1211 samsung_clk_register_pll(ctx, exynos4210_plls,
1209 ARRAY_SIZE(exynos4210_plls), reg_base); 1212 ARRAY_SIZE(exynos4210_plls), reg_base);
1210 } else { 1213 } else {
1211 if (_get_rate("fin_pll") == 24000000) { 1214 if (_get_rate("fin_pll") == 24000000) {
@@ -1217,42 +1220,42 @@ static void __init exynos4_clk_init(struct device_node *np,
1217 exynos4x12_vpll_rates; 1220 exynos4x12_vpll_rates;
1218 } 1221 }
1219 1222
1220 samsung_clk_register_pll(exynos4x12_plls, 1223 samsung_clk_register_pll(ctx, exynos4x12_plls,
1221 ARRAY_SIZE(exynos4x12_plls), reg_base); 1224 ARRAY_SIZE(exynos4x12_plls), reg_base);
1222 } 1225 }
1223 1226
1224 samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks, 1227 samsung_clk_register_fixed_rate(ctx, exynos4_fixed_rate_clks,
1225 ARRAY_SIZE(exynos4_fixed_rate_clks)); 1228 ARRAY_SIZE(exynos4_fixed_rate_clks));
1226 samsung_clk_register_mux(exynos4_mux_clks, 1229 samsung_clk_register_mux(ctx, exynos4_mux_clks,
1227 ARRAY_SIZE(exynos4_mux_clks)); 1230 ARRAY_SIZE(exynos4_mux_clks));
1228 samsung_clk_register_div(exynos4_div_clks, 1231 samsung_clk_register_div(ctx, exynos4_div_clks,
1229 ARRAY_SIZE(exynos4_div_clks)); 1232 ARRAY_SIZE(exynos4_div_clks));
1230 samsung_clk_register_gate(exynos4_gate_clks, 1233 samsung_clk_register_gate(ctx, exynos4_gate_clks,
1231 ARRAY_SIZE(exynos4_gate_clks)); 1234 ARRAY_SIZE(exynos4_gate_clks));
1232 1235
1233 if (exynos4_soc == EXYNOS4210) { 1236 if (exynos4_soc == EXYNOS4210) {
1234 samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks, 1237 samsung_clk_register_fixed_rate(ctx, exynos4210_fixed_rate_clks,
1235 ARRAY_SIZE(exynos4210_fixed_rate_clks)); 1238 ARRAY_SIZE(exynos4210_fixed_rate_clks));
1236 samsung_clk_register_mux(exynos4210_mux_clks, 1239 samsung_clk_register_mux(ctx, exynos4210_mux_clks,
1237 ARRAY_SIZE(exynos4210_mux_clks)); 1240 ARRAY_SIZE(exynos4210_mux_clks));
1238 samsung_clk_register_div(exynos4210_div_clks, 1241 samsung_clk_register_div(ctx, exynos4210_div_clks,
1239 ARRAY_SIZE(exynos4210_div_clks)); 1242 ARRAY_SIZE(exynos4210_div_clks));
1240 samsung_clk_register_gate(exynos4210_gate_clks, 1243 samsung_clk_register_gate(ctx, exynos4210_gate_clks,
1241 ARRAY_SIZE(exynos4210_gate_clks)); 1244 ARRAY_SIZE(exynos4210_gate_clks));
1242 samsung_clk_register_alias(exynos4210_aliases, 1245 samsung_clk_register_alias(ctx, exynos4210_aliases,
1243 ARRAY_SIZE(exynos4210_aliases)); 1246 ARRAY_SIZE(exynos4210_aliases));
1244 } else { 1247 } else {
1245 samsung_clk_register_mux(exynos4x12_mux_clks, 1248 samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
1246 ARRAY_SIZE(exynos4x12_mux_clks)); 1249 ARRAY_SIZE(exynos4x12_mux_clks));
1247 samsung_clk_register_div(exynos4x12_div_clks, 1250 samsung_clk_register_div(ctx, exynos4x12_div_clks,
1248 ARRAY_SIZE(exynos4x12_div_clks)); 1251 ARRAY_SIZE(exynos4x12_div_clks));
1249 samsung_clk_register_gate(exynos4x12_gate_clks, 1252 samsung_clk_register_gate(ctx, exynos4x12_gate_clks,
1250 ARRAY_SIZE(exynos4x12_gate_clks)); 1253 ARRAY_SIZE(exynos4x12_gate_clks));
1251 samsung_clk_register_alias(exynos4x12_aliases, 1254 samsung_clk_register_alias(ctx, exynos4x12_aliases,
1252 ARRAY_SIZE(exynos4x12_aliases)); 1255 ARRAY_SIZE(exynos4x12_aliases));
1253 } 1256 }
1254 1257
1255 samsung_clk_register_alias(exynos4_aliases, 1258 samsung_clk_register_alias(ctx, exynos4_aliases,
1256 ARRAY_SIZE(exynos4_aliases)); 1259 ARRAY_SIZE(exynos4_aliases));
1257 1260
1258 exynos4_clk_sleep_init(); 1261 exynos4_clk_sleep_init();
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index e7ee4420da81..1fad4c5e3f5d 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -24,10 +24,14 @@
24#define APLL_CON0 0x100 24#define APLL_CON0 0x100
25#define SRC_CPU 0x200 25#define SRC_CPU 0x200
26#define DIV_CPU0 0x500 26#define DIV_CPU0 0x500
27#define PWR_CTRL1 0x1020
28#define PWR_CTRL2 0x1024
27#define MPLL_LOCK 0x4000 29#define MPLL_LOCK 0x4000
28#define MPLL_CON0 0x4100 30#define MPLL_CON0 0x4100
29#define SRC_CORE1 0x4204 31#define SRC_CORE1 0x4204
30#define GATE_IP_ACP 0x8800 32#define GATE_IP_ACP 0x8800
33#define GATE_IP_ISP0 0xc800
34#define GATE_IP_ISP1 0xc804
31#define CPLL_LOCK 0x10020 35#define CPLL_LOCK 0x10020
32#define EPLL_LOCK 0x10030 36#define EPLL_LOCK 0x10030
33#define VPLL_LOCK 0x10040 37#define VPLL_LOCK 0x10040
@@ -37,6 +41,7 @@
37#define VPLL_CON0 0x10140 41#define VPLL_CON0 0x10140
38#define GPLL_CON0 0x10150 42#define GPLL_CON0 0x10150
39#define SRC_TOP0 0x10210 43#define SRC_TOP0 0x10210
44#define SRC_TOP1 0x10214
40#define SRC_TOP2 0x10218 45#define SRC_TOP2 0x10218
41#define SRC_TOP3 0x1021c 46#define SRC_TOP3 0x1021c
42#define SRC_GSCL 0x10220 47#define SRC_GSCL 0x10220
@@ -71,6 +76,7 @@
71#define GATE_IP_GSCL 0x10920 76#define GATE_IP_GSCL 0x10920
72#define GATE_IP_DISP1 0x10928 77#define GATE_IP_DISP1 0x10928
73#define GATE_IP_MFC 0x1092c 78#define GATE_IP_MFC 0x1092c
79#define GATE_IP_G3D 0x10930
74#define GATE_IP_GEN 0x10934 80#define GATE_IP_GEN 0x10934
75#define GATE_IP_FSYS 0x10944 81#define GATE_IP_FSYS 0x10944
76#define GATE_IP_PERIC 0x10950 82#define GATE_IP_PERIC 0x10950
@@ -80,6 +86,23 @@
80#define SRC_CDREX 0x20200 86#define SRC_CDREX 0x20200
81#define PLL_DIV2_SEL 0x20a24 87#define PLL_DIV2_SEL 0x20a24
82 88
89/*Below definitions are used for PWR_CTRL settings*/
90#define PWR_CTRL1_CORE2_DOWN_RATIO (7 << 28)
91#define PWR_CTRL1_CORE1_DOWN_RATIO (7 << 16)
92#define PWR_CTRL1_DIV2_DOWN_EN (1 << 9)
93#define PWR_CTRL1_DIV1_DOWN_EN (1 << 8)
94#define PWR_CTRL1_USE_CORE1_WFE (1 << 5)
95#define PWR_CTRL1_USE_CORE0_WFE (1 << 4)
96#define PWR_CTRL1_USE_CORE1_WFI (1 << 1)
97#define PWR_CTRL1_USE_CORE0_WFI (1 << 0)
98
99#define PWR_CTRL2_DIV2_UP_EN (1 << 25)
100#define PWR_CTRL2_DIV1_UP_EN (1 << 24)
101#define PWR_CTRL2_DUR_STANDBY2_VAL (1 << 16)
102#define PWR_CTRL2_DUR_STANDBY1_VAL (1 << 8)
103#define PWR_CTRL2_CORE2_UP_RATIO (1 << 4)
104#define PWR_CTRL2_CORE1_UP_RATIO (1 << 0)
105
83/* list of PLLs to be registered */ 106/* list of PLLs to be registered */
84enum exynos5250_plls { 107enum exynos5250_plls {
85 apll, mpll, cpll, epll, vpll, gpll, bpll, 108 apll, mpll, cpll, epll, vpll, gpll, bpll,
@@ -98,8 +121,11 @@ static struct samsung_clk_reg_dump *exynos5250_save;
98static unsigned long exynos5250_clk_regs[] __initdata = { 121static unsigned long exynos5250_clk_regs[] __initdata = {
99 SRC_CPU, 122 SRC_CPU,
100 DIV_CPU0, 123 DIV_CPU0,
124 PWR_CTRL1,
125 PWR_CTRL2,
101 SRC_CORE1, 126 SRC_CORE1,
102 SRC_TOP0, 127 SRC_TOP0,
128 SRC_TOP1,
103 SRC_TOP2, 129 SRC_TOP2,
104 SRC_TOP3, 130 SRC_TOP3,
105 SRC_GSCL, 131 SRC_GSCL,
@@ -133,6 +159,7 @@ static unsigned long exynos5250_clk_regs[] __initdata = {
133 DIV_PERIC5, 159 DIV_PERIC5,
134 GATE_IP_GSCL, 160 GATE_IP_GSCL,
135 GATE_IP_MFC, 161 GATE_IP_MFC,
162 GATE_IP_G3D,
136 GATE_IP_GEN, 163 GATE_IP_GEN,
137 GATE_IP_FSYS, 164 GATE_IP_FSYS,
138 GATE_IP_PERIC, 165 GATE_IP_PERIC,
@@ -141,6 +168,8 @@ static unsigned long exynos5250_clk_regs[] __initdata = {
141 PLL_DIV2_SEL, 168 PLL_DIV2_SEL,
142 GATE_IP_DISP1, 169 GATE_IP_DISP1,
143 GATE_IP_ACP, 170 GATE_IP_ACP,
171 GATE_IP_ISP0,
172 GATE_IP_ISP1,
144}; 173};
145 174
146static int exynos5250_clk_suspend(void) 175static int exynos5250_clk_suspend(void)
@@ -189,13 +218,16 @@ PNAME(mout_vpllsrc_p) = { "fin_pll", "sclk_hdmi27m" };
189PNAME(mout_vpll_p) = { "mout_vpllsrc", "fout_vpll" }; 218PNAME(mout_vpll_p) = { "mout_vpllsrc", "fout_vpll" };
190PNAME(mout_cpll_p) = { "fin_pll", "fout_cpll" }; 219PNAME(mout_cpll_p) = { "fin_pll", "fout_cpll" };
191PNAME(mout_epll_p) = { "fin_pll", "fout_epll" }; 220PNAME(mout_epll_p) = { "fin_pll", "fout_epll" };
221PNAME(mout_gpll_p) = { "fin_pll", "fout_gpll" };
192PNAME(mout_mpll_user_p) = { "fin_pll", "mout_mpll" }; 222PNAME(mout_mpll_user_p) = { "fin_pll", "mout_mpll" };
193PNAME(mout_bpll_user_p) = { "fin_pll", "mout_bpll" }; 223PNAME(mout_bpll_user_p) = { "fin_pll", "mout_bpll" };
194PNAME(mout_aclk166_p) = { "mout_cpll", "mout_mpll_user" }; 224PNAME(mout_aclk166_p) = { "mout_cpll", "mout_mpll_user" };
195PNAME(mout_aclk200_p) = { "mout_mpll_user", "mout_bpll_user" }; 225PNAME(mout_aclk200_p) = { "mout_mpll_user", "mout_bpll_user" };
226PNAME(mout_aclk400_p) = { "mout_aclk400_g3d_mid", "mout_gpll" };
196PNAME(mout_aclk200_sub_p) = { "fin_pll", "div_aclk200" }; 227PNAME(mout_aclk200_sub_p) = { "fin_pll", "div_aclk200" };
197PNAME(mout_aclk266_sub_p) = { "fin_pll", "div_aclk266" }; 228PNAME(mout_aclk266_sub_p) = { "fin_pll", "div_aclk266" };
198PNAME(mout_aclk333_sub_p) = { "fin_pll", "div_aclk333" }; 229PNAME(mout_aclk333_sub_p) = { "fin_pll", "div_aclk333" };
230PNAME(mout_aclk400_isp_sub_p) = { "fin_pll", "div_aclk400_isp" };
199PNAME(mout_hdmi_p) = { "div_hdmi_pixel", "sclk_hdmiphy" }; 231PNAME(mout_hdmi_p) = { "div_hdmi_pixel", "sclk_hdmiphy" };
200PNAME(mout_usb3_p) = { "mout_mpll_user", "mout_cpll" }; 232PNAME(mout_usb3_p) = { "mout_mpll_user", "mout_cpll" };
201PNAME(mout_group1_p) = { "fin_pll", "fin_pll", "sclk_hdmi27m", 233PNAME(mout_group1_p) = { "fin_pll", "fin_pll", "sclk_hdmi27m",
@@ -273,15 +305,23 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
273 MUX(0, "mout_aclk166", mout_aclk166_p, SRC_TOP0, 8, 1), 305 MUX(0, "mout_aclk166", mout_aclk166_p, SRC_TOP0, 8, 1),
274 MUX(0, "mout_aclk200", mout_aclk200_p, SRC_TOP0, 12, 1), 306 MUX(0, "mout_aclk200", mout_aclk200_p, SRC_TOP0, 12, 1),
275 MUX(0, "mout_aclk333", mout_aclk166_p, SRC_TOP0, 16, 1), 307 MUX(0, "mout_aclk333", mout_aclk166_p, SRC_TOP0, 16, 1),
308 MUX(0, "mout_aclk400_g3d_mid", mout_aclk200_p, SRC_TOP0, 20, 1),
309
310 MUX(0, "mout_aclk400_isp", mout_aclk200_p, SRC_TOP1, 24, 1),
311 MUX(0, "mout_aclk400_g3d", mout_aclk400_p, SRC_TOP1, 28, 1),
276 312
277 MUX(0, "mout_cpll", mout_cpll_p, SRC_TOP2, 8, 1), 313 MUX(0, "mout_cpll", mout_cpll_p, SRC_TOP2, 8, 1),
278 MUX(0, "mout_epll", mout_epll_p, SRC_TOP2, 12, 1), 314 MUX(0, "mout_epll", mout_epll_p, SRC_TOP2, 12, 1),
279 MUX(0, "mout_vpll", mout_vpll_p, SRC_TOP2, 16, 1), 315 MUX(0, "mout_vpll", mout_vpll_p, SRC_TOP2, 16, 1),
280 MUX(0, "mout_mpll_user", mout_mpll_user_p, SRC_TOP2, 20, 1), 316 MUX(0, "mout_mpll_user", mout_mpll_user_p, SRC_TOP2, 20, 1),
281 MUX(0, "mout_bpll_user", mout_bpll_user_p, SRC_TOP2, 24, 1), 317 MUX(0, "mout_bpll_user", mout_bpll_user_p, SRC_TOP2, 24, 1),
318 MUX(CLK_MOUT_GPLL, "mout_gpll", mout_gpll_p, SRC_TOP2, 28, 1),
282 319
283 MUX(0, "mout_aclk200_disp1_sub", mout_aclk200_sub_p, SRC_TOP3, 4, 1), 320 MUX(0, "mout_aclk200_disp1_sub", mout_aclk200_sub_p, SRC_TOP3, 4, 1),
284 MUX(0, "mout_aclk266_gscl_sub", mout_aclk266_sub_p, SRC_TOP3, 8, 1), 321 MUX(0, "mout_aclk266_gscl_sub", mout_aclk266_sub_p, SRC_TOP3, 8, 1),
322 MUX(0, "mout_aclk_266_isp_sub", mout_aclk266_sub_p, SRC_TOP3, 16, 1),
323 MUX(0, "mout_aclk_400_isp_sub", mout_aclk400_isp_sub_p,
324 SRC_TOP3, 20, 1),
285 MUX(0, "mout_aclk333_sub", mout_aclk333_sub_p, SRC_TOP3, 24, 1), 325 MUX(0, "mout_aclk333_sub", mout_aclk333_sub_p, SRC_TOP3, 24, 1),
286 326
287 MUX(0, "mout_cam_bayer", mout_group1_p, SRC_GSCL, 12, 4), 327 MUX(0, "mout_cam_bayer", mout_group1_p, SRC_GSCL, 12, 4),
@@ -351,7 +391,10 @@ static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
351 DIV(0, "div_aclk200", "mout_aclk200", DIV_TOP0, 12, 3), 391 DIV(0, "div_aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
352 DIV(0, "div_aclk266", "mout_mpll_user", DIV_TOP0, 16, 3), 392 DIV(0, "div_aclk266", "mout_mpll_user", DIV_TOP0, 16, 3),
353 DIV(0, "div_aclk333", "mout_aclk333", DIV_TOP0, 20, 3), 393 DIV(0, "div_aclk333", "mout_aclk333", DIV_TOP0, 20, 3),
394 DIV(0, "div_aclk400_g3d", "mout_aclk400_g3d", DIV_TOP0,
395 24, 3),
354 396
397 DIV(0, "div_aclk400_isp", "mout_aclk400_isp", DIV_TOP1, 20, 3),
355 DIV(0, "div_aclk66_pre", "mout_mpll_user", DIV_TOP1, 24, 3), 398 DIV(0, "div_aclk66_pre", "mout_mpll_user", DIV_TOP1, 24, 3),
356 399
357 DIV(0, "div_cam_bayer", "mout_cam_bayer", DIV_GSCL, 12, 4), 400 DIV(0, "div_cam_bayer", "mout_cam_bayer", DIV_GSCL, 12, 4),
@@ -428,6 +471,7 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
428 * CMU_ACP 471 * CMU_ACP
429 */ 472 */
430 GATE(CLK_MDMA0, "mdma0", "div_aclk266", GATE_IP_ACP, 1, 0, 0), 473 GATE(CLK_MDMA0, "mdma0", "div_aclk266", GATE_IP_ACP, 1, 0, 0),
474 GATE(CLK_SSS, "sss", "div_aclk266", GATE_IP_ACP, 2, 0, 0),
431 GATE(CLK_G2D, "g2d", "div_aclk200", GATE_IP_ACP, 3, 0, 0), 475 GATE(CLK_G2D, "g2d", "div_aclk200", GATE_IP_ACP, 3, 0, 0),
432 GATE(CLK_SMMU_MDMA0, "smmu_mdma0", "div_aclk266", GATE_IP_ACP, 5, 0, 0), 476 GATE(CLK_SMMU_MDMA0, "smmu_mdma0", "div_aclk266", GATE_IP_ACP, 5, 0, 0),
433 477
@@ -533,7 +577,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
533 0), 577 0),
534 GATE(CLK_SMMU_MFCL, "smmu_mfcl", "mout_aclk333_sub", GATE_IP_MFC, 2, 0, 578 GATE(CLK_SMMU_MFCL, "smmu_mfcl", "mout_aclk333_sub", GATE_IP_MFC, 2, 0,
535 0), 579 0),
536 580 GATE(CLK_G3D, "g3d", "div_aclk400_g3d", GATE_IP_G3D, 0,
581 CLK_SET_RATE_PARENT, 0),
537 GATE(CLK_ROTATOR, "rotator", "div_aclk266", GATE_IP_GEN, 1, 0, 0), 582 GATE(CLK_ROTATOR, "rotator", "div_aclk266", GATE_IP_GEN, 1, 0, 0),
538 GATE(CLK_JPEG, "jpeg", "div_aclk166", GATE_IP_GEN, 2, 0, 0), 583 GATE(CLK_JPEG, "jpeg", "div_aclk166", GATE_IP_GEN, 2, 0, 0),
539 GATE(CLK_MDMA1, "mdma1", "div_aclk266", GATE_IP_GEN, 4, 0, 0), 584 GATE(CLK_MDMA1, "mdma1", "div_aclk266", GATE_IP_GEN, 4, 0, 0),
@@ -615,6 +660,31 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
615 GATE(CLK_WDT, "wdt", "div_aclk66", GATE_IP_PERIS, 19, 0, 0), 660 GATE(CLK_WDT, "wdt", "div_aclk66", GATE_IP_PERIS, 19, 0, 0),
616 GATE(CLK_RTC, "rtc", "div_aclk66", GATE_IP_PERIS, 20, 0, 0), 661 GATE(CLK_RTC, "rtc", "div_aclk66", GATE_IP_PERIS, 20, 0, 0),
617 GATE(CLK_TMU, "tmu", "div_aclk66", GATE_IP_PERIS, 21, 0, 0), 662 GATE(CLK_TMU, "tmu", "div_aclk66", GATE_IP_PERIS, 21, 0, 0),
663 GATE(CLK_SMMU_TV, "smmu_tv", "mout_aclk200_disp1_sub",
664 GATE_IP_DISP1, 2, 0, 0),
665 GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "mout_aclk200_disp1_sub",
666 GATE_IP_DISP1, 8, 0, 0),
667 GATE(CLK_SMMU_2D, "smmu_2d", "div_aclk200", GATE_IP_ACP, 7, 0, 0),
668 GATE(CLK_SMMU_FIMC_ISP, "smmu_fimc_isp", "mout_aclk_266_isp_sub",
669 GATE_IP_ISP0, 8, 0, 0),
670 GATE(CLK_SMMU_FIMC_DRC, "smmu_fimc_drc", "mout_aclk_266_isp_sub",
671 GATE_IP_ISP0, 9, 0, 0),
672 GATE(CLK_SMMU_FIMC_FD, "smmu_fimc_fd", "mout_aclk_266_isp_sub",
673 GATE_IP_ISP0, 10, 0, 0),
674 GATE(CLK_SMMU_FIMC_SCC, "smmu_fimc_scc", "mout_aclk_266_isp_sub",
675 GATE_IP_ISP0, 11, 0, 0),
676 GATE(CLK_SMMU_FIMC_SCP, "smmu_fimc_scp", "mout_aclk_266_isp_sub",
677 GATE_IP_ISP0, 12, 0, 0),
678 GATE(CLK_SMMU_FIMC_MCU, "smmu_fimc_mcu", "mout_aclk_400_isp_sub",
679 GATE_IP_ISP0, 13, 0, 0),
680 GATE(CLK_SMMU_FIMC_ODC, "smmu_fimc_odc", "mout_aclk_266_isp_sub",
681 GATE_IP_ISP1, 4, 0, 0),
682 GATE(CLK_SMMU_FIMC_DIS0, "smmu_fimc_dis0", "mout_aclk_266_isp_sub",
683 GATE_IP_ISP1, 5, 0, 0),
684 GATE(CLK_SMMU_FIMC_DIS1, "smmu_fimc_dis1", "mout_aclk_266_isp_sub",
685 GATE_IP_ISP1, 6, 0, 0),
686 GATE(CLK_SMMU_FIMC_3DNR, "smmu_fimc_3dnr", "mout_aclk_266_isp_sub",
687 GATE_IP_ISP1, 7, 0, 0),
618}; 688};
619 689
620static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = { 690static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = {
@@ -686,6 +756,9 @@ static struct of_device_id ext_clk_match[] __initdata = {
686/* register exynox5250 clocks */ 756/* register exynox5250 clocks */
687static void __init exynos5250_clk_init(struct device_node *np) 757static void __init exynos5250_clk_init(struct device_node *np)
688{ 758{
759 struct samsung_clk_provider *ctx;
760 unsigned int tmp;
761
689 if (np) { 762 if (np) {
690 reg_base = of_iomap(np, 0); 763 reg_base = of_iomap(np, 0);
691 if (!reg_base) 764 if (!reg_base)
@@ -694,11 +767,13 @@ static void __init exynos5250_clk_init(struct device_node *np)
694 panic("%s: unable to determine soc\n", __func__); 767 panic("%s: unable to determine soc\n", __func__);
695 } 768 }
696 769
697 samsung_clk_init(np, reg_base, CLK_NR_CLKS); 770 ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
698 samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks, 771 if (!ctx)
772 panic("%s: unable to allocate context.\n", __func__);
773 samsung_clk_of_register_fixed_ext(ctx, exynos5250_fixed_rate_ext_clks,
699 ARRAY_SIZE(exynos5250_fixed_rate_ext_clks), 774 ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
700 ext_clk_match); 775 ext_clk_match);
701 samsung_clk_register_mux(exynos5250_pll_pmux_clks, 776 samsung_clk_register_mux(ctx, exynos5250_pll_pmux_clks,
702 ARRAY_SIZE(exynos5250_pll_pmux_clks)); 777 ARRAY_SIZE(exynos5250_pll_pmux_clks));
703 778
704 if (_get_rate("fin_pll") == 24 * MHZ) { 779 if (_get_rate("fin_pll") == 24 * MHZ) {
@@ -709,19 +784,40 @@ static void __init exynos5250_clk_init(struct device_node *np)
709 if (_get_rate("mout_vpllsrc") == 24 * MHZ) 784 if (_get_rate("mout_vpllsrc") == 24 * MHZ)
710 exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl; 785 exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl;
711 786
712 samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls), 787 samsung_clk_register_pll(ctx, exynos5250_plls,
713 reg_base); 788 ARRAY_SIZE(exynos5250_plls),
714 samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks, 789 reg_base);
790 samsung_clk_register_fixed_rate(ctx, exynos5250_fixed_rate_clks,
715 ARRAY_SIZE(exynos5250_fixed_rate_clks)); 791 ARRAY_SIZE(exynos5250_fixed_rate_clks));
716 samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks, 792 samsung_clk_register_fixed_factor(ctx, exynos5250_fixed_factor_clks,
717 ARRAY_SIZE(exynos5250_fixed_factor_clks)); 793 ARRAY_SIZE(exynos5250_fixed_factor_clks));
718 samsung_clk_register_mux(exynos5250_mux_clks, 794 samsung_clk_register_mux(ctx, exynos5250_mux_clks,
719 ARRAY_SIZE(exynos5250_mux_clks)); 795 ARRAY_SIZE(exynos5250_mux_clks));
720 samsung_clk_register_div(exynos5250_div_clks, 796 samsung_clk_register_div(ctx, exynos5250_div_clks,
721 ARRAY_SIZE(exynos5250_div_clks)); 797 ARRAY_SIZE(exynos5250_div_clks));
722 samsung_clk_register_gate(exynos5250_gate_clks, 798 samsung_clk_register_gate(ctx, exynos5250_gate_clks,
723 ARRAY_SIZE(exynos5250_gate_clks)); 799 ARRAY_SIZE(exynos5250_gate_clks));
724 800
801 /*
802 * Enable arm clock down (in idle) and set arm divider
803 * ratios in WFI/WFE state.
804 */
805 tmp = (PWR_CTRL1_CORE2_DOWN_RATIO | PWR_CTRL1_CORE1_DOWN_RATIO |
806 PWR_CTRL1_DIV2_DOWN_EN | PWR_CTRL1_DIV1_DOWN_EN |
807 PWR_CTRL1_USE_CORE1_WFE | PWR_CTRL1_USE_CORE0_WFE |
808 PWR_CTRL1_USE_CORE1_WFI | PWR_CTRL1_USE_CORE0_WFI);
809 __raw_writel(tmp, reg_base + PWR_CTRL1);
810
811 /*
812 * Enable arm clock up (on exiting idle). Set arm divider
813 * ratios when not in idle along with the standby duration
814 * ratios.
815 */
816 tmp = (PWR_CTRL2_DIV2_UP_EN | PWR_CTRL2_DIV1_UP_EN |
817 PWR_CTRL2_DUR_STANDBY2_VAL | PWR_CTRL2_DUR_STANDBY1_VAL |
818 PWR_CTRL2_CORE2_UP_RATIO | PWR_CTRL2_CORE1_UP_RATIO);
819 __raw_writel(tmp, reg_base + PWR_CTRL2);
820
725 exynos5250_clk_sleep_init(); 821 exynos5250_clk_sleep_init();
726 822
727 pr_info("Exynos5250: clock setup completed, armclk=%ld\n", 823 pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
new file mode 100644
index 000000000000..64596ba58df1
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos5260.c
@@ -0,0 +1,1980 @@
1/*
2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 * Author: Rahul Sharma <rahul.sharma@samsung.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 * Common Clock Framework support for Exynos5260 SoC.
10 */
11
12#include <linux/clk.h>
13#include <linux/clkdev.h>
14#include <linux/clk-provider.h>
15#include <linux/of.h>
16#include <linux/of_address.h>
17#include <linux/syscore_ops.h>
18
19#include "clk-exynos5260.h"
20#include "clk.h"
21#include "clk-pll.h"
22
23#include <dt-bindings/clock/exynos5260-clk.h>
24
25static LIST_HEAD(clock_reg_cache_list);
26
27struct exynos5260_clock_reg_cache {
28 struct list_head node;
29 void __iomem *reg_base;
30 struct samsung_clk_reg_dump *rdump;
31 unsigned int rd_num;
32};
33
34struct exynos5260_cmu_info {
35 /* list of pll clocks and respective count */
36 struct samsung_pll_clock *pll_clks;
37 unsigned int nr_pll_clks;
38 /* list of mux clocks and respective count */
39 struct samsung_mux_clock *mux_clks;
40 unsigned int nr_mux_clks;
41 /* list of div clocks and respective count */
42 struct samsung_div_clock *div_clks;
43 unsigned int nr_div_clks;
44 /* list of gate clocks and respective count */
45 struct samsung_gate_clock *gate_clks;
46 unsigned int nr_gate_clks;
47 /* list of fixed clocks and respective count */
48 struct samsung_fixed_rate_clock *fixed_clks;
49 unsigned int nr_fixed_clks;
50 /* total number of clocks with IDs assigned*/
51 unsigned int nr_clk_ids;
52
53 /* list and number of clocks registers */
54 unsigned long *clk_regs;
55 unsigned int nr_clk_regs;
56};
57
58/*
59 * Applicable for all 2550 Type PLLS for Exynos5260, listed below
60 * DISP_PLL, EGL_PLL, KFC_PLL, MEM_PLL, BUS_PLL, MEDIA_PLL, G3D_PLL.
61 */
62static struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initdata = {
63 PLL_35XX_RATE(1700000000, 425, 6, 0),
64 PLL_35XX_RATE(1600000000, 200, 3, 0),
65 PLL_35XX_RATE(1500000000, 250, 4, 0),
66 PLL_35XX_RATE(1400000000, 175, 3, 0),
67 PLL_35XX_RATE(1300000000, 325, 6, 0),
68 PLL_35XX_RATE(1200000000, 400, 4, 1),
69 PLL_35XX_RATE(1100000000, 275, 3, 1),
70 PLL_35XX_RATE(1000000000, 250, 3, 1),
71 PLL_35XX_RATE(933000000, 311, 4, 1),
72 PLL_35XX_RATE(900000000, 300, 4, 1),
73 PLL_35XX_RATE(800000000, 200, 3, 1),
74 PLL_35XX_RATE(733000000, 733, 12, 1),
75 PLL_35XX_RATE(700000000, 175, 3, 1),
76 PLL_35XX_RATE(667000000, 667, 12, 1),
77 PLL_35XX_RATE(633000000, 211, 4, 1),
78 PLL_35XX_RATE(620000000, 310, 3, 2),
79 PLL_35XX_RATE(600000000, 400, 4, 2),
80 PLL_35XX_RATE(543000000, 362, 4, 2),
81 PLL_35XX_RATE(533000000, 533, 6, 2),
82 PLL_35XX_RATE(500000000, 250, 3, 2),
83 PLL_35XX_RATE(450000000, 300, 4, 2),
84 PLL_35XX_RATE(400000000, 200, 3, 2),
85 PLL_35XX_RATE(350000000, 175, 3, 2),
86 PLL_35XX_RATE(300000000, 400, 4, 3),
87 PLL_35XX_RATE(266000000, 266, 3, 3),
88 PLL_35XX_RATE(200000000, 200, 3, 3),
89 PLL_35XX_RATE(160000000, 160, 3, 3),
90};
91
92/*
93 * Applicable for 2650 Type PLL for AUD_PLL.
94 */
95static struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initdata = {
96 PLL_36XX_RATE(1600000000, 200, 3, 0, 0),
97 PLL_36XX_RATE(1200000000, 100, 2, 0, 0),
98 PLL_36XX_RATE(1000000000, 250, 3, 1, 0),
99 PLL_36XX_RATE(800000000, 200, 3, 1, 0),
100 PLL_36XX_RATE(600000000, 100, 2, 1, 0),
101 PLL_36XX_RATE(532000000, 266, 3, 2, 0),
102 PLL_36XX_RATE(480000000, 160, 2, 2, 0),
103 PLL_36XX_RATE(432000000, 144, 2, 2, 0),
104 PLL_36XX_RATE(400000000, 200, 3, 2, 0),
105 PLL_36XX_RATE(394073130, 459, 7, 2, 49282),
106 PLL_36XX_RATE(333000000, 111, 2, 2, 0),
107 PLL_36XX_RATE(300000000, 100, 2, 2, 0),
108 PLL_36XX_RATE(266000000, 266, 3, 3, 0),
109 PLL_36XX_RATE(200000000, 200, 3, 3, 0),
110 PLL_36XX_RATE(166000000, 166, 3, 3, 0),
111 PLL_36XX_RATE(133000000, 266, 3, 4, 0),
112 PLL_36XX_RATE(100000000, 200, 3, 4, 0),
113 PLL_36XX_RATE(66000000, 176, 2, 5, 0),
114};
115
116#ifdef CONFIG_PM_SLEEP
117
118static int exynos5260_clk_suspend(void)
119{
120 struct exynos5260_clock_reg_cache *cache;
121
122 list_for_each_entry(cache, &clock_reg_cache_list, node)
123 samsung_clk_save(cache->reg_base, cache->rdump,
124 cache->rd_num);
125
126 return 0;
127}
128
129static void exynos5260_clk_resume(void)
130{
131 struct exynos5260_clock_reg_cache *cache;
132
133 list_for_each_entry(cache, &clock_reg_cache_list, node)
134 samsung_clk_restore(cache->reg_base, cache->rdump,
135 cache->rd_num);
136}
137
138static struct syscore_ops exynos5260_clk_syscore_ops = {
139 .suspend = exynos5260_clk_suspend,
140 .resume = exynos5260_clk_resume,
141};
142
143static void exynos5260_clk_sleep_init(void __iomem *reg_base,
144 unsigned long *rdump,
145 unsigned long nr_rdump)
146{
147 struct exynos5260_clock_reg_cache *reg_cache;
148
149 reg_cache = kzalloc(sizeof(struct exynos5260_clock_reg_cache),
150 GFP_KERNEL);
151 if (!reg_cache)
152 panic("could not allocate register cache.\n");
153
154 reg_cache->rdump = samsung_clk_alloc_reg_dump(rdump, nr_rdump);
155
156 if (!reg_cache->rdump)
157 panic("could not allocate register dump storage.\n");
158
159 if (list_empty(&clock_reg_cache_list))
160 register_syscore_ops(&exynos5260_clk_syscore_ops);
161
162 reg_cache->rd_num = nr_rdump;
163 reg_cache->reg_base = reg_base;
164 list_add_tail(&reg_cache->node, &clock_reg_cache_list);
165}
166
167#else
168static void exynos5260_clk_sleep_init(void __iomem *reg_base,
169 unsigned long *rdump,
170 unsigned long nr_rdump){}
171#endif
172
173/*
174 * Common function which registers plls, muxes, dividers and gates
175 * for each CMU. It also add CMU register list to register cache.
176 */
177
178void __init exynos5260_cmu_register_one(struct device_node *np,
179 struct exynos5260_cmu_info *cmu)
180{
181 void __iomem *reg_base;
182 struct samsung_clk_provider *ctx;
183
184 reg_base = of_iomap(np, 0);
185 if (!reg_base)
186 panic("%s: failed to map registers\n", __func__);
187
188 ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids);
189 if (!ctx)
190 panic("%s: unable to alllocate ctx\n", __func__);
191
192 if (cmu->pll_clks)
193 samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks,
194 reg_base);
195 if (cmu->mux_clks)
196 samsung_clk_register_mux(ctx, cmu->mux_clks,
197 cmu->nr_mux_clks);
198 if (cmu->div_clks)
199 samsung_clk_register_div(ctx, cmu->div_clks, cmu->nr_div_clks);
200 if (cmu->gate_clks)
201 samsung_clk_register_gate(ctx, cmu->gate_clks,
202 cmu->nr_gate_clks);
203 if (cmu->fixed_clks)
204 samsung_clk_register_fixed_rate(ctx, cmu->fixed_clks,
205 cmu->nr_fixed_clks);
206 if (cmu->clk_regs)
207 exynos5260_clk_sleep_init(reg_base, cmu->clk_regs,
208 cmu->nr_clk_regs);
209}
210
211
212/* CMU_AUD */
213
214static unsigned long aud_clk_regs[] __initdata = {
215 MUX_SEL_AUD,
216 DIV_AUD0,
217 DIV_AUD1,
218 EN_ACLK_AUD,
219 EN_PCLK_AUD,
220 EN_SCLK_AUD,
221 EN_IP_AUD,
222};
223
224PNAME(mout_aud_pll_user_p) = {"fin_pll", "fout_aud_pll"};
225PNAME(mout_sclk_aud_i2s_p) = {"mout_aud_pll_user", "ioclk_i2s_cdclk"};
226PNAME(mout_sclk_aud_pcm_p) = {"mout_aud_pll_user", "ioclk_pcm_extclk"};
227
228struct samsung_mux_clock aud_mux_clks[] __initdata = {
229 MUX(AUD_MOUT_AUD_PLL_USER, "mout_aud_pll_user", mout_aud_pll_user_p,
230 MUX_SEL_AUD, 0, 1),
231 MUX(AUD_MOUT_SCLK_AUD_I2S, "mout_sclk_aud_i2s", mout_sclk_aud_i2s_p,
232 MUX_SEL_AUD, 4, 1),
233 MUX(AUD_MOUT_SCLK_AUD_PCM, "mout_sclk_aud_pcm", mout_sclk_aud_pcm_p,
234 MUX_SEL_AUD, 8, 1),
235};
236
237struct samsung_div_clock aud_div_clks[] __initdata = {
238 DIV(AUD_DOUT_ACLK_AUD_131, "dout_aclk_aud_131", "mout_aud_pll_user",
239 DIV_AUD0, 0, 4),
240
241 DIV(AUD_DOUT_SCLK_AUD_I2S, "dout_sclk_aud_i2s", "mout_sclk_aud_i2s",
242 DIV_AUD1, 0, 4),
243 DIV(AUD_DOUT_SCLK_AUD_PCM, "dout_sclk_aud_pcm", "mout_sclk_aud_pcm",
244 DIV_AUD1, 4, 8),
245 DIV(AUD_DOUT_SCLK_AUD_UART, "dout_sclk_aud_uart", "mout_aud_pll_user",
246 DIV_AUD1, 12, 4),
247};
248
249struct samsung_gate_clock aud_gate_clks[] __initdata = {
250 GATE(AUD_SCLK_I2S, "sclk_aud_i2s", "dout_sclk_aud_i2s",
251 EN_SCLK_AUD, 0, CLK_SET_RATE_PARENT, 0),
252 GATE(AUD_SCLK_PCM, "sclk_aud_pcm", "dout_sclk_aud_pcm",
253 EN_SCLK_AUD, 1, CLK_SET_RATE_PARENT, 0),
254 GATE(AUD_SCLK_AUD_UART, "sclk_aud_uart", "dout_sclk_aud_uart",
255 EN_SCLK_AUD, 2, CLK_SET_RATE_PARENT, 0),
256
257 GATE(AUD_CLK_SRAMC, "clk_sramc", "dout_aclk_aud_131", EN_IP_AUD,
258 0, 0, 0),
259 GATE(AUD_CLK_DMAC, "clk_dmac", "dout_aclk_aud_131",
260 EN_IP_AUD, 1, 0, 0),
261 GATE(AUD_CLK_I2S, "clk_i2s", "dout_aclk_aud_131", EN_IP_AUD, 2, 0, 0),
262 GATE(AUD_CLK_PCM, "clk_pcm", "dout_aclk_aud_131", EN_IP_AUD, 3, 0, 0),
263 GATE(AUD_CLK_AUD_UART, "clk_aud_uart", "dout_aclk_aud_131",
264 EN_IP_AUD, 4, 0, 0),
265};
266
267static void __init exynos5260_clk_aud_init(struct device_node *np)
268{
269 struct exynos5260_cmu_info cmu = {0};
270
271 cmu.mux_clks = aud_mux_clks;
272 cmu.nr_mux_clks = ARRAY_SIZE(aud_mux_clks);
273 cmu.div_clks = aud_div_clks;
274 cmu.nr_div_clks = ARRAY_SIZE(aud_div_clks);
275 cmu.gate_clks = aud_gate_clks;
276 cmu.nr_gate_clks = ARRAY_SIZE(aud_gate_clks);
277 cmu.nr_clk_ids = AUD_NR_CLK;
278 cmu.clk_regs = aud_clk_regs;
279 cmu.nr_clk_regs = ARRAY_SIZE(aud_clk_regs);
280
281 exynos5260_cmu_register_one(np, &cmu);
282}
283
284CLK_OF_DECLARE(exynos5260_clk_aud, "samsung,exynos5260-clock-aud",
285 exynos5260_clk_aud_init);
286
287
288/* CMU_DISP */
289
290static unsigned long disp_clk_regs[] __initdata = {
291 MUX_SEL_DISP0,
292 MUX_SEL_DISP1,
293 MUX_SEL_DISP2,
294 MUX_SEL_DISP3,
295 MUX_SEL_DISP4,
296 DIV_DISP,
297 EN_ACLK_DISP,
298 EN_PCLK_DISP,
299 EN_SCLK_DISP0,
300 EN_SCLK_DISP1,
301 EN_IP_DISP,
302 EN_IP_DISP_BUS,
303};
304
305PNAME(mout_phyclk_dptx_phy_ch3_txd_clk_user_p) = {"fin_pll",
306 "phyclk_dptx_phy_ch3_txd_clk"};
307PNAME(mout_phyclk_dptx_phy_ch2_txd_clk_user_p) = {"fin_pll",
308 "phyclk_dptx_phy_ch2_txd_clk"};
309PNAME(mout_phyclk_dptx_phy_ch1_txd_clk_user_p) = {"fin_pll",
310 "phyclk_dptx_phy_ch1_txd_clk"};
311PNAME(mout_phyclk_dptx_phy_ch0_txd_clk_user_p) = {"fin_pll",
312 "phyclk_dptx_phy_ch0_txd_clk"};
313PNAME(mout_aclk_disp_222_user_p) = {"fin_pll", "dout_aclk_disp_222"};
314PNAME(mout_sclk_disp_pixel_user_p) = {"fin_pll", "dout_sclk_disp_pixel"};
315PNAME(mout_aclk_disp_333_user_p) = {"fin_pll", "dout_aclk_disp_333"};
316PNAME(mout_phyclk_hdmi_phy_tmds_clko_user_p) = {"fin_pll",
317 "phyclk_hdmi_phy_tmds_clko"};
318PNAME(mout_phyclk_hdmi_phy_ref_clko_user_p) = {"fin_pll",
319 "phyclk_hdmi_phy_ref_clko"};
320PNAME(mout_phyclk_hdmi_phy_pixel_clko_user_p) = {"fin_pll",
321 "phyclk_hdmi_phy_pixel_clko"};
322PNAME(mout_phyclk_hdmi_link_o_tmds_clkhi_user_p) = {"fin_pll",
323 "phyclk_hdmi_link_o_tmds_clkhi"};
324PNAME(mout_phyclk_mipi_dphy_4l_m_txbyte_clkhs_p) = {"fin_pll",
325 "phyclk_mipi_dphy_4l_m_txbyte_clkhs"};
326PNAME(mout_phyclk_dptx_phy_o_ref_clk_24m_user_p) = {"fin_pll",
327 "phyclk_dptx_phy_o_ref_clk_24m"};
328PNAME(mout_phyclk_dptx_phy_clk_div2_user_p) = {"fin_pll",
329 "phyclk_dptx_phy_clk_div2"};
330PNAME(mout_sclk_hdmi_pixel_p) = {"mout_sclk_disp_pixel_user",
331 "mout_aclk_disp_222_user"};
332PNAME(mout_phyclk_mipi_dphy_4lmrxclk_esc0_user_p) = {"fin_pll",
333 "phyclk_mipi_dphy_4l_m_rxclkesc0"};
334PNAME(mout_sclk_hdmi_spdif_p) = {"fin_pll", "ioclk_spdif_extclk",
335 "dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"};
336
337struct samsung_mux_clock disp_mux_clks[] __initdata = {
338 MUX(DISP_MOUT_ACLK_DISP_333_USER, "mout_aclk_disp_333_user",
339 mout_aclk_disp_333_user_p,
340 MUX_SEL_DISP0, 0, 1),
341 MUX(DISP_MOUT_SCLK_DISP_PIXEL_USER, "mout_sclk_disp_pixel_user",
342 mout_sclk_disp_pixel_user_p,
343 MUX_SEL_DISP0, 4, 1),
344 MUX(DISP_MOUT_ACLK_DISP_222_USER, "mout_aclk_disp_222_user",
345 mout_aclk_disp_222_user_p,
346 MUX_SEL_DISP0, 8, 1),
347 MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CH0_TXD_CLK_USER,
348 "mout_phyclk_dptx_phy_ch0_txd_clk_user",
349 mout_phyclk_dptx_phy_ch0_txd_clk_user_p,
350 MUX_SEL_DISP0, 16, 1),
351 MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CH1_TXD_CLK_USER,
352 "mout_phyclk_dptx_phy_ch1_txd_clk_user",
353 mout_phyclk_dptx_phy_ch1_txd_clk_user_p,
354 MUX_SEL_DISP0, 20, 1),
355 MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CH2_TXD_CLK_USER,
356 "mout_phyclk_dptx_phy_ch2_txd_clk_user",
357 mout_phyclk_dptx_phy_ch2_txd_clk_user_p,
358 MUX_SEL_DISP0, 24, 1),
359 MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CH3_TXD_CLK_USER,
360 "mout_phyclk_dptx_phy_ch3_txd_clk_user",
361 mout_phyclk_dptx_phy_ch3_txd_clk_user_p,
362 MUX_SEL_DISP0, 28, 1),
363
364 MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CLK_DIV2_USER,
365 "mout_phyclk_dptx_phy_clk_div2_user",
366 mout_phyclk_dptx_phy_clk_div2_user_p,
367 MUX_SEL_DISP1, 0, 1),
368 MUX(DISP_MOUT_PHYCLK_DPTX_PHY_O_REF_CLK_24M_USER,
369 "mout_phyclk_dptx_phy_o_ref_clk_24m_user",
370 mout_phyclk_dptx_phy_o_ref_clk_24m_user_p,
371 MUX_SEL_DISP1, 4, 1),
372 MUX(DISP_MOUT_PHYCLK_MIPI_DPHY_4L_M_TXBYTE_CLKHS,
373 "mout_phyclk_mipi_dphy_4l_m_txbyte_clkhs",
374 mout_phyclk_mipi_dphy_4l_m_txbyte_clkhs_p,
375 MUX_SEL_DISP1, 8, 1),
376 MUX(DISP_MOUT_PHYCLK_HDMI_LINK_O_TMDS_CLKHI_USER,
377 "mout_phyclk_hdmi_link_o_tmds_clkhi_user",
378 mout_phyclk_hdmi_link_o_tmds_clkhi_user_p,
379 MUX_SEL_DISP1, 16, 1),
380 MUX(DISP_MOUT_HDMI_PHY_PIXEL,
381 "mout_phyclk_hdmi_phy_pixel_clko_user",
382 mout_phyclk_hdmi_phy_pixel_clko_user_p,
383 MUX_SEL_DISP1, 20, 1),
384 MUX(DISP_MOUT_PHYCLK_HDMI_PHY_REF_CLKO_USER,
385 "mout_phyclk_hdmi_phy_ref_clko_user",
386 mout_phyclk_hdmi_phy_ref_clko_user_p,
387 MUX_SEL_DISP1, 24, 1),
388 MUX(DISP_MOUT_PHYCLK_HDMI_PHY_TMDS_CLKO_USER,
389 "mout_phyclk_hdmi_phy_tmds_clko_user",
390 mout_phyclk_hdmi_phy_tmds_clko_user_p,
391 MUX_SEL_DISP1, 28, 1),
392
393 MUX(DISP_MOUT_PHYCLK_MIPI_DPHY_4LMRXCLK_ESC0_USER,
394 "mout_phyclk_mipi_dphy_4lmrxclk_esc0_user",
395 mout_phyclk_mipi_dphy_4lmrxclk_esc0_user_p,
396 MUX_SEL_DISP2, 0, 1),
397 MUX(DISP_MOUT_SCLK_HDMI_PIXEL, "mout_sclk_hdmi_pixel",
398 mout_sclk_hdmi_pixel_p,
399 MUX_SEL_DISP2, 4, 1),
400
401 MUX(DISP_MOUT_SCLK_HDMI_SPDIF, "mout_sclk_hdmi_spdif",
402 mout_sclk_hdmi_spdif_p,
403 MUX_SEL_DISP4, 4, 2),
404};
405
406struct samsung_div_clock disp_div_clks[] __initdata = {
407 DIV(DISP_DOUT_PCLK_DISP_111, "dout_pclk_disp_111",
408 "mout_aclk_disp_222_user",
409 DIV_DISP, 8, 4),
410 DIV(DISP_DOUT_SCLK_FIMD1_EXTCLKPLL, "dout_sclk_fimd1_extclkpll",
411 "mout_sclk_disp_pixel_user",
412 DIV_DISP, 12, 4),
413 DIV(DISP_DOUT_SCLK_HDMI_PHY_PIXEL_CLKI,
414 "dout_sclk_hdmi_phy_pixel_clki",
415 "mout_sclk_hdmi_pixel",
416 DIV_DISP, 16, 4),
417};
418
419struct samsung_gate_clock disp_gate_clks[] __initdata = {
420 GATE(DISP_MOUT_HDMI_PHY_PIXEL_USER, "sclk_hdmi_link_i_pixel",
421 "mout_phyclk_hdmi_phy_pixel_clko_user",
422 EN_SCLK_DISP0, 26, CLK_SET_RATE_PARENT, 0),
423 GATE(DISP_SCLK_PIXEL, "sclk_hdmi_phy_pixel_clki",
424 "dout_sclk_hdmi_phy_pixel_clki",
425 EN_SCLK_DISP0, 29, CLK_SET_RATE_PARENT, 0),
426
427 GATE(DISP_CLK_DP, "clk_dptx_link", "mout_aclk_disp_222_user",
428 EN_IP_DISP, 4, 0, 0),
429 GATE(DISP_CLK_DPPHY, "clk_dptx_phy", "mout_aclk_disp_222_user",
430 EN_IP_DISP, 5, 0, 0),
431 GATE(DISP_CLK_DSIM1, "clk_dsim1", "mout_aclk_disp_222_user",
432 EN_IP_DISP, 6, 0, 0),
433 GATE(DISP_CLK_FIMD1, "clk_fimd1", "mout_aclk_disp_222_user",
434 EN_IP_DISP, 7, 0, 0),
435 GATE(DISP_CLK_HDMI, "clk_hdmi", "mout_aclk_disp_222_user",
436 EN_IP_DISP, 8, 0, 0),
437 GATE(DISP_CLK_HDMIPHY, "clk_hdmiphy", "mout_aclk_disp_222_user",
438 EN_IP_DISP, 9, 0, 0),
439 GATE(DISP_CLK_MIPIPHY, "clk_mipi_dphy", "mout_aclk_disp_222_user",
440 EN_IP_DISP, 10, 0, 0),
441 GATE(DISP_CLK_MIXER, "clk_mixer", "mout_aclk_disp_222_user",
442 EN_IP_DISP, 11, 0, 0),
443 GATE(DISP_CLK_PIXEL_DISP, "clk_pixel_disp", "mout_aclk_disp_222_user",
444 EN_IP_DISP, 12, CLK_IGNORE_UNUSED, 0),
445 GATE(DISP_CLK_PIXEL_MIXER, "clk_pixel_mixer", "mout_aclk_disp_222_user",
446 EN_IP_DISP, 13, CLK_IGNORE_UNUSED, 0),
447 GATE(DISP_CLK_SMMU_FIMD1M0, "clk_smmu3_fimd1m0",
448 "mout_aclk_disp_222_user",
449 EN_IP_DISP, 22, 0, 0),
450 GATE(DISP_CLK_SMMU_FIMD1M1, "clk_smmu3_fimd1m1",
451 "mout_aclk_disp_222_user",
452 EN_IP_DISP, 23, 0, 0),
453 GATE(DISP_CLK_SMMU_TV, "clk_smmu3_tv", "mout_aclk_disp_222_user",
454 EN_IP_DISP, 25, 0, 0),
455};
456
457static void __init exynos5260_clk_disp_init(struct device_node *np)
458{
459 struct exynos5260_cmu_info cmu = {0};
460
461 cmu.mux_clks = disp_mux_clks;
462 cmu.nr_mux_clks = ARRAY_SIZE(disp_mux_clks);
463 cmu.div_clks = disp_div_clks;
464 cmu.nr_div_clks = ARRAY_SIZE(disp_div_clks);
465 cmu.gate_clks = disp_gate_clks;
466 cmu.nr_gate_clks = ARRAY_SIZE(disp_gate_clks);
467 cmu.nr_clk_ids = DISP_NR_CLK;
468 cmu.clk_regs = disp_clk_regs;
469 cmu.nr_clk_regs = ARRAY_SIZE(disp_clk_regs);
470
471 exynos5260_cmu_register_one(np, &cmu);
472}
473
474CLK_OF_DECLARE(exynos5260_clk_disp, "samsung,exynos5260-clock-disp",
475 exynos5260_clk_disp_init);
476
477
478/* CMU_EGL */
479
480static unsigned long egl_clk_regs[] __initdata = {
481 EGL_PLL_LOCK,
482 EGL_PLL_CON0,
483 EGL_PLL_CON1,
484 EGL_PLL_FREQ_DET,
485 MUX_SEL_EGL,
486 MUX_ENABLE_EGL,
487 DIV_EGL,
488 DIV_EGL_PLL_FDET,
489 EN_ACLK_EGL,
490 EN_PCLK_EGL,
491 EN_SCLK_EGL,
492};
493
494PNAME(mout_egl_b_p) = {"mout_egl_pll", "dout_bus_pll"};
495PNAME(mout_egl_pll_p) = {"fin_pll", "fout_egl_pll"};
496
497struct samsung_mux_clock egl_mux_clks[] __initdata = {
498 MUX(EGL_MOUT_EGL_PLL, "mout_egl_pll", mout_egl_pll_p,
499 MUX_SEL_EGL, 4, 1),
500 MUX(EGL_MOUT_EGL_B, "mout_egl_b", mout_egl_b_p, MUX_SEL_EGL, 16, 1),
501};
502
503struct samsung_div_clock egl_div_clks[] __initdata = {
504 DIV(EGL_DOUT_EGL1, "dout_egl1", "mout_egl_b", DIV_EGL, 0, 3),
505 DIV(EGL_DOUT_EGL2, "dout_egl2", "dout_egl1", DIV_EGL, 4, 3),
506 DIV(EGL_DOUT_ACLK_EGL, "dout_aclk_egl", "dout_egl2", DIV_EGL, 8, 3),
507 DIV(EGL_DOUT_PCLK_EGL, "dout_pclk_egl", "dout_egl_atclk",
508 DIV_EGL, 12, 3),
509 DIV(EGL_DOUT_EGL_ATCLK, "dout_egl_atclk", "dout_egl2", DIV_EGL, 16, 3),
510 DIV(EGL_DOUT_EGL_PCLK_DBG, "dout_egl_pclk_dbg", "dout_egl_atclk",
511 DIV_EGL, 20, 3),
512 DIV(EGL_DOUT_EGL_PLL, "dout_egl_pll", "mout_egl_b", DIV_EGL, 24, 3),
513};
514
515static struct samsung_pll_clock egl_pll_clks[] __initdata = {
516 PLL(pll_2550xx, EGL_FOUT_EGL_PLL, "fout_egl_pll", "fin_pll",
517 EGL_PLL_LOCK, EGL_PLL_CON0,
518 pll2550_24mhz_tbl),
519};
520
521static void __init exynos5260_clk_egl_init(struct device_node *np)
522{
523 struct exynos5260_cmu_info cmu = {0};
524
525 cmu.pll_clks = egl_pll_clks;
526 cmu.nr_pll_clks = ARRAY_SIZE(egl_pll_clks);
527 cmu.mux_clks = egl_mux_clks;
528 cmu.nr_mux_clks = ARRAY_SIZE(egl_mux_clks);
529 cmu.div_clks = egl_div_clks;
530 cmu.nr_div_clks = ARRAY_SIZE(egl_div_clks);
531 cmu.nr_clk_ids = EGL_NR_CLK;
532 cmu.clk_regs = egl_clk_regs;
533 cmu.nr_clk_regs = ARRAY_SIZE(egl_clk_regs);
534
535 exynos5260_cmu_register_one(np, &cmu);
536}
537
538CLK_OF_DECLARE(exynos5260_clk_egl, "samsung,exynos5260-clock-egl",
539 exynos5260_clk_egl_init);
540
541
542/* CMU_FSYS */
543
544static unsigned long fsys_clk_regs[] __initdata = {
545 MUX_SEL_FSYS0,
546 MUX_SEL_FSYS1,
547 EN_ACLK_FSYS,
548 EN_ACLK_FSYS_SECURE_RTIC,
549 EN_ACLK_FSYS_SECURE_SMMU_RTIC,
550 EN_SCLK_FSYS,
551 EN_IP_FSYS,
552 EN_IP_FSYS_SECURE_RTIC,
553 EN_IP_FSYS_SECURE_SMMU_RTIC,
554};
555
556PNAME(mout_phyclk_usbhost20_phyclk_user_p) = {"fin_pll",
557 "phyclk_usbhost20_phy_phyclock"};
558PNAME(mout_phyclk_usbhost20_freeclk_user_p) = {"fin_pll",
559 "phyclk_usbhost20_phy_freeclk"};
560PNAME(mout_phyclk_usbhost20_clk48mohci_user_p) = {"fin_pll",
561 "phyclk_usbhost20_phy_clk48mohci"};
562PNAME(mout_phyclk_usbdrd30_pipe_pclk_user_p) = {"fin_pll",
563 "phyclk_usbdrd30_udrd30_pipe_pclk"};
564PNAME(mout_phyclk_usbdrd30_phyclock_user_p) = {"fin_pll",
565 "phyclk_usbdrd30_udrd30_phyclock"};
566
567struct samsung_mux_clock fsys_mux_clks[] __initdata = {
568 MUX(FSYS_MOUT_PHYCLK_USBDRD30_PHYCLOCK_USER,
569 "mout_phyclk_usbdrd30_phyclock_user",
570 mout_phyclk_usbdrd30_phyclock_user_p,
571 MUX_SEL_FSYS1, 0, 1),
572 MUX(FSYS_MOUT_PHYCLK_USBDRD30_PIPE_PCLK_USER,
573 "mout_phyclk_usbdrd30_pipe_pclk_user",
574 mout_phyclk_usbdrd30_pipe_pclk_user_p,
575 MUX_SEL_FSYS1, 4, 1),
576 MUX(FSYS_MOUT_PHYCLK_USBHOST20_CLK48MOHCI_USER,
577 "mout_phyclk_usbhost20_clk48mohci_user",
578 mout_phyclk_usbhost20_clk48mohci_user_p,
579 MUX_SEL_FSYS1, 8, 1),
580 MUX(FSYS_MOUT_PHYCLK_USBHOST20_FREECLK_USER,
581 "mout_phyclk_usbhost20_freeclk_user",
582 mout_phyclk_usbhost20_freeclk_user_p,
583 MUX_SEL_FSYS1, 12, 1),
584 MUX(FSYS_MOUT_PHYCLK_USBHOST20_PHYCLK_USER,
585 "mout_phyclk_usbhost20_phyclk_user",
586 mout_phyclk_usbhost20_phyclk_user_p,
587 MUX_SEL_FSYS1, 16, 1),
588};
589
590struct samsung_gate_clock fsys_gate_clks[] __initdata = {
591 GATE(FSYS_PHYCLK_USBHOST20, "phyclk_usbhost20_phyclock",
592 "mout_phyclk_usbdrd30_phyclock_user",
593 EN_SCLK_FSYS, 1, 0, 0),
594 GATE(FSYS_PHYCLK_USBDRD30, "phyclk_usbdrd30_udrd30_phyclock_g",
595 "mout_phyclk_usbdrd30_phyclock_user",
596 EN_SCLK_FSYS, 7, 0, 0),
597
598 GATE(FSYS_CLK_MMC0, "clk_mmc0", "dout_aclk_fsys_200",
599 EN_IP_FSYS, 6, 0, 0),
600 GATE(FSYS_CLK_MMC1, "clk_mmc1", "dout_aclk_fsys_200",
601 EN_IP_FSYS, 7, 0, 0),
602 GATE(FSYS_CLK_MMC2, "clk_mmc2", "dout_aclk_fsys_200",
603 EN_IP_FSYS, 8, 0, 0),
604 GATE(FSYS_CLK_PDMA, "clk_pdma", "dout_aclk_fsys_200",
605 EN_IP_FSYS, 9, 0, 0),
606 GATE(FSYS_CLK_SROMC, "clk_sromc", "dout_aclk_fsys_200",
607 EN_IP_FSYS, 13, 0, 0),
608 GATE(FSYS_CLK_USBDRD30, "clk_usbdrd30", "dout_aclk_fsys_200",
609 EN_IP_FSYS, 14, 0, 0),
610 GATE(FSYS_CLK_USBHOST20, "clk_usbhost20", "dout_aclk_fsys_200",
611 EN_IP_FSYS, 15, 0, 0),
612 GATE(FSYS_CLK_USBLINK, "clk_usblink", "dout_aclk_fsys_200",
613 EN_IP_FSYS, 18, 0, 0),
614 GATE(FSYS_CLK_TSI, "clk_tsi", "dout_aclk_fsys_200",
615 EN_IP_FSYS, 20, 0, 0),
616
617 GATE(FSYS_CLK_RTIC, "clk_rtic", "dout_aclk_fsys_200",
618 EN_IP_FSYS_SECURE_RTIC, 11, 0, 0),
619 GATE(FSYS_CLK_SMMU_RTIC, "clk_smmu_rtic", "dout_aclk_fsys_200",
620 EN_IP_FSYS_SECURE_SMMU_RTIC, 12, 0, 0),
621};
622
623static void __init exynos5260_clk_fsys_init(struct device_node *np)
624{
625 struct exynos5260_cmu_info cmu = {0};
626
627 cmu.mux_clks = fsys_mux_clks;
628 cmu.nr_mux_clks = ARRAY_SIZE(fsys_mux_clks);
629 cmu.gate_clks = fsys_gate_clks;
630 cmu.nr_gate_clks = ARRAY_SIZE(fsys_gate_clks);
631 cmu.nr_clk_ids = FSYS_NR_CLK;
632 cmu.clk_regs = fsys_clk_regs;
633 cmu.nr_clk_regs = ARRAY_SIZE(fsys_clk_regs);
634
635 exynos5260_cmu_register_one(np, &cmu);
636}
637
638CLK_OF_DECLARE(exynos5260_clk_fsys, "samsung,exynos5260-clock-fsys",
639 exynos5260_clk_fsys_init);
640
641
642/* CMU_G2D */
643
644static unsigned long g2d_clk_regs[] __initdata = {
645 MUX_SEL_G2D,
646 MUX_STAT_G2D,
647 DIV_G2D,
648 EN_ACLK_G2D,
649 EN_ACLK_G2D_SECURE_SSS,
650 EN_ACLK_G2D_SECURE_SLIM_SSS,
651 EN_ACLK_G2D_SECURE_SMMU_SLIM_SSS,
652 EN_ACLK_G2D_SECURE_SMMU_SSS,
653 EN_ACLK_G2D_SECURE_SMMU_MDMA,
654 EN_ACLK_G2D_SECURE_SMMU_G2D,
655 EN_PCLK_G2D,
656 EN_PCLK_G2D_SECURE_SMMU_SLIM_SSS,
657 EN_PCLK_G2D_SECURE_SMMU_SSS,
658 EN_PCLK_G2D_SECURE_SMMU_MDMA,
659 EN_PCLK_G2D_SECURE_SMMU_G2D,
660 EN_IP_G2D,
661 EN_IP_G2D_SECURE_SSS,
662 EN_IP_G2D_SECURE_SLIM_SSS,
663 EN_IP_G2D_SECURE_SMMU_SLIM_SSS,
664 EN_IP_G2D_SECURE_SMMU_SSS,
665 EN_IP_G2D_SECURE_SMMU_MDMA,
666 EN_IP_G2D_SECURE_SMMU_G2D,
667};
668
669PNAME(mout_aclk_g2d_333_user_p) = {"fin_pll", "dout_aclk_g2d_333"};
670
671struct samsung_mux_clock g2d_mux_clks[] __initdata = {
672 MUX(G2D_MOUT_ACLK_G2D_333_USER, "mout_aclk_g2d_333_user",
673 mout_aclk_g2d_333_user_p,
674 MUX_SEL_G2D, 0, 1),
675};
676
677struct samsung_div_clock g2d_div_clks[] __initdata = {
678 DIV(G2D_DOUT_PCLK_G2D_83, "dout_pclk_g2d_83", "mout_aclk_g2d_333_user",
679 DIV_G2D, 0, 3),
680};
681
682struct samsung_gate_clock g2d_gate_clks[] __initdata = {
683 GATE(G2D_CLK_G2D, "clk_g2d", "mout_aclk_g2d_333_user",
684 EN_IP_G2D, 4, 0, 0),
685 GATE(G2D_CLK_JPEG, "clk_jpeg", "mout_aclk_g2d_333_user",
686 EN_IP_G2D, 5, 0, 0),
687 GATE(G2D_CLK_MDMA, "clk_mdma", "mout_aclk_g2d_333_user",
688 EN_IP_G2D, 6, 0, 0),
689 GATE(G2D_CLK_SMMU3_JPEG, "clk_smmu3_jpeg", "mout_aclk_g2d_333_user",
690 EN_IP_G2D, 16, 0, 0),
691
692 GATE(G2D_CLK_SSS, "clk_sss", "mout_aclk_g2d_333_user",
693 EN_IP_G2D_SECURE_SSS, 17, 0, 0),
694
695 GATE(G2D_CLK_SLIM_SSS, "clk_slim_sss", "mout_aclk_g2d_333_user",
696 EN_IP_G2D_SECURE_SLIM_SSS, 11, 0, 0),
697
698 GATE(G2D_CLK_SMMU_SLIM_SSS, "clk_smmu_slim_sss",
699 "mout_aclk_g2d_333_user",
700 EN_IP_G2D_SECURE_SMMU_SLIM_SSS, 13, 0, 0),
701
702 GATE(G2D_CLK_SMMU_SSS, "clk_smmu_sss", "mout_aclk_g2d_333_user",
703 EN_IP_G2D_SECURE_SMMU_SSS, 14, 0, 0),
704
705 GATE(G2D_CLK_SMMU_MDMA, "clk_smmu_mdma", "mout_aclk_g2d_333_user",
706 EN_IP_G2D_SECURE_SMMU_MDMA, 12, 0, 0),
707
708 GATE(G2D_CLK_SMMU3_G2D, "clk_smmu3_g2d", "mout_aclk_g2d_333_user",
709 EN_IP_G2D_SECURE_SMMU_G2D, 15, 0, 0),
710};
711
712static void __init exynos5260_clk_g2d_init(struct device_node *np)
713{
714 struct exynos5260_cmu_info cmu = {0};
715
716 cmu.mux_clks = g2d_mux_clks;
717 cmu.nr_mux_clks = ARRAY_SIZE(g2d_mux_clks);
718 cmu.div_clks = g2d_div_clks;
719 cmu.nr_div_clks = ARRAY_SIZE(g2d_div_clks);
720 cmu.gate_clks = g2d_gate_clks;
721 cmu.nr_gate_clks = ARRAY_SIZE(g2d_gate_clks);
722 cmu.nr_clk_ids = G2D_NR_CLK;
723 cmu.clk_regs = g2d_clk_regs;
724 cmu.nr_clk_regs = ARRAY_SIZE(g2d_clk_regs);
725
726 exynos5260_cmu_register_one(np, &cmu);
727}
728
729CLK_OF_DECLARE(exynos5260_clk_g2d, "samsung,exynos5260-clock-g2d",
730 exynos5260_clk_g2d_init);
731
732
733/* CMU_G3D */
734
735static unsigned long g3d_clk_regs[] __initdata = {
736 G3D_PLL_LOCK,
737 G3D_PLL_CON0,
738 G3D_PLL_CON1,
739 G3D_PLL_FDET,
740 MUX_SEL_G3D,
741 DIV_G3D,
742 DIV_G3D_PLL_FDET,
743 EN_ACLK_G3D,
744 EN_PCLK_G3D,
745 EN_SCLK_G3D,
746 EN_IP_G3D,
747};
748
749PNAME(mout_g3d_pll_p) = {"fin_pll", "fout_g3d_pll"};
750
751struct samsung_mux_clock g3d_mux_clks[] __initdata = {
752 MUX(G3D_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
753 MUX_SEL_G3D, 0, 1),
754};
755
756struct samsung_div_clock g3d_div_clks[] __initdata = {
757 DIV(G3D_DOUT_PCLK_G3D, "dout_pclk_g3d", "dout_aclk_g3d", DIV_G3D, 0, 3),
758 DIV(G3D_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_g3d_pll", DIV_G3D, 4, 3),
759};
760
761struct samsung_gate_clock g3d_gate_clks[] __initdata = {
762 GATE(G3D_CLK_G3D, "clk_g3d", "dout_aclk_g3d", EN_IP_G3D, 2, 0, 0),
763 GATE(G3D_CLK_G3D_HPM, "clk_g3d_hpm", "dout_aclk_g3d",
764 EN_IP_G3D, 3, 0, 0),
765};
766
767static struct samsung_pll_clock g3d_pll_clks[] __initdata = {
768 PLL(pll_2550, G3D_FOUT_G3D_PLL, "fout_g3d_pll", "fin_pll",
769 G3D_PLL_LOCK, G3D_PLL_CON0,
770 pll2550_24mhz_tbl),
771};
772
773static void __init exynos5260_clk_g3d_init(struct device_node *np)
774{
775 struct exynos5260_cmu_info cmu = {0};
776
777 cmu.pll_clks = g3d_pll_clks;
778 cmu.nr_pll_clks = ARRAY_SIZE(g3d_pll_clks);
779 cmu.mux_clks = g3d_mux_clks;
780 cmu.nr_mux_clks = ARRAY_SIZE(g3d_mux_clks);
781 cmu.div_clks = g3d_div_clks;
782 cmu.nr_div_clks = ARRAY_SIZE(g3d_div_clks);
783 cmu.gate_clks = g3d_gate_clks;
784 cmu.nr_gate_clks = ARRAY_SIZE(g3d_gate_clks);
785 cmu.nr_clk_ids = G3D_NR_CLK;
786 cmu.clk_regs = g3d_clk_regs;
787 cmu.nr_clk_regs = ARRAY_SIZE(g3d_clk_regs);
788
789 exynos5260_cmu_register_one(np, &cmu);
790}
791
792CLK_OF_DECLARE(exynos5260_clk_g3d, "samsung,exynos5260-clock-g3d",
793 exynos5260_clk_g3d_init);
794
795
796/* CMU_GSCL */
797
798static unsigned long gscl_clk_regs[] __initdata = {
799 MUX_SEL_GSCL,
800 DIV_GSCL,
801 EN_ACLK_GSCL,
802 EN_ACLK_GSCL_FIMC,
803 EN_ACLK_GSCL_SECURE_SMMU_GSCL0,
804 EN_ACLK_GSCL_SECURE_SMMU_GSCL1,
805 EN_ACLK_GSCL_SECURE_SMMU_MSCL0,
806 EN_ACLK_GSCL_SECURE_SMMU_MSCL1,
807 EN_PCLK_GSCL,
808 EN_PCLK_GSCL_FIMC,
809 EN_PCLK_GSCL_SECURE_SMMU_GSCL0,
810 EN_PCLK_GSCL_SECURE_SMMU_GSCL1,
811 EN_PCLK_GSCL_SECURE_SMMU_MSCL0,
812 EN_PCLK_GSCL_SECURE_SMMU_MSCL1,
813 EN_SCLK_GSCL,
814 EN_SCLK_GSCL_FIMC,
815 EN_IP_GSCL,
816 EN_IP_GSCL_FIMC,
817 EN_IP_GSCL_SECURE_SMMU_GSCL0,
818 EN_IP_GSCL_SECURE_SMMU_GSCL1,
819 EN_IP_GSCL_SECURE_SMMU_MSCL0,
820 EN_IP_GSCL_SECURE_SMMU_MSCL1,
821};
822
823PNAME(mout_aclk_gscl_333_user_p) = {"fin_pll", "dout_aclk_gscl_333"};
824PNAME(mout_aclk_m2m_400_user_p) = {"fin_pll", "dout_aclk_gscl_400"};
825PNAME(mout_aclk_gscl_fimc_user_p) = {"fin_pll", "dout_aclk_gscl_400"};
826PNAME(mout_aclk_csis_p) = {"dout_aclk_csis_200", "mout_aclk_gscl_fimc_user"};
827
828struct samsung_mux_clock gscl_mux_clks[] __initdata = {
829 MUX(GSCL_MOUT_ACLK_GSCL_333_USER, "mout_aclk_gscl_333_user",
830 mout_aclk_gscl_333_user_p,
831 MUX_SEL_GSCL, 0, 1),
832 MUX(GSCL_MOUT_ACLK_M2M_400_USER, "mout_aclk_m2m_400_user",
833 mout_aclk_m2m_400_user_p,
834 MUX_SEL_GSCL, 4, 1),
835 MUX(GSCL_MOUT_ACLK_GSCL_FIMC_USER, "mout_aclk_gscl_fimc_user",
836 mout_aclk_gscl_fimc_user_p,
837 MUX_SEL_GSCL, 8, 1),
838 MUX(GSCL_MOUT_ACLK_CSIS, "mout_aclk_csis", mout_aclk_csis_p,
839 MUX_SEL_GSCL, 24, 1),
840};
841
842struct samsung_div_clock gscl_div_clks[] __initdata = {
843 DIV(GSCL_DOUT_PCLK_M2M_100, "dout_pclk_m2m_100",
844 "mout_aclk_m2m_400_user",
845 DIV_GSCL, 0, 3),
846 DIV(GSCL_DOUT_ACLK_CSIS_200, "dout_aclk_csis_200",
847 "mout_aclk_m2m_400_user",
848 DIV_GSCL, 4, 3),
849};
850
851struct samsung_gate_clock gscl_gate_clks[] __initdata = {
852 GATE(GSCL_SCLK_CSIS0_WRAP, "sclk_csis0_wrap", "dout_aclk_csis_200",
853 EN_SCLK_GSCL_FIMC, 0, CLK_SET_RATE_PARENT, 0),
854 GATE(GSCL_SCLK_CSIS1_WRAP, "sclk_csis1_wrap", "dout_aclk_csis_200",
855 EN_SCLK_GSCL_FIMC, 1, CLK_SET_RATE_PARENT, 0),
856
857 GATE(GSCL_CLK_GSCL0, "clk_gscl0", "mout_aclk_gscl_333_user",
858 EN_IP_GSCL, 2, 0, 0),
859 GATE(GSCL_CLK_GSCL1, "clk_gscl1", "mout_aclk_gscl_333_user",
860 EN_IP_GSCL, 3, 0, 0),
861 GATE(GSCL_CLK_MSCL0, "clk_mscl0", "mout_aclk_gscl_333_user",
862 EN_IP_GSCL, 4, 0, 0),
863 GATE(GSCL_CLK_MSCL1, "clk_mscl1", "mout_aclk_gscl_333_user",
864 EN_IP_GSCL, 5, 0, 0),
865 GATE(GSCL_CLK_PIXEL_GSCL0, "clk_pixel_gscl0",
866 "mout_aclk_gscl_333_user",
867 EN_IP_GSCL, 8, 0, 0),
868 GATE(GSCL_CLK_PIXEL_GSCL1, "clk_pixel_gscl1",
869 "mout_aclk_gscl_333_user",
870 EN_IP_GSCL, 9, 0, 0),
871
872 GATE(GSCL_CLK_SMMU3_LITE_A, "clk_smmu3_lite_a",
873 "mout_aclk_gscl_fimc_user",
874 EN_IP_GSCL_FIMC, 5, 0, 0),
875 GATE(GSCL_CLK_SMMU3_LITE_B, "clk_smmu3_lite_b",
876 "mout_aclk_gscl_fimc_user",
877 EN_IP_GSCL_FIMC, 6, 0, 0),
878 GATE(GSCL_CLK_SMMU3_LITE_D, "clk_smmu3_lite_d",
879 "mout_aclk_gscl_fimc_user",
880 EN_IP_GSCL_FIMC, 7, 0, 0),
881 GATE(GSCL_CLK_CSIS0, "clk_csis0", "mout_aclk_gscl_fimc_user",
882 EN_IP_GSCL_FIMC, 8, 0, 0),
883 GATE(GSCL_CLK_CSIS1, "clk_csis1", "mout_aclk_gscl_fimc_user",
884 EN_IP_GSCL_FIMC, 9, 0, 0),
885 GATE(GSCL_CLK_FIMC_LITE_A, "clk_fimc_lite_a",
886 "mout_aclk_gscl_fimc_user",
887 EN_IP_GSCL_FIMC, 10, 0, 0),
888 GATE(GSCL_CLK_FIMC_LITE_B, "clk_fimc_lite_b",
889 "mout_aclk_gscl_fimc_user",
890 EN_IP_GSCL_FIMC, 11, 0, 0),
891 GATE(GSCL_CLK_FIMC_LITE_D, "clk_fimc_lite_d",
892 "mout_aclk_gscl_fimc_user",
893 EN_IP_GSCL_FIMC, 12, 0, 0),
894
895 GATE(GSCL_CLK_SMMU3_GSCL0, "clk_smmu3_gscl0",
896 "mout_aclk_gscl_333_user",
897 EN_IP_GSCL_SECURE_SMMU_GSCL0, 17, 0, 0),
898 GATE(GSCL_CLK_SMMU3_GSCL1, "clk_smmu3_gscl1", "mout_aclk_gscl_333_user",
899 EN_IP_GSCL_SECURE_SMMU_GSCL1, 18, 0, 0),
900 GATE(GSCL_CLK_SMMU3_MSCL0, "clk_smmu3_mscl0",
901 "mout_aclk_m2m_400_user",
902 EN_IP_GSCL_SECURE_SMMU_MSCL0, 19, 0, 0),
903 GATE(GSCL_CLK_SMMU3_MSCL1, "clk_smmu3_mscl1",
904 "mout_aclk_m2m_400_user",
905 EN_IP_GSCL_SECURE_SMMU_MSCL1, 20, 0, 0),
906};
907
908static void __init exynos5260_clk_gscl_init(struct device_node *np)
909{
910 struct exynos5260_cmu_info cmu = {0};
911
912 cmu.mux_clks = gscl_mux_clks;
913 cmu.nr_mux_clks = ARRAY_SIZE(gscl_mux_clks);
914 cmu.div_clks = gscl_div_clks;
915 cmu.nr_div_clks = ARRAY_SIZE(gscl_div_clks);
916 cmu.gate_clks = gscl_gate_clks;
917 cmu.nr_gate_clks = ARRAY_SIZE(gscl_gate_clks);
918 cmu.nr_clk_ids = GSCL_NR_CLK;
919 cmu.clk_regs = gscl_clk_regs;
920 cmu.nr_clk_regs = ARRAY_SIZE(gscl_clk_regs);
921
922 exynos5260_cmu_register_one(np, &cmu);
923}
924
925CLK_OF_DECLARE(exynos5260_clk_gscl, "samsung,exynos5260-clock-gscl",
926 exynos5260_clk_gscl_init);
927
928
929/* CMU_ISP */
930
931static unsigned long isp_clk_regs[] __initdata = {
932 MUX_SEL_ISP0,
933 MUX_SEL_ISP1,
934 DIV_ISP,
935 EN_ACLK_ISP0,
936 EN_ACLK_ISP1,
937 EN_PCLK_ISP0,
938 EN_PCLK_ISP1,
939 EN_SCLK_ISP,
940 EN_IP_ISP0,
941 EN_IP_ISP1,
942};
943
944PNAME(mout_isp_400_user_p) = {"fin_pll", "dout_aclk_isp1_400"};
945PNAME(mout_isp_266_user_p) = {"fin_pll", "dout_aclk_isp1_266"};
946
947struct samsung_mux_clock isp_mux_clks[] __initdata = {
948 MUX(ISP_MOUT_ISP_266_USER, "mout_isp_266_user", mout_isp_266_user_p,
949 MUX_SEL_ISP0, 0, 1),
950 MUX(ISP_MOUT_ISP_400_USER, "mout_isp_400_user", mout_isp_400_user_p,
951 MUX_SEL_ISP0, 4, 1),
952};
953
954struct samsung_div_clock isp_div_clks[] __initdata = {
955 DIV(ISP_DOUT_PCLK_ISP_66, "dout_pclk_isp_66", "mout_kfc",
956 DIV_ISP, 0, 3),
957 DIV(ISP_DOUT_PCLK_ISP_133, "dout_pclk_isp_133", "mout_kfc",
958 DIV_ISP, 4, 4),
959 DIV(ISP_DOUT_CA5_ATCLKIN, "dout_ca5_atclkin", "mout_kfc",
960 DIV_ISP, 12, 3),
961 DIV(ISP_DOUT_CA5_PCLKDBG, "dout_ca5_pclkdbg", "mout_kfc",
962 DIV_ISP, 16, 4),
963 DIV(ISP_DOUT_SCLK_MPWM, "dout_sclk_mpwm", "mout_kfc", DIV_ISP, 20, 2),
964};
965
966struct samsung_gate_clock isp_gate_clks[] __initdata = {
967 GATE(ISP_CLK_GIC, "clk_isp_gic", "mout_aclk_isp1_266",
968 EN_IP_ISP0, 15, 0, 0),
969
970 GATE(ISP_CLK_CA5, "clk_isp_ca5", "mout_aclk_isp1_266",
971 EN_IP_ISP1, 1, 0, 0),
972 GATE(ISP_CLK_FIMC_DRC, "clk_isp_fimc_drc", "mout_aclk_isp1_266",
973 EN_IP_ISP1, 2, 0, 0),
974 GATE(ISP_CLK_FIMC_FD, "clk_isp_fimc_fd", "mout_aclk_isp1_266",
975 EN_IP_ISP1, 3, 0, 0),
976 GATE(ISP_CLK_FIMC, "clk_isp_fimc", "mout_aclk_isp1_266",
977 EN_IP_ISP1, 4, 0, 0),
978 GATE(ISP_CLK_FIMC_SCALERC, "clk_isp_fimc_scalerc",
979 "mout_aclk_isp1_266",
980 EN_IP_ISP1, 5, 0, 0),
981 GATE(ISP_CLK_FIMC_SCALERP, "clk_isp_fimc_scalerp",
982 "mout_aclk_isp1_266",
983 EN_IP_ISP1, 6, 0, 0),
984 GATE(ISP_CLK_I2C0, "clk_isp_i2c0", "mout_aclk_isp1_266",
985 EN_IP_ISP1, 7, 0, 0),
986 GATE(ISP_CLK_I2C1, "clk_isp_i2c1", "mout_aclk_isp1_266",
987 EN_IP_ISP1, 8, 0, 0),
988 GATE(ISP_CLK_MCUCTL, "clk_isp_mcuctl", "mout_aclk_isp1_266",
989 EN_IP_ISP1, 9, 0, 0),
990 GATE(ISP_CLK_MPWM, "clk_isp_mpwm", "mout_aclk_isp1_266",
991 EN_IP_ISP1, 10, 0, 0),
992 GATE(ISP_CLK_MTCADC, "clk_isp_mtcadc", "mout_aclk_isp1_266",
993 EN_IP_ISP1, 11, 0, 0),
994 GATE(ISP_CLK_PWM, "clk_isp_pwm", "mout_aclk_isp1_266",
995 EN_IP_ISP1, 14, 0, 0),
996 GATE(ISP_CLK_SMMU_DRC, "clk_smmu_drc", "mout_aclk_isp1_266",
997 EN_IP_ISP1, 21, 0, 0),
998 GATE(ISP_CLK_SMMU_FD, "clk_smmu_fd", "mout_aclk_isp1_266",
999 EN_IP_ISP1, 22, 0, 0),
1000 GATE(ISP_CLK_SMMU_ISP, "clk_smmu_isp", "mout_aclk_isp1_266",
1001 EN_IP_ISP1, 23, 0, 0),
1002 GATE(ISP_CLK_SMMU_ISPCX, "clk_smmu_ispcx", "mout_aclk_isp1_266",
1003 EN_IP_ISP1, 24, 0, 0),
1004 GATE(ISP_CLK_SMMU_SCALERC, "clk_isp_smmu_scalerc",
1005 "mout_aclk_isp1_266",
1006 EN_IP_ISP1, 25, 0, 0),
1007 GATE(ISP_CLK_SMMU_SCALERP, "clk_isp_smmu_scalerp",
1008 "mout_aclk_isp1_266",
1009 EN_IP_ISP1, 26, 0, 0),
1010 GATE(ISP_CLK_SPI0, "clk_isp_spi0", "mout_aclk_isp1_266",
1011 EN_IP_ISP1, 27, 0, 0),
1012 GATE(ISP_CLK_SPI1, "clk_isp_spi1", "mout_aclk_isp1_266",
1013 EN_IP_ISP1, 28, 0, 0),
1014 GATE(ISP_CLK_WDT, "clk_isp_wdt", "mout_aclk_isp1_266",
1015 EN_IP_ISP1, 31, 0, 0),
1016 GATE(ISP_CLK_UART, "clk_isp_uart", "mout_aclk_isp1_266",
1017 EN_IP_ISP1, 30, 0, 0),
1018
1019 GATE(ISP_SCLK_UART_EXT, "sclk_isp_uart_ext", "fin_pll",
1020 EN_SCLK_ISP, 7, CLK_SET_RATE_PARENT, 0),
1021 GATE(ISP_SCLK_SPI1_EXT, "sclk_isp_spi1_ext", "fin_pll",
1022 EN_SCLK_ISP, 8, CLK_SET_RATE_PARENT, 0),
1023 GATE(ISP_SCLK_SPI0_EXT, "sclk_isp_spi0_ext", "fin_pll",
1024 EN_SCLK_ISP, 9, CLK_SET_RATE_PARENT, 0),
1025};
1026
1027static void __init exynos5260_clk_isp_init(struct device_node *np)
1028{
1029 struct exynos5260_cmu_info cmu = {0};
1030
1031 cmu.mux_clks = isp_mux_clks;
1032 cmu.nr_mux_clks = ARRAY_SIZE(isp_mux_clks);
1033 cmu.div_clks = isp_div_clks;
1034 cmu.nr_div_clks = ARRAY_SIZE(isp_div_clks);
1035 cmu.gate_clks = isp_gate_clks;
1036 cmu.nr_gate_clks = ARRAY_SIZE(isp_gate_clks);
1037 cmu.nr_clk_ids = ISP_NR_CLK;
1038 cmu.clk_regs = isp_clk_regs;
1039 cmu.nr_clk_regs = ARRAY_SIZE(isp_clk_regs);
1040
1041 exynos5260_cmu_register_one(np, &cmu);
1042}
1043
1044CLK_OF_DECLARE(exynos5260_clk_isp, "samsung,exynos5260-clock-isp",
1045 exynos5260_clk_isp_init);
1046
1047
1048/* CMU_KFC */
1049
1050static unsigned long kfc_clk_regs[] __initdata = {
1051 KFC_PLL_LOCK,
1052 KFC_PLL_CON0,
1053 KFC_PLL_CON1,
1054 KFC_PLL_FDET,
1055 MUX_SEL_KFC0,
1056 MUX_SEL_KFC2,
1057 DIV_KFC,
1058 DIV_KFC_PLL_FDET,
1059 EN_ACLK_KFC,
1060 EN_PCLK_KFC,
1061 EN_SCLK_KFC,
1062 EN_IP_KFC,
1063};
1064
1065PNAME(mout_kfc_pll_p) = {"fin_pll", "fout_kfc_pll"};
1066PNAME(mout_kfc_p) = {"mout_kfc_pll", "dout_media_pll"};
1067
1068struct samsung_mux_clock kfc_mux_clks[] __initdata = {
1069 MUX(KFC_MOUT_KFC_PLL, "mout_kfc_pll", mout_kfc_pll_p,
1070 MUX_SEL_KFC0, 0, 1),
1071 MUX(KFC_MOUT_KFC, "mout_kfc", mout_kfc_p, MUX_SEL_KFC2, 0, 1),
1072};
1073
1074struct samsung_div_clock kfc_div_clks[] __initdata = {
1075 DIV(KFC_DOUT_KFC1, "dout_kfc1", "mout_kfc", DIV_KFC, 0, 3),
1076 DIV(KFC_DOUT_KFC2, "dout_kfc2", "dout_kfc1", DIV_KFC, 4, 3),
1077 DIV(KFC_DOUT_KFC_ATCLK, "dout_kfc_atclk", "dout_kfc2", DIV_KFC, 8, 3),
1078 DIV(KFC_DOUT_KFC_PCLK_DBG, "dout_kfc_pclk_dbg", "dout_kfc2",
1079 DIV_KFC, 12, 3),
1080 DIV(KFC_DOUT_ACLK_KFC, "dout_aclk_kfc", "dout_kfc2", DIV_KFC, 16, 3),
1081 DIV(KFC_DOUT_PCLK_KFC, "dout_pclk_kfc", "dout_kfc2", DIV_KFC, 20, 3),
1082 DIV(KFC_DOUT_KFC_PLL, "dout_kfc_pll", "mout_kfc", DIV_KFC, 24, 3),
1083};
1084
1085static struct samsung_pll_clock kfc_pll_clks[] __initdata = {
1086 PLL(pll_2550xx, KFC_FOUT_KFC_PLL, "fout_kfc_pll", "fin_pll",
1087 KFC_PLL_LOCK, KFC_PLL_CON0,
1088 pll2550_24mhz_tbl),
1089};
1090
1091static void __init exynos5260_clk_kfc_init(struct device_node *np)
1092{
1093 struct exynos5260_cmu_info cmu = {0};
1094
1095 cmu.pll_clks = kfc_pll_clks;
1096 cmu.nr_pll_clks = ARRAY_SIZE(kfc_pll_clks);
1097 cmu.mux_clks = kfc_mux_clks;
1098 cmu.nr_mux_clks = ARRAY_SIZE(kfc_mux_clks);
1099 cmu.div_clks = kfc_div_clks;
1100 cmu.nr_div_clks = ARRAY_SIZE(kfc_div_clks);
1101 cmu.nr_clk_ids = KFC_NR_CLK;
1102 cmu.clk_regs = kfc_clk_regs;
1103 cmu.nr_clk_regs = ARRAY_SIZE(kfc_clk_regs);
1104
1105 exynos5260_cmu_register_one(np, &cmu);
1106}
1107
1108CLK_OF_DECLARE(exynos5260_clk_kfc, "samsung,exynos5260-clock-kfc",
1109 exynos5260_clk_kfc_init);
1110
1111
1112/* CMU_MFC */
1113
1114static unsigned long mfc_clk_regs[] __initdata = {
1115 MUX_SEL_MFC,
1116 DIV_MFC,
1117 EN_ACLK_MFC,
1118 EN_ACLK_SECURE_SMMU2_MFC,
1119 EN_PCLK_MFC,
1120 EN_PCLK_SECURE_SMMU2_MFC,
1121 EN_IP_MFC,
1122 EN_IP_MFC_SECURE_SMMU2_MFC,
1123};
1124
1125PNAME(mout_aclk_mfc_333_user_p) = {"fin_pll", "dout_aclk_mfc_333"};
1126
1127struct samsung_mux_clock mfc_mux_clks[] __initdata = {
1128 MUX(MFC_MOUT_ACLK_MFC_333_USER, "mout_aclk_mfc_333_user",
1129 mout_aclk_mfc_333_user_p,
1130 MUX_SEL_MFC, 0, 1),
1131};
1132
1133struct samsung_div_clock mfc_div_clks[] __initdata = {
1134 DIV(MFC_DOUT_PCLK_MFC_83, "dout_pclk_mfc_83", "mout_aclk_mfc_333_user",
1135 DIV_MFC, 0, 3),
1136};
1137
1138struct samsung_gate_clock mfc_gate_clks[] __initdata = {
1139 GATE(MFC_CLK_MFC, "clk_mfc", "mout_aclk_mfc_333_user",
1140 EN_IP_MFC, 1, 0, 0),
1141 GATE(MFC_CLK_SMMU2_MFCM0, "clk_smmu2_mfcm0", "mout_aclk_mfc_333_user",
1142 EN_IP_MFC_SECURE_SMMU2_MFC, 6, 0, 0),
1143 GATE(MFC_CLK_SMMU2_MFCM1, "clk_smmu2_mfcm1", "mout_aclk_mfc_333_user",
1144 EN_IP_MFC_SECURE_SMMU2_MFC, 7, 0, 0),
1145};
1146
1147static void __init exynos5260_clk_mfc_init(struct device_node *np)
1148{
1149 struct exynos5260_cmu_info cmu = {0};
1150
1151 cmu.mux_clks = mfc_mux_clks;
1152 cmu.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks);
1153 cmu.div_clks = mfc_div_clks;
1154 cmu.nr_div_clks = ARRAY_SIZE(mfc_div_clks);
1155 cmu.gate_clks = mfc_gate_clks;
1156 cmu.nr_gate_clks = ARRAY_SIZE(mfc_gate_clks);
1157 cmu.nr_clk_ids = MFC_NR_CLK;
1158 cmu.clk_regs = mfc_clk_regs;
1159 cmu.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs);
1160
1161 exynos5260_cmu_register_one(np, &cmu);
1162}
1163
1164CLK_OF_DECLARE(exynos5260_clk_mfc, "samsung,exynos5260-clock-mfc",
1165 exynos5260_clk_mfc_init);
1166
1167
1168/* CMU_MIF */
1169
1170static unsigned long mif_clk_regs[] __initdata = {
1171 MEM_PLL_LOCK,
1172 BUS_PLL_LOCK,
1173 MEDIA_PLL_LOCK,
1174 MEM_PLL_CON0,
1175 MEM_PLL_CON1,
1176 MEM_PLL_FDET,
1177 BUS_PLL_CON0,
1178 BUS_PLL_CON1,
1179 BUS_PLL_FDET,
1180 MEDIA_PLL_CON0,
1181 MEDIA_PLL_CON1,
1182 MEDIA_PLL_FDET,
1183 MUX_SEL_MIF,
1184 DIV_MIF,
1185 DIV_MIF_PLL_FDET,
1186 EN_ACLK_MIF,
1187 EN_ACLK_MIF_SECURE_DREX1_TZ,
1188 EN_ACLK_MIF_SECURE_DREX0_TZ,
1189 EN_ACLK_MIF_SECURE_INTMEM,
1190 EN_PCLK_MIF,
1191 EN_PCLK_MIF_SECURE_MONOCNT,
1192 EN_PCLK_MIF_SECURE_RTC_APBIF,
1193 EN_PCLK_MIF_SECURE_DREX1_TZ,
1194 EN_PCLK_MIF_SECURE_DREX0_TZ,
1195 EN_SCLK_MIF,
1196 EN_IP_MIF,
1197 EN_IP_MIF_SECURE_MONOCNT,
1198 EN_IP_MIF_SECURE_RTC_APBIF,
1199 EN_IP_MIF_SECURE_DREX1_TZ,
1200 EN_IP_MIF_SECURE_DREX0_TZ,
1201 EN_IP_MIF_SECURE_INTEMEM,
1202};
1203
1204PNAME(mout_mem_pll_p) = {"fin_pll", "fout_mem_pll"};
1205PNAME(mout_bus_pll_p) = {"fin_pll", "fout_bus_pll"};
1206PNAME(mout_media_pll_p) = {"fin_pll", "fout_media_pll"};
1207PNAME(mout_mif_drex_p) = {"dout_mem_pll", "dout_bus_pll"};
1208PNAME(mout_mif_drex2x_p) = {"dout_mem_pll", "dout_bus_pll"};
1209PNAME(mout_clkm_phy_p) = {"mout_mif_drex", "dout_media_pll"};
1210PNAME(mout_clk2x_phy_p) = {"mout_mif_drex2x", "dout_media_pll"};
1211
1212struct samsung_mux_clock mif_mux_clks[] __initdata = {
1213 MUX(MIF_MOUT_MEM_PLL, "mout_mem_pll", mout_mem_pll_p,
1214 MUX_SEL_MIF, 0, 1),
1215 MUX(MIF_MOUT_BUS_PLL, "mout_bus_pll", mout_bus_pll_p,
1216 MUX_SEL_MIF, 4, 1),
1217 MUX(MIF_MOUT_MEDIA_PLL, "mout_media_pll", mout_media_pll_p,
1218 MUX_SEL_MIF, 8, 1),
1219 MUX(MIF_MOUT_MIF_DREX, "mout_mif_drex", mout_mif_drex_p,
1220 MUX_SEL_MIF, 12, 1),
1221 MUX(MIF_MOUT_CLKM_PHY, "mout_clkm_phy", mout_clkm_phy_p,
1222 MUX_SEL_MIF, 16, 1),
1223 MUX(MIF_MOUT_MIF_DREX2X, "mout_mif_drex2x", mout_mif_drex2x_p,
1224 MUX_SEL_MIF, 20, 1),
1225 MUX(MIF_MOUT_CLK2X_PHY, "mout_clk2x_phy", mout_clk2x_phy_p,
1226 MUX_SEL_MIF, 24, 1),
1227};
1228
1229struct samsung_div_clock mif_div_clks[] __initdata = {
1230 DIV(MIF_DOUT_MEDIA_PLL, "dout_media_pll", "mout_media_pll",
1231 DIV_MIF, 0, 3),
1232 DIV(MIF_DOUT_MEM_PLL, "dout_mem_pll", "mout_mem_pll",
1233 DIV_MIF, 4, 3),
1234 DIV(MIF_DOUT_BUS_PLL, "dout_bus_pll", "mout_bus_pll",
1235 DIV_MIF, 8, 3),
1236 DIV(MIF_DOUT_CLKM_PHY, "dout_clkm_phy", "mout_clkm_phy",
1237 DIV_MIF, 12, 3),
1238 DIV(MIF_DOUT_CLK2X_PHY, "dout_clk2x_phy", "mout_clk2x_phy",
1239 DIV_MIF, 16, 4),
1240 DIV(MIF_DOUT_ACLK_MIF_466, "dout_aclk_mif_466", "dout_clk2x_phy",
1241 DIV_MIF, 20, 3),
1242 DIV(MIF_DOUT_ACLK_BUS_200, "dout_aclk_bus_200", "dout_bus_pll",
1243 DIV_MIF, 24, 3),
1244 DIV(MIF_DOUT_ACLK_BUS_100, "dout_aclk_bus_100", "dout_bus_pll",
1245 DIV_MIF, 28, 4),
1246};
1247
1248struct samsung_gate_clock mif_gate_clks[] __initdata = {
1249 GATE(MIF_CLK_LPDDR3PHY_WRAP0, "clk_lpddr3phy_wrap0", "dout_clk2x_phy",
1250 EN_IP_MIF, 12, CLK_IGNORE_UNUSED, 0),
1251 GATE(MIF_CLK_LPDDR3PHY_WRAP1, "clk_lpddr3phy_wrap1", "dout_clk2x_phy",
1252 EN_IP_MIF, 13, CLK_IGNORE_UNUSED, 0),
1253
1254 GATE(MIF_CLK_MONOCNT, "clk_monocnt", "dout_aclk_bus_100",
1255 EN_IP_MIF_SECURE_MONOCNT, 22,
1256 CLK_IGNORE_UNUSED, 0),
1257
1258 GATE(MIF_CLK_MIF_RTC, "clk_mif_rtc", "dout_aclk_bus_100",
1259 EN_IP_MIF_SECURE_RTC_APBIF, 23,
1260 CLK_IGNORE_UNUSED, 0),
1261
1262 GATE(MIF_CLK_DREX1, "clk_drex1", "dout_aclk_mif_466",
1263 EN_IP_MIF_SECURE_DREX1_TZ, 9,
1264 CLK_IGNORE_UNUSED, 0),
1265
1266 GATE(MIF_CLK_DREX0, "clk_drex0", "dout_aclk_mif_466",
1267 EN_IP_MIF_SECURE_DREX0_TZ, 9,
1268 CLK_IGNORE_UNUSED, 0),
1269
1270 GATE(MIF_CLK_INTMEM, "clk_intmem", "dout_aclk_bus_200",
1271 EN_IP_MIF_SECURE_INTEMEM, 11,
1272 CLK_IGNORE_UNUSED, 0),
1273
1274 GATE(MIF_SCLK_LPDDR3PHY_WRAP_U0, "sclk_lpddr3phy_wrap_u0",
1275 "dout_clkm_phy", EN_SCLK_MIF, 0,
1276 CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
1277 GATE(MIF_SCLK_LPDDR3PHY_WRAP_U1, "sclk_lpddr3phy_wrap_u1",
1278 "dout_clkm_phy", EN_SCLK_MIF, 1,
1279 CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
1280};
1281
1282static struct samsung_pll_clock mif_pll_clks[] __initdata = {
1283 PLL(pll_2550xx, MIF_FOUT_MEM_PLL, "fout_mem_pll", "fin_pll",
1284 MEM_PLL_LOCK, MEM_PLL_CON0,
1285 pll2550_24mhz_tbl),
1286 PLL(pll_2550xx, MIF_FOUT_BUS_PLL, "fout_bus_pll", "fin_pll",
1287 BUS_PLL_LOCK, BUS_PLL_CON0,
1288 pll2550_24mhz_tbl),
1289 PLL(pll_2550xx, MIF_FOUT_MEDIA_PLL, "fout_media_pll", "fin_pll",
1290 MEDIA_PLL_LOCK, MEDIA_PLL_CON0,
1291 pll2550_24mhz_tbl),
1292};
1293
1294static void __init exynos5260_clk_mif_init(struct device_node *np)
1295{
1296 struct exynos5260_cmu_info cmu = {0};
1297
1298 cmu.pll_clks = mif_pll_clks;
1299 cmu.nr_pll_clks = ARRAY_SIZE(mif_pll_clks);
1300 cmu.mux_clks = mif_mux_clks;
1301 cmu.nr_mux_clks = ARRAY_SIZE(mif_mux_clks);
1302 cmu.div_clks = mif_div_clks;
1303 cmu.nr_div_clks = ARRAY_SIZE(mif_div_clks);
1304 cmu.gate_clks = mif_gate_clks;
1305 cmu.nr_gate_clks = ARRAY_SIZE(mif_gate_clks);
1306 cmu.nr_clk_ids = MIF_NR_CLK;
1307 cmu.clk_regs = mif_clk_regs;
1308 cmu.nr_clk_regs = ARRAY_SIZE(mif_clk_regs);
1309
1310 exynos5260_cmu_register_one(np, &cmu);
1311}
1312
1313CLK_OF_DECLARE(exynos5260_clk_mif, "samsung,exynos5260-clock-mif",
1314 exynos5260_clk_mif_init);
1315
1316
1317/* CMU_PERI */
1318
1319static unsigned long peri_clk_regs[] __initdata = {
1320 MUX_SEL_PERI,
1321 MUX_SEL_PERI1,
1322 DIV_PERI,
1323 EN_PCLK_PERI0,
1324 EN_PCLK_PERI1,
1325 EN_PCLK_PERI2,
1326 EN_PCLK_PERI3,
1327 EN_PCLK_PERI_SECURE_CHIPID,
1328 EN_PCLK_PERI_SECURE_PROVKEY0,
1329 EN_PCLK_PERI_SECURE_PROVKEY1,
1330 EN_PCLK_PERI_SECURE_SECKEY,
1331 EN_PCLK_PERI_SECURE_ANTIRBKCNT,
1332 EN_PCLK_PERI_SECURE_TOP_RTC,
1333 EN_PCLK_PERI_SECURE_TZPC,
1334 EN_SCLK_PERI,
1335 EN_SCLK_PERI_SECURE_TOP_RTC,
1336 EN_IP_PERI0,
1337 EN_IP_PERI1,
1338 EN_IP_PERI2,
1339 EN_IP_PERI_SECURE_CHIPID,
1340 EN_IP_PERI_SECURE_PROVKEY0,
1341 EN_IP_PERI_SECURE_PROVKEY1,
1342 EN_IP_PERI_SECURE_SECKEY,
1343 EN_IP_PERI_SECURE_ANTIRBKCNT,
1344 EN_IP_PERI_SECURE_TOP_RTC,
1345 EN_IP_PERI_SECURE_TZPC,
1346};
1347
1348PNAME(mout_sclk_pcm_p) = {"ioclk_pcm_extclk", "fin_pll", "dout_aclk_peri_aud",
1349 "phyclk_hdmi_phy_ref_cko"};
1350PNAME(mout_sclk_i2scod_p) = {"ioclk_i2s_cdclk", "fin_pll", "dout_aclk_peri_aud",
1351 "phyclk_hdmi_phy_ref_cko"};
1352PNAME(mout_sclk_spdif_p) = {"ioclk_spdif_extclk", "fin_pll",
1353 "dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"};
1354
1355struct samsung_mux_clock peri_mux_clks[] __initdata = {
1356 MUX(PERI_MOUT_SCLK_PCM, "mout_sclk_pcm", mout_sclk_pcm_p,
1357 MUX_SEL_PERI1, 4, 2),
1358 MUX(PERI_MOUT_SCLK_I2SCOD, "mout_sclk_i2scod", mout_sclk_i2scod_p,
1359 MUX_SEL_PERI1, 12, 2),
1360 MUX(PERI_MOUT_SCLK_SPDIF, "mout_sclk_spdif", mout_sclk_spdif_p,
1361 MUX_SEL_PERI1, 20, 2),
1362};
1363
1364struct samsung_div_clock peri_div_clks[] __initdata = {
1365 DIV(PERI_DOUT_PCM, "dout_pcm", "mout_sclk_pcm", DIV_PERI, 0, 8),
1366 DIV(PERI_DOUT_I2S, "dout_i2s", "mout_sclk_i2scod", DIV_PERI, 8, 6),
1367};
1368
1369struct samsung_gate_clock peri_gate_clks[] __initdata = {
1370 GATE(PERI_SCLK_PCM1, "sclk_pcm1", "dout_pcm", EN_SCLK_PERI, 0,
1371 CLK_SET_RATE_PARENT, 0),
1372 GATE(PERI_SCLK_I2S, "sclk_i2s", "dout_i2s", EN_SCLK_PERI, 1,
1373 CLK_SET_RATE_PARENT, 0),
1374 GATE(PERI_SCLK_SPDIF, "sclk_spdif", "dout_sclk_peri_spi0_b",
1375 EN_SCLK_PERI, 2, CLK_SET_RATE_PARENT, 0),
1376 GATE(PERI_SCLK_SPI0, "sclk_spi0", "dout_sclk_peri_spi0_b",
1377 EN_SCLK_PERI, 7, CLK_SET_RATE_PARENT, 0),
1378 GATE(PERI_SCLK_SPI1, "sclk_spi1", "dout_sclk_peri_spi1_b",
1379 EN_SCLK_PERI, 8, CLK_SET_RATE_PARENT, 0),
1380 GATE(PERI_SCLK_SPI2, "sclk_spi2", "dout_sclk_peri_spi2_b",
1381 EN_SCLK_PERI, 9, CLK_SET_RATE_PARENT, 0),
1382 GATE(PERI_SCLK_UART0, "sclk_uart0", "dout_sclk_peri_uart0",
1383 EN_SCLK_PERI, 10, CLK_SET_RATE_PARENT, 0),
1384 GATE(PERI_SCLK_UART1, "sclk_uart1", "dout_sclk_peri_uart1",
1385 EN_SCLK_PERI, 11, CLK_SET_RATE_PARENT, 0),
1386 GATE(PERI_SCLK_UART2, "sclk_uart2", "dout_sclk_peri_uart2",
1387 EN_SCLK_PERI, 12, CLK_SET_RATE_PARENT, 0),
1388
1389 GATE(PERI_CLK_ABB, "clk_abb", "dout_aclk_peri_66",
1390 EN_IP_PERI0, 1, 0, 0),
1391 GATE(PERI_CLK_EFUSE_WRITER, "clk_efuse_writer", "dout_aclk_peri_66",
1392 EN_IP_PERI0, 5, 0, 0),
1393 GATE(PERI_CLK_HDMICEC, "clk_hdmicec", "dout_aclk_peri_66",
1394 EN_IP_PERI0, 6, 0, 0),
1395 GATE(PERI_CLK_I2C10, "clk_i2c10", "dout_aclk_peri_66",
1396 EN_IP_PERI0, 7, 0, 0),
1397 GATE(PERI_CLK_I2C11, "clk_i2c11", "dout_aclk_peri_66",
1398 EN_IP_PERI0, 8, 0, 0),
1399 GATE(PERI_CLK_I2C8, "clk_i2c8", "dout_aclk_peri_66",
1400 EN_IP_PERI0, 9, 0, 0),
1401 GATE(PERI_CLK_I2C9, "clk_i2c9", "dout_aclk_peri_66",
1402 EN_IP_PERI0, 10, 0, 0),
1403 GATE(PERI_CLK_I2C4, "clk_i2c4", "dout_aclk_peri_66",
1404 EN_IP_PERI0, 11, 0, 0),
1405 GATE(PERI_CLK_I2C5, "clk_i2c5", "dout_aclk_peri_66",
1406 EN_IP_PERI0, 12, 0, 0),
1407 GATE(PERI_CLK_I2C6, "clk_i2c6", "dout_aclk_peri_66",
1408 EN_IP_PERI0, 13, 0, 0),
1409 GATE(PERI_CLK_I2C7, "clk_i2c7", "dout_aclk_peri_66",
1410 EN_IP_PERI0, 14, 0, 0),
1411 GATE(PERI_CLK_I2CHDMI, "clk_i2chdmi", "dout_aclk_peri_66",
1412 EN_IP_PERI0, 15, 0, 0),
1413 GATE(PERI_CLK_I2S, "clk_peri_i2s", "dout_aclk_peri_66",
1414 EN_IP_PERI0, 16, 0, 0),
1415 GATE(PERI_CLK_MCT, "clk_mct", "dout_aclk_peri_66",
1416 EN_IP_PERI0, 17, 0, 0),
1417 GATE(PERI_CLK_PCM, "clk_peri_pcm", "dout_aclk_peri_66",
1418 EN_IP_PERI0, 18, 0, 0),
1419 GATE(PERI_CLK_HSIC0, "clk_hsic0", "dout_aclk_peri_66",
1420 EN_IP_PERI0, 20, 0, 0),
1421 GATE(PERI_CLK_HSIC1, "clk_hsic1", "dout_aclk_peri_66",
1422 EN_IP_PERI0, 21, 0, 0),
1423 GATE(PERI_CLK_HSIC2, "clk_hsic2", "dout_aclk_peri_66",
1424 EN_IP_PERI0, 22, 0, 0),
1425 GATE(PERI_CLK_HSIC3, "clk_hsic3", "dout_aclk_peri_66",
1426 EN_IP_PERI0, 23, 0, 0),
1427 GATE(PERI_CLK_WDT_EGL, "clk_wdt_egl", "dout_aclk_peri_66",
1428 EN_IP_PERI0, 24, 0, 0),
1429 GATE(PERI_CLK_WDT_KFC, "clk_wdt_kfc", "dout_aclk_peri_66",
1430 EN_IP_PERI0, 25, 0, 0),
1431
1432 GATE(PERI_CLK_UART4, "clk_uart4", "dout_aclk_peri_66",
1433 EN_IP_PERI2, 0, 0, 0),
1434 GATE(PERI_CLK_PWM, "clk_pwm", "dout_aclk_peri_66",
1435 EN_IP_PERI2, 3, 0, 0),
1436 GATE(PERI_CLK_SPDIF, "clk_spdif", "dout_aclk_peri_66",
1437 EN_IP_PERI2, 6, 0, 0),
1438 GATE(PERI_CLK_SPI0, "clk_spi0", "dout_aclk_peri_66",
1439 EN_IP_PERI2, 7, 0, 0),
1440 GATE(PERI_CLK_SPI1, "clk_spi1", "dout_aclk_peri_66",
1441 EN_IP_PERI2, 8, 0, 0),
1442 GATE(PERI_CLK_SPI2, "clk_spi2", "dout_aclk_peri_66",
1443 EN_IP_PERI2, 9, 0, 0),
1444 GATE(PERI_CLK_TMU0, "clk_tmu0", "dout_aclk_peri_66",
1445 EN_IP_PERI2, 10, 0, 0),
1446 GATE(PERI_CLK_TMU1, "clk_tmu1", "dout_aclk_peri_66",
1447 EN_IP_PERI2, 11, 0, 0),
1448 GATE(PERI_CLK_TMU2, "clk_tmu2", "dout_aclk_peri_66",
1449 EN_IP_PERI2, 12, 0, 0),
1450 GATE(PERI_CLK_TMU3, "clk_tmu3", "dout_aclk_peri_66",
1451 EN_IP_PERI2, 13, 0, 0),
1452 GATE(PERI_CLK_TMU4, "clk_tmu4", "dout_aclk_peri_66",
1453 EN_IP_PERI2, 14, 0, 0),
1454 GATE(PERI_CLK_ADC, "clk_adc", "dout_aclk_peri_66",
1455 EN_IP_PERI2, 18, 0, 0),
1456 GATE(PERI_CLK_UART0, "clk_uart0", "dout_aclk_peri_66",
1457 EN_IP_PERI2, 19, 0, 0),
1458 GATE(PERI_CLK_UART1, "clk_uart1", "dout_aclk_peri_66",
1459 EN_IP_PERI2, 20, 0, 0),
1460 GATE(PERI_CLK_UART2, "clk_uart2", "dout_aclk_peri_66",
1461 EN_IP_PERI2, 21, 0, 0),
1462
1463 GATE(PERI_CLK_CHIPID, "clk_chipid", "dout_aclk_peri_66",
1464 EN_IP_PERI_SECURE_CHIPID, 2, 0, 0),
1465
1466 GATE(PERI_CLK_PROVKEY0, "clk_provkey0", "dout_aclk_peri_66",
1467 EN_IP_PERI_SECURE_PROVKEY0, 1, 0, 0),
1468
1469 GATE(PERI_CLK_PROVKEY1, "clk_provkey1", "dout_aclk_peri_66",
1470 EN_IP_PERI_SECURE_PROVKEY1, 2, 0, 0),
1471
1472 GATE(PERI_CLK_SECKEY, "clk_seckey", "dout_aclk_peri_66",
1473 EN_IP_PERI_SECURE_SECKEY, 5, 0, 0),
1474
1475 GATE(PERI_CLK_TOP_RTC, "clk_top_rtc", "dout_aclk_peri_66",
1476 EN_IP_PERI_SECURE_TOP_RTC, 5, 0, 0),
1477
1478 GATE(PERI_CLK_TZPC0, "clk_tzpc0", "dout_aclk_peri_66",
1479 EN_IP_PERI_SECURE_TZPC, 10, 0, 0),
1480 GATE(PERI_CLK_TZPC1, "clk_tzpc1", "dout_aclk_peri_66",
1481 EN_IP_PERI_SECURE_TZPC, 11, 0, 0),
1482 GATE(PERI_CLK_TZPC2, "clk_tzpc2", "dout_aclk_peri_66",
1483 EN_IP_PERI_SECURE_TZPC, 12, 0, 0),
1484 GATE(PERI_CLK_TZPC3, "clk_tzpc3", "dout_aclk_peri_66",
1485 EN_IP_PERI_SECURE_TZPC, 13, 0, 0),
1486 GATE(PERI_CLK_TZPC4, "clk_tzpc4", "dout_aclk_peri_66",
1487 EN_IP_PERI_SECURE_TZPC, 14, 0, 0),
1488 GATE(PERI_CLK_TZPC5, "clk_tzpc5", "dout_aclk_peri_66",
1489 EN_IP_PERI_SECURE_TZPC, 15, 0, 0),
1490 GATE(PERI_CLK_TZPC6, "clk_tzpc6", "dout_aclk_peri_66",
1491 EN_IP_PERI_SECURE_TZPC, 16, 0, 0),
1492 GATE(PERI_CLK_TZPC7, "clk_tzpc7", "dout_aclk_peri_66",
1493 EN_IP_PERI_SECURE_TZPC, 17, 0, 0),
1494 GATE(PERI_CLK_TZPC8, "clk_tzpc8", "dout_aclk_peri_66",
1495 EN_IP_PERI_SECURE_TZPC, 18, 0, 0),
1496 GATE(PERI_CLK_TZPC9, "clk_tzpc9", "dout_aclk_peri_66",
1497 EN_IP_PERI_SECURE_TZPC, 19, 0, 0),
1498 GATE(PERI_CLK_TZPC10, "clk_tzpc10", "dout_aclk_peri_66",
1499 EN_IP_PERI_SECURE_TZPC, 20, 0, 0),
1500};
1501
1502static void __init exynos5260_clk_peri_init(struct device_node *np)
1503{
1504 struct exynos5260_cmu_info cmu = {0};
1505
1506 cmu.mux_clks = peri_mux_clks;
1507 cmu.nr_mux_clks = ARRAY_SIZE(peri_mux_clks);
1508 cmu.div_clks = peri_div_clks;
1509 cmu.nr_div_clks = ARRAY_SIZE(peri_div_clks);
1510 cmu.gate_clks = peri_gate_clks;
1511 cmu.nr_gate_clks = ARRAY_SIZE(peri_gate_clks);
1512 cmu.nr_clk_ids = PERI_NR_CLK;
1513 cmu.clk_regs = peri_clk_regs;
1514 cmu.nr_clk_regs = ARRAY_SIZE(peri_clk_regs);
1515
1516 exynos5260_cmu_register_one(np, &cmu);
1517}
1518
1519CLK_OF_DECLARE(exynos5260_clk_peri, "samsung,exynos5260-clock-peri",
1520 exynos5260_clk_peri_init);
1521
1522
1523/* CMU_TOP */
1524
1525static unsigned long top_clk_regs[] __initdata = {
1526 DISP_PLL_LOCK,
1527 AUD_PLL_LOCK,
1528 DISP_PLL_CON0,
1529 DISP_PLL_CON1,
1530 DISP_PLL_FDET,
1531 AUD_PLL_CON0,
1532 AUD_PLL_CON1,
1533 AUD_PLL_CON2,
1534 AUD_PLL_FDET,
1535 MUX_SEL_TOP_PLL0,
1536 MUX_SEL_TOP_MFC,
1537 MUX_SEL_TOP_G2D,
1538 MUX_SEL_TOP_GSCL,
1539 MUX_SEL_TOP_ISP10,
1540 MUX_SEL_TOP_ISP11,
1541 MUX_SEL_TOP_DISP0,
1542 MUX_SEL_TOP_DISP1,
1543 MUX_SEL_TOP_BUS,
1544 MUX_SEL_TOP_PERI0,
1545 MUX_SEL_TOP_PERI1,
1546 MUX_SEL_TOP_FSYS,
1547 DIV_TOP_G2D_MFC,
1548 DIV_TOP_GSCL_ISP0,
1549 DIV_TOP_ISP10,
1550 DIV_TOP_ISP11,
1551 DIV_TOP_DISP,
1552 DIV_TOP_BUS,
1553 DIV_TOP_PERI0,
1554 DIV_TOP_PERI1,
1555 DIV_TOP_PERI2,
1556 DIV_TOP_FSYS0,
1557 DIV_TOP_FSYS1,
1558 DIV_TOP_HPM,
1559 DIV_TOP_PLL_FDET,
1560 EN_ACLK_TOP,
1561 EN_SCLK_TOP,
1562 EN_IP_TOP,
1563};
1564
1565/* fixed rate clocks generated inside the soc */
1566struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = {
1567 FRATE(PHYCLK_DPTX_PHY_CH3_TXD_CLK, "phyclk_dptx_phy_ch3_txd_clk", NULL,
1568 CLK_IS_ROOT, 270000000),
1569 FRATE(PHYCLK_DPTX_PHY_CH2_TXD_CLK, "phyclk_dptx_phy_ch2_txd_clk", NULL,
1570 CLK_IS_ROOT, 270000000),
1571 FRATE(PHYCLK_DPTX_PHY_CH1_TXD_CLK, "phyclk_dptx_phy_ch1_txd_clk", NULL,
1572 CLK_IS_ROOT, 270000000),
1573 FRATE(PHYCLK_DPTX_PHY_CH0_TXD_CLK, "phyclk_dptx_phy_ch0_txd_clk", NULL,
1574 CLK_IS_ROOT, 270000000),
1575 FRATE(phyclk_hdmi_phy_tmds_clko, "phyclk_hdmi_phy_tmds_clko", NULL,
1576 CLK_IS_ROOT, 250000000),
1577 FRATE(PHYCLK_HDMI_PHY_PIXEL_CLKO, "phyclk_hdmi_phy_pixel_clko", NULL,
1578 CLK_IS_ROOT, 1660000000),
1579 FRATE(PHYCLK_HDMI_LINK_O_TMDS_CLKHI, "phyclk_hdmi_link_o_tmds_clkhi",
1580 NULL, CLK_IS_ROOT, 125000000),
1581 FRATE(PHYCLK_MIPI_DPHY_4L_M_TXBYTECLKHS,
1582 "phyclk_mipi_dphy_4l_m_txbyteclkhs" , NULL,
1583 CLK_IS_ROOT, 187500000),
1584 FRATE(PHYCLK_DPTX_PHY_O_REF_CLK_24M, "phyclk_dptx_phy_o_ref_clk_24m",
1585 NULL, CLK_IS_ROOT, 24000000),
1586 FRATE(PHYCLK_DPTX_PHY_CLK_DIV2, "phyclk_dptx_phy_clk_div2", NULL,
1587 CLK_IS_ROOT, 135000000),
1588 FRATE(PHYCLK_MIPI_DPHY_4L_M_RXCLKESC0,
1589 "phyclk_mipi_dphy_4l_m_rxclkesc0", NULL,
1590 CLK_IS_ROOT, 20000000),
1591 FRATE(PHYCLK_USBHOST20_PHY_PHYCLOCK, "phyclk_usbhost20_phy_phyclock",
1592 NULL, CLK_IS_ROOT, 60000000),
1593 FRATE(PHYCLK_USBHOST20_PHY_FREECLK, "phyclk_usbhost20_phy_freeclk",
1594 NULL, CLK_IS_ROOT, 60000000),
1595 FRATE(PHYCLK_USBHOST20_PHY_CLK48MOHCI,
1596 "phyclk_usbhost20_phy_clk48mohci",
1597 NULL, CLK_IS_ROOT, 48000000),
1598 FRATE(PHYCLK_USBDRD30_UDRD30_PIPE_PCLK,
1599 "phyclk_usbdrd30_udrd30_pipe_pclk", NULL,
1600 CLK_IS_ROOT, 125000000),
1601 FRATE(PHYCLK_USBDRD30_UDRD30_PHYCLOCK,
1602 "phyclk_usbdrd30_udrd30_phyclock", NULL,
1603 CLK_IS_ROOT, 60000000),
1604};
1605
1606PNAME(mout_memtop_pll_user_p) = {"fin_pll", "dout_mem_pll"};
1607PNAME(mout_bustop_pll_user_p) = {"fin_pll", "dout_bus_pll"};
1608PNAME(mout_mediatop_pll_user_p) = {"fin_pll", "dout_media_pll"};
1609PNAME(mout_audtop_pll_user_p) = {"fin_pll", "mout_aud_pll"};
1610PNAME(mout_aud_pll_p) = {"fin_pll", "fout_aud_pll"};
1611PNAME(mout_disp_pll_p) = {"fin_pll", "fout_disp_pll"};
1612PNAME(mout_mfc_bustop_333_p) = {"mout_bustop_pll_user", "mout_disp_pll"};
1613PNAME(mout_aclk_mfc_333_p) = {"mout_mediatop_pll_user", "mout_mfc_bustop_333"};
1614PNAME(mout_g2d_bustop_333_p) = {"mout_bustop_pll_user", "mout_disp_pll"};
1615PNAME(mout_aclk_g2d_333_p) = {"mout_mediatop_pll_user", "mout_g2d_bustop_333"};
1616PNAME(mout_gscl_bustop_333_p) = {"mout_bustop_pll_user", "mout_disp_pll"};
1617PNAME(mout_aclk_gscl_333_p) = {"mout_mediatop_pll_user",
1618 "mout_gscl_bustop_333"};
1619PNAME(mout_m2m_mediatop_400_p) = {"mout_mediatop_pll_user", "mout_disp_pll"};
1620PNAME(mout_aclk_gscl_400_p) = {"mout_bustop_pll_user",
1621 "mout_m2m_mediatop_400"};
1622PNAME(mout_gscl_bustop_fimc_p) = {"mout_bustop_pll_user", "mout_disp_pll"};
1623PNAME(mout_aclk_gscl_fimc_p) = {"mout_mediatop_pll_user",
1624 "mout_gscl_bustop_fimc"};
1625PNAME(mout_isp1_media_266_p) = {"mout_mediatop_pll_user",
1626 "mout_memtop_pll_user"};
1627PNAME(mout_aclk_isp1_266_p) = {"mout_bustop_pll_user", "mout_isp1_media_266"};
1628PNAME(mout_isp1_media_400_p) = {"mout_mediatop_pll_user", "mout_disp_pll"};
1629PNAME(mout_aclk_isp1_400_p) = {"mout_bustop_pll_user", "mout_isp1_media_400"};
1630PNAME(mout_sclk_isp_spi_p) = {"fin_pll", "mout_bustop_pll_user"};
1631PNAME(mout_sclk_isp_uart_p) = {"fin_pll", "mout_bustop_pll_user"};
1632PNAME(mout_sclk_isp_sensor_p) = {"fin_pll", "mout_bustop_pll_user"};
1633PNAME(mout_disp_disp_333_p) = {"mout_disp_pll", "mout_bustop_pll_user"};
1634PNAME(mout_aclk_disp_333_p) = {"mout_mediatop_pll_user", "mout_disp_disp_333"};
1635PNAME(mout_disp_disp_222_p) = {"mout_disp_pll", "mout_bustop_pll_user"};
1636PNAME(mout_aclk_disp_222_p) = {"mout_mediatop_pll_user", "mout_disp_disp_222"};
1637PNAME(mout_disp_media_pixel_p) = {"mout_mediatop_pll_user",
1638 "mout_bustop_pll_user"};
1639PNAME(mout_sclk_disp_pixel_p) = {"mout_disp_pll", "mout_disp_media_pixel"};
1640PNAME(mout_bus_bustop_400_p) = {"mout_bustop_pll_user", "mout_memtop_pll_user"};
1641PNAME(mout_bus_bustop_100_p) = {"mout_bustop_pll_user", "mout_memtop_pll_user"};
1642PNAME(mout_sclk_peri_spi_clk_p) = {"fin_pll", "mout_bustop_pll_user"};
1643PNAME(mout_sclk_peri_uart_uclk_p) = {"fin_pll", "mout_bustop_pll_user"};
1644PNAME(mout_sclk_fsys_usb_p) = {"fin_pll", "mout_bustop_pll_user"};
1645PNAME(mout_sclk_fsys_mmc_sdclkin_a_p) = {"fin_pll", "mout_bustop_pll_user"};
1646PNAME(mout_sclk_fsys_mmc0_sdclkin_b_p) = {"mout_sclk_fsys_mmc0_sdclkin_a",
1647 "mout_mediatop_pll_user"};
1648PNAME(mout_sclk_fsys_mmc1_sdclkin_b_p) = {"mout_sclk_fsys_mmc1_sdclkin_a",
1649 "mout_mediatop_pll_user"};
1650PNAME(mout_sclk_fsys_mmc2_sdclkin_b_p) = {"mout_sclk_fsys_mmc2_sdclkin_a",
1651 "mout_mediatop_pll_user"};
1652
1653struct samsung_mux_clock top_mux_clks[] __initdata = {
1654 MUX(TOP_MOUT_MEDIATOP_PLL_USER, "mout_mediatop_pll_user",
1655 mout_mediatop_pll_user_p,
1656 MUX_SEL_TOP_PLL0, 0, 1),
1657 MUX(TOP_MOUT_MEMTOP_PLL_USER, "mout_memtop_pll_user",
1658 mout_memtop_pll_user_p,
1659 MUX_SEL_TOP_PLL0, 4, 1),
1660 MUX(TOP_MOUT_BUSTOP_PLL_USER, "mout_bustop_pll_user",
1661 mout_bustop_pll_user_p,
1662 MUX_SEL_TOP_PLL0, 8, 1),
1663 MUX(TOP_MOUT_DISP_PLL, "mout_disp_pll", mout_disp_pll_p,
1664 MUX_SEL_TOP_PLL0, 12, 1),
1665 MUX(TOP_MOUT_AUD_PLL, "mout_aud_pll", mout_aud_pll_p,
1666 MUX_SEL_TOP_PLL0, 16, 1),
1667 MUX(TOP_MOUT_AUDTOP_PLL_USER, "mout_audtop_pll_user",
1668 mout_audtop_pll_user_p,
1669 MUX_SEL_TOP_PLL0, 24, 1),
1670
1671 MUX(TOP_MOUT_DISP_DISP_333, "mout_disp_disp_333", mout_disp_disp_333_p,
1672 MUX_SEL_TOP_DISP0, 0, 1),
1673 MUX(TOP_MOUT_ACLK_DISP_333, "mout_aclk_disp_333", mout_aclk_disp_333_p,
1674 MUX_SEL_TOP_DISP0, 8, 1),
1675 MUX(TOP_MOUT_DISP_DISP_222, "mout_disp_disp_222", mout_disp_disp_222_p,
1676 MUX_SEL_TOP_DISP0, 12, 1),
1677 MUX(TOP_MOUT_ACLK_DISP_222, "mout_aclk_disp_222", mout_aclk_disp_222_p,
1678 MUX_SEL_TOP_DISP0, 20, 1),
1679
1680 MUX(TOP_MOUT_FIMD1, "mout_sclk_disp_pixel", mout_sclk_disp_pixel_p,
1681 MUX_SEL_TOP_DISP1, 0, 1),
1682 MUX(TOP_MOUT_DISP_MEDIA_PIXEL, "mout_disp_media_pixel",
1683 mout_disp_media_pixel_p,
1684 MUX_SEL_TOP_DISP1, 8, 1),
1685
1686 MUX(TOP_MOUT_SCLK_PERI_SPI2_CLK, "mout_sclk_peri_spi2_clk",
1687 mout_sclk_peri_spi_clk_p,
1688 MUX_SEL_TOP_PERI1, 0, 1),
1689 MUX(TOP_MOUT_SCLK_PERI_SPI1_CLK, "mout_sclk_peri_spi1_clk",
1690 mout_sclk_peri_spi_clk_p,
1691 MUX_SEL_TOP_PERI1, 4, 1),
1692 MUX(TOP_MOUT_SCLK_PERI_SPI0_CLK, "mout_sclk_peri_spi0_clk",
1693 mout_sclk_peri_spi_clk_p,
1694 MUX_SEL_TOP_PERI1, 8, 1),
1695 MUX(TOP_MOUT_SCLK_PERI_UART1_UCLK, "mout_sclk_peri_uart1_uclk",
1696 mout_sclk_peri_uart_uclk_p,
1697 MUX_SEL_TOP_PERI1, 12, 1),
1698 MUX(TOP_MOUT_SCLK_PERI_UART2_UCLK, "mout_sclk_peri_uart2_uclk",
1699 mout_sclk_peri_uart_uclk_p,
1700 MUX_SEL_TOP_PERI1, 16, 1),
1701 MUX(TOP_MOUT_SCLK_PERI_UART0_UCLK, "mout_sclk_peri_uart0_uclk",
1702 mout_sclk_peri_uart_uclk_p,
1703 MUX_SEL_TOP_PERI1, 20, 1),
1704
1705
1706 MUX(TOP_MOUT_BUS1_BUSTOP_400, "mout_bus1_bustop_400",
1707 mout_bus_bustop_400_p,
1708 MUX_SEL_TOP_BUS, 0, 1),
1709 MUX(TOP_MOUT_BUS1_BUSTOP_100, "mout_bus1_bustop_100",
1710 mout_bus_bustop_100_p,
1711 MUX_SEL_TOP_BUS, 4, 1),
1712 MUX(TOP_MOUT_BUS2_BUSTOP_100, "mout_bus2_bustop_100",
1713 mout_bus_bustop_100_p,
1714 MUX_SEL_TOP_BUS, 8, 1),
1715 MUX(TOP_MOUT_BUS2_BUSTOP_400, "mout_bus2_bustop_400",
1716 mout_bus_bustop_400_p,
1717 MUX_SEL_TOP_BUS, 12, 1),
1718 MUX(TOP_MOUT_BUS3_BUSTOP_400, "mout_bus3_bustop_400",
1719 mout_bus_bustop_400_p,
1720 MUX_SEL_TOP_BUS, 16, 1),
1721 MUX(TOP_MOUT_BUS3_BUSTOP_100, "mout_bus3_bustop_100",
1722 mout_bus_bustop_100_p,
1723 MUX_SEL_TOP_BUS, 20, 1),
1724 MUX(TOP_MOUT_BUS4_BUSTOP_400, "mout_bus4_bustop_400",
1725 mout_bus_bustop_400_p,
1726 MUX_SEL_TOP_BUS, 24, 1),
1727 MUX(TOP_MOUT_BUS4_BUSTOP_100, "mout_bus4_bustop_100",
1728 mout_bus_bustop_100_p,
1729 MUX_SEL_TOP_BUS, 28, 1),
1730
1731 MUX(TOP_MOUT_SCLK_FSYS_USB, "mout_sclk_fsys_usb",
1732 mout_sclk_fsys_usb_p,
1733 MUX_SEL_TOP_FSYS, 0, 1),
1734 MUX(TOP_MOUT_SCLK_FSYS_MMC2_SDCLKIN_A, "mout_sclk_fsys_mmc2_sdclkin_a",
1735 mout_sclk_fsys_mmc_sdclkin_a_p,
1736 MUX_SEL_TOP_FSYS, 4, 1),
1737 MUX(TOP_MOUT_SCLK_FSYS_MMC2_SDCLKIN_B, "mout_sclk_fsys_mmc2_sdclkin_b",
1738 mout_sclk_fsys_mmc2_sdclkin_b_p,
1739 MUX_SEL_TOP_FSYS, 8, 1),
1740 MUX(TOP_MOUT_SCLK_FSYS_MMC1_SDCLKIN_A, "mout_sclk_fsys_mmc1_sdclkin_a",
1741 mout_sclk_fsys_mmc_sdclkin_a_p,
1742 MUX_SEL_TOP_FSYS, 12, 1),
1743 MUX(TOP_MOUT_SCLK_FSYS_MMC1_SDCLKIN_B, "mout_sclk_fsys_mmc1_sdclkin_b",
1744 mout_sclk_fsys_mmc1_sdclkin_b_p,
1745 MUX_SEL_TOP_FSYS, 16, 1),
1746 MUX(TOP_MOUT_SCLK_FSYS_MMC0_SDCLKIN_A, "mout_sclk_fsys_mmc0_sdclkin_a",
1747 mout_sclk_fsys_mmc_sdclkin_a_p,
1748 MUX_SEL_TOP_FSYS, 20, 1),
1749 MUX(TOP_MOUT_SCLK_FSYS_MMC0_SDCLKIN_B, "mout_sclk_fsys_mmc0_sdclkin_b",
1750 mout_sclk_fsys_mmc0_sdclkin_b_p,
1751 MUX_SEL_TOP_FSYS, 24, 1),
1752
1753 MUX(TOP_MOUT_ISP1_MEDIA_400, "mout_isp1_media_400",
1754 mout_isp1_media_400_p,
1755 MUX_SEL_TOP_ISP10, 4, 1),
1756 MUX(TOP_MOUT_ACLK_ISP1_400, "mout_aclk_isp1_400", mout_aclk_isp1_400_p,
1757 MUX_SEL_TOP_ISP10, 8 , 1),
1758 MUX(TOP_MOUT_ISP1_MEDIA_266, "mout_isp1_media_266",
1759 mout_isp1_media_266_p,
1760 MUX_SEL_TOP_ISP10, 16, 1),
1761 MUX(TOP_MOUT_ACLK_ISP1_266, "mout_aclk_isp1_266", mout_aclk_isp1_266_p,
1762 MUX_SEL_TOP_ISP10, 20, 1),
1763
1764 MUX(TOP_MOUT_SCLK_ISP1_SPI0, "mout_sclk_isp1_spi0", mout_sclk_isp_spi_p,
1765 MUX_SEL_TOP_ISP11, 4, 1),
1766 MUX(TOP_MOUT_SCLK_ISP1_SPI1, "mout_sclk_isp1_spi1", mout_sclk_isp_spi_p,
1767 MUX_SEL_TOP_ISP11, 8, 1),
1768 MUX(TOP_MOUT_SCLK_ISP1_UART, "mout_sclk_isp1_uart",
1769 mout_sclk_isp_uart_p,
1770 MUX_SEL_TOP_ISP11, 12, 1),
1771 MUX(TOP_MOUT_SCLK_ISP1_SENSOR0, "mout_sclk_isp1_sensor0",
1772 mout_sclk_isp_sensor_p,
1773 MUX_SEL_TOP_ISP11, 16, 1),
1774 MUX(TOP_MOUT_SCLK_ISP1_SENSOR1, "mout_sclk_isp1_sensor1",
1775 mout_sclk_isp_sensor_p,
1776 MUX_SEL_TOP_ISP11, 20, 1),
1777 MUX(TOP_MOUT_SCLK_ISP1_SENSOR2, "mout_sclk_isp1_sensor2",
1778 mout_sclk_isp_sensor_p,
1779 MUX_SEL_TOP_ISP11, 24, 1),
1780
1781 MUX(TOP_MOUT_MFC_BUSTOP_333, "mout_mfc_bustop_333",
1782 mout_mfc_bustop_333_p,
1783 MUX_SEL_TOP_MFC, 4, 1),
1784 MUX(TOP_MOUT_ACLK_MFC_333, "mout_aclk_mfc_333", mout_aclk_mfc_333_p,
1785 MUX_SEL_TOP_MFC, 8, 1),
1786
1787 MUX(TOP_MOUT_G2D_BUSTOP_333, "mout_g2d_bustop_333",
1788 mout_g2d_bustop_333_p,
1789 MUX_SEL_TOP_G2D, 4, 1),
1790 MUX(TOP_MOUT_ACLK_G2D_333, "mout_aclk_g2d_333", mout_aclk_g2d_333_p,
1791 MUX_SEL_TOP_G2D, 8, 1),
1792
1793 MUX(TOP_MOUT_M2M_MEDIATOP_400, "mout_m2m_mediatop_400",
1794 mout_m2m_mediatop_400_p,
1795 MUX_SEL_TOP_GSCL, 0, 1),
1796 MUX(TOP_MOUT_ACLK_GSCL_400, "mout_aclk_gscl_400",
1797 mout_aclk_gscl_400_p,
1798 MUX_SEL_TOP_GSCL, 4, 1),
1799 MUX(TOP_MOUT_GSCL_BUSTOP_333, "mout_gscl_bustop_333",
1800 mout_gscl_bustop_333_p,
1801 MUX_SEL_TOP_GSCL, 8, 1),
1802 MUX(TOP_MOUT_ACLK_GSCL_333, "mout_aclk_gscl_333",
1803 mout_aclk_gscl_333_p,
1804 MUX_SEL_TOP_GSCL, 12, 1),
1805 MUX(TOP_MOUT_GSCL_BUSTOP_FIMC, "mout_gscl_bustop_fimc",
1806 mout_gscl_bustop_fimc_p,
1807 MUX_SEL_TOP_GSCL, 16, 1),
1808 MUX(TOP_MOUT_ACLK_GSCL_FIMC, "mout_aclk_gscl_fimc",
1809 mout_aclk_gscl_fimc_p,
1810 MUX_SEL_TOP_GSCL, 20, 1),
1811};
1812
1813struct samsung_div_clock top_div_clks[] __initdata = {
1814 DIV(TOP_DOUT_ACLK_G2D_333, "dout_aclk_g2d_333", "mout_aclk_g2d_333",
1815 DIV_TOP_G2D_MFC, 0, 3),
1816 DIV(TOP_DOUT_ACLK_MFC_333, "dout_aclk_mfc_333", "mout_aclk_mfc_333",
1817 DIV_TOP_G2D_MFC, 4, 3),
1818
1819 DIV(TOP_DOUT_ACLK_GSCL_333, "dout_aclk_gscl_333", "mout_aclk_gscl_333",
1820 DIV_TOP_GSCL_ISP0, 0, 3),
1821 DIV(TOP_DOUT_ACLK_GSCL_400, "dout_aclk_gscl_400", "mout_aclk_gscl_400",
1822 DIV_TOP_GSCL_ISP0, 4, 3),
1823 DIV(TOP_DOUT_ACLK_GSCL_FIMC, "dout_aclk_gscl_fimc",
1824 "mout_aclk_gscl_fimc", DIV_TOP_GSCL_ISP0, 8, 3),
1825 DIV(TOP_DOUT_SCLK_ISP1_SENSOR0_A, "dout_sclk_isp1_sensor0_a",
1826 "mout_aclk_gscl_fimc", DIV_TOP_GSCL_ISP0, 16, 4),
1827 DIV(TOP_DOUT_SCLK_ISP1_SENSOR1_A, "dout_sclk_isp1_sensor1_a",
1828 "mout_aclk_gscl_400", DIV_TOP_GSCL_ISP0, 20, 4),
1829 DIV(TOP_DOUT_SCLK_ISP1_SENSOR2_A, "dout_sclk_isp1_sensor2_a",
1830 "mout_aclk_gscl_fimc", DIV_TOP_GSCL_ISP0, 24, 4),
1831
1832 DIV(TOP_DOUT_ACLK_ISP1_266, "dout_aclk_isp1_266", "mout_aclk_isp1_266",
1833 DIV_TOP_ISP10, 0, 3),
1834 DIV(TOP_DOUT_ACLK_ISP1_400, "dout_aclk_isp1_400", "mout_aclk_isp1_400",
1835 DIV_TOP_ISP10, 4, 3),
1836 DIV(TOP_DOUT_SCLK_ISP1_SPI0_A, "dout_sclk_isp1_spi0_a",
1837 "mout_sclk_isp1_spi0", DIV_TOP_ISP10, 12, 4),
1838 DIV(TOP_DOUT_SCLK_ISP1_SPI0_B, "dout_sclk_isp1_spi0_b",
1839 "dout_sclk_isp1_spi0_a", DIV_TOP_ISP10, 16, 8),
1840
1841 DIV(TOP_DOUT_SCLK_ISP1_SPI1_A, "dout_sclk_isp1_spi1_a",
1842 "mout_sclk_isp1_spi1", DIV_TOP_ISP11, 0, 4),
1843 DIV(TOP_DOUT_SCLK_ISP1_SPI1_B, "dout_sclk_isp1_spi1_b",
1844 "dout_sclk_isp1_spi1_a", DIV_TOP_ISP11, 4, 8),
1845 DIV(TOP_DOUT_SCLK_ISP1_UART, "dout_sclk_isp1_uart",
1846 "mout_sclk_isp1_uart", DIV_TOP_ISP11, 12, 4),
1847 DIV(TOP_DOUT_SCLK_ISP1_SENSOR0_B, "dout_sclk_isp1_sensor0_b",
1848 "dout_sclk_isp1_sensor0_a", DIV_TOP_ISP11, 16, 4),
1849 DIV(TOP_DOUT_SCLK_ISP1_SENSOR1_B, "dout_sclk_isp1_sensor1_b",
1850 "dout_sclk_isp1_sensor1_a", DIV_TOP_ISP11, 20, 4),
1851 DIV(TOP_DOUT_SCLK_ISP1_SENSOR2_B, "dout_sclk_isp1_sensor2_b",
1852 "dout_sclk_isp1_sensor2_a", DIV_TOP_ISP11, 24, 4),
1853
1854 DIV(TOP_DOUTTOP__SCLK_HPM_TARGETCLK, "dout_sclk_hpm_targetclk",
1855 "mout_bustop_pll_user", DIV_TOP_HPM, 0, 3),
1856
1857 DIV(TOP_DOUT_ACLK_DISP_333, "dout_aclk_disp_333", "mout_aclk_disp_333",
1858 DIV_TOP_DISP, 0, 3),
1859 DIV(TOP_DOUT_ACLK_DISP_222, "dout_aclk_disp_222", "mout_aclk_disp_222",
1860 DIV_TOP_DISP, 4, 3),
1861 DIV(TOP_DOUT_SCLK_DISP_PIXEL, "dout_sclk_disp_pixel",
1862 "mout_sclk_disp_pixel", DIV_TOP_DISP, 8, 3),
1863
1864 DIV(TOP_DOUT_ACLK_BUS1_400, "dout_aclk_bus1_400",
1865 "mout_bus1_bustop_400", DIV_TOP_BUS, 0, 3),
1866 DIV(TOP_DOUT_ACLK_BUS1_100, "dout_aclk_bus1_100",
1867 "mout_bus1_bustop_100", DIV_TOP_BUS, 4, 4),
1868 DIV(TOP_DOUT_ACLK_BUS2_400, "dout_aclk_bus2_400",
1869 "mout_bus2_bustop_400", DIV_TOP_BUS, 8, 3),
1870 DIV(TOP_DOUT_ACLK_BUS2_100, "dout_aclk_bus2_100",
1871 "mout_bus2_bustop_100", DIV_TOP_BUS, 12, 4),
1872 DIV(TOP_DOUT_ACLK_BUS3_400, "dout_aclk_bus3_400",
1873 "mout_bus3_bustop_400", DIV_TOP_BUS, 16, 3),
1874 DIV(TOP_DOUT_ACLK_BUS3_100, "dout_aclk_bus3_100",
1875 "mout_bus3_bustop_100", DIV_TOP_BUS, 20, 4),
1876 DIV(TOP_DOUT_ACLK_BUS4_400, "dout_aclk_bus4_400",
1877 "mout_bus4_bustop_400", DIV_TOP_BUS, 24, 3),
1878 DIV(TOP_DOUT_ACLK_BUS4_100, "dout_aclk_bus4_100",
1879 "mout_bus4_bustop_100", DIV_TOP_BUS, 28, 4),
1880
1881 DIV(TOP_DOUT_SCLK_PERI_SPI0_A, "dout_sclk_peri_spi0_a",
1882 "mout_sclk_peri_spi0_clk", DIV_TOP_PERI0, 4, 4),
1883 DIV(TOP_DOUT_SCLK_PERI_SPI0_B, "dout_sclk_peri_spi0_b",
1884 "dout_sclk_peri_spi0_a", DIV_TOP_PERI0, 8, 8),
1885 DIV(TOP_DOUT_SCLK_PERI_SPI1_A, "dout_sclk_peri_spi1_a",
1886 "mout_sclk_peri_spi1_clk", DIV_TOP_PERI0, 16, 4),
1887 DIV(TOP_DOUT_SCLK_PERI_SPI1_B, "dout_sclk_peri_spi1_b",
1888 "dout_sclk_peri_spi1_a", DIV_TOP_PERI0, 20, 8),
1889
1890 DIV(TOP_DOUT_SCLK_PERI_SPI2_A, "dout_sclk_peri_spi2_a",
1891 "mout_sclk_peri_spi2_clk", DIV_TOP_PERI1, 0, 4),
1892 DIV(TOP_DOUT_SCLK_PERI_SPI2_B, "dout_sclk_peri_spi2_b",
1893 "dout_sclk_peri_spi2_a", DIV_TOP_PERI1, 4, 8),
1894 DIV(TOP_DOUT_SCLK_PERI_UART1, "dout_sclk_peri_uart1",
1895 "mout_sclk_peri_uart1_uclk", DIV_TOP_PERI1, 16, 4),
1896 DIV(TOP_DOUT_SCLK_PERI_UART2, "dout_sclk_peri_uart2",
1897 "mout_sclk_peri_uart2_uclk", DIV_TOP_PERI1, 20, 4),
1898 DIV(TOP_DOUT_SCLK_PERI_UART0, "dout_sclk_peri_uart0",
1899 "mout_sclk_peri_uart0_uclk", DIV_TOP_PERI1, 24, 4),
1900
1901 DIV(TOP_DOUT_ACLK_PERI_66, "dout_aclk_peri_66", "mout_bustop_pll_user",
1902 DIV_TOP_PERI2, 20, 4),
1903 DIV(TOP_DOUT_ACLK_PERI_AUD, "dout_aclk_peri_aud",
1904 "mout_audtop_pll_user", DIV_TOP_PERI2, 24, 3),
1905
1906 DIV(TOP_DOUT_ACLK_FSYS_200, "dout_aclk_fsys_200",
1907 "mout_bustop_pll_user", DIV_TOP_FSYS0, 0, 3),
1908 DIV(TOP_DOUT_SCLK_FSYS_USBDRD30_SUSPEND_CLK,
1909 "dout_sclk_fsys_usbdrd30_suspend_clk",
1910 "mout_sclk_fsys_usb", DIV_TOP_FSYS0, 4, 4),
1911 DIV(TOP_DOUT_SCLK_FSYS_MMC0_SDCLKIN_A, "dout_sclk_fsys_mmc0_sdclkin_a",
1912 "mout_sclk_fsys_mmc0_sdclkin_b",
1913 DIV_TOP_FSYS0, 12, 4),
1914 DIV(TOP_DOUT_SCLK_FSYS_MMC0_SDCLKIN_B, "dout_sclk_fsys_mmc0_sdclkin_b",
1915 "dout_sclk_fsys_mmc0_sdclkin_a",
1916 DIV_TOP_FSYS0, 16, 8),
1917
1918
1919 DIV(TOP_DOUT_SCLK_FSYS_MMC1_SDCLKIN_A, "dout_sclk_fsys_mmc1_sdclkin_a",
1920 "mout_sclk_fsys_mmc1_sdclkin_b",
1921 DIV_TOP_FSYS1, 0, 4),
1922 DIV(TOP_DOUT_SCLK_FSYS_MMC1_SDCLKIN_B, "dout_sclk_fsys_mmc1_sdclkin_b",
1923 "dout_sclk_fsys_mmc1_sdclkin_a",
1924 DIV_TOP_FSYS1, 4, 8),
1925 DIV(TOP_DOUT_SCLK_FSYS_MMC2_SDCLKIN_A, "dout_sclk_fsys_mmc2_sdclkin_a",
1926 "mout_sclk_fsys_mmc2_sdclkin_b",
1927 DIV_TOP_FSYS1, 12, 4),
1928 DIV(TOP_DOUT_SCLK_FSYS_MMC2_SDCLKIN_B, "dout_sclk_fsys_mmc2_sdclkin_b",
1929 "dout_sclk_fsys_mmc2_sdclkin_a",
1930 DIV_TOP_FSYS1, 16, 8),
1931
1932};
1933
1934struct samsung_gate_clock top_gate_clks[] __initdata = {
1935 GATE(TOP_SCLK_MMC0, "sclk_fsys_mmc0_sdclkin",
1936 "dout_sclk_fsys_mmc0_sdclkin_b",
1937 EN_SCLK_TOP, 7, CLK_SET_RATE_PARENT, 0),
1938 GATE(TOP_SCLK_MMC1, "sclk_fsys_mmc1_sdclkin",
1939 "dout_sclk_fsys_mmc1_sdclkin_b",
1940 EN_SCLK_TOP, 8, CLK_SET_RATE_PARENT, 0),
1941 GATE(TOP_SCLK_MMC2, "sclk_fsys_mmc2_sdclkin",
1942 "dout_sclk_fsys_mmc2_sdclkin_b",
1943 EN_SCLK_TOP, 9, CLK_SET_RATE_PARENT, 0),
1944 GATE(TOP_SCLK_FIMD1, "sclk_disp_pixel", "dout_sclk_disp_pixel",
1945 EN_ACLK_TOP, 10, CLK_IGNORE_UNUSED |
1946 CLK_SET_RATE_PARENT, 0),
1947};
1948
1949static struct samsung_pll_clock top_pll_clks[] __initdata = {
1950 PLL(pll_2550xx, TOP_FOUT_DISP_PLL, "fout_disp_pll", "fin_pll",
1951 DISP_PLL_LOCK, DISP_PLL_CON0,
1952 pll2550_24mhz_tbl),
1953 PLL(pll_2650xx, TOP_FOUT_AUD_PLL, "fout_aud_pll", "fin_pll",
1954 AUD_PLL_LOCK, AUD_PLL_CON0,
1955 pll2650_24mhz_tbl),
1956};
1957
1958static void __init exynos5260_clk_top_init(struct device_node *np)
1959{
1960 struct exynos5260_cmu_info cmu = {0};
1961
1962 cmu.pll_clks = top_pll_clks;
1963 cmu.nr_pll_clks = ARRAY_SIZE(top_pll_clks);
1964 cmu.mux_clks = top_mux_clks;
1965 cmu.nr_mux_clks = ARRAY_SIZE(top_mux_clks);
1966 cmu.div_clks = top_div_clks;
1967 cmu.nr_div_clks = ARRAY_SIZE(top_div_clks);
1968 cmu.gate_clks = top_gate_clks;
1969 cmu.nr_gate_clks = ARRAY_SIZE(top_gate_clks);
1970 cmu.fixed_clks = fixed_rate_clks;
1971 cmu.nr_fixed_clks = ARRAY_SIZE(fixed_rate_clks);
1972 cmu.nr_clk_ids = TOP_NR_CLK;
1973 cmu.clk_regs = top_clk_regs;
1974 cmu.nr_clk_regs = ARRAY_SIZE(top_clk_regs);
1975
1976 exynos5260_cmu_register_one(np, &cmu);
1977}
1978
1979CLK_OF_DECLARE(exynos5260_clk_top, "samsung,exynos5260-clock-top",
1980 exynos5260_clk_top_init);
diff --git a/drivers/clk/samsung/clk-exynos5260.h b/drivers/clk/samsung/clk-exynos5260.h
new file mode 100644
index 000000000000..d739716d6ea1
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos5260.h
@@ -0,0 +1,459 @@
1/*
2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 * Author: Rahul Sharma <rahul.sharma@samsung.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 * Common Clock Framework support for Exynos5260 SoC.
10 */
11
12#ifndef __CLK_EXYNOS5260_H
13#define __CLK_EXYNOS5260_H
14
15/*
16*Registers for CMU_AUD
17*/
18#define MUX_SEL_AUD 0x0200
19#define MUX_ENABLE_AUD 0x0300
20#define MUX_STAT_AUD 0x0400
21#define MUX_IGNORE_AUD 0x0500
22#define DIV_AUD0 0x0600
23#define DIV_AUD1 0x0604
24#define DIV_STAT_AUD0 0x0700
25#define DIV_STAT_AUD1 0x0704
26#define EN_ACLK_AUD 0x0800
27#define EN_PCLK_AUD 0x0900
28#define EN_SCLK_AUD 0x0a00
29#define EN_IP_AUD 0x0b00
30
31/*
32*Registers for CMU_DISP
33*/
34#define MUX_SEL_DISP0 0x0200
35#define MUX_SEL_DISP1 0x0204
36#define MUX_SEL_DISP2 0x0208
37#define MUX_SEL_DISP3 0x020C
38#define MUX_SEL_DISP4 0x0210
39#define MUX_ENABLE_DISP0 0x0300
40#define MUX_ENABLE_DISP1 0x0304
41#define MUX_ENABLE_DISP2 0x0308
42#define MUX_ENABLE_DISP3 0x030c
43#define MUX_ENABLE_DISP4 0x0310
44#define MUX_STAT_DISP0 0x0400
45#define MUX_STAT_DISP1 0x0404
46#define MUX_STAT_DISP2 0x0408
47#define MUX_STAT_DISP3 0x040c
48#define MUX_STAT_DISP4 0x0410
49#define MUX_IGNORE_DISP0 0x0500
50#define MUX_IGNORE_DISP1 0x0504
51#define MUX_IGNORE_DISP2 0x0508
52#define MUX_IGNORE_DISP3 0x050c
53#define MUX_IGNORE_DISP4 0x0510
54#define DIV_DISP 0x0600
55#define DIV_STAT_DISP 0x0700
56#define EN_ACLK_DISP 0x0800
57#define EN_PCLK_DISP 0x0900
58#define EN_SCLK_DISP0 0x0a00
59#define EN_SCLK_DISP1 0x0a04
60#define EN_IP_DISP 0x0b00
61#define EN_IP_DISP_BUS 0x0b04
62
63
64/*
65*Registers for CMU_EGL
66*/
67#define EGL_PLL_LOCK 0x0000
68#define EGL_DPLL_LOCK 0x0004
69#define EGL_PLL_CON0 0x0100
70#define EGL_PLL_CON1 0x0104
71#define EGL_PLL_FREQ_DET 0x010c
72#define EGL_DPLL_CON0 0x0110
73#define EGL_DPLL_CON1 0x0114
74#define EGL_DPLL_FREQ_DET 0x011c
75#define MUX_SEL_EGL 0x0200
76#define MUX_ENABLE_EGL 0x0300
77#define MUX_STAT_EGL 0x0400
78#define DIV_EGL 0x0600
79#define DIV_EGL_PLL_FDET 0x0604
80#define DIV_STAT_EGL 0x0700
81#define DIV_STAT_EGL_PLL_FDET 0x0704
82#define EN_ACLK_EGL 0x0800
83#define EN_PCLK_EGL 0x0900
84#define EN_SCLK_EGL 0x0a00
85#define EN_IP_EGL 0x0b00
86#define CLKOUT_CMU_EGL 0x0c00
87#define CLKOUT_CMU_EGL_DIV_STAT 0x0c04
88#define ARMCLK_STOPCTRL 0x1000
89#define EAGLE_EMA_CTRL 0x1008
90#define EAGLE_EMA_STATUS 0x100c
91#define PWR_CTRL 0x1020
92#define PWR_CTRL2 0x1024
93#define CLKSTOP_CTRL 0x1028
94#define INTR_SPREAD_EN 0x1080
95#define INTR_SPREAD_USE_STANDBYWFI 0x1084
96#define INTR_SPREAD_BLOCKING_DURATION 0x1088
97#define CMU_EGL_SPARE0 0x2000
98#define CMU_EGL_SPARE1 0x2004
99#define CMU_EGL_SPARE2 0x2008
100#define CMU_EGL_SPARE3 0x200c
101#define CMU_EGL_SPARE4 0x2010
102
103/*
104*Registers for CMU_FSYS
105*/
106
107#define MUX_SEL_FSYS0 0x0200
108#define MUX_SEL_FSYS1 0x0204
109#define MUX_ENABLE_FSYS0 0x0300
110#define MUX_ENABLE_FSYS1 0x0304
111#define MUX_STAT_FSYS0 0x0400
112#define MUX_STAT_FSYS1 0x0404
113#define MUX_IGNORE_FSYS0 0x0500
114#define MUX_IGNORE_FSYS1 0x0504
115#define EN_ACLK_FSYS 0x0800
116#define EN_ACLK_FSYS_SECURE_RTIC 0x0804
117#define EN_ACLK_FSYS_SECURE_SMMU_RTIC 0x0808
118#define EN_PCLK_FSYS 0x0900
119#define EN_SCLK_FSYS 0x0a00
120#define EN_IP_FSYS 0x0b00
121#define EN_IP_FSYS_SECURE_RTIC 0x0b04
122#define EN_IP_FSYS_SECURE_SMMU_RTIC 0x0b08
123
124/*
125*Registers for CMU_G2D
126*/
127
128#define MUX_SEL_G2D 0x0200
129#define MUX_ENABLE_G2D 0x0300
130#define MUX_STAT_G2D 0x0400
131#define DIV_G2D 0x0600
132#define DIV_STAT_G2D 0x0700
133#define EN_ACLK_G2D 0x0800
134#define EN_ACLK_G2D_SECURE_SSS 0x0804
135#define EN_ACLK_G2D_SECURE_SLIM_SSS 0x0808
136#define EN_ACLK_G2D_SECURE_SMMU_SLIM_SSS 0x080c
137#define EN_ACLK_G2D_SECURE_SMMU_SSS 0x0810
138#define EN_ACLK_G2D_SECURE_SMMU_MDMA 0x0814
139#define EN_ACLK_G2D_SECURE_SMMU_G2D 0x0818
140#define EN_PCLK_G2D 0x0900
141#define EN_PCLK_G2D_SECURE_SMMU_SLIM_SSS 0x0904
142#define EN_PCLK_G2D_SECURE_SMMU_SSS 0x0908
143#define EN_PCLK_G2D_SECURE_SMMU_MDMA 0x090c
144#define EN_PCLK_G2D_SECURE_SMMU_G2D 0x0910
145#define EN_IP_G2D 0x0b00
146#define EN_IP_G2D_SECURE_SSS 0x0b04
147#define EN_IP_G2D_SECURE_SLIM_SSS 0x0b08
148#define EN_IP_G2D_SECURE_SMMU_SLIM_SSS 0x0b0c
149#define EN_IP_G2D_SECURE_SMMU_SSS 0x0b10
150#define EN_IP_G2D_SECURE_SMMU_MDMA 0x0b14
151#define EN_IP_G2D_SECURE_SMMU_G2D 0x0b18
152
153/*
154*Registers for CMU_G3D
155*/
156
157#define G3D_PLL_LOCK 0x0000
158#define G3D_PLL_CON0 0x0100
159#define G3D_PLL_CON1 0x0104
160#define G3D_PLL_FDET 0x010c
161#define MUX_SEL_G3D 0x0200
162#define MUX_EN_G3D 0x0300
163#define MUX_STAT_G3D 0x0400
164#define MUX_IGNORE_G3D 0x0500
165#define DIV_G3D 0x0600
166#define DIV_G3D_PLL_FDET 0x0604
167#define DIV_STAT_G3D 0x0700
168#define DIV_STAT_G3D_PLL_FDET 0x0704
169#define EN_ACLK_G3D 0x0800
170#define EN_PCLK_G3D 0x0900
171#define EN_SCLK_G3D 0x0a00
172#define EN_IP_G3D 0x0b00
173#define CLKOUT_CMU_G3D 0x0c00
174#define CLKOUT_CMU_G3D_DIV_STAT 0x0c04
175#define G3DCLK_STOPCTRL 0x1000
176#define G3D_EMA_CTRL 0x1008
177#define G3D_EMA_STATUS 0x100c
178
179/*
180*Registers for CMU_GSCL
181*/
182
183#define MUX_SEL_GSCL 0x0200
184#define MUX_EN_GSCL 0x0300
185#define MUX_STAT_GSCL 0x0400
186#define MUX_IGNORE_GSCL 0x0500
187#define DIV_GSCL 0x0600
188#define DIV_STAT_GSCL 0x0700
189#define EN_ACLK_GSCL 0x0800
190#define EN_ACLK_GSCL_FIMC 0x0804
191#define EN_ACLK_GSCL_SECURE_SMMU_GSCL0 0x0808
192#define EN_ACLK_GSCL_SECURE_SMMU_GSCL1 0x080c
193#define EN_ACLK_GSCL_SECURE_SMMU_MSCL0 0x0810
194#define EN_ACLK_GSCL_SECURE_SMMU_MSCL1 0x0814
195#define EN_PCLK_GSCL 0x0900
196#define EN_PCLK_GSCL_FIMC 0x0904
197#define EN_PCLK_GSCL_SECURE_SMMU_GSCL0 0x0908
198#define EN_PCLK_GSCL_SECURE_SMMU_GSCL1 0x090c
199#define EN_PCLK_GSCL_SECURE_SMMU_MSCL0 0x0910
200#define EN_PCLK_GSCL_SECURE_SMMU_MSCL1 0x0914
201#define EN_SCLK_GSCL 0x0a00
202#define EN_SCLK_GSCL_FIMC 0x0a04
203#define EN_IP_GSCL 0x0b00
204#define EN_IP_GSCL_FIMC 0x0b04
205#define EN_IP_GSCL_SECURE_SMMU_GSCL0 0x0b08
206#define EN_IP_GSCL_SECURE_SMMU_GSCL1 0x0b0c
207#define EN_IP_GSCL_SECURE_SMMU_MSCL0 0x0b10
208#define EN_IP_GSCL_SECURE_SMMU_MSCL1 0x0b14
209
210/*
211*Registers for CMU_ISP
212*/
213#define MUX_SEL_ISP0 0x0200
214#define MUX_SEL_ISP1 0x0204
215#define MUX_ENABLE_ISP0 0x0300
216#define MUX_ENABLE_ISP1 0x0304
217#define MUX_STAT_ISP0 0x0400
218#define MUX_STAT_ISP1 0x0404
219#define MUX_IGNORE_ISP0 0x0500
220#define MUX_IGNORE_ISP1 0x0504
221#define DIV_ISP 0x0600
222#define DIV_STAT_ISP 0x0700
223#define EN_ACLK_ISP0 0x0800
224#define EN_ACLK_ISP1 0x0804
225#define EN_PCLK_ISP0 0x0900
226#define EN_PCLK_ISP1 0x0904
227#define EN_SCLK_ISP 0x0a00
228#define EN_IP_ISP0 0x0b00
229#define EN_IP_ISP1 0x0b04
230
231/*
232*Registers for CMU_KFC
233*/
234#define KFC_PLL_LOCK 0x0000
235#define KFC_PLL_CON0 0x0100
236#define KFC_PLL_CON1 0x0104
237#define KFC_PLL_FDET 0x010c
238#define MUX_SEL_KFC0 0x0200
239#define MUX_SEL_KFC2 0x0208
240#define MUX_ENABLE_KFC0 0x0300
241#define MUX_ENABLE_KFC2 0x0308
242#define MUX_STAT_KFC0 0x0400
243#define MUX_STAT_KFC2 0x0408
244#define DIV_KFC 0x0600
245#define DIV_KFC_PLL_FDET 0x0604
246#define DIV_STAT_KFC 0x0700
247#define DIV_STAT_KFC_PLL_FDET 0x0704
248#define EN_ACLK_KFC 0x0800
249#define EN_PCLK_KFC 0x0900
250#define EN_SCLK_KFC 0x0a00
251#define EN_IP_KFC 0x0b00
252#define CLKOUT_CMU_KFC 0x0c00
253#define CLKOUT_CMU_KFC_DIV_STAT 0x0c04
254#define ARMCLK_STOPCTRL_KFC 0x1000
255#define ARM_EMA_CTRL 0x1008
256#define ARM_EMA_STATUS 0x100c
257#define PWR_CTRL_KFC 0x1020
258#define PWR_CTRL2_KFC 0x1024
259#define CLKSTOP_CTRL_KFC 0x1028
260#define INTR_SPREAD_ENABLE_KFC 0x1080
261#define INTR_SPREAD_USE_STANDBYWFI_KFC 0x1084
262#define INTR_SPREAD_BLOCKING_DURATION_KFC 0x1088
263#define CMU_KFC_SPARE0 0x2000
264#define CMU_KFC_SPARE1 0x2004
265#define CMU_KFC_SPARE2 0x2008
266#define CMU_KFC_SPARE3 0x200c
267#define CMU_KFC_SPARE4 0x2010
268
269/*
270*Registers for CMU_MFC
271*/
272#define MUX_SEL_MFC 0x0200
273#define MUX_ENABLE_MFC 0x0300
274#define MUX_STAT_MFC 0x0400
275#define DIV_MFC 0x0600
276#define DIV_STAT_MFC 0x0700
277#define EN_ACLK_MFC 0x0800
278#define EN_ACLK_SECURE_SMMU2_MFC 0x0804
279#define EN_PCLK_MFC 0x0900
280#define EN_PCLK_SECURE_SMMU2_MFC 0x0904
281#define EN_IP_MFC 0x0b00
282#define EN_IP_MFC_SECURE_SMMU2_MFC 0x0b04
283
284/*
285*Registers for CMU_MIF
286*/
287#define MEM_PLL_LOCK 0x0000
288#define BUS_PLL_LOCK 0x0004
289#define MEDIA_PLL_LOCK 0x0008
290#define MEM_PLL_CON0 0x0100
291#define MEM_PLL_CON1 0x0104
292#define MEM_PLL_FDET 0x010c
293#define BUS_PLL_CON0 0x0110
294#define BUS_PLL_CON1 0x0114
295#define BUS_PLL_FDET 0x011c
296#define MEDIA_PLL_CON0 0x0120
297#define MEDIA_PLL_CON1 0x0124
298#define MEDIA_PLL_FDET 0x012c
299#define MUX_SEL_MIF 0x0200
300#define MUX_ENABLE_MIF 0x0300
301#define MUX_STAT_MIF 0x0400
302#define MUX_IGNORE_MIF 0x0500
303#define DIV_MIF 0x0600
304#define DIV_MIF_PLL_FDET 0x0604
305#define DIV_STAT_MIF 0x0700
306#define DIV_STAT_MIF_PLL_FDET 0x0704
307#define EN_ACLK_MIF 0x0800
308#define EN_ACLK_MIF_SECURE_DREX1_TZ 0x0804
309#define EN_ACLK_MIF_SECURE_DREX0_TZ 0x0808
310#define EN_ACLK_MIF_SECURE_INTMEM 0x080c
311#define EN_PCLK_MIF 0x0900
312#define EN_PCLK_MIF_SECURE_MONOCNT 0x0904
313#define EN_PCLK_MIF_SECURE_RTC_APBIF 0x0908
314#define EN_PCLK_MIF_SECURE_DREX1_TZ 0x090c
315#define EN_PCLK_MIF_SECURE_DREX0_TZ 0x0910
316#define EN_SCLK_MIF 0x0a00
317#define EN_IP_MIF 0x0b00
318#define EN_IP_MIF_SECURE_MONOCNT 0x0b04
319#define EN_IP_MIF_SECURE_RTC_APBIF 0x0b08
320#define EN_IP_MIF_SECURE_DREX1_TZ 0x0b0c
321#define EN_IP_MIF_SECURE_DREX0_TZ 0x0b10
322#define EN_IP_MIF_SECURE_INTEMEM 0x0b14
323#define CLKOUT_CMU_MIF_DIV_STAT 0x0c04
324#define DREX_FREQ_CTRL 0x1000
325#define PAUSE 0x1004
326#define DDRPHY_LOCK_CTRL 0x1008
327#define CLKOUT_CMU_MIF 0xcb00
328
329/*
330*Registers for CMU_PERI
331*/
332#define MUX_SEL_PERI 0x0200
333#define MUX_SEL_PERI1 0x0204
334#define MUX_ENABLE_PERI 0x0300
335#define MUX_ENABLE_PERI1 0x0304
336#define MUX_STAT_PERI 0x0400
337#define MUX_STAT_PERI1 0x0404
338#define MUX_IGNORE_PERI 0x0500
339#define MUX_IGNORE_PERI1 0x0504
340#define DIV_PERI 0x0600
341#define DIV_STAT_PERI 0x0700
342#define EN_PCLK_PERI0 0x0800
343#define EN_PCLK_PERI1 0x0804
344#define EN_PCLK_PERI2 0x0808
345#define EN_PCLK_PERI3 0x080c
346#define EN_PCLK_PERI_SECURE_CHIPID 0x0810
347#define EN_PCLK_PERI_SECURE_PROVKEY0 0x0814
348#define EN_PCLK_PERI_SECURE_PROVKEY1 0x0818
349#define EN_PCLK_PERI_SECURE_SECKEY 0x081c
350#define EN_PCLK_PERI_SECURE_ANTIRBKCNT 0x0820
351#define EN_PCLK_PERI_SECURE_TOP_RTC 0x0824
352#define EN_PCLK_PERI_SECURE_TZPC 0x0828
353#define EN_SCLK_PERI 0x0a00
354#define EN_SCLK_PERI_SECURE_TOP_RTC 0x0a04
355#define EN_IP_PERI0 0x0b00
356#define EN_IP_PERI1 0x0b04
357#define EN_IP_PERI2 0x0b08
358#define EN_IP_PERI_SECURE_CHIPID 0x0b0c
359#define EN_IP_PERI_SECURE_PROVKEY0 0x0b10
360#define EN_IP_PERI_SECURE_PROVKEY1 0x0b14
361#define EN_IP_PERI_SECURE_SECKEY 0x0b18
362#define EN_IP_PERI_SECURE_ANTIRBKCNT 0x0b1c
363#define EN_IP_PERI_SECURE_TOP_RTC 0x0b20
364#define EN_IP_PERI_SECURE_TZPC 0x0b24
365
366/*
367*Registers for CMU_TOP
368*/
369#define DISP_PLL_LOCK 0x0000
370#define AUD_PLL_LOCK 0x0004
371#define DISP_PLL_CON0 0x0100
372#define DISP_PLL_CON1 0x0104
373#define DISP_PLL_FDET 0x0108
374#define AUD_PLL_CON0 0x0110
375#define AUD_PLL_CON1 0x0114
376#define AUD_PLL_CON2 0x0118
377#define AUD_PLL_FDET 0x011c
378#define MUX_SEL_TOP_PLL0 0x0200
379#define MUX_SEL_TOP_MFC 0x0204
380#define MUX_SEL_TOP_G2D 0x0208
381#define MUX_SEL_TOP_GSCL 0x020c
382#define MUX_SEL_TOP_ISP10 0x0214
383#define MUX_SEL_TOP_ISP11 0x0218
384#define MUX_SEL_TOP_DISP0 0x021c
385#define MUX_SEL_TOP_DISP1 0x0220
386#define MUX_SEL_TOP_BUS 0x0224
387#define MUX_SEL_TOP_PERI0 0x0228
388#define MUX_SEL_TOP_PERI1 0x022c
389#define MUX_SEL_TOP_FSYS 0x0230
390#define MUX_ENABLE_TOP_PLL0 0x0300
391#define MUX_ENABLE_TOP_MFC 0x0304
392#define MUX_ENABLE_TOP_G2D 0x0308
393#define MUX_ENABLE_TOP_GSCL 0x030c
394#define MUX_ENABLE_TOP_ISP10 0x0314
395#define MUX_ENABLE_TOP_ISP11 0x0318
396#define MUX_ENABLE_TOP_DISP0 0x031c
397#define MUX_ENABLE_TOP_DISP1 0x0320
398#define MUX_ENABLE_TOP_BUS 0x0324
399#define MUX_ENABLE_TOP_PERI0 0x0328
400#define MUX_ENABLE_TOP_PERI1 0x032c
401#define MUX_ENABLE_TOP_FSYS 0x0330
402#define MUX_STAT_TOP_PLL0 0x0400
403#define MUX_STAT_TOP_MFC 0x0404
404#define MUX_STAT_TOP_G2D 0x0408
405#define MUX_STAT_TOP_GSCL 0x040c
406#define MUX_STAT_TOP_ISP10 0x0414
407#define MUX_STAT_TOP_ISP11 0x0418
408#define MUX_STAT_TOP_DISP0 0x041c
409#define MUX_STAT_TOP_DISP1 0x0420
410#define MUX_STAT_TOP_BUS 0x0424
411#define MUX_STAT_TOP_PERI0 0x0428
412#define MUX_STAT_TOP_PERI1 0x042c
413#define MUX_STAT_TOP_FSYS 0x0430
414#define MUX_IGNORE_TOP_PLL0 0x0500
415#define MUX_IGNORE_TOP_MFC 0x0504
416#define MUX_IGNORE_TOP_G2D 0x0508
417#define MUX_IGNORE_TOP_GSCL 0x050c
418#define MUX_IGNORE_TOP_ISP10 0x0514
419#define MUX_IGNORE_TOP_ISP11 0x0518
420#define MUX_IGNORE_TOP_DISP0 0x051c
421#define MUX_IGNORE_TOP_DISP1 0x0520
422#define MUX_IGNORE_TOP_BUS 0x0524
423#define MUX_IGNORE_TOP_PERI0 0x0528
424#define MUX_IGNORE_TOP_PERI1 0x052c
425#define MUX_IGNORE_TOP_FSYS 0x0530
426#define DIV_TOP_G2D_MFC 0x0600
427#define DIV_TOP_GSCL_ISP0 0x0604
428#define DIV_TOP_ISP10 0x0608
429#define DIV_TOP_ISP11 0x060c
430#define DIV_TOP_DISP 0x0610
431#define DIV_TOP_BUS 0x0614
432#define DIV_TOP_PERI0 0x0618
433#define DIV_TOP_PERI1 0x061c
434#define DIV_TOP_PERI2 0x0620
435#define DIV_TOP_FSYS0 0x0624
436#define DIV_TOP_FSYS1 0x0628
437#define DIV_TOP_HPM 0x062c
438#define DIV_TOP_PLL_FDET 0x0630
439#define DIV_STAT_TOP_G2D_MFC 0x0700
440#define DIV_STAT_TOP_GSCL_ISP0 0x0704
441#define DIV_STAT_TOP_ISP10 0x0708
442#define DIV_STAT_TOP_ISP11 0x070c
443#define DIV_STAT_TOP_DISP 0x0710
444#define DIV_STAT_TOP_BUS 0x0714
445#define DIV_STAT_TOP_PERI0 0x0718
446#define DIV_STAT_TOP_PERI1 0x071c
447#define DIV_STAT_TOP_PERI2 0x0720
448#define DIV_STAT_TOP_FSYS0 0x0724
449#define DIV_STAT_TOP_FSYS1 0x0728
450#define DIV_STAT_TOP_HPM 0x072c
451#define DIV_STAT_TOP_PLL_FDET 0x0730
452#define EN_ACLK_TOP 0x0800
453#define EN_SCLK_TOP 0x0a00
454#define EN_IP_TOP 0x0b00
455#define CLKOUT_CMU_TOP 0x0c00
456#define CLKOUT_CMU_TOP_DIV_STAT 0x0c04
457
458#endif /*__CLK_EXYNOS5260_H */
459
diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
new file mode 100644
index 000000000000..c9505ab9ee70
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -0,0 +1,209 @@
1/*
2 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
3 * Author: Tarek Dakhran <t.dakhran@samsung.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 * Common Clock Framework support for Exynos5410 SoC.
10*/
11
12#include <dt-bindings/clock/exynos5410.h>
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
20#include "clk.h"
21
22#define APLL_LOCK 0x0
23#define APLL_CON0 0x100
24#define CPLL_LOCK 0x10020
25#define CPLL_CON0 0x10120
26#define MPLL_LOCK 0x4000
27#define MPLL_CON0 0x4100
28#define BPLL_LOCK 0x20010
29#define BPLL_CON0 0x20110
30#define KPLL_LOCK 0x28000
31#define KPLL_CON0 0x28100
32
33#define SRC_CPU 0x200
34#define DIV_CPU0 0x500
35#define SRC_CPERI1 0x4204
36#define DIV_TOP0 0x10510
37#define DIV_TOP1 0x10514
38#define DIV_FSYS1 0x1054c
39#define DIV_FSYS2 0x10550
40#define DIV_PERIC0 0x10558
41#define SRC_TOP0 0x10210
42#define SRC_TOP1 0x10214
43#define SRC_TOP2 0x10218
44#define SRC_FSYS 0x10244
45#define SRC_PERIC0 0x10250
46#define SRC_MASK_FSYS 0x10340
47#define SRC_MASK_PERIC0 0x10350
48#define GATE_BUS_FSYS0 0x10740
49#define GATE_IP_FSYS 0x10944
50#define GATE_IP_PERIC 0x10950
51#define GATE_IP_PERIS 0x10960
52#define SRC_CDREX 0x20200
53#define SRC_KFC 0x28200
54#define DIV_KFC0 0x28500
55
56/* list of PLLs */
57enum exynos5410_plls {
58 apll, cpll, mpll,
59 bpll, kpll,
60 nr_plls /* number of PLLs */
61};
62
63/* list of all parent clocks */
64PNAME(apll_p) = { "fin_pll", "fout_apll", };
65PNAME(bpll_p) = { "fin_pll", "fout_bpll", };
66PNAME(cpll_p) = { "fin_pll", "fout_cpll" };
67PNAME(mpll_p) = { "fin_pll", "fout_mpll", };
68PNAME(kpll_p) = { "fin_pll", "fout_kpll", };
69
70PNAME(mout_cpu_p) = { "mout_apll", "sclk_mpll", };
71PNAME(mout_kfc_p) = { "mout_kpll", "sclk_mpll", };
72
73PNAME(mpll_user_p) = { "fin_pll", "sclk_mpll", };
74PNAME(bpll_user_p) = { "fin_pll", "sclk_bpll", };
75PNAME(mpll_bpll_p) = { "sclk_mpll_muxed", "sclk_bpll_muxed", };
76
77PNAME(group2_p) = { "fin_pll", "fin_pll", "none", "none",
78 "none", "none", "sclk_mpll_bpll",
79 "none", "none", "sclk_cpll" };
80
81static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
82 MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1),
83 MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
84
85 MUX(0, "mout_kpll", kpll_p, SRC_KFC, 0, 1),
86 MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1),
87
88 MUX(0, "sclk_mpll", mpll_p, SRC_CPERI1, 8, 1),
89 MUX(0, "sclk_mpll_muxed", mpll_user_p, SRC_TOP2, 20, 1),
90
91 MUX(0, "sclk_bpll", bpll_p, SRC_CDREX, 0, 1),
92 MUX(0, "sclk_bpll_muxed", bpll_user_p, SRC_TOP2, 24, 1),
93
94 MUX(0, "sclk_cpll", cpll_p, SRC_TOP2, 8, 1),
95
96 MUX(0, "sclk_mpll_bpll", mpll_bpll_p, SRC_TOP1, 20, 1),
97
98 MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 0, 4),
99 MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 4, 4),
100 MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 8, 4),
101
102 MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 0, 4),
103 MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 4, 4),
104 MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 8, 4),
105
106 MUX(0, "mout_aclk200", mpll_bpll_p, SRC_TOP0, 12, 1),
107 MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1),
108};
109
110static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
111 DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
112 DIV(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3),
113
114 DIV(0, "div_acp", "div_arm2", DIV_CPU0, 8, 3),
115 DIV(0, "div_cpud", "div_arm2", DIV_CPU0, 4, 3),
116 DIV(0, "div_atb", "div_arm2", DIV_CPU0, 16, 3),
117 DIV(0, "pclk_dbg", "div_arm2", DIV_CPU0, 20, 3),
118
119 DIV(0, "div_kfc", "mout_kfc", DIV_KFC0, 0, 3),
120 DIV(0, "div_aclk", "div_kfc", DIV_KFC0, 4, 3),
121 DIV(0, "div_pclk", "div_kfc", DIV_KFC0, 20, 3),
122
123 DIV(0, "aclk66_pre", "sclk_mpll_muxed", DIV_TOP1, 24, 3),
124 DIV(0, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3),
125
126 DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
127 DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
128 DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
129
130 DIV_F(0, "div_mmc_pre0", "div_mmc0",
131 DIV_FSYS1, 8, 8, CLK_SET_RATE_PARENT, 0),
132 DIV_F(0, "div_mmc_pre1", "div_mmc1",
133 DIV_FSYS1, 24, 8, CLK_SET_RATE_PARENT, 0),
134 DIV_F(0, "div_mmc_pre2", "div_mmc2",
135 DIV_FSYS2, 8, 8, CLK_SET_RATE_PARENT, 0),
136
137 DIV(0, "div_uart0", "mout_uart0", DIV_PERIC0, 0, 4),
138 DIV(0, "div_uart1", "mout_uart1", DIV_PERIC0, 4, 4),
139 DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
140 DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
141
142 DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
143 DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3),
144};
145
146static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
147 GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
148
149 GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
150 SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
151 GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc_pre1",
152 SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0),
153 GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc_pre2",
154 SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
155
156 GATE(CLK_MMC0, "sdmmc0", "aclk200", GATE_BUS_FSYS0, 12, 0, 0),
157 GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0),
158 GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0),
159
160 GATE(CLK_UART0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0),
161 GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
162 GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
163
164 GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
165 SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
166 GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1",
167 SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
168 GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2",
169 SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
170};
171
172static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
173 [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
174 APLL_CON0, NULL),
175 [cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
176 CPLL_CON0, NULL),
177 [mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK,
178 MPLL_CON0, NULL),
179 [bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK,
180 BPLL_CON0, NULL),
181 [kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll", KPLL_LOCK,
182 KPLL_CON0, NULL),
183};
184
185/* register exynos5410 clocks */
186static void __init exynos5410_clk_init(struct device_node *np)
187{
188 struct samsung_clk_provider *ctx;
189 void __iomem *reg_base;
190
191 reg_base = of_iomap(np, 0);
192 if (!reg_base)
193 panic("%s: failed to map registers\n", __func__);
194
195 ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
196
197 samsung_clk_register_pll(ctx, exynos5410_plls,
198 ARRAY_SIZE(exynos5410_plls), reg_base);
199
200 samsung_clk_register_mux(ctx, exynos5410_mux_clks,
201 ARRAY_SIZE(exynos5410_mux_clks));
202 samsung_clk_register_div(ctx, exynos5410_div_clks,
203 ARRAY_SIZE(exynos5410_div_clks));
204 samsung_clk_register_gate(ctx, exynos5410_gate_clks,
205 ARRAY_SIZE(exynos5410_gate_clks));
206
207 pr_debug("Exynos5410: clock setup completed.\n");
208}
209CLK_OF_DECLARE(exynos5410_clk, "samsung,exynos5410-clock", exynos5410_clk_init);
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 60b26819bed5..9d7d7eed03fd 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -27,18 +27,24 @@
27#define DIV_CPU1 0x504 27#define DIV_CPU1 0x504
28#define GATE_BUS_CPU 0x700 28#define GATE_BUS_CPU 0x700
29#define GATE_SCLK_CPU 0x800 29#define GATE_SCLK_CPU 0x800
30#define CLKOUT_CMU_CPU 0xa00
31#define GATE_IP_G2D 0x8800
30#define CPLL_LOCK 0x10020 32#define CPLL_LOCK 0x10020
31#define DPLL_LOCK 0x10030 33#define DPLL_LOCK 0x10030
32#define EPLL_LOCK 0x10040 34#define EPLL_LOCK 0x10040
33#define RPLL_LOCK 0x10050 35#define RPLL_LOCK 0x10050
34#define IPLL_LOCK 0x10060 36#define IPLL_LOCK 0x10060
35#define SPLL_LOCK 0x10070 37#define SPLL_LOCK 0x10070
36#define VPLL_LOCK 0x10070 38#define VPLL_LOCK 0x10080
37#define MPLL_LOCK 0x10090 39#define MPLL_LOCK 0x10090
38#define CPLL_CON0 0x10120 40#define CPLL_CON0 0x10120
39#define DPLL_CON0 0x10128 41#define DPLL_CON0 0x10128
40#define EPLL_CON0 0x10130 42#define EPLL_CON0 0x10130
43#define EPLL_CON1 0x10134
44#define EPLL_CON2 0x10138
41#define RPLL_CON0 0x10140 45#define RPLL_CON0 0x10140
46#define RPLL_CON1 0x10144
47#define RPLL_CON2 0x10148
42#define IPLL_CON0 0x10150 48#define IPLL_CON0 0x10150
43#define SPLL_CON0 0x10160 49#define SPLL_CON0 0x10160
44#define VPLL_CON0 0x10170 50#define VPLL_CON0 0x10170
@@ -51,21 +57,31 @@
51#define SRC_TOP5 0x10214 57#define SRC_TOP5 0x10214
52#define SRC_TOP6 0x10218 58#define SRC_TOP6 0x10218
53#define SRC_TOP7 0x1021c 59#define SRC_TOP7 0x1021c
60#define SRC_TOP8 0x10220 /* 5800 specific */
61#define SRC_TOP9 0x10224 /* 5800 specific */
54#define SRC_DISP10 0x1022c 62#define SRC_DISP10 0x1022c
55#define SRC_MAU 0x10240 63#define SRC_MAU 0x10240
56#define SRC_FSYS 0x10244 64#define SRC_FSYS 0x10244
57#define SRC_PERIC0 0x10250 65#define SRC_PERIC0 0x10250
58#define SRC_PERIC1 0x10254 66#define SRC_PERIC1 0x10254
67#define SRC_ISP 0x10270
68#define SRC_CAM 0x10274 /* 5800 specific */
59#define SRC_TOP10 0x10280 69#define SRC_TOP10 0x10280
60#define SRC_TOP11 0x10284 70#define SRC_TOP11 0x10284
61#define SRC_TOP12 0x10288 71#define SRC_TOP12 0x10288
62#define SRC_MASK_DISP10 0x1032c 72#define SRC_TOP13 0x1028c /* 5800 specific */
73#define SRC_MASK_TOP2 0x10308
74#define SRC_MASK_TOP7 0x1031c
75#define SRC_MASK_DISP10 0x1032c
76#define SRC_MASK_MAU 0x10334
63#define SRC_MASK_FSYS 0x10340 77#define SRC_MASK_FSYS 0x10340
64#define SRC_MASK_PERIC0 0x10350 78#define SRC_MASK_PERIC0 0x10350
65#define SRC_MASK_PERIC1 0x10354 79#define SRC_MASK_PERIC1 0x10354
66#define DIV_TOP0 0x10500 80#define DIV_TOP0 0x10500
67#define DIV_TOP1 0x10504 81#define DIV_TOP1 0x10504
68#define DIV_TOP2 0x10508 82#define DIV_TOP2 0x10508
83#define DIV_TOP8 0x10520 /* 5800 specific */
84#define DIV_TOP9 0x10524 /* 5800 specific */
69#define DIV_DISP10 0x1052c 85#define DIV_DISP10 0x1052c
70#define DIV_MAU 0x10544 86#define DIV_MAU 0x10544
71#define DIV_FSYS0 0x10548 87#define DIV_FSYS0 0x10548
@@ -76,54 +92,82 @@
76#define DIV_PERIC2 0x10560 92#define DIV_PERIC2 0x10560
77#define DIV_PERIC3 0x10564 93#define DIV_PERIC3 0x10564
78#define DIV_PERIC4 0x10568 94#define DIV_PERIC4 0x10568
95#define DIV_CAM 0x10574 /* 5800 specific */
96#define SCLK_DIV_ISP0 0x10580
97#define SCLK_DIV_ISP1 0x10584
98#define DIV2_RATIO0 0x10590
99#define DIV4_RATIO 0x105a0
79#define GATE_BUS_TOP 0x10700 100#define GATE_BUS_TOP 0x10700
101#define GATE_BUS_GEN 0x1073c
80#define GATE_BUS_FSYS0 0x10740 102#define GATE_BUS_FSYS0 0x10740
103#define GATE_BUS_FSYS2 0x10748
81#define GATE_BUS_PERIC 0x10750 104#define GATE_BUS_PERIC 0x10750
82#define GATE_BUS_PERIC1 0x10754 105#define GATE_BUS_PERIC1 0x10754
83#define GATE_BUS_PERIS0 0x10760 106#define GATE_BUS_PERIS0 0x10760
84#define GATE_BUS_PERIS1 0x10764 107#define GATE_BUS_PERIS1 0x10764
108#define GATE_BUS_NOC 0x10770
109#define GATE_TOP_SCLK_ISP 0x10870
85#define GATE_IP_GSCL0 0x10910 110#define GATE_IP_GSCL0 0x10910
86#define GATE_IP_GSCL1 0x10920 111#define GATE_IP_GSCL1 0x10920
112#define GATE_IP_CAM 0x10924 /* 5800 specific */
87#define GATE_IP_MFC 0x1092c 113#define GATE_IP_MFC 0x1092c
88#define GATE_IP_DISP1 0x10928 114#define GATE_IP_DISP1 0x10928
89#define GATE_IP_G3D 0x10930 115#define GATE_IP_G3D 0x10930
90#define GATE_IP_GEN 0x10934 116#define GATE_IP_GEN 0x10934
117#define GATE_IP_FSYS 0x10944
118#define GATE_IP_PERIC 0x10950
119#define GATE_IP_PERIS 0x10960
91#define GATE_IP_MSCL 0x10970 120#define GATE_IP_MSCL 0x10970
92#define GATE_TOP_SCLK_GSCL 0x10820 121#define GATE_TOP_SCLK_GSCL 0x10820
93#define GATE_TOP_SCLK_DISP1 0x10828 122#define GATE_TOP_SCLK_DISP1 0x10828
94#define GATE_TOP_SCLK_MAU 0x1083c 123#define GATE_TOP_SCLK_MAU 0x1083c
95#define GATE_TOP_SCLK_FSYS 0x10840 124#define GATE_TOP_SCLK_FSYS 0x10840
96#define GATE_TOP_SCLK_PERIC 0x10850 125#define GATE_TOP_SCLK_PERIC 0x10850
126#define TOP_SPARE2 0x10b08
97#define BPLL_LOCK 0x20010 127#define BPLL_LOCK 0x20010
98#define BPLL_CON0 0x20110 128#define BPLL_CON0 0x20110
99#define SRC_CDREX 0x20200
100#define KPLL_LOCK 0x28000 129#define KPLL_LOCK 0x28000
101#define KPLL_CON0 0x28100 130#define KPLL_CON0 0x28100
102#define SRC_KFC 0x28200 131#define SRC_KFC 0x28200
103#define DIV_KFC0 0x28500 132#define DIV_KFC0 0x28500
104 133
134/* Exynos5x SoC type */
135enum exynos5x_soc {
136 EXYNOS5420,
137 EXYNOS5800,
138};
139
105/* list of PLLs */ 140/* list of PLLs */
106enum exynos5420_plls { 141enum exynos5x_plls {
107 apll, cpll, dpll, epll, rpll, ipll, spll, vpll, mpll, 142 apll, cpll, dpll, epll, rpll, ipll, spll, vpll, mpll,
108 bpll, kpll, 143 bpll, kpll,
109 nr_plls /* number of PLLs */ 144 nr_plls /* number of PLLs */
110}; 145};
111 146
112static void __iomem *reg_base; 147static void __iomem *reg_base;
148static enum exynos5x_soc exynos5x_soc;
113 149
114#ifdef CONFIG_PM_SLEEP 150#ifdef CONFIG_PM_SLEEP
115static struct samsung_clk_reg_dump *exynos5420_save; 151static struct samsung_clk_reg_dump *exynos5x_save;
152static struct samsung_clk_reg_dump *exynos5800_save;
116 153
117/* 154/*
118 * list of controller registers to be saved and restored during a 155 * list of controller registers to be saved and restored during a
119 * suspend/resume cycle. 156 * suspend/resume cycle.
120 */ 157 */
121static unsigned long exynos5420_clk_regs[] __initdata = { 158static unsigned long exynos5x_clk_regs[] __initdata = {
122 SRC_CPU, 159 SRC_CPU,
123 DIV_CPU0, 160 DIV_CPU0,
124 DIV_CPU1, 161 DIV_CPU1,
125 GATE_BUS_CPU, 162 GATE_BUS_CPU,
126 GATE_SCLK_CPU, 163 GATE_SCLK_CPU,
164 CLKOUT_CMU_CPU,
165 EPLL_CON0,
166 EPLL_CON1,
167 EPLL_CON2,
168 RPLL_CON0,
169 RPLL_CON1,
170 RPLL_CON2,
127 SRC_TOP0, 171 SRC_TOP0,
128 SRC_TOP1, 172 SRC_TOP1,
129 SRC_TOP2, 173 SRC_TOP2,
@@ -140,10 +184,13 @@ static unsigned long exynos5420_clk_regs[] __initdata = {
140 SRC_TOP10, 184 SRC_TOP10,
141 SRC_TOP11, 185 SRC_TOP11,
142 SRC_TOP12, 186 SRC_TOP12,
187 SRC_MASK_TOP2,
188 SRC_MASK_TOP7,
143 SRC_MASK_DISP10, 189 SRC_MASK_DISP10,
144 SRC_MASK_FSYS, 190 SRC_MASK_FSYS,
145 SRC_MASK_PERIC0, 191 SRC_MASK_PERIC0,
146 SRC_MASK_PERIC1, 192 SRC_MASK_PERIC1,
193 SRC_ISP,
147 DIV_TOP0, 194 DIV_TOP0,
148 DIV_TOP1, 195 DIV_TOP1,
149 DIV_TOP2, 196 DIV_TOP2,
@@ -157,41 +204,71 @@ static unsigned long exynos5420_clk_regs[] __initdata = {
157 DIV_PERIC2, 204 DIV_PERIC2,
158 DIV_PERIC3, 205 DIV_PERIC3,
159 DIV_PERIC4, 206 DIV_PERIC4,
207 SCLK_DIV_ISP0,
208 SCLK_DIV_ISP1,
209 DIV2_RATIO0,
210 DIV4_RATIO,
160 GATE_BUS_TOP, 211 GATE_BUS_TOP,
212 GATE_BUS_GEN,
161 GATE_BUS_FSYS0, 213 GATE_BUS_FSYS0,
214 GATE_BUS_FSYS2,
162 GATE_BUS_PERIC, 215 GATE_BUS_PERIC,
163 GATE_BUS_PERIC1, 216 GATE_BUS_PERIC1,
164 GATE_BUS_PERIS0, 217 GATE_BUS_PERIS0,
165 GATE_BUS_PERIS1, 218 GATE_BUS_PERIS1,
219 GATE_BUS_NOC,
220 GATE_TOP_SCLK_ISP,
166 GATE_IP_GSCL0, 221 GATE_IP_GSCL0,
167 GATE_IP_GSCL1, 222 GATE_IP_GSCL1,
168 GATE_IP_MFC, 223 GATE_IP_MFC,
169 GATE_IP_DISP1, 224 GATE_IP_DISP1,
170 GATE_IP_G3D, 225 GATE_IP_G3D,
171 GATE_IP_GEN, 226 GATE_IP_GEN,
227 GATE_IP_FSYS,
228 GATE_IP_PERIC,
229 GATE_IP_PERIS,
172 GATE_IP_MSCL, 230 GATE_IP_MSCL,
173 GATE_TOP_SCLK_GSCL, 231 GATE_TOP_SCLK_GSCL,
174 GATE_TOP_SCLK_DISP1, 232 GATE_TOP_SCLK_DISP1,
175 GATE_TOP_SCLK_MAU, 233 GATE_TOP_SCLK_MAU,
176 GATE_TOP_SCLK_FSYS, 234 GATE_TOP_SCLK_FSYS,
177 GATE_TOP_SCLK_PERIC, 235 GATE_TOP_SCLK_PERIC,
178 SRC_CDREX, 236 TOP_SPARE2,
179 SRC_KFC, 237 SRC_KFC,
180 DIV_KFC0, 238 DIV_KFC0,
181}; 239};
182 240
241static unsigned long exynos5800_clk_regs[] __initdata = {
242 SRC_TOP8,
243 SRC_TOP9,
244 SRC_CAM,
245 SRC_TOP1,
246 DIV_TOP8,
247 DIV_TOP9,
248 DIV_CAM,
249 GATE_IP_CAM,
250};
251
183static int exynos5420_clk_suspend(void) 252static int exynos5420_clk_suspend(void)
184{ 253{
185 samsung_clk_save(reg_base, exynos5420_save, 254 samsung_clk_save(reg_base, exynos5x_save,
186 ARRAY_SIZE(exynos5420_clk_regs)); 255 ARRAY_SIZE(exynos5x_clk_regs));
256
257 if (exynos5x_soc == EXYNOS5800)
258 samsung_clk_save(reg_base, exynos5800_save,
259 ARRAY_SIZE(exynos5800_clk_regs));
187 260
188 return 0; 261 return 0;
189} 262}
190 263
191static void exynos5420_clk_resume(void) 264static void exynos5420_clk_resume(void)
192{ 265{
193 samsung_clk_restore(reg_base, exynos5420_save, 266 samsung_clk_restore(reg_base, exynos5x_save,
194 ARRAY_SIZE(exynos5420_clk_regs)); 267 ARRAY_SIZE(exynos5x_clk_regs));
268
269 if (exynos5x_soc == EXYNOS5800)
270 samsung_clk_restore(reg_base, exynos5800_save,
271 ARRAY_SIZE(exynos5800_clk_regs));
195} 272}
196 273
197static struct syscore_ops exynos5420_clk_syscore_ops = { 274static struct syscore_ops exynos5420_clk_syscore_ops = {
@@ -201,108 +278,183 @@ static struct syscore_ops exynos5420_clk_syscore_ops = {
201 278
202static void exynos5420_clk_sleep_init(void) 279static void exynos5420_clk_sleep_init(void)
203{ 280{
204 exynos5420_save = samsung_clk_alloc_reg_dump(exynos5420_clk_regs, 281 exynos5x_save = samsung_clk_alloc_reg_dump(exynos5x_clk_regs,
205 ARRAY_SIZE(exynos5420_clk_regs)); 282 ARRAY_SIZE(exynos5x_clk_regs));
206 if (!exynos5420_save) { 283 if (!exynos5x_save) {
207 pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", 284 pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
208 __func__); 285 __func__);
209 return; 286 return;
210 } 287 }
211 288
289 if (exynos5x_soc == EXYNOS5800) {
290 exynos5800_save =
291 samsung_clk_alloc_reg_dump(exynos5800_clk_regs,
292 ARRAY_SIZE(exynos5800_clk_regs));
293 if (!exynos5800_save)
294 goto err_soc;
295 }
296
212 register_syscore_ops(&exynos5420_clk_syscore_ops); 297 register_syscore_ops(&exynos5420_clk_syscore_ops);
298 return;
299err_soc:
300 kfree(exynos5x_save);
301 pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
302 __func__);
303 return;
213} 304}
214#else 305#else
215static void exynos5420_clk_sleep_init(void) {} 306static void exynos5420_clk_sleep_init(void) {}
216#endif 307#endif
217 308
218/* list of all parent clocks */ 309/* list of all parent clocks */
219PNAME(mspll_cpu_p) = { "sclk_cpll", "sclk_dpll", 310PNAME(mout_mspll_cpu_p) = {"mout_sclk_cpll", "mout_sclk_dpll",
220 "sclk_mpll", "sclk_spll" }; 311 "mout_sclk_mpll", "mout_sclk_spll"};
221PNAME(cpu_p) = { "mout_apll" , "mout_mspll_cpu" }; 312PNAME(mout_cpu_p) = {"mout_apll" , "mout_mspll_cpu"};
222PNAME(kfc_p) = { "mout_kpll" , "mout_mspll_kfc" }; 313PNAME(mout_kfc_p) = {"mout_kpll" , "mout_mspll_kfc"};
223PNAME(apll_p) = { "fin_pll", "fout_apll", }; 314PNAME(mout_apll_p) = {"fin_pll", "fout_apll"};
224PNAME(bpll_p) = { "fin_pll", "fout_bpll", }; 315PNAME(mout_bpll_p) = {"fin_pll", "fout_bpll"};
225PNAME(cpll_p) = { "fin_pll", "fout_cpll", }; 316PNAME(mout_cpll_p) = {"fin_pll", "fout_cpll"};
226PNAME(dpll_p) = { "fin_pll", "fout_dpll", }; 317PNAME(mout_dpll_p) = {"fin_pll", "fout_dpll"};
227PNAME(epll_p) = { "fin_pll", "fout_epll", }; 318PNAME(mout_epll_p) = {"fin_pll", "fout_epll"};
228PNAME(ipll_p) = { "fin_pll", "fout_ipll", }; 319PNAME(mout_ipll_p) = {"fin_pll", "fout_ipll"};
229PNAME(kpll_p) = { "fin_pll", "fout_kpll", }; 320PNAME(mout_kpll_p) = {"fin_pll", "fout_kpll"};
230PNAME(mpll_p) = { "fin_pll", "fout_mpll", }; 321PNAME(mout_mpll_p) = {"fin_pll", "fout_mpll"};
231PNAME(rpll_p) = { "fin_pll", "fout_rpll", }; 322PNAME(mout_rpll_p) = {"fin_pll", "fout_rpll"};
232PNAME(spll_p) = { "fin_pll", "fout_spll", }; 323PNAME(mout_spll_p) = {"fin_pll", "fout_spll"};
233PNAME(vpll_p) = { "fin_pll", "fout_vpll", }; 324PNAME(mout_vpll_p) = {"fin_pll", "fout_vpll"};
234 325
235PNAME(group1_p) = { "sclk_cpll", "sclk_dpll", "sclk_mpll" }; 326PNAME(mout_group1_p) = {"mout_sclk_cpll", "mout_sclk_dpll",
236PNAME(group2_p) = { "fin_pll", "sclk_cpll", "sclk_dpll", "sclk_mpll", 327 "mout_sclk_mpll"};
237 "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; 328PNAME(mout_group2_p) = {"fin_pll", "mout_sclk_cpll",
238PNAME(group3_p) = { "sclk_rpll", "sclk_spll" }; 329 "mout_sclk_dpll", "mout_sclk_mpll", "mout_sclk_spll",
239PNAME(group4_p) = { "sclk_ipll", "sclk_dpll", "sclk_mpll" }; 330 "mout_sclk_ipll", "mout_sclk_epll", "mout_sclk_rpll"};
240PNAME(group5_p) = { "sclk_vpll", "sclk_dpll" }; 331PNAME(mout_group3_p) = {"mout_sclk_rpll", "mout_sclk_spll"};
241 332PNAME(mout_group4_p) = {"mout_sclk_ipll", "mout_sclk_dpll", "mout_sclk_mpll"};
242PNAME(sw_aclk66_p) = { "dout_aclk66", "sclk_spll" }; 333PNAME(mout_group5_p) = {"mout_sclk_vpll", "mout_sclk_dpll"};
243PNAME(aclk66_peric_p) = { "fin_pll", "mout_sw_aclk66" }; 334
244 335PNAME(mout_fimd1_final_p) = {"mout_fimd1", "mout_fimd1_opt"};
245PNAME(sw_aclk200_fsys_p) = { "dout_aclk200_fsys", "sclk_spll"}; 336PNAME(mout_sw_aclk66_p) = {"dout_aclk66", "mout_sclk_spll"};
246PNAME(user_aclk200_fsys_p) = { "fin_pll", "mout_sw_aclk200_fsys" }; 337PNAME(mout_user_aclk66_peric_p) = { "fin_pll", "mout_sw_aclk66"};
247 338PNAME(mout_user_pclk66_gpio_p) = {"mout_sw_aclk66", "ff_sw_aclk66"};
248PNAME(sw_aclk200_fsys2_p) = { "dout_aclk200_fsys2", "sclk_spll"}; 339
249PNAME(user_aclk200_fsys2_p) = { "fin_pll", "mout_sw_aclk200_fsys2" }; 340PNAME(mout_sw_aclk200_fsys_p) = {"dout_aclk200_fsys", "mout_sclk_spll"};
250 341PNAME(mout_sw_pclk200_fsys_p) = {"dout_pclk200_fsys", "mout_sclk_spll"};
251PNAME(sw_aclk200_p) = { "dout_aclk200", "sclk_spll"}; 342PNAME(mout_user_pclk200_fsys_p) = {"fin_pll", "mout_sw_pclk200_fsys"};
252PNAME(aclk200_disp1_p) = { "fin_pll", "mout_sw_aclk200" }; 343PNAME(mout_user_aclk200_fsys_p) = {"fin_pll", "mout_sw_aclk200_fsys"};
253 344
254PNAME(sw_aclk400_mscl_p) = { "dout_aclk400_mscl", "sclk_spll"}; 345PNAME(mout_sw_aclk200_fsys2_p) = {"dout_aclk200_fsys2", "mout_sclk_spll"};
255PNAME(user_aclk400_mscl_p) = { "fin_pll", "mout_sw_aclk400_mscl" }; 346PNAME(mout_user_aclk200_fsys2_p) = {"fin_pll", "mout_sw_aclk200_fsys2"};
256 347PNAME(mout_sw_aclk100_noc_p) = {"dout_aclk100_noc", "mout_sclk_spll"};
257PNAME(sw_aclk333_p) = { "dout_aclk333", "sclk_spll"}; 348PNAME(mout_user_aclk100_noc_p) = {"fin_pll", "mout_sw_aclk100_noc"};
258PNAME(user_aclk333_p) = { "fin_pll", "mout_sw_aclk333" }; 349
259 350PNAME(mout_sw_aclk400_wcore_p) = {"dout_aclk400_wcore", "mout_sclk_spll"};
260PNAME(sw_aclk166_p) = { "dout_aclk166", "sclk_spll"}; 351PNAME(mout_aclk400_wcore_bpll_p) = {"mout_aclk400_wcore", "sclk_bpll"};
261PNAME(user_aclk166_p) = { "fin_pll", "mout_sw_aclk166" }; 352PNAME(mout_user_aclk400_wcore_p) = {"fin_pll", "mout_sw_aclk400_wcore"};
262 353
263PNAME(sw_aclk266_p) = { "dout_aclk266", "sclk_spll"}; 354PNAME(mout_sw_aclk400_isp_p) = {"dout_aclk400_isp", "mout_sclk_spll"};
264PNAME(user_aclk266_p) = { "fin_pll", "mout_sw_aclk266" }; 355PNAME(mout_user_aclk400_isp_p) = {"fin_pll", "mout_sw_aclk400_isp"};
265 356
266PNAME(sw_aclk333_432_gscl_p) = { "dout_aclk333_432_gscl", "sclk_spll"}; 357PNAME(mout_sw_aclk333_432_isp0_p) = {"dout_aclk333_432_isp0",
267PNAME(user_aclk333_432_gscl_p) = { "fin_pll", "mout_sw_aclk333_432_gscl" }; 358 "mout_sclk_spll"};
268 359PNAME(mout_user_aclk333_432_isp0_p) = {"fin_pll", "mout_sw_aclk333_432_isp0"};
269PNAME(sw_aclk300_gscl_p) = { "dout_aclk300_gscl", "sclk_spll"}; 360
270PNAME(user_aclk300_gscl_p) = { "fin_pll", "mout_sw_aclk300_gscl" }; 361PNAME(mout_sw_aclk333_432_isp_p) = {"dout_aclk333_432_isp", "mout_sclk_spll"};
271 362PNAME(mout_user_aclk333_432_isp_p) = {"fin_pll", "mout_sw_aclk333_432_isp"};
272PNAME(sw_aclk300_disp1_p) = { "dout_aclk300_disp1", "sclk_spll"}; 363
273PNAME(user_aclk300_disp1_p) = { "fin_pll", "mout_sw_aclk300_disp1" }; 364PNAME(mout_sw_aclk200_p) = {"dout_aclk200", "mout_sclk_spll"};
274 365PNAME(mout_user_aclk200_disp1_p) = {"fin_pll", "mout_sw_aclk200"};
275PNAME(sw_aclk300_jpeg_p) = { "dout_aclk300_jpeg", "sclk_spll"}; 366
276PNAME(user_aclk300_jpeg_p) = { "fin_pll", "mout_sw_aclk300_jpeg" }; 367PNAME(mout_sw_aclk400_mscl_p) = {"dout_aclk400_mscl", "mout_sclk_spll"};
277 368PNAME(mout_user_aclk400_mscl_p) = {"fin_pll", "mout_sw_aclk400_mscl"};
278PNAME(sw_aclk_g3d_p) = { "dout_aclk_g3d", "sclk_spll"}; 369
279PNAME(user_aclk_g3d_p) = { "fin_pll", "mout_sw_aclk_g3d" }; 370PNAME(mout_sw_aclk333_p) = {"dout_aclk333", "mout_sclk_spll"};
280 371PNAME(mout_user_aclk333_p) = {"fin_pll", "mout_sw_aclk333"};
281PNAME(sw_aclk266_g2d_p) = { "dout_aclk266_g2d", "sclk_spll"}; 372
282PNAME(user_aclk266_g2d_p) = { "fin_pll", "mout_sw_aclk266_g2d" }; 373PNAME(mout_sw_aclk166_p) = {"dout_aclk166", "mout_sclk_spll"};
283 374PNAME(mout_user_aclk166_p) = {"fin_pll", "mout_sw_aclk166"};
284PNAME(sw_aclk333_g2d_p) = { "dout_aclk333_g2d", "sclk_spll"}; 375
285PNAME(user_aclk333_g2d_p) = { "fin_pll", "mout_sw_aclk333_g2d" }; 376PNAME(mout_sw_aclk266_p) = {"dout_aclk266", "mout_sclk_spll"};
286 377PNAME(mout_user_aclk266_p) = {"fin_pll", "mout_sw_aclk266"};
287PNAME(audio0_p) = { "fin_pll", "cdclk0", "sclk_dpll", "sclk_mpll", 378PNAME(mout_user_aclk266_isp_p) = {"fin_pll", "mout_sw_aclk266"};
288 "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; 379
289PNAME(audio1_p) = { "fin_pll", "cdclk1", "sclk_dpll", "sclk_mpll", 380PNAME(mout_sw_aclk333_432_gscl_p) = {"dout_aclk333_432_gscl", "mout_sclk_spll"};
290 "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; 381PNAME(mout_user_aclk333_432_gscl_p) = {"fin_pll", "mout_sw_aclk333_432_gscl"};
291PNAME(audio2_p) = { "fin_pll", "cdclk2", "sclk_dpll", "sclk_mpll", 382
292 "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; 383PNAME(mout_sw_aclk300_gscl_p) = {"dout_aclk300_gscl", "mout_sclk_spll"};
293PNAME(spdif_p) = { "fin_pll", "dout_audio0", "dout_audio1", "dout_audio2", 384PNAME(mout_user_aclk300_gscl_p) = {"fin_pll", "mout_sw_aclk300_gscl"};
294 "spdif_extclk", "sclk_ipll", "sclk_epll", "sclk_rpll" }; 385
295PNAME(hdmi_p) = { "dout_hdmi_pixel", "sclk_hdmiphy" }; 386PNAME(mout_sw_aclk300_disp1_p) = {"dout_aclk300_disp1", "mout_sclk_spll"};
296PNAME(maudio0_p) = { "fin_pll", "maudio_clk", "sclk_dpll", "sclk_mpll", 387PNAME(mout_sw_aclk400_disp1_p) = {"dout_aclk400_disp1", "mout_sclk_spll"};
297 "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; 388PNAME(mout_user_aclk300_disp1_p) = {"fin_pll", "mout_sw_aclk300_disp1"};
389PNAME(mout_user_aclk400_disp1_p) = {"fin_pll", "mout_sw_aclk400_disp1"};
390
391PNAME(mout_sw_aclk300_jpeg_p) = {"dout_aclk300_jpeg", "mout_sclk_spll"};
392PNAME(mout_user_aclk300_jpeg_p) = {"fin_pll", "mout_sw_aclk300_jpeg"};
393
394PNAME(mout_sw_aclk_g3d_p) = {"dout_aclk_g3d", "mout_sclk_spll"};
395PNAME(mout_user_aclk_g3d_p) = {"fin_pll", "mout_sw_aclk_g3d"};
396
397PNAME(mout_sw_aclk266_g2d_p) = {"dout_aclk266_g2d", "mout_sclk_spll"};
398PNAME(mout_user_aclk266_g2d_p) = {"fin_pll", "mout_sw_aclk266_g2d"};
399
400PNAME(mout_sw_aclk333_g2d_p) = {"dout_aclk333_g2d", "mout_sclk_spll"};
401PNAME(mout_user_aclk333_g2d_p) = {"fin_pll", "mout_sw_aclk333_g2d"};
402
403PNAME(mout_audio0_p) = {"fin_pll", "cdclk0", "mout_sclk_dpll",
404 "mout_sclk_mpll", "mout_sclk_spll", "mout_sclk_ipll",
405 "mout_sclk_epll", "mout_sclk_rpll"};
406PNAME(mout_audio1_p) = {"fin_pll", "cdclk1", "mout_sclk_dpll",
407 "mout_sclk_mpll", "mout_sclk_spll", "mout_sclk_ipll",
408 "mout_sclk_epll", "mout_sclk_rpll"};
409PNAME(mout_audio2_p) = {"fin_pll", "cdclk2", "mout_sclk_dpll",
410 "mout_sclk_mpll", "mout_sclk_spll", "mout_sclk_ipll",
411 "mout_sclk_epll", "mout_sclk_rpll"};
412PNAME(mout_spdif_p) = {"fin_pll", "dout_audio0", "dout_audio1",
413 "dout_audio2", "spdif_extclk", "mout_sclk_ipll",
414 "mout_sclk_epll", "mout_sclk_rpll"};
415PNAME(mout_hdmi_p) = {"dout_hdmi_pixel", "sclk_hdmiphy"};
416PNAME(mout_maudio0_p) = {"fin_pll", "maudio_clk", "mout_sclk_dpll",
417 "mout_sclk_mpll", "mout_sclk_spll", "mout_sclk_ipll",
418 "mout_sclk_epll", "mout_sclk_rpll"};
419PNAME(mout_mau_epll_clk_p) = {"mout_sclk_epll", "mout_sclk_dpll",
420 "mout_sclk_mpll", "mout_sclk_spll"};
421/* List of parents specific to exynos5800 */
422PNAME(mout_epll2_5800_p) = { "mout_sclk_epll", "ff_dout_epll2" };
423PNAME(mout_group1_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll",
424 "mout_sclk_mpll", "ff_dout_spll2" };
425PNAME(mout_group2_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll",
426 "mout_sclk_mpll", "ff_dout_spll2",
427 "mout_epll2", "mout_sclk_ipll" };
428PNAME(mout_group3_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll",
429 "mout_sclk_mpll", "ff_dout_spll2",
430 "mout_epll2" };
431PNAME(mout_group5_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll",
432 "mout_sclk_mpll", "mout_sclk_spll" };
433PNAME(mout_group6_5800_p) = { "mout_sclk_ipll", "mout_sclk_dpll",
434 "mout_sclk_mpll", "ff_dout_spll2" };
435PNAME(mout_group7_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll",
436 "mout_sclk_mpll", "mout_sclk_spll",
437 "mout_epll2", "mout_sclk_ipll" };
438PNAME(mout_mau_epll_clk_5800_p) = { "mout_sclk_epll", "mout_sclk_dpll",
439 "mout_sclk_mpll",
440 "ff_dout_spll2" };
441PNAME(mout_group8_5800_p) = { "dout_aclk432_scaler", "dout_sclk_sw" };
442PNAME(mout_group9_5800_p) = { "dout_osc_div", "mout_sw_aclk432_scaler" };
443PNAME(mout_group10_5800_p) = { "dout_aclk432_cam", "dout_sclk_sw" };
444PNAME(mout_group11_5800_p) = { "dout_osc_div", "mout_sw_aclk432_cam" };
445PNAME(mout_group12_5800_p) = { "dout_aclkfl1_550_cam", "dout_sclk_sw" };
446PNAME(mout_group13_5800_p) = { "dout_osc_div", "mout_sw_aclkfl1_550_cam" };
447PNAME(mout_group14_5800_p) = { "dout_aclk550_cam", "dout_sclk_sw" };
448PNAME(mout_group15_5800_p) = { "dout_osc_div", "mout_sw_aclk550_cam" };
298 449
299/* fixed rate clocks generated outside the soc */ 450/* fixed rate clocks generated outside the soc */
300static struct samsung_fixed_rate_clock exynos5420_fixed_rate_ext_clks[] __initdata = { 451static struct samsung_fixed_rate_clock
452 exynos5x_fixed_rate_ext_clks[] __initdata = {
301 FRATE(CLK_FIN_PLL, "fin_pll", NULL, CLK_IS_ROOT, 0), 453 FRATE(CLK_FIN_PLL, "fin_pll", NULL, CLK_IS_ROOT, 0),
302}; 454};
303 455
304/* fixed rate clocks generated inside the soc */ 456/* fixed rate clocks generated inside the soc */
305static struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = { 457static struct samsung_fixed_rate_clock exynos5x_fixed_rate_clks[] __initdata = {
306 FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000), 458 FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
307 FRATE(0, "sclk_pwi", NULL, CLK_IS_ROOT, 24000000), 459 FRATE(0, "sclk_pwi", NULL, CLK_IS_ROOT, 24000000),
308 FRATE(0, "sclk_usbh20", NULL, CLK_IS_ROOT, 48000000), 460 FRATE(0, "sclk_usbh20", NULL, CLK_IS_ROOT, 48000000),
@@ -310,146 +462,309 @@ static struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata =
310 FRATE(0, "sclk_usbh20_scan_clk", NULL, CLK_IS_ROOT, 480000000), 462 FRATE(0, "sclk_usbh20_scan_clk", NULL, CLK_IS_ROOT, 480000000),
311}; 463};
312 464
313static struct samsung_fixed_factor_clock exynos5420_fixed_factor_clks[] __initdata = { 465static struct samsung_fixed_factor_clock
314 FFACTOR(0, "sclk_hsic_12m", "fin_pll", 1, 2, 0), 466 exynos5x_fixed_factor_clks[] __initdata = {
467 FFACTOR(0, "ff_hsic_12m", "fin_pll", 1, 2, 0),
468 FFACTOR(0, "ff_sw_aclk66", "mout_sw_aclk66", 1, 2, 0),
315}; 469};
316 470
317static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { 471static struct samsung_fixed_factor_clock
318 MUX(0, "mout_mspll_kfc", mspll_cpu_p, SRC_TOP7, 8, 2), 472 exynos5800_fixed_factor_clks[] __initdata = {
319 MUX(0, "mout_mspll_cpu", mspll_cpu_p, SRC_TOP7, 12, 2), 473 FFACTOR(0, "ff_dout_epll2", "mout_sclk_epll", 1, 2, 0),
320 MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1), 474 FFACTOR(0, "ff_dout_spll2", "mout_sclk_spll", 1, 2, 0),
321 MUX(0, "mout_cpu", cpu_p, SRC_CPU, 16, 1), 475};
322 MUX(0, "mout_kpll", kpll_p, SRC_KFC, 0, 1), 476
323 MUX(0, "mout_cpu_kfc", kfc_p, SRC_KFC, 16, 1), 477struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
324 478 MUX(0, "mout_aclk400_isp", mout_group3_5800_p, SRC_TOP0, 0, 3),
325 MUX(0, "sclk_bpll", bpll_p, SRC_CDREX, 0, 1), 479 MUX(0, "mout_aclk400_mscl", mout_group3_5800_p, SRC_TOP0, 4, 3),
326 480 MUX(0, "mout_aclk400_wcore", mout_group2_5800_p, SRC_TOP0, 16, 3),
327 MUX_A(0, "mout_aclk400_mscl", group1_p, 481 MUX(0, "mout_aclk100_noc", mout_group1_5800_p, SRC_TOP0, 20, 2),
328 SRC_TOP0, 4, 2, "aclk400_mscl"), 482
329 MUX(0, "mout_aclk200", group1_p, SRC_TOP0, 8, 2), 483 MUX(0, "mout_aclk333_432_gscl", mout_group6_5800_p, SRC_TOP1, 0, 2),
330 MUX(0, "mout_aclk200_fsys2", group1_p, SRC_TOP0, 12, 2), 484 MUX(0, "mout_aclk333_432_isp", mout_group6_5800_p, SRC_TOP1, 4, 2),
331 MUX(0, "mout_aclk200_fsys", group1_p, SRC_TOP0, 28, 2), 485 MUX(0, "mout_aclk333_432_isp0", mout_group6_5800_p, SRC_TOP1, 12, 2),
332 486 MUX(0, "mout_aclk266", mout_group5_5800_p, SRC_TOP1, 20, 2),
333 MUX(0, "mout_aclk333_432_gscl", group4_p, SRC_TOP1, 0, 2), 487 MUX(0, "mout_aclk333", mout_group1_5800_p, SRC_TOP1, 28, 2),
334 MUX(0, "mout_aclk66", group1_p, SRC_TOP1, 8, 2), 488
335 MUX(0, "mout_aclk266", group1_p, SRC_TOP1, 20, 2), 489 MUX(0, "mout_aclk400_disp1", mout_group7_5800_p, SRC_TOP2, 4, 3),
336 MUX(0, "mout_aclk166", group1_p, SRC_TOP1, 24, 2), 490 MUX(0, "mout_aclk333_g2d", mout_group5_5800_p, SRC_TOP2, 8, 2),
337 MUX(0, "mout_aclk333", group1_p, SRC_TOP1, 28, 2), 491 MUX(0, "mout_aclk266_g2d", mout_group5_5800_p, SRC_TOP2, 12, 2),
338 492 MUX(0, "mout_aclk300_jpeg", mout_group5_5800_p, SRC_TOP2, 20, 2),
339 MUX(0, "mout_aclk333_g2d", group1_p, SRC_TOP2, 8, 2), 493 MUX(0, "mout_aclk300_disp1", mout_group5_5800_p, SRC_TOP2, 24, 2),
340 MUX(0, "mout_aclk266_g2d", group1_p, SRC_TOP2, 12, 2), 494 MUX(0, "mout_aclk300_gscl", mout_group5_5800_p, SRC_TOP2, 28, 2),
341 MUX(0, "mout_aclk_g3d", group5_p, SRC_TOP2, 16, 1), 495
342 MUX(0, "mout_aclk300_jpeg", group1_p, SRC_TOP2, 20, 2), 496 MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p, SRC_TOP7,
343 MUX(0, "mout_aclk300_disp1", group1_p, SRC_TOP2, 24, 2), 497 20, 2),
344 MUX(0, "mout_aclk300_gscl", group1_p, SRC_TOP2, 28, 2), 498 MUX(0, "sclk_bpll", mout_bpll_p, SRC_TOP7, 24, 1),
345 499 MUX(0, "mout_epll2", mout_epll2_5800_p, SRC_TOP7, 28, 1),
346 MUX(0, "mout_user_aclk400_mscl", user_aclk400_mscl_p, 500
501 MUX(0, "mout_aclk550_cam", mout_group3_5800_p, SRC_TOP8, 16, 3),
502 MUX(0, "mout_aclkfl1_550_cam", mout_group3_5800_p, SRC_TOP8, 20, 3),
503 MUX(0, "mout_aclk432_cam", mout_group6_5800_p, SRC_TOP8, 24, 2),
504 MUX(0, "mout_aclk432_scaler", mout_group6_5800_p, SRC_TOP8, 28, 2),
505
506 MUX(0, "mout_user_aclk550_cam", mout_group15_5800_p,
507 SRC_TOP9, 16, 1),
508 MUX(0, "mout_user_aclkfl1_550_cam", mout_group13_5800_p,
509 SRC_TOP9, 20, 1),
510 MUX(0, "mout_user_aclk432_cam", mout_group11_5800_p,
511 SRC_TOP9, 24, 1),
512 MUX(0, "mout_user_aclk432_scaler", mout_group9_5800_p,
513 SRC_TOP9, 28, 1),
514
515 MUX(0, "mout_sw_aclk550_cam", mout_group14_5800_p, SRC_TOP13, 16, 1),
516 MUX(0, "mout_sw_aclkfl1_550_cam", mout_group12_5800_p,
517 SRC_TOP13, 20, 1),
518 MUX(0, "mout_sw_aclk432_cam", mout_group10_5800_p,
519 SRC_TOP13, 24, 1),
520 MUX(0, "mout_sw_aclk432_scaler", mout_group8_5800_p,
521 SRC_TOP13, 28, 1),
522
523 MUX(0, "mout_fimd1", mout_group2_p, SRC_DISP10, 4, 3),
524};
525
526struct samsung_div_clock exynos5800_div_clks[] __initdata = {
527 DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore", DIV_TOP0, 16, 3),
528
529 DIV(0, "dout_aclk550_cam", "mout_aclk550_cam",
530 DIV_TOP8, 16, 3),
531 DIV(0, "dout_aclkfl1_550_cam", "mout_aclkfl1_550_cam",
532 DIV_TOP8, 20, 3),
533 DIV(0, "dout_aclk432_cam", "mout_aclk432_cam",
534 DIV_TOP8, 24, 3),
535 DIV(0, "dout_aclk432_scaler", "mout_aclk432_scaler",
536 DIV_TOP8, 28, 3),
537
538 DIV(0, "dout_osc_div", "fin_pll", DIV_TOP9, 20, 3),
539 DIV(0, "dout_sclk_sw", "sclk_spll", DIV_TOP9, 24, 6),
540};
541
542struct samsung_gate_clock exynos5800_gate_clks[] __initdata = {
543 GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam",
544 GATE_BUS_TOP, 24, 0, 0),
545 GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
546 GATE_BUS_TOP, 27, 0, 0),
547};
548
549struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
550 MUX(0, "sclk_bpll", mout_bpll_p, TOP_SPARE2, 0, 1),
551 MUX(0, "mout_aclk400_wcore_bpll", mout_aclk400_wcore_bpll_p,
552 TOP_SPARE2, 4, 1),
553
554 MUX(0, "mout_aclk400_isp", mout_group1_p, SRC_TOP0, 0, 2),
555 MUX_A(0, "mout_aclk400_mscl", mout_group1_p,
556 SRC_TOP0, 4, 2, "aclk400_mscl"),
557 MUX(0, "mout_aclk400_wcore", mout_group1_p, SRC_TOP0, 16, 2),
558 MUX(0, "mout_aclk100_noc", mout_group1_p, SRC_TOP0, 20, 2),
559
560 MUX(0, "mout_aclk333_432_gscl", mout_group4_p, SRC_TOP1, 0, 2),
561 MUX(0, "mout_aclk333_432_isp", mout_group4_p,
562 SRC_TOP1, 4, 2),
563 MUX(0, "mout_aclk333_432_isp0", mout_group4_p, SRC_TOP1, 12, 2),
564 MUX(0, "mout_aclk266", mout_group1_p, SRC_TOP1, 20, 2),
565 MUX(0, "mout_aclk333", mout_group1_p, SRC_TOP1, 28, 2),
566
567 MUX(0, "mout_aclk400_disp1", mout_group1_p, SRC_TOP2, 4, 2),
568 MUX(0, "mout_aclk333_g2d", mout_group1_p, SRC_TOP2, 8, 2),
569 MUX(0, "mout_aclk266_g2d", mout_group1_p, SRC_TOP2, 12, 2),
570 MUX(0, "mout_aclk300_jpeg", mout_group1_p, SRC_TOP2, 20, 2),
571 MUX(0, "mout_aclk300_disp1", mout_group1_p, SRC_TOP2, 24, 2),
572 MUX(0, "mout_aclk300_gscl", mout_group1_p, SRC_TOP2, 28, 2),
573
574 MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_p, SRC_TOP7, 20, 2),
575
576 MUX(0, "mout_fimd1", mout_group3_p, SRC_DISP10, 4, 1),
577};
578
579struct samsung_div_clock exynos5420_div_clks[] __initdata = {
580 DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore_bpll",
581 DIV_TOP0, 16, 3),
582};
583
584static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
585 MUX(0, "mout_user_pclk66_gpio", mout_user_pclk66_gpio_p,
586 SRC_TOP7, 4, 1),
587 MUX(0, "mout_mspll_kfc", mout_mspll_cpu_p, SRC_TOP7, 8, 2),
588 MUX(0, "mout_mspll_cpu", mout_mspll_cpu_p, SRC_TOP7, 12, 2),
589
590 MUX(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1),
591 MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
592 MUX(0, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1),
593 MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1),
594
595 MUX(0, "mout_aclk200", mout_group1_p, SRC_TOP0, 8, 2),
596 MUX(0, "mout_aclk200_fsys2", mout_group1_p, SRC_TOP0, 12, 2),
597 MUX(0, "mout_pclk200_fsys", mout_group1_p, SRC_TOP0, 24, 2),
598 MUX(0, "mout_aclk200_fsys", mout_group1_p, SRC_TOP0, 28, 2),
599
600 MUX(0, "mout_aclk66", mout_group1_p, SRC_TOP1, 8, 2),
601 MUX(0, "mout_aclk166", mout_group1_p, SRC_TOP1, 24, 2),
602
603 MUX(0, "mout_aclk_g3d", mout_group5_p, SRC_TOP2, 16, 1),
604
605 MUX(0, "mout_user_aclk400_isp", mout_user_aclk400_isp_p,
606 SRC_TOP3, 0, 1),
607 MUX(0, "mout_user_aclk400_mscl", mout_user_aclk400_mscl_p,
347 SRC_TOP3, 4, 1), 608 SRC_TOP3, 4, 1),
348 MUX_A(0, "mout_aclk200_disp1", aclk200_disp1_p, 609 MUX(0, "mout_user_aclk200_disp1", mout_user_aclk200_disp1_p,
349 SRC_TOP3, 8, 1, "aclk200_disp1"), 610 SRC_TOP3, 8, 1),
350 MUX(0, "mout_user_aclk200_fsys2", user_aclk200_fsys2_p, 611 MUX(0, "mout_user_aclk200_fsys2", mout_user_aclk200_fsys2_p,
351 SRC_TOP3, 12, 1), 612 SRC_TOP3, 12, 1),
352 MUX(0, "mout_user_aclk200_fsys", user_aclk200_fsys_p, 613 MUX(0, "mout_user_aclk400_wcore", mout_user_aclk400_wcore_p,
614 SRC_TOP3, 16, 1),
615 MUX(0, "mout_user_aclk100_noc", mout_user_aclk100_noc_p,
616 SRC_TOP3, 20, 1),
617 MUX(0, "mout_user_pclk200_fsys", mout_user_pclk200_fsys_p,
618 SRC_TOP3, 24, 1),
619 MUX(0, "mout_user_aclk200_fsys", mout_user_aclk200_fsys_p,
353 SRC_TOP3, 28, 1), 620 SRC_TOP3, 28, 1),
354 621
355 MUX(0, "mout_user_aclk333_432_gscl", user_aclk333_432_gscl_p, 622 MUX(0, "mout_user_aclk333_432_gscl", mout_user_aclk333_432_gscl_p,
356 SRC_TOP4, 0, 1), 623 SRC_TOP4, 0, 1),
357 MUX(0, "mout_aclk66_peric", aclk66_peric_p, SRC_TOP4, 8, 1), 624 MUX(0, "mout_user_aclk333_432_isp", mout_user_aclk333_432_isp_p,
358 MUX(0, "mout_user_aclk266", user_aclk266_p, SRC_TOP4, 20, 1), 625 SRC_TOP4, 4, 1),
359 MUX(0, "mout_user_aclk166", user_aclk166_p, SRC_TOP4, 24, 1), 626 MUX(0, "mout_user_aclk66_peric", mout_user_aclk66_peric_p,
360 MUX(0, "mout_user_aclk333", user_aclk333_p, SRC_TOP4, 28, 1), 627 SRC_TOP4, 8, 1),
361 628 MUX(0, "mout_user_aclk333_432_isp0", mout_user_aclk333_432_isp0_p,
362 MUX(0, "mout_aclk66_psgen", aclk66_peric_p, SRC_TOP5, 4, 1), 629 SRC_TOP4, 12, 1),
363 MUX(0, "mout_user_aclk333_g2d", user_aclk333_g2d_p, SRC_TOP5, 8, 1), 630 MUX(0, "mout_user_aclk266_isp", mout_user_aclk266_isp_p,
364 MUX(0, "mout_user_aclk266_g2d", user_aclk266_g2d_p, SRC_TOP5, 12, 1), 631 SRC_TOP4, 16, 1),
365 MUX_A(0, "mout_user_aclk_g3d", user_aclk_g3d_p, 632 MUX(0, "mout_user_aclk266", mout_user_aclk266_p, SRC_TOP4, 20, 1),
366 SRC_TOP5, 16, 1, "aclkg3d"), 633 MUX(0, "mout_user_aclk166", mout_user_aclk166_p, SRC_TOP4, 24, 1),
367 MUX(0, "mout_user_aclk300_jpeg", user_aclk300_jpeg_p, 634 MUX(0, "mout_user_aclk333", mout_user_aclk333_p, SRC_TOP4, 28, 1),
635
636 MUX(0, "mout_user_aclk400_disp1", mout_user_aclk400_disp1_p,
637 SRC_TOP5, 0, 1),
638 MUX(0, "mout_user_aclk66_psgen", mout_user_aclk66_peric_p,
639 SRC_TOP5, 4, 1),
640 MUX(0, "mout_user_aclk333_g2d", mout_user_aclk333_g2d_p,
641 SRC_TOP5, 8, 1),
642 MUX(0, "mout_user_aclk266_g2d", mout_user_aclk266_g2d_p,
643 SRC_TOP5, 12, 1),
644 MUX(CLK_MOUT_G3D, "mout_user_aclk_g3d", mout_user_aclk_g3d_p,
645 SRC_TOP5, 16, 1),
646 MUX(0, "mout_user_aclk300_jpeg", mout_user_aclk300_jpeg_p,
368 SRC_TOP5, 20, 1), 647 SRC_TOP5, 20, 1),
369 MUX(0, "mout_user_aclk300_disp1", user_aclk300_disp1_p, 648 MUX(0, "mout_user_aclk300_disp1", mout_user_aclk300_disp1_p,
370 SRC_TOP5, 24, 1), 649 SRC_TOP5, 24, 1),
371 MUX(0, "mout_user_aclk300_gscl", user_aclk300_gscl_p, 650 MUX(0, "mout_user_aclk300_gscl", mout_user_aclk300_gscl_p,
372 SRC_TOP5, 28, 1), 651 SRC_TOP5, 28, 1),
373 652
374 MUX(0, "sclk_mpll", mpll_p, SRC_TOP6, 0, 1), 653 MUX(0, "mout_sclk_mpll", mout_mpll_p, SRC_TOP6, 0, 1),
375 MUX(0, "sclk_vpll", vpll_p, SRC_TOP6, 4, 1), 654 MUX(CLK_MOUT_VPLL, "mout_sclk_vpll", mout_vpll_p, SRC_TOP6, 4, 1),
376 MUX(0, "sclk_spll", spll_p, SRC_TOP6, 8, 1), 655 MUX(0, "mout_sclk_spll", mout_spll_p, SRC_TOP6, 8, 1),
377 MUX(0, "sclk_ipll", ipll_p, SRC_TOP6, 12, 1), 656 MUX(0, "mout_sclk_ipll", mout_ipll_p, SRC_TOP6, 12, 1),
378 MUX(0, "sclk_rpll", rpll_p, SRC_TOP6, 16, 1), 657 MUX(0, "mout_sclk_rpll", mout_rpll_p, SRC_TOP6, 16, 1),
379 MUX(0, "sclk_epll", epll_p, SRC_TOP6, 20, 1), 658 MUX(0, "mout_sclk_epll", mout_epll_p, SRC_TOP6, 20, 1),
380 MUX(0, "sclk_dpll", dpll_p, SRC_TOP6, 24, 1), 659 MUX(0, "mout_sclk_dpll", mout_dpll_p, SRC_TOP6, 24, 1),
381 MUX(0, "sclk_cpll", cpll_p, SRC_TOP6, 28, 1), 660 MUX(0, "mout_sclk_cpll", mout_cpll_p, SRC_TOP6, 28, 1),
382 661
383 MUX(0, "mout_sw_aclk400_mscl", sw_aclk400_mscl_p, SRC_TOP10, 4, 1), 662 MUX(0, "mout_sw_aclk400_isp", mout_sw_aclk400_isp_p,
384 MUX(0, "mout_sw_aclk200", sw_aclk200_p, SRC_TOP10, 8, 1), 663 SRC_TOP10, 0, 1),
385 MUX(0, "mout_sw_aclk200_fsys2", sw_aclk200_fsys2_p, 664 MUX(0, "mout_sw_aclk400_mscl", mout_sw_aclk400_mscl_p,
665 SRC_TOP10, 4, 1),
666 MUX(0, "mout_sw_aclk200", mout_sw_aclk200_p, SRC_TOP10, 8, 1),
667 MUX(0, "mout_sw_aclk200_fsys2", mout_sw_aclk200_fsys2_p,
386 SRC_TOP10, 12, 1), 668 SRC_TOP10, 12, 1),
387 MUX(0, "mout_sw_aclk200_fsys", sw_aclk200_fsys_p, SRC_TOP10, 28, 1), 669 MUX(0, "mout_sw_aclk400_wcore", mout_sw_aclk400_wcore_p,
388 670 SRC_TOP10, 16, 1),
389 MUX(0, "mout_sw_aclk333_432_gscl", sw_aclk333_432_gscl_p, 671 MUX(0, "mout_sw_aclk100_noc", mout_sw_aclk100_noc_p,
672 SRC_TOP10, 20, 1),
673 MUX(0, "mout_sw_pclk200_fsys", mout_sw_pclk200_fsys_p,
674 SRC_TOP10, 24, 1),
675 MUX(0, "mout_sw_aclk200_fsys", mout_sw_aclk200_fsys_p,
676 SRC_TOP10, 28, 1),
677
678 MUX(0, "mout_sw_aclk333_432_gscl", mout_sw_aclk333_432_gscl_p,
390 SRC_TOP11, 0, 1), 679 SRC_TOP11, 0, 1),
391 MUX(0, "mout_sw_aclk66", sw_aclk66_p, SRC_TOP11, 8, 1), 680 MUX(0, "mout_sw_aclk333_432_isp", mout_sw_aclk333_432_isp_p,
392 MUX(0, "mout_sw_aclk266", sw_aclk266_p, SRC_TOP11, 20, 1), 681 SRC_TOP11, 4, 1),
393 MUX(0, "mout_sw_aclk166", sw_aclk166_p, SRC_TOP11, 24, 1), 682 MUX(0, "mout_sw_aclk66", mout_sw_aclk66_p, SRC_TOP11, 8, 1),
394 MUX(0, "mout_sw_aclk333", sw_aclk333_p, SRC_TOP11, 28, 1), 683 MUX(0, "mout_sw_aclk333_432_isp0", mout_sw_aclk333_432_isp0_p,
395 684 SRC_TOP11, 12, 1),
396 MUX(0, "mout_sw_aclk333_g2d", sw_aclk333_g2d_p, SRC_TOP12, 8, 1), 685 MUX(0, "mout_sw_aclk266", mout_sw_aclk266_p, SRC_TOP11, 20, 1),
397 MUX(0, "mout_sw_aclk266_g2d", sw_aclk266_g2d_p, SRC_TOP12, 12, 1), 686 MUX(0, "mout_sw_aclk166", mout_sw_aclk166_p, SRC_TOP11, 24, 1),
398 MUX(0, "mout_sw_aclk_g3d", sw_aclk_g3d_p, SRC_TOP12, 16, 1), 687 MUX(0, "mout_sw_aclk333", mout_sw_aclk333_p, SRC_TOP11, 28, 1),
399 MUX(0, "mout_sw_aclk300_jpeg", sw_aclk300_jpeg_p, SRC_TOP12, 20, 1), 688
400 MUX(0, "mout_sw_aclk300_disp1", sw_aclk300_disp1_p, 689 MUX(0, "mout_sw_aclk400_disp1", mout_sw_aclk400_disp1_p,
690 SRC_TOP12, 4, 1),
691 MUX(0, "mout_sw_aclk333_g2d", mout_sw_aclk333_g2d_p,
692 SRC_TOP12, 8, 1),
693 MUX(0, "mout_sw_aclk266_g2d", mout_sw_aclk266_g2d_p,
694 SRC_TOP12, 12, 1),
695 MUX(0, "mout_sw_aclk_g3d", mout_sw_aclk_g3d_p, SRC_TOP12, 16, 1),
696 MUX(0, "mout_sw_aclk300_jpeg", mout_sw_aclk300_jpeg_p,
697 SRC_TOP12, 20, 1),
698 MUX(0, "mout_sw_aclk300_disp1", mout_sw_aclk300_disp1_p,
401 SRC_TOP12, 24, 1), 699 SRC_TOP12, 24, 1),
402 MUX(0, "mout_sw_aclk300_gscl", sw_aclk300_gscl_p, SRC_TOP12, 28, 1), 700 MUX(0, "mout_sw_aclk300_gscl", mout_sw_aclk300_gscl_p,
701 SRC_TOP12, 28, 1),
403 702
404 /* DISP1 Block */ 703 /* DISP1 Block */
405 MUX(0, "mout_fimd1", group3_p, SRC_DISP10, 4, 1), 704 MUX(0, "mout_mipi1", mout_group2_p, SRC_DISP10, 16, 3),
406 MUX(0, "mout_mipi1", group2_p, SRC_DISP10, 16, 3), 705 MUX(0, "mout_dp1", mout_group2_p, SRC_DISP10, 20, 3),
407 MUX(0, "mout_dp1", group2_p, SRC_DISP10, 20, 3), 706 MUX(0, "mout_pixel", mout_group2_p, SRC_DISP10, 24, 3),
408 MUX(0, "mout_pixel", group2_p, SRC_DISP10, 24, 3), 707 MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_DISP10, 28, 1),
409 MUX(CLK_MOUT_HDMI, "mout_hdmi", hdmi_p, SRC_DISP10, 28, 1), 708 MUX(0, "mout_fimd1_opt", mout_group2_p, SRC_DISP10, 8, 3),
709
710 MUX(0, "mout_fimd1_final", mout_fimd1_final_p, TOP_SPARE2, 8, 1),
410 711
411 /* MAU Block */ 712 /* MAU Block */
412 MUX(0, "mout_maudio0", maudio0_p, SRC_MAU, 28, 3), 713 MUX(CLK_MOUT_MAUDIO0, "mout_maudio0", mout_maudio0_p, SRC_MAU, 28, 3),
413 714
414 /* FSYS Block */ 715 /* FSYS Block */
415 MUX(0, "mout_usbd301", group2_p, SRC_FSYS, 4, 3), 716 MUX(0, "mout_usbd301", mout_group2_p, SRC_FSYS, 4, 3),
416 MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 8, 3), 717 MUX(0, "mout_mmc0", mout_group2_p, SRC_FSYS, 8, 3),
417 MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 12, 3), 718 MUX(0, "mout_mmc1", mout_group2_p, SRC_FSYS, 12, 3),
418 MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 16, 3), 719 MUX(0, "mout_mmc2", mout_group2_p, SRC_FSYS, 16, 3),
419 MUX(0, "mout_usbd300", group2_p, SRC_FSYS, 20, 3), 720 MUX(0, "mout_usbd300", mout_group2_p, SRC_FSYS, 20, 3),
420 MUX(0, "mout_unipro", group2_p, SRC_FSYS, 24, 3), 721 MUX(0, "mout_unipro", mout_group2_p, SRC_FSYS, 24, 3),
722 MUX(0, "mout_mphy_refclk", mout_group2_p, SRC_FSYS, 28, 3),
421 723
422 /* PERIC Block */ 724 /* PERIC Block */
423 MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 4, 3), 725 MUX(0, "mout_uart0", mout_group2_p, SRC_PERIC0, 4, 3),
424 MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 8, 3), 726 MUX(0, "mout_uart1", mout_group2_p, SRC_PERIC0, 8, 3),
425 MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 12, 3), 727 MUX(0, "mout_uart2", mout_group2_p, SRC_PERIC0, 12, 3),
426 MUX(0, "mout_uart3", group2_p, SRC_PERIC0, 16, 3), 728 MUX(0, "mout_uart3", mout_group2_p, SRC_PERIC0, 16, 3),
427 MUX(0, "mout_pwm", group2_p, SRC_PERIC0, 24, 3), 729 MUX(0, "mout_pwm", mout_group2_p, SRC_PERIC0, 24, 3),
428 MUX(0, "mout_spdif", spdif_p, SRC_PERIC0, 28, 3), 730 MUX(0, "mout_spdif", mout_spdif_p, SRC_PERIC0, 28, 3),
429 MUX(0, "mout_audio0", audio0_p, SRC_PERIC1, 8, 3), 731 MUX(0, "mout_audio0", mout_audio0_p, SRC_PERIC1, 8, 3),
430 MUX(0, "mout_audio1", audio1_p, SRC_PERIC1, 12, 3), 732 MUX(0, "mout_audio1", mout_audio1_p, SRC_PERIC1, 12, 3),
431 MUX(0, "mout_audio2", audio2_p, SRC_PERIC1, 16, 3), 733 MUX(0, "mout_audio2", mout_audio2_p, SRC_PERIC1, 16, 3),
432 MUX(0, "mout_spi0", group2_p, SRC_PERIC1, 20, 3), 734 MUX(0, "mout_spi0", mout_group2_p, SRC_PERIC1, 20, 3),
433 MUX(0, "mout_spi1", group2_p, SRC_PERIC1, 24, 3), 735 MUX(0, "mout_spi1", mout_group2_p, SRC_PERIC1, 24, 3),
434 MUX(0, "mout_spi2", group2_p, SRC_PERIC1, 28, 3), 736 MUX(0, "mout_spi2", mout_group2_p, SRC_PERIC1, 28, 3),
737
738 /* ISP Block */
739 MUX(0, "mout_pwm_isp", mout_group2_p, SRC_ISP, 24, 3),
740 MUX(0, "mout_uart_isp", mout_group2_p, SRC_ISP, 20, 3),
741 MUX(0, "mout_spi0_isp", mout_group2_p, SRC_ISP, 12, 3),
742 MUX(0, "mout_spi1_isp", mout_group2_p, SRC_ISP, 16, 3),
743 MUX(0, "mout_isp_sensor", mout_group2_p, SRC_ISP, 28, 3),
435}; 744};
436 745
437static struct samsung_div_clock exynos5420_div_clks[] __initdata = { 746static struct samsung_div_clock exynos5x_div_clks[] __initdata = {
438 DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3), 747 DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
439 DIV(0, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3), 748 DIV(0, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
440 DIV(0, "armclk2", "div_arm", DIV_CPU0, 28, 3), 749 DIV(0, "armclk2", "div_arm", DIV_CPU0, 28, 3),
441 DIV(0, "div_kfc", "mout_cpu_kfc", DIV_KFC0, 0, 3), 750 DIV(0, "div_kfc", "mout_kfc", DIV_KFC0, 0, 3),
442 DIV(0, "sclk_kpll", "mout_kpll", DIV_KFC0, 24, 3), 751 DIV(0, "sclk_kpll", "mout_kpll", DIV_KFC0, 24, 3),
443 752
753 DIV(0, "dout_aclk400_isp", "mout_aclk400_isp", DIV_TOP0, 0, 3),
444 DIV(0, "dout_aclk400_mscl", "mout_aclk400_mscl", DIV_TOP0, 4, 3), 754 DIV(0, "dout_aclk400_mscl", "mout_aclk400_mscl", DIV_TOP0, 4, 3),
445 DIV(0, "dout_aclk200", "mout_aclk200", DIV_TOP0, 8, 3), 755 DIV(0, "dout_aclk200", "mout_aclk200", DIV_TOP0, 8, 3),
446 DIV(0, "dout_aclk200_fsys2", "mout_aclk200_fsys2", DIV_TOP0, 12, 3), 756 DIV(0, "dout_aclk200_fsys2", "mout_aclk200_fsys2", DIV_TOP0, 12, 3),
757 DIV(0, "dout_aclk100_noc", "mout_aclk100_noc", DIV_TOP0, 20, 3),
447 DIV(0, "dout_pclk200_fsys", "mout_pclk200_fsys", DIV_TOP0, 24, 3), 758 DIV(0, "dout_pclk200_fsys", "mout_pclk200_fsys", DIV_TOP0, 24, 3),
448 DIV(0, "dout_aclk200_fsys", "mout_aclk200_fsys", DIV_TOP0, 28, 3), 759 DIV(0, "dout_aclk200_fsys", "mout_aclk200_fsys", DIV_TOP0, 28, 3),
449 760
450 DIV(0, "dout_aclk333_432_gscl", "mout_aclk333_432_gscl", 761 DIV(0, "dout_aclk333_432_gscl", "mout_aclk333_432_gscl",
451 DIV_TOP1, 0, 3), 762 DIV_TOP1, 0, 3),
763 DIV(0, "dout_aclk333_432_isp", "mout_aclk333_432_isp",
764 DIV_TOP1, 4, 3),
452 DIV(0, "dout_aclk66", "mout_aclk66", DIV_TOP1, 8, 6), 765 DIV(0, "dout_aclk66", "mout_aclk66", DIV_TOP1, 8, 6),
766 DIV(0, "dout_aclk333_432_isp0", "mout_aclk333_432_isp0",
767 DIV_TOP1, 16, 3),
453 DIV(0, "dout_aclk266", "mout_aclk266", DIV_TOP1, 20, 3), 768 DIV(0, "dout_aclk266", "mout_aclk266", DIV_TOP1, 20, 3),
454 DIV(0, "dout_aclk166", "mout_aclk166", DIV_TOP1, 24, 3), 769 DIV(0, "dout_aclk166", "mout_aclk166", DIV_TOP1, 24, 3),
455 DIV(0, "dout_aclk333", "mout_aclk333", DIV_TOP1, 28, 3), 770 DIV(0, "dout_aclk333", "mout_aclk333", DIV_TOP1, 28, 3),
@@ -458,15 +773,16 @@ static struct samsung_div_clock exynos5420_div_clks[] __initdata = {
458 DIV(0, "dout_aclk266_g2d", "mout_aclk266_g2d", DIV_TOP2, 12, 3), 773 DIV(0, "dout_aclk266_g2d", "mout_aclk266_g2d", DIV_TOP2, 12, 3),
459 DIV(0, "dout_aclk_g3d", "mout_aclk_g3d", DIV_TOP2, 16, 3), 774 DIV(0, "dout_aclk_g3d", "mout_aclk_g3d", DIV_TOP2, 16, 3),
460 DIV(0, "dout_aclk300_jpeg", "mout_aclk300_jpeg", DIV_TOP2, 20, 3), 775 DIV(0, "dout_aclk300_jpeg", "mout_aclk300_jpeg", DIV_TOP2, 20, 3),
461 DIV_A(0, "dout_aclk300_disp1", "mout_aclk300_disp1", 776 DIV(0, "dout_aclk300_disp1", "mout_aclk300_disp1", DIV_TOP2, 24, 3),
462 DIV_TOP2, 24, 3, "aclk300_disp1"),
463 DIV(0, "dout_aclk300_gscl", "mout_aclk300_gscl", DIV_TOP2, 28, 3), 777 DIV(0, "dout_aclk300_gscl", "mout_aclk300_gscl", DIV_TOP2, 28, 3),
464 778
465 /* DISP1 Block */ 779 /* DISP1 Block */
466 DIV(0, "dout_fimd1", "mout_fimd1", DIV_DISP10, 0, 4), 780 DIV(0, "dout_fimd1", "mout_fimd1_final", DIV_DISP10, 0, 4),
467 DIV(0, "dout_mipi1", "mout_mipi1", DIV_DISP10, 16, 8), 781 DIV(0, "dout_mipi1", "mout_mipi1", DIV_DISP10, 16, 8),
468 DIV(0, "dout_dp1", "mout_dp1", DIV_DISP10, 24, 4), 782 DIV(0, "dout_dp1", "mout_dp1", DIV_DISP10, 24, 4),
469 DIV(CLK_DOUT_PIXEL, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4), 783 DIV(CLK_DOUT_PIXEL, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4),
784 DIV(0, "dout_disp1_blk", "aclk200_disp1", DIV2_RATIO0, 16, 2),
785 DIV(0, "dout_aclk400_disp1", "mout_aclk400_disp1", DIV_TOP2, 4, 3),
470 786
471 /* Audio Block */ 787 /* Audio Block */
472 DIV(0, "dout_maudio0", "mout_maudio0", DIV_MAU, 20, 4), 788 DIV(0, "dout_maudio0", "mout_maudio0", DIV_MAU, 20, 4),
@@ -484,6 +800,7 @@ static struct samsung_div_clock exynos5420_div_clks[] __initdata = {
484 DIV(0, "dout_mmc2", "mout_mmc2", DIV_FSYS1, 20, 10), 800 DIV(0, "dout_mmc2", "mout_mmc2", DIV_FSYS1, 20, 10),
485 801
486 DIV(0, "dout_unipro", "mout_unipro", DIV_FSYS2, 24, 8), 802 DIV(0, "dout_unipro", "mout_unipro", DIV_FSYS2, 24, 8),
803 DIV(0, "dout_mphy_refclk", "mout_mphy_refclk", DIV_FSYS2, 16, 8),
487 804
488 /* UART and PWM */ 805 /* UART and PWM */
489 DIV(0, "dout_uart0", "mout_uart0", DIV_PERIC0, 8, 4), 806 DIV(0, "dout_uart0", "mout_uart0", DIV_PERIC0, 8, 4),
@@ -497,6 +814,9 @@ static struct samsung_div_clock exynos5420_div_clks[] __initdata = {
497 DIV(0, "dout_spi1", "mout_spi1", DIV_PERIC1, 24, 4), 814 DIV(0, "dout_spi1", "mout_spi1", DIV_PERIC1, 24, 4),
498 DIV(0, "dout_spi2", "mout_spi2", DIV_PERIC1, 28, 4), 815 DIV(0, "dout_spi2", "mout_spi2", DIV_PERIC1, 28, 4),
499 816
817 /* Mfc Block */
818 DIV(0, "dout_mfc_blk", "mout_user_aclk333", DIV4_RATIO, 0, 2),
819
500 /* PCM */ 820 /* PCM */
501 DIV(0, "dout_pcm1", "dout_audio1", DIV_PERIC2, 16, 8), 821 DIV(0, "dout_pcm1", "dout_audio1", DIV_PERIC2, 16, 8),
502 DIV(0, "dout_pcm2", "dout_audio2", DIV_PERIC2, 24, 8), 822 DIV(0, "dout_pcm2", "dout_audio2", DIV_PERIC2, 24, 8),
@@ -509,15 +829,43 @@ static struct samsung_div_clock exynos5420_div_clks[] __initdata = {
509 DIV(0, "dout_audio2", "mout_audio2", DIV_PERIC3, 28, 4), 829 DIV(0, "dout_audio2", "mout_audio2", DIV_PERIC3, 28, 4),
510 830
511 /* SPI Pre-Ratio */ 831 /* SPI Pre-Ratio */
512 DIV(0, "dout_pre_spi0", "dout_spi0", DIV_PERIC4, 8, 8), 832 DIV(0, "dout_spi0_pre", "dout_spi0", DIV_PERIC4, 8, 8),
513 DIV(0, "dout_pre_spi1", "dout_spi1", DIV_PERIC4, 16, 8), 833 DIV(0, "dout_spi1_pre", "dout_spi1", DIV_PERIC4, 16, 8),
514 DIV(0, "dout_pre_spi2", "dout_spi2", DIV_PERIC4, 24, 8), 834 DIV(0, "dout_spi2_pre", "dout_spi2", DIV_PERIC4, 24, 8),
835
836 /* GSCL Block */
837 DIV(0, "dout_gscl_blk_300", "mout_user_aclk300_gscl",
838 DIV2_RATIO0, 4, 2),
839 DIV(0, "dout_gscl_blk_333", "aclk333_432_gscl", DIV2_RATIO0, 6, 2),
840
841 /* MSCL Block */
842 DIV(0, "dout_mscl_blk", "aclk400_mscl", DIV2_RATIO0, 28, 2),
843
844 /* PSGEN */
845 DIV(0, "dout_gen_blk", "mout_user_aclk266", DIV2_RATIO0, 8, 1),
846 DIV(0, "dout_jpg_blk", "aclk166", DIV2_RATIO0, 20, 1),
847
848 /* ISP Block */
849 DIV(0, "dout_isp_sensor0", "mout_isp_sensor", SCLK_DIV_ISP0, 8, 8),
850 DIV(0, "dout_isp_sensor1", "mout_isp_sensor", SCLK_DIV_ISP0, 16, 8),
851 DIV(0, "dout_isp_sensor2", "mout_isp_sensor", SCLK_DIV_ISP0, 24, 8),
852 DIV(0, "dout_pwm_isp", "mout_pwm_isp", SCLK_DIV_ISP1, 28, 4),
853 DIV(0, "dout_uart_isp", "mout_uart_isp", SCLK_DIV_ISP1, 24, 4),
854 DIV(0, "dout_spi0_isp", "mout_spi0_isp", SCLK_DIV_ISP1, 16, 4),
855 DIV(0, "dout_spi1_isp", "mout_spi1_isp", SCLK_DIV_ISP1, 20, 4),
856 DIV_F(0, "dout_spi0_isp_pre", "dout_spi0_isp", SCLK_DIV_ISP1, 0, 8,
857 CLK_SET_RATE_PARENT, 0),
858 DIV_F(0, "dout_spi1_isp_pre", "dout_spi1_isp", SCLK_DIV_ISP1, 8, 8,
859 CLK_SET_RATE_PARENT, 0),
515}; 860};
516 861
517static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { 862static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = {
518 /* TODO: Re-verify the CG bits for all the gate clocks */ 863 /* G2D */
519 GATE_A(CLK_MCT, "pclk_st", "aclk66_psgen", GATE_BUS_PERIS1, 2, 0, 0, 864 GATE(CLK_MDMA0, "mdma0", "aclk266_g2d", GATE_IP_G2D, 1, 0, 0),
520 "mct"), 865 GATE(CLK_SSS, "sss", "aclk266_g2d", GATE_IP_G2D, 2, 0, 0),
866 GATE(CLK_G2D, "g2d", "aclk333_g2d", GATE_IP_G2D, 3, 0, 0),
867 GATE(CLK_SMMU_MDMA0, "smmu_mdma0", "aclk266_g2d", GATE_IP_G2D, 5, 0, 0),
868 GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk333_g2d", GATE_IP_G2D, 7, 0, 0),
521 869
522 GATE(0, "aclk200_fsys", "mout_user_aclk200_fsys", 870 GATE(0, "aclk200_fsys", "mout_user_aclk200_fsys",
523 GATE_BUS_FSYS0, 9, CLK_IGNORE_UNUSED, 0), 871 GATE_BUS_FSYS0, 9, CLK_IGNORE_UNUSED, 0),
@@ -530,20 +878,42 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {
530 GATE_BUS_TOP, 1, CLK_IGNORE_UNUSED, 0), 878 GATE_BUS_TOP, 1, CLK_IGNORE_UNUSED, 0),
531 GATE(0, "aclk300_jpeg", "mout_user_aclk300_jpeg", 879 GATE(0, "aclk300_jpeg", "mout_user_aclk300_jpeg",
532 GATE_BUS_TOP, 4, CLK_IGNORE_UNUSED, 0), 880 GATE_BUS_TOP, 4, CLK_IGNORE_UNUSED, 0),
881 GATE(0, "aclk333_432_isp0", "mout_user_aclk333_432_isp0",
882 GATE_BUS_TOP, 5, 0, 0),
533 GATE(0, "aclk300_gscl", "mout_user_aclk300_gscl", 883 GATE(0, "aclk300_gscl", "mout_user_aclk300_gscl",
534 GATE_BUS_TOP, 6, CLK_IGNORE_UNUSED, 0), 884 GATE_BUS_TOP, 6, CLK_IGNORE_UNUSED, 0),
535 GATE(0, "aclk333_432_gscl", "mout_user_aclk333_432_gscl", 885 GATE(0, "aclk333_432_gscl", "mout_user_aclk333_432_gscl",
536 GATE_BUS_TOP, 7, CLK_IGNORE_UNUSED, 0), 886 GATE_BUS_TOP, 7, CLK_IGNORE_UNUSED, 0),
537 GATE(0, "pclk66_gpio", "mout_sw_aclk66", 887 GATE(0, "aclk333_432_isp", "mout_user_aclk333_432_isp",
888 GATE_BUS_TOP, 8, 0, 0),
889 GATE(CLK_PCLK66_GPIO, "pclk66_gpio", "mout_user_pclk66_gpio",
538 GATE_BUS_TOP, 9, CLK_IGNORE_UNUSED, 0), 890 GATE_BUS_TOP, 9, CLK_IGNORE_UNUSED, 0),
539 GATE(0, "aclk66_psgen", "mout_aclk66_psgen", 891 GATE(0, "aclk66_psgen", "mout_user_aclk66_psgen",
540 GATE_BUS_TOP, 10, CLK_IGNORE_UNUSED, 0), 892 GATE_BUS_TOP, 10, CLK_IGNORE_UNUSED, 0),
541 GATE(0, "aclk66_peric", "mout_aclk66_peric", 893 GATE(CLK_ACLK66_PERIC, "aclk66_peric", "mout_user_aclk66_peric",
542 GATE_BUS_TOP, 11, 0, 0), 894 GATE_BUS_TOP, 11, CLK_IGNORE_UNUSED, 0),
895 GATE(0, "aclk266_isp", "mout_user_aclk266_isp",
896 GATE_BUS_TOP, 13, 0, 0),
543 GATE(0, "aclk166", "mout_user_aclk166", 897 GATE(0, "aclk166", "mout_user_aclk166",
544 GATE_BUS_TOP, 14, CLK_IGNORE_UNUSED, 0), 898 GATE_BUS_TOP, 14, CLK_IGNORE_UNUSED, 0),
545 GATE(0, "aclk333", "mout_aclk333", 899 GATE(0, "aclk333", "mout_aclk333",
546 GATE_BUS_TOP, 15, CLK_IGNORE_UNUSED, 0), 900 GATE_BUS_TOP, 15, CLK_IGNORE_UNUSED, 0),
901 GATE(0, "aclk400_isp", "mout_user_aclk400_isp",
902 GATE_BUS_TOP, 16, 0, 0),
903 GATE(0, "aclk400_mscl", "mout_user_aclk400_mscl",
904 GATE_BUS_TOP, 17, 0, 0),
905 GATE(0, "aclk200_disp1", "mout_user_aclk200_disp1",
906 GATE_BUS_TOP, 18, 0, 0),
907 GATE(CLK_SCLK_MPHY_IXTAL24, "sclk_mphy_ixtal24", "mphy_refclk_ixtal24",
908 GATE_BUS_TOP, 28, 0, 0),
909 GATE(CLK_SCLK_HSIC_12M, "sclk_hsic_12m", "ff_hsic_12m",
910 GATE_BUS_TOP, 29, 0, 0),
911
912 GATE(0, "aclk300_disp1", "mout_user_aclk300_disp1",
913 SRC_MASK_TOP2, 24, 0, 0),
914
915 GATE(CLK_MAU_EPLL, "mau_epll", "mout_mau_epll_clk",
916 SRC_MASK_TOP7, 20, 0, 0),
547 917
548 /* sclk */ 918 /* sclk */
549 GATE(CLK_SCLK_UART0, "sclk_uart0", "dout_uart0", 919 GATE(CLK_SCLK_UART0, "sclk_uart0", "dout_uart0",
@@ -554,11 +924,11 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {
554 GATE_TOP_SCLK_PERIC, 2, CLK_SET_RATE_PARENT, 0), 924 GATE_TOP_SCLK_PERIC, 2, CLK_SET_RATE_PARENT, 0),
555 GATE(CLK_SCLK_UART3, "sclk_uart3", "dout_uart3", 925 GATE(CLK_SCLK_UART3, "sclk_uart3", "dout_uart3",
556 GATE_TOP_SCLK_PERIC, 3, CLK_SET_RATE_PARENT, 0), 926 GATE_TOP_SCLK_PERIC, 3, CLK_SET_RATE_PARENT, 0),
557 GATE(CLK_SCLK_SPI0, "sclk_spi0", "dout_pre_spi0", 927 GATE(CLK_SCLK_SPI0, "sclk_spi0", "dout_spi0_pre",
558 GATE_TOP_SCLK_PERIC, 6, CLK_SET_RATE_PARENT, 0), 928 GATE_TOP_SCLK_PERIC, 6, CLK_SET_RATE_PARENT, 0),
559 GATE(CLK_SCLK_SPI1, "sclk_spi1", "dout_pre_spi1", 929 GATE(CLK_SCLK_SPI1, "sclk_spi1", "dout_spi1_pre",
560 GATE_TOP_SCLK_PERIC, 7, CLK_SET_RATE_PARENT, 0), 930 GATE_TOP_SCLK_PERIC, 7, CLK_SET_RATE_PARENT, 0),
561 GATE(CLK_SCLK_SPI2, "sclk_spi2", "dout_pre_spi2", 931 GATE(CLK_SCLK_SPI2, "sclk_spi2", "dout_spi2_pre",
562 GATE_TOP_SCLK_PERIC, 8, CLK_SET_RATE_PARENT, 0), 932 GATE_TOP_SCLK_PERIC, 8, CLK_SET_RATE_PARENT, 0),
563 GATE(CLK_SCLK_SPDIF, "sclk_spdif", "mout_spdif", 933 GATE(CLK_SCLK_SPDIF, "sclk_spdif", "mout_spdif",
564 GATE_TOP_SCLK_PERIC, 9, CLK_SET_RATE_PARENT, 0), 934 GATE_TOP_SCLK_PERIC, 9, CLK_SET_RATE_PARENT, 0),
@@ -588,164 +958,191 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {
588 GATE(CLK_SCLK_USBD301, "sclk_usbd301", "dout_usbd301", 958 GATE(CLK_SCLK_USBD301, "sclk_usbd301", "dout_usbd301",
589 GATE_TOP_SCLK_FSYS, 10, CLK_SET_RATE_PARENT, 0), 959 GATE_TOP_SCLK_FSYS, 10, CLK_SET_RATE_PARENT, 0),
590 960
591 GATE(CLK_SCLK_USBD301, "sclk_unipro", "dout_unipro",
592 SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
593
594 GATE(CLK_SCLK_GSCL_WA, "sclk_gscl_wa", "aclK333_432_gscl",
595 GATE_TOP_SCLK_GSCL, 6, CLK_SET_RATE_PARENT, 0),
596 GATE(CLK_SCLK_GSCL_WB, "sclk_gscl_wb", "aclk333_432_gscl",
597 GATE_TOP_SCLK_GSCL, 7, CLK_SET_RATE_PARENT, 0),
598
599 /* Display */ 961 /* Display */
600 GATE(CLK_SCLK_FIMD1, "sclk_fimd1", "dout_fimd1", 962 GATE(CLK_SCLK_FIMD1, "sclk_fimd1", "dout_fimd1",
601 GATE_TOP_SCLK_DISP1, 0, CLK_SET_RATE_PARENT, 0), 963 GATE_TOP_SCLK_DISP1, 0, CLK_SET_RATE_PARENT, 0),
602 GATE(CLK_SCLK_MIPI1, "sclk_mipi1", "dout_mipi1", 964 GATE(CLK_SCLK_MIPI1, "sclk_mipi1", "dout_mipi1",
603 GATE_TOP_SCLK_DISP1, 3, CLK_SET_RATE_PARENT, 0), 965 GATE_TOP_SCLK_DISP1, 3, CLK_SET_RATE_PARENT, 0),
604 GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi", 966 GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi",
605 GATE_TOP_SCLK_DISP1, 9, CLK_SET_RATE_PARENT, 0), 967 GATE_TOP_SCLK_DISP1, 9, 0, 0),
606 GATE(CLK_SCLK_PIXEL, "sclk_pixel", "dout_hdmi_pixel", 968 GATE(CLK_SCLK_PIXEL, "sclk_pixel", "dout_hdmi_pixel",
607 GATE_TOP_SCLK_DISP1, 10, CLK_SET_RATE_PARENT, 0), 969 GATE_TOP_SCLK_DISP1, 10, CLK_SET_RATE_PARENT, 0),
608 GATE(CLK_SCLK_DP1, "sclk_dp1", "dout_dp1", 970 GATE(CLK_SCLK_DP1, "sclk_dp1", "dout_dp1",
609 GATE_TOP_SCLK_DISP1, 20, CLK_SET_RATE_PARENT, 0), 971 GATE_TOP_SCLK_DISP1, 20, CLK_SET_RATE_PARENT, 0),
610 972
611 /* Maudio Block */ 973 /* Maudio Block */
612 GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0", 974 GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
613 GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0), 975 GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
614 GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0", 976 GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
615 GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0), 977 GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
616 /* FSYS */ 978
979 /* FSYS Block */
617 GATE(CLK_TSI, "tsi", "aclk200_fsys", GATE_BUS_FSYS0, 0, 0, 0), 980 GATE(CLK_TSI, "tsi", "aclk200_fsys", GATE_BUS_FSYS0, 0, 0, 0),
618 GATE(CLK_PDMA0, "pdma0", "aclk200_fsys", GATE_BUS_FSYS0, 1, 0, 0), 981 GATE(CLK_PDMA0, "pdma0", "aclk200_fsys", GATE_BUS_FSYS0, 1, 0, 0),
619 GATE(CLK_PDMA1, "pdma1", "aclk200_fsys", GATE_BUS_FSYS0, 2, 0, 0), 982 GATE(CLK_PDMA1, "pdma1", "aclk200_fsys", GATE_BUS_FSYS0, 2, 0, 0),
620 GATE(CLK_UFS, "ufs", "aclk200_fsys2", GATE_BUS_FSYS0, 3, 0, 0), 983 GATE(CLK_UFS, "ufs", "aclk200_fsys2", GATE_BUS_FSYS0, 3, 0, 0),
621 GATE(CLK_RTIC, "rtic", "aclk200_fsys", GATE_BUS_FSYS0, 5, 0, 0), 984 GATE(CLK_RTIC, "rtic", "aclk200_fsys", GATE_IP_FSYS, 9, 0, 0),
622 GATE(CLK_MMC0, "mmc0", "aclk200_fsys2", GATE_BUS_FSYS0, 12, 0, 0), 985 GATE(CLK_MMC0, "mmc0", "aclk200_fsys2", GATE_IP_FSYS, 12, 0, 0),
623 GATE(CLK_MMC1, "mmc1", "aclk200_fsys2", GATE_BUS_FSYS0, 13, 0, 0), 986 GATE(CLK_MMC1, "mmc1", "aclk200_fsys2", GATE_IP_FSYS, 13, 0, 0),
624 GATE(CLK_MMC2, "mmc2", "aclk200_fsys2", GATE_BUS_FSYS0, 14, 0, 0), 987 GATE(CLK_MMC2, "mmc2", "aclk200_fsys2", GATE_IP_FSYS, 14, 0, 0),
625 GATE(CLK_SROMC, "sromc", "aclk200_fsys2", 988 GATE(CLK_SROMC, "sromc", "aclk200_fsys2",
626 GATE_BUS_FSYS0, 19, CLK_IGNORE_UNUSED, 0), 989 GATE_IP_FSYS, 17, CLK_IGNORE_UNUSED, 0),
627 GATE(CLK_USBH20, "usbh20", "aclk200_fsys", GATE_BUS_FSYS0, 20, 0, 0), 990 GATE(CLK_USBH20, "usbh20", "aclk200_fsys", GATE_IP_FSYS, 18, 0, 0),
628 GATE(CLK_USBD300, "usbd300", "aclk200_fsys", GATE_BUS_FSYS0, 21, 0, 0), 991 GATE(CLK_USBD300, "usbd300", "aclk200_fsys", GATE_IP_FSYS, 19, 0, 0),
629 GATE(CLK_USBD301, "usbd301", "aclk200_fsys", GATE_BUS_FSYS0, 28, 0, 0), 992 GATE(CLK_USBD301, "usbd301", "aclk200_fsys", GATE_IP_FSYS, 20, 0, 0),
630 993 GATE(CLK_SCLK_UNIPRO, "sclk_unipro", "dout_unipro",
631 /* UART */ 994 SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
632 GATE(CLK_UART0, "uart0", "aclk66_peric", GATE_BUS_PERIC, 4, 0, 0),
633 GATE(CLK_UART1, "uart1", "aclk66_peric", GATE_BUS_PERIC, 5, 0, 0),
634 GATE_A(CLK_UART2, "uart2", "aclk66_peric",
635 GATE_BUS_PERIC, 6, CLK_IGNORE_UNUSED, 0, "uart2"),
636 GATE(CLK_UART3, "uart3", "aclk66_peric", GATE_BUS_PERIC, 7, 0, 0),
637 /* I2C */
638 GATE(CLK_I2C0, "i2c0", "aclk66_peric", GATE_BUS_PERIC, 9, 0, 0),
639 GATE(CLK_I2C1, "i2c1", "aclk66_peric", GATE_BUS_PERIC, 10, 0, 0),
640 GATE(CLK_I2C2, "i2c2", "aclk66_peric", GATE_BUS_PERIC, 11, 0, 0),
641 GATE(CLK_I2C3, "i2c3", "aclk66_peric", GATE_BUS_PERIC, 12, 0, 0),
642 GATE(CLK_I2C4, "i2c4", "aclk66_peric", GATE_BUS_PERIC, 13, 0, 0),
643 GATE(CLK_I2C5, "i2c5", "aclk66_peric", GATE_BUS_PERIC, 14, 0, 0),
644 GATE(CLK_I2C6, "i2c6", "aclk66_peric", GATE_BUS_PERIC, 15, 0, 0),
645 GATE(CLK_I2C7, "i2c7", "aclk66_peric", GATE_BUS_PERIC, 16, 0, 0),
646 GATE(CLK_I2C_HDMI, "i2c_hdmi", "aclk66_peric", GATE_BUS_PERIC, 17, 0,
647 0),
648 GATE(CLK_TSADC, "tsadc", "aclk66_peric", GATE_BUS_PERIC, 18, 0, 0),
649 /* SPI */
650 GATE(CLK_SPI0, "spi0", "aclk66_peric", GATE_BUS_PERIC, 19, 0, 0),
651 GATE(CLK_SPI1, "spi1", "aclk66_peric", GATE_BUS_PERIC, 20, 0, 0),
652 GATE(CLK_SPI2, "spi2", "aclk66_peric", GATE_BUS_PERIC, 21, 0, 0),
653 GATE(CLK_KEYIF, "keyif", "aclk66_peric", GATE_BUS_PERIC, 22, 0, 0),
654 /* I2S */
655 GATE(CLK_I2S1, "i2s1", "aclk66_peric", GATE_BUS_PERIC, 23, 0, 0),
656 GATE(CLK_I2S2, "i2s2", "aclk66_peric", GATE_BUS_PERIC, 24, 0, 0),
657 /* PCM */
658 GATE(CLK_PCM1, "pcm1", "aclk66_peric", GATE_BUS_PERIC, 25, 0, 0),
659 GATE(CLK_PCM2, "pcm2", "aclk66_peric", GATE_BUS_PERIC, 26, 0, 0),
660 /* PWM */
661 GATE(CLK_PWM, "pwm", "aclk66_peric", GATE_BUS_PERIC, 27, 0, 0),
662 /* SPDIF */
663 GATE(CLK_SPDIF, "spdif", "aclk66_peric", GATE_BUS_PERIC, 29, 0, 0),
664 995
665 GATE(CLK_I2C8, "i2c8", "aclk66_peric", GATE_BUS_PERIC1, 0, 0, 0), 996 /* PERIC Block */
666 GATE(CLK_I2C9, "i2c9", "aclk66_peric", GATE_BUS_PERIC1, 1, 0, 0), 997 GATE(CLK_UART0, "uart0", "aclk66_peric", GATE_IP_PERIC, 0, 0, 0),
667 GATE(CLK_I2C10, "i2c10", "aclk66_peric", GATE_BUS_PERIC1, 2, 0, 0), 998 GATE(CLK_UART1, "uart1", "aclk66_peric", GATE_IP_PERIC, 1, 0, 0),
999 GATE(CLK_UART2, "uart2", "aclk66_peric", GATE_IP_PERIC, 2, 0, 0),
1000 GATE(CLK_UART3, "uart3", "aclk66_peric", GATE_IP_PERIC, 3, 0, 0),
1001 GATE(CLK_I2C0, "i2c0", "aclk66_peric", GATE_IP_PERIC, 6, 0, 0),
1002 GATE(CLK_I2C1, "i2c1", "aclk66_peric", GATE_IP_PERIC, 7, 0, 0),
1003 GATE(CLK_I2C2, "i2c2", "aclk66_peric", GATE_IP_PERIC, 8, 0, 0),
1004 GATE(CLK_I2C3, "i2c3", "aclk66_peric", GATE_IP_PERIC, 9, 0, 0),
1005 GATE(CLK_USI0, "usi0", "aclk66_peric", GATE_IP_PERIC, 10, 0, 0),
1006 GATE(CLK_USI1, "usi1", "aclk66_peric", GATE_IP_PERIC, 11, 0, 0),
1007 GATE(CLK_USI2, "usi2", "aclk66_peric", GATE_IP_PERIC, 12, 0, 0),
1008 GATE(CLK_USI3, "usi3", "aclk66_peric", GATE_IP_PERIC, 13, 0, 0),
1009 GATE(CLK_I2C_HDMI, "i2c_hdmi", "aclk66_peric", GATE_IP_PERIC, 14, 0, 0),
1010 GATE(CLK_TSADC, "tsadc", "aclk66_peric", GATE_IP_PERIC, 15, 0, 0),
1011 GATE(CLK_SPI0, "spi0", "aclk66_peric", GATE_IP_PERIC, 16, 0, 0),
1012 GATE(CLK_SPI1, "spi1", "aclk66_peric", GATE_IP_PERIC, 17, 0, 0),
1013 GATE(CLK_SPI2, "spi2", "aclk66_peric", GATE_IP_PERIC, 18, 0, 0),
1014 GATE(CLK_I2S1, "i2s1", "aclk66_peric", GATE_IP_PERIC, 20, 0, 0),
1015 GATE(CLK_I2S2, "i2s2", "aclk66_peric", GATE_IP_PERIC, 21, 0, 0),
1016 GATE(CLK_PCM1, "pcm1", "aclk66_peric", GATE_IP_PERIC, 22, 0, 0),
1017 GATE(CLK_PCM2, "pcm2", "aclk66_peric", GATE_IP_PERIC, 23, 0, 0),
1018 GATE(CLK_PWM, "pwm", "aclk66_peric", GATE_IP_PERIC, 24, 0, 0),
1019 GATE(CLK_SPDIF, "spdif", "aclk66_peric", GATE_IP_PERIC, 26, 0, 0),
1020 GATE(CLK_USI4, "usi4", "aclk66_peric", GATE_IP_PERIC, 28, 0, 0),
1021 GATE(CLK_USI5, "usi5", "aclk66_peric", GATE_IP_PERIC, 30, 0, 0),
1022 GATE(CLK_USI6, "usi6", "aclk66_peric", GATE_IP_PERIC, 31, 0, 0),
668 1023
1024 GATE(CLK_KEYIF, "keyif", "aclk66_peric", GATE_BUS_PERIC, 22, 0, 0),
1025
1026 /* PERIS Block */
669 GATE(CLK_CHIPID, "chipid", "aclk66_psgen", 1027 GATE(CLK_CHIPID, "chipid", "aclk66_psgen",
670 GATE_BUS_PERIS0, 12, CLK_IGNORE_UNUSED, 0), 1028 GATE_IP_PERIS, 0, CLK_IGNORE_UNUSED, 0),
671 GATE(CLK_SYSREG, "sysreg", "aclk66_psgen", 1029 GATE(CLK_SYSREG, "sysreg", "aclk66_psgen",
672 GATE_BUS_PERIS0, 13, CLK_IGNORE_UNUSED, 0), 1030 GATE_IP_PERIS, 1, CLK_IGNORE_UNUSED, 0),
673 GATE(CLK_TZPC0, "tzpc0", "aclk66_psgen", GATE_BUS_PERIS0, 18, 0, 0), 1031 GATE(CLK_TZPC0, "tzpc0", "aclk66_psgen", GATE_IP_PERIS, 6, 0, 0),
674 GATE(CLK_TZPC1, "tzpc1", "aclk66_psgen", GATE_BUS_PERIS0, 19, 0, 0), 1032 GATE(CLK_TZPC1, "tzpc1", "aclk66_psgen", GATE_IP_PERIS, 7, 0, 0),
675 GATE(CLK_TZPC2, "tzpc2", "aclk66_psgen", GATE_BUS_PERIS0, 20, 0, 0), 1033 GATE(CLK_TZPC2, "tzpc2", "aclk66_psgen", GATE_IP_PERIS, 8, 0, 0),
676 GATE(CLK_TZPC3, "tzpc3", "aclk66_psgen", GATE_BUS_PERIS0, 21, 0, 0), 1034 GATE(CLK_TZPC3, "tzpc3", "aclk66_psgen", GATE_IP_PERIS, 9, 0, 0),
677 GATE(CLK_TZPC4, "tzpc4", "aclk66_psgen", GATE_BUS_PERIS0, 22, 0, 0), 1035 GATE(CLK_TZPC4, "tzpc4", "aclk66_psgen", GATE_IP_PERIS, 10, 0, 0),
678 GATE(CLK_TZPC5, "tzpc5", "aclk66_psgen", GATE_BUS_PERIS0, 23, 0, 0), 1036 GATE(CLK_TZPC5, "tzpc5", "aclk66_psgen", GATE_IP_PERIS, 11, 0, 0),
679 GATE(CLK_TZPC6, "tzpc6", "aclk66_psgen", GATE_BUS_PERIS0, 24, 0, 0), 1037 GATE(CLK_TZPC6, "tzpc6", "aclk66_psgen", GATE_IP_PERIS, 12, 0, 0),
680 GATE(CLK_TZPC7, "tzpc7", "aclk66_psgen", GATE_BUS_PERIS0, 25, 0, 0), 1038 GATE(CLK_TZPC7, "tzpc7", "aclk66_psgen", GATE_IP_PERIS, 13, 0, 0),
681 GATE(CLK_TZPC8, "tzpc8", "aclk66_psgen", GATE_BUS_PERIS0, 26, 0, 0), 1039 GATE(CLK_TZPC8, "tzpc8", "aclk66_psgen", GATE_IP_PERIS, 14, 0, 0),
682 GATE(CLK_TZPC9, "tzpc9", "aclk66_psgen", GATE_BUS_PERIS0, 27, 0, 0), 1040 GATE(CLK_TZPC9, "tzpc9", "aclk66_psgen", GATE_IP_PERIS, 15, 0, 0),
683 1041 GATE(CLK_HDMI_CEC, "hdmi_cec", "aclk66_psgen", GATE_IP_PERIS, 16, 0, 0),
684 GATE(CLK_HDMI_CEC, "hdmi_cec", "aclk66_psgen", GATE_BUS_PERIS1, 0, 0, 1042 GATE(CLK_MCT, "mct", "aclk66_psgen", GATE_IP_PERIS, 18, 0, 0),
685 0), 1043 GATE(CLK_WDT, "wdt", "aclk66_psgen", GATE_IP_PERIS, 19, 0, 0),
1044 GATE(CLK_RTC, "rtc", "aclk66_psgen", GATE_IP_PERIS, 20, 0, 0),
1045 GATE(CLK_TMU, "tmu", "aclk66_psgen", GATE_IP_PERIS, 21, 0, 0),
1046 GATE(CLK_TMU_GPU, "tmu_gpu", "aclk66_psgen", GATE_IP_PERIS, 22, 0, 0),
1047
686 GATE(CLK_SECKEY, "seckey", "aclk66_psgen", GATE_BUS_PERIS1, 1, 0, 0), 1048 GATE(CLK_SECKEY, "seckey", "aclk66_psgen", GATE_BUS_PERIS1, 1, 0, 0),
687 GATE(CLK_WDT, "wdt", "aclk66_psgen", GATE_BUS_PERIS1, 3, 0, 0), 1049
688 GATE(CLK_RTC, "rtc", "aclk66_psgen", GATE_BUS_PERIS1, 4, 0, 0), 1050 /* GEN Block */
689 GATE(CLK_TMU, "tmu", "aclk66_psgen", GATE_BUS_PERIS1, 5, 0, 0), 1051 GATE(CLK_ROTATOR, "rotator", "mout_user_aclk266", GATE_IP_GEN, 1, 0, 0),
690 GATE(CLK_TMU_GPU, "tmu_gpu", "aclk66_psgen", GATE_BUS_PERIS1, 6, 0, 0), 1052 GATE(CLK_JPEG, "jpeg", "aclk300_jpeg", GATE_IP_GEN, 2, 0, 0),
1053 GATE(CLK_JPEG2, "jpeg2", "aclk300_jpeg", GATE_IP_GEN, 3, 0, 0),
1054 GATE(CLK_MDMA1, "mdma1", "mout_user_aclk266", GATE_IP_GEN, 4, 0, 0),
1055 GATE(CLK_TOP_RTC, "top_rtc", "aclk66_psgen", GATE_IP_GEN, 5, 0, 0),
1056 GATE(CLK_SMMU_ROTATOR, "smmu_rotator", "dout_gen_blk",
1057 GATE_IP_GEN, 6, 0, 0),
1058 GATE(CLK_SMMU_JPEG, "smmu_jpeg", "dout_jpg_blk", GATE_IP_GEN, 7, 0, 0),
1059 GATE(CLK_SMMU_MDMA1, "smmu_mdma1", "dout_gen_blk",
1060 GATE_IP_GEN, 9, 0, 0),
1061
1062 /* GATE_IP_GEN doesn't list gates for smmu_jpeg2 and mc */
1063 GATE(CLK_SMMU_JPEG2, "smmu_jpeg2", "dout_jpg_blk",
1064 GATE_BUS_GEN, 28, 0, 0),
1065 GATE(CLK_MC, "mc", "aclk66_psgen", GATE_BUS_GEN, 12, 0, 0),
1066
1067 /* GSCL Block */
1068 GATE(CLK_SCLK_GSCL_WA, "sclk_gscl_wa", "mout_user_aclk333_432_gscl",
1069 GATE_TOP_SCLK_GSCL, 6, 0, 0),
1070 GATE(CLK_SCLK_GSCL_WB, "sclk_gscl_wb", "mout_user_aclk333_432_gscl",
1071 GATE_TOP_SCLK_GSCL, 7, 0, 0),
691 1072
692 GATE(CLK_GSCL0, "gscl0", "aclk300_gscl", GATE_IP_GSCL0, 0, 0, 0), 1073 GATE(CLK_GSCL0, "gscl0", "aclk300_gscl", GATE_IP_GSCL0, 0, 0, 0),
693 GATE(CLK_GSCL1, "gscl1", "aclk300_gscl", GATE_IP_GSCL0, 1, 0, 0), 1074 GATE(CLK_GSCL1, "gscl1", "aclk300_gscl", GATE_IP_GSCL0, 1, 0, 0),
694 GATE(CLK_CLK_3AA, "clk_3aa", "aclk300_gscl", GATE_IP_GSCL0, 4, 0, 0), 1075 GATE(CLK_FIMC_3AA, "fimc_3aa", "aclk333_432_gscl",
695 1076 GATE_IP_GSCL0, 4, 0, 0),
696 GATE(CLK_SMMU_3AA, "smmu_3aa", "aclk333_432_gscl", GATE_IP_GSCL1, 2, 0, 1077 GATE(CLK_FIMC_LITE0, "fimc_lite0", "aclk333_432_gscl",
697 0), 1078 GATE_IP_GSCL0, 5, 0, 0),
698 GATE(CLK_SMMU_FIMCL0, "smmu_fimcl0", "aclk333_432_gscl", 1079 GATE(CLK_FIMC_LITE1, "fimc_lite1", "aclk333_432_gscl",
1080 GATE_IP_GSCL0, 6, 0, 0),
1081
1082 GATE(CLK_SMMU_3AA, "smmu_3aa", "dout_gscl_blk_333",
1083 GATE_IP_GSCL1, 2, 0, 0),
1084 GATE(CLK_SMMU_FIMCL0, "smmu_fimcl0", "dout_gscl_blk_333",
699 GATE_IP_GSCL1, 3, 0, 0), 1085 GATE_IP_GSCL1, 3, 0, 0),
700 GATE(CLK_SMMU_FIMCL1, "smmu_fimcl1", "aclk333_432_gscl", 1086 GATE(CLK_SMMU_FIMCL1, "smmu_fimcl1", "dout_gscl_blk_333",
701 GATE_IP_GSCL1, 4, 0, 0), 1087 GATE_IP_GSCL1, 4, 0, 0),
702 GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "aclk300_gscl", GATE_IP_GSCL1, 6, 0, 1088 GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "dout_gscl_blk_300",
703 0), 1089 GATE_IP_GSCL1, 6, 0, 0),
704 GATE(CLK_SMMU_GSCL1, "smmu_gscl1", "aclk300_gscl", GATE_IP_GSCL1, 7, 0, 1090 GATE(CLK_SMMU_GSCL1, "smmu_gscl1", "dout_gscl_blk_300",
705 0), 1091 GATE_IP_GSCL1, 7, 0, 0),
706 GATE(CLK_GSCL_WA, "gscl_wa", "aclk300_gscl", GATE_IP_GSCL1, 12, 0, 0), 1092 GATE(CLK_GSCL_WA, "gscl_wa", "sclk_gscl_wa", GATE_IP_GSCL1, 12, 0, 0),
707 GATE(CLK_GSCL_WB, "gscl_wb", "aclk300_gscl", GATE_IP_GSCL1, 13, 0, 0), 1093 GATE(CLK_GSCL_WB, "gscl_wb", "sclk_gscl_wb", GATE_IP_GSCL1, 13, 0, 0),
708 GATE(CLK_SMMU_FIMCL3, "smmu_fimcl3,", "aclk333_432_gscl", 1094 GATE(CLK_SMMU_FIMCL3, "smmu_fimcl3,", "dout_gscl_blk_333",
709 GATE_IP_GSCL1, 16, 0, 0), 1095 GATE_IP_GSCL1, 16, 0, 0),
710 GATE(CLK_FIMC_LITE3, "fimc_lite3", "aclk333_432_gscl", 1096 GATE(CLK_FIMC_LITE3, "fimc_lite3", "aclk333_432_gscl",
711 GATE_IP_GSCL1, 17, 0, 0), 1097 GATE_IP_GSCL1, 17, 0, 0),
712 1098
1099 /* MSCL Block */
1100 GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0),
1101 GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0),
1102 GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0),
1103 GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "dout_mscl_blk",
1104 GATE_IP_MSCL, 8, 0, 0),
1105 GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "dout_mscl_blk",
1106 GATE_IP_MSCL, 9, 0, 0),
1107 GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk",
1108 GATE_IP_MSCL, 10, 0, 0),
1109
713 GATE(CLK_FIMD1, "fimd1", "aclk300_disp1", GATE_IP_DISP1, 0, 0, 0), 1110 GATE(CLK_FIMD1, "fimd1", "aclk300_disp1", GATE_IP_DISP1, 0, 0, 0),
714 GATE(CLK_DSIM1, "dsim1", "aclk200_disp1", GATE_IP_DISP1, 3, 0, 0), 1111 GATE(CLK_DSIM1, "dsim1", "aclk200_disp1", GATE_IP_DISP1, 3, 0, 0),
715 GATE(CLK_DP1, "dp1", "aclk200_disp1", GATE_IP_DISP1, 4, 0, 0), 1112 GATE(CLK_DP1, "dp1", "aclk200_disp1", GATE_IP_DISP1, 4, 0, 0),
716 GATE(CLK_MIXER, "mixer", "aclk166", GATE_IP_DISP1, 5, 0, 0), 1113 GATE(CLK_MIXER, "mixer", "aclk200_disp1", GATE_IP_DISP1, 5, 0, 0),
717 GATE(CLK_HDMI, "hdmi", "aclk200_disp1", GATE_IP_DISP1, 6, 0, 0), 1114 GATE(CLK_HDMI, "hdmi", "aclk200_disp1", GATE_IP_DISP1, 6, 0, 0),
718 GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "aclk300_disp1", GATE_IP_DISP1, 8, 0, 1115 GATE(CLK_SMMU_FIMD1M0, "smmu_fimd1m0", "dout_disp1_blk",
719 0), 1116 GATE_IP_DISP1, 7, 0, 0),
1117 GATE(CLK_SMMU_FIMD1M1, "smmu_fimd1m1", "dout_disp1_blk",
1118 GATE_IP_DISP1, 8, 0, 0),
1119 GATE(CLK_SMMU_MIXER, "smmu_mixer", "aclk200_disp1",
1120 GATE_IP_DISP1, 9, 0, 0),
1121
1122 /* ISP */
1123 GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "dout_uart_isp",
1124 GATE_TOP_SCLK_ISP, 0, CLK_SET_RATE_PARENT, 0),
1125 GATE(CLK_SCLK_SPI0_ISP, "sclk_spi0_isp", "dout_spi0_isp_pre",
1126 GATE_TOP_SCLK_ISP, 1, CLK_SET_RATE_PARENT, 0),
1127 GATE(CLK_SCLK_SPI1_ISP, "sclk_spi1_isp", "dout_spi1_isp_pre",
1128 GATE_TOP_SCLK_ISP, 2, CLK_SET_RATE_PARENT, 0),
1129 GATE(CLK_SCLK_PWM_ISP, "sclk_pwm_isp", "dout_pwm_isp",
1130 GATE_TOP_SCLK_ISP, 3, CLK_SET_RATE_PARENT, 0),
1131 GATE(CLK_SCLK_ISP_SENSOR0, "sclk_isp_sensor0", "dout_isp_sensor0",
1132 GATE_TOP_SCLK_ISP, 4, CLK_SET_RATE_PARENT, 0),
1133 GATE(CLK_SCLK_ISP_SENSOR1, "sclk_isp_sensor1", "dout_isp_sensor1",
1134 GATE_TOP_SCLK_ISP, 8, CLK_SET_RATE_PARENT, 0),
1135 GATE(CLK_SCLK_ISP_SENSOR2, "sclk_isp_sensor2", "dout_isp_sensor2",
1136 GATE_TOP_SCLK_ISP, 12, CLK_SET_RATE_PARENT, 0),
720 1137
721 GATE(CLK_MFC, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0), 1138 GATE(CLK_MFC, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0),
722 GATE(CLK_SMMU_MFCL, "smmu_mfcl", "aclk333", GATE_IP_MFC, 1, 0, 0), 1139 GATE(CLK_SMMU_MFCL, "smmu_mfcl", "dout_mfc_blk", GATE_IP_MFC, 1, 0, 0),
723 GATE(CLK_SMMU_MFCR, "smmu_mfcr", "aclk333", GATE_IP_MFC, 2, 0, 0), 1140 GATE(CLK_SMMU_MFCR, "smmu_mfcr", "dout_mfc_blk", GATE_IP_MFC, 2, 0, 0),
724
725 GATE(CLK_G3D, "g3d", "aclkg3d", GATE_IP_G3D, 9, 0, 0),
726 1141
727 GATE(CLK_ROTATOR, "rotator", "aclk266", GATE_IP_GEN, 1, 0, 0), 1142 GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
728 GATE(CLK_JPEG, "jpeg", "aclk300_jpeg", GATE_IP_GEN, 2, 0, 0),
729 GATE(CLK_JPEG2, "jpeg2", "aclk300_jpeg", GATE_IP_GEN, 3, 0, 0),
730 GATE(CLK_MDMA1, "mdma1", "aclk266", GATE_IP_GEN, 4, 0, 0),
731 GATE(CLK_SMMU_ROTATOR, "smmu_rotator", "aclk266", GATE_IP_GEN, 6, 0, 0),
732 GATE(CLK_SMMU_JPEG, "smmu_jpeg", "aclk300_jpeg", GATE_IP_GEN, 7, 0, 0),
733 GATE(CLK_SMMU_MDMA1, "smmu_mdma1", "aclk266", GATE_IP_GEN, 9, 0, 0),
734
735 GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0),
736 GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0),
737 GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0),
738 GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "aclk400_mscl", GATE_IP_MSCL, 8, 0,
739 0),
740 GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "aclk400_mscl", GATE_IP_MSCL, 9, 0,
741 0),
742 GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "aclk400_mscl", GATE_IP_MSCL, 10, 0,
743 0),
744 GATE(CLK_SMMU_MIXER, "smmu_mixer", "aclk200_disp1", GATE_IP_DISP1, 9, 0,
745 0),
746}; 1143};
747 1144
748static struct samsung_pll_clock exynos5420_plls[nr_plls] __initdata = { 1145static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
749 [apll] = PLL(pll_2550, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK, 1146 [apll] = PLL(pll_2550, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
750 APLL_CON0, NULL), 1147 APLL_CON0, NULL),
751 [cpll] = PLL(pll_2550, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK, 1148 [cpll] = PLL(pll_2550, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
@@ -776,8 +1173,11 @@ static struct of_device_id ext_clk_match[] __initdata = {
776}; 1173};
777 1174
778/* register exynos5420 clocks */ 1175/* register exynos5420 clocks */
779static void __init exynos5420_clk_init(struct device_node *np) 1176static void __init exynos5x_clk_init(struct device_node *np,
1177 enum exynos5x_soc soc)
780{ 1178{
1179 struct samsung_clk_provider *ctx;
1180
781 if (np) { 1181 if (np) {
782 reg_base = of_iomap(np, 0); 1182 reg_base = of_iomap(np, 0);
783 if (!reg_base) 1183 if (!reg_base)
@@ -786,23 +1186,56 @@ static void __init exynos5420_clk_init(struct device_node *np)
786 panic("%s: unable to determine soc\n", __func__); 1186 panic("%s: unable to determine soc\n", __func__);
787 } 1187 }
788 1188
789 samsung_clk_init(np, reg_base, CLK_NR_CLKS); 1189 exynos5x_soc = soc;
790 samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks, 1190
791 ARRAY_SIZE(exynos5420_fixed_rate_ext_clks), 1191 ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
1192 if (!ctx)
1193 panic("%s: unable to allocate context.\n", __func__);
1194
1195 samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks,
1196 ARRAY_SIZE(exynos5x_fixed_rate_ext_clks),
792 ext_clk_match); 1197 ext_clk_match);
793 samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls), 1198 samsung_clk_register_pll(ctx, exynos5x_plls, ARRAY_SIZE(exynos5x_plls),
794 reg_base); 1199 reg_base);
795 samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks, 1200 samsung_clk_register_fixed_rate(ctx, exynos5x_fixed_rate_clks,
796 ARRAY_SIZE(exynos5420_fixed_rate_clks)); 1201 ARRAY_SIZE(exynos5x_fixed_rate_clks));
797 samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks, 1202 samsung_clk_register_fixed_factor(ctx, exynos5x_fixed_factor_clks,
798 ARRAY_SIZE(exynos5420_fixed_factor_clks)); 1203 ARRAY_SIZE(exynos5x_fixed_factor_clks));
799 samsung_clk_register_mux(exynos5420_mux_clks, 1204 samsung_clk_register_mux(ctx, exynos5x_mux_clks,
800 ARRAY_SIZE(exynos5420_mux_clks)); 1205 ARRAY_SIZE(exynos5x_mux_clks));
801 samsung_clk_register_div(exynos5420_div_clks, 1206 samsung_clk_register_div(ctx, exynos5x_div_clks,
802 ARRAY_SIZE(exynos5420_div_clks)); 1207 ARRAY_SIZE(exynos5x_div_clks));
803 samsung_clk_register_gate(exynos5420_gate_clks, 1208 samsung_clk_register_gate(ctx, exynos5x_gate_clks,
804 ARRAY_SIZE(exynos5420_gate_clks)); 1209 ARRAY_SIZE(exynos5x_gate_clks));
1210
1211 if (soc == EXYNOS5420) {
1212 samsung_clk_register_mux(ctx, exynos5420_mux_clks,
1213 ARRAY_SIZE(exynos5420_mux_clks));
1214 samsung_clk_register_div(ctx, exynos5420_div_clks,
1215 ARRAY_SIZE(exynos5420_div_clks));
1216 } else {
1217 samsung_clk_register_fixed_factor(
1218 ctx, exynos5800_fixed_factor_clks,
1219 ARRAY_SIZE(exynos5800_fixed_factor_clks));
1220 samsung_clk_register_mux(ctx, exynos5800_mux_clks,
1221 ARRAY_SIZE(exynos5800_mux_clks));
1222 samsung_clk_register_div(ctx, exynos5800_div_clks,
1223 ARRAY_SIZE(exynos5800_div_clks));
1224 samsung_clk_register_gate(ctx, exynos5800_gate_clks,
1225 ARRAY_SIZE(exynos5800_gate_clks));
1226 }
805 1227
806 exynos5420_clk_sleep_init(); 1228 exynos5420_clk_sleep_init();
807} 1229}
1230
1231static void __init exynos5420_clk_init(struct device_node *np)
1232{
1233 exynos5x_clk_init(np, EXYNOS5420);
1234}
808CLK_OF_DECLARE(exynos5420_clk, "samsung,exynos5420-clock", exynos5420_clk_init); 1235CLK_OF_DECLARE(exynos5420_clk, "samsung,exynos5420-clock", exynos5420_clk_init);
1236
1237static void __init exynos5800_clk_init(struct device_node *np)
1238{
1239 exynos5x_clk_init(np, EXYNOS5800);
1240}
1241CLK_OF_DECLARE(exynos5800_clk, "samsung,exynos5800-clock", exynos5800_clk_init);
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c
index 2bfad5a993d0..647f1440aa6a 100644
--- a/drivers/clk/samsung/clk-exynos5440.c
+++ b/drivers/clk/samsung/clk-exynos5440.c
@@ -93,6 +93,7 @@ static struct of_device_id ext_clk_match[] __initdata = {
93static void __init exynos5440_clk_init(struct device_node *np) 93static void __init exynos5440_clk_init(struct device_node *np)
94{ 94{
95 void __iomem *reg_base; 95 void __iomem *reg_base;
96 struct samsung_clk_provider *ctx;
96 97
97 reg_base = of_iomap(np, 0); 98 reg_base = of_iomap(np, 0);
98 if (!reg_base) { 99 if (!reg_base) {
@@ -101,22 +102,25 @@ static void __init exynos5440_clk_init(struct device_node *np)
101 return; 102 return;
102 } 103 }
103 104
104 samsung_clk_init(np, reg_base, CLK_NR_CLKS); 105 ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
105 samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks, 106 if (!ctx)
107 panic("%s: unable to allocate context.\n", __func__);
108
109 samsung_clk_of_register_fixed_ext(ctx, exynos5440_fixed_rate_ext_clks,
106 ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match); 110 ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
107 111
108 samsung_clk_register_pll2550x("cplla", "xtal", reg_base + 0x1c, 0x10); 112 samsung_clk_register_pll2550x("cplla", "xtal", reg_base + 0x1c, 0x10);
109 samsung_clk_register_pll2550x("cpllb", "xtal", reg_base + 0x20, 0x10); 113 samsung_clk_register_pll2550x("cpllb", "xtal", reg_base + 0x20, 0x10);
110 114
111 samsung_clk_register_fixed_rate(exynos5440_fixed_rate_clks, 115 samsung_clk_register_fixed_rate(ctx, exynos5440_fixed_rate_clks,
112 ARRAY_SIZE(exynos5440_fixed_rate_clks)); 116 ARRAY_SIZE(exynos5440_fixed_rate_clks));
113 samsung_clk_register_fixed_factor(exynos5440_fixed_factor_clks, 117 samsung_clk_register_fixed_factor(ctx, exynos5440_fixed_factor_clks,
114 ARRAY_SIZE(exynos5440_fixed_factor_clks)); 118 ARRAY_SIZE(exynos5440_fixed_factor_clks));
115 samsung_clk_register_mux(exynos5440_mux_clks, 119 samsung_clk_register_mux(ctx, exynos5440_mux_clks,
116 ARRAY_SIZE(exynos5440_mux_clks)); 120 ARRAY_SIZE(exynos5440_mux_clks));
117 samsung_clk_register_div(exynos5440_div_clks, 121 samsung_clk_register_div(ctx, exynos5440_div_clks,
118 ARRAY_SIZE(exynos5440_div_clks)); 122 ARRAY_SIZE(exynos5440_div_clks));
119 samsung_clk_register_gate(exynos5440_gate_clks, 123 samsung_clk_register_gate(ctx, exynos5440_gate_clks,
120 ARRAY_SIZE(exynos5440_gate_clks)); 124 ARRAY_SIZE(exynos5440_gate_clks));
121 125
122 pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk")); 126 pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk"));
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 81e6d2f49aa0..b07fad2a9167 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -11,6 +11,7 @@
11 11
12#include <linux/errno.h> 12#include <linux/errno.h>
13#include <linux/hrtimer.h> 13#include <linux/hrtimer.h>
14#include <linux/delay.h>
14#include "clk.h" 15#include "clk.h"
15#include "clk-pll.h" 16#include "clk-pll.h"
16 17
@@ -59,6 +60,72 @@ static long samsung_pll_round_rate(struct clk_hw *hw,
59} 60}
60 61
61/* 62/*
63 * PLL2126 Clock Type
64 */
65
66#define PLL2126_MDIV_MASK (0xff)
67#define PLL2126_PDIV_MASK (0x3f)
68#define PLL2126_SDIV_MASK (0x3)
69#define PLL2126_MDIV_SHIFT (16)
70#define PLL2126_PDIV_SHIFT (8)
71#define PLL2126_SDIV_SHIFT (0)
72
73static unsigned long samsung_pll2126_recalc_rate(struct clk_hw *hw,
74 unsigned long parent_rate)
75{
76 struct samsung_clk_pll *pll = to_clk_pll(hw);
77 u32 pll_con, mdiv, pdiv, sdiv;
78 u64 fvco = parent_rate;
79
80 pll_con = __raw_readl(pll->con_reg);
81 mdiv = (pll_con >> PLL2126_MDIV_SHIFT) & PLL2126_MDIV_MASK;
82 pdiv = (pll_con >> PLL2126_PDIV_SHIFT) & PLL2126_PDIV_MASK;
83 sdiv = (pll_con >> PLL2126_SDIV_SHIFT) & PLL2126_SDIV_MASK;
84
85 fvco *= (mdiv + 8);
86 do_div(fvco, (pdiv + 2) << sdiv);
87
88 return (unsigned long)fvco;
89}
90
91static const struct clk_ops samsung_pll2126_clk_ops = {
92 .recalc_rate = samsung_pll2126_recalc_rate,
93};
94
95/*
96 * PLL3000 Clock Type
97 */
98
99#define PLL3000_MDIV_MASK (0xff)
100#define PLL3000_PDIV_MASK (0x3)
101#define PLL3000_SDIV_MASK (0x3)
102#define PLL3000_MDIV_SHIFT (16)
103#define PLL3000_PDIV_SHIFT (8)
104#define PLL3000_SDIV_SHIFT (0)
105
106static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw,
107 unsigned long parent_rate)
108{
109 struct samsung_clk_pll *pll = to_clk_pll(hw);
110 u32 pll_con, mdiv, pdiv, sdiv;
111 u64 fvco = parent_rate;
112
113 pll_con = __raw_readl(pll->con_reg);
114 mdiv = (pll_con >> PLL3000_MDIV_SHIFT) & PLL3000_MDIV_MASK;
115 pdiv = (pll_con >> PLL3000_PDIV_SHIFT) & PLL3000_PDIV_MASK;
116 sdiv = (pll_con >> PLL3000_SDIV_SHIFT) & PLL3000_SDIV_MASK;
117
118 fvco *= (2 * (mdiv + 8));
119 do_div(fvco, pdiv << sdiv);
120
121 return (unsigned long)fvco;
122}
123
124static const struct clk_ops samsung_pll3000_clk_ops = {
125 .recalc_rate = samsung_pll3000_recalc_rate,
126};
127
128/*
62 * PLL35xx Clock Type 129 * PLL35xx Clock Type
63 */ 130 */
64/* Maximum lock time can be 270 * PDIV cycles */ 131/* Maximum lock time can be 270 * PDIV cycles */
@@ -564,7 +631,9 @@ static const struct clk_ops samsung_pll46xx_clk_min_ops = {
564#define PLL6552_PDIV_MASK 0x3f 631#define PLL6552_PDIV_MASK 0x3f
565#define PLL6552_SDIV_MASK 0x7 632#define PLL6552_SDIV_MASK 0x7
566#define PLL6552_MDIV_SHIFT 16 633#define PLL6552_MDIV_SHIFT 16
634#define PLL6552_MDIV_SHIFT_2416 14
567#define PLL6552_PDIV_SHIFT 8 635#define PLL6552_PDIV_SHIFT 8
636#define PLL6552_PDIV_SHIFT_2416 5
568#define PLL6552_SDIV_SHIFT 0 637#define PLL6552_SDIV_SHIFT 0
569 638
570static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, 639static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
@@ -575,8 +644,13 @@ static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
575 u64 fvco = parent_rate; 644 u64 fvco = parent_rate;
576 645
577 pll_con = __raw_readl(pll->con_reg); 646 pll_con = __raw_readl(pll->con_reg);
578 mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK; 647 if (pll->type == pll_6552_s3c2416) {
579 pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK; 648 mdiv = (pll_con >> PLL6552_MDIV_SHIFT_2416) & PLL6552_MDIV_MASK;
649 pdiv = (pll_con >> PLL6552_PDIV_SHIFT_2416) & PLL6552_PDIV_MASK;
650 } else {
651 mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK;
652 pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK;
653 }
580 sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK; 654 sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK;
581 655
582 fvco *= mdiv; 656 fvco *= mdiv;
@@ -628,6 +702,169 @@ static const struct clk_ops samsung_pll6553_clk_ops = {
628}; 702};
629 703
630/* 704/*
705 * PLL Clock Type of S3C24XX before S3C2443
706 */
707
708#define PLLS3C2410_MDIV_MASK (0xff)
709#define PLLS3C2410_PDIV_MASK (0x1f)
710#define PLLS3C2410_SDIV_MASK (0x3)
711#define PLLS3C2410_MDIV_SHIFT (12)
712#define PLLS3C2410_PDIV_SHIFT (4)
713#define PLLS3C2410_SDIV_SHIFT (0)
714
715#define PLLS3C2410_ENABLE_REG_OFFSET 0x10
716
717static unsigned long samsung_s3c2410_pll_recalc_rate(struct clk_hw *hw,
718 unsigned long parent_rate)
719{
720 struct samsung_clk_pll *pll = to_clk_pll(hw);
721 u32 pll_con, mdiv, pdiv, sdiv;
722 u64 fvco = parent_rate;
723
724 pll_con = __raw_readl(pll->con_reg);
725 mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
726 pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
727 sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
728
729 fvco *= (mdiv + 8);
730 do_div(fvco, (pdiv + 2) << sdiv);
731
732 return (unsigned int)fvco;
733}
734
735static unsigned long samsung_s3c2440_mpll_recalc_rate(struct clk_hw *hw,
736 unsigned long parent_rate)
737{
738 struct samsung_clk_pll *pll = to_clk_pll(hw);
739 u32 pll_con, mdiv, pdiv, sdiv;
740 u64 fvco = parent_rate;
741
742 pll_con = __raw_readl(pll->con_reg);
743 mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
744 pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
745 sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
746
747 fvco *= (2 * (mdiv + 8));
748 do_div(fvco, (pdiv + 2) << sdiv);
749
750 return (unsigned int)fvco;
751}
752
753static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
754 unsigned long prate)
755{
756 struct samsung_clk_pll *pll = to_clk_pll(hw);
757 const struct samsung_pll_rate_table *rate;
758 u32 tmp;
759
760 /* Get required rate settings from table */
761 rate = samsung_get_pll_settings(pll, drate);
762 if (!rate) {
763 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
764 drate, __clk_get_name(hw->clk));
765 return -EINVAL;
766 }
767
768 tmp = __raw_readl(pll->con_reg);
769
770 /* Change PLL PMS values */
771 tmp &= ~((PLLS3C2410_MDIV_MASK << PLLS3C2410_MDIV_SHIFT) |
772 (PLLS3C2410_PDIV_MASK << PLLS3C2410_PDIV_SHIFT) |
773 (PLLS3C2410_SDIV_MASK << PLLS3C2410_SDIV_SHIFT));
774 tmp |= (rate->mdiv << PLLS3C2410_MDIV_SHIFT) |
775 (rate->pdiv << PLLS3C2410_PDIV_SHIFT) |
776 (rate->sdiv << PLLS3C2410_SDIV_SHIFT);
777 __raw_writel(tmp, pll->con_reg);
778
779 /* Time to settle according to the manual */
780 udelay(300);
781
782 return 0;
783}
784
785static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable)
786{
787 struct samsung_clk_pll *pll = to_clk_pll(hw);
788 u32 pll_en = __raw_readl(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
789 u32 pll_en_orig = pll_en;
790
791 if (enable)
792 pll_en &= ~BIT(bit);
793 else
794 pll_en |= BIT(bit);
795
796 __raw_writel(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
797
798 /* if we started the UPLL, then allow to settle */
799 if (enable && (pll_en_orig & BIT(bit)))
800 udelay(300);
801
802 return 0;
803}
804
805static int samsung_s3c2410_mpll_enable(struct clk_hw *hw)
806{
807 return samsung_s3c2410_pll_enable(hw, 5, true);
808}
809
810static void samsung_s3c2410_mpll_disable(struct clk_hw *hw)
811{
812 samsung_s3c2410_pll_enable(hw, 5, false);
813}
814
815static int samsung_s3c2410_upll_enable(struct clk_hw *hw)
816{
817 return samsung_s3c2410_pll_enable(hw, 7, true);
818}
819
820static void samsung_s3c2410_upll_disable(struct clk_hw *hw)
821{
822 samsung_s3c2410_pll_enable(hw, 7, false);
823}
824
825static const struct clk_ops samsung_s3c2410_mpll_clk_min_ops = {
826 .recalc_rate = samsung_s3c2410_pll_recalc_rate,
827 .enable = samsung_s3c2410_mpll_enable,
828 .disable = samsung_s3c2410_mpll_disable,
829};
830
831static const struct clk_ops samsung_s3c2410_upll_clk_min_ops = {
832 .recalc_rate = samsung_s3c2410_pll_recalc_rate,
833 .enable = samsung_s3c2410_upll_enable,
834 .disable = samsung_s3c2410_upll_disable,
835};
836
837static const struct clk_ops samsung_s3c2440_mpll_clk_min_ops = {
838 .recalc_rate = samsung_s3c2440_mpll_recalc_rate,
839 .enable = samsung_s3c2410_mpll_enable,
840 .disable = samsung_s3c2410_mpll_disable,
841};
842
843static const struct clk_ops samsung_s3c2410_mpll_clk_ops = {
844 .recalc_rate = samsung_s3c2410_pll_recalc_rate,
845 .enable = samsung_s3c2410_mpll_enable,
846 .disable = samsung_s3c2410_mpll_disable,
847 .round_rate = samsung_pll_round_rate,
848 .set_rate = samsung_s3c2410_pll_set_rate,
849};
850
851static const struct clk_ops samsung_s3c2410_upll_clk_ops = {
852 .recalc_rate = samsung_s3c2410_pll_recalc_rate,
853 .enable = samsung_s3c2410_upll_enable,
854 .disable = samsung_s3c2410_upll_disable,
855 .round_rate = samsung_pll_round_rate,
856 .set_rate = samsung_s3c2410_pll_set_rate,
857};
858
859static const struct clk_ops samsung_s3c2440_mpll_clk_ops = {
860 .recalc_rate = samsung_s3c2440_mpll_recalc_rate,
861 .enable = samsung_s3c2410_mpll_enable,
862 .disable = samsung_s3c2410_mpll_disable,
863 .round_rate = samsung_pll_round_rate,
864 .set_rate = samsung_s3c2410_pll_set_rate,
865};
866
867/*
631 * PLL2550x Clock Type 868 * PLL2550x Clock Type
632 */ 869 */
633 870
@@ -710,8 +947,206 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name,
710 return clk; 947 return clk;
711} 948}
712 949
713static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, 950/*
714 void __iomem *base) 951 * PLL2550xx Clock Type
952 */
953
954/* Maximum lock time can be 270 * PDIV cycles */
955#define PLL2550XX_LOCK_FACTOR 270
956
957#define PLL2550XX_M_MASK 0x3FF
958#define PLL2550XX_P_MASK 0x3F
959#define PLL2550XX_S_MASK 0x7
960#define PLL2550XX_LOCK_STAT_MASK 0x1
961#define PLL2550XX_M_SHIFT 9
962#define PLL2550XX_P_SHIFT 3
963#define PLL2550XX_S_SHIFT 0
964#define PLL2550XX_LOCK_STAT_SHIFT 21
965
966static unsigned long samsung_pll2550xx_recalc_rate(struct clk_hw *hw,
967 unsigned long parent_rate)
968{
969 struct samsung_clk_pll *pll = to_clk_pll(hw);
970 u32 mdiv, pdiv, sdiv, pll_con;
971 u64 fvco = parent_rate;
972
973 pll_con = __raw_readl(pll->con_reg);
974 mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK;
975 pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK;
976 sdiv = (pll_con >> PLL2550XX_S_SHIFT) & PLL2550XX_S_MASK;
977
978 fvco *= mdiv;
979 do_div(fvco, (pdiv << sdiv));
980
981 return (unsigned long)fvco;
982}
983
984static inline bool samsung_pll2550xx_mp_change(u32 mdiv, u32 pdiv, u32 pll_con)
985{
986 u32 old_mdiv, old_pdiv;
987
988 old_mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK;
989 old_pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK;
990
991 return mdiv != old_mdiv || pdiv != old_pdiv;
992}
993
994static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate,
995 unsigned long prate)
996{
997 struct samsung_clk_pll *pll = to_clk_pll(hw);
998 const struct samsung_pll_rate_table *rate;
999 u32 tmp;
1000
1001 /* Get required rate settings from table */
1002 rate = samsung_get_pll_settings(pll, drate);
1003 if (!rate) {
1004 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
1005 drate, __clk_get_name(hw->clk));
1006 return -EINVAL;
1007 }
1008
1009 tmp = __raw_readl(pll->con_reg);
1010
1011 if (!(samsung_pll2550xx_mp_change(rate->mdiv, rate->pdiv, tmp))) {
1012 /* If only s change, change just s value only*/
1013 tmp &= ~(PLL2550XX_S_MASK << PLL2550XX_S_SHIFT);
1014 tmp |= rate->sdiv << PLL2550XX_S_SHIFT;
1015 __raw_writel(tmp, pll->con_reg);
1016
1017 return 0;
1018 }
1019
1020 /* Set PLL lock time. */
1021 __raw_writel(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg);
1022
1023 /* Change PLL PMS values */
1024 tmp &= ~((PLL2550XX_M_MASK << PLL2550XX_M_SHIFT) |
1025 (PLL2550XX_P_MASK << PLL2550XX_P_SHIFT) |
1026 (PLL2550XX_S_MASK << PLL2550XX_S_SHIFT));
1027 tmp |= (rate->mdiv << PLL2550XX_M_SHIFT) |
1028 (rate->pdiv << PLL2550XX_P_SHIFT) |
1029 (rate->sdiv << PLL2550XX_S_SHIFT);
1030 __raw_writel(tmp, pll->con_reg);
1031
1032 /* wait_lock_time */
1033 do {
1034 cpu_relax();
1035 tmp = __raw_readl(pll->con_reg);
1036 } while (!(tmp & (PLL2550XX_LOCK_STAT_MASK
1037 << PLL2550XX_LOCK_STAT_SHIFT)));
1038
1039 return 0;
1040}
1041
1042static const struct clk_ops samsung_pll2550xx_clk_ops = {
1043 .recalc_rate = samsung_pll2550xx_recalc_rate,
1044 .round_rate = samsung_pll_round_rate,
1045 .set_rate = samsung_pll2550xx_set_rate,
1046};
1047
1048static const struct clk_ops samsung_pll2550xx_clk_min_ops = {
1049 .recalc_rate = samsung_pll2550xx_recalc_rate,
1050};
1051
1052/*
1053 * PLL2650XX Clock Type
1054 */
1055
1056/* Maximum lock time can be 3000 * PDIV cycles */
1057#define PLL2650XX_LOCK_FACTOR 3000
1058
1059#define PLL2650XX_MDIV_SHIFT 9
1060#define PLL2650XX_PDIV_SHIFT 3
1061#define PLL2650XX_SDIV_SHIFT 0
1062#define PLL2650XX_KDIV_SHIFT 0
1063#define PLL2650XX_MDIV_MASK 0x1ff
1064#define PLL2650XX_PDIV_MASK 0x3f
1065#define PLL2650XX_SDIV_MASK 0x7
1066#define PLL2650XX_KDIV_MASK 0xffff
1067#define PLL2650XX_PLL_ENABLE_SHIFT 23
1068#define PLL2650XX_PLL_LOCKTIME_SHIFT 21
1069#define PLL2650XX_PLL_FOUTMASK_SHIFT 31
1070
1071static unsigned long samsung_pll2650xx_recalc_rate(struct clk_hw *hw,
1072 unsigned long parent_rate)
1073{
1074 struct samsung_clk_pll *pll = to_clk_pll(hw);
1075 u32 mdiv, pdiv, sdiv, pll_con0, pll_con2;
1076 s16 kdiv;
1077 u64 fvco = parent_rate;
1078
1079 pll_con0 = __raw_readl(pll->con_reg);
1080 pll_con2 = __raw_readl(pll->con_reg + 8);
1081 mdiv = (pll_con0 >> PLL2650XX_MDIV_SHIFT) & PLL2650XX_MDIV_MASK;
1082 pdiv = (pll_con0 >> PLL2650XX_PDIV_SHIFT) & PLL2650XX_PDIV_MASK;
1083 sdiv = (pll_con0 >> PLL2650XX_SDIV_SHIFT) & PLL2650XX_SDIV_MASK;
1084 kdiv = (s16)(pll_con2 & PLL2650XX_KDIV_MASK);
1085
1086 fvco *= (mdiv << 16) + kdiv;
1087 do_div(fvco, (pdiv << sdiv));
1088 fvco >>= 16;
1089
1090 return (unsigned long)fvco;
1091}
1092
1093static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate,
1094 unsigned long parent_rate)
1095{
1096 struct samsung_clk_pll *pll = to_clk_pll(hw);
1097 u32 tmp, pll_con0, pll_con2;
1098 const struct samsung_pll_rate_table *rate;
1099
1100 rate = samsung_get_pll_settings(pll, drate);
1101 if (!rate) {
1102 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
1103 drate, __clk_get_name(hw->clk));
1104 return -EINVAL;
1105 }
1106
1107 pll_con0 = __raw_readl(pll->con_reg);
1108 pll_con2 = __raw_readl(pll->con_reg + 8);
1109
1110 /* Change PLL PMS values */
1111 pll_con0 &= ~(PLL2650XX_MDIV_MASK << PLL2650XX_MDIV_SHIFT |
1112 PLL2650XX_PDIV_MASK << PLL2650XX_PDIV_SHIFT |
1113 PLL2650XX_SDIV_MASK << PLL2650XX_SDIV_SHIFT);
1114 pll_con0 |= rate->mdiv << PLL2650XX_MDIV_SHIFT;
1115 pll_con0 |= rate->pdiv << PLL2650XX_PDIV_SHIFT;
1116 pll_con0 |= rate->sdiv << PLL2650XX_SDIV_SHIFT;
1117 pll_con0 |= 1 << PLL2650XX_PLL_ENABLE_SHIFT;
1118 pll_con0 |= 1 << PLL2650XX_PLL_FOUTMASK_SHIFT;
1119
1120 pll_con2 &= ~(PLL2650XX_KDIV_MASK << PLL2650XX_KDIV_SHIFT);
1121 pll_con2 |= ((~(rate->kdiv) + 1) & PLL2650XX_KDIV_MASK)
1122 << PLL2650XX_KDIV_SHIFT;
1123
1124 /* Set PLL lock time. */
1125 __raw_writel(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg);
1126
1127 __raw_writel(pll_con0, pll->con_reg);
1128 __raw_writel(pll_con2, pll->con_reg + 8);
1129
1130 do {
1131 tmp = __raw_readl(pll->con_reg);
1132 } while (!(tmp & (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT)));
1133
1134 return 0;
1135}
1136
1137static const struct clk_ops samsung_pll2650xx_clk_ops = {
1138 .recalc_rate = samsung_pll2650xx_recalc_rate,
1139 .set_rate = samsung_pll2650xx_set_rate,
1140 .round_rate = samsung_pll_round_rate,
1141};
1142
1143static const struct clk_ops samsung_pll2650xx_clk_min_ops = {
1144 .recalc_rate = samsung_pll2650xx_recalc_rate,
1145};
1146
1147static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
1148 struct samsung_pll_clock *pll_clk,
1149 void __iomem *base)
715{ 1150{
716 struct samsung_clk_pll *pll; 1151 struct samsung_clk_pll *pll;
717 struct clk *clk; 1152 struct clk *clk;
@@ -746,6 +1181,12 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
746 } 1181 }
747 1182
748 switch (pll_clk->type) { 1183 switch (pll_clk->type) {
1184 case pll_2126:
1185 init.ops = &samsung_pll2126_clk_ops;
1186 break;
1187 case pll_3000:
1188 init.ops = &samsung_pll3000_clk_ops;
1189 break;
749 /* clk_ops for 35xx and 2550 are similar */ 1190 /* clk_ops for 35xx and 2550 are similar */
750 case pll_35xx: 1191 case pll_35xx:
751 case pll_2550: 1192 case pll_2550:
@@ -773,6 +1214,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
773 init.ops = &samsung_pll36xx_clk_ops; 1214 init.ops = &samsung_pll36xx_clk_ops;
774 break; 1215 break;
775 case pll_6552: 1216 case pll_6552:
1217 case pll_6552_s3c2416:
776 init.ops = &samsung_pll6552_clk_ops; 1218 init.ops = &samsung_pll6552_clk_ops;
777 break; 1219 break;
778 case pll_6553: 1220 case pll_6553:
@@ -786,6 +1228,36 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
786 else 1228 else
787 init.ops = &samsung_pll46xx_clk_ops; 1229 init.ops = &samsung_pll46xx_clk_ops;
788 break; 1230 break;
1231 case pll_s3c2410_mpll:
1232 if (!pll->rate_table)
1233 init.ops = &samsung_s3c2410_mpll_clk_min_ops;
1234 else
1235 init.ops = &samsung_s3c2410_mpll_clk_ops;
1236 break;
1237 case pll_s3c2410_upll:
1238 if (!pll->rate_table)
1239 init.ops = &samsung_s3c2410_upll_clk_min_ops;
1240 else
1241 init.ops = &samsung_s3c2410_upll_clk_ops;
1242 break;
1243 case pll_s3c2440_mpll:
1244 if (!pll->rate_table)
1245 init.ops = &samsung_s3c2440_mpll_clk_min_ops;
1246 else
1247 init.ops = &samsung_s3c2440_mpll_clk_ops;
1248 break;
1249 case pll_2550xx:
1250 if (!pll->rate_table)
1251 init.ops = &samsung_pll2550xx_clk_min_ops;
1252 else
1253 init.ops = &samsung_pll2550xx_clk_ops;
1254 break;
1255 case pll_2650xx:
1256 if (!pll->rate_table)
1257 init.ops = &samsung_pll2650xx_clk_min_ops;
1258 else
1259 init.ops = &samsung_pll2650xx_clk_ops;
1260 break;
789 default: 1261 default:
790 pr_warn("%s: Unknown pll type for pll clk %s\n", 1262 pr_warn("%s: Unknown pll type for pll clk %s\n",
791 __func__, pll_clk->name); 1263 __func__, pll_clk->name);
@@ -804,7 +1276,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
804 return; 1276 return;
805 } 1277 }
806 1278
807 samsung_clk_add_lookup(clk, pll_clk->id); 1279 samsung_clk_add_lookup(ctx, clk, pll_clk->id);
808 1280
809 if (!pll_clk->alias) 1281 if (!pll_clk->alias)
810 return; 1282 return;
@@ -815,11 +1287,12 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
815 __func__, pll_clk->name, ret); 1287 __func__, pll_clk->name, ret);
816} 1288}
817 1289
818void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, 1290void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
819 unsigned int nr_pll, void __iomem *base) 1291 struct samsung_pll_clock *pll_list,
1292 unsigned int nr_pll, void __iomem *base)
820{ 1293{
821 int cnt; 1294 int cnt;
822 1295
823 for (cnt = 0; cnt < nr_pll; cnt++) 1296 for (cnt = 0; cnt < nr_pll; cnt++)
824 _samsung_clk_register_pll(&pll_list[cnt], base); 1297 _samsung_clk_register_pll(ctx, &pll_list[cnt], base);
825} 1298}
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index 6c39030080fb..c0ed4d41fd90 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -13,6 +13,8 @@
13#define __SAMSUNG_CLK_PLL_H 13#define __SAMSUNG_CLK_PLL_H
14 14
15enum samsung_pll_type { 15enum samsung_pll_type {
16 pll_2126,
17 pll_3000,
16 pll_35xx, 18 pll_35xx,
17 pll_36xx, 19 pll_36xx,
18 pll_2550, 20 pll_2550,
@@ -24,7 +26,13 @@ enum samsung_pll_type {
24 pll_4650, 26 pll_4650,
25 pll_4650c, 27 pll_4650c,
26 pll_6552, 28 pll_6552,
29 pll_6552_s3c2416,
27 pll_6553, 30 pll_6553,
31 pll_s3c2410_mpll,
32 pll_s3c2410_upll,
33 pll_s3c2440_mpll,
34 pll_2550xx,
35 pll_2650xx,
28}; 36};
29 37
30#define PLL_35XX_RATE(_rate, _m, _p, _s) \ 38#define PLL_35XX_RATE(_rate, _m, _p, _s) \
diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c
new file mode 100644
index 000000000000..0449cc0458ed
--- /dev/null
+++ b/drivers/clk/samsung/clk-s3c2410-dclk.c
@@ -0,0 +1,440 @@
1/*
2 * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Common Clock Framework support for s3c24xx external clock output.
9 */
10
11#include <linux/platform_device.h>
12#include <linux/module.h>
13#include "clk.h"
14
15/* legacy access to misccr, until dt conversion is finished */
16#include <mach/hardware.h>
17#include <mach/regs-gpio.h>
18
19#define MUX_DCLK0 0
20#define MUX_DCLK1 1
21#define DIV_DCLK0 2
22#define DIV_DCLK1 3
23#define GATE_DCLK0 4
24#define GATE_DCLK1 5
25#define MUX_CLKOUT0 6
26#define MUX_CLKOUT1 7
27#define DCLK_MAX_CLKS (MUX_CLKOUT1 + 1)
28
29enum supported_socs {
30 S3C2410,
31 S3C2412,
32 S3C2440,
33 S3C2443,
34};
35
36struct s3c24xx_dclk_drv_data {
37 const char **clkout0_parent_names;
38 int clkout0_num_parents;
39 const char **clkout1_parent_names;
40 int clkout1_num_parents;
41 const char **mux_parent_names;
42 int mux_num_parents;
43};
44
45/*
46 * Clock for output-parent selection in misccr
47 */
48
49struct s3c24xx_clkout {
50 struct clk_hw hw;
51 u32 mask;
52 u8 shift;
53};
54
55#define to_s3c24xx_clkout(_hw) container_of(_hw, struct s3c24xx_clkout, hw)
56
57static u8 s3c24xx_clkout_get_parent(struct clk_hw *hw)
58{
59 struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw);
60 int num_parents = __clk_get_num_parents(hw->clk);
61 u32 val;
62
63 val = readl_relaxed(S3C24XX_MISCCR) >> clkout->shift;
64 val >>= clkout->shift;
65 val &= clkout->mask;
66
67 if (val >= num_parents)
68 return -EINVAL;
69
70 return val;
71}
72
73static int s3c24xx_clkout_set_parent(struct clk_hw *hw, u8 index)
74{
75 struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw);
76 int ret = 0;
77
78 s3c2410_modify_misccr((clkout->mask << clkout->shift),
79 (index << clkout->shift));
80
81 return ret;
82}
83
84const struct clk_ops s3c24xx_clkout_ops = {
85 .get_parent = s3c24xx_clkout_get_parent,
86 .set_parent = s3c24xx_clkout_set_parent,
87 .determine_rate = __clk_mux_determine_rate,
88};
89
90struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
91 const char **parent_names, u8 num_parents,
92 u8 shift, u32 mask)
93{
94 struct s3c24xx_clkout *clkout;
95 struct clk *clk;
96 struct clk_init_data init;
97
98 /* allocate the clkout */
99 clkout = kzalloc(sizeof(*clkout), GFP_KERNEL);
100 if (!clkout)
101 return ERR_PTR(-ENOMEM);
102
103 init.name = name;
104 init.ops = &s3c24xx_clkout_ops;
105 init.flags = CLK_IS_BASIC;
106 init.parent_names = parent_names;
107 init.num_parents = num_parents;
108
109 clkout->shift = shift;
110 clkout->mask = mask;
111 clkout->hw.init = &init;
112
113 clk = clk_register(dev, &clkout->hw);
114
115 return clk;
116}
117
118/*
119 * dclk and clkout init
120 */
121
122struct s3c24xx_dclk {
123 struct device *dev;
124 void __iomem *base;
125 struct clk_onecell_data clk_data;
126 struct notifier_block dclk0_div_change_nb;
127 struct notifier_block dclk1_div_change_nb;
128 spinlock_t dclk_lock;
129 unsigned long reg_save;
130};
131
132#define to_s3c24xx_dclk0(x) \
133 container_of(x, struct s3c24xx_dclk, dclk0_div_change_nb)
134
135#define to_s3c24xx_dclk1(x) \
136 container_of(x, struct s3c24xx_dclk, dclk1_div_change_nb)
137
138static const char *dclk_s3c2410_p[] = { "pclk", "uclk" };
139static const char *clkout0_s3c2410_p[] = { "mpll", "upll", "fclk", "hclk", "pclk",
140 "gate_dclk0" };
141static const char *clkout1_s3c2410_p[] = { "mpll", "upll", "fclk", "hclk", "pclk",
142 "gate_dclk1" };
143
144static const char *clkout0_s3c2412_p[] = { "mpll", "upll", "rtc_clkout",
145 "hclk", "pclk", "gate_dclk0" };
146static const char *clkout1_s3c2412_p[] = { "xti", "upll", "fclk", "hclk", "pclk",
147 "gate_dclk1" };
148
149static const char *clkout0_s3c2440_p[] = { "xti", "upll", "fclk", "hclk", "pclk",
150 "gate_dclk0" };
151static const char *clkout1_s3c2440_p[] = { "mpll", "upll", "rtc_clkout",
152 "hclk", "pclk", "gate_dclk1" };
153
154static const char *dclk_s3c2443_p[] = { "pclk", "epll" };
155static const char *clkout0_s3c2443_p[] = { "xti", "epll", "armclk", "hclk", "pclk",
156 "gate_dclk0" };
157static const char *clkout1_s3c2443_p[] = { "dummy", "epll", "rtc_clkout",
158 "hclk", "pclk", "gate_dclk1" };
159
160#define DCLKCON_DCLK_DIV_MASK 0xf
161#define DCLKCON_DCLK0_DIV_SHIFT 4
162#define DCLKCON_DCLK0_CMP_SHIFT 8
163#define DCLKCON_DCLK1_DIV_SHIFT 20
164#define DCLKCON_DCLK1_CMP_SHIFT 24
165
166static void s3c24xx_dclk_update_cmp(struct s3c24xx_dclk *s3c24xx_dclk,
167 int div_shift, int cmp_shift)
168{
169 unsigned long flags = 0;
170 u32 dclk_con, div, cmp;
171
172 spin_lock_irqsave(&s3c24xx_dclk->dclk_lock, flags);
173
174 dclk_con = readl_relaxed(s3c24xx_dclk->base);
175
176 div = ((dclk_con >> div_shift) & DCLKCON_DCLK_DIV_MASK) + 1;
177 cmp = ((div + 1) / 2) - 1;
178
179 dclk_con &= ~(DCLKCON_DCLK_DIV_MASK << cmp_shift);
180 dclk_con |= (cmp << cmp_shift);
181
182 writel_relaxed(dclk_con, s3c24xx_dclk->base);
183
184 spin_unlock_irqrestore(&s3c24xx_dclk->dclk_lock, flags);
185}
186
187static int s3c24xx_dclk0_div_notify(struct notifier_block *nb,
188 unsigned long event, void *data)
189{
190 struct s3c24xx_dclk *s3c24xx_dclk = to_s3c24xx_dclk0(nb);
191
192 if (event == POST_RATE_CHANGE) {
193 s3c24xx_dclk_update_cmp(s3c24xx_dclk,
194 DCLKCON_DCLK0_DIV_SHIFT, DCLKCON_DCLK0_CMP_SHIFT);
195 }
196
197 return NOTIFY_DONE;
198}
199
200static int s3c24xx_dclk1_div_notify(struct notifier_block *nb,
201 unsigned long event, void *data)
202{
203 struct s3c24xx_dclk *s3c24xx_dclk = to_s3c24xx_dclk1(nb);
204
205 if (event == POST_RATE_CHANGE) {
206 s3c24xx_dclk_update_cmp(s3c24xx_dclk,
207 DCLKCON_DCLK1_DIV_SHIFT, DCLKCON_DCLK1_CMP_SHIFT);
208 }
209
210 return NOTIFY_DONE;
211}
212
213#ifdef CONFIG_PM_SLEEP
214static int s3c24xx_dclk_suspend(struct device *dev)
215{
216 struct platform_device *pdev = to_platform_device(dev);
217 struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev);
218
219 s3c24xx_dclk->reg_save = readl_relaxed(s3c24xx_dclk->base);
220 return 0;
221}
222
223static int s3c24xx_dclk_resume(struct device *dev)
224{
225 struct platform_device *pdev = to_platform_device(dev);
226 struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev);
227
228 writel_relaxed(s3c24xx_dclk->reg_save, s3c24xx_dclk->base);
229 return 0;
230}
231#endif
232
233static SIMPLE_DEV_PM_OPS(s3c24xx_dclk_pm_ops,
234 s3c24xx_dclk_suspend, s3c24xx_dclk_resume);
235
236static int s3c24xx_dclk_probe(struct platform_device *pdev)
237{
238 struct s3c24xx_dclk *s3c24xx_dclk;
239 struct resource *mem;
240 struct clk **clk_table;
241 struct s3c24xx_dclk_drv_data *dclk_variant;
242 int ret, i;
243
244 s3c24xx_dclk = devm_kzalloc(&pdev->dev, sizeof(*s3c24xx_dclk),
245 GFP_KERNEL);
246 if (!s3c24xx_dclk)
247 return -ENOMEM;
248
249 s3c24xx_dclk->dev = &pdev->dev;
250 platform_set_drvdata(pdev, s3c24xx_dclk);
251 spin_lock_init(&s3c24xx_dclk->dclk_lock);
252
253 clk_table = devm_kzalloc(&pdev->dev,
254 sizeof(struct clk *) * DCLK_MAX_CLKS,
255 GFP_KERNEL);
256 if (!clk_table)
257 return -ENOMEM;
258
259 s3c24xx_dclk->clk_data.clks = clk_table;
260 s3c24xx_dclk->clk_data.clk_num = DCLK_MAX_CLKS;
261
262 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
263 s3c24xx_dclk->base = devm_ioremap_resource(&pdev->dev, mem);
264 if (IS_ERR(s3c24xx_dclk->base))
265 return PTR_ERR(s3c24xx_dclk->base);
266
267 dclk_variant = (struct s3c24xx_dclk_drv_data *)
268 platform_get_device_id(pdev)->driver_data;
269
270
271 clk_table[MUX_DCLK0] = clk_register_mux(&pdev->dev, "mux_dclk0",
272 dclk_variant->mux_parent_names,
273 dclk_variant->mux_num_parents, 0,
274 s3c24xx_dclk->base, 1, 1, 0,
275 &s3c24xx_dclk->dclk_lock);
276 clk_table[MUX_DCLK1] = clk_register_mux(&pdev->dev, "mux_dclk1",
277 dclk_variant->mux_parent_names,
278 dclk_variant->mux_num_parents, 0,
279 s3c24xx_dclk->base, 17, 1, 0,
280 &s3c24xx_dclk->dclk_lock);
281
282 clk_table[DIV_DCLK0] = clk_register_divider(&pdev->dev, "div_dclk0",
283 "mux_dclk0", 0, s3c24xx_dclk->base,
284 4, 4, 0, &s3c24xx_dclk->dclk_lock);
285 clk_table[DIV_DCLK1] = clk_register_divider(&pdev->dev, "div_dclk1",
286 "mux_dclk1", 0, s3c24xx_dclk->base,
287 20, 4, 0, &s3c24xx_dclk->dclk_lock);
288
289 clk_table[GATE_DCLK0] = clk_register_gate(&pdev->dev, "gate_dclk0",
290 "div_dclk0", CLK_SET_RATE_PARENT,
291 s3c24xx_dclk->base, 0, 0,
292 &s3c24xx_dclk->dclk_lock);
293 clk_table[GATE_DCLK1] = clk_register_gate(&pdev->dev, "gate_dclk1",
294 "div_dclk1", CLK_SET_RATE_PARENT,
295 s3c24xx_dclk->base, 16, 0,
296 &s3c24xx_dclk->dclk_lock);
297
298 clk_table[MUX_CLKOUT0] = s3c24xx_register_clkout(&pdev->dev,
299 "clkout0", dclk_variant->clkout0_parent_names,
300 dclk_variant->clkout0_num_parents, 4, 7);
301 clk_table[MUX_CLKOUT1] = s3c24xx_register_clkout(&pdev->dev,
302 "clkout1", dclk_variant->clkout1_parent_names,
303 dclk_variant->clkout1_num_parents, 8, 7);
304
305 for (i = 0; i < DCLK_MAX_CLKS; i++)
306 if (IS_ERR(clk_table[i])) {
307 dev_err(&pdev->dev, "clock %d failed to register\n", i);
308 ret = PTR_ERR(clk_table[i]);
309 goto err_clk_register;
310 }
311
312 ret = clk_register_clkdev(clk_table[MUX_DCLK0], "dclk0", NULL);
313 if (!ret)
314 ret = clk_register_clkdev(clk_table[MUX_DCLK1], "dclk1", NULL);
315 if (!ret)
316 ret = clk_register_clkdev(clk_table[MUX_CLKOUT0],
317 "clkout0", NULL);
318 if (!ret)
319 ret = clk_register_clkdev(clk_table[MUX_CLKOUT1],
320 "clkout1", NULL);
321 if (ret) {
322 dev_err(&pdev->dev, "failed to register aliases, %d\n", ret);
323 goto err_clk_register;
324 }
325
326 s3c24xx_dclk->dclk0_div_change_nb.notifier_call =
327 s3c24xx_dclk0_div_notify;
328
329 s3c24xx_dclk->dclk1_div_change_nb.notifier_call =
330 s3c24xx_dclk1_div_notify;
331
332 ret = clk_notifier_register(clk_table[DIV_DCLK0],
333 &s3c24xx_dclk->dclk0_div_change_nb);
334 if (ret)
335 goto err_clk_register;
336
337 ret = clk_notifier_register(clk_table[DIV_DCLK1],
338 &s3c24xx_dclk->dclk1_div_change_nb);
339 if (ret)
340 goto err_dclk_notify;
341
342 return 0;
343
344err_dclk_notify:
345 clk_notifier_unregister(clk_table[DIV_DCLK0],
346 &s3c24xx_dclk->dclk0_div_change_nb);
347err_clk_register:
348 for (i = 0; i < DCLK_MAX_CLKS; i++)
349 if (clk_table[i] && !IS_ERR(clk_table[i]))
350 clk_unregister(clk_table[i]);
351
352 return ret;
353}
354
355static int s3c24xx_dclk_remove(struct platform_device *pdev)
356{
357 struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev);
358 struct clk **clk_table = s3c24xx_dclk->clk_data.clks;
359 int i;
360
361 clk_notifier_unregister(clk_table[DIV_DCLK1],
362 &s3c24xx_dclk->dclk1_div_change_nb);
363 clk_notifier_unregister(clk_table[DIV_DCLK0],
364 &s3c24xx_dclk->dclk0_div_change_nb);
365
366 for (i = 0; i < DCLK_MAX_CLKS; i++)
367 clk_unregister(clk_table[i]);
368
369 return 0;
370}
371
372static struct s3c24xx_dclk_drv_data dclk_variants[] = {
373 [S3C2410] = {
374 .clkout0_parent_names = clkout0_s3c2410_p,
375 .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2410_p),
376 .clkout1_parent_names = clkout1_s3c2410_p,
377 .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2410_p),
378 .mux_parent_names = dclk_s3c2410_p,
379 .mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p),
380 },
381 [S3C2412] = {
382 .clkout0_parent_names = clkout0_s3c2412_p,
383 .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2412_p),
384 .clkout1_parent_names = clkout1_s3c2412_p,
385 .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2412_p),
386 .mux_parent_names = dclk_s3c2410_p,
387 .mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p),
388 },
389 [S3C2440] = {
390 .clkout0_parent_names = clkout0_s3c2440_p,
391 .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2440_p),
392 .clkout1_parent_names = clkout1_s3c2440_p,
393 .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2440_p),
394 .mux_parent_names = dclk_s3c2410_p,
395 .mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p),
396 },
397 [S3C2443] = {
398 .clkout0_parent_names = clkout0_s3c2443_p,
399 .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2443_p),
400 .clkout1_parent_names = clkout1_s3c2443_p,
401 .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2443_p),
402 .mux_parent_names = dclk_s3c2443_p,
403 .mux_num_parents = ARRAY_SIZE(dclk_s3c2443_p),
404 },
405};
406
407static struct platform_device_id s3c24xx_dclk_driver_ids[] = {
408 {
409 .name = "s3c2410-dclk",
410 .driver_data = (kernel_ulong_t)&dclk_variants[S3C2410],
411 }, {
412 .name = "s3c2412-dclk",
413 .driver_data = (kernel_ulong_t)&dclk_variants[S3C2412],
414 }, {
415 .name = "s3c2440-dclk",
416 .driver_data = (kernel_ulong_t)&dclk_variants[S3C2440],
417 }, {
418 .name = "s3c2443-dclk",
419 .driver_data = (kernel_ulong_t)&dclk_variants[S3C2443],
420 },
421 { }
422};
423
424MODULE_DEVICE_TABLE(platform, s3c24xx_dclk_driver_ids);
425
426static struct platform_driver s3c24xx_dclk_driver = {
427 .driver = {
428 .name = "s3c24xx-dclk",
429 .owner = THIS_MODULE,
430 .pm = &s3c24xx_dclk_pm_ops,
431 },
432 .probe = s3c24xx_dclk_probe,
433 .remove = s3c24xx_dclk_remove,
434 .id_table = s3c24xx_dclk_driver_ids,
435};
436module_platform_driver(s3c24xx_dclk_driver);
437
438MODULE_LICENSE("GPL v2");
439MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
440MODULE_DESCRIPTION("Driver for the S3C24XX external clock outputs");
diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c
new file mode 100644
index 000000000000..ba0716801db2
--- /dev/null
+++ b/drivers/clk/samsung/clk-s3c2410.c
@@ -0,0 +1,482 @@
1/*
2 * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Common Clock Framework support for S3C2410 and following SoCs.
9 */
10
11#include <linux/clk.h>
12#include <linux/clkdev.h>
13#include <linux/clk-provider.h>
14#include <linux/of.h>
15#include <linux/of_address.h>
16#include <linux/syscore_ops.h>
17
18#include <dt-bindings/clock/s3c2410.h>
19
20#include "clk.h"
21#include "clk-pll.h"
22
23#define LOCKTIME 0x00
24#define MPLLCON 0x04
25#define UPLLCON 0x08
26#define CLKCON 0x0c
27#define CLKSLOW 0x10
28#define CLKDIVN 0x14
29#define CAMDIVN 0x18
30
31/* the soc types */
32enum supported_socs {
33 S3C2410,
34 S3C2440,
35 S3C2442,
36};
37
38/* list of PLLs to be registered */
39enum s3c2410_plls {
40 mpll, upll,
41};
42
43static void __iomem *reg_base;
44
45#ifdef CONFIG_PM_SLEEP
46static struct samsung_clk_reg_dump *s3c2410_save;
47
48/*
49 * list of controller registers to be saved and restored during a
50 * suspend/resume cycle.
51 */
52static unsigned long s3c2410_clk_regs[] __initdata = {
53 LOCKTIME,
54 MPLLCON,
55 UPLLCON,
56 CLKCON,
57 CLKSLOW,
58 CLKDIVN,
59 CAMDIVN,
60};
61
62static int s3c2410_clk_suspend(void)
63{
64 samsung_clk_save(reg_base, s3c2410_save,
65 ARRAY_SIZE(s3c2410_clk_regs));
66
67 return 0;
68}
69
70static void s3c2410_clk_resume(void)
71{
72 samsung_clk_restore(reg_base, s3c2410_save,
73 ARRAY_SIZE(s3c2410_clk_regs));
74}
75
76static struct syscore_ops s3c2410_clk_syscore_ops = {
77 .suspend = s3c2410_clk_suspend,
78 .resume = s3c2410_clk_resume,
79};
80
81static void s3c2410_clk_sleep_init(void)
82{
83 s3c2410_save = samsung_clk_alloc_reg_dump(s3c2410_clk_regs,
84 ARRAY_SIZE(s3c2410_clk_regs));
85 if (!s3c2410_save) {
86 pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
87 __func__);
88 return;
89 }
90
91 register_syscore_ops(&s3c2410_clk_syscore_ops);
92 return;
93}
94#else
95static void s3c2410_clk_sleep_init(void) {}
96#endif
97
98PNAME(fclk_p) = { "mpll", "div_slow" };
99
100struct samsung_mux_clock s3c2410_common_muxes[] __initdata = {
101 MUX(FCLK, "fclk", fclk_p, CLKSLOW, 4, 1),
102};
103
104static struct clk_div_table divslow_d[] = {
105 { .val = 0, .div = 1 },
106 { .val = 1, .div = 2 },
107 { .val = 2, .div = 4 },
108 { .val = 3, .div = 6 },
109 { .val = 4, .div = 8 },
110 { .val = 5, .div = 10 },
111 { .val = 6, .div = 12 },
112 { .val = 7, .div = 14 },
113 { /* sentinel */ },
114};
115
116struct samsung_div_clock s3c2410_common_dividers[] __initdata = {
117 DIV_T(0, "div_slow", "xti", CLKSLOW, 0, 3, divslow_d),
118 DIV(PCLK, "pclk", "hclk", CLKDIVN, 0, 1),
119};
120
121struct samsung_gate_clock s3c2410_common_gates[] __initdata = {
122 GATE(PCLK_SPI, "spi", "pclk", CLKCON, 18, 0, 0),
123 GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 17, 0, 0),
124 GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 16, 0, 0),
125 GATE(PCLK_ADC, "adc", "pclk", CLKCON, 15, 0, 0),
126 GATE(PCLK_RTC, "rtc", "pclk", CLKCON, 14, 0, 0),
127 GATE(PCLK_GPIO, "gpio", "pclk", CLKCON, 13, CLK_IGNORE_UNUSED, 0),
128 GATE(PCLK_UART2, "uart2", "pclk", CLKCON, 12, 0, 0),
129 GATE(PCLK_UART1, "uart1", "pclk", CLKCON, 11, 0, 0),
130 GATE(PCLK_UART0, "uart0", "pclk", CLKCON, 10, 0, 0),
131 GATE(PCLK_SDI, "sdi", "pclk", CLKCON, 9, 0, 0),
132 GATE(PCLK_PWM, "pwm", "pclk", CLKCON, 8, 0, 0),
133 GATE(HCLK_USBD, "usb-device", "hclk", CLKCON, 7, 0, 0),
134 GATE(HCLK_USBH, "usb-host", "hclk", CLKCON, 6, 0, 0),
135 GATE(HCLK_LCD, "lcd", "hclk", CLKCON, 5, 0, 0),
136 GATE(HCLK_NAND, "nand", "hclk", CLKCON, 4, 0, 0),
137};
138
139/* should be added _after_ the soc-specific clocks are created */
140struct samsung_clock_alias s3c2410_common_aliases[] __initdata = {
141 ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"),
142 ALIAS(PCLK_ADC, NULL, "adc"),
143 ALIAS(PCLK_RTC, NULL, "rtc"),
144 ALIAS(PCLK_PWM, NULL, "timers"),
145 ALIAS(HCLK_LCD, NULL, "lcd"),
146 ALIAS(HCLK_USBD, NULL, "usb-device"),
147 ALIAS(HCLK_USBH, NULL, "usb-host"),
148 ALIAS(UCLK, NULL, "usb-bus-host"),
149 ALIAS(UCLK, NULL, "usb-bus-gadget"),
150 ALIAS(ARMCLK, NULL, "armclk"),
151 ALIAS(UCLK, NULL, "uclk"),
152 ALIAS(HCLK, NULL, "hclk"),
153 ALIAS(MPLL, NULL, "mpll"),
154 ALIAS(FCLK, NULL, "fclk"),
155};
156
157/* S3C2410 specific clocks */
158
159static struct samsung_pll_rate_table pll_s3c2410_12mhz_tbl[] __initdata = {
160 /* sorted in descending order */
161 /* 2410A extras */
162 PLL_35XX_RATE(270000000, 127, 1, 1),
163 PLL_35XX_RATE(268000000, 126, 1, 1),
164 PLL_35XX_RATE(266000000, 125, 1, 1),
165 PLL_35XX_RATE(226000000, 105, 1, 1),
166 PLL_35XX_RATE(210000000, 132, 2, 1),
167 /* 2410 common */
168 PLL_35XX_RATE(203000000, 161, 3, 1),
169 PLL_35XX_RATE(192000000, 88, 1, 1),
170 PLL_35XX_RATE(186000000, 85, 1, 1),
171 PLL_35XX_RATE(180000000, 82, 1, 1),
172 PLL_35XX_RATE(170000000, 77, 1, 1),
173 PLL_35XX_RATE(158000000, 71, 1, 1),
174 PLL_35XX_RATE(152000000, 68, 1, 1),
175 PLL_35XX_RATE(147000000, 90, 2, 1),
176 PLL_35XX_RATE(135000000, 82, 2, 1),
177 PLL_35XX_RATE(124000000, 116, 1, 2),
178 PLL_35XX_RATE(118000000, 150, 2, 2),
179 PLL_35XX_RATE(113000000, 105, 1, 2),
180 PLL_35XX_RATE(101000000, 127, 2, 2),
181 PLL_35XX_RATE(90000000, 112, 2, 2),
182 PLL_35XX_RATE(85000000, 105, 2, 2),
183 PLL_35XX_RATE(79000000, 71, 1, 2),
184 PLL_35XX_RATE(68000000, 82, 2, 2),
185 PLL_35XX_RATE(56000000, 142, 2, 3),
186 PLL_35XX_RATE(48000000, 120, 2, 3),
187 PLL_35XX_RATE(51000000, 161, 3, 3),
188 PLL_35XX_RATE(45000000, 82, 1, 3),
189 PLL_35XX_RATE(34000000, 82, 2, 3),
190 { /* sentinel */ },
191};
192
193static struct samsung_pll_clock s3c2410_plls[] __initdata = {
194 [mpll] = PLL(pll_s3c2410_mpll, MPLL, "mpll", "xti",
195 LOCKTIME, MPLLCON, NULL),
196 [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "xti",
197 LOCKTIME, UPLLCON, NULL),
198};
199
200struct samsung_div_clock s3c2410_dividers[] __initdata = {
201 DIV(HCLK, "hclk", "mpll", CLKDIVN, 1, 1),
202};
203
204struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = {
205 /*
206 * armclk is directly supplied by the fclk, without
207 * switching possibility like on the s3c244x below.
208 */
209 FFACTOR(ARMCLK, "armclk", "fclk", 1, 1, 0),
210
211 /* uclk is fed from the unmodified upll */
212 FFACTOR(UCLK, "uclk", "upll", 1, 1, 0),
213};
214
215struct samsung_clock_alias s3c2410_aliases[] __initdata = {
216 ALIAS(PCLK_UART0, "s3c2410-uart.0", "uart"),
217 ALIAS(PCLK_UART1, "s3c2410-uart.1", "uart"),
218 ALIAS(PCLK_UART2, "s3c2410-uart.2", "uart"),
219 ALIAS(PCLK_UART0, "s3c2410-uart.0", "clk_uart_baud0"),
220 ALIAS(PCLK_UART1, "s3c2410-uart.1", "clk_uart_baud0"),
221 ALIAS(PCLK_UART2, "s3c2410-uart.2", "clk_uart_baud0"),
222 ALIAS(UCLK, NULL, "clk_uart_baud1"),
223};
224
225/* S3C244x specific clocks */
226
227static struct samsung_pll_rate_table pll_s3c244x_12mhz_tbl[] __initdata = {
228 /* sorted in descending order */
229 PLL_35XX_RATE(400000000, 0x5c, 1, 1),
230 PLL_35XX_RATE(390000000, 0x7a, 2, 1),
231 PLL_35XX_RATE(380000000, 0x57, 1, 1),
232 PLL_35XX_RATE(370000000, 0xb1, 4, 1),
233 PLL_35XX_RATE(360000000, 0x70, 2, 1),
234 PLL_35XX_RATE(350000000, 0xa7, 4, 1),
235 PLL_35XX_RATE(340000000, 0x4d, 1, 1),
236 PLL_35XX_RATE(330000000, 0x66, 2, 1),
237 PLL_35XX_RATE(320000000, 0x98, 4, 1),
238 PLL_35XX_RATE(310000000, 0x93, 4, 1),
239 PLL_35XX_RATE(300000000, 0x75, 3, 1),
240 PLL_35XX_RATE(240000000, 0x70, 1, 2),
241 PLL_35XX_RATE(230000000, 0x6b, 1, 2),
242 PLL_35XX_RATE(220000000, 0x66, 1, 2),
243 PLL_35XX_RATE(210000000, 0x84, 2, 2),
244 PLL_35XX_RATE(200000000, 0x5c, 1, 2),
245 PLL_35XX_RATE(190000000, 0x57, 1, 2),
246 PLL_35XX_RATE(180000000, 0x70, 2, 2),
247 PLL_35XX_RATE(170000000, 0x4d, 1, 2),
248 PLL_35XX_RATE(160000000, 0x98, 4, 2),
249 PLL_35XX_RATE(150000000, 0x75, 3, 2),
250 PLL_35XX_RATE(120000000, 0x70, 1, 3),
251 PLL_35XX_RATE(110000000, 0x66, 1, 3),
252 PLL_35XX_RATE(100000000, 0x5c, 1, 3),
253 PLL_35XX_RATE(90000000, 0x70, 2, 3),
254 PLL_35XX_RATE(80000000, 0x98, 4, 3),
255 PLL_35XX_RATE(75000000, 0x75, 3, 3),
256 { /* sentinel */ },
257};
258
259static struct samsung_pll_clock s3c244x_common_plls[] __initdata = {
260 [mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti",
261 LOCKTIME, MPLLCON, NULL),
262 [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "xti",
263 LOCKTIME, UPLLCON, NULL),
264};
265
266PNAME(hclk_p) = { "fclk", "div_hclk_2", "div_hclk_4", "div_hclk_3" };
267PNAME(armclk_p) = { "fclk", "hclk" };
268
269struct samsung_mux_clock s3c244x_common_muxes[] __initdata = {
270 MUX(HCLK, "hclk", hclk_p, CLKDIVN, 1, 2),
271 MUX(ARMCLK, "armclk", armclk_p, CAMDIVN, 12, 1),
272};
273
274struct samsung_fixed_factor_clock s3c244x_common_ffactor[] __initdata = {
275 FFACTOR(0, "div_hclk_2", "fclk", 1, 2, 0),
276 FFACTOR(0, "ff_cam", "div_cam", 2, 1, CLK_SET_RATE_PARENT),
277};
278
279static struct clk_div_table div_hclk_4_d[] = {
280 { .val = 0, .div = 4 },
281 { .val = 1, .div = 8 },
282 { /* sentinel */ },
283};
284
285static struct clk_div_table div_hclk_3_d[] = {
286 { .val = 0, .div = 3 },
287 { .val = 1, .div = 6 },
288 { /* sentinel */ },
289};
290
291struct samsung_div_clock s3c244x_common_dividers[] __initdata = {
292 DIV(UCLK, "uclk", "upll", CLKDIVN, 3, 1),
293 DIV(0, "div_hclk", "fclk", CLKDIVN, 1, 1),
294 DIV_T(0, "div_hclk_4", "fclk", CAMDIVN, 9, 1, div_hclk_4_d),
295 DIV_T(0, "div_hclk_3", "fclk", CAMDIVN, 8, 1, div_hclk_3_d),
296 DIV(0, "div_cam", "upll", CAMDIVN, 0, 3),
297};
298
299struct samsung_gate_clock s3c244x_common_gates[] __initdata = {
300 GATE(HCLK_CAM, "cam", "hclk", CLKCON, 19, 0, 0),
301};
302
303struct samsung_clock_alias s3c244x_common_aliases[] __initdata = {
304 ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"),
305 ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"),
306 ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"),
307 ALIAS(PCLK_UART0, "s3c2440-uart.0", "clk_uart_baud2"),
308 ALIAS(PCLK_UART1, "s3c2440-uart.1", "clk_uart_baud2"),
309 ALIAS(PCLK_UART2, "s3c2440-uart.2", "clk_uart_baud2"),
310 ALIAS(HCLK_CAM, NULL, "camif"),
311 ALIAS(CAMIF, NULL, "camif-upll"),
312};
313
314/* S3C2440 specific clocks */
315
316PNAME(s3c2440_camif_p) = { "upll", "ff_cam" };
317
318struct samsung_mux_clock s3c2440_muxes[] __initdata = {
319 MUX(CAMIF, "camif", s3c2440_camif_p, CAMDIVN, 4, 1),
320};
321
322struct samsung_gate_clock s3c2440_gates[] __initdata = {
323 GATE(PCLK_AC97, "ac97", "pclk", CLKCON, 20, 0, 0),
324};
325
326/* S3C2442 specific clocks */
327
328struct samsung_fixed_factor_clock s3c2442_ffactor[] __initdata = {
329 FFACTOR(0, "upll_3", "upll", 1, 3, 0),
330};
331
332PNAME(s3c2442_camif_p) = { "upll", "ff_cam", "upll", "upll_3" };
333
334struct samsung_mux_clock s3c2442_muxes[] __initdata = {
335 MUX(CAMIF, "camif", s3c2442_camif_p, CAMDIVN, 4, 2),
336};
337
338/*
339 * fixed rate clocks generated outside the soc
340 * Only necessary until the devicetree-move is complete
341 */
342#define XTI 1
343struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = {
344 FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0),
345};
346
347static void __init s3c2410_common_clk_register_fixed_ext(
348 struct samsung_clk_provider *ctx,
349 unsigned long xti_f)
350{
351 struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal");
352
353 s3c2410_common_frate_clks[0].fixed_rate = xti_f;
354 samsung_clk_register_fixed_rate(ctx, s3c2410_common_frate_clks,
355 ARRAY_SIZE(s3c2410_common_frate_clks));
356
357 samsung_clk_register_alias(ctx, &xti_alias, 1);
358}
359
360void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
361 int current_soc,
362 void __iomem *base)
363{
364 struct samsung_clk_provider *ctx;
365 reg_base = base;
366
367 if (np) {
368 reg_base = of_iomap(np, 0);
369 if (!reg_base)
370 panic("%s: failed to map registers\n", __func__);
371 }
372
373 ctx = samsung_clk_init(np, reg_base, NR_CLKS);
374 if (!ctx)
375 panic("%s: unable to allocate context.\n", __func__);
376
377 /* Register external clocks only in non-dt cases */
378 if (!np)
379 s3c2410_common_clk_register_fixed_ext(ctx, xti_f);
380
381 if (current_soc == 2410) {
382 if (_get_rate("xti") == 12 * MHZ) {
383 s3c2410_plls[mpll].rate_table = pll_s3c2410_12mhz_tbl;
384 s3c2410_plls[upll].rate_table = pll_s3c2410_12mhz_tbl;
385 }
386
387 /* Register PLLs. */
388 samsung_clk_register_pll(ctx, s3c2410_plls,
389 ARRAY_SIZE(s3c2410_plls), reg_base);
390
391 } else { /* S3C2440, S3C2442 */
392 if (_get_rate("xti") == 12 * MHZ) {
393 /*
394 * plls follow different calculation schemes, with the
395 * upll following the same scheme as the s3c2410 plls
396 */
397 s3c244x_common_plls[mpll].rate_table =
398 pll_s3c244x_12mhz_tbl;
399 s3c244x_common_plls[upll].rate_table =
400 pll_s3c2410_12mhz_tbl;
401 }
402
403 /* Register PLLs. */
404 samsung_clk_register_pll(ctx, s3c244x_common_plls,
405 ARRAY_SIZE(s3c244x_common_plls), reg_base);
406 }
407
408 /* Register common internal clocks. */
409 samsung_clk_register_mux(ctx, s3c2410_common_muxes,
410 ARRAY_SIZE(s3c2410_common_muxes));
411 samsung_clk_register_div(ctx, s3c2410_common_dividers,
412 ARRAY_SIZE(s3c2410_common_dividers));
413 samsung_clk_register_gate(ctx, s3c2410_common_gates,
414 ARRAY_SIZE(s3c2410_common_gates));
415
416 if (current_soc == S3C2440 || current_soc == S3C2442) {
417 samsung_clk_register_div(ctx, s3c244x_common_dividers,
418 ARRAY_SIZE(s3c244x_common_dividers));
419 samsung_clk_register_gate(ctx, s3c244x_common_gates,
420 ARRAY_SIZE(s3c244x_common_gates));
421 samsung_clk_register_mux(ctx, s3c244x_common_muxes,
422 ARRAY_SIZE(s3c244x_common_muxes));
423 samsung_clk_register_fixed_factor(ctx, s3c244x_common_ffactor,
424 ARRAY_SIZE(s3c244x_common_ffactor));
425 }
426
427 /* Register SoC-specific clocks. */
428 switch (current_soc) {
429 case S3C2410:
430 samsung_clk_register_div(ctx, s3c2410_dividers,
431 ARRAY_SIZE(s3c2410_dividers));
432 samsung_clk_register_fixed_factor(ctx, s3c2410_ffactor,
433 ARRAY_SIZE(s3c2410_ffactor));
434 samsung_clk_register_alias(ctx, s3c2410_aliases,
435 ARRAY_SIZE(s3c2410_common_aliases));
436 break;
437 case S3C2440:
438 samsung_clk_register_mux(ctx, s3c2440_muxes,
439 ARRAY_SIZE(s3c2440_muxes));
440 samsung_clk_register_gate(ctx, s3c2440_gates,
441 ARRAY_SIZE(s3c2440_gates));
442 break;
443 case S3C2442:
444 samsung_clk_register_mux(ctx, s3c2442_muxes,
445 ARRAY_SIZE(s3c2442_muxes));
446 samsung_clk_register_fixed_factor(ctx, s3c2442_ffactor,
447 ARRAY_SIZE(s3c2442_ffactor));
448 break;
449 }
450
451 /*
452 * Register common aliases at the end, as some of the aliased clocks
453 * are SoC specific.
454 */
455 samsung_clk_register_alias(ctx, s3c2410_common_aliases,
456 ARRAY_SIZE(s3c2410_common_aliases));
457
458 if (current_soc == S3C2440 || current_soc == S3C2442) {
459 samsung_clk_register_alias(ctx, s3c244x_common_aliases,
460 ARRAY_SIZE(s3c244x_common_aliases));
461 }
462
463 s3c2410_clk_sleep_init();
464}
465
466static void __init s3c2410_clk_init(struct device_node *np)
467{
468 s3c2410_common_clk_init(np, 0, S3C2410, 0);
469}
470CLK_OF_DECLARE(s3c2410_clk, "samsung,s3c2410-clock", s3c2410_clk_init);
471
472static void __init s3c2440_clk_init(struct device_node *np)
473{
474 s3c2410_common_clk_init(np, 0, S3C2440, 0);
475}
476CLK_OF_DECLARE(s3c2440_clk, "samsung,s3c2440-clock", s3c2440_clk_init);
477
478static void __init s3c2442_clk_init(struct device_node *np)
479{
480 s3c2410_common_clk_init(np, 0, S3C2442, 0);
481}
482CLK_OF_DECLARE(s3c2442_clk, "samsung,s3c2442-clock", s3c2442_clk_init);
diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c
new file mode 100644
index 000000000000..23e4313f625e
--- /dev/null
+++ b/drivers/clk/samsung/clk-s3c2412.c
@@ -0,0 +1,274 @@
1/*
2 * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Common Clock Framework support for S3C2412 and S3C2413.
9 */
10
11#include <linux/clk.h>
12#include <linux/clkdev.h>
13#include <linux/clk-provider.h>
14#include <linux/of.h>
15#include <linux/of_address.h>
16#include <linux/syscore_ops.h>
17
18#include <dt-bindings/clock/s3c2412.h>
19
20#include "clk.h"
21#include "clk-pll.h"
22
23#define LOCKTIME 0x00
24#define MPLLCON 0x04
25#define UPLLCON 0x08
26#define CLKCON 0x0c
27#define CLKDIVN 0x14
28#define CLKSRC 0x1c
29
30/* list of PLLs to be registered */
31enum s3c2412_plls {
32 mpll, upll,
33};
34
35static void __iomem *reg_base;
36
37#ifdef CONFIG_PM_SLEEP
38static struct samsung_clk_reg_dump *s3c2412_save;
39
40/*
41 * list of controller registers to be saved and restored during a
42 * suspend/resume cycle.
43 */
44static unsigned long s3c2412_clk_regs[] __initdata = {
45 LOCKTIME,
46 MPLLCON,
47 UPLLCON,
48 CLKCON,
49 CLKDIVN,
50 CLKSRC,
51};
52
53static int s3c2412_clk_suspend(void)
54{
55 samsung_clk_save(reg_base, s3c2412_save,
56 ARRAY_SIZE(s3c2412_clk_regs));
57
58 return 0;
59}
60
61static void s3c2412_clk_resume(void)
62{
63 samsung_clk_restore(reg_base, s3c2412_save,
64 ARRAY_SIZE(s3c2412_clk_regs));
65}
66
67static struct syscore_ops s3c2412_clk_syscore_ops = {
68 .suspend = s3c2412_clk_suspend,
69 .resume = s3c2412_clk_resume,
70};
71
72static void s3c2412_clk_sleep_init(void)
73{
74 s3c2412_save = samsung_clk_alloc_reg_dump(s3c2412_clk_regs,
75 ARRAY_SIZE(s3c2412_clk_regs));
76 if (!s3c2412_save) {
77 pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
78 __func__);
79 return;
80 }
81
82 register_syscore_ops(&s3c2412_clk_syscore_ops);
83 return;
84}
85#else
86static void s3c2412_clk_sleep_init(void) {}
87#endif
88
89static struct clk_div_table divxti_d[] = {
90 { .val = 0, .div = 1 },
91 { .val = 1, .div = 2 },
92 { .val = 2, .div = 4 },
93 { .val = 3, .div = 6 },
94 { .val = 4, .div = 8 },
95 { .val = 5, .div = 10 },
96 { .val = 6, .div = 12 },
97 { .val = 7, .div = 14 },
98 { /* sentinel */ },
99};
100
101struct samsung_div_clock s3c2412_dividers[] __initdata = {
102 DIV_T(0, "div_xti", "xti", CLKSRC, 0, 3, divxti_d),
103 DIV(0, "div_cam", "mux_cam", CLKDIVN, 16, 4),
104 DIV(0, "div_i2s", "mux_i2s", CLKDIVN, 12, 4),
105 DIV(0, "div_uart", "mux_uart", CLKDIVN, 8, 4),
106 DIV(0, "div_usb", "mux_usb", CLKDIVN, 6, 1),
107 DIV(0, "div_hclk_half", "hclk", CLKDIVN, 5, 1),
108 DIV(ARMDIV, "armdiv", "msysclk", CLKDIVN, 3, 1),
109 DIV(PCLK, "pclk", "hclk", CLKDIVN, 2, 1),
110 DIV(HCLK, "hclk", "armdiv", CLKDIVN, 0, 2),
111};
112
113struct samsung_fixed_factor_clock s3c2412_ffactor[] __initdata = {
114 FFACTOR(0, "ff_hclk", "hclk", 2, 1, CLK_SET_RATE_PARENT),
115};
116
117/*
118 * The first two use the OM[4] setting, which is not readable from
119 * software, so assume it is set to xti.
120 */
121PNAME(erefclk_p) = { "xti", "xti", "xti", "ext" };
122PNAME(urefclk_p) = { "xti", "xti", "xti", "ext" };
123
124PNAME(camclk_p) = { "usysclk", "hclk" };
125PNAME(usbclk_p) = { "usysclk", "hclk" };
126PNAME(i2sclk_p) = { "erefclk", "mpll" };
127PNAME(uartclk_p) = { "erefclk", "mpll" };
128PNAME(usysclk_p) = { "urefclk", "upll" };
129PNAME(msysclk_p) = { "mdivclk", "mpll" };
130PNAME(mdivclk_p) = { "xti", "div_xti" };
131PNAME(armclk_p) = { "armdiv", "hclk" };
132
133struct samsung_mux_clock s3c2412_muxes[] __initdata = {
134 MUX(0, "erefclk", erefclk_p, CLKSRC, 14, 2),
135 MUX(0, "urefclk", urefclk_p, CLKSRC, 12, 2),
136 MUX(0, "mux_cam", camclk_p, CLKSRC, 11, 1),
137 MUX(0, "mux_usb", usbclk_p, CLKSRC, 10, 1),
138 MUX(0, "mux_i2s", i2sclk_p, CLKSRC, 9, 1),
139 MUX(0, "mux_uart", uartclk_p, CLKSRC, 8, 1),
140 MUX(USYSCLK, "usysclk", usysclk_p, CLKSRC, 5, 1),
141 MUX(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1),
142 MUX(MDIVCLK, "mdivclk", mdivclk_p, CLKSRC, 3, 1),
143 MUX(ARMCLK, "armclk", armclk_p, CLKDIVN, 4, 1),
144};
145
146static struct samsung_pll_clock s3c2412_plls[] __initdata = {
147 [mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti",
148 LOCKTIME, MPLLCON, NULL),
149 [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "urefclk",
150 LOCKTIME, UPLLCON, NULL),
151};
152
153struct samsung_gate_clock s3c2412_gates[] __initdata = {
154 GATE(PCLK_WDT, "wdt", "pclk", CLKCON, 28, 0, 0),
155 GATE(PCLK_SPI, "spi", "pclk", CLKCON, 27, 0, 0),
156 GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 26, 0, 0),
157 GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 25, 0, 0),
158 GATE(PCLK_ADC, "adc", "pclk", CLKCON, 24, 0, 0),
159 GATE(PCLK_RTC, "rtc", "pclk", CLKCON, 23, 0, 0),
160 GATE(PCLK_GPIO, "gpio", "pclk", CLKCON, 22, CLK_IGNORE_UNUSED, 0),
161 GATE(PCLK_UART2, "uart2", "pclk", CLKCON, 21, 0, 0),
162 GATE(PCLK_UART1, "uart1", "pclk", CLKCON, 20, 0, 0),
163 GATE(PCLK_UART0, "uart0", "pclk", CLKCON, 19, 0, 0),
164 GATE(PCLK_SDI, "sdi", "pclk", CLKCON, 18, 0, 0),
165 GATE(PCLK_PWM, "pwm", "pclk", CLKCON, 17, 0, 0),
166 GATE(PCLK_USBD, "usb-device", "pclk", CLKCON, 16, 0, 0),
167 GATE(SCLK_CAM, "sclk_cam", "div_cam", CLKCON, 15, 0, 0),
168 GATE(SCLK_UART, "sclk_uart", "div_uart", CLKCON, 14, 0, 0),
169 GATE(SCLK_I2S, "sclk_i2s", "div_i2s", CLKCON, 13, 0, 0),
170 GATE(SCLK_USBH, "sclk_usbh", "div_usb", CLKCON, 12, 0, 0),
171 GATE(SCLK_USBD, "sclk_usbd", "div_usb", CLKCON, 11, 0, 0),
172 GATE(HCLK_HALF, "hclk_half", "div_hclk_half", CLKCON, 10, CLK_IGNORE_UNUSED, 0),
173 GATE(HCLK_X2, "hclkx2", "ff_hclk", CLKCON, 9, CLK_IGNORE_UNUSED, 0),
174 GATE(HCLK_SDRAM, "sdram", "hclk", CLKCON, 8, CLK_IGNORE_UNUSED, 0),
175 GATE(HCLK_USBH, "usb-host", "hclk", CLKCON, 6, 0, 0),
176 GATE(HCLK_LCD, "lcd", "hclk", CLKCON, 5, 0, 0),
177 GATE(HCLK_NAND, "nand", "hclk", CLKCON, 4, 0, 0),
178 GATE(HCLK_DMA3, "dma3", "hclk", CLKCON, 3, CLK_IGNORE_UNUSED, 0),
179 GATE(HCLK_DMA2, "dma2", "hclk", CLKCON, 2, CLK_IGNORE_UNUSED, 0),
180 GATE(HCLK_DMA1, "dma1", "hclk", CLKCON, 1, CLK_IGNORE_UNUSED, 0),
181 GATE(HCLK_DMA0, "dma0", "hclk", CLKCON, 0, CLK_IGNORE_UNUSED, 0),
182};
183
184struct samsung_clock_alias s3c2412_aliases[] __initdata = {
185 ALIAS(PCLK_UART0, "s3c2412-uart.0", "uart"),
186 ALIAS(PCLK_UART1, "s3c2412-uart.1", "uart"),
187 ALIAS(PCLK_UART2, "s3c2412-uart.2", "uart"),
188 ALIAS(PCLK_UART0, "s3c2412-uart.0", "clk_uart_baud2"),
189 ALIAS(PCLK_UART1, "s3c2412-uart.1", "clk_uart_baud2"),
190 ALIAS(PCLK_UART2, "s3c2412-uart.2", "clk_uart_baud2"),
191 ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
192 ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"),
193 ALIAS(PCLK_ADC, NULL, "adc"),
194 ALIAS(PCLK_RTC, NULL, "rtc"),
195 ALIAS(PCLK_PWM, NULL, "timers"),
196 ALIAS(HCLK_LCD, NULL, "lcd"),
197 ALIAS(PCLK_USBD, NULL, "usb-device"),
198 ALIAS(SCLK_USBD, NULL, "usb-bus-gadget"),
199 ALIAS(HCLK_USBH, NULL, "usb-host"),
200 ALIAS(SCLK_USBH, NULL, "usb-bus-host"),
201 ALIAS(ARMCLK, NULL, "armclk"),
202 ALIAS(HCLK, NULL, "hclk"),
203 ALIAS(MPLL, NULL, "mpll"),
204 ALIAS(MSYSCLK, NULL, "fclk"),
205};
206
207/*
208 * fixed rate clocks generated outside the soc
209 * Only necessary until the devicetree-move is complete
210 */
211#define XTI 1
212struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = {
213 FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0),
214 FRATE(0, "ext", NULL, CLK_IS_ROOT, 0),
215};
216
217static void __init s3c2412_common_clk_register_fixed_ext(
218 struct samsung_clk_provider *ctx,
219 unsigned long xti_f, unsigned long ext_f)
220{
221 /* xtal alias is necessary for the current cpufreq driver */
222 struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal");
223
224 s3c2412_common_frate_clks[0].fixed_rate = xti_f;
225 s3c2412_common_frate_clks[1].fixed_rate = ext_f;
226 samsung_clk_register_fixed_rate(ctx, s3c2412_common_frate_clks,
227 ARRAY_SIZE(s3c2412_common_frate_clks));
228
229 samsung_clk_register_alias(ctx, &xti_alias, 1);
230}
231
232void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
233 unsigned long ext_f, void __iomem *base)
234{
235 struct samsung_clk_provider *ctx;
236 reg_base = base;
237
238 if (np) {
239 reg_base = of_iomap(np, 0);
240 if (!reg_base)
241 panic("%s: failed to map registers\n", __func__);
242 }
243
244 ctx = samsung_clk_init(np, reg_base, NR_CLKS);
245 if (!ctx)
246 panic("%s: unable to allocate context.\n", __func__);
247
248 /* Register external clocks only in non-dt cases */
249 if (!np)
250 s3c2412_common_clk_register_fixed_ext(ctx, xti_f, ext_f);
251
252 /* Register PLLs. */
253 samsung_clk_register_pll(ctx, s3c2412_plls, ARRAY_SIZE(s3c2412_plls),
254 reg_base);
255
256 /* Register common internal clocks. */
257 samsung_clk_register_mux(ctx, s3c2412_muxes, ARRAY_SIZE(s3c2412_muxes));
258 samsung_clk_register_div(ctx, s3c2412_dividers,
259 ARRAY_SIZE(s3c2412_dividers));
260 samsung_clk_register_gate(ctx, s3c2412_gates,
261 ARRAY_SIZE(s3c2412_gates));
262 samsung_clk_register_fixed_factor(ctx, s3c2412_ffactor,
263 ARRAY_SIZE(s3c2412_ffactor));
264 samsung_clk_register_alias(ctx, s3c2412_aliases,
265 ARRAY_SIZE(s3c2412_aliases));
266
267 s3c2412_clk_sleep_init();
268}
269
270static void __init s3c2412_clk_init(struct device_node *np)
271{
272 s3c2412_common_clk_init(np, 0, 0, 0);
273}
274CLK_OF_DECLARE(s3c2412_clk, "samsung,s3c2412-clock", s3c2412_clk_init);
diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c
new file mode 100644
index 000000000000..c4bbdabebaa4
--- /dev/null
+++ b/drivers/clk/samsung/clk-s3c2443.c
@@ -0,0 +1,466 @@
1/*
2 * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Common Clock Framework support for S3C2443 and following SoCs.
9 */
10
11#include <linux/clk.h>
12#include <linux/clkdev.h>
13#include <linux/clk-provider.h>
14#include <linux/of.h>
15#include <linux/of_address.h>
16#include <linux/syscore_ops.h>
17
18#include <dt-bindings/clock/s3c2443.h>
19
20#include "clk.h"
21#include "clk-pll.h"
22
23/* S3C2416 clock controller register offsets */
24#define LOCKCON0 0x00
25#define LOCKCON1 0x04
26#define MPLLCON 0x10
27#define EPLLCON 0x18
28#define EPLLCON_K 0x1C
29#define CLKSRC 0x20
30#define CLKDIV0 0x24
31#define CLKDIV1 0x28
32#define CLKDIV2 0x2C
33#define HCLKCON 0x30
34#define PCLKCON 0x34
35#define SCLKCON 0x38
36
37/* the soc types */
38enum supported_socs {
39 S3C2416,
40 S3C2443,
41 S3C2450,
42};
43
44/* list of PLLs to be registered */
45enum s3c2443_plls {
46 mpll, epll,
47};
48
49static void __iomem *reg_base;
50
51#ifdef CONFIG_PM_SLEEP
52static struct samsung_clk_reg_dump *s3c2443_save;
53
54/*
55 * list of controller registers to be saved and restored during a
56 * suspend/resume cycle.
57 */
58static unsigned long s3c2443_clk_regs[] __initdata = {
59 LOCKCON0,
60 LOCKCON1,
61 MPLLCON,
62 EPLLCON,
63 EPLLCON_K,
64 CLKSRC,
65 CLKDIV0,
66 CLKDIV1,
67 CLKDIV2,
68 PCLKCON,
69 HCLKCON,
70 SCLKCON,
71};
72
73static int s3c2443_clk_suspend(void)
74{
75 samsung_clk_save(reg_base, s3c2443_save,
76 ARRAY_SIZE(s3c2443_clk_regs));
77
78 return 0;
79}
80
81static void s3c2443_clk_resume(void)
82{
83 samsung_clk_restore(reg_base, s3c2443_save,
84 ARRAY_SIZE(s3c2443_clk_regs));
85}
86
87static struct syscore_ops s3c2443_clk_syscore_ops = {
88 .suspend = s3c2443_clk_suspend,
89 .resume = s3c2443_clk_resume,
90};
91
92static void s3c2443_clk_sleep_init(void)
93{
94 s3c2443_save = samsung_clk_alloc_reg_dump(s3c2443_clk_regs,
95 ARRAY_SIZE(s3c2443_clk_regs));
96 if (!s3c2443_save) {
97 pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
98 __func__);
99 return;
100 }
101
102 register_syscore_ops(&s3c2443_clk_syscore_ops);
103 return;
104}
105#else
106static void s3c2443_clk_sleep_init(void) {}
107#endif
108
109PNAME(epllref_p) = { "mpllref", "mpllref", "xti", "ext" };
110PNAME(esysclk_p) = { "epllref", "epll" };
111PNAME(mpllref_p) = { "xti", "mdivclk" };
112PNAME(msysclk_p) = { "mpllref", "mpll" };
113PNAME(armclk_p) = { "armdiv" , "hclk" };
114PNAME(i2s0_p) = { "div_i2s0", "ext_i2s", "epllref", "epllref" };
115
116struct samsung_mux_clock s3c2443_common_muxes[] __initdata = {
117 MUX(0, "epllref", epllref_p, CLKSRC, 7, 2),
118 MUX(ESYSCLK, "esysclk", esysclk_p, CLKSRC, 6, 1),
119 MUX(0, "mpllref", mpllref_p, CLKSRC, 3, 1),
120 MUX_A(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1, "msysclk"),
121 MUX_A(ARMCLK, "armclk", armclk_p, CLKDIV0, 13, 1, "armclk"),
122 MUX(0, "mux_i2s0", i2s0_p, CLKSRC, 14, 2),
123};
124
125static struct clk_div_table hclk_d[] = {
126 { .val = 0, .div = 1 },
127 { .val = 1, .div = 2 },
128 { .val = 3, .div = 4 },
129 { /* sentinel */ },
130};
131
132static struct clk_div_table mdivclk_d[] = {
133 { .val = 0, .div = 1 },
134 { .val = 1, .div = 3 },
135 { .val = 2, .div = 5 },
136 { .val = 3, .div = 7 },
137 { .val = 4, .div = 9 },
138 { .val = 5, .div = 11 },
139 { .val = 6, .div = 13 },
140 { .val = 7, .div = 15 },
141 { /* sentinel */ },
142};
143
144struct samsung_div_clock s3c2443_common_dividers[] __initdata = {
145 DIV_T(0, "mdivclk", "xti", CLKDIV0, 6, 3, mdivclk_d),
146 DIV(0, "prediv", "msysclk", CLKDIV0, 4, 2),
147 DIV_T(HCLK, "hclk", "prediv", CLKDIV0, 0, 2, hclk_d),
148 DIV(PCLK, "pclk", "hclk", CLKDIV0, 2, 1),
149 DIV(0, "div_hsspi0_epll", "esysclk", CLKDIV1, 24, 2),
150 DIV(0, "div_fimd", "esysclk", CLKDIV1, 16, 8),
151 DIV(0, "div_i2s0", "esysclk", CLKDIV1, 12, 4),
152 DIV(0, "div_uart", "esysclk", CLKDIV1, 8, 4),
153 DIV(0, "div_hsmmc1", "esysclk", CLKDIV1, 6, 2),
154 DIV(0, "div_usbhost", "esysclk", CLKDIV1, 4, 2),
155};
156
157struct samsung_gate_clock s3c2443_common_gates[] __initdata = {
158 GATE(SCLK_HSMMC_EXT, "sclk_hsmmcext", "ext", SCLKCON, 13, 0, 0),
159 GATE(SCLK_HSMMC1, "sclk_hsmmc1", "div_hsmmc1", SCLKCON, 12, 0, 0),
160 GATE(SCLK_FIMD, "sclk_fimd", "div_fimd", SCLKCON, 10, 0, 0),
161 GATE(SCLK_I2S0, "sclk_i2s0", "mux_i2s0", SCLKCON, 9, 0, 0),
162 GATE(SCLK_UART, "sclk_uart", "div_uart", SCLKCON, 8, 0, 0),
163 GATE(SCLK_USBH, "sclk_usbhost", "div_usbhost", SCLKCON, 1, 0, 0),
164 GATE(HCLK_DRAM, "dram", "hclk", HCLKCON, 19, CLK_IGNORE_UNUSED, 0),
165 GATE(HCLK_SSMC, "ssmc", "hclk", HCLKCON, 18, CLK_IGNORE_UNUSED, 0),
166 GATE(HCLK_HSMMC1, "hsmmc1", "hclk", HCLKCON, 16, 0, 0),
167 GATE(HCLK_USBD, "usb-device", "hclk", HCLKCON, 12, 0, 0),
168 GATE(HCLK_USBH, "usb-host", "hclk", HCLKCON, 11, 0, 0),
169 GATE(HCLK_LCD, "lcd", "hclk", HCLKCON, 9, 0, 0),
170 GATE(HCLK_DMA5, "dma5", "hclk", HCLKCON, 5, CLK_IGNORE_UNUSED, 0),
171 GATE(HCLK_DMA4, "dma4", "hclk", HCLKCON, 4, CLK_IGNORE_UNUSED, 0),
172 GATE(HCLK_DMA3, "dma3", "hclk", HCLKCON, 3, CLK_IGNORE_UNUSED, 0),
173 GATE(HCLK_DMA2, "dma2", "hclk", HCLKCON, 2, CLK_IGNORE_UNUSED, 0),
174 GATE(HCLK_DMA1, "dma1", "hclk", HCLKCON, 1, CLK_IGNORE_UNUSED, 0),
175 GATE(HCLK_DMA0, "dma0", "hclk", HCLKCON, 0, CLK_IGNORE_UNUSED, 0),
176 GATE(PCLK_GPIO, "gpio", "pclk", PCLKCON, 13, CLK_IGNORE_UNUSED, 0),
177 GATE(PCLK_RTC, "rtc", "pclk", PCLKCON, 12, 0, 0),
178 GATE(PCLK_WDT, "wdt", "pclk", PCLKCON, 11, 0, 0),
179 GATE(PCLK_PWM, "pwm", "pclk", PCLKCON, 10, 0, 0),
180 GATE(PCLK_I2S0, "i2s0", "pclk", PCLKCON, 9, 0, 0),
181 GATE(PCLK_AC97, "ac97", "pclk", PCLKCON, 8, 0, 0),
182 GATE(PCLK_ADC, "adc", "pclk", PCLKCON, 7, 0, 0),
183 GATE(PCLK_SPI0, "spi0", "pclk", PCLKCON, 6, 0, 0),
184 GATE(PCLK_I2C0, "i2c0", "pclk", PCLKCON, 4, 0, 0),
185 GATE(PCLK_UART3, "uart3", "pclk", PCLKCON, 3, 0, 0),
186 GATE(PCLK_UART2, "uart2", "pclk", PCLKCON, 2, 0, 0),
187 GATE(PCLK_UART1, "uart1", "pclk", PCLKCON, 1, 0, 0),
188 GATE(PCLK_UART0, "uart0", "pclk", PCLKCON, 0, 0, 0),
189};
190
191struct samsung_clock_alias s3c2443_common_aliases[] __initdata = {
192 ALIAS(HCLK, NULL, "hclk"),
193 ALIAS(HCLK_SSMC, NULL, "nand"),
194 ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"),
195 ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"),
196 ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"),
197 ALIAS(PCLK_UART3, "s3c2440-uart.3", "uart"),
198 ALIAS(PCLK_UART0, "s3c2440-uart.0", "clk_uart_baud2"),
199 ALIAS(PCLK_UART1, "s3c2440-uart.1", "clk_uart_baud2"),
200 ALIAS(PCLK_UART2, "s3c2440-uart.2", "clk_uart_baud2"),
201 ALIAS(PCLK_UART3, "s3c2440-uart.3", "clk_uart_baud2"),
202 ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
203 ALIAS(PCLK_PWM, NULL, "timers"),
204 ALIAS(PCLK_RTC, NULL, "rtc"),
205 ALIAS(PCLK_WDT, NULL, "watchdog"),
206 ALIAS(PCLK_ADC, NULL, "adc"),
207 ALIAS(PCLK_I2C0, "s3c2410-i2c.0", "i2c"),
208 ALIAS(HCLK_USBD, NULL, "usb-device"),
209 ALIAS(HCLK_USBH, NULL, "usb-host"),
210 ALIAS(SCLK_USBH, NULL, "usb-bus-host"),
211 ALIAS(PCLK_SPI0, "s3c2443-spi.0", "spi"),
212 ALIAS(PCLK_SPI0, "s3c2443-spi.0", "spi_busclk0"),
213 ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"),
214 ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
215 ALIAS(PCLK_I2S0, "samsung-i2s.0", "iis"),
216 ALIAS(SCLK_I2S0, NULL, "i2s-if"),
217 ALIAS(HCLK_LCD, NULL, "lcd"),
218 ALIAS(SCLK_FIMD, NULL, "sclk_fimd"),
219};
220
221/* S3C2416 specific clocks */
222
223static struct samsung_pll_clock s3c2416_pll_clks[] __initdata = {
224 [mpll] = PLL(pll_6552_s3c2416, 0, "mpll", "mpllref",
225 LOCKCON0, MPLLCON, NULL),
226 [epll] = PLL(pll_6553, 0, "epll", "epllref",
227 LOCKCON1, EPLLCON, NULL),
228};
229
230PNAME(s3c2416_hsmmc0_p) = { "sclk_hsmmc0", "sclk_hsmmcext" };
231PNAME(s3c2416_hsmmc1_p) = { "sclk_hsmmc1", "sclk_hsmmcext" };
232PNAME(s3c2416_hsspi0_p) = { "hsspi0_epll", "hsspi0_mpll" };
233
234static struct clk_div_table armdiv_s3c2416_d[] = {
235 { .val = 0, .div = 1 },
236 { .val = 1, .div = 2 },
237 { .val = 2, .div = 3 },
238 { .val = 3, .div = 4 },
239 { .val = 5, .div = 6 },
240 { .val = 7, .div = 8 },
241 { /* sentinel */ },
242};
243
244struct samsung_div_clock s3c2416_dividers[] __initdata = {
245 DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 3, armdiv_s3c2416_d),
246 DIV(0, "div_hsspi0_mpll", "msysclk", CLKDIV2, 0, 4),
247 DIV(0, "div_hsmmc0", "esysclk", CLKDIV2, 6, 2),
248};
249
250struct samsung_mux_clock s3c2416_muxes[] __initdata = {
251 MUX(MUX_HSMMC0, "mux_hsmmc0", s3c2416_hsmmc0_p, CLKSRC, 16, 1),
252 MUX(MUX_HSMMC1, "mux_hsmmc1", s3c2416_hsmmc1_p, CLKSRC, 17, 1),
253 MUX(MUX_HSSPI0, "mux_hsspi0", s3c2416_hsspi0_p, CLKSRC, 18, 1),
254};
255
256struct samsung_gate_clock s3c2416_gates[] __initdata = {
257 GATE(0, "hsspi0_mpll", "div_hsspi0_mpll", SCLKCON, 19, 0, 0),
258 GATE(0, "hsspi0_epll", "div_hsspi0_epll", SCLKCON, 14, 0, 0),
259 GATE(0, "sclk_hsmmc0", "div_hsmmc0", SCLKCON, 6, 0, 0),
260 GATE(HCLK_2D, "2d", "hclk", HCLKCON, 20, 0, 0),
261 GATE(HCLK_HSMMC0, "hsmmc0", "hclk", HCLKCON, 15, 0, 0),
262 GATE(HCLK_IROM, "irom", "hclk", HCLKCON, 13, CLK_IGNORE_UNUSED, 0),
263 GATE(PCLK_PCM, "pcm", "pclk", PCLKCON, 19, 0, 0),
264};
265
266struct samsung_clock_alias s3c2416_aliases[] __initdata = {
267 ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
268 ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
269 ALIAS(MUX_HSMMC0, "s3c-sdhci.0", "mmc_busclk.2"),
270 ALIAS(MUX_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"),
271 ALIAS(MUX_HSSPI0, "s3c2443-spi.0", "spi_busclk2"),
272 ALIAS(ARMDIV, NULL, "armdiv"),
273};
274
275/* S3C2443 specific clocks */
276
277static struct samsung_pll_clock s3c2443_pll_clks[] __initdata = {
278 [mpll] = PLL(pll_3000, 0, "mpll", "mpllref",
279 LOCKCON0, MPLLCON, NULL),
280 [epll] = PLL(pll_2126, 0, "epll", "epllref",
281 LOCKCON1, EPLLCON, NULL),
282};
283
284static struct clk_div_table armdiv_s3c2443_d[] = {
285 { .val = 0, .div = 1 },
286 { .val = 8, .div = 2 },
287 { .val = 2, .div = 3 },
288 { .val = 9, .div = 4 },
289 { .val = 10, .div = 6 },
290 { .val = 11, .div = 8 },
291 { .val = 13, .div = 12 },
292 { .val = 15, .div = 16 },
293 { /* sentinel */ },
294};
295
296struct samsung_div_clock s3c2443_dividers[] __initdata = {
297 DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 4, armdiv_s3c2443_d),
298 DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4),
299};
300
301struct samsung_gate_clock s3c2443_gates[] __initdata = {
302 GATE(SCLK_HSSPI0, "sclk_hsspi0", "div_hsspi0_epll", SCLKCON, 14, 0, 0),
303 GATE(SCLK_CAM, "sclk_cam", "div_cam", SCLKCON, 11, 0, 0),
304 GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, CLK_IGNORE_UNUSED, 0),
305 GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0),
306 GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 15, 0, 0),
307 GATE(PCLK_SDI, "sdi", "pclk", PCLKCON, 5, 0, 0),
308};
309
310struct samsung_clock_alias s3c2443_aliases[] __initdata = {
311 ALIAS(SCLK_HSSPI0, "s3c2443-spi.0", "spi_busclk2"),
312 ALIAS(SCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"),
313 ALIAS(SCLK_CAM, NULL, "camif-upll"),
314 ALIAS(PCLK_SPI1, "s3c2410-spi.0", "spi"),
315 ALIAS(PCLK_SDI, NULL, "sdi"),
316 ALIAS(HCLK_CFC, NULL, "cfc"),
317 ALIAS(ARMDIV, NULL, "armdiv"),
318};
319
320/* S3C2450 specific clocks */
321
322PNAME(s3c2450_cam_p) = { "div_cam", "hclk" };
323PNAME(s3c2450_hsspi1_p) = { "hsspi1_epll", "hsspi1_mpll" };
324PNAME(i2s1_p) = { "div_i2s1", "ext_i2s", "epllref", "epllref" };
325
326struct samsung_div_clock s3c2450_dividers[] __initdata = {
327 DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4),
328 DIV(0, "div_hsspi1_epll", "esysclk", CLKDIV2, 24, 2),
329 DIV(0, "div_hsspi1_mpll", "msysclk", CLKDIV2, 16, 4),
330 DIV(0, "div_i2s1", "esysclk", CLKDIV2, 12, 4),
331};
332
333struct samsung_mux_clock s3c2450_muxes[] __initdata = {
334 MUX(0, "mux_cam", s3c2450_cam_p, CLKSRC, 20, 1),
335 MUX(MUX_HSSPI1, "mux_hsspi1", s3c2450_hsspi1_p, CLKSRC, 19, 1),
336 MUX(0, "mux_i2s1", i2s1_p, CLKSRC, 12, 2),
337};
338
339struct samsung_gate_clock s3c2450_gates[] __initdata = {
340 GATE(SCLK_I2S1, "sclk_i2s1", "div_i2s1", SCLKCON, 5, 0, 0),
341 GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, 0, 0),
342 GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0),
343 GATE(HCLK_DMA7, "dma7", "hclk", HCLKCON, 7, CLK_IGNORE_UNUSED, 0),
344 GATE(HCLK_DMA6, "dma6", "hclk", HCLKCON, 6, CLK_IGNORE_UNUSED, 0),
345 GATE(PCLK_I2S1, "i2s1", "pclk", PCLKCON, 17, 0, 0),
346 GATE(PCLK_I2C1, "i2c1", "pclk", PCLKCON, 16, 0, 0),
347 GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 14, 0, 0),
348};
349
350struct samsung_clock_alias s3c2450_aliases[] __initdata = {
351 ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi"),
352 ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi_busclk0"),
353 ALIAS(MUX_HSSPI1, "s3c2443-spi.1", "spi_busclk2"),
354 ALIAS(PCLK_I2C1, "s3c2410-i2c.1", "i2c"),
355};
356
357/*
358 * fixed rate clocks generated outside the soc
359 * Only necessary until the devicetree-move is complete
360 */
361struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = {
362 FRATE(0, "xti", NULL, CLK_IS_ROOT, 0),
363 FRATE(0, "ext", NULL, CLK_IS_ROOT, 0),
364 FRATE(0, "ext_i2s", NULL, CLK_IS_ROOT, 0),
365 FRATE(0, "ext_uart", NULL, CLK_IS_ROOT, 0),
366};
367
368static void __init s3c2443_common_clk_register_fixed_ext(
369 struct samsung_clk_provider *ctx, unsigned long xti_f)
370{
371 s3c2443_common_frate_clks[0].fixed_rate = xti_f;
372 samsung_clk_register_fixed_rate(ctx, s3c2443_common_frate_clks,
373 ARRAY_SIZE(s3c2443_common_frate_clks));
374}
375
376void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
377 int current_soc,
378 void __iomem *base)
379{
380 struct samsung_clk_provider *ctx;
381 reg_base = base;
382
383 if (np) {
384 reg_base = of_iomap(np, 0);
385 if (!reg_base)
386 panic("%s: failed to map registers\n", __func__);
387 }
388
389 ctx = samsung_clk_init(np, reg_base, NR_CLKS);
390 if (!ctx)
391 panic("%s: unable to allocate context.\n", __func__);
392
393 /* Register external clocks only in non-dt cases */
394 if (!np)
395 s3c2443_common_clk_register_fixed_ext(ctx, xti_f);
396
397 /* Register PLLs. */
398 if (current_soc == S3C2416 || current_soc == S3C2450)
399 samsung_clk_register_pll(ctx, s3c2416_pll_clks,
400 ARRAY_SIZE(s3c2416_pll_clks), reg_base);
401 else
402 samsung_clk_register_pll(ctx, s3c2443_pll_clks,
403 ARRAY_SIZE(s3c2443_pll_clks), reg_base);
404
405 /* Register common internal clocks. */
406 samsung_clk_register_mux(ctx, s3c2443_common_muxes,
407 ARRAY_SIZE(s3c2443_common_muxes));
408 samsung_clk_register_div(ctx, s3c2443_common_dividers,
409 ARRAY_SIZE(s3c2443_common_dividers));
410 samsung_clk_register_gate(ctx, s3c2443_common_gates,
411 ARRAY_SIZE(s3c2443_common_gates));
412 samsung_clk_register_alias(ctx, s3c2443_common_aliases,
413 ARRAY_SIZE(s3c2443_common_aliases));
414
415 /* Register SoC-specific clocks. */
416 switch (current_soc) {
417 case S3C2450:
418 samsung_clk_register_div(ctx, s3c2450_dividers,
419 ARRAY_SIZE(s3c2450_dividers));
420 samsung_clk_register_mux(ctx, s3c2450_muxes,
421 ARRAY_SIZE(s3c2450_muxes));
422 samsung_clk_register_gate(ctx, s3c2450_gates,
423 ARRAY_SIZE(s3c2450_gates));
424 samsung_clk_register_alias(ctx, s3c2450_aliases,
425 ARRAY_SIZE(s3c2450_aliases));
426 /* fall through, as s3c2450 extends the s3c2416 clocks */
427 case S3C2416:
428 samsung_clk_register_div(ctx, s3c2416_dividers,
429 ARRAY_SIZE(s3c2416_dividers));
430 samsung_clk_register_mux(ctx, s3c2416_muxes,
431 ARRAY_SIZE(s3c2416_muxes));
432 samsung_clk_register_gate(ctx, s3c2416_gates,
433 ARRAY_SIZE(s3c2416_gates));
434 samsung_clk_register_alias(ctx, s3c2416_aliases,
435 ARRAY_SIZE(s3c2416_aliases));
436 break;
437 case S3C2443:
438 samsung_clk_register_div(ctx, s3c2443_dividers,
439 ARRAY_SIZE(s3c2443_dividers));
440 samsung_clk_register_gate(ctx, s3c2443_gates,
441 ARRAY_SIZE(s3c2443_gates));
442 samsung_clk_register_alias(ctx, s3c2443_aliases,
443 ARRAY_SIZE(s3c2443_aliases));
444 break;
445 }
446
447 s3c2443_clk_sleep_init();
448}
449
450static void __init s3c2416_clk_init(struct device_node *np)
451{
452 s3c2443_common_clk_init(np, 0, S3C2416, 0);
453}
454CLK_OF_DECLARE(s3c2416_clk, "samsung,s3c2416-clock", s3c2416_clk_init);
455
456static void __init s3c2443_clk_init(struct device_node *np)
457{
458 s3c2443_common_clk_init(np, 0, S3C2443, 0);
459}
460CLK_OF_DECLARE(s3c2443_clk, "samsung,s3c2443-clock", s3c2443_clk_init);
461
462static void __init s3c2450_clk_init(struct device_node *np)
463{
464 s3c2443_common_clk_init(np, 0, S3C2450, 0);
465}
466CLK_OF_DECLARE(s3c2450_clk, "samsung,s3c2450-clock", s3c2450_clk_init);
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
index 8bda658137a8..efa16ee592c8 100644
--- a/drivers/clk/samsung/clk-s3c64xx.c
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -442,12 +442,14 @@ static struct samsung_clock_alias s3c6410_clock_aliases[] = {
442 ALIAS(MEM0_SROM, NULL, "srom"), 442 ALIAS(MEM0_SROM, NULL, "srom"),
443}; 443};
444 444
445static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f, 445static void __init s3c64xx_clk_register_fixed_ext(
446 unsigned long xusbxti_f) 446 struct samsung_clk_provider *ctx,
447 unsigned long fin_pll_f,
448 unsigned long xusbxti_f)
447{ 449{
448 s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f; 450 s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f;
449 s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f; 451 s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
450 samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_ext_clks, 452 samsung_clk_register_fixed_rate(ctx, s3c64xx_fixed_rate_ext_clks,
451 ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks)); 453 ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks));
452} 454}
453 455
@@ -456,6 +458,8 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
456 unsigned long xusbxti_f, bool s3c6400, 458 unsigned long xusbxti_f, bool s3c6400,
457 void __iomem *base) 459 void __iomem *base)
458{ 460{
461 struct samsung_clk_provider *ctx;
462
459 reg_base = base; 463 reg_base = base;
460 is_s3c6400 = s3c6400; 464 is_s3c6400 = s3c6400;
461 465
@@ -465,48 +469,50 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
465 panic("%s: failed to map registers\n", __func__); 469 panic("%s: failed to map registers\n", __func__);
466 } 470 }
467 471
468 samsung_clk_init(np, reg_base, NR_CLKS); 472 ctx = samsung_clk_init(np, reg_base, NR_CLKS);
473 if (!ctx)
474 panic("%s: unable to allocate context.\n", __func__);
469 475
470 /* Register external clocks. */ 476 /* Register external clocks. */
471 if (!np) 477 if (!np)
472 s3c64xx_clk_register_fixed_ext(xtal_f, xusbxti_f); 478 s3c64xx_clk_register_fixed_ext(ctx, xtal_f, xusbxti_f);
473 479
474 /* Register PLLs. */ 480 /* Register PLLs. */
475 samsung_clk_register_pll(s3c64xx_pll_clks, 481 samsung_clk_register_pll(ctx, s3c64xx_pll_clks,
476 ARRAY_SIZE(s3c64xx_pll_clks), reg_base); 482 ARRAY_SIZE(s3c64xx_pll_clks), reg_base);
477 483
478 /* Register common internal clocks. */ 484 /* Register common internal clocks. */
479 samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_clks, 485 samsung_clk_register_fixed_rate(ctx, s3c64xx_fixed_rate_clks,
480 ARRAY_SIZE(s3c64xx_fixed_rate_clks)); 486 ARRAY_SIZE(s3c64xx_fixed_rate_clks));
481 samsung_clk_register_mux(s3c64xx_mux_clks, 487 samsung_clk_register_mux(ctx, s3c64xx_mux_clks,
482 ARRAY_SIZE(s3c64xx_mux_clks)); 488 ARRAY_SIZE(s3c64xx_mux_clks));
483 samsung_clk_register_div(s3c64xx_div_clks, 489 samsung_clk_register_div(ctx, s3c64xx_div_clks,
484 ARRAY_SIZE(s3c64xx_div_clks)); 490 ARRAY_SIZE(s3c64xx_div_clks));
485 samsung_clk_register_gate(s3c64xx_gate_clks, 491 samsung_clk_register_gate(ctx, s3c64xx_gate_clks,
486 ARRAY_SIZE(s3c64xx_gate_clks)); 492 ARRAY_SIZE(s3c64xx_gate_clks));
487 493
488 /* Register SoC-specific clocks. */ 494 /* Register SoC-specific clocks. */
489 if (is_s3c6400) { 495 if (is_s3c6400) {
490 samsung_clk_register_mux(s3c6400_mux_clks, 496 samsung_clk_register_mux(ctx, s3c6400_mux_clks,
491 ARRAY_SIZE(s3c6400_mux_clks)); 497 ARRAY_SIZE(s3c6400_mux_clks));
492 samsung_clk_register_div(s3c6400_div_clks, 498 samsung_clk_register_div(ctx, s3c6400_div_clks,
493 ARRAY_SIZE(s3c6400_div_clks)); 499 ARRAY_SIZE(s3c6400_div_clks));
494 samsung_clk_register_gate(s3c6400_gate_clks, 500 samsung_clk_register_gate(ctx, s3c6400_gate_clks,
495 ARRAY_SIZE(s3c6400_gate_clks)); 501 ARRAY_SIZE(s3c6400_gate_clks));
496 samsung_clk_register_alias(s3c6400_clock_aliases, 502 samsung_clk_register_alias(ctx, s3c6400_clock_aliases,
497 ARRAY_SIZE(s3c6400_clock_aliases)); 503 ARRAY_SIZE(s3c6400_clock_aliases));
498 } else { 504 } else {
499 samsung_clk_register_mux(s3c6410_mux_clks, 505 samsung_clk_register_mux(ctx, s3c6410_mux_clks,
500 ARRAY_SIZE(s3c6410_mux_clks)); 506 ARRAY_SIZE(s3c6410_mux_clks));
501 samsung_clk_register_div(s3c6410_div_clks, 507 samsung_clk_register_div(ctx, s3c6410_div_clks,
502 ARRAY_SIZE(s3c6410_div_clks)); 508 ARRAY_SIZE(s3c6410_div_clks));
503 samsung_clk_register_gate(s3c6410_gate_clks, 509 samsung_clk_register_gate(ctx, s3c6410_gate_clks,
504 ARRAY_SIZE(s3c6410_gate_clks)); 510 ARRAY_SIZE(s3c6410_gate_clks));
505 samsung_clk_register_alias(s3c6410_clock_aliases, 511 samsung_clk_register_alias(ctx, s3c6410_clock_aliases,
506 ARRAY_SIZE(s3c6410_clock_aliases)); 512 ARRAY_SIZE(s3c6410_clock_aliases));
507 } 513 }
508 514
509 samsung_clk_register_alias(s3c64xx_clock_aliases, 515 samsung_clk_register_alias(ctx, s3c64xx_clock_aliases,
510 ARRAY_SIZE(s3c64xx_clock_aliases)); 516 ARRAY_SIZE(s3c64xx_clock_aliases));
511 s3c64xx_clk_sleep_init(); 517 s3c64xx_clk_sleep_init();
512 518
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index 91bec3ebdc8f..49629c71c9e7 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -14,13 +14,6 @@
14#include <linux/syscore_ops.h> 14#include <linux/syscore_ops.h>
15#include "clk.h" 15#include "clk.h"
16 16
17static DEFINE_SPINLOCK(lock);
18static struct clk **clk_table;
19static void __iomem *reg_base;
20#ifdef CONFIG_OF
21static struct clk_onecell_data clk_data;
22#endif
23
24void samsung_clk_save(void __iomem *base, 17void samsung_clk_save(void __iomem *base,
25 struct samsung_clk_reg_dump *rd, 18 struct samsung_clk_reg_dump *rd,
26 unsigned int num_regs) 19 unsigned int num_regs)
@@ -55,40 +48,58 @@ struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
55} 48}
56 49
57/* setup the essentials required to support clock lookup using ccf */ 50/* setup the essentials required to support clock lookup using ccf */
58void __init samsung_clk_init(struct device_node *np, void __iomem *base, 51struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np,
59 unsigned long nr_clks) 52 void __iomem *base, unsigned long nr_clks)
60{ 53{
61 reg_base = base; 54 struct samsung_clk_provider *ctx;
55 struct clk **clk_table;
56 int ret;
57 int i;
62 58
63 clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL); 59 ctx = kzalloc(sizeof(struct samsung_clk_provider), GFP_KERNEL);
60 if (!ctx)
61 panic("could not allocate clock provider context.\n");
62
63 clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
64 if (!clk_table) 64 if (!clk_table)
65 panic("could not allocate clock lookup table\n"); 65 panic("could not allocate clock lookup table\n");
66 66
67 for (i = 0; i < nr_clks; ++i)
68 clk_table[i] = ERR_PTR(-ENOENT);
69
70 ctx->reg_base = base;
71 ctx->clk_data.clks = clk_table;
72 ctx->clk_data.clk_num = nr_clks;
73 spin_lock_init(&ctx->lock);
74
67 if (!np) 75 if (!np)
68 return; 76 return ctx;
69 77
70#ifdef CONFIG_OF 78 ret = of_clk_add_provider(np, of_clk_src_onecell_get,
71 clk_data.clks = clk_table; 79 &ctx->clk_data);
72 clk_data.clk_num = nr_clks; 80 if (ret)
73 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); 81 panic("could not register clock provide\n");
74#endif 82
83 return ctx;
75} 84}
76 85
77/* add a clock instance to the clock lookup table used for dt based lookup */ 86/* add a clock instance to the clock lookup table used for dt based lookup */
78void samsung_clk_add_lookup(struct clk *clk, unsigned int id) 87void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk,
88 unsigned int id)
79{ 89{
80 if (clk_table && id) 90 if (ctx->clk_data.clks && id)
81 clk_table[id] = clk; 91 ctx->clk_data.clks[id] = clk;
82} 92}
83 93
84/* register a list of aliases */ 94/* register a list of aliases */
85void __init samsung_clk_register_alias(struct samsung_clock_alias *list, 95void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
86 unsigned int nr_clk) 96 struct samsung_clock_alias *list,
97 unsigned int nr_clk)
87{ 98{
88 struct clk *clk; 99 struct clk *clk;
89 unsigned int idx, ret; 100 unsigned int idx, ret;
90 101
91 if (!clk_table) { 102 if (!ctx->clk_data.clks) {
92 pr_err("%s: clock table missing\n", __func__); 103 pr_err("%s: clock table missing\n", __func__);
93 return; 104 return;
94 } 105 }
@@ -100,7 +111,7 @@ void __init samsung_clk_register_alias(struct samsung_clock_alias *list,
100 continue; 111 continue;
101 } 112 }
102 113
103 clk = clk_table[list->id]; 114 clk = ctx->clk_data.clks[list->id];
104 if (!clk) { 115 if (!clk) {
105 pr_err("%s: failed to find clock %d\n", __func__, 116 pr_err("%s: failed to find clock %d\n", __func__,
106 list->id); 117 list->id);
@@ -115,7 +126,7 @@ void __init samsung_clk_register_alias(struct samsung_clock_alias *list,
115} 126}
116 127
117/* register a list of fixed clocks */ 128/* register a list of fixed clocks */
118void __init samsung_clk_register_fixed_rate( 129void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
119 struct samsung_fixed_rate_clock *list, unsigned int nr_clk) 130 struct samsung_fixed_rate_clock *list, unsigned int nr_clk)
120{ 131{
121 struct clk *clk; 132 struct clk *clk;
@@ -130,7 +141,7 @@ void __init samsung_clk_register_fixed_rate(
130 continue; 141 continue;
131 } 142 }
132 143
133 samsung_clk_add_lookup(clk, list->id); 144 samsung_clk_add_lookup(ctx, clk, list->id);
134 145
135 /* 146 /*
136 * Unconditionally add a clock lookup for the fixed rate clocks. 147 * Unconditionally add a clock lookup for the fixed rate clocks.
@@ -144,7 +155,7 @@ void __init samsung_clk_register_fixed_rate(
144} 155}
145 156
146/* register a list of fixed factor clocks */ 157/* register a list of fixed factor clocks */
147void __init samsung_clk_register_fixed_factor( 158void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
148 struct samsung_fixed_factor_clock *list, unsigned int nr_clk) 159 struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
149{ 160{
150 struct clk *clk; 161 struct clk *clk;
@@ -159,28 +170,30 @@ void __init samsung_clk_register_fixed_factor(
159 continue; 170 continue;
160 } 171 }
161 172
162 samsung_clk_add_lookup(clk, list->id); 173 samsung_clk_add_lookup(ctx, clk, list->id);
163 } 174 }
164} 175}
165 176
166/* register a list of mux clocks */ 177/* register a list of mux clocks */
167void __init samsung_clk_register_mux(struct samsung_mux_clock *list, 178void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
168 unsigned int nr_clk) 179 struct samsung_mux_clock *list,
180 unsigned int nr_clk)
169{ 181{
170 struct clk *clk; 182 struct clk *clk;
171 unsigned int idx, ret; 183 unsigned int idx, ret;
172 184
173 for (idx = 0; idx < nr_clk; idx++, list++) { 185 for (idx = 0; idx < nr_clk; idx++, list++) {
174 clk = clk_register_mux(NULL, list->name, list->parent_names, 186 clk = clk_register_mux(NULL, list->name, list->parent_names,
175 list->num_parents, list->flags, reg_base + list->offset, 187 list->num_parents, list->flags,
176 list->shift, list->width, list->mux_flags, &lock); 188 ctx->reg_base + list->offset,
189 list->shift, list->width, list->mux_flags, &ctx->lock);
177 if (IS_ERR(clk)) { 190 if (IS_ERR(clk)) {
178 pr_err("%s: failed to register clock %s\n", __func__, 191 pr_err("%s: failed to register clock %s\n", __func__,
179 list->name); 192 list->name);
180 continue; 193 continue;
181 } 194 }
182 195
183 samsung_clk_add_lookup(clk, list->id); 196 samsung_clk_add_lookup(ctx, clk, list->id);
184 197
185 /* register a clock lookup only if a clock alias is specified */ 198 /* register a clock lookup only if a clock alias is specified */
186 if (list->alias) { 199 if (list->alias) {
@@ -194,8 +207,9 @@ void __init samsung_clk_register_mux(struct samsung_mux_clock *list,
194} 207}
195 208
196/* register a list of div clocks */ 209/* register a list of div clocks */
197void __init samsung_clk_register_div(struct samsung_div_clock *list, 210void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
198 unsigned int nr_clk) 211 struct samsung_div_clock *list,
212 unsigned int nr_clk)
199{ 213{
200 struct clk *clk; 214 struct clk *clk;
201 unsigned int idx, ret; 215 unsigned int idx, ret;
@@ -203,22 +217,22 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list,
203 for (idx = 0; idx < nr_clk; idx++, list++) { 217 for (idx = 0; idx < nr_clk; idx++, list++) {
204 if (list->table) 218 if (list->table)
205 clk = clk_register_divider_table(NULL, list->name, 219 clk = clk_register_divider_table(NULL, list->name,
206 list->parent_name, list->flags, 220 list->parent_name, list->flags,
207 reg_base + list->offset, list->shift, 221 ctx->reg_base + list->offset,
208 list->width, list->div_flags, 222 list->shift, list->width, list->div_flags,
209 list->table, &lock); 223 list->table, &ctx->lock);
210 else 224 else
211 clk = clk_register_divider(NULL, list->name, 225 clk = clk_register_divider(NULL, list->name,
212 list->parent_name, list->flags, 226 list->parent_name, list->flags,
213 reg_base + list->offset, list->shift, 227 ctx->reg_base + list->offset, list->shift,
214 list->width, list->div_flags, &lock); 228 list->width, list->div_flags, &ctx->lock);
215 if (IS_ERR(clk)) { 229 if (IS_ERR(clk)) {
216 pr_err("%s: failed to register clock %s\n", __func__, 230 pr_err("%s: failed to register clock %s\n", __func__,
217 list->name); 231 list->name);
218 continue; 232 continue;
219 } 233 }
220 234
221 samsung_clk_add_lookup(clk, list->id); 235 samsung_clk_add_lookup(ctx, clk, list->id);
222 236
223 /* register a clock lookup only if a clock alias is specified */ 237 /* register a clock lookup only if a clock alias is specified */
224 if (list->alias) { 238 if (list->alias) {
@@ -232,16 +246,17 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list,
232} 246}
233 247
234/* register a list of gate clocks */ 248/* register a list of gate clocks */
235void __init samsung_clk_register_gate(struct samsung_gate_clock *list, 249void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
236 unsigned int nr_clk) 250 struct samsung_gate_clock *list,
251 unsigned int nr_clk)
237{ 252{
238 struct clk *clk; 253 struct clk *clk;
239 unsigned int idx, ret; 254 unsigned int idx, ret;
240 255
241 for (idx = 0; idx < nr_clk; idx++, list++) { 256 for (idx = 0; idx < nr_clk; idx++, list++) {
242 clk = clk_register_gate(NULL, list->name, list->parent_name, 257 clk = clk_register_gate(NULL, list->name, list->parent_name,
243 list->flags, reg_base + list->offset, 258 list->flags, ctx->reg_base + list->offset,
244 list->bit_idx, list->gate_flags, &lock); 259 list->bit_idx, list->gate_flags, &ctx->lock);
245 if (IS_ERR(clk)) { 260 if (IS_ERR(clk)) {
246 pr_err("%s: failed to register clock %s\n", __func__, 261 pr_err("%s: failed to register clock %s\n", __func__,
247 list->name); 262 list->name);
@@ -257,7 +272,7 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
257 __func__, list->alias); 272 __func__, list->alias);
258 } 273 }
259 274
260 samsung_clk_add_lookup(clk, list->id); 275 samsung_clk_add_lookup(ctx, clk, list->id);
261 } 276 }
262} 277}
263 278
@@ -266,21 +281,21 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
266 * tree and register it 281 * tree and register it
267 */ 282 */
268#ifdef CONFIG_OF 283#ifdef CONFIG_OF
269void __init samsung_clk_of_register_fixed_ext( 284void __init samsung_clk_of_register_fixed_ext(struct samsung_clk_provider *ctx,
270 struct samsung_fixed_rate_clock *fixed_rate_clk, 285 struct samsung_fixed_rate_clock *fixed_rate_clk,
271 unsigned int nr_fixed_rate_clk, 286 unsigned int nr_fixed_rate_clk,
272 struct of_device_id *clk_matches) 287 struct of_device_id *clk_matches)
273{ 288{
274 const struct of_device_id *match; 289 const struct of_device_id *match;
275 struct device_node *np; 290 struct device_node *clk_np;
276 u32 freq; 291 u32 freq;
277 292
278 for_each_matching_node_and_match(np, clk_matches, &match) { 293 for_each_matching_node_and_match(clk_np, clk_matches, &match) {
279 if (of_property_read_u32(np, "clock-frequency", &freq)) 294 if (of_property_read_u32(clk_np, "clock-frequency", &freq))
280 continue; 295 continue;
281 fixed_rate_clk[(u32)match->data].fixed_rate = freq; 296 fixed_rate_clk[(unsigned long)match->data].fixed_rate = freq;
282 } 297 }
283 samsung_clk_register_fixed_rate(fixed_rate_clk, nr_fixed_rate_clk); 298 samsung_clk_register_fixed_rate(ctx, fixed_rate_clk, nr_fixed_rate_clk);
284} 299}
285#endif 300#endif
286 301
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index c7141ba826e0..9693b80d924f 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -22,6 +22,18 @@
22#include "clk-pll.h" 22#include "clk-pll.h"
23 23
24/** 24/**
25 * struct samsung_clk_provider: information about clock provider
26 * @reg_base: virtual address for the register base.
27 * @clk_data: holds clock related data like clk* and number of clocks.
28 * @lock: maintains exclusion bwtween callbacks for a given clock-provider.
29 */
30struct samsung_clk_provider {
31 void __iomem *reg_base;
32 struct clk_onecell_data clk_data;
33 spinlock_t lock;
34};
35
36/**
25 * struct samsung_clock_alias: information about mux clock 37 * struct samsung_clock_alias: information about mux clock
26 * @id: platform specific id of the clock. 38 * @id: platform specific id of the clock.
27 * @dev_name: name of the device to which this clock belongs. 39 * @dev_name: name of the device to which this clock belongs.
@@ -312,40 +324,52 @@ struct samsung_pll_clock {
312 __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ 324 __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
313 _lock, _con, _rtable, _alias) 325 _lock, _con, _rtable, _alias)
314 326
315extern void __init samsung_clk_init(struct device_node *np, void __iomem *base, 327extern struct samsung_clk_provider *__init samsung_clk_init(
316 unsigned long nr_clks); 328 struct device_node *np, void __iomem *base,
329 unsigned long nr_clks);
317extern void __init samsung_clk_of_register_fixed_ext( 330extern void __init samsung_clk_of_register_fixed_ext(
318 struct samsung_fixed_rate_clock *fixed_rate_clk, 331 struct samsung_clk_provider *ctx,
319 unsigned int nr_fixed_rate_clk, 332 struct samsung_fixed_rate_clock *fixed_rate_clk,
320 struct of_device_id *clk_matches); 333 unsigned int nr_fixed_rate_clk,
334 struct of_device_id *clk_matches);
321 335
322extern void samsung_clk_add_lookup(struct clk *clk, unsigned int id); 336extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
337 struct clk *clk, unsigned int id);
323 338
324extern void samsung_clk_register_alias(struct samsung_clock_alias *list, 339extern void samsung_clk_register_alias(struct samsung_clk_provider *ctx,
325 unsigned int nr_clk); 340 struct samsung_clock_alias *list,
341 unsigned int nr_clk);
326extern void __init samsung_clk_register_fixed_rate( 342extern void __init samsung_clk_register_fixed_rate(
327 struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk); 343 struct samsung_clk_provider *ctx,
344 struct samsung_fixed_rate_clock *clk_list,
345 unsigned int nr_clk);
328extern void __init samsung_clk_register_fixed_factor( 346extern void __init samsung_clk_register_fixed_factor(
329 struct samsung_fixed_factor_clock *list, unsigned int nr_clk); 347 struct samsung_clk_provider *ctx,
330extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list, 348 struct samsung_fixed_factor_clock *list,
331 unsigned int nr_clk); 349 unsigned int nr_clk);
332extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list, 350extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
333 unsigned int nr_clk); 351 struct samsung_mux_clock *clk_list,
334extern void __init samsung_clk_register_gate( 352 unsigned int nr_clk);
335 struct samsung_gate_clock *clk_list, unsigned int nr_clk); 353extern void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
336extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, 354 struct samsung_div_clock *clk_list,
337 unsigned int nr_clk, void __iomem *base); 355 unsigned int nr_clk);
356extern void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
357 struct samsung_gate_clock *clk_list,
358 unsigned int nr_clk);
359extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
360 struct samsung_pll_clock *pll_list,
361 unsigned int nr_clk, void __iomem *base);
338 362
339extern unsigned long _get_rate(const char *clk_name); 363extern unsigned long _get_rate(const char *clk_name);
340 364
341extern void samsung_clk_save(void __iomem *base, 365extern void samsung_clk_save(void __iomem *base,
342 struct samsung_clk_reg_dump *rd, 366 struct samsung_clk_reg_dump *rd,
343 unsigned int num_regs); 367 unsigned int num_regs);
344extern void samsung_clk_restore(void __iomem *base, 368extern void samsung_clk_restore(void __iomem *base,
345 const struct samsung_clk_reg_dump *rd, 369 const struct samsung_clk_reg_dump *rd,
346 unsigned int num_regs); 370 unsigned int num_regs);
347extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( 371extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
348 const unsigned long *rdump, 372 const unsigned long *rdump,
349 unsigned long nr_rdump); 373 unsigned long nr_rdump);
350 374
351#endif /* __SAMSUNG_CLK_H */ 375#endif /* __SAMSUNG_CLK_H */
diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile
index 5404cb931ebf..e0029237827a 100644
--- a/drivers/clk/shmobile/Makefile
+++ b/drivers/clk/shmobile/Makefile
@@ -1,5 +1,7 @@
1obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o 1obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o
2obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o 2obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o
3obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o
4obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o
3obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o 5obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o
4obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o 6obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o
5obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o 7obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o
diff --git a/drivers/clk/shmobile/clk-mstp.c b/drivers/clk/shmobile/clk-mstp.c
index 1f6324e29a80..2d2fe773ac81 100644
--- a/drivers/clk/shmobile/clk-mstp.c
+++ b/drivers/clk/shmobile/clk-mstp.c
@@ -112,7 +112,7 @@ static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
112 else 112 else
113 value = clk_readl(group->smstpcr); 113 value = clk_readl(group->smstpcr);
114 114
115 return !!(value & BIT(clock->bit_index)); 115 return !(value & BIT(clock->bit_index));
116} 116}
117 117
118static const struct clk_ops cpg_mstp_clock_ops = { 118static const struct clk_ops cpg_mstp_clock_ops = {
diff --git a/drivers/clk/shmobile/clk-r8a7740.c b/drivers/clk/shmobile/clk-r8a7740.c
new file mode 100644
index 000000000000..1e2eaae21e01
--- /dev/null
+++ b/drivers/clk/shmobile/clk-r8a7740.c
@@ -0,0 +1,199 @@
1/*
2 * r8a7740 Core CPG Clocks
3 *
4 * Copyright (C) 2014 Ulrich Hecht
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; version 2 of the License.
9 */
10
11#include <linux/clk-provider.h>
12#include <linux/clkdev.h>
13#include <linux/clk/shmobile.h>
14#include <linux/init.h>
15#include <linux/kernel.h>
16#include <linux/of.h>
17#include <linux/of_address.h>
18#include <linux/spinlock.h>
19
20struct r8a7740_cpg {
21 struct clk_onecell_data data;
22 spinlock_t lock;
23 void __iomem *reg;
24};
25
26#define CPG_FRQCRA 0x00
27#define CPG_FRQCRB 0x04
28#define CPG_PLLC2CR 0x2c
29#define CPG_USBCKCR 0x8c
30#define CPG_FRQCRC 0xe0
31
32#define CLK_ENABLE_ON_INIT BIT(0)
33
34struct div4_clk {
35 const char *name;
36 unsigned int reg;
37 unsigned int shift;
38 int flags;
39};
40
41static struct div4_clk div4_clks[] = {
42 { "i", CPG_FRQCRA, 20, CLK_ENABLE_ON_INIT },
43 { "zg", CPG_FRQCRA, 16, CLK_ENABLE_ON_INIT },
44 { "b", CPG_FRQCRA, 8, CLK_ENABLE_ON_INIT },
45 { "m1", CPG_FRQCRA, 4, CLK_ENABLE_ON_INIT },
46 { "hp", CPG_FRQCRB, 4, 0 },
47 { "hpp", CPG_FRQCRC, 20, 0 },
48 { "usbp", CPG_FRQCRC, 16, 0 },
49 { "s", CPG_FRQCRC, 12, 0 },
50 { "zb", CPG_FRQCRC, 8, 0 },
51 { "m3", CPG_FRQCRC, 4, 0 },
52 { "cp", CPG_FRQCRC, 0, 0 },
53 { NULL, 0, 0, 0 },
54};
55
56static const struct clk_div_table div4_div_table[] = {
57 { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 12 },
58 { 6, 16 }, { 7, 18 }, { 8, 24 }, { 9, 32 }, { 10, 36 }, { 11, 48 },
59 { 13, 72 }, { 14, 96 }, { 0, 0 }
60};
61
62static u32 cpg_mode __initdata;
63
64static struct clk * __init
65r8a7740_cpg_register_clock(struct device_node *np, struct r8a7740_cpg *cpg,
66 const char *name)
67{
68 const struct clk_div_table *table = NULL;
69 const char *parent_name;
70 unsigned int shift, reg;
71 unsigned int mult = 1;
72 unsigned int div = 1;
73
74 if (!strcmp(name, "r")) {
75 switch (cpg_mode & (BIT(2) | BIT(1))) {
76 case BIT(1) | BIT(2):
77 /* extal1 */
78 parent_name = of_clk_get_parent_name(np, 0);
79 div = 2048;
80 break;
81 case BIT(2):
82 /* extal1 */
83 parent_name = of_clk_get_parent_name(np, 0);
84 div = 1024;
85 break;
86 default:
87 /* extalr */
88 parent_name = of_clk_get_parent_name(np, 2);
89 break;
90 }
91 } else if (!strcmp(name, "system")) {
92 parent_name = of_clk_get_parent_name(np, 0);
93 if (cpg_mode & BIT(1))
94 div = 2;
95 } else if (!strcmp(name, "pllc0")) {
96 /* PLLC0/1 are configurable multiplier clocks. Register them as
97 * fixed factor clocks for now as there's no generic multiplier
98 * clock implementation and we currently have no need to change
99 * the multiplier value.
100 */
101 u32 value = clk_readl(cpg->reg + CPG_FRQCRC);
102 parent_name = "system";
103 mult = ((value >> 24) & 0x7f) + 1;
104 } else if (!strcmp(name, "pllc1")) {
105 u32 value = clk_readl(cpg->reg + CPG_FRQCRA);
106 parent_name = "system";
107 mult = ((value >> 24) & 0x7f) + 1;
108 div = 2;
109 } else if (!strcmp(name, "pllc2")) {
110 u32 value = clk_readl(cpg->reg + CPG_PLLC2CR);
111 parent_name = "system";
112 mult = ((value >> 24) & 0x3f) + 1;
113 } else if (!strcmp(name, "usb24s")) {
114 u32 value = clk_readl(cpg->reg + CPG_USBCKCR);
115 if (value & BIT(7))
116 /* extal2 */
117 parent_name = of_clk_get_parent_name(np, 1);
118 else
119 parent_name = "system";
120 if (!(value & BIT(6)))
121 div = 2;
122 } else {
123 struct div4_clk *c;
124 for (c = div4_clks; c->name; c++) {
125 if (!strcmp(name, c->name)) {
126 parent_name = "pllc1";
127 table = div4_div_table;
128 reg = c->reg;
129 shift = c->shift;
130 break;
131 }
132 }
133 if (!c->name)
134 return ERR_PTR(-EINVAL);
135 }
136
137 if (!table) {
138 return clk_register_fixed_factor(NULL, name, parent_name, 0,
139 mult, div);
140 } else {
141 return clk_register_divider_table(NULL, name, parent_name, 0,
142 cpg->reg + reg, shift, 4, 0,
143 table, &cpg->lock);
144 }
145}
146
147static void __init r8a7740_cpg_clocks_init(struct device_node *np)
148{
149 struct r8a7740_cpg *cpg;
150 struct clk **clks;
151 unsigned int i;
152 int num_clks;
153
154 if (of_property_read_u32(np, "renesas,mode", &cpg_mode))
155 pr_warn("%s: missing renesas,mode property\n", __func__);
156
157 num_clks = of_property_count_strings(np, "clock-output-names");
158 if (num_clks < 0) {
159 pr_err("%s: failed to count clocks\n", __func__);
160 return;
161 }
162
163 cpg = kzalloc(sizeof(*cpg), GFP_KERNEL);
164 clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL);
165 if (cpg == NULL || clks == NULL) {
166 /* We're leaking memory on purpose, there's no point in cleaning
167 * up as the system won't boot anyway.
168 */
169 return;
170 }
171
172 spin_lock_init(&cpg->lock);
173
174 cpg->data.clks = clks;
175 cpg->data.clk_num = num_clks;
176
177 cpg->reg = of_iomap(np, 0);
178 if (WARN_ON(cpg->reg == NULL))
179 return;
180
181 for (i = 0; i < num_clks; ++i) {
182 const char *name;
183 struct clk *clk;
184
185 of_property_read_string_index(np, "clock-output-names", i,
186 &name);
187
188 clk = r8a7740_cpg_register_clock(np, cpg, name);
189 if (IS_ERR(clk))
190 pr_err("%s: failed to register %s %s clock (%ld)\n",
191 __func__, np->name, name, PTR_ERR(clk));
192 else
193 cpg->data.clks[i] = clk;
194 }
195
196 of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data);
197}
198CLK_OF_DECLARE(r8a7740_cpg_clks, "renesas,r8a7740-cpg-clocks",
199 r8a7740_cpg_clocks_init);
diff --git a/drivers/clk/shmobile/clk-r8a7779.c b/drivers/clk/shmobile/clk-r8a7779.c
new file mode 100644
index 000000000000..652ecacb6daf
--- /dev/null
+++ b/drivers/clk/shmobile/clk-r8a7779.c
@@ -0,0 +1,180 @@
1/*
2 * r8a7779 Core CPG Clocks
3 *
4 * Copyright (C) 2013, 2014 Horms Solutions Ltd.
5 *
6 * Contact: Simon Horman <horms@verge.net.au>
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 <linux/clkdev.h>
15#include <linux/clk/shmobile.h>
16#include <linux/init.h>
17#include <linux/kernel.h>
18#include <linux/of.h>
19#include <linux/of_address.h>
20#include <linux/spinlock.h>
21
22#include <dt-bindings/clock/r8a7779-clock.h>
23
24#define CPG_NUM_CLOCKS (R8A7779_CLK_OUT + 1)
25
26struct r8a7779_cpg {
27 struct clk_onecell_data data;
28 spinlock_t lock;
29 void __iomem *reg;
30};
31
32/* -----------------------------------------------------------------------------
33 * CPG Clock Data
34 */
35
36/*
37 * MD1 = 1 MD1 = 0
38 * (PLLA = 1500) (PLLA = 1600)
39 * (MHz) (MHz)
40 *------------------------------------------------+--------------------
41 * clkz 1000 (2/3) 800 (1/2)
42 * clkzs 250 (1/6) 200 (1/8)
43 * clki 750 (1/2) 800 (1/2)
44 * clks 250 (1/6) 200 (1/8)
45 * clks1 125 (1/12) 100 (1/16)
46 * clks3 187.5 (1/8) 200 (1/8)
47 * clks4 93.7 (1/16) 100 (1/16)
48 * clkp 62.5 (1/24) 50 (1/32)
49 * clkg 62.5 (1/24) 66.6 (1/24)
50 * clkb, CLKOUT
51 * (MD2 = 0) 62.5 (1/24) 66.6 (1/24)
52 * (MD2 = 1) 41.6 (1/36) 50 (1/32)
53 */
54
55#define CPG_CLK_CONFIG_INDEX(md) (((md) & (BIT(2)|BIT(1))) >> 1)
56
57struct cpg_clk_config {
58 unsigned int z_mult;
59 unsigned int z_div;
60 unsigned int zs_and_s_div;
61 unsigned int s1_div;
62 unsigned int p_div;
63 unsigned int b_and_out_div;
64};
65
66static const struct cpg_clk_config cpg_clk_configs[4] __initconst = {
67 { 1, 2, 8, 16, 32, 24 },
68 { 2, 3, 6, 12, 24, 24 },
69 { 1, 2, 8, 16, 32, 32 },
70 { 2, 3, 6, 12, 24, 36 },
71};
72
73/*
74 * MD PLLA Ratio
75 * 12 11
76 *------------------------
77 * 0 0 x42
78 * 0 1 x48
79 * 1 0 x56
80 * 1 1 x64
81 */
82
83#define CPG_PLLA_MULT_INDEX(md) (((md) & (BIT(12)|BIT(11))) >> 11)
84
85static const unsigned int cpg_plla_mult[4] __initconst = { 42, 48, 56, 64 };
86
87/* -----------------------------------------------------------------------------
88 * Initialization
89 */
90
91static u32 cpg_mode __initdata;
92
93static struct clk * __init
94r8a7779_cpg_register_clock(struct device_node *np, struct r8a7779_cpg *cpg,
95 const struct cpg_clk_config *config,
96 unsigned int plla_mult, const char *name)
97{
98 const char *parent_name = "plla";
99 unsigned int mult = 1;
100 unsigned int div = 1;
101
102 if (!strcmp(name, "plla")) {
103 parent_name = of_clk_get_parent_name(np, 0);
104 mult = plla_mult;
105 } else if (!strcmp(name, "z")) {
106 div = config->z_div;
107 mult = config->z_mult;
108 } else if (!strcmp(name, "zs") || !strcmp(name, "s")) {
109 div = config->zs_and_s_div;
110 } else if (!strcmp(name, "s1")) {
111 div = config->s1_div;
112 } else if (!strcmp(name, "p")) {
113 div = config->p_div;
114 } else if (!strcmp(name, "b") || !strcmp(name, "out")) {
115 div = config->b_and_out_div;
116 } else {
117 return ERR_PTR(-EINVAL);
118 }
119
120 return clk_register_fixed_factor(NULL, name, parent_name, 0, mult, div);
121}
122
123static void __init r8a7779_cpg_clocks_init(struct device_node *np)
124{
125 const struct cpg_clk_config *config;
126 struct r8a7779_cpg *cpg;
127 struct clk **clks;
128 unsigned int i, plla_mult;
129 int num_clks;
130
131 num_clks = of_property_count_strings(np, "clock-output-names");
132 if (num_clks < 0) {
133 pr_err("%s: failed to count clocks\n", __func__);
134 return;
135 }
136
137 cpg = kzalloc(sizeof(*cpg), GFP_KERNEL);
138 clks = kzalloc(CPG_NUM_CLOCKS * sizeof(*clks), GFP_KERNEL);
139 if (cpg == NULL || clks == NULL) {
140 /* We're leaking memory on purpose, there's no point in cleaning
141 * up as the system won't boot anyway.
142 */
143 return;
144 }
145
146 spin_lock_init(&cpg->lock);
147
148 cpg->data.clks = clks;
149 cpg->data.clk_num = num_clks;
150
151 config = &cpg_clk_configs[CPG_CLK_CONFIG_INDEX(cpg_mode)];
152 plla_mult = cpg_plla_mult[CPG_PLLA_MULT_INDEX(cpg_mode)];
153
154 for (i = 0; i < num_clks; ++i) {
155 const char *name;
156 struct clk *clk;
157
158 of_property_read_string_index(np, "clock-output-names", i,
159 &name);
160
161 clk = r8a7779_cpg_register_clock(np, cpg, config,
162 plla_mult, name);
163 if (IS_ERR(clk))
164 pr_err("%s: failed to register %s %s clock (%ld)\n",
165 __func__, np->name, name, PTR_ERR(clk));
166 else
167 cpg->data.clks[i] = clk;
168 }
169
170 of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data);
171}
172CLK_OF_DECLARE(r8a7779_cpg_clks, "renesas,r8a7779-cpg-clocks",
173 r8a7779_cpg_clocks_init);
174
175void __init r8a7779_clocks_init(u32 mode)
176{
177 cpg_mode = mode;
178
179 of_clk_init(NULL);
180}
diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c
index 501d513bf890..dd3a78c64795 100644
--- a/drivers/clk/socfpga/clk-gate.c
+++ b/drivers/clk/socfpga/clk-gate.c
@@ -32,7 +32,6 @@
32#define SOCFPGA_MMC_CLK "sdmmc_clk" 32#define SOCFPGA_MMC_CLK "sdmmc_clk"
33#define SOCFPGA_GPIO_DB_CLK_OFFSET 0xA8 33#define SOCFPGA_GPIO_DB_CLK_OFFSET 0xA8
34 34
35#define div_mask(width) ((1 << (width)) - 1)
36#define streq(a, b) (strcmp((a), (b)) == 0) 35#define streq(a, b) (strcmp((a), (b)) == 0)
37 36
38#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw) 37#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
diff --git a/drivers/clk/socfpga/clk-periph.c b/drivers/clk/socfpga/clk-periph.c
index 81623a3736f9..46531c34ec9b 100644
--- a/drivers/clk/socfpga/clk-periph.c
+++ b/drivers/clk/socfpga/clk-periph.c
@@ -29,12 +29,18 @@ static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
29 unsigned long parent_rate) 29 unsigned long parent_rate)
30{ 30{
31 struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk); 31 struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk);
32 u32 div; 32 u32 div, val;
33 33
34 if (socfpgaclk->fixed_div) 34 if (socfpgaclk->fixed_div) {
35 div = socfpgaclk->fixed_div; 35 div = socfpgaclk->fixed_div;
36 else 36 } else {
37 if (socfpgaclk->div_reg) {
38 val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
39 val &= div_mask(socfpgaclk->width);
40 parent_rate /= (val + 1);
41 }
37 div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1); 42 div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1);
43 }
38 44
39 return parent_rate / div; 45 return parent_rate / div;
40} 46}
@@ -54,6 +60,7 @@ static __init void __socfpga_periph_init(struct device_node *node,
54 struct clk_init_data init; 60 struct clk_init_data init;
55 int rc; 61 int rc;
56 u32 fixed_div; 62 u32 fixed_div;
63 u32 div_reg[3];
57 64
58 of_property_read_u32(node, "reg", &reg); 65 of_property_read_u32(node, "reg", &reg);
59 66
@@ -63,6 +70,15 @@ static __init void __socfpga_periph_init(struct device_node *node,
63 70
64 periph_clk->hw.reg = clk_mgr_base_addr + reg; 71 periph_clk->hw.reg = clk_mgr_base_addr + reg;
65 72
73 rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
74 if (!rc) {
75 periph_clk->div_reg = clk_mgr_base_addr + div_reg[0];
76 periph_clk->shift = div_reg[1];
77 periph_clk->width = div_reg[2];
78 } else {
79 periph_clk->div_reg = 0;
80 }
81
66 rc = of_property_read_u32(node, "fixed-divider", &fixed_div); 82 rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
67 if (rc) 83 if (rc)
68 periph_clk->fixed_div = 0; 84 periph_clk->fixed_div = 0;
diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
index d2e54019c94f..d291f60c46e1 100644
--- a/drivers/clk/socfpga/clk.h
+++ b/drivers/clk/socfpga/clk.h
@@ -27,6 +27,7 @@
27#define CLKMGR_PERPLL_SRC 0xAC 27#define CLKMGR_PERPLL_SRC 0xAC
28 28
29#define SOCFPGA_MAX_PARENTS 3 29#define SOCFPGA_MAX_PARENTS 3
30#define div_mask(width) ((1 << (width)) - 1)
30 31
31extern void __iomem *clk_mgr_base_addr; 32extern void __iomem *clk_mgr_base_addr;
32 33
@@ -52,6 +53,9 @@ struct socfpga_periph_clk {
52 struct clk_gate hw; 53 struct clk_gate hw;
53 char *parent_name; 54 char *parent_name;
54 u32 fixed_div; 55 u32 fixed_div;
56 void __iomem *div_reg;
57 u32 width; /* only valid if div_reg != 0 */
58 u32 shift; /* only valid if div_reg != 0 */
55}; 59};
56 60
57#endif /* SOCFPGA_CLK_H */ 61#endif /* SOCFPGA_CLK_H */
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
index a886702f7c8b..d8b9b1a2aeda 100644
--- a/drivers/clk/st/clkgen-pll.c
+++ b/drivers/clk/st/clkgen-pll.c
@@ -655,6 +655,7 @@ static struct of_device_id c32_gpu_pll_of_match[] = {
655 .compatible = "st,stih416-gpu-pll-c32", 655 .compatible = "st,stih416-gpu-pll-c32",
656 .data = &st_pll1200c32_gpu_416, 656 .data = &st_pll1200c32_gpu_416,
657 }, 657 },
658 {}
658}; 659};
659 660
660static void __init clkgengpu_c32_pll_setup(struct device_node *np) 661static void __init clkgengpu_c32_pll_setup(struct device_node *np)
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 9e232644f07e..3806d97e529b 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -77,6 +77,41 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate,
77 return rate; 77 return rate;
78} 78}
79 79
80static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
81 unsigned long *best_parent_rate,
82 struct clk **best_parent_p)
83{
84 struct clk *clk = hw->clk, *parent, *best_parent = NULL;
85 int i, num_parents;
86 unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0;
87
88 /* find the parent that can help provide the fastest rate <= rate */
89 num_parents = __clk_get_num_parents(clk);
90 for (i = 0; i < num_parents; i++) {
91 parent = clk_get_parent_by_index(clk, i);
92 if (!parent)
93 continue;
94 if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
95 parent_rate = __clk_round_rate(parent, rate);
96 else
97 parent_rate = __clk_get_rate(parent);
98
99 child_rate = clk_factors_round_rate(hw, rate, &parent_rate);
100
101 if (child_rate <= rate && child_rate > best_child_rate) {
102 best_parent = parent;
103 best = parent_rate;
104 best_child_rate = child_rate;
105 }
106 }
107
108 if (best_parent)
109 *best_parent_p = best_parent;
110 *best_parent_rate = best;
111
112 return best_child_rate;
113}
114
80static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, 115static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
81 unsigned long parent_rate) 116 unsigned long parent_rate)
82{ 117{
@@ -113,6 +148,7 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
113} 148}
114 149
115const struct clk_ops clk_factors_ops = { 150const struct clk_ops clk_factors_ops = {
151 .determine_rate = clk_factors_determine_rate,
116 .recalc_rate = clk_factors_recalc_rate, 152 .recalc_rate = clk_factors_recalc_rate,
117 .round_rate = clk_factors_round_rate, 153 .round_rate = clk_factors_round_rate,
118 .set_rate = clk_factors_set_rate, 154 .set_rate = clk_factors_set_rate,
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index bd7dc733c1ca..426483422d3d 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -507,6 +507,43 @@ CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
507 507
508 508
509/** 509/**
510 * clk_sunxi_mmc_phase_control() - configures MMC clock phase control
511 */
512
513void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output)
514{
515 #define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw)
516 #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
517
518 struct clk_hw *hw = __clk_get_hw(clk);
519 struct clk_composite *composite = to_clk_composite(hw);
520 struct clk_hw *rate_hw = composite->rate_hw;
521 struct clk_factors *factors = to_clk_factors(rate_hw);
522 unsigned long flags = 0;
523 u32 reg;
524
525 if (factors->lock)
526 spin_lock_irqsave(factors->lock, flags);
527
528 reg = readl(factors->reg);
529
530 /* set sample clock phase control */
531 reg &= ~(0x7 << 20);
532 reg |= ((sample & 0x7) << 20);
533
534 /* set output clock phase control */
535 reg &= ~(0x7 << 8);
536 reg |= ((output & 0x7) << 8);
537
538 writel(reg, factors->reg);
539
540 if (factors->lock)
541 spin_unlock_irqrestore(factors->lock, flags);
542}
543EXPORT_SYMBOL(clk_sunxi_mmc_phase_control);
544
545
546/**
510 * sunxi_factors_clk_setup() - Setup function for factor clocks 547 * sunxi_factors_clk_setup() - Setup function for factor clocks
511 */ 548 */
512 549
@@ -1278,8 +1315,7 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat
1278 const struct of_device_id *match; 1315 const struct of_device_id *match;
1279 void (*setup_function)(struct device_node *, const void *) = function; 1316 void (*setup_function)(struct device_node *, const void *) = function;
1280 1317
1281 for_each_matching_node(np, clk_match) { 1318 for_each_matching_node_and_match(np, clk_match, &match) {
1282 match = of_match_node(clk_match, np);
1283 data = match->data; 1319 data = match->data;
1284 setup_function(np, data); 1320 setup_function(np, data);
1285 } 1321 }
@@ -1310,7 +1346,7 @@ static void __init sunxi_clock_protect(void)
1310 } 1346 }
1311} 1347}
1312 1348
1313static void __init sunxi_init_clocks(void) 1349static void __init sunxi_init_clocks(struct device_node *np)
1314{ 1350{
1315 /* Register factor clocks */ 1351 /* Register factor clocks */
1316 of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); 1352 of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup);
diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h
index c39613c519af..0011d547a9f7 100644
--- a/drivers/clk/tegra/clk-id.h
+++ b/drivers/clk/tegra/clk-id.h
@@ -233,6 +233,7 @@ enum clk_id {
233 tegra_clk_xusb_hs_src, 233 tegra_clk_xusb_hs_src,
234 tegra_clk_xusb_ss, 234 tegra_clk_xusb_ss,
235 tegra_clk_xusb_ss_src, 235 tegra_clk_xusb_ss_src,
236 tegra_clk_xusb_ss_div2,
236 tegra_clk_max, 237 tegra_clk_max,
237}; 238};
238 239
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 6aad8abc69a2..637b62ccc91e 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -96,10 +96,20 @@
96 (PLLE_SS_MAX_VAL | PLLE_SS_INC_VAL | PLLE_SS_INCINTRV_VAL) 96 (PLLE_SS_MAX_VAL | PLLE_SS_INC_VAL | PLLE_SS_INCINTRV_VAL)
97 97
98#define PLLE_AUX_PLLP_SEL BIT(2) 98#define PLLE_AUX_PLLP_SEL BIT(2)
99#define PLLE_AUX_USE_LOCKDET BIT(3)
99#define PLLE_AUX_ENABLE_SWCTL BIT(4) 100#define PLLE_AUX_ENABLE_SWCTL BIT(4)
101#define PLLE_AUX_SS_SWCTL BIT(6)
100#define PLLE_AUX_SEQ_ENABLE BIT(24) 102#define PLLE_AUX_SEQ_ENABLE BIT(24)
103#define PLLE_AUX_SEQ_START_STATE BIT(25)
101#define PLLE_AUX_PLLRE_SEL BIT(28) 104#define PLLE_AUX_PLLRE_SEL BIT(28)
102 105
106#define XUSBIO_PLL_CFG0 0x51c
107#define XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL BIT(0)
108#define XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL BIT(2)
109#define XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET BIT(6)
110#define XUSBIO_PLL_CFG0_SEQ_ENABLE BIT(24)
111#define XUSBIO_PLL_CFG0_SEQ_START_STATE BIT(25)
112
103#define PLLE_MISC_PLLE_PTS BIT(8) 113#define PLLE_MISC_PLLE_PTS BIT(8)
104#define PLLE_MISC_IDDQ_SW_VALUE BIT(13) 114#define PLLE_MISC_IDDQ_SW_VALUE BIT(13)
105#define PLLE_MISC_IDDQ_SW_CTRL BIT(14) 115#define PLLE_MISC_IDDQ_SW_CTRL BIT(14)
@@ -1328,7 +1338,28 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
1328 pll_writel(val, PLLE_SS_CTRL, pll); 1338 pll_writel(val, PLLE_SS_CTRL, pll);
1329 udelay(1); 1339 udelay(1);
1330 1340
1331 /* TODO: enable hw control of xusb brick pll */ 1341 /* Enable hw control of xusb brick pll */
1342 val = pll_readl_misc(pll);
1343 val &= ~PLLE_MISC_IDDQ_SW_CTRL;
1344 pll_writel_misc(val, pll);
1345
1346 val = pll_readl(pll->params->aux_reg, pll);
1347 val |= (PLLE_AUX_USE_LOCKDET | PLLE_AUX_SEQ_START_STATE);
1348 val &= ~(PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL);
1349 pll_writel(val, pll->params->aux_reg, pll);
1350 udelay(1);
1351 val |= PLLE_AUX_SEQ_ENABLE;
1352 pll_writel(val, pll->params->aux_reg, pll);
1353
1354 val = pll_readl(XUSBIO_PLL_CFG0, pll);
1355 val |= (XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET |
1356 XUSBIO_PLL_CFG0_SEQ_START_STATE);
1357 val &= ~(XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL |
1358 XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL);
1359 pll_writel(val, XUSBIO_PLL_CFG0, pll);
1360 udelay(1);
1361 val |= XUSBIO_PLL_CFG0_SEQ_ENABLE;
1362 pll_writel(val, XUSBIO_PLL_CFG0, pll);
1332 1363
1333out: 1364out:
1334 if (pll->lock) 1365 if (pll->lock)
diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c
index 1fa5c3f33b20..adf6b814b5bc 100644
--- a/drivers/clk/tegra/clk-tegra-periph.c
+++ b/drivers/clk/tegra/clk-tegra-periph.c
@@ -329,7 +329,9 @@ static u32 mux_clkm_pllp_pllc_pllre_idx[] = {
329static const char *mux_clkm_48M_pllp_480M[] = { 329static const char *mux_clkm_48M_pllp_480M[] = {
330 "clk_m", "pll_u_48M", "pll_p", "pll_u_480M" 330 "clk_m", "pll_u_48M", "pll_p", "pll_u_480M"
331}; 331};
332#define mux_clkm_48M_pllp_480M_idx NULL 332static u32 mux_clkm_48M_pllp_480M_idx[] = {
333 [0] = 0, [1] = 2, [2] = 4, [3] = 6,
334};
333 335
334static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = { 336static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = {
335 "clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref" 337 "clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref"
@@ -338,6 +340,11 @@ static u32 mux_clkm_pllre_clk32_480M_pllc_ref_idx[] = {
338 [0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7, 340 [0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7,
339}; 341};
340 342
343static const char *mux_ss_60M[] = {
344 "xusb_ss_div2", "pll_u_60M"
345};
346#define mux_ss_60M_idx NULL
347
341static const char *mux_d_audio_clk[] = { 348static const char *mux_d_audio_clk[] = {
342 "pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync", 349 "pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync",
343 "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync", 350 "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
@@ -499,6 +506,7 @@ static struct tegra_periph_init_data periph_clks[] = {
499 XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src), 506 XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src),
500 XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src), 507 XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src),
501 XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ss_src), 508 XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ss_src),
509 NODIV("xusb_hs_src", mux_ss_60M, CLK_SOURCE_XUSB_SS_SRC, 25, MASK(1), 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_hs_src, NULL),
502 XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src), 510 XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src),
503}; 511};
504 512
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
index 80431f0fb268..b9c8ba258ef0 100644
--- a/drivers/clk/tegra/clk-tegra114.c
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -142,7 +142,6 @@
142#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0) 142#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0)
143 143
144#define CLK_SOURCE_CSITE 0x1d4 144#define CLK_SOURCE_CSITE 0x1d4
145#define CLK_SOURCE_XUSB_SS_SRC 0x610
146#define CLK_SOURCE_EMC 0x19c 145#define CLK_SOURCE_EMC 0x19c
147 146
148/* PLLM override registers */ 147/* PLLM override registers */
@@ -834,6 +833,7 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
834 [tegra_clk_xusb_falcon_src] = { .dt_id = TEGRA114_CLK_XUSB_FALCON_SRC, .present = true }, 833 [tegra_clk_xusb_falcon_src] = { .dt_id = TEGRA114_CLK_XUSB_FALCON_SRC, .present = true },
835 [tegra_clk_xusb_fs_src] = { .dt_id = TEGRA114_CLK_XUSB_FS_SRC, .present = true }, 834 [tegra_clk_xusb_fs_src] = { .dt_id = TEGRA114_CLK_XUSB_FS_SRC, .present = true },
836 [tegra_clk_xusb_ss_src] = { .dt_id = TEGRA114_CLK_XUSB_SS_SRC, .present = true }, 835 [tegra_clk_xusb_ss_src] = { .dt_id = TEGRA114_CLK_XUSB_SS_SRC, .present = true },
836 [tegra_clk_xusb_ss_div2] = { .dt_id = TEGRA114_CLK_XUSB_SS_DIV2, .present = true},
837 [tegra_clk_xusb_dev_src] = { .dt_id = TEGRA114_CLK_XUSB_DEV_SRC, .present = true }, 837 [tegra_clk_xusb_dev_src] = { .dt_id = TEGRA114_CLK_XUSB_DEV_SRC, .present = true },
838 [tegra_clk_xusb_dev] = { .dt_id = TEGRA114_CLK_XUSB_DEV, .present = true }, 838 [tegra_clk_xusb_dev] = { .dt_id = TEGRA114_CLK_XUSB_DEV, .present = true },
839 [tegra_clk_xusb_hs_src] = { .dt_id = TEGRA114_CLK_XUSB_HS_SRC, .present = true }, 839 [tegra_clk_xusb_hs_src] = { .dt_id = TEGRA114_CLK_XUSB_HS_SRC, .present = true },
@@ -1182,16 +1182,11 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base,
1182 void __iomem *pmc_base) 1182 void __iomem *pmc_base)
1183{ 1183{
1184 struct clk *clk; 1184 struct clk *clk;
1185 u32 val;
1186
1187 /* xusb_hs_src */
1188 val = readl(clk_base + CLK_SOURCE_XUSB_SS_SRC);
1189 val |= BIT(25); /* always select PLLU_60M */
1190 writel(val, clk_base + CLK_SOURCE_XUSB_SS_SRC);
1191 1185
1192 clk = clk_register_fixed_factor(NULL, "xusb_hs_src", "pll_u_60M", 0, 1186 /* xusb_ss_div2 */
1193 1, 1); 1187 clk = clk_register_fixed_factor(NULL, "xusb_ss_div2", "xusb_ss_src", 0,
1194 clks[TEGRA114_CLK_XUSB_HS_SRC] = clk; 1188 1, 2);
1189 clks[TEGRA114_CLK_XUSB_SS_DIV2] = clk;
1195 1190
1196 /* dsia mux */ 1191 /* dsia mux */
1197 clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0, 1192 clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0,
@@ -1301,7 +1296,12 @@ static struct tegra_clk_init_table init_table[] __initdata = {
1301 {TEGRA114_CLK_GR3D, TEGRA114_CLK_PLL_C2, 300000000, 0}, 1296 {TEGRA114_CLK_GR3D, TEGRA114_CLK_PLL_C2, 300000000, 0},
1302 {TEGRA114_CLK_DSIALP, TEGRA114_CLK_PLL_P, 68000000, 0}, 1297 {TEGRA114_CLK_DSIALP, TEGRA114_CLK_PLL_P, 68000000, 0},
1303 {TEGRA114_CLK_DSIBLP, TEGRA114_CLK_PLL_P, 68000000, 0}, 1298 {TEGRA114_CLK_DSIBLP, TEGRA114_CLK_PLL_P, 68000000, 0},
1304 1299 {TEGRA114_CLK_PLL_RE_VCO, TEGRA114_CLK_CLK_MAX, 612000000, 0},
1300 {TEGRA114_CLK_XUSB_SS_SRC, TEGRA114_CLK_PLL_RE_OUT, 122400000, 0},
1301 {TEGRA114_CLK_XUSB_FS_SRC, TEGRA114_CLK_PLL_U_48M, 48000000, 0},
1302 {TEGRA114_CLK_XUSB_HS_SRC, TEGRA114_CLK_XUSB_SS_DIV2, 61200000, 0},
1303 {TEGRA114_CLK_XUSB_FALCON_SRC, TEGRA114_CLK_PLL_P, 204000000, 0},
1304 {TEGRA114_CLK_XUSB_HOST_SRC, TEGRA114_CLK_PLL_P, 102000000, 0},
1305 /* This MUST be the last entry. */ 1305 /* This MUST be the last entry. */
1306 {TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0}, 1306 {TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0},
1307}; 1307};
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index cc37c342c4cb..80efe51fdcdf 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -30,7 +30,6 @@
30 30
31#define CLK_SOURCE_CSITE 0x1d4 31#define CLK_SOURCE_CSITE 0x1d4
32#define CLK_SOURCE_EMC 0x19c 32#define CLK_SOURCE_EMC 0x19c
33#define CLK_SOURCE_XUSB_SS_SRC 0x610
34 33
35#define PLLC_BASE 0x80 34#define PLLC_BASE 0x80
36#define PLLC_OUT 0x84 35#define PLLC_OUT 0x84
@@ -925,6 +924,7 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
925 [tegra_clk_xusb_falcon_src] = { .dt_id = TEGRA124_CLK_XUSB_FALCON_SRC, .present = true }, 924 [tegra_clk_xusb_falcon_src] = { .dt_id = TEGRA124_CLK_XUSB_FALCON_SRC, .present = true },
926 [tegra_clk_xusb_fs_src] = { .dt_id = TEGRA124_CLK_XUSB_FS_SRC, .present = true }, 925 [tegra_clk_xusb_fs_src] = { .dt_id = TEGRA124_CLK_XUSB_FS_SRC, .present = true },
927 [tegra_clk_xusb_ss_src] = { .dt_id = TEGRA124_CLK_XUSB_SS_SRC, .present = true }, 926 [tegra_clk_xusb_ss_src] = { .dt_id = TEGRA124_CLK_XUSB_SS_SRC, .present = true },
927 [tegra_clk_xusb_ss_div2] = { .dt_id = TEGRA124_CLK_XUSB_SS_DIV2, .present = true },
928 [tegra_clk_xusb_dev_src] = { .dt_id = TEGRA124_CLK_XUSB_DEV_SRC, .present = true }, 928 [tegra_clk_xusb_dev_src] = { .dt_id = TEGRA124_CLK_XUSB_DEV_SRC, .present = true },
929 [tegra_clk_xusb_dev] = { .dt_id = TEGRA124_CLK_XUSB_DEV, .present = true }, 929 [tegra_clk_xusb_dev] = { .dt_id = TEGRA124_CLK_XUSB_DEV, .present = true },
930 [tegra_clk_xusb_hs_src] = { .dt_id = TEGRA124_CLK_XUSB_HS_SRC, .present = true }, 930 [tegra_clk_xusb_hs_src] = { .dt_id = TEGRA124_CLK_XUSB_HS_SRC, .present = true },
@@ -1105,16 +1105,11 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base,
1105 void __iomem *pmc_base) 1105 void __iomem *pmc_base)
1106{ 1106{
1107 struct clk *clk; 1107 struct clk *clk;
1108 u32 val;
1109
1110 /* xusb_hs_src */
1111 val = readl(clk_base + CLK_SOURCE_XUSB_SS_SRC);
1112 val |= BIT(25); /* always select PLLU_60M */
1113 writel(val, clk_base + CLK_SOURCE_XUSB_SS_SRC);
1114 1108
1115 clk = clk_register_fixed_factor(NULL, "xusb_hs_src", "pll_u_60M", 0, 1109 /* xusb_ss_div2 */
1116 1, 1); 1110 clk = clk_register_fixed_factor(NULL, "xusb_ss_div2", "xusb_ss_src", 0,
1117 clks[TEGRA124_CLK_XUSB_HS_SRC] = clk; 1111 1, 2);
1112 clks[TEGRA124_CLK_XUSB_SS_DIV2] = clk;
1118 1113
1119 /* dsia mux */ 1114 /* dsia mux */
1120 clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0, 1115 clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0,
@@ -1368,6 +1363,12 @@ static struct tegra_clk_init_table init_table[] __initdata = {
1368 {TEGRA124_CLK_SBC4, TEGRA124_CLK_PLL_P, 12000000, 1}, 1363 {TEGRA124_CLK_SBC4, TEGRA124_CLK_PLL_P, 12000000, 1},
1369 {TEGRA124_CLK_TSEC, TEGRA124_CLK_PLL_C3, 0, 0}, 1364 {TEGRA124_CLK_TSEC, TEGRA124_CLK_PLL_C3, 0, 0},
1370 {TEGRA124_CLK_MSENC, TEGRA124_CLK_PLL_C3, 0, 0}, 1365 {TEGRA124_CLK_MSENC, TEGRA124_CLK_PLL_C3, 0, 0},
1366 {TEGRA124_CLK_PLL_RE_VCO, TEGRA124_CLK_CLK_MAX, 672000000, 0},
1367 {TEGRA124_CLK_XUSB_SS_SRC, TEGRA124_CLK_PLL_U_480M, 120000000, 0},
1368 {TEGRA124_CLK_XUSB_FS_SRC, TEGRA124_CLK_PLL_U_48M, 48000000, 0},
1369 {TEGRA124_CLK_XUSB_HS_SRC, TEGRA124_CLK_PLL_U_60M, 60000000, 0},
1370 {TEGRA124_CLK_XUSB_FALCON_SRC, TEGRA124_CLK_PLL_RE_OUT, 224000000, 0},
1371 {TEGRA124_CLK_XUSB_HOST_SRC, TEGRA124_CLK_PLL_RE_OUT, 112000000, 0},
1371 /* This MUST be the last entry. */ 1372 /* This MUST be the last entry. */
1372 {TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0}, 1373 {TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0},
1373}; 1374};
diff --git a/drivers/clk/ti/clk-43xx.c b/drivers/clk/ti/clk-43xx.c
index b4877e0ee910..3795fce8a830 100644
--- a/drivers/clk/ti/clk-43xx.c
+++ b/drivers/clk/ti/clk-43xx.c
@@ -105,6 +105,12 @@ static struct ti_dt_clk am43xx_clks[] = {
105 DT_CLK(NULL, "func_12m_clk", "func_12m_clk"), 105 DT_CLK(NULL, "func_12m_clk", "func_12m_clk"),
106 DT_CLK(NULL, "vtp_clk_div", "vtp_clk_div"), 106 DT_CLK(NULL, "vtp_clk_div", "vtp_clk_div"),
107 DT_CLK(NULL, "usbphy_32khz_clkmux", "usbphy_32khz_clkmux"), 107 DT_CLK(NULL, "usbphy_32khz_clkmux", "usbphy_32khz_clkmux"),
108 DT_CLK("48300200.ehrpwm", "tbclk", "ehrpwm0_tbclk"),
109 DT_CLK("48302200.ehrpwm", "tbclk", "ehrpwm1_tbclk"),
110 DT_CLK("48304200.ehrpwm", "tbclk", "ehrpwm2_tbclk"),
111 DT_CLK("48306200.ehrpwm", "tbclk", "ehrpwm3_tbclk"),
112 DT_CLK("48308200.ehrpwm", "tbclk", "ehrpwm4_tbclk"),
113 DT_CLK("4830a200.ehrpwm", "tbclk", "ehrpwm5_tbclk"),
108 { .node_name = NULL }, 114 { .node_name = NULL },
109}; 115};
110 116
diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c
index 3e2999d11d15..58734817d502 100644
--- a/drivers/clk/ti/gate.c
+++ b/drivers/clk/ti/gate.c
@@ -221,7 +221,7 @@ static void __init of_ti_gate_clk_setup(struct device_node *node)
221{ 221{
222 _of_ti_gate_clk_setup(node, &omap_gate_clk_ops, NULL); 222 _of_ti_gate_clk_setup(node, &omap_gate_clk_ops, NULL);
223} 223}
224CLK_OF_DECLARE(ti_gate_clk, "ti,gate-clock", of_ti_gate_clk_setup) 224CLK_OF_DECLARE(ti_gate_clk, "ti,gate-clock", of_ti_gate_clk_setup);
225 225
226static void __init of_ti_wait_gate_clk_setup(struct device_node *node) 226static void __init of_ti_wait_gate_clk_setup(struct device_node *node)
227{ 227{
diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig
new file mode 100644
index 000000000000..1530c9352a76
--- /dev/null
+++ b/drivers/clk/versatile/Kconfig
@@ -0,0 +1,26 @@
1config COMMON_CLK_VERSATILE
2 bool "Clock driver for ARM Reference designs"
3 depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64
4 ---help---
5 Supports clocking on ARM Reference designs:
6 - Integrator/AP and Integrator/CP
7 - RealView PB1176, EB, PB11MP and PBX
8 - Versatile Express
9
10config CLK_SP810
11 bool "Clock driver for ARM SP810 System Controller"
12 depends on COMMON_CLK_VERSATILE
13 default y if ARCH_VEXPRESS
14 ---help---
15 Supports clock muxing (REFCLK/TIMCLK to TIMERCLKEN0-3) capabilities
16 of the ARM SP810 System Controller cell.
17
18config CLK_VEXPRESS_OSC
19 bool "Clock driver for Versatile Express OSC clock generators"
20 depends on COMMON_CLK_VERSATILE
21 depends on VEXPRESS_CONFIG
22 default y if ARCH_VEXPRESS
23 ---help---
24 Simple regmap-based driver driving clock generators on Versatile
25 Express platforms hidden behind its configuration infrastructure,
26 commonly known as OSCs.
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
index c16ca787170a..fd449f9b006d 100644
--- a/drivers/clk/versatile/Makefile
+++ b/drivers/clk/versatile/Makefile
@@ -3,5 +3,6 @@ obj-$(CONFIG_ICST) += clk-icst.o
3obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o 3obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o
4obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o 4obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o
5obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o 5obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o
6obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o clk-sp810.o 6obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o
7obj-$(CONFIG_VEXPRESS_CONFIG) += clk-vexpress-osc.o 7obj-$(CONFIG_CLK_SP810) += clk-sp810.o
8obj-$(CONFIG_CLK_VEXPRESS_OSC) += clk-vexpress-osc.o
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c
index a820b0cfcf57..bc96f103bd7c 100644
--- a/drivers/clk/versatile/clk-icst.c
+++ b/drivers/clk/versatile/clk-icst.c
@@ -140,6 +140,7 @@ struct clk *icst_clk_register(struct device *dev,
140 140
141 pclone = kmemdup(desc->params, sizeof(*pclone), GFP_KERNEL); 141 pclone = kmemdup(desc->params, sizeof(*pclone), GFP_KERNEL);
142 if (!pclone) { 142 if (!pclone) {
143 kfree(icst);
143 pr_err("could not clone ICST params\n"); 144 pr_err("could not clone ICST params\n");
144 return ERR_PTR(-ENOMEM); 145 return ERR_PTR(-ENOMEM);
145 } 146 }
@@ -160,3 +161,4 @@ struct clk *icst_clk_register(struct device *dev,
160 161
161 return clk; 162 return clk;
162} 163}
164EXPORT_SYMBOL_GPL(icst_clk_register);
diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c
index 31b44f025f9e..1cc1330dc570 100644
--- a/drivers/clk/versatile/clk-impd1.c
+++ b/drivers/clk/versatile/clk-impd1.c
@@ -20,6 +20,8 @@
20#define IMPD1_LOCK 0x08 20#define IMPD1_LOCK 0x08
21 21
22struct impd1_clk { 22struct impd1_clk {
23 char *pclkname;
24 struct clk *pclk;
23 char *vco1name; 25 char *vco1name;
24 struct clk *vco1clk; 26 struct clk *vco1clk;
25 char *vco2name; 27 char *vco2name;
@@ -31,7 +33,7 @@ struct impd1_clk {
31 struct clk *spiclk; 33 struct clk *spiclk;
32 char *scname; 34 char *scname;
33 struct clk *scclk; 35 struct clk *scclk;
34 struct clk_lookup *clks[6]; 36 struct clk_lookup *clks[15];
35}; 37};
36 38
37/* One entry for each connected IM-PD1 LM */ 39/* One entry for each connected IM-PD1 LM */
@@ -86,6 +88,7 @@ void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
86{ 88{
87 struct impd1_clk *imc; 89 struct impd1_clk *imc;
88 struct clk *clk; 90 struct clk *clk;
91 struct clk *pclk;
89 int i; 92 int i;
90 93
91 if (id > 3) { 94 if (id > 3) {
@@ -94,11 +97,18 @@ void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
94 } 97 }
95 imc = &impd1_clks[id]; 98 imc = &impd1_clks[id];
96 99
100 /* Register the fixed rate PCLK */
101 imc->pclkname = kasprintf(GFP_KERNEL, "lm%x-pclk", id);
102 pclk = clk_register_fixed_rate(NULL, imc->pclkname, NULL,
103 CLK_IS_ROOT, 0);
104 imc->pclk = pclk;
105
97 imc->vco1name = kasprintf(GFP_KERNEL, "lm%x-vco1", id); 106 imc->vco1name = kasprintf(GFP_KERNEL, "lm%x-vco1", id);
98 clk = icst_clk_register(NULL, &impd1_icst1_desc, imc->vco1name, NULL, 107 clk = icst_clk_register(NULL, &impd1_icst1_desc, imc->vco1name, NULL,
99 base); 108 base);
100 imc->vco1clk = clk; 109 imc->vco1clk = clk;
101 imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id); 110 imc->clks[0] = clkdev_alloc(pclk, "apb_pclk", "lm%x:01000", id);
111 imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:01000", id);
102 112
103 /* VCO2 is also called "CLK2" */ 113 /* VCO2 is also called "CLK2" */
104 imc->vco2name = kasprintf(GFP_KERNEL, "lm%x-vco2", id); 114 imc->vco2name = kasprintf(GFP_KERNEL, "lm%x-vco2", id);
@@ -107,32 +117,43 @@ void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
107 imc->vco2clk = clk; 117 imc->vco2clk = clk;
108 118
109 /* MMCI uses CLK2 right off */ 119 /* MMCI uses CLK2 right off */
110 imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:00700", id); 120 imc->clks[2] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00700", id);
121 imc->clks[3] = clkdev_alloc(clk, NULL, "lm%x:00700", id);
111 122
112 /* UART reference clock divides CLK2 by a fixed factor 4 */ 123 /* UART reference clock divides CLK2 by a fixed factor 4 */
113 imc->uartname = kasprintf(GFP_KERNEL, "lm%x-uartclk", id); 124 imc->uartname = kasprintf(GFP_KERNEL, "lm%x-uartclk", id);
114 clk = clk_register_fixed_factor(NULL, imc->uartname, imc->vco2name, 125 clk = clk_register_fixed_factor(NULL, imc->uartname, imc->vco2name,
115 CLK_IGNORE_UNUSED, 1, 4); 126 CLK_IGNORE_UNUSED, 1, 4);
116 imc->uartclk = clk; 127 imc->uartclk = clk;
117 imc->clks[2] = clkdev_alloc(clk, NULL, "lm%x:00100", id); 128 imc->clks[4] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00100", id);
118 imc->clks[3] = clkdev_alloc(clk, NULL, "lm%x:00200", id); 129 imc->clks[5] = clkdev_alloc(clk, NULL, "lm%x:00100", id);
130 imc->clks[6] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00200", id);
131 imc->clks[7] = clkdev_alloc(clk, NULL, "lm%x:00200", id);
119 132
120 /* SPI PL022 clock divides CLK2 by a fixed factor 64 */ 133 /* SPI PL022 clock divides CLK2 by a fixed factor 64 */
121 imc->spiname = kasprintf(GFP_KERNEL, "lm%x-spiclk", id); 134 imc->spiname = kasprintf(GFP_KERNEL, "lm%x-spiclk", id);
122 clk = clk_register_fixed_factor(NULL, imc->spiname, imc->vco2name, 135 clk = clk_register_fixed_factor(NULL, imc->spiname, imc->vco2name,
123 CLK_IGNORE_UNUSED, 1, 64); 136 CLK_IGNORE_UNUSED, 1, 64);
124 imc->clks[4] = clkdev_alloc(clk, NULL, "lm%x:00300", id); 137 imc->clks[8] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00300", id);
138 imc->clks[9] = clkdev_alloc(clk, NULL, "lm%x:00300", id);
139
140 /* The GPIO blocks and AACI have only PCLK */
141 imc->clks[10] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00400", id);
142 imc->clks[11] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00500", id);
143 imc->clks[12] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00800", id);
125 144
126 /* Smart Card clock divides CLK2 by a fixed factor 4 */ 145 /* Smart Card clock divides CLK2 by a fixed factor 4 */
127 imc->scname = kasprintf(GFP_KERNEL, "lm%x-scclk", id); 146 imc->scname = kasprintf(GFP_KERNEL, "lm%x-scclk", id);
128 clk = clk_register_fixed_factor(NULL, imc->scname, imc->vco2name, 147 clk = clk_register_fixed_factor(NULL, imc->scname, imc->vco2name,
129 CLK_IGNORE_UNUSED, 1, 4); 148 CLK_IGNORE_UNUSED, 1, 4);
130 imc->scclk = clk; 149 imc->scclk = clk;
131 imc->clks[5] = clkdev_alloc(clk, NULL, "lm%x:00600", id); 150 imc->clks[13] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00600", id);
151 imc->clks[14] = clkdev_alloc(clk, NULL, "lm%x:00600", id);
132 152
133 for (i = 0; i < ARRAY_SIZE(imc->clks); i++) 153 for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
134 clkdev_add(imc->clks[i]); 154 clkdev_add(imc->clks[i]);
135} 155}
156EXPORT_SYMBOL_GPL(integrator_impd1_clk_init);
136 157
137void integrator_impd1_clk_exit(unsigned int id) 158void integrator_impd1_clk_exit(unsigned int id)
138{ 159{
@@ -149,9 +170,12 @@ void integrator_impd1_clk_exit(unsigned int id)
149 clk_unregister(imc->uartclk); 170 clk_unregister(imc->uartclk);
150 clk_unregister(imc->vco2clk); 171 clk_unregister(imc->vco2clk);
151 clk_unregister(imc->vco1clk); 172 clk_unregister(imc->vco1clk);
173 clk_unregister(imc->pclk);
152 kfree(imc->scname); 174 kfree(imc->scname);
153 kfree(imc->spiname); 175 kfree(imc->spiname);
154 kfree(imc->uartname); 176 kfree(imc->uartname);
155 kfree(imc->vco2name); 177 kfree(imc->vco2name);
156 kfree(imc->vco1name); 178 kfree(imc->vco1name);
179 kfree(imc->pclkname);
157} 180}
181EXPORT_SYMBOL_GPL(integrator_impd1_clk_exit);
diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c
index 422391242b39..529a59c0fbfa 100644
--- a/drivers/clk/versatile/clk-vexpress-osc.c
+++ b/drivers/clk/versatile/clk-vexpress-osc.c
@@ -11,8 +11,6 @@
11 * Copyright (C) 2012 ARM Limited 11 * Copyright (C) 2012 ARM Limited
12 */ 12 */
13 13
14#define pr_fmt(fmt) "vexpress-osc: " fmt
15
16#include <linux/clkdev.h> 14#include <linux/clkdev.h>
17#include <linux/clk-provider.h> 15#include <linux/clk-provider.h>
18#include <linux/err.h> 16#include <linux/err.h>
@@ -22,7 +20,7 @@
22#include <linux/vexpress.h> 20#include <linux/vexpress.h>
23 21
24struct vexpress_osc { 22struct vexpress_osc {
25 struct vexpress_config_func *func; 23 struct regmap *reg;
26 struct clk_hw hw; 24 struct clk_hw hw;
27 unsigned long rate_min; 25 unsigned long rate_min;
28 unsigned long rate_max; 26 unsigned long rate_max;
@@ -36,7 +34,7 @@ static unsigned long vexpress_osc_recalc_rate(struct clk_hw *hw,
36 struct vexpress_osc *osc = to_vexpress_osc(hw); 34 struct vexpress_osc *osc = to_vexpress_osc(hw);
37 u32 rate; 35 u32 rate;
38 36
39 vexpress_config_read(osc->func, 0, &rate); 37 regmap_read(osc->reg, 0, &rate);
40 38
41 return rate; 39 return rate;
42} 40}
@@ -60,7 +58,7 @@ static int vexpress_osc_set_rate(struct clk_hw *hw, unsigned long rate,
60{ 58{
61 struct vexpress_osc *osc = to_vexpress_osc(hw); 59 struct vexpress_osc *osc = to_vexpress_osc(hw);
62 60
63 return vexpress_config_write(osc->func, 0, rate); 61 return regmap_write(osc->reg, 0, rate);
64} 62}
65 63
66static struct clk_ops vexpress_osc_ops = { 64static struct clk_ops vexpress_osc_ops = {
@@ -70,58 +68,31 @@ static struct clk_ops vexpress_osc_ops = {
70}; 68};
71 69
72 70
73struct clk * __init vexpress_osc_setup(struct device *dev) 71static int vexpress_osc_probe(struct platform_device *pdev)
74{
75 struct clk_init_data init;
76 struct vexpress_osc *osc = kzalloc(sizeof(*osc), GFP_KERNEL);
77
78 if (!osc)
79 return NULL;
80
81 osc->func = vexpress_config_func_get_by_dev(dev);
82 if (!osc->func) {
83 kfree(osc);
84 return NULL;
85 }
86
87 init.name = dev_name(dev);
88 init.ops = &vexpress_osc_ops;
89 init.flags = CLK_IS_ROOT;
90 init.num_parents = 0;
91 osc->hw.init = &init;
92
93 return clk_register(NULL, &osc->hw);
94}
95
96void __init vexpress_osc_of_setup(struct device_node *node)
97{ 72{
73 struct clk_lookup *cl = pdev->dev.platform_data; /* Non-DT lookup */
98 struct clk_init_data init; 74 struct clk_init_data init;
99 struct vexpress_osc *osc; 75 struct vexpress_osc *osc;
100 struct clk *clk; 76 struct clk *clk;
101 u32 range[2]; 77 u32 range[2];
102 78
103 vexpress_sysreg_of_early_init(); 79 osc = devm_kzalloc(&pdev->dev, sizeof(*osc), GFP_KERNEL);
104
105 osc = kzalloc(sizeof(*osc), GFP_KERNEL);
106 if (!osc) 80 if (!osc)
107 return; 81 return -ENOMEM;
108 82
109 osc->func = vexpress_config_func_get_by_node(node); 83 osc->reg = devm_regmap_init_vexpress_config(&pdev->dev);
110 if (!osc->func) { 84 if (IS_ERR(osc->reg))
111 pr_err("Failed to obtain config func for node '%s'!\n", 85 return PTR_ERR(osc->reg);
112 node->full_name);
113 goto error;
114 }
115 86
116 if (of_property_read_u32_array(node, "freq-range", range, 87 if (of_property_read_u32_array(pdev->dev.of_node, "freq-range", range,
117 ARRAY_SIZE(range)) == 0) { 88 ARRAY_SIZE(range)) == 0) {
118 osc->rate_min = range[0]; 89 osc->rate_min = range[0];
119 osc->rate_max = range[1]; 90 osc->rate_max = range[1];
120 } 91 }
121 92
122 of_property_read_string(node, "clock-output-names", &init.name); 93 if (of_property_read_string(pdev->dev.of_node, "clock-output-names",
123 if (!init.name) 94 &init.name) != 0)
124 init.name = node->full_name; 95 init.name = dev_name(&pdev->dev);
125 96
126 init.ops = &vexpress_osc_ops; 97 init.ops = &vexpress_osc_ops;
127 init.flags = CLK_IS_ROOT; 98 init.flags = CLK_IS_ROOT;
@@ -130,20 +101,37 @@ void __init vexpress_osc_of_setup(struct device_node *node)
130 osc->hw.init = &init; 101 osc->hw.init = &init;
131 102
132 clk = clk_register(NULL, &osc->hw); 103 clk = clk_register(NULL, &osc->hw);
133 if (IS_ERR(clk)) { 104 if (IS_ERR(clk))
134 pr_err("Failed to register clock '%s'!\n", init.name); 105 return PTR_ERR(clk);
135 goto error; 106
107 of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, clk);
108
109 /* Only happens for non-DT cases */
110 if (cl) {
111 cl->clk = clk;
112 clkdev_add(cl);
136 } 113 }
137 114
138 of_clk_add_provider(node, of_clk_src_simple_get, clk); 115 dev_dbg(&pdev->dev, "Registered clock '%s'\n", init.name);
116
117 return 0;
118}
139 119
140 pr_debug("Registered clock '%s'\n", init.name); 120static struct of_device_id vexpress_osc_of_match[] = {
121 { .compatible = "arm,vexpress-osc", },
122 {}
123};
141 124
142 return; 125static struct platform_driver vexpress_osc_driver = {
126 .driver = {
127 .name = "vexpress-osc",
128 .of_match_table = vexpress_osc_of_match,
129 },
130 .probe = vexpress_osc_probe,
131};
143 132
144error: 133static int __init vexpress_osc_init(void)
145 if (osc->func) 134{
146 vexpress_config_func_put(osc->func); 135 return platform_driver_register(&vexpress_osc_driver);
147 kfree(osc);
148} 136}
149CLK_OF_DECLARE(vexpress_soc, "arm,vexpress-osc", vexpress_osc_of_setup); 137core_initcall(vexpress_osc_init);
diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c
index 52c09afdcfb7..246cf1226eaa 100644
--- a/drivers/clk/zynq/clkc.c
+++ b/drivers/clk/zynq/clkc.c
@@ -53,6 +53,9 @@ static void __iomem *zynq_clkc_base;
53 53
54#define NUM_MIO_PINS 54 54#define NUM_MIO_PINS 54
55 55
56#define DBG_CLK_CTRL_CLKACT_TRC BIT(0)
57#define DBG_CLK_CTRL_CPU_1XCLKACT BIT(1)
58
56enum zynq_clk { 59enum zynq_clk {
57 armpll, ddrpll, iopll, 60 armpll, ddrpll, iopll,
58 cpu_6or4x, cpu_3or2x, cpu_2x, cpu_1x, 61 cpu_6or4x, cpu_3or2x, cpu_2x, cpu_1x,
@@ -499,6 +502,15 @@ static void __init zynq_clk_setup(struct device_node *np)
499 clk_output_name[cpu_1x], 0, SLCR_DBG_CLK_CTRL, 1, 0, 502 clk_output_name[cpu_1x], 0, SLCR_DBG_CLK_CTRL, 1, 0,
500 &dbgclk_lock); 503 &dbgclk_lock);
501 504
505 /* leave debug clocks in the state the bootloader set them up to */
506 tmp = clk_readl(SLCR_DBG_CLK_CTRL);
507 if (tmp & DBG_CLK_CTRL_CLKACT_TRC)
508 if (clk_prepare_enable(clks[dbg_trc]))
509 pr_warn("%s: trace clk enable failed\n", __func__);
510 if (tmp & DBG_CLK_CTRL_CPU_1XCLKACT)
511 if (clk_prepare_enable(clks[dbg_apb]))
512 pr_warn("%s: debug APB clk enable failed\n", __func__);
513
502 /* One gated clock for all APER clocks. */ 514 /* One gated clock for all APER clocks. */
503 clks[dma] = clk_register_gate(NULL, clk_output_name[dma], 515 clks[dma] = clk_register_gate(NULL, clk_output_name[dma],
504 clk_output_name[cpu_2x], 0, SLCR_APER_CLK_CTRL, 0, 0, 516 clk_output_name[cpu_2x], 0, SLCR_APER_CLK_CTRL, 0, 0,