2 * Cobalt CPLD functions
4 * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
7 * This program is free software; you may redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
11 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
15 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
16 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
17 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 #include <linux/delay.h>
23 #include "cobalt-cpld.h"
25 #define ADRS(offset) (COBALT_BUS_CPLD_BASE + offset)
27 static u16
cpld_read(struct cobalt
*cobalt
, u32 offset
)
29 return cobalt_bus_read32(cobalt
->bar1
, ADRS(offset
));
32 static void cpld_write(struct cobalt
*cobalt
, u32 offset
, u16 val
)
34 return cobalt_bus_write32(cobalt
->bar1
, ADRS(offset
), val
);
37 static void cpld_info_ver3(struct cobalt
*cobalt
)
42 cobalt_info("CPLD System control register (read/write)\n");
43 cobalt_info("\t\tSystem control: 0x%04x (0x0f00)\n",
44 cpld_read(cobalt
, 0));
45 cobalt_info("CPLD Clock control register (read/write)\n");
46 cobalt_info("\t\tClock control: 0x%04x (0x0000)\n",
47 cpld_read(cobalt
, 0x04));
48 cobalt_info("CPLD HSMA Clk Osc register (read/write) - Must set wr trigger to load default values\n");
49 cobalt_info("\t\tRegister #7:\t0x%04x (0x0022)\n",
50 cpld_read(cobalt
, 0x08));
51 cobalt_info("\t\tRegister #8:\t0x%04x (0x0047)\n",
52 cpld_read(cobalt
, 0x0c));
53 cobalt_info("\t\tRegister #9:\t0x%04x (0x00fa)\n",
54 cpld_read(cobalt
, 0x10));
55 cobalt_info("\t\tRegister #10:\t0x%04x (0x0061)\n",
56 cpld_read(cobalt
, 0x14));
57 cobalt_info("\t\tRegister #11:\t0x%04x (0x001e)\n",
58 cpld_read(cobalt
, 0x18));
59 cobalt_info("\t\tRegister #12:\t0x%04x (0x0045)\n",
60 cpld_read(cobalt
, 0x1c));
61 cobalt_info("\t\tRegister #135:\t0x%04x\n",
62 cpld_read(cobalt
, 0x20));
63 cobalt_info("\t\tRegister #137:\t0x%04x\n",
64 cpld_read(cobalt
, 0x24));
65 cobalt_info("CPLD System status register (read only)\n");
66 cobalt_info("\t\tSystem status: 0x%04x\n",
67 cpld_read(cobalt
, 0x28));
68 cobalt_info("CPLD MAXII info register (read only)\n");
69 cobalt_info("\t\tBoard serial number: 0x%04x\n",
70 cpld_read(cobalt
, 0x2c));
71 cobalt_info("\t\tMAXII program revision: 0x%04x\n",
72 cpld_read(cobalt
, 0x30));
73 cobalt_info("CPLD temp and voltage ADT7411 registers (read only)\n");
74 cobalt_info("\t\tBoard temperature: %u Celcius\n",
75 cpld_read(cobalt
, 0x34) / 4);
76 cobalt_info("\t\tFPGA temperature: %u Celcius\n",
77 cpld_read(cobalt
, 0x38) / 4);
78 rd
= cpld_read(cobalt
, 0x3c);
79 tmp
= (rd
* 33 * 1000) / (483 * 10);
80 cobalt_info("\t\tVDD 3V3: %u,%03uV\n", tmp
/ 1000, tmp
% 1000);
81 rd
= cpld_read(cobalt
, 0x40);
82 tmp
= (rd
* 74 * 2197) / (27 * 1000);
83 cobalt_info("\t\tADC ch3 5V: %u,%03uV\n", tmp
/ 1000, tmp
% 1000);
84 rd
= cpld_read(cobalt
, 0x44);
85 tmp
= (rd
* 74 * 2197) / (47 * 1000);
86 cobalt_info("\t\tADC ch4 3V: %u,%03uV\n", tmp
/ 1000, tmp
% 1000);
87 rd
= cpld_read(cobalt
, 0x48);
88 tmp
= (rd
* 57 * 2197) / (47 * 1000);
89 cobalt_info("\t\tADC ch5 2V5: %u,%03uV\n", tmp
/ 1000, tmp
% 1000);
90 rd
= cpld_read(cobalt
, 0x4c);
91 tmp
= (rd
* 2197) / 1000;
92 cobalt_info("\t\tADC ch6 1V8: %u,%03uV\n", tmp
/ 1000, tmp
% 1000);
93 rd
= cpld_read(cobalt
, 0x50);
94 tmp
= (rd
* 2197) / 1000;
95 cobalt_info("\t\tADC ch7 1V5: %u,%03uV\n", tmp
/ 1000, tmp
% 1000);
96 rd
= cpld_read(cobalt
, 0x54);
97 tmp
= (rd
* 2197) / 1000;
98 cobalt_info("\t\tADC ch8 0V9: %u,%03uV\n", tmp
/ 1000, tmp
% 1000);
101 void cobalt_cpld_status(struct cobalt
*cobalt
)
103 u32 rev
= cpld_read(cobalt
, 0x30);
109 cpld_info_ver3(cobalt
);
112 cobalt_info("CPLD revision %u is not supported!\n", rev
);
117 #define DCO_MIN 4850000000ULL
118 #define DCO_MAX 5670000000ULL
120 #define SI570_CLOCK_CTRL 0x04
121 #define S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_WR_TRIGGER 0x200
122 #define S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_RST_TRIGGER 0x100
123 #define S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL 0x80
124 #define S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN 0x40
126 #define SI570_REG7 0x08
127 #define SI570_REG8 0x0c
128 #define SI570_REG9 0x10
129 #define SI570_REG10 0x14
130 #define SI570_REG11 0x18
131 #define SI570_REG12 0x1c
132 #define SI570_REG135 0x20
133 #define SI570_REG137 0x24
136 unsigned mult
, hsdiv
, n1
;
139 /* List all possible multipliers (= hsdiv * n1). There are lots of duplicates,
140 which are all removed in this list to keep the list as short as possible.
141 The values for hsdiv and n1 are the actual values, not the register values.
143 static const struct multiplier multipliers
[] = {
144 { 4, 4, 1 }, { 5, 5, 1 }, { 6, 6, 1 },
145 { 7, 7, 1 }, { 8, 4, 2 }, { 9, 9, 1 },
146 { 10, 5, 2 }, { 11, 11, 1 }, { 12, 6, 2 },
147 { 14, 7, 2 }, { 16, 4, 4 }, { 18, 9, 2 },
148 { 20, 5, 4 }, { 22, 11, 2 }, { 24, 4, 6 },
149 { 28, 7, 4 }, { 30, 5, 6 }, { 32, 4, 8 },
150 { 36, 6, 6 }, { 40, 4, 10 }, { 42, 7, 6 },
151 { 44, 11, 4 }, { 48, 4, 12 }, { 50, 5, 10 },
152 { 54, 9, 6 }, { 56, 4, 14 }, { 60, 5, 12 },
153 { 64, 4, 16 }, { 66, 11, 6 }, { 70, 5, 14 },
154 { 72, 4, 18 }, { 80, 4, 20 }, { 84, 6, 14 },
155 { 88, 11, 8 }, { 90, 5, 18 }, { 96, 4, 24 },
156 { 98, 7, 14 }, { 100, 5, 20 }, { 104, 4, 26 },
157 { 108, 6, 18 }, { 110, 11, 10 }, { 112, 4, 28 },
158 { 120, 4, 30 }, { 126, 7, 18 }, { 128, 4, 32 },
159 { 130, 5, 26 }, { 132, 11, 12 }, { 136, 4, 34 },
160 { 140, 5, 28 }, { 144, 4, 36 }, { 150, 5, 30 },
161 { 152, 4, 38 }, { 154, 11, 14 }, { 156, 6, 26 },
162 { 160, 4, 40 }, { 162, 9, 18 }, { 168, 4, 42 },
163 { 170, 5, 34 }, { 176, 11, 16 }, { 180, 5, 36 },
164 { 182, 7, 26 }, { 184, 4, 46 }, { 190, 5, 38 },
165 { 192, 4, 48 }, { 196, 7, 28 }, { 198, 11, 18 },
166 { 198, 9, 22 }, { 200, 4, 50 }, { 204, 6, 34 },
167 { 208, 4, 52 }, { 210, 5, 42 }, { 216, 4, 54 },
168 { 220, 11, 20 }, { 224, 4, 56 }, { 228, 6, 38 },
169 { 230, 5, 46 }, { 232, 4, 58 }, { 234, 9, 26 },
170 { 238, 7, 34 }, { 240, 4, 60 }, { 242, 11, 22 },
171 { 248, 4, 62 }, { 250, 5, 50 }, { 252, 6, 42 },
172 { 256, 4, 64 }, { 260, 5, 52 }, { 264, 11, 24 },
173 { 266, 7, 38 }, { 270, 5, 54 }, { 272, 4, 68 },
174 { 276, 6, 46 }, { 280, 4, 70 }, { 286, 11, 26 },
175 { 288, 4, 72 }, { 290, 5, 58 }, { 294, 7, 42 },
176 { 296, 4, 74 }, { 300, 5, 60 }, { 304, 4, 76 },
177 { 306, 9, 34 }, { 308, 11, 28 }, { 310, 5, 62 },
178 { 312, 4, 78 }, { 320, 4, 80 }, { 322, 7, 46 },
179 { 324, 6, 54 }, { 328, 4, 82 }, { 330, 11, 30 },
180 { 336, 4, 84 }, { 340, 5, 68 }, { 342, 9, 38 },
181 { 344, 4, 86 }, { 348, 6, 58 }, { 350, 5, 70 },
182 { 352, 11, 32 }, { 360, 4, 90 }, { 364, 7, 52 },
183 { 368, 4, 92 }, { 370, 5, 74 }, { 372, 6, 62 },
184 { 374, 11, 34 }, { 376, 4, 94 }, { 378, 7, 54 },
185 { 380, 5, 76 }, { 384, 4, 96 }, { 390, 5, 78 },
186 { 392, 4, 98 }, { 396, 11, 36 }, { 400, 4, 100 },
187 { 406, 7, 58 }, { 408, 4, 102 }, { 410, 5, 82 },
188 { 414, 9, 46 }, { 416, 4, 104 }, { 418, 11, 38 },
189 { 420, 5, 84 }, { 424, 4, 106 }, { 430, 5, 86 },
190 { 432, 4, 108 }, { 434, 7, 62 }, { 440, 11, 40 },
191 { 444, 6, 74 }, { 448, 4, 112 }, { 450, 5, 90 },
192 { 456, 4, 114 }, { 460, 5, 92 }, { 462, 11, 42 },
193 { 464, 4, 116 }, { 468, 6, 78 }, { 470, 5, 94 },
194 { 472, 4, 118 }, { 476, 7, 68 }, { 480, 4, 120 },
195 { 484, 11, 44 }, { 486, 9, 54 }, { 488, 4, 122 },
196 { 490, 5, 98 }, { 492, 6, 82 }, { 496, 4, 124 },
197 { 500, 5, 100 }, { 504, 4, 126 }, { 506, 11, 46 },
198 { 510, 5, 102 }, { 512, 4, 128 }, { 516, 6, 86 },
199 { 518, 7, 74 }, { 520, 5, 104 }, { 522, 9, 58 },
200 { 528, 11, 48 }, { 530, 5, 106 }, { 532, 7, 76 },
201 { 540, 5, 108 }, { 546, 7, 78 }, { 550, 11, 50 },
202 { 552, 6, 92 }, { 558, 9, 62 }, { 560, 5, 112 },
203 { 564, 6, 94 }, { 570, 5, 114 }, { 572, 11, 52 },
204 { 574, 7, 82 }, { 576, 6, 96 }, { 580, 5, 116 },
205 { 588, 6, 98 }, { 590, 5, 118 }, { 594, 11, 54 },
206 { 600, 5, 120 }, { 602, 7, 86 }, { 610, 5, 122 },
207 { 612, 6, 102 }, { 616, 11, 56 }, { 620, 5, 124 },
208 { 624, 6, 104 }, { 630, 5, 126 }, { 636, 6, 106 },
209 { 638, 11, 58 }, { 640, 5, 128 }, { 644, 7, 92 },
210 { 648, 6, 108 }, { 658, 7, 94 }, { 660, 11, 60 },
211 { 666, 9, 74 }, { 672, 6, 112 }, { 682, 11, 62 },
212 { 684, 6, 114 }, { 686, 7, 98 }, { 696, 6, 116 },
213 { 700, 7, 100 }, { 702, 9, 78 }, { 704, 11, 64 },
214 { 708, 6, 118 }, { 714, 7, 102 }, { 720, 6, 120 },
215 { 726, 11, 66 }, { 728, 7, 104 }, { 732, 6, 122 },
216 { 738, 9, 82 }, { 742, 7, 106 }, { 744, 6, 124 },
217 { 748, 11, 68 }, { 756, 6, 126 }, { 768, 6, 128 },
218 { 770, 11, 70 }, { 774, 9, 86 }, { 784, 7, 112 },
219 { 792, 11, 72 }, { 798, 7, 114 }, { 810, 9, 90 },
220 { 812, 7, 116 }, { 814, 11, 74 }, { 826, 7, 118 },
221 { 828, 9, 92 }, { 836, 11, 76 }, { 840, 7, 120 },
222 { 846, 9, 94 }, { 854, 7, 122 }, { 858, 11, 78 },
223 { 864, 9, 96 }, { 868, 7, 124 }, { 880, 11, 80 },
224 { 882, 7, 126 }, { 896, 7, 128 }, { 900, 9, 100 },
225 { 902, 11, 82 }, { 918, 9, 102 }, { 924, 11, 84 },
226 { 936, 9, 104 }, { 946, 11, 86 }, { 954, 9, 106 },
227 { 968, 11, 88 }, { 972, 9, 108 }, { 990, 11, 90 },
228 { 1008, 9, 112 }, { 1012, 11, 92 }, { 1026, 9, 114 },
229 { 1034, 11, 94 }, { 1044, 9, 116 }, { 1056, 11, 96 },
230 { 1062, 9, 118 }, { 1078, 11, 98 }, { 1080, 9, 120 },
231 { 1098, 9, 122 }, { 1100, 11, 100 }, { 1116, 9, 124 },
232 { 1122, 11, 102 }, { 1134, 9, 126 }, { 1144, 11, 104 },
233 { 1152, 9, 128 }, { 1166, 11, 106 }, { 1188, 11, 108 },
234 { 1210, 11, 110 }, { 1232, 11, 112 }, { 1254, 11, 114 },
235 { 1276, 11, 116 }, { 1298, 11, 118 }, { 1320, 11, 120 },
236 { 1342, 11, 122 }, { 1364, 11, 124 }, { 1386, 11, 126 },
240 bool cobalt_cpld_set_freq(struct cobalt
*cobalt
, unsigned f_out
)
242 const unsigned f_xtal
= 39170000; /* xtal for si598 */
245 unsigned delta
= 0xffffffff;
254 for (i
= 0; i
< ARRAY_SIZE(multipliers
); i
++) {
255 unsigned mult
= multipliers
[i
].mult
;
258 dco
= (u64
)f_out
* mult
;
259 if (dco
< DCO_MIN
|| dco
> DCO_MAX
)
261 div_u64_rem((dco
<< 28) + f_xtal
/ 2, f_xtal
, &d
);
270 dco
= (u64
)f_out
* multipliers
[i_best
].mult
;
271 n1
= multipliers
[i_best
].n1
- 1;
272 hsdiv
= multipliers
[i_best
].hsdiv
- 4;
273 rfreq
= div_u64(dco
<< 28, f_xtal
);
275 clock_ctrl
= cpld_read(cobalt
, SI570_CLOCK_CTRL
);
276 clock_ctrl
|= S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL
;
277 clock_ctrl
|= S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN
;
279 regs
[0] = (hsdiv
<< 5) | (n1
>> 2);
280 regs
[1] = ((n1
& 0x3) << 6) | (rfreq
>> 32);
281 regs
[2] = (rfreq
>> 24) & 0xff;
282 regs
[3] = (rfreq
>> 16) & 0xff;
283 regs
[4] = (rfreq
>> 8) & 0xff;
284 regs
[5] = rfreq
& 0xff;
286 /* The sequence of clock_ctrl flags to set is very weird. It looks
287 like I have to reset it, then set the new frequency and reset it
288 again. It shouldn't be necessary to do a reset, but if I don't,
289 then a strange frequency is set (156.412034 MHz, or register values
290 0x01, 0xc7, 0xfc, 0x7f, 0x53, 0x62).
293 cobalt_dbg(1, "%u: %6ph\n", f_out
, regs
);
298 cpld_write(cobalt
, SI570_CLOCK_CTRL
,
299 S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN
|
300 S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL
);
301 usleep_range(10000, 15000);
302 cpld_write(cobalt
, SI570_REG7
, regs
[0]);
303 cpld_write(cobalt
, SI570_REG8
, regs
[1]);
304 cpld_write(cobalt
, SI570_REG9
, regs
[2]);
305 cpld_write(cobalt
, SI570_REG10
, regs
[3]);
306 cpld_write(cobalt
, SI570_REG11
, regs
[4]);
307 cpld_write(cobalt
, SI570_REG12
, regs
[5]);
308 cpld_write(cobalt
, SI570_CLOCK_CTRL
,
309 S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN
|
310 S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_WR_TRIGGER
);
311 usleep_range(10000, 15000);
312 cpld_write(cobalt
, SI570_CLOCK_CTRL
,
313 S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN
|
314 S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL
);
315 usleep_range(10000, 15000);
316 read_regs
[0] = cpld_read(cobalt
, SI570_REG7
);
317 read_regs
[1] = cpld_read(cobalt
, SI570_REG8
);
318 read_regs
[2] = cpld_read(cobalt
, SI570_REG9
);
319 read_regs
[3] = cpld_read(cobalt
, SI570_REG10
);
320 read_regs
[4] = cpld_read(cobalt
, SI570_REG11
);
321 read_regs
[5] = cpld_read(cobalt
, SI570_REG12
);
322 cpld_write(cobalt
, SI570_CLOCK_CTRL
,
323 S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN
|
324 S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL
|
325 S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_RST_TRIGGER
);
326 usleep_range(10000, 15000);
327 cpld_write(cobalt
, SI570_CLOCK_CTRL
,
328 S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN
);
329 usleep_range(10000, 15000);
331 if (!memcmp(read_regs
, regs
, sizeof(read_regs
)))
333 cobalt_dbg(1, "retry: %6ph\n", read_regs
);
336 cobalt_info("Needed %d retries\n", 2 - retries
);