root/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c

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

DEFINITIONS

This source file includes following definitions.
  1. read_vco
  2. read_clk
  3. read_pll
  4. gt215_clk_read
  5. gt215_clk_info
  6. gt215_pll_info
  7. calc_clk
  8. calc_host
  9. gt215_clk_pre
  10. gt215_clk_post
  11. disable_clk_src
  12. prog_pll
  13. prog_clk
  14. prog_host
  15. prog_core
  16. gt215_clk_calc
  17. gt215_clk_prog
  18. gt215_clk_tidy
  19. gt215_clk_new

   1 /*
   2  * Copyright 2012 Red Hat Inc.
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice shall be included in
  12  * all copies or substantial portions of the Software.
  13  *
  14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20  * OTHER DEALINGS IN THE SOFTWARE.
  21  *
  22  * Authors: Ben Skeggs
  23  *          Roy Spliet
  24  */
  25 #define gt215_clk(p) container_of((p), struct gt215_clk, base)
  26 #include "gt215.h"
  27 #include "pll.h"
  28 
  29 #include <engine/fifo.h>
  30 #include <subdev/bios.h>
  31 #include <subdev/bios/pll.h>
  32 #include <subdev/timer.h>
  33 
  34 struct gt215_clk {
  35         struct nvkm_clk base;
  36         struct gt215_clk_info eng[nv_clk_src_max];
  37 };
  38 
  39 static u32 read_clk(struct gt215_clk *, int, bool);
  40 static u32 read_pll(struct gt215_clk *, int, u32);
  41 
  42 static u32
  43 read_vco(struct gt215_clk *clk, int idx)
  44 {
  45         struct nvkm_device *device = clk->base.subdev.device;
  46         u32 sctl = nvkm_rd32(device, 0x4120 + (idx * 4));
  47 
  48         switch (sctl & 0x00000030) {
  49         case 0x00000000:
  50                 return device->crystal;
  51         case 0x00000020:
  52                 return read_pll(clk, 0x41, 0x00e820);
  53         case 0x00000030:
  54                 return read_pll(clk, 0x42, 0x00e8a0);
  55         default:
  56                 return 0;
  57         }
  58 }
  59 
  60 static u32
  61 read_clk(struct gt215_clk *clk, int idx, bool ignore_en)
  62 {
  63         struct nvkm_device *device = clk->base.subdev.device;
  64         u32 sctl, sdiv, sclk;
  65 
  66         /* refclk for the 0xe8xx plls is a fixed frequency */
  67         if (idx >= 0x40) {
  68                 if (device->chipset == 0xaf) {
  69                         /* no joke.. seriously.. sigh.. */
  70                         return nvkm_rd32(device, 0x00471c) * 1000;
  71                 }
  72 
  73                 return device->crystal;
  74         }
  75 
  76         sctl = nvkm_rd32(device, 0x4120 + (idx * 4));
  77         if (!ignore_en && !(sctl & 0x00000100))
  78                 return 0;
  79 
  80         /* out_alt */
  81         if (sctl & 0x00000400)
  82                 return 108000;
  83 
  84         /* vco_out */
  85         switch (sctl & 0x00003000) {
  86         case 0x00000000:
  87                 if (!(sctl & 0x00000200))
  88                         return device->crystal;
  89                 return 0;
  90         case 0x00002000:
  91                 if (sctl & 0x00000040)
  92                         return 108000;
  93                 return 100000;
  94         case 0x00003000:
  95                 /* vco_enable */
  96                 if (!(sctl & 0x00000001))
  97                         return 0;
  98 
  99                 sclk = read_vco(clk, idx);
 100                 sdiv = ((sctl & 0x003f0000) >> 16) + 2;
 101                 return (sclk * 2) / sdiv;
 102         default:
 103                 return 0;
 104         }
 105 }
 106 
 107 static u32
 108 read_pll(struct gt215_clk *clk, int idx, u32 pll)
 109 {
 110         struct nvkm_device *device = clk->base.subdev.device;
 111         u32 ctrl = nvkm_rd32(device, pll + 0);
 112         u32 sclk = 0, P = 1, N = 1, M = 1;
 113         u32 MP;
 114 
 115         if (!(ctrl & 0x00000008)) {
 116                 if (ctrl & 0x00000001) {
 117                         u32 coef = nvkm_rd32(device, pll + 4);
 118                         M = (coef & 0x000000ff) >> 0;
 119                         N = (coef & 0x0000ff00) >> 8;
 120                         P = (coef & 0x003f0000) >> 16;
 121 
 122                         /* no post-divider on these..
 123                          * XXX: it looks more like two post-"dividers" that
 124                          * cross each other out in the default RPLL config */
 125                         if ((pll & 0x00ff00) == 0x00e800)
 126                                 P = 1;
 127 
 128                         sclk = read_clk(clk, 0x00 + idx, false);
 129                 }
 130         } else {
 131                 sclk = read_clk(clk, 0x10 + idx, false);
 132         }
 133 
 134         MP = M * P;
 135 
 136         if (!MP)
 137                 return 0;
 138 
 139         return sclk * N / MP;
 140 }
 141 
 142 static int
 143 gt215_clk_read(struct nvkm_clk *base, enum nv_clk_src src)
 144 {
 145         struct gt215_clk *clk = gt215_clk(base);
 146         struct nvkm_subdev *subdev = &clk->base.subdev;
 147         struct nvkm_device *device = subdev->device;
 148         u32 hsrc;
 149 
 150         switch (src) {
 151         case nv_clk_src_crystal:
 152                 return device->crystal;
 153         case nv_clk_src_core:
 154         case nv_clk_src_core_intm:
 155                 return read_pll(clk, 0x00, 0x4200);
 156         case nv_clk_src_shader:
 157                 return read_pll(clk, 0x01, 0x4220);
 158         case nv_clk_src_mem:
 159                 return read_pll(clk, 0x02, 0x4000);
 160         case nv_clk_src_disp:
 161                 return read_clk(clk, 0x20, false);
 162         case nv_clk_src_vdec:
 163                 return read_clk(clk, 0x21, false);
 164         case nv_clk_src_pmu:
 165                 return read_clk(clk, 0x25, false);
 166         case nv_clk_src_host:
 167                 hsrc = (nvkm_rd32(device, 0xc040) & 0x30000000) >> 28;
 168                 switch (hsrc) {
 169                 case 0:
 170                         return read_clk(clk, 0x1d, false);
 171                 case 2:
 172                 case 3:
 173                         return 277000;
 174                 default:
 175                         nvkm_error(subdev, "unknown HOST clock source %d\n", hsrc);
 176                         return -EINVAL;
 177                 }
 178         default:
 179                 nvkm_error(subdev, "invalid clock source %d\n", src);
 180                 return -EINVAL;
 181         }
 182 
 183         return 0;
 184 }
 185 
 186 static int
 187 gt215_clk_info(struct nvkm_clk *base, int idx, u32 khz,
 188                struct gt215_clk_info *info)
 189 {
 190         struct gt215_clk *clk = gt215_clk(base);
 191         u32 oclk, sclk, sdiv;
 192         s32 diff;
 193 
 194         info->clk = 0;
 195 
 196         switch (khz) {
 197         case 27000:
 198                 info->clk = 0x00000100;
 199                 return khz;
 200         case 100000:
 201                 info->clk = 0x00002100;
 202                 return khz;
 203         case 108000:
 204                 info->clk = 0x00002140;
 205                 return khz;
 206         default:
 207                 sclk = read_vco(clk, idx);
 208                 sdiv = min((sclk * 2) / khz, (u32)65);
 209                 oclk = (sclk * 2) / sdiv;
 210                 diff = ((khz + 3000) - oclk);
 211 
 212                 /* When imprecise, play it safe and aim for a clock lower than
 213                  * desired rather than higher */
 214                 if (diff < 0) {
 215                         sdiv++;
 216                         oclk = (sclk * 2) / sdiv;
 217                 }
 218 
 219                 /* divider can go as low as 2, limited here because NVIDIA
 220                  * and the VBIOS on my NVA8 seem to prefer using the PLL
 221                  * for 810MHz - is there a good reason?
 222                  * XXX: PLLs with refclk 810MHz?  */
 223                 if (sdiv > 4) {
 224                         info->clk = (((sdiv - 2) << 16) | 0x00003100);
 225                         return oclk;
 226                 }
 227 
 228                 break;
 229         }
 230 
 231         return -ERANGE;
 232 }
 233 
 234 int
 235 gt215_pll_info(struct nvkm_clk *base, int idx, u32 pll, u32 khz,
 236                struct gt215_clk_info *info)
 237 {
 238         struct gt215_clk *clk = gt215_clk(base);
 239         struct nvkm_subdev *subdev = &clk->base.subdev;
 240         struct nvbios_pll limits;
 241         int P, N, M, diff;
 242         int ret;
 243 
 244         info->pll = 0;
 245 
 246         /* If we can get a within [-2, 3) MHz of a divider, we'll disable the
 247          * PLL and use the divider instead. */
 248         ret = gt215_clk_info(&clk->base, idx, khz, info);
 249         diff = khz - ret;
 250         if (!pll || (diff >= -2000 && diff < 3000)) {
 251                 goto out;
 252         }
 253 
 254         /* Try with PLL */
 255         ret = nvbios_pll_parse(subdev->device->bios, pll, &limits);
 256         if (ret)
 257                 return ret;
 258 
 259         ret = gt215_clk_info(&clk->base, idx - 0x10, limits.refclk, info);
 260         if (ret != limits.refclk)
 261                 return -EINVAL;
 262 
 263         ret = gt215_pll_calc(subdev, &limits, khz, &N, NULL, &M, &P);
 264         if (ret >= 0) {
 265                 info->pll = (P << 16) | (N << 8) | M;
 266         }
 267 
 268 out:
 269         info->fb_delay = max(((khz + 7566) / 15133), (u32) 18);
 270         return ret ? ret : -ERANGE;
 271 }
 272 
 273 static int
 274 calc_clk(struct gt215_clk *clk, struct nvkm_cstate *cstate,
 275          int idx, u32 pll, int dom)
 276 {
 277         int ret = gt215_pll_info(&clk->base, idx, pll, cstate->domain[dom],
 278                                  &clk->eng[dom]);
 279         if (ret >= 0)
 280                 return 0;
 281         return ret;
 282 }
 283 
 284 static int
 285 calc_host(struct gt215_clk *clk, struct nvkm_cstate *cstate)
 286 {
 287         int ret = 0;
 288         u32 kHz = cstate->domain[nv_clk_src_host];
 289         struct gt215_clk_info *info = &clk->eng[nv_clk_src_host];
 290 
 291         if (kHz == 277000) {
 292                 info->clk = 0;
 293                 info->host_out = NVA3_HOST_277;
 294                 return 0;
 295         }
 296 
 297         info->host_out = NVA3_HOST_CLK;
 298 
 299         ret = gt215_clk_info(&clk->base, 0x1d, kHz, info);
 300         if (ret >= 0)
 301                 return 0;
 302 
 303         return ret;
 304 }
 305 
 306 int
 307 gt215_clk_pre(struct nvkm_clk *clk, unsigned long *flags)
 308 {
 309         struct nvkm_device *device = clk->subdev.device;
 310         struct nvkm_fifo *fifo = device->fifo;
 311 
 312         /* halt and idle execution engines */
 313         nvkm_mask(device, 0x020060, 0x00070000, 0x00000000);
 314         nvkm_mask(device, 0x002504, 0x00000001, 0x00000001);
 315         /* Wait until the interrupt handler is finished */
 316         if (nvkm_msec(device, 2000,
 317                 if (!nvkm_rd32(device, 0x000100))
 318                         break;
 319         ) < 0)
 320                 return -EBUSY;
 321 
 322         if (fifo)
 323                 nvkm_fifo_pause(fifo, flags);
 324 
 325         if (nvkm_msec(device, 2000,
 326                 if (nvkm_rd32(device, 0x002504) & 0x00000010)
 327                         break;
 328         ) < 0)
 329                 return -EIO;
 330 
 331         if (nvkm_msec(device, 2000,
 332                 u32 tmp = nvkm_rd32(device, 0x00251c) & 0x0000003f;
 333                 if (tmp == 0x0000003f)
 334                         break;
 335         ) < 0)
 336                 return -EIO;
 337 
 338         return 0;
 339 }
 340 
 341 void
 342 gt215_clk_post(struct nvkm_clk *clk, unsigned long *flags)
 343 {
 344         struct nvkm_device *device = clk->subdev.device;
 345         struct nvkm_fifo *fifo = device->fifo;
 346 
 347         if (fifo && flags)
 348                 nvkm_fifo_start(fifo, flags);
 349 
 350         nvkm_mask(device, 0x002504, 0x00000001, 0x00000000);
 351         nvkm_mask(device, 0x020060, 0x00070000, 0x00040000);
 352 }
 353 
 354 static void
 355 disable_clk_src(struct gt215_clk *clk, u32 src)
 356 {
 357         struct nvkm_device *device = clk->base.subdev.device;
 358         nvkm_mask(device, src, 0x00000100, 0x00000000);
 359         nvkm_mask(device, src, 0x00000001, 0x00000000);
 360 }
 361 
 362 static void
 363 prog_pll(struct gt215_clk *clk, int idx, u32 pll, int dom)
 364 {
 365         struct gt215_clk_info *info = &clk->eng[dom];
 366         struct nvkm_device *device = clk->base.subdev.device;
 367         const u32 src0 = 0x004120 + (idx * 4);
 368         const u32 src1 = 0x004160 + (idx * 4);
 369         const u32 ctrl = pll + 0;
 370         const u32 coef = pll + 4;
 371         u32 bypass;
 372 
 373         if (info->pll) {
 374                 /* Always start from a non-PLL clock */
 375                 bypass = nvkm_rd32(device, ctrl)  & 0x00000008;
 376                 if (!bypass) {
 377                         nvkm_mask(device, src1, 0x00000101, 0x00000101);
 378                         nvkm_mask(device, ctrl, 0x00000008, 0x00000008);
 379                         udelay(20);
 380                 }
 381 
 382                 nvkm_mask(device, src0, 0x003f3141, 0x00000101 | info->clk);
 383                 nvkm_wr32(device, coef, info->pll);
 384                 nvkm_mask(device, ctrl, 0x00000015, 0x00000015);
 385                 nvkm_mask(device, ctrl, 0x00000010, 0x00000000);
 386                 if (nvkm_msec(device, 2000,
 387                         if (nvkm_rd32(device, ctrl) & 0x00020000)
 388                                 break;
 389                 ) < 0) {
 390                         nvkm_mask(device, ctrl, 0x00000010, 0x00000010);
 391                         nvkm_mask(device, src0, 0x00000101, 0x00000000);
 392                         return;
 393                 }
 394                 nvkm_mask(device, ctrl, 0x00000010, 0x00000010);
 395                 nvkm_mask(device, ctrl, 0x00000008, 0x00000000);
 396                 disable_clk_src(clk, src1);
 397         } else {
 398                 nvkm_mask(device, src1, 0x003f3141, 0x00000101 | info->clk);
 399                 nvkm_mask(device, ctrl, 0x00000018, 0x00000018);
 400                 udelay(20);
 401                 nvkm_mask(device, ctrl, 0x00000001, 0x00000000);
 402                 disable_clk_src(clk, src0);
 403         }
 404 }
 405 
 406 static void
 407 prog_clk(struct gt215_clk *clk, int idx, int dom)
 408 {
 409         struct gt215_clk_info *info = &clk->eng[dom];
 410         struct nvkm_device *device = clk->base.subdev.device;
 411         nvkm_mask(device, 0x004120 + (idx * 4), 0x003f3141, 0x00000101 | info->clk);
 412 }
 413 
 414 static void
 415 prog_host(struct gt215_clk *clk)
 416 {
 417         struct gt215_clk_info *info = &clk->eng[nv_clk_src_host];
 418         struct nvkm_device *device = clk->base.subdev.device;
 419         u32 hsrc = (nvkm_rd32(device, 0xc040));
 420 
 421         switch (info->host_out) {
 422         case NVA3_HOST_277:
 423                 if ((hsrc & 0x30000000) == 0) {
 424                         nvkm_wr32(device, 0xc040, hsrc | 0x20000000);
 425                         disable_clk_src(clk, 0x4194);
 426                 }
 427                 break;
 428         case NVA3_HOST_CLK:
 429                 prog_clk(clk, 0x1d, nv_clk_src_host);
 430                 if ((hsrc & 0x30000000) >= 0x20000000) {
 431                         nvkm_wr32(device, 0xc040, hsrc & ~0x30000000);
 432                 }
 433                 break;
 434         default:
 435                 break;
 436         }
 437 
 438         /* This seems to be a clock gating factor on idle, always set to 64 */
 439         nvkm_wr32(device, 0xc044, 0x3e);
 440 }
 441 
 442 static void
 443 prog_core(struct gt215_clk *clk, int dom)
 444 {
 445         struct gt215_clk_info *info = &clk->eng[dom];
 446         struct nvkm_device *device = clk->base.subdev.device;
 447         u32 fb_delay = nvkm_rd32(device, 0x10002c);
 448 
 449         if (fb_delay < info->fb_delay)
 450                 nvkm_wr32(device, 0x10002c, info->fb_delay);
 451 
 452         prog_pll(clk, 0x00, 0x004200, dom);
 453 
 454         if (fb_delay > info->fb_delay)
 455                 nvkm_wr32(device, 0x10002c, info->fb_delay);
 456 }
 457 
 458 static int
 459 gt215_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate)
 460 {
 461         struct gt215_clk *clk = gt215_clk(base);
 462         struct gt215_clk_info *core = &clk->eng[nv_clk_src_core];
 463         int ret;
 464 
 465         if ((ret = calc_clk(clk, cstate, 0x10, 0x4200, nv_clk_src_core)) ||
 466             (ret = calc_clk(clk, cstate, 0x11, 0x4220, nv_clk_src_shader)) ||
 467             (ret = calc_clk(clk, cstate, 0x20, 0x0000, nv_clk_src_disp)) ||
 468             (ret = calc_clk(clk, cstate, 0x21, 0x0000, nv_clk_src_vdec)) ||
 469             (ret = calc_host(clk, cstate)))
 470                 return ret;
 471 
 472         /* XXX: Should be reading the highest bit in the VBIOS clock to decide
 473          * whether to use a PLL or not... but using a PLL defeats the purpose */
 474         if (core->pll) {
 475                 ret = gt215_clk_info(&clk->base, 0x10,
 476                                      cstate->domain[nv_clk_src_core_intm],
 477                                      &clk->eng[nv_clk_src_core_intm]);
 478                 if (ret < 0)
 479                         return ret;
 480         }
 481 
 482         return 0;
 483 }
 484 
 485 static int
 486 gt215_clk_prog(struct nvkm_clk *base)
 487 {
 488         struct gt215_clk *clk = gt215_clk(base);
 489         struct gt215_clk_info *core = &clk->eng[nv_clk_src_core];
 490         int ret = 0;
 491         unsigned long flags;
 492         unsigned long *f = &flags;
 493 
 494         ret = gt215_clk_pre(&clk->base, f);
 495         if (ret)
 496                 goto out;
 497 
 498         if (core->pll)
 499                 prog_core(clk, nv_clk_src_core_intm);
 500 
 501         prog_core(clk,  nv_clk_src_core);
 502         prog_pll(clk, 0x01, 0x004220, nv_clk_src_shader);
 503         prog_clk(clk, 0x20, nv_clk_src_disp);
 504         prog_clk(clk, 0x21, nv_clk_src_vdec);
 505         prog_host(clk);
 506 
 507 out:
 508         if (ret == -EBUSY)
 509                 f = NULL;
 510 
 511         gt215_clk_post(&clk->base, f);
 512         return ret;
 513 }
 514 
 515 static void
 516 gt215_clk_tidy(struct nvkm_clk *base)
 517 {
 518 }
 519 
 520 static const struct nvkm_clk_func
 521 gt215_clk = {
 522         .read = gt215_clk_read,
 523         .calc = gt215_clk_calc,
 524         .prog = gt215_clk_prog,
 525         .tidy = gt215_clk_tidy,
 526         .domains = {
 527                 { nv_clk_src_crystal  , 0xff },
 528                 { nv_clk_src_core     , 0x00, 0, "core", 1000 },
 529                 { nv_clk_src_shader   , 0x01, 0, "shader", 1000 },
 530                 { nv_clk_src_mem      , 0x02, 0, "memory", 1000 },
 531                 { nv_clk_src_vdec     , 0x03 },
 532                 { nv_clk_src_disp     , 0x04 },
 533                 { nv_clk_src_host     , 0x05 },
 534                 { nv_clk_src_core_intm, 0x06 },
 535                 { nv_clk_src_max }
 536         }
 537 };
 538 
 539 int
 540 gt215_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk)
 541 {
 542         struct gt215_clk *clk;
 543 
 544         if (!(clk = kzalloc(sizeof(*clk), GFP_KERNEL)))
 545                 return -ENOMEM;
 546         *pclk = &clk->base;
 547 
 548         return nvkm_clk_ctor(&gt215_clk, device, index, true, &clk->base);
 549 }

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