1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * Copyright (C) 2014 Google, Inc 3*4882a593Smuzhiyun * Copyright (C) 2015 Bin Meng <bmeng.cn@gmail.com> 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+ 6*4882a593Smuzhiyun */ 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun #ifndef _ASM_MRCCACHE_H 9*4882a593Smuzhiyun #define _ASM_MRCCACHE_H 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun #define MRC_DATA_ALIGN 0x1000 12*4882a593Smuzhiyun #define MRC_DATA_SIGNATURE (('M' << 0) | ('R' << 8) | \ 13*4882a593Smuzhiyun ('C' << 16) | ('D'<<24)) 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun #define MRC_DATA_HEADER_SIZE 32 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun struct __packed mrc_data_container { 18*4882a593Smuzhiyun u32 signature; /* "MRCD" */ 19*4882a593Smuzhiyun u32 data_size; /* Size of the 'data' field */ 20*4882a593Smuzhiyun u32 checksum; /* IP style checksum */ 21*4882a593Smuzhiyun u32 reserved; /* For header alignment */ 22*4882a593Smuzhiyun u8 data[0]; /* Variable size, platform/run time dependent */ 23*4882a593Smuzhiyun }; 24*4882a593Smuzhiyun 25*4882a593Smuzhiyun struct mrc_region { 26*4882a593Smuzhiyun u32 base; 27*4882a593Smuzhiyun u32 offset; 28*4882a593Smuzhiyun u32 length; 29*4882a593Smuzhiyun }; 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun struct udevice; 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun /** 34*4882a593Smuzhiyun * mrccache_find_current() - find the latest MRC cache record 35*4882a593Smuzhiyun * 36*4882a593Smuzhiyun * This searches the MRC cache region looking for the latest record to use 37*4882a593Smuzhiyun * for setting up SDRAM 38*4882a593Smuzhiyun * 39*4882a593Smuzhiyun * @entry: Position and size of MRC cache in SPI flash 40*4882a593Smuzhiyun * @return pointer to latest record, or NULL if none 41*4882a593Smuzhiyun */ 42*4882a593Smuzhiyun struct mrc_data_container *mrccache_find_current(struct mrc_region *entry); 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun /** 45*4882a593Smuzhiyun * mrccache_update() - update the MRC cache with a new record 46*4882a593Smuzhiyun * 47*4882a593Smuzhiyun * This writes a new record to the end of the MRC cache region. If the new 48*4882a593Smuzhiyun * record is the same as the latest record then the write is skipped 49*4882a593Smuzhiyun * 50*4882a593Smuzhiyun * @sf: SPI flash to write to 51*4882a593Smuzhiyun * @entry: Position and size of MRC cache in SPI flash 52*4882a593Smuzhiyun * @cur: Record to write 53*4882a593Smuzhiyun * @return 0 if updated, -EEXIST if the record is the same as the latest 54*4882a593Smuzhiyun * record, -EINVAL if the record is not valid, other error if SPI write failed 55*4882a593Smuzhiyun */ 56*4882a593Smuzhiyun int mrccache_update(struct udevice *sf, struct mrc_region *entry, 57*4882a593Smuzhiyun struct mrc_data_container *cur); 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun /** 60*4882a593Smuzhiyun * mrccache_reserve() - reserve MRC data on the stack 61*4882a593Smuzhiyun * 62*4882a593Smuzhiyun * This copies MRC data pointed by gd->arch.mrc_output to a new place on the 63*4882a593Smuzhiyun * stack with length gd->arch.mrc_output_len, and updates gd->arch.mrc_output 64*4882a593Smuzhiyun * to point to the new place once the migration is done. 65*4882a593Smuzhiyun * 66*4882a593Smuzhiyun * This routine should be called by reserve_arch() before U-Boot is relocated 67*4882a593Smuzhiyun * when MRC cache is enabled. 68*4882a593Smuzhiyun * 69*4882a593Smuzhiyun * @return 0 always 70*4882a593Smuzhiyun */ 71*4882a593Smuzhiyun int mrccache_reserve(void); 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun /** 74*4882a593Smuzhiyun * mrccache_get_region() - get MRC region on the SPI flash 75*4882a593Smuzhiyun * 76*4882a593Smuzhiyun * This gets MRC region whose offset and size are described in the device tree 77*4882a593Smuzhiyun * as a subnode to the SPI flash. If a non-NULL device pointer is supplied, 78*4882a593Smuzhiyun * this also probes the SPI flash device and returns its device pointer for 79*4882a593Smuzhiyun * the caller to use later. 80*4882a593Smuzhiyun * 81*4882a593Smuzhiyun * Be careful when calling this routine with a non-NULL device pointer: 82*4882a593Smuzhiyun * - driver model initialization must be complete 83*4882a593Smuzhiyun * - calling in the pre-relocation phase may bring some side effects during 84*4882a593Smuzhiyun * the SPI flash device probe (eg: for SPI controllers on a PCI bus, it 85*4882a593Smuzhiyun * triggers PCI bus enumeration during which insufficient memory issue 86*4882a593Smuzhiyun * might be exposed and it causes subsequent SPI flash probe fails). 87*4882a593Smuzhiyun * 88*4882a593Smuzhiyun * @devp: Returns pointer to the SPI flash device 89*4882a593Smuzhiyun * @entry: Position and size of MRC cache in SPI flash 90*4882a593Smuzhiyun * @return 0 if success, -ENOENT if SPI flash node does not exist in the 91*4882a593Smuzhiyun * device tree, -EPERM if MRC region subnode does not exist in the device 92*4882a593Smuzhiyun * tree, -EINVAL if MRC region properties format is incorrect, other error 93*4882a593Smuzhiyun * if SPI flash probe failed. 94*4882a593Smuzhiyun */ 95*4882a593Smuzhiyun int mrccache_get_region(struct udevice **devp, struct mrc_region *entry); 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun /** 98*4882a593Smuzhiyun * mrccache_save() - save MRC data to the SPI flash 99*4882a593Smuzhiyun * 100*4882a593Smuzhiyun * This saves MRC data stored previously by gd->arch.mrc_output to a proper 101*4882a593Smuzhiyun * place within the MRC region on the SPI flash. 102*4882a593Smuzhiyun * 103*4882a593Smuzhiyun * @return 0 if saved to SPI flash successfully, other error if failed 104*4882a593Smuzhiyun */ 105*4882a593Smuzhiyun int mrccache_save(void); 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun #endif /* _ASM_MRCCACHE_H */ 108