xref: /openbmc/linux/drivers/media/pci/cobalt/cobalt-cpld.c (revision 4a561c4b70b908c0b5cbcc8bc95bc796139e63ad)
185756a06SHans Verkuil /*
285756a06SHans Verkuil  *  Cobalt CPLD functions
385756a06SHans Verkuil  *
485756a06SHans Verkuil  *  Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
585756a06SHans Verkuil  *  All rights reserved.
685756a06SHans Verkuil  *
785756a06SHans Verkuil  *  This program is free software; you may redistribute it and/or modify
885756a06SHans Verkuil  *  it under the terms of the GNU General Public License as published by
985756a06SHans Verkuil  *  the Free Software Foundation; version 2 of the License.
1085756a06SHans Verkuil  *
1185756a06SHans Verkuil  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1285756a06SHans Verkuil  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1385756a06SHans Verkuil  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1485756a06SHans Verkuil  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1585756a06SHans Verkuil  *  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1685756a06SHans Verkuil  *  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1785756a06SHans Verkuil  *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1885756a06SHans Verkuil  *  SOFTWARE.
1985756a06SHans Verkuil  */
2085756a06SHans Verkuil 
2185756a06SHans Verkuil #include <linux/delay.h>
2285756a06SHans Verkuil 
2385756a06SHans Verkuil #include "cobalt-driver.h"
2485756a06SHans Verkuil 
2585756a06SHans Verkuil #define ADRS(offset) (COBALT_BUS_CPLD_BASE + offset)
2685756a06SHans Verkuil 
2785756a06SHans Verkuil static u16 cpld_read(struct cobalt *cobalt, u32 offset)
2885756a06SHans Verkuil {
29*4a561c4bSHans Verkuil 	return cobalt_bus_read32(cobalt->bar1, ADRS(offset));
3085756a06SHans Verkuil }
3185756a06SHans Verkuil 
3285756a06SHans Verkuil static void cpld_write(struct cobalt *cobalt, u32 offset, u16 val)
3385756a06SHans Verkuil {
34*4a561c4bSHans Verkuil 	return cobalt_bus_write32(cobalt->bar1, ADRS(offset), val);
3585756a06SHans Verkuil }
3685756a06SHans Verkuil 
3785756a06SHans Verkuil static void cpld_info_ver3(struct cobalt *cobalt)
3885756a06SHans Verkuil {
3985756a06SHans Verkuil 	u32 rd;
4085756a06SHans Verkuil 	u32 tmp;
4185756a06SHans Verkuil 
4285756a06SHans Verkuil 	cobalt_info("CPLD System control register (read/write)\n");
4385756a06SHans Verkuil 	cobalt_info("\t\tSystem control:  0x%04x (0x0f00)\n",
4485756a06SHans Verkuil 		    cpld_read(cobalt, 0));
4585756a06SHans Verkuil 	cobalt_info("CPLD Clock control register (read/write)\n");
4685756a06SHans Verkuil 	cobalt_info("\t\tClock control:   0x%04x (0x0000)\n",
4785756a06SHans Verkuil 		    cpld_read(cobalt, 0x04));
4885756a06SHans Verkuil 	cobalt_info("CPLD HSMA Clk Osc register (read/write) - Must set wr trigger to load default values\n");
4985756a06SHans Verkuil 	cobalt_info("\t\tRegister #7:\t0x%04x (0x0022)\n",
5085756a06SHans Verkuil 		    cpld_read(cobalt, 0x08));
5185756a06SHans Verkuil 	cobalt_info("\t\tRegister #8:\t0x%04x (0x0047)\n",
5285756a06SHans Verkuil 		    cpld_read(cobalt, 0x0c));
5385756a06SHans Verkuil 	cobalt_info("\t\tRegister #9:\t0x%04x (0x00fa)\n",
5485756a06SHans Verkuil 		    cpld_read(cobalt, 0x10));
5585756a06SHans Verkuil 	cobalt_info("\t\tRegister #10:\t0x%04x (0x0061)\n",
5685756a06SHans Verkuil 		    cpld_read(cobalt, 0x14));
5785756a06SHans Verkuil 	cobalt_info("\t\tRegister #11:\t0x%04x (0x001e)\n",
5885756a06SHans Verkuil 		    cpld_read(cobalt, 0x18));
5985756a06SHans Verkuil 	cobalt_info("\t\tRegister #12:\t0x%04x (0x0045)\n",
6085756a06SHans Verkuil 		    cpld_read(cobalt, 0x1c));
6185756a06SHans Verkuil 	cobalt_info("\t\tRegister #135:\t0x%04x\n",
6285756a06SHans Verkuil 		    cpld_read(cobalt, 0x20));
6385756a06SHans Verkuil 	cobalt_info("\t\tRegister #137:\t0x%04x\n",
6485756a06SHans Verkuil 		    cpld_read(cobalt, 0x24));
6585756a06SHans Verkuil 	cobalt_info("CPLD System status register (read only)\n");
6685756a06SHans Verkuil 	cobalt_info("\t\tSystem status:  0x%04x\n",
6785756a06SHans Verkuil 		    cpld_read(cobalt, 0x28));
6885756a06SHans Verkuil 	cobalt_info("CPLD MAXII info register (read only)\n");
6985756a06SHans Verkuil 	cobalt_info("\t\tBoard serial number:     0x%04x\n",
7085756a06SHans Verkuil 		    cpld_read(cobalt, 0x2c));
7185756a06SHans Verkuil 	cobalt_info("\t\tMAXII program revision:  0x%04x\n",
7285756a06SHans Verkuil 		    cpld_read(cobalt, 0x30));
7385756a06SHans Verkuil 	cobalt_info("CPLD temp and voltage ADT7411 registers (read only)\n");
7485756a06SHans Verkuil 	cobalt_info("\t\tBoard temperature:  %u Celcius\n",
7585756a06SHans Verkuil 		    cpld_read(cobalt, 0x34) / 4);
7685756a06SHans Verkuil 	cobalt_info("\t\tFPGA temperature:   %u Celcius\n",
7785756a06SHans Verkuil 		    cpld_read(cobalt, 0x38) / 4);
7885756a06SHans Verkuil 	rd = cpld_read(cobalt, 0x3c);
7985756a06SHans Verkuil 	tmp = (rd * 33 * 1000) / (483 * 10);
8085756a06SHans Verkuil 	cobalt_info("\t\tVDD 3V3:      %u,%03uV\n", tmp / 1000, tmp % 1000);
8185756a06SHans Verkuil 	rd = cpld_read(cobalt, 0x40);
8285756a06SHans Verkuil 	tmp = (rd * 74 * 2197) / (27 * 1000);
8385756a06SHans Verkuil 	cobalt_info("\t\tADC ch3 5V:   %u,%03uV\n", tmp / 1000, tmp % 1000);
8485756a06SHans Verkuil 	rd = cpld_read(cobalt, 0x44);
8585756a06SHans Verkuil 	tmp = (rd * 74 * 2197) / (47 * 1000);
8685756a06SHans Verkuil 	cobalt_info("\t\tADC ch4 3V:   %u,%03uV\n", tmp / 1000, tmp % 1000);
8785756a06SHans Verkuil 	rd = cpld_read(cobalt, 0x48);
8885756a06SHans Verkuil 	tmp = (rd * 57 * 2197) / (47 * 1000);
8985756a06SHans Verkuil 	cobalt_info("\t\tADC ch5 2V5:  %u,%03uV\n", tmp / 1000, tmp % 1000);
9085756a06SHans Verkuil 	rd = cpld_read(cobalt, 0x4c);
9185756a06SHans Verkuil 	tmp = (rd * 2197) / 1000;
9285756a06SHans Verkuil 	cobalt_info("\t\tADC ch6 1V8:  %u,%03uV\n", tmp / 1000, tmp % 1000);
9385756a06SHans Verkuil 	rd = cpld_read(cobalt, 0x50);
9485756a06SHans Verkuil 	tmp = (rd * 2197) / 1000;
9585756a06SHans Verkuil 	cobalt_info("\t\tADC ch7 1V5:  %u,%03uV\n", tmp / 1000, tmp % 1000);
9685756a06SHans Verkuil 	rd = cpld_read(cobalt, 0x54);
9785756a06SHans Verkuil 	tmp = (rd * 2197) / 1000;
9885756a06SHans Verkuil 	cobalt_info("\t\tADC ch8 0V9:  %u,%03uV\n", tmp / 1000, tmp % 1000);
9985756a06SHans Verkuil }
10085756a06SHans Verkuil 
10185756a06SHans Verkuil void cobalt_cpld_status(struct cobalt *cobalt)
10285756a06SHans Verkuil {
10385756a06SHans Verkuil 	u32 rev = cpld_read(cobalt, 0x30);
10485756a06SHans Verkuil 
10585756a06SHans Verkuil 	switch (rev) {
10685756a06SHans Verkuil 	case 3:
10785756a06SHans Verkuil 	case 4:
10885756a06SHans Verkuil 	case 5:
10985756a06SHans Verkuil 		cpld_info_ver3(cobalt);
11085756a06SHans Verkuil 		break;
11185756a06SHans Verkuil 	default:
11285756a06SHans Verkuil 		cobalt_info("CPLD revision %u is not supported!\n", rev);
11385756a06SHans Verkuil 		break;
11485756a06SHans Verkuil 	}
11585756a06SHans Verkuil }
11685756a06SHans Verkuil 
11785756a06SHans Verkuil #define DCO_MIN 4850000000ULL
11885756a06SHans Verkuil #define DCO_MAX 5670000000ULL
11985756a06SHans Verkuil 
12085756a06SHans Verkuil #define SI570_CLOCK_CTRL   0x04
12185756a06SHans Verkuil #define S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_WR_TRIGGER 0x200
12285756a06SHans Verkuil #define S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_RST_TRIGGER 0x100
12385756a06SHans Verkuil #define S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL 0x80
12485756a06SHans Verkuil #define S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN 0x40
12585756a06SHans Verkuil 
12685756a06SHans Verkuil #define SI570_REG7   0x08
12785756a06SHans Verkuil #define SI570_REG8   0x0c
12885756a06SHans Verkuil #define SI570_REG9   0x10
12985756a06SHans Verkuil #define SI570_REG10  0x14
13085756a06SHans Verkuil #define SI570_REG11  0x18
13185756a06SHans Verkuil #define SI570_REG12  0x1c
13285756a06SHans Verkuil #define SI570_REG135 0x20
13385756a06SHans Verkuil #define SI570_REG137 0x24
13485756a06SHans Verkuil 
13585756a06SHans Verkuil struct multiplier {
13685756a06SHans Verkuil 	unsigned mult, hsdiv, n1;
13785756a06SHans Verkuil };
13885756a06SHans Verkuil 
13985756a06SHans Verkuil /* List all possible multipliers (= hsdiv * n1). There are lots of duplicates,
14085756a06SHans Verkuil    which are all removed in this list to keep the list as short as possible.
14185756a06SHans Verkuil    The values for hsdiv and n1 are the actual values, not the register values.
14285756a06SHans Verkuil  */
14385756a06SHans Verkuil static const struct multiplier multipliers[] = {
14485756a06SHans Verkuil 	{    4,  4,   1 }, {    5,  5,   1 }, {    6,  6,   1 },
14585756a06SHans Verkuil 	{    7,  7,   1 }, {    8,  4,   2 }, {    9,  9,   1 },
14685756a06SHans Verkuil 	{   10,  5,   2 }, {   11, 11,   1 }, {   12,  6,   2 },
14785756a06SHans Verkuil 	{   14,  7,   2 }, {   16,  4,   4 }, {   18,  9,   2 },
14885756a06SHans Verkuil 	{   20,  5,   4 }, {   22, 11,   2 }, {   24,  4,   6 },
14985756a06SHans Verkuil 	{   28,  7,   4 }, {   30,  5,   6 }, {   32,  4,   8 },
15085756a06SHans Verkuil 	{   36,  6,   6 }, {   40,  4,  10 }, {   42,  7,   6 },
15185756a06SHans Verkuil 	{   44, 11,   4 }, {   48,  4,  12 }, {   50,  5,  10 },
15285756a06SHans Verkuil 	{   54,  9,   6 }, {   56,  4,  14 }, {   60,  5,  12 },
15385756a06SHans Verkuil 	{   64,  4,  16 }, {   66, 11,   6 }, {   70,  5,  14 },
15485756a06SHans Verkuil 	{   72,  4,  18 }, {   80,  4,  20 }, {   84,  6,  14 },
15585756a06SHans Verkuil 	{   88, 11,   8 }, {   90,  5,  18 }, {   96,  4,  24 },
15685756a06SHans Verkuil 	{   98,  7,  14 }, {  100,  5,  20 }, {  104,  4,  26 },
15785756a06SHans Verkuil 	{  108,  6,  18 }, {  110, 11,  10 }, {  112,  4,  28 },
15885756a06SHans Verkuil 	{  120,  4,  30 }, {  126,  7,  18 }, {  128,  4,  32 },
15985756a06SHans Verkuil 	{  130,  5,  26 }, {  132, 11,  12 }, {  136,  4,  34 },
16085756a06SHans Verkuil 	{  140,  5,  28 }, {  144,  4,  36 }, {  150,  5,  30 },
16185756a06SHans Verkuil 	{  152,  4,  38 }, {  154, 11,  14 }, {  156,  6,  26 },
16285756a06SHans Verkuil 	{  160,  4,  40 }, {  162,  9,  18 }, {  168,  4,  42 },
16385756a06SHans Verkuil 	{  170,  5,  34 }, {  176, 11,  16 }, {  180,  5,  36 },
16485756a06SHans Verkuil 	{  182,  7,  26 }, {  184,  4,  46 }, {  190,  5,  38 },
16585756a06SHans Verkuil 	{  192,  4,  48 }, {  196,  7,  28 }, {  198, 11,  18 },
16685756a06SHans Verkuil 	{  198,  9,  22 }, {  200,  4,  50 }, {  204,  6,  34 },
16785756a06SHans Verkuil 	{  208,  4,  52 }, {  210,  5,  42 }, {  216,  4,  54 },
16885756a06SHans Verkuil 	{  220, 11,  20 }, {  224,  4,  56 }, {  228,  6,  38 },
16985756a06SHans Verkuil 	{  230,  5,  46 }, {  232,  4,  58 }, {  234,  9,  26 },
17085756a06SHans Verkuil 	{  238,  7,  34 }, {  240,  4,  60 }, {  242, 11,  22 },
17185756a06SHans Verkuil 	{  248,  4,  62 }, {  250,  5,  50 }, {  252,  6,  42 },
17285756a06SHans Verkuil 	{  256,  4,  64 }, {  260,  5,  52 }, {  264, 11,  24 },
17385756a06SHans Verkuil 	{  266,  7,  38 }, {  270,  5,  54 }, {  272,  4,  68 },
17485756a06SHans Verkuil 	{  276,  6,  46 }, {  280,  4,  70 }, {  286, 11,  26 },
17585756a06SHans Verkuil 	{  288,  4,  72 }, {  290,  5,  58 }, {  294,  7,  42 },
17685756a06SHans Verkuil 	{  296,  4,  74 }, {  300,  5,  60 }, {  304,  4,  76 },
17785756a06SHans Verkuil 	{  306,  9,  34 }, {  308, 11,  28 }, {  310,  5,  62 },
17885756a06SHans Verkuil 	{  312,  4,  78 }, {  320,  4,  80 }, {  322,  7,  46 },
17985756a06SHans Verkuil 	{  324,  6,  54 }, {  328,  4,  82 }, {  330, 11,  30 },
18085756a06SHans Verkuil 	{  336,  4,  84 }, {  340,  5,  68 }, {  342,  9,  38 },
18185756a06SHans Verkuil 	{  344,  4,  86 }, {  348,  6,  58 }, {  350,  5,  70 },
18285756a06SHans Verkuil 	{  352, 11,  32 }, {  360,  4,  90 }, {  364,  7,  52 },
18385756a06SHans Verkuil 	{  368,  4,  92 }, {  370,  5,  74 }, {  372,  6,  62 },
18485756a06SHans Verkuil 	{  374, 11,  34 }, {  376,  4,  94 }, {  378,  7,  54 },
18585756a06SHans Verkuil 	{  380,  5,  76 }, {  384,  4,  96 }, {  390,  5,  78 },
18685756a06SHans Verkuil 	{  392,  4,  98 }, {  396, 11,  36 }, {  400,  4, 100 },
18785756a06SHans Verkuil 	{  406,  7,  58 }, {  408,  4, 102 }, {  410,  5,  82 },
18885756a06SHans Verkuil 	{  414,  9,  46 }, {  416,  4, 104 }, {  418, 11,  38 },
18985756a06SHans Verkuil 	{  420,  5,  84 }, {  424,  4, 106 }, {  430,  5,  86 },
19085756a06SHans Verkuil 	{  432,  4, 108 }, {  434,  7,  62 }, {  440, 11,  40 },
19185756a06SHans Verkuil 	{  444,  6,  74 }, {  448,  4, 112 }, {  450,  5,  90 },
19285756a06SHans Verkuil 	{  456,  4, 114 }, {  460,  5,  92 }, {  462, 11,  42 },
19385756a06SHans Verkuil 	{  464,  4, 116 }, {  468,  6,  78 }, {  470,  5,  94 },
19485756a06SHans Verkuil 	{  472,  4, 118 }, {  476,  7,  68 }, {  480,  4, 120 },
19585756a06SHans Verkuil 	{  484, 11,  44 }, {  486,  9,  54 }, {  488,  4, 122 },
19685756a06SHans Verkuil 	{  490,  5,  98 }, {  492,  6,  82 }, {  496,  4, 124 },
19785756a06SHans Verkuil 	{  500,  5, 100 }, {  504,  4, 126 }, {  506, 11,  46 },
19885756a06SHans Verkuil 	{  510,  5, 102 }, {  512,  4, 128 }, {  516,  6,  86 },
19985756a06SHans Verkuil 	{  518,  7,  74 }, {  520,  5, 104 }, {  522,  9,  58 },
20085756a06SHans Verkuil 	{  528, 11,  48 }, {  530,  5, 106 }, {  532,  7,  76 },
20185756a06SHans Verkuil 	{  540,  5, 108 }, {  546,  7,  78 }, {  550, 11,  50 },
20285756a06SHans Verkuil 	{  552,  6,  92 }, {  558,  9,  62 }, {  560,  5, 112 },
20385756a06SHans Verkuil 	{  564,  6,  94 }, {  570,  5, 114 }, {  572, 11,  52 },
20485756a06SHans Verkuil 	{  574,  7,  82 }, {  576,  6,  96 }, {  580,  5, 116 },
20585756a06SHans Verkuil 	{  588,  6,  98 }, {  590,  5, 118 }, {  594, 11,  54 },
20685756a06SHans Verkuil 	{  600,  5, 120 }, {  602,  7,  86 }, {  610,  5, 122 },
20785756a06SHans Verkuil 	{  612,  6, 102 }, {  616, 11,  56 }, {  620,  5, 124 },
20885756a06SHans Verkuil 	{  624,  6, 104 }, {  630,  5, 126 }, {  636,  6, 106 },
20985756a06SHans Verkuil 	{  638, 11,  58 }, {  640,  5, 128 }, {  644,  7,  92 },
21085756a06SHans Verkuil 	{  648,  6, 108 }, {  658,  7,  94 }, {  660, 11,  60 },
21185756a06SHans Verkuil 	{  666,  9,  74 }, {  672,  6, 112 }, {  682, 11,  62 },
21285756a06SHans Verkuil 	{  684,  6, 114 }, {  686,  7,  98 }, {  696,  6, 116 },
21385756a06SHans Verkuil 	{  700,  7, 100 }, {  702,  9,  78 }, {  704, 11,  64 },
21485756a06SHans Verkuil 	{  708,  6, 118 }, {  714,  7, 102 }, {  720,  6, 120 },
21585756a06SHans Verkuil 	{  726, 11,  66 }, {  728,  7, 104 }, {  732,  6, 122 },
21685756a06SHans Verkuil 	{  738,  9,  82 }, {  742,  7, 106 }, {  744,  6, 124 },
21785756a06SHans Verkuil 	{  748, 11,  68 }, {  756,  6, 126 }, {  768,  6, 128 },
21885756a06SHans Verkuil 	{  770, 11,  70 }, {  774,  9,  86 }, {  784,  7, 112 },
21985756a06SHans Verkuil 	{  792, 11,  72 }, {  798,  7, 114 }, {  810,  9,  90 },
22085756a06SHans Verkuil 	{  812,  7, 116 }, {  814, 11,  74 }, {  826,  7, 118 },
22185756a06SHans Verkuil 	{  828,  9,  92 }, {  836, 11,  76 }, {  840,  7, 120 },
22285756a06SHans Verkuil 	{  846,  9,  94 }, {  854,  7, 122 }, {  858, 11,  78 },
22385756a06SHans Verkuil 	{  864,  9,  96 }, {  868,  7, 124 }, {  880, 11,  80 },
22485756a06SHans Verkuil 	{  882,  7, 126 }, {  896,  7, 128 }, {  900,  9, 100 },
22585756a06SHans Verkuil 	{  902, 11,  82 }, {  918,  9, 102 }, {  924, 11,  84 },
22685756a06SHans Verkuil 	{  936,  9, 104 }, {  946, 11,  86 }, {  954,  9, 106 },
22785756a06SHans Verkuil 	{  968, 11,  88 }, {  972,  9, 108 }, {  990, 11,  90 },
22885756a06SHans Verkuil 	{ 1008,  9, 112 }, { 1012, 11,  92 }, { 1026,  9, 114 },
22985756a06SHans Verkuil 	{ 1034, 11,  94 }, { 1044,  9, 116 }, { 1056, 11,  96 },
23085756a06SHans Verkuil 	{ 1062,  9, 118 }, { 1078, 11,  98 }, { 1080,  9, 120 },
23185756a06SHans Verkuil 	{ 1098,  9, 122 }, { 1100, 11, 100 }, { 1116,  9, 124 },
23285756a06SHans Verkuil 	{ 1122, 11, 102 }, { 1134,  9, 126 }, { 1144, 11, 104 },
23385756a06SHans Verkuil 	{ 1152,  9, 128 }, { 1166, 11, 106 }, { 1188, 11, 108 },
23485756a06SHans Verkuil 	{ 1210, 11, 110 }, { 1232, 11, 112 }, { 1254, 11, 114 },
23585756a06SHans Verkuil 	{ 1276, 11, 116 }, { 1298, 11, 118 }, { 1320, 11, 120 },
23685756a06SHans Verkuil 	{ 1342, 11, 122 }, { 1364, 11, 124 }, { 1386, 11, 126 },
23785756a06SHans Verkuil 	{ 1408, 11, 128 },
23885756a06SHans Verkuil };
23985756a06SHans Verkuil 
24085756a06SHans Verkuil bool cobalt_cpld_set_freq(struct cobalt *cobalt, unsigned f_out)
24185756a06SHans Verkuil {
24285756a06SHans Verkuil 	const unsigned f_xtal = 39170000;	/* xtal for si598 */
24385756a06SHans Verkuil 	unsigned long long dco;
24485756a06SHans Verkuil 	unsigned long long rfreq;
24585756a06SHans Verkuil 	unsigned delta = 0xffffffff;
24685756a06SHans Verkuil 	unsigned i_best = 0;
24785756a06SHans Verkuil 	unsigned i;
24885756a06SHans Verkuil 	u8 n1, hsdiv;
24985756a06SHans Verkuil 	u8 regs[6];
25085756a06SHans Verkuil 	int found = 0;
25185756a06SHans Verkuil 	u16 clock_ctrl;
25285756a06SHans Verkuil 	int retries = 3;
25385756a06SHans Verkuil 
25485756a06SHans Verkuil 	for (i = 0; i < ARRAY_SIZE(multipliers); i++) {
25585756a06SHans Verkuil 		unsigned mult = multipliers[i].mult;
25685756a06SHans Verkuil 		unsigned d;
25785756a06SHans Verkuil 
25885756a06SHans Verkuil 		dco = (unsigned long long)f_out * mult;
25985756a06SHans Verkuil 		if (dco < DCO_MIN || dco > DCO_MAX)
26085756a06SHans Verkuil 			continue;
26185756a06SHans Verkuil 		d = ((dco << 28) + f_xtal / 2) % f_xtal;
26285756a06SHans Verkuil 		if (d < delta) {
26385756a06SHans Verkuil 			found = 1;
26485756a06SHans Verkuil 			i_best = i;
26585756a06SHans Verkuil 			delta = d;
26685756a06SHans Verkuil 		}
26785756a06SHans Verkuil 	}
26885756a06SHans Verkuil 	if (!found)
26985756a06SHans Verkuil 		return false;
27085756a06SHans Verkuil 	dco = (unsigned long long)f_out * multipliers[i_best].mult;
27185756a06SHans Verkuil 	n1 = multipliers[i_best].n1 - 1;
27285756a06SHans Verkuil 	hsdiv = multipliers[i_best].hsdiv - 4;
27385756a06SHans Verkuil 	rfreq = (dco << 28) / f_xtal;
27485756a06SHans Verkuil 
27585756a06SHans Verkuil 	clock_ctrl = cpld_read(cobalt, SI570_CLOCK_CTRL);
27685756a06SHans Verkuil 	clock_ctrl |= S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL;
27785756a06SHans Verkuil 	clock_ctrl |= S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN;
27885756a06SHans Verkuil 
27985756a06SHans Verkuil 	regs[0] = (hsdiv << 5) | (n1 >> 2);
28085756a06SHans Verkuil 	regs[1] = ((n1 & 0x3) << 6) | (rfreq >> 32);
28185756a06SHans Verkuil 	regs[2] = (rfreq >> 24) & 0xff;
28285756a06SHans Verkuil 	regs[3] = (rfreq >> 16) & 0xff;
28385756a06SHans Verkuil 	regs[4] = (rfreq >> 8) & 0xff;
28485756a06SHans Verkuil 	regs[5] = rfreq & 0xff;
28585756a06SHans Verkuil 
28685756a06SHans Verkuil 	/* The sequence of clock_ctrl flags to set is very weird. It looks
28785756a06SHans Verkuil 	   like I have to reset it, then set the new frequency and reset it
28885756a06SHans Verkuil 	   again. It shouldn't be necessary to do a reset, but if I don't,
28985756a06SHans Verkuil 	   then a strange frequency is set (156.412034 MHz, or register values
29085756a06SHans Verkuil 	   0x01, 0xc7, 0xfc, 0x7f, 0x53, 0x62).
29185756a06SHans Verkuil 	 */
29285756a06SHans Verkuil 
29385756a06SHans Verkuil 	cobalt_dbg(1, "%u: %02x %02x %02x %02x %02x %02x\n", f_out,
29485756a06SHans Verkuil 			regs[0], regs[1], regs[2], regs[3], regs[4], regs[5]);
29585756a06SHans Verkuil 	while (retries--) {
29685756a06SHans Verkuil 		u8 read_regs[6];
29785756a06SHans Verkuil 
29885756a06SHans Verkuil 		cpld_write(cobalt, SI570_CLOCK_CTRL,
29985756a06SHans Verkuil 			S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
30085756a06SHans Verkuil 			S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL);
30185756a06SHans Verkuil 		usleep_range(10000, 15000);
30285756a06SHans Verkuil 		cpld_write(cobalt, SI570_REG7, regs[0]);
30385756a06SHans Verkuil 		cpld_write(cobalt, SI570_REG8, regs[1]);
30485756a06SHans Verkuil 		cpld_write(cobalt, SI570_REG9, regs[2]);
30585756a06SHans Verkuil 		cpld_write(cobalt, SI570_REG10, regs[3]);
30685756a06SHans Verkuil 		cpld_write(cobalt, SI570_REG11, regs[4]);
30785756a06SHans Verkuil 		cpld_write(cobalt, SI570_REG12, regs[5]);
30885756a06SHans Verkuil 		cpld_write(cobalt, SI570_CLOCK_CTRL,
30985756a06SHans Verkuil 			S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
31085756a06SHans Verkuil 			S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_WR_TRIGGER);
31185756a06SHans Verkuil 		usleep_range(10000, 15000);
31285756a06SHans Verkuil 		cpld_write(cobalt, SI570_CLOCK_CTRL,
31385756a06SHans Verkuil 			S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
31485756a06SHans Verkuil 			S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL);
31585756a06SHans Verkuil 		usleep_range(10000, 15000);
31685756a06SHans Verkuil 		read_regs[0] = cpld_read(cobalt, SI570_REG7);
31785756a06SHans Verkuil 		read_regs[1] = cpld_read(cobalt, SI570_REG8);
31885756a06SHans Verkuil 		read_regs[2] = cpld_read(cobalt, SI570_REG9);
31985756a06SHans Verkuil 		read_regs[3] = cpld_read(cobalt, SI570_REG10);
32085756a06SHans Verkuil 		read_regs[4] = cpld_read(cobalt, SI570_REG11);
32185756a06SHans Verkuil 		read_regs[5] = cpld_read(cobalt, SI570_REG12);
32285756a06SHans Verkuil 		cpld_write(cobalt, SI570_CLOCK_CTRL,
32385756a06SHans Verkuil 			S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
32485756a06SHans Verkuil 			S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL |
32585756a06SHans Verkuil 			S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_RST_TRIGGER);
32685756a06SHans Verkuil 		usleep_range(10000, 15000);
32785756a06SHans Verkuil 		cpld_write(cobalt, SI570_CLOCK_CTRL,
32885756a06SHans Verkuil 			S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN);
32985756a06SHans Verkuil 		usleep_range(10000, 15000);
33085756a06SHans Verkuil 
33185756a06SHans Verkuil 		if (!memcmp(read_regs, regs, sizeof(read_regs)))
33285756a06SHans Verkuil 			break;
33385756a06SHans Verkuil 		cobalt_dbg(1, "retry: %02x %02x %02x %02x %02x %02x\n",
33485756a06SHans Verkuil 			read_regs[0], read_regs[1], read_regs[2],
33585756a06SHans Verkuil 			read_regs[3], read_regs[4], read_regs[5]);
33685756a06SHans Verkuil 	}
33785756a06SHans Verkuil 	if (2 - retries)
33885756a06SHans Verkuil 		cobalt_info("Needed %d retries\n", 2 - retries);
33985756a06SHans Verkuil 
34085756a06SHans Verkuil 	return true;
34185756a06SHans Verkuil }
342