diff options
Diffstat (limited to 'drivers/clk')
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 | ||
33 | config COMMON_CLK_VERSATILE | 33 | source "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 | ||
42 | config COMMON_CLK_MAX77686 | 35 | config 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 | ||
67 | config COMMON_CLK_S2MPS11 | 60 | config 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 | ||
75 | config CLK_TWL6040 | 68 | config 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 | ||
116 | source "drivers/clk/bcm/Kconfig" | 109 | source "drivers/clk/bcm/Kconfig" |
117 | source "drivers/clk/mvebu/Kconfig" | 110 | source "drivers/clk/mvebu/Kconfig" |
111 | |||
112 | source "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 | |||
8 | obj-$(CONFIG_COMMON_CLK) += clk-gate.o | 8 | obj-$(CONFIG_COMMON_CLK) += clk-gate.o |
9 | obj-$(CONFIG_COMMON_CLK) += clk-mux.o | 9 | obj-$(CONFIG_COMMON_CLK) += clk-mux.o |
10 | obj-$(CONFIG_COMMON_CLK) += clk-composite.o | 10 | obj-$(CONFIG_COMMON_CLK) += clk-composite.o |
11 | obj-$(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 |
14 | obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o | 15 | obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o |
16 | obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o | ||
15 | obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o | 17 | obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o |
16 | obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o | 18 | obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o |
17 | obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o | 19 | obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o |
@@ -31,8 +33,10 @@ obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o | |||
31 | obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o | 33 | obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o |
32 | obj-$(CONFIG_COMMON_CLK_AT91) += at91/ | 34 | obj-$(CONFIG_COMMON_CLK_AT91) += at91/ |
33 | obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm/ | 35 | obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm/ |
36 | obj-$(CONFIG_ARCH_BERLIN) += berlin/ | ||
34 | obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/ | 37 | obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/ |
35 | obj-$(CONFIG_ARCH_HIP04) += hisilicon/ | 38 | obj-$(CONFIG_ARCH_HIP04) += hisilicon/ |
39 | obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/ | ||
36 | obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ | 40 | obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ |
37 | ifeq ($(CONFIG_COMMON_CLK), y) | 41 | ifeq ($(CONFIG_COMMON_CLK), y) |
38 | obj-$(CONFIG_ARCH_MMP) += mmp/ | 42 | obj-$(CONFIG_ARCH_MMP) += mmp/ |
@@ -41,7 +45,7 @@ obj-$(CONFIG_PLAT_ORION) += mvebu/ | |||
41 | obj-$(CONFIG_ARCH_MXS) += mxs/ | 45 | obj-$(CONFIG_ARCH_MXS) += mxs/ |
42 | obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ | 46 | obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ |
43 | obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ | 47 | obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ |
44 | obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ | 48 | obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ |
45 | obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += shmobile/ | 49 | obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += shmobile/ |
46 | obj-$(CONFIG_ARCH_SIRF) += sirf/ | 50 | obj-$(CONFIG_ARCH_SIRF) += sirf/ |
47 | obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ | 51 | obj-$(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 | ||
5 | obj-y += pmc.o | 5 | obj-y += pmc.o sckc.o |
6 | obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o | 6 | obj-y += clk-slow.o clk-main.o clk-pll.o clk-plldiv.o clk-master.o |
7 | obj-y += clk-system.o clk-peripheral.o clk-programmable.o | 7 | obj-y += clk-system.o clk-peripheral.o clk-programmable.o |
8 | 8 | ||
9 | obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o | 9 | obj-$(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 | ||
33 | struct clk_main { | 33 | #define MOR_KEY_MASK (0xff << 16) |
34 | |||
35 | struct 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 | |||
44 | struct 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 | |||
55 | struct 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 | ||
43 | static irqreturn_t clk_main_irq_handler(int irq, void *dev_id) | 62 | struct 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 | |||
72 | static 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 | ||
53 | static int clk_main_prepare(struct clk_hw *hw) | 82 | static 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 | |||
106 | static 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 | |||
122 | static 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 | |||
135 | static 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 | |||
141 | static struct clk * __init | ||
142 | at91_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 | |||
192 | void __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 | |||
216 | static 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 | |||
226 | static 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 | |||
248 | static 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 | |||
261 | static 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 | |||
270 | static 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 | |||
278 | static 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 | |||
286 | static 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 | |||
294 | static struct clk * __init | ||
295 | at91_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 | |||
340 | void __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 | |||
366 | static 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 | ||
81 | static int clk_main_is_prepared(struct clk_hw *hw) | 383 | static 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 | ||
88 | static unsigned long clk_main_recalc_rate(struct clk_hw *hw, | 398 | static 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 | |||
405 | static 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 | |||
412 | static 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 | |||
420 | static 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 | |||
426 | static struct clk * __init | ||
427 | at91_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 | |||
461 | void __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 | |||
478 | static 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 | |||
488 | static 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; | 502 | static 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 | ||
104 | static const struct clk_ops main_ops = { | 509 | static 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 | |||
517 | static 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 | |||
542 | static 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 | |||
549 | static 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 | ||
110 | static struct clk * __init | 557 | static struct clk * __init |
111 | at91_clk_register_main(struct at91_pmc *pmc, | 558 | at91_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 | 606 | void __init of_at91sam9x5_clk_main_setup(struct device_node *np, | |
159 | 607 | struct at91_pmc *pmc) | |
160 | static void __init | ||
161 | of_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 | |||
183 | void __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 | |||
40 | struct 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 | |||
48 | struct 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 | |||
58 | struct 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 | |||
65 | struct 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 | |||
74 | static 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 | |||
90 | static 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 | |||
102 | static 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 | |||
114 | static 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 | |||
120 | static struct clk * __init | ||
121 | at91_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 | |||
159 | void __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 | |||
181 | static 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 | |||
189 | static 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 | |||
197 | static 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 | |||
209 | static 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 | |||
217 | static 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 | |||
224 | static 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 | |||
232 | static struct clk * __init | ||
233 | at91_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 | |||
269 | void __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 | |||
291 | static 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 | |||
318 | static 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 | |||
325 | static 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 | |||
330 | static struct clk * __init | ||
331 | at91_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 | |||
364 | void __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 | |||
393 | static 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 | |||
400 | static const struct clk_ops sam9260_slow_ops = { | ||
401 | .get_parent = clk_sam9260_slow_get_parent, | ||
402 | }; | ||
403 | |||
404 | static struct clk * __init | ||
405 | at91_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 | |||
440 | void __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 | ||
231 | static const struct of_device_id pmc_clk_ids[] __initconst = { | 231 | static 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) | |||
58 | int of_at91_get_clk_range(struct device_node *np, const char *propname, | 58 | int of_at91_get_clk_range(struct device_node *np, const char *propname, |
59 | struct clk_range *range); | 59 | struct clk_range *range); |
60 | 60 | ||
61 | extern void __init of_at91sam9260_clk_slow_setup(struct device_node *np, | ||
62 | struct at91_pmc *pmc); | ||
63 | |||
64 | extern void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np, | ||
65 | struct at91_pmc *pmc); | ||
66 | extern void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np, | ||
67 | struct at91_pmc *pmc); | ||
61 | extern void __init of_at91rm9200_clk_main_setup(struct device_node *np, | 68 | extern void __init of_at91rm9200_clk_main_setup(struct device_node *np, |
62 | struct at91_pmc *pmc); | 69 | struct at91_pmc *pmc); |
70 | extern void __init of_at91sam9x5_clk_main_setup(struct device_node *np, | ||
71 | struct at91_pmc *pmc); | ||
63 | 72 | ||
64 | extern void __init of_at91rm9200_clk_pll_setup(struct device_node *np, | 73 | extern 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 | |||
21 | static 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 | |||
38 | static 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 | } | ||
56 | CLK_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 | |||
15 | extern void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np, | ||
16 | void __iomem *sckcr); | ||
17 | extern void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np, | ||
18 | void __iomem *sckcr); | ||
19 | extern 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 @@ | |||
1 | obj-$(CONFIG_CLK_BCM_KONA) += clk-kona.o | 1 | obj-$(CONFIG_CLK_BCM_KONA) += clk-kona.o |
2 | obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o | 2 | obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o |
3 | obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o | 3 | obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o |
4 | obj-$(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 | |||
23 | static struct peri_clk_data frac_1m_data = { | ||
24 | .gate = HW_SW_GATE(0x214, 16, 0, 1), | ||
25 | .clocks = CLOCKS("ref_crystal"), | ||
26 | }; | ||
27 | |||
28 | static 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 | |||
40 | static 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 | |||
50 | static 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 | |||
65 | static 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 | |||
77 | static 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 | |||
89 | static 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 | |||
101 | static 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 | |||
113 | static struct peri_clk_data sdio1_sleep_data = { | ||
114 | .clocks = CLOCKS("ref_32k"), /* Verify */ | ||
115 | .gate = HW_SW_GATE(0x0358, 18, 2, 3), | ||
116 | }; | ||
117 | |||
118 | static struct peri_clk_data sdio2_sleep_data = { | ||
119 | .clocks = CLOCKS("ref_32k"), /* Verify */ | ||
120 | .gate = HW_SW_GATE(0x035c, 18, 2, 3), | ||
121 | }; | ||
122 | |||
123 | static struct peri_clk_data sdio3_sleep_data = { | ||
124 | .clocks = CLOCKS("ref_32k"), /* Verify */ | ||
125 | .gate = HW_SW_GATE(0x0364, 18, 2, 3), | ||
126 | }; | ||
127 | |||
128 | static struct peri_clk_data sdio4_sleep_data = { | ||
129 | .clocks = CLOCKS("ref_32k"), /* Verify */ | ||
130 | .gate = HW_SW_GATE(0x0360, 18, 2, 3), | ||
131 | }; | ||
132 | |||
133 | static 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 | |||
162 | static 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 | |||
172 | static 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 | |||
182 | static 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 | |||
192 | static 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 | |||
203 | static 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 | |||
214 | static 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 | |||
225 | static 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 | |||
236 | static 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 | |||
263 | static void __init kona_dt_root_ccu_setup(struct device_node *node) | ||
264 | { | ||
265 | kona_dt_ccu_setup(&root_ccu_data, node); | ||
266 | } | ||
267 | |||
268 | static void __init kona_dt_aon_ccu_setup(struct device_node *node) | ||
269 | { | ||
270 | kona_dt_ccu_setup(&aon_ccu_data, node); | ||
271 | } | ||
272 | |||
273 | static void __init kona_dt_master_ccu_setup(struct device_node *node) | ||
274 | { | ||
275 | kona_dt_ccu_setup(&master_ccu_data, node); | ||
276 | } | ||
277 | |||
278 | static void __init kona_dt_slave_ccu_setup(struct device_node *node) | ||
279 | { | ||
280 | kona_dt_ccu_setup(&slave_ccu_data, node); | ||
281 | } | ||
282 | |||
283 | CLK_OF_DECLARE(bcm21664_root_ccu, BCM21664_DT_ROOT_CCU_COMPAT, | ||
284 | kona_dt_root_ccu_setup); | ||
285 | CLK_OF_DECLARE(bcm21664_aon_ccu, BCM21664_DT_AON_CCU_COMPAT, | ||
286 | kona_dt_aon_ccu_setup); | ||
287 | CLK_OF_DECLARE(bcm21664_master_ccu, BCM21664_DT_MASTER_CCU_COMPAT, | ||
288 | kona_dt_master_ccu_setup); | ||
289 | CLK_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 | ||
27 | static struct peri_clk_data frac_1m_data = { | 23 | static 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 */ | 30 | static 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 | ||
36 | static struct peri_clk_data hub_timer_data = { | 41 | static 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 */ | 68 | static 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 | ||
65 | static struct peri_clk_data tmon_1m_data = { | 83 | static 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 */ | 91 | static 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 | ||
75 | static struct peri_clk_data sdio1_data = { | 102 | static 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 */ | 183 | static 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 | ||
158 | static struct peri_clk_data uartb_data = { | 206 | static 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 | /* | 312 | static 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), |
273 | static 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 | |||
291 | static 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 | |||
311 | static 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 | |||
329 | static 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 | |||
353 | static 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 | ||
382 | static void __init kona_dt_root_ccu_setup(struct device_node *node) | 341 | static 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 | ||
387 | static void __init kona_dt_aon_ccu_setup(struct device_node *node) | 346 | static 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 | ||
392 | static void __init kona_dt_hub_ccu_setup(struct device_node *node) | 351 | static 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 | ||
397 | static void __init kona_dt_master_ccu_setup(struct device_node *node) | 356 | static 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 | ||
402 | static void __init kona_dt_slave_ccu_setup(struct device_node *node) | 361 | static 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 | ||
407 | CLK_OF_DECLARE(bcm11351_root_ccu, BCM11351_DT_ROOT_CCU_COMPAT, | 366 | CLK_OF_DECLARE(bcm281xx_root_ccu, BCM281XX_DT_ROOT_CCU_COMPAT, |
408 | kona_dt_root_ccu_setup); | 367 | kona_dt_root_ccu_setup); |
409 | CLK_OF_DECLARE(bcm11351_aon_ccu, BCM11351_DT_AON_CCU_COMPAT, | 368 | CLK_OF_DECLARE(bcm281xx_aon_ccu, BCM281XX_DT_AON_CCU_COMPAT, |
410 | kona_dt_aon_ccu_setup); | 369 | kona_dt_aon_ccu_setup); |
411 | CLK_OF_DECLARE(bcm11351_hub_ccu, BCM11351_DT_HUB_CCU_COMPAT, | 370 | CLK_OF_DECLARE(bcm281xx_hub_ccu, BCM281XX_DT_HUB_CCU_COMPAT, |
412 | kona_dt_hub_ccu_setup); | 371 | kona_dt_hub_ccu_setup); |
413 | CLK_OF_DECLARE(bcm11351_master_ccu, BCM11351_DT_MASTER_CCU_COMPAT, | 372 | CLK_OF_DECLARE(bcm281xx_master_ccu, BCM281XX_DT_MASTER_CCU_COMPAT, |
414 | kona_dt_master_ccu_setup); | 373 | kona_dt_master_ccu_setup); |
415 | CLK_OF_DECLARE(bcm11351_slave_ccu, BCM11351_DT_SLAVE_CCU_COMPAT, | 374 | CLK_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 | ||
28 | static 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 | |||
28 | static bool clk_requires_trigger(struct kona_clk *bcm_clk) | 53 | static 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) | |||
54 | static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk) | 79 | static 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 | ||
219 | static bool | ||
220 | ccu_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 | |||
241 | static 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 | ||
278 | static 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 | |||
312 | peri_clk_data_valid(struct kona_clk *bcm_clk) | 402 | peri_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 | */ |
579 | static int peri_clk_setup(struct ccu_data *ccu, struct peri_clk_data *data, | 679 | static int |
580 | struct clk_init_data *init_data) | 680 | peri_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 | ||
620 | struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name, | 719 | struct 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; |
666 | out_teardown: | 752 | out_teardown: |
667 | bcm_clk_teardown(bcm_clk); | 753 | bcm_clk_teardown(bcm_clk); |
668 | out_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 | ||
683 | static void kona_ccu_teardown(struct ccu_data *ccu) | 767 | static 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); |
696 | done: | 780 | ccu->base = NULL; |
697 | kfree(ccu->name); | 781 | } |
698 | kfree(ccu); | 782 | |
783 | static 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 | */ |
705 | void __init kona_dt_ccu_setup(struct device_node *node, | 802 | void __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 | |||
226 | static 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 | |||
280 | static 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 | */ | ||
322 | static 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 | */ | ||
539 | static 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 | ||
812 | static void kona_peri_clk_disable(struct clk_hw *hw) | 994 | static 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 | ||
820 | static int kona_peri_clk_is_enabled(struct clk_hw *hw) | 1002 | static 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 | ||
1034 | static 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 | |||
852 | static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index) | 1086 | static 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 */ |
66 | enum bcm_clk_type { | 77 | enum 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 | */ |
82 | struct ccu_data { | 92 | struct 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 */ | ||
211 | struct 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 | ||
362 | struct peri_clk_data { | 390 | struct 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 | ||
374 | struct kona_clk { | 404 | struct 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 | ||
390 | extern 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 | */ | ||
436 | struct 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 | |||
448 | struct 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 | |||
464 | struct 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 | */ | ||
478 | struct 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) \ | 502 | extern 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); | |||
401 | extern u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, | 508 | extern u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, |
402 | u32 billionths); | 509 | u32 billionths); |
403 | 510 | ||
404 | extern struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name, | 511 | extern struct clk *kona_clk_setup(struct kona_clk *bcm_clk); |
405 | enum bcm_clk_type type, void *data); | 512 | extern void __init kona_dt_ccu_setup(struct ccu_data *ccu, |
406 | extern void __init kona_dt_ccu_setup(struct device_node *node, | 513 | struct device_node *node); |
407 | int (*ccu_clks_setup)(struct ccu_data *)); | ||
408 | extern bool __init kona_ccu_init(struct ccu_data *ccu); | 514 | extern 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 @@ | |||
1 | obj-y += berlin2-avpll.o berlin2-pll.o berlin2-div.o | ||
2 | obj-$(CONFIG_MACH_BERLIN_BG2) += bg2.o | ||
3 | obj-$(CONFIG_MACH_BERLIN_BG2CD) += bg2.o | ||
4 | obj-$(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 | |||
116 | struct 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 | |||
124 | static 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 | |||
136 | static 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 | |||
151 | static 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 | |||
164 | static u8 vco_refdiv[] = { 1, 2, 4, 3 }; | ||
165 | |||
166 | static unsigned long | ||
167 | berlin2_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 | |||
184 | static 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 | |||
191 | struct 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 | |||
214 | struct 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 | |||
223 | static 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 | |||
237 | static 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 | |||
249 | static 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 | |||
259 | static const u8 div_hdmi[] = { 1, 2, 4, 6 }; | ||
260 | static const u8 div_av1[] = { 1, 2, 5, 5 }; | ||
261 | |||
262 | static unsigned long | ||
263 | berlin2_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 | |||
346 | skip_div: | ||
347 | do_div(freq, divider); | ||
348 | return (unsigned long)freq; | ||
349 | } | ||
350 | |||
351 | static 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 | */ | ||
365 | static const u8 quirk_index[] __initconst = { 0, 6, 5, 4, 3, 2, 1, 7 }; | ||
366 | |||
367 | struct 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 | |||
22 | struct clk; | ||
23 | |||
24 | #define BERLIN2_AVPLL_BIT_QUIRK BIT(0) | ||
25 | #define BERLIN2_AVPLL_SCRAMBLE_QUIRK BIT(1) | ||
26 | |||
27 | struct clk * __init | ||
28 | berlin2_avpll_vco_register(void __iomem *base, const char *name, | ||
29 | const char *parent_name, u8 vco_flags, unsigned long flags); | ||
30 | |||
31 | struct clk * __init | ||
32 | berlin2_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 | |||
64 | struct 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 | |||
73 | static u8 clk_div[] = { 1, 2, 4, 6, 8, 12, 1, 1 }; | ||
74 | |||
75 | static 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 | |||
93 | static 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 | |||
112 | static 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 | |||
129 | static 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 | |||
160 | static 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 | |||
186 | static 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 | |||
222 | static const struct clk_ops berlin2_div_rate_ops = { | ||
223 | .recalc_rate = berlin2_div_recalc_rate, | ||
224 | }; | ||
225 | |||
226 | static 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 | |||
232 | static const struct clk_ops berlin2_div_mux_ops = { | ||
233 | .set_parent = berlin2_div_set_parent, | ||
234 | .get_parent = berlin2_div_get_parent, | ||
235 | }; | ||
236 | |||
237 | struct clk * __init | ||
238 | berlin2_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 | |||
22 | struct 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 | |||
59 | struct 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 | |||
74 | struct 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 | |||
83 | struct clk * __init | ||
84 | berlin2_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 | |||
29 | struct 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 | |||
37 | struct 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 | */ | ||
59 | static unsigned long | ||
60 | berlin2_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 | |||
90 | static const struct clk_ops berlin2_pll_ops = { | ||
91 | .recalc_rate = berlin2_pll_recalc_rate, | ||
92 | }; | ||
93 | |||
94 | struct clk * __init | ||
95 | berlin2_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 | |||
22 | struct clk; | ||
23 | |||
24 | struct 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 | |||
32 | struct clk * __init | ||
33 | berlin2_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 | ||
95 | static struct clk *clks[MAX_CLKS]; | ||
96 | static struct clk_onecell_data clk_data; | ||
97 | static DEFINE_SPINLOCK(lock); | ||
98 | static void __iomem *gbase; | ||
99 | |||
100 | enum { | ||
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 | |||
113 | static 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 | |||
145 | static 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 | |||
153 | static const u8 default_parent_ids[] = { | ||
154 | SYSPLL, AVPLL_B4, AVPLL_A5, AVPLL_B6, AVPLL_B7, SYSPLL | ||
155 | }; | ||
156 | |||
157 | static 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 | |||
485 | static 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 | |||
503 | static 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 | |||
685 | bg2_fail: | ||
686 | iounmap(gbase); | ||
687 | } | ||
688 | CLK_OF_DECLARE(berlin2_clock, "marvell,berlin2-chip-ctrl", | ||
689 | berlin2_clock_setup); | ||
690 | CLK_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 | ||
49 | static struct clk *clks[MAX_CLKS]; | ||
50 | static struct clk_onecell_data clk_data; | ||
51 | static DEFINE_SPINLOCK(lock); | ||
52 | static void __iomem *gbase; | ||
53 | static void __iomem *cpupll_base; | ||
54 | |||
55 | enum { | ||
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 | |||
62 | static 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 | |||
76 | static 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 | |||
84 | static const u8 default_parent_ids[] = { | ||
85 | SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL | ||
86 | }; | ||
87 | |||
88 | static 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 | |||
276 | static 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 | |||
292 | static 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 | |||
384 | bg2q_fail: | ||
385 | iounmap(cpupll_base); | ||
386 | iounmap(gbase); | ||
387 | } | ||
388 | CLK_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 | |||
22 | struct 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 | */ | ||
29 | struct 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 | */ | ||
40 | struct 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 | */ | ||
50 | static unsigned long | ||
51 | axxia_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 | |||
67 | static 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 | */ | ||
78 | struct 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 | */ | ||
89 | static unsigned long | ||
90 | axxia_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 | |||
102 | static 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 | */ | ||
113 | struct 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 | */ | ||
124 | static 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 | |||
136 | static const struct clk_ops axxia_clkmux_ops = { | ||
137 | .get_parent = axxia_clkmux_get_parent, | ||
138 | }; | ||
139 | |||
140 | |||
141 | /* | ||
142 | * PLLs | ||
143 | */ | ||
144 | |||
145 | static 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 | |||
157 | static 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 | |||
169 | static 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 | |||
181 | static 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 | |||
193 | static 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 | |||
209 | static 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 | |||
223 | static 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 | |||
237 | static 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 | |||
251 | static 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 | |||
265 | static 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 | |||
279 | static 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 | |||
293 | static 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 | |||
307 | static 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 | |||
322 | static 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 | |||
341 | static 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 | |||
358 | static 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 | |||
375 | static 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 | |||
392 | static 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 | |||
409 | static 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 | |||
426 | static 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 | |||
443 | static 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 | |||
460 | static 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 | |||
475 | static 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 | */ | ||
493 | static 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 | |||
519 | static 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 | |||
527 | static const struct of_device_id axmclk_match_table[] = { | ||
528 | { .compatible = "lsi,axm5516-clks" }, | ||
529 | { } | ||
530 | }; | ||
531 | MODULE_DEVICE_TABLE(of, axmclk_match_table); | ||
532 | |||
533 | struct axmclk_priv { | ||
534 | struct clk_onecell_data onecell; | ||
535 | struct clk *clks[]; | ||
536 | }; | ||
537 | |||
538 | static 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 | |||
585 | static int axmclk_remove(struct platform_device *pdev) | ||
586 | { | ||
587 | of_clk_del_provider(pdev->dev.of_node); | ||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | static 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 | |||
601 | static int __init axmclk_init(void) | ||
602 | { | ||
603 | return platform_driver_register(&axmclk_driver); | ||
604 | } | ||
605 | core_initcall(axmclk_init); | ||
606 | |||
607 | static void __exit axmclk_exit(void) | ||
608 | { | ||
609 | platform_driver_unregister(&axmclk_driver); | ||
610 | } | ||
611 | module_exit(axmclk_exit); | ||
612 | |||
613 | MODULE_DESCRIPTION("AXM5516 clock driver"); | ||
614 | MODULE_LICENSE("GPL v2"); | ||
615 | MODULE_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 | ||
46 | static 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 | |||
46 | static unsigned int _get_maxdiv(struct clk_divider *divider) | 57 | static 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 | ||
176 | static 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 | |||
165 | static int _div_round_up(struct clk_divider *divider, | 194 | static 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 | ||
207 | static 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 | |||
225 | static 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 | |||
234 | static 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 | |||
243 | static 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 | |||
178 | static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, | 255 | static 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 | }; |
285 | EXPORT_SYMBOL_GPL(clk_divider_ops); | 362 | EXPORT_SYMBOL_GPL(clk_divider_ops); |
286 | 363 | ||
364 | const struct clk_ops clk_divider_ro_ops = { | ||
365 | .recalc_rate = clk_divider_recalc_rate, | ||
366 | }; | ||
367 | EXPORT_SYMBOL_GPL(clk_divider_ro_ops); | ||
368 | |||
287 | static struct clk *_register_divider(struct device *dev, const char *name, | 369 | static 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 | |||
20 | static 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 | |||
45 | static 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 | |||
65 | static 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 | |||
92 | const 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 | }; | ||
97 | EXPORT_SYMBOL_GPL(clk_fractional_divider_ops); | ||
98 | |||
99 | struct 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 | } | ||
135 | EXPORT_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 | ||
45 | struct s2mps11_clk { | 42 | struct 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 | ||
128 | static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev) | 126 | static 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 | |||
139 | static 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 | ||
259 | static const struct platform_device_id s2mps11_clk_id[] = { | 294 | static 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 = { | |||
526 | module_i2c_driver(si570_driver); | 526 | module_i2c_driver(si570_driver); |
527 | 527 | ||
528 | MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>"); | 528 | MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>"); |
529 | MODULE_AUTHOR("Soeren Brinkmann <soren.brinkmann@xilinx.com"); | 529 | MODULE_AUTHOR("Soeren Brinkmann <soren.brinkmann@xilinx.com>"); |
530 | MODULE_DESCRIPTION("Si570 driver"); | 530 | MODULE_DESCRIPTION("Si570 driver"); |
531 | MODULE_LICENSE("GPL"); | 531 | MODULE_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 | ||
117 | static void clk_summary_show_subtree(struct seq_file *s, struct clk *c, | 116 | static 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 | */ |
823 | void clk_unprepare(struct clk *clk) | 822 | void 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 | } |
1009 | EXPORT_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 | } |
1116 | EXPORT_SYMBOL_GPL(clk_get_accuracy); | 1119 | EXPORT_SYMBOL_GPL(clk_get_accuracy); |
1117 | 1120 | ||
1121 | static 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) |
13 | struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec); | ||
13 | struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec); | 14 | struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec); |
14 | void of_clk_lock(void); | 15 | void of_clk_lock(void); |
15 | void of_clk_unlock(void); | 16 | void 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); | |||
27 | static DEFINE_MUTEX(clocks_mutex); | 27 | static 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 | */ | ||
39 | struct 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 | |||
30 | struct clk *of_clk_get(struct device_node *np, int index) | 56 | struct 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 | ||
7 | obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o | 7 | obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o |
8 | obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o | 8 | obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o |
9 | obj-$(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 | |||
14 | static 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 | |||
47 | static const char *sfc_mux_p[] __initconst = { | ||
48 | "24m", "150m", "200m", "100m", "75m", }; | ||
49 | static u32 sfc_mux_table[] = {0, 4, 5, 6, 7}; | ||
50 | |||
51 | static const char *sdio1_mux_p[] __initconst = { | ||
52 | "75m", "100m", "50m", "15m", }; | ||
53 | static u32 sdio1_mux_table[] = {0, 1, 2, 3}; | ||
54 | |||
55 | static const char *fephy_mux_p[] __initconst = { "25m", "125m"}; | ||
56 | static u32 fephy_mux_table[] = {0, 1}; | ||
57 | |||
58 | |||
59 | static 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 | |||
69 | static 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 | |||
84 | static 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 | |||
101 | CLK_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 | ||
180 | void __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 | |||
177 | void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks, | 208 | void __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 *); |
104 | void __init hisi_clk_register_divider(struct hisi_divider_clock *, | 105 | void __init hisi_clk_register_divider(struct hisi_divider_clock *, |
105 | int, struct hisi_clock_data *); | 106 | int, struct hisi_clock_data *); |
107 | void __init hisi_clk_register_gate(struct hisi_gate_clock *, | ||
108 | int, struct hisi_clock_data *); | ||
106 | void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *, | 109 | void __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 | |||
34 | config KIRKWOOD_CLK | 34 | config KIRKWOOD_CLK |
35 | bool | 35 | bool |
36 | select MVEBU_CLK_COMMON | 36 | select MVEBU_CLK_COMMON |
37 | |||
38 | config 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 | |||
8 | obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o | 8 | obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o |
9 | obj-$(CONFIG_DOVE_CLK) += dove.o | 9 | obj-$(CONFIG_DOVE_CLK) += dove.o |
10 | obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o | 10 | obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o |
11 | obj-$(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 | |||
19 | static 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 | |||
30 | static 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 | |||
45 | static 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 | |||
59 | static 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 | |||
76 | static 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 | |||
84 | static void __init mv88f5182_clk_init(struct device_node *np) | ||
85 | { | ||
86 | return mvebu_coreclk_setup(np, &mv88f5182_coreclks); | ||
87 | } | ||
88 | |||
89 | CLK_OF_DECLARE(mv88f5182_clk, "marvell,mv88f5182-core-clock", mv88f5182_clk_init); | ||
90 | |||
91 | /* | ||
92 | * Orion 5281 | ||
93 | */ | ||
94 | |||
95 | static 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 | |||
104 | static 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 | |||
116 | static 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 | |||
133 | static 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 | |||
141 | static void __init mv88f5281_clk_init(struct device_node *np) | ||
142 | { | ||
143 | return mvebu_coreclk_setup(np, &mv88f5281_coreclks); | ||
144 | } | ||
145 | |||
146 | CLK_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 | |||
155 | static 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 | |||
170 | static 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 | |||
182 | static 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 | |||
196 | static 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 | |||
205 | static void __init mv88f6183_clk_init(struct device_node *np) | ||
206 | { | ||
207 | return mvebu_coreclk_setup(np, &mv88f6183_coreclks); | ||
208 | } | ||
209 | |||
210 | CLK_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 | ||
15 | config MSM_GCC_8960 | 15 | config 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 @@ | |||
1 | obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o | 1 | obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o |
2 | 2 | ||
3 | clk-qcom-y += common.o | ||
3 | clk-qcom-y += clk-regmap.o | 4 | clk-qcom-y += clk-regmap.o |
4 | clk-qcom-y += clk-pll.o | 5 | clk-qcom-y += clk-pll.o |
5 | clk-qcom-y += clk-rcg.o | 6 | clk-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 | ||
157 | extern const struct clk_ops clk_rcg2_ops; | 157 | extern const struct clk_ops clk_rcg2_ops; |
158 | extern const struct clk_ops clk_edp_pixel_ops; | ||
159 | extern const struct clk_ops clk_byte_ops; | ||
160 | extern 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 | ||
61 | static u8 clk_rcg2_get_parent(struct clk_hw *hw) | 62 | static 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 | ||
187 | static long _freq_tbl_determine_rate(struct clk_hw *hw, | 189 | static 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 | ||
227 | static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate) | 229 | static 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 | ||
266 | static 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 | |||
270 | static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, | 278 | static 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 | }; |
291 | EXPORT_SYMBOL_GPL(clk_rcg2_ops); | 299 | EXPORT_SYMBOL_GPL(clk_rcg2_ops); |
300 | |||
301 | struct frac_entry { | ||
302 | int num; | ||
303 | int den; | ||
304 | }; | ||
305 | |||
306 | static 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 | |||
317 | static 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 | |||
328 | static 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 | |||
367 | static 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 | |||
374 | static 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 | |||
414 | const 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 | }; | ||
423 | EXPORT_SYMBOL_GPL(clk_edp_pixel_ops); | ||
424 | |||
425 | static 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 | |||
445 | static 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 | |||
461 | static 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 | |||
468 | const 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 | }; | ||
477 | EXPORT_SYMBOL_GPL(clk_byte_ops); | ||
478 | |||
479 | static const struct frac_entry frac_table_pixel[] = { | ||
480 | { 3, 8 }, | ||
481 | { 2, 9 }, | ||
482 | { 4, 9 }, | ||
483 | { 1, 1 }, | ||
484 | { } | ||
485 | }; | ||
486 | |||
487 | static 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 | |||
512 | static 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 | |||
545 | static 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 | |||
552 | const 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 | }; | ||
561 | EXPORT_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 | |||
24 | struct qcom_cc { | ||
25 | struct qcom_reset_controller reset; | ||
26 | struct clk_onecell_data data; | ||
27 | struct clk *clks[]; | ||
28 | }; | ||
29 | |||
30 | int 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 | } | ||
94 | EXPORT_SYMBOL_GPL(qcom_cc_probe); | ||
95 | |||
96 | void 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 | } | ||
101 | EXPORT_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 | |||
16 | struct platform_device; | ||
17 | struct regmap_config; | ||
18 | struct clk_regmap; | ||
19 | struct qcom_reset_map; | ||
20 | |||
21 | struct 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 | |||
29 | extern int qcom_cc_probe(struct platform_device *pdev, | ||
30 | const struct qcom_cc_desc *desc); | ||
31 | |||
32 | extern 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 | ||
2705 | static 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 | |||
2704 | static const struct of_device_id gcc_msm8660_match_table[] = { | 2713 | static const struct of_device_id gcc_msm8660_match_table[] = { |
2705 | { .compatible = "qcom,gcc-msm8660" }, | 2714 | { .compatible = "qcom,gcc-msm8660" }, |
2706 | { } | 2715 | { } |
2707 | }; | 2716 | }; |
2708 | MODULE_DEVICE_TABLE(of, gcc_msm8660_match_table); | 2717 | MODULE_DEVICE_TABLE(of, gcc_msm8660_match_table); |
2709 | 2718 | ||
2710 | struct qcom_cc { | ||
2711 | struct qcom_reset_controller reset; | ||
2712 | struct clk_onecell_data data; | ||
2713 | struct clk *clks[]; | ||
2714 | }; | ||
2715 | |||
2716 | static int gcc_msm8660_probe(struct platform_device *pdev) | 2719 | static 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 | ||
2788 | static int gcc_msm8660_remove(struct platform_device *pdev) | 2736 | static 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 | ||
2871 | static 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 | |||
2870 | static const struct regmap_config gcc_msm8960_regmap_config = { | 2881 | static 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 | ||
2889 | static 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 | |||
2897 | static 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 | |||
2878 | static const struct of_device_id gcc_msm8960_match_table[] = { | 2905 | static 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 | }; |
2882 | MODULE_DEVICE_TABLE(of, gcc_msm8960_match_table); | 2910 | MODULE_DEVICE_TABLE(of, gcc_msm8960_match_table); |
2883 | 2911 | ||
2884 | struct qcom_cc { | ||
2885 | struct qcom_reset_controller reset; | ||
2886 | struct clk_onecell_data data; | ||
2887 | struct clk *clks[]; | ||
2888 | }; | ||
2889 | |||
2890 | static int gcc_msm8960_probe(struct platform_device *pdev) | 2912 | static 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 | ||
2962 | static int gcc_msm8960_remove(struct platform_device *pdev) | 2934 | static 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 | ||
38 | static const u8 gcc_xo_gpll0_map[] = { | 40 | static 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 | ||
50 | static const u8 gcc_xo_gpll0_gpll4_map[] = { | ||
51 | [P_XO] = 0, | ||
52 | [P_GPLL0] = 1, | ||
53 | [P_GPLL4] = 5, | ||
54 | }; | ||
55 | |||
56 | static 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 | ||
50 | static struct clk_pll gpll0 = { | 64 | static struct clk_pll gpll0 = { |
@@ -137,6 +151,33 @@ static struct clk_regmap gpll1_vote = { | |||
137 | }, | 151 | }, |
138 | }; | 152 | }; |
139 | 153 | ||
154 | static 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 | |||
170 | static 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 | |||
140 | static const struct freq_tbl ftbl_gcc_usb30_master_clk[] = { | 181 | static 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 | ||
855 | static 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 | |||
868 | static 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 | |||
814 | static struct clk_rcg2 sdcc1_apps_clk_src = { | 875 | static 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 | ||
828 | static struct clk_rcg2 sdcc2_apps_clk_src = { | 884 | static struct clk_rcg2 sdcc2_apps_clk_src = { |
@@ -1340,7 +1396,7 @@ static struct clk_branch gcc_blsp1_uart6_apps_clk = { | |||
1340 | }; | 1396 | }; |
1341 | 1397 | ||
1342 | static struct clk_branch gcc_blsp2_ahb_clk = { | 1398 | static 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 | ||
2053 | static 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 | |||
2069 | static 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 | |||
1997 | static struct clk_branch gcc_sdcc2_ahb_clk = { | 2085 | static 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 | ||
2488 | static const struct qcom_reset_map gcc_msm8974_resets[] = { | 2580 | static 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 | ||
2669 | static 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 | |||
2577 | static const struct of_device_id gcc_msm8974_match_table[] = { | 2677 | static 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 | }; |
2581 | MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table); | 2683 | MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table); |
2582 | 2684 | ||
2583 | struct qcom_cc { | 2685 | static 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 | ||
2589 | static int gcc_msm8974_probe(struct platform_device *pdev) | 2700 | static 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 | ||
2663 | static int gcc_msm8974_remove(struct platform_device *pdev) | 2729 | static 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 | ||
2226 | static 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 | |||
2225 | static const struct of_device_id mmcc_msm8960_match_table[] = { | 2234 | static const struct of_device_id mmcc_msm8960_match_table[] = { |
2226 | { .compatible = "qcom,mmcc-msm8960" }, | 2235 | { .compatible = "qcom,mmcc-msm8960" }, |
2227 | { } | 2236 | { } |
2228 | }; | 2237 | }; |
2229 | MODULE_DEVICE_TABLE(of, mmcc_msm8960_match_table); | 2238 | MODULE_DEVICE_TABLE(of, mmcc_msm8960_match_table); |
2230 | 2239 | ||
2231 | struct qcom_cc { | ||
2232 | struct qcom_reset_controller reset; | ||
2233 | struct clk_onecell_data data; | ||
2234 | struct clk *clks[]; | ||
2235 | }; | ||
2236 | |||
2237 | static int mmcc_msm8960_probe(struct platform_device *pdev) | 2240 | static 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 | ||
2300 | static int mmcc_msm8960_remove(struct platform_device *pdev) | 2245 | static 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 | ||
47 | static const u8 mmcc_xo_mmpll0_mmpll1_gpll0_map[] = { | 50 | static 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 | ||
166 | static 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 | |||
175 | static 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 | ||
165 | static struct clk_pll mmpll0 = { | 186 | static 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 | ||
499 | static struct freq_tbl ftbl_mdss_pclk0_clk[] = { | 523 | static 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 | |||
505 | static 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 | ||
753 | static struct freq_tbl ftbl_mdss_byte0_clk[] = { | 772 | static 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 | |||
759 | static 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 | ||
765 | static struct clk_rcg2 byte0_clk_src = { | 777 | static 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 | ||
778 | static struct clk_rcg2 byte1_clk_src = { | 791 | static 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 | ||
828 | static struct freq_tbl ftbl_mdss_edppixel_clk[] = { | 843 | static 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[] = { | |||
853 | static struct clk_rcg2 esc0_clk_src = { | 867 | static 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 = { | |||
866 | static struct clk_rcg2 esc1_clk_src = { | 880 | static 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 | ||
879 | static struct freq_tbl ftbl_mdss_extpclk_clk[] = { | 893 | static 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 | ||
2534 | static 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 | |||
2527 | static const struct of_device_id mmcc_msm8974_match_table[] = { | 2542 | static const struct of_device_id mmcc_msm8974_match_table[] = { |
2528 | { .compatible = "qcom,mmcc-msm8974" }, | 2543 | { .compatible = "qcom,mmcc-msm8974" }, |
2529 | { } | 2544 | { } |
2530 | }; | 2545 | }; |
2531 | MODULE_DEVICE_TABLE(of, mmcc_msm8974_match_table); | 2546 | MODULE_DEVICE_TABLE(of, mmcc_msm8974_match_table); |
2532 | 2547 | ||
2533 | struct qcom_cc { | ||
2534 | struct qcom_reset_controller reset; | ||
2535 | struct clk_onecell_data data; | ||
2536 | struct clk *clks[]; | ||
2537 | }; | ||
2538 | |||
2539 | static int mmcc_msm8974_probe(struct platform_device *pdev) | 2548 | static 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 | ||
2605 | static int mmcc_msm8974_remove(struct platform_device *pdev) | 2564 | static 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 | ||
27 | static void __init rk2928_gate_clk_init(struct device_node *node, | 27 | static 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 @@ | |||
1 | config COMMON_CLK_SAMSUNG | ||
2 | bool | ||
3 | select COMMON_CLK | ||
4 | |||
5 | config 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 | |||
11 | config 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 | |||
19 | config S3C2412_COMMON_CLK | ||
20 | bool | ||
21 | select COMMON_CLK_SAMSUNG | ||
22 | |||
23 | config 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 | ||
5 | obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o | 5 | obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o |
6 | obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o | ||
6 | obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o | 7 | obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o |
7 | obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o | 8 | obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o |
9 | obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o | ||
10 | obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o | ||
8 | obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o | 11 | obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o |
9 | obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o | 12 | obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o |
10 | obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o | 13 | obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o |
14 | obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o | ||
15 | obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o | ||
16 | obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o | ||
17 | obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o | ||
11 | obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o | 18 | obj-$(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 */ | ||
92 | enum exynos3250_plls { | ||
93 | apll, mpll, vpll, upll, | ||
94 | nr_plls | ||
95 | }; | ||
96 | |||
97 | static void __iomem *reg_base; | ||
98 | |||
99 | /* | ||
100 | * Support for CMU save/restore across system suspends | ||
101 | */ | ||
102 | #ifdef CONFIG_PM_SLEEP | ||
103 | static struct samsung_clk_reg_dump *exynos3250_clk_regs; | ||
104 | |||
105 | static 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 | |||
173 | static 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 | |||
180 | static void exynos3250_clk_resume(void) | ||
181 | { | ||
182 | samsung_clk_restore(reg_base, exynos3250_clk_regs, | ||
183 | ARRAY_SIZE(exynos3250_cmu_clk_regs)); | ||
184 | } | ||
185 | |||
186 | static struct syscore_ops exynos3250_clk_syscore_ops = { | ||
187 | .suspend = exynos3250_clk_suspend, | ||
188 | .resume = exynos3250_clk_resume, | ||
189 | }; | ||
190 | |||
191 | static 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; | ||
203 | err: | ||
204 | kfree(exynos3250_clk_regs); | ||
205 | } | ||
206 | #else | ||
207 | static inline void exynos3250_clk_sleep_init(void) { } | ||
208 | #endif | ||
209 | |||
210 | /* list of all parent clock list */ | ||
211 | PNAME(mout_vpllsrc_p) = { "fin_pll", }; | ||
212 | |||
213 | PNAME(mout_apll_p) = { "fin_pll", "fout_apll", }; | ||
214 | PNAME(mout_mpll_p) = { "fin_pll", "fout_mpll", }; | ||
215 | PNAME(mout_vpll_p) = { "fin_pll", "fout_vpll", }; | ||
216 | PNAME(mout_upll_p) = { "fin_pll", "fout_upll", }; | ||
217 | |||
218 | PNAME(mout_mpll_user_p) = { "fin_pll", "div_mpll_pre", }; | ||
219 | PNAME(mout_epll_user_p) = { "fin_pll", "mout_epll", }; | ||
220 | PNAME(mout_core_p) = { "mout_apll", "mout_mpll_user_c", }; | ||
221 | PNAME(mout_hpm_p) = { "mout_apll", "mout_mpll_user_c", }; | ||
222 | |||
223 | PNAME(mout_ebi_p) = { "div_aclk_200", "div_aclk_160", }; | ||
224 | PNAME(mout_ebi_1_p) = { "mout_ebi", "mout_vpll", }; | ||
225 | |||
226 | PNAME(mout_gdl_p) = { "mout_mpll_user_l", }; | ||
227 | PNAME(mout_gdr_p) = { "mout_mpll_user_r", }; | ||
228 | |||
229 | PNAME(mout_aclk_400_mcuisp_sub_p) | ||
230 | = { "fin_pll", "div_aclk_400_mcuisp", }; | ||
231 | PNAME(mout_aclk_266_0_p) = { "div_mpll_pre", "mout_vpll", }; | ||
232 | PNAME(mout_aclk_266_1_p) = { "mout_epll_user", }; | ||
233 | PNAME(mout_aclk_266_p) = { "mout_aclk_266_0", "mout_aclk_266_1", }; | ||
234 | PNAME(mout_aclk_266_sub_p) = { "fin_pll", "div_aclk_266", }; | ||
235 | |||
236 | PNAME(group_div_mpll_pre_p) = { "div_mpll_pre", }; | ||
237 | PNAME(group_epll_vpll_p) = { "mout_epll_user", "mout_vpll" }; | ||
238 | PNAME(group_sclk_p) = { "xxti", "xusbxti", | ||
239 | "none", "none", | ||
240 | "none", "none", "div_mpll_pre", | ||
241 | "mout_epll_user", "mout_vpll", }; | ||
242 | PNAME(group_sclk_audio_p) = { "audiocdclk", "none", | ||
243 | "none", "none", | ||
244 | "xxti", "xusbxti", | ||
245 | "div_mpll_pre", "mout_epll_user", | ||
246 | "mout_vpll", }; | ||
247 | PNAME(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", }; | ||
252 | PNAME(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 | |||
259 | PNAME(mout_mfc_p) = { "mout_mfc_0", "mout_mfc_1" }; | ||
260 | PNAME(mout_g3d_p) = { "mout_g3d_0", "mout_g3d_1" }; | ||
261 | |||
262 | static 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 | |||
273 | static 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 | |||
358 | static 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 | |||
455 | static 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 */ | ||
688 | static 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 */ | ||
710 | static 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 | |||
740 | static 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 | |||
751 | static 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 | } | ||
780 | CLK_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 | ||
327 | static void exynos4_clk_sleep_init(void) | 327 | static 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 |
362 | static void exynos4_clk_sleep_init(void) {} | 362 | static 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 */ |
429 | static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = { | 429 | static 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 | ||
1046 | static void __init exynos4_clk_register_finpll(void) | 1046 | static 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 = { | |||
1176 | static void __init exynos4_clk_init(struct device_node *np, | 1176 | static 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 */ |
84 | enum exynos5250_plls { | 107 | enum 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; | |||
98 | static unsigned long exynos5250_clk_regs[] __initdata = { | 121 | static 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 | ||
146 | static int exynos5250_clk_suspend(void) | 175 | static int exynos5250_clk_suspend(void) |
@@ -189,13 +218,16 @@ PNAME(mout_vpllsrc_p) = { "fin_pll", "sclk_hdmi27m" }; | |||
189 | PNAME(mout_vpll_p) = { "mout_vpllsrc", "fout_vpll" }; | 218 | PNAME(mout_vpll_p) = { "mout_vpllsrc", "fout_vpll" }; |
190 | PNAME(mout_cpll_p) = { "fin_pll", "fout_cpll" }; | 219 | PNAME(mout_cpll_p) = { "fin_pll", "fout_cpll" }; |
191 | PNAME(mout_epll_p) = { "fin_pll", "fout_epll" }; | 220 | PNAME(mout_epll_p) = { "fin_pll", "fout_epll" }; |
221 | PNAME(mout_gpll_p) = { "fin_pll", "fout_gpll" }; | ||
192 | PNAME(mout_mpll_user_p) = { "fin_pll", "mout_mpll" }; | 222 | PNAME(mout_mpll_user_p) = { "fin_pll", "mout_mpll" }; |
193 | PNAME(mout_bpll_user_p) = { "fin_pll", "mout_bpll" }; | 223 | PNAME(mout_bpll_user_p) = { "fin_pll", "mout_bpll" }; |
194 | PNAME(mout_aclk166_p) = { "mout_cpll", "mout_mpll_user" }; | 224 | PNAME(mout_aclk166_p) = { "mout_cpll", "mout_mpll_user" }; |
195 | PNAME(mout_aclk200_p) = { "mout_mpll_user", "mout_bpll_user" }; | 225 | PNAME(mout_aclk200_p) = { "mout_mpll_user", "mout_bpll_user" }; |
226 | PNAME(mout_aclk400_p) = { "mout_aclk400_g3d_mid", "mout_gpll" }; | ||
196 | PNAME(mout_aclk200_sub_p) = { "fin_pll", "div_aclk200" }; | 227 | PNAME(mout_aclk200_sub_p) = { "fin_pll", "div_aclk200" }; |
197 | PNAME(mout_aclk266_sub_p) = { "fin_pll", "div_aclk266" }; | 228 | PNAME(mout_aclk266_sub_p) = { "fin_pll", "div_aclk266" }; |
198 | PNAME(mout_aclk333_sub_p) = { "fin_pll", "div_aclk333" }; | 229 | PNAME(mout_aclk333_sub_p) = { "fin_pll", "div_aclk333" }; |
230 | PNAME(mout_aclk400_isp_sub_p) = { "fin_pll", "div_aclk400_isp" }; | ||
199 | PNAME(mout_hdmi_p) = { "div_hdmi_pixel", "sclk_hdmiphy" }; | 231 | PNAME(mout_hdmi_p) = { "div_hdmi_pixel", "sclk_hdmiphy" }; |
200 | PNAME(mout_usb3_p) = { "mout_mpll_user", "mout_cpll" }; | 232 | PNAME(mout_usb3_p) = { "mout_mpll_user", "mout_cpll" }; |
201 | PNAME(mout_group1_p) = { "fin_pll", "fin_pll", "sclk_hdmi27m", | 233 | PNAME(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 | ||
620 | static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = { | 690 | static 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 */ |
687 | static void __init exynos5250_clk_init(struct device_node *np) | 757 | static 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 | |||
25 | static LIST_HEAD(clock_reg_cache_list); | ||
26 | |||
27 | struct 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 | |||
34 | struct 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 | */ | ||
62 | static 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 | */ | ||
95 | static 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 | |||
118 | static 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 | |||
129 | static 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 | |||
138 | static struct syscore_ops exynos5260_clk_syscore_ops = { | ||
139 | .suspend = exynos5260_clk_suspend, | ||
140 | .resume = exynos5260_clk_resume, | ||
141 | }; | ||
142 | |||
143 | static 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(®_cache->node, &clock_reg_cache_list); | ||
165 | } | ||
166 | |||
167 | #else | ||
168 | static 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 | |||
178 | void __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 | |||
214 | static 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 | |||
224 | PNAME(mout_aud_pll_user_p) = {"fin_pll", "fout_aud_pll"}; | ||
225 | PNAME(mout_sclk_aud_i2s_p) = {"mout_aud_pll_user", "ioclk_i2s_cdclk"}; | ||
226 | PNAME(mout_sclk_aud_pcm_p) = {"mout_aud_pll_user", "ioclk_pcm_extclk"}; | ||
227 | |||
228 | struct 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 | |||
237 | struct 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 | |||
249 | struct 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 | |||
267 | static 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 | |||
284 | CLK_OF_DECLARE(exynos5260_clk_aud, "samsung,exynos5260-clock-aud", | ||
285 | exynos5260_clk_aud_init); | ||
286 | |||
287 | |||
288 | /* CMU_DISP */ | ||
289 | |||
290 | static 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 | |||
305 | PNAME(mout_phyclk_dptx_phy_ch3_txd_clk_user_p) = {"fin_pll", | ||
306 | "phyclk_dptx_phy_ch3_txd_clk"}; | ||
307 | PNAME(mout_phyclk_dptx_phy_ch2_txd_clk_user_p) = {"fin_pll", | ||
308 | "phyclk_dptx_phy_ch2_txd_clk"}; | ||
309 | PNAME(mout_phyclk_dptx_phy_ch1_txd_clk_user_p) = {"fin_pll", | ||
310 | "phyclk_dptx_phy_ch1_txd_clk"}; | ||
311 | PNAME(mout_phyclk_dptx_phy_ch0_txd_clk_user_p) = {"fin_pll", | ||
312 | "phyclk_dptx_phy_ch0_txd_clk"}; | ||
313 | PNAME(mout_aclk_disp_222_user_p) = {"fin_pll", "dout_aclk_disp_222"}; | ||
314 | PNAME(mout_sclk_disp_pixel_user_p) = {"fin_pll", "dout_sclk_disp_pixel"}; | ||
315 | PNAME(mout_aclk_disp_333_user_p) = {"fin_pll", "dout_aclk_disp_333"}; | ||
316 | PNAME(mout_phyclk_hdmi_phy_tmds_clko_user_p) = {"fin_pll", | ||
317 | "phyclk_hdmi_phy_tmds_clko"}; | ||
318 | PNAME(mout_phyclk_hdmi_phy_ref_clko_user_p) = {"fin_pll", | ||
319 | "phyclk_hdmi_phy_ref_clko"}; | ||
320 | PNAME(mout_phyclk_hdmi_phy_pixel_clko_user_p) = {"fin_pll", | ||
321 | "phyclk_hdmi_phy_pixel_clko"}; | ||
322 | PNAME(mout_phyclk_hdmi_link_o_tmds_clkhi_user_p) = {"fin_pll", | ||
323 | "phyclk_hdmi_link_o_tmds_clkhi"}; | ||
324 | PNAME(mout_phyclk_mipi_dphy_4l_m_txbyte_clkhs_p) = {"fin_pll", | ||
325 | "phyclk_mipi_dphy_4l_m_txbyte_clkhs"}; | ||
326 | PNAME(mout_phyclk_dptx_phy_o_ref_clk_24m_user_p) = {"fin_pll", | ||
327 | "phyclk_dptx_phy_o_ref_clk_24m"}; | ||
328 | PNAME(mout_phyclk_dptx_phy_clk_div2_user_p) = {"fin_pll", | ||
329 | "phyclk_dptx_phy_clk_div2"}; | ||
330 | PNAME(mout_sclk_hdmi_pixel_p) = {"mout_sclk_disp_pixel_user", | ||
331 | "mout_aclk_disp_222_user"}; | ||
332 | PNAME(mout_phyclk_mipi_dphy_4lmrxclk_esc0_user_p) = {"fin_pll", | ||
333 | "phyclk_mipi_dphy_4l_m_rxclkesc0"}; | ||
334 | PNAME(mout_sclk_hdmi_spdif_p) = {"fin_pll", "ioclk_spdif_extclk", | ||
335 | "dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"}; | ||
336 | |||
337 | struct 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 | |||
406 | struct 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 | |||
419 | struct 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 | |||
457 | static 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 | |||
474 | CLK_OF_DECLARE(exynos5260_clk_disp, "samsung,exynos5260-clock-disp", | ||
475 | exynos5260_clk_disp_init); | ||
476 | |||
477 | |||
478 | /* CMU_EGL */ | ||
479 | |||
480 | static 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 | |||
494 | PNAME(mout_egl_b_p) = {"mout_egl_pll", "dout_bus_pll"}; | ||
495 | PNAME(mout_egl_pll_p) = {"fin_pll", "fout_egl_pll"}; | ||
496 | |||
497 | struct 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 | |||
503 | struct 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 | |||
515 | static 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 | |||
521 | static 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 | |||
538 | CLK_OF_DECLARE(exynos5260_clk_egl, "samsung,exynos5260-clock-egl", | ||
539 | exynos5260_clk_egl_init); | ||
540 | |||
541 | |||
542 | /* CMU_FSYS */ | ||
543 | |||
544 | static 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 | |||
556 | PNAME(mout_phyclk_usbhost20_phyclk_user_p) = {"fin_pll", | ||
557 | "phyclk_usbhost20_phy_phyclock"}; | ||
558 | PNAME(mout_phyclk_usbhost20_freeclk_user_p) = {"fin_pll", | ||
559 | "phyclk_usbhost20_phy_freeclk"}; | ||
560 | PNAME(mout_phyclk_usbhost20_clk48mohci_user_p) = {"fin_pll", | ||
561 | "phyclk_usbhost20_phy_clk48mohci"}; | ||
562 | PNAME(mout_phyclk_usbdrd30_pipe_pclk_user_p) = {"fin_pll", | ||
563 | "phyclk_usbdrd30_udrd30_pipe_pclk"}; | ||
564 | PNAME(mout_phyclk_usbdrd30_phyclock_user_p) = {"fin_pll", | ||
565 | "phyclk_usbdrd30_udrd30_phyclock"}; | ||
566 | |||
567 | struct 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 | |||
590 | struct 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 | |||
623 | static 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 | |||
638 | CLK_OF_DECLARE(exynos5260_clk_fsys, "samsung,exynos5260-clock-fsys", | ||
639 | exynos5260_clk_fsys_init); | ||
640 | |||
641 | |||
642 | /* CMU_G2D */ | ||
643 | |||
644 | static 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 | |||
669 | PNAME(mout_aclk_g2d_333_user_p) = {"fin_pll", "dout_aclk_g2d_333"}; | ||
670 | |||
671 | struct 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 | |||
677 | struct 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 | |||
682 | struct 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 | |||
712 | static 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 | |||
729 | CLK_OF_DECLARE(exynos5260_clk_g2d, "samsung,exynos5260-clock-g2d", | ||
730 | exynos5260_clk_g2d_init); | ||
731 | |||
732 | |||
733 | /* CMU_G3D */ | ||
734 | |||
735 | static 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 | |||
749 | PNAME(mout_g3d_pll_p) = {"fin_pll", "fout_g3d_pll"}; | ||
750 | |||
751 | struct 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 | |||
756 | struct 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 | |||
761 | struct 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 | |||
767 | static 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 | |||
773 | static 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 | |||
792 | CLK_OF_DECLARE(exynos5260_clk_g3d, "samsung,exynos5260-clock-g3d", | ||
793 | exynos5260_clk_g3d_init); | ||
794 | |||
795 | |||
796 | /* CMU_GSCL */ | ||
797 | |||
798 | static 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 | |||
823 | PNAME(mout_aclk_gscl_333_user_p) = {"fin_pll", "dout_aclk_gscl_333"}; | ||
824 | PNAME(mout_aclk_m2m_400_user_p) = {"fin_pll", "dout_aclk_gscl_400"}; | ||
825 | PNAME(mout_aclk_gscl_fimc_user_p) = {"fin_pll", "dout_aclk_gscl_400"}; | ||
826 | PNAME(mout_aclk_csis_p) = {"dout_aclk_csis_200", "mout_aclk_gscl_fimc_user"}; | ||
827 | |||
828 | struct 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 | |||
842 | struct 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 | |||
851 | struct 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 | |||
908 | static 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 | |||
925 | CLK_OF_DECLARE(exynos5260_clk_gscl, "samsung,exynos5260-clock-gscl", | ||
926 | exynos5260_clk_gscl_init); | ||
927 | |||
928 | |||
929 | /* CMU_ISP */ | ||
930 | |||
931 | static 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 | |||
944 | PNAME(mout_isp_400_user_p) = {"fin_pll", "dout_aclk_isp1_400"}; | ||
945 | PNAME(mout_isp_266_user_p) = {"fin_pll", "dout_aclk_isp1_266"}; | ||
946 | |||
947 | struct 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 | |||
954 | struct 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 | |||
966 | struct 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 | |||
1027 | static 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 | |||
1044 | CLK_OF_DECLARE(exynos5260_clk_isp, "samsung,exynos5260-clock-isp", | ||
1045 | exynos5260_clk_isp_init); | ||
1046 | |||
1047 | |||
1048 | /* CMU_KFC */ | ||
1049 | |||
1050 | static 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 | |||
1065 | PNAME(mout_kfc_pll_p) = {"fin_pll", "fout_kfc_pll"}; | ||
1066 | PNAME(mout_kfc_p) = {"mout_kfc_pll", "dout_media_pll"}; | ||
1067 | |||
1068 | struct 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 | |||
1074 | struct 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 | |||
1085 | static 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 | |||
1091 | static 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 | |||
1108 | CLK_OF_DECLARE(exynos5260_clk_kfc, "samsung,exynos5260-clock-kfc", | ||
1109 | exynos5260_clk_kfc_init); | ||
1110 | |||
1111 | |||
1112 | /* CMU_MFC */ | ||
1113 | |||
1114 | static 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 | |||
1125 | PNAME(mout_aclk_mfc_333_user_p) = {"fin_pll", "dout_aclk_mfc_333"}; | ||
1126 | |||
1127 | struct 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 | |||
1133 | struct 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 | |||
1138 | struct 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 | |||
1147 | static 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 | |||
1164 | CLK_OF_DECLARE(exynos5260_clk_mfc, "samsung,exynos5260-clock-mfc", | ||
1165 | exynos5260_clk_mfc_init); | ||
1166 | |||
1167 | |||
1168 | /* CMU_MIF */ | ||
1169 | |||
1170 | static 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 | |||
1204 | PNAME(mout_mem_pll_p) = {"fin_pll", "fout_mem_pll"}; | ||
1205 | PNAME(mout_bus_pll_p) = {"fin_pll", "fout_bus_pll"}; | ||
1206 | PNAME(mout_media_pll_p) = {"fin_pll", "fout_media_pll"}; | ||
1207 | PNAME(mout_mif_drex_p) = {"dout_mem_pll", "dout_bus_pll"}; | ||
1208 | PNAME(mout_mif_drex2x_p) = {"dout_mem_pll", "dout_bus_pll"}; | ||
1209 | PNAME(mout_clkm_phy_p) = {"mout_mif_drex", "dout_media_pll"}; | ||
1210 | PNAME(mout_clk2x_phy_p) = {"mout_mif_drex2x", "dout_media_pll"}; | ||
1211 | |||
1212 | struct 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 | |||
1229 | struct 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 | |||
1248 | struct 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 | |||
1282 | static 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 | |||
1294 | static 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 | |||
1313 | CLK_OF_DECLARE(exynos5260_clk_mif, "samsung,exynos5260-clock-mif", | ||
1314 | exynos5260_clk_mif_init); | ||
1315 | |||
1316 | |||
1317 | /* CMU_PERI */ | ||
1318 | |||
1319 | static 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 | |||
1348 | PNAME(mout_sclk_pcm_p) = {"ioclk_pcm_extclk", "fin_pll", "dout_aclk_peri_aud", | ||
1349 | "phyclk_hdmi_phy_ref_cko"}; | ||
1350 | PNAME(mout_sclk_i2scod_p) = {"ioclk_i2s_cdclk", "fin_pll", "dout_aclk_peri_aud", | ||
1351 | "phyclk_hdmi_phy_ref_cko"}; | ||
1352 | PNAME(mout_sclk_spdif_p) = {"ioclk_spdif_extclk", "fin_pll", | ||
1353 | "dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"}; | ||
1354 | |||
1355 | struct 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 | |||
1364 | struct 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 | |||
1369 | struct 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 | |||
1502 | static 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 | |||
1519 | CLK_OF_DECLARE(exynos5260_clk_peri, "samsung,exynos5260-clock-peri", | ||
1520 | exynos5260_clk_peri_init); | ||
1521 | |||
1522 | |||
1523 | /* CMU_TOP */ | ||
1524 | |||
1525 | static 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 */ | ||
1566 | struct 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 | |||
1606 | PNAME(mout_memtop_pll_user_p) = {"fin_pll", "dout_mem_pll"}; | ||
1607 | PNAME(mout_bustop_pll_user_p) = {"fin_pll", "dout_bus_pll"}; | ||
1608 | PNAME(mout_mediatop_pll_user_p) = {"fin_pll", "dout_media_pll"}; | ||
1609 | PNAME(mout_audtop_pll_user_p) = {"fin_pll", "mout_aud_pll"}; | ||
1610 | PNAME(mout_aud_pll_p) = {"fin_pll", "fout_aud_pll"}; | ||
1611 | PNAME(mout_disp_pll_p) = {"fin_pll", "fout_disp_pll"}; | ||
1612 | PNAME(mout_mfc_bustop_333_p) = {"mout_bustop_pll_user", "mout_disp_pll"}; | ||
1613 | PNAME(mout_aclk_mfc_333_p) = {"mout_mediatop_pll_user", "mout_mfc_bustop_333"}; | ||
1614 | PNAME(mout_g2d_bustop_333_p) = {"mout_bustop_pll_user", "mout_disp_pll"}; | ||
1615 | PNAME(mout_aclk_g2d_333_p) = {"mout_mediatop_pll_user", "mout_g2d_bustop_333"}; | ||
1616 | PNAME(mout_gscl_bustop_333_p) = {"mout_bustop_pll_user", "mout_disp_pll"}; | ||
1617 | PNAME(mout_aclk_gscl_333_p) = {"mout_mediatop_pll_user", | ||
1618 | "mout_gscl_bustop_333"}; | ||
1619 | PNAME(mout_m2m_mediatop_400_p) = {"mout_mediatop_pll_user", "mout_disp_pll"}; | ||
1620 | PNAME(mout_aclk_gscl_400_p) = {"mout_bustop_pll_user", | ||
1621 | "mout_m2m_mediatop_400"}; | ||
1622 | PNAME(mout_gscl_bustop_fimc_p) = {"mout_bustop_pll_user", "mout_disp_pll"}; | ||
1623 | PNAME(mout_aclk_gscl_fimc_p) = {"mout_mediatop_pll_user", | ||
1624 | "mout_gscl_bustop_fimc"}; | ||
1625 | PNAME(mout_isp1_media_266_p) = {"mout_mediatop_pll_user", | ||
1626 | "mout_memtop_pll_user"}; | ||
1627 | PNAME(mout_aclk_isp1_266_p) = {"mout_bustop_pll_user", "mout_isp1_media_266"}; | ||
1628 | PNAME(mout_isp1_media_400_p) = {"mout_mediatop_pll_user", "mout_disp_pll"}; | ||
1629 | PNAME(mout_aclk_isp1_400_p) = {"mout_bustop_pll_user", "mout_isp1_media_400"}; | ||
1630 | PNAME(mout_sclk_isp_spi_p) = {"fin_pll", "mout_bustop_pll_user"}; | ||
1631 | PNAME(mout_sclk_isp_uart_p) = {"fin_pll", "mout_bustop_pll_user"}; | ||
1632 | PNAME(mout_sclk_isp_sensor_p) = {"fin_pll", "mout_bustop_pll_user"}; | ||
1633 | PNAME(mout_disp_disp_333_p) = {"mout_disp_pll", "mout_bustop_pll_user"}; | ||
1634 | PNAME(mout_aclk_disp_333_p) = {"mout_mediatop_pll_user", "mout_disp_disp_333"}; | ||
1635 | PNAME(mout_disp_disp_222_p) = {"mout_disp_pll", "mout_bustop_pll_user"}; | ||
1636 | PNAME(mout_aclk_disp_222_p) = {"mout_mediatop_pll_user", "mout_disp_disp_222"}; | ||
1637 | PNAME(mout_disp_media_pixel_p) = {"mout_mediatop_pll_user", | ||
1638 | "mout_bustop_pll_user"}; | ||
1639 | PNAME(mout_sclk_disp_pixel_p) = {"mout_disp_pll", "mout_disp_media_pixel"}; | ||
1640 | PNAME(mout_bus_bustop_400_p) = {"mout_bustop_pll_user", "mout_memtop_pll_user"}; | ||
1641 | PNAME(mout_bus_bustop_100_p) = {"mout_bustop_pll_user", "mout_memtop_pll_user"}; | ||
1642 | PNAME(mout_sclk_peri_spi_clk_p) = {"fin_pll", "mout_bustop_pll_user"}; | ||
1643 | PNAME(mout_sclk_peri_uart_uclk_p) = {"fin_pll", "mout_bustop_pll_user"}; | ||
1644 | PNAME(mout_sclk_fsys_usb_p) = {"fin_pll", "mout_bustop_pll_user"}; | ||
1645 | PNAME(mout_sclk_fsys_mmc_sdclkin_a_p) = {"fin_pll", "mout_bustop_pll_user"}; | ||
1646 | PNAME(mout_sclk_fsys_mmc0_sdclkin_b_p) = {"mout_sclk_fsys_mmc0_sdclkin_a", | ||
1647 | "mout_mediatop_pll_user"}; | ||
1648 | PNAME(mout_sclk_fsys_mmc1_sdclkin_b_p) = {"mout_sclk_fsys_mmc1_sdclkin_a", | ||
1649 | "mout_mediatop_pll_user"}; | ||
1650 | PNAME(mout_sclk_fsys_mmc2_sdclkin_b_p) = {"mout_sclk_fsys_mmc2_sdclkin_a", | ||
1651 | "mout_mediatop_pll_user"}; | ||
1652 | |||
1653 | struct 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 | |||
1813 | struct 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 | |||
1934 | struct 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 | |||
1949 | static 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 | |||
1958 | static 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 | |||
1979 | CLK_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 */ | ||
57 | enum exynos5410_plls { | ||
58 | apll, cpll, mpll, | ||
59 | bpll, kpll, | ||
60 | nr_plls /* number of PLLs */ | ||
61 | }; | ||
62 | |||
63 | /* list of all parent clocks */ | ||
64 | PNAME(apll_p) = { "fin_pll", "fout_apll", }; | ||
65 | PNAME(bpll_p) = { "fin_pll", "fout_bpll", }; | ||
66 | PNAME(cpll_p) = { "fin_pll", "fout_cpll" }; | ||
67 | PNAME(mpll_p) = { "fin_pll", "fout_mpll", }; | ||
68 | PNAME(kpll_p) = { "fin_pll", "fout_kpll", }; | ||
69 | |||
70 | PNAME(mout_cpu_p) = { "mout_apll", "sclk_mpll", }; | ||
71 | PNAME(mout_kfc_p) = { "mout_kpll", "sclk_mpll", }; | ||
72 | |||
73 | PNAME(mpll_user_p) = { "fin_pll", "sclk_mpll", }; | ||
74 | PNAME(bpll_user_p) = { "fin_pll", "sclk_bpll", }; | ||
75 | PNAME(mpll_bpll_p) = { "sclk_mpll_muxed", "sclk_bpll_muxed", }; | ||
76 | |||
77 | PNAME(group2_p) = { "fin_pll", "fin_pll", "none", "none", | ||
78 | "none", "none", "sclk_mpll_bpll", | ||
79 | "none", "none", "sclk_cpll" }; | ||
80 | |||
81 | static 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 | |||
110 | static 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 | |||
146 | static 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 | |||
172 | static 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 */ | ||
186 | static 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 | } | ||
209 | CLK_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 */ | ||
135 | enum exynos5x_soc { | ||
136 | EXYNOS5420, | ||
137 | EXYNOS5800, | ||
138 | }; | ||
139 | |||
105 | /* list of PLLs */ | 140 | /* list of PLLs */ |
106 | enum exynos5420_plls { | 141 | enum 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 | ||
112 | static void __iomem *reg_base; | 147 | static void __iomem *reg_base; |
148 | static enum exynos5x_soc exynos5x_soc; | ||
113 | 149 | ||
114 | #ifdef CONFIG_PM_SLEEP | 150 | #ifdef CONFIG_PM_SLEEP |
115 | static struct samsung_clk_reg_dump *exynos5420_save; | 151 | static struct samsung_clk_reg_dump *exynos5x_save; |
152 | static 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 | */ |
121 | static unsigned long exynos5420_clk_regs[] __initdata = { | 158 | static 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 | ||
241 | static 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 | |||
183 | static int exynos5420_clk_suspend(void) | 252 | static 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 | ||
191 | static void exynos5420_clk_resume(void) | 264 | static 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 | ||
197 | static struct syscore_ops exynos5420_clk_syscore_ops = { | 274 | static struct syscore_ops exynos5420_clk_syscore_ops = { |
@@ -201,108 +278,183 @@ static struct syscore_ops exynos5420_clk_syscore_ops = { | |||
201 | 278 | ||
202 | static void exynos5420_clk_sleep_init(void) | 279 | static 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; | ||
299 | err_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 |
215 | static void exynos5420_clk_sleep_init(void) {} | 306 | static void exynos5420_clk_sleep_init(void) {} |
216 | #endif | 307 | #endif |
217 | 308 | ||
218 | /* list of all parent clocks */ | 309 | /* list of all parent clocks */ |
219 | PNAME(mspll_cpu_p) = { "sclk_cpll", "sclk_dpll", | 310 | PNAME(mout_mspll_cpu_p) = {"mout_sclk_cpll", "mout_sclk_dpll", |
220 | "sclk_mpll", "sclk_spll" }; | 311 | "mout_sclk_mpll", "mout_sclk_spll"}; |
221 | PNAME(cpu_p) = { "mout_apll" , "mout_mspll_cpu" }; | 312 | PNAME(mout_cpu_p) = {"mout_apll" , "mout_mspll_cpu"}; |
222 | PNAME(kfc_p) = { "mout_kpll" , "mout_mspll_kfc" }; | 313 | PNAME(mout_kfc_p) = {"mout_kpll" , "mout_mspll_kfc"}; |
223 | PNAME(apll_p) = { "fin_pll", "fout_apll", }; | 314 | PNAME(mout_apll_p) = {"fin_pll", "fout_apll"}; |
224 | PNAME(bpll_p) = { "fin_pll", "fout_bpll", }; | 315 | PNAME(mout_bpll_p) = {"fin_pll", "fout_bpll"}; |
225 | PNAME(cpll_p) = { "fin_pll", "fout_cpll", }; | 316 | PNAME(mout_cpll_p) = {"fin_pll", "fout_cpll"}; |
226 | PNAME(dpll_p) = { "fin_pll", "fout_dpll", }; | 317 | PNAME(mout_dpll_p) = {"fin_pll", "fout_dpll"}; |
227 | PNAME(epll_p) = { "fin_pll", "fout_epll", }; | 318 | PNAME(mout_epll_p) = {"fin_pll", "fout_epll"}; |
228 | PNAME(ipll_p) = { "fin_pll", "fout_ipll", }; | 319 | PNAME(mout_ipll_p) = {"fin_pll", "fout_ipll"}; |
229 | PNAME(kpll_p) = { "fin_pll", "fout_kpll", }; | 320 | PNAME(mout_kpll_p) = {"fin_pll", "fout_kpll"}; |
230 | PNAME(mpll_p) = { "fin_pll", "fout_mpll", }; | 321 | PNAME(mout_mpll_p) = {"fin_pll", "fout_mpll"}; |
231 | PNAME(rpll_p) = { "fin_pll", "fout_rpll", }; | 322 | PNAME(mout_rpll_p) = {"fin_pll", "fout_rpll"}; |
232 | PNAME(spll_p) = { "fin_pll", "fout_spll", }; | 323 | PNAME(mout_spll_p) = {"fin_pll", "fout_spll"}; |
233 | PNAME(vpll_p) = { "fin_pll", "fout_vpll", }; | 324 | PNAME(mout_vpll_p) = {"fin_pll", "fout_vpll"}; |
234 | 325 | ||
235 | PNAME(group1_p) = { "sclk_cpll", "sclk_dpll", "sclk_mpll" }; | 326 | PNAME(mout_group1_p) = {"mout_sclk_cpll", "mout_sclk_dpll", |
236 | PNAME(group2_p) = { "fin_pll", "sclk_cpll", "sclk_dpll", "sclk_mpll", | 327 | "mout_sclk_mpll"}; |
237 | "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; | 328 | PNAME(mout_group2_p) = {"fin_pll", "mout_sclk_cpll", |
238 | PNAME(group3_p) = { "sclk_rpll", "sclk_spll" }; | 329 | "mout_sclk_dpll", "mout_sclk_mpll", "mout_sclk_spll", |
239 | PNAME(group4_p) = { "sclk_ipll", "sclk_dpll", "sclk_mpll" }; | 330 | "mout_sclk_ipll", "mout_sclk_epll", "mout_sclk_rpll"}; |
240 | PNAME(group5_p) = { "sclk_vpll", "sclk_dpll" }; | 331 | PNAME(mout_group3_p) = {"mout_sclk_rpll", "mout_sclk_spll"}; |
241 | 332 | PNAME(mout_group4_p) = {"mout_sclk_ipll", "mout_sclk_dpll", "mout_sclk_mpll"}; | |
242 | PNAME(sw_aclk66_p) = { "dout_aclk66", "sclk_spll" }; | 333 | PNAME(mout_group5_p) = {"mout_sclk_vpll", "mout_sclk_dpll"}; |
243 | PNAME(aclk66_peric_p) = { "fin_pll", "mout_sw_aclk66" }; | 334 | |
244 | 335 | PNAME(mout_fimd1_final_p) = {"mout_fimd1", "mout_fimd1_opt"}; | |
245 | PNAME(sw_aclk200_fsys_p) = { "dout_aclk200_fsys", "sclk_spll"}; | 336 | PNAME(mout_sw_aclk66_p) = {"dout_aclk66", "mout_sclk_spll"}; |
246 | PNAME(user_aclk200_fsys_p) = { "fin_pll", "mout_sw_aclk200_fsys" }; | 337 | PNAME(mout_user_aclk66_peric_p) = { "fin_pll", "mout_sw_aclk66"}; |
247 | 338 | PNAME(mout_user_pclk66_gpio_p) = {"mout_sw_aclk66", "ff_sw_aclk66"}; | |
248 | PNAME(sw_aclk200_fsys2_p) = { "dout_aclk200_fsys2", "sclk_spll"}; | 339 | |
249 | PNAME(user_aclk200_fsys2_p) = { "fin_pll", "mout_sw_aclk200_fsys2" }; | 340 | PNAME(mout_sw_aclk200_fsys_p) = {"dout_aclk200_fsys", "mout_sclk_spll"}; |
250 | 341 | PNAME(mout_sw_pclk200_fsys_p) = {"dout_pclk200_fsys", "mout_sclk_spll"}; | |
251 | PNAME(sw_aclk200_p) = { "dout_aclk200", "sclk_spll"}; | 342 | PNAME(mout_user_pclk200_fsys_p) = {"fin_pll", "mout_sw_pclk200_fsys"}; |
252 | PNAME(aclk200_disp1_p) = { "fin_pll", "mout_sw_aclk200" }; | 343 | PNAME(mout_user_aclk200_fsys_p) = {"fin_pll", "mout_sw_aclk200_fsys"}; |
253 | 344 | ||
254 | PNAME(sw_aclk400_mscl_p) = { "dout_aclk400_mscl", "sclk_spll"}; | 345 | PNAME(mout_sw_aclk200_fsys2_p) = {"dout_aclk200_fsys2", "mout_sclk_spll"}; |
255 | PNAME(user_aclk400_mscl_p) = { "fin_pll", "mout_sw_aclk400_mscl" }; | 346 | PNAME(mout_user_aclk200_fsys2_p) = {"fin_pll", "mout_sw_aclk200_fsys2"}; |
256 | 347 | PNAME(mout_sw_aclk100_noc_p) = {"dout_aclk100_noc", "mout_sclk_spll"}; | |
257 | PNAME(sw_aclk333_p) = { "dout_aclk333", "sclk_spll"}; | 348 | PNAME(mout_user_aclk100_noc_p) = {"fin_pll", "mout_sw_aclk100_noc"}; |
258 | PNAME(user_aclk333_p) = { "fin_pll", "mout_sw_aclk333" }; | 349 | |
259 | 350 | PNAME(mout_sw_aclk400_wcore_p) = {"dout_aclk400_wcore", "mout_sclk_spll"}; | |
260 | PNAME(sw_aclk166_p) = { "dout_aclk166", "sclk_spll"}; | 351 | PNAME(mout_aclk400_wcore_bpll_p) = {"mout_aclk400_wcore", "sclk_bpll"}; |
261 | PNAME(user_aclk166_p) = { "fin_pll", "mout_sw_aclk166" }; | 352 | PNAME(mout_user_aclk400_wcore_p) = {"fin_pll", "mout_sw_aclk400_wcore"}; |
262 | 353 | ||
263 | PNAME(sw_aclk266_p) = { "dout_aclk266", "sclk_spll"}; | 354 | PNAME(mout_sw_aclk400_isp_p) = {"dout_aclk400_isp", "mout_sclk_spll"}; |
264 | PNAME(user_aclk266_p) = { "fin_pll", "mout_sw_aclk266" }; | 355 | PNAME(mout_user_aclk400_isp_p) = {"fin_pll", "mout_sw_aclk400_isp"}; |
265 | 356 | ||
266 | PNAME(sw_aclk333_432_gscl_p) = { "dout_aclk333_432_gscl", "sclk_spll"}; | 357 | PNAME(mout_sw_aclk333_432_isp0_p) = {"dout_aclk333_432_isp0", |
267 | PNAME(user_aclk333_432_gscl_p) = { "fin_pll", "mout_sw_aclk333_432_gscl" }; | 358 | "mout_sclk_spll"}; |
268 | 359 | PNAME(mout_user_aclk333_432_isp0_p) = {"fin_pll", "mout_sw_aclk333_432_isp0"}; | |
269 | PNAME(sw_aclk300_gscl_p) = { "dout_aclk300_gscl", "sclk_spll"}; | 360 | |
270 | PNAME(user_aclk300_gscl_p) = { "fin_pll", "mout_sw_aclk300_gscl" }; | 361 | PNAME(mout_sw_aclk333_432_isp_p) = {"dout_aclk333_432_isp", "mout_sclk_spll"}; |
271 | 362 | PNAME(mout_user_aclk333_432_isp_p) = {"fin_pll", "mout_sw_aclk333_432_isp"}; | |
272 | PNAME(sw_aclk300_disp1_p) = { "dout_aclk300_disp1", "sclk_spll"}; | 363 | |
273 | PNAME(user_aclk300_disp1_p) = { "fin_pll", "mout_sw_aclk300_disp1" }; | 364 | PNAME(mout_sw_aclk200_p) = {"dout_aclk200", "mout_sclk_spll"}; |
274 | 365 | PNAME(mout_user_aclk200_disp1_p) = {"fin_pll", "mout_sw_aclk200"}; | |
275 | PNAME(sw_aclk300_jpeg_p) = { "dout_aclk300_jpeg", "sclk_spll"}; | 366 | |
276 | PNAME(user_aclk300_jpeg_p) = { "fin_pll", "mout_sw_aclk300_jpeg" }; | 367 | PNAME(mout_sw_aclk400_mscl_p) = {"dout_aclk400_mscl", "mout_sclk_spll"}; |
277 | 368 | PNAME(mout_user_aclk400_mscl_p) = {"fin_pll", "mout_sw_aclk400_mscl"}; | |
278 | PNAME(sw_aclk_g3d_p) = { "dout_aclk_g3d", "sclk_spll"}; | 369 | |
279 | PNAME(user_aclk_g3d_p) = { "fin_pll", "mout_sw_aclk_g3d" }; | 370 | PNAME(mout_sw_aclk333_p) = {"dout_aclk333", "mout_sclk_spll"}; |
280 | 371 | PNAME(mout_user_aclk333_p) = {"fin_pll", "mout_sw_aclk333"}; | |
281 | PNAME(sw_aclk266_g2d_p) = { "dout_aclk266_g2d", "sclk_spll"}; | 372 | |
282 | PNAME(user_aclk266_g2d_p) = { "fin_pll", "mout_sw_aclk266_g2d" }; | 373 | PNAME(mout_sw_aclk166_p) = {"dout_aclk166", "mout_sclk_spll"}; |
283 | 374 | PNAME(mout_user_aclk166_p) = {"fin_pll", "mout_sw_aclk166"}; | |
284 | PNAME(sw_aclk333_g2d_p) = { "dout_aclk333_g2d", "sclk_spll"}; | 375 | |
285 | PNAME(user_aclk333_g2d_p) = { "fin_pll", "mout_sw_aclk333_g2d" }; | 376 | PNAME(mout_sw_aclk266_p) = {"dout_aclk266", "mout_sclk_spll"}; |
286 | 377 | PNAME(mout_user_aclk266_p) = {"fin_pll", "mout_sw_aclk266"}; | |
287 | PNAME(audio0_p) = { "fin_pll", "cdclk0", "sclk_dpll", "sclk_mpll", | 378 | PNAME(mout_user_aclk266_isp_p) = {"fin_pll", "mout_sw_aclk266"}; |
288 | "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; | 379 | |
289 | PNAME(audio1_p) = { "fin_pll", "cdclk1", "sclk_dpll", "sclk_mpll", | 380 | PNAME(mout_sw_aclk333_432_gscl_p) = {"dout_aclk333_432_gscl", "mout_sclk_spll"}; |
290 | "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; | 381 | PNAME(mout_user_aclk333_432_gscl_p) = {"fin_pll", "mout_sw_aclk333_432_gscl"}; |
291 | PNAME(audio2_p) = { "fin_pll", "cdclk2", "sclk_dpll", "sclk_mpll", | 382 | |
292 | "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; | 383 | PNAME(mout_sw_aclk300_gscl_p) = {"dout_aclk300_gscl", "mout_sclk_spll"}; |
293 | PNAME(spdif_p) = { "fin_pll", "dout_audio0", "dout_audio1", "dout_audio2", | 384 | PNAME(mout_user_aclk300_gscl_p) = {"fin_pll", "mout_sw_aclk300_gscl"}; |
294 | "spdif_extclk", "sclk_ipll", "sclk_epll", "sclk_rpll" }; | 385 | |
295 | PNAME(hdmi_p) = { "dout_hdmi_pixel", "sclk_hdmiphy" }; | 386 | PNAME(mout_sw_aclk300_disp1_p) = {"dout_aclk300_disp1", "mout_sclk_spll"}; |
296 | PNAME(maudio0_p) = { "fin_pll", "maudio_clk", "sclk_dpll", "sclk_mpll", | 387 | PNAME(mout_sw_aclk400_disp1_p) = {"dout_aclk400_disp1", "mout_sclk_spll"}; |
297 | "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; | 388 | PNAME(mout_user_aclk300_disp1_p) = {"fin_pll", "mout_sw_aclk300_disp1"}; |
389 | PNAME(mout_user_aclk400_disp1_p) = {"fin_pll", "mout_sw_aclk400_disp1"}; | ||
390 | |||
391 | PNAME(mout_sw_aclk300_jpeg_p) = {"dout_aclk300_jpeg", "mout_sclk_spll"}; | ||
392 | PNAME(mout_user_aclk300_jpeg_p) = {"fin_pll", "mout_sw_aclk300_jpeg"}; | ||
393 | |||
394 | PNAME(mout_sw_aclk_g3d_p) = {"dout_aclk_g3d", "mout_sclk_spll"}; | ||
395 | PNAME(mout_user_aclk_g3d_p) = {"fin_pll", "mout_sw_aclk_g3d"}; | ||
396 | |||
397 | PNAME(mout_sw_aclk266_g2d_p) = {"dout_aclk266_g2d", "mout_sclk_spll"}; | ||
398 | PNAME(mout_user_aclk266_g2d_p) = {"fin_pll", "mout_sw_aclk266_g2d"}; | ||
399 | |||
400 | PNAME(mout_sw_aclk333_g2d_p) = {"dout_aclk333_g2d", "mout_sclk_spll"}; | ||
401 | PNAME(mout_user_aclk333_g2d_p) = {"fin_pll", "mout_sw_aclk333_g2d"}; | ||
402 | |||
403 | PNAME(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"}; | ||
406 | PNAME(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"}; | ||
409 | PNAME(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"}; | ||
412 | PNAME(mout_spdif_p) = {"fin_pll", "dout_audio0", "dout_audio1", | ||
413 | "dout_audio2", "spdif_extclk", "mout_sclk_ipll", | ||
414 | "mout_sclk_epll", "mout_sclk_rpll"}; | ||
415 | PNAME(mout_hdmi_p) = {"dout_hdmi_pixel", "sclk_hdmiphy"}; | ||
416 | PNAME(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"}; | ||
419 | PNAME(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 */ | ||
422 | PNAME(mout_epll2_5800_p) = { "mout_sclk_epll", "ff_dout_epll2" }; | ||
423 | PNAME(mout_group1_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", | ||
424 | "mout_sclk_mpll", "ff_dout_spll2" }; | ||
425 | PNAME(mout_group2_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", | ||
426 | "mout_sclk_mpll", "ff_dout_spll2", | ||
427 | "mout_epll2", "mout_sclk_ipll" }; | ||
428 | PNAME(mout_group3_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", | ||
429 | "mout_sclk_mpll", "ff_dout_spll2", | ||
430 | "mout_epll2" }; | ||
431 | PNAME(mout_group5_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", | ||
432 | "mout_sclk_mpll", "mout_sclk_spll" }; | ||
433 | PNAME(mout_group6_5800_p) = { "mout_sclk_ipll", "mout_sclk_dpll", | ||
434 | "mout_sclk_mpll", "ff_dout_spll2" }; | ||
435 | PNAME(mout_group7_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", | ||
436 | "mout_sclk_mpll", "mout_sclk_spll", | ||
437 | "mout_epll2", "mout_sclk_ipll" }; | ||
438 | PNAME(mout_mau_epll_clk_5800_p) = { "mout_sclk_epll", "mout_sclk_dpll", | ||
439 | "mout_sclk_mpll", | ||
440 | "ff_dout_spll2" }; | ||
441 | PNAME(mout_group8_5800_p) = { "dout_aclk432_scaler", "dout_sclk_sw" }; | ||
442 | PNAME(mout_group9_5800_p) = { "dout_osc_div", "mout_sw_aclk432_scaler" }; | ||
443 | PNAME(mout_group10_5800_p) = { "dout_aclk432_cam", "dout_sclk_sw" }; | ||
444 | PNAME(mout_group11_5800_p) = { "dout_osc_div", "mout_sw_aclk432_cam" }; | ||
445 | PNAME(mout_group12_5800_p) = { "dout_aclkfl1_550_cam", "dout_sclk_sw" }; | ||
446 | PNAME(mout_group13_5800_p) = { "dout_osc_div", "mout_sw_aclkfl1_550_cam" }; | ||
447 | PNAME(mout_group14_5800_p) = { "dout_aclk550_cam", "dout_sclk_sw" }; | ||
448 | PNAME(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 */ |
300 | static struct samsung_fixed_rate_clock exynos5420_fixed_rate_ext_clks[] __initdata = { | 451 | static 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 */ |
305 | static struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = { | 457 | static 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 | ||
313 | static struct samsung_fixed_factor_clock exynos5420_fixed_factor_clks[] __initdata = { | 465 | static 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 | ||
317 | static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { | 471 | static 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), | 477 | struct 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 | |||
526 | struct 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 | |||
542 | struct 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 | |||
549 | struct 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 | |||
579 | struct samsung_div_clock exynos5420_div_clks[] __initdata = { | ||
580 | DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore_bpll", | ||
581 | DIV_TOP0, 16, 3), | ||
582 | }; | ||
583 | |||
584 | static 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 | ||
437 | static struct samsung_div_clock exynos5420_div_clks[] __initdata = { | 746 | static 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 | ||
517 | static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { | 862 | static 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 | ||
748 | static struct samsung_pll_clock exynos5420_plls[nr_plls] __initdata = { | 1145 | static 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 */ |
779 | static void __init exynos5420_clk_init(struct device_node *np) | 1176 | static 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 | |||
1231 | static void __init exynos5420_clk_init(struct device_node *np) | ||
1232 | { | ||
1233 | exynos5x_clk_init(np, EXYNOS5420); | ||
1234 | } | ||
808 | CLK_OF_DECLARE(exynos5420_clk, "samsung,exynos5420-clock", exynos5420_clk_init); | 1235 | CLK_OF_DECLARE(exynos5420_clk, "samsung,exynos5420-clock", exynos5420_clk_init); |
1236 | |||
1237 | static void __init exynos5800_clk_init(struct device_node *np) | ||
1238 | { | ||
1239 | exynos5x_clk_init(np, EXYNOS5800); | ||
1240 | } | ||
1241 | CLK_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 = { | |||
93 | static void __init exynos5440_clk_init(struct device_node *np) | 93 | static 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 | |||
73 | static 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 | |||
91 | static 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 | |||
106 | static 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 | |||
124 | static 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 | ||
570 | static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, | 639 | static 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 | |||
717 | static 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 | |||
735 | static 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 | |||
753 | static 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 | |||
785 | static 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 | |||
805 | static int samsung_s3c2410_mpll_enable(struct clk_hw *hw) | ||
806 | { | ||
807 | return samsung_s3c2410_pll_enable(hw, 5, true); | ||
808 | } | ||
809 | |||
810 | static void samsung_s3c2410_mpll_disable(struct clk_hw *hw) | ||
811 | { | ||
812 | samsung_s3c2410_pll_enable(hw, 5, false); | ||
813 | } | ||
814 | |||
815 | static int samsung_s3c2410_upll_enable(struct clk_hw *hw) | ||
816 | { | ||
817 | return samsung_s3c2410_pll_enable(hw, 7, true); | ||
818 | } | ||
819 | |||
820 | static void samsung_s3c2410_upll_disable(struct clk_hw *hw) | ||
821 | { | ||
822 | samsung_s3c2410_pll_enable(hw, 7, false); | ||
823 | } | ||
824 | |||
825 | static 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 | |||
831 | static 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 | |||
837 | static 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 | |||
843 | static 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 | |||
851 | static 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 | |||
859 | static 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 | ||
713 | static 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 | |||
966 | static 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 | |||
984 | static 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 | |||
994 | static 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 | |||
1042 | static 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 | |||
1048 | static 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 | |||
1071 | static 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 | |||
1093 | static 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 | |||
1137 | static 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 | |||
1143 | static const struct clk_ops samsung_pll2650xx_clk_min_ops = { | ||
1144 | .recalc_rate = samsung_pll2650xx_recalc_rate, | ||
1145 | }; | ||
1146 | |||
1147 | static 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 | ||
818 | void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, | 1290 | void __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 | ||
15 | enum samsung_pll_type { | 15 | enum 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 | |||
29 | enum supported_socs { | ||
30 | S3C2410, | ||
31 | S3C2412, | ||
32 | S3C2440, | ||
33 | S3C2443, | ||
34 | }; | ||
35 | |||
36 | struct 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 | |||
49 | struct 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 | |||
57 | static 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 | |||
73 | static 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 | |||
84 | const 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 | |||
90 | struct 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 | |||
122 | struct 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 | |||
138 | static const char *dclk_s3c2410_p[] = { "pclk", "uclk" }; | ||
139 | static const char *clkout0_s3c2410_p[] = { "mpll", "upll", "fclk", "hclk", "pclk", | ||
140 | "gate_dclk0" }; | ||
141 | static const char *clkout1_s3c2410_p[] = { "mpll", "upll", "fclk", "hclk", "pclk", | ||
142 | "gate_dclk1" }; | ||
143 | |||
144 | static const char *clkout0_s3c2412_p[] = { "mpll", "upll", "rtc_clkout", | ||
145 | "hclk", "pclk", "gate_dclk0" }; | ||
146 | static const char *clkout1_s3c2412_p[] = { "xti", "upll", "fclk", "hclk", "pclk", | ||
147 | "gate_dclk1" }; | ||
148 | |||
149 | static const char *clkout0_s3c2440_p[] = { "xti", "upll", "fclk", "hclk", "pclk", | ||
150 | "gate_dclk0" }; | ||
151 | static const char *clkout1_s3c2440_p[] = { "mpll", "upll", "rtc_clkout", | ||
152 | "hclk", "pclk", "gate_dclk1" }; | ||
153 | |||
154 | static const char *dclk_s3c2443_p[] = { "pclk", "epll" }; | ||
155 | static const char *clkout0_s3c2443_p[] = { "xti", "epll", "armclk", "hclk", "pclk", | ||
156 | "gate_dclk0" }; | ||
157 | static 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 | |||
166 | static 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 | |||
187 | static 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 | |||
200 | static 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 | ||
214 | static 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 | |||
223 | static 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 | |||
233 | static SIMPLE_DEV_PM_OPS(s3c24xx_dclk_pm_ops, | ||
234 | s3c24xx_dclk_suspend, s3c24xx_dclk_resume); | ||
235 | |||
236 | static 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 | |||
344 | err_dclk_notify: | ||
345 | clk_notifier_unregister(clk_table[DIV_DCLK0], | ||
346 | &s3c24xx_dclk->dclk0_div_change_nb); | ||
347 | err_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 | |||
355 | static 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 | |||
372 | static 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 | |||
407 | static 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 | |||
424 | MODULE_DEVICE_TABLE(platform, s3c24xx_dclk_driver_ids); | ||
425 | |||
426 | static 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 | }; | ||
436 | module_platform_driver(s3c24xx_dclk_driver); | ||
437 | |||
438 | MODULE_LICENSE("GPL v2"); | ||
439 | MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); | ||
440 | MODULE_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 */ | ||
32 | enum supported_socs { | ||
33 | S3C2410, | ||
34 | S3C2440, | ||
35 | S3C2442, | ||
36 | }; | ||
37 | |||
38 | /* list of PLLs to be registered */ | ||
39 | enum s3c2410_plls { | ||
40 | mpll, upll, | ||
41 | }; | ||
42 | |||
43 | static void __iomem *reg_base; | ||
44 | |||
45 | #ifdef CONFIG_PM_SLEEP | ||
46 | static 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 | */ | ||
52 | static unsigned long s3c2410_clk_regs[] __initdata = { | ||
53 | LOCKTIME, | ||
54 | MPLLCON, | ||
55 | UPLLCON, | ||
56 | CLKCON, | ||
57 | CLKSLOW, | ||
58 | CLKDIVN, | ||
59 | CAMDIVN, | ||
60 | }; | ||
61 | |||
62 | static 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 | |||
70 | static void s3c2410_clk_resume(void) | ||
71 | { | ||
72 | samsung_clk_restore(reg_base, s3c2410_save, | ||
73 | ARRAY_SIZE(s3c2410_clk_regs)); | ||
74 | } | ||
75 | |||
76 | static struct syscore_ops s3c2410_clk_syscore_ops = { | ||
77 | .suspend = s3c2410_clk_suspend, | ||
78 | .resume = s3c2410_clk_resume, | ||
79 | }; | ||
80 | |||
81 | static 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 | ||
95 | static void s3c2410_clk_sleep_init(void) {} | ||
96 | #endif | ||
97 | |||
98 | PNAME(fclk_p) = { "mpll", "div_slow" }; | ||
99 | |||
100 | struct samsung_mux_clock s3c2410_common_muxes[] __initdata = { | ||
101 | MUX(FCLK, "fclk", fclk_p, CLKSLOW, 4, 1), | ||
102 | }; | ||
103 | |||
104 | static 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 | |||
116 | struct 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 | |||
121 | struct 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 */ | ||
140 | struct 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 | |||
159 | static 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 | |||
193 | static 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 | |||
200 | struct samsung_div_clock s3c2410_dividers[] __initdata = { | ||
201 | DIV(HCLK, "hclk", "mpll", CLKDIVN, 1, 1), | ||
202 | }; | ||
203 | |||
204 | struct 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 | |||
215 | struct 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 | |||
227 | static 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 | |||
259 | static 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 | |||
266 | PNAME(hclk_p) = { "fclk", "div_hclk_2", "div_hclk_4", "div_hclk_3" }; | ||
267 | PNAME(armclk_p) = { "fclk", "hclk" }; | ||
268 | |||
269 | struct 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 | |||
274 | struct 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 | |||
279 | static struct clk_div_table div_hclk_4_d[] = { | ||
280 | { .val = 0, .div = 4 }, | ||
281 | { .val = 1, .div = 8 }, | ||
282 | { /* sentinel */ }, | ||
283 | }; | ||
284 | |||
285 | static struct clk_div_table div_hclk_3_d[] = { | ||
286 | { .val = 0, .div = 3 }, | ||
287 | { .val = 1, .div = 6 }, | ||
288 | { /* sentinel */ }, | ||
289 | }; | ||
290 | |||
291 | struct 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 | |||
299 | struct samsung_gate_clock s3c244x_common_gates[] __initdata = { | ||
300 | GATE(HCLK_CAM, "cam", "hclk", CLKCON, 19, 0, 0), | ||
301 | }; | ||
302 | |||
303 | struct 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 | |||
316 | PNAME(s3c2440_camif_p) = { "upll", "ff_cam" }; | ||
317 | |||
318 | struct samsung_mux_clock s3c2440_muxes[] __initdata = { | ||
319 | MUX(CAMIF, "camif", s3c2440_camif_p, CAMDIVN, 4, 1), | ||
320 | }; | ||
321 | |||
322 | struct samsung_gate_clock s3c2440_gates[] __initdata = { | ||
323 | GATE(PCLK_AC97, "ac97", "pclk", CLKCON, 20, 0, 0), | ||
324 | }; | ||
325 | |||
326 | /* S3C2442 specific clocks */ | ||
327 | |||
328 | struct samsung_fixed_factor_clock s3c2442_ffactor[] __initdata = { | ||
329 | FFACTOR(0, "upll_3", "upll", 1, 3, 0), | ||
330 | }; | ||
331 | |||
332 | PNAME(s3c2442_camif_p) = { "upll", "ff_cam", "upll", "upll_3" }; | ||
333 | |||
334 | struct 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 | ||
343 | struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = { | ||
344 | FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0), | ||
345 | }; | ||
346 | |||
347 | static 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 | |||
360 | void __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 | |||
466 | static void __init s3c2410_clk_init(struct device_node *np) | ||
467 | { | ||
468 | s3c2410_common_clk_init(np, 0, S3C2410, 0); | ||
469 | } | ||
470 | CLK_OF_DECLARE(s3c2410_clk, "samsung,s3c2410-clock", s3c2410_clk_init); | ||
471 | |||
472 | static void __init s3c2440_clk_init(struct device_node *np) | ||
473 | { | ||
474 | s3c2410_common_clk_init(np, 0, S3C2440, 0); | ||
475 | } | ||
476 | CLK_OF_DECLARE(s3c2440_clk, "samsung,s3c2440-clock", s3c2440_clk_init); | ||
477 | |||
478 | static void __init s3c2442_clk_init(struct device_node *np) | ||
479 | { | ||
480 | s3c2410_common_clk_init(np, 0, S3C2442, 0); | ||
481 | } | ||
482 | CLK_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 */ | ||
31 | enum s3c2412_plls { | ||
32 | mpll, upll, | ||
33 | }; | ||
34 | |||
35 | static void __iomem *reg_base; | ||
36 | |||
37 | #ifdef CONFIG_PM_SLEEP | ||
38 | static 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 | */ | ||
44 | static unsigned long s3c2412_clk_regs[] __initdata = { | ||
45 | LOCKTIME, | ||
46 | MPLLCON, | ||
47 | UPLLCON, | ||
48 | CLKCON, | ||
49 | CLKDIVN, | ||
50 | CLKSRC, | ||
51 | }; | ||
52 | |||
53 | static 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 | |||
61 | static void s3c2412_clk_resume(void) | ||
62 | { | ||
63 | samsung_clk_restore(reg_base, s3c2412_save, | ||
64 | ARRAY_SIZE(s3c2412_clk_regs)); | ||
65 | } | ||
66 | |||
67 | static struct syscore_ops s3c2412_clk_syscore_ops = { | ||
68 | .suspend = s3c2412_clk_suspend, | ||
69 | .resume = s3c2412_clk_resume, | ||
70 | }; | ||
71 | |||
72 | static 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 | ||
86 | static void s3c2412_clk_sleep_init(void) {} | ||
87 | #endif | ||
88 | |||
89 | static 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 | |||
101 | struct 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 | |||
113 | struct 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 | */ | ||
121 | PNAME(erefclk_p) = { "xti", "xti", "xti", "ext" }; | ||
122 | PNAME(urefclk_p) = { "xti", "xti", "xti", "ext" }; | ||
123 | |||
124 | PNAME(camclk_p) = { "usysclk", "hclk" }; | ||
125 | PNAME(usbclk_p) = { "usysclk", "hclk" }; | ||
126 | PNAME(i2sclk_p) = { "erefclk", "mpll" }; | ||
127 | PNAME(uartclk_p) = { "erefclk", "mpll" }; | ||
128 | PNAME(usysclk_p) = { "urefclk", "upll" }; | ||
129 | PNAME(msysclk_p) = { "mdivclk", "mpll" }; | ||
130 | PNAME(mdivclk_p) = { "xti", "div_xti" }; | ||
131 | PNAME(armclk_p) = { "armdiv", "hclk" }; | ||
132 | |||
133 | struct 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 | |||
146 | static 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 | |||
153 | struct 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 | |||
184 | struct 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 | ||
212 | struct 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 | |||
217 | static 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 | |||
232 | void __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 | |||
270 | static void __init s3c2412_clk_init(struct device_node *np) | ||
271 | { | ||
272 | s3c2412_common_clk_init(np, 0, 0, 0); | ||
273 | } | ||
274 | CLK_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 */ | ||
38 | enum supported_socs { | ||
39 | S3C2416, | ||
40 | S3C2443, | ||
41 | S3C2450, | ||
42 | }; | ||
43 | |||
44 | /* list of PLLs to be registered */ | ||
45 | enum s3c2443_plls { | ||
46 | mpll, epll, | ||
47 | }; | ||
48 | |||
49 | static void __iomem *reg_base; | ||
50 | |||
51 | #ifdef CONFIG_PM_SLEEP | ||
52 | static 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 | */ | ||
58 | static 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 | |||
73 | static 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 | |||
81 | static void s3c2443_clk_resume(void) | ||
82 | { | ||
83 | samsung_clk_restore(reg_base, s3c2443_save, | ||
84 | ARRAY_SIZE(s3c2443_clk_regs)); | ||
85 | } | ||
86 | |||
87 | static struct syscore_ops s3c2443_clk_syscore_ops = { | ||
88 | .suspend = s3c2443_clk_suspend, | ||
89 | .resume = s3c2443_clk_resume, | ||
90 | }; | ||
91 | |||
92 | static 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 | ||
106 | static void s3c2443_clk_sleep_init(void) {} | ||
107 | #endif | ||
108 | |||
109 | PNAME(epllref_p) = { "mpllref", "mpllref", "xti", "ext" }; | ||
110 | PNAME(esysclk_p) = { "epllref", "epll" }; | ||
111 | PNAME(mpllref_p) = { "xti", "mdivclk" }; | ||
112 | PNAME(msysclk_p) = { "mpllref", "mpll" }; | ||
113 | PNAME(armclk_p) = { "armdiv" , "hclk" }; | ||
114 | PNAME(i2s0_p) = { "div_i2s0", "ext_i2s", "epllref", "epllref" }; | ||
115 | |||
116 | struct 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 | |||
125 | static 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 | |||
132 | static 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 | |||
144 | struct 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 | |||
157 | struct 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 | |||
191 | struct 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 | |||
223 | static 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 | |||
230 | PNAME(s3c2416_hsmmc0_p) = { "sclk_hsmmc0", "sclk_hsmmcext" }; | ||
231 | PNAME(s3c2416_hsmmc1_p) = { "sclk_hsmmc1", "sclk_hsmmcext" }; | ||
232 | PNAME(s3c2416_hsspi0_p) = { "hsspi0_epll", "hsspi0_mpll" }; | ||
233 | |||
234 | static 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 | |||
244 | struct 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 | |||
250 | struct 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 | |||
256 | struct 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 | |||
266 | struct 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 | |||
277 | static 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 | |||
284 | static 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 | |||
296 | struct 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 | |||
301 | struct 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 | |||
310 | struct 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 | |||
322 | PNAME(s3c2450_cam_p) = { "div_cam", "hclk" }; | ||
323 | PNAME(s3c2450_hsspi1_p) = { "hsspi1_epll", "hsspi1_mpll" }; | ||
324 | PNAME(i2s1_p) = { "div_i2s1", "ext_i2s", "epllref", "epllref" }; | ||
325 | |||
326 | struct 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 | |||
333 | struct 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 | |||
339 | struct 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 | |||
350 | struct 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 | */ | ||
361 | struct 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 | |||
368 | static 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 | |||
376 | void __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 | |||
450 | static void __init s3c2416_clk_init(struct device_node *np) | ||
451 | { | ||
452 | s3c2443_common_clk_init(np, 0, S3C2416, 0); | ||
453 | } | ||
454 | CLK_OF_DECLARE(s3c2416_clk, "samsung,s3c2416-clock", s3c2416_clk_init); | ||
455 | |||
456 | static void __init s3c2443_clk_init(struct device_node *np) | ||
457 | { | ||
458 | s3c2443_common_clk_init(np, 0, S3C2443, 0); | ||
459 | } | ||
460 | CLK_OF_DECLARE(s3c2443_clk, "samsung,s3c2443-clock", s3c2443_clk_init); | ||
461 | |||
462 | static void __init s3c2450_clk_init(struct device_node *np) | ||
463 | { | ||
464 | s3c2443_common_clk_init(np, 0, S3C2450, 0); | ||
465 | } | ||
466 | CLK_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 | ||
445 | static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f, | 445 | static 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 | ||
17 | static DEFINE_SPINLOCK(lock); | ||
18 | static struct clk **clk_table; | ||
19 | static void __iomem *reg_base; | ||
20 | #ifdef CONFIG_OF | ||
21 | static struct clk_onecell_data clk_data; | ||
22 | #endif | ||
23 | |||
24 | void samsung_clk_save(void __iomem *base, | 17 | void 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 */ |
58 | void __init samsung_clk_init(struct device_node *np, void __iomem *base, | 51 | struct 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 */ |
78 | void samsung_clk_add_lookup(struct clk *clk, unsigned int id) | 87 | void 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 */ |
85 | void __init samsung_clk_register_alias(struct samsung_clock_alias *list, | 95 | void __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 */ |
118 | void __init samsung_clk_register_fixed_rate( | 129 | void __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 */ |
147 | void __init samsung_clk_register_fixed_factor( | 158 | void __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 */ |
167 | void __init samsung_clk_register_mux(struct samsung_mux_clock *list, | 178 | void __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 */ |
197 | void __init samsung_clk_register_div(struct samsung_div_clock *list, | 210 | void __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 */ |
235 | void __init samsung_clk_register_gate(struct samsung_gate_clock *list, | 249 | void __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 |
269 | void __init samsung_clk_of_register_fixed_ext( | 284 | void __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 | */ | ||
30 | struct 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 | ||
315 | extern void __init samsung_clk_init(struct device_node *np, void __iomem *base, | 327 | extern 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); | ||
317 | extern void __init samsung_clk_of_register_fixed_ext( | 330 | extern 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 | ||
322 | extern void samsung_clk_add_lookup(struct clk *clk, unsigned int id); | 336 | extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, |
337 | struct clk *clk, unsigned int id); | ||
323 | 338 | ||
324 | extern void samsung_clk_register_alias(struct samsung_clock_alias *list, | 339 | extern 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); | ||
326 | extern void __init samsung_clk_register_fixed_rate( | 342 | extern 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); | ||
328 | extern void __init samsung_clk_register_fixed_factor( | 346 | extern void __init samsung_clk_register_fixed_factor( |
329 | struct samsung_fixed_factor_clock *list, unsigned int nr_clk); | 347 | struct samsung_clk_provider *ctx, |
330 | extern 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); |
332 | extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list, | 350 | extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx, |
333 | unsigned int nr_clk); | 351 | struct samsung_mux_clock *clk_list, |
334 | extern void __init samsung_clk_register_gate( | 352 | unsigned int nr_clk); |
335 | struct samsung_gate_clock *clk_list, unsigned int nr_clk); | 353 | extern void __init samsung_clk_register_div(struct samsung_clk_provider *ctx, |
336 | extern 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); |
356 | extern void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, | ||
357 | struct samsung_gate_clock *clk_list, | ||
358 | unsigned int nr_clk); | ||
359 | extern 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 | ||
339 | extern unsigned long _get_rate(const char *clk_name); | 363 | extern unsigned long _get_rate(const char *clk_name); |
340 | 364 | ||
341 | extern void samsung_clk_save(void __iomem *base, | 365 | extern 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); |
344 | extern void samsung_clk_restore(void __iomem *base, | 368 | extern 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); |
347 | extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( | 371 | extern 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 @@ | |||
1 | obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o | 1 | obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o |
2 | obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o | 2 | obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o |
3 | obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o | ||
4 | obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o | ||
3 | obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o | 5 | obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o |
4 | obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o | 6 | obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o |
5 | obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o | 7 | obj-$(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 | ||
118 | static const struct clk_ops cpg_mstp_clock_ops = { | 118 | static 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 | |||
20 | struct 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 | |||
34 | struct div4_clk { | ||
35 | const char *name; | ||
36 | unsigned int reg; | ||
37 | unsigned int shift; | ||
38 | int flags; | ||
39 | }; | ||
40 | |||
41 | static 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 | |||
56 | static 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 | |||
62 | static u32 cpg_mode __initdata; | ||
63 | |||
64 | static struct clk * __init | ||
65 | r8a7740_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 | |||
147 | static 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 | } | ||
198 | CLK_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 | |||
26 | struct 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 | |||
57 | struct 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 | |||
66 | static 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 | |||
85 | static const unsigned int cpg_plla_mult[4] __initconst = { 42, 48, 56, 64 }; | ||
86 | |||
87 | /* ----------------------------------------------------------------------------- | ||
88 | * Initialization | ||
89 | */ | ||
90 | |||
91 | static u32 cpg_mode __initdata; | ||
92 | |||
93 | static struct clk * __init | ||
94 | r8a7779_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 | |||
123 | static 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 | } | ||
172 | CLK_OF_DECLARE(r8a7779_cpg_clks, "renesas,r8a7779-cpg-clocks", | ||
173 | r8a7779_cpg_clocks_init); | ||
174 | |||
175 | void __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", ®); | 65 | of_property_read_u32(node, "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 | ||
31 | extern void __iomem *clk_mgr_base_addr; | 32 | extern 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 | ||
660 | static void __init clkgengpu_c32_pll_setup(struct device_node *np) | 661 | static 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 | ||
80 | static 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 | |||
80 | static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, | 115 | static 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 | ||
115 | const struct clk_ops clk_factors_ops = { | 150 | const 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 | |||
513 | void 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 | } | ||
543 | EXPORT_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 | ||
1313 | static void __init sunxi_init_clocks(void) | 1349 | static 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 | ||
1333 | out: | 1364 | out: |
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[] = { | |||
329 | static const char *mux_clkm_48M_pllp_480M[] = { | 329 | static 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 | 332 | static u32 mux_clkm_48M_pllp_480M_idx[] = { |
333 | [0] = 0, [1] = 2, [2] = 4, [3] = 6, | ||
334 | }; | ||
333 | 335 | ||
334 | static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = { | 336 | static 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 | ||
343 | static const char *mux_ss_60M[] = { | ||
344 | "xusb_ss_div2", "pll_u_60M" | ||
345 | }; | ||
346 | #define mux_ss_60M_idx NULL | ||
347 | |||
341 | static const char *mux_d_audio_clk[] = { | 348 | static 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 | } |
224 | CLK_OF_DECLARE(ti_gate_clk, "ti,gate-clock", of_ti_gate_clk_setup) | 224 | CLK_OF_DECLARE(ti_gate_clk, "ti,gate-clock", of_ti_gate_clk_setup); |
225 | 225 | ||
226 | static void __init of_ti_wait_gate_clk_setup(struct device_node *node) | 226 | static 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 @@ | |||
1 | config 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 | |||
10 | config 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 | |||
18 | config 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 | |||
3 | obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o | 3 | obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o |
4 | obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o | 4 | obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o |
5 | obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o | 5 | obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o |
6 | obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o clk-sp810.o | 6 | obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o |
7 | obj-$(CONFIG_VEXPRESS_CONFIG) += clk-vexpress-osc.o | 7 | obj-$(CONFIG_CLK_SP810) += clk-sp810.o |
8 | obj-$(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 | } |
164 | EXPORT_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 | ||
22 | struct impd1_clk { | 22 | struct 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 | } |
156 | EXPORT_SYMBOL_GPL(integrator_impd1_clk_init); | ||
136 | 157 | ||
137 | void integrator_impd1_clk_exit(unsigned int id) | 158 | void 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 | } |
181 | EXPORT_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 | ||
24 | struct vexpress_osc { | 22 | struct 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 | ||
66 | static struct clk_ops vexpress_osc_ops = { | 64 | static struct clk_ops vexpress_osc_ops = { |
@@ -70,58 +68,31 @@ static struct clk_ops vexpress_osc_ops = { | |||
70 | }; | 68 | }; |
71 | 69 | ||
72 | 70 | ||
73 | struct clk * __init vexpress_osc_setup(struct device *dev) | 71 | static 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 | |||
96 | void __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); | 120 | static struct of_device_id vexpress_osc_of_match[] = { |
121 | { .compatible = "arm,vexpress-osc", }, | ||
122 | {} | ||
123 | }; | ||
141 | 124 | ||
142 | return; | 125 | static 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 | ||
144 | error: | 133 | static 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 | } |
149 | CLK_OF_DECLARE(vexpress_soc, "arm,vexpress-osc", vexpress_osc_of_setup); | 137 | core_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 | |||
56 | enum zynq_clk { | 59 | enum 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, |