cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gt215.c (13658B)


      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}