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>
18 #include <bcm63xx_clk.h>
20 static DEFINE_MUTEX(clocks_mutex);
23 static void clk_enable_unlocked(struct clk *clk)
25 if (clk->set && (clk->usage++) == 0)
29 static void clk_disable_unlocked(struct clk *clk)
31 if (clk->set && (--clk->usage) == 0)
35 static void bcm_hwclock_set(u32 mask, int enable)
39 reg = bcm_perf_readl(PERF_CKCTL_REG);
44 bcm_perf_writel(reg, PERF_CKCTL_REG);
48 * Ethernet MAC "misc" clock: dma clocks and main clock on 6348
50 static void enet_misc_set(struct clk *clk, int enable)
55 mask = CKCTL_6338_ENET_EN;
56 else if (BCMCPU_IS_6345())
57 mask = CKCTL_6345_ENET_EN;
58 else if (BCMCPU_IS_6348())
59 mask = CKCTL_6348_ENET_EN;
62 mask = CKCTL_6358_EMUSB_EN;
63 bcm_hwclock_set(mask, enable);
66 static struct clk clk_enet_misc = {
71 * Ethernet MAC clocks: only revelant on 6358, silently enable misc
74 static void enetx_set(struct clk *clk, int enable)
77 clk_enable_unlocked(&clk_enet_misc);
79 clk_disable_unlocked(&clk_enet_misc);
81 if (BCMCPU_IS_6358()) {
85 mask = CKCTL_6358_ENET0_EN;
87 mask = CKCTL_6358_ENET1_EN;
88 bcm_hwclock_set(mask, enable);
92 static struct clk clk_enet0 = {
97 static struct clk clk_enet1 = {
105 static void ephy_set(struct clk *clk, int enable)
107 if (!BCMCPU_IS_6358())
109 bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable);
113 static struct clk clk_ephy = {
118 * Ethernet switch clock
120 static void enetsw_set(struct clk *clk, int enable)
122 if (!BCMCPU_IS_6368())
124 bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
125 CKCTL_6368_SWPKT_USB_EN |
126 CKCTL_6368_SWPKT_SAR_EN, enable);
128 /* reset switch core afer clock change */
129 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
131 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
136 static struct clk clk_enetsw = {
143 static void pcm_set(struct clk *clk, int enable)
145 if (!BCMCPU_IS_6358())
147 bcm_hwclock_set(CKCTL_6358_PCM_EN, enable);
150 static struct clk clk_pcm = {
157 static void usbh_set(struct clk *clk, int enable)
159 if (BCMCPU_IS_6328())
160 bcm_hwclock_set(CKCTL_6328_USBH_EN, enable);
161 else if (BCMCPU_IS_6348())
162 bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
163 else if (BCMCPU_IS_6368())
164 bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
167 static struct clk clk_usbh = {
174 static void usbd_set(struct clk *clk, int enable)
176 if (BCMCPU_IS_6328())
177 bcm_hwclock_set(CKCTL_6328_USBD_EN, enable);
178 else if (BCMCPU_IS_6368())
179 bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
182 static struct clk clk_usbd = {
189 static void spi_set(struct clk *clk, int enable)
193 if (BCMCPU_IS_6338())
194 mask = CKCTL_6338_SPI_EN;
195 else if (BCMCPU_IS_6348())
196 mask = CKCTL_6348_SPI_EN;
197 else if (BCMCPU_IS_6358())
198 mask = CKCTL_6358_SPI_EN;
201 mask = CKCTL_6368_SPI_EN;
202 bcm_hwclock_set(mask, enable);
205 static struct clk clk_spi = {
212 static void xtm_set(struct clk *clk, int enable)
214 if (!BCMCPU_IS_6368())
217 bcm_hwclock_set(CKCTL_6368_SAR_EN |
218 CKCTL_6368_SWPKT_SAR_EN, enable);
221 /* reset sar core afer clock change */
222 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
224 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
230 static struct clk clk_xtm = {
237 static void ipsec_set(struct clk *clk, int enable)
239 bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
242 static struct clk clk_ipsec = {
250 static void pcie_set(struct clk *clk, int enable)
252 bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
255 static struct clk clk_pcie = {
260 * Internal peripheral clock
262 static struct clk clk_periph = {
263 .rate = (50 * 1000 * 1000),
268 * Linux clock API implementation
270 int clk_enable(struct clk *clk)
272 mutex_lock(&clocks_mutex);
273 clk_enable_unlocked(clk);
274 mutex_unlock(&clocks_mutex);
278 EXPORT_SYMBOL(clk_enable);
280 void clk_disable(struct clk *clk)
282 mutex_lock(&clocks_mutex);
283 clk_disable_unlocked(clk);
284 mutex_unlock(&clocks_mutex);
287 EXPORT_SYMBOL(clk_disable);
289 unsigned long clk_get_rate(struct clk *clk)
294 EXPORT_SYMBOL(clk_get_rate);
296 struct clk *clk_get(struct device *dev, const char *id)
298 if (!strcmp(id, "enet0"))
300 if (!strcmp(id, "enet1"))
302 if (!strcmp(id, "enetsw"))
304 if (!strcmp(id, "ephy"))
306 if (!strcmp(id, "usbh"))
308 if (!strcmp(id, "usbd"))
310 if (!strcmp(id, "spi"))
312 if (!strcmp(id, "xtm"))
314 if (!strcmp(id, "periph"))
316 if (BCMCPU_IS_6358() && !strcmp(id, "pcm"))
318 if (BCMCPU_IS_6368() && !strcmp(id, "ipsec"))
320 if (BCMCPU_IS_6328() && !strcmp(id, "pcie"))
322 return ERR_PTR(-ENOENT);
325 EXPORT_SYMBOL(clk_get);
327 void clk_put(struct clk *clk)
331 EXPORT_SYMBOL(clk_put);