[U-Boot] [PATCH 0/8] x86: Support booting Linux kernel on Intel Galileo

Currently U-Boot works great on Intel Galileo board, but it still has some issues when booting a Linux kernel. The issues are mainly with Isolated Memory Region (IMR) and thermal sensor support in the Linux kernel for Intel Quark SoC. For example, kernel just hangs after kernel IMR driver is probed.
It turns out U-Boot still misses some key register programming. Add those register initializtion so that Linux kernel can boot succesfully.
Tested on Intel Galileo board, with an AHCI Mini-PCIe card with an SSD attached (to test PCI IRQ behind the root port), as well as a micro-SD card, a USB flash disk and ethernet under Linux.
Note the mainline Linux designware Ethernet driver uses an API dmi_get_system_info() to determine the PHY address. Since U-Boot currently does not support the DMI, to test the Ethernet under Linux we need patch the kernel driver, but in the long term, we should add DMI support in U-Boot. Add a TODO in README.x86 for now.
Bin Meng (8): x86: galileo: Enable random mac address for Quark x86: quark: Add clrbits, setbits, clrsetbits macros for message port access x86: quark: Convert to use clrbits, setbits, clrsetbits macros x86: quark: Lock HMBOUND register before jumping to kernel x86: quark: Initialize thermal sensor properly x86: galileo: Add PCIe root port IRQ routing x86: doc: Document some porting hints about Intel Quark x86: doc: Add DMI to the TODO list
arch/x86/cpu/quark/quark.c | 115 ++++++++++++++++------------- arch/x86/dts/galileo.dts | 12 +++ arch/x86/include/asm/arch-quark/msg_port.h | 39 ++++++++++ arch/x86/include/asm/arch-quark/quark.h | 15 ++++ configs/galileo_defconfig | 1 + doc/README.x86 | 25 +++++++ 6 files changed, 156 insertions(+), 51 deletions(-)

Not like other Intel Ethernet controllers (e.g.: E1000), Intel Quark SoC integrated designware Ethernet controller does not have a chipset defined way to store/restore mac address. Enable random mac address so that we can use Ethernet even without 'ethaddr'.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
configs/galileo_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/galileo_defconfig b/configs/galileo_defconfig index 9623986..d1808a5 100644 --- a/configs/galileo_defconfig +++ b/configs/galileo_defconfig @@ -11,6 +11,7 @@ CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_CONTROL=y +CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPI_FLASH=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y

On Tuesday, 8 September 2015, Bin Meng bmeng.cn@gmail.com wrote:
Not like other Intel Ethernet controllers (e.g.: E1000), Intel Quark SoC integrated designware Ethernet controller does not have a chipset defined way to store/rest
ore mac address. Enable random mac address
so that we can use Ethernet even without 'ethaddr'.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
configs/galileo_defconfig | 1 +
1 file changed, 1 insertion(+)
Acked-by: Simon Glass sjg@chromium.org
diff --git a/configs/galileo_defconfig b/configs/galileo_defconfig index 9623986..d1808a5 100644 --- a/configs/galileo_defconfig +++ b/configs/galileo_defconfig @@ -11,6 +11,7 @@ CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_CONTROL=y +CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPI_FLASH=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y -- 1.8.2.1

On Intel Quark, lots of registers on the message port need be programmed. Add handy clrbits, setbits, clrsetbits macros for message port access.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/include/asm/arch-quark/msg_port.h | 39 ++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/arch/x86/include/asm/arch-quark/msg_port.h b/arch/x86/include/asm/arch-quark/msg_port.h index 2e78a66..825ae90 100644 --- a/arch/x86/include/asm/arch-quark/msg_port.h +++ b/arch/x86/include/asm/arch-quark/msg_port.h @@ -101,6 +101,45 @@ u32 msg_port_io_read(u8 port, u32 reg); */ void msg_port_io_write(u8 port, u32 reg, u32 value);
+/* clrbits, setbits, clrsetbits macros for message port access */ + +#define msg_port_normal_read msg_port_read +#define msg_port_normal_write msg_port_write + +#define msg_port_generic_clrbits(type, port, reg, clr) \ + msg_port_##type##_write(port, reg, \ + msg_port_##type##_read(port, reg) & ~(clr)) + +#define msg_port_generic_setbits(type, port, reg, set) \ + msg_port_##type##_write(port, reg, \ + msg_port_##type##_read(port, reg) | (set)) + +#define msg_port_generic_clrsetbits(type, port, reg, clr, set) \ + msg_port_##type##_write(port, reg, \ + (msg_port_##type##_read(port, reg) \ + & ~(clr)) | (set)) + +#define msg_port_clrbits(port, reg, clr) \ + msg_port_generic_clrbits(normal, port, reg, clr) +#define msg_port_setbits(port, reg, set) \ + msg_port_generic_setbits(normal, port, reg, set) +#define msg_port_clrsetbits(port, reg, clr, set) \ + msg_port_generic_clrsetbits(normal, port, reg, clr, set) + +#define msg_port_alt_clrbits(port, reg, clr) \ + msg_port_generic_clrbits(alt, port, reg, clr) +#define msg_port_alt_setbits(port, reg, set) \ + msg_port_generic_setbits(alt, port, reg, set) +#define msg_port_alt_clrsetbits(port, reg, clr, set) \ + msg_port_generic_clrsetbits(alt, port, reg, clr, set) + +#define msg_port_io_clrbits(port, reg, clr) \ + msg_port_generic_clrbits(io, port, reg, clr) +#define msg_port_io_setbits(port, reg, set) \ + msg_port_generic_setbits(io, port, reg, set) +#define msg_port_io_clrsetbits(port, reg, clr, set) \ + msg_port_generic_clrsetbits(io, port, reg, clr, set) + #endif /* __ASSEMBLY__ */
#endif /* _QUARK_MSG_PORT_H_ */

Hi Bin,
On Tuesday, 8 September 2015, Bin Meng bmeng.cn@gmail.com wrote:
On Intel Quark, lots of registers on the message port need be programmed. Add handy clrbits, setbits, clrsetbits macros for message port access.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Reviewed-by: Simon Glass sjg@chromium.org
But please see below.
arch/x86/include/asm/arch-quark/msg_port.h | 39 ++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/arch/x86/include/asm/arch-quark/msg_port.h b/arch/x86/include/asm/arch-quark/msg_port.h index 2e78a66..825ae90 100644 --- a/arch/x86/include/asm/arch-quark/msg_port.h +++ b/arch/x86/include/asm/arch-quark/msg_port.h @@ -101,6 +101,45 @@ u32 msg_port_io_read(u8 port, u32 reg); */ void msg_port_io_write(u8 port, u32 reg, u32 value);
+/* clrbits, setbits, clrsetbits macros for message port access */
+#define msg_port_normal_read msg_port_read +#define msg_port_normal_write msg_port_write
+#define msg_port_generic_clrbits(type, port, reg, clr) \
msg_port_##type##_write(port, reg, \
msg_port_##type##_read(port, reg) & ~(clr))
Could be #defined to msg_port_clrsetbits(type, port, reg, clr, 0)
+#define msg_port_generic_setbits(type, port, reg, set) \
msg_port_##type##_write(port, reg, \
msg_port_##type##_read(port, reg) | (set))
Similarly msg_port_clrsetbits(type, port, reg, 0, set)
+#define msg_port_generic_clrsetbits(type, port, reg, clr, set) \
msg_port_##type##_write(port, reg, \
(msg_port_##type##_read(port, reg) \
& ~(clr)) | (set))
+#define msg_port_clrbits(port, reg, clr) \
msg_port_generic_clrbits(normal, port, reg, clr)
+#define msg_port_setbits(port, reg, set) \
msg_port_generic_setbits(normal, port, reg, set)
+#define msg_port_clrsetbits(port, reg, clr, set) \
msg_port_generic_clrsetbits(normal, port, reg, clr, set)
+#define msg_port_alt_clrbits(port, reg, clr) \
msg_port_generic_clrbits(alt, port, reg, clr)
+#define msg_port_alt_setbits(port, reg, set) \
msg_port_generic_setbits(alt, port, reg, set)
+#define msg_port_alt_clrsetbits(port, reg, clr, set) \
msg_port_generic_clrsetbits(alt, port, reg, clr, set)
+#define msg_port_io_clrbits(port, reg, clr) \
msg_port_generic_clrbits(io, port, reg, clr)
+#define msg_port_io_setbits(port, reg, set) \
msg_port_generic_setbits(io, port, reg, set)
+#define msg_port_io_clrsetbits(port, reg, clr, set) \
msg_port_generic_clrsetbits(io, port, reg, clr, set)
#endif /* __ASSEMBLY__ */
#endif /* _QUARK_MSG_PORT_H_ */
1.8.2.1
Regards, Simon

Change existing codes to use clrbits, setbits, clrsetbits macros.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/cpu/quark/quark.c | 72 ++++++++++++++-------------------------------- 1 file changed, 21 insertions(+), 51 deletions(-)
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index 934250b..8d53fe3 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -73,8 +73,6 @@ static void quark_setup_bars(void)
static void quark_pcie_early_init(void) { - u32 pcie_cfg; - /* * Step1: Assert PCIe signal PERST# * @@ -84,23 +82,18 @@ static void quark_pcie_early_init(void) board_assert_perst();
/* Step2: PHY common lane reset */ - pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG); - pcie_cfg |= PCIE_PHY_LANE_RST; - msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg); + msg_port_alt_setbits(MSG_PORT_SOC_UNIT, PCIE_CFG, PCIE_PHY_LANE_RST); /* wait 1 ms for PHY common lane reset */ mdelay(1);
/* Step3: PHY sideband interface reset and controller main reset */ - pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG); - pcie_cfg |= (PCIE_PHY_SB_RST | PCIE_CTLR_MAIN_RST); - msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg); + msg_port_alt_setbits(MSG_PORT_SOC_UNIT, PCIE_CFG, + PCIE_PHY_SB_RST | PCIE_CTLR_MAIN_RST); /* wait 80ms for PLL to lock */ mdelay(80);
/* Step4: Controller sideband interface reset */ - pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG); - pcie_cfg |= PCIE_CTLR_SB_RST; - msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg); + msg_port_alt_setbits(MSG_PORT_SOC_UNIT, PCIE_CFG, PCIE_CTLR_SB_RST); /* wait 20ms for controller sideband interface reset */ mdelay(20);
@@ -108,66 +101,43 @@ static void quark_pcie_early_init(void) board_deassert_perst();
/* Step6: Controller primary interface reset */ - pcie_cfg = msg_port_alt_read(MSG_PORT_SOC_UNIT, PCIE_CFG); - pcie_cfg |= PCIE_CTLR_PRI_RST; - msg_port_alt_write(MSG_PORT_SOC_UNIT, PCIE_CFG, pcie_cfg); + msg_port_alt_setbits(MSG_PORT_SOC_UNIT, PCIE_CFG, PCIE_CTLR_PRI_RST);
/* Mixer Load Lane 0 */ - pcie_cfg = msg_port_io_read(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L0); - pcie_cfg &= ~((1 << 6) | (1 << 7)); - msg_port_io_write(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L0, pcie_cfg); + msg_port_io_clrbits(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L0, + (1 << 6) | (1 << 7));
/* Mixer Load Lane 1 */ - pcie_cfg = msg_port_io_read(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1); - pcie_cfg &= ~((1 << 6) | (1 << 7)); - msg_port_io_write(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1, pcie_cfg); + msg_port_io_clrbits(MSG_PORT_PCIE_AFE, PCIE_RXPICTRL0_L1, + (1 << 6) | (1 << 7)); }
static void quark_usb_early_init(void) { - u32 usb; - /* The sequence below comes from Quark firmware writer guide */
- usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT); - usb &= ~(1 << 1); - usb |= ((1 << 6) | (1 << 7)); - msg_port_alt_write(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT, usb); + msg_port_alt_clrsetbits(MSG_PORT_USB_AFE, USB2_GLOBAL_PORT, + 1 << 1, (1 << 6) | (1 << 7));
- usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_COMPBG); - usb &= ~((1 << 8) | (1 << 9)); - usb |= ((1 << 7) | (1 << 10)); - msg_port_alt_write(MSG_PORT_USB_AFE, USB2_COMPBG, usb); + msg_port_alt_clrsetbits(MSG_PORT_USB_AFE, USB2_COMPBG, + (1 << 8) | (1 << 9), (1 << 7) | (1 << 10));
- usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2); - usb |= (1 << 29); - msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb); + msg_port_alt_setbits(MSG_PORT_USB_AFE, USB2_PLL2, 1 << 29);
- usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL1); - usb |= (1 << 1); - msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL1, usb); + msg_port_alt_setbits(MSG_PORT_USB_AFE, USB2_PLL1, 1 << 1);
- usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL1); - usb &= ~((1 << 3) | (1 << 4) | (1 << 5)); - usb |= (1 << 6); - msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL1, usb); + msg_port_alt_clrsetbits(MSG_PORT_USB_AFE, USB2_PLL1, + (1 << 3) | (1 << 4) | (1 << 5), 1 << 6);
- usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2); - usb &= ~(1 << 29); - msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb); + msg_port_alt_clrbits(MSG_PORT_USB_AFE, USB2_PLL2, 1 << 29);
- usb = msg_port_alt_read(MSG_PORT_USB_AFE, USB2_PLL2); - usb |= (1 << 24); - msg_port_alt_write(MSG_PORT_USB_AFE, USB2_PLL2, usb); + msg_port_alt_setbits(MSG_PORT_USB_AFE, USB2_PLL2, 1 << 24); }
static void quark_enable_legacy_seg(void) { - u32 hmisc2; - - hmisc2 = msg_port_read(MSG_PORT_HOST_BRIDGE, HMISC2); - hmisc2 |= (HMISC2_SEGE | HMISC2_SEGF | HMISC2_SEGAB); - msg_port_write(MSG_PORT_HOST_BRIDGE, HMISC2, hmisc2); + msg_port_setbits(MSG_PORT_HOST_BRIDGE, HMISC2, + HMISC2_SEGE | HMISC2_SEGF | HMISC2_SEGAB); }
int arch_cpu_init(void)

On Tuesday, 8 September 2015, Bin Meng bmeng.cn@gmail.com wrote:
Change existing codes to use clrbits, setbits, clrsetbits macros.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/cpu/quark/quark.c | 72 ++++++++++++++-------------------------------- 1 file changed, 21 insertions(+), 51 deletions(-)
Acked-by: Simon Glass sjg@chromium.org

When Linux kernel boots, it hangs at:
[ 0.829408] Intel Quark side-band driver registered
This happens when Quark kernel Isolated Memory Region (IMR) driver tries to lock an IMR register to protect kernel's text and rodata sections. However in order to have IMR function correctly, HMBOUND register must be locked otherwise the system just hangs.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/cpu/quark/quark.c | 3 +++ arch/x86/include/asm/arch-quark/quark.h | 1 + 2 files changed, 4 insertions(+)
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index 8d53fe3..3ddf079 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -288,5 +288,8 @@ void board_final_cleanup(void) val &= ~0xff0000; writel(val, &rcba->esd);
+ /* Lock HMBOUND for security */ + msg_port_setbits(MSG_PORT_HOST_BRIDGE, HM_BOUND, HM_BOUND_LOCK); + return; } diff --git a/arch/x86/include/asm/arch-quark/quark.h b/arch/x86/include/asm/arch-quark/quark.h index eb3afbf..338c896 100644 --- a/arch/x86/include/asm/arch-quark/quark.h +++ b/arch/x86/include/asm/arch-quark/quark.h @@ -32,6 +32,7 @@
/* Host Memory I/O Boundary */ #define HM_BOUND 0x08 +#define HM_BOUND_LOCK 0x00000001
/* Extended Configuration Space */ #define HEC_REG 0x09

On Tuesday, 8 September 2015, Bin Meng bmeng.cn@gmail.com wrote:
When Linux kernel boots, it hangs at:
[ 0.829408] Intel Quark side-band driver registered
This happens when Quark kernel Isolated Memory Region (IMR) driver tries to lock an IMR register to protect kernel's text and rodata sections. However in order to have IMR function correctly, HMBOUND register must be locked otherwise the system just hangs.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/cpu/quark/quark.c | 3 +++ arch/x86/include/asm/arch-quark/quark.h | 1 + 2 files changed, 4 insertions(+)
Acked-by: Simon Glass sjg@chromium.org

Thermal sensor on Quark SoC needs to be properly initialized per Quark firmware writer guide, otherwise when booting Linux kernel, it triggers system shutdown because of wrong temperature in the thermal sensor is detected by the kernel driver (see below):
[ 5.119819] thermal_sys: Critical temperature reached(206 C),shutting down [ 5.128997] Failed to start orderly shutdown: forcing the issue [ 5.135495] Emergency Sync complete
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/cpu/quark/quark.c | 40 +++++++++++++++++++++++++++++++++ arch/x86/include/asm/arch-quark/quark.h | 14 ++++++++++++ 2 files changed, 54 insertions(+)
diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index 3ddf079..8b78a86 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -134,6 +134,43 @@ static void quark_usb_early_init(void) msg_port_alt_setbits(MSG_PORT_USB_AFE, USB2_PLL2, 1 << 24); }
+static void quark_thermal_early_init(void) +{ + /* The sequence below comes from Quark firmware writer guide */ + + /* thermal sensor mode config */ + msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG1, + (1 << 3) | (1 << 4) | (1 << 5), 1 << 5); + msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG1, + (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | + (1 << 12), 1 << 9); + msg_port_alt_setbits(MSG_PORT_SOC_UNIT, TS_CFG1, 1 << 14); + msg_port_alt_clrbits(MSG_PORT_SOC_UNIT, TS_CFG1, 1 << 17); + msg_port_alt_clrbits(MSG_PORT_SOC_UNIT, TS_CFG1, 1 << 18); + msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG2, 0xffff, 0x011f); + msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG3, 0xff, 0x17); + msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG3, + (1 << 8) | (1 << 9), 1 << 8); + msg_port_alt_clrbits(MSG_PORT_SOC_UNIT, TS_CFG3, 0xff000000); + msg_port_alt_clrsetbits(MSG_PORT_SOC_UNIT, TS_CFG4, + 0x7ff800, 0xc8 << 11); + + /* thermal monitor catastrophic trip set point (105 celsius) */ + msg_port_clrsetbits(MSG_PORT_RMU, TS_TRIP, 0xff, 155); + + /* thermal monitor catastrophic trip clear point (0 celsius) */ + msg_port_clrsetbits(MSG_PORT_RMU, TS_TRIP, 0xff0000, 50 << 16); + + /* take thermal sensor out of reset */ + msg_port_alt_clrbits(MSG_PORT_SOC_UNIT, TS_CFG4, 1 << 0); + + /* enable thermal monitor */ + msg_port_setbits(MSG_PORT_RMU, TS_MODE, 1 << 15); + + /* lock all thermal configuration */ + msg_port_setbits(MSG_PORT_RMU, RMU_CTRL, (1 << 5) | (1 << 6)); +} + static void quark_enable_legacy_seg(void) { msg_port_setbits(MSG_PORT_HOST_BRIDGE, HMISC2, @@ -173,6 +210,9 @@ int arch_cpu_init(void) /* Initialize USB2 PHY */ quark_usb_early_init();
+ /* Initialize thermal sensor */ + quark_thermal_early_init(); + /* Turn on legacy segments (A/B/E/F) decode to system RAM */ quark_enable_legacy_seg();
diff --git a/arch/x86/include/asm/arch-quark/quark.h b/arch/x86/include/asm/arch-quark/quark.h index 338c896..f6009f6 100644 --- a/arch/x86/include/asm/arch-quark/quark.h +++ b/arch/x86/include/asm/arch-quark/quark.h @@ -42,9 +42,17 @@ /* ACPI PBLK Base Address Register */ #define PBLK_BA 0x70
+/* Control Register */ +#define RMU_CTRL 0x71 + /* SPI DMA Base Address Register */ #define SPI_DMA_BA 0x7a
+/* Thermal Sensor Register */ +#define TS_MODE 0xb0 +#define TS_TEMP 0xb1 +#define TS_TRIP 0xb2 + /* Port 0x05: Memory Manager Message Port Registers */
/* eSRAM Block Page Control */ @@ -65,6 +73,12 @@
/* Port 0x31: SoC Unit Port Registers */
+/* Thermal Sensor Config */ +#define TS_CFG1 0x31 +#define TS_CFG2 0x32 +#define TS_CFG3 0x33 +#define TS_CFG4 0x34 + /* PCIe Controller Config */ #define PCIE_CFG 0x36 #define PCIE_CTLR_PRI_RST 0x00010000

On Tuesday, 8 September 2015, Bin Meng bmeng.cn@gmail.com wrote:
Thermal sensor on Quark SoC needs to be properly initialized per Quark firmware writer guide, otherwise when booting Linux kernel, it triggers system shutdown because of wrong temperature in the thermal sensor is detected by the kernel driver (see below):
[ 5.119819] thermal_sys: Critical temperature reached(206 C),shutting down [ 5.128997] Failed to start orderly shutdown: forcing the issue [ 5.135495] Emergency Sync complete
Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/cpu/quark/quark.c | 40 +++++++++++++++++++++++++++++++++ arch/x86/include/asm/arch-quark/quark.h | 14 ++++++++++++ 2 files changed, 54 insertions(+)
Acked-by: Simon Glass sjg@chromium.org

Now we have enabled PCIe root port on Quark SoC, add its PIRQ routing information in the device tree as well.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
arch/x86/dts/galileo.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/arch/x86/dts/galileo.dts b/arch/x86/dts/galileo.dts index f119bf7..a4e1676 100644 --- a/arch/x86/dts/galileo.dts +++ b/arch/x86/dts/galileo.dts @@ -92,6 +92,18 @@ PCI_BDF(0, 21, 0) INTA PIRQE PCI_BDF(0, 21, 1) INTB PIRQF PCI_BDF(0, 21, 2) INTC PIRQG + PCI_BDF(0, 23, 0) INTA PIRQA + PCI_BDF(0, 23, 1) INTB PIRQB + + /* PCIe root ports downstream interrupts */ + PCI_BDF(1, 0, 0) INTA PIRQA + PCI_BDF(1, 0, 0) INTB PIRQB + PCI_BDF(1, 0, 0) INTC PIRQC + PCI_BDF(1, 0, 0) INTD PIRQD + PCI_BDF(2, 0, 0) INTA PIRQB + PCI_BDF(2, 0, 0) INTB PIRQC + PCI_BDF(2, 0, 0) INTC PIRQD + PCI_BDF(2, 0, 0) INTD PIRQA >; }; };

On Tuesday, 8 September 2015, Bin Meng bmeng.cn@gmail.com wrote:
Now we have enabled PCIe root port on Quark SoC, add its PIRQ routing information in the device tree as well.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
arch/x86/dts/galileo.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+)
Acked-by: Simon Glass sjg@chromium.org

Document porting considerations for Intel Quark based board, including MRC parameters and PCIe initialization.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
---
doc/README.x86 | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
diff --git a/doc/README.x86 b/doc/README.x86 index 5f9c46f..f76db7f 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -733,6 +733,29 @@ Example output: PCI_BDF(0, 3, 0) INTA PIRQA ...
+Porting Hints +------------- + +Quark-specific considerations: + +To port U-Boot on other Intel Quark SoC based board, something needs to be taken +care of. The first important part is the Memory Reference Code (MRC) parameters. +Quark MRC supports memory-down configuration only. All these MRC parameters are +supplied via board device tree. To get started, first copy the MRC section of +arch/x86/dts/galileo.dts to your board's device tree, then change these values +by consulting board manuals or your hardware vendor. Available MRC parameter +values are listed in include/dt-bindings/mrc/quark.h. The other tricky part is +with PCIe. Quark SoC integrates two PCIe root ports, but by default it is held +in reset after power on. In U-Boot, PCIe initialization is properly handled as +per Quark's firmware writer guide. In your board support codes, you need provide +two routines to aid PCIe initialization, which are: board_assert_perst() and +board_deassert_perst(). The two routines need implement board-specific mechanism +to assert/deassert PCIe PERST# pin. Care must be taken that in those routines +that any APIs that may trigger PCI enumeration process are strictly forbidden, +as any access to PCIe root port's configuration registers will cause system hang +while it is held in reset. For more details, check how it is implemented by the +Intel Galileo board supported codes in board/intel/galileo/galileo.c. + TODO List --------- - Audio

Hi Bin,
On Tuesday, 8 September 2015, Bin Meng bmeng.cn@gmail.com wrote:
Document porting considerations for Intel Quark based board, including MRC parameters and PCIe initialization.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
doc/README.x86 | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
Some nits below.
Acked-by: Simon Glass sjg@chromium.org
diff --git a/doc/README.x86 b/doc/README.x86 index 5f9c46f..f76db7f 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -733,6 +733,29 @@ Example output: PCI_BDF(0, 3, 0) INTA PIRQA ...
+Porting Hints +-------------
+Quark-specific considerations:
+To port U-Boot on other Intel Quark SoC based board, something needs to be taken
To port U-Boot to other boards based on the Intel Quark SoC, a few things need to be taken care of
+care of. The first important part is the Memory Reference Code (MRC) parameters. +Quark MRC supports memory-down configuration only. All these MRC parameters are +supplied via board device tree. To get started, first copy the MRC section of
via the board
+arch/x86/dts/galileo.dts to your board's device tree, then change these values +by consulting board manuals or your hardware vendor. Available MRC parameter +values are listed in include/dt-bindings/mrc/quark.h. The other tricky part is +with PCIe. Quark SoC integrates two PCIe root ports, but by default it is held +in reset after power on. In U-Boot, PCIe initialization is properly handled as +per Quark's firmware writer guide. In your board support codes, you need provide +two routines to aid PCIe initialization, which are: board_assert_perst() and +board_deassert_perst(). The two routines need implement board-specific mechanism
implement a board-specific
+to assert/deassert PCIe PERST# pin. Care must be taken that in those routines +that any APIs that may trigger PCI enumeration process are strictly forbidden, +as any access to PCIe root port's configuration registers will cause system hang +while it is held in reset. For more details, check how it is implemented by the +Intel Galileo board supported codes in board/intel/galileo/galileo.c.
TODO List
- Audio
-- 1.8.2.1
Regards, Simon

Desktop Management Interface (DMI) is not supported by U-Boot now. Add it to the TODO list.
Signed-off-by: Bin Meng bmeng.cn@gmail.com ---
doc/README.x86 | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/doc/README.x86 b/doc/README.x86 index f76db7f..98ad7b2 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -761,6 +761,7 @@ TODO List - Audio - Chrome OS verified boot - SMI and ACPI support, to provide platform info and facilities to Linux +- Desktop Management Interface (DMI) [15] support
References ---------- @@ -778,3 +779,4 @@ References [12] http://events.linuxfoundation.org/sites/events/files/slides/chromeos_and_diy... [13] http://events.linuxfoundation.org/sites/events/files/slides/elce-2014.pdf [14] doc/device-tree-bindings/misc/intel,irq-router.txt +[15] http://en.wikipedia.org/wiki/Desktop_Management_Interface

On Tuesday, 8 September 2015, Bin Meng bmeng.cn@gmail.com wrote:
Desktop Management Interface (DMI) is not supported by U-Boot now. Add it to the TODO list.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
doc/README.x86 | 2 ++ 1 file changed, 2 insertions(+)
Acked-by: Simon Glass sjg@chromium.org
participants (2)
-
Bin Meng
-
Simon Glass