2 * This file is part of the coreboot project.
4 * Copyright 2016 Google Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <console/console.h>
17 #include <soc/meminit.h>
18 #include <stddef.h> /* required for FspmUpd.h */
19 #include <soc/fsp/FspmUpd.h>
22 static void set_lpddr4_defaults(struct FSP_M_CONFIG
*cfg
)
24 /* Enable memory down BGA since it's the only LPDDR4 packaging. */
28 cfg
->ScramblerSupport
= 1;
29 cfg
->ChannelHashMask
= 0x36;
30 cfg
->SliceHashMask
= 0x9;
31 cfg
->InterleavedMode
= 2;
32 cfg
->ChannelsSlicesEnable
= 0;
33 cfg
->MinRefRate2xEnable
= 0;
34 cfg
->DualRankSupportEnable
= 1;
35 /* Don't enforce a memory size limit. */
36 cfg
->MemorySizeLimit
= 0;
37 /* Use a 2GiB I/O hole -- field is in MiB units. */
38 cfg
->LowMemoryMaxValue
= 2 * (GiB
/MiB
);
39 /* No restrictions on memory above 4GiB */
40 cfg
->HighMemoryMaxValue
= 0;
42 /* Always default to attempt to use saved training data. */
43 cfg
->DisableFastBoot
= 0;
45 /* LPDDR4 is memory down so no SPD addresses. */
46 cfg
->DIMM0SPDAddress
= 0;
47 cfg
->DIMM1SPDAddress
= 0;
49 /* Clear all the rank enables. */
50 cfg
->Ch0_RankEnable
= 0x0;
51 cfg
->Ch1_RankEnable
= 0x0;
52 cfg
->Ch2_RankEnable
= 0x0;
53 cfg
->Ch3_RankEnable
= 0x0;
56 * Set the device width to x16 which is half a LPDDR4 module as that's
57 * what the reference code expects.
59 cfg
->Ch0_DeviceWidth
= 0x1;
60 cfg
->Ch1_DeviceWidth
= 0x1;
61 cfg
->Ch2_DeviceWidth
= 0x1;
62 cfg
->Ch3_DeviceWidth
= 0x1;
65 * Enable bank hashing (bit 1) and rank interleaving (bit 0) with
66 * a 1KiB address mapping (bits 5:4).
68 cfg
->Ch0_Option
= 0x3;
69 cfg
->Ch1_Option
= 0x3;
70 cfg
->Ch2_Option
= 0x3;
71 cfg
->Ch3_Option
= 0x3;
73 /* Weak on-die termination. */
74 cfg
->Ch0_OdtConfig
= 0;
75 cfg
->Ch1_OdtConfig
= 0;
76 cfg
->Ch2_OdtConfig
= 0;
77 cfg
->Ch3_OdtConfig
= 0;
80 void meminit_lpddr4(struct FSP_M_CONFIG
*cfg
, int speed
)
95 printk(BIOS_WARNING
, "Invalid LPDDR4 speed: %d\n", speed
);
97 speed
= LP4_SPEED_1600
;
101 printk(BIOS_INFO
, "LP4DDR speed is %dMHz\n", speed
);
102 cfg
->Profile
= profile
;
104 set_lpddr4_defaults(cfg
);
107 static void enable_logical_chan0(struct FSP_M_CONFIG
*cfg
, int device_density
,
108 const struct lpddr4_swizzle_cfg
*scfg
)
110 const struct lpddr4_chan_swizzle_cfg
*chan
;
111 /* Number of bytes to copy per DQS. */
112 const size_t sz
= DQ_BITS_PER_DQS
;
115 * Logical channel 0 is comprised of physical channel 0 and 1.
116 * Physical channel 0 is comprised of the CH0_DQB signals.
117 * Physical channel 1 is comprised of the CH0_DQA signals.
119 cfg
->Ch0_DramDensity
= device_density
;
120 cfg
->Ch1_DramDensity
= device_density
;
121 /* Enable rank 0 on both channels. */
122 cfg
->Ch0_RankEnable
= 1;
123 cfg
->Ch1_RankEnable
= 1;
126 * CH0_DQB byte lanes in the bit swizzle configuration field are
127 * not 1:1. The mapping within the swizzling field is:
128 * indicies [0:7] - byte lane 1 (DQS1) DQ[8:15]
129 * indicies [8:15] - byte lane 0 (DQS0) DQ[0:7]
130 * indicies [16:23] - byte lane 3 (DQS3) DQ[24:31]
131 * indicies [24:31] - byte lane 2 (DQS2) DQ[16:23]
133 chan
= &scfg
->phys
[LP4_PHYS_CH0B
];
134 memcpy(&cfg
->Ch0_Bit_swizzling
[0], &chan
->dqs
[LP4_DQS1
], sz
);
135 memcpy(&cfg
->Ch0_Bit_swizzling
[8], &chan
->dqs
[LP4_DQS0
], sz
);
136 memcpy(&cfg
->Ch0_Bit_swizzling
[16], &chan
->dqs
[LP4_DQS3
], sz
);
137 memcpy(&cfg
->Ch0_Bit_swizzling
[24], &chan
->dqs
[LP4_DQS2
], sz
);
140 * CH0_DQA byte lanes in the bit swizzle configuration field are 1:1.
142 chan
= &scfg
->phys
[LP4_PHYS_CH0A
];
143 memcpy(&cfg
->Ch1_Bit_swizzling
[0], &chan
->dqs
[LP4_DQS0
], sz
);
144 memcpy(&cfg
->Ch1_Bit_swizzling
[8], &chan
->dqs
[LP4_DQS1
], sz
);
145 memcpy(&cfg
->Ch1_Bit_swizzling
[16], &chan
->dqs
[LP4_DQS2
], sz
);
146 memcpy(&cfg
->Ch1_Bit_swizzling
[24], &chan
->dqs
[LP4_DQS3
], sz
);
149 static void enable_logical_chan1(struct FSP_M_CONFIG
*cfg
, int device_density
,
150 const struct lpddr4_swizzle_cfg
*scfg
)
152 const struct lpddr4_chan_swizzle_cfg
*chan
;
153 /* Number of bytes to copy per DQS. */
154 const size_t sz
= DQ_BITS_PER_DQS
;
157 * Logical channel 1 is comprised of physical channel 2 and 3.
158 * Physical channel 2 is comprised of the CH1_DQB signals.
159 * Physical channel 3 is comprised of the CH1_DQA signals.
161 cfg
->Ch2_DramDensity
= device_density
;
162 cfg
->Ch3_DramDensity
= device_density
;
163 /* Enable rank 0 on both channels. */
164 cfg
->Ch2_RankEnable
= 1;
165 cfg
->Ch3_RankEnable
= 1;
168 * CH1_DQB byte lanes in the bit swizzle configuration field are
169 * not 1:1. The mapping within the swizzling field is:
170 * indicies [0:7] - byte lane 1 (DQS1) DQ[8:15]
171 * indicies [8:15] - byte lane 0 (DQS0) DQ[0:7]
172 * indicies [16:23] - byte lane 3 (DQS3) DQ[24:31]
173 * indicies [24:31] - byte lane 2 (DQS2) DQ[16:23]
175 chan
= &scfg
->phys
[LP4_PHYS_CH1B
];
176 memcpy(&cfg
->Ch2_Bit_swizzling
[0], &chan
->dqs
[LP4_DQS1
], sz
);
177 memcpy(&cfg
->Ch2_Bit_swizzling
[8], &chan
->dqs
[LP4_DQS0
], sz
);
178 memcpy(&cfg
->Ch2_Bit_swizzling
[16], &chan
->dqs
[LP4_DQS3
], sz
);
179 memcpy(&cfg
->Ch2_Bit_swizzling
[24], &chan
->dqs
[LP4_DQS2
], sz
);
182 * CH1_DQA byte lanes in the bit swizzle configuration field are 1:1.
184 chan
= &scfg
->phys
[LP4_PHYS_CH1A
];
185 memcpy(&cfg
->Ch3_Bit_swizzling
[0], &chan
->dqs
[LP4_DQS0
], sz
);
186 memcpy(&cfg
->Ch3_Bit_swizzling
[8], &chan
->dqs
[LP4_DQS1
], sz
);
187 memcpy(&cfg
->Ch3_Bit_swizzling
[16], &chan
->dqs
[LP4_DQS2
], sz
);
188 memcpy(&cfg
->Ch3_Bit_swizzling
[24], &chan
->dqs
[LP4_DQS3
], sz
);
191 void meminit_lpddr4_enable_channel(struct FSP_M_CONFIG
*cfg
, int logical_chan
,
193 const struct lpddr4_swizzle_cfg
*scfg
)
195 if (device_density
< LP4_8Gb_DENSITY
||
196 device_density
> LP4_16Gb_DENSITY
) {
197 printk(BIOS_ERR
, "Invalid LPDDR4 density: %d\n",
202 switch (logical_chan
) {
204 enable_logical_chan0(cfg
, device_density
, scfg
);
207 enable_logical_chan1(cfg
, device_density
, scfg
);
210 printk(BIOS_ERR
, "Invalid logical channel: %d\n", logical_chan
);