2021-09-20 11:24:03 +02:00
|
|
|
# SPD tools
|
|
|
|
|
|
|
|
A set of tools to generate SPD files for platforms with memory down
|
|
|
|
configurations.
|
|
|
|
|
|
|
|
The memory technologies currently supported are:
|
|
|
|
|
|
|
|
* LPDDR4x - based on the JESD209-4C spec and Intel recommendations
|
|
|
|
(docs #616599, #610202, #634730).
|
|
|
|
* DDR4 - based on the JESD79-4C and Jedec 4.1.2.L-5 R29 v103 specs.
|
2021-10-07 07:08:18 +02:00
|
|
|
* LPDDR5 - based on the LPDDR5 spec JESD209-5B, the SPD spec SPD4.1.2.M-2 (the
|
|
|
|
LPDDR3/4 spec is used since JEDEC has not released an SPD spec for LPDDR5),
|
|
|
|
and Intel recommendations in advisory #616599.
|
2021-09-20 11:24:03 +02:00
|
|
|
|
|
|
|
There are two tools provided to assist with generating SPDs and Makefiles to
|
|
|
|
integrate into the coreboot build. These tools can also be used to allocate DRAM
|
|
|
|
IDs (configure DRAM hardware straps) for any memory part used by a board.
|
|
|
|
|
|
|
|
* `spd_gen`: This tool generates de-duplicated SPD files using a global memory
|
|
|
|
part list. It also generates a CSV manifest file which maps each memory part
|
|
|
|
in the global list to one of the generated SPD files. For each supported
|
|
|
|
memory technology, multiple sets of SPDs are generated. Each set corresponds
|
|
|
|
to a set of SoC platforms with different SPD requirements, e.g. due to
|
|
|
|
different expectations in the memory training code. Another CSV manifest
|
|
|
|
maps each supported platform to one of these sets.
|
|
|
|
* `part_id_gen`: This tool allocates DRAM strap IDs for the different memory
|
|
|
|
parts used by a board. It takes as input a CSV file of the memory parts used
|
|
|
|
with optional fixed IDs. It generates a Makefile.inc which is used to
|
|
|
|
integrate the SPD files generated by `spd_gen` into the coreboot build.
|
|
|
|
|
|
|
|
## Tool 1 - `spd_gen`
|
|
|
|
|
|
|
|
This program takes the following inputs:
|
|
|
|
|
|
|
|
* A JSON file containing a global list of memory parts with their attributes
|
|
|
|
as per the datasheet. This is the list of all known memory parts for the
|
|
|
|
given memory technology.
|
|
|
|
* The memory technology for which to generate the SPDs, e.g. "lp4x".
|
|
|
|
|
|
|
|
The input JSON file requires the following two fields for every memory part:
|
|
|
|
|
|
|
|
* `name`: The name of the memory part.
|
|
|
|
* `attribs`: A list of the memory part's attributes, as per its datasheet.
|
|
|
|
These attributes match the part specifications and are independent of any
|
|
|
|
SoC expectations. The tool takes care of translating the physical attributes
|
|
|
|
of the memory part to match JEDEC spec and memory traning code expectations.
|
|
|
|
|
|
|
|
The `attribs` field further contains two types of sub-field:
|
|
|
|
|
|
|
|
* Mandatory: These attributes must be provided for each memory part.
|
|
|
|
* Optional: These attributes may be provided for a memory part in order to
|
|
|
|
override the defaults.
|
|
|
|
|
|
|
|
The attributes are different for each memory technology.
|
|
|
|
|
|
|
|
### LP4x attributes
|
|
|
|
|
|
|
|
#### Mandatory
|
|
|
|
|
|
|
|
* `densityPerChannelGb`: Density in Gb of the physical channel.
|
|
|
|
|
|
|
|
* `banks`: Number of banks per physical channel. This is typically 8 for
|
|
|
|
LPDDR4x memory parts.
|
|
|
|
|
|
|
|
* `channelsPerDie`: Number of physical channels per die. Valid values: `1, 2,
|
|
|
|
4`. For a part with x16 bit width, number of channels per die is 1 or 2. For
|
|
|
|
a part with x8 bit width, number of channels can be 2 or 4 (4 is basically
|
|
|
|
when two dual-channel byte mode devices are combined as shown in Figure 3 in
|
|
|
|
JESD209-4C).
|
|
|
|
|
|
|
|
* `diesPerPackage`: Number of physical dies in each SDRAM package. As per
|
|
|
|
JESD209-4C, "Standard LPDDR4 package ballmaps allocate one ZQ ball per die."
|
|
|
|
Thus, number of diesPerPackage is the number of ZQ balls on the package.
|
|
|
|
|
|
|
|
* `bitWidthPerChannel`: Width of each physical channel. Valid values: `8, 16`
|
|
|
|
bits.
|
|
|
|
|
|
|
|
* `ranksPerChannel`: Number of ranks per physical channel. Valid values: `1,
|
|
|
|
2`. If the channels across multiple dies share the same DQ/DQS pins but use
|
|
|
|
a separate CS, then ranks is 2 else it is 1.
|
|
|
|
|
|
|
|
* `speedMbps`: Maximum data rate supported by the part in Mbps. Valid values:
|
|
|
|
`3200, 3733, 4267` Mbps.
|
|
|
|
|
|
|
|
#### Optional
|
|
|
|
|
|
|
|
* `trfcabNs`: Minimum Refresh Recovery Delay Time (tRFCab) for all banks in
|
|
|
|
nanoseconds. As per JESD209-4C, this is dependent on the density per
|
|
|
|
channel. Default values used:
|
|
|
|
|
|
|
|
* 6Gb : 280ns
|
|
|
|
* 8Gb : 280ns
|
|
|
|
* 12Gb: 380ns
|
|
|
|
* 16Gb: 380ns
|
|
|
|
|
|
|
|
* `trfcpbNs`: Minimum Refresh Recovery Delay Time (tRFCab) per bank in
|
|
|
|
nanoseconds. As per JESD209-4C, this is dependent on the density per
|
|
|
|
channel. Default values used:
|
|
|
|
|
|
|
|
* 6Gb : 140ns
|
|
|
|
* 8Gb : 140ns
|
|
|
|
* 12Gb: 190ns
|
|
|
|
* 16Gb: 190ns
|
|
|
|
|
|
|
|
* `trpabMinNs`: Minimum Row Precharge Delay Time (tRPab) for all banks in
|
|
|
|
nanoseconds. As per JESD209-4C, this is max(21ns, 4nck) which defaults to
|
|
|
|
`21ns`.
|
|
|
|
|
|
|
|
* `trppbMinNs`: Minimum Row Precharge Delay Time (tRPpb) per bank in
|
|
|
|
nanoseconds. As per JESD209-4C, this is max(18ns, 4nck) which defaults to
|
|
|
|
`18ns`.
|
|
|
|
|
|
|
|
* `tckMinPs`: SDRAM minimum cycle time (tckMin) value in picoseconds. This is
|
|
|
|
typically calculated based on the `speedMbps` attribute. `(1 / speedMbps) *
|
|
|
|
2`. Default values used(taken from JESD209-4C):
|
|
|
|
|
|
|
|
* 4267 Mbps: 468ps
|
|
|
|
* 3733 Mbps: 535ps
|
|
|
|
* 3200 Mbps: 625ps
|
|
|
|
|
|
|
|
* `tckMaxPs`: SDRAM maximum cycle time (tckMax) value in picoseconds. Default
|
|
|
|
value used: `31875ps`. As per JESD209-4C, TCKmax should be 100ns (100000ps)
|
|
|
|
for all speed grades. But the SPD byte to encode this field is only 1 byte.
|
|
|
|
Hence, the maximum value that can be encoded is 31875ps.
|
|
|
|
|
|
|
|
* `taaMinPs`: Minimum CAS Latency Time(taaMin) in picoseconds. This value
|
|
|
|
defaults to nck * tckMin, where nck is minimum CAS latency.
|
|
|
|
|
|
|
|
* `trcdMinNs`: Minimum RAS# to CAS# Delay Time (tRCDmin) in nanoseconds. As
|
|
|
|
per JESD209-4C, this is max(18ns, 4nck) which defaults to `18ns`.
|
|
|
|
|
|
|
|
* `casLatencies`: List of CAS latencies supported by the part. This is
|
|
|
|
dependent on the attrib `speedMbps`. Default values used:
|
|
|
|
|
|
|
|
* 4267: `"6 10 14 20 24 28 32 36"`.
|
|
|
|
* 3733: `"6 10 14 20 24 28 32"`.
|
|
|
|
* 3200: `"6 10 14 20 24 28"`.
|
|
|
|
|
|
|
|
#### Example `memory_parts.json`
|
|
|
|
|
|
|
|
```
|
|
|
|
{
|
|
|
|
"parts": [
|
|
|
|
{
|
|
|
|
"name": "MT53D512M64D4NW-046 WT:F",
|
|
|
|
"attribs": {
|
|
|
|
"densityPerChannelGb": 8,
|
|
|
|
"banks": 8,
|
|
|
|
"channelsPerDie": 2,
|
|
|
|
"diesPerPackage": 2,
|
|
|
|
"bitWidthPerChannel": 16,
|
|
|
|
"ranksPerChannel": 1,
|
|
|
|
"speedMbps": 4267
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "NT6AP256T32AV-J1",
|
|
|
|
"attribs": {
|
|
|
|
"densityPerChannelGb": 4,
|
|
|
|
"banks": 8,
|
|
|
|
"channelsPerDie": 2,
|
|
|
|
"diesPerPackage": 1,
|
|
|
|
"bitWidthPerChannel": 16,
|
|
|
|
"ranksPerChannel": 1,
|
|
|
|
"speedMbps": 4267,
|
|
|
|
"tckMaxPs": 1250,
|
|
|
|
"casLatencies": "14 20 24 28 32 36"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
]
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### DDR4 attributes
|
|
|
|
|
|
|
|
#### Mandatory
|
|
|
|
|
|
|
|
* `speedMTps`: Maximum rate supported by the part in MT/s. Valid values:
|
|
|
|
`1600, 1866, 2133, 2400, 2666, 2933, 3200` MT/s.
|
|
|
|
|
|
|
|
* `CL_nRCD_nRP`: Refers to CAS Latency specified for the part (find
|
|
|
|
"CL-nRCD-nRP" in the vendor spec for the DDR4 part).
|
|
|
|
|
|
|
|
* `capacityPerDieGb`: Capacity per die in gigabits. Valid values: `2, 4, 8,
|
|
|
|
16` Gb part.
|
|
|
|
|
|
|
|
* `diesPerPackage`: Number of dies on the part. Valid values: `1, 2` dies per
|
|
|
|
package.
|
|
|
|
|
|
|
|
* `packageBusWidth`: Number of bits of the device's address bus. Valid values:
|
|
|
|
`8, 16` bit-wide bus. NOTE: Width of x4 is not supported by this tool.
|
|
|
|
|
|
|
|
* `ranksPerPackage`: From Jedec doc 4_01_02_AnnexL-1R23: “Package ranks per
|
|
|
|
DIMM” refers to the collections of devices on the module sharing common chip
|
|
|
|
select signals (across the data width of the DIMM), either from the edge
|
|
|
|
connector for unbuffered modules or from the outputs of a registering clock
|
|
|
|
driver for RDIMMs and LRDIMMs.Number of bits of the device's address bus.
|
|
|
|
Valid values: `1, 2` package ranks.
|
|
|
|
|
|
|
|
#### Optional
|
|
|
|
|
|
|
|
The following options are calculated by the tool based on the mandatory
|
|
|
|
attributes described for the part, but there may be cases where a default value
|
|
|
|
must be overridden, such as when a device appears to be 3200AA, but does not
|
|
|
|
support all of the CAS latencies typically supported by a speed bin 3200AA part.
|
|
|
|
To deal with such a case, the variable can be overridden here and the tool will
|
|
|
|
use this value instead of calculating one. All values must be defined in
|
|
|
|
picosecond units, except for "CASLatencies", which would be represented as a
|
|
|
|
string like "9 10 11 12 14".
|
|
|
|
|
|
|
|
* `TAAMinPs`: Defines the minimum CAS Latency. Table 48 of Jedec doc
|
|
|
|
4_01_02_AnnexL-5R29 lists tAAmin for each speed grade.
|
|
|
|
|
|
|
|
* `TRASMinPs`: Refers to the minimum active to precharge delay time. Table 55
|
|
|
|
of Jedec doc 4_01_02_AnnexL-5R29 lists tRPmin for each speed grade.
|
|
|
|
|
|
|
|
* `TCKMinPs`: Refers to the minimum clock cycle time. Table 42 of Jedec doc
|
|
|
|
4_01_02_AnnexL-5R29 lists tCKmin for each speed grade.
|
|
|
|
|
|
|
|
* `TCKMaxPs`:Refers to the minimum clock cycle time. Table 44 of Jedec doc
|
|
|
|
4_01_02_AnnexL-5R29 lists tCKmin for each speed grade.
|
|
|
|
|
|
|
|
* `TRFC1MinPs`: Refers to the minimum refresh recovery delay time. Table 59 of
|
|
|
|
Jedec doc 4_01_02_AnnexL-5R29 lists tRFC1min for each page size.
|
|
|
|
|
|
|
|
* `TRFC2MinPs`: Refers to the minimum refresh recovery delay time. Table 61 of
|
|
|
|
Jedec doc 4_01_02_AnnexL-5R29 lists tRFC2min for each page size.
|
|
|
|
|
|
|
|
* `TRFC4MinPs`: Refers to the minimum refresh recovery delay time. Table 63 of
|
|
|
|
Jedec doc 4_01_02_AnnexL-5R29 lists tRFC4min for each page size.
|
|
|
|
|
|
|
|
* `TFAWMinPs`:: Refers to the minimum four activate window delay time. Table
|
|
|
|
66 of Jedec doc 4_01_02_AnnexL-5R29 lists tFAWmin for each speed grade and
|
|
|
|
page size combination.
|
|
|
|
|
|
|
|
* `TRRDSMinPs`: Refers to the minimum activate to activate delay time to
|
|
|
|
different bank groups. Table 68 of Jedec doc 4_01_02_AnnexL-5R29 lists
|
|
|
|
tRRD_Smin for each speed grade and page size combination.
|
|
|
|
|
|
|
|
* `TRRDLMinPs`: Refers to the minimum activate to activate delay time to the
|
|
|
|
same bank group. Table 70 of Jedec doc 4_01_02_AnnexL-5R29 lists tRRD_Lmin
|
|
|
|
for each speed grade and page size combination.
|
|
|
|
|
|
|
|
* `TCCDLMinPs`: Refers to the minimum CAS to CAS delay time to same bank
|
|
|
|
group. Table 72 of Jedec doc 4_01_02_AnnexL-5R29 lists tCCD_Lmin for each
|
|
|
|
speed grade.
|
|
|
|
|
|
|
|
* `TWRMinPs`: Refers to the minimum write recovery time. Table 75 of Jedec doc
|
|
|
|
4_01_02_AnnexL-5R29 lists tWRmin for each ddr4 type.
|
|
|
|
|
|
|
|
* `TWTRSMinPs`: Refers to minimum write to read time to different bank group.
|
|
|
|
Table 78 of Jedec doc 4_01_02_AnnexL-5R29 lists tWTR_Smin for each ddr4
|
|
|
|
type.
|
|
|
|
|
|
|
|
* `TWTRLMinPs`: Refers to minimum write to read time to same bank group. Table
|
|
|
|
80 of Jedec doc 4_01_02_AnnexL-5R29 lists tWTR_Lmin for each ddr4 type.
|
|
|
|
|
|
|
|
* `CASLatencies`: Refers to the CAS latencies supported by the part. The speed
|
|
|
|
bin tables in the back of Jedec doc 4_01_02_AnnexL-5R29 define the standard
|
|
|
|
CAS latencies that a speed bin part is supposed to support. In cases where a
|
|
|
|
part does not support all of the CAS latencies listed in the speed bin
|
|
|
|
tables, this entry should be used to override the default settings.
|
|
|
|
|
|
|
|
#### Example `memory_parts.json`
|
|
|
|
|
|
|
|
```
|
|
|
|
{
|
|
|
|
"parts": [
|
|
|
|
{
|
|
|
|
"name": "K4A8G165WC-BCWE",
|
|
|
|
"attribs": {
|
|
|
|
"speedMTps": 3200,
|
|
|
|
"CL_nRCD_nRP": 22,
|
|
|
|
"capacityPerDieGb": 8,
|
|
|
|
"diesPerPackage": 1,
|
|
|
|
"packageBusWidth": 16,
|
|
|
|
"ranksPerPackage": 1
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "MT40A1G16KD-062E:E",
|
|
|
|
"attribs": {
|
|
|
|
"speedMTps": 3200,
|
|
|
|
"CL_nRCD_nRP": 22,
|
|
|
|
"capacityPerDieGb": 16,
|
|
|
|
"diesPerPackage": 1,
|
|
|
|
"packageBusWidth": 16,
|
|
|
|
"ranksPerPackage": 1,
|
|
|
|
"TRFC1MinPs": 350000,
|
|
|
|
"TRFC2MinPs": 260000,
|
|
|
|
"TRFC4MinPs": 160000
|
|
|
|
}
|
|
|
|
},
|
|
|
|
]
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2021-10-07 07:08:18 +02:00
|
|
|
### LP5 attributes
|
|
|
|
|
|
|
|
#### Mandatory
|
|
|
|
|
|
|
|
* `densityPerDieGb`: Density per die in Gb. Valid values: `4, 6, 8, 12, 16,
|
|
|
|
24, 32` Gb per die.
|
|
|
|
|
|
|
|
* `diesPerPackage`: Number of physical dies in each SDRAM package. Valid
|
|
|
|
values: `2, 4, 8` dies per package.
|
|
|
|
|
|
|
|
* `bitWidthPerChannel`: Width of each physical channel. Valid values: `8, 16`
|
|
|
|
bits.
|
|
|
|
|
|
|
|
* `ranksPerChannel`: Number of ranks per physical channel. Valid values: `1,
|
|
|
|
2`. If the channels across multiple dies share the same DQ/DQS pins but use
|
|
|
|
a separate CS, then ranks is 2 else it is 1.
|
|
|
|
|
|
|
|
* `speedMbps`: Maximum data rate supported by the part in Mbps. Valid values:
|
|
|
|
`5500, 6400` Mbps.
|
|
|
|
|
|
|
|
#### Optional
|
|
|
|
|
|
|
|
* `trfcabNs`: Minimum Refresh Recovery Delay Time (tRFCab) for all banks in
|
|
|
|
nanoseconds. As per JESD209-5B, this is dependent on the density per die.
|
|
|
|
Default values used:
|
|
|
|
|
|
|
|
* 4 Gb : 180 ns
|
|
|
|
* 6 Gb : 210 ns
|
|
|
|
* 8 Gb : 210 ns
|
|
|
|
* 12 Gb: 280 ns
|
|
|
|
* 16 Gb: 280 ns
|
|
|
|
* 24 Gb: 380 ns
|
|
|
|
* 32 Gb: 380 ns
|
|
|
|
|
|
|
|
* `trfcpbNs`: Minimum Refresh Recovery Delay Time (tRFCpb) per bank in
|
|
|
|
nanoseconds. As per JESD209-5B, this is dependent on the density per die.
|
|
|
|
Default values used:
|
|
|
|
|
|
|
|
* 4 Gb : 90 ns
|
|
|
|
* 6 Gb : 120 ns
|
|
|
|
* 8 Gb : 120 ns
|
|
|
|
* 12 Gb: 140 ns
|
|
|
|
* 16 Gb: 140 ns
|
|
|
|
* 24 Gb: 190 ns
|
|
|
|
* 32 Gb: 190 ns
|
|
|
|
|
|
|
|
* `trpabMinNs`: Minimum Row Precharge Delay Time (tRPab) for all banks in
|
|
|
|
nanoseconds. As per JESD209-5B, this is max(21ns, 2nCK), which defaults to
|
|
|
|
`21 ns`.
|
|
|
|
|
|
|
|
* `trppbMinNs`: Minimum Row Precharge Delay Time (tRPpb) per bank in
|
|
|
|
nanoseconds. As per JESD209-5B, this is max(18ns, 2nCK) which defaults to
|
|
|
|
`18 ns`.
|
|
|
|
|
|
|
|
* `tckMinPs`: SDRAM minimum cycle time (tCKmin) value in picoseconds. LPDDR5
|
|
|
|
has two clocks: the command/addrees clock (CK) and the data clock (WCK).
|
|
|
|
They are related by the WCK:CK ratio, which can be either 4:1 or 2:1. For
|
|
|
|
LPDDR5, tCKmin is the CK period, which can be calculated from the
|
|
|
|
`speedMbps` attribute and the WCK:CK ratio as follows: `tCKmin = 1 /
|
|
|
|
(speedMbps / 2 / WCK:CK)`. The default values used are for a 4:1 WCK:CK
|
|
|
|
ratio:
|
|
|
|
|
|
|
|
* 6400 Mbps: 1250 ps
|
|
|
|
* 5500 Mbps: 1455 ps
|
|
|
|
|
|
|
|
* `taaMinPs`: Minimum CAS Latency Time(tAAmin) in picoseconds. This value
|
|
|
|
defaults to nck * tCKmin, where nck is maximum CAS latency, and is
|
|
|
|
determined from the `speedMbps` attribute as per JESD209-5B:
|
|
|
|
|
|
|
|
* 6400 Mbps: 17
|
|
|
|
* 5500 Mbps: 15
|
|
|
|
|
|
|
|
* `trcdMinNs`: Minimum RAS# to CAS# Delay Time (tRCDmin) in nanoseconds. As
|
|
|
|
per JESD209-5B, this is max(18ns, 2nCK) which defaults to `18 ns`.
|
|
|
|
|
|
|
|
#### Example `memory_parts.json`
|
|
|
|
|
|
|
|
```
|
|
|
|
{
|
|
|
|
"parts": [
|
|
|
|
{
|
|
|
|
"name": "MT62F1G32D4DR-031 WT:B",
|
|
|
|
"attribs": {
|
|
|
|
"densityPerDieGb": 8,
|
|
|
|
"diesPerPackage": 4,
|
|
|
|
"bitWidthPerChannel": 16,
|
|
|
|
"ranksPerChannel": 2,
|
|
|
|
"speedMbps": 6400
|
|
|
|
}
|
|
|
|
},
|
|
|
|
]
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2021-09-20 11:24:03 +02:00
|
|
|
### Output
|
|
|
|
|
|
|
|
The `spd_gen` tool generates the directory structure shown below. The inputs to
|
|
|
|
the tool are the `memory_parts.json` files, and all other files are generated.
|
|
|
|
|
|
|
|
```
|
|
|
|
spd
|
|
|
|
|
|
|
|
|
|_ lp4x
|
|
|
|
|
|
|
|
|
|_ memory_parts.json
|
|
|
|
|_ platforms_manifest.generated.txt
|
|
|
|
|_ set-0
|
|
|
|
|_parts_spd_manifest.generated.txt
|
|
|
|
|_spd-1.hex
|
|
|
|
|_spd-2.hex
|
|
|
|
|_...
|
|
|
|
|_ set-1
|
|
|
|
|_...
|
|
|
|
|_...
|
|
|
|
|
|
|
|
|
|_ ddr4
|
|
|
|
|
|
|
|
|
|_ memory_parts.json
|
|
|
|
|_ platforms_manifest.generated.txt
|
|
|
|
|_ set-0
|
|
|
|
|_parts_spd_manifest.generated.txt
|
|
|
|
|_spd-1.hex
|
|
|
|
|_spd-2.hex
|
|
|
|
|_...
|
|
|
|
|_ set-1
|
|
|
|
|_...
|
|
|
|
|_...
|
|
|
|
|_...
|
|
|
|
```
|
|
|
|
|
|
|
|
The files generated are:
|
|
|
|
|
|
|
|
* `spd-X.hex`: Deduplicated SPDs for all the memory parts in the input JSON
|
|
|
|
file.
|
|
|
|
|
|
|
|
* `parts_spd_manifest.generated.txt`: A CSV file mapping each memory part to
|
|
|
|
one of the deduplicated SPD files. E.g.
|
|
|
|
|
|
|
|
```
|
|
|
|
H9HCNNNBKMMLXR-NEE,spd-1.hex
|
|
|
|
H9HCNNNFAMMLXR-NEE,spd-2.hex
|
|
|
|
K4U6E3S4AA-MGCL,spd-1.hex
|
|
|
|
K4UBE3D4AA-MGCL,spd-3.hex
|
|
|
|
MT53E1G32D2NP-046 WT:A,spd-4.hex
|
|
|
|
```
|
|
|
|
|
|
|
|
* `platforms_manifest.generated.txt`: A CSV file mapping each platform to the
|
|
|
|
SPD set used by that platform. E.g.
|
|
|
|
|
|
|
|
```
|
|
|
|
TGL,set-0
|
|
|
|
ADL,set-0
|
|
|
|
JSL,set-1
|
|
|
|
CZN,set-1
|
|
|
|
```
|
|
|
|
|
|
|
|
## Tool 2 - `part_id_gen`
|
|
|
|
|
|
|
|
This program takes the following inputs:
|
|
|
|
|
|
|
|
* The SoC platform which the board is based on, e.g. ADL.
|
|
|
|
* The memory technology used by the board, e.g. lp4x.
|
|
|
|
* The path to the directory where the generated Makefile.inc should be placed.
|
|
|
|
* A CSV file containing a list of the memory parts used by the board, with an
|
2022-03-17 20:14:12 +01:00
|
|
|
* optional fixed or exclusive ID for each part. A fixed ID is simply an integer
|
|
|
|
* and it ensure that part (and any that share the same SPD) will be assigned
|
|
|
|
* that ID. An exclusive ID is prefixed with `*` and ensures that only parts with
|
|
|
|
* the same exclusive ID will be assigned that ID, even if they would otherwise
|
|
|
|
* share the same ID.
|
|
|
|
* NOTE: Only assign a fixed/exclusive ID if required for legacy reasons.
|
2021-09-20 11:24:03 +02:00
|
|
|
|
2022-03-17 20:14:12 +01:00
|
|
|
Example of a CSV file using fixed and exclusive IDs:
|
2021-09-20 11:24:03 +02:00
|
|
|
|
|
|
|
```
|
|
|
|
K4AAG165WA-BCWE,1
|
|
|
|
MT40A512M16TB-062E:J
|
|
|
|
MT40A1G16KD-062E:E
|
|
|
|
K4A8G165WC-BCWE
|
|
|
|
H5AN8G6NDJR-XNC,8
|
2022-03-17 20:14:12 +01:00
|
|
|
H5ANAG6NCMR-XNC,*9
|
2021-09-20 11:24:03 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
Explanation: This will ensure that the SPDs for K4AAG165WA-BCWE and
|
2022-03-17 20:14:12 +01:00
|
|
|
H5AN8G6NDJR-XNC are assigned to IDs 1 and 8 respectively. H5ANAG6NCMR-XNC
|
|
|
|
will be assigned ID 9 and no other part will be assigned ID 9 even if it
|
|
|
|
shares the same SPD. The SPDs for all other memory parts will be assigned to
|
|
|
|
the first compatible ID. Assigning fixed/exclusive IDs may result in duplicate
|
|
|
|
SPD entries or gaps in the ID mapping.
|
2021-09-20 11:24:03 +02:00
|
|
|
|
|
|
|
### Output
|
|
|
|
|
|
|
|
The `part_id_gen` tool outputs the following:
|
|
|
|
|
|
|
|
* It prints the DRAM hardware strap ID which should be allocated to each
|
|
|
|
memory part in the input file.
|
|
|
|
* It generates a `Makefile.inc` in the given directory. This is used to
|
|
|
|
integrate the SPD files generated by `spd_gen` with the coreboot build for
|
|
|
|
the board.
|
|
|
|
* It generates a `dram_id.generated.txt` in the same directory as the
|
|
|
|
`Makefile.inc`. This lists the part IDs assigned to each memory part, and is
|
|
|
|
useful for itegration with the board schematics.
|
|
|
|
|
|
|
|
Sample `Makefile.inc`:
|
|
|
|
|
|
|
|
```
|
|
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
# This is an auto-generated file. Do not edit!!
|
|
|
|
# Generated by:
|
|
|
|
# util/spd_tools/bin/part_id_gen ADL lp4x src/mainboard/google/brya/variants/felwinter/memory src/mainboard/google/brya/variants/felwinter/memory/mem_parts_used.txt
|
|
|
|
|
|
|
|
SPD_SOURCES =
|
|
|
|
SPD_SOURCES += spd/lp4x/set-0/spd-1.hex # ID = 0(0b0000) Parts = K4U6E3S4AA-MGCR, H9HCNNNBKMMLXR-NEE
|
|
|
|
SPD_SOURCES += spd/lp4x/set-0/spd-3.hex # ID = 1(0b0001) Parts = K4UBE3D4AA-MGCR
|
|
|
|
SPD_SOURCES += spd/lp4x/set-0/spd-4.hex # ID = 2(0b0010) Parts = MT53E1G32D2NP-046 WT:A
|
|
|
|
```
|
|
|
|
|
|
|
|
NOTE: Empty entries may be required if there is a gap created by a memory part
|
|
|
|
with a fixed ID.
|
|
|
|
|
|
|
|
Sample `dram_id.generated.txt`:
|
|
|
|
|
|
|
|
```
|
|
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
# This is an auto-generated file. Do not edit!!
|
|
|
|
# Generated by:
|
|
|
|
# util/spd_tools/bin/part_id_gen ADL lp4x src/mainboard/google/brya/variants/felwinter/memory src/mainboard/google/brya/variants/felwinter/memory/mem_parts_used.txt
|
|
|
|
|
|
|
|
DRAM Part Name ID to assign
|
|
|
|
K4U6E3S4AA-MGCR 0 (0000)
|
|
|
|
K4UBE3D4AA-MGCR 1 (0001)
|
|
|
|
H9HCNNNBKMMLXR-NEE 0 (0000)
|
|
|
|
MT53E1G32D2NP-046 WT:A 2 (0010)
|
|
|
|
```
|
|
|
|
|
|
|
|
### Note of caution
|
|
|
|
|
|
|
|
The `part_id_gen` tool assigns DRAM IDs based on the order of the part names in
|
|
|
|
the input file. Thus, when adding a new memory part to the list, it should
|
|
|
|
always go at the end of the file. This guarantees that the memory parts that
|
|
|
|
were already assigned IDs do not change.
|
|
|
|
|
|
|
|
## How to build the tools?
|
|
|
|
|
|
|
|
```
|
|
|
|
make clean -C util/spd_tools
|
|
|
|
make -C util/spd_tools
|
|
|
|
```
|
|
|
|
|
|
|
|
## How to use the tools?
|
|
|
|
|
|
|
|
### `spd_gen`
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
|
|
|
|
```
|
|
|
|
util/spd_tools/bin/spd_gen <mem_parts_list_json> <mem_technology>
|
|
|
|
```
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
```
|
|
|
|
util/spd_tools/bin/spd_gen spd/lp4x/memory_parts.json lp4x
|
|
|
|
```
|
|
|
|
|
|
|
|
### `part_id_gen`
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
|
|
|
|
```
|
|
|
|
util/spd_tools/bin/part_id_gen <platform> <mem_technology> <makefile_dir> <mem_parts_used_file>
|
|
|
|
```
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
```
|
|
|
|
util/spd_tools/bin/part_id_gen \
|
|
|
|
ADL \
|
|
|
|
lp4x \
|
|
|
|
src/mainboard/google/brya/variants/felwinter/memory \
|
|
|
|
src/mainboard/google/brya/variants/felwinter/memory/mem_parts_used.txt
|
|
|
|
```
|
|
|
|
|
|
|
|
### Need to add a new memory part for a board?
|
|
|
|
|
|
|
|
* If the memory part is not present in the global list of memory parts for
|
|
|
|
that memory technology (e.g. `spd/lp4x/memory_parts.json`), then add the
|
|
|
|
memory part name and attributes as per the datasheet.
|
|
|
|
|
|
|
|
* Use `spd_gen` to regenerate all the SPD files and manifests for that
|
|
|
|
memory technology. Either a new SPD file will be generated for the new
|
|
|
|
part, or an existing one will be reused.
|
|
|
|
* Upload the new SPD (if one is created) and the manifest changes for
|
|
|
|
review.
|
|
|
|
|
|
|
|
* Update the file containing the memory parts used by board (variant), by
|
|
|
|
adding the new memory part name at the end of the file.
|
|
|
|
|
|
|
|
* Use `part_id_gen` to update the variant's `Makefile.inc` and
|
|
|
|
`dram_id.generated.txt` with the new part.
|
|
|
|
* Upload the changes to `Makefile.inc` and `dram_id.generated.txt` for
|
|
|
|
review.
|
2021-11-08 01:18:42 +01:00
|
|
|
|
|
|
|
## How to add support for a new memory technology
|
|
|
|
|
|
|
|
### 1. Gather the SPD requirements
|
|
|
|
|
|
|
|
To generate SPDs for the new memory technology, information is needed about the
|
|
|
|
list of bytes in the SPD and how the value of each byte should be determined.
|
|
|
|
This information usually comes from a combination of:
|
|
|
|
|
|
|
|
* The JEDEC spec for the memory technology, e.g. JESD209-5B for LPDDR5.
|
|
|
|
* The JEDEC SPD spec for the memory technology, e.g. SPD4.1.2.M-2 for LPDDR3/4
|
|
|
|
(also used for LP4x and LP5).
|
|
|
|
* Platform-specific requirements. SoC vendors often don't follow the JEDEC
|
|
|
|
specs exactly. E.g. the memory training code may expect certain SPD bytes to
|
|
|
|
encode a different value to what is stated in the spec. So for each SoC
|
|
|
|
platform using the new memory technology, any platform-specific requirements
|
|
|
|
need to be gathered.
|
|
|
|
|
|
|
|
### 2. Implement support in spd_tools
|
|
|
|
|
|
|
|
Support for the new memory technology needs to be added to both the `spd_gen`
|
|
|
|
and `part_id_gen` tools.
|
|
|
|
|
|
|
|
#### `spd_gen`
|
|
|
|
|
|
|
|
Adding support to `spd_gen` requires implementing the logic to generate SPDs for
|
|
|
|
the new memory technology. The changes required are:
|
|
|
|
|
|
|
|
* Add the new memory technology to the `memTechMap` in `spd_gen/spd_gen.go`.
|
|
|
|
* Add a new file `spd_gen/<mem_tech>.go`. This file will contain all the logic
|
|
|
|
for generating SPDs for the new memory technology. It needs to implement the
|
|
|
|
`memTech` interface defined in `spd_gen/spd_gen.go`. The interface functions
|
|
|
|
are documented inline. Examples of how the interface is implemented for
|
|
|
|
existing memory technologies can be found in the `spd_gen/` directory, e.g.
|
|
|
|
`lp4x.go`, `ddr4.go`, `lp5.go`. While not strictly necessary, it is
|
|
|
|
recommended to follow the overall structure of these existing files when
|
|
|
|
adding a new memory technology.
|
|
|
|
|
|
|
|
#### `part_id_gen`
|
|
|
|
|
|
|
|
The `part_id_gen` tool is memory technology-agnostic, so the only change
|
|
|
|
required is:
|
|
|
|
|
|
|
|
* Add the new memory technology to the `supportedMemTechs` list in
|
|
|
|
`part_id_gen/part_id_gen.go`.
|