Merge branch 'for-4.14-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj...
[sfrench/cifs-2.6.git] / arch / mips / bcm63xx / clk.c
1 /*
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
4  * for more details.
5  *
6  * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
7  */
8
9 #include <linux/init.h>
10 #include <linux/export.h>
11 #include <linux/mutex.h>
12 #include <linux/err.h>
13 #include <linux/clk.h>
14 #include <linux/delay.h>
15 #include <bcm63xx_cpu.h>
16 #include <bcm63xx_io.h>
17 #include <bcm63xx_regs.h>
18 #include <bcm63xx_reset.h>
19
20 struct clk {
21         void            (*set)(struct clk *, int);
22         unsigned int    rate;
23         unsigned int    usage;
24         int             id;
25 };
26
27 static DEFINE_MUTEX(clocks_mutex);
28
29
30 static void clk_enable_unlocked(struct clk *clk)
31 {
32         if (clk->set && (clk->usage++) == 0)
33                 clk->set(clk, 1);
34 }
35
36 static void clk_disable_unlocked(struct clk *clk)
37 {
38         if (clk->set && (--clk->usage) == 0)
39                 clk->set(clk, 0);
40 }
41
42 static void bcm_hwclock_set(u32 mask, int enable)
43 {
44         u32 reg;
45
46         reg = bcm_perf_readl(PERF_CKCTL_REG);
47         if (enable)
48                 reg |= mask;
49         else
50                 reg &= ~mask;
51         bcm_perf_writel(reg, PERF_CKCTL_REG);
52 }
53
54 /*
55  * Ethernet MAC "misc" clock: dma clocks and main clock on 6348
56  */
57 static void enet_misc_set(struct clk *clk, int enable)
58 {
59         u32 mask;
60
61         if (BCMCPU_IS_6338())
62                 mask = CKCTL_6338_ENET_EN;
63         else if (BCMCPU_IS_6345())
64                 mask = CKCTL_6345_ENET_EN;
65         else if (BCMCPU_IS_6348())
66                 mask = CKCTL_6348_ENET_EN;
67         else
68                 /* BCMCPU_IS_6358 */
69                 mask = CKCTL_6358_EMUSB_EN;
70         bcm_hwclock_set(mask, enable);
71 }
72
73 static struct clk clk_enet_misc = {
74         .set    = enet_misc_set,
75 };
76
77 /*
78  * Ethernet MAC clocks: only revelant on 6358, silently enable misc
79  * clocks
80  */
81 static void enetx_set(struct clk *clk, int enable)
82 {
83         if (enable)
84                 clk_enable_unlocked(&clk_enet_misc);
85         else
86                 clk_disable_unlocked(&clk_enet_misc);
87
88         if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) {
89                 u32 mask;
90
91                 if (clk->id == 0)
92                         mask = CKCTL_6358_ENET0_EN;
93                 else
94                         mask = CKCTL_6358_ENET1_EN;
95                 bcm_hwclock_set(mask, enable);
96         }
97 }
98
99 static struct clk clk_enet0 = {
100         .id     = 0,
101         .set    = enetx_set,
102 };
103
104 static struct clk clk_enet1 = {
105         .id     = 1,
106         .set    = enetx_set,
107 };
108
109 /*
110  * Ethernet PHY clock
111  */
112 static void ephy_set(struct clk *clk, int enable)
113 {
114         if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
115                 bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable);
116 }
117
118
119 static struct clk clk_ephy = {
120         .set    = ephy_set,
121 };
122
123 /*
124  * Ethernet switch clock
125  */
126 static void enetsw_set(struct clk *clk, int enable)
127 {
128         if (BCMCPU_IS_6328())
129                 bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable);
130         else if (BCMCPU_IS_6362())
131                 bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable);
132         else if (BCMCPU_IS_6368())
133                 bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
134                                 CKCTL_6368_SWPKT_USB_EN |
135                                 CKCTL_6368_SWPKT_SAR_EN,
136                                 enable);
137         else
138                 return;
139
140         if (enable) {
141                 /* reset switch core afer clock change */
142                 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
143                 msleep(10);
144                 bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
145                 msleep(10);
146         }
147 }
148
149 static struct clk clk_enetsw = {
150         .set    = enetsw_set,
151 };
152
153 /*
154  * PCM clock
155  */
156 static void pcm_set(struct clk *clk, int enable)
157 {
158         if (BCMCPU_IS_3368())
159                 bcm_hwclock_set(CKCTL_3368_PCM_EN, enable);
160         if (BCMCPU_IS_6358())
161                 bcm_hwclock_set(CKCTL_6358_PCM_EN, enable);
162 }
163
164 static struct clk clk_pcm = {
165         .set    = pcm_set,
166 };
167
168 /*
169  * USB host clock
170  */
171 static void usbh_set(struct clk *clk, int enable)
172 {
173         if (BCMCPU_IS_6328())
174                 bcm_hwclock_set(CKCTL_6328_USBH_EN, enable);
175         else if (BCMCPU_IS_6348())
176                 bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
177         else if (BCMCPU_IS_6362())
178                 bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
179         else if (BCMCPU_IS_6368())
180                 bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
181 }
182
183 static struct clk clk_usbh = {
184         .set    = usbh_set,
185 };
186
187 /*
188  * USB device clock
189  */
190 static void usbd_set(struct clk *clk, int enable)
191 {
192         if (BCMCPU_IS_6328())
193                 bcm_hwclock_set(CKCTL_6328_USBD_EN, enable);
194         else if (BCMCPU_IS_6362())
195                 bcm_hwclock_set(CKCTL_6362_USBD_EN, enable);
196         else if (BCMCPU_IS_6368())
197                 bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
198 }
199
200 static struct clk clk_usbd = {
201         .set    = usbd_set,
202 };
203
204 /*
205  * SPI clock
206  */
207 static void spi_set(struct clk *clk, int enable)
208 {
209         u32 mask;
210
211         if (BCMCPU_IS_6338())
212                 mask = CKCTL_6338_SPI_EN;
213         else if (BCMCPU_IS_6348())
214                 mask = CKCTL_6348_SPI_EN;
215         else if (BCMCPU_IS_3368() || BCMCPU_IS_6358())
216                 mask = CKCTL_6358_SPI_EN;
217         else if (BCMCPU_IS_6362())
218                 mask = CKCTL_6362_SPI_EN;
219         else
220                 /* BCMCPU_IS_6368 */
221                 mask = CKCTL_6368_SPI_EN;
222         bcm_hwclock_set(mask, enable);
223 }
224
225 static struct clk clk_spi = {
226         .set    = spi_set,
227 };
228
229 /*
230  * HSSPI clock
231  */
232 static void hsspi_set(struct clk *clk, int enable)
233 {
234         u32 mask;
235
236         if (BCMCPU_IS_6328())
237                 mask = CKCTL_6328_HSSPI_EN;
238         else if (BCMCPU_IS_6362())
239                 mask = CKCTL_6362_HSSPI_EN;
240         else
241                 return;
242
243         bcm_hwclock_set(mask, enable);
244 }
245
246 static struct clk clk_hsspi = {
247         .set    = hsspi_set,
248 };
249
250
251 /*
252  * XTM clock
253  */
254 static void xtm_set(struct clk *clk, int enable)
255 {
256         if (!BCMCPU_IS_6368())
257                 return;
258
259         bcm_hwclock_set(CKCTL_6368_SAR_EN |
260                         CKCTL_6368_SWPKT_SAR_EN, enable);
261
262         if (enable) {
263                 /* reset sar core afer clock change */
264                 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
265                 mdelay(1);
266                 bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
267                 mdelay(1);
268         }
269 }
270
271
272 static struct clk clk_xtm = {
273         .set    = xtm_set,
274 };
275
276 /*
277  * IPsec clock
278  */
279 static void ipsec_set(struct clk *clk, int enable)
280 {
281         if (BCMCPU_IS_6362())
282                 bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable);
283         else if (BCMCPU_IS_6368())
284                 bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
285 }
286
287 static struct clk clk_ipsec = {
288         .set    = ipsec_set,
289 };
290
291 /*
292  * PCIe clock
293  */
294
295 static void pcie_set(struct clk *clk, int enable)
296 {
297         if (BCMCPU_IS_6328())
298                 bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
299         else if (BCMCPU_IS_6362())
300                 bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
301 }
302
303 static struct clk clk_pcie = {
304         .set    = pcie_set,
305 };
306
307 /*
308  * Internal peripheral clock
309  */
310 static struct clk clk_periph = {
311         .rate   = (50 * 1000 * 1000),
312 };
313
314
315 /*
316  * Linux clock API implementation
317  */
318 int clk_enable(struct clk *clk)
319 {
320         mutex_lock(&clocks_mutex);
321         clk_enable_unlocked(clk);
322         mutex_unlock(&clocks_mutex);
323         return 0;
324 }
325
326 EXPORT_SYMBOL(clk_enable);
327
328 void clk_disable(struct clk *clk)
329 {
330         if (!clk)
331                 return;
332
333         mutex_lock(&clocks_mutex);
334         clk_disable_unlocked(clk);
335         mutex_unlock(&clocks_mutex);
336 }
337
338 EXPORT_SYMBOL(clk_disable);
339
340 unsigned long clk_get_rate(struct clk *clk)
341 {
342         if (!clk)
343                 return 0;
344
345         return clk->rate;
346 }
347
348 EXPORT_SYMBOL(clk_get_rate);
349
350 int clk_set_rate(struct clk *clk, unsigned long rate)
351 {
352         return 0;
353 }
354 EXPORT_SYMBOL_GPL(clk_set_rate);
355
356 long clk_round_rate(struct clk *clk, unsigned long rate)
357 {
358         return 0;
359 }
360 EXPORT_SYMBOL_GPL(clk_round_rate);
361
362 struct clk *clk_get(struct device *dev, const char *id)
363 {
364         if (!strcmp(id, "enet0"))
365                 return &clk_enet0;
366         if (!strcmp(id, "enet1"))
367                 return &clk_enet1;
368         if (!strcmp(id, "enetsw"))
369                 return &clk_enetsw;
370         if (!strcmp(id, "ephy"))
371                 return &clk_ephy;
372         if (!strcmp(id, "usbh"))
373                 return &clk_usbh;
374         if (!strcmp(id, "usbd"))
375                 return &clk_usbd;
376         if (!strcmp(id, "spi"))
377                 return &clk_spi;
378         if (!strcmp(id, "hsspi"))
379                 return &clk_hsspi;
380         if (!strcmp(id, "xtm"))
381                 return &clk_xtm;
382         if (!strcmp(id, "periph"))
383                 return &clk_periph;
384         if ((BCMCPU_IS_3368() || BCMCPU_IS_6358()) && !strcmp(id, "pcm"))
385                 return &clk_pcm;
386         if ((BCMCPU_IS_6362() || BCMCPU_IS_6368()) && !strcmp(id, "ipsec"))
387                 return &clk_ipsec;
388         if ((BCMCPU_IS_6328() || BCMCPU_IS_6362()) && !strcmp(id, "pcie"))
389                 return &clk_pcie;
390         return ERR_PTR(-ENOENT);
391 }
392
393 EXPORT_SYMBOL(clk_get);
394
395 void clk_put(struct clk *clk)
396 {
397 }
398
399 EXPORT_SYMBOL(clk_put);
400
401 #define HSSPI_PLL_HZ_6328       133333333
402 #define HSSPI_PLL_HZ_6362       400000000
403
404 static int __init bcm63xx_clk_init(void)
405 {
406         switch (bcm63xx_get_cpu_id()) {
407         case BCM6328_CPU_ID:
408                 clk_hsspi.rate = HSSPI_PLL_HZ_6328;
409                 break;
410         case BCM6362_CPU_ID:
411                 clk_hsspi.rate = HSSPI_PLL_HZ_6362;
412                 break;
413         }
414
415         return 0;
416 }
417 arch_initcall(bcm63xx_clk_init);