util/spd_tools: Implement a unified version of the spd_gen tool
Currently there are two versions of spd_tools: one for LP4x and one for DDR4. This change is the first step in unifying these into a single tool. This change implements a unified version of the spd_gen tool, by combining the functionality currently in lp4x/gen_spd.go and ddr4/gen_spd.go. The unified version takes the memory technology as an argument, and generates SPD files for all platforms supporting that technology. BUG=b:191776301 TEST=Compare the SPDs generated by the old and new versions of the tool for all supported platforms. For reference, the test script used is here: https://review.coreboot.org/c/coreboot/+/57511 Signed-off-by: Reka Norman <rekanorman@google.com> Change-Id: I7fc036996dbafbb54e075da0c3ac2ea0886a6db2 Reviewed-on: https://review.coreboot.org/c/coreboot/+/57512 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Furquan Shaikh <furquan@google.com> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org> Reviewed-by: Karthik Ramasubramanian <kramasub@google.com> Reviewed-by: Michael Niewöhner <foss@mniewoehner.de>
This commit is contained in:
		
							
								
								
									
										1
									
								
								util/spd_tools/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								util/spd_tools/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,2 +1,3 @@
 | 
				
			|||||||
*/gen_spd
 | 
					*/gen_spd
 | 
				
			||||||
*/gen_part_id
 | 
					*/gen_part_id
 | 
				
			||||||
 | 
					bin
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								util/spd_tools/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								util/spd_tools/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					SPD_GEN = bin/spd_gen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					all: $(SPD_GEN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(SPD_GEN):
 | 
				
			||||||
 | 
						go build -o $(SPD_GEN) src/spd_gen/*.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					clean:
 | 
				
			||||||
 | 
						rm -rf bin/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PHONY: all
 | 
				
			||||||
							
								
								
									
										1284
									
								
								util/spd_tools/src/spd_gen/ddr4.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1284
									
								
								util/spd_tools/src/spd_gen/ddr4.go
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										906
									
								
								util/spd_tools/src/spd_gen/lp4x.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										906
									
								
								util/spd_tools/src/spd_gen/lp4x.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,906 @@
 | 
				
			|||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					/*                                     LP4x-defined types                                     */
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type lp4x struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type LP4xMemAttributes struct {
 | 
				
			||||||
 | 
						/* Primary attributes - must be provided by JSON file for each part */
 | 
				
			||||||
 | 
						DensityPerChannelGb int
 | 
				
			||||||
 | 
						Banks               int
 | 
				
			||||||
 | 
						ChannelsPerDie      int
 | 
				
			||||||
 | 
						DiesPerPackage      int
 | 
				
			||||||
 | 
						BitWidthPerChannel  int
 | 
				
			||||||
 | 
						RanksPerChannel     int
 | 
				
			||||||
 | 
						SpeedMbps           int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * All the following parameters are optional and required only if the part requires
 | 
				
			||||||
 | 
						 * special parameters as per the datasheet.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						/* Timing parameters */
 | 
				
			||||||
 | 
						TRFCABNs   int
 | 
				
			||||||
 | 
						TRFCPBNs   int
 | 
				
			||||||
 | 
						TRPABMinNs int
 | 
				
			||||||
 | 
						TRPPBMinNs int
 | 
				
			||||||
 | 
						TCKMinPs   int
 | 
				
			||||||
 | 
						TCKMaxPs   int
 | 
				
			||||||
 | 
						TAAMinPs   int
 | 
				
			||||||
 | 
						TRCDMinNs  int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* CAS */
 | 
				
			||||||
 | 
						CASLatencies  string
 | 
				
			||||||
 | 
						CASFirstByte  byte
 | 
				
			||||||
 | 
						CASSecondByte byte
 | 
				
			||||||
 | 
						CASThirdByte  byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type LP4xSpeedParams struct {
 | 
				
			||||||
 | 
						TCKMinPs               int
 | 
				
			||||||
 | 
						TCKMaxPs               int
 | 
				
			||||||
 | 
						CASLatenciesx16Channel string
 | 
				
			||||||
 | 
						CASLatenciesx8Channel  string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type LP4xRefreshTimings struct {
 | 
				
			||||||
 | 
						TRFCABNs int
 | 
				
			||||||
 | 
						TRFCPBNs int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type LP4xSPDAttribFunc func(*LP4xMemAttributes) byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type LP4xSPDAttribTableEntry struct {
 | 
				
			||||||
 | 
						constVal byte
 | 
				
			||||||
 | 
						getVal   LP4xSPDAttribFunc
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type LP4xSetFunc func(*LP4xMemAttributes) int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type LP4xSet struct {
 | 
				
			||||||
 | 
						getMRCDensity     LP4xSetFunc
 | 
				
			||||||
 | 
						getDiesPerPackage LP4xSetFunc
 | 
				
			||||||
 | 
						busWidthEncoding  byte
 | 
				
			||||||
 | 
						normalizeAttribs  LP4xSetFunc
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					/*                                         Constants                                          */
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						/* SPD Byte Index */
 | 
				
			||||||
 | 
						LP4xSPDIndexSize                            = 0
 | 
				
			||||||
 | 
						LP4xSPDIndexRevision                        = 1
 | 
				
			||||||
 | 
						LP4xSPDIndexMemoryType                      = 2
 | 
				
			||||||
 | 
						LP4xSPDIndexModuleType                      = 3
 | 
				
			||||||
 | 
						LP4xSPDIndexDensityBanks                    = 4
 | 
				
			||||||
 | 
						LP4xSPDIndexAddressing                      = 5
 | 
				
			||||||
 | 
						LP4xSPDIndexPackageType                     = 6
 | 
				
			||||||
 | 
						LP4xSPDIndexOptionalFeatures                = 7
 | 
				
			||||||
 | 
						LP4xSPDIndexModuleOrganization              = 12
 | 
				
			||||||
 | 
						LP4xSPDIndexBusWidth                        = 13
 | 
				
			||||||
 | 
						LP4xSPDIndexTimebases                       = 17
 | 
				
			||||||
 | 
						LP4xSPDIndexTCKMin                          = 18
 | 
				
			||||||
 | 
						LP4xSPDIndexTCKMax                          = 19
 | 
				
			||||||
 | 
						LP4xSPDIndexCASFirstByte                    = 20
 | 
				
			||||||
 | 
						LP4xSPDIndexCASSecondByte                   = 21
 | 
				
			||||||
 | 
						LP4xSPDIndexCASThirdByte                    = 22
 | 
				
			||||||
 | 
						LP4xSPDIndexCASFourthByte                   = 23
 | 
				
			||||||
 | 
						LP4xSPDIndexTAAMin                          = 24
 | 
				
			||||||
 | 
						LP4xSPDIndexReadWriteLatency                = 25
 | 
				
			||||||
 | 
						LP4xSPDIndexTRCDMin                         = 26
 | 
				
			||||||
 | 
						LP4xSPDIndexTRPABMin                        = 27
 | 
				
			||||||
 | 
						LP4xSPDIndexTRPPBMin                        = 28
 | 
				
			||||||
 | 
						LP4xSPDIndexTRFCABMinLSB                    = 29
 | 
				
			||||||
 | 
						LP4xSPDIndexTRFCABMinMSB                    = 30
 | 
				
			||||||
 | 
						LP4xSPDIndexTRFCPBMinLSB                    = 31
 | 
				
			||||||
 | 
						LP4xSPDIndexTRFCPBMinMSB                    = 32
 | 
				
			||||||
 | 
						LP4xSPDIndexTRPPBMinFineOffset              = 120
 | 
				
			||||||
 | 
						LP4xSPDIndexTRPABMinFineOffset              = 121
 | 
				
			||||||
 | 
						LP4xSPDIndexTRCDMinFineOffset               = 122
 | 
				
			||||||
 | 
						LP4xSPDIndexTAAMinFineOffset                = 123
 | 
				
			||||||
 | 
						LP4xSPDIndexTCKMaxFineOffset                = 124
 | 
				
			||||||
 | 
						LP4xSPDIndexTCKMinFineOffset                = 125
 | 
				
			||||||
 | 
						LP4xSPDIndexManufacturerPartNumberStartByte = 329
 | 
				
			||||||
 | 
						LP4xSPDIndexManufacturerPartNumberEndByte   = 348
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* SPD Byte Value */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * From JEDEC spec:
 | 
				
			||||||
 | 
						 * 6:4 (Bytes total) = 2 (512 bytes)
 | 
				
			||||||
 | 
						 * 3:0 (Bytes used) = 3 (384 bytes)
 | 
				
			||||||
 | 
						 * Set to 0x23 for LPDDR4x.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						LP4xSPDValueSize = 0x23
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * From JEDEC spec: Revision 1.1
 | 
				
			||||||
 | 
						 * Set to 0x11.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						LP4xSPDValueRevision = 0x11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* LPDDR4x memory type = 0x11 */
 | 
				
			||||||
 | 
						LP4xSPDValueMemoryType = 0x11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * From JEDEC spec:
 | 
				
			||||||
 | 
						 * 7:7 (Hybrid) = 0 (Not hybrid)
 | 
				
			||||||
 | 
						 * 6:4 (Hybrid media) = 000 (Not hybrid)
 | 
				
			||||||
 | 
						 * 3:0 (Base Module Type) = 1110 (Non-DIMM solution)
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * This is dependent on hardware design. LPDDR4x only has memory down solution.
 | 
				
			||||||
 | 
						 * Hence this is not hybrid non-DIMM solution.
 | 
				
			||||||
 | 
						 * Set to 0x0E.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						LP4xSPDValueModuleType = 0x0e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * From JEDEC spec:
 | 
				
			||||||
 | 
						 * 5:4 (Maximum Activate Window) = 00 (8192 * tREFI)
 | 
				
			||||||
 | 
						 * 3:0 (Maximum Activate Count) = 1000 (Unlimited MAC)
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Needs to come from datasheet, but most parts seem to support unlimited MAC.
 | 
				
			||||||
 | 
						 * MR#24 OP3
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						LP4xSPDValueOptionalFeatures = 0x08
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * From JEDEC spec:
 | 
				
			||||||
 | 
						 * 3:2 (MTB) = 00 (0.125ns)
 | 
				
			||||||
 | 
						 * 1:0 (FTB) = 00 (1ps)
 | 
				
			||||||
 | 
						 * Set to 0x00.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						LP4xSPDValueTimebases = 0x00
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* CAS fourth byte: All bits are reserved */
 | 
				
			||||||
 | 
						LP4xSPDValueCASFourthByte = 0x00
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Write Latency Set A and Read Latency DBI-RD disabled. */
 | 
				
			||||||
 | 
						LP4xSPDValueReadWriteLatency = 0x00
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* As per JEDEC spec, unused digits of manufacturer part number are left as blank. */
 | 
				
			||||||
 | 
						LP4xSPDValueManufacturerPartNumberBlank = 0x20
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						/* First Byte */
 | 
				
			||||||
 | 
						LP4xCAS6  = 1 << 1
 | 
				
			||||||
 | 
						LP4xCAS10 = 1 << 4
 | 
				
			||||||
 | 
						LP4xCAS14 = 1 << 7
 | 
				
			||||||
 | 
						/* Second Byte */
 | 
				
			||||||
 | 
						LP4xCAS16 = 1 << 0
 | 
				
			||||||
 | 
						LP4xCAS20 = 1 << 2
 | 
				
			||||||
 | 
						LP4xCAS22 = 1 << 3
 | 
				
			||||||
 | 
						LP4xCAS24 = 1 << 4
 | 
				
			||||||
 | 
						LP4xCAS26 = 1 << 5
 | 
				
			||||||
 | 
						LP4xCAS28 = 1 << 6
 | 
				
			||||||
 | 
						/* Third Byte */
 | 
				
			||||||
 | 
						LP4xCAS32 = 1 << 0
 | 
				
			||||||
 | 
						LP4xCAS36 = 1 << 2
 | 
				
			||||||
 | 
						LP4xCAS40 = 1 << 4
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * JEDEC spec says that TCKmax should be 100ns for all speed grades.
 | 
				
			||||||
 | 
						 * 100ns in MTB units comes out to be 0x320. But since this is a byte field, set it to
 | 
				
			||||||
 | 
						 * 0xFF i.e. 31.875ns.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						LP4xTCKMaxPsDefault = 31875
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					/*                                    Global variables                                        */
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var LP4xPlatformSetMap = map[int][]int{
 | 
				
			||||||
 | 
						0: {PlatformTGL, PlatformADL},
 | 
				
			||||||
 | 
						1: {PlatformJSL, PlatformCZN},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var LP4xSetInfo = map[int]LP4xSet{
 | 
				
			||||||
 | 
						0: {
 | 
				
			||||||
 | 
							getMRCDensity:     LP4xGetMRCDensitySet0,
 | 
				
			||||||
 | 
							getDiesPerPackage: LP4xGetDiesPerPackageSet0,
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * As per advisory 616599:
 | 
				
			||||||
 | 
							 * 7:5 (Number of system channels) = 000 (1 channel always)
 | 
				
			||||||
 | 
							 * 2:0 (Bus width) = 001 (x16 always)
 | 
				
			||||||
 | 
							 * Set to 0x01.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							busWidthEncoding: 0x01,
 | 
				
			||||||
 | 
							normalizeAttribs: LP4xNormalizeAttribsSet0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						1: {
 | 
				
			||||||
 | 
							getMRCDensity:     LP4xGetMRCDensitySet1,
 | 
				
			||||||
 | 
							getDiesPerPackage: LP4xGetDiesPerPackageSet1,
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							* As per advisory 610202:
 | 
				
			||||||
 | 
							* 7:5 (Number of system channels) = 001 (2 channel always)
 | 
				
			||||||
 | 
							* 2:0 (Bus width) = 010 (x32 always)
 | 
				
			||||||
 | 
							* Set to 0x22.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							busWidthEncoding: 0x22,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var LP4xPartAttributeMap = map[string]LP4xMemAttributes{}
 | 
				
			||||||
 | 
					var LP4xCurrSet int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* This encodes the density in Gb to SPD values as per JESD 21-C */
 | 
				
			||||||
 | 
					var LP4xDensityGbToSPDEncoding = map[int]byte{
 | 
				
			||||||
 | 
						4:  0x4,
 | 
				
			||||||
 | 
						6:  0xb,
 | 
				
			||||||
 | 
						8:  0x5,
 | 
				
			||||||
 | 
						12: 0x8,
 | 
				
			||||||
 | 
						16: 0x6,
 | 
				
			||||||
 | 
						24: 0x9,
 | 
				
			||||||
 | 
						32: 0x7,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Table 5 from JESD209-4C.
 | 
				
			||||||
 | 
					 * Maps density per physical channel to row-column encoding as per JESD 21-C for a device with
 | 
				
			||||||
 | 
					 * x8 physical channel.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					var LP4xDensityGbx8ChannelToRowColumnEncoding = map[int]byte{
 | 
				
			||||||
 | 
						3:  0x21, /* 16 rows, 10 columns */
 | 
				
			||||||
 | 
						4:  0x21, /* 16 rows, 10 columns */
 | 
				
			||||||
 | 
						6:  0x29, /* 17 rows, 10 columns */
 | 
				
			||||||
 | 
						8:  0x29, /* 17 rows, 10 columns */
 | 
				
			||||||
 | 
						12: 0x31, /* 18 rows, 10 columns */
 | 
				
			||||||
 | 
						16: 0x31, /* 18 rows, 10 columns */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Table 3 from JESD209-4C.
 | 
				
			||||||
 | 
					 * Maps density per physical channel to row-column encoding as per JESD 21-C for a device with
 | 
				
			||||||
 | 
					 * x16 physical channel.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					var LP4xDensityGbx16ChannelToRowColumnEncoding = map[int]byte{
 | 
				
			||||||
 | 
						4:  0x19, /* 15 rows, 10 columns */
 | 
				
			||||||
 | 
						6:  0x21, /* 16 rows, 10 columns */
 | 
				
			||||||
 | 
						8:  0x21, /* 16 rows, 10 columns */
 | 
				
			||||||
 | 
						12: 0x29, /* 17 rows, 10 columns */
 | 
				
			||||||
 | 
						16: 0x29, /* 17 rows, 10 columns */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Table 112 from JESD209-4C
 | 
				
			||||||
 | 
					 * Maps density per physical channel to refresh timings. This is the same for x8 and x16
 | 
				
			||||||
 | 
					 * devices.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					var LP4xDensityGbPhysicalChannelToRefreshEncoding = map[int]LP4xRefreshTimings{
 | 
				
			||||||
 | 
						3: {
 | 
				
			||||||
 | 
							TRFCABNs: 180,
 | 
				
			||||||
 | 
							TRFCPBNs: 90,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						4: {
 | 
				
			||||||
 | 
							TRFCABNs: 180,
 | 
				
			||||||
 | 
							TRFCPBNs: 90,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						6: {
 | 
				
			||||||
 | 
							TRFCABNs: 280,
 | 
				
			||||||
 | 
							TRFCPBNs: 140,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						8: {
 | 
				
			||||||
 | 
							TRFCABNs: 280,
 | 
				
			||||||
 | 
							TRFCPBNs: 140,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						12: {
 | 
				
			||||||
 | 
							TRFCABNs: 380,
 | 
				
			||||||
 | 
							TRFCPBNs: 190,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						16: {
 | 
				
			||||||
 | 
							TRFCABNs: 380,
 | 
				
			||||||
 | 
							TRFCPBNs: 190,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var LP4xBankEncoding = map[int]byte{
 | 
				
			||||||
 | 
						4: 0 << 4,
 | 
				
			||||||
 | 
						8: 1 << 4,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var LP4xSpeedMbpsToSPDEncoding = map[int]LP4xSpeedParams{
 | 
				
			||||||
 | 
						4267: {
 | 
				
			||||||
 | 
							TCKMinPs:               468, /* 1/4267 * 2 */
 | 
				
			||||||
 | 
							TCKMaxPs:               LP4xTCKMaxPsDefault,
 | 
				
			||||||
 | 
							CASLatenciesx16Channel: "6 10 14 20 24 28 32 36",
 | 
				
			||||||
 | 
							CASLatenciesx8Channel:  "6 10 16 22 26 32 36 40",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						3733: {
 | 
				
			||||||
 | 
							TCKMinPs:               535, /* 1/3733 * 2 */
 | 
				
			||||||
 | 
							TCKMaxPs:               LP4xTCKMaxPsDefault,
 | 
				
			||||||
 | 
							CASLatenciesx16Channel: "6 10 14 20 24 28 32",
 | 
				
			||||||
 | 
							CASLatenciesx8Channel:  "6 10 16 22 26 32 36",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						3200: {
 | 
				
			||||||
 | 
							TCKMinPs:               625, /* 1/3200 * 2 */
 | 
				
			||||||
 | 
							TCKMaxPs:               LP4xTCKMaxPsDefault,
 | 
				
			||||||
 | 
							CASLatenciesx16Channel: "6 10 14 20 24 28",
 | 
				
			||||||
 | 
							CASLatenciesx8Channel:  "6 10 16 22 26 32",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var LP4xSPDAttribTable = map[int]LP4xSPDAttribTableEntry{
 | 
				
			||||||
 | 
						LP4xSPDIndexSize:               {constVal: LP4xSPDValueSize},
 | 
				
			||||||
 | 
						LP4xSPDIndexRevision:           {constVal: LP4xSPDValueRevision},
 | 
				
			||||||
 | 
						LP4xSPDIndexMemoryType:         {constVal: LP4xSPDValueMemoryType},
 | 
				
			||||||
 | 
						LP4xSPDIndexModuleType:         {constVal: LP4xSPDValueModuleType},
 | 
				
			||||||
 | 
						LP4xSPDIndexDensityBanks:       {getVal: LP4xEncodeDensityBanks},
 | 
				
			||||||
 | 
						LP4xSPDIndexAddressing:         {getVal: LP4xEncodeSdramAddressing},
 | 
				
			||||||
 | 
						LP4xSPDIndexPackageType:        {getVal: LP4xEncodePackageType},
 | 
				
			||||||
 | 
						LP4xSPDIndexOptionalFeatures:   {constVal: LP4xSPDValueOptionalFeatures},
 | 
				
			||||||
 | 
						LP4xSPDIndexModuleOrganization: {getVal: LP4xEncodeModuleOrganization},
 | 
				
			||||||
 | 
						LP4xSPDIndexBusWidth:           {getVal: LP4xEncodeBusWidth},
 | 
				
			||||||
 | 
						LP4xSPDIndexTimebases:          {constVal: LP4xSPDValueTimebases},
 | 
				
			||||||
 | 
						LP4xSPDIndexTCKMin:             {getVal: LP4xEncodeTCKMin},
 | 
				
			||||||
 | 
						LP4xSPDIndexTCKMax:             {getVal: LP4xEncodeTCKMax},
 | 
				
			||||||
 | 
						LP4xSPDIndexTCKMaxFineOffset:   {getVal: LP4xEncodeTCKMaxFineOffset},
 | 
				
			||||||
 | 
						LP4xSPDIndexTCKMinFineOffset:   {getVal: LP4xEncodeTCKMinFineOffset},
 | 
				
			||||||
 | 
						LP4xSPDIndexCASFirstByte:       {getVal: LP4xEncodeCASFirstByte},
 | 
				
			||||||
 | 
						LP4xSPDIndexCASSecondByte:      {getVal: LP4xEncodeCASSecondByte},
 | 
				
			||||||
 | 
						LP4xSPDIndexCASThirdByte:       {getVal: LP4xEncodeCASThirdByte},
 | 
				
			||||||
 | 
						LP4xSPDIndexCASFourthByte:      {constVal: LP4xSPDValueCASFourthByte},
 | 
				
			||||||
 | 
						LP4xSPDIndexTAAMin:             {getVal: LP4xEncodeTAAMin},
 | 
				
			||||||
 | 
						LP4xSPDIndexTAAMinFineOffset:   {getVal: LP4xEncodeTAAMinFineOffset},
 | 
				
			||||||
 | 
						LP4xSPDIndexReadWriteLatency:   {constVal: LP4xSPDValueReadWriteLatency},
 | 
				
			||||||
 | 
						LP4xSPDIndexTRCDMin:            {getVal: LP4xEncodeTRCDMin},
 | 
				
			||||||
 | 
						LP4xSPDIndexTRCDMinFineOffset:  {getVal: LP4xEncodeTRCDMinFineOffset},
 | 
				
			||||||
 | 
						LP4xSPDIndexTRPABMin:           {getVal: LP4xEncodeTRPABMin},
 | 
				
			||||||
 | 
						LP4xSPDIndexTRPABMinFineOffset: {getVal: LP4xEncodeTRPABMinFineOffset},
 | 
				
			||||||
 | 
						LP4xSPDIndexTRPPBMin:           {getVal: LP4xEncodeTRPPBMin},
 | 
				
			||||||
 | 
						LP4xSPDIndexTRPPBMinFineOffset: {getVal: LP4xEncodeTRPPBMinFineOffset},
 | 
				
			||||||
 | 
						LP4xSPDIndexTRFCABMinLSB:       {getVal: LP4xEncodeTRFCABMinLsb},
 | 
				
			||||||
 | 
						LP4xSPDIndexTRFCABMinMSB:       {getVal: LP4xEncodeTRFCABMinMsb},
 | 
				
			||||||
 | 
						LP4xSPDIndexTRFCPBMinLSB:       {getVal: LP4xEncodeTRFCPBMinLsb},
 | 
				
			||||||
 | 
						LP4xSPDIndexTRFCPBMinMSB:       {getVal: LP4xEncodeTRFCPBMinMsb},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					/*                                        Functions                                           */
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xGetMRCDensitySet0(memAttribs *LP4xMemAttributes) int {
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Intel MRC on TGL/ADL expects density per logical channel to be encoded in
 | 
				
			||||||
 | 
						 * SPDIndexDensityBanks. Logical channel on TGL/ADL is an x16 channel.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						return memAttribs.DensityPerChannelGb * 16 / memAttribs.BitWidthPerChannel
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xGetMRCDensitySet1(memAttribs *LP4xMemAttributes) int {
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Intel MRC on JSL expects density per die to be encoded in
 | 
				
			||||||
 | 
						 * SPDIndexDensityBanks.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						return memAttribs.DensityPerChannelGb * memAttribs.ChannelsPerDie
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xGetMRCDensity(memAttribs *LP4xMemAttributes) int {
 | 
				
			||||||
 | 
						f, ok := LP4xSetInfo[LP4xCurrSet]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ok == false || f.getMRCDensity == nil {
 | 
				
			||||||
 | 
							return 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return f.getMRCDensity(memAttribs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeDensityBanks(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						var b byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b = LP4xDensityGbToSPDEncoding[LP4xGetMRCDensity(memAttribs)]
 | 
				
			||||||
 | 
						b |= LP4xBankEncoding[memAttribs.Banks]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return b
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeSdramAddressing(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						densityPerChannelGb := memAttribs.DensityPerChannelGb
 | 
				
			||||||
 | 
						if memAttribs.BitWidthPerChannel == 8 {
 | 
				
			||||||
 | 
							return LP4xDensityGbx8ChannelToRowColumnEncoding[densityPerChannelGb]
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return LP4xDensityGbx16ChannelToRowColumnEncoding[densityPerChannelGb]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodePackage(dies int) byte {
 | 
				
			||||||
 | 
						var temp byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if dies > 1 {
 | 
				
			||||||
 | 
							/* If more than one die, then this is a non-monolithic device. */
 | 
				
			||||||
 | 
							temp = 1
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/* If only single die, then this is a monolithic device. */
 | 
				
			||||||
 | 
							temp = 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return temp << 7
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeChannelsPerDie(channels int) byte {
 | 
				
			||||||
 | 
						var temp byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						temp = byte(channels >> 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return temp << 2
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xGetDiesPerPackageSet0(memAttribs *LP4xMemAttributes) int {
 | 
				
			||||||
 | 
						/* Intel MRC expects logical dies to be encoded for TGL/ADL. */
 | 
				
			||||||
 | 
						return memAttribs.ChannelsPerDie * memAttribs.RanksPerChannel * memAttribs.BitWidthPerChannel / 16
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xGetDiesPerPackageSet1(memAttribs *LP4xMemAttributes) int {
 | 
				
			||||||
 | 
						/* Intel MRC expects physical dies to be encoded for JSL. */
 | 
				
			||||||
 | 
						/* AMD PSP expects physical dies (ZQ balls) */
 | 
				
			||||||
 | 
						return memAttribs.DiesPerPackage
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Per JESD209-4C Dies = ZQ balls on the package */
 | 
				
			||||||
 | 
					/* Note that this can be different than the part's die count */
 | 
				
			||||||
 | 
					func LP4xEncodeDiesPerPackage(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						var dies int = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f, ok := LP4xSetInfo[LP4xCurrSet]
 | 
				
			||||||
 | 
						if ok != false && f.getDiesPerPackage != nil {
 | 
				
			||||||
 | 
							dies = f.getDiesPerPackage(memAttribs)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b := LP4xEncodePackage(dies) /* Monolithic / Non-monolithic device */
 | 
				
			||||||
 | 
						b |= (byte(dies) - 1) << 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return b
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodePackageType(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						var b byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b |= LP4xEncodeChannelsPerDie(memAttribs.ChannelsPerDie)
 | 
				
			||||||
 | 
						b |= LP4xEncodeDiesPerPackage(memAttribs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return b
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeDataWidth(bitWidthPerChannel int) byte {
 | 
				
			||||||
 | 
						return byte(bitWidthPerChannel / 8)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeRanks(ranks int) byte {
 | 
				
			||||||
 | 
						var b byte
 | 
				
			||||||
 | 
						b = byte(ranks - 1)
 | 
				
			||||||
 | 
						return b << 3
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeModuleOrganization(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						var b byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						b = LP4xEncodeDataWidth(memAttribs.BitWidthPerChannel)
 | 
				
			||||||
 | 
						b |= LP4xEncodeRanks(memAttribs.RanksPerChannel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return b
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeBusWidth(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						f, ok := LP4xSetInfo[LP4xCurrSet]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ok == false {
 | 
				
			||||||
 | 
							return 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return f.busWidthEncoding
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTCKMin(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return convPsToMtbByte(memAttribs.TCKMinPs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTCKMinFineOffset(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return convPsToFtbByte(memAttribs.TCKMinPs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTCKMax(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return convPsToMtbByte(memAttribs.TCKMaxPs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTCKMaxFineOffset(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return convPsToFtbByte(memAttribs.TCKMaxPs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeCASFirstByte(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return memAttribs.CASFirstByte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeCASSecondByte(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return memAttribs.CASSecondByte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeCASThirdByte(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return memAttribs.CASThirdByte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTAAMin(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return convPsToMtbByte(memAttribs.TAAMinPs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTAAMinFineOffset(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return convPsToFtbByte(memAttribs.TAAMinPs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTRCDMin(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return convNsToMtbByte(memAttribs.TRCDMinNs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTRCDMinFineOffset(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return convNsToFtbByte(memAttribs.TRCDMinNs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTRPABMin(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return convNsToMtbByte(memAttribs.TRPABMinNs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTRPABMinFineOffset(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return convNsToFtbByte(memAttribs.TRPABMinNs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTRPPBMin(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return convNsToMtbByte(memAttribs.TRPPBMinNs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTRPPBMinFineOffset(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return convNsToFtbByte(memAttribs.TRPPBMinNs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTRFCABMinMsb(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return byte((convNsToMtb(memAttribs.TRFCABNs) >> 8) & 0xff)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTRFCABMinLsb(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return byte(convNsToMtb(memAttribs.TRFCABNs) & 0xff)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTRFCPBMinMsb(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return byte((convNsToMtb(memAttribs.TRFCPBNs) >> 8) & 0xff)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeTRFCPBMinLsb(memAttribs *LP4xMemAttributes) byte {
 | 
				
			||||||
 | 
						return byte(convNsToMtb(memAttribs.TRFCPBNs) & 0xff)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xEncodeLatencies(latency int, memAttribs *LP4xMemAttributes) error {
 | 
				
			||||||
 | 
						switch latency {
 | 
				
			||||||
 | 
						case 6:
 | 
				
			||||||
 | 
							memAttribs.CASFirstByte |= LP4xCAS6
 | 
				
			||||||
 | 
						case 10:
 | 
				
			||||||
 | 
							memAttribs.CASFirstByte |= LP4xCAS10
 | 
				
			||||||
 | 
						case 14:
 | 
				
			||||||
 | 
							memAttribs.CASFirstByte |= LP4xCAS14
 | 
				
			||||||
 | 
						case 16:
 | 
				
			||||||
 | 
							memAttribs.CASSecondByte |= LP4xCAS16
 | 
				
			||||||
 | 
						case 20:
 | 
				
			||||||
 | 
							memAttribs.CASSecondByte |= LP4xCAS20
 | 
				
			||||||
 | 
						case 22:
 | 
				
			||||||
 | 
							memAttribs.CASSecondByte |= LP4xCAS22
 | 
				
			||||||
 | 
						case 24:
 | 
				
			||||||
 | 
							memAttribs.CASSecondByte |= LP4xCAS24
 | 
				
			||||||
 | 
						case 26:
 | 
				
			||||||
 | 
							memAttribs.CASSecondByte |= LP4xCAS26
 | 
				
			||||||
 | 
						case 28:
 | 
				
			||||||
 | 
							memAttribs.CASSecondByte |= LP4xCAS28
 | 
				
			||||||
 | 
						case 32:
 | 
				
			||||||
 | 
							memAttribs.CASThirdByte |= LP4xCAS32
 | 
				
			||||||
 | 
						case 36:
 | 
				
			||||||
 | 
							memAttribs.CASThirdByte |= LP4xCAS36
 | 
				
			||||||
 | 
						case 40:
 | 
				
			||||||
 | 
							memAttribs.CASThirdByte |= LP4xCAS40
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							fmt.Errorf("Incorrect CAS Latency: ", latency)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xUpdateTCK(memAttribs *LP4xMemAttributes) {
 | 
				
			||||||
 | 
						if memAttribs.TCKMinPs == 0 {
 | 
				
			||||||
 | 
							memAttribs.TCKMinPs = LP4xSpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].TCKMinPs
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if memAttribs.TCKMaxPs == 0 {
 | 
				
			||||||
 | 
							memAttribs.TCKMaxPs = LP4xSpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].TCKMaxPs
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xGetCASLatencies(memAttribs *LP4xMemAttributes) string {
 | 
				
			||||||
 | 
						if memAttribs.BitWidthPerChannel == 16 {
 | 
				
			||||||
 | 
							return LP4xSpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].CASLatenciesx16Channel
 | 
				
			||||||
 | 
						} else if memAttribs.BitWidthPerChannel == 8 {
 | 
				
			||||||
 | 
							return LP4xSpeedMbpsToSPDEncoding[memAttribs.SpeedMbps].CASLatenciesx8Channel
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xUpdateCAS(memAttribs *LP4xMemAttributes) error {
 | 
				
			||||||
 | 
						if len(memAttribs.CASLatencies) == 0 {
 | 
				
			||||||
 | 
							memAttribs.CASLatencies = LP4xGetCASLatencies(memAttribs)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						latencies := strings.Fields(memAttribs.CASLatencies)
 | 
				
			||||||
 | 
						for i := 0; i < len(latencies); i++ {
 | 
				
			||||||
 | 
							latency, err := strconv.Atoi(latencies[i])
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("Unable to convert latency ", latencies[i])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := LP4xEncodeLatencies(latency, memAttribs); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xGetMinCAS(memAttribs *LP4xMemAttributes) (int, error) {
 | 
				
			||||||
 | 
						if (memAttribs.CASThirdByte & LP4xCAS40) != 0 {
 | 
				
			||||||
 | 
							return 40, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (memAttribs.CASThirdByte & LP4xCAS36) != 0 {
 | 
				
			||||||
 | 
							return 36, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (memAttribs.CASThirdByte & LP4xCAS32) != 0 {
 | 
				
			||||||
 | 
							return 32, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (memAttribs.CASSecondByte & LP4xCAS28) != 0 {
 | 
				
			||||||
 | 
							return 28, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0, fmt.Errorf("Unexpected min CAS")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xUpdateTAAMin(memAttribs *LP4xMemAttributes) error {
 | 
				
			||||||
 | 
						if memAttribs.TAAMinPs == 0 {
 | 
				
			||||||
 | 
							minCAS, err := LP4xGetMinCAS(memAttribs)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							memAttribs.TAAMinPs = memAttribs.TCKMinPs * minCAS
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xUpdateTRFCAB(memAttribs *LP4xMemAttributes) {
 | 
				
			||||||
 | 
						if memAttribs.TRFCABNs == 0 {
 | 
				
			||||||
 | 
							memAttribs.TRFCABNs = LP4xDensityGbPhysicalChannelToRefreshEncoding[memAttribs.DensityPerChannelGb].TRFCABNs
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xUpdateTRFCPB(memAttribs *LP4xMemAttributes) {
 | 
				
			||||||
 | 
						if memAttribs.TRFCPBNs == 0 {
 | 
				
			||||||
 | 
							memAttribs.TRFCPBNs = LP4xDensityGbPhysicalChannelToRefreshEncoding[memAttribs.DensityPerChannelGb].TRFCPBNs
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xUpdateTRCD(memAttribs *LP4xMemAttributes) {
 | 
				
			||||||
 | 
						if memAttribs.TRCDMinNs == 0 {
 | 
				
			||||||
 | 
							/* JEDEC spec says max of 18ns */
 | 
				
			||||||
 | 
							memAttribs.TRCDMinNs = 18
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xUpdateTRPAB(memAttribs *LP4xMemAttributes) {
 | 
				
			||||||
 | 
						if memAttribs.TRPABMinNs == 0 {
 | 
				
			||||||
 | 
							/* JEDEC spec says max of 21ns */
 | 
				
			||||||
 | 
							memAttribs.TRPABMinNs = 21
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xUpdateTRPPB(memAttribs *LP4xMemAttributes) {
 | 
				
			||||||
 | 
						if memAttribs.TRPPBMinNs == 0 {
 | 
				
			||||||
 | 
							/* JEDEC spec says max of 18ns */
 | 
				
			||||||
 | 
							memAttribs.TRPPBMinNs = 18
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xNormalizeAttribsSet0(memAttribs *LP4xMemAttributes) int {
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * TGL does not really use physical organization of dies per package when
 | 
				
			||||||
 | 
						 * generating the SPD. So, set it to 0 here so that deduplication ignores
 | 
				
			||||||
 | 
						 * that field.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						memAttribs.DiesPerPackage = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xNormalizeMemoryAttributes(memAttribs *LP4xMemAttributes) {
 | 
				
			||||||
 | 
						f, ok := LP4xSetInfo[LP4xCurrSet]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ok == false || f.normalizeAttribs == nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f.normalizeAttribs(memAttribs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Lp4xUpdateMemoryAttributes(memAttribs *LP4xMemAttributes) error {
 | 
				
			||||||
 | 
						LP4xUpdateTCK(memAttribs)
 | 
				
			||||||
 | 
						if err := LP4xUpdateCAS(memAttribs); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := LP4xUpdateTAAMin(memAttribs); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						LP4xUpdateTRFCAB(memAttribs)
 | 
				
			||||||
 | 
						LP4xUpdateTRFCPB(memAttribs)
 | 
				
			||||||
 | 
						LP4xUpdateTRCD(memAttribs)
 | 
				
			||||||
 | 
						LP4xUpdateTRPAB(memAttribs)
 | 
				
			||||||
 | 
						LP4xUpdateTRPPB(memAttribs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LP4xNormalizeMemoryAttributes(memAttribs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xValidateDensityx8Channel(densityPerChannelGb int) error {
 | 
				
			||||||
 | 
						if _, ok := LP4xDensityGbx8ChannelToRowColumnEncoding[densityPerChannelGb]; ok == false {
 | 
				
			||||||
 | 
							return fmt.Errorf("Incorrect x8 density: %d Gb", densityPerChannelGb)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xValidateDensityx16Channel(densityPerChannelGb int) error {
 | 
				
			||||||
 | 
						if _, ok := LP4xDensityGbx16ChannelToRowColumnEncoding[densityPerChannelGb]; ok == false {
 | 
				
			||||||
 | 
							return fmt.Errorf("Incorrect x16 density: %d Gb", densityPerChannelGb)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xValidateDensity(memAttribs *LP4xMemAttributes) error {
 | 
				
			||||||
 | 
						if memAttribs.BitWidthPerChannel == 8 {
 | 
				
			||||||
 | 
							return LP4xValidateDensityx8Channel(memAttribs.DensityPerChannelGb)
 | 
				
			||||||
 | 
						} else if memAttribs.BitWidthPerChannel == 16 {
 | 
				
			||||||
 | 
							return LP4xValidateDensityx16Channel(memAttribs.DensityPerChannelGb)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return fmt.Errorf("No density table for this bit width: %d", memAttribs.BitWidthPerChannel)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xValidateBanks(banks int) error {
 | 
				
			||||||
 | 
						if banks != 4 && banks != 8 {
 | 
				
			||||||
 | 
							return fmt.Errorf("Incorrect banks: %d", banks)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xValidateChannels(channels int) error {
 | 
				
			||||||
 | 
						if channels != 1 && channels != 2 && channels != 4 {
 | 
				
			||||||
 | 
							return fmt.Errorf("Incorrect channels per die: %d ", channels)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xValidateDataWidth(width int) error {
 | 
				
			||||||
 | 
						if width != 8 && width != 16 {
 | 
				
			||||||
 | 
							return fmt.Errorf("Incorrect bit width: %d", width)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xValidateRanks(ranks int) error {
 | 
				
			||||||
 | 
						if ranks != 1 && ranks != 2 {
 | 
				
			||||||
 | 
							return fmt.Errorf("Incorrect ranks: %d", ranks)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xValidateSpeed(speed int) error {
 | 
				
			||||||
 | 
						if _, ok := LP4xSpeedMbpsToSPDEncoding[speed]; ok == false {
 | 
				
			||||||
 | 
							return fmt.Errorf("Incorrect speed: %d Mbps", speed)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Lp4xValidateMemPartAttributes(memAttribs *LP4xMemAttributes) error {
 | 
				
			||||||
 | 
						if err := LP4xValidateBanks(memAttribs.Banks); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := LP4xValidateChannels(memAttribs.ChannelsPerDie); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := LP4xValidateDataWidth(memAttribs.BitWidthPerChannel); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := LP4xValidateDensity(memAttribs); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := LP4xValidateRanks(memAttribs.RanksPerChannel); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := LP4xValidateSpeed(memAttribs.SpeedMbps); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LP4xIsManufacturerPartNumberByte(index int) bool {
 | 
				
			||||||
 | 
						if index >= LP4xSPDIndexManufacturerPartNumberStartByte &&
 | 
				
			||||||
 | 
							index <= LP4xSPDIndexManufacturerPartNumberEndByte {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					/*                                 Interface Functions                                       */
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (lp4x) getSetMap() map[int][]int {
 | 
				
			||||||
 | 
						return LP4xPlatformSetMap
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (lp4x) addNewPart(name string, attribs interface{}) error {
 | 
				
			||||||
 | 
						var lp4xAttributes LP4xMemAttributes
 | 
				
			||||||
 | 
						eByte, err := json.Marshal(attribs)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := json.Unmarshal(eByte, &lp4xAttributes); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := Lp4xValidateMemPartAttributes(&lp4xAttributes); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LP4xPartAttributeMap[name] = lp4xAttributes
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (lp4x) getSPDAttribs(name string, set int) (interface{}, error) {
 | 
				
			||||||
 | 
						lp4xAttributes := LP4xPartAttributeMap[name]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LP4xCurrSet = set
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := Lp4xUpdateMemoryAttributes(&lp4xAttributes); err != nil {
 | 
				
			||||||
 | 
							return lp4xAttributes, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return lp4xAttributes, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (lp4x) getSPDLen() int {
 | 
				
			||||||
 | 
						return 512
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (lp4x) getSPDByte(index int, attribs interface{}) byte {
 | 
				
			||||||
 | 
						e, ok := LP4xSPDAttribTable[index]
 | 
				
			||||||
 | 
						if ok == false {
 | 
				
			||||||
 | 
							if LP4xIsManufacturerPartNumberByte(index) {
 | 
				
			||||||
 | 
								return LP4xSPDValueManufacturerPartNumberBlank
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return 0x00
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if e.getVal != nil {
 | 
				
			||||||
 | 
							var lp4xAttribs LP4xMemAttributes
 | 
				
			||||||
 | 
							lp4xAttribs = attribs.(LP4xMemAttributes)
 | 
				
			||||||
 | 
							return e.getVal(&lp4xAttribs)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return e.constVal
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										281
									
								
								util/spd_tools/src/spd_gen/spd_gen.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								util/spd_tools/src/spd_gen/spd_gen.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,281 @@
 | 
				
			|||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					/*                                     Program-defined types                                  */
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					type memParts struct {
 | 
				
			||||||
 | 
						MemParts []memPart `json:"parts"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type memPart struct {
 | 
				
			||||||
 | 
						Name    string
 | 
				
			||||||
 | 
						Attribs interface{}
 | 
				
			||||||
 | 
						SPDId   int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type memTech interface {
 | 
				
			||||||
 | 
						getSetMap() map[int][]int
 | 
				
			||||||
 | 
						addNewPart(string, interface{}) error
 | 
				
			||||||
 | 
						getSPDAttribs(string, int) (interface{}, error)
 | 
				
			||||||
 | 
						getSPDLen() int
 | 
				
			||||||
 | 
						getSPDByte(int, interface{}) byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					/*                                         Constants                                          */
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						PlatformTGL = iota
 | 
				
			||||||
 | 
						PlatformADL
 | 
				
			||||||
 | 
						PlatformJSL
 | 
				
			||||||
 | 
						PlatformPCO
 | 
				
			||||||
 | 
						PlatformPLK
 | 
				
			||||||
 | 
						PlatformCZN
 | 
				
			||||||
 | 
						PlatformMax
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						SPDManifestFileName      = "parts_spd_manifest.generated.txt"
 | 
				
			||||||
 | 
						PlatformManifestFileName = "platforms_manifest.generated.txt"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					/*                                    Global variables                                        */
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var platformNames = map[int]string{
 | 
				
			||||||
 | 
						PlatformTGL: "TGL",
 | 
				
			||||||
 | 
						PlatformADL: "ADL",
 | 
				
			||||||
 | 
						PlatformJSL: "JSL",
 | 
				
			||||||
 | 
						PlatformPCO: "PCO",
 | 
				
			||||||
 | 
						PlatformPLK: "PLK",
 | 
				
			||||||
 | 
						PlatformCZN: "CZN",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					/*                                Conversion Helper Functions                                 */
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func convNsToPs(timeNs int) int {
 | 
				
			||||||
 | 
						return timeNs * 1000
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func convMtbToPs(mtb int) int {
 | 
				
			||||||
 | 
						return mtb * 125
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func convPsToMtb(timePs int) int {
 | 
				
			||||||
 | 
						return divRoundUp(timePs, 125)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func convPsToMtbByte(timePs int) byte {
 | 
				
			||||||
 | 
						return byte(convPsToMtb(timePs) & 0xff)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func convPsToFtbByte(timePs int) byte {
 | 
				
			||||||
 | 
						mtb := convPsToMtb(timePs)
 | 
				
			||||||
 | 
						ftb := timePs - convMtbToPs(mtb)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return byte(ftb)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func convNsToMtb(timeNs int) int {
 | 
				
			||||||
 | 
						return convPsToMtb(convNsToPs(timeNs))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func convNsToMtbByte(timeNs int) byte {
 | 
				
			||||||
 | 
						return convPsToMtbByte(convNsToPs(timeNs))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func convNsToFtbByte(timeNs int) byte {
 | 
				
			||||||
 | 
						return convPsToFtbByte(convNsToPs(timeNs))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func divRoundUp(dividend int, divisor int) int {
 | 
				
			||||||
 | 
						return (dividend + divisor - 1) / divisor
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					/*                                        Functions                                           */
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func findIndex(dedupedAttribs []interface{}, newSPDAttribs interface{}) int {
 | 
				
			||||||
 | 
						for i := 0; i < len(dedupedAttribs); i++ {
 | 
				
			||||||
 | 
							if reflect.DeepEqual(dedupedAttribs[i], newSPDAttribs) {
 | 
				
			||||||
 | 
								return i
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func readMemParts(memPartsFilePath string) (memParts, error) {
 | 
				
			||||||
 | 
						var memParts memParts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dataBytes, err := ioutil.ReadFile(memPartsFilePath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return memParts, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Strip comments from json file
 | 
				
			||||||
 | 
						re := regexp.MustCompile(`(?m)^\s*//.*`)
 | 
				
			||||||
 | 
						dataBytes = re.ReplaceAll(dataBytes, []byte(""))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := json.Unmarshal(dataBytes, &memParts); err != nil {
 | 
				
			||||||
 | 
							return memParts, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return memParts, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func createSPD(memAttribs interface{}, t memTech) string {
 | 
				
			||||||
 | 
						var s string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < t.getSPDLen(); i++ {
 | 
				
			||||||
 | 
							var b byte = 0
 | 
				
			||||||
 | 
							if memAttribs != nil {
 | 
				
			||||||
 | 
								b = t.getSPDByte(i, memAttribs)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (i+1)%16 == 0 {
 | 
				
			||||||
 | 
								s += fmt.Sprintf("%02X\n", b)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								s += fmt.Sprintf("%02X ", b)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return s
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func writeSPD(memAttribs interface{}, SPDId int, SPDSetDirName string, t memTech) {
 | 
				
			||||||
 | 
						s := createSPD(memAttribs, t)
 | 
				
			||||||
 | 
						SPDFileName := fmt.Sprintf("spd-%d.hex", SPDId)
 | 
				
			||||||
 | 
						ioutil.WriteFile(filepath.Join(SPDSetDirName, SPDFileName), []byte(s), 0644)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func writeEmptySPD(SPDSetDirName string, t memTech) {
 | 
				
			||||||
 | 
						s := createSPD(nil, t)
 | 
				
			||||||
 | 
						SPDFileName := "spd-empty.hex"
 | 
				
			||||||
 | 
						ioutil.WriteFile(filepath.Join(SPDSetDirName, SPDFileName), []byte(s), 0644)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getGeneratedString() string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("# Generated by:\n# %s\n\n", strings.Join(os.Args[0:], " "))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func writeSPDManifest(memPartArray []memPart, SPDSetDirName string) {
 | 
				
			||||||
 | 
						var s string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s += getGeneratedString()
 | 
				
			||||||
 | 
						for i := 0; i < len(memPartArray); i++ {
 | 
				
			||||||
 | 
							s += fmt.Sprintf("%s,spd-%d.hex\n", memPartArray[i].Name, memPartArray[i].SPDId)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ioutil.WriteFile(filepath.Join(SPDSetDirName, SPDManifestFileName), []byte(s), 0644)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func writeSetMap(setMap map[int][]int, SPDDirName string) {
 | 
				
			||||||
 | 
						var s string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s += getGeneratedString()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for index, arr := range setMap {
 | 
				
			||||||
 | 
							for _, item := range arr {
 | 
				
			||||||
 | 
								s += fmt.Sprintf("%s,set-%d\n", platformNames[item], index)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ioutil.WriteFile(filepath.Join(SPDDirName, PlatformManifestFileName), []byte(s), 0644)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func usage() {
 | 
				
			||||||
 | 
						fmt.Printf("\nUsage: %s <mem_parts_list_json> <mem_technology>\n\n", os.Args[0])
 | 
				
			||||||
 | 
						fmt.Printf("   where,\n")
 | 
				
			||||||
 | 
						fmt.Printf("   mem_parts_list_json = JSON File containing list of memory parts and attributes\n")
 | 
				
			||||||
 | 
						fmt.Printf("   mem_technology = Memory technology -- one of lp4x, ddr4\n\n\n")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						if len(os.Args) != 3 {
 | 
				
			||||||
 | 
							usage()
 | 
				
			||||||
 | 
							log.Fatal("Incorrect number of arguments")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var t memTech
 | 
				
			||||||
 | 
						memPartsFilePath, memTechnology := os.Args[1], os.Args[2]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if strings.ToUpper(memTechnology) == "LP4X" {
 | 
				
			||||||
 | 
							t = lp4x{}
 | 
				
			||||||
 | 
						} else if strings.ToUpper(memTechnology) == "DDR4" {
 | 
				
			||||||
 | 
							t = ddr4{}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							log.Fatal("Unsupported memory technology ", memTechnology)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SPDDir, err := filepath.Abs(filepath.Dir(memPartsFilePath))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memParts, err := readMemParts(memPartsFilePath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memPartExists := make(map[string]bool)
 | 
				
			||||||
 | 
						for i := 0; i < len(memParts.MemParts); i++ {
 | 
				
			||||||
 | 
							if memPartExists[memParts.MemParts[i].Name] {
 | 
				
			||||||
 | 
								log.Fatalf("%s is duplicated in mem_parts_list_json", memParts.MemParts[i].Name)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							memPartExists[memParts.MemParts[i].Name] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err := t.addNewPart(memParts.MemParts[i].Name, memParts.MemParts[i].Attribs); err != nil {
 | 
				
			||||||
 | 
								log.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						setMap := t.getSetMap()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < len(setMap); i++ {
 | 
				
			||||||
 | 
							var dedupedAttribs []interface{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for j := 0; j < len(memParts.MemParts); j++ {
 | 
				
			||||||
 | 
								spdAttribs, _ := t.getSPDAttribs(memParts.MemParts[j].Name, i)
 | 
				
			||||||
 | 
								index := -1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if index = findIndex(dedupedAttribs, spdAttribs); index == -1 {
 | 
				
			||||||
 | 
									dedupedAttribs = append(dedupedAttribs, spdAttribs)
 | 
				
			||||||
 | 
									index = len(dedupedAttribs) - 1
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								memParts.MemParts[j].SPDId = index + 1
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							SPDSetDir := fmt.Sprintf("%s/set-%d", SPDDir, i)
 | 
				
			||||||
 | 
							os.MkdirAll(SPDSetDir, os.ModePerm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for j := 0; j < len(dedupedAttribs); j++ {
 | 
				
			||||||
 | 
								writeSPD(dedupedAttribs[j], j+1, SPDSetDir, t)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							writeEmptySPD(SPDSetDir, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							writeSPDManifest(memParts.MemParts, SPDSetDir)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						writeSetMap(setMap, SPDDir)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user