Commit d0ba88f5dd675af7d2bb93d33ef08f96af2ced51

Authored by Jagan Teki
Committed by Kever Yang
1 parent 1ff5283d92

ram: rk3399: Add rank detection support

Right now the rk3399 sdram driver assume that the board
has configured with 2 channels, so any possibility to
enable single channel on the same driver will encounter
channel #1 data training failure.

Log:
U-Boot TPL board init
sdram_init: data training failed
rk3399_dmc_init DRAM init failed -5

So, add an algorithm that can capable to compute the active
or configured rank with associated channel like
a) do rank loop to compute the active rank, with associated
   channel numbers
b) then, succeed the data training only for configured channel
c) preserve the rank for given channel
d) do channel loop for setting the active channel
e) if given rank is zero or inactive on the specific channel,
   clear the timings for the associated channel
f) finally, return error if number of channels is zero

Tested in NanoPI-NEO4 since it support single channel sdram
configuration.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Signed-off-by: YouMin Chen <cym@rock-chips.com>
Reviewed-by: Kever Yang <Kever.yang@rock-chips.com>
(add PI_READ_GATE_TRAINING for LPDDR3 to support rk3399-evb case)
Signed-off-by: Kever Yang <Kever.yang@rock-chips.com>

Showing 1 changed file with 100 additions and 22 deletions Side-by-side Diff

drivers/ram/rockchip/sdram_rk3399.c
... ... @@ -1254,13 +1254,52 @@
1254 1254 return stride;
1255 1255 }
1256 1256  
  1257 +static void clear_channel_params(struct rk3399_sdram_params *params, u8 channel)
  1258 +{
  1259 + params->ch[channel].cap_info.rank = 0;
  1260 + params->ch[channel].cap_info.col = 0;
  1261 + params->ch[channel].cap_info.bk = 0;
  1262 + params->ch[channel].cap_info.bw = 32;
  1263 + params->ch[channel].cap_info.dbw = 32;
  1264 + params->ch[channel].cap_info.row_3_4 = 0;
  1265 + params->ch[channel].cap_info.cs0_row = 0;
  1266 + params->ch[channel].cap_info.cs1_row = 0;
  1267 + params->ch[channel].cap_info.ddrconfig = 0;
  1268 +}
  1269 +
  1270 +static int pctl_init(struct dram_info *dram, struct rk3399_sdram_params *params)
  1271 +{
  1272 + int channel;
  1273 + int ret;
  1274 +
  1275 + for (channel = 0; channel < 2; channel++) {
  1276 + const struct chan_info *chan = &dram->chan[channel];
  1277 + struct rk3399_cru *cru = dram->cru;
  1278 + struct rk3399_ddr_publ_regs *publ = chan->publ;
  1279 +
  1280 + phy_pctrl_reset(cru, channel);
  1281 + phy_dll_bypass_set(publ, params->base.ddr_freq);
  1282 +
  1283 + ret = pctl_cfg(dram, chan, channel, params);
  1284 + if (ret < 0) {
  1285 + printf("%s: pctl config failed\n", __func__);
  1286 + return ret;
  1287 + }
  1288 +
  1289 + /* start to trigger initialization */
  1290 + pctl_start(dram, channel);
  1291 + }
  1292 +
  1293 + return 0;
  1294 +}
  1295 +
1257 1296 static int sdram_init(struct dram_info *dram,
1258 1297 struct rk3399_sdram_params *params)
1259 1298 {
1260 1299 unsigned char dramtype = params->base.dramtype;
1261 1300 unsigned int ddr_freq = params->base.ddr_freq;
1262   - struct rk3399_cru *cru = dram->cru;
1263   - int channel;
  1301 + u32 training_flag = PI_READ_GATE_TRAINING;
  1302 + int channel, ch, rank;
1264 1303 int ret;
1265 1304  
1266 1305 debug("Starting SDRAM initialization...\n");
1267 1306  
1268 1307  
1269 1308  
1270 1309  
1271 1310  
1272 1311  
1273 1312  
... ... @@ -1272,36 +1311,75 @@
1272 1311 return -E2BIG;
1273 1312 }
1274 1313  
  1314 + for (ch = 0; ch < 2; ch++) {
  1315 + params->ch[ch].cap_info.rank = 2;
  1316 + for (rank = 2; rank != 0; rank--) {
  1317 + ret = pctl_init(dram, params);
  1318 + if (ret < 0) {
  1319 + printf("%s: pctl init failed\n", __func__);
  1320 + return ret;
  1321 + }
  1322 +
  1323 + /* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */
  1324 + if (dramtype == LPDDR3)
  1325 + udelay(10);
  1326 +
  1327 + params->ch[ch].cap_info.rank = rank;
  1328 +
  1329 + /*
  1330 + * LPDDR3 CA training msut be trigger before
  1331 + * other training.
  1332 + * DDR3 is not have CA training.
  1333 + */
  1334 + if (params->base.dramtype == LPDDR3)
  1335 + training_flag |= PI_CA_TRAINING;
  1336 +
  1337 + if (!(data_training(&dram->chan[ch], ch,
  1338 + params, training_flag)))
  1339 + break;
  1340 + }
  1341 + /* Computed rank with associated channel number */
  1342 + params->ch[ch].cap_info.rank = rank;
  1343 + }
  1344 +
  1345 + params->base.num_channels = 0;
1275 1346 for (channel = 0; channel < 2; channel++) {
1276 1347 const struct chan_info *chan = &dram->chan[channel];
1277   - struct rk3399_ddr_publ_regs *publ = chan->publ;
  1348 + struct sdram_cap_info *cap_info = &params->ch[channel].cap_info;
  1349 + u8 training_flag = PI_FULL_TRAINING;
1278 1350  
1279   - phy_pctrl_reset(cru, channel);
1280   - phy_dll_bypass_set(publ, ddr_freq);
1281   -
1282   - if (channel >= params->base.num_channels)
  1351 + if (cap_info->rank == 0) {
  1352 + clear_channel_params(params, channel);
1283 1353 continue;
1284   -
1285   - ret = pctl_cfg(dram, chan, channel, params);
1286   - if (ret < 0) {
1287   - printf("%s: pctl config failed\n", __func__);
1288   - return ret;
  1354 + } else {
  1355 + params->base.num_channels++;
1289 1356 }
1290 1357  
1291   - /* start to trigger initialization */
1292   - pctl_start(dram, channel);
  1358 + debug("Channel ");
  1359 + debug(channel ? "1: " : "0: ");
1293 1360  
1294   - /* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */
1295   - if (dramtype == LPDDR3)
1296   - udelay(10);
  1361 + /* LPDDR3 should have write and read gate training */
  1362 + if (params->base.dramtype == LPDDR3)
  1363 + training_flag = PI_WRITE_LEVELING |
  1364 + PI_READ_GATE_TRAINING;
1297 1365  
1298   - if (data_training(chan, channel, params, PI_FULL_TRAINING)) {
1299   - printf("%s: data training failed\n", __func__);
1300   - return -EIO;
  1366 + if (params->base.dramtype != LPDDR4) {
  1367 + ret = data_training(dram, channel, params,
  1368 + training_flag);
  1369 + if (!ret) {
  1370 + debug("%s: data train failed for channel %d\n",
  1371 + __func__, ret);
  1372 + continue;
  1373 + }
1301 1374 }
1302 1375  
1303   - set_ddrconfig(chan, params, channel,
1304   - params->ch[channel].cap_info.ddrconfig);
  1376 + set_ddrconfig(chan, params, channel, cap_info->ddrconfig);
  1377 + }
  1378 +
  1379 + if (params->base.num_channels == 0) {
  1380 + printf("%s: ", __func__);
  1381 + printf(" - %dMHz failed!\n", params->base.ddr_freq);
  1382 + return -EINVAL;
1305 1383 }
1306 1384  
1307 1385 params->base.stride = calculate_stride(params);