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