[PATCH v2 1/5] imx9: Add support for saving DDR training data to NVM
Marek Vasut
marex at nabladev.com
Tue Mar 17 13:45:58 CET 2026
On 3/17/26 1:36 PM, Simona Toaca wrote:
Hi,
>>> @@ -100,6 +100,56 @@ struct dram_timing_info {
>>> extern struct dram_timing_info dram_timing;
>>> +#if IS_ENABLED(CONFIG_IMX95) || IS_ENABLED(CONFIG_IMX94) /* CONFIG_IMX95 || CONFIG_IMX94 */
>>> +#if IS_ENABLED(CONFIG_IMX_SNPS_DDR_PHY_QB_GEN)
>>
>> These are only macros and structure definitions, do they need to be
>> conditionally compiled ?
>>
>
> I agree that this might be redundant, especially since IMX_SNPS_DDR_PHY_QB_GEN
> depends on IMX94 || IMX95. I would leave the IMX_SNPS_DDR_PHY_QB_GEN
> ifdef so that it is clear in which context this structure is used,
> if it is also ok with you. If not, I will remove it.
Remove it, it is superfluous. If you need to denote context, add code
comment.
>>> +/* Quick Boot related */
>>> +#define DDRPHY_QB_CSR_SIZE 5168
>>> +#define DDRPHY_QB_ACSM_SIZE 4 * 1024
>>
>> (4 * 1024) to avoid side effects
>>
>>> +#define DDRPHY_QB_MSB_SIZE 0x200
>>> +#define DDRPHY_QB_PSTATES 0
>>> +#define DDRPHY_QB_PST_SIZE DDRPHY_QB_PSTATES * 4 * 1024
>>
>> Add ( )
>
> Should I add () to all the numbers so it is consistent, or
> just to the macros that contain computations?
The ones which contain more than plain integer and can have side effect
if used in the wrong place.
> [ ... ]
>
>>> +static int do_qb_mmc(int dev, bool save, bool is_bootdev)
>>> +{
>>> + struct mmc *mmc;
>>> + int ret = 0, mmc_dev;
>>> + bool has_hw_part;
>>> + u8 orig_part, part;
>>> + u32 offset;
>>> + void *buf;
>>> +
>>> + mmc_dev = mmc_get_device_index(dev);
>>> + if (mmc_dev < 0)
>>> + return mmc_dev;
>>> +
>>> + ret = mmc_find_device(&mmc, mmc_dev);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + if (!mmc->has_init)
>>> + ret = mmc_init(mmc);
>>
>> mmc_init() already handles the mmc->has_init conditional, drop it.
>>
>>> + if (ret)
>>> + return ret;
>>> +
>>> + has_hw_part = !IS_SD(mmc) && mmc->part_config != MMCPART_NOAVAILABLE;
>>> +
>>> + if (has_hw_part) {
>>> + orig_part = mmc_get_blk_desc(mmc)->hwpart;
>>> + part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
>>> +
>>> + /* Select the partition */
>>> + ret = mmc_switch_part(mmc, part);
>>> + if (ret)
>>> + return ret;
>>> + }
>>> +
>>> + ret = get_qbdata_offset(mmc, MMC_DEV, &offset, is_bootdev);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + if (save) {
>>> + /* QB data is stored in DDR -> can use it as buf */
>>> + buf = (void *)CONFIG_SAVED_QB_STATE_BASE;
>>> + ret = blk_dwrite(mmc_get_blk_desc(mmc),
>>> + offset / mmc->write_bl_len,
>>> + QB_STATE_LOAD_SIZE / mmc->write_bl_len,
>>> + (const void *)buf);
>>> + } else {
>>> + /* erase */
>>> + ret = blk_derase(mmc_get_blk_desc(mmc),
>>> + offset / mmc->write_bl_len,
>>> + QB_STATE_LOAD_SIZE / mmc->write_bl_len);
>>> + }
>>> +
>>> + ret = (ret > 0) ? 0 : -1;
>>
>> Use CMD_RET_SUCCESS and co.
>>
>
> I am using these enum values in cmd_qb. However, here I would have
> do this 'if' at every return statement, since the other methods
> return 0 or an errno code. Should I still change this?
If this function does not implement a command, then it should be renamed
to something less confusing.
>>> + /* Return to original partition */
>>> + if (has_hw_part)
>>> + ret |= mmc_switch_part(mmc, orig_part);
>
> [ ... ]
>
>>> diff --git a/arch/arm/mach-imx/imx9/scmi/soc.c b/arch/arm/mach-imx/imx9/scmi/soc.c
>>> index 17269ddd2fc..eb9bfe19a69 100644
>>> --- a/arch/arm/mach-imx/imx9/scmi/soc.c
>>> +++ b/arch/arm/mach-imx/imx9/scmi/soc.c
>>> @@ -281,6 +281,15 @@ static struct mm_region imx9_mem_map[] = {
>>> PTE_BLOCK_NON_SHARE |
>>> PTE_BLOCK_PXN | PTE_BLOCK_UXN
>>> }, {
>>> +#if IS_ENABLED(CONFIG_IMX_SNPS_DDR_PHY_QB_GEN)
>>> + /* QB data */
>>
>> Is the ifdeffery necessary ?
>>
>> Where are the QB data located in this case, DRAM or SRAM ?
>>
>
> It is necessary because CONFIG_SAVED_QB_STATE_BASE is only
> defined when CONFIG_IMX_SNPS_DDR_PHY_QB_GEN is enabled. So it
> throws a compilation error without this. And this is DRAM.
Are there going to be any users that will actually want ot disable this
functionality ? Why would they do that ?
>>> + .virt = CONFIG_SAVED_QB_STATE_BASE,
>>> + .phys = CONFIG_SAVED_QB_STATE_BASE,
>>> + .size = 0x200000UL, /* 2M */
>>> + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
>>> + PTE_BLOCK_OUTER_SHARE
>>> + }, {
[...]
More information about the U-Boot
mailing list