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
6 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
9 #include <linux/module.h>
10 #include <linux/mutex.h>
11 #include <linux/err.h>
12 #include <linux/clk.h>
13 #include <linux/delay.h>
14 #include <bcm63xx_cpu.h>
15 #include <bcm63xx_io.h>
16 #include <bcm63xx_regs.h>
17 #include <bcm63xx_reset.h>
20 void (*set)(struct clk *, int);
26 static DEFINE_MUTEX(clocks_mutex);
29 static void clk_enable_unlocked(struct clk *clk)
31 if (clk->set && (clk->usage++) == 0)
35 static void clk_disable_unlocked(struct clk *clk)
37 if (clk->set && (--clk->usage) == 0)
41 static void bcm_hwclock_set(u32 mask, int enable)
45 reg = bcm_perf_readl(PERF_CKCTL_REG);
50 bcm_perf_writel(reg, PERF_CKCTL_REG);
54 * Ethernet MAC "misc" clock: dma clocks and main clock on 6348
56 static void enet_misc_set(struct clk *clk, int enable)
61 mask = CKCTL_6338_ENET_EN;
62 else if (BCMCPU_IS_6345())
63 mask = CKCTL_6345_ENET_EN;
64 else if (BCMCPU_IS_6348())
65 mask = CKCTL_6348_ENET_EN;
68 mask = CKCTL_6358_EMUSB_EN;
69 bcm_hwclock_set(mask, enable);
72 static struct clk clk_enet_misc = {
77 * Ethernet MAC clocks: only revelant on 6358, silently enable misc
80 static void enetx_set(struct clk *clk, int enable)
83 clk_enable_unlocked(&clk_enet_misc);
85 clk_disable_unlocked(&clk_enet_misc);
87 if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) {
91 mask = CKCTL_6358_ENET0_EN;
93 mask = CKCTL_6358_ENET1_EN;
94 bcm_hwclock_set(mask, enable);
98 static struct clk clk_enet0 = {
103 static struct clk clk_enet1 = {
111 static void ephy_set(struct clk *clk, int enable)
113 if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
114 bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable);
118 static struct clk clk_ephy = {
123 * Ethernet switch clock
125 static void enetsw_set(struct clk *clk, int enable)
127 if (BCMCPU_IS_6328())
128 bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable);
129 else if (BCMCPU_IS_6362())
130 bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable);
131 else if (BCMCPU_IS_6368())
132 bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
133 CKCTL_6368_SWPKT_USB_EN |
134 CKCTL_6368_SWPKT_SAR_EN,
140 /* reset switch core afer clock change */
141 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
143 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
148 static struct clk clk_enetsw = {
155 static void pcm_set(struct clk *clk, int enable)
157 if (BCMCPU_IS_3368())
158 bcm_hwclock_set(CKCTL_3368_PCM_EN, enable);
159 if (BCMCPU_IS_6358())
160 bcm_hwclock_set(CKCTL_6358_PCM_EN, enable);
163 static struct clk clk_pcm = {
170 static void usbh_set(struct clk *clk, int enable)
172 if (BCMCPU_IS_6328())
173 bcm_hwclock_set(CKCTL_6328_USBH_EN, enable);
174 else if (BCMCPU_IS_6348())
175 bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
176 else if (BCMCPU_IS_6362())
177 bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
178 else if (BCMCPU_IS_6368())
179 bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
182 static struct clk clk_usbh = {
189 static void usbd_set(struct clk *clk, int enable)
191 if (BCMCPU_IS_6328())
192 bcm_hwclock_set(CKCTL_6328_USBD_EN, enable);
193 else if (BCMCPU_IS_6362())
194 bcm_hwclock_set(CKCTL_6362_USBD_EN, enable);
195 else if (BCMCPU_IS_6368())
196 bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
199 static struct clk clk_usbd = {
206 static void spi_set(struct clk *clk, int enable)
210 if (BCMCPU_IS_6338())
211 mask = CKCTL_6338_SPI_EN;
212 else if (BCMCPU_IS_6348())
213 mask = CKCTL_6348_SPI_EN;
214 else if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
215 mask = CKCTL_6358_SPI_EN;
216 else if (BCMCPU_IS_6362())
217 mask = CKCTL_6362_SPI_EN;
220 mask = CKCTL_6368_SPI_EN;
221 bcm_hwclock_set(mask, enable);
224 static struct clk clk_spi = {
231 static void hsspi_set(struct clk *clk, int enable)
235 if (BCMCPU_IS_6328())
236 mask = CKCTL_6328_HSSPI_EN;
237 else if (BCMCPU_IS_6362())
238 mask = CKCTL_6362_HSSPI_EN;
242 bcm_hwclock_set(mask, enable);
245 static struct clk clk_hsspi = {
253 static void xtm_set(struct clk *clk, int enable)
255 if (!BCMCPU_IS_6368())
258 bcm_hwclock_set(CKCTL_6368_SAR_EN |
259 CKCTL_6368_SWPKT_SAR_EN, enable);
262 /* reset sar core afer clock change */
263 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
265 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
271 static struct clk clk_xtm = {
278 static void ipsec_set(struct clk *clk, int enable)
280 if (BCMCPU_IS_6362())
281 bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable);
282 else if (BCMCPU_IS_6368())
283 bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
286 static struct clk clk_ipsec = {
294 static void pcie_set(struct clk *clk, int enable)
296 if (BCMCPU_IS_6328())
297 bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
298 else if (BCMCPU_IS_6362())
299 bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
302 static struct clk clk_pcie = {
307 * Internal peripheral clock
309 static struct clk clk_periph = {
310 .rate = (50 * 1000 * 1000),
315 * Linux clock API implementation
317 int clk_enable(struct clk *clk)
319 mutex_lock(&clocks_mutex);
320 clk_enable_unlocked(clk);
321 mutex_unlock(&clocks_mutex);
325 EXPORT_SYMBOL(clk_enable);
327 void clk_disable(struct clk *clk)
329 mutex_lock(&clocks_mutex);
330 clk_disable_unlocked(clk);
331 mutex_unlock(&clocks_mutex);
334 EXPORT_SYMBOL(clk_disable);
336 unsigned long clk_get_rate(struct clk *clk)
341 EXPORT_SYMBOL(clk_get_rate);
343 int clk_set_rate(struct clk *clk, unsigned long rate)
347 EXPORT_SYMBOL_GPL(clk_set_rate);
349 long clk_round_rate(struct clk *clk, unsigned long rate)
353 EXPORT_SYMBOL_GPL(clk_round_rate);
355 struct clk *clk_get(struct device *dev, const char *id)
357 if (!strcmp(id, "enet0"))
359 if (!strcmp(id, "enet1"))
361 if (!strcmp(id, "enetsw"))
363 if (!strcmp(id, "ephy"))
365 if (!strcmp(id, "usbh"))
367 if (!strcmp(id, "usbd"))
369 if (!strcmp(id, "spi"))
371 if (!strcmp(id, "hsspi"))
373 if (!strcmp(id, "xtm"))
375 if (!strcmp(id, "periph"))
377 if ((BCMCPU_IS_3368() || BCMCPU_IS_6358()) && !strcmp(id, "pcm"))
379 if ((BCMCPU_IS_6362() || BCMCPU_IS_6368()) && !strcmp(id, "ipsec"))
381 if ((BCMCPU_IS_6328() || BCMCPU_IS_6362()) && !strcmp(id, "pcie"))
383 return ERR_PTR(-ENOENT);
386 EXPORT_SYMBOL(clk_get);
388 void clk_put(struct clk *clk)
392 EXPORT_SYMBOL(clk_put);
394 #define HSSPI_PLL_HZ_6328 133333333
395 #define HSSPI_PLL_HZ_6362 400000000
397 static int __init bcm63xx_clk_init(void)
399 switch (bcm63xx_get_cpu_id()) {
401 clk_hsspi.rate = HSSPI_PLL_HZ_6328;
404 clk_hsspi.rate = HSSPI_PLL_HZ_6362;
410 arch_initcall(bcm63xx_clk_init);