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)
345 EXPORT_SYMBOL(clk_get_rate);
347 int clk_set_rate(struct clk *clk, unsigned long rate)
351 EXPORT_SYMBOL_GPL(clk_set_rate);
353 long clk_round_rate(struct clk *clk, unsigned long rate)
357 EXPORT_SYMBOL_GPL(clk_round_rate);
359 struct clk *clk_get(struct device *dev, const char *id)
361 if (!strcmp(id, "enet0"))
363 if (!strcmp(id, "enet1"))
365 if (!strcmp(id, "enetsw"))
367 if (!strcmp(id, "ephy"))
369 if (!strcmp(id, "usbh"))
371 if (!strcmp(id, "usbd"))
373 if (!strcmp(id, "spi"))
375 if (!strcmp(id, "hsspi"))
377 if (!strcmp(id, "xtm"))
379 if (!strcmp(id, "periph"))
381 if ((BCMCPU_IS_3368() || BCMCPU_IS_6358()) && !strcmp(id, "pcm"))
383 if ((BCMCPU_IS_6362() || BCMCPU_IS_6368()) && !strcmp(id, "ipsec"))
385 if ((BCMCPU_IS_6328() || BCMCPU_IS_6362()) && !strcmp(id, "pcie"))
387 return ERR_PTR(-ENOENT);
390 EXPORT_SYMBOL(clk_get);
392 void clk_put(struct clk *clk)
396 EXPORT_SYMBOL(clk_put);
398 #define HSSPI_PLL_HZ_6328 133333333
399 #define HSSPI_PLL_HZ_6362 400000000
401 static int __init bcm63xx_clk_init(void)
403 switch (bcm63xx_get_cpu_id()) {
405 clk_hsspi.rate = HSSPI_PLL_HZ_6328;
408 clk_hsspi.rate = HSSPI_PLL_HZ_6362;
414 arch_initcall(bcm63xx_clk_init);