1 /* 2 * Copyright 2013 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 */ 24 #include <subdev/bios.h> 25 #include <subdev/bios/bit.h> 26 #include <subdev/bios/M0205.h> 27 28 u32 29 nvbios_M0205Te(struct nvkm_bios *bios, 30 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz) 31 { 32 struct bit_entry bit_M; 33 u32 data = 0x00000000; 34 35 if (!bit_entry(bios, 'M', &bit_M)) { 36 if (bit_M.version == 2 && bit_M.length > 0x08) 37 data = nvbios_rd32(bios, bit_M.offset + 0x05); 38 if (data) { 39 *ver = nvbios_rd08(bios, data + 0x00); 40 switch (*ver) { 41 case 0x10: 42 *hdr = nvbios_rd08(bios, data + 0x01); 43 *len = nvbios_rd08(bios, data + 0x02); 44 *ssz = nvbios_rd08(bios, data + 0x03); 45 *snr = nvbios_rd08(bios, data + 0x04); 46 *cnt = nvbios_rd08(bios, data + 0x05); 47 return data; 48 default: 49 break; 50 } 51 } 52 } 53 54 return 0x00000000; 55 } 56 57 u32 58 nvbios_M0205Tp(struct nvkm_bios *bios, 59 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz, 60 struct nvbios_M0205T *info) 61 { 62 u32 data = nvbios_M0205Te(bios, ver, hdr, cnt, len, snr, ssz); 63 memset(info, 0x00, sizeof(*info)); 64 switch (!!data * *ver) { 65 case 0x10: 66 info->freq = nvbios_rd16(bios, data + 0x06); 67 break; 68 default: 69 break; 70 } 71 return data; 72 } 73 74 u32 75 nvbios_M0205Ee(struct nvkm_bios *bios, int idx, 76 u8 *ver, u8 *hdr, u8 *cnt, u8 *len) 77 { 78 u8 snr, ssz; 79 u32 data = nvbios_M0205Te(bios, ver, hdr, cnt, len, &snr, &ssz); 80 if (data && idx < *cnt) { 81 data = data + *hdr + idx * (*len + (snr * ssz)); 82 *hdr = *len; 83 *cnt = snr; 84 *len = ssz; 85 return data; 86 } 87 return 0x00000000; 88 } 89 90 u32 91 nvbios_M0205Ep(struct nvkm_bios *bios, int idx, 92 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, 93 struct nvbios_M0205E *info) 94 { 95 u32 data = nvbios_M0205Ee(bios, idx, ver, hdr, cnt, len); 96 memset(info, 0x00, sizeof(*info)); 97 switch (!!data * *ver) { 98 case 0x10: 99 info->type = nvbios_rd08(bios, data + 0x00) & 0x0f; 100 return data; 101 default: 102 break; 103 } 104 return 0x00000000; 105 } 106 107 u32 108 nvbios_M0205Se(struct nvkm_bios *bios, int ent, int idx, u8 *ver, u8 *hdr) 109 { 110 111 u8 cnt, len; 112 u32 data = nvbios_M0205Ee(bios, ent, ver, hdr, &cnt, &len); 113 if (data && idx < cnt) { 114 data = data + *hdr + idx * len; 115 *hdr = len; 116 return data; 117 } 118 return 0x00000000; 119 } 120 121 u32 122 nvbios_M0205Sp(struct nvkm_bios *bios, int ent, int idx, u8 *ver, u8 *hdr, 123 struct nvbios_M0205S *info) 124 { 125 u32 data = nvbios_M0205Se(bios, ent, idx, ver, hdr); 126 memset(info, 0x00, sizeof(*info)); 127 switch (!!data * *ver) { 128 case 0x10: 129 info->data = nvbios_rd08(bios, data + 0x00); 130 return data; 131 default: 132 break; 133 } 134 return 0x00000000; 135 } 136