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