1
0
Fork 0

Merge git://git.denx.de/u-boot-x86

utp
Tom Rini 2015-09-17 17:00:08 -04:00
commit 1fb8d79339
11 changed files with 403 additions and 73 deletions

View File

@ -7,8 +7,10 @@
#include <common.h>
#include <errno.h>
#include <fdtdec.h>
#include <asm/mtrr.h>
#include <asm/post.h>
#include <asm/arch/mrc.h>
#include <asm/arch/msg_port.h>
#include <asm/arch/quark.h>
DECLARE_GLOBAL_DATA_PTR;
@ -111,6 +113,14 @@ int dram_init(void)
gd->ram_size = mrc_params.mem_size;
post_code(POST_DRAM);
/* variable range MTRR#2: RAM area */
disable_caches();
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYBASE(MTRR_VAR_RAM),
0 | MTRR_TYPE_WRBACK);
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYMASK(MTRR_VAR_RAM),
(~(gd->ram_size - 1)) | MTRR_PHYS_MASK_VALID);
enable_caches();
return 0;
}

View File

@ -6,10 +6,9 @@
#include <common.h>
#include <mmc.h>
#include <netdev.h>
#include <phy.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mtrr.h>
#include <asm/pci.h>
#include <asm/post.h>
#include <asm/processor.h>
@ -36,6 +35,55 @@ static void unprotect_spi_flash(void)
qrk_pci_write_config_dword(QUARK_LEGACY_BRIDGE, 0xd8, bc);
}
static void quark_setup_mtrr(void)
{
u32 base, mask;
int i;
disable_caches();
/* mark the VGA RAM area as uncacheable */
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_A0000,
MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_B0000,
MTRR_FIX_TYPE(MTRR_TYPE_UNCACHEABLE));
/* mark other fixed range areas as cacheable */
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_64K_00000,
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_64K_40000,
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_80000,
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_FIX_16K_90000,
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
for (i = MTRR_FIX_4K_C0000; i <= MTRR_FIX_4K_FC000; i++)
msg_port_write(MSG_PORT_HOST_BRIDGE, i,
MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
/* variable range MTRR#0: ROM area */
mask = ~(CONFIG_SYS_MONITOR_LEN - 1);
base = CONFIG_SYS_TEXT_BASE & mask;
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYBASE(MTRR_VAR_ROM),
base | MTRR_TYPE_WRBACK);
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYMASK(MTRR_VAR_ROM),
mask | MTRR_PHYS_MASK_VALID);
/* variable range MTRR#1: eSRAM area */
mask = ~(ESRAM_SIZE - 1);
base = CONFIG_ESRAM_BASE & mask;
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYBASE(MTRR_VAR_ESRAM),
base | MTRR_TYPE_WRBACK);
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_VAR_PHYMASK(MTRR_VAR_ESRAM),
mask | MTRR_PHYS_MASK_VALID);
/* enable both variable and fixed range MTRRs */
msg_port_write(MSG_PORT_HOST_BRIDGE, MTRR_DEF_TYPE,
MTRR_DEF_TYPE_EN | MTRR_DEF_TYPE_FIX_EN);
enable_caches();
}
static void quark_setup_bars(void)
{
/* GPIO - D31:F0:R44h */
@ -75,8 +123,6 @@ static void quark_setup_bars(void)
static void quark_pcie_early_init(void)
{
u32 pcie_cfg;
/*
* Step1: Assert PCIe signal PERST#
*
@ -86,23 +132,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);
@ -110,66 +151,80 @@ 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_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)
{
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)
@ -185,6 +240,13 @@ int arch_cpu_init(void)
if (ret)
return ret;
/*
* Quark SoC does not support MSR MTRRs. Fixed and variable range MTRRs
* are accessed indirectly via the message port and not the traditional
* MSR mechanism. Only UC, WT and WB cache types are supported.
*/
quark_setup_mtrr();
/*
* Quark SoC has some non-standard BARs (excluding PCI standard BARs)
* which need be initialized with suggested values
@ -205,6 +267,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();
@ -225,29 +290,59 @@ void reset_cpu(ulong addr)
x86_full_reset();
}
static void quark_pcie_init(void)
{
u32 val;
/* PCIe upstream non-posted & posted request size */
qrk_pci_write_config_dword(QUARK_PCIE0, PCIE_RP_CCFG,
CCFG_UPRS | CCFG_UNRS);
qrk_pci_write_config_dword(QUARK_PCIE1, PCIE_RP_CCFG,
CCFG_UPRS | CCFG_UNRS);
/* PCIe packet fast transmit mode (IPF) */
qrk_pci_write_config_dword(QUARK_PCIE0, PCIE_RP_MPC2, MPC2_IPF);
qrk_pci_write_config_dword(QUARK_PCIE1, PCIE_RP_MPC2, MPC2_IPF);
/* PCIe message bus idle counter (SBIC) */
qrk_pci_read_config_dword(QUARK_PCIE0, PCIE_RP_MBC, &val);
val |= MBC_SBIC;
qrk_pci_write_config_dword(QUARK_PCIE0, PCIE_RP_MBC, val);
qrk_pci_read_config_dword(QUARK_PCIE1, PCIE_RP_MBC, &val);
val |= MBC_SBIC;
qrk_pci_write_config_dword(QUARK_PCIE1, PCIE_RP_MBC, val);
}
static void quark_usb_init(void)
{
u32 bar;
/* Change USB EHCI packet buffer OUT/IN threshold */
qrk_pci_read_config_dword(QUARK_USB_EHCI, PCI_BASE_ADDRESS_0, &bar);
writel((0x7f << 16) | 0x7f, bar + EHCI_INSNREG01);
/* Disable USB device interrupts */
qrk_pci_read_config_dword(QUARK_USB_DEVICE, PCI_BASE_ADDRESS_0, &bar);
writel(0x7f, bar + USBD_INT_MASK);
writel((0xf << 16) | 0xf, bar + USBD_EP_INT_MASK);
writel((0xf << 16) | 0xf, bar + USBD_EP_INT_STS);
}
int arch_early_init_r(void)
{
quark_pcie_init();
quark_usb_init();
return 0;
}
int cpu_mmc_init(bd_t *bis)
{
return pci_mmc_init("Quark SDHCI", mmc_supported,
ARRAY_SIZE(mmc_supported));
}
int cpu_eth_init(bd_t *bis)
{
u32 base;
int ret0, ret1;
qrk_pci_read_config_dword(QUARK_EMAC0, PCI_BASE_ADDRESS_0, &base);
ret0 = designware_initialize(base, PHY_INTERFACE_MODE_RMII);
qrk_pci_read_config_dword(QUARK_EMAC1, PCI_BASE_ADDRESS_0, &base);
ret1 = designware_initialize(base, PHY_INTERFACE_MODE_RMII);
if (ret0 < 0 && ret1 < 0)
return -1;
else
return 0;
}
void cpu_irq_init(void)
{
struct quark_rcba *rcba;
@ -275,3 +370,23 @@ int arch_misc_init(void)
{
return pirq_init();
}
void board_final_cleanup(void)
{
struct quark_rcba *rcba;
u32 base, val;
qrk_pci_read_config_dword(QUARK_LEGACY_BRIDGE, LB_RCBA, &base);
base &= ~MEM_BAR_EN;
rcba = (struct quark_rcba *)base;
/* Initialize 'Component ID' to zero */
val = readl(&rcba->esd);
val &= ~0xff0000;
writel(val, &rcba->esd);
/* Lock HMBOUND for security */
msg_port_setbits(MSG_PORT_HOST_BRIDGE, HM_BOUND, HM_BOUND_LOCK);
return;
}

View File

@ -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
>;
};
};

View File

@ -101,6 +101,37 @@ 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_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_clrsetbits(normal, port, reg, clr, 0)
#define msg_port_setbits(port, reg, set) \
msg_port_generic_clrsetbits(normal, port, reg, 0, 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_clrsetbits(alt, port, reg, clr, 0)
#define msg_port_alt_setbits(port, reg, set) \
msg_port_generic_clrsetbits(alt, port, reg, 0, 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_clrsetbits(io, port, reg, clr, 0)
#define msg_port_io_setbits(port, reg, set) \
msg_port_generic_clrsetbits(io, port, reg, 0, 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_ */

View File

@ -32,18 +32,71 @@
/* Host Memory I/O Boundary */
#define HM_BOUND 0x08
#define HM_BOUND_LOCK 0x00000001
/* Extended Configuration Space */
#define HEC_REG 0x09
/* MTRR Registers */
#define MTRR_CAP 0x40
#define MTRR_DEF_TYPE 0x41
#define MTRR_FIX_64K_00000 0x42
#define MTRR_FIX_64K_40000 0x43
#define MTRR_FIX_16K_80000 0x44
#define MTRR_FIX_16K_90000 0x45
#define MTRR_FIX_16K_A0000 0x46
#define MTRR_FIX_16K_B0000 0x47
#define MTRR_FIX_4K_C0000 0x48
#define MTRR_FIX_4K_C4000 0x49
#define MTRR_FIX_4K_C8000 0x4a
#define MTRR_FIX_4K_CC000 0x4b
#define MTRR_FIX_4K_D0000 0x4c
#define MTRR_FIX_4K_D4000 0x4d
#define MTRR_FIX_4K_D8000 0x4e
#define MTRR_FIX_4K_DC000 0x4f
#define MTRR_FIX_4K_E0000 0x50
#define MTRR_FIX_4K_E4000 0x51
#define MTRR_FIX_4K_E8000 0x52
#define MTRR_FIX_4K_EC000 0x53
#define MTRR_FIX_4K_F0000 0x54
#define MTRR_FIX_4K_F4000 0x55
#define MTRR_FIX_4K_F8000 0x56
#define MTRR_FIX_4K_FC000 0x57
#define MTRR_SMRR_PHYBASE 0x58
#define MTRR_SMRR_PHYMASK 0x59
#define MTRR_VAR_PHYBASE(n) (0x5a + 2 * (n))
#define MTRR_VAR_PHYMASK(n) (0x5b + 2 * (n))
#ifndef __ASSEMBLY__
/* variable range MTRR usage */
enum {
MTRR_VAR_ROM,
MTRR_VAR_ESRAM,
MTRR_VAR_RAM
};
#endif /* __ASSEMBLY__ */
/* Port 0x04: Remote Management Unit Message Port Registers */
/* 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 */
@ -64,6 +117,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
@ -88,6 +147,20 @@
/* 64KiB of RMU binary in flash */
#define RMU_BINARY_SIZE 0x10000
/* PCIe Root Port Configuration Registers */
#define PCIE_RP_CCFG 0xd0
#define CCFG_UPRS (1 << 14)
#define CCFG_UNRS (1 << 15)
#define CCFG_UNSD (1 << 23)
#define CCFG_UPSD (1 << 24)
#define PCIE_RP_MPC2 0xd4
#define MPC2_IPF (1 << 11)
#define PCIE_RP_MBC 0xf4
#define MBC_SBIC (3 << 16)
/* Legacy Bridge PCI Configuration Registers */
#define LB_GBA 0x44
#define LB_PM1BLK 0x48
@ -100,6 +173,14 @@
#define LB_BC 0xd8
#define LB_RCBA 0xf0
/* USB EHCI memory-mapped registers */
#define EHCI_INSNREG01 0x94
/* USB device memory-mapped registers */
#define USBD_INT_MASK 0x410
#define USBD_EP_INT_STS 0x414
#define USBD_EP_INT_MASK 0x418
#ifndef __ASSEMBLY__
/* Root Complex Register Block */

View File

@ -11,8 +11,9 @@ 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_NETDEVICES=y
CONFIG_DM_ETH=y
CONFIG_ETH_DESIGNWARE=y
CONFIG_DM_PCI=y
CONFIG_DM_RTC=y

View File

@ -733,11 +733,36 @@ Example output:
PCI_BDF(0, 3, 0) INTA PIRQA
...
Porting Hints
-------------
Quark-specific considerations:
To port U-Boot to other boards based on the Intel Quark SoC, a few things need
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 the 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 they are 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 a 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 they are implemented by the Intel
Galileo board support codes in board/intel/galileo/galileo.c.
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
----------
@ -755,3 +780,4 @@ References
[12] http://events.linuxfoundation.org/sites/events/files/slides/chromeos_and_diy_vboot_0.pdf
[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

View File

@ -14,6 +14,7 @@
#include <errno.h>
#include <miiphy.h>
#include <malloc.h>
#include <pci.h>
#include <linux/compiler.h>
#include <linux/err.h>
#include <asm/io.h>
@ -558,6 +559,22 @@ static int designware_eth_write_hwaddr(struct udevice *dev)
return _dw_write_hwaddr(priv, pdata->enetaddr);
}
static int designware_eth_bind(struct udevice *dev)
{
#ifdef CONFIG_DM_PCI
static int num_cards;
char name[20];
/* Create a unique device name for PCI type devices */
if (device_is_on_pci_bus(dev)) {
sprintf(name, "eth_designware#%u", num_cards++);
device_set_name(dev, name);
}
#endif
return 0;
}
static int designware_eth_probe(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_platdata(dev);
@ -565,6 +582,23 @@ static int designware_eth_probe(struct udevice *dev)
u32 iobase = pdata->iobase;
int ret;
#ifdef CONFIG_DM_PCI
/*
* If we are on PCI bus, either directly attached to a PCI root port,
* or via a PCI bridge, fill in platdata before we probe the hardware.
*/
if (device_is_on_pci_bus(dev)) {
pci_dev_t bdf = pci_get_bdf(dev);
dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase);
iobase &= PCI_BASE_ADDRESS_MEM_MASK;
iobase = pci_mem_to_phys(bdf, iobase);
pdata->iobase = iobase;
pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
}
#endif
debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv);
priv->mac_regs_p = (struct eth_mac_regs *)iobase;
priv->dma_regs_p = (struct eth_dma_regs *)(iobase + DW_DMA_BASE_OFFSET);
@ -617,10 +651,18 @@ U_BOOT_DRIVER(eth_designware) = {
.id = UCLASS_ETH,
.of_match = designware_eth_ids,
.ofdata_to_platdata = designware_eth_ofdata_to_platdata,
.bind = designware_eth_bind,
.probe = designware_eth_probe,
.ops = &designware_eth_ops,
.priv_auto_alloc_size = sizeof(struct dw_eth_dev),
.platdata_auto_alloc_size = sizeof(struct eth_pdata),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
};
static struct pci_device_id supported[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) },
{ }
};
U_BOOT_PCI_DEVICE(eth_designware, supported);
#endif

View File

@ -238,7 +238,7 @@ int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value,
{
struct udevice *bus;
for (bus = dev; device_get_uclass_id(bus->parent) == UCLASS_PCI;)
for (bus = dev; device_is_on_pci_bus(bus);)
bus = bus->parent;
return pci_bus_write_config(bus, pci_get_bdf(dev), offset, value, size);
}
@ -303,7 +303,7 @@ int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep,
{
struct udevice *bus;
for (bus = dev; device_get_uclass_id(bus->parent) == UCLASS_PCI;)
for (bus = dev; device_is_on_pci_bus(bus);)
bus = bus->parent;
return pci_bus_read_config(bus, pci_get_bdf(dev), offset, valuep,
size);

View File

@ -15,6 +15,7 @@
#define CONFIG_SYS_MONITOR_LEN (1 << 20)
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_ARCH_EARLY_INIT_R
#define CONFIG_ARCH_MISC_INIT
/* ns16550 UART is memory-mapped in Quark SoC */

View File

@ -485,6 +485,17 @@ bool device_is_last_sibling(struct udevice *dev);
*/
int device_set_name(struct udevice *dev, const char *name);
/**
* device_is_on_pci_bus - Test if a device is on a PCI bus
*
* @dev: device to test
* @return: true if it is on a PCI bus, false otherwise
*/
static inline bool device_is_on_pci_bus(struct udevice *dev)
{
return device_get_uclass_id(dev->parent) == UCLASS_PCI;
}
/* device resource management */
typedef void (*dr_release_t)(struct udevice *dev, void *res);
typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data);