Home | History | Annotate | Line # | Download | only in bios
      1 /*	$NetBSD: nouveau_nvkm_subdev_bios_rammap.c,v 1.3 2021/12/18 23:45:38 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2013 Red Hat Inc.
      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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors: Ben Skeggs
     25  */
     26 #include <sys/cdefs.h>
     27 __KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_subdev_bios_rammap.c,v 1.3 2021/12/18 23:45:38 riastradh Exp $");
     28 
     29 #include <subdev/bios.h>
     30 #include <subdev/bios/bit.h>
     31 #include <subdev/bios/rammap.h>
     32 
     33 u32
     34 nvbios_rammapTe(struct nvkm_bios *bios, u8 *ver, u8 *hdr,
     35 		u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
     36 {
     37 	struct bit_entry bit_P;
     38 	u32 rammap = 0x0000;
     39 
     40 	if (!bit_entry(bios, 'P', &bit_P)) {
     41 		if (bit_P.version == 2)
     42 			rammap = nvbios_rd32(bios, bit_P.offset + 4);
     43 
     44 		if (rammap) {
     45 			*ver = nvbios_rd08(bios, rammap + 0);
     46 			switch (*ver) {
     47 			case 0x10:
     48 			case 0x11:
     49 				*hdr = nvbios_rd08(bios, rammap + 1);
     50 				*cnt = nvbios_rd08(bios, rammap + 5);
     51 				*len = nvbios_rd08(bios, rammap + 2);
     52 				*snr = nvbios_rd08(bios, rammap + 4);
     53 				*ssz = nvbios_rd08(bios, rammap + 3);
     54 				return rammap;
     55 			default:
     56 				break;
     57 			}
     58 		}
     59 	}
     60 
     61 	return 0x0000;
     62 }
     63 
     64 u32
     65 nvbios_rammapEe(struct nvkm_bios *bios, int idx,
     66 		u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
     67 {
     68 	u8  snr, ssz;
     69 	u32 rammap = nvbios_rammapTe(bios, ver, hdr, cnt, len, &snr, &ssz);
     70 	if (rammap && idx < *cnt) {
     71 		rammap = rammap + *hdr + (idx * (*len + (snr * ssz)));
     72 		*hdr = *len;
     73 		*cnt = snr;
     74 		*len = ssz;
     75 		return rammap;
     76 	}
     77 	return 0x0000;
     78 }
     79 
     80 /* Pretend a performance mode is also a rammap entry, helps coalesce entries
     81  * later on */
     82 u32
     83 nvbios_rammapEp_from_perf(struct nvkm_bios *bios, u32 data, u8 size,
     84 		struct nvbios_ramcfg *p)
     85 {
     86 	memset(p, 0x00, sizeof(*p));
     87 
     88 	p->rammap_00_16_20 = (nvbios_rd08(bios, data + 0x16) & 0x20) >> 5;
     89 	p->rammap_00_16_40 = (nvbios_rd08(bios, data + 0x16) & 0x40) >> 6;
     90 	p->rammap_00_17_02 = (nvbios_rd08(bios, data + 0x17) & 0x02) >> 1;
     91 
     92 	return data;
     93 }
     94 
     95 u32
     96 nvbios_rammapEp(struct nvkm_bios *bios, int idx,
     97 		u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ramcfg *p)
     98 {
     99 	u32 data = nvbios_rammapEe(bios, idx, ver, hdr, cnt, len), temp;
    100 	memset(p, 0x00, sizeof(*p));
    101 	p->rammap_ver = *ver;
    102 	p->rammap_hdr = *hdr;
    103 	switch (!!data * *ver) {
    104 	case 0x10:
    105 		p->rammap_min      =  nvbios_rd16(bios, data + 0x00);
    106 		p->rammap_max      =  nvbios_rd16(bios, data + 0x02);
    107 		p->rammap_10_04_02 = (nvbios_rd08(bios, data + 0x04) & 0x02) >> 1;
    108 		p->rammap_10_04_08 = (nvbios_rd08(bios, data + 0x04) & 0x08) >> 3;
    109 		break;
    110 	case 0x11:
    111 		p->rammap_min      =  nvbios_rd16(bios, data + 0x00);
    112 		p->rammap_max      =  nvbios_rd16(bios, data + 0x02);
    113 		p->rammap_11_08_01 = (nvbios_rd08(bios, data + 0x08) & 0x01) >> 0;
    114 		p->rammap_11_08_0c = (nvbios_rd08(bios, data + 0x08) & 0x0c) >> 2;
    115 		p->rammap_11_08_10 = (nvbios_rd08(bios, data + 0x08) & 0x10) >> 4;
    116 		temp = nvbios_rd32(bios, data + 0x09);
    117 		p->rammap_11_09_01ff = (temp & 0x000001ff) >> 0;
    118 		p->rammap_11_0a_03fe = (temp & 0x0003fe00) >> 9;
    119 		p->rammap_11_0a_0400 = (temp & 0x00040000) >> 18;
    120 		p->rammap_11_0a_0800 = (temp & 0x00080000) >> 19;
    121 		p->rammap_11_0b_01f0 = (temp & 0x01f00000) >> 20;
    122 		p->rammap_11_0b_0200 = (temp & 0x02000000) >> 25;
    123 		p->rammap_11_0b_0400 = (temp & 0x04000000) >> 26;
    124 		p->rammap_11_0b_0800 = (temp & 0x08000000) >> 27;
    125 		p->rammap_11_0d    =  nvbios_rd08(bios, data + 0x0d);
    126 		p->rammap_11_0e    =  nvbios_rd08(bios, data + 0x0e);
    127 		p->rammap_11_0f    =  nvbios_rd08(bios, data + 0x0f);
    128 		p->rammap_11_11_0c = (nvbios_rd08(bios, data + 0x11) & 0x0c) >> 2;
    129 		break;
    130 	default:
    131 		data = 0;
    132 		break;
    133 	}
    134 	return data;
    135 }
    136 
    137 u32
    138 nvbios_rammapEm(struct nvkm_bios *bios, u16 mhz,
    139 		u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ramcfg *info)
    140 {
    141 	int idx = 0;
    142 	u32 data;
    143 	while ((data = nvbios_rammapEp(bios, idx++, ver, hdr, cnt, len, info))) {
    144 		if (mhz >= info->rammap_min && mhz <= info->rammap_max)
    145 			break;
    146 	}
    147 	return data;
    148 }
    149 
    150 u32
    151 nvbios_rammapSe(struct nvkm_bios *bios, u32 data,
    152 		u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx, u8 *ver, u8 *hdr)
    153 {
    154 	if (idx < ecnt) {
    155 		data = data + ehdr + (idx * elen);
    156 		*ver = ever;
    157 		*hdr = elen;
    158 		return data;
    159 	}
    160 	return 0;
    161 }
    162 
    163 u32
    164 nvbios_rammapSp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, int idx,
    165 		struct nvbios_ramcfg *p)
    166 {
    167 	data += (idx * size);
    168 
    169 	if (size < 11)
    170 		return 0x00000000;
    171 
    172 	p->ramcfg_ver = 0;
    173 	p->ramcfg_timing   =  nvbios_rd08(bios, data + 0x01);
    174 	p->ramcfg_00_03_01 = (nvbios_rd08(bios, data + 0x03) & 0x01) >> 0;
    175 	p->ramcfg_00_03_02 = (nvbios_rd08(bios, data + 0x03) & 0x02) >> 1;
    176 	p->ramcfg_DLLoff   = (nvbios_rd08(bios, data + 0x03) & 0x04) >> 2;
    177 	p->ramcfg_00_03_08 = (nvbios_rd08(bios, data + 0x03) & 0x08) >> 3;
    178 	p->ramcfg_RON      = (nvbios_rd08(bios, data + 0x03) & 0x10) >> 3;
    179 	p->ramcfg_FBVDDQ   = (nvbios_rd08(bios, data + 0x03) & 0x80) >> 7;
    180 	p->ramcfg_00_04_02 = (nvbios_rd08(bios, data + 0x04) & 0x02) >> 1;
    181 	p->ramcfg_00_04_04 = (nvbios_rd08(bios, data + 0x04) & 0x04) >> 2;
    182 	p->ramcfg_00_04_20 = (nvbios_rd08(bios, data + 0x04) & 0x20) >> 5;
    183 	p->ramcfg_00_05    = (nvbios_rd08(bios, data + 0x05) & 0xff) >> 0;
    184 	p->ramcfg_00_06    = (nvbios_rd08(bios, data + 0x06) & 0xff) >> 0;
    185 	p->ramcfg_00_07    = (nvbios_rd08(bios, data + 0x07) & 0xff) >> 0;
    186 	p->ramcfg_00_08    = (nvbios_rd08(bios, data + 0x08) & 0xff) >> 0;
    187 	p->ramcfg_00_09    = (nvbios_rd08(bios, data + 0x09) & 0xff) >> 0;
    188 	p->ramcfg_00_0a_0f = (nvbios_rd08(bios, data + 0x0a) & 0x0f) >> 0;
    189 	p->ramcfg_00_0a_f0 = (nvbios_rd08(bios, data + 0x0a) & 0xf0) >> 4;
    190 
    191 	return data;
    192 }
    193 
    194 u32
    195 nvbios_rammapSp(struct nvkm_bios *bios, u32 data,
    196 		u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
    197 		u8 *ver, u8 *hdr, struct nvbios_ramcfg *p)
    198 {
    199 	data = nvbios_rammapSe(bios, data, ever, ehdr, ecnt, elen, idx, ver, hdr);
    200 	p->ramcfg_ver = *ver;
    201 	p->ramcfg_hdr = *hdr;
    202 	switch (!!data * *ver) {
    203 	case 0x10:
    204 		p->ramcfg_timing   =  nvbios_rd08(bios, data + 0x01);
    205 		p->ramcfg_10_02_01 = (nvbios_rd08(bios, data + 0x02) & 0x01) >> 0;
    206 		p->ramcfg_10_02_02 = (nvbios_rd08(bios, data + 0x02) & 0x02) >> 1;
    207 		p->ramcfg_10_02_04 = (nvbios_rd08(bios, data + 0x02) & 0x04) >> 2;
    208 		p->ramcfg_10_02_08 = (nvbios_rd08(bios, data + 0x02) & 0x08) >> 3;
    209 		p->ramcfg_10_02_10 = (nvbios_rd08(bios, data + 0x02) & 0x10) >> 4;
    210 		p->ramcfg_10_02_20 = (nvbios_rd08(bios, data + 0x02) & 0x20) >> 5;
    211 		p->ramcfg_DLLoff   = (nvbios_rd08(bios, data + 0x02) & 0x40) >> 6;
    212 		p->ramcfg_10_03_0f = (nvbios_rd08(bios, data + 0x03) & 0x0f) >> 0;
    213 		p->ramcfg_10_04_01 = (nvbios_rd08(bios, data + 0x04) & 0x01) >> 0;
    214 		p->ramcfg_FBVDDQ   = (nvbios_rd08(bios, data + 0x04) & 0x08) >> 3;
    215 		p->ramcfg_10_05    = (nvbios_rd08(bios, data + 0x05) & 0xff) >> 0;
    216 		p->ramcfg_10_06    = (nvbios_rd08(bios, data + 0x06) & 0xff) >> 0;
    217 		p->ramcfg_10_07    = (nvbios_rd08(bios, data + 0x07) & 0xff) >> 0;
    218 		p->ramcfg_10_08    = (nvbios_rd08(bios, data + 0x08) & 0xff) >> 0;
    219 		p->ramcfg_10_09_0f = (nvbios_rd08(bios, data + 0x09) & 0x0f) >> 0;
    220 		p->ramcfg_10_09_f0 = (nvbios_rd08(bios, data + 0x09) & 0xf0) >> 4;
    221 		break;
    222 	case 0x11:
    223 		p->ramcfg_timing   =  nvbios_rd08(bios, data + 0x00);
    224 		p->ramcfg_11_01_01 = (nvbios_rd08(bios, data + 0x01) & 0x01) >> 0;
    225 		p->ramcfg_11_01_02 = (nvbios_rd08(bios, data + 0x01) & 0x02) >> 1;
    226 		p->ramcfg_11_01_04 = (nvbios_rd08(bios, data + 0x01) & 0x04) >> 2;
    227 		p->ramcfg_11_01_08 = (nvbios_rd08(bios, data + 0x01) & 0x08) >> 3;
    228 		p->ramcfg_11_01_10 = (nvbios_rd08(bios, data + 0x01) & 0x10) >> 4;
    229 		p->ramcfg_DLLoff =   (nvbios_rd08(bios, data + 0x01) & 0x20) >> 5;
    230 		p->ramcfg_11_01_40 = (nvbios_rd08(bios, data + 0x01) & 0x40) >> 6;
    231 		p->ramcfg_11_01_80 = (nvbios_rd08(bios, data + 0x01) & 0x80) >> 7;
    232 		p->ramcfg_11_02_03 = (nvbios_rd08(bios, data + 0x02) & 0x03) >> 0;
    233 		p->ramcfg_11_02_04 = (nvbios_rd08(bios, data + 0x02) & 0x04) >> 2;
    234 		p->ramcfg_11_02_08 = (nvbios_rd08(bios, data + 0x02) & 0x08) >> 3;
    235 		p->ramcfg_11_02_10 = (nvbios_rd08(bios, data + 0x02) & 0x10) >> 4;
    236 		p->ramcfg_11_02_40 = (nvbios_rd08(bios, data + 0x02) & 0x40) >> 6;
    237 		p->ramcfg_11_02_80 = (nvbios_rd08(bios, data + 0x02) & 0x80) >> 7;
    238 		p->ramcfg_11_03_0f = (nvbios_rd08(bios, data + 0x03) & 0x0f) >> 0;
    239 		p->ramcfg_11_03_30 = (nvbios_rd08(bios, data + 0x03) & 0x30) >> 4;
    240 		p->ramcfg_11_03_c0 = (nvbios_rd08(bios, data + 0x03) & 0xc0) >> 6;
    241 		p->ramcfg_11_03_f0 = (nvbios_rd08(bios, data + 0x03) & 0xf0) >> 4;
    242 		p->ramcfg_11_04    = (nvbios_rd08(bios, data + 0x04) & 0xff) >> 0;
    243 		p->ramcfg_11_06    = (nvbios_rd08(bios, data + 0x06) & 0xff) >> 0;
    244 		p->ramcfg_11_07_02 = (nvbios_rd08(bios, data + 0x07) & 0x02) >> 1;
    245 		p->ramcfg_11_07_04 = (nvbios_rd08(bios, data + 0x07) & 0x04) >> 2;
    246 		p->ramcfg_11_07_08 = (nvbios_rd08(bios, data + 0x07) & 0x08) >> 3;
    247 		p->ramcfg_11_07_10 = (nvbios_rd08(bios, data + 0x07) & 0x10) >> 4;
    248 		p->ramcfg_11_07_40 = (nvbios_rd08(bios, data + 0x07) & 0x40) >> 6;
    249 		p->ramcfg_11_07_80 = (nvbios_rd08(bios, data + 0x07) & 0x80) >> 7;
    250 		p->ramcfg_11_08_01 = (nvbios_rd08(bios, data + 0x08) & 0x01) >> 0;
    251 		p->ramcfg_11_08_02 = (nvbios_rd08(bios, data + 0x08) & 0x02) >> 1;
    252 		p->ramcfg_11_08_04 = (nvbios_rd08(bios, data + 0x08) & 0x04) >> 2;
    253 		p->ramcfg_11_08_08 = (nvbios_rd08(bios, data + 0x08) & 0x08) >> 3;
    254 		p->ramcfg_11_08_10 = (nvbios_rd08(bios, data + 0x08) & 0x10) >> 4;
    255 		p->ramcfg_11_08_20 = (nvbios_rd08(bios, data + 0x08) & 0x20) >> 5;
    256 		p->ramcfg_11_09    = (nvbios_rd08(bios, data + 0x09) & 0xff) >> 0;
    257 		break;
    258 	default:
    259 		data = 0;
    260 		break;
    261 	}
    262 	return data;
    263 }
    264