static int stm32mp1_ddr_setup(void) { struct ddr_info *priv = &ddr_priv_data; int ret; struct stm32mp1_ddr_config config; int node, len; uint32_t uret, idx; void *fdt; #define PARAM(x, y) \ { \ .name = x, \ .offset = offsetof(struct stm32mp1_ddr_config, y), \ .size = sizeof(config.y) / sizeof(uint32_t) \ } #define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x) #define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x) const struct { const char *name; /* Name in DT */ const uint32_t offset; /* Offset in config struct */ const uint32_t size; /* Size of parameters */ } param[] = { CTL_PARAM(reg), CTL_PARAM(timing), CTL_PARAM(map), CTL_PARAM(perf), PHY_PARAM(reg), PHY_PARAM(timing), PHY_PARAM(cal) }; if (fdt_get_address(&fdt) == 0) { return -ENOENT; } node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); if (node < 0) { ERROR("%s: Cannot read DDR node in DT\n", __func__); return -EINVAL; } config.info.speed = fdt_read_uint32_default(node, "st,mem-speed", 0); if (!config.info.speed) { VERBOSE("%s: no st,mem-speed\n", __func__); return -EINVAL; } config.info.size = fdt_read_uint32_default(node, "st,mem-size", 0); if (!config.info.size) { VERBOSE("%s: no st,mem-size\n", __func__); return -EINVAL; } config.info.name = fdt_getprop(fdt, node, "st,mem-name", &len); if (config.info.name == NULL) { VERBOSE("%s: no st,mem-name\n", __func__); return -EINVAL; } INFO("RAM: %s\n", config.info.name); for (idx = 0; idx < ARRAY_SIZE(param); idx++) { ret = fdt_read_uint32_array(node, param[idx].name, (void *)((uintptr_t)&config + param[idx].offset), param[idx].size); VERBOSE("%s: %s[0x%x] = %d\n", __func__, param[idx].name, param[idx].size, ret); if (ret != 0) { ERROR("%s: Cannot read %s\n", __func__, param[idx].name); return -EINVAL; } } /* Disable axidcg clock gating during init */ mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); stm32mp1_ddr_init(priv, &config); /* Enable axidcg clock gating */ mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); priv->info.size = config.info.size; VERBOSE("%s : ram size(%x, %x)\n", __func__, (uint32_t)priv->info.base, (uint32_t)priv->info.size); write_sctlr(read_sctlr() & ~SCTLR_C_BIT); dcsw_op_all(DC_OP_CISW); uret = ddr_test_data_bus(); if (uret != 0U) { ERROR("DDR data bus test: can't access memory @ 0x%x\n", uret); panic(); } uret = ddr_test_addr_bus(); if (uret != 0U) { ERROR("DDR addr bus test: can't access memory @ 0x%x\n", uret); panic(); } uret = ddr_check_size(); if (uret < config.info.size) { ERROR("DDR size: 0x%x does not match DT config: 0x%x\n", uret, config.info.size); panic(); } write_sctlr(read_sctlr() | SCTLR_C_BIT); return 0; }
static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev) { struct ddr_info *priv = dev_get_priv(dev); int ret, idx; struct clk axidcg; struct stm32mp1_ddr_config config; #define PARAM(x, y) \ { x,\ offsetof(struct stm32mp1_ddr_config, y),\ sizeof(config.y) / sizeof(u32)} #define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x) #define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x) const struct { const char *name; /* name in DT */ const u32 offset; /* offset in config struct */ const u32 size; /* size of parameters */ } param[] = { CTL_PARAM(reg), CTL_PARAM(timing), CTL_PARAM(map), CTL_PARAM(perf), PHY_PARAM(reg), PHY_PARAM(timing), PHY_PARAM(cal) }; config.info.speed = dev_read_u32_default(dev, "st,mem-speed", 0); config.info.size = dev_read_u32_default(dev, "st,mem-size", 0); config.info.name = dev_read_string(dev, "st,mem-name"); if (!config.info.name) { debug("%s: no st,mem-name\n", __func__); return -EINVAL; } printf("RAM: %s\n", config.info.name); for (idx = 0; idx < ARRAY_SIZE(param); idx++) { ret = dev_read_u32_array(dev, param[idx].name, (void *)((u32)&config + param[idx].offset), param[idx].size); debug("%s: %s[0x%x] = %d\n", __func__, param[idx].name, param[idx].size, ret); if (ret) { pr_err("%s: Cannot read %s\n", __func__, param[idx].name); return -EINVAL; } } ret = clk_get_by_name(dev, "axidcg", &axidcg); if (ret) { debug("%s: Cannot found axidcg\n", __func__); return -EINVAL; } clk_disable(&axidcg); /* disable clock gating during init */ stm32mp1_ddr_init(priv, &config); clk_enable(&axidcg); /* enable clock gating */ /* check size */ debug("%s : get_ram_size(%x, %x)\n", __func__, (u32)priv->info.base, (u32)STM32_DDR_SIZE); priv->info.size = get_ram_size((long *)priv->info.base, STM32_DDR_SIZE); debug("%s : %x\n", __func__, (u32)priv->info.size); /* check memory access for all memory */ if (config.info.size != priv->info.size) { printf("DDR invalid size : 0x%x, expected 0x%x\n", priv->info.size, config.info.size); return -EINVAL; } return 0; }