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_CLK_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_CLK_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;
186 mask = CKCTL_6358_SPI_EN;
187 bcm_hwclock_set(mask, enable);
190 static struct clk clk_spi = {
197 static void xtm_set(struct clk *clk, int enable)
199 if (!BCMCPU_IS_6368())
202 bcm_hwclock_set(CKCTL_6368_SAR_CLK_EN |
203 CKCTL_6368_SWPKT_SAR_EN, enable);
208 /* reset sar core afer clock change */
209 val = bcm_perf_readl(PERF_SOFTRESET_6368_REG);
210 val &= ~SOFTRESET_6368_SAR_MASK;
211 bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
213 val |= SOFTRESET_6368_SAR_MASK;
214 bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
220 static struct clk clk_xtm = {
225 * Internal peripheral clock
227 static struct clk clk_periph = {
228 .rate = (50 * 1000 * 1000),
233 * Linux clock API implementation
235 int clk_enable(struct clk *clk)
237 mutex_lock(&clocks_mutex);
238 clk_enable_unlocked(clk);
239 mutex_unlock(&clocks_mutex);
243 EXPORT_SYMBOL(clk_enable);
245 void clk_disable(struct clk *clk)
247 mutex_lock(&clocks_mutex);
248 clk_disable_unlocked(clk);
249 mutex_unlock(&clocks_mutex);
252 EXPORT_SYMBOL(clk_disable);
254 unsigned long clk_get_rate(struct clk *clk)
259 EXPORT_SYMBOL(clk_get_rate);
261 struct clk *clk_get(struct device *dev, const char *id)
263 if (!strcmp(id, "enet0"))
265 if (!strcmp(id, "enet1"))
267 if (!strcmp(id, "enetsw"))
269 if (!strcmp(id, "ephy"))
271 if (!strcmp(id, "usbh"))
273 if (!strcmp(id, "spi"))
275 if (!strcmp(id, "xtm"))
277 if (!strcmp(id, "periph"))
279 if (BCMCPU_IS_6358() && !strcmp(id, "pcm"))
281 return ERR_PTR(-ENOENT);
284 EXPORT_SYMBOL(clk_get);
286 void clk_put(struct clk *clk)
290 EXPORT_SYMBOL(clk_put);