1 /* SPDX-License-Identifier: GPL-2.0-or-later */
9 /* ------------------------------------------------------------------------------------------ */
10 /* LP5-defined types */
11 /* ------------------------------------------------------------------------------------------ */
16 type LP5MemAttributes
struct {
17 /* Primary attributes - must be provided by JSON file for each part */
20 BitWidthPerChannel
int
25 * All the following parameters are optional and required only if the part requires
26 * special parameters as per the datasheet.
28 /* Timing parameters */
38 type LP5DensityParams
struct {
40 RowAddressBitsx8Channel
int
41 RowAddressBitsx16Channel
int
46 type LP5SpeedParams
struct {
51 type LP5SPDAttribFunc
func(*LP5MemAttributes
) byte
53 type LP5SPDAttribTableEntry
struct {
55 getVal LP5SPDAttribFunc
61 otherOptionalFeatures
byte
65 /* ------------------------------------------------------------------------------------------ */
67 /* ------------------------------------------------------------------------------------------ */
72 LP5SPDIndexRevision
= 1
73 LP5SPDIndexMemoryType
= 2
74 LP5SPDIndexModuleType
= 3
75 LP5SPDIndexDensityBanks
= 4
76 LP5SPDIndexAddressing
= 5
77 LP5SPDIndexPackageType
= 6
78 LP5SPDIndexOptionalFeatures
= 7
79 LP5SPDIndexOtherOptionalFeatures
= 9
80 LP5SPDIndexModuleOrganization
= 12
81 LP5SPDIndexBusWidth
= 13
82 LP5SPDIndexTimebases
= 17
83 LP5SPDIndexTCKMin
= 18
84 LP5SPDIndexTAAMin
= 24
85 LP5SPDIndexTRCDMin
= 26
86 LP5SPDIndexTRPABMin
= 27
87 LP5SPDIndexTRPPBMin
= 28
88 LP5SPDIndexTRFCABMinLSB
= 29
89 LP5SPDIndexTRFCABMinMSB
= 30
90 LP5SPDIndexTRFCPBMinLSB
= 31
91 LP5SPDIndexTRFCPBMinMSB
= 32
92 LP5SPDIndexTRPPBMinFineOffset
= 120
93 LP5SPDIndexTRPABMinFineOffset
= 121
94 LP5SPDIndexTRCDMinFineOffset
= 122
95 LP5SPDIndexTAAMinFineOffset
= 123
96 LP5SPDIndexTCKMinFineOffset
= 125
97 LP5SPDIndexManufacturerPartNumberStartByte
= 329
98 LP5SPDIndexManufacturerPartNumberEndByte
= 348
104 * 6:4 (Bytes total) = 2 (512 bytes)
105 * 3:0 (Bytes used) = 3 (384 bytes)
106 * Set to 0x23 for LPDDR5.
108 LP5SPDValueSize
= 0x23
111 * Revision 1.0. Expected by ADL
113 LP5SPDValueRevision1_0
= 0x10
115 * Revision 1.1. Expected by Sabrina
117 LP5SPDValueRevision1_1
= 0x11
120 * As per advisory #616599, ADL MRC expects LPDDR5 memory type = 0x13.
122 LP5SPDValueMemoryType
= 0x13
126 * 7:7 (Hybrid) = 0 (Not hybrid)
127 * 6:4 (Hybrid media) = 000 (Not hybrid)
128 * 3:0 (Base Module Type) = 1110 (Non-DIMM solution)
130 * This is dependent on hardware design. LPDDR5 only has memory down solution.
131 * Hence this is not hybrid non-DIMM solution.
134 LP5SPDValueModuleType
= 0x0e
138 * 3:2 (MTB) = 00 (0.125ns)
139 * 1:0 (FTB) = 00 (1ps)
142 LP5SPDValueTimebases
= 0x00
144 /* As per JEDEC spec, unused digits of manufacturer part number are left as blank. */
145 LP5SPDValueManufacturerPartNumberBlank
= 0x20
150 * LPDDR5 has a flexible bank architecture with three programmable bank modes: BG, 8B, 16B.
151 * ADL will use 8B mode for all parts.
154 * 7:6 (Bank Group Bits) = 00 (no bank groups)
155 * 5:4 (Bank Address Bits) = 01 (8 banks)
156 * Set bits 7:4 to 0b0001.
158 LP5BankGroupsBanks
= 0x1
161 * Tables 8 and 9 from JESD209-5B.
162 * ADL uses 8B mode for all parts. The column addresses are the same for x8 and x16.
163 * Effective column address bits = column address bits + burst address bits = 6 + 5 = 11.
164 * As per JESD 21-C, this is encoded as 0b010.
166 LP5ColumnAddressBits
= 0x2
169 /* ------------------------------------------------------------------------------------------ */
170 /* Global variables */
171 /* ------------------------------------------------------------------------------------------ */
173 var LP5PlatformSetMap
= map[int][]int{
178 var LP5SetInfo
= map[int]LP5Set
{
180 SPDRevision
: LP5SPDValueRevision1_0
,
183 * 5:4 (Maximum Activate Window) = 00 (8192 * tREFI)
184 * 3:0 (Maximum Activate Count) = 1000 (Unlimited MAC)
187 optionalFeatures
: 0x08,
189 * For ADL (as per advisory #616599):
190 * 7:5 (Number of system channels) = 000 (1 channel always)
191 * 4:3 (Bus width extension) = 00 (no ECC)
192 * 2:0 (Bus width) = 001 (x16 always)
195 busWidthEncoding
: 0x01,
198 SPDRevision
: LP5SPDValueRevision1_1
,
200 * For Sabrina (as per advisory b/211510456):
201 * 5:4 (Maximum Activate Window) = 01 (4096 * tREFI)
202 * 3:0 (Maximum Activate Count) = 1000 (Unlimited MAC)
205 optionalFeatures
: 0x18,
207 * For Sabrina (as per advisory b/211510456):
208 * 7:6 (PPR) = 1 (Post Package Repair is supported)
211 otherOptionalFeatures
: 0x40,
213 * For Sabrina (as per advisory b/211510456):
214 * 7:5 (Number of system channels) = 000 (1 channel always)
215 * 4:3 (Bus width extension) = 00 (no ECC)
216 * 2:0 (Bus width) = 010 (x32 always)
219 busWidthEncoding
: 0x02,
223 var LP5PartAttributeMap
= map[string]LP5MemAttributes
{}
227 * DensityEncoding: Maps the die density in Gb to the SPD encoding of the die density
230 * RowAddressBits: Maps the die density to the number of row address bits.
231 * Tables 6-11 in JESD209-5B (same for all three bank modes).
233 * TRFCABNs/TRFCPBNs: Maps the die density to the refresh timings.
234 * Tables 235 and 236 in JESD209-5B (same for all three bank modes).
236 var LP5DensityGbToSPDEncoding
= map[int]LP5DensityParams
{
238 DensityEncoding
: 0x4,
239 RowAddressBitsx8Channel
: 15,
240 RowAddressBitsx16Channel
: 14,
245 DensityEncoding
: 0xb,
246 RowAddressBitsx8Channel
: 16,
247 RowAddressBitsx16Channel
: 15,
252 DensityEncoding
: 0x5,
253 RowAddressBitsx8Channel
: 16,
254 RowAddressBitsx16Channel
: 15,
259 DensityEncoding
: 0x8,
260 RowAddressBitsx8Channel
: 17,
261 RowAddressBitsx16Channel
: 16,
266 DensityEncoding
: 0x6,
267 RowAddressBitsx8Channel
: 17,
268 RowAddressBitsx16Channel
: 16,
273 DensityEncoding
: 0x9,
274 RowAddressBitsx8Channel
: 18,
275 RowAddressBitsx16Channel
: 17,
280 DensityEncoding
: 0x7,
281 RowAddressBitsx8Channel
: 18,
282 RowAddressBitsx16Channel
: 17,
289 * Maps the number of row address bits to the SPD encoding as per JESD 21-C.
291 var LP5RowAddressBitsEncoding
= map[int]byte{
301 * LPDDR5 has two clocks: the command/address clock (CK) and the data clock (WCK). They are
302 * related by the WCK:CK ratio, which can be either 4:1 or 2:1. On ADL, 4:1 is used.
303 * For ADL, the MRC expects the tCKmin to encode the CK period. This is calculated as:
304 * tCKmin = 1 / CK rate
305 * = 1 / (WCK rate / WCK:CK)
306 * = 1 / (speed grade / 2 / WCK:CK) // "double data rate"
309 * From Table 220 of JESD209-5B, using a 4:1 WCK:CK ratio and Set 0.
311 var LP5SpeedMbpsToSPDEncoding
= map[int]LP5SpeedParams
{
313 TCKMinPs
: 1250, /* 1 / (6400 / 2 / 4) */
317 TCKMinPs
: 1455, /* 1 / (5500 / 2 / 4) */
322 var LP5SPDAttribTable
= map[int]LP5SPDAttribTableEntry
{
323 LP5SPDIndexSize
: {constVal
: LP5SPDValueSize
},
324 LP5SPDIndexRevision
: {getVal
: LP5EncodeSPDRevision
},
325 LP5SPDIndexMemoryType
: {constVal
: LP5SPDValueMemoryType
},
326 LP5SPDIndexModuleType
: {constVal
: LP5SPDValueModuleType
},
327 LP5SPDIndexDensityBanks
: {getVal
: LP5EncodeDensityBanks
},
328 LP5SPDIndexAddressing
: {getVal
: LP5EncodeSdramAddressing
},
329 LP5SPDIndexPackageType
: {getVal
: LP5EncodePackageType
},
330 LP5SPDIndexOptionalFeatures
: {getVal
: LP5EncodeOptionalFeatures
},
331 LP5SPDIndexOtherOptionalFeatures
: {getVal
: LP5EncodeOtherOptionalFeatures
},
332 LP5SPDIndexModuleOrganization
: {getVal
: LP5EncodeModuleOrganization
},
333 LP5SPDIndexBusWidth
: {getVal
: LP5EncodeBusWidth
},
334 LP5SPDIndexTimebases
: {constVal
: LP5SPDValueTimebases
},
335 LP5SPDIndexTCKMin
: {getVal
: LP5EncodeTCKMin
},
336 LP5SPDIndexTCKMinFineOffset
: {getVal
: LP5EncodeTCKMinFineOffset
},
337 LP5SPDIndexTAAMin
: {getVal
: LP5EncodeTAAMin
},
338 LP5SPDIndexTAAMinFineOffset
: {getVal
: LP5EncodeTAAMinFineOffset
},
339 LP5SPDIndexTRCDMin
: {getVal
: LP5EncodeTRCDMin
},
340 LP5SPDIndexTRCDMinFineOffset
: {getVal
: LP5EncodeTRCDMinFineOffset
},
341 LP5SPDIndexTRPABMin
: {getVal
: LP5EncodeTRPABMin
},
342 LP5SPDIndexTRPABMinFineOffset
: {getVal
: LP5EncodeTRPABMinFineOffset
},
343 LP5SPDIndexTRPPBMin
: {getVal
: LP5EncodeTRPPBMin
},
344 LP5SPDIndexTRPPBMinFineOffset
: {getVal
: LP5EncodeTRPPBMinFineOffset
},
345 LP5SPDIndexTRFCABMinLSB
: {getVal
: LP5EncodeTRFCABMinLsb
},
346 LP5SPDIndexTRFCABMinMSB
: {getVal
: LP5EncodeTRFCABMinMsb
},
347 LP5SPDIndexTRFCPBMinLSB
: {getVal
: LP5EncodeTRFCPBMinLsb
},
348 LP5SPDIndexTRFCPBMinMSB
: {getVal
: LP5EncodeTRFCPBMinMsb
},
351 /* ------------------------------------------------------------------------------------------ */
353 /* ------------------------------------------------------------------------------------------ */
354 func LP5EncodeSPDRevision(memAttribs
*LP5MemAttributes
) byte {
355 f
, ok
:= LP5SetInfo
[LP5CurrSet
]
364 func LP5EncodeDensityBanks(memAttribs
*LP5MemAttributes
) byte {
367 // 3:0 Density per die.
368 b
= LP5DensityGbToSPDEncoding
[memAttribs
.DensityPerDieGb
].DensityEncoding
370 // 5:4 Bank address bits.
371 // 7:6 Bank group bits.
372 b |
= LP5BankGroupsBanks
<< 4
377 func LP5EncodeSdramAddressing(memAttribs
*LP5MemAttributes
) byte {
380 // 2:0 Column address bits.
381 b
= LP5ColumnAddressBits
383 // 5:3 Row address bits.
384 density
:= memAttribs
.DensityPerDieGb
385 var rowAddressBits
int
386 if memAttribs
.BitWidthPerChannel
== 8 {
387 rowAddressBits
= LP5DensityGbToSPDEncoding
[density
].RowAddressBitsx8Channel
389 rowAddressBits
= LP5DensityGbToSPDEncoding
[density
].RowAddressBitsx16Channel
391 b |
= LP5RowAddressBitsEncoding
[rowAddressBits
] << 3
396 func LP5EncodePackageType(memAttribs
*LP5MemAttributes
) byte {
399 // 1:0 Signal loading index.
402 // 3:2 Channels per package.
403 // Channels per package = package width (e.g. x32) / bitWidthPerChannel (x8 or x16).
404 // This can equivalently be calculated as diesPerPackage / ranksPerChannel.
405 // This calculation is used to avoid adding a redundant attribute for package width.
406 channels
:= memAttribs
.DiesPerPackage
/ memAttribs
.RanksPerChannel
407 b |
= byte(channels
>>1) << 2
409 // 6:4 Dies per package.
410 b |
= (byte(memAttribs
.DiesPerPackage
) - 1) << 4
414 if memAttribs
.DiesPerPackage
> 1 {
415 packageType
= 1 // Non-Monolithic
417 packageType
= 0 // Monolithic
419 b |
= packageType
<< 7
424 func LP5EncodeModuleOrganization(memAttribs
*LP5MemAttributes
) byte {
427 // 2:0 Device data width per channel
428 b
= byte(memAttribs
.BitWidthPerChannel
/ 8)
430 // 5:3 Package ranks per channel
431 b |
= byte(memAttribs
.RanksPerChannel
-1) << 3
436 func LP5EncodeOptionalFeatures(memAttribs
*LP5MemAttributes
) byte {
437 f
, ok
:= LP5SetInfo
[LP5CurrSet
]
443 return f
.optionalFeatures
446 func LP5EncodeOtherOptionalFeatures(memAttribs
*LP5MemAttributes
) byte {
447 f
, ok
:= LP5SetInfo
[LP5CurrSet
]
453 return f
.otherOptionalFeatures
456 func LP5EncodeBusWidth(memAttribs
*LP5MemAttributes
) byte {
457 f
, ok
:= LP5SetInfo
[LP5CurrSet
]
463 return f
.busWidthEncoding
466 func LP5EncodeTCKMin(memAttribs
*LP5MemAttributes
) byte {
467 return convPsToMtbByte(memAttribs
.TCKMinPs
)
470 func LP5EncodeTCKMinFineOffset(memAttribs
*LP5MemAttributes
) byte {
471 return convPsToFtbByte(memAttribs
.TCKMinPs
)
474 func LP5EncodeTAAMin(memAttribs
*LP5MemAttributes
) byte {
475 return convPsToMtbByte(memAttribs
.TAAMinPs
)
478 func LP5EncodeTAAMinFineOffset(memAttribs
*LP5MemAttributes
) byte {
479 return convPsToFtbByte(memAttribs
.TAAMinPs
)
482 func LP5EncodeTRCDMin(memAttribs
*LP5MemAttributes
) byte {
483 return convNsToMtbByte(memAttribs
.TRCDMinNs
)
486 func LP5EncodeTRCDMinFineOffset(memAttribs
*LP5MemAttributes
) byte {
487 return convNsToFtbByte(memAttribs
.TRCDMinNs
)
490 func LP5EncodeTRPABMin(memAttribs
*LP5MemAttributes
) byte {
491 return convNsToMtbByte(memAttribs
.TRPABMinNs
)
494 func LP5EncodeTRPABMinFineOffset(memAttribs
*LP5MemAttributes
) byte {
495 return convNsToFtbByte(memAttribs
.TRPABMinNs
)
498 func LP5EncodeTRPPBMin(memAttribs
*LP5MemAttributes
) byte {
499 return convNsToMtbByte(memAttribs
.TRPPBMinNs
)
502 func LP5EncodeTRPPBMinFineOffset(memAttribs
*LP5MemAttributes
) byte {
503 return convNsToFtbByte(memAttribs
.TRPPBMinNs
)
506 func LP5EncodeTRFCABMinMsb(memAttribs
*LP5MemAttributes
) byte {
507 return byte((convNsToMtb(memAttribs
.TRFCABNs
) >> 8) & 0xff)
510 func LP5EncodeTRFCABMinLsb(memAttribs
*LP5MemAttributes
) byte {
511 return byte(convNsToMtb(memAttribs
.TRFCABNs
) & 0xff)
514 func LP5EncodeTRFCPBMinMsb(memAttribs
*LP5MemAttributes
) byte {
515 return byte((convNsToMtb(memAttribs
.TRFCPBNs
) >> 8) & 0xff)
518 func LP5EncodeTRFCPBMinLsb(memAttribs
*LP5MemAttributes
) byte {
519 return byte(convNsToMtb(memAttribs
.TRFCPBNs
) & 0xff)
522 func LP5UpdateTCKMin(memAttribs
*LP5MemAttributes
) {
523 if memAttribs
.TCKMinPs
== 0 {
524 memAttribs
.TCKMinPs
= LP5SpeedMbpsToSPDEncoding
[memAttribs
.SpeedMbps
].TCKMinPs
528 func LP5UpdateTAAMin(memAttribs
*LP5MemAttributes
) {
529 if memAttribs
.TAAMinPs
== 0 {
530 maxCAS
:= LP5SpeedMbpsToSPDEncoding
[memAttribs
.SpeedMbps
].MaxCASLatency
531 memAttribs
.TAAMinPs
= memAttribs
.TCKMinPs
* maxCAS
535 func LP5UpdateTRFCAB(memAttribs
*LP5MemAttributes
) {
536 if memAttribs
.TRFCABNs
== 0 {
537 memAttribs
.TRFCABNs
= LP5DensityGbToSPDEncoding
[memAttribs
.DensityPerDieGb
].TRFCABNs
541 func LP5UpdateTRFCPB(memAttribs
*LP5MemAttributes
) {
542 if memAttribs
.TRFCPBNs
== 0 {
543 memAttribs
.TRFCPBNs
= LP5DensityGbToSPDEncoding
[memAttribs
.DensityPerDieGb
].TRFCPBNs
547 func LP5UpdateTRCD(memAttribs
*LP5MemAttributes
) {
548 if memAttribs
.TRCDMinNs
== 0 {
549 /* Table 372 from JESD209-5B */
550 memAttribs
.TRCDMinNs
= 18
554 func LP5UpdateTRPAB(memAttribs
*LP5MemAttributes
) {
555 if memAttribs
.TRPABMinNs
== 0 {
556 /* Table 372 from JESD209-5B */
557 memAttribs
.TRPABMinNs
= 21
561 func LP5UpdateTRPPB(memAttribs
*LP5MemAttributes
) {
562 if memAttribs
.TRPPBMinNs
== 0 {
563 /* Table 372 from JESD209-5B */
564 memAttribs
.TRPPBMinNs
= 18
568 func lp5UpdateMemoryAttributes(memAttribs
*LP5MemAttributes
) {
569 LP5UpdateTCKMin(memAttribs
)
570 LP5UpdateTAAMin(memAttribs
)
571 LP5UpdateTRFCAB(memAttribs
)
572 LP5UpdateTRFCPB(memAttribs
)
573 LP5UpdateTRCD(memAttribs
)
574 LP5UpdateTRPAB(memAttribs
)
575 LP5UpdateTRPPB(memAttribs
)
578 func LP5ValidateDensity(density
int) error
{
579 if _
, ok
:= LP5DensityGbToSPDEncoding
[density
]; !ok
{
580 return fmt
.Errorf("Incorrect density per die: %d Gb", density
)
585 func LP5ValidateDies(dies
int) error
{
586 if dies
!= 2 && dies
!= 4 && dies
!= 8 {
587 return fmt
.Errorf("Incorrect dies: %d", dies
)
592 func LP5ValidateDataWidth(width
int) error
{
593 if width
!= 8 && width
!= 16 {
594 return fmt
.Errorf("Incorrect bit width: %d", width
)
599 func LP5ValidateRanks(ranks
int) error
{
600 if ranks
!= 1 && ranks
!= 2 {
601 return fmt
.Errorf("Incorrect ranks: %d", ranks
)
606 func LP5ValidateSpeed(speed
int) error
{
607 if _
, ok
:= LP5SpeedMbpsToSPDEncoding
[speed
]; !ok
{
608 return fmt
.Errorf("Incorrect speed: %d Mbps", speed
)
613 func lp5ValidateMemPartAttributes(memAttribs
*LP5MemAttributes
) error
{
614 if err
:= LP5ValidateDensity(memAttribs
.DensityPerDieGb
); err
!= nil {
617 if err
:= LP5ValidateDies(memAttribs
.DiesPerPackage
); err
!= nil {
620 if err
:= LP5ValidateDataWidth(memAttribs
.BitWidthPerChannel
); err
!= nil {
623 if err
:= LP5ValidateRanks(memAttribs
.RanksPerChannel
); err
!= nil {
626 if err
:= LP5ValidateSpeed(memAttribs
.SpeedMbps
); err
!= nil {
633 func LP5IsManufacturerPartNumberByte(index
int) bool {
634 if index
>= LP5SPDIndexManufacturerPartNumberStartByte
&&
635 index
<= LP5SPDIndexManufacturerPartNumberEndByte
{
641 /* ------------------------------------------------------------------------------------------ */
642 /* Interface Functions */
643 /* ------------------------------------------------------------------------------------------ */
645 func (lp5
) getSetMap() map[int][]int {
646 return LP5PlatformSetMap
649 func (lp5
) addNewPart(name
string, attribs
interface{}) error
{
650 var lp5Attributes LP5MemAttributes
651 eByte
, err
:= json
.Marshal(attribs
)
656 if err
:= json
.Unmarshal(eByte
, &lp5Attributes
); err
!= nil {
660 if err
:= lp5ValidateMemPartAttributes(&lp5Attributes
); err
!= nil {
664 LP5PartAttributeMap
[name
] = lp5Attributes
668 func (lp5
) getSPDAttribs(name
string, set
int) (interface{}, error
) {
669 lp5Attributes
:= LP5PartAttributeMap
[name
]
673 lp5UpdateMemoryAttributes(&lp5Attributes
)
675 return lp5Attributes
, nil
678 func (lp5
) getSPDLen() int {
682 func (lp5
) getSPDByte(index
int, attribs
interface{}) byte {
683 e
, ok
:= LP5SPDAttribTable
[index
]
685 if LP5IsManufacturerPartNumberByte(index
) {
686 return LP5SPDValueManufacturerPartNumberBlank
692 var lp5Attribs LP5MemAttributes
693 lp5Attribs
= attribs
.(LP5MemAttributes
)
694 return e
.getVal(&lp5Attribs
)