Hello Subrata Banik, Bora Guvendik,
I'd like you to do a code review. Please visit
https://review.coreboot.org/25189
to review the following change.
Change subject: storage: Pass the firmware sdhci data to depthcharge ......................................................................
storage: Pass the firmware sdhci data to depthcharge
If CONFIG_SOC_INTEL_COMMON_BLOCK_EMMC Kconfig is selected from SOC, then this patch writes sdhci and mmc driver data to coreboot tables so that the payload can use the data and start talking to emmc device without reinitializing the storage driver.
Thus, in case the EMMC init code is done in coreboot, it will save the media information in coreboot table and pass to depthcharge, and thus depthcharge can skip the EMMC init code, saving around ~100-300 msecs of booting time.
Change-Id: I38e26cb7b3daa5d6bc6d38c3b9efb6640ab78a86 Signed-off-by: Barnali Sarkar barnali.sarkar@intel.com Signed-off-by: Subrata Banik subrata.banik@intel.com Signed-off-by: Bora Guvendik bora.guvendik@intel.com --- M payloads/libpayload/include/coreboot_tables.h M payloads/libpayload/include/sysinfo.h M payloads/libpayload/libc/coreboot.c M src/commonlib/include/commonlib/coreboot_tables.h M src/commonlib/include/commonlib/sdhci.h M src/lib/coreboot_table.c 6 files changed, 275 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/89/25189/1
diff --git a/payloads/libpayload/include/coreboot_tables.h b/payloads/libpayload/include/coreboot_tables.h index 6b6d1b4..7059219 100644 --- a/payloads/libpayload/include/coreboot_tables.h +++ b/payloads/libpayload/include/coreboot_tables.h @@ -280,6 +280,60 @@ uint8_t pad[2]; /* Pad it to 8 bytes to keep it simple. */ };
+#define CB_TAG_SDHCI_HOST 0x0034 +struct cb_sdhci_host_info { + uint32_t tag; + uint32_t size; + int initialized; + unsigned quirks; + unsigned host_caps; + unsigned version; + unsigned clock; + unsigned clock_f_min; + unsigned clock_f_max; + unsigned clock_base; + int removable; + unsigned voltages; + unsigned dma64; +}; + +#define CB_TAG_MMC_MEDIA 0x0035 +struct cb_mmc_media_info { + uint32_t tag; + uint32_t size; + uint32_t caps; + uint32_t version; + uint32_t read_bl_len; + uint32_t write_bl_len; + uint64_t capacity; + int high_capacity; + uint32_t tran_speed; + uint32_t erase_size; + uint32_t trim_mult; + uint32_t ocr; + uint16_t rca; + uint32_t scr[2]; + uint32_t csd[4]; + uint32_t cid[4]; + uint32_t op_cond_response; +}; + +#define CB_TAG_MMC_CTRLR 0x0036 +struct cb_mmc_ctrlr_info { + uint32_t tag; + uint32_t size; + uint32_t voltages; + uint32_t f_min; + uint32_t f_max; + uint32_t bus_width; + uint32_t bus_hz; + uint32_t caps; + uint32_t b_max; + uint32_t timing; + uint32_t hardcoded_voltage; +}; + + struct cb_macs { uint32_t tag; uint32_t size; diff --git a/payloads/libpayload/include/sysinfo.h b/payloads/libpayload/include/sysinfo.h index f221a15..98c8174 100644 --- a/payloads/libpayload/include/sysinfo.h +++ b/payloads/libpayload/include/sysinfo.h @@ -129,6 +129,9 @@ uint64_t mtc_start; uint32_t mtc_size; void *chromeos_vpd; + struct cb_sdhci_host_info *sdhci_host; + struct cb_mmc_media_info *mmc_media; + struct cb_mmc_ctrlr_info *mmc_ctrlr; };
extern struct sysinfo_t lib_sysinfo; diff --git a/payloads/libpayload/libc/coreboot.c b/payloads/libpayload/libc/coreboot.c index d831b96..cc585d3 100644 --- a/payloads/libpayload/libc/coreboot.c +++ b/payloads/libpayload/libc/coreboot.c @@ -151,6 +151,21 @@ info->board_id = cbbid->id_code; }
+static void cb_parse_sdhci_info(unsigned char *ptr, struct sysinfo_t *info) +{ + info->sdhci_host = (struct cb_sdhci_host_info*)ptr; +} + +static void cb_mmc_media_info(unsigned char *ptr, struct sysinfo_t *info) +{ + info->mmc_media = (struct cb_mmc_media_info*)ptr; +} + +static void cb_mmc_ctrlr_info(unsigned char *ptr, struct sysinfo_t *info) +{ + info->mmc_ctrlr = (struct cb_mmc_ctrlr_info*)ptr; +} + static void cb_parse_ram_code(unsigned char *ptr, struct sysinfo_t *info) { struct cb_strapping_id *const ram_code = (struct cb_strapping_id *)ptr; @@ -384,6 +399,15 @@ case CB_TAG_BOARD_ID: cb_parse_board_id(ptr, info); break; + case CB_TAG_SDHCI_HOST: + cb_parse_sdhci_info(ptr, info); + break; + case CB_TAG_MMC_MEDIA: + cb_mmc_media_info(ptr, info); + break; + case CB_TAG_MMC_CTRLR: + cb_mmc_ctrlr_info(ptr, info); + break; case CB_TAG_RAM_CODE: cb_parse_ram_code(ptr, info); break; diff --git a/src/commonlib/include/commonlib/coreboot_tables.h b/src/commonlib/include/commonlib/coreboot_tables.h index f411ff2..b6090c9 100644 --- a/src/commonlib/include/commonlib/coreboot_tables.h +++ b/src/commonlib/include/commonlib/coreboot_tables.h @@ -384,6 +384,59 @@ uint8_t pad[2]; /* Pad it to 8 bytes to keep it simple. */ };
+#define LB_TAG_SDHCI_HOST 0x0034 +struct lb_sdhci_host_info { + uint32_t tag; + uint32_t size; + int initialized; + unsigned quirks; + unsigned host_caps; + unsigned version; + unsigned clock; + unsigned clock_f_min; + unsigned clock_f_max; + unsigned clock_base; + int removable; + unsigned voltages; + unsigned dma64; +}; + +#define LB_TAG_MMC_MEDIA 0x0035 +struct lb_mmc_media_info { + uint32_t tag; + uint32_t size; + uint32_t caps; + uint32_t version; + uint32_t read_bl_len; + uint32_t write_bl_len; + uint64_t capacity; + int high_capacity; + uint32_t tran_speed; + uint32_t erase_size; + uint32_t trim_mult; + uint32_t ocr; + uint16_t rca; + uint32_t scr[2]; + uint32_t csd[4]; + uint32_t cid[4]; + uint32_t op_cond_response; +}; + +#define LB_TAG_MMC_CTRLR 0x0036 +struct lb_mmc_ctrlr_info { + uint32_t tag; + uint32_t size; + uint32_t voltages; + uint32_t f_min; + uint32_t f_max; + uint32_t bus_width; + uint32_t bus_hz; + uint32_t caps; + uint32_t b_max; + uint32_t timing; + uint32_t hardcoded_voltage; +}; + struct lb_macs { uint32_t tag; uint32_t size; diff --git a/src/commonlib/include/commonlib/sdhci.h b/src/commonlib/include/commonlib/sdhci.h index ffeb662..d2ad86b 100644 --- a/src/commonlib/include/commonlib/sdhci.h +++ b/src/commonlib/include/commonlib/sdhci.h @@ -32,6 +32,13 @@ #define DRVR_CAP_SPI 0x00800000 #define DRVR_CAP_WAIT_SEND_CMD 0x01000000
+/* + * quirks + */ +#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1 << 7) +#define SDHCI_QUIRK_NO_EMMC_HS200 (1 << 8) +#define SDHCI_QUIRK_SUPPORTS_HS400ES (1 << 11) + /* ADMA packet descriptor */ struct sdhci_adma { u16 attributes; diff --git a/src/lib/coreboot_table.c b/src/lib/coreboot_table.c index d03b771..47ae95b 100644 --- a/src/lib/coreboot_table.c +++ b/src/lib/coreboot_table.c @@ -47,6 +47,14 @@ #include <cpu/x86/mtrr.h> #endif #include <commonlib/helpers.h> +#if IS_ENABLED(CONFIG_SOC_INTEL_COMMON_BLOCK_EMMC_INIT_OVER_AP) +#include <cbmem.h> +#include <commonlib/cbmem_id.h> +#include <commonlib/sdhci.h> +#include <commonlib/storage.h> +#include <delay.h> +#endif +
static struct lb_header *lb_table_init(unsigned long addr) { @@ -149,6 +157,128 @@ framebuffer->size = sizeof(*framebuffer); }
+#if IS_ENABLED(CONFIG_SOC_INTEL_COMMON_BLOCK_EMMC_INIT_OVER_AP) +static struct storage_media *get_media_list(void) +{ + struct storage_media *media; + + while(1) { + media = cbmem_find(CBMEM_ID_STORAGE_DATA); + if (media) + break; + } + return media; +} + +static void lb_sdhci_host( struct lb_header *header, + struct storage_media *media) +{ + struct lb_sdhci_host_info *lb_host; + struct sd_mmc_ctrlr *host_ptr; + unsigned quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER; + + host_ptr = media->ctrlr; + + lb_host = (struct lb_sdhci_host_info *)lb_new_record(header); + + lb_host->tag = LB_TAG_SDHCI_HOST; + lb_host->size = sizeof(*lb_host); + + quirks |= SDHCI_QUIRK_SUPPORTS_HS400ES; + + lb_host->initialized = host_ptr->initialized; + lb_host->quirks = quirks; + lb_host->host_caps = host_ptr->caps; + lb_host->version = host_ptr->version; + lb_host->clock = host_ptr->clock_base; + lb_host->clock_f_min = host_ptr->f_min; + lb_host->clock_f_max = host_ptr->f_max; + lb_host->clock_base = host_ptr->clock_base; + lb_host->removable = (host_ptr->caps & DRVR_CAP_REMOVABLE) ? 1 : 0; + lb_host->voltages = host_ptr->voltages; + lb_host->dma64 = (host_ptr->caps & DRVR_CAP_DMA_64BIT) ? 1 : 0; +} + +static void lb_mmc_media( struct lb_header *header, + struct storage_media *media) +{ + struct lb_mmc_media_info *lb_mmc_media; + + lb_mmc_media = (struct lb_mmc_media_info *)lb_new_record(header); + + lb_mmc_media->tag = LB_TAG_MMC_MEDIA; + lb_mmc_media->size = sizeof(*lb_mmc_media); + + lb_mmc_media->caps = media->caps; + lb_mmc_media->version = media->version; + lb_mmc_media->read_bl_len = media->read_bl_len; + lb_mmc_media->write_bl_len = media->write_bl_len; + lb_mmc_media->capacity = media->capacity[0]; + lb_mmc_media->high_capacity = media->high_capacity; + lb_mmc_media->tran_speed = media->tran_speed; + lb_mmc_media->erase_size = media->erase_blocks; + lb_mmc_media->trim_mult = media->trim_mult; + lb_mmc_media->ocr = media->ocr; + lb_mmc_media->rca = media->rca; + lb_mmc_media->op_cond_response = media->op_cond_response; + + memcpy(&lb_mmc_media->scr[0],&media->scr[0],2); + memcpy(&lb_mmc_media->csd[0],&media->csd[0],4); + memcpy(&lb_mmc_media->cid[0],&media->cid[0],4); +} + +static void lb_mmc_ctrlr(struct lb_header *header, struct storage_media *media) +{ + struct lb_mmc_ctrlr_info *lb_mmc_ctrlr; + int removable; + struct sd_mmc_ctrlr *host_ptr; + + host_ptr = media->ctrlr; + + lb_mmc_ctrlr = (struct lb_mmc_ctrlr_info *)lb_new_record(header); + + lb_mmc_ctrlr->tag = LB_TAG_MMC_CTRLR; + lb_mmc_ctrlr->size = sizeof(*lb_mmc_ctrlr); + + lb_mmc_ctrlr->voltages = host_ptr->voltages; + lb_mmc_ctrlr->f_min = host_ptr->f_min; + lb_mmc_ctrlr->f_max = host_ptr->f_max; + lb_mmc_ctrlr->bus_width = host_ptr->bus_width; + lb_mmc_ctrlr->bus_hz = host_ptr->bus_hz; + lb_mmc_ctrlr->caps = host_ptr->caps; + lb_mmc_ctrlr->b_max = host_ptr->b_max; + lb_mmc_ctrlr->timing = host_ptr->timing; + + removable = (host_ptr->caps & DRVR_CAP_REMOVABLE) ? 1 : 0; + if (!removable) + /* + * The value translates to 'block access mode, supporting + * 1.7..1.95 and 2.7..3.6 voltage ranges, which is typical for + * eMMC devices. + */ + lb_mmc_ctrlr->hardcoded_voltage = 0x40ff8080; +} + +static void fill_emmc_structure(struct lb_header *head) +{ + struct storage_media *media; + + media = get_media_list(); + + if (media->ctrlr->initialized) { + printk(BIOS_INFO, "Passing eMMC structure to payload:\n"); + /* Add sdhci host information */ + lb_sdhci_host(head, media); + + /* Add mmc media information */ + lb_mmc_media(head, media); + + /* Add mmc ctrlr information */ + lb_mmc_ctrlr(head, media); + } +} +#endif /* CONFIG_SOC_INTEL_COMMON_BLOCK_EMMC_INIT_OVER_AP */ + void lb_add_gpios(struct lb_gpios *gpios, const struct lb_gpio *gpio_table, size_t count) { @@ -588,6 +718,10 @@ /* Add all cbmem entries into the coreboot tables. */ cbmem_add_records_to_cbtable(head);
+#if IS_ENABLED(CONFIG_SOC_INTEL_COMMON_BLOCK_EMMC_INIT_OVER_AP) + fill_emmc_structure(head); +#endif + /* Remember where my valid memory ranges are */ return lb_table_fini(head); }