]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/media/pci/cobalt/cobalt-cpld.c
Merge branch 'jdelvare-hwmon/master'
[karo-tx-linux.git] / drivers / media / pci / cobalt / cobalt-cpld.c
1 /*
2  *  Cobalt CPLD functions
3  *
4  *  Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
5  *  All rights reserved.
6  *
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.
10  *
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
18  *  SOFTWARE.
19  */
20
21 #include <linux/delay.h>
22
23 #include "cobalt-cpld.h"
24
25 #define ADRS(offset) (COBALT_BUS_CPLD_BASE + offset)
26
27 static u16 cpld_read(struct cobalt *cobalt, u32 offset)
28 {
29         return cobalt_bus_read32(cobalt->bar1, ADRS(offset));
30 }
31
32 static void cpld_write(struct cobalt *cobalt, u32 offset, u16 val)
33 {
34         return cobalt_bus_write32(cobalt->bar1, ADRS(offset), val);
35 }
36
37 static void cpld_info_ver3(struct cobalt *cobalt)
38 {
39         u32 rd;
40         u32 tmp;
41
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);
99 }
100
101 void cobalt_cpld_status(struct cobalt *cobalt)
102 {
103         u32 rev = cpld_read(cobalt, 0x30);
104
105         switch (rev) {
106         case 3:
107         case 4:
108         case 5:
109                 cpld_info_ver3(cobalt);
110                 break;
111         default:
112                 cobalt_info("CPLD revision %u is not supported!\n", rev);
113                 break;
114         }
115 }
116
117 #define DCO_MIN 4850000000ULL
118 #define DCO_MAX 5670000000ULL
119
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
125
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
134
135 struct multiplier {
136         unsigned mult, hsdiv, n1;
137 };
138
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.
142  */
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 },
237         { 1408, 11, 128 },
238 };
239
240 bool cobalt_cpld_set_freq(struct cobalt *cobalt, unsigned f_out)
241 {
242         const unsigned f_xtal = 39170000;       /* xtal for si598 */
243         u64 dco;
244         u64 rfreq;
245         unsigned delta = 0xffffffff;
246         unsigned i_best = 0;
247         unsigned i;
248         u8 n1, hsdiv;
249         u8 regs[6];
250         int found = 0;
251         u16 clock_ctrl;
252         int retries = 3;
253
254         for (i = 0; i < ARRAY_SIZE(multipliers); i++) {
255                 unsigned mult = multipliers[i].mult;
256                 u32 d;
257
258                 dco = (u64)f_out * mult;
259                 if (dco < DCO_MIN || dco > DCO_MAX)
260                         continue;
261                 div_u64_rem((dco << 28) + f_xtal / 2, f_xtal, &d);
262                 if (d < delta) {
263                         found = 1;
264                         i_best = i;
265                         delta = d;
266                 }
267         }
268         if (!found)
269                 return false;
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);
274
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;
278
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;
285
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).
291          */
292
293         cobalt_dbg(1, "%u: %02x %02x %02x %02x %02x %02x\n", f_out,
294                         regs[0], regs[1], regs[2], regs[3], regs[4], regs[5]);
295         while (retries--) {
296                 u8 read_regs[6];
297
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);
330
331                 if (!memcmp(read_regs, regs, sizeof(read_regs)))
332                         break;
333                 cobalt_dbg(1, "retry: %02x %02x %02x %02x %02x %02x\n",
334                         read_regs[0], read_regs[1], read_regs[2],
335                         read_regs[3], read_regs[4], read_regs[5]);
336         }
337         if (2 - retries)
338                 cobalt_info("Needed %d retries\n", 2 - retries);
339
340         return true;
341 }