soc/intel/apollolake: Take advantage of common opregion code
[coreboot.git] / src / soc / intel / apollolake / meminit.c
blob8b661c9568041c257ebf6b1bf7bd9ce6b8516124
1 /*
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>
20 #include <string.h>
22 static void set_lpddr4_defaults(struct FSP_M_CONFIG *cfg)
24 /* Enable memory down BGA since it's the only LPDDR4 packaging. */
25 cfg->Package = 1;
26 cfg->MemoryDown = 1;
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)
82 uint8_t profile;
84 switch (speed) {
85 case LP4_SPEED_1600:
86 profile = 0x9;
87 break;
88 case LP4_SPEED_2133:
89 profile = 0xa;
90 break;
91 case LP4_SPEED_2400:
92 profile = 0xb;
93 break;
94 default:
95 printk(BIOS_WARNING, "Invalid LPDDR4 speed: %d\n", speed);
96 /* Set defaults. */
97 speed = LP4_SPEED_1600;
98 profile = 0x9;
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,
192 int device_density,
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",
198 device_density);
199 return;
202 switch (logical_chan) {
203 case LP4_LCH0:
204 enable_logical_chan0(cfg, device_density, scfg);
205 break;
206 case LP4_LCH1:
207 enable_logical_chan1(cfg, device_density, scfg);
208 break;
209 default:
210 printk(BIOS_ERR, "Invalid logical channel: %d\n", logical_chan);
211 break;