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
);
This page took 0.037326 seconds and 5 git commands to generate.