root/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nvbios_iccsense_table
  2. nvbios_iccsense_parse

   1 /*
   2  * Copyright 2015 Martin Peres
   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: Martin Peres
  23  */
  24 #include <subdev/bios.h>
  25 #include <subdev/bios/bit.h>
  26 #include <subdev/bios/extdev.h>
  27 #include <subdev/bios/iccsense.h>
  28 
  29 static u32
  30 nvbios_iccsense_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt,
  31                       u8 *len)
  32 {
  33         struct bit_entry bit_P;
  34         u32 iccsense;
  35 
  36         if (bit_entry(bios, 'P', &bit_P) || bit_P.version != 2 ||
  37             bit_P.length < 0x2c)
  38                 return 0;
  39 
  40         iccsense = nvbios_rd32(bios, bit_P.offset + 0x28);
  41         if (!iccsense)
  42                 return 0;
  43 
  44         *ver = nvbios_rd08(bios, iccsense + 0);
  45         switch (*ver) {
  46         case 0x10:
  47         case 0x20:
  48                 *hdr = nvbios_rd08(bios, iccsense + 1);
  49                 *len = nvbios_rd08(bios, iccsense + 2);
  50                 *cnt = nvbios_rd08(bios, iccsense + 3);
  51                 return iccsense;
  52         default:
  53                 break;
  54         }
  55 
  56         return 0;
  57 }
  58 
  59 int
  60 nvbios_iccsense_parse(struct nvkm_bios *bios, struct nvbios_iccsense *iccsense)
  61 {
  62         struct nvkm_subdev *subdev = &bios->subdev;
  63         u8 ver, hdr, cnt, len, i;
  64         u32 table, entry;
  65 
  66         table = nvbios_iccsense_table(bios, &ver, &hdr, &cnt, &len);
  67         if (!table || !cnt)
  68                 return -EINVAL;
  69 
  70         if (ver != 0x10 && ver != 0x20) {
  71                 nvkm_error(subdev, "ICCSENSE version 0x%02x unknown\n", ver);
  72                 return -EINVAL;
  73         }
  74 
  75         iccsense->nr_entry = cnt;
  76         iccsense->rail = kmalloc_array(cnt, sizeof(struct pwr_rail_t),
  77                                        GFP_KERNEL);
  78         if (!iccsense->rail)
  79                 return -ENOMEM;
  80 
  81         for (i = 0; i < cnt; ++i) {
  82                 struct nvbios_extdev_func extdev;
  83                 struct pwr_rail_t *rail = &iccsense->rail[i];
  84                 u8 res_start = 0;
  85                 int r;
  86 
  87                 entry = table + hdr + i * len;
  88 
  89                 switch(ver) {
  90                 case 0x10:
  91                         if ((nvbios_rd08(bios, entry + 0x1) & 0xf8) == 0xf8)
  92                                 rail->mode = 1;
  93                         else
  94                                 rail->mode = 0;
  95                         rail->extdev_id = nvbios_rd08(bios, entry + 0x2);
  96                         res_start = 0x3;
  97                         break;
  98                 case 0x20:
  99                         rail->mode = nvbios_rd08(bios, entry);
 100                         rail->extdev_id = nvbios_rd08(bios, entry + 0x1);
 101                         res_start = 0x5;
 102                         break;
 103                 }
 104 
 105                 if (nvbios_extdev_parse(bios, rail->extdev_id, &extdev))
 106                         continue;
 107 
 108                 switch (extdev.type) {
 109                 case NVBIOS_EXTDEV_INA209:
 110                 case NVBIOS_EXTDEV_INA219:
 111                         rail->resistor_count = 1;
 112                         break;
 113                 case NVBIOS_EXTDEV_INA3221:
 114                         rail->resistor_count = 3;
 115                         break;
 116                 default:
 117                         rail->resistor_count = 0;
 118                         break;
 119                 }
 120 
 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);
 124                 }
 125                 rail->config = nvbios_rd16(bios, entry + res_start + rail->resistor_count * 2);
 126         }
 127 
 128         return 0;
 129 }

/* [<][>][^][v][top][bottom][index][help] */