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_clk.h>
19 static DEFINE_MUTEX(clocks_mutex);
22 static void clk_enable_unlocked(struct clk *clk)
24 if (clk->set && (clk->usage++) == 0)
28 static void clk_disable_unlocked(struct clk *clk)
30 if (clk->set && (--clk->usage) == 0)
34 static void bcm_hwclock_set(u32 mask, int enable)
38 reg = bcm_perf_readl(PERF_CKCTL_REG);
43 bcm_perf_writel(reg, PERF_CKCTL_REG);
47 * Ethernet MAC "misc" clock: dma clocks and main clock on 6348
49 static void enet_misc_set(struct clk *clk, int enable)
54 mask = CKCTL_6338_ENET_EN;
55 else if (BCMCPU_IS_6345())
56 mask = CKCTL_6345_ENET_EN;
57 else if (BCMCPU_IS_6348())
58 mask = CKCTL_6348_ENET_EN;
61 mask = CKCTL_6358_EMUSB_EN;
62 bcm_hwclock_set(mask, enable);
65 static struct clk clk_enet_misc = {
70 * Ethernet MAC clocks: only revelant on 6358, silently enable misc
73 static void enetx_set(struct clk *clk, int enable)
76 clk_enable_unlocked(&clk_enet_misc);
78 clk_disable_unlocked(&clk_enet_misc);
80 if (BCMCPU_IS_6358()) {
84 mask = CKCTL_6358_ENET0_EN;
86 mask = CKCTL_6358_ENET1_EN;
87 bcm_hwclock_set(mask, enable);
91 static struct clk clk_enet0 = {
96 static struct clk clk_enet1 = {
104 static void ephy_set(struct clk *clk, int enable)
106 if (!BCMCPU_IS_6358())
108 bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable);
112 static struct clk clk_ephy = {
117 * Ethernet switch clock
119 static void enetsw_set(struct clk *clk, int enable)
121 if (!BCMCPU_IS_6368())
123 bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
124 CKCTL_6368_SWPKT_USB_EN |
125 CKCTL_6368_SWPKT_SAR_EN, enable);
129 /* reset switch core afer clock change */
130 val = bcm_perf_readl(PERF_SOFTRESET_6368_REG);
131 val &= ~SOFTRESET_6368_ENETSW_MASK;
132 bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
134 val |= SOFTRESET_6368_ENETSW_MASK;
135 bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
140 static struct clk clk_enetsw = {
147 static void pcm_set(struct clk *clk, int enable)
149 if (!BCMCPU_IS_6358())
151 bcm_hwclock_set(CKCTL_6358_PCM_EN, enable);
154 static struct clk clk_pcm = {
161 static void usbh_set(struct clk *clk, int enable)
163 if (BCMCPU_IS_6348())
164 bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
165 else if (BCMCPU_IS_6368())
166 bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
169 static struct clk clk_usbh = {
176 static void spi_set(struct clk *clk, int enable)
180 if (BCMCPU_IS_6338())
181 mask = CKCTL_6338_SPI_EN;
182 else if (BCMCPU_IS_6348())
183 mask = CKCTL_6348_SPI_EN;
184 else if (BCMCPU_IS_6358())
185 mask = CKCTL_6358_SPI_EN;
188 mask = CKCTL_6368_SPI_EN;
189 bcm_hwclock_set(mask, enable);
192 static struct clk clk_spi = {
199 static void xtm_set(struct clk *clk, int enable)
201 if (!BCMCPU_IS_6368())
204 bcm_hwclock_set(CKCTL_6368_SAR_EN |
205 CKCTL_6368_SWPKT_SAR_EN, enable);
210 /* reset sar core afer clock change */
211 val = bcm_perf_readl(PERF_SOFTRESET_6368_REG);
212 val &= ~SOFTRESET_6368_SAR_MASK;
213 bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
215 val |= SOFTRESET_6368_SAR_MASK;
216 bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
222 static struct clk clk_xtm = {
229 static void ipsec_set(struct clk *clk, int enable)
231 bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
234 static struct clk clk_ipsec = {
239 * Internal peripheral clock
241 static struct clk clk_periph = {
242 .rate = (50 * 1000 * 1000),
247 * Linux clock API implementation
249 int clk_enable(struct clk *clk)
251 mutex_lock(&clocks_mutex);
252 clk_enable_unlocked(clk);
253 mutex_unlock(&clocks_mutex);
257 EXPORT_SYMBOL(clk_enable);
259 void clk_disable(struct clk *clk)
261 mutex_lock(&clocks_mutex);
262 clk_disable_unlocked(clk);
263 mutex_unlock(&clocks_mutex);
266 EXPORT_SYMBOL(clk_disable);
268 unsigned long clk_get_rate(struct clk *clk)
273 EXPORT_SYMBOL(clk_get_rate);
275 struct clk *clk_get(struct device *dev, const char *id)
277 if (!strcmp(id, "enet0"))
279 if (!strcmp(id, "enet1"))
281 if (!strcmp(id, "enetsw"))
283 if (!strcmp(id, "ephy"))
285 if (!strcmp(id, "usbh"))
287 if (!strcmp(id, "spi"))
289 if (!strcmp(id, "xtm"))
291 if (!strcmp(id, "periph"))
293 if (BCMCPU_IS_6358() && !strcmp(id, "pcm"))
295 if (BCMCPU_IS_6368() && !strcmp(id, "ipsec"))
297 return ERR_PTR(-ENOENT);
300 EXPORT_SYMBOL(clk_get);
302 void clk_put(struct clk *clk)
306 EXPORT_SYMBOL(clk_put);