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