diff --git a/arch.mk b/arch.mk index c95cb7a50..a974fa3ca 100644 --- a/arch.mk +++ b/arch.mk @@ -425,6 +425,7 @@ ifeq ($(TARGET),nxp_t1024) LDFLAGS+=-Wl,--as-needed # remove weak functions not used OBJS+=src/boot_ppc_mp.o # support for spin table OBJS+=src/fdt.o + OBJS+=src/pci.o UPDATE_OBJS:=src/update_ram.o ifeq ($(SPMATH),1) MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o diff --git a/hal/nxp_t1024.c b/hal/nxp_t1024.c index 6a0323750..8fb8e4547 100644 --- a/hal/nxp_t1024.c +++ b/hal/nxp_t1024.c @@ -25,6 +25,7 @@ #include "hal.h" #include "nxp_ppc.h" #include "fdt.h" +#include "pci.h" /* Tested on T1024E Rev 1.0, e5500 core 2.1, PVR 8024_1021 and SVR 8548_0010 */ /* IFC: CS0 NOR, CS1 MRAM, CS2 APU CPLD, CS3, MPU CPLD */ @@ -118,8 +119,34 @@ static void hal_flash_unlock_sector(uint32_t sector); #define DCFG_DMA2LIODNR ((volatile uint32_t*)(DCFG_BASE + 0x584)) /* PCI Express LIODN base register */ -#define PCI_BASE(n) (0x240000 + ((n) * 0x10000)) -#define PCIE_LIODN(n) ((volatile uint32_t*)(PCI_BASE(n) + 0x40)) /* PEXx_PEX_LBR */ +#define PCI_BASE(n) (CCSRBAR + 0x240000 + ((n-1) * 0x10000)) +#define PCIE_CONFIG_ADDR(n) ((volatile uint32_t*)(PCI_BASE(n) + 0x00)) /* PEXx_PEX_CONFIG_ADDR - configuration address */ +#define PCIE_CONFIG_DATA(n) ((volatile uint32_t*)(PCI_BASE(n) + 0x04)) /* PEXx_PEX_CONFIG_DATA - configuration data */ +#define PCIE_LIODN(n) ((volatile uint32_t*)(PCI_BASE(n) + 0x40)) /* PEXx_PEX_LBR */ +#define PCIE_BLK_REV1(n) ((volatile uint32_t*)(PCI_BASE(n) + 0xBF8)) /* PEXx_PEX_IP_BLK_REV1 */ +#define PCIE_BLK_REV2(n) ((volatile uint32_t*)(PCI_BASE(n) + 0xBFC)) /* PEXx_PEX_IP_BLK_REV1 */ + +/* PCIe Output Windows (max 5) */ +#define PCIE_OTAR(n, w) ((volatile uint32_t*)(PCI_BASE(n) + 0xC00 + ((w) * 32))) /* PEXx_PEXOTARn - outbound translation address */ +#define PCIE_OTEAR(n, w) ((volatile uint32_t*)(PCI_BASE(n) + 0xC04 + ((w) * 32))) /* PEXx_PEXOTEARn - outbound translation extended address */ +#define PCIE_OWBAR(n, w) ((volatile uint32_t*)(PCI_BASE(n) + 0xC08 + ((w) * 32))) /* PEXx_PEXOWBARn - outbound window base address */ +#define PCIE_OWAR(n, w) ((volatile uint32_t*)(PCI_BASE(n) + 0xC10 + ((w) * 32))) /* PEXx_PEXOWARn - outbound window attributes */ +#define POWAR_EN 0x80000000 +#define POWAR_IO_READ 0x00080000 +#define POWAR_MEM_READ 0x00040000 +#define POWAR_IO_WRITE 0x00008000 +#define POWAR_MEM_WRITE 0x00004000 + +/* PCIe Input Windows (max 4 - seq is 3,2,1,0) */ +#define PCIE_ITAR(n, w) ((volatile uint32_t*)(PCI_BASE(n) + 0xD80 + ((3-((w) & 0x3)) * 32))) /* PEXx_PEXITARn - inbound translation address */ +#define PCIE_IWBAR(n, w) ((volatile uint32_t*)(PCI_BASE(n) + 0xD88 + ((3-((w) & 0x3)) * 32))) /* PEXx_PEXIWBARn - inbound window base address */ +#define PCIE_IWBEAR(n, w) ((volatile uint32_t*)(PCI_BASE(n) + 0xD8C + ((3-((w) & 0x3)) * 32))) /* PEXx_PEXIWBEARn- inbound window base extended address */ +#define PCIE_IWAR(n, w) ((volatile uint32_t*)(PCI_BASE(n) + 0xD90 + ((3-((w) & 0x3)) * 32))) /* PEXx_PEXIWARn - inbound window attributes */ +#define PIWAR_EN 0x80000000 +#define PIWAR_PF 0x20000000 +#define PIWAR_LOCAL 0x00f00000 +#define PIWAR_READ_SNOOP 0x00050000 +#define PIWAR_WRITE_SNOOP 0x00005000 /* Buffer Manager */ #define BMAN_LIODNR ((volatile uint32_t*)(BMAN_CCSR_BASE + 0xD08)) @@ -128,7 +155,7 @@ static void hal_flash_unlock_sector(uint32_t sector); /* Frame Queue Descriptor (FQD) */ #define FQD_BAR ((volatile uint32_t*)(QMAN_CCSR_BASE + 0xC04)) #define FQD_AR ((volatile uint32_t*)(QMAN_CCSR_BASE + 0xC10)) -/* Packed Frame Desc riptor Record (PFDR) */ +/* Packed Frame Descriptor Record (PFDR) */ #define PFDR_BARE ((volatile uint32_t*)(QMAN_CCSR_BASE + 0xC20)) #define PFDR_BAR ((volatile uint32_t*)(QMAN_CCSR_BASE + 0xC24)) #define PFDR_AR ((volatile uint32_t*)(QMAN_CCSR_BASE + 0xC30)) @@ -300,10 +327,13 @@ static void hal_flash_unlock_sector(uint32_t sector); /* Hardware Ports (0-63) 4KB each (256KB total) */ #define FMAN_BMI(n) ((FMAN_BASE + 0x80000) + ((n) * 0x1000)) +#define FMAN_BMI_SPLIODN(n, p) ((volatile uint32_t*)(FMAN_BMI(n) + 0x304 + ((((p) - 1) & 0x3F) * 4))) #define FMAN_QMI(n) ((FMAN_BASE + 0x80000) + ((n) * 0x1000) + 0x400) #define FMAN_DMA (FMAN_BASE + 0xC2000UL) /* FMan DMA */ +#define FMAN_DMA_ENTRIES (32) +#define FMAN_DMA_PORT_LIODN(n) ((volatile uint32_t*)(FMAN_DMA + 0x60 + (((n) & 0x1F) * 4))) /* FMan DMA portID-LIODN #0..31 register */ #define FMAN_FPM (FMAN_BASE + 0xC3000UL) /* Frame processing manager (FPM) */ @@ -1141,37 +1171,178 @@ void hal_early_init(void) } #ifdef ENABLE_PCIE + +/* PCI IO read/write functions */ +/* Intel PCI addr/data mappings for compatibility with our PCI driver */ +#define PCI_CONFIG_ADDR_PORT 0xcf8 +#define PCI_CONFIG_DATA_PORT 0xcfc +static int pcie_bus = 0; +void io_write32(uint16_t port, uint32_t value) +{ + if (port == PCI_CONFIG_ADDR_PORT) { + set32(PCIE_CONFIG_ADDR(pcie_bus), value); + } + else if (port == PCI_CONFIG_DATA_PORT) { + set32(PCIE_CONFIG_DATA(pcie_bus), value); + } +} +uint32_t io_read32(uint16_t port) +{ + uint32_t value = 0; + if (port == PCI_CONFIG_ADDR_PORT) { + value = get32(PCIE_CONFIG_ADDR(1)); + } + else if (port == PCI_CONFIG_DATA_PORT) { + value = get32(PCIE_CONFIG_DATA(1)); + } + return value; +} + +#define PCI_MMIO32_LENGTH (1024UL * 1024U * 1024U) +#define PCI_MMIO32_PREFETCH_LENGTH (1024UL * 1024U * 1024U) + #define CONFIG_SYS_PCIE1_MEM_PHYS_HIGH 0xC -#define CONFIG_SYS_PCIE1_MEM_PHYS 0x00000000 -#define CONFIG_SYS_PCIE1_MEM_VIRT 0x80000000 -#define CONFIG_SYS_PCIE1_IO_PHYS_HIGH 0xF -#define CONFIG_SYS_PCIE1_IO_PHYS 0xF8000000 -#define CONFIG_SYS_PCIE1_IO_VIRT CONFIG_SYS_PCIE1_IO_PHYS +#define CONFIG_SYS_PCIE1_MEM_PHYS 0x00000000 +#define CONFIG_SYS_PCIE1_MEM_VIRT 0x80000000 +#define CONFIG_SYS_PCIE1_IO_PHYS_HIGH 0xF +#define CONFIG_SYS_PCIE1_IO_PHYS 0xF8000000 +#define CONFIG_SYS_PCIE1_IO_VIRT CONFIG_SYS_PCIE1_IO_PHYS #define CONFIG_SYS_PCIE2_MEM_PHYS_HIGH 0xC -#define CONFIG_SYS_PCIE2_MEM_PHYS 0x10000000 -#define CONFIG_SYS_PCIE2_MEM_VIRT 0x90000000 +#define CONFIG_SYS_PCIE2_MEM_PHYS 0x10000000 +#define CONFIG_SYS_PCIE2_MEM_VIRT 0x90000000 #define CONFIG_SYS_PCIE2_IO_PHYS_HIGHT 0xF -#define CONFIG_SYS_PCIE2_IO_PHYS 0xF8010000 -#define CONFIG_SYS_PCIE2_IO_VIRT CONFIG_SYS_PCIE2_IO_PHYS +#define CONFIG_SYS_PCIE2_IO_PHYS 0xF8010000 +#define CONFIG_SYS_PCIE2_IO_VIRT CONFIG_SYS_PCIE2_IO_PHYS #define CONFIG_SYS_PCIE3_MEM_PHYS_HIGH 0xC -#define CONFIG_SYS_PCIE3_MEM_PHYS 0x20000000 -#define CONFIG_SYS_PCIE3_MEM_VIRT 0xA0000000 -#define CONFIG_SYS_PCIE3_IO_PHYS_HIGH 0xF -#define CONFIG_SYS_PCIE3_IO_PHYS 0xF8020000 -#define CONFIG_SYS_PCIE3_IO_VIRT CONFIG_SYS_PCIE3_IO_PHYS +#define CONFIG_SYS_PCIE3_MEM_PHYS 0x20000000 +#define CONFIG_SYS_PCIE3_MEM_VIRT 0xA0000000 +#define CONFIG_SYS_PCIE3_IO_PHYS_HIGH 0xF +#define CONFIG_SYS_PCIE3_IO_PHYS 0xF8020000 +#define CONFIG_SYS_PCIE3_IO_VIRT CONFIG_SYS_PCIE3_IO_PHYS + static int hal_pcie_init(void) { - /* Map TLB for PCIe */ - set_tlb(1, 3, CONFIG_SYS_PCIE1_MEM_VIRT, - CONFIG_SYS_PCIE1_MEM_PHYS, CONFIG_SYS_PCIE1_MEM_PHYS_HIGH, - (MAS3_SX | MAS3_SW | MAS3_SR), (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_1G, 1); - set_tlb(1, 4, CONFIG_SYS_PCIE1_MEM_VIRT, - CONFIG_SYS_PCIE1_MEM_PHYS, CONFIG_SYS_PCIE1_MEM_PHYS_HIGH, - (MAS3_SX | MAS3_SW | MAS3_SR), (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_256K, 1); + int ret; + int bus, i; + int law_start = 14; + struct pci_enum_info enum_info; + + for (pcie_bus=1; pcie_bus<=3; pcie_bus++) { + /* Check device disable register */ + if (get32(DCFG_DEVDISR3) & (1 << (32-pcie_bus))) { + wolfBoot_printf("PCIe %d: Disabled\n", pcie_bus); + continue; + } - return 0; + /* Read block revision */ + wolfBoot_printf("PCIe %d: Base 0x%x, Rev 0x%x\n", + pcie_bus, PCI_BASE(pcie_bus), + get32(PCIE_BLK_REV1(pcie_bus))); + + /* Setup PCIe memory regions */ + memset(&enum_info, 0, sizeof(enum_info)); + if (pcie_bus == 1) { + enum_info.mem = CONFIG_SYS_PCIE1_MEM_VIRT; + enum_info.io = CONFIG_SYS_PCIE1_IO_VIRT; + + /* Map TLB for PCIe */ + set_tlb(1, law_start++, CONFIG_SYS_PCIE1_MEM_VIRT, + CONFIG_SYS_PCIE1_MEM_PHYS, CONFIG_SYS_PCIE1_MEM_PHYS_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_1G, 1); + set_tlb(1, law_start++, CONFIG_SYS_PCIE1_MEM_VIRT, + CONFIG_SYS_PCIE1_MEM_PHYS, CONFIG_SYS_PCIE1_MEM_PHYS_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_256K, 1); + } + else if (pcie_bus == 2) { + enum_info.mem = CONFIG_SYS_PCIE2_MEM_VIRT; + enum_info.io = CONFIG_SYS_PCIE2_IO_VIRT; + + /* Map TLB for PCIe */ + set_tlb(1, law_start++, CONFIG_SYS_PCIE2_MEM_VIRT, + CONFIG_SYS_PCIE2_MEM_PHYS, CONFIG_SYS_PCIE2_MEM_PHYS_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_1G, 1); + set_tlb(1, law_start++, CONFIG_SYS_PCIE2_MEM_VIRT, + CONFIG_SYS_PCIE2_MEM_PHYS, CONFIG_SYS_PCIE2_MEM_PHYS_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_256K, 1); + } + else if (pcie_bus == 3) { + enum_info.mem = CONFIG_SYS_PCIE3_MEM_VIRT; + enum_info.io = CONFIG_SYS_PCIE3_IO_VIRT; + + /* Map TLB for PCIe */ + set_tlb(1, law_start++, CONFIG_SYS_PCIE3_MEM_VIRT, + CONFIG_SYS_PCIE3_MEM_PHYS, CONFIG_SYS_PCIE3_MEM_PHYS_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_1G, 1); + set_tlb(1, law_start++, CONFIG_SYS_PCIE3_MEM_VIRT, + CONFIG_SYS_PCIE3_MEM_PHYS, CONFIG_SYS_PCIE3_MEM_PHYS_HIGH, + (MAS3_SX | MAS3_SW | MAS3_SR), (MAS2_I | MAS2_G), 0, BOOKE_PAGESZ_256K, 1); + } + enum_info.mem_limit = enum_info.mem + (PCI_MMIO32_LENGTH - 1); + enum_info.mem_pf = (enum_info.mem + PCI_MMIO32_PREFETCH_LENGTH); + enum_info.mem_pf_limit = PCI_MMIO32_PREFETCH_LENGTH; + + /* Setup PCIe Output Windows */ + if (pcie_bus == 1) { + set32( PCIE_OTAR(pcie_bus, 0), 0x0); + set32(PCIE_OTEAR(pcie_bus, 0), 0x0); + set32( PCIE_OWAR(pcie_bus, 0), 0x80044027); + + set32( PCIE_OTAR(pcie_bus, 1), 0xE0000); + set32(PCIE_OTEAR(pcie_bus, 1), 0x0); + set32(PCIE_OWBAR(pcie_bus, 1), 0xC00000); /* MEM_PHYS >> 12 */ + set32( PCIE_OWAR(pcie_bus, 1), 0x8004401B); + + set32( PCIE_OTAR(pcie_bus, 2), 0x0); + set32(PCIE_OTEAR(pcie_bus, 2), 0x0); + set32(PCIE_OWBAR(pcie_bus, 2), 0xFF8000); /* IO_PHYS >> 12 */ + set32( PCIE_OWAR(pcie_bus, 2), 0x8008800F); + + } + else if (pcie_bus == 3) { + set32( PCIE_OTAR(pcie_bus, 0), 0x0); + set32(PCIE_OWBAR(pcie_bus, 0), 0x0); + set32( PCIE_OWAR(pcie_bus, 0), 0x80044027); + + set32( PCIE_OTAR(pcie_bus, 1), 0xE0000); + set32(PCIE_OTEAR(pcie_bus, 1), 0x0); + set32(PCIE_OWBAR(pcie_bus, 1), 0xC20000); /* MEM_PHYS >> 12 */ + set32( PCIE_OWAR(pcie_bus, 1), 0x8004401B); + + set32( PCIE_OTAR(pcie_bus, 2), 0x0); + set32(PCIE_OTEAR(pcie_bus, 2), 0x0); + set32(PCIE_OWBAR(pcie_bus, 2), 0xFF8020); /* IO_PHYS >> 12 */ + set32( PCIE_OWAR(pcie_bus, 2), 0x8008800F); + } + + /* Setup PCIe Input Windows */ + set32( PCIE_ITAR(pcie_bus, 0), 0xFFE000); + set32( PCIE_IWAR(pcie_bus, 0), 0x80E44017); + + set32( PCIE_ITAR(pcie_bus, 1), 0x0); + set32( PCIE_IWBAR(pcie_bus, 1), 0x0); + set32( PCIE_IWAR(pcie_bus, 1), 0xA0F5501E); + + set32( PCIE_ITAR(pcie_bus, 2), 0x0); + set32( PCIE_IWBAR(pcie_bus, 2), 0x1000000); + set32(PCIE_IWBEAR(pcie_bus, 2), 0x0); + set32( PCIE_IWAR(pcie_bus, 2), 0xA0F5501E); + + set32( PCIE_ITAR(pcie_bus, 3), 0x0); + set32( PCIE_IWBAR(pcie_bus, 3), 0x0); + set32(PCIE_IWBEAR(pcie_bus, 3), 0x0); + set32( PCIE_IWAR(pcie_bus, 3), 0x20F44027); + + /* TODO: setup PCSRBAR/PEXCSRBAR */ + + + ret = pci_enum_bus(0, &enum_info); + if (ret != 0) { + wolfBoot_printf("PCIe %d: Enum failed %d\n", pcie_bus, ret); + } + } + return ret; } #endif @@ -1368,23 +1539,27 @@ static const struct liodn_id_table liodn_tbl[] = { SET_LIODN("fsl,qe", 559, DCFG_QELIODNR), SET_LIODN("fsl,elo3-dma", 147, DCFG_DMA1LIODNR), SET_LIODN("fsl,elo3-dma", 227, DCFG_DMA2LIODNR), - + SET_LIODN("fsl,fman-port-1g-rx", 0x425, NULL), + SET_LIODN("fsl,fman-port-1g-rx", 0x426, NULL), + SET_LIODN("fsl,fman-port-1g-rx", 0x427, NULL), + SET_LIODN("fsl,fman-port-1g-rx", 0x428, NULL), SET_LIODN("fsl,qman", 62, QMAN_LIODNR), SET_LIODN("fsl,bman", 63, BMAN_LIODNR), - SET_LIODN("fsl,qoriq-pcie-v2.4", 148, PCIE_LIODN(1)), - SET_LIODN("fsl,qoriq-pcie-v2.4", 228, PCIE_LIODN(2)), - SET_LIODN("fsl,qoriq-pcie-v2.4", 308, PCIE_LIODN(3)), + SET_LIODN("fsl,qoriq-pcie", 148, PCIE_LIODN(1)), + SET_LIODN("fsl,qoriq-pcie", 228, PCIE_LIODN(2)), + SET_LIODN("fsl,qoriq-pcie", 308, PCIE_LIODN(3)), }; - /* Logical I/O Device Number */ void hal_liodn_init(void) { int i; for (i=0; i<(int)(sizeof(liodn_tbl)/sizeof(struct liodn_id_table)); i++) { - wolfBoot_printf("LIODN %s: %p=%d\n", - liodn_tbl[i].compat, liodn_tbl[i].reg_offset, liodn_tbl[i].id); - set32(liodn_tbl[i].reg_offset, liodn_tbl[i].id); + if (liodn_tbl[i].reg_offset != NULL) { + wolfBoot_printf("LIODN %s: %p=%d\n", + liodn_tbl[i].compat, liodn_tbl[i].reg_offset, liodn_tbl[i].id); + set32(liodn_tbl[i].reg_offset, liodn_tbl[i].id); + } } } @@ -1609,9 +1784,11 @@ static int fman_upload_firmware(const struct qe_firmware *firmware) return 0; } +#define FMAN_DMA_LIODN 973 + static int hal_fman_init(void) { - int ret; + int ret, i; const struct qe_firmware* fw = (const struct qe_firmware*)FMAN_FW_ADDR; /* Upload microcode to IRAM */ @@ -1620,7 +1797,17 @@ static int hal_fman_init(void) ret = fman_upload_firmware(fw); } if (ret == 0) { - + /* Setup FMAN LIDON */ + set32(FMAN_BMI_SPLIODN(0, 0+8), 88); /* RX_10G_TYPE2 */ + set32(FMAN_BMI_SPLIODN(0, 1+8), 89); /* RX_1G */ + set32(FMAN_BMI_SPLIODN(0, 2+8), 90); /* RX_1G */ + set32(FMAN_BMI_SPLIODN(0, 3+8), 91); /* RX_1G */ + + /* Setup FMAN DMA LIODN - use same base for all */ + for (i=0; itotalsize += 1024; /* expand by 1KB */ - wolfBoot_printf("FDT: Expanded (1KB) to %d bytes\n", fdt->totalsize); + fdt->totalsize += 2048; /* expand by 2KB */ + wolfBoot_printf("FDT: Expanded (2KB) to %d bytes\n", fdt->totalsize); /* fixup the memory region - single bank */ off = fdt_find_devtype(fdt, -1, "memory"); @@ -2027,18 +2220,24 @@ int hal_dts_fixup(void* dts_addr) } /* fixup the LIODN */ + prev_compat = NULL; for (i=0; i<(int)(sizeof(liodn_tbl)/sizeof(struct liodn_id_table)); i++) { - off = fdt_node_offset_by_compatible(fdt, -1, liodn_tbl[i].compat); + if (prev_compat == NULL || strcmp(prev_compat, liodn_tbl[i].compat) != 0) { + off = -1; + } + off = fdt_node_offset_by_compatible(fdt, off, liodn_tbl[i].compat); if (off >= 0) { fdt_fixup_val(fdt, off, liodn_tbl[i].compat, "fsl,liodn", liodn_tbl[i].id); } + prev_compat = liodn_tbl[i].compat; } /* fixup the QMAN portals */ off = fdt_node_offset_by_compatible(fdt, -1, "fsl,qman-portal"); while (off != -FDT_ERR_NOTFOUND) { uint32_t liodns[2]; + int childoff; reg = (uint32_t*)fdt_getprop(fdt, off, "cell-index", NULL); if (reg == NULL) @@ -2054,13 +2253,72 @@ int hal_dts_fixup(void* dts_addr) "qman-portal", i, off, "fsl,liodn", liodns[0], liodns[1]); fdt_setprop(fdt, off, "fsl,liodn", liodns, sizeof(liodns)); + /* Add fman@0 node and fsl,liodon = FMAN_DMA_LIODN + index */ + childoff = fdt_add_subnode(fdt, off, "fman@0"); + if (childoff > 0) { + liodns[0] = FMAN_DMA_LIODN + i + 1; + wolfBoot_printf("FDT: Set %s@%d/%s (%d), %s=%d\n", + "qman-portal", i, "fman@0", childoff, "fsl,liodn", liodns[0]); + fdt_setprop(fdt, childoff, "fsl,liodn", liodns, sizeof(liodns[0])); + off = childoff; + } + off = fdt_node_offset_by_compatible(fdt, off, "fsl,qman-portal"); } - /* mpic clock */ - off = fdt_find_devtype(fdt, -1, "open-pic"); - if (off != -FDT_ERR_NOTFOUND) { - fdt_fixup_val(fdt, off, "open-pic", "clock-frequency", hal_get_bus_clk()); + /* fixup the fman clock */ + off = fdt_node_offset_by_compatible(fdt, -1, "fsl,fman"); + if (off != !FDT_ERR_NOTFOUND) { + fdt_fixup_val(fdt, off, "fman@", "clock-frequency", hal_get_bus_clk()); + } + + /* Ethernet Devices */ + off = fdt_node_offset_by_compatible(fdt, -1, "fsl,fman-memac"); + while (off != -FDT_ERR_NOTFOUND) { + reg = (uint32_t*)fdt_getprop(fdt, off, "cell-index", NULL); + if (reg == NULL) + break; + i = (int)fdt32_to_cpu(*reg); + + wolfBoot_printf("FDT: Ethernet%d: Offset %d\n", i, off); + + /* Set Ethernet MAC addresses (incrementing) */ + wolfBoot_printf("FDT: Set %s@%d (%d), %s=%x:%x:%x:%x:%x:%x\n", + "ethernet", i, off, "local-mac-address", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); + fdt_setprop(fdt, off, "local-mac-address", mac_addr, sizeof(mac_addr)); + + mac_addr[5]++; + off = fdt_node_offset_by_compatible(fdt, off, "fsl,fman-memac"); + } + + /* PCIe Ranges */ + i = 0; + off = fdt_node_offset_by_compatible(fdt, -1, "fsl,qoriq-pcie"); + while (off != -FDT_ERR_NOTFOUND) { + uint32_t dma_ranges[] = { + /* TYPE BUS START PHYS SIZE */ + (FDT_PCI_MEM32), + 0x00, 0xff000000, 0x0f, 0xfe000000, 0x00, 0x01000000, + (FDT_PCI_PREFETCH | FDT_PCI_MEM32), + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80000000, + (FDT_PCI_PREFETCH | FDT_PCI_MEM32), + 0x10, 0x00, 0x00, 0x00, 0x00, 0x80000000 + }; + uint32_t bus_range[2]; + bus_range[0] = 0; + bus_range[1] = i; + + wolfBoot_printf("FDT: PCI%d: Offset %d\n", i, off); + + /* Set "dma-ranges" */ + fdt_setprop(fdt, off, "dma-ranges", dma_ranges, sizeof(dma_ranges)); + /* Set "bus-range" */ + fdt_setprop(fdt, off, "bus-range", bus_range, sizeof(bus_range)); + + i++; + off = fdt_node_offset_by_compatible(fdt, off, "fsl,qoriq-pcie"); } #endif /* !BUILD_LOADER_STAGE1 */ return 0; diff --git a/include/fdt.h b/include/fdt.h index 12a50774c..60d804eb5 100644 --- a/include/fdt.h +++ b/include/fdt.h @@ -91,7 +91,12 @@ struct fdt_property { #define FDT_ERR_NOSPACE 7 #define FDT_ERR_TRUNCATED 8 #define FDT_ERR_INTERNAL 9 +#define FDT_ERR_EXISTS 10 +#define FDT_PCI_PREFETCH (0x40000000) +#define FDT_PCI_MEM32 (0x02000000) +#define FDT_PCI_IO (0x01000000) +#define FDT_PCI_MEM64 (0x03000000) uint32_t cpu_to_fdt32(uint32_t x); uint64_t cpu_to_fdt64(uint64_t x); @@ -137,6 +142,7 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, in int fdt_find_devtype(void* fdt, int startoff, const char* node); int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible); int fdt_node_offset_by_compatible(const void *fdt, int startoffset, const char *compatible); +int fdt_add_subnode(void* fdt, int parentoff, const char* name); /* helpers to fix/append a property to a node */ int fdt_fixup_str(void* fdt, int off, const char* node, const char* name, const char* str); diff --git a/include/pci.h b/include/pci.h index 14e22746a..9ad571e13 100644 --- a/include/pci.h +++ b/include/pci.h @@ -31,7 +31,7 @@ #define PCI_HEADER_TYPE_OFFSET 0x0E #define PCI_BAR0_OFFSET (0x10) #define PCI_BAR5_OFFSET 0x24 -#define PCI_BAR5_MASK (~0x3) +#define PCI_BAR_MASK (~0x3) #define PCI_INTR_OFFSET 0x3C #define PCI_HEADER_TYPE_MULTIFUNC_MASK 0x80 #define PCI_HEADER_TYPE_TYPE_MASK 0x7F @@ -50,7 +50,8 @@ #define PCI_MMIO_LIMIT_OFF 0x22 #define PCI_IO_BASE_OFF 0x30 #define PCI_IO_LIMIT_OFF 0x32 - +#define PCI_PWR_MGMT_CTRL_STATUS 0x84 +#define PCI_POWER_STATE_MASK 0x3 /* Shifts & masks for CONFIG_ADDRESS register */ #define PCI_CONFIG_ADDRESS_ENABLE_BIT_SHIFT 31 #define PCI_CONFIG_ADDRESS_BUS_SHIFT 16 @@ -70,9 +71,33 @@ #define PCI_COMMAND_MEM_SPACE (1 << 1) #define PCI_COMMAND_IO_SPACE (1 << 0) +typedef struct { + int bus; + int device; + int function; + uint32_t device_id; +} pci_ctrlr_info_t; + +struct pci_enum_info { + uint32_t mem; + uint32_t mem_limit; + uint32_t io; + uint32_t mem_pf; + uint32_t mem_pf_limit; + uint8_t curr_bus_number; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef PCH_HAS_PCR uint32_t pch_read32(uint8_t port_id, uint16_t offset); void pch_write32(uint8_t port_id, uint16_t offset, uint32_t val); +#endif + uint32_t pci_config_read32(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t off); void pci_config_write32(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t off, uint32_t value); @@ -82,5 +107,15 @@ void pci_config_write16(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t off, uint8_t pci_config_read8(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t off); void pci_config_write8(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t off, uint8_t value); -int pci_enum_do(); +uint64_t pci_get_mmio_addr(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t bar); + +uint32_t pci_enum_bus(uint8_t bus, struct pci_enum_info *info); + +int pci_enum_do(void); +int pci_pre_enum(void); + +#ifdef __cplusplus +} +#endif + #endif /* PCI_H */ diff --git a/src/boot_ppc_start.S b/src/boot_ppc_start.S index 3ce577cc9..8211a0aa3 100644 --- a/src/boot_ppc_start.S +++ b/src/boot_ppc_start.S @@ -544,7 +544,7 @@ init_sram_law: isync init_sram_tlb: - /* Inital SRAM: TLB 1, Entry 9, Supervisor X/R/W, M, TS=0, IPROT */ + /* Initial SRAM: TLB 1, Entry 9, Supervisor X/R/W, M, TS=0, IPROT */ set_tlb(1, 9, INITIAL_SRAM_ADDR, INITIAL_SRAM_ADDR, 0, MAS3_SX | MAS3_SW | MAS3_SR, MAS2_M, 0, diff --git a/src/fdt.c b/src/fdt.c index ae5b7f5cc..17da097db 100644 --- a/src/fdt.c +++ b/src/fdt.c @@ -364,6 +364,41 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, return 0; } +/* return: 0=no match, 1=matched */ +static int fdt_nodename_eq_(const void *fdt, int offset, const char *s, + int len) +{ + const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); + if (p == NULL || memcmp(p, s, len) != 0) { + return 0; + } + if (p[len] == '\0') { + return 1; + } else if (!memchr(s, '@', len) && (p[len] == '@')) { + return 1; + } + return 0; +} + +static int fdt_subnode_offset_namelen(const void *fdt, int offset, + const char *name, int namelen) +{ + int depth; + for (depth = 0; + (offset >= 0) && (depth >= 0); + offset = fdt_next_node(fdt, offset, &depth)) + { + if ((depth == 1) && fdt_nodename_eq_(fdt, offset, name, namelen)) { + return offset; + } + } + if (depth < 0) { + return -FDT_ERR_NOTFOUND; + } + return offset; /* error */ +} + + /* Public Functions */ int fdt_check_header(const void *fdt) @@ -514,6 +549,10 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, memcpy(prop_data, val, len); } } + if (err != 0) { + wolfBoot_printf("FDT: Set prop failed! %d (name %d, off %d)\n", + err, name, nodeoffset); + } return err; } @@ -581,6 +620,49 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, return offset; } +int fdt_add_subnode(void* fdt, int parentoff, const char *name) +{ + int err; + struct fdt_node_header *nh; + int offset, nextoffset; + int nodelen; + uint32_t tag, *endtag; + int namelen = (int)strlen(name); + + err = fdt_check_header(fdt); + if (err != 0) + return err; + + offset = fdt_subnode_offset_namelen(fdt, parentoff, name, namelen); + if (offset >= 0) + return -FDT_ERR_EXISTS; + else if (offset != -FDT_ERR_NOTFOUND) + return offset; + + /* Find the node after properties */ + /* skip the first node (BEGIN_NODE) */ + fdt_next_tag(fdt, parentoff, &nextoffset); + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + } while ((tag == FDT_PROP) || (tag == FDT_NOP)); + + nh = (struct fdt_node_header*)fdt_offset_ptr_(fdt, offset); + nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; + + err = fdt_splice_struct_(fdt, nh, 0, nodelen); + if (err == 0) { + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); + memcpy(nh->name, name, namelen); + endtag = (uint32_t*)((char *)nh + nodelen - FDT_TAGSIZE); + *endtag = cpu_to_fdt32(FDT_END_NODE); + err = offset; + } + return err; +} + + /* adjust the actual total size in the FDT header */ int fdt_shrink(void* fdt) { diff --git a/src/pci.c b/src/pci.c index 3dff773c7..3f9f275f7 100644 --- a/src/pci.c +++ b/src/pci.c @@ -77,17 +77,14 @@ #define PCI_ENUM_MM_BAR_MASK ~(0xf) #define PCI_ENUM_IO_BAR_MASK ~(0x3) +#define CAPID0_A_0_0_0_PCI (0xE4) +#define DEVICE_ENABLE (0x54) +#define DTT_DEVICE_DISABLE (1 << 15) #define ONE_MB (1024 * 1024) #define FOUR_KB (4 * 1024) -struct pci_enum_info { - uint32_t mem; - uint32_t mem_limit; - uint32_t io; - uint32_t mem_pf; - uint32_t mem_pf_limit; - uint8_t curr_bus_number; -}; +static int pci_enum_is_64bit(uint32_t value); +static int pci_enum_is_mmio(uint32_t value); static inline uint32_t align_up(uint32_t address, uint32_t alignment) { return (address + alignment - 1) & ~(alignment - 1); @@ -202,7 +199,7 @@ static void pci_ecam_config_write16(uint8_t bus, uint8_t dev, uint8_t fun, #define PCI_IO_CONFIG_ADDR(bus, dev, fn, off) \ (uint32_t)( \ - (1UL << PCI_CONFIG_ADDRESS_ENABLE_BIT_SHIFT) | \ + (1 << PCI_CONFIG_ADDRESS_ENABLE_BIT_SHIFT) | \ (bus << PCI_CONFIG_ADDRESS_BUS_SHIFT) | \ (dev << PCI_CONFIG_ADDRESS_DEVICE_SHIFT) | \ (fn << PCI_CONFIG_ADDRESS_FUNCTION_SHIFT) | \ @@ -340,6 +337,36 @@ uint8_t pci_config_read8(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t off) return (reg >> shift); } +uint64_t pci_get_mmio_addr(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t bar) +{ + uint32_t reg; + uint64_t addr = 0; + + if (bar >= PCI_ENUM_MAX_BARS) + { + return addr; + } + + reg = pci_config_read32(bus, dev, fun, PCI_BAR0_OFFSET + (bar * 8)); + wolfBoot_printf("BAR%d[0x%x] reg value = 0x%x\r\n", bar, PCI_BAR0_OFFSET + (bar * 8), reg); + + if (!pci_enum_is_mmio(reg)) + { + return addr; + } + + addr = reg & 0xFFFFFFF0; + + if (pci_enum_is_64bit(reg)) + { + reg = pci_config_read32(bus, dev, fun, (PCI_BAR0_OFFSET + 4) + (bar * 8)); + wolfBoot_printf("BAR%d_HIGH[0x%x] reg value = 0x%x\r\n", bar, (PCI_BAR0_OFFSET + 4) + (bar * 8), reg); + addr |= ((uint64_t)reg << 32); + } + + return addr; +} + static int pci_enum_is_64bit(uint32_t value) { uint8_t type = (value & PCI_ENUM_TYPE_MASK) >> PCI_ENUM_TYPE_SHIFT; @@ -380,7 +407,8 @@ static int pci_pre_enum_cb(uint8_t bus, uint8_t dev, uint8_t fun) #ifdef WOLFBOOT_TGL if (bus != 0) return 0; - if (dev == 0x1e) { + /* don't change UART mapping */ + if (dev == 0x1e && (fun == 0 || fun == 1)) { return 1; } /* PMC BARs shouldn't be programmed as per FSP integration guide */ @@ -420,6 +448,7 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun, return -1; is_prefetch = 0; + (void)is_prefetch; bar_off = PCI_BAR0_OFFSET + bar_idx * 4; orig_bar = pci_config_read32(bus, dev, fun, bar_off); pci_config_write32(bus, dev, fun, bar_off, 0xffffffff); @@ -498,6 +527,7 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun, return ret; } +#if defined(DEBUG_PCI) static void pci_dump_id(uint8_t bus, uint8_t dev, uint8_t fun) { uint16_t vid, did; @@ -505,9 +535,17 @@ static void pci_dump_id(uint8_t bus, uint8_t dev, uint8_t fun) vid = pci_config_read16(bus, dev, fun, PCI_VENDOR_ID_OFFSET); did = pci_config_read16(bus, dev, fun, PCI_DEVICE_ID_OFFSET); - PCI_DEBUG_PRINTF("PCI enum: dev: %x:%x.%x vid: %x did: %x\r\n", + PCI_DEBUG_PRINTF("\r\n\r\nPCI: %x:%x.%x %x:%x\r\n", bus, dev, fun, (int)vid, (int)did); } +#else +static inline void pci_dump_id(uint8_t bus, uint8_t dev, uint8_t fun) +{ + (void)bus; + (void)dev; + (void)fun; +}; +#endif static int pci_program_bars(uint8_t bus, uint8_t dev, uint8_t fun, struct pci_enum_info *info) @@ -535,8 +573,6 @@ static int pci_program_bars(uint8_t bus, uint8_t dev, uint8_t fun, return 0; } -static uint32_t pci_enum_bus(uint8_t bus, struct pci_enum_info *info); - #ifdef DEBUG_PCI static void pci_dump_bridge(uint8_t bus, uint8_t dev, uint8_t fun) { @@ -579,12 +615,12 @@ static int pci_program_bridge(uint8_t bus, uint8_t dev, uint8_t fun, uint32_t orig_cmd; int ret; - PCI_DEBUG_PRINTF("bridge: %x.%x.%x\r\n", - (int)bus, (int)dev, (int)fun); orig_cmd = pci_config_read16(bus, dev, fun, PCI_COMMAND_OFFSET); pci_config_write16(bus, dev, fun, PCI_COMMAND_OFFSET, 0); info->curr_bus_number++; + PCI_DEBUG_PRINTF("Bridge: %x.%x.%x (using bus number: %d)\r\n", + (int)bus, (int)dev, (int)fun, info->curr_bus_number); pci_config_write8(bus, dev, fun, PCI_PRIMARY_BUS, bus); pci_config_write8(bus, dev, fun, PCI_SECONDARY_BUS, info->curr_bus_number); @@ -691,27 +727,33 @@ static int pci_program_bridge(uint8_t bus, uint8_t dev, uint8_t fun, return -1; } -static uint32_t pci_enum_bus(uint8_t bus, struct pci_enum_info *info) +uint32_t pci_enum_bus(uint8_t bus, struct pci_enum_info *info) { uint16_t vendor_id, device_id, header_type; uint32_t vd_code, reg; uint32_t dev, fun; int ret; + PCI_DEBUG_PRINTF("enumerating bus %d\r\n", bus); + for (dev = 0; dev < PCI_ENUM_MAX_DEV; dev++) { - vd_code = pci_config_read32(bus, dev, 0, 0x0); + vd_code = pci_config_read32(bus, dev, 0, PCI_VENDOR_ID_OFFSET); if (vd_code == 0xFFFFFFFF) { + PCI_DEBUG_PRINTF("Skipping %x:%x\r\n", bus, dev); /* No device here. */ continue; } for (fun = 0; fun < PCI_ENUM_MAX_FUN; fun++) { - if (pci_pre_enum_cb(bus, dev, fun)) + if (pci_pre_enum_cb(bus, dev, fun)) { + PCI_DEBUG_PRINTF("skipping fun %x:%x.%x\r\n", bus, dev, fun); continue; + } vd_code = pci_config_read32(bus, dev, fun, PCI_VENDOR_ID_OFFSET); if (vd_code == 0xFFFFFFFF) { + PCI_DEBUG_PRINTF("Skipping %x:%x.%x\r\n", bus, dev, fun); /* No device here, try next function*/ continue; } @@ -725,8 +767,10 @@ static uint32_t pci_enum_bus(uint8_t bus, struct pci_enum_info *info) pci_program_bridge(bus, dev, fun, info); } /* just one function */ - if (!(header_type & PCI_HEADER_TYPE_MULTIFUNC_MASK)) + if ((fun == 0) && !(header_type & PCI_HEADER_TYPE_MULTIFUNC_MASK)) { + PCI_DEBUG_PRINTF("one function only device\r\n"); break; + } } } @@ -734,7 +778,26 @@ static uint32_t pci_enum_bus(uint8_t bus, struct pci_enum_info *info) return 0; } -int pci_enum_do() +int pci_pre_enum(void) +{ + uint32_t reg; + + reg = pci_config_read32(0, 0, 0, CAPID0_A_0_0_0_PCI); + wolfBoot_printf("cap a %d\r\n", reg); + wolfBoot_printf("ddt disabled %d\r\n", reg & DTT_DEVICE_DISABLE); + reg &= ~(DTT_DEVICE_DISABLE); + pci_config_write32(0, 0, 0, CAPID0_A_0_0_0_PCI, reg); + reg = pci_config_read32(0, 0, 0, DEVICE_ENABLE); + wolfBoot_printf("device enable: %d\r\n", reg); + reg |= (1 << 7); + pci_config_write32(0, 0, 0, DEVICE_ENABLE, reg); + reg = pci_config_read32(0, 0, 0, DEVICE_ENABLE); + wolfBoot_printf("device enable: %d\r\n", reg); + + return 0; +} + +int pci_enum_do(void) { struct pci_enum_info enum_info; int ret; @@ -747,6 +810,12 @@ int pci_enum_do() enum_info.io = PCI_IO32_BASE; enum_info.curr_bus_number = 0; + ret = pci_pre_enum(); + if (ret != 0) { + wolfBoot_printf("pci_pre_enum error: %d\r\n", ret); + return ret; + } + ret = pci_enum_bus(0, &enum_info); PCI_DEBUG_PRINTF("PCI Memory Mapped I/O range [0x%x,0x%x] (0x%x)\r\n",