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