]> asedeno.scripts.mit.edu Git - linux.git/blob - arch/mips/bcm63xx/clk.c
MIPS: BCM63XX: add clkdev lookup support
[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         /* gated clocks */
367         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
368         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
369         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
370         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
371         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
372         CLKDEV_INIT(NULL, "spi", &clk_spi),
373         CLKDEV_INIT(NULL, "pcm", &clk_pcm),
374 };
375
376 static struct clk_lookup bcm6328_clks[] = {
377         /* fixed rate clocks */
378         CLKDEV_INIT(NULL, "periph", &clk_periph),
379         /* gated clocks */
380         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
381         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
382         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
383         CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
384         CLKDEV_INIT(NULL, "pcie", &clk_pcie),
385 };
386
387 static struct clk_lookup bcm6338_clks[] = {
388         /* fixed rate clocks */
389         CLKDEV_INIT(NULL, "periph", &clk_periph),
390         /* gated clocks */
391         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
392         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
393         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
394         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
395         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
396         CLKDEV_INIT(NULL, "spi", &clk_spi),
397 };
398
399 static struct clk_lookup bcm6345_clks[] = {
400         /* fixed rate clocks */
401         CLKDEV_INIT(NULL, "periph", &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 };
410
411 static struct clk_lookup bcm6348_clks[] = {
412         /* fixed rate clocks */
413         CLKDEV_INIT(NULL, "periph", &clk_periph),
414         /* gated clocks */
415         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
416         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
417         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
418         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
419         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
420         CLKDEV_INIT(NULL, "spi", &clk_spi),
421 };
422
423 static struct clk_lookup bcm6358_clks[] = {
424         /* fixed rate clocks */
425         CLKDEV_INIT(NULL, "periph", &clk_periph),
426         /* gated clocks */
427         CLKDEV_INIT(NULL, "enet0", &clk_enet0),
428         CLKDEV_INIT(NULL, "enet1", &clk_enet1),
429         CLKDEV_INIT(NULL, "ephy", &clk_ephy),
430         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
431         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
432         CLKDEV_INIT(NULL, "spi", &clk_spi),
433         CLKDEV_INIT(NULL, "pcm", &clk_pcm),
434 };
435
436 static struct clk_lookup bcm6362_clks[] = {
437         /* fixed rate clocks */
438         CLKDEV_INIT(NULL, "periph", &clk_periph),
439         /* gated clocks */
440         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
441         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
442         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
443         CLKDEV_INIT(NULL, "spi", &clk_spi),
444         CLKDEV_INIT(NULL, "hsspi", &clk_hsspi),
445         CLKDEV_INIT(NULL, "pcie", &clk_pcie),
446         CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
447 };
448
449 static struct clk_lookup bcm6368_clks[] = {
450         /* fixed rate clocks */
451         CLKDEV_INIT(NULL, "periph", &clk_periph),
452         /* gated clocks */
453         CLKDEV_INIT(NULL, "enetsw", &clk_enetsw),
454         CLKDEV_INIT(NULL, "usbh", &clk_usbh),
455         CLKDEV_INIT(NULL, "usbd", &clk_usbd),
456         CLKDEV_INIT(NULL, "spi", &clk_spi),
457         CLKDEV_INIT(NULL, "xtm", &clk_xtm),
458         CLKDEV_INIT(NULL, "ipsec", &clk_ipsec),
459 };
460
461 #define HSSPI_PLL_HZ_6328       133333333
462 #define HSSPI_PLL_HZ_6362       400000000
463
464 static int __init bcm63xx_clk_init(void)
465 {
466         switch (bcm63xx_get_cpu_id()) {
467         case BCM3368_CPU_ID:
468                 clkdev_add_table(bcm3368_clks, ARRAY_SIZE(bcm3368_clks));
469                 break;
470         case BCM6328_CPU_ID:
471                 clk_hsspi.rate = HSSPI_PLL_HZ_6328;
472                 clkdev_add_table(bcm6328_clks, ARRAY_SIZE(bcm6328_clks));
473                 break;
474         case BCM6338_CPU_ID:
475                 clkdev_add_table(bcm6338_clks, ARRAY_SIZE(bcm6338_clks));
476                 break;
477         case BCM6345_CPU_ID:
478                 clkdev_add_table(bcm6345_clks, ARRAY_SIZE(bcm6345_clks));
479                 break;
480         case BCM6348_CPU_ID:
481                 clkdev_add_table(bcm6348_clks, ARRAY_SIZE(bcm6348_clks));
482                 break;
483         case BCM6358_CPU_ID:
484                 clkdev_add_table(bcm6358_clks, ARRAY_SIZE(bcm6358_clks));
485                 break;
486         case BCM6362_CPU_ID:
487                 clk_hsspi.rate = HSSPI_PLL_HZ_6362;
488                 clkdev_add_table(bcm6362_clks, ARRAY_SIZE(bcm6362_clks));
489                 break;
490         case BCM6368_CPU_ID:
491                 clkdev_add_table(bcm6368_clks, ARRAY_SIZE(bcm6368_clks));
492                 break;
493         }
494
495         return 0;
496 }
497 arch_initcall(bcm63xx_clk_init);