]> asedeno.scripts.mit.edu Git - linux.git/blob - arch/mips/bcm63xx/clk.c
MIPS: BCM63XX: provide periph clock as refclk for uart
[linux.git] / arch / mips / bcm63xx / clk.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
7  */
8
9 #include <linux/init.h>
10 #include <linux/export.h>
11 #include <linux/mutex.h>
12 #include <linux/err.h>
13 #include <linux/clk.h>
14 #include <linux/clkdev.h>
15 #include <linux/delay.h>
16 #include <bcm63xx_cpu.h>
17 #include <bcm63xx_io.h>
18 #include <bcm63xx_regs.h>
19 #include <bcm63xx_reset.h>
20
21 struct clk {
22         void            (*set)(struct clk *, int);
23         unsigned int    rate;
24         unsigned int    usage;
25         int             id;
26 };
27
28 static DEFINE_MUTEX(clocks_mutex);
29
30
31 static void clk_enable_unlocked(struct clk *clk)
32 {
33         if (clk->set && (clk->usage++) == 0)
34                 clk->set(clk, 1);
35 }
36
37 static void clk_disable_unlocked(struct clk *clk)
38 {
39         if (clk->set && (--clk->usage) == 0)
40                 clk->set(clk, 0);
41 }
42
43 static void bcm_hwclock_set(u32 mask, int enable)
44 {
45         u32 reg;
46
47         reg = bcm_perf_readl(PERF_CKCTL_REG);
48         if (enable)
49                 reg |= mask;
50         else
51                 reg &= ~mask;
52         bcm_perf_writel(reg, PERF_CKCTL_REG);
53 }
54
55 /*
56  * Ethernet MAC "misc" clock: dma clocks and main clock on 6348
57  */
58 static void enet_misc_set(struct clk *clk, int enable)
59 {
60         u32 mask;
61
62         if (BCMCPU_IS_6338())
63                 mask = CKCTL_6338_ENET_EN;
64         else if (BCMCPU_IS_6345())
65                 mask = CKCTL_6345_ENET_EN;
66         else if (BCMCPU_IS_6348())
67                 mask = CKCTL_6348_ENET_EN;
68         else
69                 /* BCMCPU_IS_6358 */
70                 mask = CKCTL_6358_EMUSB_EN;
71         bcm_hwclock_set(mask, enable);
72 }
73
74 static struct clk clk_enet_misc = {
75         .set    = enet_misc_set,
76 };
77
78 /*
79  * Ethernet MAC clocks: only revelant on 6358, silently enable misc
80  * clocks
81  */
82 static void enetx_set(struct clk *clk, int enable)
83 {
84         if (enable)
85                 clk_enable_unlocked(&clk_enet_misc);
86         else
87                 clk_disable_unlocked(&clk_enet_misc);
88
89         if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) {
90                 u32 mask;
91
92                 if (clk->id == 0)
93                         mask = CKCTL_6358_ENET0_EN;
94                 else
95                         mask = CKCTL_6358_ENET1_EN;
96                 bcm_hwclock_set(mask, enable);
97         }
98 }
99
100 static struct clk clk_enet0 = {
101         .id     = 0,
102         .set    = enetx_set,
103 };
104
105 static struct clk clk_enet1 = {
106         .id     = 1,
107         .set    = enetx_set,
108 };
109
110 /*
111  * Ethernet PHY clock
112  */
113 static void ephy_set(struct clk *clk, int enable)
114 {
115         if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
116                 bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable);
117 }
118
119
120 static struct clk clk_ephy = {
121         .set    = ephy_set,
122 };
123
124 /*
125  * Ethernet switch clock
126  */
127 static void enetsw_set(struct clk *clk, int enable)
128 {
129         if (BCMCPU_IS_6328())
130                 bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable);
131         else if (BCMCPU_IS_6362())
132                 bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable);
133         else if (BCMCPU_IS_6368())
134                 bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
135                                 CKCTL_6368_SWPKT_USB_EN |
136                                 CKCTL_6368_SWPKT_SAR_EN,
137                                 enable);
138         else
139                 return;
140
141         if (enable) {
142                 /* reset switch core afer clock change */
143                 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
144                 msleep(10);
145                 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
146                 msleep(10);
147         }
148 }
149
150 static struct clk clk_enetsw = {
151         .set    = enetsw_set,
152 };
153
154 /*
155  * PCM clock
156  */
157 static void pcm_set(struct clk *clk, int enable)
158 {
159         if (BCMCPU_IS_3368())
160                 bcm_hwclock_set(CKCTL_3368_PCM_EN, enable);
161         if (BCMCPU_IS_6358())
162                 bcm_hwclock_set(CKCTL_6358_PCM_EN, enable);
163 }
164
165 static struct clk clk_pcm = {
166         .set    = pcm_set,
167 };
168
169 /*
170  * USB host clock
171  */
172 static void usbh_set(struct clk *clk, int enable)
173 {
174         if (BCMCPU_IS_6328())
175                 bcm_hwclock_set(CKCTL_6328_USBH_EN, enable);
176         else if (BCMCPU_IS_6348())
177                 bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
178         else if (BCMCPU_IS_6362())
179                 bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
180         else if (BCMCPU_IS_6368())
181                 bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
182 }
183
184 static struct clk clk_usbh = {
185         .set    = usbh_set,
186 };
187
188 /*
189  * USB device clock
190  */
191 static void usbd_set(struct clk *clk, int enable)
192 {
193         if (BCMCPU_IS_6328())
194                 bcm_hwclock_set(CKCTL_6328_USBD_EN, enable);
195         else if (BCMCPU_IS_6362())
196                 bcm_hwclock_set(CKCTL_6362_USBD_EN, enable);
197         else if (BCMCPU_IS_6368())
198                 bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
199 }
200
201 static struct clk clk_usbd = {
202         .set    = usbd_set,
203 };
204
205 /*
206  * SPI clock
207  */
208 static void spi_set(struct clk *clk, int enable)
209 {
210         u32 mask;
211
212         if (BCMCPU_IS_6338())
213                 mask = CKCTL_6338_SPI_EN;
214         else if (BCMCPU_IS_6348())
215                 mask = CKCTL_6348_SPI_EN;
216         else if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
217                 mask = CKCTL_6358_SPI_EN;
218         else if (BCMCPU_IS_6362())
219                 mask = CKCTL_6362_SPI_EN;
220         else
221                 /* BCMCPU_IS_6368 */
222                 mask = CKCTL_6368_SPI_EN;
223         bcm_hwclock_set(mask, enable);
224 }
225
226 static struct clk clk_spi = {
227         .set    = spi_set,
228 };
229
230 /*
231  * HSSPI clock
232  */
233 static void hsspi_set(struct clk *clk, int enable)
234 {
235         u32 mask;
236
237         if (BCMCPU_IS_6328())
238                 mask = CKCTL_6328_HSSPI_EN;
239         else if (BCMCPU_IS_6362())
240                 mask = CKCTL_6362_HSSPI_EN;
241         else
242                 return;
243
244         bcm_hwclock_set(mask, enable);
245 }
246
247 static struct clk clk_hsspi = {
248         .set    = hsspi_set,
249 };
250
251
252 /*
253  * XTM clock
254  */
255 static void xtm_set(struct clk *clk, int enable)
256 {
257         if (!BCMCPU_IS_6368())
258                 return;
259
260         bcm_hwclock_set(CKCTL_6368_SAR_EN |
261                         CKCTL_6368_SWPKT_SAR_EN, enable);
262
263         if (enable) {
264                 /* reset sar core afer clock change */
265                 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
266                 mdelay(1);
267                 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
268                 mdelay(1);
269         }
270 }
271
272
273 static struct clk clk_xtm = {
274         .set    = xtm_set,
275 };
276
277 /*
278  * IPsec clock
279  */
280 static void ipsec_set(struct clk *clk, int enable)
281 {
282         if (BCMCPU_IS_6362())
283                 bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable);
284         else if (BCMCPU_IS_6368())
285                 bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
286 }
287
288 static struct clk clk_ipsec = {
289         .set    = ipsec_set,
290 };
291
292 /*
293  * PCIe clock
294  */
295
296 static void pcie_set(struct clk *clk, int enable)
297 {
298         if (BCMCPU_IS_6328())
299                 bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
300         else if (BCMCPU_IS_6362())
301                 bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
302 }
303
304 static struct clk clk_pcie = {
305         .set    = pcie_set,
306 };
307
308 /*
309  * Internal peripheral clock
310  */
311 static struct clk clk_periph = {
312         .rate   = (50 * 1000 * 1000),
313 };
314
315
316 /*
317  * Linux clock API implementation
318  */
319 int clk_enable(struct clk *clk)
320 {
321         mutex_lock(&clocks_mutex);
322         clk_enable_unlocked(clk);
323         mutex_unlock(&clocks_mutex);
324         return 0;
325 }
326
327 EXPORT_SYMBOL(clk_enable);
328
329 void clk_disable(struct clk *clk)
330 {
331         if (!clk)
332                 return;
333
334         mutex_lock(&clocks_mutex);
335         clk_disable_unlocked(clk);
336         mutex_unlock(&clocks_mutex);
337 }
338
339 EXPORT_SYMBOL(clk_disable);
340
341 unsigned long clk_get_rate(struct clk *clk)
342 {
343         if (!clk)
344                 return 0;
345
346         return clk->rate;
347 }
348
349 EXPORT_SYMBOL(clk_get_rate);
350
351 int clk_set_rate(struct clk *clk, unsigned long rate)
352 {
353         return 0;
354 }
355 EXPORT_SYMBOL_GPL(clk_set_rate);
356
357 long clk_round_rate(struct clk *clk, unsigned long rate)
358 {
359         return 0;
360 }
361 EXPORT_SYMBOL_GPL(clk_round_rate);
362
363 static struct clk_lookup bcm3368_clks[] = {
364         /* fixed rate clocks */
365         CLKDEV_INIT(NULL, "periph", &clk_periph),
366         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
367         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
368         /* gated clocks */
369         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
370         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
371         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
372         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
373         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
374         CLKDEV_INIT(NULL, "spi", &clk_spi),
375         CLKDEV_INIT(NULL, "pcm", &clk_pcm),
376 };
377
378 static struct clk_lookup bcm6328_clks[] = {
379         /* fixed rate clocks */
380         CLKDEV_INIT(NULL, "periph", &clk_periph),
381         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
382         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
383         /* gated clocks */
384         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
385         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
386         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
387         CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
388         CLKDEV_INIT(NULL, "pcie", &clk_pcie),
389 };
390
391 static struct clk_lookup bcm6338_clks[] = {
392         /* fixed rate clocks */
393         CLKDEV_INIT(NULL, "periph", &clk_periph),
394         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
395         /* gated clocks */
396         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
397         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
398         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
399         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
400         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
401         CLKDEV_INIT(NULL, "spi", &clk_spi),
402 };
403
404 static struct clk_lookup bcm6345_clks[] = {
405         /* fixed rate clocks */
406         CLKDEV_INIT(NULL, "periph", &clk_periph),
407         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
408         /* gated clocks */
409         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
410         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
411         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
412         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
413         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
414         CLKDEV_INIT(NULL, "spi", &clk_spi),
415 };
416
417 static struct clk_lookup bcm6348_clks[] = {
418         /* fixed rate clocks */
419         CLKDEV_INIT(NULL, "periph", &clk_periph),
420         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
421         /* gated clocks */
422         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
423         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
424         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
425         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
426         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
427         CLKDEV_INIT(NULL, "spi", &clk_spi),
428 };
429
430 static struct clk_lookup bcm6358_clks[] = {
431         /* fixed rate clocks */
432         CLKDEV_INIT(NULL, "periph", &clk_periph),
433         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
434         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
435         /* gated clocks */
436         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
437         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
438         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
439         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
440         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
441         CLKDEV_INIT(NULL, "spi", &clk_spi),
442         CLKDEV_INIT(NULL, "pcm", &clk_pcm),
443 };
444
445 static struct clk_lookup bcm6362_clks[] = {
446         /* fixed rate clocks */
447         CLKDEV_INIT(NULL, "periph", &clk_periph),
448         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
449         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
450         /* gated clocks */
451         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
452         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
453         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
454         CLKDEV_INIT(NULL, "spi", &clk_spi),
455         CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
456         CLKDEV_INIT(NULL, "pcie", &clk_pcie),
457         CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
458 };
459
460 static struct clk_lookup bcm6368_clks[] = {
461         /* fixed rate clocks */
462         CLKDEV_INIT(NULL, "periph", &clk_periph),
463         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
464         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
465         /* gated clocks */
466         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
467         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
468         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
469         CLKDEV_INIT(NULL, "spi", &clk_spi),
470         CLKDEV_INIT(NULL, "xtm", &clk_xtm),
471         CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
472 };
473
474 #define HSSPI_PLL_HZ_6328       133333333
475 #define HSSPI_PLL_HZ_6362       400000000
476
477 static int __init bcm63xx_clk_init(void)
478 {
479         switch (bcm63xx_get_cpu_id()) {
480         case BCM3368_CPU_ID:
481                 clkdev_add_table(bcm3368_clks, ARRAY_SIZE(bcm3368_clks));
482                 break;
483         case BCM6328_CPU_ID:
484                 clk_hsspi.rate = HSSPI_PLL_HZ_6328;
485                 clkdev_add_table(bcm6328_clks, ARRAY_SIZE(bcm6328_clks));
486                 break;
487         case BCM6338_CPU_ID:
488                 clkdev_add_table(bcm6338_clks, ARRAY_SIZE(bcm6338_clks));
489                 break;
490         case BCM6345_CPU_ID:
491                 clkdev_add_table(bcm6345_clks, ARRAY_SIZE(bcm6345_clks));
492                 break;
493         case BCM6348_CPU_ID:
494                 clkdev_add_table(bcm6348_clks, ARRAY_SIZE(bcm6348_clks));
495                 break;
496         case BCM6358_CPU_ID:
497                 clkdev_add_table(bcm6358_clks, ARRAY_SIZE(bcm6358_clks));
498                 break;
499         case BCM6362_CPU_ID:
500                 clk_hsspi.rate = HSSPI_PLL_HZ_6362;
501                 clkdev_add_table(bcm6362_clks, ARRAY_SIZE(bcm6362_clks));
502                 break;
503         case BCM6368_CPU_ID:
504                 clkdev_add_table(bcm6368_clks, ARRAY_SIZE(bcm6368_clks));
505                 break;
506         }
507
508         return 0;
509 }
510 arch_initcall(bcm63xx_clk_init);