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)
320 mutex_lock(&clocks_mutex);
321 clk_enable_unlocked(clk);
322 mutex_unlock(&clocks_mutex);
326 EXPORT_SYMBOL(clk_enable);
328 void clk_disable(struct clk *clk)
333 mutex_lock(&clocks_mutex);
334 clk_disable_unlocked(clk);
335 mutex_unlock(&clocks_mutex);
338 EXPORT_SYMBOL(clk_disable);
340 unsigned long clk_get_rate(struct clk *clk)
348 EXPORT_SYMBOL(clk_get_rate);
350 int clk_set_rate(struct clk *clk, unsigned long rate)
354 EXPORT_SYMBOL_GPL(clk_set_rate);
356 long clk_round_rate(struct clk *clk, unsigned long rate)
360 EXPORT_SYMBOL_GPL(clk_round_rate);
362 struct clk *clk_get(struct device *dev, const char *id)
364 if (!strcmp(id, "enet0"))
366 if (!strcmp(id, "enet1"))
368 if (!strcmp(id, "enetsw"))
370 if (!strcmp(id, "ephy"))
372 if (!strcmp(id, "usbh"))
374 if (!strcmp(id, "usbd"))
376 if (!strcmp(id, "spi"))
378 if (!strcmp(id, "hsspi"))
380 if (!strcmp(id, "xtm"))
382 if (!strcmp(id, "periph"))
384 if ((BCMCPU_IS_3368() || BCMCPU_IS_6358()) && !strcmp(id, "pcm"))
386 if ((BCMCPU_IS_6362() || BCMCPU_IS_6368()) && !strcmp(id, "ipsec"))
388 if ((BCMCPU_IS_6328() || BCMCPU_IS_6362()) && !strcmp(id, "pcie"))
390 return ERR_PTR(-ENOENT);
393 EXPORT_SYMBOL(clk_get);
395 void clk_put(struct clk *clk)
399 EXPORT_SYMBOL(clk_put);
401 #define HSSPI_PLL_HZ_6328 133333333
402 #define HSSPI_PLL_HZ_6362 400000000
404 static int __init bcm63xx_clk_init(void)
406 switch (bcm63xx_get_cpu_id()) {
408 clk_hsspi.rate = HSSPI_PLL_HZ_6328;
411 clk_hsspi.rate = HSSPI_PLL_HZ_6362;
417 arch_initcall(bcm63xx_clk_init);