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