Skip to content

Instantly share code, notes, and snippets.

@qinghon
Created April 24, 2022 07:06
Show Gist options
  • Save qinghon/422164726d26b1d0b51254ba7a26ca8a to your computer and use it in GitHub Desktop.
Save qinghon/422164726d26b1d0b51254ba7a26ca8a to your computer and use it in GitHub Desktop.
i2c_release_bus_0
// plat/nxp/drivers/ddr/nxp-ddr/ddr.c
/* Return the bit mask of valid DIMMs found */
static int parse_spd(struct ddr_info *priv)
{
struct ddr_conf *conf = &priv->conf;
struct dimm_params *dimm = &priv->dimm;
int j, valid_mask = 0;
#ifdef CONFIG_DDR_NODIMM
valid_mask = ddr_get_ddr_params(dimm, conf);
if (valid_mask < 0) {
ERROR("DDR params error\n");
return valid_mask;
}
#else
const int *spd_addr = priv->spd_addr;
const int num_ctlrs = priv->num_ctlrs;
const int num_dimm = priv->dimm_on_ctlr;
struct ddr4_spd spd[2];
unsigned int spd_checksum[2];
int addr_idx = 0;
int spd_idx = 0;
int ret, addr, i;
/* Scan all DIMMs */
for (i = 0; i < num_ctlrs; i++) {
debug("Controller %d\n", i);
for (j = 0; j < num_dimm; j++, addr_idx++) {
debug("DIMM %d\n", j);
addr = spd_addr[addr_idx];
if (!addr) {
if (!j) {
ERROR("First SPD addr wrong.\n");
return -EINVAL;
}
continue;
}
debug("addr 0x%x\n", addr);
ret = read_spd(addr, &spd[spd_idx],
sizeof(struct ddr4_spd));
if (ret) { /* invalid */
debug("Invalid SPD at address 0x%x\n", addr);
continue;
}
spd_checksum[spd_idx] =
(spd[spd_idx].crc[1] << 24) |
(spd[spd_idx].crc[0] << 16) |
(spd[spd_idx].mod_section.uc[127] << 8) |
(spd[spd_idx].mod_section.uc[126] << 0);
debug("checksum 0x%x\n", spd_checksum[spd_idx]);
if (!spd_checksum[spd_idx]) {
debug("Bad checksum, ignored.\n");
continue;
}
if (!spd_idx) {
/* first valid SPD */
ret = cal_dimm_params(&spd[0], dimm);
if (ret) {
ERROR("SPD calculation error\n");
return -EINVAL;
}
}
if (spd_idx && spd_checksum[0] !=
spd_checksum[spd_idx]) {
ERROR("Not identical DIMMs.\n");
return -EINVAL;
}
conf->dimm_in_use[j] = 1;
valid_mask |= 1 << addr_idx;
spd_idx = 1;
}
debug("done with controller %d\n", i);
}
switch (num_ctlrs) {
case 1:
if (!(valid_mask & 0x1)) {
ERROR("First slot cannot be empty.\n");
return -EINVAL;
}
break;
case 2:
switch (num_dimm) {
case 1:
if (!valid_mask) {
ERROR("Both slot empty\n");
i2c_bus_release(); // 这个地方
soc_sys_reset();
return -EINVAL;
}
break;
case 2:
if (valid_mask != 0x5 &&
valid_mask != 0xf &&
(valid_mask & 0x7) != 0x4 &&
(valid_mask & 0xd) != 0x1) {
ERROR("Invalid DIMM combination.\n");
return -EINVAL;
}
break;
default:
ERROR("Invalid number of DIMMs.\n");
return -EINVAL;
}
break;
default:
ERROR("Invalid number of controllers.\n");
return -EINVAL;
}
/* now we have valid and identical DIMMs on controllers */
#endif /* CONFIG_DDR_NODIMM */
debug("cal cs\n");
conf->cs_in_use = 0;
for (j = 0; j < DDRC_NUM_DIMM; j++) {
if (!conf->dimm_in_use[j])
continue;
switch (dimm->n_ranks) {
case 4:
ERROR("Quad-rank DIMM not supported\n");
return -EINVAL;
case 2:
conf->cs_on_dimm[j] = 0x3 << (j * CONFIG_CS_PER_SLOT);
conf->cs_in_use |= conf->cs_on_dimm[j];
break;
case 1:
conf->cs_on_dimm[j] = 0x1 << (j * CONFIG_CS_PER_SLOT);
conf->cs_in_use |= conf->cs_on_dimm[j];
break;
default:
ERROR("SPD error with n_ranks\n");
return -EINVAL;
}
debug("cs_in_use = %x\n", conf->cs_in_use);
debug("cs_on_dimm[%d] = %x\n", j, conf->cs_on_dimm[j]);
}
#ifndef CONFIG_DDR_NODIMM
if (priv->dimm.rdimm)
NOTICE("RDIMM %s\n", priv->dimm.mpart);
else
NOTICE("UDIMM %s\n", priv->dimm.mpart);
#else
NOTICE("%s\n", priv->dimm.mpart);
#endif
return valid_mask;
}
// plat/nxp/soc-lx2160/lx2160a_dpn4025/ddr_init.c
void soc_sys_reset(void)
{
*(int *)(NXP_RST_ADDR + RSTCNTL_OFFSET) = SW_RST_REQ_INIT;
asm volatile("dc cvac,%0"
:
:"r"((unsigned long long)(NXP_RST_ADDR + RSTCNTL_OFFSET)) : );
asm volatile("dsb st": : :);
asm volatile("isb": : :);
}
/*
* errata: a-010650
*/
void i2c_bus_release(void)
{
uint reg_a;
int i;
//step 2
ERROR("Step 1\n");
reg_a = in_be32(0x700100134);
ERROR("Step 2\n");
//step 3
out_be32(0x700100134, reg_a | 0x400);
udelay(10);
ERROR("Step 3\n");
//step 4
out_be32(0x2300000, 0x10000000);
udelay(10);
ERROR("Step 4\n");
//step 5
for (i = 0; i < 9; ++i) {
out_be32(0x2300008, 0x10000000);
udelay(10);
out_be32(0x2300008, 0);
udelay(10);
}
ERROR("Step 5\n");
//step 6
out8(0x2000002, 0);
udelay(10);
out8(0x2000002, 0x80);
ERROR("Step 6\n");
//step 7
out32(0x700100134, 0);
ERROR("Step 7\n");
//step 8
out8(0x2000003, in8(0x2000003) & 0xef);
ERROR("Step 8\n");
ERROR("DDR bus 0 released . reseting\n");
}
NOTICE: BL2: v1.5(release):LSDK-20.04-4-gdcfc62e80-dirty
NOTICE: BL2: Built : 21:23:22, Apr 22 2022
NOTICE: time base 7 ms
NOTICE: BL2: v1.5(release):LSDK-20.04-4-gdcfc62e80-dirty
NOTICE: BL2: Built : 21:23:22, Apr 22 2022
NOTICE: time base 7 ms
ERROR: Both slot empty
ERROR: Step 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment