xref: /OK3568_Linux_fs/kernel/drivers/media/pci/cobalt/cobalt-cpld.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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