root/drivers/media/pci/cobalt/cobalt-cpld.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cpld_read
  2. cpld_write
  3. cpld_info_ver3
  4. cobalt_cpld_status
  5. cobalt_cpld_set_freq

   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 
  15 static u16 cpld_read(struct cobalt *cobalt, u32 offset)
  16 {
  17         return cobalt_bus_read32(cobalt->bar1, ADRS(offset));
  18 }
  19 
  20 static void cpld_write(struct cobalt *cobalt, u32 offset, u16 val)
  21 {
  22         return cobalt_bus_write32(cobalt->bar1, ADRS(offset), val);
  23 }
  24 
  25 static 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 
  89 void 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 
 123 struct 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  */
 131 static 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 
 228 bool 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         u16 clock_ctrl;
 240         int retries = 3;
 241 
 242         for (i = 0; i < ARRAY_SIZE(multipliers); i++) {
 243                 unsigned mult = multipliers[i].mult;
 244                 u32 d;
 245 
 246                 dco = (u64)f_out * mult;
 247                 if (dco < DCO_MIN || dco > DCO_MAX)
 248                         continue;
 249                 div_u64_rem((dco << 28) + f_xtal / 2, f_xtal, &d);
 250                 if (d < delta) {
 251                         found = 1;
 252                         i_best = i;
 253                         delta = d;
 254                 }
 255         }
 256         if (!found)
 257                 return false;
 258         dco = (u64)f_out * multipliers[i_best].mult;
 259         n1 = multipliers[i_best].n1 - 1;
 260         hsdiv = multipliers[i_best].hsdiv - 4;
 261         rfreq = div_u64(dco << 28, f_xtal);
 262 
 263         clock_ctrl = cpld_read(cobalt, SI570_CLOCK_CTRL);
 264         clock_ctrl |= S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL;
 265         clock_ctrl |= S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN;
 266 
 267         regs[0] = (hsdiv << 5) | (n1 >> 2);
 268         regs[1] = ((n1 & 0x3) << 6) | (rfreq >> 32);
 269         regs[2] = (rfreq >> 24) & 0xff;
 270         regs[3] = (rfreq >> 16) & 0xff;
 271         regs[4] = (rfreq >> 8) & 0xff;
 272         regs[5] = rfreq & 0xff;
 273 
 274         /* The sequence of clock_ctrl flags to set is very weird. It looks
 275            like I have to reset it, then set the new frequency and reset it
 276            again. It shouldn't be necessary to do a reset, but if I don't,
 277            then a strange frequency is set (156.412034 MHz, or register values
 278            0x01, 0xc7, 0xfc, 0x7f, 0x53, 0x62).
 279          */
 280 
 281         cobalt_dbg(1, "%u: %6ph\n", f_out, regs);
 282 
 283         while (retries--) {
 284                 u8 read_regs[6];
 285 
 286                 cpld_write(cobalt, SI570_CLOCK_CTRL,
 287                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
 288                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL);
 289                 usleep_range(10000, 15000);
 290                 cpld_write(cobalt, SI570_REG7, regs[0]);
 291                 cpld_write(cobalt, SI570_REG8, regs[1]);
 292                 cpld_write(cobalt, SI570_REG9, regs[2]);
 293                 cpld_write(cobalt, SI570_REG10, regs[3]);
 294                 cpld_write(cobalt, SI570_REG11, regs[4]);
 295                 cpld_write(cobalt, SI570_REG12, regs[5]);
 296                 cpld_write(cobalt, SI570_CLOCK_CTRL,
 297                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
 298                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_WR_TRIGGER);
 299                 usleep_range(10000, 15000);
 300                 cpld_write(cobalt, SI570_CLOCK_CTRL,
 301                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
 302                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL);
 303                 usleep_range(10000, 15000);
 304                 read_regs[0] = cpld_read(cobalt, SI570_REG7);
 305                 read_regs[1] = cpld_read(cobalt, SI570_REG8);
 306                 read_regs[2] = cpld_read(cobalt, SI570_REG9);
 307                 read_regs[3] = cpld_read(cobalt, SI570_REG10);
 308                 read_regs[4] = cpld_read(cobalt, SI570_REG11);
 309                 read_regs[5] = cpld_read(cobalt, SI570_REG12);
 310                 cpld_write(cobalt, SI570_CLOCK_CTRL,
 311                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN |
 312                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL |
 313                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_RST_TRIGGER);
 314                 usleep_range(10000, 15000);
 315                 cpld_write(cobalt, SI570_CLOCK_CTRL,
 316                         S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN);
 317                 usleep_range(10000, 15000);
 318 
 319                 if (!memcmp(read_regs, regs, sizeof(read_regs)))
 320                         break;
 321                 cobalt_dbg(1, "retry: %6ph\n", read_regs);
 322         }
 323         if (2 - retries)
 324                 cobalt_info("Needed %d retries\n", 2 - retries);
 325 
 326         return true;
 327 }

/* [<][>][^][v][top][bottom][index][help] */