Skip to content

Commit 81128d1

Browse files
KasslimCalcProgrammer1
authored andcommitted
add part_number() to SPDAccessor interfaces and implement
1 parent ac00a8f commit 81128d1

4 files changed

Lines changed: 65 additions & 0 deletions

File tree

SPDAccessor/SPDAccessor.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,17 @@ using namespace std::chrono_literals;
2929
#define BASIC_MEMORY_TYPE_ADDR (0x02)
3030

3131
#define DDR4_JEDEC_ID_ADDR (0x140)
32+
#define DDR4_PART_NR_START (0x149)
33+
#define DDR4_PART_NR_END (0x15C)
34+
#define DDR4_PART_NR_LEN (DDR4_PART_NR_END - DDR4_PART_NR_START + 1)
3235
#define DDR4_MANUF_SPECIFIC_START (0x161)
3336
#define DDR4_MANUF_SPECIFIC_END (0x17D)
3437
#define DDR4_MANUF_SPECIFIC_LEN (DDR4_MANUF_SPECIFIC_END - DDR4_MANUF_SPECIFIC_START + 1)
3538

3639
#define DDR5_JEDEC_ID_ADDR (0x200)
40+
#define DDR5_PART_NR_START (0x209)
41+
#define DDR5_PART_NR_END (0x226)
42+
#define DDR5_PART_NR_LEN (DDR5_PART_NR_END - DDR5_PART_NR_START + 1)
3743
#define DDR5_MANUF_SPECIFIC_START (0x22B)
3844
#define DDR5_MANUF_SPECIFIC_END (0x27F)
3945
#define DDR5_MANUF_SPECIFIC_LEN (DDR5_MANUF_SPECIFIC_END - DDR5_MANUF_SPECIFIC_START + 1)
@@ -105,6 +111,36 @@ SPDAccessor *SPDAccessor::for_memory_type(SPDMemoryType type, i2c_smbus_interfac
105111
return(nullptr);
106112
};
107113

114+
std::string SPDAccessor::read_part_nr_at(uint16_t address, std::size_t len)
115+
{
116+
std::string part_number;
117+
118+
for(std::size_t i = 0; i < len; i++)
119+
{
120+
std::size_t spd_addr = address + i;
121+
part_number += (char)this->at(spd_addr);
122+
}
123+
124+
// Find the true end of string & truncate it to that point.
125+
// Part number should be padded with 0x20 (space) for DDR4 (Source: Wikipedia)
126+
// It may be padded with 0x00 (Source: real-life tests on DDR5 memory)
127+
// Note: To prevent infinite loop, end_of_string_idx MUST be signed.
128+
int end_of_string_idx = part_number.length()-1;
129+
for(; end_of_string_idx >= 0; end_of_string_idx--)
130+
{
131+
if(
132+
part_number[end_of_string_idx] != '\0' &&
133+
part_number[end_of_string_idx] != ' '
134+
)
135+
{
136+
break;
137+
}
138+
}
139+
part_number = part_number.substr(0, end_of_string_idx + 1);
140+
141+
return part_number;
142+
}
143+
108144
/*---------------------------------------------------------*\
109145
| Internal implementation for specific memory type. |
110146
\*---------------------------------------------------------*/
@@ -128,6 +164,11 @@ uint16_t DDR4Accessor::jedec_id()
128164
return((this->at(DDR4_JEDEC_ID_ADDR) << 8) + (this->at(DDR4_JEDEC_ID_ADDR+1) & 0x7f) - 1);
129165
}
130166

167+
std::string DDR4Accessor::part_number()
168+
{
169+
return this->read_part_nr_at(DDR4_PART_NR_START, DDR4_PART_NR_LEN);
170+
}
171+
131172
uint8_t DDR4Accessor::manufacturer_data(uint16_t index)
132173
{
133174
if(index > DDR4_MANUF_SPECIFIC_LEN-1)
@@ -157,6 +198,11 @@ uint16_t DDR5Accessor::jedec_id()
157198
return((this->at(DDR5_JEDEC_ID_ADDR) << 8) + (this->at(DDR5_JEDEC_ID_ADDR+1) & 0x7f) - 1);
158199
}
159200

201+
std::string DDR5Accessor::part_number()
202+
{
203+
return this->read_part_nr_at(DDR5_PART_NR_START, DDR5_PART_NR_LEN);
204+
}
205+
160206
uint8_t DDR5Accessor::manufacturer_data(uint16_t index)
161207
{
162208
if(index > DDR5_MANUF_SPECIFIC_LEN-1)

SPDAccessor/SPDAccessor.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111

1212
#include "SPDCommon.h"
1313

14+
#include <cstddef>
15+
#include <cstdint>
16+
#include <string>
17+
1418
class SPDAccessor
1519
{
1620
public:
@@ -21,6 +25,7 @@ class SPDAccessor
2125

2226
virtual SPDMemoryType memory_type() = 0;
2327
virtual uint16_t jedec_id() = 0;
28+
virtual std::string part_number() = 0;
2429
virtual uint8_t manufacturer_data(uint16_t index) = 0;
2530

2631
virtual SPDAccessor *copy() = 0;
@@ -30,6 +35,8 @@ class SPDAccessor
3035
protected:
3136
i2c_smbus_interface *bus;
3237
uint8_t address;
38+
39+
std::string read_part_nr_at(uint16_t address, std::size_t len);
3340
};
3441

3542
/*---------------------------------------------------------*\
@@ -43,6 +50,7 @@ class DDR4Accessor : public SPDAccessor
4350
virtual ~DDR4Accessor();
4451
virtual SPDMemoryType memory_type();
4552
virtual uint16_t jedec_id();
53+
virtual std::string part_number();
4654
virtual uint8_t manufacturer_data(uint16_t index);
4755
};
4856

@@ -53,5 +61,6 @@ class DDR5Accessor : public SPDAccessor
5361
virtual ~DDR5Accessor();
5462
virtual SPDMemoryType memory_type();
5563
virtual uint16_t jedec_id();
64+
virtual std::string part_number();
5665
virtual uint8_t manufacturer_data(uint16_t index);
5766
};

SPDAccessor/SPDWrapper.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ uint16_t SPDWrapper::jedec_id()
8383
return jedec_id_val;
8484
}
8585

86+
std::string SPDWrapper::part_number()
87+
{
88+
if(accessor == nullptr)
89+
{
90+
return std::string();
91+
}
92+
return accessor->part_number();
93+
}
94+
8695
uint8_t SPDWrapper::manufacturer_data(uint16_t index)
8796
{
8897
if(accessor == nullptr)

SPDAccessor/SPDWrapper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class SPDWrapper
2424
SPDMemoryType memory_type();
2525
int index();
2626
uint16_t jedec_id();
27+
std::string part_number();
2728
uint8_t manufacturer_data(uint16_t index);
2829

2930
private:

0 commit comments

Comments
 (0)