From 15c7c6b31ad8742bd6e63be35f82193895ff8bdd Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 10 Dec 2014 16:35:50 +0800 Subject: [PATCH 01/26] x86: ich-spi: Fix a bug of reading from a non-64 bytes aligned address The ich spi controller driver spi_xfer() tries to align reading address to 64 bytes when doing spi data in, which causes a bug of either infinite loop or a huge size memcpy(). Actually the ich spi controller does not have such requirement of 64 bytes alignment when reading data from spi slave devices. Signed-off-by: Bin Meng Acked-by: Simon Glass Tested-by: Simon Glass --- drivers/spi/ich.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c index f5c6f3e7d2..c4d3a291e8 100644 --- a/drivers/spi/ich.c +++ b/drivers/spi/ich.c @@ -483,8 +483,6 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, struct spi_trans *trans = &ich->trans; unsigned type = flags & (SPI_XFER_BEGIN | SPI_XFER_END); int using_cmd = 0; - /* Align read transactions to 64-byte boundaries */ - char buff[ctlr.databytes]; /* Ee don't support writing partial bytes. */ if (bitlen % 8) { @@ -632,14 +630,9 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, */ while (trans->bytesout || trans->bytesin) { uint32_t data_length; - uint32_t aligned_offset; - uint32_t diff; - - aligned_offset = trans->offset & ~(ctlr.databytes - 1); - diff = trans->offset - aligned_offset; /* SPI addresses are 24 bit only */ - ich_writel(aligned_offset & 0x00FFFFFF, ctlr.addr); + ich_writel(trans->offset & 0x00FFFFFF, ctlr.addr); if (trans->bytesout) data_length = min(trans->bytesout, ctlr.databytes); @@ -673,13 +666,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, } if (trans->bytesin) { - if (diff) { - data_length -= diff; - read_reg(ctlr.data, buff, ctlr.databytes); - memcpy(trans->in, buff + diff, data_length); - } else { - read_reg(ctlr.data, trans->in, data_length); - } + read_reg(ctlr.data, trans->in, data_length); spi_use_in(trans, data_length); if (with_address) trans->offset += data_length; From 0a54745fc2537cbbd9d9e405086cfff39d37c55e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 7 Dec 2014 12:48:27 +0800 Subject: [PATCH 02/26] gpio: intel_ich6: Set correct gpio output value in ich6_gpio_direction_output() Current code does not set gpio output value in ich6_gpio_direction_output(), fix it. Signed-off-by: Axel Lin Acked-by: Simon Glass --- drivers/gpio/intel_ich6_gpio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c index b095d17f57..92c23aed4c 100644 --- a/drivers/gpio/intel_ich6_gpio.c +++ b/drivers/gpio/intel_ich6_gpio.c @@ -251,6 +251,8 @@ static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset, struct ich6_bank_priv *bank = dev_get_priv(dev); u32 tmplong; + gpio_set_value(offset, value); + tmplong = inl(bank->io_sel); tmplong &= ~(1UL << offset); outl(bank->io_sel, tmplong); From f46f3f356f684a20d1ccb50c943536591a7697f3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 10 Dec 2014 20:12:01 -0700 Subject: [PATCH 03/26] bios_emulator: Correct ordering of includes We should include common.h before other includes. This actually causes a build error on chromebook_link. Signed-off-by: Simon Glass --- drivers/bios_emulator/besys.c | 2 +- drivers/bios_emulator/bios.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/bios_emulator/besys.c b/drivers/bios_emulator/besys.c index 752a928f66..02c4286a85 100644 --- a/drivers/bios_emulator/besys.c +++ b/drivers/bios_emulator/besys.c @@ -48,8 +48,8 @@ ****************************************************************************/ #define __io -#include #include +#include #include "biosemui.h" /*------------------------- Global Variables ------------------------------*/ diff --git a/drivers/bios_emulator/bios.c b/drivers/bios_emulator/bios.c index 152d70a778..dd4c0a4f32 100644 --- a/drivers/bios_emulator/bios.c +++ b/drivers/bios_emulator/bios.c @@ -42,8 +42,8 @@ ****************************************************************************/ #define __io -#include #include +#include #include "biosemui.h" /*----------------------------- Implementation ----------------------------*/ From 6dd6e90e13acc4014634d78fc469e7e82eefc255 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Fri, 12 Dec 2014 19:36:11 +0530 Subject: [PATCH 04/26] sf: Fix look for the fastest read command Few of the spi controllers are only supports array slow read which is quite different behaviour compared to others. So this fix on sf will correctly handle the slow read supported controllers. Signed-off-by: Jagannadha Sutradharudu Teki Tested-by: Bin Meng --- drivers/mtd/spi/sf_internal.h | 13 +++-- drivers/mtd/spi/sf_params.c | 102 +++++++++++++++++----------------- drivers/mtd/spi/sf_probe.c | 1 + 3 files changed, 60 insertions(+), 56 deletions(-) diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 5b7670c9aa..e159f04000 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -23,13 +23,16 @@ enum spi_dual_flash { /* Enum list - Full read commands */ enum spi_read_cmds { ARRAY_SLOW = 1 << 0, - DUAL_OUTPUT_FAST = 1 << 1, - DUAL_IO_FAST = 1 << 2, - QUAD_OUTPUT_FAST = 1 << 3, - QUAD_IO_FAST = 1 << 4, + ARRAY_FAST = 1 << 1, + DUAL_OUTPUT_FAST = 1 << 2, + DUAL_IO_FAST = 1 << 3, + QUAD_OUTPUT_FAST = 1 << 4, + QUAD_IO_FAST = 1 << 5, }; -#define RD_EXTN (ARRAY_SLOW | DUAL_OUTPUT_FAST | DUAL_IO_FAST) +/* Normal - Extended - Full command set */ +#define RD_NORM (ARRAY_SLOW | ARRAY_FAST) +#define RD_EXTN (RD_NORM | DUAL_OUTPUT_FAST | DUAL_IO_FAST) #define RD_FULL (RD_EXTN | QUAD_OUTPUT_FAST | QUAD_IO_FAST) /* sf param flags */ diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c index 61545cacaa..0f1f837106 100644 --- a/drivers/mtd/spi/sf_params.c +++ b/drivers/mtd/spi/sf_params.c @@ -15,42 +15,42 @@ /* SPI/QSPI flash device params structure */ const struct spi_flash_params spi_flash_params_table[] = { #ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */ - {"AT45DB011D", 0x1f2200, 0x0, 64 * 1024, 4, 0, SECT_4K}, - {"AT45DB021D", 0x1f2300, 0x0, 64 * 1024, 8, 0, SECT_4K}, - {"AT45DB041D", 0x1f2400, 0x0, 64 * 1024, 8, 0, SECT_4K}, - {"AT45DB081D", 0x1f2500, 0x0, 64 * 1024, 16, 0, SECT_4K}, - {"AT45DB161D", 0x1f2600, 0x0, 64 * 1024, 32, 0, SECT_4K}, - {"AT45DB321D", 0x1f2700, 0x0, 64 * 1024, 64, 0, SECT_4K}, - {"AT45DB641D", 0x1f2800, 0x0, 64 * 1024, 128, 0, SECT_4K}, - {"AT25DF321", 0x1f4701, 0x0, 64 * 1024, 64, 0, SECT_4K}, + {"AT45DB011D", 0x1f2200, 0x0, 64 * 1024, 4, RD_NORM, SECT_4K}, + {"AT45DB021D", 0x1f2300, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K}, + {"AT45DB041D", 0x1f2400, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K}, + {"AT45DB081D", 0x1f2500, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K}, + {"AT45DB161D", 0x1f2600, 0x0, 64 * 1024, 32, RD_NORM, SECT_4K}, + {"AT45DB321D", 0x1f2700, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K}, + {"AT45DB641D", 0x1f2800, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, + {"AT25DF321", 0x1f4701, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K}, #endif #ifdef CONFIG_SPI_FLASH_EON /* EON */ - {"EN25Q32B", 0x1c3016, 0x0, 64 * 1024, 64, 0, 0}, - {"EN25Q64", 0x1c3017, 0x0, 64 * 1024, 128, 0, SECT_4K}, - {"EN25Q128B", 0x1c3018, 0x0, 64 * 1024, 256, 0, 0}, - {"EN25S64", 0x1c3817, 0x0, 64 * 1024, 128, 0, 0}, + {"EN25Q32B", 0x1c3016, 0x0, 64 * 1024, 64, RD_NORM, 0}, + {"EN25Q64", 0x1c3017, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, + {"EN25Q128B", 0x1c3018, 0x0, 64 * 1024, 256, RD_NORM, 0}, + {"EN25S64", 0x1c3817, 0x0, 64 * 1024, 128, RD_NORM, 0}, #endif #ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */ - {"GD25Q64B", 0xc84017, 0x0, 64 * 1024, 128, 0, SECT_4K}, - {"GD25LQ32", 0xc86016, 0x0, 64 * 1024, 64, 0, SECT_4K}, + {"GD25Q64B", 0xc84017, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, + {"GD25LQ32", 0xc86016, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K}, #endif #ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */ - {"MX25L2006E", 0xc22012, 0x0, 64 * 1024, 4, 0, 0}, - {"MX25L4005", 0xc22013, 0x0, 64 * 1024, 8, 0, 0}, - {"MX25L8005", 0xc22014, 0x0, 64 * 1024, 16, 0, 0}, - {"MX25L1605D", 0xc22015, 0x0, 64 * 1024, 32, 0, 0}, - {"MX25L3205D", 0xc22016, 0x0, 64 * 1024, 64, 0, 0}, - {"MX25L6405D", 0xc22017, 0x0, 64 * 1024, 128, 0, 0}, + {"MX25L2006E", 0xc22012, 0x0, 64 * 1024, 4, RD_NORM, 0}, + {"MX25L4005", 0xc22013, 0x0, 64 * 1024, 8, RD_NORM, 0}, + {"MX25L8005", 0xc22014, 0x0, 64 * 1024, 16, RD_NORM, 0}, + {"MX25L1605D", 0xc22015, 0x0, 64 * 1024, 32, RD_NORM, 0}, + {"MX25L3205D", 0xc22016, 0x0, 64 * 1024, 64, RD_NORM, 0}, + {"MX25L6405D", 0xc22017, 0x0, 64 * 1024, 128, RD_NORM, 0}, {"MX25L12805", 0xc22018, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP}, {"MX25L25635F", 0xc22019, 0x0, 64 * 1024, 512, RD_FULL, WR_QPP}, {"MX25L51235F", 0xc2201a, 0x0, 64 * 1024, 1024, RD_FULL, WR_QPP}, {"MX25L12855E", 0xc22618, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP}, #endif #ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */ - {"S25FL008A", 0x010213, 0x0, 64 * 1024, 16, 0, 0}, - {"S25FL016A", 0x010214, 0x0, 64 * 1024, 32, 0, 0}, - {"S25FL032A", 0x010215, 0x0, 64 * 1024, 64, 0, 0}, - {"S25FL064A", 0x010216, 0x0, 64 * 1024, 128, 0, 0}, + {"S25FL008A", 0x010213, 0x0, 64 * 1024, 16, RD_NORM, 0}, + {"S25FL016A", 0x010214, 0x0, 64 * 1024, 32, RD_NORM, 0}, + {"S25FL032A", 0x010215, 0x0, 64 * 1024, 64, RD_NORM, 0}, + {"S25FL064A", 0x010216, 0x0, 64 * 1024, 128, RD_NORM, 0}, {"S25FL128P_256K", 0x012018, 0x0300, 256 * 1024, 64, RD_FULL, WR_QPP}, {"S25FL128P_64K", 0x012018, 0x0301, 64 * 1024, 256, RD_FULL, WR_QPP}, {"S25FL032P", 0x010215, 0x4d00, 64 * 1024, 64, RD_FULL, WR_QPP}, @@ -64,17 +64,17 @@ const struct spi_flash_params spi_flash_params_table[] = { {"S25FL512S_512K", 0x010220, 0x4f00, 256 * 1024, 256, RD_FULL, WR_QPP}, #endif #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ - {"M25P10", 0x202011, 0x0, 32 * 1024, 4, 0, 0}, - {"M25P20", 0x202012, 0x0, 64 * 1024, 4, 0, 0}, - {"M25P40", 0x202013, 0x0, 64 * 1024, 8, 0, 0}, - {"M25P80", 0x202014, 0x0, 64 * 1024, 16, 0, 0}, - {"M25P16", 0x202015, 0x0, 64 * 1024, 32, 0, 0}, - {"M25PE16", 0x208015, 0x1000, 64 * 1024, 32, 0, 0}, + {"M25P10", 0x202011, 0x0, 32 * 1024, 4, RD_NORM, 0}, + {"M25P20", 0x202012, 0x0, 64 * 1024, 4, RD_NORM, 0}, + {"M25P40", 0x202013, 0x0, 64 * 1024, 8, RD_NORM, 0}, + {"M25P80", 0x202014, 0x0, 64 * 1024, 16, RD_NORM, 0}, + {"M25P16", 0x202015, 0x0, 64 * 1024, 32, RD_NORM, 0}, + {"M25PE16", 0x208015, 0x1000, 64 * 1024, 32, RD_NORM, 0}, {"M25PX16", 0x207115, 0x1000, 64 * 1024, 32, RD_EXTN, 0}, - {"M25P32", 0x202016, 0x0, 64 * 1024, 64, 0, 0}, - {"M25P64", 0x202017, 0x0, 64 * 1024, 128, 0, 0}, - {"M25P128", 0x202018, 0x0, 256 * 1024, 64, 0, 0}, - {"M25PX64", 0x207117, 0x0, 64 * 1024, 128, 0, SECT_4K}, + {"M25P32", 0x202016, 0x0, 64 * 1024, 64, RD_NORM, 0}, + {"M25P64", 0x202017, 0x0, 64 * 1024, 128, RD_NORM, 0}, + {"M25P128", 0x202018, 0x0, 256 * 1024, 64, RD_NORM, 0}, + {"M25PX64", 0x207117, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, {"N25Q32", 0x20ba16, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, {"N25Q32A", 0x20bb16, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, {"N25Q64", 0x20ba17, 0x0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K}, @@ -89,25 +89,25 @@ const struct spi_flash_params spi_flash_params_table[] = { {"N25Q1024A", 0x20bb21, 0x0, 64 * 1024, 2048, RD_FULL, WR_QPP | E_FSR | SECT_4K}, #endif #ifdef CONFIG_SPI_FLASH_SST /* SST */ - {"SST25VF040B", 0xbf258d, 0x0, 64 * 1024, 8, 0, SECT_4K | SST_WP}, - {"SST25VF080B", 0xbf258e, 0x0, 64 * 1024, 16, 0, SECT_4K | SST_WP}, - {"SST25VF016B", 0xbf2541, 0x0, 64 * 1024, 32, 0, SECT_4K | SST_WP}, - {"SST25VF032B", 0xbf254a, 0x0, 64 * 1024, 64, 0, SECT_4K | SST_WP}, - {"SST25VF064C", 0xbf254b, 0x0, 64 * 1024, 128, 0, SECT_4K}, - {"SST25WF512", 0xbf2501, 0x0, 64 * 1024, 1, 0, SECT_4K | SST_WP}, - {"SST25WF010", 0xbf2502, 0x0, 64 * 1024, 2, 0, SECT_4K | SST_WP}, - {"SST25WF020", 0xbf2503, 0x0, 64 * 1024, 4, 0, SECT_4K | SST_WP}, - {"SST25WF040", 0xbf2504, 0x0, 64 * 1024, 8, 0, SECT_4K | SST_WP}, - {"SST25WF080", 0xbf2505, 0x0, 64 * 1024, 16, 0, SECT_4K | SST_WP}, + {"SST25VF040B", 0xbf258d, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K | SST_WP}, + {"SST25VF080B", 0xbf258e, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K | SST_WP}, + {"SST25VF016B", 0xbf2541, 0x0, 64 * 1024, 32, RD_NORM, SECT_4K | SST_WP}, + {"SST25VF032B", 0xbf254a, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K | SST_WP}, + {"SST25VF064C", 0xbf254b, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, + {"SST25WF512", 0xbf2501, 0x0, 64 * 1024, 1, RD_NORM, SECT_4K | SST_WP}, + {"SST25WF010", 0xbf2502, 0x0, 64 * 1024, 2, RD_NORM, SECT_4K | SST_WP}, + {"SST25WF020", 0xbf2503, 0x0, 64 * 1024, 4, RD_NORM, SECT_4K | SST_WP}, + {"SST25WF040", 0xbf2504, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K | SST_WP}, + {"SST25WF080", 0xbf2505, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K | SST_WP}, #endif #ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */ - {"W25P80", 0xef2014, 0x0, 64 * 1024, 16, 0, 0}, - {"W25P16", 0xef2015, 0x0, 64 * 1024, 32, 0, 0}, - {"W25P32", 0xef2016, 0x0, 64 * 1024, 64, 0, 0}, - {"W25X40", 0xef3013, 0x0, 64 * 1024, 8, 0, SECT_4K}, - {"W25X16", 0xef3015, 0x0, 64 * 1024, 32, 0, SECT_4K}, - {"W25X32", 0xef3016, 0x0, 64 * 1024, 64, 0, SECT_4K}, - {"W25X64", 0xef3017, 0x0, 64 * 1024, 128, 0, SECT_4K}, + {"W25P80", 0xef2014, 0x0, 64 * 1024, 16, RD_NORM, 0}, + {"W25P16", 0xef2015, 0x0, 64 * 1024, 32, RD_NORM, 0}, + {"W25P32", 0xef2016, 0x0, 64 * 1024, 64, RD_NORM, 0}, + {"W25X40", 0xef3013, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K}, + {"W25X16", 0xef3015, 0x0, 64 * 1024, 32, RD_NORM, SECT_4K}, + {"W25X32", 0xef3016, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K}, + {"W25X64", 0xef3017, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, {"W25Q80BL", 0xef4014, 0x0, 64 * 1024, 16, RD_FULL, WR_QPP | SECT_4K}, {"W25Q16CL", 0xef4015, 0x0, 64 * 1024, 32, RD_FULL, WR_QPP | SECT_4K}, {"W25Q32BV", 0xef4016, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 26364269be..7cde4c052a 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -24,6 +24,7 @@ DECLARE_GLOBAL_DATA_PTR; /* Read commands array */ static u8 spi_read_cmds_array[] = { CMD_READ_ARRAY_SLOW, + CMD_READ_ARRAY_FAST, CMD_READ_DUAL_OUTPUT_FAST, CMD_READ_DUAL_IO_FAST, CMD_READ_QUAD_OUTPUT_FAST, From b648742a17c16639976ac5b38f246cb0f7d41da5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 12 Dec 2014 19:36:12 +0530 Subject: [PATCH 05/26] spi: Fix flag collision for SST_WP At present SECT_4K is the same as SST_WP so we cannot tell these apart. Fix this so that the table in sf_params.c can be used correctly. Reported-by: Jens Rottmann Signed-off-by: Simon Glass Reviewed-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/sf_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index e159f04000..7218e697a0 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -41,6 +41,7 @@ enum { SECT_32K = 1 << 1, E_FSR = 1 << 2, WR_QPP = 1 << 3, + SST_WP = 1 << 4, }; #define SPI_FLASH_3B_ADDR_LEN 3 @@ -104,7 +105,6 @@ enum { /* SST specific */ #ifdef CONFIG_SPI_FLASH_SST -# define SST_WP 0x01 /* Supports AAI word program */ # define CMD_SST_BP 0x02 /* Byte Program */ # define CMD_SST_AAI_WP 0xAD /* Auto Address Incr Word Program */ From 74c2cee4e82bb71953267e87900e279ab5aa1dc3 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 19:36:13 +0530 Subject: [PATCH 06/26] spi: sf: Support byte program for sst spi flash Currently if SST flash advertises SST_WP flag in the params table the word program command (ADh) with auto address increment will be used for the flash write op. However some SPI controllers do not support the word program command (like the Intel ICH 7), the byte programm command (02h) has to be used. Signed-off-by: Bin Meng Acked-by: Simon Glass Tested-by: Simon Glass Reviewed-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/sf_internal.h | 2 ++ drivers/mtd/spi/sf_ops.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 7218e697a0..fb53cb0834 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -110,6 +110,8 @@ enum { int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, const void *buf); +int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, + const void *buf); #endif /** diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 759231f2e3..34bc54e73e 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -517,4 +517,35 @@ int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, spi_release_bus(flash->spi); return ret; } + +int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, + const void *buf) +{ + size_t actual; + int ret; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: Unable to claim SPI bus\n"); + return ret; + } + + for (actual = 0; actual < len; actual++) { + ret = sst_byte_write(flash, offset, buf + actual); + if (ret) { + debug("SF: sst byte program failed\n"); + break; + } + offset++; + } + + if (!ret) + ret = spi_flash_cmd_write_disable(flash); + + debug("SF: sst: program %s %zu bytes @ 0x%zx\n", + ret ? "failure" : "success", len, offset - actual); + + spi_release_bus(flash->spi); + return ret; +} #endif From 54ba653ab63b31c8f5405fb0ee9dfba05cbb1521 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Fri, 12 Dec 2014 19:36:14 +0530 Subject: [PATCH 07/26] sf: Enable byte program support Enabled byte program support for sst flashes in sf. Few controllers will only support BP, so this patch gives a tx transfer flag to set the BP so-that sf will operate on byte program transfer. A new TX operation mode SPI_OPM_TX_BP is introduced for such SPI controller to use byte program op for SST flash. Signed-off-by: Jagannadha Sutradharudu Teki Tested-by: Bin Meng --- drivers/mtd/spi/sf_internal.h | 5 ++++- drivers/mtd/spi/sf_params.c | 18 +++++++++--------- drivers/mtd/spi/sf_probe.c | 8 ++++++-- include/spi.h | 1 + 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index fb53cb0834..785f7a96fe 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -40,10 +40,13 @@ enum { SECT_4K = 1 << 0, SECT_32K = 1 << 1, E_FSR = 1 << 2, - WR_QPP = 1 << 3, + SST_BP = 1 << 3, SST_WP = 1 << 4, + WR_QPP = 1 << 5, }; +#define SST_WR (SST_BP | SST_WP) + #define SPI_FLASH_3B_ADDR_LEN 3 #define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) #define SPI_FLASH_16MB_BOUN 0x1000000 diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c index 0f1f837106..30875b3660 100644 --- a/drivers/mtd/spi/sf_params.c +++ b/drivers/mtd/spi/sf_params.c @@ -89,16 +89,16 @@ const struct spi_flash_params spi_flash_params_table[] = { {"N25Q1024A", 0x20bb21, 0x0, 64 * 1024, 2048, RD_FULL, WR_QPP | E_FSR | SECT_4K}, #endif #ifdef CONFIG_SPI_FLASH_SST /* SST */ - {"SST25VF040B", 0xbf258d, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K | SST_WP}, - {"SST25VF080B", 0xbf258e, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K | SST_WP}, - {"SST25VF016B", 0xbf2541, 0x0, 64 * 1024, 32, RD_NORM, SECT_4K | SST_WP}, - {"SST25VF032B", 0xbf254a, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K | SST_WP}, + {"SST25VF040B", 0xbf258d, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K | SST_WR}, + {"SST25VF080B", 0xbf258e, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K | SST_WR}, + {"SST25VF016B", 0xbf2541, 0x0, 64 * 1024, 32, RD_NORM, SECT_4K | SST_WR}, + {"SST25VF032B", 0xbf254a, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K | SST_WR}, {"SST25VF064C", 0xbf254b, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, - {"SST25WF512", 0xbf2501, 0x0, 64 * 1024, 1, RD_NORM, SECT_4K | SST_WP}, - {"SST25WF010", 0xbf2502, 0x0, 64 * 1024, 2, RD_NORM, SECT_4K | SST_WP}, - {"SST25WF020", 0xbf2503, 0x0, 64 * 1024, 4, RD_NORM, SECT_4K | SST_WP}, - {"SST25WF040", 0xbf2504, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K | SST_WP}, - {"SST25WF080", 0xbf2505, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K | SST_WP}, + {"SST25WF512", 0xbf2501, 0x0, 64 * 1024, 1, RD_NORM, SECT_4K | SST_WR}, + {"SST25WF010", 0xbf2502, 0x0, 64 * 1024, 2, RD_NORM, SECT_4K | SST_WR}, + {"SST25WF020", 0xbf2503, 0x0, 64 * 1024, 4, RD_NORM, SECT_4K | SST_WR}, + {"SST25WF040", 0xbf2504, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K | SST_WR}, + {"SST25WF080", 0xbf2505, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K | SST_WR}, #endif #ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */ {"W25P80", 0xef2014, 0x0, 64 * 1024, 16, RD_NORM, 0}, diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 7cde4c052a..ce9987fd1a 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -136,8 +136,12 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, #ifndef CONFIG_DM_SPI_FLASH flash->write = spi_flash_cmd_write_ops; #if defined(CONFIG_SPI_FLASH_SST) - if (params->flags & SST_WP) - flash->write = sst_write_wp; + if (params->flags & SST_WR) { + if (flash->spi->op_mode_tx & SPI_OPM_TX_BP) + flash->write = sst_write_bp; + else + flash->write = sst_write_wp; + } #endif flash->erase = spi_flash_cmd_erase_ops; flash->read = spi_flash_cmd_read_ops; diff --git a/include/spi.h b/include/spi.h index 5b7827113d..ec17bd0bcc 100644 --- a/include/spi.h +++ b/include/spi.h @@ -34,6 +34,7 @@ /* SPI TX operation modes */ #define SPI_OPM_TX_QPP (1 << 0) +#define SPI_OPM_TX_BP (1 << 1) /* SPI RX operation modes */ #define SPI_OPM_RX_AS (1 << 0) From fa388bca3eb3f81f6412c69f0e15ab05ad4918a7 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 19:36:15 +0530 Subject: [PATCH 08/26] x86: ich-spi: Set the rx operation mode for ich 7 ICH 7 SPI controller only supports array read command (03h). Fast array read command (0Bh) is not supported. Signed-off-by: Bin Meng Acked-by: Simon Glass Tested-by: Simon Glass Reviewed-by: Jagannadha Sutradharudu Teki --- drivers/spi/ich.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c index c4d3a291e8..b356411c36 100644 --- a/drivers/spi/ich.c +++ b/drivers/spi/ich.c @@ -141,6 +141,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, ich->slave.max_write_size = ctlr.databytes; ich->speed = max_hz; + /* ICH 7 SPI controller only supports array read command */ + if (ctlr.ich_version == 7) + ich->slave.op_mode_rx = SPI_OPM_RX_AS; + return &ich->slave; } From 996467172e29e28247d8e9a35ada43a1376b5883 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 19:36:16 +0530 Subject: [PATCH 09/26] x86: ich-spi: Set the tx operation mode for ich 7 ICH 7 SPI controller only supports byte program (02h) for SST flash. Word program (ADh) is not supported. Signed-off-by: Bin Meng Reviewed-by: Jagannadha Sutradharudu Teki --- drivers/spi/ich.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c index b356411c36..16730ec33f 100644 --- a/drivers/spi/ich.c +++ b/drivers/spi/ich.c @@ -141,9 +141,14 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, ich->slave.max_write_size = ctlr.databytes; ich->speed = max_hz; - /* ICH 7 SPI controller only supports array read command */ - if (ctlr.ich_version == 7) + /* + * ICH 7 SPI controller only supports array read command + * and byte program command for SST flash + */ + if (ctlr.ich_version == 7) { ich->slave.op_mode_rx = SPI_OPM_RX_AS; + ich->slave.op_mode_tx = SPI_OPM_TX_BP; + } return &ich->slave; } From 64542f4616c484142b90534f9f174a632d7d1904 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 21:05:19 +0800 Subject: [PATCH 10/26] x86: Make ROM_SIZE configurable in Kconfig Currently the ROM_SIZE is hardcoded to 8MB in arch/x86/Kconfig. This will not be the case when adding additional board support. Hence we make ROM_SIZE configurable (512KB/1MB/2MB/4MB/8MB/16MB) and have the board Kconfig file select the default ROM_SIZE. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/Kconfig | 78 +++++++++++++++++++++++++++- board/google/chromebook_link/Kconfig | 1 + 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 4f5ce38d6f..fdfb6187b8 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -61,9 +61,85 @@ config SMM_TSEG config SMM_TSEG_SIZE hex +config BOARD_ROMSIZE_KB_512 + bool +config BOARD_ROMSIZE_KB_1024 + bool +config BOARD_ROMSIZE_KB_2048 + bool +config BOARD_ROMSIZE_KB_4096 + bool +config BOARD_ROMSIZE_KB_8192 + bool +config BOARD_ROMSIZE_KB_16384 + bool + +choice + prompt "ROM chip size" + default UBOOT_ROMSIZE_KB_512 if BOARD_ROMSIZE_KB_512 + default UBOOT_ROMSIZE_KB_1024 if BOARD_ROMSIZE_KB_1024 + default UBOOT_ROMSIZE_KB_2048 if BOARD_ROMSIZE_KB_2048 + default UBOOT_ROMSIZE_KB_4096 if BOARD_ROMSIZE_KB_4096 + default UBOOT_ROMSIZE_KB_8192 if BOARD_ROMSIZE_KB_8192 + default UBOOT_ROMSIZE_KB_16384 if BOARD_ROMSIZE_KB_16384 + help + Select the size of the ROM chip you intend to flash U-Boot on. + + The build system will take care of creating a u-boot.rom file + of the matching size. + +config UBOOT_ROMSIZE_KB_512 + bool "512 KB" + help + Choose this option if you have a 512 KB ROM chip. + +config UBOOT_ROMSIZE_KB_1024 + bool "1024 KB (1 MB)" + help + Choose this option if you have a 1024 KB (1 MB) ROM chip. + +config UBOOT_ROMSIZE_KB_2048 + bool "2048 KB (2 MB)" + help + Choose this option if you have a 2048 KB (2 MB) ROM chip. + +config UBOOT_ROMSIZE_KB_4096 + bool "4096 KB (4 MB)" + help + Choose this option if you have a 4096 KB (4 MB) ROM chip. + +config UBOOT_ROMSIZE_KB_8192 + bool "8192 KB (8 MB)" + help + Choose this option if you have a 8192 KB (8 MB) ROM chip. + +config UBOOT_ROMSIZE_KB_16384 + bool "16384 KB (16 MB)" + help + Choose this option if you have a 16384 KB (16 MB) ROM chip. + +endchoice + +# Map the config names to an integer (KB). +config UBOOT_ROMSIZE_KB + int + default 512 if UBOOT_ROMSIZE_KB_512 + default 1024 if UBOOT_ROMSIZE_KB_1024 + default 2048 if UBOOT_ROMSIZE_KB_2048 + default 4096 if UBOOT_ROMSIZE_KB_4096 + default 8192 if UBOOT_ROMSIZE_KB_8192 + default 16384 if UBOOT_ROMSIZE_KB_16384 + +# Map the config names to a hex value (bytes). config ROM_SIZE hex - default 0x800000 + default 0x80000 if UBOOT_ROMSIZE_KB_512 + default 0x100000 if UBOOT_ROMSIZE_KB_1024 + default 0x200000 if UBOOT_ROMSIZE_KB_2048 + default 0x400000 if UBOOT_ROMSIZE_KB_4096 + default 0x800000 if UBOOT_ROMSIZE_KB_8192 + default 0xc00000 if UBOOT_ROMSIZE_KB_12288 + default 0x1000000 if UBOOT_ROMSIZE_KB_16384 config HAVE_INTEL_ME bool "Platform requires Intel Management Engine" diff --git a/board/google/chromebook_link/Kconfig b/board/google/chromebook_link/Kconfig index 3a4f557d30..7f79fd206f 100644 --- a/board/google/chromebook_link/Kconfig +++ b/board/google/chromebook_link/Kconfig @@ -19,6 +19,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy select SOUTHBRIDGE_INTEL_C216 select HAVE_ACPI_RESUME select MARK_GRAPHICS_MEM_WRCOMB + select BOARD_ROMSIZE_KB_8192 config MMCONF_BASE_ADDRESS hex From 673ed2f8c2e6b5526de929861d7dd42834c572fd Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 21:05:20 +0800 Subject: [PATCH 11/26] tools/ifdtool: Support writing multiple files (-w) simultaneously Currently ifdtool only supports writing one file (-w) at a time. This looks verbose when generating u-boot.rom for x86 targets. This change allows at most 16 files to be written simultaneously. Signed-off-by: Bin Meng Acked-by: Simon Glass --- tools/ifdtool.c | 31 ++++++++++++++++++++++++------- tools/ifdtool.h | 2 ++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/tools/ifdtool.c b/tools/ifdtool.c index a4b481fb60..f81e5c87c7 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -732,6 +732,7 @@ static void print_usage(const char *name) " -x | --extract: extract intel fd modules\n" " -i | --inject : inject file into region \n" " -w | --write : write file to appear at memory address \n" + " multiple files can be written simultaneously\n" " -s | --spifreq <20|33|50> set the SPI frequency\n" " -e | --em100 set SPI frequency to 20MHz and disable\n" " Dual Output Fast Read Support\n" @@ -782,7 +783,9 @@ int main(int argc, char *argv[]) char *addr_str = NULL; int region_type = -1, inputfreq = 0; enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ; - unsigned int addr = 0; + unsigned int addr[WRITE_MAX]; + char *wr_fname[WRITE_MAX]; + unsigned char wr_idx, wr_num = 0; int rom_size = -1; bool write_it; char *filename; @@ -886,11 +889,19 @@ int main(int argc, char *argv[]) break; case 'w': mode_write = 1; - if (get_two_words(optarg, &addr_str, &src_fname)) { - print_usage(argv[0]); - exit(EXIT_FAILURE); + if (wr_num < WRITE_MAX) { + if (get_two_words(optarg, &addr_str, + &wr_fname[wr_num])) { + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + addr[wr_num] = strtol(optarg, NULL, 0); + wr_num++; + } else { + fprintf(stderr, + "The number of files to write simultaneously exceeds the limitation (%d)\n", + WRITE_MAX); } - addr = strtol(optarg, NULL, 0); break; case 'x': mode_extract = 1; @@ -1002,8 +1013,14 @@ int main(int argc, char *argv[]) if (mode_inject) ret = inject_region(image, size, region_type, src_fname); - if (mode_write) - ret = write_data(image, size, addr, src_fname); + if (mode_write) { + for (wr_idx = 0; wr_idx < wr_num; wr_idx++) { + ret = write_data(image, size, + addr[wr_idx], wr_fname[wr_idx]); + if (ret) + break; + } + } if (mode_spifreq) set_spi_frequency(image, size, spifreq); diff --git a/tools/ifdtool.h b/tools/ifdtool.h index fbec421bee..0d0cc3685e 100644 --- a/tools/ifdtool.h +++ b/tools/ifdtool.h @@ -14,6 +14,8 @@ #define IFDTOOL_VERSION "1.1-U-Boot" +#define WRITE_MAX 16 + enum spi_frequency { SPI_FREQUENCY_20MHZ = 0, SPI_FREQUENCY_33MHZ = 1, From 7dfb172d67f8c665be7377b5507e43304166cad0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 13 Dec 2014 22:25:46 -0700 Subject: [PATCH 12/26] x86: ifdtool: Separate out filenames for -D and -i To allow these options to be specified together, separate them out. Change-Id: Ib93f11cd51eb3302127f4c82936ff2b44c88d5a2 Signed-off-by: Simon Glass --- tools/ifdtool.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/ifdtool.c b/tools/ifdtool.c index f81e5c87c7..4a27b82c2e 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -779,8 +779,8 @@ int main(int argc, char *argv[]) int mode_spifreq = 0, mode_em100 = 0, mode_locked = 0; int mode_unlocked = 0, mode_write = 0, mode_write_descriptor = 0; int create = 0; - char *region_type_string = NULL, *src_fname = NULL; - char *addr_str = NULL; + char *region_type_string = NULL, *inject_fname = NULL; + char *desc_fname = NULL, *addr_str = NULL; int region_type = -1, inputfreq = 0; enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ; unsigned int addr[WRITE_MAX]; @@ -823,14 +823,14 @@ int main(int argc, char *argv[]) break; case 'D': mode_write_descriptor = 1; - src_fname = optarg; + desc_fname = optarg; break; case 'e': mode_em100 = 1; break; case 'i': if (get_two_words(optarg, ®ion_type_string, - &src_fname)) { + &inject_fname)) { print_usage(argv[0]); exit(EXIT_FAILURE); } @@ -1008,10 +1008,10 @@ int main(int argc, char *argv[]) } if (mode_write_descriptor) - ret = write_data(image, size, -size, src_fname); + ret = write_data(image, size, -size, desc_fname); if (mode_inject) - ret = inject_region(image, size, region_type, src_fname); + ret = inject_region(image, size, region_type, inject_fname); if (mode_write) { for (wr_idx = 0; wr_idx < wr_num; wr_idx++) { From c7016234f77e3c46dab08f84399bcc4b48268c04 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 21:05:21 +0800 Subject: [PATCH 13/26] x86: Refactor u-boot.rom build rules Refactor u-boot.rom build rules by utilizing quiet_cmd_ and cmd_ macros. Also make writing mrc.bin and pci option rom to u-boot.rom optional and remove mrc.bin from its dependent file list as not every x86 board port needs mrc binary blob. Signed-off-by: Bin Meng Acked-by: Simon Glass --- Makefile | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index 63eccc2364..1560bff2d8 100644 --- a/Makefile +++ b/Makefile @@ -946,27 +946,33 @@ u-boot-nand.gph: u-boot.bin FORCE ifneq ($(CONFIG_X86_RESET_VECTOR),) rom: u-boot.rom FORCE -u-boot.rom: u-boot-x86-16bit.bin u-boot-dtb.bin \ - $(srctree)/board/$(BOARDDIR)/mrc.bin - $(objtree)/tools/ifdtool -c -r $(CONFIG_ROM_SIZE) u-boot.tmp - if [ -n "$(CONFIG_HAVE_INTEL_ME)" ]; then \ - $(objtree)/tools/ifdtool -D \ - $(srctree)/board/$(BOARDDIR)/descriptor.bin u-boot.tmp; \ - $(objtree)/tools/ifdtool \ - -i ME:$(srctree)/board/$(BOARDDIR)/me.bin u-boot.tmp; \ - fi - $(objtree)/tools/ifdtool -w \ - $(CONFIG_SYS_TEXT_BASE):$(objtree)/u-boot-dtb.bin u-boot.tmp - $(objtree)/tools/ifdtool -w \ - $(CONFIG_X86_MRC_START):$(srctree)/board/$(BOARDDIR)/mrc.bin \ - u-boot.tmp - $(objtree)/tools/ifdtool -w \ - $(CONFIG_SYS_X86_START16):$(objtree)/u-boot-x86-16bit.bin \ - u-boot.tmp - $(objtree)/tools/ifdtool -w \ - $(CONFIG_X86_OPTION_ROM_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_X86_OPTION_ROM_FILENAME) \ - u-boot.tmp - mv u-boot.tmp $@ +IFDTOOL=$(objtree)/tools/ifdtool +IFDTOOL_FLAGS = -w $(CONFIG_SYS_TEXT_BASE):$(objtree)/u-boot-dtb.bin +IFDTOOL_FLAGS += -w $(CONFIG_SYS_X86_START16):$(objtree)/u-boot-x86-16bit.bin + +ifneq ($(CONFIG_HAVE_INTEL_ME),) +IFDTOOL_ME_FLAGS = -D $(srctree)/board/$(BOARDDIR)/descriptor.bin +IFDTOOL_ME_FLAGS += -i ME:$(srctree)/board/$(BOARDDIR)/me.bin +endif + +ifneq ($(CONFIG_HAVE_MRC),) +IFDTOOL_FLAGS += -w $(CONFIG_X86_MRC_START):$(srctree)/board/$(BOARDDIR)/mrc.bin +endif + +ifneq ($(CONFIG_X86_OPTION_ROM_ADDR),) +IFDTOOL_FLAGS += -w $(CONFIG_X86_OPTION_ROM_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_X86_OPTION_ROM_FILENAME) +endif + +quiet_cmd_ifdtool = IFDTOOL $@ +cmd_ifdtool = $(IFDTOOL) -c -r $(CONFIG_ROM_SIZE) u-boot.tmp; +ifneq ($(CONFIG_HAVE_INTEL_ME),) +cmd_ifdtool += $(IFDTOOL) $(IFDTOOL_ME_FLAGS) u-boot.tmp; +endif +cmd_ifdtool += $(IFDTOOL) $(IFDTOOL_FLAGS) u-boot.tmp; +cmd_ifdtool += mv u-boot.tmp $@ + +u-boot.rom: u-boot-x86-16bit.bin u-boot-dtb.bin + $(call if_changed,ifdtool) OBJCOPYFLAGS_u-boot-x86-16bit.bin := -O binary -j .start16 -j .resetvec u-boot-x86-16bit.bin: u-boot FORCE From fe0c33a5acc8cc5400747200802089177bd94b58 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 21:05:22 +0800 Subject: [PATCH 14/26] x86: Clean up asm-offsets Move GD_BIST from lib/asm-offsets.c to arch/x86/lib/asm-offsets.c as it is x86 arch specific stuff. Also remove GENERATED_GD_RELOC_OFF which is not referenced anymore. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/start.S | 3 ++- arch/x86/lib/asm-offsets.c | 2 +- lib/asm-offsets.c | 3 --- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index b0d0ac0610..f9662fb203 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -1,5 +1,5 @@ /* - * U-boot - x86 Startup Code + * U-Boot - x86 Startup Code * * (C) Copyright 2008-2011 * Graeme Russ, @@ -17,6 +17,7 @@ #include #include #include +#include .section .text .code32 diff --git a/arch/x86/lib/asm-offsets.c b/arch/x86/lib/asm-offsets.c index d65c6ab1b0..50a488f4f1 100644 --- a/arch/x86/lib/asm-offsets.c +++ b/arch/x86/lib/asm-offsets.c @@ -17,6 +17,6 @@ int main(void) { - DEFINE(GENERATED_GD_RELOC_OFF, offsetof(gd_t, reloc_off)); + DEFINE(GD_BIST, offsetof(gd_t, arch.bist)); return 0; } diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c index 580f763da6..129bc3e2af 100644 --- a/lib/asm-offsets.c +++ b/lib/asm-offsets.c @@ -31,9 +31,6 @@ int main(void) #ifdef CONFIG_SYS_MALLOC_F_LEN DEFINE(GD_MALLOC_BASE, offsetof(struct global_data, malloc_base)); #endif -#ifdef CONFIG_X86 - DEFINE(GD_BIST, offsetof(struct global_data, arch.bist)); -#endif #if defined(CONFIG_ARM) From 2795573a8c9c62db7b4bcf4bddf54d73b6ae61d3 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 21:05:23 +0800 Subject: [PATCH 15/26] x86: ich6-gpio: Move setup_pch_gpios() to board support codes Movie setup_pch_gpios() in the ich6-gpio driver to the board support codes, so that the driver does not need to know any platform specific stuff (ie: include the platform specifc chipset header file). Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/include/asm/arch-coreboot/gpio.h | 3 ++ arch/x86/include/asm/arch-ivybridge/gpio.h | 3 ++ arch/x86/include/asm/gpio.h | 1 + board/coreboot/coreboot/coreboot.c | 6 +++ board/google/chromebook_link/link.c | 40 ++++++++++++++++ drivers/gpio/intel_ich6_gpio.c | 53 +--------------------- 6 files changed, 55 insertions(+), 51 deletions(-) diff --git a/arch/x86/include/asm/arch-coreboot/gpio.h b/arch/x86/include/asm/arch-coreboot/gpio.h index 4951a8c957..31edef9623 100644 --- a/arch/x86/include/asm/arch-coreboot/gpio.h +++ b/arch/x86/include/asm/arch-coreboot/gpio.h @@ -7,4 +7,7 @@ #ifndef _X86_ARCH_GPIO_H_ #define _X86_ARCH_GPIO_H_ +/* Where in config space is the register that points to the GPIO registers? */ +#define PCI_CFG_GPIOBASE 0x48 + #endif /* _X86_ARCH_GPIO_H_ */ diff --git a/arch/x86/include/asm/arch-ivybridge/gpio.h b/arch/x86/include/asm/arch-ivybridge/gpio.h index 4951a8c957..31edef9623 100644 --- a/arch/x86/include/asm/arch-ivybridge/gpio.h +++ b/arch/x86/include/asm/arch-ivybridge/gpio.h @@ -7,4 +7,7 @@ #ifndef _X86_ARCH_GPIO_H_ #define _X86_ARCH_GPIO_H_ +/* Where in config space is the register that points to the GPIO registers? */ +#define PCI_CFG_GPIOBASE 0x48 + #endif /* _X86_ARCH_GPIO_H_ */ diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h index 5540d422b4..1787e5210c 100644 --- a/arch/x86/include/asm/gpio.h +++ b/arch/x86/include/asm/gpio.h @@ -147,6 +147,7 @@ struct pch_gpio_map { } set3; }; +void setup_pch_gpios(u32 gpiobase, const struct pch_gpio_map *gpio); void ich_gpio_set_gpio_map(const struct pch_gpio_map *map); #endif /* _X86_GPIO_H_ */ diff --git a/board/coreboot/coreboot/coreboot.c b/board/coreboot/coreboot/coreboot.c index 0240c34581..b260f9a163 100644 --- a/board/coreboot/coreboot/coreboot.c +++ b/board/coreboot/coreboot/coreboot.c @@ -6,6 +6,7 @@ #include #include +#include int arch_early_init_r(void) { @@ -14,3 +15,8 @@ int arch_early_init_r(void) return 0; } + +void setup_pch_gpios(u32 gpiobase, const struct pch_gpio_map *gpio) +{ + return; +} diff --git a/board/google/chromebook_link/link.c b/board/google/chromebook_link/link.c index 1822237dd8..4d95c1c927 100644 --- a/board/google/chromebook_link/link.c +++ b/board/google/chromebook_link/link.c @@ -7,6 +7,9 @@ #include #include #include +#include +#include +#include int arch_early_init_r(void) { @@ -121,3 +124,40 @@ int board_early_init_f(void) return 0; } + +void setup_pch_gpios(u32 gpiobase, const struct pch_gpio_map *gpio) +{ + /* GPIO Set 1 */ + if (gpio->set1.level) + outl(*((u32 *)gpio->set1.level), gpiobase + GP_LVL); + if (gpio->set1.mode) + outl(*((u32 *)gpio->set1.mode), gpiobase + GPIO_USE_SEL); + if (gpio->set1.direction) + outl(*((u32 *)gpio->set1.direction), gpiobase + GP_IO_SEL); + if (gpio->set1.reset) + outl(*((u32 *)gpio->set1.reset), gpiobase + GP_RST_SEL1); + if (gpio->set1.invert) + outl(*((u32 *)gpio->set1.invert), gpiobase + GPI_INV); + if (gpio->set1.blink) + outl(*((u32 *)gpio->set1.blink), gpiobase + GPO_BLINK); + + /* GPIO Set 2 */ + if (gpio->set2.level) + outl(*((u32 *)gpio->set2.level), gpiobase + GP_LVL2); + if (gpio->set2.mode) + outl(*((u32 *)gpio->set2.mode), gpiobase + GPIO_USE_SEL2); + if (gpio->set2.direction) + outl(*((u32 *)gpio->set2.direction), gpiobase + GP_IO_SEL2); + if (gpio->set2.reset) + outl(*((u32 *)gpio->set2.reset), gpiobase + GP_RST_SEL2); + + /* GPIO Set 3 */ + if (gpio->set3.level) + outl(*((u32 *)gpio->set3.level), gpiobase + GP_LVL3); + if (gpio->set3.mode) + outl(*((u32 *)gpio->set3.mode), gpiobase + GPIO_USE_SEL3); + if (gpio->set3.direction) + outl(*((u32 *)gpio->set3.direction), gpiobase + GP_IO_SEL3); + if (gpio->set3.reset) + outl(*((u32 *)gpio->set3.reset), gpiobase + GP_RST_SEL3); +} diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c index 92c23aed4c..3433216cb6 100644 --- a/drivers/gpio/intel_ich6_gpio.c +++ b/drivers/gpio/intel_ich6_gpio.c @@ -34,16 +34,9 @@ #include #include #include -#ifdef CONFIG_X86_RESET_VECTOR -#include -#define SUPPORT_GPIO_SETUP -#endif #define GPIO_PER_BANK 32 -/* Where in config space is the register that points to the GPIO registers? */ -#define PCI_CFG_GPIOBASE 0x48 - struct ich6_bank_priv { /* These are I/O addresses */ uint32_t use_sel; @@ -51,52 +44,11 @@ struct ich6_bank_priv { uint32_t lvl; }; -#ifdef SUPPORT_GPIO_SETUP -static void setup_pch_gpios(const struct pch_gpio_map *gpio) -{ - u16 gpiobase = pci_read_config16(PCH_LPC_DEV, GPIO_BASE) & 0xfffc; - - /* GPIO Set 1 */ - if (gpio->set1.level) - outl(*((u32 *)gpio->set1.level), gpiobase + GP_LVL); - if (gpio->set1.mode) - outl(*((u32 *)gpio->set1.mode), gpiobase + GPIO_USE_SEL); - if (gpio->set1.direction) - outl(*((u32 *)gpio->set1.direction), gpiobase + GP_IO_SEL); - if (gpio->set1.reset) - outl(*((u32 *)gpio->set1.reset), gpiobase + GP_RST_SEL1); - if (gpio->set1.invert) - outl(*((u32 *)gpio->set1.invert), gpiobase + GPI_INV); - if (gpio->set1.blink) - outl(*((u32 *)gpio->set1.blink), gpiobase + GPO_BLINK); - - /* GPIO Set 2 */ - if (gpio->set2.level) - outl(*((u32 *)gpio->set2.level), gpiobase + GP_LVL2); - if (gpio->set2.mode) - outl(*((u32 *)gpio->set2.mode), gpiobase + GPIO_USE_SEL2); - if (gpio->set2.direction) - outl(*((u32 *)gpio->set2.direction), gpiobase + GP_IO_SEL2); - if (gpio->set2.reset) - outl(*((u32 *)gpio->set2.reset), gpiobase + GP_RST_SEL2); - - /* GPIO Set 3 */ - if (gpio->set3.level) - outl(*((u32 *)gpio->set3.level), gpiobase + GP_LVL3); - if (gpio->set3.mode) - outl(*((u32 *)gpio->set3.mode), gpiobase + GPIO_USE_SEL3); - if (gpio->set3.direction) - outl(*((u32 *)gpio->set3.direction), gpiobase + GP_IO_SEL3); - if (gpio->set3.reset) - outl(*((u32 *)gpio->set3.reset), gpiobase + GP_RST_SEL3); -} - /* TODO: Move this to device tree, or platform data */ void ich_gpio_set_gpio_map(const struct pch_gpio_map *map) { gd->arch.gpio_map = map; } -#endif /* SUPPORT_GPIO_SETUP */ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev) { @@ -198,12 +150,11 @@ static int ich6_gpio_probe(struct udevice *dev) struct gpio_dev_priv *uc_priv = dev->uclass_priv; struct ich6_bank_priv *bank = dev_get_priv(dev); -#ifdef SUPPORT_GPIO_SETUP if (gd->arch.gpio_map) { - setup_pch_gpios(gd->arch.gpio_map); + setup_pch_gpios(plat->base_addr, gd->arch.gpio_map); gd->arch.gpio_map = NULL; } -#endif + uc_priv->gpio_count = GPIO_PER_BANK; uc_priv->bank_name = plat->bank_name; bank->use_sel = plat->base_addr; From 568868dda9b8f8e901962231713fc0cb3f42c410 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 21:05:24 +0800 Subject: [PATCH 16/26] x86: Add Intel Crown Bay board dts file Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/dts/Makefile | 3 ++- arch/x86/dts/crownbay.dts | 53 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 arch/x86/dts/crownbay.dts diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile index bb3b116533..3b5d6dad46 100644 --- a/arch/x86/dts/Makefile +++ b/arch/x86/dts/Makefile @@ -1,6 +1,7 @@ dtb-y += link.dtb \ chromebook_link.dtb \ - alex.dtb + alex.dtb \ + crownbay.dtb targets += $(dtb-y) diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts new file mode 100644 index 0000000000..399dafb822 --- /dev/null +++ b/arch/x86/dts/crownbay.dts @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +/include/ "coreboot.dtsi" + +/ { + #address-cells = <1>; + #size-cells = <1>; + model = "Intel Crown Bay"; + compatible = "intel,crownbay", "intel,queensbay"; + + config { + silent_console = <0>; + }; + + gpioa { + compatible = "intel,ich6-gpio"; + u-boot,dm-pre-reloc; + reg = <0 0x20>; + bank-name = "A"; + }; + + gpiob { + compatible = "intel,ich6-gpio"; + u-boot,dm-pre-reloc; + reg = <0x20 0x20>; + bank-name = "B"; + }; + + serial { + reg = <0x3f8 8>; + clock-frequency = <115200>; + }; + + chosen { }; + memory { device_type = "memory"; reg = <0 0>; }; + + spi { + #address-cells = <1>; + #size-cells = <0>; + compatible = "intel,ich7"; + spi-flash@0 { + reg = <0>; + compatible = "sst,25vf016b", "spi-flash"; + memory-map = <0xffe00000 0x00200000>; + }; + }; +}; From a2927e09bccca5b665709d77fc54919292d4bcb7 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 21:05:25 +0800 Subject: [PATCH 17/26] x86: Add a simple superio driver for SMSC LPC47M On most x86 boards, the legacy serial ports (io address 0x3f8/0x2f8) are provided by a superio chip connected to the LPC bus. We must program the superio chip so that serial ports are available for us. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/include/asm/pnp_def.h | 90 ++++++++++++++++++++++++++++++++++ drivers/misc/Makefile | 1 + drivers/misc/smsc_lpc47m.c | 33 +++++++++++++ include/smsc_lpc47m.h | 19 +++++++ 4 files changed, 143 insertions(+) create mode 100644 arch/x86/include/asm/pnp_def.h create mode 100644 drivers/misc/smsc_lpc47m.c create mode 100644 include/smsc_lpc47m.h diff --git a/arch/x86/include/asm/pnp_def.h b/arch/x86/include/asm/pnp_def.h new file mode 100644 index 0000000000..24b038d26a --- /dev/null +++ b/arch/x86/include/asm/pnp_def.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * Adapted from coreboot src/include/device/pnp_def.h + * and arch/x86/include/arch/io.h + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _ASM_PNP_DEF_H_ +#define _ASM_PNP_DEF_H_ + +#include + +#define PNP_IDX_EN 0x30 +#define PNP_IDX_IO0 0x60 +#define PNP_IDX_IO1 0x62 +#define PNP_IDX_IO2 0x64 +#define PNP_IDX_IO3 0x66 +#define PNP_IDX_IRQ0 0x70 +#define PNP_IDX_IRQ1 0x72 +#define PNP_IDX_DRQ0 0x74 +#define PNP_IDX_DRQ1 0x75 +#define PNP_IDX_MSC0 0xf0 +#define PNP_IDX_MSC1 0xf1 + +/* Generic functions for pnp devices */ + +/* + * pnp device is a 16-bit integer composed of its i/o port address at high byte + * and logic function number at low byte. + */ +#define PNP_DEV(PORT, FUNC) (((PORT) << 8) | (FUNC)) + +static inline void pnp_write_config(uint16_t dev, uint8_t reg, uint8_t value) +{ + uint8_t port = dev >> 8; + + outb(reg, port); + outb(value, port + 1); +} + +static inline uint8_t pnp_read_config(uint16_t dev, uint8_t reg) +{ + uint8_t port = dev >> 8; + + outb(reg, port); + return inb(port + 1); +} + +static inline void pnp_set_logical_device(uint16_t dev) +{ + uint8_t device = dev & 0xff; + + pnp_write_config(dev, 0x07, device); +} + +static inline void pnp_set_enable(uint16_t dev, int enable) +{ + pnp_write_config(dev, PNP_IDX_EN, enable ? 1 : 0); +} + +static inline int pnp_read_enable(uint16_t dev) +{ + return !!pnp_read_config(dev, PNP_IDX_EN); +} + +static inline void pnp_set_iobase(uint16_t dev, uint8_t index, uint16_t iobase) +{ + pnp_write_config(dev, index + 0, (iobase >> 8) & 0xff); + pnp_write_config(dev, index + 1, iobase & 0xff); +} + +static inline uint16_t pnp_read_iobase(uint16_t dev, uint8_t index) +{ + return ((uint16_t)(pnp_read_config(dev, index)) << 8) | + pnp_read_config(dev, index + 1); +} + +static inline void pnp_set_irq(uint16_t dev, uint8_t index, unsigned irq) +{ + pnp_write_config(dev, index, irq); +} + +static inline void pnp_set_drq(uint16_t dev, uint8_t index, unsigned drq) +{ + pnp_write_config(dev, index, drq & 0xff); +} + +#endif /* _ASM_PNP_DEF_H_ */ diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 6fa836f206..a34972df4e 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_PDSP188x) += pdsp188x.o ifdef CONFIG_DM_I2C obj-$(CONFIG_SANDBOX) += i2c_eeprom_emul.o endif +obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o obj-$(CONFIG_STATUS_LED) += status_led.o obj-$(CONFIG_TWL4030_LED) += twl4030_led.o obj-$(CONFIG_FSL_IFC) += fsl_ifc.o diff --git a/drivers/misc/smsc_lpc47m.c b/drivers/misc/smsc_lpc47m.c new file mode 100644 index 0000000000..d51f8e3024 --- /dev/null +++ b/drivers/misc/smsc_lpc47m.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +static void pnp_enter_conf_state(u16 dev) +{ + u16 port = dev >> 8; + + outb(0x55, port); +} + +static void pnp_exit_conf_state(u16 dev) +{ + u16 port = dev >> 8; + + outb(0xaa, port); +} + +void lpc47m_enable_serial(u16 dev, u16 iobase) +{ + pnp_enter_conf_state(dev); + pnp_set_logical_device(dev); + pnp_set_enable(dev, 0); + pnp_set_iobase(dev, PNP_IDX_IO0, iobase); + pnp_set_enable(dev, 1); + pnp_exit_conf_state(dev); +} diff --git a/include/smsc_lpc47m.h b/include/smsc_lpc47m.h new file mode 100644 index 0000000000..bffd622f0f --- /dev/null +++ b/include/smsc_lpc47m.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SMSC_LPC47M_H_ +#define _SMSC_LPC47M_H_ + +/** + * Configure the base I/O port of the specified serial device and enable the + * serial device. + * + * @dev: High 8 bits = Super I/O port, low 8 bits = logical device number. + * @iobase: Processor I/O port address to assign to this serial device. + */ +void lpc47m_enable_serial(u16 dev, u16 iobase); + +#endif /* _SMSC_LPC47M_H_ */ From 936248d92f3afb6ec2447f3eccbf9b425dc14b66 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 21:05:26 +0800 Subject: [PATCH 18/26] x86: Add Intel Topcliff PCH device IDs Signed-off-by: Bin Meng Acked-by: Simon Glass --- include/pci_ids.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/pci_ids.h b/include/pci_ids.h index ee98bee443..26f4748685 100644 --- a/include/pci_ids.h +++ b/include/pci_ids.h @@ -2998,6 +2998,14 @@ #define PCI_DEVICE_ID_INTEL_82454NX 0x84cb #define PCI_DEVICE_ID_INTEL_84460GX 0x84ea #define PCI_DEVICE_ID_INTEL_IXP4XX 0x8500 +#define PCI_DEVICE_ID_INTEL_TCF_GBE 0x8802 +#define PCI_DEVICE_ID_INTEL_TCF_SDIO_0 0x8809 +#define PCI_DEVICE_ID_INTEL_TCF_SDIO_1 0x880a +#define PCI_DEVICE_ID_INTEL_TCF_SATA 0x880b +#define PCI_DEVICE_ID_INTEL_TCF_UART_0 0x8811 +#define PCI_DEVICE_ID_INTEL_TCF_UART_1 0x8812 +#define PCI_DEVICE_ID_INTEL_TCF_UART_2 0x8813 +#define PCI_DEVICE_ID_INTEL_TCF_UART_3 0x8814 #define PCI_DEVICE_ID_INTEL_IXP2800 0x9004 #define PCI_DEVICE_ID_INTEL_S21152BB 0xb152 From 7e7740397dc9405a8ed6299e8ebc8170142ccae7 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 21:05:27 +0800 Subject: [PATCH 19/26] x86: ich-spi: Add Intel Tunnel Creek SPI controller support Add Intel Tunnel Creek SPI controller support which is an ICH7 compatible device. Signed-off-by: Bin Meng Acked-by: Simon Glass --- drivers/spi/ich.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c index 16730ec33f..0379444872 100644 --- a/drivers/spi/ich.c +++ b/drivers/spi/ich.c @@ -167,7 +167,8 @@ void spi_free_slave(struct spi_slave *slave) */ static int get_ich_version(uint16_t device_id) { - if (device_id == PCI_DEVICE_ID_INTEL_TGP_LPC) + if (device_id == PCI_DEVICE_ID_INTEL_TGP_LPC || + device_id == PCI_DEVICE_ID_INTEL_ITC_LPC) return 7; if ((device_id >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN && From 752a0b085b0c595a5979f1bee89961cffd109461 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 21:05:28 +0800 Subject: [PATCH 20/26] x86: Initial import from Intel FSP release for Queensbay platform This is the initial import from Intel FSP release for Queensbay platform (Tunnel Creek processor and Topcliff Platform Controller Hub), which can be downloaded from Intel website. For more details, check http://www.intel.com/fsp. Note: U-Boot coding convention was applied to these codes, so it looks completely different from the original Intel release. Also update FSP support codes license header to use SPDX ID. Signed-off-by: Bin Meng --- arch/x86/cpu/queensbay/fsp_configs.c | 21 + arch/x86/cpu/queensbay/fsp_support.c | 405 ++++++++++++++++++ .../include/asm/arch-queensbay/fsp/fsp_api.h | 59 +++ .../asm/arch-queensbay/fsp/fsp_bootmode.h | 24 ++ .../include/asm/arch-queensbay/fsp/fsp_ffs.h | 158 +++++++ .../include/asm/arch-queensbay/fsp/fsp_fv.h | 137 ++++++ .../include/asm/arch-queensbay/fsp/fsp_hob.h | 310 ++++++++++++++ .../asm/arch-queensbay/fsp/fsp_infoheader.h | 36 ++ .../asm/arch-queensbay/fsp/fsp_platform.h | 19 + .../asm/arch-queensbay/fsp/fsp_support.h | 198 +++++++++ .../asm/arch-queensbay/fsp/fsp_types.h | 97 +++++ .../include/asm/arch-queensbay/fsp/fsp_vpd.h | 58 +++ 12 files changed, 1522 insertions(+) create mode 100644 arch/x86/cpu/queensbay/fsp_configs.c create mode 100644 arch/x86/cpu/queensbay/fsp_support.c create mode 100644 arch/x86/include/asm/arch-queensbay/fsp/fsp_api.h create mode 100644 arch/x86/include/asm/arch-queensbay/fsp/fsp_bootmode.h create mode 100644 arch/x86/include/asm/arch-queensbay/fsp/fsp_ffs.h create mode 100644 arch/x86/include/asm/arch-queensbay/fsp/fsp_fv.h create mode 100644 arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h create mode 100644 arch/x86/include/asm/arch-queensbay/fsp/fsp_infoheader.h create mode 100644 arch/x86/include/asm/arch-queensbay/fsp/fsp_platform.h create mode 100644 arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h create mode 100644 arch/x86/include/asm/arch-queensbay/fsp/fsp_types.h create mode 100644 arch/x86/include/asm/arch-queensbay/fsp/fsp_vpd.h diff --git a/arch/x86/cpu/queensbay/fsp_configs.c b/arch/x86/cpu/queensbay/fsp_configs.c new file mode 100644 index 0000000000..a7bb31407d --- /dev/null +++ b/arch/x86/cpu/queensbay/fsp_configs.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: Intel + */ + +#include +#include +#include "fsp_support.h" + +void update_fsp_upd(struct upd_region_t *fsp_upd) +{ + /* Override any UPD setting if required */ + + /* Uncomment the line below to enable DEBUG message */ + /* fsp_upd->serial_dbgport_type = 1; */ + + /* Examples on how to initialize the pointers in UPD region */ + /* fsp_upd->pcd_example = (EXAMPLE_DATA *)&example; */ +} diff --git a/arch/x86/cpu/queensbay/fsp_support.c b/arch/x86/cpu/queensbay/fsp_support.c new file mode 100644 index 0000000000..204803008a --- /dev/null +++ b/arch/x86/cpu/queensbay/fsp_support.c @@ -0,0 +1,405 @@ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: Intel + */ + +#include +#include +#include "fsp_support.h" + +/** + * Reads a 64-bit value from memory that may be unaligned. + * + * This function returns the 64-bit value pointed to by buf. The function + * guarantees that the read operation does not produce an alignment fault. + * + * If the buf is NULL, then ASSERT(). + * + * @buf: Pointer to a 64-bit value that may be unaligned. + * + * @return: The 64-bit value read from buf. + */ +static u64 read_unaligned64(const u64 *buf) +{ + ASSERT(buf != NULL); + + return *buf; +} + +/** + * Compares two GUIDs + * + * If the GUIDs are identical then TRUE is returned. + * If there are any bit differences in the two GUIDs, then FALSE is returned. + * + * If guid1 is NULL, then ASSERT(). + * If guid2 is NULL, then ASSERT(). + * + * @guid1: A pointer to a 128 bit GUID. + * @guid2: A pointer to a 128 bit GUID. + * + * @retval TRUE: guid1 and guid2 are identical. + * @retval FALSE: guid1 and guid2 are not identical. + */ +static unsigned char compare_guid(const struct efi_guid_t *guid1, + const struct efi_guid_t *guid2) +{ + u64 guid1_low; + u64 guid2_low; + u64 guid1_high; + u64 guid2_high; + + guid1_low = read_unaligned64((const u64 *)guid1); + guid2_low = read_unaligned64((const u64 *)guid2); + guid1_high = read_unaligned64((const u64 *)guid1 + 1); + guid2_high = read_unaligned64((const u64 *)guid2 + 1); + + return (unsigned char)(guid1_low == guid2_low && guid1_high == guid2_high); +} + +u32 __attribute__((optimize("O0"))) find_fsp_header(void) +{ + volatile register u8 *fsp asm("eax"); + + /* Initalize the FSP base */ + fsp = (u8 *)CONFIG_FSP_LOCATION; + + /* Check the FV signature, _FVH */ + if (((struct fv_header_t *)fsp)->sign == 0x4856465F) { + /* Go to the end of the FV header and align the address */ + fsp += ((struct fv_header_t *)fsp)->ext_hdr_off; + fsp += ((struct fv_ext_header_t *)fsp)->ext_hdr_size; + fsp = (u8 *)(((u32)fsp + 7) & 0xFFFFFFF8); + } else { + fsp = 0; + } + + /* Check the FFS GUID */ + if (fsp && + (((u32 *)&(((struct ffs_file_header_t *)fsp)->name))[0] == 0x912740BE) && + (((u32 *)&(((struct ffs_file_header_t *)fsp)->name))[1] == 0x47342284) && + (((u32 *)&(((struct ffs_file_header_t *)fsp)->name))[2] == 0xB08471B9) && + (((u32 *)&(((struct ffs_file_header_t *)fsp)->name))[3] == 0x0C3F3527)) { + /* Add the FFS header size to find the raw section header */ + fsp += sizeof(struct ffs_file_header_t); + } else { + fsp = 0; + } + + if (fsp && + ((struct raw_section_t *)fsp)->type == EFI_SECTION_RAW) { + /* Add the raw section header size to find the FSP header */ + fsp += sizeof(struct raw_section_t); + } else { + fsp = 0; + } + + return (u32)fsp; +} + +#ifdef __PRE_RAM__ +void fsp_continue(struct shared_data_t *shared_data, u32 status, void *hob_list) +{ + u32 stack_len; + u32 stack_base; + u32 stack_top; + + ASSERT(status == 0); + + /* Get the migrated stack in normal memory */ + stack_base = (u32)get_bootloader_tmp_mem(hob_list, &stack_len); + ASSERT(stack_base != 0); + stack_top = stack_base + stack_len - sizeof(u32); + + /* + * Old stack base is stored at the very end of the stack top, + * use it to calculate the migrated shared data base + */ + shared_data = (struct shared_data_t *)(stack_base + + ((u32)shared_data - *(u32 *)stack_top)); + + /* The boot loader main function entry */ + bl_main_continue(hob_list, shared_data); +} + +void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) +{ + struct shared_data_t shared_data; + fsp_init_f init; + struct fsp_init_params_t params; + struct fspinit_rtbuf_t rt_buf; + struct vpd_region_t *fsp_vpd; + struct fsp_header_t *fsp_hdr; + struct fsp_init_params_t *params_ptr; + struct upd_region_t *fsp_upd; + + fsp_hdr = (struct fsp_header_t *)find_fsp_header(); + if (fsp_hdr == NULL) { + /* No valid FSP info header was found */ + ASSERT(FALSE); + } + + fsp_upd = (struct upd_region_t *)&shared_data.fsp_upd; + memset((void *)&rt_buf, 0, sizeof(struct fspinit_rtbuf_t)); + + /* Reserve a gap in stack top */ + rt_buf.common.stack_top = (u32 *)stack_top - 32; + rt_buf.common.boot_mode = boot_mode; + rt_buf.common.upd_data = (struct upd_region_t *)fsp_upd; + + /* Get VPD region start */ + fsp_vpd = (struct vpd_region_t *)(fsp_hdr->img_base + + fsp_hdr->cfg_region_off); + + /* Verifify the VPD data region is valid */ + ASSERT((fsp_vpd->img_rev == VPD_IMAGE_REV) && + (fsp_vpd->sign == VPD_IMAGE_ID)); + + /* Copy default data from Flash */ + memcpy(fsp_upd, (void *)(fsp_hdr->img_base + fsp_vpd->upd_offset), + sizeof(struct upd_region_t)); + + /* Verifify the UPD data region is valid */ + ASSERT(fsp_upd->terminator == 0x55AA); + + /* Override any UPD setting if required */ + update_fsp_upd(fsp_upd); + + memset((void *)¶ms, 0, sizeof(struct fsp_init_params_t)); + params.nvs_buf = nvs_buf; + params.rt_buf = (struct fspinit_rtbuf_t *)&rt_buf; + params.continuation = (fsp_continuation_f)asm_continuation; + + init = (fsp_init_f)(fsp_hdr->img_base + fsp_hdr->fsp_init); + params_ptr = ¶ms; + + shared_data.fsp_hdr = fsp_hdr; + shared_data.stack_top = (u32 *)stack_top; + + /* + * Use ASM code to ensure the register value in EAX & ECX + * will be passed into BlContinuationFunc + */ + asm volatile ( + "pushl %0;" + "call *%%eax;" + ".global asm_continuation;" + "asm_continuation:;" + "popl %%eax;" /* pop out return address */ + "pushl %%ecx;" /* push shared_data pointer */ + "pushl %%eax;" /* push back return address */ + "jmp fsp_continue;" + : : "m"(params_ptr), "a"(init), "c"(&shared_data) + ); + + /* + * Should never get here. + * Control will continue from romstage_main_continue_asm. + * This line below is to prevent the compiler from optimizing + * structure intialization. + */ + init(¶ms); + + /* + * Should never return. + * Control will continue from ContinuationFunc + */ + ASSERT(FALSE); +} + +#else + +u32 fsp_notify(struct fsp_header_t *fsp_hdr, u32 phase) +{ + fsp_notify_f notify; + struct fsp_notify_params_t params; + u32 status; + + if (!fsp_hdr) + fsp_hdr = (struct fsp_header_t *)find_fsp_header(); + + if (fsp_hdr == NULL) { + /* No valid FSP info header */ + ASSERT(FALSE); + } + + notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify); + params.phase = phase; + status = notify(¶ms); + + return status; +} + +#endif /* __PRE_RAM__ */ + +u32 get_usable_lowmem_top(const void *hob_list) +{ + union hob_pointers_t hob; + phys_addr_t phys_start; + u32 top; + + /* Get the HOB list for processing */ + hob.raw = (void *)hob_list; + + /* * Collect memory ranges */ + top = 0x100000; + while (!END_OF_HOB(hob)) { + if (hob.hdr->type == HOB_TYPE_RES_DESC) { + if (hob.res_desc->type == RES_SYS_MEM) { + phys_start = hob.res_desc->phys_start; + /* Need memory above 1MB to be collected here */ + if (phys_start >= 0x100000 && + phys_start < (phys_addr_t)0x100000000) + top += (u32)(hob.res_desc->len); + } + } + hob.raw = GET_NEXT_HOB(hob); + } + + return top; +} + +u64 get_usable_highmem_top(const void *hob_list) +{ + union hob_pointers_t hob; + phys_addr_t phys_start; + u64 top; + + /* Get the HOB list for processing */ + hob.raw = (void *)hob_list; + + /* Collect memory ranges */ + top = 0x100000000; + while (!END_OF_HOB(hob)) { + if (hob.hdr->type == HOB_TYPE_RES_DESC) { + if (hob.res_desc->type == RES_SYS_MEM) { + phys_start = hob.res_desc->phys_start; + /* Need memory above 1MB to be collected here */ + if (phys_start >= (phys_addr_t)0x100000000) + top += (u32)(hob.res_desc->len); + } + } + hob.raw = GET_NEXT_HOB(hob); + } + + return top; +} + +u64 get_fsp_reserved_mem_from_guid(const void *hob_list, u64 *len, + struct efi_guid_t *guid) +{ + union hob_pointers_t hob; + + /* Get the HOB list for processing */ + hob.raw = (void *)hob_list; + + /* Collect memory ranges */ + while (!END_OF_HOB(hob)) { + if (hob.hdr->type == HOB_TYPE_RES_DESC) { + if (hob.res_desc->type == RES_MEM_RESERVED) { + if (compare_guid(&hob.res_desc->owner, guid)) { + if (len) + *len = (u32)(hob.res_desc->len); + + return (u64)(hob.res_desc->phys_start); + } + } + } + hob.raw = GET_NEXT_HOB(hob); + } + + return 0; +} + +u32 get_fsp_reserved_mem(const void *hob_list, u32 *len) +{ + const struct efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID; + u64 length; + u32 base; + + base = (u32)get_fsp_reserved_mem_from_guid(hob_list, + &length, (struct efi_guid_t *)&guid); + if ((len != 0) && (base != 0)) + *len = (u32)length; + + return base; +} + +u32 get_tseg_reserved_mem(const void *hob_list, u32 *len) +{ + const struct efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_TSEG_GUID; + u64 length; + u32 base; + + base = (u32)get_fsp_reserved_mem_from_guid(hob_list, + &length, (struct efi_guid_t *)&guid); + if ((len != 0) && (base != 0)) + *len = (u32)length; + + return base; +} + +void *get_next_hob(u16 type, const void *hob_list) +{ + union hob_pointers_t hob; + + ASSERT(hob_list != NULL); + + hob.raw = (u8 *)hob_list; + + /* Parse the HOB list until end of list or matching type is found */ + while (!END_OF_HOB(hob)) { + if (hob.hdr->type == type) + return hob.raw; + + hob.raw = GET_NEXT_HOB(hob); + } + + return NULL; +} + +void *get_next_guid_hob(const struct efi_guid_t *guid, const void *hob_list) +{ + union hob_pointers_t hob; + + hob.raw = (u8 *)hob_list; + while ((hob.raw = get_next_hob(HOB_TYPE_GUID_EXT, + hob.raw)) != NULL) { + if (compare_guid(guid, &hob.guid->name)) + break; + hob.raw = GET_NEXT_HOB(hob); + } + + return hob.raw; +} + +void *get_guid_hob_data(const void *hob_list, u32 *len, struct efi_guid_t *guid) +{ + u8 *guid_hob; + + guid_hob = get_next_guid_hob(guid, hob_list); + if (guid_hob == NULL) { + return NULL; + } else { + if (len) + *len = GET_GUID_HOB_DATA_SIZE(guid_hob); + + return GET_GUID_HOB_DATA(guid_hob); + } +} + +void *get_fsp_nvs_data(const void *hob_list, u32 *len) +{ + const struct efi_guid_t guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID; + + return get_guid_hob_data(hob_list, len, (struct efi_guid_t *)&guid); +} + +void *get_bootloader_tmp_mem(const void *hob_list, u32 *len) +{ + const struct efi_guid_t guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID; + + return get_guid_hob_data(hob_list, len, (struct efi_guid_t *)&guid); +} diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_api.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_api.h new file mode 100644 index 0000000000..25b938fb4b --- /dev/null +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_api.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: Intel + */ + +#ifndef __FSP_API_H__ +#define __FSP_API_H__ + +/* + * FspInit continuation function prototype. + * Control will be returned to this callback function after FspInit API call. + */ +typedef void (*fsp_continuation_f)(u32 status, void *hob_list); + +#pragma pack(1) + +struct fsp_init_params_t { + /* Non-volatile storage buffer pointer */ + void *nvs_buf; + /* Runtime buffer pointer */ + void *rt_buf; + /* Continuation function address */ + fsp_continuation_f continuation; +}; + +struct common_buf_t { + /* + * Stack top pointer used by the bootloader. The new stack frame will be + * set up at this location after FspInit API call. + */ + u32 *stack_top; + u32 boot_mode; /* Current system boot mode */ + void *upd_data; /* User platform configuraiton data region */ + u32 reserved[7]; /* Reserved */ +}; + +enum fsp_phase_t { + /* Notification code for post PCI enuermation */ + INIT_PHASE_PCI = 0x20, + /* Notification code before transfering control to the payload */ + INIT_PHASE_BOOT = 0x40 +}; + +struct fsp_notify_params_t { + /* Notification phase used for NotifyPhase API */ + enum fsp_phase_t phase; +}; + +#pragma pack() + +/* FspInit API function prototype */ +typedef u32 (*fsp_init_f)(struct fsp_init_params_t *param); + +/* FspNotify API function prototype */ +typedef u32 (*fsp_notify_f)(struct fsp_notify_params_t *param); + +#endif diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_bootmode.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_bootmode.h new file mode 100644 index 0000000000..c3f8b49471 --- /dev/null +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_bootmode.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: Intel + */ + +#ifndef __FSP_BOOT_MODE_H__ +#define __FSP_BOOT_MODE_H__ + +/* 0x21 - 0xf..f are reserved */ +#define BOOT_FULL_CONFIG 0x00 +#define BOOT_MINIMAL_CONFIG 0x01 +#define BOOT_NO_CONFIG_CHANGES 0x02 +#define BOOT_FULL_CONFIG_PLUS_DIAG 0x03 +#define BOOT_DEFAULT_SETTINGS 0x04 +#define BOOT_ON_S4_RESUME 0x05 +#define BOOT_ON_S5_RESUME 0x06 +#define BOOT_ON_S2_RESUME 0x10 +#define BOOT_ON_S3_RESUME 0x11 +#define BOOT_ON_FLASH_UPDATE 0x12 +#define BOOT_IN_RECOVERY_MODE 0x20 + +#endif diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_ffs.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_ffs.h new file mode 100644 index 0000000000..1f73680032 --- /dev/null +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_ffs.h @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: Intel + */ + +#ifndef __FSP_FFS_H__ +#define __FSP_FFS_H__ + +#pragma pack(1) + +/* Used to verify the integrity of the file */ +union ffs_integrity_t { + struct { + /* + * The IntegrityCheck.checksum.header field is an 8-bit + * checksum of the file header. The State and + * IntegrityCheck.checksum.file fields are assumed to be zero + * and the checksum is calculated such that the entire header + * sums to zero. + */ + u8 header; + /* + * If the FFS_ATTRIB_CHECKSUM (see definition below) bit of + * the Attributes field is set to one, the + * IntegrityCheck.checksum.file field is an 8-bit checksum of + * the file data. If the FFS_ATTRIB_CHECKSUM bit of the + * Attributes field is cleared to zero, the + * IntegrityCheck.checksum.file field must be initialized with + * a value of 0xAA. The IntegrityCheck.checksum.file field is + * valid any time the EFI_FILE_DATA_VALID bit is set in the + * State field. + */ + u8 file; + } checksum; + + /* This is the full 16 bits of the IntegrityCheck field */ + u16 checksum16; +}; + +/* + * Each file begins with the header that describe the + * contents and state of the files. + */ +struct ffs_file_header_t { + /* + * This GUID is the file name. + * It is used to uniquely identify the file. + */ + struct efi_guid_t name; + /* Used to verify the integrity of the file */ + union ffs_integrity_t integrity; + /* Identifies the type of file */ + u8 type; + /* Declares various file attribute bits */ + u8 attr; + /* The length of the file in bytes, including the FFS header */ + u8 size[3]; + /* + * Used to track the state of the file throughout the life of + * the file from creation to deletion. + */ + u8 state; +}; + +struct ffs_file_header2_t { + /* + * This GUID is the file name. It is used to uniquely identify the file. + * There may be only one instance of a file with the file name GUID of + * Name in any given firmware volume, except if the file type is + * EFI_FV_FILE_TYPE_FFS_PAD. + */ + struct efi_guid_t name; + /* Used to verify the integrity of the file */ + union ffs_integrity_t integrity; + /* Identifies the type of file */ + u8 type; + /* Declares various file attribute bits */ + u8 attr; + /* + * The length of the file in bytes, including the FFS header. + * The length of the file data is either + * (size - sizeof(struct ffs_file_header_t)). This calculation means a + * zero-length file has a size of 24 bytes, which is + * sizeof(struct ffs_file_header_t). Size is not required to be a + * multiple of 8 bytes. Given a file F, the next file header is located + * at the next 8-byte aligned firmware volume offset following the last + * byte of the file F. + */ + u8 size[3]; + /* + * Used to track the state of the file throughout the life of + * the file from creation to deletion. + */ + u8 state; + /* + * If FFS_ATTRIB_LARGE_FILE is set in attr, then ext_size exists + * and size must be set to zero. + * If FFS_ATTRIB_LARGE_FILE is not set then + * struct ffs_file_header_t is used. + */ + u32 ext_size; +}; + +/* + * Pseudo type. It is used as a wild card when retrieving sections. + * The section type EFI_SECTION_ALL matches all section types. + */ +#define EFI_SECTION_ALL 0x00 + +/* Encapsulation section Type values */ +#define EFI_SECTION_COMPRESSION 0x01 +#define EFI_SECTION_GUID_DEFINED 0x02 +#define EFI_SECTION_DISPOSABLE 0x03 + +/* Leaf section Type values */ +#define EFI_SECTION_PE32 0x10 +#define EFI_SECTION_PIC 0x11 +#define EFI_SECTION_TE 0x12 +#define EFI_SECTION_DXE_DEPEX 0x13 +#define EFI_SECTION_VERSION 0x14 +#define EFI_SECTION_USER_INTERFACE 0x15 +#define EFI_SECTION_COMPATIBILITY16 0x16 +#define EFI_SECTION_FIRMWARE_VOLUME_IMAGE 0x17 +#define EFI_SECTION_FREEFORM_SUBTYPE_GUID 0x18 +#define EFI_SECTION_RAW 0x19 +#define EFI_SECTION_PEI_DEPEX 0x1B +#define EFI_SECTION_SMM_DEPEX 0x1C + +/* Common section header */ +struct raw_section_t { + /* + * A 24-bit unsigned integer that contains the total size of + * the section in bytes, including the EFI_COMMON_SECTION_HEADER. + */ + u8 size[3]; + u8 type; +}; + +struct raw_section2_t { + /* + * A 24-bit unsigned integer that contains the total size of + * the section in bytes, including the EFI_COMMON_SECTION_HEADER. + */ + u8 size[3]; + u8 type; + /* + * If size is 0xFFFFFF, then ext_size contains the size of + * the section. If size is not equal to 0xFFFFFF, then this + * field does not exist. + */ + u32 ext_size; +}; + +#pragma pack() + +#endif diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_fv.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_fv.h new file mode 100644 index 0000000000..01300dba6c --- /dev/null +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_fv.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: Intel + */ + +#ifndef __FSP_FV___ +#define __FSP_FV___ + +/* Value of EFI_FV_FILE_ATTRIBUTES */ +#define EFI_FV_FILE_ATTR_ALIGNMENT 0x0000001F +#define EFI_FV_FILE_ATTR_FIXED 0x00000100 +#define EFI_FV_FILE_ATTR_MEMORY_MAPPED 0x00000200 + +/* Attributes bit definitions */ +#define EFI_FVB2_READ_DISABLED_CAP 0x00000001 +#define EFI_FVB2_READ_ENABLED_CAP 0x00000002 +#define EFI_FVB2_READ_STATUS 0x00000004 +#define EFI_FVB2_WRITE_DISABLED_CAP 0x00000008 +#define EFI_FVB2_WRITE_ENABLED_CAP 0x00000010 +#define EFI_FVB2_WRITE_STATUS 0x00000020 +#define EFI_FVB2_LOCK_CAP 0x00000040 +#define EFI_FVB2_LOCK_STATUS 0x00000080 +#define EFI_FVB2_STICKY_WRITE 0x00000200 +#define EFI_FVB2_MEMORY_MAPPED 0x00000400 +#define EFI_FVB2_ERASE_POLARITY 0x00000800 +#define EFI_FVB2_READ_LOCK_CAP 0x00001000 +#define EFI_FVB2_READ_LOCK_STATUS 0x00002000 +#define EFI_FVB2_WRITE_LOCK_CAP 0x00004000 +#define EFI_FVB2_WRITE_LOCK_STATUS 0x00008000 +#define EFI_FVB2_ALIGNMENT 0x001F0000 +#define EFI_FVB2_ALIGNMENT_1 0x00000000 +#define EFI_FVB2_ALIGNMENT_2 0x00010000 +#define EFI_FVB2_ALIGNMENT_4 0x00020000 +#define EFI_FVB2_ALIGNMENT_8 0x00030000 +#define EFI_FVB2_ALIGNMENT_16 0x00040000 +#define EFI_FVB2_ALIGNMENT_32 0x00050000 +#define EFI_FVB2_ALIGNMENT_64 0x00060000 +#define EFI_FVB2_ALIGNMENT_128 0x00070000 +#define EFI_FVB2_ALIGNMENT_256 0x00080000 +#define EFI_FVB2_ALIGNMENT_512 0x00090000 +#define EFI_FVB2_ALIGNMENT_1K 0x000A0000 +#define EFI_FVB2_ALIGNMENT_2K 0x000B0000 +#define EFI_FVB2_ALIGNMENT_4K 0x000C0000 +#define EFI_FVB2_ALIGNMENT_8K 0x000D0000 +#define EFI_FVB2_ALIGNMENT_16K 0x000E0000 +#define EFI_FVB2_ALIGNMENT_32K 0x000F0000 +#define EFI_FVB2_ALIGNMENT_64K 0x00100000 +#define EFI_FVB2_ALIGNMENT_128K 0x00110000 +#define EFI_FVB2_ALIGNMENT_256K 0x00120000 +#define EFI_FVB2_ALIGNMENT_512K 0x00130000 +#define EFI_FVB2_ALIGNMENT_1M 0x00140000 +#define EFI_FVB2_ALIGNMENT_2M 0x00150000 +#define EFI_FVB2_ALIGNMENT_4M 0x00160000 +#define EFI_FVB2_ALIGNMENT_8M 0x00170000 +#define EFI_FVB2_ALIGNMENT_16M 0x00180000 +#define EFI_FVB2_ALIGNMENT_32M 0x00190000 +#define EFI_FVB2_ALIGNMENT_64M 0x001A0000 +#define EFI_FVB2_ALIGNMENT_128M 0x001B0000 +#define EFI_FVB2_ALIGNMENT_256M 0x001C0000 +#define EFI_FVB2_ALIGNMENT_512M 0x001D0000 +#define EFI_FVB2_ALIGNMENT_1G 0x001E0000 +#define EFI_FVB2_ALIGNMENT_2G 0x001F0000 + +struct fv_blkmap_entry_t { + /* The number of sequential blocks which are of the same size */ + u32 num_blocks; + /* The size of the blocks */ + u32 length; +}; + +/* Describes the features and layout of the firmware volume */ +struct fv_header_t { + /* + * The first 16 bytes are reserved to allow for the reset vector of + * processors whose reset vector is at address 0. + */ + u8 zero_vec[16]; + /* + * Declares the file system with which the firmware volume + * is formatted. + */ + struct efi_guid_t fs_guid; + /* + * Length in bytes of the complete firmware volume, including + * the header. + */ + u64 fv_len; + /* Set to EFI_FVH_SIGNATURE */ + u32 sign; + /* + * Declares capabilities and power-on defaults for the firmware + * volume. + */ + u32 attr; + /* Length in bytes of the complete firmware volume header */ + u16 hdr_len; + /* + * A 16-bit checksum of the firmware volume header. + * A valid header sums to zero. + */ + u16 checksum; + /* + * Offset, relative to the start of the header, of the extended + * header (EFI_FIRMWARE_VOLUME_EXT_HEADER) or zero if there is + * no extended header. + */ + u16 ext_hdr_off; + /* This field must always be set to zero */ + u8 reserved[1]; + /* + * Set to 2. Future versions of this specification may define new + * header fields and will increment the Revision field accordingly. + */ + u8 rev; + /* + * An array of run-length encoded FvBlockMapEntry structures. + * The array is terminated with an entry of {0,0}. + */ + struct fv_blkmap_entry_t block_map[1]; +}; + +#define EFI_FVH_SIGNATURE SIGNATURE_32('_', 'F', 'V', 'H') + +/* Firmware Volume Header Revision definition */ +#define EFI_FVH_REVISION 0x02 + +/* Extension header pointed by ExtHeaderOffset of volume header */ +struct fv_ext_header_t { + /* firmware volume name */ + struct efi_guid_t fv_name; + /* Size of the rest of the extension header including this structure */ + u32 ext_hdr_size; +}; + +#endif diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h new file mode 100644 index 0000000000..44c0f905bb --- /dev/null +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: Intel + */ + +#ifndef __FSP_HOB_H__ +#define __FSP_HOB_H__ + +/* Type of HOB Header */ +#define HOB_TYPE_MEM_ALLOC 0x0002 +#define HOB_TYPE_RES_DESC 0x0003 +#define HOB_TYPE_GUID_EXT 0x0004 +#define HOB_TYPE_UNUSED 0xFFFE +#define HOB_TYPE_EOH 0xFFFF + +/* + * Describes the format and size of the data inside the HOB. + * All HOBs must contain this generic HOB header. + */ +struct hob_header_t { + u16 type; /* HOB type */ + u16 len; /* HOB length */ + u32 reserved; /* always zero */ +}; + +/* Enumeration of memory types introduced in UEFI */ +enum efi_mem_type_t { + EFI_RESERVED_MEMORY_TYPE, + /* + * The code portions of a loaded application. + * (Note that UEFI OS loaders are UEFI applications.) + */ + EFI_LOADER_CODE, + /* + * The data portions of a loaded application and + * the default data allocation type used by an application + * to allocate pool memory. + */ + EFI_LOADER_DATA, + /* The code portions of a loaded Boot Services Driver */ + EFI_BOOT_SERVICES_CODE, + /* + * The data portions of a loaded Boot Serves Driver and + * the default data allocation type used by a Boot Services + * Driver to allocate pool memory. + */ + EFI_BOOT_SERVICES_DATA, + /* The code portions of a loaded Runtime Services Driver */ + EFI_RUNTIME_SERVICES_CODE, + /* + * The data portions of a loaded Runtime Services Driver and + * the default data allocation type used by a Runtime Services + * Driver to allocate pool memory. + */ + EFI_RUNTIME_SERVICES_DATA, + /* Free (unallocated) memory */ + EFI_CONVENTIONAL_MEMORY, + /* Memory in which errors have been detected */ + EFI_UNUSABLE_MEMORY, + /* Memory that holds the ACPI tables */ + EFI_ACPI_RECLAIM_MEMORY, + /* Address space reserved for use by the firmware */ + EFI_ACPI_MEMORY_NVS, + /* + * Used by system firmware to request that a memory-mapped IO region + * be mapped by the OS to a virtual address so it can be accessed by + * EFI runtime services. + */ + EFI_MMAP_IO, + /* + * System memory-mapped IO region that is used to translate + * memory cycles to IO cycles by the processor. + */ + EFI_MMAP_IO_PORT, + /* + * Address space reserved by the firmware for code that is + * part of the processor. + */ + EFI_PAL_CODE, + EFI_MAX_MEMORY_TYPE +}; + +/* + * Describes all memory ranges used during the HOB producer phase that + * exist outside the HOB list. This HOB type describes how memory is used, + * not the physical attributes of memory. + */ +struct hob_mem_alloc_t { + struct hob_header_t hdr; + /* + * A GUID that defines the memory allocation region's type and purpose, + * as well as other fields within the memory allocation HOB. This GUID + * is used to define the additional data within the HOB that may be + * present for the memory allocation HOB. Type efi_guid_t is defined in + * InstallProtocolInterface() in the UEFI 2.0 specification. + */ + struct efi_guid_t name; + /* + * The base address of memory allocated by this HOB. + * Type phys_addr_t is defined in AllocatePages() in the UEFI 2.0 + * specification. + */ + phys_addr_t mem_base; + /* The length in bytes of memory allocated by this HOB */ + phys_size_t mem_len; + /* + * Defines the type of memory allocated by this HOB. + * The memory type definition follows the EFI_MEMORY_TYPE definition. + * Type EFI_MEMORY_TYPE is defined in AllocatePages() in the UEFI 2.0 + * specification. + */ + enum efi_mem_type_t mem_type; + /* padding */ + u8 reserved[4]; +}; + +/* Value of ResourceType in HOB_RES_DESC */ +#define RES_SYS_MEM 0x00000000 +#define RES_MMAP_IO 0x00000001 +#define RES_IO 0x00000002 +#define RES_FW_DEVICE 0x00000003 +#define RES_MMAP_IO_PORT 0x00000004 +#define RES_MEM_RESERVED 0x00000005 +#define RES_IO_RESERVED 0x00000006 +#define RES_MAX_MEM_TYPE 0x00000007 + +/* + * These types can be ORed together as needed. + * + * The first three enumerations describe settings + * The rest of the settings describe capabilities + */ +#define RES_ATTR_PRESENT 0x00000001 +#define RES_ATTR_INITIALIZED 0x00000002 +#define RES_ATTR_TESTED 0x00000004 +#define RES_ATTR_SINGLE_BIT_ECC 0x00000008 +#define RES_ATTR_MULTIPLE_BIT_ECC 0x00000010 +#define RES_ATTR_ECC_RESERVED_1 0x00000020 +#define RES_ATTR_ECC_RESERVED_2 0x00000040 +#define RES_ATTR_READ_PROTECTED 0x00000080 +#define RES_ATTR_WRITE_PROTECTED 0x00000100 +#define RES_ATTR_EXECUTION_PROTECTED 0x00000200 +#define RES_ATTR_UNCACHEABLE 0x00000400 +#define RES_ATTR_WRITE_COMBINEABLE 0x00000800 +#define RES_ATTR_WRITE_THROUGH_CACHEABLE 0x00001000 +#define RES_ATTR_WRITE_BACK_CACHEABLE 0x00002000 +#define RES_ATTR_16_BIT_IO 0x00004000 +#define RES_ATTR_32_BIT_IO 0x00008000 +#define RES_ATTR_64_BIT_IO 0x00010000 +#define RES_ATTR_UNCACHED_EXPORTED 0x00020000 + +/* + * Describes the resource properties of all fixed, nonrelocatable resource + * ranges found on the processor host bus during the HOB producer phase. + */ +struct hob_res_desc_t { + struct hob_header_t hdr; + /* + * A GUID representing the owner of the resource. This GUID is + * used by HOB consumer phase components to correlate device + * ownership of a resource. + */ + struct efi_guid_t owner; + u32 type; + u32 attr; + /* The physical start address of the resource region */ + phys_addr_t phys_start; + /* The number of bytes of the resource region */ + phys_size_t len; +}; + +/* + * Allows writers of executable content in the HOB producer phase to + * maintain and manage HOBs with specific GUID. + */ +struct hob_guid_t { + struct hob_header_t hdr; + /* A GUID that defines the contents of this HOB */ + struct efi_guid_t name; + /* GUID specific data goes here */ +}; + +/* Union of all the possible HOB Types */ +union hob_pointers_t { + struct hob_header_t *hdr; + struct hob_mem_alloc_t *mem_alloc; + struct hob_res_desc_t *res_desc; + struct hob_guid_t *guid; + u8 *raw; +}; + +/** + * Returns the type of a HOB. + * + * This macro returns the type field from the HOB header for the + * HOB specified by hob. + * + * @hob: A pointer to a HOB. + * + * @return: HOB type. + */ +#define GET_HOB_TYPE(hob) \ + ((*(struct hob_header_t **)&(hob))->type) + +/** + * Returns the length, in bytes, of a HOB. + * + * This macro returns the len field from the HOB header for the + * HOB specified by hob. + * + * @hob: A pointer to a HOB. + * + * @return: HOB length. + */ +#define GET_HOB_LENGTH(hob) \ + ((*(struct hob_header_t **)&(hob))->len) + +/** + * Returns a pointer to the next HOB in the HOB list. + * + * This macro returns a pointer to HOB that follows the HOB specified by hob + * in the HOB List. + * + * @hob: A pointer to a HOB. + * + * @return: A pointer to the next HOB in the HOB list. + */ +#define GET_NEXT_HOB(hob) \ + (void *)(*(u8 **)&(hob) + GET_HOB_LENGTH(hob)) + +/** + * Determines if a HOB is the last HOB in the HOB list. + * + * This macro determine if the HOB specified by hob is the last HOB in the + * HOB list. If hob is last HOB in the HOB list, then TRUE is returned. + * Otherwise, FALSE is returned. + * + * @hob: A pointer to a HOB. + * + * @retval TRUE: The HOB specified by hob is the last HOB in the HOB list. + * @retval FALSE: The HOB specified by hob is not the last HOB in the HOB list. + */ +#define END_OF_HOB(hob) (GET_HOB_TYPE(hob) == (u16)HOB_TYPE_EOH) + +/** + * Returns a pointer to data buffer from a HOB of type HOB_TYPE_GUID_EXT. + * + * This macro returns a pointer to the data buffer in a HOB specified by hob. + * hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT. + * + * @hob: A pointer to a HOB. + * + * @return: A pointer to the data buffer in a HOB. + */ +#define GET_GUID_HOB_DATA(hob) \ + (void *)(*(u8 **)&(hob) + sizeof(struct hob_guid_t)) + +/** + * Returns the size of the data buffer from a HOB of type HOB_TYPE_GUID_EXT. + * + * This macro returns the size, in bytes, of the data buffer in a HOB + * specified by hob. hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT. + * + * @hob: A pointer to a HOB. + * + * @return: The size of the data buffer. + */ +#define GET_GUID_HOB_DATA_SIZE(hob) \ + (u16)(GET_HOB_LENGTH(hob) - sizeof(struct hob_guid_t)) + +/* FSP specific GUID HOB definitions */ +#define FSP_HEADER_GUID \ + { \ + 0x912740be, 0x2284, 0x4734, \ + {0xb9, 0x71, 0x84, 0xb0, 0x27, 0x35, 0x3f, 0x0c} \ + } + +#define FSP_NON_VOLATILE_STORAGE_HOB_GUID \ + { \ + 0x721acf02, 0x4d77, 0x4c2a, \ + { 0xb3, 0xdc, 0x27, 0xb, 0x7b, 0xa9, 0xe4, 0xb0 } \ + } + +#define FSP_BOOTLOADER_TEMP_MEM_HOB_GUID \ + { \ + 0xbbcff46c, 0xc8d3, 0x4113, \ + { 0x89, 0x85, 0xb9, 0xd4, 0xf3, 0xb3, 0xf6, 0x4e } \ + } + +#define FSP_HOB_RESOURCE_OWNER_FSP_GUID \ + { \ + 0x69a79759, 0x1373, 0x4367, \ + { 0xa6, 0xc4, 0xc7, 0xf5, 0x9e, 0xfd, 0x98, 0x6e } \ + } + +#define FSP_HOB_RESOURCE_OWNER_TSEG_GUID \ + { \ + 0xd038747c, 0xd00c, 0x4980, \ + { 0xb3, 0x19, 0x49, 0x01, 0x99, 0xa4, 0x7d, 0x55 } \ + } + +#define FSP_HOB_RESOURCE_OWNER_GRAPHICS_GUID \ + { \ + 0x9c7c3aa7, 0x5332, 0x4917, \ + { 0x82, 0xb9, 0x56, 0xa5, 0xf3, 0xe6, 0x2a, 0x07 } \ + } + +#endif diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_infoheader.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_infoheader.h new file mode 100644 index 0000000000..ad78bcd988 --- /dev/null +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_infoheader.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: Intel + */ + +#ifndef _FSP_HEADER_H_ +#define _FSP_HEADER_H_ + +#define FSP_HEADER_OFF 0x94 /* Fixed FSP header offset in the FSP image */ + +#pragma pack(1) + +struct fsp_header_t { + u32 sign; /* 'FSPH' */ + u32 hdr_len; /* header length */ + u8 reserved1[3]; + u8 hdr_rev; /* header rev */ + u32 img_rev; /* image rev */ + char img_id[8]; /* signature string */ + u32 img_size; /* image size */ + u32 img_base; /* image base */ + u32 img_attr; /* image attribute */ + u32 cfg_region_off; /* configuration region offset */ + u32 cfg_region_size; /* configuration region size */ + u32 api_num; /* number of API entries */ + u32 fsp_tempram_init; /* tempram_init offset */ + u32 fsp_init; /* fsp_init offset */ + u32 fsp_notify; /* fsp_notify offset */ + u32 reserved2; +}; + +#pragma pack() + +#endif diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_platform.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_platform.h new file mode 100644 index 0000000000..a7b6e6b8e7 --- /dev/null +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_platform.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: Intel + */ + +#ifndef __FSP_PLATFORM_H__ +#define __FSP_PLATFORM_H__ + +#pragma pack(1) + +struct fspinit_rtbuf_t { + struct common_buf_t common; /* FSP common runtime data structure */ +}; + +#pragma pack() + +#endif diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h new file mode 100644 index 0000000000..3e53ea1cb9 --- /dev/null +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: Intel + */ + +#ifndef __FSP_SUPPORT_H__ +#define __FSP_SUPPORT_H__ + +#include "fsp_types.h" +#include "fsp_fv.h" +#include "fsp_ffs.h" +#include "fsp_api.h" +#include "fsp_hob.h" +#include "fsp_platform.h" +#include "fsp_infoheader.h" +#include "fsp_bootmode.h" +#include "fsp_vpd.h" + +struct shared_data_t { + struct fsp_header_t *fsp_hdr; + u32 *stack_top; + struct upd_region_t fsp_upd; +}; + +void asm_continuation(void); + +void bl_main_continue(void *hob_list, struct shared_data_t *shared_data); + +/** + * FSP Continuation function + * + * @shared_data: Shared data base before stack migration + * @status: Always 0 + * @hob_list: HOB list pointer + * + * @retval: Never returns + */ +void fsp_continue(struct shared_data_t *shared_data, u32 status, + void *hob_list); + +/** + * Find FSP header offset in FSP image + * + * If this function is called before the a stack is established, special care + * must be taken. First, it cannot declare any local variable using stack. + * Only register variable can be used here. Secondly, some compiler version + * will add prolog or epilog code for the C function. If so the function call + * may not work before stack is ready. GCC 4.8.1 has been verified to be + * working for the following code. + * + * @retval: the offset of FSP header. If signature is invalid, returns 0. + */ +u32 find_fsp_header(void); + +/** + * FSP initialization wrapper function. + * + * @stack_top: bootloader stack top address + * @boot_mode: boot mode defined in fsp_bootmode.h + * @nvs_buf: Non-volatile memory buffer pointer + */ +void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf); + +/** + * FSP notification wrapper function + * + * @fsp_hdr: Pointer to FSP information header + * @phase: FSP initialization phase defined in enum fsp_phase_t + * + * @retval: compatible status code with EFI_STATUS defined in PI spec + */ +u32 fsp_notify(struct fsp_header_t *fsp_hdr, u32 phase); + +/** + * This function retrieves the top of usable low memory. + * + * @hob_list: A HOB list pointer. + * + * @retval: Usable low memory top. + */ +u32 get_usable_lowmem_top(const void *hob_list); + +/** + * This function retrieves the top of usable high memory. + * + * @hob_list: A HOB list pointer. + * + * @retval: Usable high memory top. + */ +u64 get_usable_highmem_top(const void *hob_list); + +/** + * This function retrieves a special reserved memory region. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the GUID HOB data buffer length. + * If the GUID HOB is located, the length will be updated. + * @guid: A pointer to the owner guild. + * + * @retval: Reserved region start address. + * 0 if this region does not exist. + */ +u64 get_fsp_reserved_mem_from_guid(const void *hob_list, + u64 *len, struct efi_guid_t *guid); + +/** + * This function retrieves the FSP reserved normal memory. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the FSP reserved memory length buffer. + * If the GUID HOB is located, the length will be updated. + * @retval: FSP reserved memory base + * 0 if this region does not exist. + */ +u32 get_fsp_reserved_mem(const void *hob_list, u32 *len); + +/** + * This function retrieves the TSEG reserved normal memory. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the TSEG reserved memory length buffer. + * If the GUID HOB is located, the length will be updated. + * + * @retval NULL: Failed to find the TSEG reserved memory. + * @retval others: TSEG reserved memory base. + */ +u32 get_tseg_reserved_mem(const void *hob_list, u32 *len); + +/** + * Returns the next instance of a HOB type from the starting HOB. + * + * @type: HOB type to search + * @hob_list: A pointer to the HOB list + * + * @retval: A HOB object with matching type; Otherwise NULL. + */ +void *get_next_hob(u16 type, const void *hob_list); + +/** + * Returns the next instance of the matched GUID HOB from the starting HOB. + * + * @guid: GUID to search + * @hob_list: A pointer to the HOB list + * + * @retval: A HOB object with matching GUID; Otherwise NULL. + */ +void *get_next_guid_hob(const struct efi_guid_t *guid, const void *hob_list); + +/** + * This function retrieves a GUID HOB data buffer and size. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the GUID HOB data buffer length. + * If the GUID HOB is located, the length will be updated. + * @guid A pointer to HOB GUID. + * + * @retval NULL: Failed to find the GUID HOB. + * @retval others: GUID HOB data buffer pointer. + */ +void *get_guid_hob_data(const void *hob_list, u32 *len, + struct efi_guid_t *guid); + +/** + * This function retrieves FSP Non-volatile Storage HOB buffer and size. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the NVS data buffer length. + * If the HOB is located, the length will be updated. + * + * @retval NULL: Failed to find the NVS HOB. + * @retval others: FSP NVS data buffer pointer. + */ +void *get_fsp_nvs_data(const void *hob_list, u32 *len); + +/** + * This function retrieves Bootloader temporary stack buffer and size. + * + * @hob_list: A HOB list pointer. + * @len: A pointer to the bootloader temporary stack length. + * If the HOB is located, the length will be updated. + * + * @retval NULL: Failed to find the bootloader temporary stack HOB. + * @retval others: Bootloader temporary stackbuffer pointer. + */ +void *get_bootloader_tmp_mem(const void *hob_list, u32 *len); + +/** + * This function overrides the default configurations in the UPD data region. + * + * @fsp_upd: A pointer to the upd_region_t data strcture + * + * @return: None + */ +void update_fsp_upd(struct upd_region_t *fsp_upd); + +#endif diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_types.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_types.h new file mode 100644 index 0000000000..12ebbfdc1d --- /dev/null +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_types.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: Intel + */ + +#ifndef __FSP_TYPES_H__ +#define __FSP_TYPES_H__ + +/* + * Boolean true value. UEFI Specification defines this value to be 1, + * but this form is more portable. + */ +#define TRUE ((unsigned char)(1 == 1)) + +/* + * Boolean false value. UEFI Specification defines this value to be 0, + * but this form is more portable. + */ +#define FALSE ((unsigned char)(0 == 1)) + +/* 128 bit buffer containing a unique identifier value */ +struct efi_guid_t { + u32 data1; + u16 data2; + u16 data3; + u8 data4[8]; +}; + +/** + * Returns a 16-bit signature built from 2 ASCII characters. + * + * This macro returns a 16-bit value built from the two ASCII characters + * specified by A and B. + * + * @A: The first ASCII character. + * @B: The second ASCII character. + * + * @return: A 16-bit value built from the two ASCII characters specified by + * A and B. + */ +#define SIGNATURE_16(A, B) ((A) | (B << 8)) + +/** + * Returns a 32-bit signature built from 4 ASCII characters. + * + * This macro returns a 32-bit value built from the four ASCII characters + * specified by A, B, C, and D. + * + * @A: The first ASCII character. + * @B: The second ASCII character. + * @C: The third ASCII character. + * @D: The fourth ASCII character. + * + * @return: A 32-bit value built from the two ASCII characters specified by + * A, B, C and D. + */ +#define SIGNATURE_32(A, B, C, D) \ + (SIGNATURE_16(A, B) | (SIGNATURE_16(C, D) << 16)) + +/** + * Returns a 64-bit signature built from 8 ASCII characters. + * + * This macro returns a 64-bit value built from the eight ASCII characters + * specified by A, B, C, D, E, F, G,and H. + * + * @A: The first ASCII character. + * @B: The second ASCII character. + * @C: The third ASCII character. + * @D: The fourth ASCII character. + * @E: The fifth ASCII character. + * @F: The sixth ASCII character. + * @G: The seventh ASCII character. + * @H: The eighth ASCII character. + * + * @return: A 64-bit value built from the two ASCII characters specified by + * A, B, C, D, E, F, G and H. + */ +#define SIGNATURE_64(A, B, C, D, E, F, G, H) \ + (SIGNATURE_32(A, B, C, D) | ((u64)(SIGNATURE_32(E, F, G, H)) << 32)) + +/* Assertion for debug */ +#define ASSERT(exp) do { if (!(exp)) for (;;); } while (FALSE) + +/* + * Define FSP API return status code. + * Compatiable with EFI_STATUS defined in PI Spec. + */ +#define FSP_SUCCESS 0 +#define FSP_INVALID_PARAM 0x80000002 +#define FSP_UNSUPPORTED 0x80000003 +#define FSP_DEVICE_ERROR 0x80000007 +#define FSP_NOT_FOUND 0x8000000E +#define FSP_ALREADY_STARTED 0x80000014 + +#endif diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_vpd.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_vpd.h new file mode 100644 index 0000000000..11cc32f38a --- /dev/null +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_vpd.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2013, Intel Corporation + * Copyright (C) 2014, Bin Meng + * + * This file is automatically generated. Please do NOT modify !!! + * + * SPDX-License-Identifier: Intel + */ + +#ifndef __VPDHEADER_H__ +#define __VPDHEADER_H__ + +#pragma pack(1) + +struct upd_region_t { + u64 sign; /* Offset 0x0000 */ + u64 reserved; /* Offset 0x0008 */ + u8 dummy[240]; /* Offset 0x0010 */ + u8 hda_verb_header[12]; /* Offset 0x0100 */ + u32 hda_verb_length; /* Offset 0x010C */ + u8 hda_verb_data0[16]; /* Offset 0x0110 */ + u8 hda_verb_data1[16]; /* Offset 0x0120 */ + u8 hda_verb_data2[16]; /* Offset 0x0130 */ + u8 hda_verb_data3[16]; /* Offset 0x0140 */ + u8 hda_verb_data4[16]; /* Offset 0x0150 */ + u8 hda_verb_data5[16]; /* Offset 0x0160 */ + u8 hda_verb_data6[16]; /* Offset 0x0170 */ + u8 hda_verb_data7[16]; /* Offset 0x0180 */ + u8 hda_verb_data8[16]; /* Offset 0x0190 */ + u8 hda_verb_data9[16]; /* Offset 0x01A0 */ + u8 hda_verb_data10[16]; /* Offset 0x01B0 */ + u8 hda_verb_data11[16]; /* Offset 0x01C0 */ + u8 hda_verb_data12[16]; /* Offset 0x01D0 */ + u8 hda_verb_data13[16]; /* Offset 0x01E0 */ + u8 hda_verb_pad[47]; /* Offset 0x01F0 */ + u16 terminator; /* Offset 0x021F */ +}; + +#define VPD_IMAGE_ID 0x445056574F4E4E4D /* 'MNNOWVPD' */ +#define VPD_IMAGE_REV 0x00000301 + +struct vpd_region_t { + u64 sign; /* Offset 0x0000 */ + u32 img_rev; /* Offset 0x0008 */ + u32 upd_offset; /* Offset 0x000C */ + u8 unused[16]; /* Offset 0x0010 */ + u32 fsp_res_memlen; /* Offset 0x0020 */ + u8 disable_pcie1; /* Offset 0x0024 */ + u8 disable_pcie2; /* Offset 0x0025 */ + u8 disable_pcie3; /* Offset 0x0026 */ + u8 enable_azalia; /* Offset 0x0027 */ + u8 legacy_seg_decode; /* Offset 0x0028 */ + u8 pcie_port_ioh; /* Offset 0x0029 */ +}; + +#pragma pack() + +#endif From 8e04d4c537eca06112fc8508689eb6c75d1f518e Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 21:05:29 +0800 Subject: [PATCH 21/26] x86: queensbay: Adapt FSP support codes Use inline assembly codes to call FspNotify() to make sure parameters are passed on the stack as required by the FSP calling convention. Signed-off-by: Bin Meng --- arch/x86/cpu/queensbay/fsp_configs.c | 5 +-- arch/x86/cpu/queensbay/fsp_support.c | 39 ++++++++++++------- .../asm/arch-queensbay/fsp/fsp_support.h | 2 +- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/arch/x86/cpu/queensbay/fsp_configs.c b/arch/x86/cpu/queensbay/fsp_configs.c index a7bb31407d..aef18fcb59 100644 --- a/arch/x86/cpu/queensbay/fsp_configs.c +++ b/arch/x86/cpu/queensbay/fsp_configs.c @@ -5,9 +5,8 @@ * SPDX-License-Identifier: Intel */ -#include -#include -#include "fsp_support.h" +#include +#include void update_fsp_upd(struct upd_region_t *fsp_upd) { diff --git a/arch/x86/cpu/queensbay/fsp_support.c b/arch/x86/cpu/queensbay/fsp_support.c index 204803008a..df3bbd07c9 100644 --- a/arch/x86/cpu/queensbay/fsp_support.c +++ b/arch/x86/cpu/queensbay/fsp_support.c @@ -5,9 +5,9 @@ * SPDX-License-Identifier: Intel */ -#include -#include -#include "fsp_support.h" +#include +#include +#include /** * Reads a 64-bit value from memory that may be unaligned. @@ -99,13 +99,14 @@ u32 __attribute__((optimize("O0"))) find_fsp_header(void) return (u32)fsp; } -#ifdef __PRE_RAM__ void fsp_continue(struct shared_data_t *shared_data, u32 status, void *hob_list) { u32 stack_len; u32 stack_base; u32 stack_top; + post_code(POST_MRC); + ASSERT(status == 0); /* Get the migrated stack in normal memory */ @@ -121,7 +122,7 @@ void fsp_continue(struct shared_data_t *shared_data, u32 status, void *hob_list) ((u32)shared_data - *(u32 *)stack_top)); /* The boot loader main function entry */ - bl_main_continue(hob_list, shared_data); + fsp_init_done(hob_list); } void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) @@ -178,6 +179,8 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) shared_data.fsp_hdr = fsp_hdr; shared_data.stack_top = (u32 *)stack_top; + post_code(POST_PRE_MRC); + /* * Use ASM code to ensure the register value in EAX & ECX * will be passed into BlContinuationFunc @@ -187,11 +190,11 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) "call *%%eax;" ".global asm_continuation;" "asm_continuation:;" - "popl %%eax;" /* pop out return address */ - "pushl %%ecx;" /* push shared_data pointer */ - "pushl %%eax;" /* push back return address */ + "movl %%ebx, %%eax;" /* shared_data */ + "movl 4(%%esp), %%edx;" /* status */ + "movl 8(%%esp), %%ecx;" /* hob_list */ "jmp fsp_continue;" - : : "m"(params_ptr), "a"(init), "c"(&shared_data) + : : "m"(params_ptr), "a"(init), "b"(&shared_data) ); /* @@ -209,12 +212,11 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) ASSERT(FALSE); } -#else - u32 fsp_notify(struct fsp_header_t *fsp_hdr, u32 phase) { fsp_notify_f notify; struct fsp_notify_params_t params; + struct fsp_notify_params_t *params_ptr; u32 status; if (!fsp_hdr) @@ -227,13 +229,22 @@ u32 fsp_notify(struct fsp_header_t *fsp_hdr, u32 phase) notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify); params.phase = phase; - status = notify(¶ms); + params_ptr = ¶ms; + + /* + * Use ASM code to ensure correct parameter is on the stack for + * FspNotify as U-Boot is using different ABI from FSP + */ + asm volatile ( + "pushl %1;" /* push notify phase */ + "call *%%eax;" /* call FspNotify */ + "addl $4, %%esp;" /* clean up the stack */ + : "=a"(status) : "m"(params_ptr), "a"(notify), "m"(*params_ptr) + ); return status; } -#endif /* __PRE_RAM__ */ - u32 get_usable_lowmem_top(const void *hob_list) { union hob_pointers_t hob; diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h index 3e53ea1cb9..3296a2b389 100644 --- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h @@ -26,7 +26,7 @@ struct shared_data_t { void asm_continuation(void); -void bl_main_continue(void *hob_list, struct shared_data_t *shared_data); +void fsp_init_done(void *hob_list); /** * FSP Continuation function From 95a5a474665307f231c36d1896d1ca7c6c9680f9 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 21:05:30 +0800 Subject: [PATCH 22/26] x86: Add post failure codes for bist and car Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/ivybridge/cpu.c | 1 + arch/x86/include/asm/post.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index 60976db44d..969b07b059 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -263,6 +263,7 @@ static void enable_usb_bar(void) static int report_bist_failure(void) { if (gd->arch.bist != 0) { + post_code(POST_BIST_FAILURE); printf("BIST failed: %08x\n", gd->arch.bist); return -EFAULT; } diff --git a/arch/x86/include/asm/post.h b/arch/x86/include/asm/post.h index 6d2ae5dfe7..f49ce992d1 100644 --- a/arch/x86/include/asm/post.h +++ b/arch/x86/include/asm/post.h @@ -33,6 +33,8 @@ #define POST_LAPIC 0x30 #define POST_RAM_FAILURE 0xea +#define POST_BIST_FAILURE 0xeb +#define POST_CAR_FAILURE 0xec /* Output a post code using al - value must be 0 to 0xff */ #ifdef __ASSEMBLY__ From bceb9f0fc80c71b8b2a7371288199cdacca1bad9 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 21:05:31 +0800 Subject: [PATCH 23/26] x86: Support Intel FSP initialization path in start.S Per Intel FSP architecture specification, FSP provides 3 routines for bootloader to call. The first one is the TempRamInit (aka Cache-As-Ram initialization) and the second one is the FspInit which does the memory bring up (like MRC for other x86 targets) and chipset initialization. Those two routines have to be called before U-Boot jumping to board_init_f in start.S. The FspInit() will return several memory blocks called Hand Off Blocks (HOBs) whose format is described in Platform Initialization (PI) specification (part of the UEFI specication) to the bootloader. Save this HOB address to the U-Boot global data for later use. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/start.S | 14 ++++++++++++++ arch/x86/include/asm/global_data.h | 3 +++ arch/x86/lib/asm-offsets.c | 3 +++ 3 files changed, 20 insertions(+) diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index f9662fb203..125782cf27 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -75,6 +75,7 @@ early_board_init_ret: jmp car_init .globl car_init_ret car_init_ret: +#ifndef CONFIG_HAVE_FSP /* * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM, * or fully initialised SDRAM - we really don't care which) @@ -95,6 +96,12 @@ car_init_ret: #ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE subl $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp #endif +#else + /* + * When we get here after car_init, esp points to a temporary stack + * and esi holds the HOB list address returned by the FSP. + */ +#endif /* Reserve space on stack for global data */ subl $GENERATED_GBL_DATA_SIZE, %esp @@ -109,6 +116,13 @@ car_init_ret: movl %esp, %edi rep stosb +#ifdef CONFIG_HAVE_FSP + /* Store HOB list */ + movl %esp, %edx + addl $GD_HOB_LIST, %edx + movl %esi, (%edx) +#endif + /* Setup first parameter to setup_gdt, pointer to global_data */ movl %esp, %eax diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 48bbd1ae43..03d491a17f 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -47,6 +47,9 @@ struct arch_global_data { enum pei_boot_mode_t pei_boot_mode; const struct pch_gpio_map *gpio_map; /* board GPIO map */ struct memory_info meminfo; /* Memory information */ +#ifdef CONFIG_HAVE_FSP + void *hob_list; /* FSP HOB list */ +#endif }; #endif diff --git a/arch/x86/lib/asm-offsets.c b/arch/x86/lib/asm-offsets.c index 50a488f4f1..70ccf1b0b0 100644 --- a/arch/x86/lib/asm-offsets.c +++ b/arch/x86/lib/asm-offsets.c @@ -18,5 +18,8 @@ int main(void) { DEFINE(GD_BIST, offsetof(gd_t, arch.bist)); +#ifdef CONFIG_HAVE_FSP + DEFINE(GD_HOB_LIST, offsetof(gd_t, arch.hob_list)); +#endif return 0; } From ba7b38a5295d9bad1a95f53f0a3ade20441a3831 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Dec 2014 21:05:32 +0800 Subject: [PATCH 24/26] x86: Add a simple command to show FSP HOB information FSP builds a series of data structures called the Hand-Off-Blocks (HOBs) as it progresses through initializing the silicon. These data structures conform to the HOB format as described in the Platform Initialization (PI) specification Volume 3 Shared Architectual Elements specification, which is part of the UEFI specification. Create a simple command to parse the HOB list to display the HOB address, type and length in bytes. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/lib/Makefile | 1 + arch/x86/lib/cmd_hob.c | 67 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 arch/x86/lib/cmd_hob.c diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 55de788500..73262d7263 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -10,6 +10,7 @@ obj-y += bios_asm.o obj-y += bios_interrupts.o obj-$(CONFIG_CMD_BOOTM) += bootm.o obj-y += cmd_boot.o +obj-$(CONFIG_HAVE_FSP) += cmd_hob.o obj-y += gcc.o obj-y += init_helpers.o obj-y += interrupts.o diff --git a/arch/x86/lib/cmd_hob.c b/arch/x86/lib/cmd_hob.c new file mode 100644 index 0000000000..2fdff2bfc1 --- /dev/null +++ b/arch/x86/lib/cmd_hob.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2014, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static char *hob_type[] = { + "reserved", + "Hand-off", + "Memory Allocation", + "Resource Descriptor", + "GUID Extension", + "Firmware Volumn", + "CPU", + "Memory Pool", + "reserved", + "Firmware Volumn 2", + "Load PEIM Unused", + "UEFI Capsule", +}; + +int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + union hob_pointers_t hob; + u16 type; + char *desc; + int i = 0; + + hob.raw = (u8 *)gd->arch.hob_list; + + printf("HOB list address: 0x%08x\n\n", (unsigned int)hob.raw); + + printf("No. | Address | Type | Length in Bytes\n"); + printf("----|----------|---------------------|----------------\n"); + while (!END_OF_HOB(hob)) { + printf("%-3d | %08x | ", i, (unsigned int)hob.raw); + type = hob.hdr->type; + if (type == HOB_TYPE_UNUSED) + desc = "*Unused*"; + else if (type == HOB_TYPE_EOH) + desc = "**END OF HOB**"; + else if (type >= 0 && type <= ARRAY_SIZE(hob_type)) + desc = hob_type[type]; + else + desc = "!!!Invalid Type!!!"; + printf("%-19s | %-15d\n", desc, hob.hdr->len); + hob.raw = GET_NEXT_HOB(hob); + i++; + } + + return 0; +} + +/* -------------------------------------------------------------------- */ + +U_BOOT_CMD( + hob, 1, 1, do_hob, + "print FSP Hand-Off Block information", + "" +); From e6126a58720ed8e53de93883c3f1572ad3d7b7c3 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 3 Dec 2014 17:36:57 +0900 Subject: [PATCH 25/26] x86: move arch-specific asmlinkage to Commit 65dd74a674d6 (x86: ivybridge: Implement SDRAM init) introduced x86-specific asmlinkage into arch/x86/include/asm/config.h. Commit ed0a2fbf14f7 (x86: Add a definition of asmlinkage) added the same macro define again, this time, into include/common.h. (Please do not add arch-specific stuff to include/common.h any more; it is already too cluttered.) The generic asmlinkage is defined in . If you want to override it with an arch-specific one, the best way is to add it to like Linux Kernel. Signed-off-by: Masahiro Yamada Cc: Simon Glass Tested-by: Simon Glass --- arch/x86/include/asm/arch-ivybridge/pei_data.h | 2 ++ arch/x86/include/asm/config.h | 1 - arch/x86/include/asm/linkage.h | 6 ++++++ arch/x86/lib/bios.c | 1 + arch/x86/lib/bios.h | 2 ++ include/common.h | 3 --- include/linux/linkage.h | 2 ++ 7 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 arch/x86/include/asm/linkage.h diff --git a/arch/x86/include/asm/arch-ivybridge/pei_data.h b/arch/x86/include/asm/arch-ivybridge/pei_data.h index 5026c8bab3..94533368ea 100644 --- a/arch/x86/include/asm/arch-ivybridge/pei_data.h +++ b/arch/x86/include/asm/arch-ivybridge/pei_data.h @@ -7,6 +7,8 @@ #ifndef ASM_ARCH_PEI_DATA_H #define ASM_ARCH_PEI_DATA_H +#include + struct pch_usb3_controller_settings { /* 0: Disable, 1: Enable, 2: Auto, 3: Smart Auto */ uint16_t mode; diff --git a/arch/x86/include/asm/config.h b/arch/x86/include/asm/config.h index c97d988f3b..ff15828a71 100644 --- a/arch/x86/include/asm/config.h +++ b/arch/x86/include/asm/config.h @@ -10,6 +10,5 @@ #define CONFIG_SYS_GENERIC_BOARD #define CONFIG_LMB #define CONFIG_SYS_BOOT_RAMDISK_HIGH -#define asmlinkage __attribute__((regparm(0))) #endif diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h new file mode 100644 index 0000000000..bdca72eb6c --- /dev/null +++ b/arch/x86/include/asm/linkage.h @@ -0,0 +1,6 @@ +#ifndef _ASM_X86_LINKAGE_H +#define _ASM_X86_LINKAGE_H + +#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0))) + +#endif /* _ASM_X86_LINKAGE_H */ diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c index 298fca632c..d1f8933e12 100644 --- a/arch/x86/lib/bios.c +++ b/arch/x86/lib/bios.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/lib/bios.h b/arch/x86/lib/bios.h index 8491b4acdd..668f4b5525 100644 --- a/arch/x86/lib/bios.h +++ b/arch/x86/lib/bios.h @@ -10,6 +10,8 @@ #ifndef _X86_LIB_BIOS_H #define _X86_LIB_BIOS_H +#include + #define REALMODE_BASE 0x600 #ifdef __ASSEMBLY__ diff --git a/include/common.h b/include/common.h index 46f07fe173..4f2f303f33 100644 --- a/include/common.h +++ b/include/common.h @@ -73,9 +73,6 @@ typedef volatile unsigned char vu_char; #ifdef CONFIG_ARM #define asmlinkage /* nothing */ #endif -#ifdef CONFIG_X86 -#define asmlinkage __attribute__((regparm(0))) -#endif #ifdef CONFIG_BLACKFIN #include #endif diff --git a/include/linux/linkage.h b/include/linux/linkage.h index 7435fcd026..5797498adc 100644 --- a/include/linux/linkage.h +++ b/include/linux/linkage.h @@ -17,7 +17,9 @@ #define CPP_ASMLINKAGE #endif +#ifndef asmlinkage #define asmlinkage CPP_ASMLINKAGE +#endif #define SYMBOL_NAME_STR(X) #X #define SYMBOL_NAME(X) X From 7cbd74f7484e9a58f7109e74e81002fee029b2f7 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 3 Dec 2014 17:36:58 +0900 Subject: [PATCH 26/26] ARM: remove redundant asmlinkage define Use asmlinkage defined in include/linux/linkage.h if necessary. Actually no ARM board uses asmlinkage, so this commit has no impact. Signed-off-by: Masahiro Yamada Cc: Albert ARIBAUD --- include/common.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/common.h b/include/common.h index 4f2f303f33..80c348660d 100644 --- a/include/common.h +++ b/include/common.h @@ -70,9 +70,6 @@ typedef volatile unsigned char vu_char; #ifdef CONFIG_4xx #include #endif -#ifdef CONFIG_ARM -#define asmlinkage /* nothing */ -#endif #ifdef CONFIG_BLACKFIN #include #endif