| 
 | 1 | +// SPDX-License-Identifier: GPL-2.0  | 
 | 2 | +/*  | 
 | 3 | + * Copyright (C) 2022 Intel Corporation <www.intel.com>  | 
 | 4 | + *  | 
 | 5 | + */  | 
 | 6 | +#include <common.h>  | 
 | 7 | +#include <linux/errno.h>  | 
 | 8 | +#include <spi.h>  | 
 | 9 | +#include <spi_flash.h>  | 
 | 10 | +#include <asm/arch/mailbox_s10.h>  | 
 | 11 | +#include <asm/arch/rsu.h>  | 
 | 12 | +#include <asm/arch/rsu_s10.h>  | 
 | 13 | +#include <asm/arch/rsu_spl.h>  | 
 | 14 | + | 
 | 15 | +#define SSBL_PART_PREFIX"SSBL."  | 
 | 16 | +#define RSU_ADDR_MASK0xFFFFFFFF  | 
 | 17 | +#define RSU_ADDR_SHIFT32  | 
 | 18 | + | 
 | 19 | +static int get_ssbl_slot(struct socfpga_rsu_s10_spt_slot *rsu_ssbl_slot)  | 
 | 20 | +{  | 
 | 21 | +struct socfpga_rsu_s10_spt rsu_spt = {0};  | 
 | 22 | +u32 rsu_spt0_offset = 0, rsu_spt1_offset = 0;  | 
 | 23 | +u32 spt_offset[4];  | 
 | 24 | +struct rsu_status_info rsu_status;  | 
 | 25 | +int crt_spt_index = -EINVAL;  | 
 | 26 | +char *result;  | 
 | 27 | +struct spi_flash *flash;  | 
 | 28 | +int i;  | 
 | 29 | + | 
 | 30 | +rsu_ssbl_slot->offset[0] = -EINVAL;  | 
 | 31 | + | 
 | 32 | +/* get rsu status */  | 
 | 33 | +if (mbox_rsu_status((u32 *)&rsu_status, sizeof(rsu_status) / 4)) {  | 
 | 34 | +puts("RSU: Error - mbox_rsu_status failed!\n");  | 
 | 35 | +return -EOPNOTSUPP;  | 
 | 36 | +}  | 
 | 37 | + | 
 | 38 | +/* get spt offsets */  | 
 | 39 | +if (mbox_rsu_get_spt_offset(spt_offset, 4)) {  | 
 | 40 | +puts("RSU: Error - mbox_rsu_get_spt_offset failed!\n");  | 
 | 41 | +return -EINVAL;  | 
 | 42 | +}  | 
 | 43 | + | 
 | 44 | +rsu_spt0_offset = spt_offset[SPT0_INDEX];  | 
 | 45 | +rsu_spt1_offset = spt_offset[SPT1_INDEX];  | 
 | 46 | + | 
 | 47 | +/* initialize flash */  | 
 | 48 | +flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,  | 
 | 49 | +CONFIG_SF_DEFAULT_CS,  | 
 | 50 | +CONFIG_SF_DEFAULT_SPEED,  | 
 | 51 | +CONFIG_SF_DEFAULT_MODE);  | 
 | 52 | +if (!flash) {  | 
 | 53 | +puts("RSU: Error - spi_flash_probe failed!\n");  | 
 | 54 | +return -EINVAL;  | 
 | 55 | +}  | 
 | 56 | + | 
 | 57 | +/* read spt0 */  | 
 | 58 | +if (spi_flash_read(flash, rsu_spt0_offset, sizeof(rsu_spt), &rsu_spt)) {  | 
 | 59 | +puts("RSU: Error - spi_flash_read failed!\n");  | 
 | 60 | +return -EINVAL;  | 
 | 61 | +}  | 
 | 62 | + | 
 | 63 | +/* if spt0 does not have the correct magic number */  | 
 | 64 | +if (rsu_spt.magic_number != RSU_S10_SPT_MAGIC_NUMBER) {  | 
 | 65 | +/* read spt1 */  | 
 | 66 | +if (spi_flash_read(flash, rsu_spt1_offset, sizeof(rsu_spt), &rsu_spt)) {  | 
 | 67 | +printf("RSU: Error - spi_flash_read failed!\n");  | 
 | 68 | +return -EINVAL;  | 
 | 69 | +}  | 
 | 70 | + | 
 | 71 | +/* bail out if spt1 does not have the correct magic number */  | 
 | 72 | +if (rsu_spt.magic_number != RSU_S10_SPT_MAGIC_NUMBER) {  | 
 | 73 | +printf("RSU: Error: spt table magic number not match 0x%08x!\n",  | 
 | 74 | + rsu_spt.magic_number);  | 
 | 75 | +return -EINVAL;  | 
 | 76 | +}  | 
 | 77 | +}  | 
 | 78 | + | 
 | 79 | +/* display status */  | 
 | 80 | +debug("RSU current image: 0x%08x\n", (u32)rsu_status.current_image);  | 
 | 81 | +debug("RSU state: 0x%08x\n", rsu_status.state);  | 
 | 82 | +debug("RSU error location: 0x%08x\n", rsu_status.error_location);  | 
 | 83 | +debug("RSU error details: 0x%08x\n", rsu_status.error_details);  | 
 | 84 | + | 
 | 85 | +/* display partitions */  | 
 | 86 | +for (i = 0; i < rsu_spt.entries; i++) {  | 
 | 87 | +debug("RSU: Partition '%s' start=0x%08x length=0x%08x\n",  | 
 | 88 | + rsu_spt.spt_slot[i].name, rsu_spt.spt_slot[i].offset[0],  | 
 | 89 | + rsu_spt.spt_slot[i].length);  | 
 | 90 | +}  | 
 | 91 | + | 
 | 92 | +/* locate the SPT entry for currently loaded image */  | 
 | 93 | +for (i = 0; i < rsu_spt.entries; i++) {  | 
 | 94 | +if (((rsu_status.current_image & RSU_ADDR_MASK) ==  | 
 | 95 | +rsu_spt.spt_slot[i].offset[0]) &&  | 
 | 96 | + ((rsu_status.current_image >> RSU_ADDR_SHIFT) ==  | 
 | 97 | +rsu_spt.spt_slot[i].offset[1])) {  | 
 | 98 | +crt_spt_index = i;  | 
 | 99 | +break;  | 
 | 100 | +}  | 
 | 101 | +}  | 
 | 102 | + | 
 | 103 | +if (crt_spt_index == -EINVAL) {  | 
 | 104 | +puts("RSU: Error - could not locate partition in the SPT table!\n");  | 
 | 105 | +return -EINVAL;  | 
 | 106 | +}  | 
 | 107 | + | 
 | 108 | +/* locate the u-boot proper(SSBL) partition and return its address */  | 
 | 109 | +for (i = 0; i < rsu_spt.entries; i++) {  | 
 | 110 | +/* get the substring ptr to the first occurrence of SSBL. prefix */  | 
 | 111 | +result = strstr(rsu_spt.spt_slot[i].name, SSBL_PART_PREFIX);  | 
 | 112 | + | 
 | 113 | +/* skip if not found the SSBL prefix */  | 
 | 114 | +if (!result)  | 
 | 115 | +continue;  | 
 | 116 | + | 
 | 117 | +/* check if the prefix is located at the first */  | 
 | 118 | +if (result == rsu_spt.spt_slot[i].name) {  | 
 | 119 | +/* move to the substring after SSBL. prefix */  | 
 | 120 | +result += strlen(SSBL_PART_PREFIX);  | 
 | 121 | + | 
 | 122 | +/* compare SPL's spt name after the prefix */  | 
 | 123 | +if (!strncmp(result, rsu_spt.spt_slot[crt_spt_index].name,  | 
 | 124 | + MAX_PART_NAME_LENGTH - strlen(SSBL_PART_PREFIX))) {  | 
 | 125 | +printf("RSU: found SSBL partition %s at address 0x%08x.\n",  | 
 | 126 | + result, (int)rsu_spt.spt_slot[i].offset[0]);  | 
 | 127 | +memcpy(rsu_ssbl_slot, &rsu_spt.spt_slot[i],  | 
 | 128 | + sizeof(struct socfpga_rsu_s10_spt_slot));  | 
 | 129 | + | 
 | 130 | +return 0;  | 
 | 131 | +}  | 
 | 132 | +}  | 
 | 133 | +}  | 
 | 134 | + | 
 | 135 | +/* fail to find u-boot proper(SSBL) */  | 
 | 136 | +printf("RSU: Error - could not find u-boot proper partition SSBL.%s!\n",  | 
 | 137 | + rsu_spt.spt_slot[crt_spt_index].name);  | 
 | 138 | + | 
 | 139 | +return -EINVAL;  | 
 | 140 | +}  | 
 | 141 | + | 
 | 142 | +u32 rsu_spl_ssbl_address(void)  | 
 | 143 | +{  | 
 | 144 | +int ret;  | 
 | 145 | +struct socfpga_rsu_s10_spt_slot rsu_ssbl_slot = {0};  | 
 | 146 | + | 
 | 147 | +ret = get_ssbl_slot(&rsu_ssbl_slot);  | 
 | 148 | +if (ret) {  | 
 | 149 | +if (ret == -EOPNOTSUPP) {  | 
 | 150 | +puts("RSU: Error - mbox_rsu_status failed! Check for RSU image.\n");  | 
 | 151 | +return CONFIG_SYS_SPI_U_BOOT_OFFS;  | 
 | 152 | +}  | 
 | 153 | + | 
 | 154 | +/* should throw error if cannot find u-boot proper(SSBL) address */  | 
 | 155 | +panic("ERROR: could not find u-boot proper(SSBL) address!");  | 
 | 156 | +}  | 
 | 157 | + | 
 | 158 | +printf("RSU: Success found SSBL at offset: %08x.\n", rsu_ssbl_slot.offset[0]);  | 
 | 159 | +return rsu_ssbl_slot.offset[0];  | 
 | 160 | +}  | 
 | 161 | + | 
 | 162 | +u32 rsu_spl_ssbl_size(void)  | 
 | 163 | +{  | 
 | 164 | +struct socfpga_rsu_s10_spt_slot rsu_ssbl_slot = {0};  | 
 | 165 | + | 
 | 166 | +/* check for valid u-boot proper(SSBL) address for the size */  | 
 | 167 | +if (get_ssbl_slot(&rsu_ssbl_slot) == -EOPNOTSUPP) {  | 
 | 168 | +printf("ERROR: Invalid address, could not retrieve SSBL size!");  | 
 | 169 | +return 0;  | 
 | 170 | +}  | 
 | 171 | + | 
 | 172 | +if (!rsu_ssbl_slot.length) {  | 
 | 173 | +/* throw error if cannot find u-boot proper(SSBL) size */  | 
 | 174 | +panic("ERROR: could not retrieve u-boot proper(SSBL) size!");  | 
 | 175 | +}  | 
 | 176 | + | 
 | 177 | +printf("RSU: Success found SSBL with length: %08x.\n", rsu_ssbl_slot.length);  | 
 | 178 | +return rsu_ssbl_slot.length;  | 
 | 179 | +}  | 
 | 180 | + | 
 | 181 | +unsigned int spl_spi_get_uboot_offs(struct spi_flash *flash)  | 
 | 182 | +{  | 
 | 183 | +return rsu_spl_ssbl_address();  | 
 | 184 | +}  | 
0 commit comments