Reduce CPU usage when accessing i2c smbus devices on windows (AMD)

This commit is contained in:
Shady Nawara 2022-01-24 00:20:03 +00:00 committed by Adam Honse
parent 3e45e4201d
commit d90ea6b843
5 changed files with 170 additions and 82 deletions

View file

@ -9,9 +9,37 @@
\*-----------------------------------------*/
#include "i2c_smbus_piix4.h"
#include <Windows.h>
#include "inpout32.h"
#include "LogManager.h"
#include "ResourceManager.h"
i2c_smbus_piix4::i2c_smbus_piix4()
{
json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers");
bool amd_smbus_reduce_cpu = false;
if(drivers_settings.contains("amd_smbus_reduce_cpu"))
{
amd_smbus_reduce_cpu = drivers_settings["amd_smbus_reduce_cpu"].get<bool>();
}
if(amd_smbus_reduce_cpu)
{
delay_timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_MANUAL_RESET | CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
if(!delay_timer) // high resolution timer not supported
{
delay_timer = CreateWaitableTimer(NULL, TRUE, NULL); // create regular timer instead
}
}
}
i2c_smbus_piix4::~i2c_smbus_piix4()
{
if(delay_timer)
{
CloseHandle(delay_timer);
}
}
//Logic adapted from piix4_transaction() in i2c-piix4.c
int i2c_smbus_piix4::piix4_transaction()
@ -41,11 +69,29 @@ int i2c_smbus_piix4::piix4_transaction()
/* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
temp = 0;
while ((++timeout < MAX_TIMEOUT) && temp <= 1)
if(delay_timer)
{
temp = Inp32(SMBHSTSTS);
}
LARGE_INTEGER retry_delay;
retry_delay.QuadPart = -2500;
SetWaitableTimer(delay_timer, &retry_delay, 0, NULL, NULL, FALSE);
WaitForSingleObject(delay_timer, INFINITE);
while ((++timeout < MAX_TIMEOUT) && temp <= 1)
{
temp = Inp32(SMBHSTSTS);
SetWaitableTimer(delay_timer, &retry_delay, 0, NULL, NULL, FALSE);
WaitForSingleObject(delay_timer, INFINITE);
}
}
else
{
while ((++timeout < MAX_TIMEOUT) && temp <= 1)
{
temp = Inp32(SMBHSTSTS);
}
}
/* If the SMBus is still busy, we give up */
if (timeout == MAX_TIMEOUT)
{
@ -144,7 +190,7 @@ s32 i2c_smbus_piix4::piix4_access(u16 addr, char read_write, u8 command, int siz
if (status)
return status;
if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
return 0;
switch (size)

View file

@ -10,6 +10,7 @@
\*-----------------------------------------*/
#include "i2c_smbus.h"
#include "windows.h"
#pragma once
@ -40,10 +41,13 @@ class i2c_smbus_piix4 : public i2c_smbus_interface
{
public:
u16 piix4_smba = 0x0B00;
i2c_smbus_piix4();
~i2c_smbus_piix4();
private:
int piix4_transaction();
s32 piix4_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data);
s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data);
s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data);
};
HANDLE delay_timer;
};