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/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/delay.h>
15 #include <bcm63xx_cpu.h>
16 #include <bcm63xx_io.h>
17 #include <bcm63xx_regs.h>
18 #include <bcm63xx_reset.h>
21 void (*set)(struct clk *, int);
27 static DEFINE_MUTEX(clocks_mutex);
30 static void clk_enable_unlocked(struct clk *clk)
32 if (clk->set && (clk->usage++) == 0)
36 static void clk_disable_unlocked(struct clk *clk)
38 if (clk->set && (--clk->usage) == 0)
42 static void bcm_hwclock_set(u32 mask, int enable)
46 reg = bcm_perf_readl(PERF_CKCTL_REG);
51 bcm_perf_writel(reg, PERF_CKCTL_REG);
55 * Ethernet MAC "misc" clock: dma clocks and main clock on 6348
57 static void enet_misc_set(struct clk *clk, int enable)
62 mask = CKCTL_6338_ENET_EN;
63 else if (BCMCPU_IS_6345())
64 mask = CKCTL_6345_ENET_EN;
65 else if (BCMCPU_IS_6348())
66 mask = CKCTL_6348_ENET_EN;
69 mask = CKCTL_6358_EMUSB_EN;
70 bcm_hwclock_set(mask, enable);
73 static struct clk clk_enet_misc = {
78 * Ethernet MAC clocks: only revelant on 6358, silently enable misc
81 static void enetx_set(struct clk *clk, int enable)
84 clk_enable_unlocked(&clk_enet_misc);
86 clk_disable_unlocked(&clk_enet_misc);
88 if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) {
92 mask = CKCTL_6358_ENET0_EN;
94 mask = CKCTL_6358_ENET1_EN;
95 bcm_hwclock_set(mask, enable);
99 static struct clk clk_enet0 = {
104 static struct clk clk_enet1 = {
112 static void ephy_set(struct clk *clk, int enable)
114 if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
115 bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable);
119 static struct clk clk_ephy = {
124 * Ethernet switch clock
126 static void enetsw_set(struct clk *clk, int enable)
128 if (BCMCPU_IS_6328())
129 bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable);
130 else if (BCMCPU_IS_6362())
131 bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable);
132 else if (BCMCPU_IS_6368())
133 bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
134 CKCTL_6368_SWPKT_USB_EN |
135 CKCTL_6368_SWPKT_SAR_EN,
141 /* reset switch core afer clock change */
142 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
144 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
149 static struct clk clk_enetsw = {
156 static void pcm_set(struct clk *clk, int enable)
158 if (BCMCPU_IS_3368())
159 bcm_hwclock_set(CKCTL_3368_PCM_EN, enable);
160 if (BCMCPU_IS_6358())
161 bcm_hwclock_set(CKCTL_6358_PCM_EN, enable);
164 static struct clk clk_pcm = {
171 static void usbh_set(struct clk *clk, int enable)
173 if (BCMCPU_IS_6328())
174 bcm_hwclock_set(CKCTL_6328_USBH_EN, enable);
175 else if (BCMCPU_IS_6348())
176 bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
177 else if (BCMCPU_IS_6362())
178 bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
179 else if (BCMCPU_IS_6368())
180 bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
183 static struct clk clk_usbh = {
190 static void usbd_set(struct clk *clk, int enable)
192 if (BCMCPU_IS_6328())
193 bcm_hwclock_set(CKCTL_6328_USBD_EN, enable);
194 else if (BCMCPU_IS_6362())
195 bcm_hwclock_set(CKCTL_6362_USBD_EN, enable);
196 else if (BCMCPU_IS_6368())
197 bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
200 static struct clk clk_usbd = {
207 static void spi_set(struct clk *clk, int enable)
211 if (BCMCPU_IS_6338())
212 mask = CKCTL_6338_SPI_EN;
213 else if (BCMCPU_IS_6348())
214 mask = CKCTL_6348_SPI_EN;
215 else if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
216 mask = CKCTL_6358_SPI_EN;
217 else if (BCMCPU_IS_6362())
218 mask = CKCTL_6362_SPI_EN;
221 mask = CKCTL_6368_SPI_EN;
222 bcm_hwclock_set(mask, enable);
225 static struct clk clk_spi = {
232 static void hsspi_set(struct clk *clk, int enable)
236 if (BCMCPU_IS_6328())
237 mask = CKCTL_6328_HSSPI_EN;
238 else if (BCMCPU_IS_6362())
239 mask = CKCTL_6362_HSSPI_EN;
243 bcm_hwclock_set(mask, enable);
246 static struct clk clk_hsspi = {
254 static void xtm_set(struct clk *clk, int enable)
256 if (!BCMCPU_IS_6368())
259 bcm_hwclock_set(CKCTL_6368_SAR_EN |
260 CKCTL_6368_SWPKT_SAR_EN, enable);
263 /* reset sar core afer clock change */
264 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
266 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
272 static struct clk clk_xtm = {
279 static void ipsec_set(struct clk *clk, int enable)
281 if (BCMCPU_IS_6362())
282 bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable);
283 else if (BCMCPU_IS_6368())
284 bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
287 static struct clk clk_ipsec = {
295 static void pcie_set(struct clk *clk, int enable)
297 if (BCMCPU_IS_6328())
298 bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
299 else if (BCMCPU_IS_6362())
300 bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
303 static struct clk clk_pcie = {
308 * Internal peripheral clock
310 static struct clk clk_periph = {
311 .rate = (50 * 1000 * 1000),
316 * Linux clock API implementation
318 int clk_enable(struct clk *clk)
322 mutex_lock(&clocks_mutex);
323 clk_enable_unlocked(clk);
324 mutex_unlock(&clocks_mutex);
328 EXPORT_SYMBOL(clk_enable);
330 void clk_disable(struct clk *clk)
335 mutex_lock(&clocks_mutex);
336 clk_disable_unlocked(clk);
337 mutex_unlock(&clocks_mutex);
340 EXPORT_SYMBOL(clk_disable);
342 struct clk *clk_get_parent(struct clk *clk)
346 EXPORT_SYMBOL(clk_get_parent);
348 int clk_set_parent(struct clk *clk, struct clk *parent)
352 EXPORT_SYMBOL(clk_set_parent);
354 unsigned long clk_get_rate(struct clk *clk)
362 EXPORT_SYMBOL(clk_get_rate);
364 int clk_set_rate(struct clk *clk, unsigned long rate)
368 EXPORT_SYMBOL_GPL(clk_set_rate);
370 long clk_round_rate(struct clk *clk, unsigned long rate)
374 EXPORT_SYMBOL_GPL(clk_round_rate);
376 struct clk *clk_get(struct device *dev, const char *id)
378 if (!strcmp(id, "enet0"))
380 if (!strcmp(id, "enet1"))
382 if (!strcmp(id, "enetsw"))
384 if (!strcmp(id, "ephy"))
386 if (!strcmp(id, "usbh"))
388 if (!strcmp(id, "usbd"))
390 if (!strcmp(id, "spi"))
392 if (!strcmp(id, "hsspi"))
394 if (!strcmp(id, "xtm"))
396 if (!strcmp(id, "periph"))
398 if ((BCMCPU_IS_3368() || BCMCPU_IS_6358()) && !strcmp(id, "pcm"))
400 if ((BCMCPU_IS_6362() || BCMCPU_IS_6368()) && !strcmp(id, "ipsec"))
402 if ((BCMCPU_IS_6328() || BCMCPU_IS_6362()) && !strcmp(id, "pcie"))
404 return ERR_PTR(-ENOENT);
407 EXPORT_SYMBOL(clk_get);
409 void clk_put(struct clk *clk)
413 EXPORT_SYMBOL(clk_put);
415 #define HSSPI_PLL_HZ_6328 133333333
416 #define HSSPI_PLL_HZ_6362 400000000
418 static int __init bcm63xx_clk_init(void)
420 switch (bcm63xx_get_cpu_id()) {
422 clk_hsspi.rate = HSSPI_PLL_HZ_6328;
425 clk_hsspi.rate = HSSPI_PLL_HZ_6362;
431 arch_initcall(bcm63xx_clk_init);