/** * Get clock rate based on the clock type. * * @param node - CPU node number * @param clock - Enumeration of the clock type. * @return - return the clock rate. */ uint64_t cvmx_clock_get_rate_node(int node, cvmx_clock_t clock) { const uint64_t REF_CLOCK = 50000000; #ifdef CVMX_BUILD_FOR_UBOOT uint64_t rate_eclk = 0; uint64_t rate_sclk = 0; uint64_t rate_dclk = 0; #endif if (cvmx_unlikely(!rate_eclk)) { /* Note: The order of these checks is important. ** octeon_has_feature(OCTEON_FEATURE_PCIE) is true for both 6XXX ** and 52XX/56XX, so OCTEON_FEATURE_NPEI _must_ be checked first */ if (octeon_has_feature(OCTEON_FEATURE_NPEI)) { cvmx_npei_dbg_data_t npei_dbg_data; npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); rate_eclk = REF_CLOCK * npei_dbg_data.s.c_mul; rate_sclk = rate_eclk; } else if (OCTEON_IS_OCTEON3()) { cvmx_rst_boot_t rst_boot; rst_boot.u64 = cvmx_read_csr_node(node, CVMX_RST_BOOT); rate_eclk = REF_CLOCK * rst_boot.s.c_mul; rate_sclk = REF_CLOCK * rst_boot.s.pnr_mul; } else if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { cvmx_mio_rst_boot_t mio_rst_boot; mio_rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT); rate_eclk = REF_CLOCK * mio_rst_boot.s.c_mul; rate_sclk = REF_CLOCK * mio_rst_boot.s.pnr_mul; } else { cvmx_dbg_data_t dbg_data; dbg_data.u64 = cvmx_read_csr(CVMX_DBG_DATA); rate_eclk = REF_CLOCK * dbg_data.s.c_mul; rate_sclk = rate_eclk; } } switch (clock) { case CVMX_CLOCK_SCLK: case CVMX_CLOCK_TIM: case CVMX_CLOCK_IPD: return rate_sclk; case CVMX_CLOCK_RCLK: case CVMX_CLOCK_CORE: return rate_eclk; case CVMX_CLOCK_DDR: #if !defined(CVMX_BUILD_FOR_LINUX_HOST) && !defined(CVMX_BUILD_FOR_TOOLCHAIN) if (cvmx_unlikely(!rate_dclk)) rate_dclk = cvmx_sysinfo_get()->dram_data_rate_hz; #endif return rate_dclk; } cvmx_dprintf("cvmx_clock_get_rate: Unknown clock type\n"); return 0; }
/* * Set MII/RGMII link based on mode. * * @param port interface port to set the link. * @param link_info Link status * @param mode 0 = MII, 1 = RGMII mode * * @return 0 on success and 1 on failure */ int cvmx_agl_link_set(int port, cvmx_helper_link_info_t link_info, int mode) { cvmx_agl_gmx_prtx_cfg_t agl_gmx_prtx; /* Disable GMX before we make any changes. */ agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); agl_gmx_prtx.s.en = 0; agl_gmx_prtx.s.tx_en = 0; agl_gmx_prtx.s.rx_en = 0; cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64); if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_OCTEON3()) { uint64_t one_second = cvmx_clock_get_rate(CVMX_CLOCK_CORE); /* Wait for GMX to be idle */ if (CVMX_WAIT_FOR_FIELD64(CVMX_AGL_GMX_PRTX_CFG(port), cvmx_agl_gmx_prtx_cfg_t, rx_idle, ==, 1, one_second) || CVMX_WAIT_FOR_FIELD64(CVMX_AGL_GMX_PRTX_CFG(port), cvmx_agl_gmx_prtx_cfg_t, tx_idle, ==, 1, one_second)) { cvmx_dprintf("AGL%d: Timeout waiting for GMX to be idle\n", port); return -1; } }
/** * @INTERNAL * Probe a RGMII interface and determine the number of ports * connected to it. The RGMII interface should still be down * after this call. * * @param interface Interface to probe * * @return Number of ports on the interface. Zero to disable. */ int __cvmx_helper_agl_probe(int interface) { int port = cvmx_helper_agl_get_port(interface); union cvmx_agl_gmx_bist gmx_bist; union cvmx_agl_gmx_prtx_cfg gmx_prtx_cfg; union cvmx_agl_prtx_ctl agl_prtx_ctl; uint64_t clock_scale; int result; result = __cvmx_helper_agl_enumerate(interface); if (result == 0) return 0; /* Check BIST status */ gmx_bist.u64 = cvmx_read_csr(CVMX_AGL_GMX_BIST); if (gmx_bist.u64) cvmx_warn("Managment port AGL failed BIST (0x%016llx) on AGL%d\n", CAST64(gmx_bist.u64), port); /* Disable the external input/output */ gmx_prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); gmx_prtx_cfg.s.en = 0; cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), gmx_prtx_cfg.u64); /* Set the rgx_ref_clk MUX with AGL_PRTx_CTL[REFCLK_SEL]. Default value is 0 (RGMII REFCLK). Recommended to use RGMII RXC(1) or sclk/4 (2) to save cost. */ /* MII clocks counts are based on the 125Mhz reference, so our * delays need to be scaled to match the core clock rate. The * "+1" is to make sure rounding always waits a little too * long. FIXME. */ clock_scale = cvmx_clock_get_rate(CVMX_CLOCK_CORE) / 125000000 + 1; agl_prtx_ctl.u64 = cvmx_read_csr(CVMX_AGL_PRTX_CTL(port)); agl_prtx_ctl.s.clkrst = 0; agl_prtx_ctl.s.dllrst = 0; agl_prtx_ctl.s.clktx_byp = 0; if (OCTEON_IS_MODEL(OCTEON_CN70XX)) { agl_prtx_ctl.s.refclk_sel = 0; agl_prtx_ctl.s.clkrx_set = cvmx_helper_get_agl_rx_clock_skew(interface, port); agl_prtx_ctl.s.clkrx_byp = cvmx_helper_get_agl_rx_clock_delay_bypass(interface, port); } cvmx_write_csr(CVMX_AGL_PRTX_CTL(port), agl_prtx_ctl.u64); /* Force write out before wait */ cvmx_read_csr(CVMX_AGL_PRTX_CTL(port)); /* * Wait for the DLL to lock. External 125 MHz reference clock must be * stable at this point. */ cvmx_wait(256 * clock_scale); /* Enable the componsation controller */ agl_prtx_ctl.u64 = cvmx_read_csr(CVMX_AGL_PRTX_CTL(port)); agl_prtx_ctl.s.drv_byp = 0; cvmx_write_csr(CVMX_AGL_PRTX_CTL(port), agl_prtx_ctl.u64); /* Force write out before wait */ cvmx_read_csr(CVMX_AGL_PRTX_CTL(port)); if (!OCTEON_IS_OCTEON3()) { /* Enable the interface */ agl_prtx_ctl.u64 = cvmx_read_csr(CVMX_AGL_PRTX_CTL(port)); agl_prtx_ctl.s.enable = 1; cvmx_write_csr(CVMX_AGL_PRTX_CTL(port), agl_prtx_ctl.u64); /* Read the value back to force the previous write */ agl_prtx_ctl.u64 = cvmx_read_csr(CVMX_AGL_PRTX_CTL(port)); } /* Enable the compensation controller */ agl_prtx_ctl.u64 = cvmx_read_csr(CVMX_AGL_PRTX_CTL(port)); agl_prtx_ctl.s.comp = 1; cvmx_write_csr(CVMX_AGL_PRTX_CTL(port), agl_prtx_ctl.u64); /* Force write out before wait */ cvmx_read_csr(CVMX_AGL_PRTX_CTL(port)); /* for componsation state to lock. */ cvmx_wait(1024 * clock_scale); return result; }
/** * Initialize the QLM layer */ void cvmx_qlm_init(void) { int qlm; int qlm_jtag_length; char *qlm_jtag_name = "cvmx_qlm_jtag"; int qlm_jtag_size = CVMX_QLM_JTAG_UINT32 * 8 * sizeof(uint32_t); static uint64_t qlm_base = 0; const cvmx_bootmem_named_block_desc_t *desc; if (OCTEON_IS_OCTEON3()) return; #ifndef CVMX_BUILD_FOR_LINUX_HOST /* Skip actual JTAG accesses on simulator */ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) return; #endif qlm_jtag_length = cvmx_qlm_jtag_get_length(); if (sizeof(uint32_t) * qlm_jtag_length > (int)sizeof(__cvmx_qlm_jtag_xor_ref[0]) * 8) { cvmx_dprintf("ERROR: cvmx_qlm_init: JTAG chain larger than XOR ref size\n"); return; } /* No need to initialize the initial JTAG state if cvmx_qlm_jtag named block is already created. */ if ((desc = cvmx_bootmem_find_named_block(qlm_jtag_name)) != NULL) { #ifdef CVMX_BUILD_FOR_LINUX_HOST char buffer[qlm_jtag_size]; octeon_remote_read_mem(buffer, desc->base_addr, qlm_jtag_size); memcpy(__cvmx_qlm_jtag_xor_ref, buffer, qlm_jtag_size); #else __cvmx_qlm_jtag_xor_ref = cvmx_phys_to_ptr(desc->base_addr); #endif /* Initialize the internal JTAG */ cvmx_helper_qlm_jtag_init(); return; } /* Create named block to store the initial JTAG state. */ qlm_base = cvmx_bootmem_phy_named_block_alloc(qlm_jtag_size, 0, 0, 128, qlm_jtag_name, CVMX_BOOTMEM_FLAG_END_ALLOC); if (qlm_base == -1ull) { cvmx_dprintf("ERROR: cvmx_qlm_init: Error in creating %s named block\n", qlm_jtag_name); return; } #ifndef CVMX_BUILD_FOR_LINUX_HOST __cvmx_qlm_jtag_xor_ref = cvmx_phys_to_ptr(qlm_base); #endif memset(__cvmx_qlm_jtag_xor_ref, 0, qlm_jtag_size); /* Initialize the internal JTAG */ cvmx_helper_qlm_jtag_init(); /* Read the XOR defaults for the JTAG chain */ for (qlm = 0; qlm < cvmx_qlm_get_num(); qlm++) { int i; int num_lanes = cvmx_qlm_get_lanes(qlm); /* Shift all zeros in the chain to make sure all fields are at reset defaults */ cvmx_helper_qlm_jtag_shift_zeros(qlm, qlm_jtag_length * num_lanes); cvmx_helper_qlm_jtag_update(qlm); /* Capture the reset defaults */ cvmx_helper_qlm_jtag_capture(qlm); /* Save the reset defaults. This will shift out too much data, but the extra zeros don't hurt anything */ for (i = 0; i < CVMX_QLM_JTAG_UINT32; i++) __cvmx_qlm_jtag_xor_ref[qlm][i] = cvmx_helper_qlm_jtag_shift(qlm, 32, 0); } #ifdef CVMX_BUILD_FOR_LINUX_HOST /* Update the initial state for oct-remote utils. */ { char buffer[qlm_jtag_size]; memcpy(buffer, &__cvmx_qlm_jtag_xor_ref, qlm_jtag_size); octeon_remote_write_mem(qlm_base, buffer, qlm_jtag_size); } #endif /* Apply all QLM errata workarounds. */ __cvmx_qlm_speed_tweak(); __cvmx_qlm_pcie_idle_dac_tweak(); }
/* Version of octeon_model_get_string() that takes buffer as argument, as ** running early in u-boot static/global variables don't work when running from ** flash */ const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer) { const char *family; const char *core_model; char pass[4]; #ifndef CVMX_BUILD_FOR_UBOOT int clock_mhz; #endif const char *suffix; cvmx_l2d_fus3_t fus3; int num_cores; cvmx_mio_fus_dat2_t fus_dat2; cvmx_mio_fus_dat3_t fus_dat3; char fuse_model[10]; char fuse_suffix[4] = {0}; uint64_t fuse_data = 0; fus3.u64 = 0; if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)) fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3); fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2); fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3); if (OCTEON_IS_MODEL(OCTEON_CN78XX)) num_cores = cvmx_pop(cvmx_read_csr(CVMX_CIU3_FUSE)); else num_cores = cvmx_pop(cvmx_read_csr(CVMX_CIU_FUSE)); /* Make sure the non existent devices look disabled */ switch ((chip_id >> 8) & 0xff) { case 6: /* CN50XX */ case 2: /* CN30XX */ fus_dat3.s.nodfa_dte = 1; fus_dat3.s.nozip = 1; break; case 4: /* CN57XX or CN56XX */ fus_dat3.s.nodfa_dte = 1; break; default: break; } /* Make a guess at the suffix */ /* NSP = everything */ /* EXP = No crypto */ /* SCP = No DFA, No zip */ /* CP = No DFA, No crypto, No zip */ if (fus_dat3.s.nodfa_dte) { if (fus_dat2.s.nocrypto) suffix = "CP"; else suffix = "SCP"; } else if (fus_dat2.s.nocrypto) suffix = "EXP"; else suffix = "NSP"; /* Assume pass number is encoded using <5:3><2:0>. Exceptions will be fixed later */ sprintf(pass, "%d.%d", (int)((chip_id >> 3) & 7) + 1, (int)chip_id & 7); /* Use the number of cores to determine the last 2 digits of the model number. There are some exceptions that are fixed later */ switch (num_cores) { case 32: core_model = "80"; break; case 24: core_model = "70"; break; case 16: core_model = "60"; break; case 15: core_model = "58"; break; case 14: core_model = "55"; break; case 13: core_model = "52"; break; case 12: core_model = "50"; break; case 11: core_model = "48"; break; case 10: core_model = "45"; break; case 9: core_model = "42"; break; case 8: core_model = "40"; break; case 7: core_model = "38"; break; case 6: core_model = "34"; break; case 5: core_model = "32"; break; case 4: core_model = "30"; break; case 3: core_model = "25"; break; case 2: core_model = "20"; break; case 1: core_model = "10"; break; default: core_model = "XX"; break; } /* Now figure out the family, the first two digits */ switch ((chip_id >> 8) & 0xff) { case 0: /* CN38XX, CN37XX or CN36XX */ if (fus3.cn38xx.crip_512k) { /* For some unknown reason, the 16 core one is called 37 instead of 36 */ if (num_cores >= 16) family = "37"; else family = "36"; } else family = "38"; /* This series of chips didn't follow the standard pass numbering */ switch (chip_id & 0xf) { case 0: strcpy(pass, "1.X"); break; case 1: strcpy(pass, "2.X"); break; case 3: strcpy(pass, "3.X"); break; default: strcpy(pass, "X.X"); break; } break; case 1: /* CN31XX or CN3020 */ if ((chip_id & 0x10) || fus3.cn31xx.crip_128k) family = "30"; else family = "31"; /* This series of chips didn't follow the standard pass numbering */ switch (chip_id & 0xf) { case 0: strcpy(pass, "1.0"); break; case 2: strcpy(pass, "1.1"); break; default: strcpy(pass, "X.X"); break; } break; case 2: /* CN3010 or CN3005 */ family = "30"; /* A chip with half cache is an 05 */ if (fus3.cn30xx.crip_64k) core_model = "05"; /* This series of chips didn't follow the standard pass numbering */ switch (chip_id & 0xf) { case 0: strcpy(pass, "1.0"); break; case 2: strcpy(pass, "1.1"); break; default: strcpy(pass, "X.X"); break; } break; case 3: /* CN58XX */ family = "58"; /* Special case. 4 core, half cache (CP with half cache) */ if ((num_cores == 4) && fus3.cn58xx.crip_1024k && !strncmp(suffix, "CP", 2)) core_model = "29"; /* Pass 1 uses different encodings for pass numbers */ if ((chip_id & 0xFF) < 0x8) { switch (chip_id & 0x3) { case 0: strcpy(pass, "1.0"); break; case 1: strcpy(pass, "1.1"); break; case 3: strcpy(pass, "1.2"); break; default: strcpy(pass, "1.X"); break; } } break; case 4: /* CN57XX, CN56XX, CN55XX, CN54XX */ if (fus_dat2.cn56xx.raid_en) { if (fus3.cn56xx.crip_1024k) family = "55"; else family = "57"; if (fus_dat2.cn56xx.nocrypto) suffix = "SP"; else suffix = "SSP"; } else { if (fus_dat2.cn56xx.nocrypto) suffix = "CP"; else { suffix = "NSP"; if (fus_dat3.s.nozip) suffix = "SCP"; if (fus_dat3.cn56xx.bar2_en) suffix = "NSPB2"; } if (fus3.cn56xx.crip_1024k) family = "54"; else family = "56"; } break; case 6: /* CN50XX */ family = "50"; break; case 7: /* CN52XX */ if (fus3.cn52xx.crip_256k) family = "51"; else family = "52"; break; case 0x93: /* CN61XX/CN60XX */ family = "61"; if (fus_dat3.cn63xx.l2c_crip == 2) family = "60"; if (fus_dat3.cn61xx.nozip) suffix = "SCP"; else suffix = "AAP"; break; case 0x90: /* CN63XX/CN62XX */ family = "63"; if (fus_dat3.s.l2c_crip == 2) family = "62"; if (num_cores == 6) /* Other core counts match generic */ core_model = "35"; if (fus_dat2.cn63xx.nocrypto) suffix = "CP"; else if (fus_dat2.cn63xx.dorm_crypto) suffix = "DAP"; else if (fus_dat3.cn63xx.nozip) suffix = "SCP"; else suffix = "AAP"; break; case 0x92: /* CN66XX */ family = "66"; if (num_cores == 6) /* Other core counts match generic */ core_model = "35"; if (fus_dat2.cn66xx.nocrypto && fus_dat2.cn66xx.dorm_crypto) suffix = "AP"; if (fus_dat2.cn66xx.nocrypto) suffix = "CP"; else if (fus_dat2.cn66xx.dorm_crypto) suffix = "DAP"; else if (fus_dat3.cn66xx.nozip && fus_dat2.cn66xx.raid_en) suffix = "SCP"; else if (!fus_dat2.cn66xx.raid_en) suffix = "HAP"; else suffix = "AAP"; break; case 0x91: /* CN68XX */ family = "68"; if (fus_dat2.cn68xx.nocrypto && fus_dat3.cn68xx.nozip) suffix = "CP"; else if (fus_dat2.cn68xx.dorm_crypto) suffix = "DAP"; else if (fus_dat3.cn68xx.nozip) suffix = "SCP"; else if (fus_dat2.cn68xx.nocrypto) suffix = "SP"; else if (!fus_dat2.cn68xx.raid_en) suffix = "HAP"; else suffix = "AAP"; break; case 0x94: /* CNF71XX */ family = "F71"; if (fus_dat3.cnf71xx.nozip) suffix = "SCP"; else suffix = "AAP"; break; case 0x95: /* CN78XX */ family = "78"; if (fus_dat3.cn70xx.nozip) suffix = "SCP"; else suffix = "AAP"; break; case 0x96: /* CN70XX */ family = "70"; if (cvmx_read_csr(CVMX_MIO_FUS_PDF) & (0x1ULL << 32)) family = "71"; if (fus_dat2.cn70xx.nocrypto) suffix = "CP"; else if (fus_dat3.cn70xx.nodfa_dte) suffix = "SCP"; else suffix = "AAP"; break; default: family = "XX"; core_model = "XX"; strcpy(pass, "X.X"); suffix = "XXX"; break; } #ifndef CVMX_BUILD_FOR_UBOOT clock_mhz = cvmx_clock_get_rate(CVMX_CLOCK_RCLK) / 1000000; #endif if (family[0] != '3') { if (OCTEON_IS_OCTEON1PLUS() || OCTEON_IS_OCTEON2()) { int fuse_base = 384 / 8; if (family[0] == '6' || OCTEON_IS_OCTEON3()) fuse_base = 832 / 8; /* Check for model in fuses, overrides normal decode */ /* This is _not_ valid for Octeon CN3XXX models */ fuse_data |= cvmx_fuse_read_byte(fuse_base + 5); fuse_data = fuse_data << 8; fuse_data |= cvmx_fuse_read_byte(fuse_base + 4); fuse_data = fuse_data << 8; fuse_data |= cvmx_fuse_read_byte(fuse_base + 3); fuse_data = fuse_data << 8; fuse_data |= cvmx_fuse_read_byte(fuse_base + 2); fuse_data = fuse_data << 8; fuse_data |= cvmx_fuse_read_byte(fuse_base + 1); fuse_data = fuse_data << 8; fuse_data |= cvmx_fuse_read_byte(fuse_base); if (fuse_data & 0x7ffff) { int model = fuse_data & 0x3fff; int suffix = (fuse_data >> 14) & 0x1f; if (suffix && model) { /* Have both number and suffix in fuses, so both */ sprintf(fuse_model, "%d%c", model, 'A' + suffix - 1); core_model = ""; family = fuse_model; } else if (suffix && !model) { /* Only have suffix, so add suffix to 'normal' model number */ sprintf(fuse_model, "%s%c", core_model, 'A' + suffix - 1); core_model = fuse_model; } else { /* Don't have suffix, so just use model from fuses */ sprintf(fuse_model, "%d", model); core_model = ""; family = fuse_model; } } } else {
void init_octeon_pcie(void) { int first_busno; int i; int rc = 0; int node = cvmx_get_node_num(); struct pci_controller *hose; int pcie_port; first_busno = OCTEON_FIRST_PCIE_BUSNO; memset(&hose_pcie[0], 0, sizeof(hose_pcie[0]) * num_pcie_ports); debug("Starting PCIE on node %d\n", node); for (i = 0; i < num_pcie_ports; i++) { pcie_port = ((node << 4) | i); rc = cvmx_pcie_rc_initialize(pcie_port); if (rc != 0) continue; mdelay(1000); /* Should delay 1 second according to standard */ hose = &hose_pcie[i]; hose->priv_data = (void *)&oct_pcie_data[i]; oct_pcie_data[i].pcie_port = pcie_port;; hose->config_table = pci_board_config_table; hose->first_busno = first_busno; hose->last_busno = 0xff; /* PCI I/O space (Sub-DID == 2) */ pci_set_region(hose->regions + 0, octeon_pcie_region_info[i].io_base, octeon_pcie_region_info[i].io_base, octeon_pcie_region_info[i].io_size, PCI_REGION_IO); /* PCI memory space (Sub-DID == 3) */ pci_set_region(hose->regions + 1, octeon_pcie_region_info[i].mem_base, octeon_pcie_region_info[i].mem_base, octeon_pcie_region_info[i].mem_size, PCI_REGION_MEM); hose->region_count = 2; pci_set_ops(hose, octeon_pcie_read_config_byte, octeon_pcie_read_config_word, octeon_pcie_read_config_dword, octeon_pcie_write_config_byte, octeon_pcie_write_config_word, octeon_pcie_write_config_dword); pci_register_hose(hose); hose->last_busno = pci_hose_scan(hose); debug("PCIe: port=%d, first_bus=%d, last_bus=%d,\n\t" "mem_base=0x%x, mem_size=0x%x, io_base=0x%x, io_size=0x%x\n", octeon_get_pcie_port(hose), hose->first_busno, hose->last_busno, octeon_pcie_region_info[i].mem_base, octeon_pcie_region_info[i].mem_size, octeon_pcie_region_info[i].io_base, octeon_pcie_region_info[i].io_size); first_busno = hose->last_busno + 1; #if CONFIG_OCTEON_PCI_ENABLE_32BIT_MAPPING if (OCTEON_IS_OCTEON2() || OCTEON_IS_OCTEON3()) { cvmx_pemx_bar_ctl_t bar_ctl; cvmx_pemx_bar1_indexx_t pemx_bar1_indexx; uint64_t bar_base; int j; /* Setup BAR1 to map bus address 0x0 to the base of * u-boot's TLB mapping. This allows us to have u-boot * located anywhere in memory (including above 32 bit * addressable space) and still have 32 bit PCI devices * have access to memory that is statically allocated * or malloced by u-boot, both of which are TLB mapped. */ cvmx_write_csr_node(node, CVMX_PEMX_P2N_BAR1_START(i), 0); /* Disable bar0/bar2, as we are not using them here */ cvmx_write_csr_node(node, CVMX_PEMX_P2N_BAR0_START(i), -1); cvmx_write_csr_node(node, CVMX_PEMX_P2N_BAR2_START(i), -1); /* Select 64 MByte mapping size for bar 1 on * all ports */ bar_ctl.u64 = cvmx_read_csr_node(node, CVMX_PEMX_BAR_CTL(i)); bar_ctl.s.bar1_siz = 1; /* 64MB */ bar_ctl.s.bar2_enb = 0; cvmx_write_csr_node(node, CVMX_PEMX_BAR_CTL(i), bar_ctl.u64); /* Configure the regions in bar 1 to map to the * DRAM used by u-boot. */ /* Round down to 4MByte boundary to meet BAR mapping * requirements */ bar_base = gd->bd->bi_uboot_ram_addr & ~0x3fffffull; debug("pcie: port %d, setting BAR base to 0x%llx\n", i, bar_base); pemx_bar1_indexx.u64 = 0; pemx_bar1_indexx.s.addr_v = 1; pemx_bar1_indexx.s.end_swp = 1; pemx_bar1_indexx.s.ca = 1; for (j = 0; j < 16; j++) { pemx_bar1_indexx.s.addr_idx = (bar_base + 4 * 1024 * 1024 * j) >> 22; cvmx_write64_uint64(CVMX_PEMX_BAR1_INDEXX(j, i), pemx_bar1_indexx.u64); } } #endif /* CONFIG_OCTEON_PCI_ENABLE_32BIT_MAPPING */ }