blob: 36819a4700f2ddc61210da466c1409cbbd061b46 [file] [log] [blame]
Lee Leahy16bc9ba2017-04-01 20:33:58 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2017 Intel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <arch/early_variables.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020017#include <device/pci_ops.h>
Lee Leahy16bc9ba2017-04-01 20:33:58 -070018#include <assert.h>
19#include <cbmem.h>
20#include <commonlib/cbmem_id.h>
Lee Leahy48dbc662017-05-08 16:56:03 -070021#include <commonlib/sdhci.h>
22#include <commonlib/storage.h>
Lee Leahy16bc9ba2017-04-01 20:33:58 -070023#include <console/console.h>
Lee Leahy16bc9ba2017-04-01 20:33:58 -070024#include <lib.h>
25#include <soc/iomap.h>
26#include <soc/pci_devs.h>
27#include <soc/storage_test.h>
28#include <string.h>
29
30#if IS_ENABLED(CONFIG_STORAGE_LOG)
31struct log_entry log[LOG_ENTRIES] CAR_GLOBAL;
32uint8_t log_index CAR_GLOBAL;
33int log_full CAR_GLOBAL;
34long log_start_time CAR_GLOBAL;
35#endif
Kyösti Mälkkif30123b2019-02-01 06:44:07 +020036
37static uint8_t drivers_storage[256] CAR_GLOBAL;
Lee Leahy16bc9ba2017-04-01 20:33:58 -070038
39#define STORAGE_DEBUG BIOS_DEBUG
40#define LOG_DEBUG (IS_ENABLED(CONFIG_STORAGE_LOG) ? STORAGE_DEBUG : BIOS_NEVER)
41
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010042#ifdef __SIMPLE_DEVICE__
43uint32_t storage_test_init(pci_devfn_t dev, uint32_t *previous_bar,
Lee Leahy16bc9ba2017-04-01 20:33:58 -070044 uint16_t *previous_command)
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010045#else
46uint32_t storage_test_init(struct device *dev, uint32_t *previous_bar,
47 uint16_t *previous_command)
48#endif
Lee Leahy16bc9ba2017-04-01 20:33:58 -070049{
50 uint32_t bar;
51
52 /* Display the vendor/device IDs */
53 printk(LOG_DEBUG, "Vendor ID: 0x%04x, Device ID: 0x%04x\n",
54 pci_read_config16(dev, PCI_VENDOR_ID),
55 pci_read_config16(dev, PCI_DEVICE_ID));
56
57 /* Set the temporary base address */
58 bar = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
59 *previous_bar = bar;
60 bar &= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
61 if (!bar) {
62 bar = SD_BASE_ADDRESS;
63 pci_write_config32(dev, PCI_BASE_ADDRESS_0, bar);
64 }
65
66 /* Enable the SD/MMC controller */
67 *previous_command = pci_read_config16(dev, PCI_COMMAND);
68 pci_write_config16(dev, PCI_COMMAND, *previous_command
69 | PCI_COMMAND_MEMORY);
70
71 /* Return the controller address */
72 return bar;
73}
74
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010075#ifdef __SIMPLE_DEVICE__
76void storage_test_complete(pci_devfn_t dev, uint32_t previous_bar,
Lee Leahy16bc9ba2017-04-01 20:33:58 -070077 uint16_t previous_command)
Elyes HAOUAS6f01f432018-12-05 10:56:30 +010078#else
79void storage_test_complete(struct device *dev, uint32_t previous_bar,
80 uint16_t previous_command)
81#endif
Lee Leahy16bc9ba2017-04-01 20:33:58 -070082{
83 pci_write_config16(dev, PCI_COMMAND, previous_command);
84 pci_write_config32(dev, PCI_BASE_ADDRESS_0, previous_bar);
85}
86
87#if !ENV_BOOTBLOCK
88static void display_log(void)
89{
90 /* Determine the array bounds */
91 if (IS_ENABLED(CONFIG_STORAGE_LOG)) {
92 long delta;
93 uint8_t end;
94 uint8_t index;
95 uint8_t start;
96
97 end = log_index;
98 start = log_full ? log_index : 0;
99 for (index = start; (log_full || (index != end)); index++) {
100 log_full = 0;
101 delta = log[index].time.microseconds - log_start_time;
102 printk(BIOS_DEBUG, "%3ld.%03ld mSec, cmd: %2d 0x%08x%s",
103 delta / 1000, delta % 1000,
104 log[index].cmd.cmdidx,
105 log[index].cmd.cmdarg,
106 log[index].cmd_issued ? "" : "(not issued)");
107 if (log[index].response_entries == 1)
108 printk(BIOS_DEBUG, ", rsp: 0x%08x",
109 log[index].response[0]);
110 else if (log[index].response_entries == 4)
111 printk(BIOS_DEBUG,
112 ", rsp: 0x%08x.%08x.%08x.%08x",
113 log[index].response[3],
114 log[index].response[2],
115 log[index].response[1],
116 log[index].response[0]);
117 printk(BIOS_DEBUG, ", ret: %d\n", log[index].ret);
118 }
119 }
120}
121
122void sdhc_log_command(struct mmc_command *cmd)
123{
124 if (IS_ENABLED(CONFIG_STORAGE_LOG)) {
125 timer_monotonic_get(&log[log_index].time);
126 log[log_index].cmd = *cmd;
127 log[log_index].cmd_issued = 0;
128 log[log_index].response_entries = 0;
129 if ((log_index == 0) && (!log_full))
130 log_start_time = log[0].time.microseconds;
131 }
132}
133
134void sdhc_log_command_issued(void)
135{
136 if (IS_ENABLED(CONFIG_STORAGE_LOG)) {
137 log[log_index].cmd_issued = 1;
138 }
139}
140
141void sdhc_log_response(uint32_t entries, uint32_t *response)
142{
143 unsigned int entry;
144
145 if (IS_ENABLED(CONFIG_STORAGE_LOG)) {
146 log[log_index].response_entries = entries;
147 for (entry = 0; entry < entries; entry++)
148 log[log_index].response[entry] = response[entry];
149 }
150}
151
152void sdhc_log_ret(int ret)
153{
154 if (IS_ENABLED(CONFIG_STORAGE_LOG)) {
155 log[log_index].ret = ret;
156 if (++log_index == 0)
157 log_full = 1;
158 }
159}
160
161void storage_test(uint32_t bar, int full_initialization)
162{
163 uint64_t blocks_read;
164 uint8_t buffer[512];
165 int err;
166 struct storage_media *media;
167 const char *name;
168 unsigned int partition;
169 unsigned int previous_partition;
170 struct sdhci_ctrlr *sdhci_ctrlr;
171
Kyösti Mälkkif30123b2019-02-01 06:44:07 +0200172 ASSERT(sizeof(struct sdhci_ctrlr) <= sizeof(drivers_storage));
173
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700174 /* Get the structure addresses */
175 media = NULL;
176 if (ENV_ROMSTAGE)
Kyösti Mälkkif30123b2019-02-01 06:44:07 +0200177 media = car_get_var_ptr(drivers_storage);
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700178 else
179 media = cbmem_find(CBMEM_ID_STORAGE_DATA);
180 sdhci_ctrlr = (void *)(((uintptr_t)(media + 1) + 0x7) & ~7);
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700181 media->ctrlr = (struct sd_mmc_ctrlr *)sdhci_ctrlr;
182 sdhci_ctrlr->ioaddr = (void *)bar;
183
184 /* Initialize the controller */
185 if (!full_initialization) {
186 /* Perform fast initialization */
187 sdhci_update_pointers(sdhci_ctrlr);
188 sdhci_display_setup(sdhci_ctrlr);
189 storage_display_setup(media);
190 } else {
191 /* Initialize the log */
192 if (IS_ENABLED(CONFIG_STORAGE_LOG)) {
193 log_index = 0;
194 log_full = 0;
195 }
196
197 printk(LOG_DEBUG, "Initializing the SD/MMC controller\n");
198 err = sdhci_controller_init(sdhci_ctrlr, (void *)bar);
199 if (err) {
200 display_log();
201 printk(BIOS_ERR,
202 "ERROR - Controller failed to initialize, err = %d\n",
203 err);
204 return;
205 }
206
207 /* Initialize the SD/MMC/eMMC card or device */
208 printk(LOG_DEBUG, "Initializing the device\n");
209 err = storage_setup_media(media, &sdhci_ctrlr->sd_mmc_ctrlr);
210 if (err) {
211 display_log();
212 printk(BIOS_ERR,
213 "ERROR: Device failed to initialize, err = %d\n",
214 err);
215 return;
216 }
217 display_log();
218 }
219
220 /* Save the current partition */
221 previous_partition = storage_get_current_partition(media);
222
223 /* Read block 0 from each partition */
224 for (partition = 0; partition < ARRAY_SIZE(media->capacity);
225 partition++) {
226 if (media->capacity[partition] == 0)
227 continue;
228 name = storage_partition_name(media, partition);
229 printk(STORAGE_DEBUG, "%s%sReading block 0\n", name,
230 name[0] ? ": " : "");
231 err = storage_set_partition(media, partition);
232 if (err)
233 continue;
234 blocks_read = storage_block_read(media, 0, 1, &buffer);
235 if (blocks_read)
236 hexdump(buffer, sizeof(buffer));
237 }
238
239 /* Restore the previous partition */
240 storage_set_partition(media, previous_partition);
241}
242#endif
243
244#if ENV_ROMSTAGE
245static void copy_storage_structures(int is_recovery)
246{
247 struct storage_media *media;
248 struct sdhci_ctrlr *sdhci_ctrlr;
Kyösti Mälkkif30123b2019-02-01 06:44:07 +0200249 size_t size = sizeof(drivers_storage);
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700250
251 /* Locate the data structures in CBMEM */
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700252 media = cbmem_add(CBMEM_ID_STORAGE_DATA, size);
253 ASSERT(media != NULL);
254 sdhci_ctrlr = (void *)(((uintptr_t)(media + 1) + 0x7) & ~7);
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700255
256 /* Migrate the data into CBMEM */
Kyösti Mälkkif30123b2019-02-01 06:44:07 +0200257 memcpy(media, car_get_var_ptr(drivers_storage), size);
Lee Leahy16bc9ba2017-04-01 20:33:58 -0700258 media->ctrlr = &sdhci_ctrlr->sd_mmc_ctrlr;
259}
260
261ROMSTAGE_CBMEM_INIT_HOOK(copy_storage_structures);
262#endif