Commit | Line | Data |
---|---|---|
bbc6fac3 SW |
1 | /* |
2 | * PowerQUICC II support functions | |
3 | * | |
4 | * Author: Scott Wood <scottwood@freescale.com> | |
5 | * | |
6 | * Copyright (c) 2007 Freescale Semiconductor, Inc. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License version 2 as published | |
10 | * by the Free Software Foundation. | |
11 | */ | |
12 | ||
13 | #include "ops.h" | |
14 | #include "types.h" | |
15 | #include "fsl-soc.h" | |
16 | #include "pq2.h" | |
17 | #include "stdio.h" | |
18 | #include "io.h" | |
19 | ||
20 | #define PQ2_SCCR (0x10c80/4) /* System Clock Configuration Register */ | |
21 | #define PQ2_SCMR (0x10c88/4) /* System Clock Mode Register */ | |
22 | ||
23 | static int pq2_corecnf_map[] = { | |
24 | 3, 2, 2, 2, 4, 4, 5, 9, 6, 11, 8, 10, 3, 12, 7, -1, | |
25 | 6, 5, 13, 2, 14, 4, 15, 9, 0, 11, 8, 10, 16, 12, 7, -1 | |
26 | }; | |
27 | ||
28 | /* Get various clocks from crystal frequency. | |
29 | * Returns zero on failure and non-zero on success. | |
30 | */ | |
31 | int pq2_get_clocks(u32 crystal, u32 *sysfreq, u32 *corefreq, | |
32 | u32 *timebase, u32 *brgfreq) | |
33 | { | |
34 | u32 *immr; | |
35 | u32 sccr, scmr, mainclk, busclk; | |
36 | int corecnf, busdf, plldf, pllmf, dfbrg; | |
37 | ||
38 | immr = fsl_get_immr(); | |
39 | if (!immr) { | |
40 | printf("pq2_get_clocks: Couldn't get IMMR base.\r\n"); | |
41 | return 0; | |
42 | } | |
43 | ||
44 | sccr = in_be32(&immr[PQ2_SCCR]); | |
45 | scmr = in_be32(&immr[PQ2_SCMR]); | |
46 | ||
47 | dfbrg = sccr & 3; | |
48 | corecnf = (scmr >> 24) & 0x1f; | |
49 | busdf = (scmr >> 20) & 0xf; | |
50 | plldf = (scmr >> 12) & 1; | |
51 | pllmf = scmr & 0xfff; | |
52 | ||
53 | mainclk = crystal * (pllmf + 1) / (plldf + 1); | |
54 | busclk = mainclk / (busdf + 1); | |
55 | ||
56 | if (sysfreq) | |
57 | *sysfreq = mainclk / 2; | |
58 | if (timebase) | |
59 | *timebase = busclk / 4; | |
60 | if (brgfreq) | |
61 | *brgfreq = mainclk / (1 << ((dfbrg + 1) * 2)); | |
62 | ||
63 | if (corefreq) { | |
64 | int coremult = pq2_corecnf_map[corecnf]; | |
65 | ||
66 | if (coremult < 0) | |
67 | *corefreq = mainclk / 2; | |
68 | else if (coremult == 0) | |
69 | return 0; | |
70 | else | |
71 | *corefreq = busclk * coremult / 2; | |
72 | } | |
73 | ||
74 | return 1; | |
75 | } | |
76 | ||
77 | /* Set common device tree fields based on the given clock frequencies. */ | |
78 | void pq2_set_clocks(u32 sysfreq, u32 corefreq, u32 timebase, u32 brgfreq) | |
79 | { | |
80 | void *node; | |
81 | ||
82 | dt_fixup_cpu_clocks(corefreq, timebase, sysfreq); | |
83 | ||
84 | node = finddevice("/soc/cpm"); | |
85 | if (node) | |
86 | setprop(node, "clock-frequency", &sysfreq, 4); | |
87 | ||
88 | node = finddevice("/soc/cpm/brg"); | |
89 | if (node) | |
90 | setprop(node, "clock-frequency", &brgfreq, 4); | |
91 | } | |
92 | ||
93 | int pq2_fixup_clocks(u32 crystal) | |
94 | { | |
95 | u32 sysfreq, corefreq, timebase, brgfreq; | |
96 | ||
97 | if (!pq2_get_clocks(crystal, &sysfreq, &corefreq, &timebase, &brgfreq)) | |
98 | return 0; | |
99 | ||
100 | pq2_set_clocks(sysfreq, corefreq, timebase, brgfreq); | |
101 | return 1; | |
102 | } |