in pci/pcie-octeon.c [1860:2087]
static int __init octeon_pcie_setup(void)
{
int result;
int host_mode;
int srio_war15205 = 0, port;
union cvmx_sli_ctl_portx sli_ctl_portx;
union cvmx_sriox_status_reg sriox_status_reg;
/* These chips don't have PCIe */
if (!octeon_has_feature(OCTEON_FEATURE_PCIE))
return 0;
/* No PCIe simulation */
if (octeon_is_simulation())
return 0;
/* Disable PCI if instructed on the command line */
if (pcie_disable)
return 0;
/* Point pcibios_map_irq() to the PCIe version of it */
octeon_pcibios_map_irq = octeon_pcie_pcibios_map_irq;
/*
* PCIe I/O range. It is based on port 0 but includes up until
* port 1's end.
*/
set_io_port_base(CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(0)));
ioport_resource.start = 0;
ioport_resource.end =
cvmx_pcie_get_io_base_address(1) -
cvmx_pcie_get_io_base_address(0) + cvmx_pcie_get_io_size(1) - 1;
/*
* Create a dummy PCIe controller to swallow up bus 0. IDT bridges
* don't work if the primary bus number is zero. Here we add a fake
* PCIe controller that the kernel will give bus 0. This allows
* us to not change the normal kernel bus enumeration
*/
octeon_dummy_controller.io_map_base = -1;
octeon_dummy_controller.mem_resource->start = (1ull<<48);
octeon_dummy_controller.mem_resource->end = (1ull<<48);
register_pci_controller(&octeon_dummy_controller);
if (octeon_has_feature(OCTEON_FEATURE_NPEI)) {
union cvmx_npei_ctl_status npei_ctl_status;
npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS);
host_mode = npei_ctl_status.s.host_mode;
octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_PCIE;
} else {
union cvmx_mio_rst_ctlx mio_rst_ctl;
mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(0));
host_mode = mio_rst_ctl.s.host_mode;
octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_PCIE2;
}
if (host_mode) {
pr_notice("PCIe: Initializing port 0\n");
/* CN63XX pass 1_x/2.0 errata PCIe-15205 */
if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) ||
OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0)) {
sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(0));
if (sriox_status_reg.s.srio) {
srio_war15205 += 1; /* Port is SRIO */
port = 0;
}
}
result = cvmx_pcie_rc_initialize(0);
if (result == 0) {
uint32_t device0;
/* Memory offsets are physical addresses */
octeon_pcie0_controller.mem_offset =
cvmx_pcie_get_mem_base_address(0);
/* IO offsets are Mips virtual addresses */
octeon_pcie0_controller.io_map_base =
CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address
(0));
octeon_pcie0_controller.io_offset = 0;
/*
* To keep things similar to PCI, we start
* device addresses at the same place as PCI
* uisng big bar support. This normally
* translates to 4GB-256MB, which is the same
* as most x86 PCs.
*/
octeon_pcie0_controller.mem_resource->start =
cvmx_pcie_get_mem_base_address(0) +
(4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20);
octeon_pcie0_controller.mem_resource->end =
cvmx_pcie_get_mem_base_address(0) +
cvmx_pcie_get_mem_size(0) - 1;
/*
* Ports must be above 16KB for the ISA bus
* filtering in the PCI-X to PCI bridge.
*/
octeon_pcie0_controller.io_resource->start = 4 << 10;
octeon_pcie0_controller.io_resource->end =
cvmx_pcie_get_io_size(0) - 1;
msleep(100); /* Some devices need extra time */
register_pci_controller(&octeon_pcie0_controller);
device0 = cvmx_pcie_config_read32(0, 0, 0, 0, 0);
enable_pcie_bus_num_war[0] =
device_needs_bus_num_war(device0);
}
} else {
pr_notice("PCIe: Port 0 in endpoint mode, skipping.\n");
/* CN63XX pass 1_x/2.0 errata PCIe-15205 */
if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) ||
OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0)) {
srio_war15205 += 1;
port = 0;
}
}
if (octeon_has_feature(OCTEON_FEATURE_NPEI)) {
host_mode = 1;
/* Skip the 2nd port on CN52XX if port 0 is in 4 lane mode */
if (OCTEON_IS_MODEL(OCTEON_CN52XX)) {
union cvmx_npei_dbg_data dbg_data;
dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA);
if (dbg_data.cn52xx.qlm0_link_width)
host_mode = 0;
}
} else {
union cvmx_mio_rst_ctlx mio_rst_ctl;
mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(1));
host_mode = mio_rst_ctl.s.host_mode;
}
if (host_mode) {
pr_notice("PCIe: Initializing port 1\n");
/* CN63XX pass 1_x/2.0 errata PCIe-15205 */
if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) ||
OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0)) {
sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(1));
if (sriox_status_reg.s.srio) {
srio_war15205 += 1; /* Port is SRIO */
port = 1;
}
}
result = cvmx_pcie_rc_initialize(1);
if (result == 0) {
uint32_t device0;
/* Memory offsets are physical addresses */
octeon_pcie1_controller.mem_offset =
cvmx_pcie_get_mem_base_address(1);
/*
* To calculate the address for accessing the 2nd PCIe device,
* either 'io_map_base' (pci_iomap()), or 'mips_io_port_base'
* (ioport_map()) value is added to
* pci_resource_start(dev,bar)). The 'mips_io_port_base' is set
* only once based on first PCIe. Also changing 'io_map_base'
* based on first slot's value so that both the routines will
* work properly.
*/
octeon_pcie1_controller.io_map_base =
CVMX_ADD_IO_SEG(cvmx_pcie_get_io_base_address(0));
/* IO offsets are Mips virtual addresses */
octeon_pcie1_controller.io_offset =
cvmx_pcie_get_io_base_address(1) -
cvmx_pcie_get_io_base_address(0);
/*
* To keep things similar to PCI, we start device
* addresses at the same place as PCI uisng big bar
* support. This normally translates to 4GB-256MB,
* which is the same as most x86 PCs.
*/
octeon_pcie1_controller.mem_resource->start =
cvmx_pcie_get_mem_base_address(1) + (4ul << 30) -
(OCTEON_PCI_BAR1_HOLE_SIZE << 20);
octeon_pcie1_controller.mem_resource->end =
cvmx_pcie_get_mem_base_address(1) +
cvmx_pcie_get_mem_size(1) - 1;
/*
* Ports must be above 16KB for the ISA bus filtering
* in the PCI-X to PCI bridge.
*/
octeon_pcie1_controller.io_resource->start =
cvmx_pcie_get_io_base_address(1) -
cvmx_pcie_get_io_base_address(0);
octeon_pcie1_controller.io_resource->end =
octeon_pcie1_controller.io_resource->start +
cvmx_pcie_get_io_size(1) - 1;
msleep(100); /* Some devices need extra time */
register_pci_controller(&octeon_pcie1_controller);
device0 = cvmx_pcie_config_read32(1, 0, 0, 0, 0);
enable_pcie_bus_num_war[1] =
device_needs_bus_num_war(device0);
}
} else {
pr_notice("PCIe: Port 1 not in root complex mode, skipping.\n");
/* CN63XX pass 1_x/2.0 errata PCIe-15205 */
if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) ||
OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0)) {
srio_war15205 += 1;
port = 1;
}
}
/*
* CN63XX pass 1_x/2.0 errata PCIe-15205 requires setting all
* of SRIO MACs SLI_CTL_PORT*[INT*_MAP] to similar value and
* all of PCIe Macs SLI_CTL_PORT*[INT*_MAP] to different value
* from the previous set values
*/
if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) ||
OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0)) {
if (srio_war15205 == 1) {
sli_ctl_portx.u64 = cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(port));
sli_ctl_portx.s.inta_map = 1;
sli_ctl_portx.s.intb_map = 1;
sli_ctl_portx.s.intc_map = 1;
sli_ctl_portx.s.intd_map = 1;
cvmx_write_csr(CVMX_PEXP_SLI_CTL_PORTX(port), sli_ctl_portx.u64);
sli_ctl_portx.u64 = cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(!port));
sli_ctl_portx.s.inta_map = 0;
sli_ctl_portx.s.intb_map = 0;
sli_ctl_portx.s.intc_map = 0;
sli_ctl_portx.s.intd_map = 0;
cvmx_write_csr(CVMX_PEXP_SLI_CTL_PORTX(!port), sli_ctl_portx.u64);
}
}
octeon_pci_dma_init();
return 0;
}