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
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_3368() || 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_3368() || BCMCPU_IS_6358())
114 bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable);
118 static struct clk clk_ephy = {
123 * Ethernet switch clock
125 static void enetsw_set(struct clk *clk, int enable)
127 if (BCMCPU_IS_6328())
128 bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable);
129 else if (BCMCPU_IS_6362())
130 bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable);
131 else if (BCMCPU_IS_6368())
132 bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
133 CKCTL_6368_SWPKT_USB_EN |
134 CKCTL_6368_SWPKT_SAR_EN,
140 /* reset switch core afer clock change */
141 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
143 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
148 static struct clk clk_enetsw = {
155 static void pcm_set(struct clk *clk, int enable)
157 if (BCMCPU_IS_3368())
158 bcm_hwclock_set(CKCTL_3368_PCM_EN, enable);
159 if (BCMCPU_IS_6358())
160 bcm_hwclock_set(CKCTL_6358_PCM_EN, enable);
163 static struct clk clk_pcm = {
170 static void usbh_set(struct clk *clk, int enable)
172 if (BCMCPU_IS_6328())
173 bcm_hwclock_set(CKCTL_6328_USBH_EN, enable);
174 else if (BCMCPU_IS_6348())
175 bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
176 else if (BCMCPU_IS_6362())
177 bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
178 else if (BCMCPU_IS_6368())
179 bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
182 static struct clk clk_usbh = {
189 static void usbd_set(struct clk *clk, int enable)
191 if (BCMCPU_IS_6328())
192 bcm_hwclock_set(CKCTL_6328_USBD_EN, enable);
193 else if (BCMCPU_IS_6362())
194 bcm_hwclock_set(CKCTL_6362_USBD_EN, enable);
195 else if (BCMCPU_IS_6368())
196 bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
199 static struct clk clk_usbd = {
206 static void spi_set(struct clk *clk, int enable)
210 if (BCMCPU_IS_6338())
211 mask = CKCTL_6338_SPI_EN;
212 else if (BCMCPU_IS_6348())
213 mask = CKCTL_6348_SPI_EN;
214 else if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
215 mask = CKCTL_6358_SPI_EN;
216 else if (BCMCPU_IS_6362())
217 mask = CKCTL_6362_SPI_EN;
220 mask = CKCTL_6368_SPI_EN;
221 bcm_hwclock_set(mask, enable);
224 static struct clk clk_spi = {
231 static void xtm_set(struct clk *clk, int enable)
233 if (!BCMCPU_IS_6368())
236 bcm_hwclock_set(CKCTL_6368_SAR_EN |
237 CKCTL_6368_SWPKT_SAR_EN, enable);
240 /* reset sar core afer clock change */
241 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
243 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
249 static struct clk clk_xtm = {
256 static void ipsec_set(struct clk *clk, int enable)
258 if (BCMCPU_IS_6362())
259 bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable);
260 else if (BCMCPU_IS_6368())
261 bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
264 static struct clk clk_ipsec = {
272 static void pcie_set(struct clk *clk, int enable)
274 if (BCMCPU_IS_6328())
275 bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
276 else if (BCMCPU_IS_6362())
277 bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
280 static struct clk clk_pcie = {
285 * Internal peripheral clock
287 static struct clk clk_periph = {
288 .rate = (50 * 1000 * 1000),
293 * Linux clock API implementation
295 int clk_enable(struct clk *clk)
297 mutex_lock(&clocks_mutex);
298 clk_enable_unlocked(clk);
299 mutex_unlock(&clocks_mutex);
303 EXPORT_SYMBOL(clk_enable);
305 void clk_disable(struct clk *clk)
307 mutex_lock(&clocks_mutex);
308 clk_disable_unlocked(clk);
309 mutex_unlock(&clocks_mutex);
312 EXPORT_SYMBOL(clk_disable);
314 unsigned long clk_get_rate(struct clk *clk)
319 EXPORT_SYMBOL(clk_get_rate);
321 int clk_set_rate(struct clk *clk, unsigned long rate)
325 EXPORT_SYMBOL_GPL(clk_set_rate);
327 long clk_round_rate(struct clk *clk, unsigned long rate)
331 EXPORT_SYMBOL_GPL(clk_round_rate);
333 struct clk *clk_get(struct device *dev, const char *id)
335 if (!strcmp(id, "enet0"))
337 if (!strcmp(id, "enet1"))
339 if (!strcmp(id, "enetsw"))
341 if (!strcmp(id, "ephy"))
343 if (!strcmp(id, "usbh"))
345 if (!strcmp(id, "usbd"))
347 if (!strcmp(id, "spi"))
349 if (!strcmp(id, "xtm"))
351 if (!strcmp(id, "periph"))
353 if ((BCMCPU_IS_3368() || BCMCPU_IS_6358()) && !strcmp(id, "pcm"))
355 if ((BCMCPU_IS_6362() || BCMCPU_IS_6368()) && !strcmp(id, "ipsec"))
357 if ((BCMCPU_IS_6328() || BCMCPU_IS_6362()) && !strcmp(id, "pcie"))
359 return ERR_PTR(-ENOENT);
362 EXPORT_SYMBOL(clk_get);
364 void clk_put(struct clk *clk)
368 EXPORT_SYMBOL(clk_put);