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

pll.c (12113B)


      1/*
      2 * Copyright 2005-2006 Erik Waling
      3 * Copyright 2006 Stephane Marchesin
      4 * Copyright 2007-2009 Stuart Bennett
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a
      7 * copy of this software and associated documentation files (the "Software"),
      8 * to deal in the Software without restriction, including without limitation
      9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10 * and/or sell copies of the Software, and to permit persons to whom the
     11 * Software is furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice shall be included in
     14 * all copies or substantial portions of the Software.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
     21 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22 * SOFTWARE.
     23 */
     24#include <subdev/bios.h>
     25#include <subdev/bios/bit.h>
     26#include <subdev/bios/bmp.h>
     27#include <subdev/bios/pll.h>
     28#include <subdev/vga.h>
     29
     30
     31struct pll_mapping {
     32	u8  type;
     33	u32 reg;
     34};
     35
     36static struct pll_mapping
     37nv04_pll_mapping[] = {
     38	{ PLL_CORE  , 0x680500 },
     39	{ PLL_MEMORY, 0x680504 },
     40	{ PLL_VPLL0 , 0x680508 },
     41	{ PLL_VPLL1 , 0x680520 },
     42	{}
     43};
     44
     45static struct pll_mapping
     46nv40_pll_mapping[] = {
     47	{ PLL_CORE  , 0x004000 },
     48	{ PLL_MEMORY, 0x004020 },
     49	{ PLL_VPLL0 , 0x680508 },
     50	{ PLL_VPLL1 , 0x680520 },
     51	{}
     52};
     53
     54static struct pll_mapping
     55nv50_pll_mapping[] = {
     56	{ PLL_CORE  , 0x004028 },
     57	{ PLL_SHADER, 0x004020 },
     58	{ PLL_UNK03 , 0x004000 },
     59	{ PLL_MEMORY, 0x004008 },
     60	{ PLL_UNK40 , 0x00e810 },
     61	{ PLL_UNK41 , 0x00e818 },
     62	{ PLL_UNK42 , 0x00e824 },
     63	{ PLL_VPLL0 , 0x614100 },
     64	{ PLL_VPLL1 , 0x614900 },
     65	{}
     66};
     67
     68static struct pll_mapping
     69g84_pll_mapping[] = {
     70	{ PLL_CORE  , 0x004028 },
     71	{ PLL_SHADER, 0x004020 },
     72	{ PLL_MEMORY, 0x004008 },
     73	{ PLL_VDEC  , 0x004030 },
     74	{ PLL_UNK41 , 0x00e818 },
     75	{ PLL_VPLL0 , 0x614100 },
     76	{ PLL_VPLL1 , 0x614900 },
     77	{}
     78};
     79
     80static u32
     81pll_limits_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
     82{
     83	struct bit_entry bit_C;
     84	u32 data = 0x0000;
     85
     86	if (!bit_entry(bios, 'C', &bit_C)) {
     87		if (bit_C.version == 1 && bit_C.length >= 10)
     88			data = nvbios_rd16(bios, bit_C.offset + 8);
     89		if (bit_C.version == 2 && bit_C.length >= 4)
     90			data = nvbios_rd32(bios, bit_C.offset + 0);
     91		if (data) {
     92			*ver = nvbios_rd08(bios, data + 0);
     93			*hdr = nvbios_rd08(bios, data + 1);
     94			*len = nvbios_rd08(bios, data + 2);
     95			*cnt = nvbios_rd08(bios, data + 3);
     96			return data;
     97		}
     98	}
     99
    100	if (bmp_version(bios) >= 0x0524) {
    101		data = nvbios_rd16(bios, bios->bmp_offset + 142);
    102		if (data) {
    103			*ver = nvbios_rd08(bios, data + 0);
    104			*hdr = 1;
    105			*cnt = 1;
    106			*len = 0x18;
    107			return data;
    108		}
    109	}
    110
    111	*ver = 0x00;
    112	return data;
    113}
    114
    115static struct pll_mapping *
    116pll_map(struct nvkm_bios *bios)
    117{
    118	struct nvkm_device *device = bios->subdev.device;
    119	switch (device->card_type) {
    120	case NV_04:
    121	case NV_10:
    122	case NV_11:
    123	case NV_20:
    124	case NV_30:
    125		return nv04_pll_mapping;
    126	case NV_40:
    127		return nv40_pll_mapping;
    128	case NV_50:
    129		if (device->chipset == 0x50)
    130			return nv50_pll_mapping;
    131		else
    132		if (device->chipset <  0xa3 ||
    133		    device->chipset == 0xaa ||
    134		    device->chipset == 0xac)
    135			return g84_pll_mapping;
    136		fallthrough;
    137	default:
    138		return NULL;
    139	}
    140}
    141
    142static u32
    143pll_map_reg(struct nvkm_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len)
    144{
    145	struct pll_mapping *map;
    146	u8  hdr, cnt;
    147	u32 data;
    148
    149	data = pll_limits_table(bios, ver, &hdr, &cnt, len);
    150	if (data && *ver >= 0x30) {
    151		data += hdr;
    152		while (cnt--) {
    153			if (nvbios_rd32(bios, data + 3) == reg) {
    154				*type = nvbios_rd08(bios, data + 0);
    155				return data;
    156			}
    157			data += *len;
    158		}
    159		return 0x0000;
    160	}
    161
    162	map = pll_map(bios);
    163	while (map && map->reg) {
    164		if (map->reg == reg && *ver >= 0x20) {
    165			u32 addr = (data += hdr);
    166			*type = map->type;
    167			while (cnt--) {
    168				if (nvbios_rd32(bios, data) == map->reg)
    169					return data;
    170				data += *len;
    171			}
    172			return addr;
    173		} else
    174		if (map->reg == reg) {
    175			*type = map->type;
    176			return data + 1;
    177		}
    178		map++;
    179	}
    180
    181	return 0x0000;
    182}
    183
    184static u32
    185pll_map_type(struct nvkm_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len)
    186{
    187	struct pll_mapping *map;
    188	u8  hdr, cnt;
    189	u32 data;
    190
    191	data = pll_limits_table(bios, ver, &hdr, &cnt, len);
    192	if (data && *ver >= 0x30) {
    193		data += hdr;
    194		while (cnt--) {
    195			if (nvbios_rd08(bios, data + 0) == type) {
    196				if (*ver < 0x50)
    197					*reg = nvbios_rd32(bios, data + 3);
    198				else
    199					*reg = 0;
    200				return data;
    201			}
    202			data += *len;
    203		}
    204		return 0x0000;
    205	}
    206
    207	map = pll_map(bios);
    208	while (map && map->reg) {
    209		if (map->type == type && *ver >= 0x20) {
    210			u32 addr = (data += hdr);
    211			*reg = map->reg;
    212			while (cnt--) {
    213				if (nvbios_rd32(bios, data) == map->reg)
    214					return data;
    215				data += *len;
    216			}
    217			return addr;
    218		} else
    219		if (map->type == type) {
    220			*reg = map->reg;
    221			return data + 1;
    222		}
    223		map++;
    224	}
    225
    226	return 0x0000;
    227}
    228
    229int
    230nvbios_pll_parse(struct nvkm_bios *bios, u32 type, struct nvbios_pll *info)
    231{
    232	struct nvkm_subdev *subdev = &bios->subdev;
    233	struct nvkm_device *device = subdev->device;
    234	u8  ver, len;
    235	u32 reg = type;
    236	u32 data;
    237
    238	if (type > PLL_MAX) {
    239		reg  = type;
    240		data = pll_map_reg(bios, reg, &type, &ver, &len);
    241	} else {
    242		data = pll_map_type(bios, type, &reg, &ver, &len);
    243	}
    244
    245	if (ver && !data)
    246		return -ENOENT;
    247
    248	memset(info, 0, sizeof(*info));
    249	info->type = type;
    250	info->reg = reg;
    251
    252	switch (ver) {
    253	case 0x00:
    254		break;
    255	case 0x10:
    256	case 0x11:
    257		info->vco1.min_freq = nvbios_rd32(bios, data + 0);
    258		info->vco1.max_freq = nvbios_rd32(bios, data + 4);
    259		info->vco2.min_freq = nvbios_rd32(bios, data + 8);
    260		info->vco2.max_freq = nvbios_rd32(bios, data + 12);
    261		info->vco1.min_inputfreq = nvbios_rd32(bios, data + 16);
    262		info->vco2.min_inputfreq = nvbios_rd32(bios, data + 20);
    263		info->vco1.max_inputfreq = INT_MAX;
    264		info->vco2.max_inputfreq = INT_MAX;
    265
    266		info->max_p = 0x7;
    267		info->max_p_usable = 0x6;
    268
    269		/* these values taken from nv30/31/36 */
    270		switch (bios->version.chip) {
    271		case 0x36:
    272			info->vco1.min_n = 0x5;
    273			break;
    274		default:
    275			info->vco1.min_n = 0x1;
    276			break;
    277		}
    278		info->vco1.max_n = 0xff;
    279		info->vco1.min_m = 0x1;
    280		info->vco1.max_m = 0xd;
    281
    282		/*
    283		 * On nv30, 31, 36 (i.e. all cards with two stage PLLs with this
    284		 * table version (apart from nv35)), N2 is compared to
    285		 * maxN2 (0x46) and 10 * maxM2 (0x4), so set maxN2 to 0x28 and
    286		 * save a comparison
    287		 */
    288		info->vco2.min_n = 0x4;
    289		switch (bios->version.chip) {
    290		case 0x30:
    291		case 0x35:
    292			info->vco2.max_n = 0x1f;
    293			break;
    294		default:
    295			info->vco2.max_n = 0x28;
    296			break;
    297		}
    298		info->vco2.min_m = 0x1;
    299		info->vco2.max_m = 0x4;
    300		break;
    301	case 0x20:
    302	case 0x21:
    303		info->vco1.min_freq = nvbios_rd16(bios, data + 4) * 1000;
    304		info->vco1.max_freq = nvbios_rd16(bios, data + 6) * 1000;
    305		info->vco2.min_freq = nvbios_rd16(bios, data + 8) * 1000;
    306		info->vco2.max_freq = nvbios_rd16(bios, data + 10) * 1000;
    307		info->vco1.min_inputfreq = nvbios_rd16(bios, data + 12) * 1000;
    308		info->vco2.min_inputfreq = nvbios_rd16(bios, data + 14) * 1000;
    309		info->vco1.max_inputfreq = nvbios_rd16(bios, data + 16) * 1000;
    310		info->vco2.max_inputfreq = nvbios_rd16(bios, data + 18) * 1000;
    311		info->vco1.min_n = nvbios_rd08(bios, data + 20);
    312		info->vco1.max_n = nvbios_rd08(bios, data + 21);
    313		info->vco1.min_m = nvbios_rd08(bios, data + 22);
    314		info->vco1.max_m = nvbios_rd08(bios, data + 23);
    315		info->vco2.min_n = nvbios_rd08(bios, data + 24);
    316		info->vco2.max_n = nvbios_rd08(bios, data + 25);
    317		info->vco2.min_m = nvbios_rd08(bios, data + 26);
    318		info->vco2.max_m = nvbios_rd08(bios, data + 27);
    319
    320		info->max_p = nvbios_rd08(bios, data + 29);
    321		info->max_p_usable = info->max_p;
    322		if (bios->version.chip < 0x60)
    323			info->max_p_usable = 0x6;
    324		info->bias_p = nvbios_rd08(bios, data + 30);
    325
    326		if (len > 0x22)
    327			info->refclk = nvbios_rd32(bios, data + 31);
    328		break;
    329	case 0x30:
    330		data = nvbios_rd16(bios, data + 1);
    331
    332		info->vco1.min_freq = nvbios_rd16(bios, data + 0) * 1000;
    333		info->vco1.max_freq = nvbios_rd16(bios, data + 2) * 1000;
    334		info->vco2.min_freq = nvbios_rd16(bios, data + 4) * 1000;
    335		info->vco2.max_freq = nvbios_rd16(bios, data + 6) * 1000;
    336		info->vco1.min_inputfreq = nvbios_rd16(bios, data + 8) * 1000;
    337		info->vco2.min_inputfreq = nvbios_rd16(bios, data + 10) * 1000;
    338		info->vco1.max_inputfreq = nvbios_rd16(bios, data + 12) * 1000;
    339		info->vco2.max_inputfreq = nvbios_rd16(bios, data + 14) * 1000;
    340		info->vco1.min_n = nvbios_rd08(bios, data + 16);
    341		info->vco1.max_n = nvbios_rd08(bios, data + 17);
    342		info->vco1.min_m = nvbios_rd08(bios, data + 18);
    343		info->vco1.max_m = nvbios_rd08(bios, data + 19);
    344		info->vco2.min_n = nvbios_rd08(bios, data + 20);
    345		info->vco2.max_n = nvbios_rd08(bios, data + 21);
    346		info->vco2.min_m = nvbios_rd08(bios, data + 22);
    347		info->vco2.max_m = nvbios_rd08(bios, data + 23);
    348		info->max_p_usable = info->max_p = nvbios_rd08(bios, data + 25);
    349		info->bias_p = nvbios_rd08(bios, data + 27);
    350		info->refclk = nvbios_rd32(bios, data + 28);
    351		break;
    352	case 0x40:
    353		info->refclk = nvbios_rd16(bios, data + 9) * 1000;
    354		data = nvbios_rd16(bios, data + 1);
    355
    356		info->vco1.min_freq = nvbios_rd16(bios, data + 0) * 1000;
    357		info->vco1.max_freq = nvbios_rd16(bios, data + 2) * 1000;
    358		info->vco1.min_inputfreq = nvbios_rd16(bios, data + 4) * 1000;
    359		info->vco1.max_inputfreq = nvbios_rd16(bios, data + 6) * 1000;
    360		info->vco1.min_m = nvbios_rd08(bios, data + 8);
    361		info->vco1.max_m = nvbios_rd08(bios, data + 9);
    362		info->vco1.min_n = nvbios_rd08(bios, data + 10);
    363		info->vco1.max_n = nvbios_rd08(bios, data + 11);
    364		info->min_p = nvbios_rd08(bios, data + 12);
    365		info->max_p = nvbios_rd08(bios, data + 13);
    366		break;
    367	case 0x50:
    368		info->refclk = nvbios_rd16(bios, data + 1) * 1000;
    369		/* info->refclk_alt = nvbios_rd16(bios, data + 3) * 1000; */
    370		info->vco1.min_freq = nvbios_rd16(bios, data + 5) * 1000;
    371		info->vco1.max_freq = nvbios_rd16(bios, data + 7) * 1000;
    372		info->vco1.min_inputfreq = nvbios_rd16(bios, data + 9) * 1000;
    373		info->vco1.max_inputfreq = nvbios_rd16(bios, data + 11) * 1000;
    374		info->vco1.min_m = nvbios_rd08(bios, data + 13);
    375		info->vco1.max_m = nvbios_rd08(bios, data + 14);
    376		info->vco1.min_n = nvbios_rd08(bios, data + 15);
    377		info->vco1.max_n = nvbios_rd08(bios, data + 16);
    378		info->min_p = nvbios_rd08(bios, data + 17);
    379		info->max_p = nvbios_rd08(bios, data + 18);
    380		break;
    381	default:
    382		nvkm_error(subdev, "unknown pll limits version 0x%02x\n", ver);
    383		return -EINVAL;
    384	}
    385
    386	if (!info->refclk) {
    387		info->refclk = device->crystal;
    388		if (bios->version.chip == 0x51) {
    389			u32 sel_clk = nvkm_rd32(device, 0x680524);
    390			if ((info->reg == 0x680508 && sel_clk & 0x20) ||
    391			    (info->reg == 0x680520 && sel_clk & 0x80)) {
    392				if (nvkm_rdvgac(device, 0, 0x27) < 0xa3)
    393					info->refclk = 200000;
    394				else
    395					info->refclk = 25000;
    396			}
    397		}
    398	}
    399
    400	/*
    401	 * By now any valid limit table ought to have set a max frequency for
    402	 * vco1, so if it's zero it's either a pre limit table bios, or one
    403	 * with an empty limit table (seen on nv18)
    404	 */
    405	if (!info->vco1.max_freq) {
    406		info->vco1.max_freq = nvbios_rd32(bios, bios->bmp_offset + 67);
    407		info->vco1.min_freq = nvbios_rd32(bios, bios->bmp_offset + 71);
    408		if (bmp_version(bios) < 0x0506) {
    409			info->vco1.max_freq = 256000;
    410			info->vco1.min_freq = 128000;
    411		}
    412
    413		info->vco1.min_inputfreq = 0;
    414		info->vco1.max_inputfreq = INT_MAX;
    415		info->vco1.min_n = 0x1;
    416		info->vco1.max_n = 0xff;
    417		info->vco1.min_m = 0x1;
    418
    419		if (device->crystal == 13500) {
    420			/* nv05 does this, nv11 doesn't, nv10 unknown */
    421			if (bios->version.chip < 0x11)
    422				info->vco1.min_m = 0x7;
    423			info->vco1.max_m = 0xd;
    424		} else {
    425			if (bios->version.chip < 0x11)
    426				info->vco1.min_m = 0x8;
    427			info->vco1.max_m = 0xe;
    428		}
    429
    430		if (bios->version.chip <  0x17 ||
    431		    bios->version.chip == 0x1a ||
    432		    bios->version.chip == 0x20)
    433			info->max_p = 4;
    434		else
    435			info->max_p = 5;
    436		info->max_p_usable = info->max_p;
    437	}
    438
    439	return 0;
    440}