linux/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
<<
>>
Prefs
   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
  34struct gt215_clk {
  35        struct nvkm_clk base;
  36        struct gt215_clk_info eng[nv_clk_src_max];
  37};
  38
  39static u32 read_clk(struct gt215_clk *, int, bool);
  40static u32 read_pll(struct gt215_clk *, int, u32);
  41
  42static u32
  43read_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
  60static u32
  61read_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
 107static u32
 108read_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
 142static int
 143gt215_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
 186static int
 187gt215_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
 234int
 235gt215_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
 268out:
 269        info->fb_delay = max(((khz + 7566) / 15133), (u32) 18);
 270        return ret ? ret : -ERANGE;
 271}
 272
 273static int
 274calc_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
 284static int
 285calc_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
 306int
 307gt215_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
 341void
 342gt215_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
 354static void
 355disable_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
 362static void
 363prog_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
 406static void
 407prog_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
 414static void
 415prog_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
 442static void
 443prog_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
 458static int
 459gt215_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
 485static int
 486gt215_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
 507out:
 508        if (ret == -EBUSY)
 509                f = NULL;
 510
 511        gt215_clk_post(&clk->base, f);
 512        return ret;
 513}
 514
 515static void
 516gt215_clk_tidy(struct nvkm_clk *base)
 517{
 518}
 519
 520static const struct nvkm_clk_func
 521gt215_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
 539int
 540gt215_clk_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
 541              struct nvkm_clk **pclk)
 542{
 543        struct gt215_clk *clk;
 544
 545        if (!(clk = kzalloc(sizeof(*clk), GFP_KERNEL)))
 546                return -ENOMEM;
 547        *pclk = &clk->base;
 548
 549        return nvkm_clk_ctor(&gt215_clk, device, type, inst, true, &clk->base);
 550}
 551
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.