Sync EC implementation to the Linux driver (#720)

* EC: add CPU core voltage sensor

* Introfuce BoardInfo struct for storing EC initialization data

We need to keep some more information about the current board than just
the sensors set and this allows us do not duplicate sensor definitions for
such board variants as " (WI-FI)" when sensors are identical to the base variant.

* EC: add board families

* fixup! EC: add board families

* EC: add Amd 400 series
This commit is contained in:
Eugene Shalygin
2022-04-29 17:09:18 +02:00
committed by GitHub
parent e7fc7c94bf
commit 019ed7192d
3 changed files with 166 additions and 100 deletions
@@ -301,6 +301,8 @@ namespace LibreHardwareMonitor.Hardware.Motherboard
return Model.AX370_Gaming_K7;
case var _ when name.Equals("PRIME X370-PRO", StringComparison.OrdinalIgnoreCase):
return Model.PRIME_X370_PRO;
case var _ when name.Equals("PRIME X470-PRO", StringComparison.OrdinalIgnoreCase):
return Model.PRIME_X470_PRO;
case var _ when name.Equals("PRIME X570-PRO", StringComparison.OrdinalIgnoreCase):
return Model.PRIME_X570_PRO;
case var _ when name.Equals("Pro WS X570-ACE", StringComparison.OrdinalIgnoreCase):
@@ -25,6 +25,8 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
TempTSensor,
/// <summary>VRM temperature [℃]</summary>
TempVrm,
/// <summary>CPU Core voltage [mV]</summary>
VoltageCPU,
/// <summary>CPU_Opt fan [RPM]</summary>
FanCPUOpt,
/// <summary>VRM heat sink fan [RPM]</summary>
@@ -44,110 +46,160 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
Max
};
private static readonly Dictionary<ECSensor, EmbeddedControllerSource> _knownSensors = new()
private enum BoardFamily
{
{ ECSensor.TempChipset, new EmbeddedControllerSource("Chipset", SensorType.Temperature, 0x003a) },
{ ECSensor.TempCPU, new EmbeddedControllerSource("CPU", SensorType.Temperature, 0x003b) },
{ ECSensor.TempMB, new EmbeddedControllerSource("Motherboard", SensorType.Temperature, 0x003c) },
{ ECSensor.TempTSensor, new EmbeddedControllerSource("T Sensor", SensorType.Temperature, 0x003d, blank: -40) },
{ ECSensor.TempVrm, new EmbeddedControllerSource("VRM", SensorType.Temperature, 0x003e) },
{ ECSensor.FanCPUOpt, new EmbeddedControllerSource("CPU Optional Fan", SensorType.Fan, 0x00b0, 2) },
{ ECSensor.FanVrmHS, new EmbeddedControllerSource("VRM Heat Sink Fan", SensorType.Fan, 0x00b2, 2) },
{ ECSensor.FanChipset, new EmbeddedControllerSource("Chipset Fan", SensorType.Fan, 0x00b4, 2) },
{ ECSensor.FanWaterPump, new EmbeddedControllerSource("Water Pump", SensorType.Fan, 0x00bc, 2) },
// TODO: "why 42?" is a silly question, I know, but still, why? On the serious side, it might be 41.6(6)
{ ECSensor.FanWaterFlow, new EmbeddedControllerSource("Water flow", SensorType.Flow, 0x00bc, 2, factor: 1.0f / 42f * 60f) },
{ ECSensor.CurrCPU, new EmbeddedControllerSource("CPU", SensorType.Current, 0x00f4) },
{ ECSensor.TempWaterIn, new EmbeddedControllerSource("Water In", SensorType.Temperature, 0x0100, blank: -40) },
{ ECSensor.TempWaterOut, new EmbeddedControllerSource("Water Out", SensorType.Temperature, 0x0101, blank: -40) },
Amd400,
Amd500,
Intel100,
Intel600,
}
private struct BoardInfo
{
public BoardInfo(Model[] models, BoardFamily family, params ECSensor[] sensors)
{
Models = models;
Family = family;
Sensors = sensors;
}
public BoardInfo(Model model, BoardFamily family, params ECSensor[] sensors)
{
Models = new Model[] { model };
Family = family;
Sensors = sensors;
}
public Model[] Models { get; }
public BoardFamily Family { get; }
public ECSensor[] Sensors { get; }
};
private static readonly Dictionary<Model, ECSensor[]> _boardSensors = new()
private static readonly Dictionary<BoardFamily, Dictionary<ECSensor, EmbeddedControllerSource>> _knownSensors = new()
{
{
Model.PRIME_X570_PRO,
new ECSensor[] { ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempVrm, ECSensor.TempTSensor, ECSensor.FanChipset }
},
{
Model.PRO_WS_X570_ACE,
new ECSensor[] { ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB ,
ECSensor.TempVrm, ECSensor.FanChipset, ECSensor.CurrCPU}
},
{
Model.ROG_CROSSHAIR_VIII_HERO,
new ECSensor[] { ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm, ECSensor.TempWaterIn, ECSensor.TempWaterOut,
ECSensor.FanCPUOpt, ECSensor.FanChipset, ECSensor.FanWaterFlow, ECSensor.CurrCPU}
},
{
Model.ROG_CROSSHAIR_VIII_HERO_WIFI,
new ECSensor[] { ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm, ECSensor.TempWaterIn, ECSensor.TempWaterOut,
ECSensor.FanCPUOpt, ECSensor.FanChipset, ECSensor.FanWaterFlow, ECSensor.CurrCPU}
},
{
Model.ROG_CROSSHAIR_VIII_DARK_HERO,
new ECSensor[] { ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm, ECSensor.TempWaterIn, ECSensor.TempWaterOut,
ECSensor.FanCPUOpt, ECSensor.FanWaterFlow, ECSensor.CurrCPU
BoardFamily.Amd400,
new() // no chipset fans in this generation
{
{ ECSensor.TempChipset, new EmbeddedControllerSource("Chipset", SensorType.Temperature, 0x003a) },
{ ECSensor.TempCPU, new EmbeddedControllerSource("CPU", SensorType.Temperature, 0x003b) },
{ ECSensor.TempMB, new EmbeddedControllerSource("Motherboard", SensorType.Temperature, 0x003c) },
{ ECSensor.TempTSensor, new EmbeddedControllerSource("T Sensor", SensorType.Temperature, 0x003d, blank: -40) },
{ ECSensor.TempVrm, new EmbeddedControllerSource("VRM", SensorType.Temperature, 0x003e) },
{ ECSensor.VoltageCPU, new EmbeddedControllerSource("CPU Core", SensorType.Voltage, 0x00a2, 2, factor: 1e-3f) },
{ ECSensor.FanCPUOpt, new EmbeddedControllerSource("CPU Optional Fan", SensorType.Fan, 0x00bc, 2) },
{ ECSensor.FanVrmHS, new EmbeddedControllerSource("VRM Heat Sink Fan", SensorType.Fan, 0x00b2, 2) },
{ ECSensor.FanWaterFlow, new EmbeddedControllerSource("Water flow", SensorType.Flow, 0x00b4, 2, factor: 1.0f / 42f * 60f) },
{ ECSensor.CurrCPU, new EmbeddedControllerSource("CPU", SensorType.Current, 0x00f4) },
{ ECSensor.TempWaterIn, new EmbeddedControllerSource("Water In", SensorType.Temperature, 0x010d, blank: -40) },
{ ECSensor.TempWaterOut, new EmbeddedControllerSource("Water Out", SensorType.Temperature, 0x010b, blank: -40) },
}
},
{
Model.CROSSHAIR_III_FORMULA,
new ECSensor[] { ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm,
ECSensor.FanCPUOpt, ECSensor.FanChipset, ECSensor.CurrCPU }
BoardFamily.Amd500,
new()
{
{ ECSensor.TempChipset, new EmbeddedControllerSource("Chipset", SensorType.Temperature, 0x003a) },
{ ECSensor.TempCPU, new EmbeddedControllerSource("CPU", SensorType.Temperature, 0x003b) },
{ ECSensor.TempMB, new EmbeddedControllerSource("Motherboard", SensorType.Temperature, 0x003c) },
{ ECSensor.TempTSensor, new EmbeddedControllerSource("T Sensor", SensorType.Temperature, 0x003d, blank: -40) },
{ ECSensor.TempVrm, new EmbeddedControllerSource("VRM", SensorType.Temperature, 0x003e) },
{ ECSensor.VoltageCPU, new EmbeddedControllerSource("CPU Core", SensorType.Voltage, 0x00a2, 2, factor: 1e-3f) },
{ ECSensor.FanCPUOpt, new EmbeddedControllerSource("CPU Optional Fan", SensorType.Fan, 0x00b0, 2) },
{ ECSensor.FanVrmHS, new EmbeddedControllerSource("VRM Heat Sink Fan", SensorType.Fan, 0x00b2, 2) },
{ ECSensor.FanChipset, new EmbeddedControllerSource("Chipset Fan", SensorType.Fan, 0x00b4, 2) },
// TODO: "why 42?" is a silly question, I know, but still, why? On the serious side, it might be 41.6(6)
{ ECSensor.FanWaterFlow, new EmbeddedControllerSource("Water flow", SensorType.Flow, 0x00bc, 2, factor: 1.0f / 42f * 60f) },
{ ECSensor.CurrCPU, new EmbeddedControllerSource("CPU", SensorType.Current, 0x00f4) },
{ ECSensor.TempWaterIn, new EmbeddedControllerSource("Water In", SensorType.Temperature, 0x0100, blank: -40) },
{ ECSensor.TempWaterOut, new EmbeddedControllerSource("Water Out", SensorType.Temperature, 0x0101, blank: -40) },
}
},
{
Model.ROG_CROSSHAIR_VIII_IMPACT,
new ECSensor[] { ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm,
ECSensor.FanChipset, ECSensor.CurrCPU }
BoardFamily.Intel100,
new() {
{ ECSensor.TempChipset, new EmbeddedControllerSource("Chipset", SensorType.Temperature, 0x003a) },
{ ECSensor.TempTSensor, new EmbeddedControllerSource("T Sensor", SensorType.Temperature, 0x003d, blank: -40) },
{ ECSensor.FanWaterPump, new EmbeddedControllerSource("Water Pump", SensorType.Fan, 0x00bc, 2) },
{ ECSensor.CurrCPU, new EmbeddedControllerSource("CPU", SensorType.Current, 0x00f4) },
{ ECSensor.VoltageCPU, new EmbeddedControllerSource("CPU Core", SensorType.Voltage, 0x00a2, 2, factor: 1e-3f) },
}
},
{
Model.ROG_STRIX_B550_E_GAMING,
new ECSensor[] { ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm, ECSensor.FanCPUOpt }
BoardFamily.Intel600,
new()
{
{ ECSensor.TempTSensor, new EmbeddedControllerSource("T Sensor", SensorType.Temperature, 0x003d, blank: -40) },
{ ECSensor.TempVrm, new EmbeddedControllerSource("VRM", SensorType.Temperature, 0x003e) },
}
},
{
Model.ROG_STRIX_B550_I_GAMING,
new ECSensor[] { ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm,
ECSensor.FanVrmHS, ECSensor.CurrCPU }
},
{
Model.ROG_STRIX_X570_E_GAMING,
new ECSensor[] { ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm,
ECSensor.FanChipset, ECSensor.CurrCPU }
},
{
Model.ROG_STRIX_X570_F_GAMING,
new ECSensor[]{ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.FanChipset}
},
{
Model.ROG_STRIX_X570_I_GAMING,
new ECSensor[] {
ECSensor.TempTSensor, ECSensor.FanVrmHS, ECSensor.FanChipset, ECSensor.CurrCPU }
},
{
Model.ROG_STRIX_Z690_A_GAMING_WIFI_D4,
new ECSensor[] {
ECSensor.TempTSensor, ECSensor.TempVrm }
},
{
Model.Z170_A,
new ECSensor[] {
ECSensor.TempTSensor, ECSensor.TempChipset, ECSensor.FanWaterPump, ECSensor.CurrCPU }
}
};
static EmbeddedController()
{
System.Diagnostics.Debug.Assert(_knownSensors.Count == ((int)ECSensor.Max));
}
private static readonly BoardInfo[] _boards = new BoardInfo[]{
new(Model.PRIME_X470_PRO, BoardFamily.Amd400,
ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempVrm, ECSensor.TempVrm, ECSensor.FanCPUOpt,
ECSensor.CurrCPU, ECSensor.VoltageCPU
),
new (Model.PRIME_X570_PRO, BoardFamily.Amd500,
ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempVrm, ECSensor.TempTSensor, ECSensor.FanChipset
),
new(Model.PRO_WS_X570_ACE, BoardFamily.Amd500,
ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempVrm, ECSensor.FanChipset, ECSensor.CurrCPU, ECSensor.VoltageCPU
),
new(new Model[] {Model.ROG_CROSSHAIR_VIII_HERO, Model.ROG_CROSSHAIR_VIII_HERO_WIFI }, BoardFamily.Amd500,
ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm, ECSensor.TempWaterIn, ECSensor.TempWaterOut,
ECSensor.FanCPUOpt, ECSensor.FanChipset, ECSensor.FanWaterFlow,
ECSensor.CurrCPU, ECSensor.VoltageCPU
),
new(Model.ROG_CROSSHAIR_VIII_DARK_HERO, BoardFamily.Amd500,
ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm, ECSensor.TempWaterIn, ECSensor.TempWaterOut,
ECSensor.FanCPUOpt, ECSensor.FanWaterFlow, ECSensor.CurrCPU, ECSensor.VoltageCPU
),
new(Model.CROSSHAIR_III_FORMULA, BoardFamily.Amd500,
ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm,
ECSensor.FanCPUOpt, ECSensor.FanChipset, ECSensor.CurrCPU, ECSensor.VoltageCPU
),
new(Model.ROG_CROSSHAIR_VIII_IMPACT, BoardFamily.Amd500,
ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm,
ECSensor.FanChipset, ECSensor.CurrCPU, ECSensor.VoltageCPU
),
new(Model.ROG_STRIX_B550_E_GAMING, BoardFamily.Amd500,
ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm, ECSensor.FanCPUOpt
),
new(Model.ROG_STRIX_B550_I_GAMING, BoardFamily.Amd500,
ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm,
ECSensor.FanVrmHS, ECSensor.CurrCPU, ECSensor.VoltageCPU
),
new(Model.ROG_STRIX_X570_E_GAMING, BoardFamily.Amd500,
ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.TempVrm,
ECSensor.FanChipset, ECSensor.CurrCPU, ECSensor.VoltageCPU
),
new(Model.ROG_STRIX_X570_F_GAMING, BoardFamily.Amd500,
ECSensor.TempChipset, ECSensor.TempCPU, ECSensor.TempMB,
ECSensor.TempTSensor, ECSensor.FanChipset
),
new(Model.ROG_STRIX_X570_I_GAMING, BoardFamily.Amd500,
ECSensor.TempTSensor, ECSensor.FanVrmHS, ECSensor.FanChipset,
ECSensor.CurrCPU, ECSensor.VoltageCPU
),
new(Model.ROG_STRIX_Z690_A_GAMING_WIFI_D4, BoardFamily.Intel600,
ECSensor.TempTSensor, ECSensor.TempVrm
),
new(Model.Z170_A, BoardFamily.Intel100,
ECSensor.TempTSensor, ECSensor.TempChipset, ECSensor.FanWaterPump,
ECSensor.CurrCPU, ECSensor.VoltageCPU
),
};
private readonly IReadOnlyList<EmbeddedControllerSource> _sources;
private readonly List<Sensor> _sensors;
@@ -192,18 +244,19 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
internal static EmbeddedController Create(Model model, ISettings settings)
{
if (_boardSensors.TryGetValue(model, out ECSensor[] sensors))
var boards = _boards.Where(b => b.Models.Contains(model)).ToList();
if (boards.Count == 0)
return null;
if (boards.Count > 1)
throw new MultipleBoardRecordsFoundException(model.ToString());
BoardInfo board = boards[0];
var sources = board.Sensors.Select(ecs => _knownSensors[board.Family][ecs]);
return Environment.OSVersion.Platform switch
{
var sources = sensors.Select(ecs => _knownSensors[ecs]);
return Environment.OSVersion.Platform switch
{
PlatformID.Win32NT => new WindowsEmbeddedController(sources, settings),
_ => null
};
}
return null;
PlatformID.Win32NT => new WindowsEmbeddedController(sources, settings),
_ => null
};
}
public override void Update()
@@ -291,5 +344,15 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
public class IOException: System.IO.IOException {
public IOException(string message): base($"ACPI embedded controller I/O error: {message}") { }
}
public class BadConfigurationException: System.Exception
{
public BadConfigurationException(string message): base(message) { }
}
public class MultipleBoardRecordsFoundException : BadConfigurationException
{
public MultipleBoardRecordsFoundException(string model) : base($"Multiple board records refer to the same model '{model}'") { }
}
}
}
@@ -62,6 +62,7 @@ namespace LibreHardwareMonitor.Hardware.Motherboard
P8Z77_V,
P9X79,
PRIME_X370_PRO,
PRIME_X470_PRO,
PRIME_X570_PRO,
PRO_WS_X570_ACE,
RAMPAGE_EXTREME,