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