|
1 | 1 | # Firmware list
|
2 | 2 | - `spm_firmware.bin`
|
3 | 3 | - `sspm.bin`
|
| 4 | +- `dram.elf` |
4 | 5 |
|
5 | 6 | --------------------------------------------------------------------------------
|
6 | 7 | # SPM introduction
|
@@ -41,3 +42,101 @@ No return value.
|
41 | 42 | `$ strings sspm.bin | grep "SSPM firmware"`
|
42 | 43 |
|
43 | 44 | --------------------------------------------------------------------------------
|
| 45 | +# `dram.elf` introduction |
| 46 | +`dram.elf` is an ELF format file, which performs DRAM full calibration, DRAM |
| 47 | +fast calibration and returns the trained calibration parameters to the caller. |
| 48 | +The caller may store the parameters on NOR/NAND or eMMC for faster subsequent |
| 49 | +bootups. |
| 50 | + |
| 51 | +## Who uses it |
| 52 | +Coreboot loads `dram.elf` during the first bootup if no valid DRAM parameters |
| 53 | +are found on NOR/NAND or eMMC. |
| 54 | + |
| 55 | +## How to load `dram.elf` |
| 56 | +Coreboot locates `dram.elf` file, locates the entry point `_start`, |
| 57 | +passes a `dramc_param` struct argument `dparam` to it, and calls |
| 58 | +`_start(&dparam)` to execute `dram.elf`. |
| 59 | + |
| 60 | +## Parameters |
| 61 | +``` |
| 62 | +struct dramc_param { |
| 63 | + struct dramc_param_header header; // see below |
| 64 | + void (*do_putc)(unsigned char c); |
| 65 | + struct dramc_data dramc_datas; // see below |
| 66 | +}; |
| 67 | +``` |
| 68 | + |
| 69 | +Below shows the internal structure of `dramc_param`: |
| 70 | +``` |
| 71 | +struct dramc_param_header { |
| 72 | + u16 version; /* DRAMC_PARAM_HEADER_VERSION, set in coreboot */ |
| 73 | + u16 size; /* size of whole dramc_param, set in coreboot */ |
| 74 | + u16 status; /* DRAMC_PARAM_STATUS_CODES, set in dram blob */ |
| 75 | + u16 flags; /* DRAMC_PARAM_FLAG, set in dram blob */ |
| 76 | + u16 config; /* DRAMC_PARAM_CONFIG, set in coreboot */ |
| 77 | +}; |
| 78 | +
|
| 79 | +struct sdram_info { |
| 80 | + u32 ddr_type; /* SDRAM_DDR_TYPE */ |
| 81 | + u32 ddr_geometry; /* SDRAM_DDR_GEOMETRY_TYPE */ |
| 82 | +}; |
| 83 | +
|
| 84 | +struct sdram_params { |
| 85 | + u32 rank_num; |
| 86 | + u16 num_dlycell_perT; |
| 87 | + u16 delay_cell_timex100; |
| 88 | +
|
| 89 | + /* duty */ |
| 90 | + s8 duty_clk_delay[CHANNEL_MAX][RANK_MAX]; |
| 91 | + s8 duty_dqs_delay[CHANNEL_MAX][DQS_NUMBER_LP4]; |
| 92 | + s8 duty_wck_delay[CHANNEL_MAX][DQS_NUMBER_LP4]; |
| 93 | + ....... |
| 94 | + ....... |
| 95 | +}; |
| 96 | +
|
| 97 | +struct emi_mdl { |
| 98 | + u32 cona_val; |
| 99 | + u32 conh_val; |
| 100 | + u32 conf_val; |
| 101 | + u32 chn_cona_val; |
| 102 | +}; |
| 103 | +
|
| 104 | +struct ddr_mrr_info { |
| 105 | + u16 mr5_vendor_id; |
| 106 | + u16 mr6_revision_id; |
| 107 | + u16 mr7_revision_id; |
| 108 | + u64 mr8_density[RANK_MAX]; |
| 109 | + u32 rank_nums; |
| 110 | + u8 die_num[RANK_MAX]; |
| 111 | +}; |
| 112 | +
|
| 113 | +struct ddr_base_info { |
| 114 | + u32 config_dvfs; /* SDRAM_DVFS_FLAG */ |
| 115 | + struct sdram_info sdram; |
| 116 | + u32 voltage_type; /* SDRAM_VOLTAGE_TYPE */ |
| 117 | + u32 support_ranks; |
| 118 | + u64 rank_size[RANK_MAX]; |
| 119 | + struct emi_mdl emi_config; |
| 120 | + DRAM_CBT_MODE_T cbt_mode[RANK_MAX]; |
| 121 | + struct ddr_mrr_info mrr_info; |
| 122 | + u32 data_rate; |
| 123 | +}; |
| 124 | +
|
| 125 | +struct dramc_data { |
| 126 | + struct ddr_base_info ddr_info; |
| 127 | + struct sdram_params freq_params[DRAM_DFS_SHU_MAX]; |
| 128 | +}; |
| 129 | +``` |
| 130 | + |
| 131 | +## The output of `dram.elf` |
| 132 | +`dram.elf` configures suitable dramc settings and returns the DRAM parameters. |
| 133 | +Then, Coreboot saves the parameters on the specified firmware flash section: |
| 134 | +`"RW_MRC_CACHE"`. |
| 135 | + |
| 136 | +## Return values |
| 137 | +0 on success; < 0 on failure. |
| 138 | + |
| 139 | +## Version |
| 140 | +`$ strings dram.elf | grep "firmware version"` |
| 141 | + |
| 142 | +-------------------------------------------------------------------------------- |
0 commit comments