diff options
4 files changed, 82 insertions, 92 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h index 9cb97477248b..e933d3eede70 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h @@ -1,10 +1,16 @@ #ifndef __NVBIOS_ICCSENSE_H__ #define __NVBIOS_ICCSENSE_H__ +struct pwr_rail_resistor_t { + u8 mohm; + bool enabled; +}; + struct pwr_rail_t { u8 mode; u8 extdev_id; - u8 resistor_mohm; - u8 rail; + u8 resistor_count; + struct pwr_rail_resistor_t resistors[3]; + u16 config; }; struct nvbios_iccsense { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c index 084328028af1..aafd5e17b1c8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c @@ -23,6 +23,7 @@ */ #include <subdev/bios.h> #include <subdev/bios/bit.h> +#include <subdev/bios/extdev.h> #include <subdev/bios/iccsense.h> static u16 @@ -77,23 +78,47 @@ nvbios_iccsense_parse(struct nvkm_bios *bios, struct nvbios_iccsense *iccsense) return -ENOMEM; for (i = 0; i < cnt; ++i) { + struct nvbios_extdev_func extdev; struct pwr_rail_t *rail = &iccsense->rail[i]; + u8 res_start = 0; + int r; + entry = table + hdr + i * len; switch(ver) { case 0x10: rail->mode = nvbios_rd08(bios, entry + 0x1); rail->extdev_id = nvbios_rd08(bios, entry + 0x2); - rail->resistor_mohm = nvbios_rd08(bios, entry + 0x3); - rail->rail = nvbios_rd08(bios, entry + 0x4); + res_start = 0x3; break; case 0x20: rail->mode = nvbios_rd08(bios, entry); rail->extdev_id = nvbios_rd08(bios, entry + 0x1); - rail->resistor_mohm = nvbios_rd08(bios, entry + 0x5); - rail->rail = nvbios_rd08(bios, entry + 0x6); + res_start = 0x5; + break; + }; + + if (nvbios_extdev_parse(bios, rail->extdev_id, &extdev)) + continue; + + switch (extdev.type) { + case NVBIOS_EXTDEV_INA209: + case NVBIOS_EXTDEV_INA219: + rail->resistor_count = 1; + break; + case NVBIOS_EXTDEV_INA3221: + rail->resistor_count = 3; + break; + default: + rail->resistor_count = 0; break; }; + + for (r = 0; r < rail->resistor_count; ++r) { + rail->resistors[r].mohm = nvbios_rd08(bios, entry + res_start + r * 2); + rail->resistors[r].enabled = !(nvbios_rd08(bios, entry + res_start + r * 2 + 1) & 0x40); + } + rail->config = nvbios_rd16(bios, entry + res_start + rail->resistor_count * 2); } return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c index 41bd5d0f7692..658355fc9354 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c @@ -96,60 +96,12 @@ nvkm_iccsense_ina3221_read(struct nvkm_iccsense *iccsense, } static void -nvkm_iccsense_ina209_config(struct nvkm_iccsense *iccsense, - struct nvkm_iccsense_sensor *sensor) -{ - struct nvkm_subdev *subdev = &iccsense->subdev; - /* configuration: - * 0x0007: 0x0007 shunt and bus continous - * 0x0078: 0x0078 128 samples shunt - * 0x0780: 0x0780 128 samples bus - * 0x1800: 0x0000 +-40 mV shunt range - * 0x2000: 0x0000 16V FSR - */ - u16 value = 0x07ff; - nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value); - nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value); -} - -static void -nvkm_iccsense_ina3221_config(struct nvkm_iccsense *iccsense, - struct nvkm_iccsense_sensor *sensor) -{ - struct nvkm_subdev *subdev = &iccsense->subdev; - /* configuration: - * 0x0007: 0x0007 shunt and bus continous - * 0x0031: 0x0000 140 us conversion time shunt - * 0x01c0: 0x0000 140 us conversion time bus - * 0x0f00: 0x0f00 1024 samples - * 0x7000: 0x?000 channels - */ - u16 value = 0x0e07; - if (sensor->rail_mask & 0x1) - value |= 0x1 << 14; - if (sensor->rail_mask & 0x2) - value |= 0x1 << 13; - if (sensor->rail_mask & 0x4) - value |= 0x1 << 12; - nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value); - nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value); -} - -static void nvkm_iccsense_sensor_config(struct nvkm_iccsense *iccsense, struct nvkm_iccsense_sensor *sensor) { - switch (sensor->type) { - case NVBIOS_EXTDEV_INA209: - case NVBIOS_EXTDEV_INA219: - nvkm_iccsense_ina209_config(iccsense, sensor); - break; - case NVBIOS_EXTDEV_INA3221: - nvkm_iccsense_ina3221_config(iccsense, sensor); - break; - default: - break; - } + struct nvkm_subdev *subdev = &iccsense->subdev; + nvkm_trace(subdev, "write config of extdev %i: 0x%04x\n", sensor->id, sensor->config); + nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, sensor->config); } int @@ -196,7 +148,6 @@ nvkm_iccsense_dtor(struct nvkm_subdev *subdev) static struct nvkm_iccsense_sensor* nvkm_iccsense_create_sensor(struct nvkm_iccsense *iccsense, u8 id) { - struct nvkm_subdev *subdev = &iccsense->subdev; struct nvkm_bios *bios = subdev->device->bios; struct nvkm_i2c *i2c = subdev->device->i2c; @@ -245,7 +196,7 @@ nvkm_iccsense_create_sensor(struct nvkm_iccsense *iccsense, u8 id) sensor->type = extdev.type; sensor->i2c = &i2c_bus->i2c; sensor->addr = addr; - sensor->rail_mask = 0x0; + sensor->config = 0x0; return sensor; } @@ -273,48 +224,56 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev) iccsense->data_valid = true; for (i = 0; i < stbl.nr_entry; ++i) { - struct pwr_rail_t *r = &stbl.rail[i]; - struct nvkm_iccsense_rail *rail; + struct pwr_rail_t *pwr_rail = &stbl.rail[i]; struct nvkm_iccsense_sensor *sensor; - int (*read)(struct nvkm_iccsense *, - struct nvkm_iccsense_rail *); + int r; - if (!r->mode || r->resistor_mohm == 0) + if (pwr_rail->mode != 1 || !pwr_rail->resistor_count) continue; - sensor = nvkm_iccsense_get_sensor(iccsense, r->extdev_id); + sensor = nvkm_iccsense_get_sensor(iccsense, pwr_rail->extdev_id); if (!sensor) continue; - switch (sensor->type) { - case NVBIOS_EXTDEV_INA209: - if (r->rail != 0) - continue; - read = nvkm_iccsense_ina209_read; - break; - case NVBIOS_EXTDEV_INA219: - if (r->rail != 0) + if (!sensor->config) + sensor->config = pwr_rail->config; + else if (sensor->config != pwr_rail->config) + nvkm_error(subdev, "config mismatch found for extdev %i\n", pwr_rail->extdev_id); + + for (r = 0; r < pwr_rail->resistor_count; ++r) { + struct nvkm_iccsense_rail *rail; + struct pwr_rail_resistor_t *res = &pwr_rail->resistors[r]; + int (*read)(struct nvkm_iccsense *, + struct nvkm_iccsense_rail *); + + if (!res->mohm || !res->enabled) continue; - read = nvkm_iccsense_ina219_read; - break; - case NVBIOS_EXTDEV_INA3221: - if (r->rail >= 3) + + switch (sensor->type) { + case NVBIOS_EXTDEV_INA209: + read = nvkm_iccsense_ina209_read; + break; + case NVBIOS_EXTDEV_INA219: + read = nvkm_iccsense_ina219_read; + break; + case NVBIOS_EXTDEV_INA3221: + read = nvkm_iccsense_ina3221_read; + break; + default: continue; - read = nvkm_iccsense_ina3221_read; - break; - default: - continue; + } + + rail = kmalloc(sizeof(*rail), GFP_KERNEL); + if (!rail) + return -ENOMEM; + + rail->read = read; + rail->sensor = sensor; + rail->idx = r; + rail->mohm = res->mohm; + nvkm_debug(subdev, "create rail for extdev %i: { idx: %i, mohm: %i }\n", pwr_rail->extdev_id, r, rail->mohm); + list_add_tail(&rail->head, &iccsense->rails); } - - rail = kmalloc(sizeof(*rail), GFP_KERNEL); - if (!rail) - return -ENOMEM; - sensor->rail_mask |= 1 << r->rail; - rail->read = read; - rail->sensor = sensor; - rail->idx = r->rail; - rail->mohm = r->resistor_mohm; - list_add_tail(&rail->head, &iccsense->rails); } return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h index b72c31d2f908..e90e0f6ed008 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h @@ -10,7 +10,7 @@ struct nvkm_iccsense_sensor { enum nvbios_extdev_type type; struct i2c_adapter *i2c; u8 addr; - u8 rail_mask; + u16 config; }; struct nvkm_iccsense_rail { |