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