Commit 1fb8d793 authored by Tom Rini's avatar Tom Rini
parents 5779b862 c6d4705f
......@@ -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;
}
......
This diff is collapsed.
......@@ -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
>;
};
};
......
......@@ -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_ */
......@@ -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 */
......
......@@ -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
......
......@@ -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
......@@ -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
......@@ -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);
......
......@@ -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 */
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment