2 * Copyright 2015 Martin Peres
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
22 * Authors: Martin Peres
24 #include <subdev/bios.h>
25 #include <subdev/bios/bit.h>
26 #include <subdev/bios/extdev.h>
27 #include <subdev/bios/iccsense.h>
30 nvbios_iccsense_table(struct nvkm_bios
*bios
, u8
*ver
, u8
*hdr
, u8
*cnt
,
33 struct bit_entry bit_P
;
36 if (bit_entry(bios
, 'P', &bit_P
) || bit_P
.version
!= 2 ||
40 iccsense
= nvbios_rd32(bios
, bit_P
.offset
+ 0x28);
44 *ver
= nvbios_rd08(bios
, iccsense
+ 0);
48 *hdr
= nvbios_rd08(bios
, iccsense
+ 1);
49 *len
= nvbios_rd08(bios
, iccsense
+ 2);
50 *cnt
= nvbios_rd08(bios
, iccsense
+ 3);
60 nvbios_iccsense_parse(struct nvkm_bios
*bios
, struct nvbios_iccsense
*iccsense
)
62 struct nvkm_subdev
*subdev
= &bios
->subdev
;
63 u8 ver
, hdr
, cnt
, len
, i
;
66 table
= nvbios_iccsense_table(bios
, &ver
, &hdr
, &cnt
, &len
);
70 if (ver
!= 0x10 && ver
!= 0x20) {
71 nvkm_error(subdev
, "ICCSENSE version 0x%02x unknown\n", ver
);
75 iccsense
->nr_entry
= cnt
;
76 iccsense
->rail
= kmalloc_array(cnt
, sizeof(struct pwr_rail_t
),
81 for (i
= 0; i
< cnt
; ++i
) {
82 struct nvbios_extdev_func extdev
;
83 struct pwr_rail_t
*rail
= &iccsense
->rail
[i
];
87 entry
= table
+ hdr
+ i
* len
;
91 if ((nvbios_rd08(bios
, entry
+ 0x1) & 0xf8) == 0xf8)
95 rail
->extdev_id
= nvbios_rd08(bios
, entry
+ 0x2);
99 rail
->mode
= nvbios_rd08(bios
, entry
);
100 rail
->extdev_id
= nvbios_rd08(bios
, entry
+ 0x1);
105 if (nvbios_extdev_parse(bios
, rail
->extdev_id
, &extdev
))
108 switch (extdev
.type
) {
109 case NVBIOS_EXTDEV_INA209
:
110 case NVBIOS_EXTDEV_INA219
:
111 rail
->resistor_count
= 1;
113 case NVBIOS_EXTDEV_INA3221
:
114 rail
->resistor_count
= 3;
117 rail
->resistor_count
= 0;
121 for (r
= 0; r
< rail
->resistor_count
; ++r
) {
122 rail
->resistors
[r
].mohm
= nvbios_rd08(bios
, entry
+ res_start
+ r
* 2);
123 rail
->resistors
[r
].enabled
= !(nvbios_rd08(bios
, entry
+ res_start
+ r
* 2 + 1) & 0x40);
125 rail
->config
= nvbios_rd16(bios
, entry
+ res_start
+ rail
->resistor_count
* 2);