0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include <subdev/bios.h>
0025 #include <subdev/bios/bit.h>
0026 #include <subdev/bios/M0203.h>
0027
0028 u32
0029 nvbios_M0203Te(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
0030 {
0031 struct bit_entry bit_M;
0032 u32 data = 0x00000000;
0033
0034 if (!bit_entry(bios, 'M', &bit_M)) {
0035 if (bit_M.version == 2 && bit_M.length > 0x04)
0036 data = nvbios_rd16(bios, bit_M.offset + 0x03);
0037 if (data) {
0038 *ver = nvbios_rd08(bios, data + 0x00);
0039 switch (*ver) {
0040 case 0x10:
0041 *hdr = nvbios_rd08(bios, data + 0x01);
0042 *len = nvbios_rd08(bios, data + 0x02);
0043 *cnt = nvbios_rd08(bios, data + 0x03);
0044 return data;
0045 default:
0046 break;
0047 }
0048 }
0049 }
0050
0051 return 0x00000000;
0052 }
0053
0054 u32
0055 nvbios_M0203Tp(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
0056 struct nvbios_M0203T *info)
0057 {
0058 u32 data = nvbios_M0203Te(bios, ver, hdr, cnt, len);
0059 memset(info, 0x00, sizeof(*info));
0060 switch (!!data * *ver) {
0061 case 0x10:
0062 info->type = nvbios_rd08(bios, data + 0x04);
0063 info->pointer = nvbios_rd16(bios, data + 0x05);
0064 break;
0065 default:
0066 break;
0067 }
0068 return data;
0069 }
0070
0071 u32
0072 nvbios_M0203Ee(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr)
0073 {
0074 u8 cnt, len;
0075 u32 data = nvbios_M0203Te(bios, ver, hdr, &cnt, &len);
0076 if (data && idx < cnt) {
0077 data = data + *hdr + idx * len;
0078 *hdr = len;
0079 return data;
0080 }
0081 return 0x00000000;
0082 }
0083
0084 u32
0085 nvbios_M0203Ep(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr,
0086 struct nvbios_M0203E *info)
0087 {
0088 u32 data = nvbios_M0203Ee(bios, idx, ver, hdr);
0089 memset(info, 0x00, sizeof(*info));
0090 switch (!!data * *ver) {
0091 case 0x10:
0092 info->type = (nvbios_rd08(bios, data + 0x00) & 0x0f) >> 0;
0093 info->strap = (nvbios_rd08(bios, data + 0x00) & 0xf0) >> 4;
0094 info->group = (nvbios_rd08(bios, data + 0x01) & 0x0f) >> 0;
0095 return data;
0096 default:
0097 break;
0098 }
0099 return 0x00000000;
0100 }
0101
0102 u32
0103 nvbios_M0203Em(struct nvkm_bios *bios, u8 ramcfg, u8 *ver, u8 *hdr,
0104 struct nvbios_M0203E *info)
0105 {
0106 struct nvkm_subdev *subdev = &bios->subdev;
0107 struct nvbios_M0203T M0203T;
0108 u8 cnt, len, idx = 0xff;
0109 u32 data;
0110
0111 if (!nvbios_M0203Tp(bios, ver, hdr, &cnt, &len, &M0203T)) {
0112 nvkm_warn(subdev, "M0203T not found\n");
0113 return 0x00000000;
0114 }
0115
0116 while ((data = nvbios_M0203Ep(bios, ++idx, ver, hdr, info))) {
0117 switch (M0203T.type) {
0118 case M0203T_TYPE_RAMCFG:
0119 if (info->strap != ramcfg)
0120 continue;
0121 return data;
0122 default:
0123 nvkm_warn(subdev, "M0203T type %02x\n", M0203T.type);
0124 return 0x00000000;
0125 }
0126 }
0127
0128 return data;
0129 }