spi: zynqmp_gqspi: fix set_speed bug on multiple runs
[platform/kernel/u-boot.git] / arch / x86 / lib / fsp2 / fsp_support.c
1 // SPDX-License-Identifier: Intel
2 /*
3  * Copyright 2019 Google LLC
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <log.h>
10 #include <spi_flash.h>
11 #include <asm/fsp/fsp_support.h>
12 #include <asm/fsp2/fsp_internal.h>
13
14 /* The amount of the FSP header to probe to obtain what we need */
15 #define PROBE_BUF_SIZE 0x180
16
17 int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
18                    struct fsp_header **fspp)
19 {
20         static efi_guid_t guid = FSP_HEADER_GUID;
21         struct fv_ext_header *exhdr;
22         struct fsp_header *fsp;
23         struct ffs_file_header *file_hdr;
24         struct fv_header *fv;
25         struct raw_section *raw;
26         void *ptr, *base;
27         u8 buf[PROBE_BUF_SIZE];
28         struct udevice *dev;
29         int ret;
30
31         /*
32          * There are quite a very steps to work through all the headers in this
33          * file and the structs have similar names. Turn on debugging if needed
34          * to understand what is going wrong.
35          *
36          * You are in a maze of twisty little headers all alike.
37          */
38         log_debug("offset=%x buf=%x, use_spi_flash=%d\n", (uint)offset,
39                   (uint)buf, use_spi_flash);
40         if (use_spi_flash) {
41                 ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
42                 if (ret)
43                         return log_msg_ret("Cannot find flash device", ret);
44                 ret = spi_flash_read_dm(dev, offset, PROBE_BUF_SIZE, buf);
45                 if (ret)
46                         return log_msg_ret("Cannot read flash", ret);
47         } else {
48                 memcpy(buf, (void *)offset, PROBE_BUF_SIZE);
49         }
50
51         /* Initalise the FSP base */
52         ptr = buf;
53         fv = ptr;
54
55         /* Check the FV signature, _FVH */
56         log_debug("offset=%x sign=%x\n", (uint)offset, (uint)fv->sign);
57         if (fv->sign != EFI_FVH_SIGNATURE)
58                 return log_msg_ret("Base FV signature", -EINVAL);
59
60         /* Go to the end of the FV header and align the address */
61         log_debug("fv->ext_hdr_off = %x\n", fv->ext_hdr_off);
62         ptr += fv->ext_hdr_off;
63         exhdr = ptr;
64         ptr += ALIGN(exhdr->ext_hdr_size, 8);
65         log_debug("ptr=%x\n", ptr - (void *)buf);
66
67         /* Check the FFS GUID */
68         file_hdr = ptr;
69         if (memcmp(&file_hdr->name, &guid, sizeof(guid)))
70                 return log_msg_ret("Base FFS GUID", -ENXIO);
71         /* Add the FFS header size to find the raw section header */
72         ptr = file_hdr + 1;
73
74         raw = ptr;
75         log_debug("raw->type = %x\n", raw->type);
76         if (raw->type != EFI_SECTION_RAW)
77                 return log_msg_ret("Section type not RAW", -ENOEXEC);
78
79         /* Add the raw section header size to find the FSP header */
80         ptr = raw + 1;
81         fsp = ptr;
82
83         /* Check the FSPH header */
84         log_debug("fsp %x, fsp-buf=%x, si=%x\n", (uint)fsp, ptr - (void *)buf,
85                   (void *)&fsp->fsp_silicon_init - (void *)buf);
86         if (fsp->sign != EFI_FSPH_SIGNATURE)
87                 return log_msg_ret("Base FSPH signature", -EACCES);
88
89         base = (void *)fsp->img_base;
90         log_debug("image base %x\n", (uint)base);
91         if (fsp->fsp_mem_init)
92                 log_debug("mem_init offset %x\n", (uint)fsp->fsp_mem_init);
93         else if (fsp->fsp_silicon_init)
94                 log_debug("silicon_init offset %x\n",
95                           (uint)fsp->fsp_silicon_init);
96         if (use_spi_flash) {
97                 ret = spi_flash_read_dm(dev, offset, size, base);
98                 if (ret)
99                         return log_msg_ret("Could not read FPS-M", ret);
100         } else {
101                 memcpy(base, (void *)offset, size);
102         }
103         ptr = base + (ptr - (void *)buf);
104         *fspp = ptr;
105
106         return 0;
107 }
108
109 u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
110 {
111         fsp_notify_f notify;
112         struct fsp_notify_params params;
113         struct fsp_notify_params *params_ptr;
114         u32 status;
115
116         if (!fsp_hdr)
117                 fsp_hdr = gd->arch.fsp_s_hdr;
118
119         if (!fsp_hdr)
120                 return log_msg_ret("no FSP", -ENOENT);
121
122         notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify);
123         params.phase = phase;
124         params_ptr = &params;
125
126         /*
127          * Use ASM code to ensure correct parameter is on the stack for
128          * FspNotify as U-Boot is using different ABI from FSP
129          */
130         asm volatile (
131                 "pushl  %1;"            /* push notify phase */
132                 "call   *%%eax;"        /* call FspNotify */
133                 "addl   $4, %%esp;"     /* clean up the stack */
134                 : "=a"(status) : "m"(params_ptr), "a"(notify), "m"(*params_ptr)
135         );
136
137         return status;
138 }