From 49bbdae318e31758cab7ed15aa29abd8ad18de13 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Sat, 30 May 2015 15:02:39 +0800 Subject: MIPS: fix missing semicolon in cacheops.h Fix missing semicolon in cacheops.h introduced in commit 2b8bcc5a2 (MIPS: avoid .set ISA for cache operations) Signed-off-by: Tony Wu Cc: Paul Burton diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h index 75ec380..af2adc7 100644 --- a/arch/mips/include/asm/cacheops.h +++ b/arch/mips/include/asm/cacheops.h @@ -18,7 +18,7 @@ static inline void mips_cache(int op, const volatile void *addr) #ifdef __GCC_HAVE_BUILTIN_MIPS_CACHE __builtin_mips_cache(op, addr); #else - __asm__ __volatile__("cache %0, %1" : : "i"(op), "R"(addr)) + __asm__ __volatile__("cache %0, %1" : : "i"(op), "R"(addr)); #endif } -- cgit v0.10.2 From b11c5d1dc29e81326d1215011d19377737082aeb Mon Sep 17 00:00:00 2001 From: Daniel Schwierzeck Date: Wed, 1 Jul 2015 16:36:43 +0200 Subject: MIPS: change 'extern inline' to 'static inline' The kernel changed it a long time ago. Also this is now broken on gcc-5.x. Reported-by: Andy Kennedy Signed-off-by: Daniel Schwierzeck diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 3fa37f5..a7ab087 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -117,7 +117,7 @@ static inline void set_io_port_base(unsigned long base) * Change virtual addresses to physical addresses and vv. * These are trivial on the 1:1 Linux/MIPS mapping */ -extern inline phys_addr_t virt_to_phys(volatile void * address) +static inline phys_addr_t virt_to_phys(volatile void * address) { #ifndef CONFIG_64BIT return CPHYSADDR(address); @@ -126,7 +126,7 @@ extern inline phys_addr_t virt_to_phys(volatile void * address) #endif } -extern inline void * phys_to_virt(unsigned long address) +static inline void * phys_to_virt(unsigned long address) { #ifndef CONFIG_64BIT return (void *)KSEG0ADDR(address); @@ -138,7 +138,7 @@ extern inline void * phys_to_virt(unsigned long address) /* * IO bus memory addresses are also 1:1 with the physical address */ -extern inline unsigned long virt_to_bus(volatile void * address) +static inline unsigned long virt_to_bus(volatile void * address) { #ifndef CONFIG_64BIT return CPHYSADDR(address); @@ -147,7 +147,7 @@ extern inline unsigned long virt_to_bus(volatile void * address) #endif } -extern inline void * bus_to_virt(unsigned long address) +static inline void * bus_to_virt(unsigned long address) { #ifndef CONFIG_64BIT return (void *)KSEG0ADDR(address); @@ -165,12 +165,12 @@ extern unsigned long isa_slot_offset; extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags); #if 0 -extern inline void *ioremap(unsigned long offset, unsigned long size) +static inline void *ioremap(unsigned long offset, unsigned long size) { return __ioremap(offset, size, _CACHE_UNCACHED); } -extern inline void *ioremap_nocache(unsigned long offset, unsigned long size) +static inline void *ioremap_nocache(unsigned long offset, unsigned long size) { return __ioremap(offset, size, _CACHE_UNCACHED); } diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h index 7a28952..d56f73b 100644 --- a/arch/mips/include/asm/system.h +++ b/arch/mips/include/asm/system.h @@ -22,7 +22,7 @@ #include #endif -extern __inline__ void +static __inline__ void __sti(void) { __asm__ __volatile__( @@ -46,7 +46,7 @@ __sti(void) * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs * no nops at all. */ -extern __inline__ void +static __inline__ void __cli(void) { __asm__ __volatile__( @@ -207,7 +207,7 @@ do { \ * For 32 and 64 bit operands we can take advantage of ll and sc. * FIXME: This doesn't work for R3000 machines. */ -extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val) +static __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val) { #ifdef CONFIG_CPU_HAS_LLSC unsigned long dummy; -- cgit v0.10.2 From 137d5b9137e0eb4f543311cd1cf4a84ad913b409 Mon Sep 17 00:00:00 2001 From: Vikas Manocha Date: Thu, 2 Jul 2015 18:29:37 -0700 Subject: stv0991: enable saving enrironment in spi flash Signed-off-by: Vikas Manocha Reviewed-by: Jagannadh Teki diff --git a/configs/stv0991_defconfig b/configs/stv0991_defconfig index 8e8ce9f..731ede1 100644 --- a/configs/stv0991_defconfig +++ b/configs/stv0991_defconfig @@ -7,7 +7,6 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_PROMPT="Hit SPACE in %d seconds to stop autoboot.\n" CONFIG_AUTOBOOT_STOP_STR=" " # CONFIG_CMD_IMLS is not set -# CONFIG_CMD_SAVEENV is not set # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set CONFIG_NETDEVICES=y diff --git a/include/configs/stv0991.h b/include/configs/stv0991.h index 6379fd3..d498c12 100644 --- a/include/configs/stv0991.h +++ b/include/configs/stv0991.h @@ -23,7 +23,9 @@ #define PHYS_SDRAM_1_SIZE 0x00198000 #define CONFIG_ENV_SIZE 0x10000 -#define CONFIG_ENV_IS_IN_FLASH +#define CONFIG_ENV_IS_IN_SPI_FLASH +#define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE +#define CONFIG_ENV_OFFSET 0x30000 #define CONFIG_ENV_ADDR \ (PHYS_SDRAM_1_SIZE - CONFIG_ENV_SIZE) #define CONFIG_SYS_MAXARGS 16 -- cgit v0.10.2 From 5160faf8cd99b9f0b0f844760164b1eb8689c0c5 Mon Sep 17 00:00:00 2001 From: Vikas Manocha Date: Thu, 2 Jul 2015 18:29:38 -0700 Subject: stv0991: move OF_CONTROL config to defconfig Signed-off-by: Vikas Manocha Reviewed-by: Jagannadh Teki diff --git a/configs/stv0991_defconfig b/configs/stv0991_defconfig index 731ede1..3bdb1fc 100644 --- a/configs/stv0991_defconfig +++ b/configs/stv0991_defconfig @@ -11,3 +11,4 @@ CONFIG_AUTOBOOT_STOP_STR=" " # CONFIG_CMD_SETEXPR is not set CONFIG_NETDEVICES=y CONFIG_ETH_DESIGNWARE=y +CONFIG_OF_CONTROL=y diff --git a/include/configs/stv0991.h b/include/configs/stv0991.h index d498c12..ff82afc 100644 --- a/include/configs/stv0991.h +++ b/include/configs/stv0991.h @@ -75,6 +75,5 @@ #define CONFIG_BOOTCOMMAND "go 0x40040000" #define CONFIG_OF_SEPARATE -#define CONFIG_OF_CONTROL #define CONFIG_OF_LIBFDT #endif /* __CONFIG_H */ -- cgit v0.10.2 From f59fa3b1811370f979c80f46d839a09f60c49e43 Mon Sep 17 00:00:00 2001 From: Vikas Manocha Date: Thu, 2 Jul 2015 18:29:39 -0700 Subject: stv0991: remove define CONFIG_OF_SEPARATE from board file CONFIG_OF_SEPARATE is default define with CONFIG_OF_CONTROL, removing this define from the board file to avoid multiple definition warning. Signed-off-by: Vikas Manocha Reviewed-by: Jagannadh Teki diff --git a/include/configs/stv0991.h b/include/configs/stv0991.h index ff82afc..718ef40 100644 --- a/include/configs/stv0991.h +++ b/include/configs/stv0991.h @@ -74,6 +74,5 @@ #define CONFIG_BOOTDELAY 3 #define CONFIG_BOOTCOMMAND "go 0x40040000" -#define CONFIG_OF_SEPARATE #define CONFIG_OF_LIBFDT #endif /* __CONFIG_H */ -- cgit v0.10.2 From 54afb5002514f88c41f3d462d1e14715a40f4107 Mon Sep 17 00:00:00 2001 From: Vikas Manocha Date: Thu, 2 Jul 2015 18:29:40 -0700 Subject: stv0991: configure clock & pad muxing for qspi stv0991 has cadence qspi controller for flash interfacing, this patch configures the device pads & clock for the controller. Signed-off-by: Vikas Manocha Reviewed-by: Jagannadh Teki diff --git a/arch/arm/cpu/armv7/stv0991/clock.c b/arch/arm/cpu/armv7/stv0991/clock.c index 70b8a8d..26c0d36 100644 --- a/arch/arm/cpu/armv7/stv0991/clock.c +++ b/arch/arm/cpu/armv7/stv0991/clock.c @@ -33,7 +33,9 @@ void clock_setup(int peripheral) /* Clock selection for ethernet tx_clk & rx_clk*/ writel((readl(&stv0991_cgu_regs->eth_ctrl) & ETH_CLK_MASK) | ETH_CLK_CTRL, &stv0991_cgu_regs->eth_ctrl); - + break; + case QSPI_CLOCK_CFG: + writel(QSPI_CLK_CTRL, &stv0991_cgu_regs->qspi_freq); break; default: break; diff --git a/arch/arm/cpu/armv7/stv0991/pinmux.c b/arch/arm/cpu/armv7/stv0991/pinmux.c index 1d086a2..24c67fa 100644 --- a/arch/arm/cpu/armv7/stv0991/pinmux.c +++ b/arch/arm/cpu/armv7/stv0991/pinmux.c @@ -55,6 +55,11 @@ int stv0991_pinmux_config(int peripheral) ETH_M_VDD_CFG, &stv0991_creg->vdd_pad1); break; + case QSPI_CS_CLK_PAD: + writel((readl(&stv0991_creg->mux13) & FLASH_CS_NC_MASK) | + CFG_FLASH_CS_NC, &stv0991_creg->mux13); + writel((readl(&stv0991_creg->mux13) & FLASH_CLK_MASK) | + CFG_FLASH_CLK, &stv0991_creg->mux13); default: break; } diff --git a/arch/arm/include/asm/arch-stv0991/stv0991_cgu.h b/arch/arm/include/asm/arch-stv0991/stv0991_cgu.h index ddcbb57..f0045f3 100644 --- a/arch/arm/include/asm/arch-stv0991/stv0991_cgu.h +++ b/arch/arm/include/asm/arch-stv0991/stv0991_cgu.h @@ -113,4 +113,19 @@ struct stv0991_cgu_regs { #define ETH_CLK_CTRL (ETH_CLK_RX_EXT_PHY << RX_CLK_SHIFT \ | ETH_CLK_TX_EXT_PHY) +/* CGU qspi clock */ +#define DIV_HCLK1_SHIFT 9 +#define DIV_CRYP_SHIFT 6 +#define MDIV_QSPI_SHIFT 3 + +#define CLK_QSPI_OSC 0 +#define CLK_QSPI_MCLK 1 +#define CLK_QSPI_PLL1 2 +#define CLK_QSPI_PLL2 3 + +#define QSPI_CLK_CTRL (3 << DIV_HCLK1_SHIFT \ + | 1 << DIV_CRYP_SHIFT \ + | 0 << MDIV_QSPI_SHIFT \ + | CLK_QSPI_OSC) + #endif diff --git a/arch/arm/include/asm/arch-stv0991/stv0991_creg.h b/arch/arm/include/asm/arch-stv0991/stv0991_creg.h index c804eb5..737c952 100644 --- a/arch/arm/include/asm/arch-stv0991/stv0991_creg.h +++ b/arch/arm/include/asm/arch-stv0991/stv0991_creg.h @@ -49,6 +49,15 @@ struct stv0991_creg { u32 vdd_comp1; /* offset 0x400 */ }; +/* CREG MUX 13 register */ +#define FLASH_CS_NC_SHIFT 4 +#define FLASH_CS_NC_MASK ~(7 << FLASH_CS_NC_SHIFT) +#define CFG_FLASH_CS_NC (0 << FLASH_CS_NC_SHIFT) + +#define FLASH_CLK_SHIFT 0 +#define FLASH_CLK_MASK ~(7 << FLASH_CLK_SHIFT) +#define CFG_FLASH_CLK (0 << FLASH_CLK_SHIFT) + /* CREG MUX 12 register */ #define GPIOC_30_MUX_SHIFT 24 #define GPIOC_30_MUX_MASK ~(1 << GPIOC_30_MUX_SHIFT) diff --git a/arch/arm/include/asm/arch-stv0991/stv0991_periph.h b/arch/arm/include/asm/arch-stv0991/stv0991_periph.h index f728c83..725da83 100644 --- a/arch/arm/include/asm/arch-stv0991/stv0991_periph.h +++ b/arch/arm/include/asm/arch-stv0991/stv0991_periph.h @@ -18,6 +18,7 @@ enum periph_id { UART_GPIOC_30_31 = 0, UART_GPIOB_16_17, ETH_GPIOB_10_31_C_0_4, + QSPI_CS_CLK_PAD, PERIPH_ID_I2C0, PERIPH_ID_I2C1, PERIPH_ID_I2C2, @@ -39,6 +40,7 @@ enum periph_id { enum periph_clock { UART_CLOCK_CFG = 0, ETH_CLOCK_CFG, + QSPI_CLOCK_CFG, }; #endif /* __ASM_ARM_ARCH_PERIPH_H */ diff --git a/board/st/stv0991/stv0991.c b/board/st/stv0991/stv0991.c index 09f973f..add1ce1 100644 --- a/board/st/stv0991/stv0991.c +++ b/board/st/stv0991/stv0991.c @@ -55,12 +55,20 @@ int board_eth_enable(void) return 0; } +int board_qspi_enable(void) +{ + stv0991_pinmux_config(QSPI_CS_CLK_PAD); + clock_setup(QSPI_CLOCK_CFG); + return 0; +} + /* * Miscellaneous platform dependent initialisations */ int board_init(void) { board_eth_enable(); + board_qspi_enable(); return 0; } -- cgit v0.10.2 From e67abcaacb8271a58c1a5e5afb17475bd8c3deaf Mon Sep 17 00:00:00 2001 From: Vikas Manocha Date: Thu, 2 Jul 2015 18:29:41 -0700 Subject: stv0991: enable cadence qspi controller & spi flash This patch does all the board configurations required to use the qspi controller & attached spi flash memory. Signed-off-by: Vikas Manocha Reviewed-by: Jagannadh Teki diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 192d9cf..0d2a808 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -227,6 +227,9 @@ config TARGET_STV0991 select CPU_V7 select DM select DM_SERIAL + select DM_SPI + select DM_SPI_FLASH + select SPI_FLASH config TARGET_X600 bool "Support x600" diff --git a/include/configs/stv0991.h b/include/configs/stv0991.h index 718ef40..887f31a 100644 --- a/include/configs/stv0991.h +++ b/include/configs/stv0991.h @@ -75,4 +75,19 @@ #define CONFIG_BOOTCOMMAND "go 0x40040000" #define CONFIG_OF_LIBFDT + +/* ++ * QSPI support ++ */ +#ifdef CONFIG_OF_CONTROL /* QSPI is controlled via DT */ +#define CONFIG_CADENCE_QSPI +#define CONFIG_CQSPI_DECODER 0 +#define CONFIG_CQSPI_REF_CLK ((30/4)/2)*1000*1000 +#define CONFIG_CMD_SPI + +#define CONFIG_SPI_FLASH_STMICRO /* Micron/Numonyx flash */ +#define CONFIG_SPI_FLASH_WINBOND /* WINBOND */ +#define CONFIG_CMD_SF +#endif + #endif /* __CONFIG_H */ -- cgit v0.10.2 From 51d558392bc71f9cfb58ce5ea70975dee6bf6292 Mon Sep 17 00:00:00 2001 From: Vikas Manocha Date: Thu, 2 Jul 2015 18:29:42 -0700 Subject: stv0991: configure device tree for cadence qspi & flash This patch add the device tree entry for qspi controller & spi flash memory. Signed-off-by: Vikas Manocha Reviewed-by: Jagannadh Teki diff --git a/arch/arm/dts/stv0991.dts b/arch/arm/dts/stv0991.dts index b25c48b..3b1efca 100644 --- a/arch/arm/dts/stv0991.dts +++ b/arch/arm/dts/stv0991.dts @@ -20,4 +20,38 @@ reg = <0x80406000 0x1000>; clock = <2700000>; }; + + aliases { + spi0 = "/spi@80203000"; /* QSPI */ + }; + + qspi: spi@80203000 { + compatible = "cadence,qspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x80203000 0x100>, + <0x40000000 0x1000000>; + clocks = <3750000>; + ext-decoder = <0>; /* external decoder */ + num-cs = <4>; + fifo-depth = <256>; + bus-num = <0>; + status = "okay"; + + flash0: n25q32@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-flash"; + reg = <0>; /* chip select */ + spi-max-frequency = <50000000>; + m25p,fast-read; + page-size = <256>; + block-size = <16>; /* 2^16, 64KB */ + read-delay = <4>; /* delay value in read data capture register */ + tshsl-ns = <50>; + tsd2d-ns = <50>; + tchsh-ns = <4>; + tslch-ns = <4>; + }; + }; }; -- cgit v0.10.2 From c0535c0ef0b7e7a3e4c1011266bf26baf94fd4a3 Mon Sep 17 00:00:00 2001 From: Vikas Manocha Date: Thu, 2 Jul 2015 18:29:43 -0700 Subject: spi: cadence_qspi: move the sram partition in init There is no need to re-configure sram partition for every read/write for better full use of sram for read or write. This patch divides the half sram for read & half for write once at initialization. Signed-off-by: Vikas Manocha Tested-by: Stefan Roese Reviewed-by: Jagannadh Teki diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index 00a115f..fb78892 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -38,10 +38,7 @@ /* Controller sram size in word */ #define CQSPI_REG_SRAM_SIZE_WORD (128) -#define CQSPI_REG_SRAM_RESV_WORDS (2) -#define CQSPI_REG_SRAM_PARTITION_WR (1) -#define CQSPI_REG_SRAM_PARTITION_RD \ - (CQSPI_REG_SRAM_SIZE_WORD - CQSPI_REG_SRAM_RESV_WORDS) +#define CQSPI_REG_SRAM_PARTITION_RD (CQSPI_REG_SRAM_SIZE_WORD/2) #define CQSPI_REG_SRAM_THRESHOLD_WORDS (50) /* Transfer mode */ @@ -538,6 +535,10 @@ void cadence_qspi_apb_controller_init(struct cadence_spi_platdata *plat) /* Configure the remap address register, no remap */ writel(0, plat->regbase + CQSPI_REG_REMAP); + /* Indirect mode configurations */ + writel(CQSPI_REG_SRAM_PARTITION_RD, + plat->regbase + CQSPI_REG_SRAMPARTITION); + /* Disable all interrupts */ writel(0, plat->regbase + CQSPI_REG_IRQMASK); @@ -700,10 +701,6 @@ int cadence_qspi_apb_indirect_read_setup(struct cadence_spi_platdata *plat, writel(((u32)plat->ahbbase & CQSPI_INDIRECTTRIGGER_ADDR_MASK), plat->regbase + CQSPI_REG_INDIRECTTRIGGER); - /* Configure SRAM partition for read. */ - writel(CQSPI_REG_SRAM_PARTITION_RD, plat->regbase + - CQSPI_REG_SRAMPARTITION); - /* Configure the opcode */ rd_reg = cmdbuf[0] << CQSPI_REG_RD_INSTR_OPCODE_LSB; @@ -801,9 +798,6 @@ int cadence_qspi_apb_indirect_write_setup(struct cadence_spi_platdata *plat, writel(((u32)plat->ahbbase & CQSPI_INDIRECTTRIGGER_ADDR_MASK), plat->regbase + CQSPI_REG_INDIRECTTRIGGER); - writel(CQSPI_REG_SRAM_PARTITION_WR, - plat->regbase + CQSPI_REG_SRAMPARTITION); - /* Configure the opcode */ reg = cmdbuf[0] << CQSPI_REG_WR_INSTR_OPCODE_LSB; writel(reg, plat->regbase + CQSPI_REG_WR_INSTR); -- cgit v0.10.2 From 90a2f7171182f3b96c28b2dcff67b02a3164cdb1 Mon Sep 17 00:00:00 2001 From: Vikas Manocha Date: Thu, 2 Jul 2015 18:29:44 -0700 Subject: spi: cadence_qspi: get sram size from device tree sram size could be different on different socs, e.g. on stv0991 it is 256 while on altera platform it is 128. It is better to receive it from device tree. Signed-off-by: Vikas Manocha Tested-by: Stefan Roese Reviewed-by: Jagannadh Teki diff --git a/arch/arm/dts/socfpga.dtsi b/arch/arm/dts/socfpga.dtsi index bf791c5..9b12420 100644 --- a/arch/arm/dts/socfpga.dtsi +++ b/arch/arm/dts/socfpga.dtsi @@ -639,6 +639,7 @@ ext-decoder = <0>; /* external decoder */ num-cs = <4>; fifo-depth = <128>; + sram-size = <128>; bus-num = <2>; status = "disabled"; }; diff --git a/arch/arm/dts/stv0991.dts b/arch/arm/dts/stv0991.dts index 3b1efca..556df82 100644 --- a/arch/arm/dts/stv0991.dts +++ b/arch/arm/dts/stv0991.dts @@ -35,6 +35,7 @@ ext-decoder = <0>; /* external decoder */ num-cs = <4>; fifo-depth = <256>; + sram-size = <256>; bus-num = <0>; status = "okay"; diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index a75fc46..34a0f46 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -309,6 +309,7 @@ static int cadence_spi_ofdata_to_platdata(struct udevice *bus) plat->tsd2d_ns = fdtdec_get_int(blob, subnode, "tsd2d-ns", 255); plat->tchsh_ns = fdtdec_get_int(blob, subnode, "tchsh-ns", 20); plat->tslch_ns = fdtdec_get_int(blob, subnode, "tslch-ns", 20); + plat->sram_size = fdtdec_get_int(blob, node, "sram-size", 128); debug("%s: regbase=%p ahbbase=%p max-frequency=%d page-size=%d\n", __func__, plat->regbase, plat->ahbbase, plat->max_hz, diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h index c9a6142..98e57aa 100644 --- a/drivers/spi/cadence_qspi.h +++ b/drivers/spi/cadence_qspi.h @@ -25,6 +25,7 @@ struct cadence_spi_platdata { u32 tsd2d_ns; u32 tchsh_ns; u32 tslch_ns; + u32 sram_size; }; struct cadence_spi_priv { diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index fb78892..cbf0d42 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -36,9 +36,6 @@ #define CQSPI_FIFO_WIDTH (4) -/* Controller sram size in word */ -#define CQSPI_REG_SRAM_SIZE_WORD (128) -#define CQSPI_REG_SRAM_PARTITION_RD (CQSPI_REG_SRAM_SIZE_WORD/2) #define CQSPI_REG_SRAM_THRESHOLD_WORDS (50) /* Transfer mode */ @@ -536,8 +533,7 @@ void cadence_qspi_apb_controller_init(struct cadence_spi_platdata *plat) writel(0, plat->regbase + CQSPI_REG_REMAP); /* Indirect mode configurations */ - writel(CQSPI_REG_SRAM_PARTITION_RD, - plat->regbase + CQSPI_REG_SRAMPARTITION); + writel((plat->sram_size/2), plat->regbase + CQSPI_REG_SRAMPARTITION); /* Disable all interrupts */ writel(0, plat->regbase + CQSPI_REG_IRQMASK); -- cgit v0.10.2 From 70bb2b141573afd75cbc4b448e430814f3990b28 Mon Sep 17 00:00:00 2001 From: Vikas Manocha Date: Thu, 2 Jul 2015 18:29:45 -0700 Subject: spi: cadence_qspi: support FIFO width other than 4 bytes This patch makes the code compatible with FIFO depths other than 4 bytes. It also simplify read/write FIFO loops. Signed-off-by: Vikas Manocha Tested-by: Stefan Roese Reviewed-by: Jagannadh Teki diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index cbf0d42..d053407 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -200,18 +200,16 @@ static void cadence_qspi_apb_read_fifo_data(void *dest, unsigned int *dest_ptr = (unsigned int *)dest; unsigned int *src_ptr = (unsigned int *)src_ahb_addr; - while (remaining > 0) { - if (remaining >= CQSPI_FIFO_WIDTH) { - *dest_ptr = readl(src_ptr); - remaining -= CQSPI_FIFO_WIDTH; - } else { - /* dangling bytes */ - temp = readl(src_ptr); - memcpy(dest_ptr, &temp, remaining); - break; - } + while (remaining >= sizeof(dest_ptr)) { + *dest_ptr = readl(src_ptr); + remaining -= sizeof(src_ptr); dest_ptr++; } + if (remaining) { + /* dangling bytes */ + temp = readl(src_ptr); + memcpy(dest_ptr, &temp, remaining); + } return; } @@ -219,24 +217,26 @@ static void cadence_qspi_apb_read_fifo_data(void *dest, static void cadence_qspi_apb_write_fifo_data(const void *dest_ahb_addr, const void *src, unsigned int bytes) { - unsigned int temp; + unsigned int temp = 0; + int i; int remaining = bytes; unsigned int *dest_ptr = (unsigned int *)dest_ahb_addr; unsigned int *src_ptr = (unsigned int *)src; - while (remaining > 0) { - if (remaining >= CQSPI_FIFO_WIDTH) { - writel(*src_ptr, dest_ptr); - remaining -= sizeof(unsigned int); - } else { - /* dangling bytes */ - memcpy(&temp, src_ptr, remaining); - writel(temp, dest_ptr); - break; - } - src_ptr++; + while (remaining >= CQSPI_FIFO_WIDTH) { + for (i = CQSPI_FIFO_WIDTH/sizeof(src_ptr) - 1; i >= 0; i--) + writel(*(src_ptr+i), dest_ptr+i); + src_ptr += CQSPI_FIFO_WIDTH/sizeof(src_ptr); + remaining -= CQSPI_FIFO_WIDTH; + } + if (remaining) { + /* dangling bytes */ + i = remaining/sizeof(dest_ptr); + memcpy(&temp, src_ptr+i, remaining % sizeof(dest_ptr)); + writel(temp, dest_ptr+i); + for (--i; i >= 0; i--) + writel(*(src_ptr+i), dest_ptr+i); } - return; } -- cgit v0.10.2 From 8097cba809d8c40d8fe72f792c7dc0644c845a32 Mon Sep 17 00:00:00 2001 From: Vikas Manocha Date: Thu, 2 Jul 2015 18:29:46 -0700 Subject: spi: cadence_qspi: add device tree binding doc This patch adds the device tree binding doc for the cadence qspi controller & also removes the not needed properties from the stv0991 device tree. Signed-off-by: Vikas Manocha Reviewed-by: Jagannadh Teki diff --git a/arch/arm/dts/stv0991.dts b/arch/arm/dts/stv0991.dts index 556df82..fa3fd64 100644 --- a/arch/arm/dts/stv0991.dts +++ b/arch/arm/dts/stv0991.dts @@ -32,11 +32,7 @@ reg = <0x80203000 0x100>, <0x40000000 0x1000000>; clocks = <3750000>; - ext-decoder = <0>; /* external decoder */ - num-cs = <4>; - fifo-depth = <256>; sram-size = <256>; - bus-num = <0>; status = "okay"; flash0: n25q32@0 { @@ -48,7 +44,6 @@ m25p,fast-read; page-size = <256>; block-size = <16>; /* 2^16, 64KB */ - read-delay = <4>; /* delay value in read data capture register */ tshsl-ns = <50>; tsd2d-ns = <50>; tchsh-ns = <4>; diff --git a/doc/device-tree-bindings/spi/spi-cadence.txt b/doc/device-tree-bindings/spi/spi-cadence.txt new file mode 100644 index 0000000..c1e2233 --- /dev/null +++ b/doc/device-tree-bindings/spi/spi-cadence.txt @@ -0,0 +1,28 @@ +Cadence QSPI controller device tree bindings +-------------------------------------------- + +Required properties: +- compatible : should be "cadence,qspi". +- reg : 1.Physical base address and size of SPI registers map. + 2. Physical base address & size of NOR Flash. +- clocks : Clock phandles (see clock bindings for details). +- sram-size : spi controller sram size. +- status : enable in requried dts. + +connected flash properties +-------------------------- + +- spi-max-frequency : Max supported spi frequency. +- page-size : Flash page size. +- block-size : Flash memory block size. +- tshsl-ns : Added delay in master reference clocks (ref_clk) for + the length that the master mode chip select outputs + are de-asserted between transactions. +- tsd2d-ns : Delay in master reference clocks (ref_clk) between one + chip select being de-activated and the activation of + another. +- tchsh-ns : Delay in master reference clocks between last bit of + current transaction and de-asserting the device chip + select (n_ss_out). +- tslch-ns : Delay in master reference clocks between setting + n_ss_out low and first bit transfer -- cgit v0.10.2 From f7848d90dde918423e6dfa462ec82bcdbba9defe Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 22 Jun 2015 17:57:36 -0500 Subject: Allow CONFIG_REGEX to be disabled when CONFIG_NET Instead of selecting REGEX when NET is enabled, make it the default, but allow boards that are tiny to disable it and lose functionality on all but the first Ethernet adapter. cm-bf548, bf538f-ezkit, and bf533-stamp need this. None appear to have more than one Ethernet interface. Signed-off-by: Joe Hershberger diff --git a/include/env_callback.h b/include/env_callback.h index ab5d42d..90b95b5 100644 --- a/include/env_callback.h +++ b/include/env_callback.h @@ -33,8 +33,10 @@ #ifdef CONFIG_REGEX #define ENV_DOT_ESCAPE "\\" +#define ETHADDR_WILDCARD "\\d?" #else #define ENV_DOT_ESCAPE +#define ETHADDR_WILDCARD #endif #ifdef CONFIG_CMD_DNS @@ -53,7 +55,7 @@ "nvlan:nvlan," \ "vlan:vlan," \ DNS_CALLBACK \ - "eth\\d?addr:ethaddr," + "eth" ETHADDR_WILDCARD "addr:ethaddr," #else #define NET_CALLBACKS #endif diff --git a/lib/Kconfig b/lib/Kconfig index 7ec8c98..c98d399 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -38,6 +38,7 @@ config SYS_VSNPRINTF config REGEX bool "Enable regular expression support" + default y if NET help If this variable is defined, U-Boot is linked against the SLRE (Super Light Regular Expression) library, which adds diff --git a/net/Kconfig b/net/Kconfig index 9a9846e..915371d 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -4,7 +4,6 @@ menuconfig NET bool "Networking support" - select REGEX if NET -- cgit v0.10.2 From e619c79ea60f9d16c62aca05cb513e2f244d0dc5 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 22 Jun 2015 17:57:37 -0500 Subject: blackfin: Fix build regression due to image size bf533-stamp, bf538f-ezkit, and cm-bf548 are very space limited. This was introduced by: 6e0d26c0502e (net: Handle ethaddr changes as an env callback) by enabling CONFIG_REGEX, which is too big for these boards. This patch disables CONFIG_REGEX at the expense of working with more than the first ethaddr. Signed-off-by: Joe Hershberger diff --git a/configs/bf533-stamp_defconfig b/configs/bf533-stamp_defconfig index 154dc26..4956078 100644 --- a/configs/bf533-stamp_defconfig +++ b/configs/bf533-stamp_defconfig @@ -2,4 +2,5 @@ CONFIG_BLACKFIN=y CONFIG_TARGET_BF533_STAMP=y # CONFIG_CMD_SETEXPR is not set CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED=y +# CONFIG_REGEX is not set CONFIG_LIB_RAND=y diff --git a/configs/bf538f-ezkit_defconfig b/configs/bf538f-ezkit_defconfig index 6cb6c6b..668f9cb 100644 --- a/configs/bf538f-ezkit_defconfig +++ b/configs/bf538f-ezkit_defconfig @@ -2,4 +2,5 @@ CONFIG_BLACKFIN=y CONFIG_TARGET_BF538F_EZKIT=y # CONFIG_CMD_SETEXPR is not set CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED=y +# CONFIG_REGEX is not set CONFIG_LIB_RAND=y diff --git a/configs/cm-bf548_defconfig b/configs/cm-bf548_defconfig index 949612d..49d59dd 100644 --- a/configs/cm-bf548_defconfig +++ b/configs/cm-bf548_defconfig @@ -2,4 +2,5 @@ CONFIG_BLACKFIN=y CONFIG_TARGET_CM_BF548=y # CONFIG_CMD_SETEXPR is not set CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED=y +# CONFIG_REGEX is not set CONFIG_LIB_RAND=y -- cgit v0.10.2 From 28fd00b7770b70caa84fac186dcbb09b65eebe5a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 7 Jul 2015 18:47:17 +0900 Subject: README.distro: fix typos The word "partition" is doubled. Keep decent forms for the following lines. Also, fix some other typos while we are here. Signed-off-by: Masahiro Yamada Acked-by: Stephen Warren diff --git a/doc/README.distro b/doc/README.distro index 0308a4c..9e4722a 100644 --- a/doc/README.distro +++ b/doc/README.distro @@ -28,7 +28,7 @@ decoupling distro install/boot logic from any knowledge of the bootloader. This model assumes that boards will load boot configuration files from a regular storage mechanism (eMMC, SD card, USB Disk, SATA disk, etc.) with -a standard partitioning scheme (MBR, GPT). Boards that cannnot support this +a standard partitioning scheme (MBR, GPT). Boards that cannot support this storage model are outside the scope of this document, and may still need board-specific installer/boot-configuration support in a distro. @@ -37,9 +37,9 @@ that contains U-Boot, and that the user has somehow installed U-Boot to this flash before running the distro installer. Even on boards that do not conform to this aspect of the model, the extent of the board-specific support in the distro installer logic would be to install a board-specific U-Boot package to -the boot partition partition during installation. This distro-supplied U-Boot -can still implement the same features as on any other board, and hence the -distro's boot configuration file generation logic can still be board-agnostic. +the boot partition during installation. This distro-supplied U-Boot can still +implement the same features as on any other board, and hence the distro's boot +configuration file generation logic can still be board-agnostic. Locating Bootable Disks ----------------------- @@ -61,7 +61,7 @@ any other bootloader) will find those boot files and execute them. This is conceptually identical to creating a grub2 configuration file on a desktop PC. -Note that in the absense of any partition that is explicitly marked bootable, +Note that in the absence of any partition that is explicitly marked bootable, U-Boot falls back to searching the first valid partition of a disk for boot configuration files. Other bootloaders are recommended to do the same, since I believe that partition table bootable flags aren't so commonly used outside @@ -238,7 +238,7 @@ kernel_addr_r: The kernel should be located within the first 128M of RAM in order for the kernel CONFIG_AUTO_ZRELADDR option to work, which is likely enabled on any distro kernel. Since the kernel will decompress itself to 0x8000 after the - start of RAM, kernel_addr_rshould not overlap that area, or the kernel will + start of RAM, kernel_addr_r should not overlap that area, or the kernel will have to copy itself somewhere else first before decompression. A size of 16MB for the kernel is likely adequate. -- cgit v0.10.2 From f41d6b7d4295e2a5f33cbdca7b5b2518fac42934 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 30 Jun 2015 16:03:02 -0600 Subject: ti: Add SPDX license identifier to omap.h This also came from Linux - according to this thread it has a GPL v2 license like arch/arm/mach-omap2/mux.h: http://lists.denx.de/pipermail/u-boot/2015-June/217827.html Signed-off-by: Simon Glass Reported-by: Ingrid Viitanen Reviewed-by: Tom Rini diff --git a/include/dt-bindings/pinctrl/omap.h b/include/dt-bindings/pinctrl/omap.h index edbd250..1dd7636 100644 --- a/include/dt-bindings/pinctrl/omap.h +++ b/include/dt-bindings/pinctrl/omap.h @@ -3,6 +3,8 @@ * * Copyright (C) 2009 Nokia * Copyright (C) 2009-2010 Texas Instruments + * + * SPDX-License-Identifier: GPL-2.0 */ #ifndef _DT_BINDINGS_PINCTRL_OMAP_H -- cgit v0.10.2 From 687a7518a1b1e40e005711603dcb14e0f6942d6d Mon Sep 17 00:00:00 2001 From: Prabhakar Kushwaha Date: Thu, 2 Jul 2015 12:00:17 +0530 Subject: Makefile:Add GCC flag -fno-delete-null-pointer-checks -fdelete-null-pointer-checks flag controls global dataflow analyses and eliminate useless checks for null pointers; It assume that if a pointer is checked after it has already been dereferenced, it cannot be null. This flag is enabled by default. gcc v4.9 has more optimizations added to this option. Hence it is very aggressive with GCC v4.9 series. Add -fno-delete-null-pointer-checks to disable the optimization Signed-off-by: Rohit Dharmakan Signed-off-by: Prabhakar Kushwaha diff --git a/Makefile b/Makefile index 37cc4c3..0dc6c53 100644 --- a/Makefile +++ b/Makefile @@ -565,6 +565,7 @@ KBUILD_CFLAGS += -DBUILD_TAG='"$(BUILD_TAG)"' endif KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector) +KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks) KBUILD_CFLAGS += -g # $(KBUILD_AFLAGS) sets -g, which causes gcc to pass a suitable -g -- cgit v0.10.2 From a5878f193341d7f01f6df173558771593169202d Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 24 Jun 2015 17:00:11 +0300 Subject: ARM: DRA7-evm: prevent DCAN1 _wait_target_disable failure in kernel If board is booted with transitions happening on DCAN1 pins then the following warning is seen in the kernel at boot when the hwmod layer initializes. "omap_hwmod: dcan1: _wait_target_disable failed" This is because DCAN1 module's SWAKEUP mechanism is broken and it fails to correctly turn OFF if it sees a transition on the DCAN1 pins. Suggested workaround is to keep DCAN1 pins in safe mode while enabling/disabling DCAN1 module. The hwmod layer enables and disables all modules at boot and we have no opportunity to put the DCAN1 pins in safe mode at that point. DCAN1 is not used by u-boot so it doesn't matter to it if these pins are in safe mode. The kernel driver correctly configures the right mode when DCAN1 is active. Signed-off-by: Roger Quadros diff --git a/board/ti/dra7xx/mux_data.h b/board/ti/dra7xx/mux_data.h index 5145301..ea8ee9f 100644 --- a/board/ti/dra7xx/mux_data.h +++ b/board/ti/dra7xx/mux_data.h @@ -359,7 +359,7 @@ const struct pad_conf_entry dra74x_core_padconf_array[] = { {SPI2_D1, (M1 | PIN_INPUT_SLEW)}, /* spi2_d1.uart3_txd */ {SPI2_D0, (M1 | PIN_INPUT_SLEW)}, /* spi2_d0.uart3_ctsn */ {SPI2_CS0, (M1 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* spi2_cs0.uart3_rtsn */ - {DCAN1_TX, (M0 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* dcan1_tx.dcan1_tx */ + {DCAN1_TX, (M15 | PULL_UP)}, /* dcan1_tx.safe for dcan1_tx */ {DCAN1_RX, (M14 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* dcan1_rx.gpio1_15 */ {UART1_RXD, (M0 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* uart1_rxd.uart1_rxd */ {UART1_TXD, (M0 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* uart1_txd.uart1_txd */ @@ -371,7 +371,7 @@ const struct pad_conf_entry dra74x_core_padconf_array[] = { {UART2_RTSN, (M3 | PIN_INPUT_PULLUP)}, /* uart2_rtsn.mmc4_dat3 */ {I2C2_SDA, (M0 | PIN_INPUT_PULLUP)}, /* i2c2_sda.i2c2_sda */ {I2C2_SCL, (M0 | PIN_INPUT_PULLUP)}, /* i2c2_scl.i2c2_scl */ - {WAKEUP0, (M1 | PIN_OUTPUT)}, /* Wakeup0.dcan1_rx */ + {WAKEUP0, (M15 | PULL_UP)}, /* Wakeup0.safe for dcan1_rx */ {WAKEUP2, (M14 | PIN_OUTPUT)}, /* Wakeup2.gpio1_2 */ }; -- cgit v0.10.2 From 16fc0f8ee370d2e73eb1b5532f511fee1ad657a7 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 25 Jun 2015 10:25:50 +0300 Subject: ARM: beagle_x15: prevent DCAN1 _wait_target_disable failure in kernel If board is booted with transitions happening on DCAN1 pins then the following warning is seen in the kernel at boot when the hwmod layer initializes. "omap_hwmod: dcan1: _wait_target_disable failed" This is because DCAN1 module's SWAKEUP mechanism is broken and it fails to correctly turn OFF if it sees a transition on the DCAN1 pins. Suggested workaround is to keep DCAN1 pins in safe mode while enabling/disabling DCAN1 module. The hwmod layer enables and disables all modules at boot and we have no opportunity to put the DCAN1 pins in safe mode at that point. DCAN1 is not used by u-boot so it doesn't matter to it if these pins are in safe mode. The kernel driver correctly configures the right mode when DCAN1 is active. Signed-off-by: Roger Quadros [trini: s/PULLUP/PULL_UP/ based on DRA7xx EVM version of this patch] Signed-off-by: Tom Rini diff --git a/board/ti/beagle_x15/mux_data.h b/board/ti/beagle_x15/mux_data.h index 09d3650..23f22a0 100644 --- a/board/ti/beagle_x15/mux_data.h +++ b/board/ti/beagle_x15/mux_data.h @@ -244,8 +244,8 @@ const struct pad_conf_entry core_padconf_array_essential[] = { {SPI2_D1, (M14 | PIN_INPUT_PULLDOWN)}, /* spi2_d1.gpio7_15 */ {SPI2_D0, (M14 | PIN_INPUT_PULLUP)}, /* spi2_d0.gpio7_16 */ {SPI2_CS0, (M14 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* spi2_cs0.gpio7_17 */ - {DCAN1_TX, (M0 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* dcan1_tx.dcan1_tx */ - {DCAN1_RX, (M0 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* dcan1_rx.dcan1_rx */ + {DCAN1_TX, (M15 | PULL_UP)}, /* dcan1_tx.safe for dcan1_tx */ + {DCAN1_RX, (M15 | PULL_UP)}, /* dcan1_rx.safe for dcan1_rx */ {UART1_RXD, (M0 | PIN_INPUT_SLEW)}, /* uart1_rxd.uart1_rxd */ {UART1_TXD, (M0 | PIN_INPUT_SLEW)}, /* uart1_txd.uart1_txd */ {UART1_CTSN, (M15 | PIN_INPUT_PULLDOWN)}, /* uart1_ctsn.Driveroff */ -- cgit v0.10.2 From a800f2fda7a321cebe695e601bc8701fe9187fe9 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Tue, 30 Jun 2015 09:59:47 +0200 Subject: arm: convert am3517_crane and am3517_evm to generic boards Add CONFIG_SYS_GENERIC_BOARD to board's config header. Boot-tested on am3517_evm board. Signed-off-by: Yegor Yefremov diff --git a/include/configs/am3517_crane.h b/include/configs/am3517_crane.h index 2f4117d..6a0240b 100644 --- a/include/configs/am3517_crane.h +++ b/include/configs/am3517_crane.h @@ -19,6 +19,7 @@ #define CONFIG_OMAP 1 /* in a TI OMAP core */ #define CONFIG_OMAP3_AM3517CRANE 1 /* working with CRANEBOARD */ #define CONFIG_OMAP_COMMON +#define CONFIG_SYS_GENERIC_BOARD /* Common ARM Erratas */ #define CONFIG_ARM_ERRATA_454179 #define CONFIG_ARM_ERRATA_430973 diff --git a/include/configs/am3517_evm.h b/include/configs/am3517_evm.h index e5b4621..b90a60d 100644 --- a/include/configs/am3517_evm.h +++ b/include/configs/am3517_evm.h @@ -19,6 +19,7 @@ #define CONFIG_OMAP 1 /* in a TI OMAP core */ #define CONFIG_OMAP3_AM3517EVM 1 /* working with AM3517EVM */ #define CONFIG_OMAP_COMMON +#define CONFIG_SYS_GENERIC_BOARD /* Common ARM Erratas */ #define CONFIG_ARM_ERRATA_454179 #define CONFIG_ARM_ERRATA_430973 -- cgit v0.10.2 From 5833521b38c014b5afffad3a70480ed4b7e00e6d Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Mon, 6 Jul 2015 17:28:34 +0200 Subject: arm: baltos: enable CMD_NET and FIT support in defconfig Signed-off-by: Yegor Yefremov Reviewed-by: Simon Glass diff --git a/configs/am335x_baltos_defconfig b/configs/am335x_baltos_defconfig index bf73919..8e8a897 100644 --- a/configs/am335x_baltos_defconfig +++ b/configs/am335x_baltos_defconfig @@ -3,9 +3,9 @@ CONFIG_TARGET_AM335X_BALTOS=y CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SPL_STACK_R_ADDR=0x82000000 +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y CONFIG_SYS_EXTRA_OPTIONS="NAND" -CONFIG_CONS_INDEX=1 # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set -# CONFIG_CMD_NET is not set diff --git a/include/configs/baltos.h b/include/configs/baltos.h index 68bfee5..632523e 100644 --- a/include/configs/baltos.h +++ b/include/configs/baltos.h @@ -39,8 +39,6 @@ #define CONFIG_CMD_PART /* FIT support */ -#define CONFIG_FIT -#define CONFIG_FIT_VERBOSE 1 /* enable fit_format_{error,warning}() */ #define CONFIG_OF_BOARD_SETUP /* UBI Support */ -- cgit v0.10.2 From e6b1b58bedbc507f840b2bae06eadb1d34512efa Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Mon, 6 Jul 2015 17:28:35 +0200 Subject: arm: baltos: drop I2C speed to 1000 Hz This action is need to make I2C communication with PMIC stable for low temperature. Print current I2C speed in SPL for visual control. Signed-off-by: Yegor Yefremov diff --git a/board/vscom/baltos/board.c b/board/vscom/baltos/board.c index 99ca60e..09bc8c6 100644 --- a/board/vscom/baltos/board.c +++ b/board/vscom/baltos/board.c @@ -184,6 +184,8 @@ void am33xx_spl_board_init(void) */ i2c_set_bus_num(1); + printf("I2C speed: %d Hz\n", CONFIG_SYS_OMAP24_I2C_SPEED); + if (i2c_probe(TPS65910_CTRL_I2C_ADDR)) { puts("i2c: cannot access TPS65910\n"); return; diff --git a/include/configs/baltos.h b/include/configs/baltos.h index 632523e..31de97f 100644 --- a/include/configs/baltos.h +++ b/include/configs/baltos.h @@ -52,7 +52,7 @@ /* I2C configuration */ #undef CONFIG_SYS_OMAP24_I2C_SPEED -#define CONFIG_SYS_OMAP24_I2C_SPEED 10000 +#define CONFIG_SYS_OMAP24_I2C_SPEED 1000 #ifdef CONFIG_NAND #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x000c0000 -- cgit v0.10.2 From 5f9c58e97e5e21380315cb42cffca6c6aa2c8383 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Mon, 6 Jul 2015 17:28:36 +0200 Subject: arm: baltos: fix NAND boot Specify proper U-Boot offset, enable prefetch mode, increase bootm size and add FIT fallback, if board_name is not present in kernel-fit.itb image. Signed-off-by: Yegor Yefremov diff --git a/include/configs/baltos.h b/include/configs/baltos.h index 31de97f..fb7818a 100644 --- a/include/configs/baltos.h +++ b/include/configs/baltos.h @@ -16,6 +16,7 @@ #ifndef __CONFIG_BALTOS_H #define __CONFIG_BALTOS_H +#include #include #define MACH_TYPE_TIAM335EVM 3589 /* Until the next sync */ @@ -39,6 +40,7 @@ #define CONFIG_CMD_PART /* FIT support */ +#define CONFIG_SYS_BOOTM_LEN SZ_64M #define CONFIG_OF_BOARD_SETUP /* UBI Support */ @@ -54,8 +56,9 @@ #undef CONFIG_SYS_OMAP24_I2C_SPEED #define CONFIG_SYS_OMAP24_I2C_SPEED 1000 +#undef CONFIG_SPL_OS_BOOT #ifdef CONFIG_NAND -#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x000c0000 +#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x00080000 #ifdef CONFIG_SPL_OS_BOOT #define CONFIG_CMD_SPL_NAND_OFS 0x00080000 /* os parameters */ #define CONFIG_SYS_NAND_SPL_KERNEL_OFFS 0x00200000 /* kernel offset */ @@ -78,7 +81,9 @@ "ubifsmount ubi0:kernel; " \ "ubifsload $loadaddr kernel-fit.itb;" \ "ubifsumount; " \ - "bootm ${loadaddr}#conf${board_name}\0" + "bootm ${loadaddr}#conf${board_name}; " \ + "if test $? -ne 0; then echo Using default FIT config; " \ + "bootm ${loadaddr}; fi;\0" #else #define NANDARGS "" #endif @@ -234,6 +239,7 @@ #ifdef CONFIG_NAND #define CONFIG_NAND_OMAP_GPMC +#define CONFIG_NAND_OMAP_GPMC_PREFETCH #define CONFIG_NAND_OMAP_ELM #define CONFIG_SYS_NAND_5_ADDR_CYCLE #define CONFIG_SYS_NAND_PAGE_COUNT (CONFIG_SYS_NAND_BLOCK_SIZE / \ -- cgit v0.10.2 From 0dd1c31d14e786bf6152c3e7fff188b708b96cf9 Mon Sep 17 00:00:00 2001 From: "Egli, Samuel" Date: Wed, 1 Jul 2015 17:57:39 +0200 Subject: siemens,am33x: adjust mtd partition Use one mtd partition for rootfs and configuration by means of ubi volumes and get rid of configuration partition. We can use partition layout for both 256MB and 512MB flash. Signed-off-by: Samuel Egli Cc: Heiko Schocher Cc: Roger Meier Reviewed-by: Tom Rini Acked-by: Heiko Schocher diff --git a/include/configs/siemens-am33x-common.h b/include/configs/siemens-am33x-common.h index 0f32594..e5fd147 100644 --- a/include/configs/siemens-am33x-common.h +++ b/include/configs/siemens-am33x-common.h @@ -480,7 +480,7 @@ /* * Variant 2 partition layout - * chip-size = 256MiB + * chip-size = 256MiB or 512 MiB *| name | size | address area | *------------------------------------------------------- *| spl | 128.000 KiB | 0x 0..0x 1ffff | @@ -490,23 +490,23 @@ *| u-boot | 1.875 MiB | 0x 80000..0x 25ffff | *| uboot.env0 | 512.000 KiB | 0x 260000..0x 2Dffff | *| uboot.env1 | 512.000 KiB | 0x 2E0000..0x 35ffff | - *| rootfs | 148.000 MiB | 0x 360000..0x 975ffff | - *| mtdoops | 512.000 KiB | 0x 9760000..0x 98Dffff | - *|configuration | 104.125 MiB | 0x 97E0000..0x fffffff | + *| mtdoops | 512.000 KiB | 0x 360000..0x 3dffff | + *| (256) rootfs | 252.125 MiB | 0x 3E0000..0x fffffff | + *| (512) rootfs | 508.125 MiB | 0x 3E0000..0x1fffffff | *------------------------------------------------------- */ #define MTDPARTS_DEFAULT_V2 "mtdparts=" MTDIDS_NAME_STR ":" \ - "128k(spl)," \ - "128k(spl.backup1)," \ - "128k(spl.backup2)," \ - "128k(spl.backup3)," \ - "1920k(u-boot)," \ - "512k(u-boot.env0)," \ - "512k(u-boot.env1)," \ - "148m(rootfs)," \ - "512k(mtdoops)," \ - "-(configuration)" + "128k(spl)," \ + "128k(spl.backup1)," \ + "128k(spl.backup2)," \ + "128k(spl.backup3)," \ + "1920k(u-boot)," \ + "512k(u-boot.env0)," \ + "512k(u-boot.env1)," \ + "512k(mtdoops)," \ + "-(rootfs)" + #define DFU_ALT_INFO_NAND_V2 \ "spl part 0 1;" \ @@ -516,8 +516,7 @@ "u-boot part 0 5;" \ "u-boot.env0 part 0 6;" \ "u-boot.env1 part 0 7;" \ - "rootfs partubi 0 8;" \ - "configuration partubi 0 10" + "rootfs partubi 0 9" \ #define CONFIG_ENV_SETTINGS_NAND_V2 \ "nand_active_ubi_vol=rootfs_a\0" \ @@ -534,7 +533,7 @@ "setenv nand_active_ubi_vol ${rootfs_name}_b;" \ "fi;" \ "setenv nand_root ubi0:${nand_active_ubi_vol} rw " \ - "ubi.mtd=7,2048 ubi.mtd=9,2048;" \ + "ubi.mtd=rootfs,2048;" \ "setenv bootargs ${bootargs} " \ "root=${nand_root} noinitrd ${mtdparts} " \ "rootfstype=${nand_root_fs_type} ip=${ip_method} " \ -- cgit v0.10.2 From 8379c7991788f8a763a9c93612b9e9558f1a4aa3 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 1 Jul 2015 14:15:02 +0800 Subject: stm32f4: fix MAINTAINERS file When "scripts/get_maintainer.pl" parses "board/.../MAINTAINERS", it uses the line containing board name as delimiter. Without this line, the script happily mixes the lines from current board MAINTAINERS file with lines from another file. Fix it by adding a reasonable board name. Tested by comparing output of: cat board/st/stm32f429-discovery/MAINTAINERS ./scripts/get_maintainer.pl -f board/st/stm32f429-discovery Signed-off-by: Antonio Borneo To: u-boot@lists.denx.de To: Kamil Lulko Cc: Tom Rini diff --git a/board/st/stm32f429-discovery/MAINTAINERS b/board/st/stm32f429-discovery/MAINTAINERS index 78b0d28..641f26a 100644 --- a/board/st/stm32f429-discovery/MAINTAINERS +++ b/board/st/stm32f429-discovery/MAINTAINERS @@ -1,3 +1,4 @@ +STM32F429-DISCOVERY BOARD M: Kamil Lulko S: Maintained F: board/st/stm32f429-discovery/ -- cgit v0.10.2 From 6f921ecc7e59792940833235b58e488638030ed6 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 1 Jul 2015 14:15:03 +0800 Subject: stm32f4: fix minor typo in comment Signed-off-by: Antonio Borneo To: u-boot@lists.denx.de To: Kamil Lulko Cc: Tom Rini diff --git a/include/configs/stm32f429-discovery.h b/include/configs/stm32f429-discovery.h index 46869dd..c8af7b6 100644 --- a/include/configs/stm32f429-discovery.h +++ b/include/configs/stm32f429-discovery.h @@ -52,7 +52,7 @@ #define CONFIG_STM32_SERIAL /* * Configuration of the USART - * 1: TX:PA9 PX:PA10 + * 1: TX:PA9 RX:PA10 * 2: TX:PD5 RX:PD6 * 3: TX:PC10 RX:PC11 * 6: TX:PC6 RX:PC7 -- cgit v0.10.2 From 03514739dce8cde8af5ee494405c9049925fb9de Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 1 Jul 2015 16:04:14 +0800 Subject: stm32f4: fix gpio description in comment On STM32F429 gpio PC6/PC7 can be allocated for USART6, as reported in the comment. But current code in drivers/serial/serial_stm32.c uses a different gpio mapping (PG14/PG9) for USART6. Fix the comment to match current code in the driver. Signed-off-by: Antonio Borneo To: u-boot@lists.denx.de To: Kamil Lulko Cc: Tom Rini diff --git a/include/configs/stm32f429-discovery.h b/include/configs/stm32f429-discovery.h index c8af7b6..1b4fd21 100644 --- a/include/configs/stm32f429-discovery.h +++ b/include/configs/stm32f429-discovery.h @@ -55,7 +55,7 @@ * 1: TX:PA9 RX:PA10 * 2: TX:PD5 RX:PD6 * 3: TX:PC10 RX:PC11 - * 6: TX:PC6 RX:PC7 + * 6: TX:PG14 RX:PG9 */ #define CONFIG_STM32_USART 1 -- cgit v0.10.2 From 40d79e483c359b8af4a379317a579c9b353dc821 Mon Sep 17 00:00:00 2001 From: Michael Scherban Date: Fri, 26 Jun 2015 09:17:31 -0500 Subject: keystone2: config: update default mtd Because it is possible for the MTD number to change, causing a filesystem mount failure, we should use the volume name instead of the MTD number and let Linux resolve the correct one. Signed-off-by: Mike Scherban diff --git a/include/configs/k2e_evm.h b/include/configs/k2e_evm.h index d83e07e..a28ceb7 100644 --- a/include/configs/k2e_evm.h +++ b/include/configs/k2e_evm.h @@ -20,7 +20,7 @@ #define CONFIG_EXTRA_ENV_KS2_BOARD_SETTINGS \ "addr_mon=0x0c140000\0" \ "args_ubi=setenv bootargs ${bootargs} rootfstype=ubifs " \ - "root=ubi0:rootfs rootflags=sync rw ubi.mtd=2,2048\0" \ + "root=ubi0:rootfs rootflags=sync rw ubi.mtd=ubifs,2048\0" \ "name_fdt=uImage-k2e-evm.dtb\0" \ "name_mon=skern-k2e-evm.bin\0" \ "name_ubi=k2e-evm-ubifs.ubi\0" \ diff --git a/include/configs/k2hk_evm.h b/include/configs/k2hk_evm.h index ffddf13..eae7721 100644 --- a/include/configs/k2hk_evm.h +++ b/include/configs/k2hk_evm.h @@ -20,7 +20,7 @@ #define CONFIG_EXTRA_ENV_KS2_BOARD_SETTINGS \ "addr_mon=0x0c5f0000\0" \ "args_ubi=setenv bootargs ${bootargs} rootfstype=ubifs " \ - "root=ubi0:rootfs rootflags=sync rw ubi.mtd=2,2048\0" \ + "root=ubi0:rootfs rootflags=sync rw ubi.mtd=ubifs,2048\0" \ "name_fdt=uImage-k2hk-evm.dtb\0" \ "name_mon=skern-k2hk-evm.bin\0" \ "name_ubi=k2hk-evm-ubifs.ubi\0" \ diff --git a/include/configs/k2l_evm.h b/include/configs/k2l_evm.h index 805164a..57da057 100644 --- a/include/configs/k2l_evm.h +++ b/include/configs/k2l_evm.h @@ -20,7 +20,7 @@ #define CONFIG_EXTRA_ENV_KS2_BOARD_SETTINGS \ "addr_mon=0x0c140000\0" \ "args_ubi=setenv bootargs ${bootargs} rootfstype=ubifs " \ - "root=ubi0:rootfs rootflags=sync rw ubi.mtd=2,4096\0" \ + "root=ubi0:rootfs rootflags=sync rw ubi.mtd=ubifs,4096\0" \ "name_fdt=uImage-k2l-evm.dtb\0" \ "name_mon=skern-k2l-evm.bin\0" \ "name_ubi=k2l-evm-ubifs.ubi\0" \ -- cgit v0.10.2 From 5e5055f0a31f02966e6fba0c11ab7548b1c20850 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Thu, 9 Jul 2015 13:34:24 +0200 Subject: arm: baltos: change USB ports functions Baltos has USB0 connected to a USB hub and thus is host-only. USB1 is connected to microUSB connector and thus should use OTG mode. Signed-off-by: Yegor Yefremov diff --git a/include/configs/baltos.h b/include/configs/baltos.h index fb7818a..cce5e4f 100644 --- a/include/configs/baltos.h +++ b/include/configs/baltos.h @@ -282,9 +282,9 @@ #define CONFIG_USB_GADGET_VBUS_DRAW 2 #define CONFIG_MUSB_HOST #define CONFIG_AM335X_USB0 -#define CONFIG_AM335X_USB0_MODE MUSB_PERIPHERAL +#define CONFIG_AM335X_USB0_MODE MUSB_HOST #define CONFIG_AM335X_USB1 -#define CONFIG_AM335X_USB1_MODE MUSB_HOST +#define CONFIG_AM335X_USB1_MODE MUSB_OTG #ifdef CONFIG_MUSB_HOST #define CONFIG_CMD_USB -- cgit v0.10.2 From fa31377ef0fd1096fbeab9c240582a93c4da9f6d Mon Sep 17 00:00:00 2001 From: Tang Yuantian Date: Thu, 9 Jul 2015 14:37:30 +0800 Subject: ahci: Fix compiling warnings under 64bit platforms When compling under 64bit platforms, there are lots of warnings, like: drivers/block/ahci.c:114:18: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] u8 *port_mmio = (u8 *)probe_ent->port[port].port_mmio; ^ drivers/block/ahci.c: In function ?.hci_host_init?. drivers/block/ahci.c:218:49: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] probe_ent->port[i].port_mmio = ahci_port_base((u32) mmio, i); ...... Reviewed-by: Simon Glass Signed-off-by: Shaohui Xie Signed-off-by: Tang Yuantian diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index 4fb846a..a57f674 100644 --- a/drivers/block/ahci.c +++ b/drivers/block/ahci.c @@ -43,13 +43,13 @@ u16 *ataid[AHCI_MAX_PORTS]; #define WAIT_MS_FLUSH 5000 #define WAIT_MS_LINKUP 200 -static inline u32 ahci_port_base(u32 base, u32 port) +static inline void __iomem *ahci_port_base(void __iomem *base, u32 port) { return base + 0x100 + (port * 0x80); } -static void ahci_setup_port(struct ahci_ioports *port, unsigned long base, +static void ahci_setup_port(struct ahci_ioports *port, void __iomem *base, unsigned int port_idx) { base = ahci_port_base(base, port_idx); @@ -61,7 +61,7 @@ static void ahci_setup_port(struct ahci_ioports *port, unsigned long base, #define msleep(a) udelay(a * 1000) -static void ahci_dcache_flush_range(unsigned begin, unsigned len) +static void ahci_dcache_flush_range(unsigned long begin, unsigned long len) { const unsigned long start = begin; const unsigned long end = start + len; @@ -75,7 +75,7 @@ static void ahci_dcache_flush_range(unsigned begin, unsigned len) * controller is invalidated from dcache; next access comes from * physical RAM. */ -static void ahci_dcache_invalidate_range(unsigned begin, unsigned len) +static void ahci_dcache_invalidate_range(unsigned long begin, unsigned long len) { const unsigned long start = begin; const unsigned long end = start + len; @@ -94,7 +94,7 @@ static void ahci_dcache_flush_sata_cmd(struct ahci_ioports *pp) AHCI_PORT_PRIV_DMA_SZ); } -static int waiting_for_cmd_completed(volatile u8 *offset, +static int waiting_for_cmd_completed(void __iomem *offset, int timeout_msec, u32 sign) { @@ -111,7 +111,7 @@ int __weak ahci_link_up(struct ahci_probe_ent *probe_ent, u8 port) { u32 tmp; int j = 0; - u8 *port_mmio = (u8 *)probe_ent->port[port].port_mmio; + void __iomem *port_mmio = probe_ent->port[port].port_mmio; /* * Bring up SATA link. @@ -131,7 +131,7 @@ int __weak ahci_link_up(struct ahci_probe_ent *probe_ent, u8 port) #ifdef CONFIG_SUNXI_AHCI /* The sunxi AHCI controller requires this undocumented setup */ -static void sunxi_dma_init(volatile u8 *port_mmio) +static void sunxi_dma_init(void __iomem *port_mmio) { clrsetbits_le32(port_mmio + PORT_P0DMACR, 0x0000ff00, 0x00004400); } @@ -171,10 +171,10 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) u16 tmp16; unsigned short vendor; #endif - volatile u8 *mmio = (volatile u8 *)probe_ent->mmio_base; + void __iomem *mmio = probe_ent->mmio_base; u32 tmp, cap_save, cmd; int i, j, ret; - volatile u8 *port_mmio; + void __iomem *port_mmio; u32 port_map; debug("ahci_host_init: start\n"); @@ -215,9 +215,9 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) for (i = 0; i < probe_ent->n_ports; i++) { if (!(port_map & (1 << i))) continue; - probe_ent->port[i].port_mmio = ahci_port_base((u32) mmio, i); + probe_ent->port[i].port_mmio = ahci_port_base(mmio, i); port_mmio = (u8 *) probe_ent->port[i].port_mmio; - ahci_setup_port(&probe_ent->port[i], (unsigned long)mmio, i); + ahci_setup_port(&probe_ent->port[i], mmio, i); /* make sure port is not active */ tmp = readl(port_mmio + PORT_CMD); @@ -329,7 +329,7 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent) pci_dev_t pdev = probe_ent->dev; u16 cc; #endif - volatile u8 *mmio = (volatile u8 *)probe_ent->mmio_base; + void __iomem *mmio = probe_ent->mmio_base; u32 vers, cap, cap2, impl, speed; const char *speed_s; const char *scc_s; @@ -462,7 +462,7 @@ static int ahci_fill_sg(u8 port, unsigned char *buf, int buf_len) for (i = 0; i < sg_count; i++) { ahci_sg->addr = - cpu_to_le32((u32) buf + i * MAX_DATA_BYTE_COUNT); + cpu_to_le32((unsigned long) buf + i * MAX_DATA_BYTE_COUNT); ahci_sg->addr_hi = 0; ahci_sg->flags_size = cpu_to_le32(0x3fffff & (buf_len < MAX_DATA_BYTE_COUNT @@ -480,8 +480,11 @@ static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 opts) { pp->cmd_slot->opts = cpu_to_le32(opts); pp->cmd_slot->status = 0; - pp->cmd_slot->tbl_addr = cpu_to_le32(pp->cmd_tbl & 0xffffffff); - pp->cmd_slot->tbl_addr_hi = 0; + pp->cmd_slot->tbl_addr = cpu_to_le32((u32)pp->cmd_tbl & 0xffffffff); +#ifdef CONFIG_PHYS_64BIT + pp->cmd_slot->tbl_addr_hi = + cpu_to_le32((u32)(((pp->cmd_tbl) >> 16) >> 16)); +#endif } @@ -489,7 +492,7 @@ static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 opts) static void ahci_set_feature(u8 port) { struct ahci_ioports *pp = &(probe_ent->port[port]); - volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio; + void __iomem *port_mmio = pp->port_mmio; u32 cmd_fis_len = 5; /* five dwords */ u8 fis[20]; @@ -514,7 +517,7 @@ static void ahci_set_feature(u8 port) } #endif -static int wait_spinup(volatile u8 *port_mmio) +static int wait_spinup(void __iomem *port_mmio) { ulong start; u32 tf_data; @@ -532,9 +535,9 @@ static int wait_spinup(volatile u8 *port_mmio) static int ahci_port_start(u8 port) { struct ahci_ioports *pp = &(probe_ent->port[port]); - volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio; + void __iomem *port_mmio = pp->port_mmio; u32 port_status; - u32 mem; + void __iomem *mem; debug("Enter start port: %d\n", port); port_status = readl(port_mmio + PORT_SCR_STAT); @@ -544,15 +547,16 @@ static int ahci_port_start(u8 port) return -1; } - mem = (u32) malloc(AHCI_PORT_PRIV_DMA_SZ + 2048); + mem = malloc(AHCI_PORT_PRIV_DMA_SZ + 2048); if (!mem) { free(pp); printf("%s: No mem for table!\n", __func__); return -ENOMEM; } - mem = (mem + 0x800) & (~0x7ff); /* Aligned to 2048-bytes */ - memset((u8 *) mem, 0, AHCI_PORT_PRIV_DMA_SZ); + /* Aligned to 2048-bytes */ + mem = memalign(2048, AHCI_PORT_PRIV_DMA_SZ); + memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ); /* * First item in chunk of DMA memory: 32-slot command table, @@ -560,7 +564,7 @@ static int ahci_port_start(u8 port) */ pp->cmd_slot = (struct ahci_cmd_hdr *)(uintptr_t)virt_to_phys((void *)mem); - debug("cmd_slot = 0x%x\n", (unsigned)pp->cmd_slot); + debug("cmd_slot = %p\n", pp->cmd_slot); mem += (AHCI_CMD_SLOT_SZ + 224); /* @@ -574,13 +578,14 @@ static int ahci_port_start(u8 port) * and its scatter-gather table */ pp->cmd_tbl = virt_to_phys((void *)mem); - debug("cmd_tbl_dma = 0x%x\n", pp->cmd_tbl); + debug("cmd_tbl_dma = %lx\n", pp->cmd_tbl); mem += AHCI_CMD_TBL_HDR; pp->cmd_tbl_sg = (struct ahci_sg *)(uintptr_t)virt_to_phys((void *)mem); - writel_with_flush((u32) pp->cmd_slot, port_mmio + PORT_LST_ADDR); + writel_with_flush((unsigned long)pp->cmd_slot, + port_mmio + PORT_LST_ADDR); writel_with_flush(pp->rx_fis, port_mmio + PORT_FIS_ADDR); @@ -607,7 +612,7 @@ static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf, { struct ahci_ioports *pp = &(probe_ent->port[port]); - volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio; + void __iomem *port_mmio = pp->port_mmio; u32 opts; u32 port_status; int sg_count; @@ -632,7 +637,7 @@ static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf, ahci_fill_cmd_slot(pp, opts); ahci_dcache_flush_sata_cmd(pp); - ahci_dcache_flush_range((unsigned)buf, (unsigned)buf_len); + ahci_dcache_flush_range((unsigned long)buf, (unsigned long)buf_len); writel_with_flush(1, port_mmio + PORT_CMD_ISSUE); @@ -642,7 +647,8 @@ static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf, return -1; } - ahci_dcache_invalidate_range((unsigned)buf, (unsigned)buf_len); + ahci_dcache_invalidate_range((unsigned long)buf, + (unsigned long)buf_len); debug("%s: %d byte transferred.\n", __func__, pp->cmd_slot->status); return 0; @@ -1026,7 +1032,7 @@ static int ata_io_flush(u8 port) { u8 fis[20]; struct ahci_ioports *pp = &(probe_ent->port[port]); - volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio; + void __iomem *port_mmio = pp->port_mmio; u32 cmd_fis_len = 5; /* five dwords */ /* Preset the FIS */ diff --git a/drivers/block/dwc_ahsata.c b/drivers/block/dwc_ahsata.c index cf3ef6b..bc072f3 100644 --- a/drivers/block/dwc_ahsata.c +++ b/drivers/block/dwc_ahsata.c @@ -80,7 +80,7 @@ struct sata_host_regs { static int is_ready; -static inline u32 ahci_port_base(u32 base, u32 port) +static inline void __iomem *ahci_port_base(void __iomem *base, u32 port) { return base + 0x100 + (port * 0x80); } @@ -167,7 +167,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) for (i = 0; i < probe_ent->n_ports; i++) { probe_ent->port[i].port_mmio = - ahci_port_base((u32)host_mmio, i); + ahci_port_base(host_mmio, i); port_mmio = (struct sata_port_regs *)probe_ent->port[i].port_mmio; @@ -399,8 +399,11 @@ static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 cmd_slot, u32 opts) memset(cmd_hdr, 0, AHCI_CMD_SLOT_SZ); cmd_hdr->opts = cpu_to_le32(opts); cmd_hdr->status = 0; - cmd_hdr->tbl_addr = cpu_to_le32(pp->cmd_tbl & 0xffffffff); - cmd_hdr->tbl_addr_hi = 0; + pp->cmd_slot->tbl_addr = cpu_to_le32((u32)pp->cmd_tbl & 0xffffffff); +#ifdef CONFIG_PHYS_64BIT + pp->cmd_slot->tbl_addr_hi = + cpu_to_le32((u32)(((pp->cmd_tbl) >> 16) >> 16)); +#endif } #define AHCI_GET_CMD_SLOT(c) ((c) ? ffs(c) : 0) @@ -520,7 +523,7 @@ static int ahci_port_start(struct ahci_probe_ent *probe_ent, * and its scatter-gather table */ pp->cmd_tbl = mem; - debug("cmd_tbl_dma = 0x%x\n", pp->cmd_tbl); + debug("cmd_tbl_dma = 0x%lx\n", pp->cmd_tbl); mem += AHCI_CMD_TBL_HDR; diff --git a/include/ahci.h b/include/ahci.h index 6d91712..0bdedac 100644 --- a/include/ahci.h +++ b/include/ahci.h @@ -135,12 +135,12 @@ struct ahci_sg { }; struct ahci_ioports { - u32 cmd_addr; - u32 scr_addr; - u32 port_mmio; + void __iomem *cmd_addr; + void __iomem *scr_addr; + void __iomem *port_mmio; struct ahci_cmd_hdr *cmd_slot; struct ahci_sg *cmd_tbl_sg; - u32 cmd_tbl; + ulong cmd_tbl; u32 rx_fis; }; -- cgit v0.10.2 From 6c7cbd32d36a5ce22b2257b2f72baab80cd4483f Mon Sep 17 00:00:00 2001 From: Minkyu Kang Date: Thu, 2 Jul 2015 10:27:48 +0900 Subject: arm: adds the status info for odroid-xu3 Adds the 'F:' entry for the board's defconfig Signed-off-by: Minkyu Kang diff --git a/board/samsung/smdk5420/MAINTAINERS b/board/samsung/smdk5420/MAINTAINERS index a26ea68..0361657 100644 --- a/board/samsung/smdk5420/MAINTAINERS +++ b/board/samsung/smdk5420/MAINTAINERS @@ -14,3 +14,4 @@ M: Przemyslaw Marczak S: Maintained F: board/samsung/smdk5420/ F: include/configs/odroid_xu3.h +F: configs/odroid-xu3_defconfig -- cgit v0.10.2 From 8fd3ec770c41115b95ca80f0f0ba344ac59dc293 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 2 Jul 2015 18:15:44 -0600 Subject: exynos: i2c: Correct bug in pinmux selection When driver model is not used the current code does not correctly select the pinmux for the I2C bus. This bug was introduced by this commit: 8dfcbaa dm: i2c: s3c24x0: adjust to dm-i2c api Signed-off-by: Simon Glass Acked-by: Heiko Schocher Reviewed-by: Przemyslaw Marczak Signed-off-by: Minkyu Kang diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c index c053e84..9a04e48 100644 --- a/drivers/i2c/s3c24x0_i2c.c +++ b/drivers/i2c/s3c24x0_i2c.c @@ -1035,7 +1035,7 @@ static void process_nodes(const void *blob, int node_list[], int count, CONFIG_SYS_I2C_S3C24X0_SPEED); bus->node = node; bus->bus_num = i; - exynos_pinmux_config(PERIPH_ID_I2C0 + bus->id, flags); + exynos_pinmux_config(bus->id, flags); /* Mark position as used */ node_list[i] = -1; -- cgit v0.10.2 From fca6105200b408d2a12acb0ef6e7cb530d773eef Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 1 Jul 2015 17:38:05 +0200 Subject: arm: mvebu: db-88f6820-gp: Add MAINTAINERS file Signed-off-by: Stefan Roese Cc: Luka Perkov Cc: Albert Aribaud diff --git a/board/Marvell/db-88f6820-gp/MAINTAINERS b/board/Marvell/db-88f6820-gp/MAINTAINERS new file mode 100644 index 0000000..f564940 --- /dev/null +++ b/board/Marvell/db-88f6820-gp/MAINTAINERS @@ -0,0 +1,6 @@ +DB_88F6820_GP BOARD +M: Stefan Roese +S: Maintained +F: board/Marvell/db-88f6820-gp/ +F: include/configs/db-88f6820-gp.h +F: configs/db-88f6820-gp_defconfig -- cgit v0.10.2 From 29905a451b7ecf86785a4404e926fb14a8daced3 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 29 Jun 2015 14:58:08 +0200 Subject: mmc: sdhci: Use timer based timeout detection in sdhci_send_command() The loop counter based timeout detection does not work on the Armada 38x based board (DB-88F6820-GP). At least with dcache enabled a timeout is detected. Without dcache enabled, the timeout does not occur. Increasing the loop counter solves this issue. But a better solution is to use a timer based timeout detection instead. This patch now implements this timer based detection. Signed-off-by: Stefan Roese Cc: Pantelis Antoniou Cc: Luka Perkov diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 75556a3..f72536b 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -133,8 +133,8 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, int trans_bytes = 0, is_aligned = 1; u32 mask, flags, mode; unsigned int time = 0, start_addr = 0; - unsigned int retry = 10000; int mmc_dev = mmc->block_dev.dev; + unsigned start = get_timer(0); /* Timeout unit - ms */ static unsigned int cmd_timeout = CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT; @@ -222,15 +222,15 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, flush_cache(start_addr, trans_bytes); #endif sdhci_writew(host, SDHCI_MAKE_CMD(cmd->cmdidx, flags), SDHCI_COMMAND); + start = get_timer(0); do { stat = sdhci_readl(host, SDHCI_INT_STATUS); if (stat & SDHCI_INT_ERROR) break; - if (--retry == 0) - break; - } while ((stat & mask) != mask); + } while (((stat & mask) != mask) && + (get_timer(start) < CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT)); - if (retry == 0) { + if (get_timer(start) >= CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT) { if (host->quirks & SDHCI_QUIRK_BROKEN_R1B) return 0; else { -- cgit v0.10.2 From 492d3223b076a9705b64897a061b60720f50d18b Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 29 Jun 2015 14:58:09 +0200 Subject: mmc: sdhci.c: Add config option to use a fixed buffer for transfers While implementing SDIO/MMC SPL booting for the Marvell Armada 38x, the following problem occured. The SPL runs in internal SRAM which is the L2 cache locked to memory. When the MMC buffers now are located on the stack (or bss), the SDIO controller (SDHCI) can't write into this L2 cache memory. This patch introduces a method to use a fixed buffer that will be used for all transfers by defining CONFIG_FIXED_SDHCI_ALIGNED_BUFFER. This way, the board can use this buffer address located in SDRAM for all transfers. This solves this SPL problem on the A38x and should only be used in the SPL U-Boot version. Tested for SPL booting on Marvell Armada 38x DB-88F6820-GP board. Signed-off-by: Stefan Roese Cc: Pantelis Antoniou Cc: Luka Perkov diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index f72536b..d89e302 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -13,7 +13,11 @@ #include #include +#if defined(CONFIG_FIXED_SDHCI_ALIGNED_BUFFER) +void *aligned_buffer = (void *)CONFIG_FIXED_SDHCI_ALIGNED_BUFFER; +#else void *aligned_buffer; +#endif static void sdhci_reset(struct sdhci_host *host, u8 mask) { @@ -205,6 +209,17 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, memcpy(aligned_buffer, data->src, trans_bytes); } +#if defined(CONFIG_FIXED_SDHCI_ALIGNED_BUFFER) + /* + * Always use this bounce-buffer when + * CONFIG_FIXED_SDHCI_ALIGNED_BUFFER is defined + */ + is_aligned = 0; + start_addr = (unsigned long)aligned_buffer; + if (data->flags != MMC_DATA_READ) + memcpy(aligned_buffer, data->src, trans_bytes); +#endif + sdhci_writel(host, start_addr, SDHCI_DMA_ADDRESS); mode |= SDHCI_TRNS_DMA; #endif -- cgit v0.10.2 From 7f1adcd74f9d0dcff8759bd2262ad40c44e1a99d Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 29 Jun 2015 14:58:10 +0200 Subject: arm: mvebu: Add SDIO/SDHCI support for Armada A38x Armada A38x implements an SDHCI compatible SDIO controller. This patch enables the Marvell driver to support this SoC. And enables the SDIO controller if selected by the board configuration. Tested on Marvell DB-88F6820-GP board. Signed-off-by: Stefan Roese Cc: Pantelis Antoniou Cc: Luka Perkov diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c index 0121db8..531d0fb 100644 --- a/arch/arm/mach-mvebu/cpu.c +++ b/arch/arm/mach-mvebu/cpu.c @@ -10,6 +10,7 @@ #include #include #include +#include #define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3)) #define DDR_SIZE_CS_OFF(n) (0x0004 + ((n) << 3)) @@ -245,6 +246,16 @@ int cpu_eth_init(bd_t *bis) } #endif +#ifdef CONFIG_MV_SDHCI +int board_mmc_init(bd_t *bis) +{ + mv_sdh_init(MVEBU_SDIO_BASE, 0, 0, + SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_WAIT_SEND_CMD); + + return 0; +} +#endif + #ifndef CONFIG_SYS_DCACHE_OFF void enable_caches(void) { diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h index 3b48460..4bdb633 100644 --- a/arch/arm/mach-mvebu/include/mach/cpu.h +++ b/arch/arm/mach-mvebu/include/mach/cpu.h @@ -114,6 +114,8 @@ void mvebu_sdram_size_adjust(enum memory_bank bank); int mvebu_mbus_probe(struct mbus_win windows[], int count); int mvebu_soc_family(void); +int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks); + /* * Highspeed SERDES PHY config init, ported from bin_hdr * to mainline U-Boot diff --git a/arch/arm/mach-mvebu/include/mach/gpio.h b/arch/arm/mach-mvebu/include/mach/gpio.h new file mode 100644 index 0000000..09e3c50 --- /dev/null +++ b/arch/arm/mach-mvebu/include/mach/gpio.h @@ -0,0 +1,10 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __MACH_MVEBU_GPIO_H +#define __MACH_MVEBU_GPIO_H + +/* Empty file - sdhci requires this. */ + +#endif diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h index 0a9307c..1aeec27 100644 --- a/arch/arm/mach-mvebu/include/mach/soc.h +++ b/arch/arm/mach-mvebu/include/mach/soc.h @@ -51,6 +51,7 @@ #define MVEBU_REG_PCIE_BASE (MVEBU_REGISTER(0x40000)) #define MVEBU_EGIGA0_BASE (MVEBU_REGISTER(0x70000)) #define MVEBU_EGIGA1_BASE (MVEBU_REGISTER(0x74000)) +#define MVEBU_SDIO_BASE (MVEBU_REGISTER(0xd8000)) #define SDRAM_MAX_CS 4 #define SDRAM_ADDR_MASK 0xFF000000 -- cgit v0.10.2 From e80f1e85d6010ca9d19edf2ec333cf30af6cbbd0 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 29 Jun 2015 14:58:11 +0200 Subject: arm: mvebu: db-88f6820-gp: Add MMC/SDIO support This patch adds MMC/SDIO support to the Marvell DB-88F6820-GP board configuration. Including support for the common partitions and filesystems. Signed-off-by: Stefan Roese Cc: Pantelis Antoniou Cc: Luka Perkov diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h index 24dbf6b..67cf748 100644 --- a/include/configs/db-88f6820-gp.h +++ b/include/configs/db-88f6820-gp.h @@ -29,7 +29,12 @@ #define CONFIG_CMD_CACHE #define CONFIG_CMD_DHCP #define CONFIG_CMD_ENV +#define CONFIG_CMD_EXT2 +#define CONFIG_CMD_EXT4 +#define CONFIG_CMD_FAT +#define CONFIG_CMD_FS_GENERIC #define CONFIG_CMD_I2C +#define CONFIG_CMD_MMC #define CONFIG_CMD_PING #define CONFIG_CMD_SF #define CONFIG_CMD_SPI @@ -48,6 +53,23 @@ #define CONFIG_SF_DEFAULT_MODE SPI_MODE_3 #define CONFIG_SPI_FLASH_STMICRO +/* + * SDIO/MMC Card Configuration + */ +#define CONFIG_MMC +#define CONFIG_MMC_SDMA +#define CONFIG_GENERIC_MMC +#define CONFIG_SDHCI +#define CONFIG_MV_SDHCI +#define CONFIG_SYS_MMC_BASE MVEBU_SDIO_BASE + +/* Partition support */ +#define CONFIG_DOS_PARTITION +#define CONFIG_EFI_PARTITION + +/* Additional FS support/configuration */ +#define CONFIG_SUPPORT_VFAT + /* Environment in SPI NOR flash */ #define CONFIG_ENV_IS_IN_SPI_FLASH #define CONFIG_ENV_OFFSET (1 << 20) /* 1MiB in */ -- cgit v0.10.2 From 2cc1aa2e0010249fe671e38eb412d0cbefb0bf73 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 29 Jun 2015 14:58:12 +0200 Subject: block: ahci: Don't enable port interrupts This patch changes the initialization of the AHCI controller to not enable the default interrupts (DEF_PORT_IRQ). As interrupts are not used in U-Boot in general, this should not break the common AHCI driver operation. This change is needed to support the Marvell Armada 38x AHCI controller. With interrupts enabled, this results in timeouts in ahci_device_data_io(). Not enabling these interrupts fixes this problem and the common AHCI driver works fine. Signed-off-by: Stefan Roese Reviewed-by: Simon Glass Cc: Tom Rini Cc: Hans de Goede Cc: Luka Perkov diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index 4fb846a..9bab0fc 100644 --- a/drivers/block/ahci.c +++ b/drivers/block/ahci.c @@ -299,9 +299,6 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) writel(1 << i, mmio + HOST_IRQ_STAT); - /* set irq mask (enables interrupts) */ - writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); - /* register linkup ports */ tmp = readl(port_mmio + PORT_SCR_STAT); debug("SATA port %d status: 0x%x\n", i, tmp); -- cgit v0.10.2 From 4d991cb3c74f1aa7742022c37e6627401b9ac030 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 29 Jun 2015 14:58:13 +0200 Subject: arm: mvebu: Add SATA/SCSI (AHCI) support for Armada A38x This patch adds support for the common AHCI controller on the Marvell Armada 38x. Tested on the Marvell DB-88F6820-GP eval board. Signed-off-by: Stefan Roese Cc: Luka Perkov diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c index 531d0fb..9bc9f00 100644 --- a/arch/arm/mach-mvebu/cpu.c +++ b/arch/arm/mach-mvebu/cpu.c @@ -6,6 +6,8 @@ #include #include +#include +#include #include #include #include @@ -256,6 +258,59 @@ int board_mmc_init(bd_t *bis) } #endif +#ifdef CONFIG_SCSI_AHCI_PLAT +#define AHCI_VENDOR_SPECIFIC_0_ADDR 0xa0 +#define AHCI_VENDOR_SPECIFIC_0_DATA 0xa4 + +#define AHCI_WINDOW_CTRL(win) (0x60 + ((win) << 4)) +#define AHCI_WINDOW_BASE(win) (0x64 + ((win) << 4)) +#define AHCI_WINDOW_SIZE(win) (0x68 + ((win) << 4)) + +static void ahci_mvebu_mbus_config(void __iomem *base) +{ + const struct mbus_dram_target_info *dram; + int i; + + dram = mvebu_mbus_dram_info(); + + for (i = 0; i < 4; i++) { + writel(0, base + AHCI_WINDOW_CTRL(i)); + writel(0, base + AHCI_WINDOW_BASE(i)); + writel(0, base + AHCI_WINDOW_SIZE(i)); + } + + for (i = 0; i < dram->num_cs; i++) { + const struct mbus_dram_window *cs = dram->cs + i; + + writel((cs->mbus_attr << 8) | + (dram->mbus_dram_target_id << 4) | 1, + base + AHCI_WINDOW_CTRL(i)); + writel(cs->base >> 16, base + AHCI_WINDOW_BASE(i)); + writel(((cs->size - 1) & 0xffff0000), + base + AHCI_WINDOW_SIZE(i)); + } +} + +static void ahci_mvebu_regret_option(void __iomem *base) +{ + /* + * Enable the regret bit to allow the SATA unit to regret a + * request that didn't receive an acknowlegde and avoid a + * deadlock + */ + writel(0x4, base + AHCI_VENDOR_SPECIFIC_0_ADDR); + writel(0x80, base + AHCI_VENDOR_SPECIFIC_0_DATA); +} + +void scsi_init(void) +{ + printf("MVEBU SATA INIT\n"); + ahci_mvebu_mbus_config((void __iomem *)MVEBU_SATA0_BASE); + ahci_mvebu_regret_option((void __iomem *)MVEBU_SATA0_BASE); + ahci_init((void __iomem *)MVEBU_SATA0_BASE); +} +#endif + #ifndef CONFIG_SYS_DCACHE_OFF void enable_caches(void) { diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h index 1aeec27..e6bfbc2 100644 --- a/arch/arm/mach-mvebu/include/mach/soc.h +++ b/arch/arm/mach-mvebu/include/mach/soc.h @@ -51,6 +51,7 @@ #define MVEBU_REG_PCIE_BASE (MVEBU_REGISTER(0x40000)) #define MVEBU_EGIGA0_BASE (MVEBU_REGISTER(0x70000)) #define MVEBU_EGIGA1_BASE (MVEBU_REGISTER(0x74000)) +#define MVEBU_SATA0_BASE (MVEBU_REGISTER(0xa8000)) #define MVEBU_SDIO_BASE (MVEBU_REGISTER(0xd8000)) #define SDRAM_MAX_CS 4 diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h index 67cf748..9ea1624 100644 --- a/include/configs/db-88f6820-gp.h +++ b/include/configs/db-88f6820-gp.h @@ -36,6 +36,7 @@ #define CONFIG_CMD_I2C #define CONFIG_CMD_MMC #define CONFIG_CMD_PING +#define CONFIG_CMD_SCSI #define CONFIG_CMD_SF #define CONFIG_CMD_SPI #define CONFIG_CMD_TFTPPUT -- cgit v0.10.2 From 7cbaff9574878f9d71a08dbe1c2a6ad72ce2822c Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 29 Jun 2015 14:58:14 +0200 Subject: arm: mvebu: db-88f6820-gp.h: Add SATA/SCSI (AHCI) support Configure and enable the SATA/SCSI (AHCI) support for the Marvell DB-88F6820-GP eval board. Signed-off-by: Stefan Roese Cc: Luka Perkov diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h index 9ea1624..5bdb29f 100644 --- a/include/configs/db-88f6820-gp.h +++ b/include/configs/db-88f6820-gp.h @@ -64,6 +64,17 @@ #define CONFIG_MV_SDHCI #define CONFIG_SYS_MMC_BASE MVEBU_SDIO_BASE +/* + * SATA/SCSI/AHCI configuration + */ +#define CONFIG_LIBATA +#define CONFIG_SCSI_AHCI +#define CONFIG_SCSI_AHCI_PLAT +#define CONFIG_SYS_SCSI_MAX_SCSI_ID 2 +#define CONFIG_SYS_SCSI_MAX_LUN 1 +#define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \ + CONFIG_SYS_SCSI_MAX_LUN) + /* Partition support */ #define CONFIG_DOS_PARTITION #define CONFIG_EFI_PARTITION -- cgit v0.10.2 From fe11ae2437e67509b0a0697d932bba10aa686756 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 29 Jun 2015 14:58:15 +0200 Subject: usb: Add EHCI support for Armada 38x (mvebu) This patch adds USB EHCI host support for the common mvebu platform. Including the Armada 38x. Tested on DB-88F6280-GP eval board. Signed-off-by: Stefan Roese Reviewed-by: Marek Vasut Cc: Luka Perkov diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h index e6bfbc2..1aaea67 100644 --- a/arch/arm/mach-mvebu/include/mach/soc.h +++ b/arch/arm/mach-mvebu/include/mach/soc.h @@ -49,6 +49,7 @@ #define MVEBU_EGIGA2_BASE (MVEBU_REGISTER(0x30000)) #define MVEBU_EGIGA3_BASE (MVEBU_REGISTER(0x34000)) #define MVEBU_REG_PCIE_BASE (MVEBU_REGISTER(0x40000)) +#define MVEBU_USB20_BASE (MVEBU_REGISTER(0x58000)) #define MVEBU_EGIGA0_BASE (MVEBU_REGISTER(0x70000)) #define MVEBU_EGIGA1_BASE (MVEBU_REGISTER(0x74000)) #define MVEBU_SATA0_BASE (MVEBU_REGISTER(0xa8000)) diff --git a/drivers/usb/host/ehci-marvell.c b/drivers/usb/host/ehci-marvell.c index 1a5fd6e..03c489c 100644 --- a/drivers/usb/host/ehci-marvell.c +++ b/drivers/usb/host/ehci-marvell.c @@ -10,6 +10,7 @@ #include #include #include "ehci.h" +#include #include #if defined(CONFIG_KIRKWOOD) @@ -30,6 +31,40 @@ DECLARE_GLOBAL_DATA_PTR; /* * USB 2.0 Bridge Address Decoding registers setup */ +#ifdef CONFIG_ARMADA_XP + +#define MVUSB0_BASE MVEBU_USB20_BASE + +/* + * Once all the older Marvell SoC's (Orion, Kirkwood) are converted + * to the common mvebu archticture including the mbus setup, this + * will be the only function needed to configure the access windows + */ +static void usb_brg_adrdec_setup(void) +{ + const struct mbus_dram_target_info *dram; + int i; + + dram = mvebu_mbus_dram_info(); + + for (i = 0; i < 4; i++) { + wrl(USB_WINDOW_CTRL(i), 0); + wrl(USB_WINDOW_BASE(i), 0); + } + + for (i = 0; i < dram->num_cs; i++) { + const struct mbus_dram_window *cs = dram->cs + i; + + /* Write size, attributes and target id to control register */ + wrl(USB_WINDOW_CTRL(i), + ((cs->size - 1) & 0xffff0000) | (cs->mbus_attr << 8) | + (dram->mbus_dram_target_id << 4) | 1); + + /* Write base address to base register */ + wrl(USB_WINDOW_BASE(i), cs->base); + } +} +#else static void usb_brg_adrdec_setup(void) { int i; @@ -69,6 +104,7 @@ static void usb_brg_adrdec_setup(void) wrl(USB_WINDOW_BASE(i), base); } } +#endif /* * Create the appropriate control structures to manage -- cgit v0.10.2 From 59565736839108846d8dfa6782babfaefff6b58b Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 29 Jun 2015 14:58:16 +0200 Subject: arm: mvebu: db-88f6820-gp: Add USB/EHCI support This patch enabled the USB/EHCI support for the Marvell DB-88F6820-GP eval board. Signed-off-by: Stefan Roese Cc: Marek Vasut Cc: Luka Perkov diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h index 5bdb29f..a429107 100644 --- a/include/configs/db-88f6820-gp.h +++ b/include/configs/db-88f6820-gp.h @@ -41,6 +41,7 @@ #define CONFIG_CMD_SPI #define CONFIG_CMD_TFTPPUT #define CONFIG_CMD_TIME +#define CONFIG_CMD_USB /* I2C */ #define CONFIG_SYS_I2C @@ -82,6 +83,12 @@ /* Additional FS support/configuration */ #define CONFIG_SUPPORT_VFAT +/* USB/EHCI configuration */ +#define CONFIG_USB_EHCI +#define CONFIG_USB_STORAGE +#define CONFIG_USB_EHCI_MARVELL +#define CONFIG_EHCI_IS_TDI + /* Environment in SPI NOR flash */ #define CONFIG_ENV_IS_IN_SPI_FLASH #define CONFIG_ENV_OFFSET (1 << 20) /* 1MiB in */ -- cgit v0.10.2 From f18d11163e4ea523aff489721db5de752fe062bf Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 1 Jul 2015 21:35:49 +0900 Subject: mtd: fix false positive "Offset exceeds device limit" error Since commit 09c3280754f8 (mtd, nand: Move common functions from cmd_nand.c to common place), NAND commands would not work at all on large devices. => nand read 80000000 10000 10000 NAND read: Offset exceeds device limit => nand erase 100000 100000 NAND erase: Offset exceeds device limit The type of the "size" of "struct mtd_info" is uint64_t, while mtd_arg_off_size() and mtd_arg_off() treat chipsize as int type. The chipsize is wrapped around if the argument is given with 2GB or larger. Acked-by: Heiko Schocher Acked-by: Scott Wood Signed-off-by: Masahiro Yamada diff --git a/drivers/mtd/mtd_uboot.c b/drivers/mtd/mtd_uboot.c index 7197007..c517b9c 100644 --- a/drivers/mtd/mtd_uboot.c +++ b/drivers/mtd/mtd_uboot.c @@ -43,7 +43,7 @@ static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size, } int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size, - loff_t *maxsize, int devtype, int chipsize) + loff_t *maxsize, int devtype, uint64_t chipsize) { if (!str2off(arg, off)) return get_part(arg, idx, off, size, maxsize, devtype); @@ -59,7 +59,8 @@ int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size, } int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off, - loff_t *size, loff_t *maxsize, int devtype, int chipsize) + loff_t *size, loff_t *maxsize, int devtype, + uint64_t chipsize) { int ret; diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 33669da..552d4d6 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -484,8 +484,9 @@ int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); int del_mtd_partitions(struct mtd_info *); int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size, - loff_t *maxsize, int devtype, int chipsize); + loff_t *maxsize, int devtype, uint64_t chipsize); int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off, - loff_t *size, loff_t *maxsize, int devtype, int chipsize); + loff_t *size, loff_t *maxsize, int devtype, + uint64_t chipsize); #endif #endif /* __MTD_MTD_H__ */ -- cgit v0.10.2 From c7d0fd797ec2ce3acd3cd7ed53971f431f8c6072 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 2 Jul 2015 01:04:23 +0100 Subject: scsi: fix compiler warning with DEBUG and 48bit LBAs Commit 2b42c9317db ("ahci: support LBA48 data reads for 2+TB drives") introduced conditional code which triggers a warning when compiled with DEBUG enabled: In file included from common/cmd_scsi.c:12:0: common/cmd_scsi.c: In function 'scsi_read': include/common.h:109:4: warning: 'smallblks' may be used uninitialized in this function [-Wmaybe-uninitialized] ... Since this is for debug only, take the easy way and initialize the variable explicitly on declaration to avoid the warning. (Fix a nearby whitespace error on the way.) Tested-by: Bin Meng Signed-off-by: Andre Przywara diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index aaca3e8..31c4319 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -368,7 +368,7 @@ static ulong scsi_read(int device, lbaint_t blknr, lbaint_t blkcnt, { lbaint_t start, blks; uintptr_t buf_addr; - unsigned short smallblks; + unsigned short smallblks = 0; ccb* pccb=(ccb *)&tempccb; device&=0xff; /* Setup device @@ -391,7 +391,7 @@ static ulong scsi_read(int device, lbaint_t blknr, lbaint_t blkcnt, scsi_setup_read16(pccb, start, blocks); start += blocks; blks -= blocks; - } else + } else #endif if (blks > SCSI_MAX_READ_BLK) { pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK; -- cgit v0.10.2 From 33711bdd4a4dce942fb5ae85a68899a8357bdd94 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Tue, 14 Jul 2015 13:32:21 -0400 Subject: Prepare v2015.07 Signed-off-by: Tom Rini diff --git a/Makefile b/Makefile index 0dc6c53..a7dce06 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2015 PATCHLEVEL = 07 SUBLEVEL = -EXTRAVERSION = -rc3 +EXTRAVERSION = NAME = # *DOCUMENTATION* -- cgit v0.10.2 From f4815763b410d8657f6f617067a1d53024b05220 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 28 Aug 2014 09:43:46 -0600 Subject: RFC: Deprecate MAKEALL Since buildman now includes most of the features of MAKEALL it is probably time to talk about deprecating MAKEALL. Comments welcome. Signed-off-by: Simon Glass diff --git a/MAKEALL b/MAKEALL index a6e378f..7e42f10 100755 --- a/MAKEALL +++ b/MAKEALL @@ -60,6 +60,14 @@ usage() exit ${ret} } +deprecation() { + echo "** Note: MAKEALL is deprecated - please use buildman instead" + echo "** See tools/buildman/README for details" + echo +} + +deprecation + SHORT_OPTS="ha:c:v:s:b:lmMCnr" LONG_OPTS="help,arch:,cpu:,vendor:,soc:,board:,list,maintainers,mails,check,continue,rebuild-errors" @@ -827,6 +835,8 @@ print_stats() { kill_children fi + deprecation + exit $RC } -- cgit v0.10.2 From dd5921104688074e2879bddeb18349bff89688ef Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Mon, 27 Apr 2015 11:34:38 -0400 Subject: builderthread.py: Keep 'SPL' On i.MX platforms the SPL binary is called "SPL" so make sure we keep that. Cc: Simon Glass Signed-off-by: Tom Rini Acked-by: Simon Glass diff --git a/tools/buildman/builderthread.py b/tools/buildman/builderthread.py index ce1cfdd..cf25bb8 100644 --- a/tools/buildman/builderthread.py +++ b/tools/buildman/builderthread.py @@ -356,7 +356,7 @@ class BuilderThread(threading.Thread): # Now write the actual build output if keep_outputs: self.CopyFiles(result.out_dir, build_dir, '', ['u-boot*', '*.bin', - '*.map', '*.img', 'MLO', 'include/autoconf.mk', + '*.map', '*.img', 'MLO', 'SPL', 'include/autoconf.mk', 'spl/u-boot-spl*']) def CopyFiles(self, out_dir, build_dir, dirname, patterns): -- cgit v0.10.2 From 343fb990646cc3d552711bff30bda743de392f08 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 7 Jun 2015 11:33:12 +0800 Subject: x86: Add Kconfig options to be used by arch/x86/cpu/config.mk Add RESET_SEG_START, RESET_SEG_SIZE and RESET_VEC_LOC Kconfig options and make arch/x86/cpu/config.mk use these options. Signed-off-by: Bin Meng Acked-by: Simon Glass Tested-by: Andrew Bradford Tested-by: Simon Glass diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 20083e6..e35ae1d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -69,6 +69,21 @@ config X86_RESET_VECTOR bool default n +config RESET_SEG_START + hex + depends on X86_RESET_VECTOR + default 0xffff0000 + +config RESET_SEG_SIZE + hex + depends on X86_RESET_VECTOR + default 0x10000 + +config RESET_VEC_LOC + hex + depends on X86_RESET_VECTOR + default 0xfffffff0 + config SYS_X86_START16 hex depends on X86_RESET_VECTOR diff --git a/arch/x86/cpu/config.mk b/arch/x86/cpu/config.mk index 4c4d0c7..1263221 100644 --- a/arch/x86/cpu/config.mk +++ b/arch/x86/cpu/config.mk @@ -10,8 +10,8 @@ CROSS_COMPILE ?= i386-linux- PLATFORM_CPPFLAGS += -D__I386__ # DO NOT MODIFY THE FOLLOWING UNLESS YOU REALLY KNOW WHAT YOU ARE DOING! -LDPPFLAGS += -DRESET_SEG_START=0xffff0000 -LDPPFLAGS += -DRESET_SEG_SIZE=0x10000 -LDPPFLAGS += -DRESET_VEC_LOC=0xfffffff0 +LDPPFLAGS += -DRESET_SEG_START=$(CONFIG_RESET_SEG_START) +LDPPFLAGS += -DRESET_SEG_SIZE=$(CONFIG_RESET_SEG_SIZE) +LDPPFLAGS += -DRESET_VEC_LOC=$(CONFIG_RESET_VEC_LOC) LDPPFLAGS += -DSTART_16=$(CONFIG_SYS_X86_START16) LDPPFLAGS += -DRESET_BASE="CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE)" -- cgit v0.10.2 From 002610f620553bec06e5724052fc5cc5f34eb1e8 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 7 Jun 2015 11:33:13 +0800 Subject: x86: fsp: Load GDT before calling FspInitEntry Currently the FSP execution environment GDT is setup by U-Boot in arch/x86/cpu/start16.S, which works pretty well. But if we try to move the FspInitEntry call a little bit later to better fit into U-Boot's initialization sequence, FSP will fail to bring up the AP due to #GP fault as AP's GDT is duplicated from BSP whose GDT is now moved into CAR, and unfortunately FSP calls AP initialization after it disables the CAR. So basically the BSP's GDT still refers to the one in the CAR, whose content is no longer available, so when AP starts up and loads its segment register, it blows up. To resolve this, we load GDT before calling into FspInitEntry. The GDT is the same one used in arch/x86/cpu/start16.S, which is in the ROM and exists forever. Signed-off-by: Bin Meng Tested-by: Andrew Bradford Tested-by: Simon Glass Acked-by: Simon Glass diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index bb4a110..b6c585a 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -164,6 +164,26 @@ void setup_gdt(gd_t *id, u64 *gdt_addr) load_fs(X86_GDT_ENTRY_32BIT_FS); } +#ifdef CONFIG_HAVE_FSP +/* + * Setup FSP execution environment GDT + * + * Per Intel FSP external architecture specification, before calling any FSP + * APIs, we need make sure the system is in flat 32-bit mode and both the code + * and data selectors should have full 4GB access range. Here we reuse the one + * we used in arch/x86/cpu/start16.S, and reload the segement registers. + */ +void setup_fsp_gdt(void) +{ + load_gdt((const u64 *)(gdt_rom + CONFIG_RESET_SEG_START), 4); + load_ds(X86_GDT_ENTRY_32BIT_DS); + load_ss(X86_GDT_ENTRY_32BIT_DS); + load_es(X86_GDT_ENTRY_32BIT_DS); + load_fs(X86_GDT_ENTRY_32BIT_DS); + load_gs(X86_GDT_ENTRY_32BIT_DS); +} +#endif + int __weak x86_cleanup_before_linux(void) { #ifdef CONFIG_BOOTSTAGE_STASH diff --git a/arch/x86/cpu/start16.S b/arch/x86/cpu/start16.S index 826e2b4..5eb17f1 100644 --- a/arch/x86/cpu/start16.S +++ b/arch/x86/cpu/start16.S @@ -71,11 +71,12 @@ idt_ptr: */ gdt_ptr: .word 0x1f /* limit (31 bytes = 4 GDT entries - 1) */ - .long BOOT_SEG + gdt /* base */ + .long BOOT_SEG + gdt_rom /* base */ /* Some CPUs are picky about GDT alignment... */ .align 16 -gdt: +.globl gdt_rom +gdt_rom: /* * The GDT table ... * diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index d1d21ed..3c6ee29 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -8,12 +8,19 @@ #ifndef _U_BOOT_I386_H_ #define _U_BOOT_I386_H_ 1 +extern char gdt_rom[]; + /* cpu/.../cpu.c */ int arch_cpu_init(void); int x86_cpu_init_f(void); int cpu_init_f(void); void init_gd(gd_t *id, u64 *gdt_addr); void setup_gdt(gd_t *id, u64 *gdt_addr); +/* + * Setup FSP execution environment GDT to use the one we used in + * arch/x86/cpu/start16.S and reload the segment registers. + */ +void setup_fsp_gdt(void); int init_cache(void); int cleanup_before_linux(void); diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c index 5809235..4585166 100644 --- a/arch/x86/lib/fsp/fsp_support.c +++ b/arch/x86/lib/fsp/fsp_support.c @@ -173,6 +173,9 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf) post_code(POST_PRE_MRC); + /* Load GDT for FSP */ + setup_fsp_gdt(); + /* * Use ASM code to ensure the register value in EAX & ECX * will be passed into BlContinuationFunc -- cgit v0.10.2 From aefaff8ed83472da5ba96e179231eee665e2d843 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 7 Jun 2015 11:33:14 +0800 Subject: x86: fsp: Move FspInitEntry call to board_init_f() The call to FspInitEntry is done in arch/x86/lib/fsp/fsp_car.S so far. It worked pretty well but looks not that good. Apart from doing too much work than just enabling CAR, it cannot read the configuration data from device tree at that time. Now we want to move it a little bit later as part of init_sequence_f[] being called by board_init_f(). This way it looks and works better in the U-Boot initialization path. Due to FSP's design, after calling FspInitEntry it will not return to its caller, instead it jumps to a continuation function which is given by bootloader with a new stack in system memory. The original stack in the CAR is gone, but its content is perserved by FSP and described by a bootloader temporary memory HOB. Technically we can recover anything we had before in the previous stack, but that is way too complicated. To make life much easier, in the FSP continuation routine we just simply call fsp_init_done() and jump back to car_init_ret() to redo the whole board_init_f() initialization, but this time with a non-zero HOB list pointer saved in U-Boot's global data so that we can bypass the FspInitEntry for the second time. Signed-off-by: Bin Meng Acked-by: Simon Glass Tested-by: Andrew Bradford Tested-by: Simon Glass diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index 2e5f9da..00e585e 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -116,12 +116,16 @@ car_init_ret: rep stosb #ifdef CONFIG_HAVE_FSP + test %esi, %esi + jz skip_hob + /* Store HOB list */ movl %esp, %edx addl $GD_HOB_LIST, %edx movl %esi, (%edx) -#endif +skip_hob: +#endif /* Setup first parameter to setup_gdt, pointer to global_data */ movl %esp, %eax diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 3c6ee29..4dae365 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -56,6 +56,9 @@ u32 isa_map_rom(u32 bus_addr, int size); /* arch/x86/lib/... */ int video_bios_init(void); +/* arch/x86/lib/fsp/... */ +int x86_fsp_init(void); + void board_init_f_r_trampoline(ulong) __attribute__ ((noreturn)); void board_init_f_r(void) __attribute__ ((noreturn)); diff --git a/arch/x86/lib/fsp/fsp_car.S b/arch/x86/lib/fsp/fsp_car.S index 5e09568..afbf3f9 100644 --- a/arch/x86/lib/fsp/fsp_car.S +++ b/arch/x86/lib/fsp/fsp_car.S @@ -56,28 +56,10 @@ temp_ram_init_ret: /* stack grows down from top of CAR */ movl %edx, %esp + subl $4, %esp - /* - * TODO: - * - * According to FSP architecture spec, the fsp_init() will not return - * to its caller, instead it requires the bootloader to provide a - * so-called continuation function to pass into the FSP as a parameter - * of fsp_init, and fsp_init() will call that continuation function - * directly. - * - * The call to fsp_init() may need to be moved out of the car_init() - * to cpu_init_f() with the help of some inline assembly codes. - * Note there is another issue that fsp_init() will setup another stack - * using the fsp_init parameter stack_top after DRAM is initialized, - * which means any data on the previous stack (on the CAR) gets lost - * (ie: U-Boot global_data). FSP is supposed to support such scenario, - * however it does not work. This should be revisited in the future. - */ - movl $CONFIG_FSP_TEMP_RAM_ADDR, %eax - xorl %edx, %edx - xorl %ecx, %ecx - call fsp_init + xor %esi, %esi + jmp car_init_done .global fsp_init_done fsp_init_done: @@ -86,6 +68,8 @@ fsp_init_done: * Save eax to esi temporarily. */ movl %eax, %esi + +car_init_done: /* * Re-initialize the ebp (BIST) to zero, as we already reach here * which means we passed BIST testing before. diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c index 001494d..5b25632 100644 --- a/arch/x86/lib/fsp/fsp_common.c +++ b/arch/x86/lib/fsp/fsp_common.c @@ -46,3 +46,11 @@ void board_final_cleanup(void) return; } + +int x86_fsp_init(void) +{ + if (!gd->arch.hob_list) + fsp_init(CONFIG_FSP_TEMP_RAM_ADDR, BOOT_FULL_CONFIG, NULL); + + return 0; +} diff --git a/common/board_f.c b/common/board_f.c index fbbad1b..21be26f 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -753,6 +753,9 @@ static init_fnc_t init_sequence_f[] = { #ifdef CONFIG_OF_CONTROL fdtdec_setup, #endif +#if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) + x86_fsp_init, +#endif #ifdef CONFIG_TRACE trace_early_init, #endif -- cgit v0.10.2 From a7d0711a2486b7420a938831512d859879e613cb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 7 Jun 2015 08:50:32 -0600 Subject: spi: sf: Print the error code on failure Rather than just 'ERROR', display the error code, which may be useful, at least with driver model. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Acked-by: Marek Vasut Reviewed-by: Jagan Teki diff --git a/common/cmd_sf.c b/common/cmd_sf.c index aef8c2a..3746e0d 100644 --- a/common/cmd_sf.c +++ b/common/cmd_sf.c @@ -303,8 +303,12 @@ static int do_spi_flash_read_write(int argc, char * const argv[]) else ret = spi_flash_write(flash, offset, len, buf); - printf("SF: %zu bytes @ %#x %s: %s\n", (size_t)len, (u32)offset, - read ? "Read" : "Written", ret ? "ERROR" : "OK"); + printf("SF: %zu bytes @ %#x %s: ", (size_t)len, (u32)offset, + read ? "Read" : "Written"); + if (ret) + printf("ERROR %d\n", ret); + else + printf("OK\n"); } unmap_physmem(buf, len); -- cgit v0.10.2 From 5d4a757ca5edb8782188c2bc2735f016e4b6c290 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 7 Jun 2015 08:50:33 -0600 Subject: dm: spi: Correct minor nits in ICH driver Tidy up three minor problems in this file. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Reviewed-by: Jagan Teki diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c index 50354fd..6b6cfbf 100644 --- a/drivers/spi/ich.c +++ b/drivers/spi/ich.c @@ -422,7 +422,7 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, int using_cmd = 0; int ret; - /* Ee don't support writing partial bytes. */ + /* We don't support writing partial bytes */ if (bitlen % 8) { debug("ICH SPI: Accessing partial bytes not supported\n"); return -EPROTONOSUPPORT; @@ -601,7 +601,7 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, return status; if (status & SPIS_FCERR) { - debug("ICH SPI: Data transaction error\n"); + debug("ICH SPI: Data transaction error %x\n", status); return -EIO; } @@ -619,7 +619,6 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, return 0; } - /* * This uses the SPI controller from the Intel Cougar Point and Panther Point * PCH to write-protect portions of the SPI flash until reboot. The changes -- cgit v0.10.2 From 166c3984e6b1271c2e31ff0528ad65aadc913860 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Jun 2015 14:52:18 +0800 Subject: dm: cpu: Fix undefined ENOSYS build error Include otherwise ENOSYS is undefined. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/common/cmd_cpu.c b/common/cmd_cpu.c index c3e229f..b4af64f 100644 --- a/common/cmd_cpu.c +++ b/common/cmd_cpu.c @@ -9,6 +9,7 @@ #include #include #include +#include static const char *cpu_feature_name[CPU_FEAT_COUNT] = { "L1 cache", diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c index ab18ee2..aa0267c 100644 --- a/drivers/cpu/cpu-uclass.c +++ b/drivers/cpu/cpu-uclass.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include -- cgit v0.10.2 From cb5cbfd503d38bfe963ebd52da958563c636709d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Jun 2015 14:52:19 +0800 Subject: dm: cpu: Test against cpu_ops->get_info in cpu_get_info() In cpu_get_info() it wrongly tests against cpu_ops->get_desc to see if it is NULL. It should test against cpu_ops->get_info. Signed-off-by: Bin Meng diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c index aa0267c..d6be9d4 100644 --- a/drivers/cpu/cpu-uclass.c +++ b/drivers/cpu/cpu-uclass.c @@ -26,7 +26,7 @@ int cpu_get_info(struct udevice *dev, struct cpu_info *info) { struct cpu_ops *ops = cpu_get_ops(dev); - if (!ops->get_desc) + if (!ops->get_info) return -ENOSYS; return ops->get_info(dev, info); -- cgit v0.10.2 From be3f06bcc47e04bfc5fb7c900958918e2d019ef4 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Jun 2015 14:52:20 +0800 Subject: x86: dm: Clean up cpu drivers This commit does the following to clean up x86 cpu dm drivers: - Move cpu_x86 driver codes from arch/x86/cpu/cpu.c to a dedicated file arch/x86/cpu/cpu_x86.c - Rename x86_cpu_get_desc() to cpu_x86_get_desc() to keep consistent naming with other dm drivers - Add a new cpu_x86_bind() in the cpu_x86 driver which does exactly the same as the one in the intel baytrail cpu driver - Update intel baytrail cpu driver to use cpu_x86_get_desc() and cpu_x86_bind() Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 7ff05e6..48197fb 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -10,7 +10,7 @@ extra-y = start.o obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o -obj-y += interrupts.o cpu.o call64.o +obj-y += interrupts.o cpu.o cpu_x86.o call64.o obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/ obj-$(CONFIG_SYS_COREBOOT) += coreboot/ diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c index 1d48206..05156a5 100644 --- a/arch/x86/cpu/baytrail/cpu.c +++ b/arch/x86/cpu/baytrail/cpu.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -175,18 +176,8 @@ static int baytrail_get_info(struct udevice *dev, struct cpu_info *info) return 0; } -static int cpu_x86_baytrail_bind(struct udevice *dev) -{ - struct cpu_platdata *plat = dev_get_parent_platdata(dev); - - plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset, - "intel,apic-id", -1); - - return 0; -} - static const struct cpu_ops cpu_x86_baytrail_ops = { - .get_desc = x86_cpu_get_desc, + .get_desc = cpu_x86_get_desc, .get_info = baytrail_get_info, }; @@ -199,7 +190,7 @@ U_BOOT_DRIVER(cpu_x86_baytrail_drv) = { .name = "cpu_x86_baytrail", .id = UCLASS_CPU, .of_match = cpu_x86_baytrail_ids, - .bind = cpu_x86_baytrail_bind, + .bind = cpu_x86_bind, .probe = cpu_x86_baytrail_probe, .ops = &cpu_x86_baytrail_ops, }; diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index b6c585a..1dfd9e6 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -21,8 +21,6 @@ #include #include -#include -#include #include #include #include @@ -540,16 +538,6 @@ char *cpu_get_name(char *name) return ptr; } -int x86_cpu_get_desc(struct udevice *dev, char *buf, int size) -{ - if (size < CPU_MAX_NAME_LEN) - return -ENOSPC; - - cpu_get_name(buf); - - return 0; -} - int default_print_cpuinfo(void) { printf("CPU: %s, vendor %s, device %xh\n", @@ -642,19 +630,3 @@ int cpu_init_r(void) { return x86_init_cpus(); } - -static const struct cpu_ops cpu_x86_ops = { - .get_desc = x86_cpu_get_desc, -}; - -static const struct udevice_id cpu_x86_ids[] = { - { .compatible = "cpu-x86" }, - { } -}; - -U_BOOT_DRIVER(cpu_x86_drv) = { - .name = "cpu_x86", - .id = UCLASS_CPU, - .of_match = cpu_x86_ids, - .ops = &cpu_x86_ops, -}; diff --git a/arch/x86/cpu/cpu_x86.c b/arch/x86/cpu/cpu_x86.c new file mode 100644 index 0000000..d32ba66 --- /dev/null +++ b/arch/x86/cpu/cpu_x86.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2015, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +int cpu_x86_bind(struct udevice *dev) +{ + struct cpu_platdata *plat = dev_get_parent_platdata(dev); + + plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + "intel,apic-id", -1); + + return 0; +} + +int cpu_x86_get_desc(struct udevice *dev, char *buf, int size) +{ + if (size < CPU_MAX_NAME_LEN) + return -ENOSPC; + + cpu_get_name(buf); + + return 0; +} + +static const struct cpu_ops cpu_x86_ops = { + .get_desc = cpu_x86_get_desc, +}; + +static const struct udevice_id cpu_x86_ids[] = { + { .compatible = "cpu-x86" }, + { } +}; + +U_BOOT_DRIVER(cpu_x86_drv) = { + .name = "cpu_x86", + .id = UCLASS_CPU, + .of_match = cpu_x86_ids, + .bind = cpu_x86_bind, + .ops = &cpu_x86_ops, +}; diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index ebc74ad..08284ee 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -197,20 +197,6 @@ const char *cpu_vendor_name(int vendor); char *cpu_get_name(char *name); /** - * -* x86_cpu_get_desc() - Get a description string for an x86 CPU -* -* This uses cpu_get_name() and is suitable to use as the get_desc() method for -* the CPU uclass. -* -* @dev: Device to check (UCLASS_CPU) -* @buf: Buffer to place string -* @size: Size of string space -* @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error -*/ -int x86_cpu_get_desc(struct udevice *dev, char *buf, int size); - -/** * cpu_call64() - Jump to a 64-bit Linux kernel (internal function) * * The kernel is uncompressed and the 64-bit entry point is expected to be diff --git a/arch/x86/include/asm/cpu_x86.h b/arch/x86/include/asm/cpu_x86.h new file mode 100644 index 0000000..1940480 --- /dev/null +++ b/arch/x86/include/asm/cpu_x86.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2015, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _ASM_CPU_X86_H +#define _ASM_CPU_X86_H + +/** + * cpu_x86_bind() - Bind an x86 CPU with the driver + * + * This updates cpu device's platform data with information from device tree, + * like the processor local apic id. + * + * @dev: Device to check (UCLASS_CPU) + * @return 0 always + */ +int cpu_x86_bind(struct udevice *dev); + +/** + * cpu_x86_get_desc() - Get a description string for an x86 CPU + * + * This uses cpu_get_name() and is suitable to use as the get_desc() method for + * the CPU uclass. + * + * @dev: Device to check (UCLASS_CPU) + * @buf: Buffer to place string + * @size: Size of string space + * @return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error + */ +int cpu_x86_get_desc(struct udevice *dev, char *buf, int size); + +#endif /* _ASM_CPU_X86_H */ -- cgit v0.10.2 From 063374d2f698162d0cc2d6ea44c8e332c639db0a Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Jun 2015 14:52:22 +0800 Subject: x86: kconfig: Make MAX_CPUS and AP_STACK_SIZE depend on SMP MAX_CPUS and AP_STACK_SIZE are only meaningful when SMP is on. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e35ae1d..984a917 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -237,6 +237,7 @@ config FSP_TEMP_RAM_ADDR config MAX_CPUS int "Maximum number of CPUs permitted" + depends on SMP default 4 help When using multi-CPU chips it is possible for U-Boot to start up @@ -258,6 +259,7 @@ config SMP config AP_STACK_SIZE hex + depends on SMP default 0x1000 help Each additional CPU started by U-Boot requires its own stack. This -- cgit v0.10.2 From 4c71322b41a657596ee5e5777393ed83e80139c6 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 12 Jun 2015 14:52:23 +0800 Subject: x86: kconfig: Fix minor nits in MAX_CPUS Move MAX_CPUS definition after SMP so that it shows below SMP in the menuconfig. Also replace the leading spaces in the MAX_CPUS section with tabs to conform coding standard. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 984a917..36e97c8 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -235,18 +235,6 @@ config FSP_TEMP_RAM_ADDR Stack top address which is used in FspInit after DRAM is ready and CAR is disabled. -config MAX_CPUS - int "Maximum number of CPUs permitted" - depends on SMP - default 4 - help - When using multi-CPU chips it is possible for U-Boot to start up - more than one CPU. The stack memory used by all of these CPUs is - pre-allocated so at present U-Boot wants to know the maximum - number of CPUs that may be present. Set this to at least as high - as the number of CPUs in your system (it uses about 4KB of RAM for - each CPU). - config SMP bool "Enable Symmetric Multiprocessing" default n @@ -257,6 +245,18 @@ config SMP only one CPU will be enabled regardless of the number of CPUs available. +config MAX_CPUS + int "Maximum number of CPUs permitted" + depends on SMP + default 4 + help + When using multi-CPU chips it is possible for U-Boot to start up + more than one CPU. The stack memory used by all of these CPUs is + pre-allocated so at present U-Boot wants to know the maximum + number of CPUs that may be present. Set this to at least as high + as the number of CPUs in your system (it uses about 4KB of RAM for + each CPU). + config AP_STACK_SIZE hex depends on SMP -- cgit v0.10.2 From 780bfdd3c72a058ba24cda0df66ca75f0a7d8b18 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 17 Jun 2015 11:15:34 +0800 Subject: dm: cpu: Add a new get_count method to cpu uclass Introduce a new method 'get_count' in the UCLASS_CPU ops to get the number of CPUs in the system. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c index d6be9d4..a2814a8 100644 --- a/drivers/cpu/cpu-uclass.c +++ b/drivers/cpu/cpu-uclass.c @@ -32,6 +32,16 @@ int cpu_get_info(struct udevice *dev, struct cpu_info *info) return ops->get_info(dev, info); } +int cpu_get_count(struct udevice *dev) +{ + struct cpu_ops *ops = cpu_get_ops(dev); + + if (!ops->get_count) + return -ENOSYS; + + return ops->get_count(dev); +} + U_BOOT_DRIVER(cpu_bus) = { .name = "cpu_bus", .id = UCLASS_SIMPLE_BUS, diff --git a/include/cpu.h b/include/cpu.h index 34c60bc..bfb0db2 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -58,6 +58,14 @@ struct cpu_ops { * @return 0 if OK, -ve on error */ int (*get_info)(struct udevice *dev, struct cpu_info *info); + + /** + * get_count() - Get number of CPUs + * + * @dev: Device to check (UCLASS_CPU) + * @return CPU count if OK, -ve on error + */ + int (*get_count)(struct udevice *dev); }; #define cpu_get_ops(dev) ((struct cpu_ops *)(dev)->driver->ops) @@ -81,4 +89,12 @@ int cpu_get_desc(struct udevice *dev, char *buf, int size); */ int cpu_get_info(struct udevice *dev, struct cpu_info *info); +/** + * cpu_get_count() - Get number of CPUs + * + * @dev: Device to check (UCLASS_CPU) + * @return CPU count if OK, -ve on error + */ +int cpu_get_count(struct udevice *dev); + #endif -- cgit v0.10.2 From 946c2b5259823ca6935a62e1a68b6e29a74e33f0 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 17 Jun 2015 11:15:35 +0800 Subject: x86: ivybridge: Remove SMP from CPU_SPECIFIC_OPTIONS Ivybridge is not ready for U-Boot MP initialization yet. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/cpu/ivybridge/Kconfig b/arch/x86/cpu/ivybridge/Kconfig index e4595be..0e249a4 100644 --- a/arch/x86/cpu/ivybridge/Kconfig +++ b/arch/x86/cpu/ivybridge/Kconfig @@ -95,7 +95,6 @@ config CPU_SPECIFIC_OPTIONS select ARCH_BOOTBLOCK_X86_32 select ARCH_ROMSTAGE_X86_32 select ARCH_RAMSTAGE_X86_32 - select SMP select SSE2 select UDELAY_LAPIC select CPU_MICROCODE_IN_CBFS -- cgit v0.10.2 From 6e6f4ce4f82501e35301322872152fe28846d743 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 17 Jun 2015 11:15:36 +0800 Subject: x86: Move MP initialization codes into a common place Most of the MP initialization codes in arch/x86/cpu/baytrail/cpu.c is common to all x86 processors, except detect_num_cpus() which varies from cpu to cpu. Move these to arch/x86/cpu/cpu.c and implement the new 'get_count' method for baytrail and cpu_x86 drivers. Now we call cpu_get_count() in mp_init() to get the number of CPUs. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c index 05156a5..a011730 100644 --- a/arch/x86/cpu/baytrail/cpu.c +++ b/arch/x86/cpu/baytrail/cpu.c @@ -12,78 +12,9 @@ #include #include #include -#include #include #include -#ifdef CONFIG_SMP -static int enable_smis(struct udevice *cpu, void *unused) -{ - return 0; -} - -static struct mp_flight_record mp_steps[] = { - MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL), - /* Wait for APs to finish initialization before proceeding. */ - MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL), -}; - -static int detect_num_cpus(void) -{ - int ecx = 0; - - /* - * Use the algorithm described in Intel 64 and IA-32 Architectures - * Software Developer's Manual Volume 3 (3A, 3B & 3C): System - * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping - * of CPUID Extended Topology Leaf. - */ - while (1) { - struct cpuid_result leaf_b; - - leaf_b = cpuid_ext(0xb, ecx); - - /* - * Bay Trail doesn't have hyperthreading so just determine the - * number of cores by from level type (ecx[15:8] == * 2) - */ - if ((leaf_b.ecx & 0xff00) == 0x0200) - return leaf_b.ebx & 0xffff; - ecx++; - } -} - -static int baytrail_init_cpus(void) -{ - struct mp_params mp_params; - - lapic_setup(); - - mp_params.num_cpus = detect_num_cpus(); - mp_params.parallel_microcode_load = 0, - mp_params.flight_plan = &mp_steps[0]; - mp_params.num_records = ARRAY_SIZE(mp_steps); - mp_params.microcode_pointer = 0; - - if (mp_init(&mp_params)) { - printf("Warning: MP init failure\n"); - return -EIO; - } - - return 0; -} -#endif - -int x86_init_cpus(void) -{ -#ifdef CONFIG_SMP - debug("Init additional CPUs\n"); - baytrail_init_cpus(); -#endif - - return 0; -} - static void set_max_freq(void) { msr_t perf_ctl; @@ -176,9 +107,38 @@ static int baytrail_get_info(struct udevice *dev, struct cpu_info *info) return 0; } +static int baytrail_get_count(struct udevice *dev) +{ + int ecx = 0; + + /* + * Use the algorithm described in Intel 64 and IA-32 Architectures + * Software Developer's Manual Volume 3 (3A, 3B & 3C): System + * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping + * of CPUID Extended Topology Leaf. + */ + while (1) { + struct cpuid_result leaf_b; + + leaf_b = cpuid_ext(0xb, ecx); + + /* + * Bay Trail doesn't have hyperthreading so just determine the + * number of cores by from level type (ecx[15:8] == * 2) + */ + if ((leaf_b.ecx & 0xff00) == 0x0200) + return leaf_b.ebx & 0xffff; + + ecx++; + } + + return 0; +} + static const struct cpu_ops cpu_x86_baytrail_ops = { .get_desc = cpu_x86_get_desc, .get_info = baytrail_get_info, + .get_count = baytrail_get_count, }; static const struct udevice_id cpu_x86_baytrail_ids[] = { diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 1dfd9e6..a6e88cf 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -21,10 +21,13 @@ #include #include +#include #include #include #include #include +#include +#include #include #include #include @@ -621,8 +624,45 @@ int last_stage_init(void) } #endif +#ifdef CONFIG_SMP +static int enable_smis(struct udevice *cpu, void *unused) +{ + return 0; +} + +static struct mp_flight_record mp_steps[] = { + MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL), + /* Wait for APs to finish initialization before proceeding */ + MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL), +}; + +static int x86_mp_init(void) +{ + struct mp_params mp_params; + + lapic_setup(); + + mp_params.parallel_microcode_load = 0, + mp_params.flight_plan = &mp_steps[0]; + mp_params.num_records = ARRAY_SIZE(mp_steps); + mp_params.microcode_pointer = 0; + + if (mp_init(&mp_params)) { + printf("Warning: MP init failure\n"); + return -EIO; + } + + return 0; +} +#endif + __weak int x86_init_cpus(void) { +#ifdef CONFIG_SMP + debug("Init additional CPUs\n"); + x86_mp_init(); +#endif + return 0; } diff --git a/arch/x86/cpu/cpu_x86.c b/arch/x86/cpu/cpu_x86.c index d32ba66..0941041 100644 --- a/arch/x86/cpu/cpu_x86.c +++ b/arch/x86/cpu/cpu_x86.c @@ -10,6 +10,8 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + int cpu_x86_bind(struct udevice *dev) { struct cpu_platdata *plat = dev_get_parent_platdata(dev); @@ -30,8 +32,34 @@ int cpu_x86_get_desc(struct udevice *dev, char *buf, int size) return 0; } +static int cpu_x86_get_count(struct udevice *dev) +{ + int node, cpu; + int num = 0; + + node = fdt_path_offset(gd->fdt_blob, "/cpus"); + if (node < 0) + return -ENOENT; + + for (cpu = fdt_first_subnode(gd->fdt_blob, node); + cpu >= 0; + cpu = fdt_next_subnode(gd->fdt_blob, cpu)) { + const char *device_type; + + device_type = fdt_getprop(gd->fdt_blob, cpu, + "device_type", NULL); + if (!device_type) + continue; + if (strcmp(device_type, "cpu") == 0) + num++; + } + + return num; +} + static const struct cpu_ops cpu_x86_ops = { .get_desc = cpu_x86_get_desc, + .get_count = cpu_x86_get_count, }; static const struct udevice_id cpu_x86_ids[] = { diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index ac5753a..5564d84 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -22,6 +22,9 @@ #include #include +/* Total CPUs include BSP */ +static int num_cpus; + /* This also needs to match the sipi.S assembly code for saved MSR encoding */ struct saved_msr { uint32_t index; @@ -383,7 +386,7 @@ static int bsp_do_flight_plan(struct udevice *cpu, struct mp_params *mp_params) int ret = 0; const int timeout_us = 100000; const int step_us = 100; - int num_aps = mp_params->num_cpus - 1; + int num_aps = num_cpus - 1; for (i = 0; i < mp_params->num_records; i++) { struct mp_flight_record *rec = &mp_params->flight_plan[i]; @@ -451,7 +454,16 @@ int mp_init(struct mp_params *p) return -1; } - ret = check_cpu_devices(p->num_cpus); + num_cpus = cpu_get_count(cpu); + if (num_cpus < 0) { + debug("Cannot get number of CPUs: err=%d\n", num_cpus); + return num_cpus; + } + + if (num_cpus < 2) + debug("Warning: Only 1 CPU is detected\n"); + + ret = check_cpu_devices(num_cpus); if (ret) debug("Warning: Device tree does not describe all CPUs. Extra ones will not be started correctly\n"); @@ -471,7 +483,7 @@ int mp_init(struct mp_params *p) wbinvd(); /* Start the APs providing number of APs and the cpus_entered field */ - num_aps = p->num_cpus - 1; + num_aps = num_cpus - 1; ret = start_aps(num_aps, ap_count); if (ret) { mdelay(1000); diff --git a/arch/x86/include/asm/mp.h b/arch/x86/include/asm/mp.h index c0930fd..2e6c312 100644 --- a/arch/x86/include/asm/mp.h +++ b/arch/x86/include/asm/mp.h @@ -59,7 +59,6 @@ struct mp_flight_record { * SMM support. */ struct mp_params { - int num_cpus; /* Total cpus include BSP */ int parallel_microcode_load; const void *microcode_pointer; /* Flight plan for APs and BSP */ diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c index a2814a8..7660f99 100644 --- a/drivers/cpu/cpu-uclass.c +++ b/drivers/cpu/cpu-uclass.c @@ -12,6 +12,8 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + int cpu_get_desc(struct udevice *dev, char *buf, int size) { struct cpu_ops *ops = cpu_get_ops(dev); -- cgit v0.10.2 From 61788e468ebe4a7b8c852ab4e761e084a7975a93 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 17 Jun 2015 11:15:37 +0800 Subject: x86: Move lapic_setup() call into init_bsp() Currently lapic_setup() is called before calling mp_init(), which then calls init_bsp() where it calls enable_lapic(), which was already enabled in lapic_setup(). Hence move lapic_setup() call into init_bsp() to avoid the duplication. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index a6e88cf..d108ee5 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -640,8 +640,6 @@ static int x86_mp_init(void) { struct mp_params mp_params; - lapic_setup(); - mp_params.parallel_microcode_load = 0, mp_params.flight_plan = &mp_steps[0]; mp_params.num_records = ARRAY_SIZE(mp_steps); diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index 5564d84..e8bc9b6 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -418,7 +418,7 @@ static int init_bsp(struct udevice **devp) cpu_get_name(processor_name); debug("CPU: %s.\n", processor_name); - enable_lapic(); + lapic_setup(); apic_id = lapicid(); ret = find_cpu_by_apid_id(apic_id, devp); -- cgit v0.10.2 From 63d54a67051e3e03b8a46b5442b65323d18ddb98 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 17 Jun 2015 11:15:38 +0800 Subject: x86: Clean up lapic codes This commit cleans up the lapic codes: - Delete arch/x86/include/asm/lapic_def.h, and move register and bit defines into arch/x86/include/asm/lapic.h - Use MSR defines from msr-index.h in enable_lapic() and disable_lapic() - Remove unnecessary stuff like NEED_LAPIC, X86_GOOD_APIC and CONFIG_AP_IN_SIPI_WAIT - Move struct x86_cpu_priv defines to asm/arch-ivybridge/bd82x6x.h, as it is not apic related and only used by ivybridge - Fix coding convention issues Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c index 8b08c40..fd7db97 100644 --- a/arch/x86/cpu/ivybridge/model_206ax.c +++ b/arch/x86/cpu/ivybridge/model_206ax.c @@ -13,12 +13,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include static void enable_vmx(void) diff --git a/arch/x86/cpu/lapic.c b/arch/x86/cpu/lapic.c index 4690603..6769ae5 100644 --- a/arch/x86/cpu/lapic.c +++ b/arch/x86/cpu/lapic.c @@ -8,50 +8,46 @@ */ #include -#include -#include #include #include void lapic_setup(void) { -#if NEED_LAPIC == 1 +#ifdef CONFIG_SMP /* Only Pentium Pro and later have those MSR stuff */ debug("Setting up local apic: "); /* Enable the local apic */ enable_lapic(); - /* - * Set Task Priority to 'accept all'. - */ + /* Set Task Priority to 'accept all' */ lapic_write_around(LAPIC_TASKPRI, lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK); /* Put the local apic in virtual wire mode */ lapic_write_around(LAPIC_SPIV, (lapic_read_around(LAPIC_SPIV) & - ~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE); + ~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE); lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) & - ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | - LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | - LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | - LAPIC_DELIVERY_MODE_MASK)) | - (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | - LAPIC_DELIVERY_MODE_EXTINT)); + ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | + LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | + LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | + LAPIC_DELIVERY_MODE_MASK)) | + (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | + LAPIC_DELIVERY_MODE_EXTINT)); lapic_write_around(LAPIC_LVT1, (lapic_read_around(LAPIC_LVT1) & - ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | - LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | - LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | - LAPIC_DELIVERY_MODE_MASK)) | - (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | - LAPIC_DELIVERY_MODE_NMI)); + ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | + LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | + LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | + LAPIC_DELIVERY_MODE_MASK)) | + (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | + LAPIC_DELIVERY_MODE_NMI)); debug("apic_id: 0x%02lx, ", lapicid()); -#else /* !NEED_LLAPIC */ +#else /* !CONFIG_SMP */ /* Only Pentium Pro and later have those MSR stuff */ debug("Disabling local apic: "); disable_lapic(); -#endif /* !NEED_LAPIC */ +#endif /* CONFIG_SMP */ debug("done.\n"); post_code(POST_LAPIC); } diff --git a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h index 5ae32f7..7786493 100644 --- a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h +++ b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h @@ -16,7 +16,19 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose, const void *blob, int node); int bd82x6x_init(void); -struct x86_cpu_priv; +/** + * struct x86_cpu_priv - Information about a single CPU + * + * @apic_id: Advanced Programmable Interrupt Controller Identifier, which is + * just a number representing the CPU core + * + * TODO: Move this to driver model once lifecycle is understood + */ +struct x86_cpu_priv { + int apic_id; + int start_err; +}; + int model_206ax_init(struct x86_cpu_priv *cpu); #endif diff --git a/arch/x86/include/asm/lapic.h b/arch/x86/include/asm/lapic.h index 0a7f443..f60974a 100644 --- a/arch/x86/include/asm/lapic.h +++ b/arch/x86/include/asm/lapic.h @@ -1,5 +1,5 @@ /* - * From Coreboot file of same name + * From coreboot file of same name * * Copyright (C) 2014 Google, Inc * @@ -10,16 +10,61 @@ #define _ARCH_ASM_LAPIC_H #include -#include #include +#include #include -/* See if I need to initialize the local apic */ -#if CONFIG_SMP || CONFIG_IOAPIC -# define NEED_LAPIC 1 -#else -# define NEED_LAPIC 0 -#endif +#define LAPIC_DEFAULT_BASE 0xfee00000 + +#define LAPIC_ID 0x020 +#define LAPIC_LVR 0x030 + +#define LAPIC_TASKPRI 0x080 +#define LAPIC_TPRI_MASK 0xff + +#define LAPIC_RRR 0x0c0 + +#define LAPIC_SPIV 0x0f0 +#define LAPIC_SPIV_ENABLE 0x100 + +#define LAPIC_ICR 0x300 +#define LAPIC_DEST_SELF 0x40000 +#define LAPIC_DEST_ALLINC 0x80000 +#define LAPIC_DEST_ALLBUT 0xc0000 +#define LAPIC_ICR_RR_MASK 0x30000 +#define LAPIC_ICR_RR_INVALID 0x00000 +#define LAPIC_ICR_RR_INPROG 0x10000 +#define LAPIC_ICR_RR_VALID 0x20000 +#define LAPIC_INT_LEVELTRIG 0x08000 +#define LAPIC_INT_ASSERT 0x04000 +#define LAPIC_ICR_BUSY 0x01000 +#define LAPIC_DEST_LOGICAL 0x00800 +#define LAPIC_DM_FIXED 0x00000 +#define LAPIC_DM_LOWEST 0x00100 +#define LAPIC_DM_SMI 0x00200 +#define LAPIC_DM_REMRD 0x00300 +#define LAPIC_DM_NMI 0x00400 +#define LAPIC_DM_INIT 0x00500 +#define LAPIC_DM_STARTUP 0x00600 +#define LAPIC_DM_EXTINT 0x00700 +#define LAPIC_VECTOR_MASK 0x000ff + +#define LAPIC_ICR2 0x310 +#define GET_LAPIC_DEST_FIELD(x) (((x) >> 24) & 0xff) +#define SET_LAPIC_DEST_FIELD(x) ((x) << 24) + +#define LAPIC_LVT0 0x350 +#define LAPIC_LVT1 0x360 +#define LAPIC_LVT_MASKED (1 << 16) +#define LAPIC_LVT_LEVEL_TRIGGER (1 << 15) +#define LAPIC_LVT_REMOTE_IRR (1 << 14) +#define LAPIC_INPUT_POLARITY (1 << 13) +#define LAPIC_SEND_PENDING (1 << 12) +#define LAPIC_LVT_RESERVED_1 (1 << 11) +#define LAPIC_DELIVERY_MODE_MASK (7 << 8) +#define LAPIC_DELIVERY_MODE_FIXED (0 << 8) +#define LAPIC_DELIVERY_MODE_NMI (4 << 8) +#define LAPIC_DELIVERY_MODE_EXTINT (7 << 8) static inline __attribute__((always_inline)) unsigned long lapic_read(unsigned long reg) @@ -42,21 +87,21 @@ static inline void enable_lapic(void) { msr_t msr; - msr = msr_read(LAPIC_BASE_MSR); + msr = msr_read(MSR_IA32_APICBASE); msr.hi &= 0xffffff00; - msr.lo |= LAPIC_BASE_MSR_ENABLE; - msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK; + msr.lo |= MSR_IA32_APICBASE_ENABLE; + msr.lo &= ~MSR_IA32_APICBASE_BASE; msr.lo |= LAPIC_DEFAULT_BASE; - msr_write(LAPIC_BASE_MSR, msr); + msr_write(MSR_IA32_APICBASE, msr); } static inline void disable_lapic(void) { msr_t msr; - msr = msr_read(LAPIC_BASE_MSR); - msr.lo &= ~(1 << 11); - msr_write(LAPIC_BASE_MSR, msr); + msr = msr_read(MSR_IA32_APICBASE); + msr.lo &= ~MSR_IA32_APICBASE_ENABLE; + msr_write(MSR_IA32_APICBASE, msr); } static inline __attribute__((always_inline)) unsigned long lapicid(void) @@ -64,30 +109,24 @@ static inline __attribute__((always_inline)) unsigned long lapicid(void) return lapic_read(LAPIC_ID) >> 24; } -#if !CONFIG_AP_IN_SIPI_WAIT -/* If we need to go back to sipi wait, we use the long non-inlined version of - * this function in lapic_cpu_init.c - */ static inline __attribute__((always_inline)) void stop_this_cpu(void) { /* Called by an AP when it is ready to halt and wait for a new task */ for (;;) cpu_hlt(); } -#else -void stop_this_cpu(void); -#endif -#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \ - sizeof(*(ptr)))) +#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \ + sizeof(*(ptr)))) -struct __xchg_dummy { unsigned long a[100]; }; -#define __xg(x) ((struct __xchg_dummy *)(x)) +struct __xchg_dummy { unsigned long a[100]; }; +#define __xg(x) ((struct __xchg_dummy *)(x)) /* - * Note: no "lock" prefix even on SMP: xchg always implies lock anyway + * Note: no "lock" prefix even on SMP. xchg always implies lock anyway. + * * Note 2: xchg has side effect, so that attribute volatile is necessary, - * but generally the primitive is invalid, *ptr is output argument. --ANK + * but generally the primitive is invalid, *ptr is output argument. */ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) @@ -121,25 +160,19 @@ static inline void lapic_write_atomic(unsigned long reg, unsigned long v) (void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v); } - -#ifdef X86_GOOD_APIC -# define FORCE_READ_AROUND_WRITE 0 -# define lapic_read_around(x) lapic_read(x) -# define lapic_write_around(x, y) lapic_write((x), (y)) -#else -# define FORCE_READ_AROUND_WRITE 1 -# define lapic_read_around(x) lapic_read(x) -# define lapic_write_around(x, y) lapic_write_atomic((x), (y)) -#endif +#define lapic_read_around(x) lapic_read(x) +#define lapic_write_around(x, y) lapic_write_atomic((x), (y)) static inline int lapic_remote_read(int apicid, int reg, unsigned long *pvalue) { int timeout; unsigned long status; int result; + lapic_wait_icr_idle(); lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid)); lapic_write_around(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4)); + timeout = 0; do { status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK; @@ -150,30 +183,10 @@ static inline int lapic_remote_read(int apicid, int reg, unsigned long *pvalue) *pvalue = lapic_read(LAPIC_RRR); result = 0; } + return result; } - void lapic_setup(void); -#if CONFIG_SMP -struct device; -int start_cpu(struct device *cpu); -#endif /* CONFIG_SMP */ - -int boot_cpu(void); - -/** - * struct x86_cpu_priv - Information about a single CPU - * - * @apic_id: Advanced Programmable Interrupt Controller Identifier, which is - * just a number representing the CPU core - * - * TODO: Move this to driver model once lifecycle is understood - */ -struct x86_cpu_priv { - int apic_id; - int start_err; -}; - #endif diff --git a/arch/x86/include/asm/lapic_def.h b/arch/x86/include/asm/lapic_def.h deleted file mode 100644 index 722cead..0000000 --- a/arch/x86/include/asm/lapic_def.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Taken from the Coreboot file of the same name - * - * (C) Copyright 2014 Google, Inc - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#ifndef _ASM_LAPIC_DEF_H -#define _ASM_LAPIC_DEF_H - -#define LAPIC_BASE_MSR 0x1B -#define LAPIC_BASE_MSR_BOOTSTRAP_PROCESSOR (1 << 8) -#define LAPIC_BASE_MSR_ENABLE (1 << 11) -#define LAPIC_BASE_MSR_ADDR_MASK 0xFFFFF000 - -#define LOCAL_APIC_ADDR 0xfee00000 -#define LAPIC_DEFAULT_BASE LOCAL_APIC_ADDR - -#define LAPIC_ID 0x020 -#define LAPIC_LVR 0x030 -#define LAPIC_TASKPRI 0x80 -#define LAPIC_TPRI_MASK 0xFF -#define LAPIC_ARBID 0x090 -#define LAPIC_RRR 0x0C0 -#define LAPIC_SVR 0x0f0 -#define LAPIC_SPIV 0x0f0 -#define LAPIC_SPIV_ENABLE 0x100 -#define LAPIC_ESR 0x280 -#define LAPIC_ESR_SEND_CS 0x00001 -#define LAPIC_ESR_RECV_CS 0x00002 -#define LAPIC_ESR_SEND_ACC 0x00004 -#define LAPIC_ESR_RECV_ACC 0x00008 -#define LAPIC_ESR_SENDILL 0x00020 -#define LAPIC_ESR_RECVILL 0x00040 -#define LAPIC_ESR_ILLREGA 0x00080 -#define LAPIC_ICR 0x300 -#define LAPIC_DEST_SELF 0x40000 -#define LAPIC_DEST_ALLINC 0x80000 -#define LAPIC_DEST_ALLBUT 0xC0000 -#define LAPIC_ICR_RR_MASK 0x30000 -#define LAPIC_ICR_RR_INVALID 0x00000 -#define LAPIC_ICR_RR_INPROG 0x10000 -#define LAPIC_ICR_RR_VALID 0x20000 -#define LAPIC_INT_LEVELTRIG 0x08000 -#define LAPIC_INT_ASSERT 0x04000 -#define LAPIC_ICR_BUSY 0x01000 -#define LAPIC_DEST_LOGICAL 0x00800 -#define LAPIC_DM_FIXED 0x00000 -#define LAPIC_DM_LOWEST 0x00100 -#define LAPIC_DM_SMI 0x00200 -#define LAPIC_DM_REMRD 0x00300 -#define LAPIC_DM_NMI 0x00400 -#define LAPIC_DM_INIT 0x00500 -#define LAPIC_DM_STARTUP 0x00600 -#define LAPIC_DM_EXTINT 0x00700 -#define LAPIC_VECTOR_MASK 0x000FF -#define LAPIC_ICR2 0x310 -#define GET_LAPIC_DEST_FIELD(x) (((x) >> 24) & 0xFF) -#define SET_LAPIC_DEST_FIELD(x) ((x) << 24) -#define LAPIC_LVTT 0x320 -#define LAPIC_LVTPC 0x340 -#define LAPIC_LVT0 0x350 -#define LAPIC_LVT_TIMER_BASE_MASK (0x3 << 18) -#define GET_LAPIC_TIMER_BASE(x) (((x) >> 18) & 0x3) -#define SET_LAPIC_TIMER_BASE(x) (((x) << 18)) -#define LAPIC_TIMER_BASE_CLKIN 0x0 -#define LAPIC_TIMER_BASE_TMBASE 0x1 -#define LAPIC_TIMER_BASE_DIV 0x2 -#define LAPIC_LVT_TIMER_PERIODIC (1 << 17) -#define LAPIC_LVT_MASKED (1 << 16) -#define LAPIC_LVT_LEVEL_TRIGGER (1 << 15) -#define LAPIC_LVT_REMOTE_IRR (1 << 14) -#define LAPIC_INPUT_POLARITY (1 << 13) -#define LAPIC_SEND_PENDING (1 << 12) -#define LAPIC_LVT_RESERVED_1 (1 << 11) -#define LAPIC_DELIVERY_MODE_MASK (7 << 8) -#define LAPIC_DELIVERY_MODE_FIXED (0 << 8) -#define LAPIC_DELIVERY_MODE_NMI (4 << 8) -#define LAPIC_DELIVERY_MODE_EXTINT (7 << 8) -#define GET_LAPIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7) -#define SET_LAPIC_DELIVERY_MODE(x, y) (((x) & ~0x700)|((y) << 8)) -#define LAPIC_MODE_FIXED 0x0 -#define LAPIC_MODE_NMI 0x4 -#define LAPIC_MODE_EXINT 0x7 -#define LAPIC_LVT1 0x360 -#define LAPIC_LVTERR 0x370 -#define LAPIC_TMICT 0x380 -#define LAPIC_TMCCT 0x390 -#define LAPIC_TDCR 0x3E0 -#define LAPIC_TDR_DIV_TMBASE (1 << 2) -#define LAPIC_TDR_DIV_1 0xB -#define LAPIC_TDR_DIV_2 0x0 -#define LAPIC_TDR_DIV_4 0x1 -#define LAPIC_TDR_DIV_8 0x2 -#define LAPIC_TDR_DIV_16 0x3 -#define LAPIC_TDR_DIV_32 0x8 -#define LAPIC_TDR_DIV_64 0x9 -#define LAPIC_TDR_DIV_128 0xA - -#endif -- cgit v0.10.2 From 990acd0d5165c3ca36716e01c5c182423bdfc16a Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 17 Jun 2015 11:15:39 +0800 Subject: x86: crownbay: Add MP initialization Intel Crown Bay board has a TunnelCreek processor which supports hyper-threading. Add /cpus node in the crownbay.dts and enable the MP initialization. Signed-off-by: Bin Meng Acked-by: Simon Glass Signed-off-by: Simon Glass (modified to remove error: overriding the value of OF_CONTROL. Old value: "y", new value: "y") diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts index d68efda..1ec90cd 100644 --- a/arch/x86/dts/crownbay.dts +++ b/arch/x86/dts/crownbay.dts @@ -23,6 +23,26 @@ silent_console = <0>; }; + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "cpu-x86"; + reg = <0>; + intel,apic-id = <0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "cpu-x86"; + reg = <1>; + intel,apic-id = <1>; + }; + + }; + gpioa { compatible = "intel,ich6-gpio"; u-boot,dm-pre-reloc; diff --git a/configs/crownbay_defconfig b/configs/crownbay_defconfig index f3fb206..93f9216 100644 --- a/configs/crownbay_defconfig +++ b/configs/crownbay_defconfig @@ -2,7 +2,10 @@ CONFIG_X86=y CONFIG_VENDOR_INTEL=y CONFIG_DEFAULT_DEVICE_TREE="crownbay" CONFIG_TARGET_CROWNBAY=y +CONFIG_SMP=y +CONFIG_MAX_CPUS=2 CONFIG_GENERATE_PIRQ_TABLE=y +CONFIG_CMD_CPU=y # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set @@ -11,6 +14,7 @@ CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_CONTROL=y +CONFIG_CPU=y CONFIG_SPI_FLASH=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y -- cgit v0.10.2 From ed2ac0d564c4fac1178d36ea46a34b923c262d03 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:41 +0800 Subject: dm: rtc: Support mc146818 driver in driver model Add driver model support to the mc146818 rtc driver. Also clean up the driver a little bit for coding convention issues. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/drivers/rtc/mc146818.c b/drivers/rtc/mc146818.c index 44857a6..363ade3 100644 --- a/drivers/rtc/mc146818.c +++ b/drivers/rtc/mc146818.c @@ -9,10 +9,9 @@ * Date & Time support for the MC146818 (PIXX4) RTC */ -/*#define DEBUG*/ - #include #include +#include #include #if defined(__I386__) || defined(CONFIG_MALTA) @@ -24,9 +23,9 @@ #if defined(CONFIG_CMD_DATE) /* Set this to 1 to clear the CMOS RAM */ -#define CLEAR_CMOS 0 +#define CLEAR_CMOS 0 -#define RTC_PORT_MC146818 CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x70 +#define RTC_PORT_MC146818 CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x70 #define RTC_SECONDS 0x00 #define RTC_SECONDS_ALARM 0x01 #define RTC_MINUTES 0x02 @@ -37,10 +36,10 @@ #define RTC_DATE_OF_MONTH 0x07 #define RTC_MONTH 0x08 #define RTC_YEAR 0x09 -#define RTC_CONFIG_A 0x0A -#define RTC_CONFIG_B 0x0B -#define RTC_CONFIG_C 0x0C -#define RTC_CONFIG_D 0x0D +#define RTC_CONFIG_A 0x0a +#define RTC_CONFIG_B 0x0b +#define RTC_CONFIG_C 0x0c +#define RTC_CONFIG_D 0x0d #define RTC_REG_SIZE 0x80 #define RTC_CONFIG_A_REF_CLCK_32KHZ (1 << 5) @@ -50,89 +49,7 @@ #define RTC_CONFIG_D_VALID_RAM_AND_TIME 0x80 -/* ------------------------------------------------------------------------- */ - -int rtc_get (struct rtc_time *tmp) -{ - uchar sec, min, hour, mday, wday, mon, year; - /* here check if rtc can be accessed */ - while ((rtc_read8(RTC_CONFIG_A) & 0x80) == 0x80); - sec = rtc_read8(RTC_SECONDS); - min = rtc_read8(RTC_MINUTES); - hour = rtc_read8(RTC_HOURS); - mday = rtc_read8(RTC_DATE_OF_MONTH); - wday = rtc_read8(RTC_DAY_OF_WEEK); - mon = rtc_read8(RTC_MONTH); - year = rtc_read8(RTC_YEAR); -#ifdef RTC_DEBUG - printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x " - "hr: %02x min: %02x sec: %02x\n", - year, mon, mday, wday, - hour, min, sec ); - printf ( "Alarms: month: %02x hour: %02x min: %02x sec: %02x\n", - rtc_read8(RTC_CONFIG_D) & 0x3F, - rtc_read8(RTC_HOURS_ALARM), - rtc_read8(RTC_MINUTES_ALARM), - rtc_read8(RTC_SECONDS_ALARM)); -#endif - tmp->tm_sec = bcd2bin (sec & 0x7F); - tmp->tm_min = bcd2bin (min & 0x7F); - tmp->tm_hour = bcd2bin (hour & 0x3F); - tmp->tm_mday = bcd2bin (mday & 0x3F); - tmp->tm_mon = bcd2bin (mon & 0x1F); - tmp->tm_year = bcd2bin (year); - tmp->tm_wday = bcd2bin (wday & 0x07); - if(tmp->tm_year<70) - tmp->tm_year+=2000; - else - tmp->tm_year+=1900; - tmp->tm_yday = 0; - tmp->tm_isdst= 0; -#ifdef RTC_DEBUG - printf ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", - tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec); -#endif - - return 0; -} - -int rtc_set (struct rtc_time *tmp) -{ -#ifdef RTC_DEBUG - printf ( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", - tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec); -#endif - rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */ - - rtc_write8(RTC_YEAR, bin2bcd(tmp->tm_year % 100)); - rtc_write8(RTC_MONTH, bin2bcd(tmp->tm_mon)); - rtc_write8(RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday)); - rtc_write8(RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday)); - rtc_write8(RTC_HOURS, bin2bcd(tmp->tm_hour)); - rtc_write8(RTC_MINUTES, bin2bcd(tmp->tm_min)); - rtc_write8(RTC_SECONDS, bin2bcd(tmp->tm_sec)); - rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */ - - return 0; -} - -void rtc_reset (void) -{ - rtc_write8(RTC_CONFIG_B, 0x82); /* disable the RTC to update the regs */ - rtc_write8(RTC_CONFIG_A, 0x20); /* Normal OP */ - rtc_write8(RTC_CONFIG_B, 0x00); - rtc_write8(RTC_CONFIG_B, 0x00); - rtc_write8(RTC_CONFIG_B, 0x02); /* enable the RTC to update the regs */ -} - -/* ------------------------------------------------------------------------- */ - -/* - * use direct memory access - */ -int rtc_read8(int reg) +static int mc146818_read8(int reg) { #ifdef CONFIG_SYS_RTC_REG_BASE_ADDR return in8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg); @@ -149,7 +66,7 @@ int rtc_read8(int reg) #endif } -void rtc_write8(int reg, uchar val) +static void mc146818_write8(int reg, uchar val) { #ifdef CONFIG_SYS_RTC_REG_BASE_ADDR out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val); @@ -165,26 +82,93 @@ void rtc_write8(int reg, uchar val) #endif } -u32 rtc_read32(int reg) +static int mc146818_get(struct rtc_time *tmp) { - u32 value = 0; - int i; + uchar sec, min, hour, mday, wday, mon, year; - for (i = 0; i < sizeof(value); i++) - value |= rtc_read8(reg + i) << (i << 3); + /* here check if rtc can be accessed */ + while ((mc146818_read8(RTC_CONFIG_A) & 0x80) == 0x80) + ; + + sec = mc146818_read8(RTC_SECONDS); + min = mc146818_read8(RTC_MINUTES); + hour = mc146818_read8(RTC_HOURS); + mday = mc146818_read8(RTC_DATE_OF_MONTH); + wday = mc146818_read8(RTC_DAY_OF_WEEK); + mon = mc146818_read8(RTC_MONTH); + year = mc146818_read8(RTC_YEAR); +#ifdef RTC_DEBUG + printf("Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x hr: %02x min: %02x sec: %02x\n", + year, mon, mday, wday, hour, min, sec); + printf("Alarms: month: %02x hour: %02x min: %02x sec: %02x\n", + mc146818_read8(RTC_CONFIG_D) & 0x3f, + mc146818_read8(RTC_HOURS_ALARM), + mc146818_read8(RTC_MINUTES_ALARM), + mc146818_read8(RTC_SECONDS_ALARM)); +#endif + tmp->tm_sec = bcd2bin(sec & 0x7f); + tmp->tm_min = bcd2bin(min & 0x7f); + tmp->tm_hour = bcd2bin(hour & 0x3f); + tmp->tm_mday = bcd2bin(mday & 0x3f); + tmp->tm_mon = bcd2bin(mon & 0x1f); + tmp->tm_year = bcd2bin(year); + tmp->tm_wday = bcd2bin(wday & 0x07); + + if (tmp->tm_year < 70) + tmp->tm_year += 2000; + else + tmp->tm_year += 1900; - return value; + tmp->tm_yday = 0; + tmp->tm_isdst = 0; +#ifdef RTC_DEBUG + printf("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); +#endif + + return 0; } -void rtc_write32(int reg, u32 value) +static int mc146818_set(struct rtc_time *tmp) { - int i; +#ifdef RTC_DEBUG + printf("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); +#endif + /* Disable the RTC to update the regs */ + mc146818_write8(RTC_CONFIG_B, 0x82); - for (i = 0; i < sizeof(value); i++) - rtc_write8(reg + i, (value >> (i << 3)) & 0xff); + mc146818_write8(RTC_YEAR, bin2bcd(tmp->tm_year % 100)); + mc146818_write8(RTC_MONTH, bin2bcd(tmp->tm_mon)); + mc146818_write8(RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday)); + mc146818_write8(RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday)); + mc146818_write8(RTC_HOURS, bin2bcd(tmp->tm_hour)); + mc146818_write8(RTC_MINUTES, bin2bcd(tmp->tm_min)); + mc146818_write8(RTC_SECONDS, bin2bcd(tmp->tm_sec)); + + /* Enable the RTC to update the regs */ + mc146818_write8(RTC_CONFIG_B, 0x02); + + return 0; } -void rtc_init(void) +static void mc146818_reset(void) +{ + /* Disable the RTC to update the regs */ + mc146818_write8(RTC_CONFIG_B, 0x82); + + /* Normal OP */ + mc146818_write8(RTC_CONFIG_A, 0x20); + mc146818_write8(RTC_CONFIG_B, 0x00); + mc146818_write8(RTC_CONFIG_B, 0x00); + + /* Enable the RTC to update the regs */ + mc146818_write8(RTC_CONFIG_B, 0x02); +} + +static void mc146818_init(void) { #if CLEAR_CMOS int i; @@ -198,14 +182,126 @@ void rtc_init(void) #endif /* Setup the real time clock */ - rtc_write8(RTC_CONFIG_B, RTC_CONFIG_B_24H); + mc146818_write8(RTC_CONFIG_B, RTC_CONFIG_B_24H); /* Setup the frequency it operates at */ - rtc_write8(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ | - RTC_CONFIG_A_RATE_1024HZ); + mc146818_write8(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ | + RTC_CONFIG_A_RATE_1024HZ); /* Ensure all reserved bits are 0 in register D */ - rtc_write8(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME); + mc146818_write8(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME); /* Clear any pending interrupts */ - rtc_read8(RTC_CONFIG_C); + mc146818_read8(RTC_CONFIG_C); } #endif + +#ifdef CONFIG_DM_RTC + +static int rtc_mc146818_get(struct udevice *dev, struct rtc_time *time) +{ + return mc146818_get(time); +} + +static int rtc_mc146818_set(struct udevice *dev, const struct rtc_time *time) +{ + return mc146818_set((struct rtc_time *)time); +} + +static int rtc_mc146818_reset(struct udevice *dev) +{ + mc146818_reset(); + + return 0; +} + +static int rtc_mc146818_read8(struct udevice *dev, unsigned int reg) +{ + return mc146818_read8(reg); +} + +static int rtc_mc146818_write8(struct udevice *dev, unsigned int reg, int val) +{ + mc146818_write8(reg, val); + + return 0; +} + +static int rtc_mc146818_bind(struct udevice *dev) +{ + mc146818_init(); + + return 0; +} + +static const struct rtc_ops rtc_mc146818_ops = { + .get = rtc_mc146818_get, + .set = rtc_mc146818_set, + .reset = rtc_mc146818_reset, + .read8 = rtc_mc146818_read8, + .write8 = rtc_mc146818_write8, +}; + +static const struct udevice_id rtc_mc146818_ids[] = { + { .compatible = "motorola,mc146818" }, + { } +}; + +U_BOOT_DRIVER(rtc_mc146818) = { + .name = "rtc_mc146818", + .id = UCLASS_RTC, + .of_match = rtc_mc146818_ids, + .bind = rtc_mc146818_bind, + .ops = &rtc_mc146818_ops, +}; + +#else /* !CONFIG_DM_RTC */ + +int rtc_get(struct rtc_time *tmp) +{ + return mc146818_get(tmp); +} + +int rtc_set(struct rtc_time *tmp) +{ + return mc146818_set(tmp); +} + +void rtc_reset(void) +{ + mc146818_reset(); +} + +int rtc_read8(int reg) +{ + return mc146818_read8(reg); +} + +void rtc_write8(int reg, uchar val) +{ + mc146818_write8(reg, val); +} + +u32 rtc_read32(int reg) +{ + u32 value = 0; + int i; + + for (i = 0; i < sizeof(value); i++) + value |= rtc_read8(reg + i) << (i << 3); + + return value; +} + +void rtc_write32(int reg, u32 value) +{ + int i; + + for (i = 0; i < sizeof(value); i++) + rtc_write8(reg + i, (value >> (i << 3)) & 0xff); +} + +void rtc_init(void) +{ + mc146818_init(); +} + +#endif /* CONFIG_DM_RTC */ -- cgit v0.10.2 From ffe387988d598f14b5cfc17b07c6dc61d8b7fa16 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:42 +0800 Subject: cmd: date: Change to use CONFIG_DM_RTC instead of CONFIG_DM_I2C Currently CONFIG_DM_I2C is used in cmd_date.c for driver model, but it should be actually CONFIG_DM_RTC. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/common/cmd_date.c b/common/cmd_date.c index 61727e3..8714699 100644 --- a/common/cmd_date.c +++ b/common/cmd_date.c @@ -37,7 +37,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) int old_bus __maybe_unused; /* switch to correct I2C bus */ -#ifdef CONFIG_DM_I2C +#ifdef CONFIG_DM_RTC struct udevice *dev; rcode = uclass_get_device(UCLASS_RTC, 0, &dev); @@ -57,7 +57,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) case 2: /* set date & time */ if (strcmp(argv[1],"reset") == 0) { puts ("Reset RTC...\n"); -#ifdef CONFIG_DM_I2C +#ifdef CONFIG_DM_RTC rcode = dm_rtc_reset(dev); if (!rcode) rcode = dm_rtc_set(dev, &default_tm); @@ -69,7 +69,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) puts("## Failed to set date after RTC reset\n"); } else { /* initialize tm with current time */ -#ifdef CONFIG_DM_I2C +#ifdef CONFIG_DM_RTC rcode = dm_rtc_get(dev, &tm); #else rcode = rtc_get(&tm); @@ -81,7 +81,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) break; } /* and write to RTC */ -#ifdef CONFIG_DM_I2C +#ifdef CONFIG_DM_RTC rcode = dm_rtc_set(dev, &tm); #else rcode = rtc_set(&tm); @@ -96,7 +96,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } /* FALL TROUGH */ case 1: /* get date & time */ -#ifdef CONFIG_DM_I2C +#ifdef CONFIG_DM_RTC rcode = dm_rtc_get(dev, &tm); #else rcode = rtc_get(&tm); @@ -120,7 +120,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* switch back to original I2C bus */ #ifdef CONFIG_SYS_I2C i2c_set_bus_num(old_bus); -#elif !defined(CONFIG_DM_I2C) +#elif !defined(CONFIG_DM_RTC) I2C_SET_BUS(old_bus); #endif -- cgit v0.10.2 From b0014b6423574780cdcb9a76478be0c1f83f7990 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:43 +0800 Subject: x86: crownbay: Enable DM RTC support Add a RTC node in the device tree to enable DM RTC support. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts index 1ec90cd..87ed0f4 100644 --- a/arch/x86/dts/crownbay.dts +++ b/arch/x86/dts/crownbay.dts @@ -10,6 +10,7 @@ /include/ "skeleton.dtsi" /include/ "serial.dtsi" +/include/ "rtc.dtsi" / { model = "Intel Crown Bay"; diff --git a/arch/x86/dts/rtc.dtsi b/arch/x86/dts/rtc.dtsi new file mode 100644 index 0000000..93dacd7 --- /dev/null +++ b/arch/x86/dts/rtc.dtsi @@ -0,0 +1,6 @@ +/ { + rtc { + compatible = "motorola,mc146818"; + reg = <0x70 2>; + }; +}; diff --git a/configs/crownbay_defconfig b/configs/crownbay_defconfig index 93f9216..6c38504 100644 --- a/configs/crownbay_defconfig +++ b/configs/crownbay_defconfig @@ -18,3 +18,4 @@ CONFIG_CPU=y CONFIG_SPI_FLASH=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y +CONFIG_DM_RTC=y -- cgit v0.10.2 From d402f922b291bb76e7e3b5c15dda7abf1ce33b85 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:44 +0800 Subject: x86: queensbay: Correct Topcliff device irqs There are 4 usb ports on the Intel Crown Bay board, 2 of which are connected to Topcliff usb host 0 and the other 2 connected to usb host 1. USB devices inserted in the ports connected to usb host 1 cannot get detected due to wrong IRQ assigned to the controller. Actually we need apply the PCI interrupt pin swizzling logic to all devices on the Topcliff chipset when configuring the PIRQ routing. This was observed on usb ports, but device 6 and 10 irqs are also wrong. Correct them all together. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts index 87ed0f4..b77c65a 100644 --- a/arch/x86/dts/crownbay.dts +++ b/arch/x86/dts/crownbay.dts @@ -180,29 +180,29 @@ * Note on the Crown Bay board, Topcliff chipset * is connected to TunnelCreek PCIe port 0, so * its bus number is 1 for its PCIe port and 2 - * for its PCI devices per U-Boot currnet PCI + * for its PCI devices per U-Boot current PCI * bus enumeration algorithm. */ PCI_BDF(1, 0, 0) INTA PIRQA PCI_BDF(2, 0, 1) INTA PIRQA PCI_BDF(2, 0, 2) INTA PIRQA - PCI_BDF(2, 2, 0) INTB PIRQB - PCI_BDF(2, 2, 1) INTB PIRQB - PCI_BDF(2, 2, 2) INTB PIRQB - PCI_BDF(2, 2, 3) INTB PIRQB - PCI_BDF(2, 2, 4) INTB PIRQB + PCI_BDF(2, 2, 0) INTB PIRQD + PCI_BDF(2, 2, 1) INTB PIRQD + PCI_BDF(2, 2, 2) INTB PIRQD + PCI_BDF(2, 2, 3) INTB PIRQD + PCI_BDF(2, 2, 4) INTB PIRQD PCI_BDF(2, 4, 0) INTC PIRQC PCI_BDF(2, 4, 1) INTC PIRQC - PCI_BDF(2, 6, 0) INTD PIRQD + PCI_BDF(2, 6, 0) INTD PIRQB PCI_BDF(2, 8, 0) INTA PIRQA PCI_BDF(2, 8, 1) INTA PIRQA PCI_BDF(2, 8, 2) INTA PIRQA PCI_BDF(2, 8, 3) INTA PIRQA - PCI_BDF(2, 10, 0) INTB PIRQB - PCI_BDF(2, 10, 1) INTB PIRQB - PCI_BDF(2, 10, 2) INTB PIRQB - PCI_BDF(2, 10, 3) INTB PIRQB - PCI_BDF(2, 10, 4) INTB PIRQB + PCI_BDF(2, 10, 0) INTB PIRQD + PCI_BDF(2, 10, 1) INTB PIRQD + PCI_BDF(2, 10, 2) INTB PIRQD + PCI_BDF(2, 10, 3) INTB PIRQD + PCI_BDF(2, 10, 4) INTB PIRQD PCI_BDF(2, 12, 0) INTC PIRQC PCI_BDF(2, 12, 1) INTC PIRQC PCI_BDF(2, 12, 2) INTC PIRQC -- cgit v0.10.2 From 9c235436a3fbc8d6959c0acee276b7060e61f2e5 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:45 +0800 Subject: x86: Write correct bus number for the irq router We should write correct bus number to the PIRQ routing table for the irq router from device tree, instead of hard-coded zero. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c index 74b89ad..7d5ccc1 100644 --- a/arch/x86/cpu/irq.c +++ b/arch/x86/cpu/irq.c @@ -161,7 +161,7 @@ static int create_pirq_routing_table(void) /* Populate the PIRQ table fields */ rt->signature = PIRQ_SIGNATURE; rt->version = PIRQ_VERSION; - rt->rtr_bus = 0; + rt->rtr_bus = PCI_BUS(irq_router.bdf); rt->rtr_devfn = (PCI_DEV(irq_router.bdf) << 3) | PCI_FUNC(irq_router.bdf); rt->rtr_vendor = PCI_VENDOR_ID_INTEL; -- cgit v0.10.2 From 8c38e4d0b8d37dcd3bfd2293481e220b1b4a3a42 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:46 +0800 Subject: x86: Ignore function number when writing PIRQ routing table In fill_irq_info() pci device's function number is written into the table, however this is not really necessary. The function number can be anything as OS doesn't care about this field, neither does the PIRQ routing specification. Change to always writing 0 as the function number. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c index 7d5ccc1..df4300c 100644 --- a/arch/x86/cpu/irq.c +++ b/arch/x86/cpu/irq.c @@ -59,12 +59,12 @@ void pirq_assign_irq(int link, u8 irq) } static inline void fill_irq_info(struct irq_info **slotp, int *entries, u8 bus, - u8 device, u8 func, u8 pin, u8 pirq) + u8 device, u8 pin, u8 pirq) { struct irq_info *slot = *slotp; slot->bus = bus; - slot->devfn = (device << 3) | func; + slot->devfn = (device << 3) | 0; slot->irq[pin - 1].link = LINK_N2V(pirq, irq_router.link_base); slot->irq[pin - 1].bitmap = irq_router.irq_mask; (*entries)++; @@ -182,8 +182,7 @@ static int create_pirq_routing_table(void) PCI_FUNC(pr.bdf), 'A' + pr.pin - 1, 'A' + pr.pirq); fill_irq_info(&slot, &irq_entries, PCI_BUS(pr.bdf), - PCI_DEV(pr.bdf), PCI_FUNC(pr.bdf), - pr.pin, pr.pirq); + PCI_DEV(pr.bdf), pr.pin, pr.pirq); cell += sizeof(struct pirq_routing) / sizeof(u32); } -- cgit v0.10.2 From df81749db7d7303508be41503e4c8d1229a07d4c Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:47 +0800 Subject: x86: Reduce PIRQ routing table size There is no need to populate multiple irq info entries with the same bus number and device number, but with different interrupt pin. We can use the same entry to store all the 4 interrupt pin (INT A/B/C/D) routing information to reduce the whole PIRQ routing table size. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c index df4300c..97dd000 100644 --- a/arch/x86/cpu/irq.c +++ b/arch/x86/cpu/irq.c @@ -58,17 +58,28 @@ void pirq_assign_irq(int link, u8 irq) writeb(irq, irq_router.ibase + LINK_N2V(link, base)); } -static inline void fill_irq_info(struct irq_info **slotp, int *entries, u8 bus, - u8 device, u8 pin, u8 pirq) +static struct irq_info *check_dup_entry(struct irq_info *slot_base, + int entry_num, int bus, int device) { - struct irq_info *slot = *slotp; + struct irq_info *slot = slot_base; + int i; + + for (i = 0; i < entry_num; i++) { + if (slot->bus == bus && slot->devfn == (device << 3)) + break; + slot++; + } + return (i == entry_num) ? NULL : slot; +} + +static inline void fill_irq_info(struct irq_info *slot, int bus, int device, + int pin, int pirq) +{ slot->bus = bus; slot->devfn = (device << 3) | 0; slot->irq[pin - 1].link = LINK_N2V(pirq, irq_router.link_base); slot->irq[pin - 1].bitmap = irq_router.irq_mask; - (*entries)++; - (*slotp)++; } __weak void cpu_irq_init(void) @@ -84,7 +95,7 @@ static int create_pirq_routing_table(void) int len, count; const u32 *cell; struct irq_routing_table *rt; - struct irq_info *slot; + struct irq_info *slot, *slot_base; int irq_entries = 0; int i; int ret; @@ -167,7 +178,7 @@ static int create_pirq_routing_table(void) rt->rtr_vendor = PCI_VENDOR_ID_INTEL; rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31; - slot = rt->slots; + slot_base = rt->slots; /* Now fill in the irq_info entries in the PIRQ table */ for (i = 0; i < count; i++) { @@ -181,8 +192,44 @@ static int create_pirq_routing_table(void) i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), PCI_FUNC(pr.bdf), 'A' + pr.pin - 1, 'A' + pr.pirq); - fill_irq_info(&slot, &irq_entries, PCI_BUS(pr.bdf), - PCI_DEV(pr.bdf), pr.pin, pr.pirq); + + slot = check_dup_entry(slot_base, irq_entries, + PCI_BUS(pr.bdf), PCI_DEV(pr.bdf)); + if (slot) { + debug("found entry for bus %d device %d, ", + PCI_BUS(pr.bdf), PCI_DEV(pr.bdf)); + + if (slot->irq[pr.pin - 1].link) { + debug("skipping\n"); + + /* + * Sanity test on the routed PIRQ pin + * + * If they don't match, show a warning to tell + * there might be something wrong with the PIRQ + * routing information in the device tree. + */ + if (slot->irq[pr.pin - 1].link != + LINK_N2V(pr.pirq, irq_router.link_base)) + debug("WARNING: Inconsistent PIRQ routing information\n"); + + cell += sizeof(struct pirq_routing) / + sizeof(u32); + continue; + } else { + debug("writing INT%c\n", 'A' + pr.pin - 1); + fill_irq_info(slot, PCI_BUS(pr.bdf), + PCI_DEV(pr.bdf), pr.pin, pr.pirq); + cell += sizeof(struct pirq_routing) / + sizeof(u32); + continue; + } + } + + slot = slot_base + irq_entries; + fill_irq_info(slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), + pr.pin, pr.pirq); + irq_entries++; cell += sizeof(struct pirq_routing) / sizeof(u32); } -- cgit v0.10.2 From ba9091f55d68fc3d7b65a710f9d47c0be15e816d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:48 +0800 Subject: x86: Clean up ioapic header file Remove all the dead/unused macros from asm/ioapic.h. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/include/asm/ioapic.h b/arch/x86/include/asm/ioapic.h index 699160f..f5d69db 100644 --- a/arch/x86/include/asm/ioapic.h +++ b/arch/x86/include/asm/ioapic.h @@ -10,29 +10,9 @@ #define __ASM_IOAPIC_H #define IO_APIC_ADDR 0xfec00000 -#define IO_APIC_INDEX IO_APIC_ADDR -#define IO_APIC_DATA (IO_APIC_ADDR + 0x10) -#define IO_APIC_INTERRUPTS 24 - -#define ALL (0xff << 24) -#define NONE 0 -#define DISABLED (1 << 16) -#define ENABLED (0 << 16) -#define TRIGGER_EDGE (0 << 15) -#define TRIGGER_LEVEL (1 << 15) -#define POLARITY_HIGH (0 << 13) -#define POLARITY_LOW (1 << 13) -#define PHYSICAL_DEST (0 << 11) -#define LOGICAL_DEST (1 << 11) -#define ExtINT (7 << 8) -#define NMI (4 << 8) -#define SMI (2 << 8) -#define INT (1 << 8) -u32 io_apic_read(u32 ioapic_base, u32 reg); -void io_apic_write(u32 ioapic_base, u32 reg, u32 value); -void set_ioapic_id(u32 ioapic_base, u8 ioapic_id); -void setup_ioapic(u32 ioapic_base, u8 ioapic_id); -void clear_ioapic(u32 ioapic_base); +/* Direct addressed register */ +#define IO_APIC_INDEX (IO_APIC_ADDR + 0x00) +#define IO_APIC_DATA (IO_APIC_ADDR + 0x10) #endif -- cgit v0.10.2 From 3d232878289bf59e83c6b152407a01f6e0fb790b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:49 +0800 Subject: x86: Add I/O APIC register access routines I/O APIC registers are addressed indirectly. Add io_apic_read() and io_apic_write() routines to help register access. Two macros for I/O APIC ID and version register offset are also added. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 48197fb..8a8e63e 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -19,7 +19,7 @@ obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/ obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/ obj-$(CONFIG_INTEL_QUARK) += quark/ obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/ -obj-y += irq.o lapic.o +obj-y += irq.o lapic.o ioapic.o obj-$(CONFIG_SMP) += mp_init.o obj-y += mtrr.o obj-$(CONFIG_PCI) += pci.o diff --git a/arch/x86/cpu/ioapic.c b/arch/x86/cpu/ioapic.c new file mode 100644 index 0000000..112a9c6 --- /dev/null +++ b/arch/x86/cpu/ioapic.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2015, Bin Meng + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +u32 io_apic_read(u32 reg) +{ + writel(reg, IO_APIC_INDEX); + return readl(IO_APIC_DATA); +} + +void io_apic_write(u32 reg, u32 val) +{ + writel(reg, IO_APIC_INDEX); + writel(val, IO_APIC_DATA); +} diff --git a/arch/x86/include/asm/ioapic.h b/arch/x86/include/asm/ioapic.h index f5d69db..77c443e 100644 --- a/arch/x86/include/asm/ioapic.h +++ b/arch/x86/include/asm/ioapic.h @@ -15,4 +15,28 @@ #define IO_APIC_INDEX (IO_APIC_ADDR + 0x00) #define IO_APIC_DATA (IO_APIC_ADDR + 0x10) +/* Indirect addressed register offset */ +#define IO_APIC_ID 0x00 +#define IO_APIC_VER 0x01 + +/** + * io_apic_read() - Read I/O APIC register + * + * This routine reads I/O APIC indirect addressed register. + * + * @reg: address of indirect addressed register + * @return: register value to read + */ +u32 io_apic_read(u32 reg); + +/** + * io_apic_write() - Write I/O APIC register + * + * This routine writes I/O APIC indirect addressed register. + * + * @reg: address of indirect addressed register + * @val: register value to write + */ +void io_apic_write(u32 reg, u32 val); + #endif -- cgit v0.10.2 From a2d73fdba638233253c14b31f3befb9099d76774 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:50 +0800 Subject: x86: Remove inline for lapic access routines Remove inline for lapic access routines and expose lapic_read() & lapic_write() as APIs to read/write lapic registers. Also move stop_this_cpu() to mp_init.c as it has nothing to do with lapic. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/cpu/lapic.c b/arch/x86/cpu/lapic.c index 6769ae5..30d2313 100644 --- a/arch/x86/cpu/lapic.c +++ b/arch/x86/cpu/lapic.c @@ -8,9 +8,116 @@ */ #include +#include #include +#include +#include #include +unsigned long lapic_read(unsigned long reg) +{ + return readl(LAPIC_DEFAULT_BASE + reg); +} + +#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \ + sizeof(*(ptr)))) + +struct __xchg_dummy { unsigned long a[100]; }; +#define __xg(x) ((struct __xchg_dummy *)(x)) + +/* + * Note: no "lock" prefix even on SMP. xchg always implies lock anyway. + * + * Note 2: xchg has side effect, so that attribute volatile is necessary, + * but generally the primitive is invalid, *ptr is output argument. + */ +static inline unsigned long __xchg(unsigned long x, volatile void *ptr, + int size) +{ + switch (size) { + case 1: + __asm__ __volatile__("xchgb %b0,%1" + : "=q" (x) + : "m" (*__xg(ptr)), "0" (x) + : "memory"); + break; + case 2: + __asm__ __volatile__("xchgw %w0,%1" + : "=r" (x) + : "m" (*__xg(ptr)), "0" (x) + : "memory"); + break; + case 4: + __asm__ __volatile__("xchgl %0,%1" + : "=r" (x) + : "m" (*__xg(ptr)), "0" (x) + : "memory"); + break; + } + + return x; +} + +void lapic_write(unsigned long reg, unsigned long v) +{ + (void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v); +} + +void enable_lapic(void) +{ + msr_t msr; + + msr = msr_read(MSR_IA32_APICBASE); + msr.hi &= 0xffffff00; + msr.lo |= MSR_IA32_APICBASE_ENABLE; + msr.lo &= ~MSR_IA32_APICBASE_BASE; + msr.lo |= LAPIC_DEFAULT_BASE; + msr_write(MSR_IA32_APICBASE, msr); +} + +void disable_lapic(void) +{ + msr_t msr; + + msr = msr_read(MSR_IA32_APICBASE); + msr.lo &= ~MSR_IA32_APICBASE_ENABLE; + msr_write(MSR_IA32_APICBASE, msr); +} + +unsigned long lapicid(void) +{ + return lapic_read(LAPIC_ID) >> 24; +} + +static void lapic_wait_icr_idle(void) +{ + do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY); +} + +int lapic_remote_read(int apicid, int reg, unsigned long *pvalue) +{ + int timeout; + unsigned long status; + int result; + + lapic_wait_icr_idle(); + lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid)); + lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4)); + + timeout = 0; + do { + status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK; + } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000); + + result = -1; + if (status == LAPIC_ICR_RR_VALID) { + *pvalue = lapic_read(LAPIC_RRR); + result = 0; + } + + return result; +} + void lapic_setup(void) { #ifdef CONFIG_SMP @@ -21,26 +128,26 @@ void lapic_setup(void) enable_lapic(); /* Set Task Priority to 'accept all' */ - lapic_write_around(LAPIC_TASKPRI, - lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK); + lapic_write(LAPIC_TASKPRI, + lapic_read(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK); /* Put the local apic in virtual wire mode */ - lapic_write_around(LAPIC_SPIV, (lapic_read_around(LAPIC_SPIV) & - ~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE); - lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) & - ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | - LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | - LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | - LAPIC_DELIVERY_MODE_MASK)) | - (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | - LAPIC_DELIVERY_MODE_EXTINT)); - lapic_write_around(LAPIC_LVT1, (lapic_read_around(LAPIC_LVT1) & - ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | - LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | - LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | - LAPIC_DELIVERY_MODE_MASK)) | - (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | - LAPIC_DELIVERY_MODE_NMI)); + lapic_write(LAPIC_SPIV, (lapic_read(LAPIC_SPIV) & + ~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE); + lapic_write(LAPIC_LVT0, (lapic_read(LAPIC_LVT0) & + ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | + LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | + LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | + LAPIC_DELIVERY_MODE_MASK)) | + (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | + LAPIC_DELIVERY_MODE_EXTINT)); + lapic_write(LAPIC_LVT1, (lapic_read(LAPIC_LVT1) & + ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | + LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | + LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | + LAPIC_DELIVERY_MODE_MASK)) | + (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | + LAPIC_DELIVERY_MODE_NMI)); debug("apic_id: 0x%02lx, ", lapicid()); #else /* !CONFIG_SMP */ diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index e8bc9b6..e686b28 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -16,7 +16,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -59,6 +61,13 @@ static inline void release_barrier(atomic_t *b) atomic_set(b, 1); } +static inline void stop_this_cpu(void) +{ + /* Called by an AP when it is ready to halt and wait for a new task */ + for (;;) + cpu_hlt(); +} + /* Returns 1 if timeout waiting for APs. 0 if target APs found */ static int wait_for_aps(atomic_t *val, int target, int total_delay, int delay_step) @@ -317,9 +326,9 @@ static int start_aps(int ap_count, atomic_t *num_aps) } /* Send INIT IPI to all but self */ - lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0)); - lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT | - LAPIC_DM_INIT); + lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0)); + lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT | + LAPIC_DM_INIT); debug("Waiting for 10ms after sending INIT.\n"); mdelay(10); @@ -334,9 +343,9 @@ static int start_aps(int ap_count, atomic_t *num_aps) } } - lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0)); - lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT | - LAPIC_DM_STARTUP | sipi_vector); + lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0)); + lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT | + LAPIC_DM_STARTUP | sipi_vector); debug("Waiting for 1st SIPI to complete..."); if (apic_wait_timeout(10000, 50)) { debug("timed out.\n"); @@ -359,9 +368,9 @@ static int start_aps(int ap_count, atomic_t *num_aps) } } - lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0)); - lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT | - LAPIC_DM_STARTUP | sipi_vector); + lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0)); + lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT | + LAPIC_DM_STARTUP | sipi_vector); debug("Waiting for 2nd SIPI to complete..."); if (apic_wait_timeout(10000, 50)) { debug("timed out.\n"); diff --git a/arch/x86/include/asm/lapic.h b/arch/x86/include/asm/lapic.h index f60974a..bc2b2d1 100644 --- a/arch/x86/include/asm/lapic.h +++ b/arch/x86/include/asm/lapic.h @@ -9,11 +9,6 @@ #ifndef _ARCH_ASM_LAPIC_H #define _ARCH_ASM_LAPIC_H -#include -#include -#include -#include - #define LAPIC_DEFAULT_BASE 0xfee00000 #define LAPIC_ID 0x020 @@ -66,126 +61,17 @@ #define LAPIC_DELIVERY_MODE_NMI (4 << 8) #define LAPIC_DELIVERY_MODE_EXTINT (7 << 8) -static inline __attribute__((always_inline)) - unsigned long lapic_read(unsigned long reg) -{ - return readl(LAPIC_DEFAULT_BASE + reg); -} - -static inline __attribute__((always_inline)) - void lapic_write(unsigned long reg, unsigned long val) -{ - writel(val, LAPIC_DEFAULT_BASE + reg); -} - -static inline __attribute__((always_inline)) void lapic_wait_icr_idle(void) -{ - do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY); -} - -static inline void enable_lapic(void) -{ - msr_t msr; - - msr = msr_read(MSR_IA32_APICBASE); - msr.hi &= 0xffffff00; - msr.lo |= MSR_IA32_APICBASE_ENABLE; - msr.lo &= ~MSR_IA32_APICBASE_BASE; - msr.lo |= LAPIC_DEFAULT_BASE; - msr_write(MSR_IA32_APICBASE, msr); -} - -static inline void disable_lapic(void) -{ - msr_t msr; - - msr = msr_read(MSR_IA32_APICBASE); - msr.lo &= ~MSR_IA32_APICBASE_ENABLE; - msr_write(MSR_IA32_APICBASE, msr); -} - -static inline __attribute__((always_inline)) unsigned long lapicid(void) -{ - return lapic_read(LAPIC_ID) >> 24; -} - -static inline __attribute__((always_inline)) void stop_this_cpu(void) -{ - /* Called by an AP when it is ready to halt and wait for a new task */ - for (;;) - cpu_hlt(); -} - -#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \ - sizeof(*(ptr)))) - -struct __xchg_dummy { unsigned long a[100]; }; -#define __xg(x) ((struct __xchg_dummy *)(x)) +unsigned long lapic_read(unsigned long reg); -/* - * Note: no "lock" prefix even on SMP. xchg always implies lock anyway. - * - * Note 2: xchg has side effect, so that attribute volatile is necessary, - * but generally the primitive is invalid, *ptr is output argument. - */ -static inline unsigned long __xchg(unsigned long x, volatile void *ptr, - int size) -{ - switch (size) { - case 1: - __asm__ __volatile__("xchgb %b0,%1" - : "=q" (x) - : "m" (*__xg(ptr)), "0" (x) - : "memory"); - break; - case 2: - __asm__ __volatile__("xchgw %w0,%1" - : "=r" (x) - : "m" (*__xg(ptr)), "0" (x) - : "memory"); - break; - case 4: - __asm__ __volatile__("xchgl %0,%1" - : "=r" (x) - : "m" (*__xg(ptr)), "0" (x) - : "memory"); - break; - } - - return x; -} - -static inline void lapic_write_atomic(unsigned long reg, unsigned long v) -{ - (void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v); -} - -#define lapic_read_around(x) lapic_read(x) -#define lapic_write_around(x, y) lapic_write_atomic((x), (y)) - -static inline int lapic_remote_read(int apicid, int reg, unsigned long *pvalue) -{ - int timeout; - unsigned long status; - int result; - - lapic_wait_icr_idle(); - lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid)); - lapic_write_around(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4)); - - timeout = 0; - do { - status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK; - } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000); - - result = -1; - if (status == LAPIC_ICR_RR_VALID) { - *pvalue = lapic_read(LAPIC_RRR); - result = 0; - } - - return result; -} +void lapic_write(unsigned long reg, unsigned long v); + +void enable_lapic(void); + +void disable_lapic(void); + +unsigned long lapicid(void); + +int lapic_remote_read(int apicid, int reg, unsigned long *pvalue); void lapic_setup(void); -- cgit v0.10.2 From 7f5df8d42d8eb0fbdb6bf168fd530aa0f01b99c7 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:51 +0800 Subject: x86: Add MultiProcessor (MP) table APIs The MP table provides a way for the operating system to support for symmetric multiprocessing as well as symmetric I/O interrupt handling with the local APIC and I/O APIC. We provide a bunch of APIs for U-Boot to write the floating table, configuration table header as well as base and extended table entries. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h new file mode 100644 index 0000000..849113a --- /dev/null +++ b/arch/x86/include/asm/mpspec.h @@ -0,0 +1,434 @@ +/* + * Copyright (C) 2015, Bin Meng + * + * Adapted from coreboot src/arch/x86/include/arch/smp/mpspec.h + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __ASM_MPSPEC_H +#define __ASM_MPSPEC_H + +/* + * Structure definitions for SMP machines following the + * Intel MultiProcessor Specification 1.4 + */ + +#define MPSPEC_V14 4 + +#define MPF_SIGNATURE "_MP_" + +struct mp_floating_table { + char mpf_signature[4]; /* "_MP_" */ + u32 mpf_physptr; /* Configuration table address */ + u8 mpf_length; /* Our length (paragraphs) */ + u8 mpf_spec; /* Specification version */ + u8 mpf_checksum; /* Checksum (makes sum 0) */ + u8 mpf_feature1; /* Predefined or Unique configuration? */ + u8 mpf_feature2; /* Bit7 set for IMCR/PIC */ + u8 mpf_feature3; /* Unused (0) */ + u8 mpf_feature4; /* Unused (0) */ + u8 mpf_feature5; /* Unused (0) */ +}; + +#define MPC_SIGNATURE "PCMP" + +struct mp_config_table { + char mpc_signature[4]; /* "PCMP" */ + u16 mpc_length; /* Size of table */ + u8 mpc_spec; /* Specification version */ + u8 mpc_checksum; /* Checksum (makes sum 0) */ + char mpc_oem[8]; /* OEM ID */ + char mpc_product[12]; /* Product ID */ + u32 mpc_oemptr; /* OEM table address */ + u16 mpc_oemsize; /* OEM table size */ + u16 mpc_entry_count; /* Number of entries in the table */ + u32 mpc_lapic; /* Local APIC address */ + u16 mpe_length; /* Extended table size */ + u8 mpe_checksum; /* Extended table checksum */ + u8 reserved; +}; + +/* Base MP configuration table entry types */ + +enum mp_base_config_entry_type { + MP_PROCESSOR, + MP_BUS, + MP_IOAPIC, + MP_INTSRC, + MP_LINTSRC +}; + +#define MPC_CPU_EN (1 << 0) +#define MPC_CPU_BP (1 << 1) + +struct mpc_config_processor { + u8 mpc_type; + u8 mpc_apicid; + u8 mpc_apicver; + u8 mpc_cpuflag; + u32 mpc_cpusignature; + u32 mpc_cpufeature; + u32 mpc_reserved[2]; +}; + +#define BUSTYPE_CBUS "CBUS " +#define BUSTYPE_CBUSII "CBUSII" +#define BUSTYPE_EISA "EISA " +#define BUSTYPE_FUTURE "FUTURE" +#define BUSTYPE_INTERN "INTERN" +#define BUSTYPE_ISA "ISA " +#define BUSTYPE_MBI "MBI " +#define BUSTYPE_MBII "MBII " +#define BUSTYPE_MCA "MCA " +#define BUSTYPE_MPI "MPI " +#define BUSTYPE_MPSA "MPSA " +#define BUSTYPE_NUBUS "NUBUS " +#define BUSTYPE_PCI "PCI " +#define BUSTYPE_PCMCIA "PCMCIA" +#define BUSTYPE_TC "TC " +#define BUSTYPE_VL "VL " +#define BUSTYPE_VME "VME " +#define BUSTYPE_XPRESS "XPRESS" + +struct mpc_config_bus { + u8 mpc_type; + u8 mpc_busid; + u8 mpc_bustype[6]; +}; + +#define MPC_APIC_USABLE (1 << 0) + +struct mpc_config_ioapic { + u8 mpc_type; + u8 mpc_apicid; + u8 mpc_apicver; + u8 mpc_flags; + u32 mpc_apicaddr; +}; + +enum mp_irq_source_types { + MP_INT, + MP_NMI, + MP_SMI, + MP_EXTINT +}; + +#define MP_IRQ_POLARITY_DEFAULT 0x0 +#define MP_IRQ_POLARITY_HIGH 0x1 +#define MP_IRQ_POLARITY_LOW 0x3 +#define MP_IRQ_POLARITY_MASK 0x3 +#define MP_IRQ_TRIGGER_DEFAULT 0x0 +#define MP_IRQ_TRIGGER_EDGE 0x4 +#define MP_IRQ_TRIGGER_LEVEL 0xc +#define MP_IRQ_TRIGGER_MASK 0xc + +#define MP_APIC_ALL 0xff + +struct mpc_config_intsrc { + u8 mpc_type; + u8 mpc_irqtype; + u16 mpc_irqflag; + u8 mpc_srcbus; + u8 mpc_srcbusirq; + u8 mpc_dstapic; + u8 mpc_dstirq; +}; + +struct mpc_config_lintsrc { + u8 mpc_type; + u8 mpc_irqtype; + u16 mpc_irqflag; + u8 mpc_srcbusid; + u8 mpc_srcbusirq; + u8 mpc_destapic; + u8 mpc_destlint; +}; + +/* Extended MP configuration table entry types */ + +enum mp_ext_config_entry_type { + MPE_SYSTEM_ADDRESS_SPACE = 128, + MPE_BUS_HIERARCHY, + MPE_COMPAT_ADDRESS_SPACE +}; + +struct mp_ext_config { + u8 mpe_type; + u8 mpe_length; +}; + +#define ADDRESS_TYPE_IO 0 +#define ADDRESS_TYPE_MEM 1 +#define ADDRESS_TYPE_PREFETCH 2 + +struct mp_ext_system_address_space { + u8 mpe_type; + u8 mpe_length; + u8 mpe_busid; + u8 mpe_addr_type; + u32 mpe_addr_base_low; + u32 mpe_addr_base_high; + u32 mpe_addr_length_low; + u32 mpe_addr_length_high; +}; + +#define BUS_SUBTRACTIVE_DECODE (1 << 0) + +struct mp_ext_bus_hierarchy { + u8 mpe_type; + u8 mpe_length; + u8 mpe_busid; + u8 mpe_bus_info; + u8 mpe_parent_busid; + u8 reserved[3]; +}; + +#define ADDRESS_RANGE_ADD 0 +#define ADDRESS_RANGE_SUBTRACT 1 + +/* + * X100 - X3FF + * X500 - X7FF + * X900 - XBFF + * XD00 - XFFF + */ +#define RANGE_LIST_IO_ISA 0 +/* + * X3B0 - X3BB + * X3C0 - X3DF + * X7B0 - X7BB + * X7C0 - X7DF + * XBB0 - XBBB + * XBC0 - XBDF + * XFB0 - XFBB + * XFC0 - XCDF + */ +#define RANGE_LIST_IO_VGA 1 + +struct mp_ext_compat_address_space { + u8 mpe_type; + u8 mpe_length; + u8 mpe_busid; + u8 mpe_addr_modifier; + u32 mpe_range_list; +}; + +/** + * mp_next_mpc_entry() - Compute MP configuration table end to be used as + * next base table entry start address + * + * This computes the end address of current MP configuration table, without + * counting any extended configuration table entry. + * + * @mc: configuration table header address + * @return: configuration table end address + */ +static inline u32 mp_next_mpc_entry(struct mp_config_table *mc) +{ + return (u32)mc + mc->mpc_length; +} + +/** + * mp_add_mpc_entry() - Add a base MP configuration table entry + * + * This adds the base MP configuration table entry size with + * added base table entry length and increases entry count by 1. + * + * @mc: configuration table header address + * @length: length of the added table entry + */ +static inline void mp_add_mpc_entry(struct mp_config_table *mc, uint length) +{ + mc->mpc_length += length; + mc->mpc_entry_count++; +} + +/** + * mp_next_mpe_entry() - Compute MP configuration table end to be used as + * next extended table entry start address + * + * This computes the end address of current MP configuration table, + * including any extended configuration table entry. + * + * @mc: configuration table header address + * @return: configuration table end address + */ +static inline u32 mp_next_mpe_entry(struct mp_config_table *mc) +{ + return (u32)mc + mc->mpc_length + mc->mpe_length; +} + +/** + * mp_add_mpe_entry() - Add an extended MP configuration table entry + * + * This adds the extended MP configuration table entry size with + * added extended table entry length. + * + * @mc: configuration table header address + * @mpe: extended table entry base address + */ +static inline void mp_add_mpe_entry(struct mp_config_table *mc, + struct mp_ext_config *mpe) +{ + mc->mpe_length += mpe->mpe_length; +} + +/** + * mp_write_floating_table() - Write the MP floating table + * + * This writes the MP floating table, and points MP configuration table + * to its end address so that MP configuration table follows immediately + * after the floating table. + * + * @mf: MP floating table base address + * @return: MP configuration table header address + */ +struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf); + +/** + * mp_config_table_init() - Initialize the MP configuration table header + * + * This populates the MP configuration table header with valid bits. + * + * @mc: MP configuration table header address + */ +void mp_config_table_init(struct mp_config_table *mc); + +/** + * mp_write_processor() - Write a processor entry + * + * This writes a processor entry to the configuration table. + * + * @mc: MP configuration table header address + */ +void mp_write_processor(struct mp_config_table *mc); + +/** + * mp_write_bus() - Write a bus entry + * + * This writes a bus entry to the configuration table. + * + * @mc: MP configuration table header address + * @id: bus id + * @bustype: bus type name + */ +void mp_write_bus(struct mp_config_table *mc, int id, const char *bustype); + +/** + * mp_write_ioapic() - Write an I/O APIC entry + * + * This writes an I/O APIC entry to the configuration table. + * + * @mc: MP configuration table header address + * @id: I/O APIC id + * @ver: I/O APIC version + * @apicaddr: I/O APIC address + */ +void mp_write_ioapic(struct mp_config_table *mc, int id, int ver, u32 apicaddr); + +/** + * mp_write_intsrc() - Write an I/O interrupt assignment entry + * + * This writes an I/O interrupt assignment entry to the configuration table. + * + * @mc: MP configuration table header address + * @irqtype: IRQ type (INT/NMI/SMI/ExtINT) + * @irqflag: IRQ flag (level/trigger) + * @srcbus: source bus id where the interrupt comes from + * @srcbusirq: IRQ number mapped on the source bus + * @dstapic: destination I/O APIC id where the interrupt goes to + * @dstirq: destination I/O APIC pin where the interrupt goes to + */ +void mp_write_intsrc(struct mp_config_table *mc, int irqtype, int irqflag, + int srcbus, int srcbusirq, int dstapic, int dstirq); + +/** + * mp_write_pci_intsrc() - Write a PCI interrupt assignment entry + * + * This writes a PCI interrupt assignment entry to the configuration table. + * + * @mc: MP configuration table header address + * @irqtype: IRQ type (INT/NMI/SMI/ExtINT) + * @srcbus: PCI bus number where the interrupt comes from + * @dev: device number on the PCI bus + * @pin: PCI interrupt pin (INT A/B/C/D) + * @dstapic: destination I/O APIC id where the interrupt goes to + * @dstirq: destination I/O APIC pin where the interrupt goes to + */ +void mp_write_pci_intsrc(struct mp_config_table *mc, int irqtype, + int srcbus, int dev, int pin, int dstapic, int dstirq); + +/** + * mp_write_lintsrc() - Write a local interrupt assignment entry + * + * This writes a local interrupt assignment entry to the configuration table. + * + * @mc: MP configuration table header address + * @irqtype: IRQ type (INT/NMI/SMI/ExtINT) + * @irqflag: IRQ flag (level/trigger) + * @srcbus: PCI bus number where the interrupt comes from + * @srcbusirq: IRQ number mapped on the source bus + * @dstapic: destination local APIC id where the interrupt goes to + * @destlint: destination local APIC pin where the interrupt goes to + */ +void mp_write_lintsrc(struct mp_config_table *mc, int irqtype, int irqflag, + int srcbus, int srcbusirq, int destapic, int destlint); + + +/** + * mp_write_address_space() - Write a system address space entry + * + * This writes a system address space entry to the configuration table. + * + * @mc: MP configuration table header address + * @busid: bus id for the bus where system address space is mapped + * @addr_type: system address type + * @addr_base_low: starting address low + * @addr_base_high: starting address high + * @addr_length_low: address length low + * @addr_length_high: address length high + */ +void mp_write_address_space(struct mp_config_table *mc, + int busid, int addr_type, + u32 addr_base_low, u32 addr_base_high, + u32 addr_length_low, u32 addr_length_high); + +/** + * mp_write_bus_hierarchy() - Write a bus hierarchy descriptor entry + * + * This writes a bus hierarchy descriptor entry to the configuration table. + * + * @mc: MP configuration table header address + * @busid: bus id + * @bus_info: bit0 indicates if the bus is a subtractive decode bus + * @parent_busid: parent bus id + */ +void mp_write_bus_hierarchy(struct mp_config_table *mc, + int busid, int bus_info, int parent_busid); + +/** + * mp_write_compat_address_space() - Write a compat bus address space entry + * + * This writes a compatibility bus address space modifier entry to the + * configuration table. + * + * @mc: MP configuration table header address + * @busid: bus id + * @addr_modifier: add or subtract to predefined address range list + * @range_list: list of predefined address space ranges + */ +void mp_write_compat_address_space(struct mp_config_table *mc, int busid, + int addr_modifier, u32 range_list); + +/** + * mptable_finalize() - Finalize the MP table + * + * This finalizes the MP table by calculating required checksums. + * + * @mc: MP configuration table header address + * @return: MP table end address + */ +u32 mptable_finalize(struct mp_config_table *mc); + +#endif /* __ASM_MPSPEC_H */ diff --git a/arch/x86/include/asm/tables.h b/arch/x86/include/asm/tables.h index 8146ba3..0aa6d9b 100644 --- a/arch/x86/include/asm/tables.h +++ b/arch/x86/include/asm/tables.h @@ -28,6 +28,20 @@ u8 table_compute_checksum(void *v, int len); /** + * table_fill_string() - Fill a string with pad in the configuration table + * + * This fills a string in the configuration table. It copies number of bytes + * from the source string, and if source string length is shorter than the + * required size to copy, pad the table string with the given pad character. + * + * @dest: where to fill a string + * @src: where to copy from + * @n: number of bytes to copy + * @pad: character to pad the remaining bytes + */ +void table_fill_string(char *dest, const char *src, size_t n, char pad); + +/** * write_tables() - Write x86 configuration tables * * This writes x86 configuration tables, including PIRQ routing table, diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 70ad19b..43489fd 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -15,6 +15,7 @@ obj-y += gcc.o obj-y += init_helpers.o obj-y += interrupts.o obj-y += lpc-uclass.o +obj-y += mpspec.o obj-y += cmd_mtrr.o obj-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o obj-$(CONFIG_SYS_PCAT_TIMER) += pcat_timer.o diff --git a/arch/x86/lib/mpspec.c b/arch/x86/lib/mpspec.c new file mode 100644 index 0000000..26d1025 --- /dev/null +++ b/arch/x86/lib/mpspec.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2015, Bin Meng + * + * Adapted from coreboot src/arch/x86/boot/mpspec.c + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf) +{ + u32 mc; + + memcpy(mf->mpf_signature, MPF_SIGNATURE, 4); + mf->mpf_physptr = (u32)mf + sizeof(struct mp_floating_table); + mf->mpf_length = 1; + mf->mpf_spec = MPSPEC_V14; + mf->mpf_checksum = 0; + /* We don't use the default configuration table */ + mf->mpf_feature1 = 0; + /* Indicate that virtual wire mode is always implemented */ + mf->mpf_feature2 = 0; + mf->mpf_feature3 = 0; + mf->mpf_feature4 = 0; + mf->mpf_feature5 = 0; + mf->mpf_checksum = table_compute_checksum(mf, mf->mpf_length * 16); + + mc = (u32)mf + sizeof(struct mp_floating_table); + return (struct mp_config_table *)mc; +} + +void mp_config_table_init(struct mp_config_table *mc) +{ + memcpy(mc->mpc_signature, MPC_SIGNATURE, 4); + mc->mpc_length = sizeof(struct mp_config_table); + mc->mpc_spec = MPSPEC_V14; + mc->mpc_checksum = 0; + mc->mpc_oemptr = 0; + mc->mpc_oemsize = 0; + mc->mpc_entry_count = 0; + mc->mpc_lapic = LAPIC_DEFAULT_BASE; + mc->mpe_length = 0; + mc->mpe_checksum = 0; + mc->reserved = 0; + + /* The oem/product id fields are exactly 8/12 bytes long */ + table_fill_string(mc->mpc_oem, CONFIG_SYS_VENDOR, 8, ' '); + table_fill_string(mc->mpc_product, CONFIG_SYS_BOARD, 12, ' '); +} + +void mp_write_processor(struct mp_config_table *mc) +{ + struct mpc_config_processor *mpc; + struct udevice *dev; + u8 boot_apicid, apicver; + u32 cpusignature, cpufeature; + struct cpuid_result result; + + boot_apicid = lapicid(); + apicver = lapic_read(LAPIC_LVR) & 0xff; + result = cpuid(1); + cpusignature = result.eax; + cpufeature = result.edx; + + for (uclass_find_first_device(UCLASS_CPU, &dev); + dev; + uclass_find_next_device(&dev)) { + struct cpu_platdata *plat = dev_get_parent_platdata(dev); + u8 cpuflag = MPC_CPU_EN; + + if (!device_active(dev)) + continue; + + mpc = (struct mpc_config_processor *)mp_next_mpc_entry(mc); + mpc->mpc_type = MP_PROCESSOR; + mpc->mpc_apicid = plat->cpu_id; + mpc->mpc_apicver = apicver; + if (boot_apicid == plat->cpu_id) + cpuflag |= MPC_CPU_BP; + mpc->mpc_cpuflag = cpuflag; + mpc->mpc_cpusignature = cpusignature; + mpc->mpc_cpufeature = cpufeature; + mpc->mpc_reserved[0] = 0; + mpc->mpc_reserved[1] = 0; + mp_add_mpc_entry(mc, sizeof(*mpc)); + } +} + +void mp_write_bus(struct mp_config_table *mc, int id, const char *bustype) +{ + struct mpc_config_bus *mpc; + + mpc = (struct mpc_config_bus *)mp_next_mpc_entry(mc); + mpc->mpc_type = MP_BUS; + mpc->mpc_busid = id; + memcpy(mpc->mpc_bustype, bustype, 6); + mp_add_mpc_entry(mc, sizeof(*mpc)); +} + +void mp_write_ioapic(struct mp_config_table *mc, int id, int ver, u32 apicaddr) +{ + struct mpc_config_ioapic *mpc; + + mpc = (struct mpc_config_ioapic *)mp_next_mpc_entry(mc); + mpc->mpc_type = MP_IOAPIC; + mpc->mpc_apicid = id; + mpc->mpc_apicver = ver; + mpc->mpc_flags = MPC_APIC_USABLE; + mpc->mpc_apicaddr = apicaddr; + mp_add_mpc_entry(mc, sizeof(*mpc)); +} + +void mp_write_intsrc(struct mp_config_table *mc, int irqtype, int irqflag, + int srcbus, int srcbusirq, int dstapic, int dstirq) +{ + struct mpc_config_intsrc *mpc; + + mpc = (struct mpc_config_intsrc *)mp_next_mpc_entry(mc); + mpc->mpc_type = MP_INTSRC; + mpc->mpc_irqtype = irqtype; + mpc->mpc_irqflag = irqflag; + mpc->mpc_srcbus = srcbus; + mpc->mpc_srcbusirq = srcbusirq; + mpc->mpc_dstapic = dstapic; + mpc->mpc_dstirq = dstirq; + mp_add_mpc_entry(mc, sizeof(*mpc)); +} + +void mp_write_pci_intsrc(struct mp_config_table *mc, int irqtype, + int srcbus, int dev, int pin, int dstapic, int dstirq) +{ + u8 srcbusirq = (dev << 2) | (pin - 1); + + mp_write_intsrc(mc, irqtype, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW, + srcbus, srcbusirq, dstapic, dstirq); +} + +void mp_write_lintsrc(struct mp_config_table *mc, int irqtype, int irqflag, + int srcbus, int srcbusirq, int destapic, int destlint) +{ + struct mpc_config_lintsrc *mpc; + + mpc = (struct mpc_config_lintsrc *)mp_next_mpc_entry(mc); + mpc->mpc_type = MP_LINTSRC; + mpc->mpc_irqtype = irqtype; + mpc->mpc_irqflag = irqflag; + mpc->mpc_srcbusid = srcbus; + mpc->mpc_srcbusirq = srcbusirq; + mpc->mpc_destapic = destapic; + mpc->mpc_destlint = destlint; + mp_add_mpc_entry(mc, sizeof(*mpc)); +} + +void mp_write_address_space(struct mp_config_table *mc, + int busid, int addr_type, + u32 addr_base_low, u32 addr_base_high, + u32 addr_length_low, u32 addr_length_high) +{ + struct mp_ext_system_address_space *mpe; + + mpe = (struct mp_ext_system_address_space *)mp_next_mpe_entry(mc); + mpe->mpe_type = MPE_SYSTEM_ADDRESS_SPACE; + mpe->mpe_length = sizeof(*mpe); + mpe->mpe_busid = busid; + mpe->mpe_addr_type = addr_type; + mpe->mpe_addr_base_low = addr_base_low; + mpe->mpe_addr_base_high = addr_base_high; + mpe->mpe_addr_length_low = addr_length_low; + mpe->mpe_addr_length_high = addr_length_high; + mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe); +} + +void mp_write_bus_hierarchy(struct mp_config_table *mc, + int busid, int bus_info, int parent_busid) +{ + struct mp_ext_bus_hierarchy *mpe; + + mpe = (struct mp_ext_bus_hierarchy *)mp_next_mpe_entry(mc); + mpe->mpe_type = MPE_BUS_HIERARCHY; + mpe->mpe_length = sizeof(*mpe); + mpe->mpe_busid = busid; + mpe->mpe_bus_info = bus_info; + mpe->mpe_parent_busid = parent_busid; + mpe->reserved[0] = 0; + mpe->reserved[1] = 0; + mpe->reserved[2] = 0; + mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe); +} + +void mp_write_compat_address_space(struct mp_config_table *mc, int busid, + int addr_modifier, u32 range_list) +{ + struct mp_ext_compat_address_space *mpe; + + mpe = (struct mp_ext_compat_address_space *)mp_next_mpe_entry(mc); + mpe->mpe_type = MPE_COMPAT_ADDRESS_SPACE; + mpe->mpe_length = sizeof(*mpe); + mpe->mpe_busid = busid; + mpe->mpe_addr_modifier = addr_modifier; + mpe->mpe_range_list = range_list; + mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe); +} + +u32 mptable_finalize(struct mp_config_table *mc) +{ + u32 end; + + mc->mpe_checksum = table_compute_checksum((void *)mp_next_mpc_entry(mc), + mc->mpe_length); + mc->mpc_checksum = table_compute_checksum(mc, mc->mpc_length); + end = mp_next_mpe_entry(mc); + + debug("Write the MP table at: %x - %x\n", (u32)mc, end); + + return end; +} diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index 8031201..41c50bc 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -20,6 +20,20 @@ u8 table_compute_checksum(void *v, int len) return checksum; } +void table_fill_string(char *dest, const char *src, size_t n, char pad) +{ + int start, len; + int i; + + strncpy(dest, src, n); + + /* Fill the remaining bytes with pad */ + len = strlen(src); + start = len < n ? len : n; + for (i = start; i < n; i++) + dest[i] = pad; +} + void write_tables(void) { u32 __maybe_unused rom_table_end = ROM_TABLE_ADDR; -- cgit v0.10.2 From 07545d861ccc54aecbeaa51b264258b90912b856 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:52 +0800 Subject: x86: Generate a valid MultiProcessor (MP) table Implement write_mp_table() to create a minimal working MP table. This includes an MP floating table, a configuration table header and all of the 5 base configuration table entries. The I/O interrupt assignment table entry is created based on the same information used in the creation of PIRQ routing table from device tree. A check duplicated entry logic is applied to prevent writing multiple I/O interrupt entries with the same information. Use a Kconfig option GENERATE_MP_TABLE to tell U-Boot whether we need actually write the MP table at the F seg, just like we did for PIRQ routing and SFI tables. With MP table existence, linux kernel will switch to I/O APIC and local APIC to process all the peripheral interrupts instead of 8259 PICs. This takes full advantage of the multicore hardware and the SMP kernel. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 36e97c8..b52a80e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -313,6 +313,15 @@ config GENERATE_SFI_TABLE For more information, see http://simplefirmware.org +config GENERATE_MP_TABLE + bool "Generate an MP (Multi-Processor) table" + default n + help + Generate an MP (Multi-Processor) table for this board. The MP table + provides a way for the operating system to support for symmetric + multiprocessing as well as symmetric I/O interrupt handling with + the local APIC and I/O APIC. + endmenu config MAX_PIRQ_LINKS diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index 849113a..efa9231 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -431,4 +431,14 @@ void mp_write_compat_address_space(struct mp_config_table *mc, int busid, */ u32 mptable_finalize(struct mp_config_table *mc); +/** + * write_mp_table() - Write MP table + * + * This writes MP table at a given address. + * + * @addr: start address to write MP table + * @return: end address of MP table + */ +u32 write_mp_table(u32 addr); + #endif /* __ASM_MPSPEC_H */ diff --git a/arch/x86/lib/mpspec.c b/arch/x86/lib/mpspec.c index 26d1025..f16fbcb 100644 --- a/arch/x86/lib/mpspec.c +++ b/arch/x86/lib/mpspec.c @@ -9,13 +9,18 @@ #include #include #include +#include +#include #include +#include #include #include #include #include #include +DECLARE_GLOBAL_DATA_PTR; + struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf) { u32 mc; @@ -223,3 +228,155 @@ u32 mptable_finalize(struct mp_config_table *mc) return end; } + +static void mptable_add_isa_interrupts(struct mp_config_table *mc, int bus_isa, + int apicid, int external_int2) +{ + int i; + + mp_write_intsrc(mc, external_int2 ? MP_INT : MP_EXTINT, + MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, + bus_isa, 0, apicid, 0); + mp_write_intsrc(mc, MP_INT, MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, + bus_isa, 1, apicid, 1); + mp_write_intsrc(mc, external_int2 ? MP_EXTINT : MP_INT, + MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, + bus_isa, 0, apicid, 2); + + for (i = 3; i < 16; i++) + mp_write_intsrc(mc, MP_INT, + MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, + bus_isa, i, apicid, i); +} + +/* + * Check duplicated I/O interrupt assignment table entry, to make sure + * there is only one entry with the given bus, device and interrupt pin. + */ +static bool check_dup_entry(struct mpc_config_intsrc *intsrc_base, + int entry_num, int bus, int device, int pin) +{ + struct mpc_config_intsrc *intsrc = intsrc_base; + int i; + + for (i = 0; i < entry_num; i++) { + if (intsrc->mpc_srcbus == bus && + intsrc->mpc_srcbusirq == ((device << 2) | (pin - 1))) + break; + intsrc++; + } + + return (i == entry_num) ? false : true; +} + +static int mptable_add_intsrc(struct mp_config_table *mc, + int bus_isa, int apicid) +{ + struct mpc_config_intsrc *intsrc_base; + int intsrc_entries = 0; + const void *blob = gd->fdt_blob; + int node; + int len, count; + const u32 *cell; + int i; + + /* Legacy Interrupts */ + debug("Writing ISA IRQs\n"); + mptable_add_isa_interrupts(mc, bus_isa, apicid, 0); + + /* Get I/O interrupt information from device tree */ + node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_IRQ_ROUTER); + if (node < 0) { + debug("%s: Cannot find irq router node\n", __func__); + return -ENOENT; + } + + cell = fdt_getprop(blob, node, "intel,pirq-routing", &len); + if (!cell) + return -ENOENT; + + if ((len % sizeof(struct pirq_routing)) == 0) + count = len / sizeof(struct pirq_routing); + else + return -EINVAL; + + intsrc_base = (struct mpc_config_intsrc *)mp_next_mpc_entry(mc); + + for (i = 0; i < count; i++) { + struct pirq_routing pr; + + pr.bdf = fdt_addr_to_cpu(cell[0]); + pr.pin = fdt_addr_to_cpu(cell[1]); + pr.pirq = fdt_addr_to_cpu(cell[2]); + + if (check_dup_entry(intsrc_base, intsrc_entries, + PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), pr.pin)) { + debug("found entry for bus %d device %d INT%c, skipping\n", + PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), + 'A' + pr.pin - 1); + cell += sizeof(struct pirq_routing) / sizeof(u32); + continue; + } + + /* PIRQ[A-H] are always connected to I/O APIC INTPIN#16-23 */ + mp_write_pci_intsrc(mc, MP_INT, PCI_BUS(pr.bdf), + PCI_DEV(pr.bdf), pr.pin, apicid, + pr.pirq + 16); + intsrc_entries++; + cell += sizeof(struct pirq_routing) / sizeof(u32); + } + + return 0; +} + +static void mptable_add_lintsrc(struct mp_config_table *mc, int bus_isa) +{ + mp_write_lintsrc(mc, MP_EXTINT, + MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, + bus_isa, 0, MP_APIC_ALL, 0); + mp_write_lintsrc(mc, MP_NMI, + MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, + bus_isa, 0, MP_APIC_ALL, 1); +} + +u32 write_mp_table(u32 addr) +{ + struct mp_config_table *mc; + int ioapic_id, ioapic_ver; + int bus_isa = 0xff; + int ret; + u32 end; + + /* 16 byte align the table address */ + addr = ALIGN(addr, 16); + + /* Write floating table */ + mc = mp_write_floating_table((struct mp_floating_table *)addr); + + /* Write configuration table header */ + mp_config_table_init(mc); + + /* Write processor entry */ + mp_write_processor(mc); + + /* Write bus entry */ + mp_write_bus(mc, bus_isa, BUSTYPE_ISA); + + /* Write I/O APIC entry */ + ioapic_id = io_apic_read(IO_APIC_ID) >> 24; + ioapic_ver = io_apic_read(IO_APIC_VER) & 0xff; + mp_write_ioapic(mc, ioapic_id, ioapic_ver, IO_APIC_ADDR); + + /* Write I/O interrupt assignment entry */ + ret = mptable_add_intsrc(mc, bus_isa, ioapic_id); + if (ret) + debug("Failed to write I/O interrupt assignment table\n"); + + /* Write local interrupt assignment entry */ + mptable_add_lintsrc(mc, bus_isa); + + /* Finalize the MP table */ + end = mptable_finalize(mc); + + return end; +} diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index 41c50bc..75ffbc1 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -6,6 +6,7 @@ #include #include +#include #include u8 table_compute_checksum(void *v, int len) @@ -46,4 +47,8 @@ void write_tables(void) rom_table_end = write_sfi_table(rom_table_end); rom_table_end = ALIGN(rom_table_end, 1024); #endif +#ifdef CONFIG_GENERATE_MP_TABLE + rom_table_end = write_mp_table(rom_table_end); + rom_table_end = ALIGN(rom_table_end, 1024); +#endif } -- cgit v0.10.2 From 1281a1fc97992b8561f500bf2d0f222149031d4b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:53 +0800 Subject: x86: Update README.x86 for SMP support Document U-Boot multi-processor support as well as configuration tables like SFI and MP tables for SMP OS kernel. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/doc/README.x86 b/doc/README.x86 index c19f4a0..49d6e83 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -258,6 +258,17 @@ Modern CPUs usually require a special bit stream called microcode [6] to be loaded on the processor after power up in order to function properly. U-Boot has already integrated these as hex dumps in the source tree. +SMP Support +----------- +On a multicore system, U-Boot is executed on the bootstrap processor (BSP). +Additional application processors (AP) can be brought up by U-Boot. In order to +have an SMP kernel to discover all of the available processors, U-Boot needs to +prepare configuration tables which contain the multi-CPUs information before +loading the OS kernel. Currently U-Boot supports generating two types of tables +for SMP, called Simple Firmware Interface (SFI) [7] and Multi-Processor (MP) [8] +tables. The writing of these two tables are controlled by two Kconfig options +GENERATE_SFI_TABLE and GENERATE_MP_TABLE. + Driver Model ------------ x86 has been converted to use driver model for serial and GPIO. @@ -362,3 +373,5 @@ References [4] http://www.intel.com/content/www/us/en/embedded/design-tools/evaluation-platforms/atom-e660-eg20t-development-kit.html [5] http://www.intel.com/fsp [6] http://en.wikipedia.org/wiki/Microcode +[7] http://simplefirmware.org +[8] http://www.intel.com/design/archives/processors/pro/docs/242016.htm -- cgit v0.10.2 From 07a52865fe4a2e8bce16d9d8f8a61c66b3afa9ee Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:54 +0800 Subject: x86: crownbay: Enable writing MP table Enable writing MP table for Intel Crown Bay board. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/configs/crownbay_defconfig b/configs/crownbay_defconfig index 6c38504..2af93bc 100644 --- a/configs/crownbay_defconfig +++ b/configs/crownbay_defconfig @@ -18,4 +18,5 @@ CONFIG_CPU=y CONFIG_SPI_FLASH=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y +CONFIG_GENERATE_MP_TABLE=y CONFIG_DM_RTC=y -- cgit v0.10.2 From cdb6babec6422ad4b89e447b1b468f625deaea79 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 23 Jun 2015 12:18:55 +0800 Subject: x86: queensbay: Change PCIe root ports' interrupt routing So far interrupt routing works pretty well for any on-chip devices on Intel Crown Bay. When inserting any PCIe card to any PCIe slot, Linux kernel is smart enough to do interrupt swizzling and figure out device's irq using its parent bridge's interrupt routing info all the way up to its root port. In U-Boot all PCIe root ports' interrupts were routed to PIRQ E/F/G/H before, while actually all PCIe downstream ports received INTx are routed to PIRQ A/B/C/D directly and not configurable. Now we change this mapping so that any external PCIe device can work correctly. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c index 873de7b..d27b2d9 100644 --- a/arch/x86/cpu/queensbay/tnc.c +++ b/arch/x86/cpu/queensbay/tnc.c @@ -69,17 +69,18 @@ void cpu_irq_init(void) * Route TunnelCreek PCI device interrupt pin to PIRQ * * Since PCIe downstream ports received INTx are routed to PIRQ - * A/B/C/D directly and not configurable, we route internal PCI - * device's INTx to PIRQ E/F/G/H. + * A/B/C/D directly and not configurable, we have to route PCIe + * root ports' INTx to PIRQ A/B/C/D as well. For other devices + * on TunneCreek, route them to PIRQ E/F/G/H. */ writew(PIRQE, &rcba->d02ir); writew(PIRQF, &rcba->d03ir); writew(PIRQG, &rcba->d27ir); writew(PIRQH, &rcba->d31ir); - writew(PIRQE, &rcba->d23ir); - writew(PIRQF, &rcba->d24ir); - writew(PIRQG, &rcba->d25ir); - writew(PIRQH, &rcba->d26ir); + writew(PIRQA, &rcba->d23ir); + writew(PIRQB, &rcba->d24ir); + writew(PIRQC, &rcba->d25ir); + writew(PIRQD, &rcba->d26ir); } int arch_misc_init(void) diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts index b77c65a..60da1f5 100644 --- a/arch/x86/dts/crownbay.dts +++ b/arch/x86/dts/crownbay.dts @@ -169,10 +169,22 @@ /* TunnelCreek PCI devices */ PCI_BDF(0, 2, 0) INTA PIRQE PCI_BDF(0, 3, 0) INTA PIRQF - PCI_BDF(0, 23, 0) INTA PIRQE - PCI_BDF(0, 24, 0) INTA PIRQF - PCI_BDF(0, 25, 0) INTA PIRQG - PCI_BDF(0, 26, 0) INTA PIRQH + PCI_BDF(0, 23, 0) INTA PIRQA + PCI_BDF(0, 23, 0) INTB PIRQB + PCI_BDF(0, 23, 0) INTC PIRQC + PCI_BDF(0, 23, 0) INTD PIRQD + PCI_BDF(0, 24, 0) INTA PIRQB + PCI_BDF(0, 24, 0) INTB PIRQC + PCI_BDF(0, 24, 0) INTC PIRQD + PCI_BDF(0, 24, 0) INTD PIRQA + PCI_BDF(0, 25, 0) INTA PIRQC + PCI_BDF(0, 25, 0) INTB PIRQD + PCI_BDF(0, 25, 0) INTC PIRQA + PCI_BDF(0, 25, 0) INTD PIRQB + PCI_BDF(0, 26, 0) INTA PIRQD + PCI_BDF(0, 26, 0) INTB PIRQA + PCI_BDF(0, 26, 0) INTC PIRQB + PCI_BDF(0, 26, 0) INTD PIRQC PCI_BDF(0, 27, 0) INTA PIRQG /* * Topcliff PCI devices -- cgit v0.10.2 From aec241dfb45e7763716c1cbc98942cb01a3a77fd Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 7 Jun 2015 08:50:40 -0600 Subject: dm: pci: Use the correct hose when configuring devices Only the PCI controller has access to the PCI region information. Make sure to use the controller (rather than any attached bridges) when configuring devices. This corrects a failure to scan and configure devices when driver model is enabled for PCI. Also add a comment to explain the problem. Signed-off-by: Simon Glass diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index de87505..41d19cb 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -296,6 +296,7 @@ int pci_auto_config_devices(struct udevice *bus) !ret && dev; ret = device_find_next_child(&dev)) { struct pci_child_platdata *pplat; + struct pci_controller *ctlr_hose; pplat = dev_get_parent_platdata(dev); unsigned int max_bus; @@ -303,7 +304,10 @@ int pci_auto_config_devices(struct udevice *bus) bdf = PCI_ADD_BUS(bus->seq, pplat->devfn); debug("%s: device %s\n", __func__, dev->name); - max_bus = pciauto_config_device(hose, bdf); + + /* The root controller has the region information */ + ctlr_hose = hose->ctlr->uclass_priv; + max_bus = pciauto_config_device(ctlr_hose, bdf); sub_bus = max(sub_bus, max_bus); } debug("%s: done\n", __func__); diff --git a/drivers/pci/pci_common.c b/drivers/pci/pci_common.c index b9ff23f..f67c9c7 100644 --- a/drivers/pci/pci_common.c +++ b/drivers/pci/pci_common.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -221,6 +222,11 @@ phys_addr_t pci_hose_bus_to_phys(struct pci_controller *hose, return phys_addr; } +#ifdef CONFIG_DM_PCI + /* The root controller has the region information */ + hose = hose->ctlr->uclass_priv; +#endif + /* * if PCI_REGION_MEM is set we do a two pass search with preference * on matches that don't have PCI_REGION_SYS_MEMORY set diff --git a/include/pci.h b/include/pci.h index 07b1e9a..3af511b 100644 --- a/include/pci.h +++ b/include/pci.h @@ -513,6 +513,16 @@ struct pci_controller { int indirect_type; + /* + * TODO(sjg@chromium.org): With driver model we use struct + * pci_controller for both the controller and any bridge devices + * attached to it. But there is only one region list and it is in the + * top-level controller. + * + * This could be changed so that struct pci_controller is only used + * for PCI controllers and a separate UCLASS (or perhaps + * UCLASS_PCI_GENERIC) is used for bridges. + */ struct pci_region regions[MAX_PCI_REGIONS]; int region_count; -- cgit v0.10.2 From 5afeb4bb456de129a88f38fae1573564cd53fc41 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 7 Jun 2015 08:50:41 -0600 Subject: dm: pci: Correct bus number when scanning sub-buses The sub-bus passed to pciauto_prescan_setup_bridge() is incorrect. Fix it so that sub-buses are numbered correctly. Signed-off-by: Simon Glass diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 41d19cb..edec93f 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -334,7 +334,7 @@ int dm_pci_hose_probe_bus(struct pci_controller *hose, pci_dev_t bdf) sub_bus = pci_get_bus_max() + 1; debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name); - pciauto_prescan_setup_bridge(hose, bdf, bus->seq); + pciauto_prescan_setup_bridge(hose, bdf, sub_bus); ret = device_probe(bus); if (ret) { -- cgit v0.10.2 From b018a8c71602d53d5d5ebac859f33327b97e9cec Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 6 Jul 2015 16:31:26 +0800 Subject: video: vesa_fb: Look up VGA device by class instead of id Per PCI spec, VGA device reports its class as standard 030000h in its configuration space, so we can use it to determine if we need run option rom instead of testing the supported vendor/device ids. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/drivers/video/vesa_fb.c b/drivers/video/vesa_fb.c index 47f824a..909f8e8 100644 --- a/drivers/video/vesa_fb.c +++ b/drivers/video/vesa_fb.c @@ -1,6 +1,5 @@ /* - * - * Vesa frame buffer driver for x86 + * VESA frame buffer driver * * Copyright (C) 2014 Google, Inc * @@ -17,16 +16,6 @@ */ GraphicDevice ctfb; -/* Devices to allow - only the last one works fully */ -struct pci_device_id vesa_video_ids[] = { - { .vendor = 0x102b, .device = 0x0525 }, - { .vendor = 0x1002, .device = 0x5159 }, - { .vendor = 0x1002, .device = 0x4752 }, - { .vendor = 0x1002, .device = 0x5452 }, - { .vendor = 0x8086, .device = 0x0f31 }, - {}, -}; - void *video_hw_init(void) { GraphicDevice *gdev = &ctfb; @@ -36,8 +25,7 @@ void *video_hw_init(void) printf("Video: "); if (vbe_get_video_info(gdev)) { - /* TODO: Should we look these up by class? */ - dev = pci_find_devices(vesa_video_ids, 0); + dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0); if (dev == -1) { printf("no card detected\n"); return NULL; -- cgit v0.10.2 From 7b5c3498901712dbd6503bf81c03bb6ea8e3b516 Mon Sep 17 00:00:00 2001 From: Jian Luo Date: Mon, 6 Jul 2015 16:42:06 +0800 Subject: x86: bios: Synchronize stack between real and protected mode PCI option rom may use different SS during its execution, so it is not safe to assume esp pointed to the same location in the protected mode. Signed-off-by: Jian Luo Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/lib/bios_asm.S b/arch/x86/lib/bios_asm.S index 4faa70e..9dbf969 100644 --- a/arch/x86/lib/bios_asm.S +++ b/arch/x86/lib/bios_asm.S @@ -246,6 +246,9 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.) push %fs push %gs + /* Save real mode SS */ + movw %ss, %cs:__realmode_ss + /* Clear DF to not break ABI assumptions */ cld @@ -258,12 +261,29 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.) enter_protected_mode + /* + * Now we are in protected mode. We need compute the right ESP based + * on saved real mode SS otherwise interrupt_handler() won't get + * correct parameters from the stack. + */ + movzwl %cs:__realmode_ss, %ecx + shll $4, %ecx + addl %ecx, %esp + /* Call the C interrupt handler */ movl $interrupt_handler, %eax call *%eax + /* Restore real mode ESP based on saved SS */ + movzwl %cs:__realmode_ss, %ecx + shll $4, %ecx + subl %ecx, %esp + enter_real_mode + /* Restore real mode SS */ + movw %cs:__realmode_ss, %ss + /* * Restore all registers, including those manipulated by the C * handler @@ -276,6 +296,9 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.) popal iret +__realmode_ss = PTR_TO_REAL_MODE(.) + .word 0 + .globl asm_realmode_code_size asm_realmode_code_size: .long . - asm_realmode_code -- cgit v0.10.2 From 1441d81a793507745603c4c3b9481930ebd53822 Mon Sep 17 00:00:00 2001 From: Jian Luo Date: Mon, 6 Jul 2015 16:31:28 +0800 Subject: x86: bios: Allow pci config read/write to host bridge in int1a_handler We should allow pci config read/write to host bridge (b.d.f = 0.0.0) in the int1a_handler() which is a valid pci device. Signed-off-by: Jian Luo Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/lib/bios_interrupts.c b/arch/x86/lib/bios_interrupts.c index 290990a..47d9f59 100644 --- a/arch/x86/lib/bios_interrupts.c +++ b/arch/x86/lib/bios_interrupts.c @@ -161,15 +161,7 @@ int int1a_handler(void) bus = M.x86.R_EBX >> 8; reg = M.x86.R_EDI; dev = PCI_BDF(bus, devfn >> 3, devfn & 7); - if (!dev) { - debug("0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, - bus, devfn); - /* Or are we supposed to return PCIBIOS_NODEV? */ - M.x86.R_EAX &= 0xffff00ff; /* Clear AH */ - M.x86.R_EAX |= PCIBIOS_BADREG; - retval = 0; - return retval; - } + switch (func) { case 0xb108: /* Read Config Byte */ byte = x86_pci_read_config8(dev, reg); -- cgit v0.10.2 From 0e98a1473a85f2d8590f97653a36f90f55267732 Mon Sep 17 00:00:00 2001 From: Jian Luo Date: Mon, 6 Jul 2015 16:31:29 +0800 Subject: video: Add 32-bit color depth support for VBE The TunnelCreek IGD VBE reports 32-bit color depth regardless 24-bit color depth is configured. Since 24-bit mode already uses 4 bytes internally, it should be OK to just add this option in switch case. Signed-off-by: Jian Luo Acked-by: Simon Glass Tested-by: Bin Meng diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 37450c8..0a644a9 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -203,6 +203,7 @@ int vbe_get_video_info(struct graphic_device *gdev) gdev->gdfBytesPP = vesa->bits_per_pixel / 8; switch (vesa->bits_per_pixel) { + case 32: case 24: gdev->gdfIndex = GDF_32BIT_X888RGB; break; -- cgit v0.10.2 From 43dd22f5fc4c368616721a69e5ea0769abf292dc Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 6 Jul 2015 16:31:30 +0800 Subject: x86: Setup fixed range MTRRs for legacy regions We should setup fixed range MTRRs for some legacy regions like VGA RAM and PCI ROM areas as uncacheable. Note FSP may setup these to other cache settings, but we can override this in x86_cpu_init_f(). Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index d108ee5..9afdafb 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -352,6 +354,26 @@ int x86_cpu_init_f(void) gd->arch.has_mtrr = has_mtrr(); } + /* Configure fixed range MTRRs for some legacy regions */ + if (gd->arch.has_mtrr) { + u64 mtrr_cap; + + mtrr_cap = native_read_msr(MTRR_CAP_MSR); + if (mtrr_cap & MTRR_CAP_FIX) { + /* Mark the VGA RAM area as uncacheable */ + native_write_msr(MTRR_FIX_16K_A0000_MSR, 0, 0); + + /* Mark the PCI ROM area as uncacheable */ + native_write_msr(MTRR_FIX_4K_C0000_MSR, 0, 0); + native_write_msr(MTRR_FIX_4K_C8000_MSR, 0, 0); + native_write_msr(MTRR_FIX_4K_D0000_MSR, 0, 0); + native_write_msr(MTRR_FIX_4K_D8000_MSR, 0, 0); + + /* Enable the fixed range MTRRs */ + msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN); + } + } + return 0; } diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index 3ad617c..70762ee 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -21,6 +21,11 @@ #define MTRR_CAP_MSR 0x0fe #define MTRR_DEF_TYPE_MSR 0x2ff +#define MTRR_CAP_SMRR (1 << 11) +#define MTRR_CAP_WC (1 << 10) +#define MTRR_CAP_FIX (1 << 8) +#define MTRR_CAP_VCNT_MASK 0xff + #define MTRR_DEF_TYPE_EN (1 << 11) #define MTRR_DEF_TYPE_FIX_EN (1 << 10) @@ -38,17 +43,17 @@ #define RANGES_PER_FIXED_MTRR 8 #define NUM_FIXED_RANGES (NUM_FIXED_MTRRS * RANGES_PER_FIXED_MTRR) -#define MTRR_FIX_64K_00000_MSR 0x250 -#define MTRR_FIX_16K_80000_MSR 0x258 -#define MTRR_FIX_16K_A0000_MSR 0x259 -#define MTRR_FIX_4K_C0000_MSR 0x268 -#define MTRR_FIX_4K_C8000_MSR 0x269 -#define MTRR_FIX_4K_D0000_MSR 0x26a -#define MTRR_FIX_4K_D8000_MSR 0x26b -#define MTRR_FIX_4K_E0000_MSR 0x26c -#define MTRR_FIX_4K_E8000_MSR 0x26d -#define MTRR_FIX_4K_F0000_MSR 0x26e -#define MTRR_FIX_4K_F8000_MSR 0x26f +#define MTRR_FIX_64K_00000_MSR 0x250 +#define MTRR_FIX_16K_80000_MSR 0x258 +#define MTRR_FIX_16K_A0000_MSR 0x259 +#define MTRR_FIX_4K_C0000_MSR 0x268 +#define MTRR_FIX_4K_C8000_MSR 0x269 +#define MTRR_FIX_4K_D0000_MSR 0x26a +#define MTRR_FIX_4K_D8000_MSR 0x26b +#define MTRR_FIX_4K_E0000_MSR 0x26c +#define MTRR_FIX_4K_E8000_MSR 0x26d +#define MTRR_FIX_4K_F0000_MSR 0x26e +#define MTRR_FIX_4K_F8000_MSR 0x26f #if !defined(__ASSEMBLER__) -- cgit v0.10.2 From 92587b364b1750612739438810f17c5b98f406fb Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 6 Jul 2015 16:31:31 +0800 Subject: x86: queensbay: Change CPU_ADDR_BITS to 32 Per CPUID:80000008h result, the maximum physical address bits of TunnelCreek processor is 32 instead of default 36. This will fix the incorrect decoding of MTRR range mask. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/cpu/queensbay/Kconfig b/arch/x86/cpu/queensbay/Kconfig index 397e599..fbf85f2 100644 --- a/arch/x86/cpu/queensbay/Kconfig +++ b/arch/x86/cpu/queensbay/Kconfig @@ -38,4 +38,8 @@ config CMC_ADDR The default base address of 0xfffb0000 indicates that the binary must be located at offset 0xb0000 from the beginning of a 1MB flash device. +config CPU_ADDR_BITS + int + default 32 + endif -- cgit v0.10.2 From df07d91956162c55f948cf150c14d678eca3b838 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 6 Jul 2015 16:31:32 +0800 Subject: x86: cmd_mtrr: Improve MTRR list information Print the meaningful base address and mask of an MTRR range without showing the memory type encoding or valid bit. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/lib/cmd_mtrr.c b/arch/x86/lib/cmd_mtrr.c index 7e0506b..f632f49 100644 --- a/arch/x86/lib/cmd_mtrr.c +++ b/arch/x86/lib/cmd_mtrr.c @@ -37,7 +37,8 @@ static int do_mtrr_list(void) valid = mask & MTRR_PHYS_MASK_VALID; type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK]; printf("%d %-5s %-12s %016llx %016llx %016llx\n", i, - valid ? "Y" : "N", type, base, mask, size); + valid ? "Y" : "N", type, base & ~MTRR_BASE_TYPE_MASK, + mask & ~MTRR_PHYS_MASK_VALID, size); } return 0; -- cgit v0.10.2 From 786a08e0dd3d0505e10cc93622ce5db696c627e9 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 6 Jul 2015 16:31:33 +0800 Subject: x86: Move VGA option rom macros to Kconfig Move X86_OPTION_ROM_FILE & X86_OPTION_ROM_ADDR to arch/x86/Kconfig and rename them to VGA_BIOS_FILE & VGA_BIOS_ADDR which depend on HAVE_VGA_BIOS. The new names are consistent with other x86 binary blob options like HAVE_FSP/FSP_FILE/FSP_ADDR. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/Makefile b/Makefile index a7dce06..b6f83a5 100644 --- a/Makefile +++ b/Makefile @@ -1035,8 +1035,8 @@ ifneq ($(CONFIG_HAVE_CMC),) IFDTOOL_FLAGS += -w $(CONFIG_CMC_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_CMC_FILE) endif -ifneq ($(CONFIG_X86_OPTION_ROM_ADDR),) -IFDTOOL_FLAGS += -w $(CONFIG_X86_OPTION_ROM_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_X86_OPTION_ROM_FILE) +ifneq ($(CONFIG_HAVE_VGA_BIOS),) +IFDTOOL_FLAGS += -w $(CONFIG_VGA_BIOS_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_VGA_BIOS_FILE) endif quiet_cmd_ifdtool = IFDTOOL $@ diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b52a80e..8381a3b 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -287,6 +287,28 @@ config TSC_FREQ_IN_MHZ help The running frequency in MHz of Time-Stamp Counter (TSC). +config HAVE_VGA_BIOS + bool "Add a VGA BIOS image" + help + Select this option if you have a VGA BIOS image that you would + like to add to your ROM. + +config VGA_BIOS_FILE + string "VGA BIOS image filename" + depends on HAVE_VGA_BIOS + default "vga.bin" + help + The filename of the VGA BIOS image in the board directory. + +config VGA_BIOS_ADDR + hex "VGA BIOS image location" + depends on HAVE_VGA_BIOS + default 0xfff90000 + help + The location of VGA BIOS image in the SPI flash. For example, base + address of 0xfff90000 indicates that the image will be put at offset + 0x90000 from the beginning of a 1MB flash device. + menu "System tables" config GENERATE_PIRQ_TABLE diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index 018fe91..9931d65 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -3,6 +3,7 @@ CONFIG_VENDOR_GOOGLE=y CONFIG_DEFAULT_DEVICE_TREE="chromebook_link" CONFIG_TARGET_CHROMEBOOK_LINK=y CONFIG_HAVE_MRC=y +CONFIG_HAVE_VGA_BIOS=y # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set diff --git a/configs/chromebox_panther_defconfig b/configs/chromebox_panther_defconfig index 2ac23ed..b3a5f28 100644 --- a/configs/chromebox_panther_defconfig +++ b/configs/chromebox_panther_defconfig @@ -3,6 +3,7 @@ CONFIG_VENDOR_GOOGLE=y CONFIG_DEFAULT_DEVICE_TREE="chromebox_panther" CONFIG_TARGET_CHROMEBOX_PANTHER=y CONFIG_HAVE_MRC=y +CONFIG_HAVE_VGA_BIOS=y # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set diff --git a/configs/minnowmax_defconfig b/configs/minnowmax_defconfig index e0a9216..b578805 100644 --- a/configs/minnowmax_defconfig +++ b/configs/minnowmax_defconfig @@ -3,6 +3,7 @@ CONFIG_VENDOR_INTEL=y CONFIG_DEFAULT_DEVICE_TREE="minnowmax" CONFIG_TARGET_MINNOWMAX=y CONFIG_HAVE_INTEL_ME=y +CONFIG_HAVE_VGA_BIOS=y CONFIG_SMP=y CONFIG_GENERATE_SFI_TABLE=y CONFIG_CMD_CPU=y diff --git a/doc/README.x86 b/doc/README.x86 index 49d6e83..7f3914f 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -79,7 +79,7 @@ Find the following files: * ./northbridge/intel/sandybridge/systemagent-r6.bin The 3rd one should be renamed to mrc.bin. -As for the video ROM, you can get it here [3]. +As for the video ROM, you can get it here [3] and rename it to vga.bin. Make sure all these binary blobs are put in the board directory. Now you can build U-Boot and obtain u-boot.rom: diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 0a644a9..dd7fd95 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -79,8 +79,8 @@ static int pci_rom_probe(pci_dev_t dev, uint class, if (vendev != mapped_vendev) debug("Device ID mapped to %#08x\n", mapped_vendev); -#ifdef CONFIG_X86_OPTION_ROM_ADDR - rom_address = CONFIG_X86_OPTION_ROM_ADDR; +#ifdef CONFIG_VGA_BIOS_ADDR + rom_address = CONFIG_VGA_BIOS_ADDR; #else if (pciauto_setup_rom(pci_bus_to_hose(PCI_BUS(dev)), dev)) { diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h index 547765d..8ee84a6 100644 --- a/include/configs/minnowmax.h +++ b/include/configs/minnowmax.h @@ -52,9 +52,6 @@ #undef CONFIG_USB_MAX_CONTROLLER_COUNT #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 -#define CONFIG_X86_OPTION_ROM_FILE vga.bin -#define CONFIG_X86_OPTION_ROM_ADDR 0xfff90000 - #define VIDEO_IO_OFFSET 0 #define CONFIG_X86EMU_RAW_IO #define CONFIG_VGA_AS_SINGLE_DEVICE diff --git a/include/configs/x86-chromebook.h b/include/configs/x86-chromebook.h index e0e7fca..408cbb1 100644 --- a/include/configs/x86-chromebook.h +++ b/include/configs/x86-chromebook.h @@ -26,9 +26,6 @@ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE}, \ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_AHCI} -#define CONFIG_X86_OPTION_ROM_FILE pci8086,0166.bin -#define CONFIG_X86_OPTION_ROM_ADDR 0xfff90000 - #define CONFIG_PCI_MEM_BUS 0xe0000000 #define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS #define CONFIG_PCI_MEM_SIZE 0x10000000 -- cgit v0.10.2 From 9e3a7c9bac35d47b7a021e311147ba0b5a128b08 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 6 Jul 2015 16:31:34 +0800 Subject: x86: Remove MARK_GRAPHICS_MEM_WRCOMB MARK_GRAPHICS_MEM_WRCOMB is not referenced anywhere in the code, hence remove it. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 8381a3b..cbbaa4f 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -188,14 +188,6 @@ config X86_RAMTEST to work correctly. It is not exhaustive but can save time by detecting obvious failures. -config MARK_GRAPHICS_MEM_WRCOMB - bool "Mark graphics memory as write-combining" - default n - help - The graphics performance may increase if the graphics - memory is set as write-combining cache type. This option - enables marking the graphics memory as write-combining. - config HAVE_FSP bool "Add an Firmware Support Package binary" help diff --git a/board/google/chromebook_link/Kconfig b/board/google/chromebook_link/Kconfig index 9c8d020..d3644a9 100644 --- a/board/google/chromebook_link/Kconfig +++ b/board/google/chromebook_link/Kconfig @@ -22,7 +22,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy select NORTHBRIDGE_INTEL_IVYBRIDGE select SOUTHBRIDGE_INTEL_C216 select HAVE_ACPI_RESUME - select MARK_GRAPHICS_MEM_WRCOMB select BOARD_ROMSIZE_KB_8192 config PCIE_ECAM_BASE diff --git a/board/google/chromebox_panther/Kconfig b/board/google/chromebox_panther/Kconfig index e3604eb..d56d903 100644 --- a/board/google/chromebox_panther/Kconfig +++ b/board/google/chromebox_panther/Kconfig @@ -23,7 +23,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy select NORTHBRIDGE_INTEL_IVYBRIDGE select SOUTHBRIDGE_INTEL_C216 select HAVE_ACPI_RESUME - select MARK_GRAPHICS_MEM_WRCOMB select BOARD_ROMSIZE_KB_8192 config SYS_CAR_ADDR -- cgit v0.10.2 From 7aaff9bf81b17b7920826f99a17eae7659292f5c Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 6 Jul 2015 16:31:35 +0800 Subject: x86: crownbay: Enable graphics support Enable graphics support on Intel Crown Bay board With the help of vgabios for Intel TunnelCreek IGD. Tested with an external LVDS panel connected to X4 connector and SDVO adapter connected to X9 connector on the board. Signed-off-by: Jian Luo Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/configs/crownbay_defconfig b/configs/crownbay_defconfig index 2af93bc..379b881 100644 --- a/configs/crownbay_defconfig +++ b/configs/crownbay_defconfig @@ -18,5 +18,8 @@ CONFIG_CPU=y CONFIG_SPI_FLASH=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y +CONFIG_HAVE_VGA_BIOS=y CONFIG_GENERATE_MP_TABLE=y +CONFIG_VIDEO_VESA=y +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_DM_RTC=y diff --git a/doc/README.x86 b/doc/README.x86 index 7f3914f..646eff1 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -113,6 +113,10 @@ binary using any hex editor (eg: bvi). Go to the offset 0x1fcd8 of the FSP binary, change the following five bytes values from orginally E8 42 FF FF FF to B8 00 80 0B 00. +As for the video ROM, you need manually extract it from the Intel provided +BIOS for Crown Bay here [6], using the AMI MMTool [7]. Check PCI option ROM +ID 8086:4108, extract and save it as vga.bin in the board directory. + Now you can build U-Boot and obtain u-boot.rom $ make crownbay_defconfig @@ -254,7 +258,7 @@ If you want to check both consoles, use '-serial stdio'. CPU Microcode ------------- -Modern CPUs usually require a special bit stream called microcode [6] to be +Modern CPUs usually require a special bit stream called microcode [8] to be loaded on the processor after power up in order to function properly. U-Boot has already integrated these as hex dumps in the source tree. @@ -265,9 +269,9 @@ Additional application processors (AP) can be brought up by U-Boot. In order to have an SMP kernel to discover all of the available processors, U-Boot needs to prepare configuration tables which contain the multi-CPUs information before loading the OS kernel. Currently U-Boot supports generating two types of tables -for SMP, called Simple Firmware Interface (SFI) [7] and Multi-Processor (MP) [8] -tables. The writing of these two tables are controlled by two Kconfig options -GENERATE_SFI_TABLE and GENERATE_MP_TABLE. +for SMP, called Simple Firmware Interface (SFI) [9] and Multi-Processor (MP) +[10] tables. The writing of these two tables are controlled by two Kconfig +options GENERATE_SFI_TABLE and GENERATE_MP_TABLE. Driver Model ------------ @@ -372,6 +376,8 @@ References [3] http://www.coreboot.org/~stepan/pci8086,0166.rom [4] http://www.intel.com/content/www/us/en/embedded/design-tools/evaluation-platforms/atom-e660-eg20t-development-kit.html [5] http://www.intel.com/fsp -[6] http://en.wikipedia.org/wiki/Microcode -[7] http://simplefirmware.org -[8] http://www.intel.com/design/archives/processors/pro/docs/242016.htm +[6] http://www.intel.com/content/www/us/en/secure/intelligent-systems/privileged/e6xx-35-b1-cmc22211.html +[7] http://www.ami.com/products/bios-uefi-tools-and-utilities/bios-uefi-utilities/ +[8] http://en.wikipedia.org/wiki/Microcode +[9] http://simplefirmware.org +[10] http://www.intel.com/design/archives/processors/pro/docs/242016.htm diff --git a/include/configs/crownbay.h b/include/configs/crownbay.h index 0e1f046..6cf53a3 100644 --- a/include/configs/crownbay.h +++ b/include/configs/crownbay.h @@ -32,15 +32,16 @@ #define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS #define CONFIG_PCI_IO_SIZE 0xe000 +#define CONFIG_PCI_CONFIG_HOST_BRIDGE #define CONFIG_SYS_EARLY_PCI_INIT #define CONFIG_PCI_PNP #define CONFIG_E1000 -#define CONFIG_STD_DEVICES_SETTINGS "stdin=serial\0" \ - "stdout=serial\0" \ - "stderr=serial\0" +#define CONFIG_STD_DEVICES_SETTINGS "stdin=serial,vga,usbkbd\0" \ + "stdout=serial,vga\0" \ + "stderr=serial,vga\0" -#define CONFIG_SCSI_DEV_LIST \ +#define CONFIG_SCSI_DEV_LIST \ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SATA} #define CONFIG_SPI_FLASH_SST @@ -55,9 +56,8 @@ #define CONFIG_PCH_GBE #define CONFIG_PHYLIB -/* Video is not supported */ -#undef CONFIG_VIDEO -#undef CONFIG_CFB_CONSOLE +/* TunnelCreek IGD support */ +#define CONFIG_VGA_AS_SINGLE_DEVICE /* Environment configuration */ #define CONFIG_ENV_SECT_SIZE 0x1000 -- cgit v0.10.2 From a452002259e172c93277dbe5752817e0732afe78 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 6 Jul 2015 16:31:36 +0800 Subject: x86: Configure VESA parameters before loading Linux kernel Store VESA parameters to Linux setup header so that vesafb driver in the kernel could work. Signed-off-by: Bin Meng Acked-by: Simon Glass Tested-by: Jian Luo diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h index 8e7dd42..bf351ed 100644 --- a/arch/x86/include/asm/zimage.h +++ b/arch/x86/include/asm/zimage.h @@ -38,5 +38,6 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size, ulong *load_addressp); int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot, unsigned long initrd_addr, unsigned long initrd_size); +void setup_video(struct screen_info *screen_info); #endif diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index c3f8a73..144471c 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -273,6 +273,8 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot, build_command_line(cmd_line, auto_boot); } + setup_video(&setup_base->screen_info); + return 0; } diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index dd7fd95..e7f9959 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef CONFIG_HAVE_ACPI_RESUME #include @@ -230,6 +231,33 @@ int vbe_get_video_info(struct graphic_device *gdev) #endif } +void setup_video(struct screen_info *screen_info) +{ +#ifdef CONFIG_FRAMEBUFFER_SET_VESA_MODE + struct vesa_mode_info *vesa = &mode_info.vesa; + + screen_info->orig_video_isVGA = VIDEO_TYPE_VLFB; + + screen_info->lfb_width = vesa->x_resolution; + screen_info->lfb_height = vesa->y_resolution; + screen_info->lfb_depth = vesa->bits_per_pixel; + screen_info->lfb_linelength = vesa->bytes_per_scanline; + screen_info->lfb_base = vesa->phys_base_ptr; + screen_info->lfb_size = + ALIGN(screen_info->lfb_linelength * screen_info->lfb_height, + 65536); + screen_info->lfb_size >>= 16; + screen_info->red_size = vesa->red_mask_size; + screen_info->red_pos = vesa->red_mask_pos; + screen_info->green_size = vesa->green_mask_size; + screen_info->green_pos = vesa->green_mask_pos; + screen_info->blue_size = vesa->blue_mask_size; + screen_info->blue_pos = vesa->blue_mask_pos; + screen_info->rsvd_size = vesa->reserved_mask_size; + screen_info->rsvd_pos = vesa->reserved_mask_pos; +#endif +} + int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), int exec_method) { struct pci_rom_header *rom, *ram; diff --git a/include/vbe.h b/include/vbe.h index c5deee9..1a86db8 100644 --- a/include/vbe.h +++ b/include/vbe.h @@ -12,7 +12,7 @@ #define _VBE_H /* these structs are for input from and output to OF */ -struct __packed screen_info { +struct __packed vbe_screen_info { u8 display_type; /* 0=NONE, 1= analog, 2=digital */ u16 screen_width; u16 screen_height; @@ -23,7 +23,7 @@ struct __packed screen_info { u8 edid_block_zero[128]; }; -struct __packed screen_info_input { +struct __packed vbe_screen_info_input { u8 signature[4]; u16 size_reserved; u8 monitor_number; -- cgit v0.10.2 From e1e332c8f2e5cac70566998a0ba0ccfdea437f10 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 3 Jul 2015 18:28:21 -0600 Subject: dm: spi: Correct status register access width The status register on ICH9 is a single byte, so use byte access when writing to it, to avoid updating the control register also. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Reviewed-by: Jagan Teki diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c index 6b6cfbf..66a5cba 100644 --- a/drivers/spi/ich.c +++ b/drivers/spi/ich.c @@ -411,6 +411,7 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { struct udevice *bus = dev_get_parent(dev); + struct ich_spi_platdata *plat = dev_get_platdata(bus); struct ich_spi_priv *ctlr = dev_get_priv(bus); uint16_t control; int16_t opcode_index; @@ -477,7 +478,10 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, if (ret < 0) return ret; - ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status); + if (plat->ich_version == 7) + ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status); + else + ich_writeb(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status); spi_setup_type(trans, using_cmd ? bytes : 0); opcode_index = spi_setup_opcode(ctlr, trans); -- cgit v0.10.2 From 507879280750fc4af5e5fd0c4387147d286ff6f7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 3 Jul 2015 18:28:22 -0600 Subject: dm: spi: Correct BIOS protection logic for ICH9 The logic is incorrect and currently has no effect. Fix it so that we can write to SPI flash, since by default it is write-protected. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Andrew Bradford diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c index 66a5cba..2e388e7 100644 --- a/drivers/spi/ich.c +++ b/drivers/spi/ich.c @@ -40,6 +40,7 @@ struct ich_spi_priv { int status; int control; int bbar; + int bcr; uint32_t *pr; /* only for ich9 */ int speed; /* pointer to speed control */ ulong max_speed; /* Maximum bus speed in MHz */ @@ -239,6 +240,7 @@ static int ich_init_controller(struct ich_spi_platdata *plat, ctlr->speed = ctlr->control + 2; ctlr->bbar = offsetof(struct ich9_spi_regs, bbar); ctlr->preop = offsetof(struct ich9_spi_regs, preop); + ctlr->bcr = offsetof(struct ich9_spi_regs, bcr); ctlr->pr = &ich9_spi->pr[0]; ctlr->base = ich9_spi; } else { @@ -688,13 +690,10 @@ static int ich_spi_probe(struct udevice *bus) * v9, deassert SMM BIOS Write Protect Disable. */ if (plat->use_sbase) { - struct ich9_spi_regs *ich9_spi; - - ich9_spi = priv->base; - bios_cntl = ich_readb(priv, ich9_spi->bcr); + bios_cntl = ich_readb(priv, priv->bcr); bios_cntl &= ~(1 << 5); /* clear Enable InSMM_STS (EISS) */ bios_cntl |= 1; /* Write Protect Disable (WPD) */ - ich_writeb(priv, bios_cntl, ich9_spi->bcr); + ich_writeb(priv, bios_cntl, priv->bcr); } else { pci_read_config_byte(plat->dev, 0xdc, &bios_cntl); if (plat->ich_version == 9) -- cgit v0.10.2 From d5359f2e4dd11d7a1e980beadff22a6e25578ad4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 3 Jul 2015 18:28:23 -0600 Subject: dm: spi: Enable environment for minnowmax Enable a SPI environment and store it in a suitable place. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Reviewed-by: Jagan Teki diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h index 8ee84a6..e0f6f8a 100644 --- a/include/configs/minnowmax.h +++ b/include/configs/minnowmax.h @@ -62,8 +62,7 @@ /* Avoid a warning in the Realtek Ethernet driver */ #define CONFIG_SYS_CACHELINE_SIZE 16 -/* Environment in SPI flash is unsupported for now */ -#undef CONFIG_ENV_IS_IN_SPI_FLASH -#define CONFIG_ENV_IS_NOWHERE +#define CONFIG_ENV_SECT_SIZE 0x1000 +#define CONFIG_ENV_OFFSET 0x007fe000 #endif /* __CONFIG_H */ -- cgit v0.10.2 From 537ccba2a425d69d407c9e2cd0fd9d34391ddf82 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 3 Jul 2015 18:28:24 -0600 Subject: x86: Add ROM image description for minnowmax The layout of the ROM is a bit hard to discover by reading the code. Add a table to make it easier. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/doc/README.x86 b/doc/README.x86 index 646eff1..46a1eeb 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -164,6 +164,23 @@ Now you can build U-Boot and obtain u-boot.rom $ make minnowmax_defconfig $ make all +The ROM image is broken up into these parts: + +Offset Description Controlling config +------------------------------------------------------------ +000000 descriptor.bin Hard-coded to 0 in ifdtool +001000 me.bin Set by the descriptor +500000 +700000 u-boot-dtb.bin CONFIG_SYS_TEXT_BASE +790000 vga.bin CONFIG_X86_OPTION_ROM_ADDR +7c0000 fsp.bin CONFIG_FSP_ADDR +7f8000 (depends on size of fsp.bin) +7fe000 Environment CONFIG_ENV_OFFSET +7ff800 U-Boot 16-bit boot CONFIG_SYS_X86_START16 + +Overall ROM image size is controlled by CONFIG_ROM_SIZE. + + Intel Galileo instructions: Only one binary blob is needed for Remote Management Unit (RMU) within Intel -- cgit v0.10.2 From 945cae79e1b547d6edcce53aae68be2e3679a364 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 3 Jul 2015 18:28:25 -0600 Subject: x86: pci: Tidy up the generic x86 PCI driver This driver should use the x86 PCI configuration functions. Also adjust its compatible string to something generic (i.e. without a vendor name). Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/cpu/coreboot/pci.c b/arch/x86/cpu/coreboot/pci.c index 67eb14c..41e29a6 100644 --- a/arch/x86/cpu/coreboot/pci.c +++ b/arch/x86/cpu/coreboot/pci.c @@ -11,29 +11,7 @@ #include #include -#include #include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -static const struct dm_pci_ops pci_x86_ops = { - .read_config = pci_x86_read_config, - .write_config = pci_x86_write_config, -}; - -static const struct udevice_id pci_x86_ids[] = { - { .compatible = "pci-x86" }, - { } -}; - -U_BOOT_DRIVER(pci_x86_drv) = { - .name = "pci_x86", - .id = UCLASS_PCI, - .of_match = pci_x86_ids, - .ops = &pci_x86_ops, -}; static const struct udevice_id generic_pch_ids[] = { { .compatible = "intel,pch" }, diff --git a/drivers/pci/pci_x86.c b/drivers/pci/pci_x86.c index 901bdca..89e8c11 100644 --- a/drivers/pci/pci_x86.c +++ b/drivers/pci/pci_x86.c @@ -7,18 +7,21 @@ #include #include #include +#include -static const struct dm_pci_ops x86_pci_ops = { +static const struct dm_pci_ops pci_x86_ops = { + .read_config = pci_x86_read_config, + .write_config = pci_x86_write_config, }; -static const struct udevice_id x86_pci_ids[] = { - { .compatible = "x86,pci" }, +static const struct udevice_id pci_x86_ids[] = { + { .compatible = "pci-x86" }, { } }; U_BOOT_DRIVER(pci_x86) = { .name = "pci_x86", .id = UCLASS_PCI, - .of_match = x86_pci_ids, - .ops = &x86_pci_ops, + .of_match = pci_x86_ids, + .ops = &pci_x86_ops, }; -- cgit v0.10.2 From b71f9dca89013b8b100006029c98d04b495ebdf7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 3 Jul 2015 18:28:26 -0600 Subject: dm: x86: minnowmax: Move PCI to use driver model Adjust minnowmax to use driver model for PCI. This requires adding a device tree node to specify the ranges, removing the board-specific PCI code and ensuring that the host bridge is configured. Reviewed-by: Bin Meng Signed-off-by: Simon Glass diff --git a/arch/x86/cpu/baytrail/Makefile b/arch/x86/cpu/baytrail/Makefile index c78b644..5be5491 100644 --- a/arch/x86/cpu/baytrail/Makefile +++ b/arch/x86/cpu/baytrail/Makefile @@ -7,5 +7,4 @@ obj-y += cpu.o obj-y += early_uart.o obj-y += fsp_configs.o -obj-y += pci.o obj-y += valleyview.o diff --git a/arch/x86/cpu/baytrail/pci.c b/arch/x86/cpu/baytrail/pci.c deleted file mode 100644 index 48409de..0000000 --- a/arch/x86/cpu/baytrail/pci.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2014, Bin Meng - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -void board_pci_setup_hose(struct pci_controller *hose) -{ - hose->first_busno = 0; - hose->last_busno = 0; - - /* PCI memory space */ - pci_set_region(hose->regions + 0, - CONFIG_PCI_MEM_BUS, - CONFIG_PCI_MEM_PHYS, - CONFIG_PCI_MEM_SIZE, - PCI_REGION_MEM); - - /* PCI IO space */ - pci_set_region(hose->regions + 1, - CONFIG_PCI_IO_BUS, - CONFIG_PCI_IO_PHYS, - CONFIG_PCI_IO_SIZE, - PCI_REGION_IO); - - pci_set_region(hose->regions + 2, - CONFIG_PCI_PREF_BUS, - CONFIG_PCI_PREF_PHYS, - CONFIG_PCI_PREF_SIZE, - PCI_REGION_PREFETCH); - - pci_set_region(hose->regions + 3, - 0, - 0, - gd->ram_size < 0x80000000 ? gd->ram_size : 0x80000000, - PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); - - hose->region_count = 4; -} diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts index bd21bfb..0e59b18 100644 --- a/arch/x86/dts/minnowmax.dts +++ b/arch/x86/dts/minnowmax.dts @@ -111,6 +111,16 @@ }; + pci { + compatible = "intel,pci-baytrail", "pci-x86"; + #address-cells = <3>; + #size-cells = <2>; + u-boot,dm-pre-reloc; + ranges = <0x02000000 0x0 0xd0000000 0xd0000000 0 0x10000000 + 0x42000000 0x0 0xc0000000 0xc0000000 0 0x10000000 + 0x01000000 0x0 0x2000 0x2000 0 0xe000>; + }; + spi { #address-cells = <1>; #size-cells = <0>; diff --git a/configs/minnowmax_defconfig b/configs/minnowmax_defconfig index b578805..45f666c 100644 --- a/configs/minnowmax_defconfig +++ b/configs/minnowmax_defconfig @@ -22,3 +22,4 @@ CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y +CONFIG_DM_PCI=y diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h index e0f6f8a..af36ac5 100644 --- a/include/configs/minnowmax.h +++ b/include/configs/minnowmax.h @@ -32,6 +32,7 @@ #define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS #define CONFIG_PCI_IO_SIZE 0xe000 +#define CONFIG_PCI_CONFIG_HOST_BRIDGE #define CONFIG_SYS_EARLY_PCI_INIT #define CONFIG_PCI_PNP #define CONFIG_RTL8169 -- cgit v0.10.2 From b9da5086b88a1565c7aede14e68bef2456c44475 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 3 Jul 2015 18:28:27 -0600 Subject: dm: x86: baytrail: Correct PCI region 3 when driver model is used Commit afbbd413a fixed this for non-driver-model. Make sure that the driver model code handles this also. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 9afdafb..af927b9 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -353,6 +353,8 @@ int x86_cpu_init_f(void) gd->arch.has_mtrr = has_mtrr(); } + /* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */ + gd->pci_ram_top = 0x80000000U; /* Configure fixed range MTRRs for some legacy regions */ if (gd->arch.has_mtrr) { diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index edec93f..5b91fe3 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -444,6 +444,7 @@ static int decode_regions(struct pci_controller *hose, const void *blob, { int pci_addr_cells, addr_cells, size_cells; int cells_per_record; + phys_addr_t addr; const u32 *prop; int len; int i; @@ -494,8 +495,11 @@ static int decode_regions(struct pci_controller *hose, const void *blob, } /* Add a region for our local memory */ - pci_set_region(hose->regions + hose->region_count++, 0, 0, - gd->ram_size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); + addr = gd->ram_size; + if (gd->pci_ram_top && gd->pci_ram_top < addr) + addr = gd->pci_ram_top; + pci_set_region(hose->regions + hose->region_count++, 0, 0, addr, + PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); return 0; } diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 6747619..db0550b 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -93,6 +93,7 @@ typedef struct global_data { #endif #ifdef CONFIG_PCI struct pci_controller *hose; /* PCI hose for early use */ + phys_addr_t pci_ram_top; /* top of region accessible to PCI */ #endif #ifdef CONFIG_PCI_BOOTDELAY int pcidelay_done; -- cgit v0.10.2 From df898678ab96b904b962743bb5388284c712b9fb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 3 Jul 2015 18:28:28 -0600 Subject: x86: Add binary blob checksums for Minnowboard MAX To try to reduce the pain of confusion of binary blobs, add MD5 checksums for the current versions. This may worsen the situation as new versions appear, but it should still be possible to obtain these versions, and thus get a working setup. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/doc/README.x86 b/doc/README.x86 index 46a1eeb..5d71244 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -164,6 +164,14 @@ Now you can build U-Boot and obtain u-boot.rom $ make minnowmax_defconfig $ make all +Checksums are as follows (but note that newer versions will invalidate this): + +$ md5sum -b board/intel/minnowmax/*.bin +ffda9a3b94df5b74323afb328d51e6b4 board/intel/minnowmax/descriptor.bin +69f65b9a580246291d20d08cbef9d7c5 board/intel/minnowmax/fsp.bin +894a97d371544ec21de9c3e8e1716c4b board/intel/minnowmax/me.bin +a2588537da387da592a27219d56e9962 board/intel/minnowmax/vga.bin + The ROM image is broken up into these parts: Offset Description Controlling config -- cgit v0.10.2 From 50e8a6bba0cf5939afe849ef792f88f09a755758 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 6 Jul 2015 15:57:06 +0800 Subject: tools: ifdtool: Write correct offset on 32-bit machine On 32-bit machine strtol() returns LONG_MAX which is 0x7fffffff, which is wrong for u-boot.rom components like u-boot-x86-16bit.bin. Change to use strtoll() so that it works on both 32-bit and 64-bit machines. Reported-by: Fei Wang Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/tools/ifdtool.c b/tools/ifdtool.c index 1d61df1..df16616 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -987,7 +987,7 @@ int main(int argc, char *argv[]) print_usage(argv[0]); exit(EXIT_FAILURE); } - ifile->addr = strtol(optarg, NULL, 0); + ifile->addr = strtoll(optarg, NULL, 0); ifile->type = opt == 'f' ? IF_fdt : opt == 'U' ? IF_uboot : IF_normal; if (ifile->type == IF_fdt) -- cgit v0.10.2 From aeda4ab664d50a7b620c8b8a4075f9512110e180 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 9 Jul 2015 18:37:40 +0800 Subject: x86: Adjust config option order in defconfig for Crown Bay and Minnowmax Update crownbay_defconfig and minnowmax_defconfig with 'savedefconfig' result so that the config option order matches Kconfig. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/configs/crownbay_defconfig b/configs/crownbay_defconfig index 379b881..17e6a72 100644 --- a/configs/crownbay_defconfig +++ b/configs/crownbay_defconfig @@ -4,7 +4,9 @@ CONFIG_DEFAULT_DEVICE_TREE="crownbay" CONFIG_TARGET_CROWNBAY=y CONFIG_SMP=y CONFIG_MAX_CPUS=2 +CONFIG_HAVE_VGA_BIOS=y CONFIG_GENERATE_PIRQ_TABLE=y +CONFIG_GENERATE_MP_TABLE=y CONFIG_CMD_CPU=y # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set @@ -16,10 +18,8 @@ CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_CONTROL=y CONFIG_CPU=y CONFIG_SPI_FLASH=y -CONFIG_USE_PRIVATE_LIBGCC=y -CONFIG_SYS_VSNPRINTF=y -CONFIG_HAVE_VGA_BIOS=y -CONFIG_GENERATE_MP_TABLE=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_DM_RTC=y +CONFIG_USE_PRIVATE_LIBGCC=y +CONFIG_SYS_VSNPRINTF=y diff --git a/configs/minnowmax_defconfig b/configs/minnowmax_defconfig index 45f666c..29dd44b 100644 --- a/configs/minnowmax_defconfig +++ b/configs/minnowmax_defconfig @@ -3,8 +3,8 @@ CONFIG_VENDOR_INTEL=y CONFIG_DEFAULT_DEVICE_TREE="minnowmax" CONFIG_TARGET_MINNOWMAX=y CONFIG_HAVE_INTEL_ME=y -CONFIG_HAVE_VGA_BIOS=y CONFIG_SMP=y +CONFIG_HAVE_VGA_BIOS=y CONFIG_GENERATE_SFI_TABLE=y CONFIG_CMD_CPU=y # CONFIG_CMD_IMLS is not set @@ -16,10 +16,10 @@ CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_CONTROL=y CONFIG_CPU=y +CONFIG_DM_PCI=y CONFIG_SPI_FLASH=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_11A=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_SYS_VSNPRINTF=y -CONFIG_DM_PCI=y -- cgit v0.10.2 From e1783b5ba3d32c0471a2b963ebec54e7e7cde264 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sat, 16 May 2015 09:33:16 +0800 Subject: drivers: block: Remove the ata_piix driver This driver was originally added to support the native IDE mode for Intel chipset, however it has some bugs like not supporting ATAPI devices, endianness issue, or even broken build when CONFIG_LAB48. Given no board is using this driver as of today, rather than fixing all these issues we just remove it from the source tree. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 8697da4..f161c01 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -6,7 +6,6 @@ # obj-$(CONFIG_SCSI_AHCI) += ahci.o -obj-$(CONFIG_ATA_PIIX) += ata_piix.o obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o obj-$(CONFIG_FSL_SATA) += fsl_sata.o obj-$(CONFIG_IDE_FTIDE020) += ftide020.o diff --git a/drivers/block/ata_piix.c b/drivers/block/ata_piix.c deleted file mode 100644 index 3042684..0000000 --- a/drivers/block/ata_piix.c +++ /dev/null @@ -1,717 +0,0 @@ -/* - * Copyright (C) Procsys. All rights reserved. - * Author: Mushtaq Khan - * - * - * SPDX-License-Identifier: GPL-2.0+ - * - * with the reference to ata_piix driver in kernel 2.4.32 - */ - -/* - * This file contains SATA controller and SATA drive initialization functions - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEBUG_SATA 0 /* For debug prints set DEBUG_SATA to 1 */ - -#define SATA_DECL -#define DRV_DECL /* For file specific declarations */ -#include "ata_piix.h" - -/* Macros realted to PCI */ -#define PCI_SATA_BUS 0x00 -#define PCI_SATA_DEV 0x1f -#define PCI_SATA_FUNC 0x02 - -#define PCI_SATA_BASE1 0x10 -#define PCI_SATA_BASE2 0x14 -#define PCI_SATA_BASE3 0x18 -#define PCI_SATA_BASE4 0x1c -#define PCI_SATA_BASE5 0x20 -#define PCI_PMR 0x90 -#define PCI_PI 0x09 -#define PCI_PCS 0x92 -#define PCI_DMA_CTL 0x48 - -#define PORT_PRESENT (1<<0) -#define PORT_ENABLED (1<<4) - -u32 bdf; -u32 iobase1; /* Primary cmd block */ -u32 iobase2; /* Primary ctl block */ -u32 iobase3; /* Sec cmd block */ -u32 iobase4; /* sec ctl block */ -u32 iobase5; /* BMDMA*/ - -int pci_sata_init(void) -{ - u32 bus = PCI_SATA_BUS; - u32 dev = PCI_SATA_DEV; - u32 fun = PCI_SATA_FUNC; - u16 cmd = 0; - u8 lat = 0, pcibios_max_latency = 0xff; - u8 pmr; /* Port mapping reg */ - u8 pi; /* Prgming Interface reg */ - - bdf = PCI_BDF(bus, dev, fun); - pci_read_config_dword(bdf, PCI_SATA_BASE1, &iobase1); - pci_read_config_dword(bdf, PCI_SATA_BASE2, &iobase2); - pci_read_config_dword(bdf, PCI_SATA_BASE3, &iobase3); - pci_read_config_dword(bdf, PCI_SATA_BASE4, &iobase4); - pci_read_config_dword(bdf, PCI_SATA_BASE5, &iobase5); - - if ((iobase1 == 0xFFFFFFFF) || (iobase2 == 0xFFFFFFFF) || - (iobase3 == 0xFFFFFFFF) || (iobase4 == 0xFFFFFFFF) || - (iobase5 == 0xFFFFFFFF)) { - /* ERROR */ - printf("error no base addr for SATA controller\n"); - return 1; - } - - iobase1 &= 0xFFFFFFFE; - iobase2 &= 0xFFFFFFFE; - iobase3 &= 0xFFFFFFFE; - iobase4 &= 0xFFFFFFFE; - iobase5 &= 0xFFFFFFFE; - - /* check for mode */ - pci_read_config_byte(bdf, PCI_PMR, &pmr); - if (pmr > 1) { - puts("combined mode not supported\n"); - return 1; - } - - pci_read_config_byte(bdf, PCI_PI, &pi); - if ((pi & 0x05) != 0x05) { - puts("Sata is in Legacy mode\n"); - return 1; - } else - puts("sata is in Native mode\n"); - - /* MASTER CFG AND IO CFG */ - pci_read_config_word(bdf, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; - pci_write_config_word(bdf, PCI_COMMAND, cmd); - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - - if (lat < 16) - lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; - else if (lat > pcibios_max_latency) - lat = pcibios_max_latency; - pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); - - return 0; -} - -int sata_bus_probe(int port_no) -{ - int orig_mask, mask; - u16 pcs; - - mask = (PORT_PRESENT << port_no); - pci_read_config_word(bdf, PCI_PCS, &pcs); - orig_mask = (int) pcs & 0xff; - if ((orig_mask & mask) != mask) - return 0; - else - return 1; -} - -int init_sata(int dev) -{ - static int done; - u8 i, rv = 0; - - if (!done) - done = 1; - else - return 0; - - rv = pci_sata_init(); - if (rv == 1) { - puts("pci initialization failed\n"); - return 1; - } - - port[0].port_no = 0; - port[0].ioaddr.cmd_addr = iobase1; - port[0].ioaddr.altstatus_addr = port[0].ioaddr.ctl_addr = - iobase2 | ATA_PCI_CTL_OFS; - port[0].ioaddr.bmdma_addr = iobase5; - - port[1].port_no = 1; - port[1].ioaddr.cmd_addr = iobase3; - port[1].ioaddr.altstatus_addr = port[1].ioaddr.ctl_addr = - iobase4 | ATA_PCI_CTL_OFS; - port[1].ioaddr.bmdma_addr = iobase5 + 0x8; - - for (i = 0; i < CONFIG_SYS_SATA_MAXBUS; i++) - sata_port(&port[i].ioaddr); - - for (i = 0; i < CONFIG_SYS_SATA_MAXBUS; i++) { - if (!(sata_bus_probe(i))) { - port[i].port_state = 0; - printf("SATA#%d port is not present\n", i); - } else { - printf("SATA#%d port is present\n", i); - if (sata_bus_softreset(i)) - port[i].port_state = 0; - else - port[i].port_state = 1; - } - } - - for (i = 0; i < CONFIG_SYS_SATA_MAXBUS; i++) { - u8 j, devno; - - if (port[i].port_state == 0) - continue; - for (j = 0; j < CONFIG_SYS_SATA_DEVS_PER_BUS; j++) { - sata_identify(i, j); - set_Feature_cmd(i, j); - devno = i * CONFIG_SYS_SATA_DEVS_PER_BUS + j; - if ((sata_dev_desc[devno].lba > 0) && - (sata_dev_desc[devno].blksz > 0)) { - dev_print(&sata_dev_desc[devno]); - /* initialize partition type */ - init_part(&sata_dev_desc[devno]); - } - } - } - return 0; -} - -int reset_sata(int dev) -{ - return 0; -} - -static inline u8 sata_inb(unsigned long ioaddr) -{ - return inb(ioaddr); -} - -static inline void sata_outb(unsigned char val, unsigned long ioaddr) -{ - outb(val, ioaddr); -} - -static void output_data(struct sata_ioports *ioaddr, ulong * sect_buf, - int words) -{ - outsw(ioaddr->data_addr, sect_buf, words << 1); -} - -static int input_data(struct sata_ioports *ioaddr, ulong * sect_buf, int words) -{ - insw(ioaddr->data_addr, sect_buf, words << 1); - return 0; -} - -static void sata_cpy(unsigned char *dst, unsigned char *src, unsigned int len) -{ - unsigned char *end, *last; - - last = dst; - end = src + len - 1; - - /* reserve space for '\0' */ - if (len < 2) - goto OUT; - - /* skip leading white space */ - while ((*src) && (src < end) && (*src == ' ')) - ++src; - - /* copy string, omitting trailing white space */ - while ((*src) && (src < end)) { - *dst++ = *src; - if (*src++ != ' ') - last = dst; - } -OUT: - *last = '\0'; -} - -int sata_bus_softreset(int num) -{ - u8 dev = 0, status = 0, i; - - port[num].dev_mask = 0; - - for (i = 0; i < CONFIG_SYS_SATA_DEVS_PER_BUS; i++) { - if (!(sata_devchk(&port[num].ioaddr, i))) { - debug("dev_chk failed for dev#%d\n", i); - } else { - port[num].dev_mask |= (1 << i); - debug("dev_chk passed for dev#%d\n", i); - } - } - - if (!(port[num].dev_mask)) { - printf("no devices on port%d\n", num); - return 1; - } - - dev_select(&port[num].ioaddr, dev); - - port[num].ctl_reg = 0x08; /* Default value of control reg */ - sata_outb(port[num].ctl_reg, port[num].ioaddr.ctl_addr); - udelay(10); - sata_outb(port[num].ctl_reg | ATA_SRST, port[num].ioaddr.ctl_addr); - udelay(10); - sata_outb(port[num].ctl_reg, port[num].ioaddr.ctl_addr); - - /* - * spec mandates ">= 2ms" before checking status. - * We wait 150ms, because that was the magic delay used for - * ATAPI devices in Hale Landis's ATADRVR, for the period of time - * between when the ATA command register is written, and then - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. - */ - mdelay(150); - status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 300); - while ((status & ATA_BUSY)) { - mdelay(100); - status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 3); - } - - if (status & ATA_BUSY) - printf("ata%u is slow to respond,plz be patient\n", num); - - while ((status & ATA_BUSY)) { - mdelay(100); - status = sata_chk_status(&port[num].ioaddr); - } - - if (status & ATA_BUSY) { - printf("ata%u failed to respond : bus reset failed\n", num); - return 1; - } - return 0; -} - -void sata_identify(int num, int dev) -{ - u8 cmd = 0, status = 0; - u8 devno = num * CONFIG_SYS_SATA_DEVS_PER_BUS + dev; - u16 iobuf[ATA_SECT_SIZE]; - u64 n_sectors = 0; - u8 mask = 0; - - memset(iobuf, 0, sizeof(iobuf)); - hd_driveid_t *iop = (hd_driveid_t *) iobuf; - - if (dev == 0) - mask = 0x01; - else - mask = 0x02; - - if (!(port[num].dev_mask & mask)) { - printf("dev%d is not present on port#%d\n", dev, num); - return; - } - - printf("port=%d dev=%d\n", num, dev); - - dev_select(&port[num].ioaddr, dev); - - status = 0; - cmd = ATA_CMD_IDENT; /* Device Identify Command */ - sata_outb(cmd, port[num].ioaddr.command_addr); - sata_inb(port[num].ioaddr.altstatus_addr); - udelay(10); - - status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 1000); - if (status & ATA_ERR) { - puts("\ndevice not responding\n"); - port[num].dev_mask &= ~mask; - return; - } - - input_data(&port[num].ioaddr, (ulong *) iobuf, ATA_SECTORWORDS); - - debug("\nata%u: dev %u cfg 49:%04x 82:%04x 83:%04x 84:%04x85:%04x" - "86:%04x" "87:%04x 88:%04x\n", num, dev, iobuf[49], - iobuf[82], iobuf[83], iobuf[84], iobuf[85], iobuf[86], - iobuf[87], iobuf[88]); - - /* we require LBA and DMA support (bits 8 & 9 of word 49) */ - if (!ata_id_has_dma(iobuf) || !ata_id_has_lba(iobuf)) - debug("ata%u: no dma/lba\n", num); - ata_dump_id(iobuf); - - if (ata_id_has_lba48(iobuf)) - n_sectors = ata_id_u64(iobuf, 100); - else - n_sectors = ata_id_u32(iobuf, 60); - debug("no. of sectors %u\n", ata_id_u64(iobuf, 100)); - debug("no. of sectors %u\n", ata_id_u32(iobuf, 60)); - - if (n_sectors == 0) { - port[num].dev_mask &= ~mask; - return; - } - - sata_cpy((unsigned char *)sata_dev_desc[devno].revision, iop->fw_rev, - sizeof(sata_dev_desc[devno].revision)); - sata_cpy((unsigned char *)sata_dev_desc[devno].vendor, iop->model, - sizeof(sata_dev_desc[devno].vendor)); - sata_cpy((unsigned char *)sata_dev_desc[devno].product, iop->serial_no, - sizeof(sata_dev_desc[devno].product)); - strswab(sata_dev_desc[devno].revision); - strswab(sata_dev_desc[devno].vendor); - - if ((iop->config & 0x0080) == 0x0080) - sata_dev_desc[devno].removable = 1; - else - sata_dev_desc[devno].removable = 0; - - sata_dev_desc[devno].lba = iop->lba_capacity; - debug("lba=0x%x", sata_dev_desc[devno].lba); - -#ifdef CONFIG_LBA48 - if (iop->command_set_2 & 0x0400) { - sata_dev_desc[devno].lba48 = 1; - lba = (unsigned long long) iop->lba48_capacity[0] | - ((unsigned long long) iop->lba48_capacity[1] << 16) | - ((unsigned long long) iop->lba48_capacity[2] << 32) | - ((unsigned long long) iop->lba48_capacity[3] << 48); - } else { - sata_dev_desc[devno].lba48 = 0; - } -#endif - - /* assuming HD */ - sata_dev_desc[devno].type = DEV_TYPE_HARDDISK; - sata_dev_desc[devno].blksz = ATA_BLOCKSIZE; - sata_dev_desc[devno].log2blksz = LOG2(sata_dev_desc[devno].blksz); - sata_dev_desc[devno].lun = 0; /* just to fill something in... */ -} - -void set_Feature_cmd(int num, int dev) -{ - u8 mask = 0x00, status = 0; - - if (dev == 0) - mask = 0x01; - else - mask = 0x02; - - if (!(port[num].dev_mask & mask)) { - debug("dev%d is not present on port#%d\n", dev, num); - return; - } - - dev_select(&port[num].ioaddr, dev); - - sata_outb(SETFEATURES_XFER, port[num].ioaddr.feature_addr); - sata_outb(XFER_PIO_4, port[num].ioaddr.nsect_addr); - sata_outb(0, port[num].ioaddr.lbal_addr); - sata_outb(0, port[num].ioaddr.lbam_addr); - sata_outb(0, port[num].ioaddr.lbah_addr); - - sata_outb(ATA_DEVICE_OBS, port[num].ioaddr.device_addr); - sata_outb(ATA_CMD_SETF, port[num].ioaddr.command_addr); - - udelay(50); - mdelay(150); - - status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 5000); - if ((status & (ATA_STAT_BUSY | ATA_STAT_ERR))) { - printf("Error : status 0x%02x\n", status); - port[num].dev_mask &= ~mask; - } -} - -void sata_port(struct sata_ioports *ioport) -{ - ioport->data_addr = ioport->cmd_addr + ATA_REG_DATA; - ioport->error_addr = ioport->cmd_addr + ATA_REG_ERR; - ioport->feature_addr = ioport->cmd_addr + ATA_REG_FEATURE; - ioport->nsect_addr = ioport->cmd_addr + ATA_REG_NSECT; - ioport->lbal_addr = ioport->cmd_addr + ATA_REG_LBAL; - ioport->lbam_addr = ioport->cmd_addr + ATA_REG_LBAM; - ioport->lbah_addr = ioport->cmd_addr + ATA_REG_LBAH; - ioport->device_addr = ioport->cmd_addr + ATA_REG_DEVICE; - ioport->status_addr = ioport->cmd_addr + ATA_REG_STATUS; - ioport->command_addr = ioport->cmd_addr + ATA_REG_CMD; -} - -int sata_devchk(struct sata_ioports *ioaddr, int dev) -{ - u8 nsect, lbal; - - dev_select(ioaddr, dev); - - sata_outb(0x55, ioaddr->nsect_addr); - sata_outb(0xaa, ioaddr->lbal_addr); - - sata_outb(0xaa, ioaddr->nsect_addr); - sata_outb(0x55, ioaddr->lbal_addr); - - sata_outb(0x55, ioaddr->nsect_addr); - sata_outb(0xaa, ioaddr->lbal_addr); - - nsect = sata_inb(ioaddr->nsect_addr); - lbal = sata_inb(ioaddr->lbal_addr); - - if ((nsect == 0x55) && (lbal == 0xaa)) - return 1; /* we found a device */ - else - return 0; /* nothing found */ -} - -void dev_select(struct sata_ioports *ioaddr, int dev) -{ - u8 tmp = 0; - - if (dev == 0) - tmp = ATA_DEVICE_OBS; - else - tmp = ATA_DEVICE_OBS | ATA_DEV1; - - sata_outb(tmp, ioaddr->device_addr); - sata_inb(ioaddr->altstatus_addr); - udelay(5); -} - -u8 sata_busy_wait(struct sata_ioports *ioaddr, int bits, unsigned int max) -{ - u8 status; - - do { - udelay(1000); - status = sata_chk_status(ioaddr); - max--; - } while ((status & bits) && (max > 0)); - - return status; -} - -u8 sata_chk_status(struct sata_ioports *ioaddr) -{ - return sata_inb(ioaddr->status_addr); -} - - -ulong sata_read(int device, ulong blknr, lbaint_t blkcnt, void *buff) -{ - ulong n = 0, *buffer = (ulong *)buff; - u8 dev = 0, num = 0, mask = 0, status = 0; - -#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; - - if (blknr & 0x0000fffff0000000) { - if (!sata_dev_desc[devno].lba48) { - printf("Drive doesn't support 48-bit addressing\n"); - return 0; - } - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; - } -#endif - /* Port Number */ - num = device / CONFIG_SYS_SATA_DEVS_PER_BUS; - /* dev on the port */ - if (device >= CONFIG_SYS_SATA_DEVS_PER_BUS) - dev = device - CONFIG_SYS_SATA_DEVS_PER_BUS; - else - dev = device; - - if (dev == 0) - mask = 0x01; - else - mask = 0x02; - - if (!(port[num].dev_mask & mask)) { - printf("dev%d is not present on port#%d\n", dev, num); - return 0; - } - - /* Select device */ - dev_select(&port[num].ioaddr, dev); - - status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500); - if (status & ATA_BUSY) { - printf("ata%u failed to respond\n", port[num].port_no); - return n; - } - while (blkcnt-- > 0) { - status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500); - if (status & ATA_BUSY) { - printf("ata%u failed to respond\n", 0); - return n; - } -#ifdef CONFIG_LBA48 - if (lba48) { - /* write high bits */ - sata_outb(0, port[num].ioaddr.nsect_addr); - sata_outb((blknr >> 24) & 0xFF, - port[num].ioaddr.lbal_addr); - sata_outb((blknr >> 32) & 0xFF, - port[num].ioaddr.lbam_addr); - sata_outb((blknr >> 40) & 0xFF, - port[num].ioaddr.lbah_addr); - } -#endif - sata_outb(1, port[num].ioaddr.nsect_addr); - sata_outb(((blknr) >> 0) & 0xFF, - port[num].ioaddr.lbal_addr); - sata_outb((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr); - sata_outb((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr); - -#ifdef CONFIG_LBA48 - if (lba48) { - sata_outb(ATA_LBA, port[num].ioaddr.device_addr); - sata_outb(ATA_CMD_READ_EXT, - port[num].ioaddr.command_addr); - } else -#endif - { - sata_outb(ATA_LBA | ((blknr >> 24) & 0xF), - port[num].ioaddr.device_addr); - sata_outb(ATA_CMD_READ, - port[num].ioaddr.command_addr); - } - - mdelay(50); - /* may take up to 4 sec */ - status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 4000); - - if ((status & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) - != ATA_STAT_DRQ) { - u8 err = 0; - - printf("Error no DRQ dev %d blk %ld: sts 0x%02x\n", - device, (ulong) blknr, status); - err = sata_inb(port[num].ioaddr.error_addr); - printf("Error reg = 0x%x\n", err); - return n; - } - input_data(&port[num].ioaddr, buffer, ATA_SECTORWORDS); - sata_inb(port[num].ioaddr.altstatus_addr); - udelay(50); - - ++n; - ++blknr; - buffer += ATA_SECTORWORDS; - } - return n; -} - -ulong sata_write(int device, ulong blknr, lbaint_t blkcnt, const void *buff) -{ - ulong n = 0, *buffer = (ulong *)buff; - unsigned char status = 0, num = 0, dev = 0, mask = 0; - -#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; - - if (blknr & 0x0000fffff0000000) { - if (!sata_dev_desc[devno].lba48) { - printf("Drive doesn't support 48-bit addressing\n"); - return 0; - } - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; - } -#endif - /* Port Number */ - num = device / CONFIG_SYS_SATA_DEVS_PER_BUS; - /* dev on the Port */ - if (device >= CONFIG_SYS_SATA_DEVS_PER_BUS) - dev = device - CONFIG_SYS_SATA_DEVS_PER_BUS; - else - dev = device; - - if (dev == 0) - mask = 0x01; - else - mask = 0x02; - - /* Select device */ - dev_select(&port[num].ioaddr, dev); - - status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500); - if (status & ATA_BUSY) { - printf("ata%u failed to respond\n", port[num].port_no); - return n; - } - - while (blkcnt-- > 0) { - status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500); - if (status & ATA_BUSY) { - printf("ata%u failed to respond\n", - port[num].port_no); - return n; - } -#ifdef CONFIG_LBA48 - if (lba48) { - /* write high bits */ - sata_outb(0, port[num].ioaddr.nsect_addr); - sata_outb((blknr >> 24) & 0xFF, - port[num].ioaddr.lbal_addr); - sata_outb((blknr >> 32) & 0xFF, - port[num].ioaddr.lbam_addr); - sata_outb((blknr >> 40) & 0xFF, - port[num].ioaddr.lbah_addr); - } -#endif - sata_outb(1, port[num].ioaddr.nsect_addr); - sata_outb((blknr >> 0) & 0xFF, port[num].ioaddr.lbal_addr); - sata_outb((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr); - sata_outb((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr); -#ifdef CONFIG_LBA48 - if (lba48) { - sata_outb(ATA_LBA, port[num].ioaddr.device_addr); - sata_outb(ATA_CMD_WRITE_EXT, - port[num].ioaddr.command_addr); - } else -#endif - { - sata_outb(ATA_LBA | ((blknr >> 24) & 0xF), - port[num].ioaddr.device_addr); - sata_outb(ATA_CMD_WRITE, - port[num].ioaddr.command_addr); - } - - mdelay(50); - /* may take up to 4 sec */ - status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 4000); - if ((status & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) - != ATA_STAT_DRQ) { - printf("Error no DRQ dev %d blk %ld: sts 0x%02x\n", - device, (ulong) blknr, status); - return n; - } - - output_data(&port[num].ioaddr, buffer, ATA_SECTORWORDS); - sata_inb(port[num].ioaddr.altstatus_addr); - udelay(50); - - ++n; - ++blknr; - buffer += ATA_SECTORWORDS; - } - return n; -} - -int scan_sata(int dev) -{ - return 0; -} diff --git a/drivers/block/ata_piix.h b/drivers/block/ata_piix.h deleted file mode 100644 index 6c68ea2..0000000 --- a/drivers/block/ata_piix.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef __ATA_PIIX_H__ -#define __ATA_PIIX_H__ - -struct sata_ioports { - unsigned long cmd_addr; - unsigned long data_addr; - unsigned long error_addr; - unsigned long feature_addr; - unsigned long nsect_addr; - unsigned long lbal_addr; - unsigned long lbam_addr; - unsigned long lbah_addr; - unsigned long device_addr; - unsigned long status_addr; - unsigned long command_addr; - unsigned long altstatus_addr; - unsigned long ctl_addr; - unsigned long bmdma_addr; - unsigned long scr_addr; -}; - -struct sata_port { - unsigned char port_no; /* primary=0, secondary=1 */ - struct sata_ioports ioaddr; /* ATA cmd/ctl/dma reg blks */ - unsigned char ctl_reg; - unsigned char last_ctl; - unsigned char port_state; /* 1-port is available and */ - /* 0-port is not available */ - unsigned char dev_mask; -}; - -/***********SATA LIBRARY SPECIFIC DEFINITIONS AND DECLARATIONS**************/ -#ifdef SATA_DECL /* SATA library specific declarations */ -inline void ata_dump_id(u16 *id) -{ - debug("49 = 0x%04x " - "53 = 0x%04x " - "63 = 0x%04x " - "64 = 0x%04x " - "75 = 0x%04x\n", id[49], id[53], id[63], id[64], id[75]); - debug("80 = 0x%04x " - "81 = 0x%04x " - "82 = 0x%04x " - "83 = 0x%04x " - "84 = 0x%04x\n", id[80], id[81], id[82], id[83], id[84]); - debug("88 = 0x%04x " "93 = 0x%04x\n", id[88], id[93]); -} -#endif - -#ifdef SATA_DECL /*SATA library specific declarations */ -int sata_bus_softreset(int num); -void sata_identify(int num, int dev); -void sata_port(struct sata_ioports *ioport); -void set_Feature_cmd(int num, int dev); -int sata_devchk(struct sata_ioports *ioaddr, int dev); -void dev_select(struct sata_ioports *ioaddr, int dev); -u8 sata_busy_wait(struct sata_ioports *ioaddr, int bits, unsigned int max); -u8 sata_chk_status(struct sata_ioports *ioaddr); -#endif - -/************DRIVER SPECIFIC DEFINITIONS AND DECLARATIONS**************/ - -#ifdef DRV_DECL /* Driver specific declaration */ -int init_sata(int dev); -#endif - -#ifdef DRV_DECL /* Defines Driver Specific variables */ -struct sata_port port[CONFIG_SYS_SATA_MAXBUS]; -#endif - -#endif /* __ATA_PIIX_H__ */ -- cgit v0.10.2 From 6c89663cb152bb49f7618f283d999c417fd85746 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 8 Jul 2015 13:06:40 +0800 Subject: pci: Configure expansion ROM during auto config process Currently PCI expansion ROM address is assigned by a call to pciauto_setup_rom() outside of the pci auto config process. This does not work when expansion ROM is on a device behind PCI bridge where bridge's memory limit register was already programmed to a value that does not cover the newly assigned expansion ROM address. To fix this, we should configure the ROM address during the auto config process. Signed-off-by: Bin Meng Reviewed-by: Simon Glass Tested-by: Simon Glass Acked-by: Simon Glass diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index 7c10983..e034ed1 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -87,6 +87,8 @@ void pciauto_setup_device(struct pci_controller *hose, pci_size_t bar_size; u16 cmdstat = 0; int bar, bar_nr = 0; + u8 header_type; + int rom_addr; #ifndef CONFIG_PCI_ENUM_ONLY pci_addr_t bar_value; struct pci_region *bar_res; @@ -182,38 +184,32 @@ void pciauto_setup_device(struct pci_controller *hose, bar_nr++; } + /* Configure the expansion ROM address */ + pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type); + if (header_type != PCI_HEADER_TYPE_CARDBUS) { + rom_addr = (header_type == PCI_HEADER_TYPE_NORMAL) ? + PCI_ROM_ADDRESS : PCI_ROM_ADDRESS1; + pci_hose_write_config_dword(hose, dev, rom_addr, 0xfffffffe); + pci_hose_read_config_dword(hose, dev, rom_addr, &bar_response); + if (bar_response) { + bar_size = -(bar_response & ~1); + DEBUGF("PCI Autoconfig: ROM, size=%#x, ", bar_size); + if (pciauto_region_allocate(mem, bar_size, + &bar_value) == 0) { + pci_hose_write_config_dword(hose, dev, rom_addr, + bar_value); + } + cmdstat |= PCI_COMMAND_MEMORY; + DEBUGF("\n"); + } + } + pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat); pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, CONFIG_SYS_PCI_CACHE_LINE_SIZE); pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); } -int pciauto_setup_rom(struct pci_controller *hose, pci_dev_t dev) -{ - pci_addr_t bar_value; - pci_size_t bar_size; - u32 bar_response; - u16 cmdstat = 0; - - pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS, 0xfffffffe); - pci_hose_read_config_dword(hose, dev, PCI_ROM_ADDRESS, &bar_response); - if (!bar_response) - return -ENOENT; - - bar_size = -(bar_response & ~1); - DEBUGF("PCI Autoconfig: ROM, size=%#x, ", bar_size); - if (pciauto_region_allocate(hose->pci_mem, bar_size, &bar_value) == 0) { - pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS, - bar_value); - } - DEBUGF("\n"); - pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat); - cmdstat |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat); - - return 0; -} - void pciauto_prescan_setup_bridge(struct pci_controller *hose, pci_dev_t dev, int sub_bus) { diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index e7f9959..aa06767 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -84,11 +84,6 @@ static int pci_rom_probe(pci_dev_t dev, uint class, rom_address = CONFIG_VGA_BIOS_ADDR; #else - if (pciauto_setup_rom(pci_bus_to_hose(PCI_BUS(dev)), dev)) { - debug("Cannot find option ROM\n"); - return -ENOENT; - } - pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_address); if (rom_address == 0x00000000 || rom_address == 0xffffffff) { debug("%s: rom_address=%x\n", __func__, rom_address); diff --git a/include/pci.h b/include/pci.h index 3af511b..542e68b 100644 --- a/include/pci.h +++ b/include/pci.h @@ -722,15 +722,6 @@ void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum, u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum); /** - * pciauto_setup_rom() - Set up access to a device ROM - * - * @hose: PCI hose to use - * @dev: PCI device to adjust - * @return 0 if done, -ve on error - */ -int pciauto_setup_rom(struct pci_controller *hose, pci_dev_t dev); - -/** * pci_hose_find_devices() - Find devices by vendor/device ID * * @hose: PCI hose to search -- cgit v0.10.2 From f110da9984c0aa0aba9e1c4178b67b7abecf7e8d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 8 Jul 2015 13:06:41 +0800 Subject: pci: Disable expansion ROM address decoding when signature check fails We should not leave the expansion ROM address window open when there is not a valid ROM. Suggested-by: Matt Porter Signed-off-by: Bin Meng Tested-by: Simon Glass Acked-by: Simon Glass diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index aa06767..a33efae 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -104,6 +104,10 @@ static int pci_rom_probe(pci_dev_t dev, uint class, if (le16_to_cpu(rom_header->signature) != PCI_ROM_HDR) { printf("Incorrect expansion ROM header signature %04x\n", le16_to_cpu(rom_header->signature)); +#ifndef CONFIG_VGA_BIOS_ADDR + /* Disable expansion ROM address decoding */ + pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address); +#endif return -EINVAL; } -- cgit v0.10.2