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_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_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_6368())
130 bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
131 CKCTL_6368_SWPKT_USB_EN |
132 CKCTL_6368_SWPKT_SAR_EN, enable);
134 /* reset switch core afer clock change */
135 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
137 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
142 static struct clk clk_enetsw = {
149 static void pcm_set(struct clk *clk, int enable)
151 if (!BCMCPU_IS_6358())
153 bcm_hwclock_set(CKCTL_6358_PCM_EN, enable);
156 static struct clk clk_pcm = {
163 static void usbh_set(struct clk *clk, int enable)
165 if (BCMCPU_IS_6328())
166 bcm_hwclock_set(CKCTL_6328_USBH_EN, enable);
167 else if (BCMCPU_IS_6348())
168 bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
169 else if (BCMCPU_IS_6368())
170 bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
173 static struct clk clk_usbh = {
180 static void usbd_set(struct clk *clk, int enable)
182 if (BCMCPU_IS_6328())
183 bcm_hwclock_set(CKCTL_6328_USBD_EN, enable);
184 else if (BCMCPU_IS_6368())
185 bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
188 static struct clk clk_usbd = {
195 static void spi_set(struct clk *clk, int enable)
199 if (BCMCPU_IS_6338())
200 mask = CKCTL_6338_SPI_EN;
201 else if (BCMCPU_IS_6348())
202 mask = CKCTL_6348_SPI_EN;
203 else if (BCMCPU_IS_6358())
204 mask = CKCTL_6358_SPI_EN;
205 else if (BCMCPU_IS_6362())
206 mask = CKCTL_6362_SPI_EN;
209 mask = CKCTL_6368_SPI_EN;
210 bcm_hwclock_set(mask, enable);
213 static struct clk clk_spi = {
220 static void xtm_set(struct clk *clk, int enable)
222 if (!BCMCPU_IS_6368())
225 bcm_hwclock_set(CKCTL_6368_SAR_EN |
226 CKCTL_6368_SWPKT_SAR_EN, enable);
229 /* reset sar core afer clock change */
230 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
232 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
238 static struct clk clk_xtm = {
245 static void ipsec_set(struct clk *clk, int enable)
247 bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
250 static struct clk clk_ipsec = {
258 static void pcie_set(struct clk *clk, int enable)
260 bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
263 static struct clk clk_pcie = {
268 * Internal peripheral clock
270 static struct clk clk_periph = {
271 .rate = (50 * 1000 * 1000),
276 * Linux clock API implementation
278 int clk_enable(struct clk *clk)
280 mutex_lock(&clocks_mutex);
281 clk_enable_unlocked(clk);
282 mutex_unlock(&clocks_mutex);
286 EXPORT_SYMBOL(clk_enable);
288 void clk_disable(struct clk *clk)
290 mutex_lock(&clocks_mutex);
291 clk_disable_unlocked(clk);
292 mutex_unlock(&clocks_mutex);
295 EXPORT_SYMBOL(clk_disable);
297 unsigned long clk_get_rate(struct clk *clk)
302 EXPORT_SYMBOL(clk_get_rate);
304 struct clk *clk_get(struct device *dev, const char *id)
306 if (!strcmp(id, "enet0"))
308 if (!strcmp(id, "enet1"))
310 if (!strcmp(id, "enetsw"))
312 if (!strcmp(id, "ephy"))
314 if (!strcmp(id, "usbh"))
316 if (!strcmp(id, "usbd"))
318 if (!strcmp(id, "spi"))
320 if (!strcmp(id, "xtm"))
322 if (!strcmp(id, "periph"))
324 if (BCMCPU_IS_6358() && !strcmp(id, "pcm"))
326 if (BCMCPU_IS_6368() && !strcmp(id, "ipsec"))
328 if (BCMCPU_IS_6328() && !strcmp(id, "pcie"))
330 return ERR_PTR(-ENOENT);
333 EXPORT_SYMBOL(clk_get);
335 void clk_put(struct clk *clk)
339 EXPORT_SYMBOL(clk_put);