blob: 1eed84e9b24d01ec447a5354ac007664cecaabbf [file] [log] [blame]
Angel Pons230e4f9d2020-04-05 15:47:14 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Lee Leahy16bc9ba2017-04-01 20:33:58 -07002
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02003#include <device/pci_ops.h>
Lee Leahy16bc9ba2017-04-01 20:33:58 -07004#include <assert.h>
5#include <cbmem.h>
Lee Leahy48dbc662017-05-08 16:56:03 -07006#include <commonlib/sdhci.h>
7#include <commonlib/storage.h>
Lee Leahy16bc9ba2017-04-01 20:33:58 -07008#include <console/console.h>
Lee Leahy16bc9ba2017-04-01 20:33:58 -07009#include <lib.h>
10#include <soc/iomap.h>
11#include <soc/pci_devs.h>
12#include <soc/storage_test.h>
Elyes HAOUASadd76f92019-03-21 09:55:49 +010013#include <timer.h>
Lee Leahy16bc9ba2017-04-01 20:33:58 -070014#include <string.h>
15
Julius Wernercd49cce2019-03-05 16:53:33 -080016#if CONFIG(STORAGE_LOG)
Arthur Heymans84e22e32019-05-25 09:57:27 +020017struct log_entry log[LOG_ENTRIES];
18uint8_t log_index;
19int log_full;
20long log_start_time;
Lee Leahy16bc9ba2017-04-01 20:33:58 -070021#endif
Kyösti Mälkkif30123b2019-02-01 06:44:07 +020022
Arthur Heymans84e22e32019-05-25 09:57:27 +020023static uint8_t drivers_storage[256];
Lee Leahy16bc9ba2017-04-01 20:33:58 -070024
25#define STORAGE_DEBUG BIOS_DEBUG
Julius Wernercd49cce2019-03-05 16:53:33 -080026#define LOG_DEBUG (CONFIG(STORAGE_LOG) ? STORAGE_DEBUG : BIOS_NEVER)
Lee Leahy16bc9ba2017-04-01 20:33:58 -070027
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010028#ifdef __SIMPLE_DEVICE__
29uint32_t storage_test_init(pci_devfn_t dev, uint32_t *previous_bar,
Lee Leahy16bc9ba2017-04-01 20:33:58 -070030 uint16_t *previous_command)
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010031#else
32uint32_t storage_test_init(struct device *dev, uint32_t *previous_bar,
33 uint16_t *previous_command)
34#endif
Lee Leahy16bc9ba2017-04-01 20:33:58 -070035{
36 uint32_t bar;
37
38 /* Display the vendor/device IDs */
39 printk(LOG_DEBUG, "Vendor ID: 0x%04x, Device ID: 0x%04x\n",
40 pci_read_config16(dev, PCI_VENDOR_ID),
41 pci_read_config16(dev, PCI_DEVICE_ID));
42
43 /* Set the temporary base address */
44 bar = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
45 *previous_bar = bar;
46 bar &= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
47 if (!bar) {
48 bar = SD_BASE_ADDRESS;
49 pci_write_config32(dev, PCI_BASE_ADDRESS_0, bar);
50 }
51
52 /* Enable the SD/MMC controller */
53 *previous_command = pci_read_config16(dev, PCI_COMMAND);
54 pci_write_config16(dev, PCI_COMMAND, *previous_command
55 | PCI_COMMAND_MEMORY);
56
57 /* Return the controller address */
58 return bar;
59}
60
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010061#ifdef __SIMPLE_DEVICE__
62void storage_test_complete(pci_devfn_t dev, uint32_t previous_bar,
Lee Leahy16bc9ba2017-04-01 20:33:58 -070063 uint16_t previous_command)
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010064#else
65void storage_test_complete(struct device *dev, uint32_t previous_bar,
66 uint16_t previous_command)
67#endif
Lee Leahy16bc9ba2017-04-01 20:33:58 -070068{
69 pci_write_config16(dev, PCI_COMMAND, previous_command);
70 pci_write_config32(dev, PCI_BASE_ADDRESS_0, previous_bar);
71}
72
73#if !ENV_BOOTBLOCK
74static void display_log(void)
75{
76 /* Determine the array bounds */
Julius Wernercd49cce2019-03-05 16:53:33 -080077 if (CONFIG(STORAGE_LOG)) {
Lee Leahy16bc9ba2017-04-01 20:33:58 -070078 long delta;
79 uint8_t end;
80 uint8_t index;
81 uint8_t start;
82
83 end = log_index;
84 start = log_full ? log_index : 0;
85 for (index = start; (log_full || (index != end)); index++) {
86 log_full = 0;
87 delta = log[index].time.microseconds - log_start_time;
88 printk(BIOS_DEBUG, "%3ld.%03ld mSec, cmd: %2d 0x%08x%s",
89 delta / 1000, delta % 1000,
90 log[index].cmd.cmdidx,
91 log[index].cmd.cmdarg,
92 log[index].cmd_issued ? "" : "(not issued)");
93 if (log[index].response_entries == 1)
94 printk(BIOS_DEBUG, ", rsp: 0x%08x",
95 log[index].response[0]);
96 else if (log[index].response_entries == 4)
97 printk(BIOS_DEBUG,
98 ", rsp: 0x%08x.%08x.%08x.%08x",
99 log[index].response[3],
100 log[index].response[2],
101 log[index].response[1],
102 log[index].response[0]);
103 printk(BIOS_DEBUG, ", ret: %d\n", log[index].ret);
104 }
105 }
106}
107
108void sdhc_log_command(struct mmc_command *cmd)
109{
Julius Wernercd49cce2019-03-05 16:53:33 -0800110 if (CONFIG(STORAGE_LOG)) {
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700111 timer_monotonic_get(&log[log_index].time);
112 log[log_index].cmd = *cmd;
113 log[log_index].cmd_issued = 0;
114 log[log_index].response_entries = 0;
115 if ((log_index == 0) && (!log_full))
116 log_start_time = log[0].time.microseconds;
117 }
118}
119
120void sdhc_log_command_issued(void)
121{
Julius Wernercd49cce2019-03-05 16:53:33 -0800122 if (CONFIG(STORAGE_LOG)) {
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700123 log[log_index].cmd_issued = 1;
124 }
125}
126
127void sdhc_log_response(uint32_t entries, uint32_t *response)
128{
129 unsigned int entry;
130
Julius Wernercd49cce2019-03-05 16:53:33 -0800131 if (CONFIG(STORAGE_LOG)) {
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700132 log[log_index].response_entries = entries;
133 for (entry = 0; entry < entries; entry++)
134 log[log_index].response[entry] = response[entry];
135 }
136}
137
138void sdhc_log_ret(int ret)
139{
Julius Wernercd49cce2019-03-05 16:53:33 -0800140 if (CONFIG(STORAGE_LOG)) {
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700141 log[log_index].ret = ret;
142 if (++log_index == 0)
143 log_full = 1;
144 }
145}
146
147void storage_test(uint32_t bar, int full_initialization)
148{
149 uint64_t blocks_read;
150 uint8_t buffer[512];
151 int err;
152 struct storage_media *media;
153 const char *name;
154 unsigned int partition;
155 unsigned int previous_partition;
156 struct sdhci_ctrlr *sdhci_ctrlr;
157
Kyösti Mälkkif30123b2019-02-01 06:44:07 +0200158 ASSERT(sizeof(struct sdhci_ctrlr) <= sizeof(drivers_storage));
159
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700160 /* Get the structure addresses */
161 media = NULL;
162 if (ENV_ROMSTAGE)
Arthur Heymans84e22e32019-05-25 09:57:27 +0200163 media = (struct storage_media *)drivers_storage;
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700164 else
165 media = cbmem_find(CBMEM_ID_STORAGE_DATA);
166 sdhci_ctrlr = (void *)(((uintptr_t)(media + 1) + 0x7) & ~7);
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700167 media->ctrlr = (struct sd_mmc_ctrlr *)sdhci_ctrlr;
168 sdhci_ctrlr->ioaddr = (void *)bar;
169
170 /* Initialize the controller */
171 if (!full_initialization) {
172 /* Perform fast initialization */
173 sdhci_update_pointers(sdhci_ctrlr);
174 sdhci_display_setup(sdhci_ctrlr);
175 storage_display_setup(media);
176 } else {
177 /* Initialize the log */
Julius Wernercd49cce2019-03-05 16:53:33 -0800178 if (CONFIG(STORAGE_LOG)) {
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700179 log_index = 0;
180 log_full = 0;
181 }
182
183 printk(LOG_DEBUG, "Initializing the SD/MMC controller\n");
184 err = sdhci_controller_init(sdhci_ctrlr, (void *)bar);
185 if (err) {
186 display_log();
187 printk(BIOS_ERR,
188 "ERROR - Controller failed to initialize, err = %d\n",
189 err);
190 return;
191 }
192
193 /* Initialize the SD/MMC/eMMC card or device */
194 printk(LOG_DEBUG, "Initializing the device\n");
195 err = storage_setup_media(media, &sdhci_ctrlr->sd_mmc_ctrlr);
196 if (err) {
197 display_log();
198 printk(BIOS_ERR,
199 "ERROR: Device failed to initialize, err = %d\n",
200 err);
201 return;
202 }
203 display_log();
204 }
205
206 /* Save the current partition */
207 previous_partition = storage_get_current_partition(media);
208
209 /* Read block 0 from each partition */
210 for (partition = 0; partition < ARRAY_SIZE(media->capacity);
211 partition++) {
212 if (media->capacity[partition] == 0)
213 continue;
214 name = storage_partition_name(media, partition);
215 printk(STORAGE_DEBUG, "%s%sReading block 0\n", name,
216 name[0] ? ": " : "");
217 err = storage_set_partition(media, partition);
218 if (err)
219 continue;
220 blocks_read = storage_block_read(media, 0, 1, &buffer);
221 if (blocks_read)
222 hexdump(buffer, sizeof(buffer));
223 }
224
225 /* Restore the previous partition */
226 storage_set_partition(media, previous_partition);
227}
228#endif
229
230#if ENV_ROMSTAGE
231static void copy_storage_structures(int is_recovery)
232{
233 struct storage_media *media;
234 struct sdhci_ctrlr *sdhci_ctrlr;
Kyösti Mälkkif30123b2019-02-01 06:44:07 +0200235 size_t size = sizeof(drivers_storage);
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700236
237 /* Locate the data structures in CBMEM */
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700238 media = cbmem_add(CBMEM_ID_STORAGE_DATA, size);
239 ASSERT(media != NULL);
240 sdhci_ctrlr = (void *)(((uintptr_t)(media + 1) + 0x7) & ~7);
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700241
242 /* Migrate the data into CBMEM */
Arthur Heymans84e22e32019-05-25 09:57:27 +0200243 memcpy(media, drivers_storage, size);
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700244 media->ctrlr = &sdhci_ctrlr->sd_mmc_ctrlr;
245}
246
247ROMSTAGE_CBMEM_INIT_HOOK(copy_storage_structures);
248#endif