Files
OpenRGB/SPDAccessor/SPDDetector.cpp

141 lines
5.0 KiB
C++

/*---------------------------------------------------------*\
| SPDDetector.cpp |
| |
| Detector for DRAM modules using SPD information |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "DDR4DirectAccessor.h"
#include "DDR5DirectAccessor.h"
#include "LogManager.h"
#include "SPDDetector.h"
#ifdef __linux__
#include "EE1004Accessor_Linux.h"
#include "SPD5118Accessor_Linux.h"
#endif
SPDDetector::SPDDetector(i2c_smbus_interface *bus, uint8_t address, SPDMemoryType mem_type = SPD_RESERVED)
: bus(bus), address(address), mem_type(mem_type), valid(false)
{
detect_memory_type();
}
bool SPDDetector::is_valid() const
{
return(valid);
}
SPDMemoryType SPDDetector::memory_type() const
{
return(mem_type);
}
void SPDDetector::detect_memory_type()
{
SPDAccessor *accessor;
/*---------------------------------------------------------*\
| On Linux, attempt to use the ee1004 or spd5118 drivers to |
| access SPD on DDR4 and DDR5, respectively |
\*---------------------------------------------------------*/
#ifdef __linux__
if(EE1004Accessor::isAvailable(bus, address))
{
LOG_DEBUG("[SPDDetector] Probing DRAM using EE1004 Accessor on bus %d, address 0x%02x", bus->bus_id, address);
accessor = new EE1004Accessor(bus, address);
}
else if(SPD5118Accessor::isAvailable(bus, address))
{
LOG_DEBUG("[SPDDetector] Probing DRAM using SPD5118 Accessor on bus %d, address 0x%02x", bus->bus_id, address);
accessor = new SPD5118Accessor(bus, address);
}
else
#endif
/*---------------------------------------------------------*\
| Otherwise, access the SPD using a direct accessor using |
| i2c for DDR4 and DDR5 |
\*---------------------------------------------------------*/
if((mem_type == SPD_RESERVED
|| mem_type == SPD_DDR4_SDRAM
|| mem_type == SPD_DDR4E_SDRAM
|| mem_type == SPD_LPDDR4_SDRAM
|| mem_type == SPD_LPDDR4X_SDRAM)
&& DDR4DirectAccessor::isAvailable(bus, address))
{
LOG_DEBUG("[SPDDetector] Probing DRAM using DDR4 Direct Accessor on bus %d, address 0x%02x", bus->bus_id, address);
accessor = new DDR4DirectAccessor(bus, address);
}
else if((mem_type == SPD_RESERVED
|| mem_type == SPD_DDR5_SDRAM
|| mem_type == SPD_LPDDR5_SDRAM)
&& DDR5DirectAccessor::isAvailable(bus, address))
{
LOG_DEBUG("[SPDDetector] Probing DRAM using DDR5 Direct Accessor on bus %d, address 0x%02x", bus->bus_id, address);
accessor = new DDR5DirectAccessor(bus, address);
}
/*---------------------------------------------------------*\
| Otherwise, probe the SPD directly using i2c, probably an |
| older system than DDR4 |
\*---------------------------------------------------------*/
else if(mem_type == SPD_RESERVED)
{
LOG_DEBUG("[SPDDetector] Probing DRAM older than DDR4 on bus %d, address 0x%02x", bus->bus_id, address);
int value = bus->i2c_smbus_read_byte_data(address, 0x02);
if(value < 0)
{
valid = false;
}
else
{
mem_type = (SPDMemoryType)value;
/*-------------------------------------------------*\
| We are only interested in DDR4 and DDR5 systems |
\*-------------------------------------------------*/
valid = (mem_type == SPD_DDR4_SDRAM
|| mem_type == SPD_DDR4E_SDRAM
|| mem_type == SPD_LPDDR4_SDRAM
|| mem_type == SPD_LPDDR4X_SDRAM
|| mem_type == SPD_DDR5_SDRAM
|| mem_type == SPD_LPDDR5_SDRAM);
}
return;
}
/*---------------------------------------------------------*\
| If memory type could not be determined, detection failed |
\*---------------------------------------------------------*/
else
{
LOG_DEBUG("[SPDDetector] Memory type could not be determined for bus %d, address 0x%02x", bus->bus_id, address);
valid = false;
return;
}
/*---------------------------------------------------------*\
| If an accessor was created, save the memory type |
\*---------------------------------------------------------*/
valid = true;
mem_type = accessor->memory_type();
/*---------------------------------------------------------*\
| Delete the accessor |
\*---------------------------------------------------------*/
delete accessor;
}
uint8_t SPDDetector::spd_address() const
{
return(this->address);
}
i2c_smbus_interface *SPDDetector::smbus() const
{
return(this->bus);
}