GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / media / pci / cobalt / cobalt-cpld.c
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         int retries = 3;
240
241         for (i = 0; i < ARRAY_SIZE(multipliers); i++) {
242                 unsigned mult = multipliers[i].mult;
243                 u32 d;
244
245                 dco = (u64)f_out * mult;
246                 if (dco < DCO_MIN || dco > DCO_MAX)
247                         continue;
248                 div_u64_rem((dco << 28) + f_xtal / 2, f_xtal, &d);
249                 if (d < delta) {
250                         found = 1;
251                         i_best = i;
252                         delta = d;
253                 }
254         }
255         if (!found)
256                 return false;
257         dco = (u64)f_out * multipliers[i_best].mult;
258         n1 = multipliers[i_best].n1 - 1;
259         hsdiv = multipliers[i_best].hsdiv - 4;
260         rfreq = div_u64(dco << 28, f_xtal);
261
262         cpld_read(cobalt, SI570_CLOCK_CTRL);
263
264         regs[0] = (hsdiv << 5) | (n1 >> 2);
265         regs[1] = ((n1 & 0x3) << 6) | (rfreq >> 32);
266         regs[2] = (rfreq >> 24) & 0xff;
267         regs[3] = (rfreq >> 16) & 0xff;
268         regs[4] = (rfreq >> 8) & 0xff;
269         regs[5] = rfreq & 0xff;
270
271         /* The sequence of clock_ctrl flags to set is very weird. It looks
272            like I have to reset it, then set the new frequency and reset it
273            again. It shouldn't be necessary to do a reset, but if I don't,
274            then a strange frequency is set (156.412034 MHz, or register values
275            0x01, 0xc7, 0xfc, 0x7f, 0x53, 0x62).
276          */
277
278         cobalt_dbg(1, "%u: %6ph\n", f_out, regs);
279
280         while (retries--) {
281                 u8 read_regs[6];
282
283                 cpld_write(cobalt, SI570_CLOCK_CTRL,
284                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
285                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL);
286                 usleep_range(10000, 15000);
287                 cpld_write(cobalt, SI570_REG7, regs[0]);
288                 cpld_write(cobalt, SI570_REG8, regs[1]);
289                 cpld_write(cobalt, SI570_REG9, regs[2]);
290                 cpld_write(cobalt, SI570_REG10, regs[3]);
291                 cpld_write(cobalt, SI570_REG11, regs[4]);
292                 cpld_write(cobalt, SI570_REG12, regs[5]);
293                 cpld_write(cobalt, SI570_CLOCK_CTRL,
294                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
295                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_WR_TRIGGER);
296                 usleep_range(10000, 15000);
297                 cpld_write(cobalt, SI570_CLOCK_CTRL,
298                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
299                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL);
300                 usleep_range(10000, 15000);
301                 read_regs[0] = cpld_read(cobalt, SI570_REG7);
302                 read_regs[1] = cpld_read(cobalt, SI570_REG8);
303                 read_regs[2] = cpld_read(cobalt, SI570_REG9);
304                 read_regs[3] = cpld_read(cobalt, SI570_REG10);
305                 read_regs[4] = cpld_read(cobalt, SI570_REG11);
306                 read_regs[5] = cpld_read(cobalt, SI570_REG12);
307                 cpld_write(cobalt, SI570_CLOCK_CTRL,
308                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
309                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL |
310                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_RST_TRIGGER);
311                 usleep_range(10000, 15000);
312                 cpld_write(cobalt, SI570_CLOCK_CTRL,
313                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN);
314                 usleep_range(10000, 15000);
315
316                 if (!memcmp(read_regs, regs, sizeof(read_regs)))
317                         break;
318                 cobalt_dbg(1, "retry: %6ph\n", read_regs);
319         }
320         if (2 - retries)
321                 cobalt_info("Needed %d retries\n", 2 - retries);
322
323         return true;
324 }