xref: /aosp_15_r20/external/coreboot/src/commonlib/bsd/include/commonlib/bsd/mem_chip_info.h (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 
3 #ifndef _COMMONLIB_BSD_MEM_CHIP_INFO_H_
4 #define _COMMONLIB_BSD_MEM_CHIP_INFO_H_
5 
6 #include <stddef.h>
7 
8 enum mem_chip_type {
9 	MEM_CHIP_DDR3 = 0x30,
10 	MEM_CHIP_LPDDR3 = 0x38,
11 	MEM_CHIP_DDR4 = 0x40,
12 	MEM_CHIP_LPDDR4 = 0x48,
13 	MEM_CHIP_LPDDR4X = 0x49,
14 };
15 
16 #define MEM_CHIP_STRUCT_VERSION 0	/* Hopefully we'll never have to bump this... */
17 
18 /*
19  * This structure describes memory topology by channel, rank and DDR chip.
20  *
21  * Definitions:
22  *	channel: A DDR channel is an entire set of DDR pins (including DQ, CS, CA, etc.) coming
23  *		 out of the DDR controller on the SoC. An SoC may support one or more DDR
24  *		 channels. The DDR chips on different channels are entirely independent from one
25  *		 another and not aware of each others' existence (concepts like dual-channel
26  *		 mode / channel-interleaving only exist inside the DDR controller and are not
27  *		 relevant to this topology description).
28  *	chip:	 A physically distinct DDR part on the mainboard, with a single "channel" worth
29  *		 of pins (DQ, CS, CA, etc.). Parts that combine multiple "channels" worth of
30  *		 pins in one package (e.g. separate DQ[0]_A and DQ[0]_B) count as multiple
31  *		 separate chips in this description.
32  *	rank:	 DDR ranks are independent sub-units within a single physical DDR chip. Each DDR
33  *		 transaction only communicates with one rank, which is selected through the CS
34  *		 pins.
35  *	MRx:	 Mode registers, as defined in the various (LP)DDR specs. Mode registers are
36  *		 read through the DQ and written through the CA pins, and each rank on each chip
37  *		 has a separate mode register as selected by the CS pins.
38  *
39  * The basic purpose of this structure is to record information read from the mode registers on
40  * all ranks of all chips on all channels, to later allow the recipient of this information to
41  * reconstruct the topology and exact parts used on the board. Since each system may have a
42  * variable number of channels, and the chips on those channels may each have a variable number
43  * of ranks, this would require a doubly-nested structure with variable array sizes in both
44  * dimensions. The size and offset calculations in such a structure would become very cumbersome
45  * and error-prone, so instead this design just stores a one-dimensional array of "entries"
46  * where each entry stores information about one specific rank on one specific channel. This
47  * means that information which is specific to the channel itself is duplicated among all such
48  * entries for all ranks on that channel, and in a well-formed instance of this structure the
49  * values in per-channel fields (`type` and `channel_io_width`) among all entries that have the
50  * same value in the `channel` field MUST be identical.
51  *
52  * The information read from the mode registers should be decoded into normal integer values,
53  * but not otherwise adjusted in any way. For example, if the value read from MR8 on an LPDDR4
54  * chip is 0b00010000, the `density_mbits` field should be set to 8192 (MR8[5:2] = 0b0100
55  * decoded to 8192 Mbits) and the `io_width` field should be set to 16 (MR8[7:6] = 0b00 decoded
56  * to x16.
57  *
58  * Note that on some systems the I/O width (number of DQ pins) of the SoC controller's channel
59  * is a multiple of the I/O width on the DDR chip (which is the reason the two are recorded
60  * separately in this structure). This means that two identical DDR chips are wired in parallel
61  * on the same channel (e.g. one 16-bit part is wired to DQ[0:15] and the other to DQ[16:31]).
62  * All other pins beside DQ are shorted together in this configuration. This means that only the
63  * mode registers of the first chip can be read and recorded in this structure (and all mode
64  * register writes automatically write the same value to all chips through the shorted CA pins).
65  * The other chips are reported "implicitly" via the mismatch in I/O width.
66  *
67  * That means that the total amount of memory in bytes available on the whole system is:
68  *
69  * SUM[over all entries](density_mbits * (channel_io_width/io_width)) * 1024 * 1024 / 8
70  */
71 struct mem_chip_info {
72 	uint8_t num_entries;
73 	uint8_t reserved[2];		/* Must be set to 0 */
74 	uint8_t struct_version;		/* Must always be MEM_CHIP_STRUCT_VERSION */
75 	struct mem_chip_entry {
76 		uint8_t channel;	/* Channel number this entry belongs to */
77 		uint8_t rank;		/* Rank number within that channel */
78 
79 		/* per-channel information */
80 		uint8_t type;		/* enum mem_chip_type */
81 		uint8_t channel_io_width; /* I/O width of the channel (no. of DQ pins on SoC) */
82 
83 		/* per-rank information */
84 		uint32_t density_mbits;	/* density in megabits, decoded from MR8 */
85 		uint8_t io_width;	/* I/O width of the DDR chip, decoded from MR8 */
86 		uint8_t manufacturer_id; /* raw value from MR5 */
87 		uint8_t revision_id[2];	/* raw values from MR6 and MR7 */
88 		uint8_t serial_id[8];	/* LPDDR5 only (set to 0 otherwise), MR47 - MR54 */
89 	} entries[];
90 };
91 
mem_chip_info_size(int entries)92 static inline size_t mem_chip_info_size(int entries)
93 {
94 	return sizeof(struct mem_chip_info) + sizeof(struct mem_chip_entry) * entries;
95 };
96 
mem_chip_info_total_density_bytes(const struct mem_chip_info * info)97 static inline uint64_t mem_chip_info_total_density_bytes(const struct mem_chip_info *info)
98 {
99 	uint64_t bytes = 0;
100 	int i;
101 
102 	for (i = 0; i < info->num_entries; i++) {
103 		const struct mem_chip_entry *e = &info->entries[i];
104 		bytes += (uint64_t)e->density_mbits * (e->channel_io_width / e->io_width)
105 			 * (MiB / 8);
106 	}
107 
108 	return bytes;
109 }
110 
111 #endif /* _COMMONLIB_BSD_MEM_CHIP_INFO_H_ */
112