arm, am335x: add support for 3 siemens boards
[platform/kernel/u-boot.git] / tools / mpc86x_clk.c
1 /*
2  * (C) Copyright 2003 Intracom S.A.
3  * Pantelis Antoniou <panto@intracom.gr>
4  *
5  * This little program makes an exhaustive search for the
6  * correct terms of pdf, mfi, mfn, mfd, s, dbrmo, in PLPRCR.
7  * The goal is to produce a gclk2 from a xin input, while respecting
8  * all the restrictions on their combination.
9  *
10  * Generaly you select the first row of the produced table.
11  *
12  * SPDX-License-Identifier:     GPL-2.0+
13  */
14
15
16 #include <stdio.h>
17 #include <stdlib.h>
18
19 #define DPREF_MIN        10000000
20 #define DPREF_MAX        32000000
21
22 #define DPGDCK_MAX      320000000
23 #define DPGDCK_MIN      160000000
24
25 #define S_MIN           0
26 #define S_MAX           2
27
28 #define MFI_MIN         5
29 #define MFI_MAX         15
30
31 #define MFN_MIN         0
32 #define MFN_MAX         15
33
34 #define MFD_MIN         0
35 #define MFD_MAX         31
36
37 #define MF_MIN          5
38 #define MF_MAX          15
39
40 #define PDF_MIN         0
41 #define PDF_MAX         15
42
43 #define GCLK2_MAX       150000000
44
45 static int calculate (int xin, int target_clock,
46                       int ppm, int pdf, int mfi, int mfn, int mfd, int s,
47                       int *dprefp, int *dpgdckp, int *jdbckp,
48                       int *gclk2p, int *dbrmop)
49 {
50         unsigned int dpref, dpgdck, jdbck, gclk2, t1, t2, dbrmo;
51
52         /* valid MFI? */
53         if (mfi < MFI_MIN)
54                 return -1;
55
56         /* valid num, denum? */
57         if (mfn > 0 && mfn >= mfd)
58                 return -1;
59
60         dpref = xin / (pdf + 1);
61
62         /* valid dpef? */
63         if (dpref < DPREF_MIN || dpref > DPREF_MAX)
64                 return -1;
65
66         if (mfn == 0) {
67                 dpgdck  = (2 * mfi * xin) / (pdf + 1) ;
68                 dbrmo = 0;
69         } else {
70                 /* 5 <= mfi + (mfn / mfd + 1) <= 15 */
71                 t1 = mfd + 1;
72                 t2 = mfi * t1 + mfn;
73                 if ( MF_MIN * t1 > t2 || MF_MAX * t1 < t2)
74                         return -1;
75
76                 dpgdck  = (unsigned int)(2 * (mfi * mfd + mfi + mfn) *
77                                 (unsigned int)xin) /
78                                 ((mfd + 1) * (pdf + 1));
79
80                 dbrmo = 10 * mfn < (mfd + 1);
81         }
82
83         /* valid dpgclk? */
84         if (dpgdck < DPGDCK_MIN || dpgdck > DPGDCK_MAX)
85                 return -1;
86
87         jdbck = dpgdck >> s;
88         gclk2 = jdbck / 2;
89
90         /* valid gclk2 */
91         if (gclk2 > GCLK2_MAX)
92                 return -1;
93
94         t1 = abs(gclk2 - target_clock);
95
96         /* XXX max 1MHz dev. in clock */
97         if (t1 > 1000000)
98                 return -1;
99
100         /* dev within range (XXX gclk2 scaled to avoid overflow) */
101         if (t1 * 1000 > (unsigned int)ppm * (gclk2 / 1000))
102                 return -1;
103
104         *dprefp = dpref;
105         *dpgdckp = dpgdck;
106         *jdbckp = jdbck;
107         *gclk2p = gclk2;
108         *dbrmop = dbrmo;
109
110         return gclk2;
111 }
112
113 int conf_clock(int xin, int target_clock, int ppm)
114 {
115         int pdf, s, mfn, mfd, mfi;
116         int dpref, dpgdck, jdbck, gclk2, xout, dbrmo;
117         int found = 0;
118
119         /* integer multipliers */
120         for (pdf = PDF_MIN; pdf <= PDF_MAX; pdf++) {
121                 for (mfi = MFI_MIN; mfi <= MFI_MAX; mfi++) {
122                         for (s = 0; s <= S_MAX; s++) {
123                                 xout = calculate(xin, target_clock,
124                                                  ppm, pdf, mfi, 0, 0, s,
125                                                  &dpref, &dpgdck, &jdbck,
126                                                  &gclk2, &dbrmo);
127                                 if (xout < 0)
128                                         continue;
129
130                                 if (found == 0) {
131                                         printf("pdf mfi mfn mfd s dbrmo     dpref    dpgdck     jdbck     gclk2 exact?\n");
132                                         printf("--- --- --- --- - -----     -----    ------     -----     ----- ------\n");
133                                 }
134
135                                 printf("%3d %3d --- --- %1d %5d %9d %9d %9d %9d%s\n",
136                                         pdf, mfi, s, dbrmo,
137                                         dpref, dpgdck, jdbck, gclk2,
138                                         gclk2 == target_clock ? "    YES" : "");
139
140                                 found++;
141                         }
142                 }
143         }
144
145         /* fractional multipliers */
146         for (pdf = PDF_MIN; pdf <= PDF_MAX; pdf++) {
147                 for (mfi = MFI_MIN; mfi <= MFI_MAX; mfi++) {
148                         for (mfn = 1; mfn <= MFN_MAX; mfn++) {
149                                 for (mfd = 1; mfd <= MFD_MAX; mfd++) {
150                                         for (s = 0; s <= S_MAX; s++) {
151                                                 xout = calculate(xin, target_clock,
152                                                             ppm, pdf, mfi, mfn, mfd, s,
153                                                             &dpref, &dpgdck, &jdbck,
154                                                             &gclk2, &dbrmo);
155                                                 if (xout < 0)
156                                                         continue;
157
158                                                 if (found == 0) {
159                                                         printf("pdf mfi mfn mfd s dbrmo     dpref    dpgdck     jdbck     gclk2 exact?\n");
160                                                         printf("--- --- --- --- - -----     -----    ------     -----     ----- ------\n");
161                                                 }
162
163                                                 printf("%3d %3d %3d %3d %1d %5d %9d %9d %9d %9d%s\n",
164                                                         pdf, mfi, mfn, mfd, s,
165                                                         dbrmo, dpref, dpgdck, jdbck, gclk2,
166                                                         gclk2 == target_clock ? "    YES" : "");
167
168                                                 found++;
169                                         }
170                                 }
171                         }
172
173                 }
174         }
175
176         return found;
177 }
178
179 int main(int argc, char *argv[])
180 {
181         int xin, want_gclk2, found, ppm = 100;
182
183         if (argc < 3) {
184                 fprintf(stderr, "usage: mpc86x_clk <xin> <want_gclk2> [ppm]\n");
185                 fprintf(stderr, "       default ppm is 100\n");
186                 return 10;
187         }
188
189         xin  = atoi(argv[1]);
190         want_gclk2 = atoi(argv[2]);
191         if (argc >= 4)
192                 ppm = atoi(argv[3]);
193
194         found = conf_clock(xin, want_gclk2, ppm);
195         if (found <= 0) {
196                 fprintf(stderr, "cannot produce gclk2 %d from xin %d\n",
197                         want_gclk2, xin);
198                 return EXIT_FAILURE;
199         }
200
201         return EXIT_SUCCESS;
202 }