-
-
Notifications
You must be signed in to change notification settings - Fork 222
/
Copy pathSPDDetector.cpp
137 lines (121 loc) · 4.45 KB
/
SPDDetector.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*---------------------------------------------------------*\
| SPDDetector.cpp |
| |
| Detector for DRAM modules using SPD information |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#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;
LOG_DEBUG("[SPDDetector] Probing DRAM on bus %d address 0x%02x", bus->bus_id, address);
/*---------------------------------------------------------*\
| 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))
{
accessor = new EE1004Accessor(bus, address);
}
else if(SPD5118Accessor::isAvailable(bus, 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))
{
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))
{
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_TRACE("[SPDDetector] Probing memory type older than DDR4");
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
{
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);
}