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