Fixes for NXP T1024 with Integrity OS. Adds additional FDT fixups for FMAN, Ethernet, PCI. Add PCI init and enumeration.

pull/404/head
David Garske 2024-01-24 15:11:39 -08:00 committed by Daniele Lacamera
parent 6ccf221483
commit 0b206d6758
7 changed files with 517 additions and 66 deletions

View File

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

View File

@ -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;
return 0;
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;
}
/* 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; i<FMAN_DMA_ENTRIES; i++) {
set32(FMAN_DMA_PORT_LIODN(i),
((FMAN_DMA_LIODN << 16) | FMAN_DMA_LIODN));
}
}
return ret;
}
@ -1752,7 +1939,9 @@ void hal_init(void)
hal_flash_init();
hal_cpld_init();
#ifdef ENABLE_PCIE
hal_pcie_init();
if (hal_pcie_init() != 0) {
wolfBoot_printf("PCIe: init failed!\n");
}
#endif
#ifdef ENABLE_QE
@ -1947,6 +2136,10 @@ int hal_dts_fixup(void* dts_addr)
struct fdt_header *fdt = (struct fdt_header *)dts_addr;
int off, i;
uint32_t *reg;
const char* prev_compat;
/* TODO: Ethenet MAC should be dynamic value */
uint8_t mac_addr[6] = {0xDC, 0xA7, 0xD9, 0x00, 0x07, 0x10};
/* verify the FTD is valid */
off = fdt_check_header(dts_addr);
@ -1960,8 +2153,8 @@ int hal_dts_fixup(void* dts_addr)
fdt_version(fdt), fdt_totalsize(fdt));
/* expand total size */
fdt->totalsize += 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;

View File

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

View File

@ -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 */

View File

@ -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,

View File

@ -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)
{

109
src/pci.c
View File

@ -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 @@ restore_bar:
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",