1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #include <bootblock_common.h> 4 #include <cpu/x86/tsc.h> 5 #include <psp_verstage/psp_transfer.h> 6 #include <symbols.h> 7 #include <timestamp.h> 8 #include <types.h> 9 10 /* 11 * Verstage on PSP uses the weak timestamp_tick_freq_mhz implementation returning 1, so the 12 * unit of the timestamps in the transfer buffer is microseconds. The x86 side uses the TSC 13 * rate as reference for the timestamps, so the values from the PSP transfer buffer need to be 14 * multiplied by the TSC frequency in MHz. 15 */ timestamp_from_usec(uint64_t usec)16static uint64_t timestamp_from_usec(uint64_t usec) 17 { 18 return usec * tsc_freq_mhz(); 19 } 20 boot_with_psp_timestamp(uint64_t base_timestamp)21void boot_with_psp_timestamp(uint64_t base_timestamp) 22 { 23 const struct transfer_info_struct *info = (const struct transfer_info_struct *) 24 (void *)(uintptr_t)_transfer_buffer; 25 26 if (!transfer_buffer_valid(info) || info->timestamp == 0) 27 return; 28 29 replay_transfer_buffer_cbmemc(); 30 31 /* 32 * info->timestamp is PSP's timestamp (in microseconds) 33 * when x86 processor is released. 34 */ 35 uint64_t psp_last_ts_usec = info->timestamp; 36 37 int i; 38 struct timestamp_table *psp_ts_table = 39 (struct timestamp_table *)(void *) 40 ((uintptr_t)_transfer_buffer + info->timestamp_offset); 41 /* new base_timestamp will be offset for all PSP timestamps. */ 42 base_timestamp -= timestamp_from_usec(psp_last_ts_usec); 43 44 for (i = 0; i < psp_ts_table->num_entries; i++) { 45 struct timestamp_entry *tse = &psp_ts_table->entries[i]; 46 /* 47 * We ignore the time between x86 processor release and bootblock. 48 * Since timestamp_add subtracts base_time, we first add old base_time 49 * to make it absolute then add base_timestamp again since 50 * it'll be a new base_time. 51 * 52 * Verstage on PSP uses a 1 microsecond timestamp granularity while the x86 53 * part of coreboot uses the TSC tick time as granularity, so this needs to be 54 * converted. 55 */ 56 tse->entry_stamp = timestamp_from_usec(psp_ts_table->base_time + 57 tse->entry_stamp) + base_timestamp; 58 } 59 60 bootblock_main_with_timestamp(base_timestamp, psp_ts_table->entries, 61 psp_ts_table->num_entries); 62 } 63