]> asedeno.scripts.mit.edu Git - linux.git/blob - arch/mips/bcm63xx/clk.c
MIPS: BCM63XX: provide enet clocks as "enet" to the ethernet devices
[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  * HSSPI PLL
253  */
254 static struct clk clk_hsspi_pll;
255
256 /*
257  * XTM clock
258  */
259 static void xtm_set(struct clk *clk, int enable)
260 {
261         if (!BCMCPU_IS_6368())
262                 return;
263
264         bcm_hwclock_set(CKCTL_6368_SAR_EN |
265                         CKCTL_6368_SWPKT_SAR_EN, enable);
266
267         if (enable) {
268                 /* reset sar core afer clock change */
269                 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
270                 mdelay(1);
271                 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
272                 mdelay(1);
273         }
274 }
275
276
277 static struct clk clk_xtm = {
278         .set    = xtm_set,
279 };
280
281 /*
282  * IPsec clock
283  */
284 static void ipsec_set(struct clk *clk, int enable)
285 {
286         if (BCMCPU_IS_6362())
287                 bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable);
288         else if (BCMCPU_IS_6368())
289                 bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
290 }
291
292 static struct clk clk_ipsec = {
293         .set    = ipsec_set,
294 };
295
296 /*
297  * PCIe clock
298  */
299
300 static void pcie_set(struct clk *clk, int enable)
301 {
302         if (BCMCPU_IS_6328())
303                 bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
304         else if (BCMCPU_IS_6362())
305                 bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
306 }
307
308 static struct clk clk_pcie = {
309         .set    = pcie_set,
310 };
311
312 /*
313  * Internal peripheral clock
314  */
315 static struct clk clk_periph = {
316         .rate   = (50 * 1000 * 1000),
317 };
318
319
320 /*
321  * Linux clock API implementation
322  */
323 int clk_enable(struct clk *clk)
324 {
325         mutex_lock(&clocks_mutex);
326         clk_enable_unlocked(clk);
327         mutex_unlock(&clocks_mutex);
328         return 0;
329 }
330
331 EXPORT_SYMBOL(clk_enable);
332
333 void clk_disable(struct clk *clk)
334 {
335         if (!clk)
336                 return;
337
338         mutex_lock(&clocks_mutex);
339         clk_disable_unlocked(clk);
340         mutex_unlock(&clocks_mutex);
341 }
342
343 EXPORT_SYMBOL(clk_disable);
344
345 unsigned long clk_get_rate(struct clk *clk)
346 {
347         if (!clk)
348                 return 0;
349
350         return clk->rate;
351 }
352
353 EXPORT_SYMBOL(clk_get_rate);
354
355 int clk_set_rate(struct clk *clk, unsigned long rate)
356 {
357         return 0;
358 }
359 EXPORT_SYMBOL_GPL(clk_set_rate);
360
361 long clk_round_rate(struct clk *clk, unsigned long rate)
362 {
363         return 0;
364 }
365 EXPORT_SYMBOL_GPL(clk_round_rate);
366
367 static struct clk_lookup bcm3368_clks[] = {
368         /* fixed rate clocks */
369         CLKDEV_INIT(NULL, "periph", &clk_periph),
370         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
371         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
372         /* gated clocks */
373         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
374         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
375         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
376         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
377         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
378         CLKDEV_INIT(NULL, "spi", &clk_spi),
379         CLKDEV_INIT(NULL, "pcm", &clk_pcm),
380         CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
381         CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
382 };
383
384 static struct clk_lookup bcm6328_clks[] = {
385         /* fixed rate clocks */
386         CLKDEV_INIT(NULL, "periph", &clk_periph),
387         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
388         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
389         CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
390         /* gated clocks */
391         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
392         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
393         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
394         CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
395         CLKDEV_INIT(NULL, "pcie", &clk_pcie),
396 };
397
398 static struct clk_lookup bcm6338_clks[] = {
399         /* fixed rate clocks */
400         CLKDEV_INIT(NULL, "periph", &clk_periph),
401         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
402         /* gated clocks */
403         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
404         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
405         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
406         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
407         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
408         CLKDEV_INIT(NULL, "spi", &clk_spi),
409         CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
410 };
411
412 static struct clk_lookup bcm6345_clks[] = {
413         /* fixed rate clocks */
414         CLKDEV_INIT(NULL, "periph", &clk_periph),
415         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
416         /* gated clocks */
417         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
418         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
419         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
420         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
421         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
422         CLKDEV_INIT(NULL, "spi", &clk_spi),
423         CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
424 };
425
426 static struct clk_lookup bcm6348_clks[] = {
427         /* fixed rate clocks */
428         CLKDEV_INIT(NULL, "periph", &clk_periph),
429         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
430         /* gated clocks */
431         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
432         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
433         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
434         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
435         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
436         CLKDEV_INIT(NULL, "spi", &clk_spi),
437         CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet_misc),
438         CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet_misc),
439 };
440
441 static struct clk_lookup bcm6358_clks[] = {
442         /* fixed rate clocks */
443         CLKDEV_INIT(NULL, "periph", &clk_periph),
444         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
445         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
446         /* gated clocks */
447         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
448         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
449         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
450         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
451         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
452         CLKDEV_INIT(NULL, "spi", &clk_spi),
453         CLKDEV_INIT(NULL, "pcm", &clk_pcm),
454         CLKDEV_INIT("bcm63xx_enet.0", "enet", &clk_enet0),
455         CLKDEV_INIT("bcm63xx_enet.1", "enet", &clk_enet1),
456 };
457
458 static struct clk_lookup bcm6362_clks[] = {
459         /* fixed rate clocks */
460         CLKDEV_INIT(NULL, "periph", &clk_periph),
461         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
462         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
463         CLKDEV_INIT("bcm63xx-hsspi.0", "pll", &clk_hsspi_pll),
464         /* gated clocks */
465         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
466         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
467         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
468         CLKDEV_INIT(NULL, "spi", &clk_spi),
469         CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
470         CLKDEV_INIT(NULL, "pcie", &clk_pcie),
471         CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
472 };
473
474 static struct clk_lookup bcm6368_clks[] = {
475         /* fixed rate clocks */
476         CLKDEV_INIT(NULL, "periph", &clk_periph),
477         CLKDEV_INIT("bcm63xx_uart.0", "refclk", &clk_periph),
478         CLKDEV_INIT("bcm63xx_uart.1", "refclk", &clk_periph),
479         /* gated clocks */
480         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
481         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
482         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
483         CLKDEV_INIT(NULL, "spi", &clk_spi),
484         CLKDEV_INIT(NULL, "xtm", &clk_xtm),
485         CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
486 };
487
488 #define HSSPI_PLL_HZ_6328       133333333
489 #define HSSPI_PLL_HZ_6362       400000000
490
491 static int __init bcm63xx_clk_init(void)
492 {
493         switch (bcm63xx_get_cpu_id()) {
494         case BCM3368_CPU_ID:
495                 clkdev_add_table(bcm3368_clks, ARRAY_SIZE(bcm3368_clks));
496                 break;
497         case BCM6328_CPU_ID:
498                 clk_hsspi_pll.rate = HSSPI_PLL_HZ_6328;
499                 clkdev_add_table(bcm6328_clks, ARRAY_SIZE(bcm6328_clks));
500                 break;
501         case BCM6338_CPU_ID:
502                 clkdev_add_table(bcm6338_clks, ARRAY_SIZE(bcm6338_clks));
503                 break;
504         case BCM6345_CPU_ID:
505                 clkdev_add_table(bcm6345_clks, ARRAY_SIZE(bcm6345_clks));
506                 break;
507         case BCM6348_CPU_ID:
508                 clkdev_add_table(bcm6348_clks, ARRAY_SIZE(bcm6348_clks));
509                 break;
510         case BCM6358_CPU_ID:
511                 clkdev_add_table(bcm6358_clks, ARRAY_SIZE(bcm6358_clks));
512                 break;
513         case BCM6362_CPU_ID:
514                 clk_hsspi_pll.rate = HSSPI_PLL_HZ_6362;
515                 clkdev_add_table(bcm6362_clks, ARRAY_SIZE(bcm6362_clks));
516                 break;
517         case BCM6368_CPU_ID:
518                 clkdev_add_table(bcm6368_clks, ARRAY_SIZE(bcm6368_clks));
519                 break;
520         }
521
522         return 0;
523 }
524 arch_initcall(bcm63xx_clk_init);