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