|
@@ -80,16 +80,28 @@ static int rc_delay[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
|
|
|
/* The PCI I/O space size in each PCI domain. */
|
|
|
#define IO_SPACE_SIZE 0x10000
|
|
|
|
|
|
+/* Provide shorter versions of some very long constant names. */
|
|
|
+#define AUTO_CONFIG_RC \
|
|
|
+ TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC
|
|
|
+#define AUTO_CONFIG_RC_G1 \
|
|
|
+ TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC_G1
|
|
|
+#define AUTO_CONFIG_EP \
|
|
|
+ TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT
|
|
|
+#define AUTO_CONFIG_EP_G1 \
|
|
|
+ TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT_G1
|
|
|
+
|
|
|
/* Array of the PCIe ports configuration info obtained from the BIB. */
|
|
|
struct pcie_port_property pcie_ports[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
|
|
|
|
|
|
+/* Number of configured TRIO instances. */
|
|
|
+int num_trio_shims;
|
|
|
+
|
|
|
/* All drivers share the TRIO contexts defined here. */
|
|
|
gxio_trio_context_t trio_contexts[TILEGX_NUM_TRIO];
|
|
|
|
|
|
/* Pointer to an array of PCIe RC controllers. */
|
|
|
struct pci_controller pci_controllers[TILEGX_NUM_TRIO * TILEGX_TRIO_PCIES];
|
|
|
int num_rc_controllers;
|
|
|
-static int num_ep_controllers;
|
|
|
|
|
|
static struct pci_ops tile_cfg_ops;
|
|
|
|
|
@@ -141,13 +153,14 @@ static int tile_pcie_open(int trio_index)
|
|
|
{
|
|
|
gxio_trio_context_t *context = &trio_contexts[trio_index];
|
|
|
int ret;
|
|
|
+ int mac;
|
|
|
|
|
|
/*
|
|
|
* This opens a file descriptor to the TRIO shim.
|
|
|
*/
|
|
|
ret = gxio_trio_init(context, trio_index);
|
|
|
if (ret < 0)
|
|
|
- return ret;
|
|
|
+ goto gxio_trio_init_failure;
|
|
|
|
|
|
/*
|
|
|
* Allocate an ASID for the kernel.
|
|
@@ -189,17 +202,89 @@ static int tile_pcie_open(int trio_index)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+ /* Get the properties of the PCIe ports on this TRIO instance. */
|
|
|
+ ret = hv_dev_pread(context->fd, 0,
|
|
|
+ (HV_VirtAddr)&pcie_ports[trio_index][0],
|
|
|
+ sizeof(struct pcie_port_property) * TILEGX_TRIO_PCIES,
|
|
|
+ GXIO_TRIO_OP_GET_PORT_PROPERTY);
|
|
|
+ if (ret < 0) {
|
|
|
+ pr_err("PCI: PCIE_GET_PORT_PROPERTY failure, error %d,"
|
|
|
+ " on TRIO %d\n", ret, trio_index);
|
|
|
+ goto get_port_property_failure;
|
|
|
+ }
|
|
|
+
|
|
|
+ context->mmio_base_mac =
|
|
|
+ iorpc_ioremap(context->fd, 0, HV_TRIO_CONFIG_IOREMAP_SIZE);
|
|
|
+ if (context->mmio_base_mac == NULL) {
|
|
|
+ pr_err("PCI: TRIO config space mapping failure, error %d,"
|
|
|
+ " on TRIO %d\n", ret, trio_index);
|
|
|
+ ret = -ENOMEM;
|
|
|
+
|
|
|
+ goto trio_mmio_mapping_failure;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Check the port strap state which will override the BIB setting. */
|
|
|
+ for (mac = 0; mac < TILEGX_TRIO_PCIES; mac++) {
|
|
|
+ TRIO_PCIE_INTFC_PORT_CONFIG_t port_config;
|
|
|
+ unsigned int reg_offset;
|
|
|
+
|
|
|
+ /* Ignore ports that are not specified in the BIB. */
|
|
|
+ if (!pcie_ports[trio_index][mac].allow_rc &&
|
|
|
+ !pcie_ports[trio_index][mac].allow_ep)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ reg_offset =
|
|
|
+ (TRIO_PCIE_INTFC_PORT_CONFIG <<
|
|
|
+ TRIO_CFG_REGION_ADDR__REG_SHIFT) |
|
|
|
+ (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
|
|
|
+ TRIO_CFG_REGION_ADDR__INTFC_SHIFT) |
|
|
|
+ (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
|
|
|
+
|
|
|
+ port_config.word =
|
|
|
+ __gxio_mmio_read(context->mmio_base_mac + reg_offset);
|
|
|
+
|
|
|
+ if (port_config.strap_state != AUTO_CONFIG_RC &&
|
|
|
+ port_config.strap_state != AUTO_CONFIG_RC_G1) {
|
|
|
+ /*
|
|
|
+ * If this is really intended to be an EP port, record
|
|
|
+ * it so that the endpoint driver will know about it.
|
|
|
+ */
|
|
|
+ if (port_config.strap_state == AUTO_CONFIG_EP ||
|
|
|
+ port_config.strap_state == AUTO_CONFIG_EP_G1)
|
|
|
+ pcie_ports[trio_index][mac].allow_ep = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
return ret;
|
|
|
|
|
|
+trio_mmio_mapping_failure:
|
|
|
+get_port_property_failure:
|
|
|
asid_alloc_failure:
|
|
|
#ifdef USE_SHARED_PCIE_CONFIG_REGION
|
|
|
pio_alloc_failure:
|
|
|
#endif
|
|
|
hv_dev_close(context->fd);
|
|
|
+gxio_trio_init_failure:
|
|
|
+ context->fd = -1;
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int __init tile_trio_init(void)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ /* We loop over all the TRIO shims. */
|
|
|
+ for (i = 0; i < TILEGX_NUM_TRIO; i++) {
|
|
|
+ if (tile_pcie_open(i) < 0)
|
|
|
+ continue;
|
|
|
+ num_trio_shims++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+postcore_initcall(tile_trio_init);
|
|
|
+
|
|
|
static void
|
|
|
tilegx_legacy_irq_ack(struct irq_data *d)
|
|
|
{
|
|
@@ -319,15 +404,40 @@ free_irqs:
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Return 1 if the port is strapped to operate in RC mode.
|
|
|
+ */
|
|
|
+static int
|
|
|
+strapped_for_rc(gxio_trio_context_t *trio_context, int mac)
|
|
|
+{
|
|
|
+ TRIO_PCIE_INTFC_PORT_CONFIG_t port_config;
|
|
|
+ unsigned int reg_offset;
|
|
|
+
|
|
|
+ /* Check the port configuration. */
|
|
|
+ reg_offset =
|
|
|
+ (TRIO_PCIE_INTFC_PORT_CONFIG <<
|
|
|
+ TRIO_CFG_REGION_ADDR__REG_SHIFT) |
|
|
|
+ (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
|
|
|
+ TRIO_CFG_REGION_ADDR__INTFC_SHIFT) |
|
|
|
+ (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
|
|
|
+ port_config.word =
|
|
|
+ __gxio_mmio_read(trio_context->mmio_base_mac + reg_offset);
|
|
|
+
|
|
|
+ if (port_config.strap_state == AUTO_CONFIG_RC ||
|
|
|
+ port_config.strap_state == AUTO_CONFIG_RC_G1)
|
|
|
+ return 1;
|
|
|
+ else
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Find valid controllers and fill in pci_controller structs for each
|
|
|
* of them.
|
|
|
*
|
|
|
- * Returns the number of controllers discovered.
|
|
|
+ * Return the number of controllers discovered.
|
|
|
*/
|
|
|
int __init tile_pci_init(void)
|
|
|
{
|
|
|
- int num_trio_shims = 0;
|
|
|
int ctl_index = 0;
|
|
|
int i, j;
|
|
|
|
|
@@ -338,19 +448,6 @@ int __init tile_pci_init(void)
|
|
|
|
|
|
pr_info("PCI: Searching for controllers...\n");
|
|
|
|
|
|
- /*
|
|
|
- * We loop over all the TRIO shims.
|
|
|
- */
|
|
|
- for (i = 0; i < TILEGX_NUM_TRIO; i++) {
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = tile_pcie_open(i);
|
|
|
- if (ret < 0)
|
|
|
- continue;
|
|
|
-
|
|
|
- num_trio_shims++;
|
|
|
- }
|
|
|
-
|
|
|
if (num_trio_shims == 0 || sim_is_simulator())
|
|
|
return 0;
|
|
|
|
|
@@ -361,29 +458,16 @@ int __init tile_pci_init(void)
|
|
|
*/
|
|
|
for (i = 0; i < TILEGX_NUM_TRIO; i++) {
|
|
|
gxio_trio_context_t *context = &trio_contexts[i];
|
|
|
- int ret;
|
|
|
|
|
|
if (context->fd < 0)
|
|
|
continue;
|
|
|
|
|
|
- ret = hv_dev_pread(context->fd, 0,
|
|
|
- (HV_VirtAddr)&pcie_ports[i][0],
|
|
|
- sizeof(struct pcie_port_property) * TILEGX_TRIO_PCIES,
|
|
|
- GXIO_TRIO_OP_GET_PORT_PROPERTY);
|
|
|
- if (ret < 0) {
|
|
|
- pr_err("PCI: PCIE_GET_PORT_PROPERTY failure, error %d,"
|
|
|
- " on TRIO %d\n", ret, i);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
for (j = 0; j < TILEGX_TRIO_PCIES; j++) {
|
|
|
- if (pcie_ports[i][j].allow_rc) {
|
|
|
+ if (pcie_ports[i][j].allow_rc &&
|
|
|
+ strapped_for_rc(context, j)) {
|
|
|
pcie_rc[i][j] = 1;
|
|
|
num_rc_controllers++;
|
|
|
}
|
|
|
- else if (pcie_ports[i][j].allow_ep) {
|
|
|
- num_ep_controllers++;
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -600,34 +684,9 @@ int __init pcibios_init(void)
|
|
|
|
|
|
tile_pci_init();
|
|
|
|
|
|
- if (num_rc_controllers == 0 && num_ep_controllers == 0)
|
|
|
+ if (num_rc_controllers == 0)
|
|
|
return 0;
|
|
|
|
|
|
- /*
|
|
|
- * We loop over all the TRIO shims and set up the MMIO mappings.
|
|
|
- */
|
|
|
- for (i = 0; i < TILEGX_NUM_TRIO; i++) {
|
|
|
- gxio_trio_context_t *context = &trio_contexts[i];
|
|
|
-
|
|
|
- if (context->fd < 0)
|
|
|
- continue;
|
|
|
-
|
|
|
- /*
|
|
|
- * Map in the MMIO space for the MAC.
|
|
|
- */
|
|
|
- offset = 0;
|
|
|
- context->mmio_base_mac =
|
|
|
- iorpc_ioremap(context->fd, offset,
|
|
|
- HV_TRIO_CONFIG_IOREMAP_SIZE);
|
|
|
- if (context->mmio_base_mac == NULL) {
|
|
|
- pr_err("PCI: MAC map failure on TRIO %d\n", i);
|
|
|
-
|
|
|
- hv_dev_close(context->fd);
|
|
|
- context->fd = -1;
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/*
|
|
|
* Delay a bit in case devices aren't ready. Some devices are
|
|
|
* known to require at least 20ms here, but we use a more
|
|
@@ -639,7 +698,6 @@ int __init pcibios_init(void)
|
|
|
for (next_busno = 0, i = 0; i < num_rc_controllers; i++) {
|
|
|
struct pci_controller *controller = &pci_controllers[i];
|
|
|
gxio_trio_context_t *trio_context = controller->trio;
|
|
|
- TRIO_PCIE_INTFC_PORT_CONFIG_t port_config;
|
|
|
TRIO_PCIE_INTFC_PORT_STATUS_t port_status;
|
|
|
TRIO_PCIE_INTFC_TX_FIFO_CTL_t tx_fifo_ctl;
|
|
|
struct pci_bus *bus;
|
|
@@ -655,39 +713,6 @@ int __init pcibios_init(void)
|
|
|
trio_index = controller->trio_index;
|
|
|
mac = controller->mac;
|
|
|
|
|
|
- /*
|
|
|
- * Check the port strap state which will override the BIB
|
|
|
- * setting.
|
|
|
- */
|
|
|
-
|
|
|
- reg_offset =
|
|
|
- (TRIO_PCIE_INTFC_PORT_CONFIG <<
|
|
|
- TRIO_CFG_REGION_ADDR__REG_SHIFT) |
|
|
|
- (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
|
|
|
- TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
|
|
|
- (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
|
|
|
-
|
|
|
- port_config.word =
|
|
|
- __gxio_mmio_read(trio_context->mmio_base_mac +
|
|
|
- reg_offset);
|
|
|
-
|
|
|
- if ((port_config.strap_state !=
|
|
|
- TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC) &&
|
|
|
- (port_config.strap_state !=
|
|
|
- TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC_G1)) {
|
|
|
- /*
|
|
|
- * If this is really intended to be an EP port,
|
|
|
- * record it so that the endpoint driver will know about it.
|
|
|
- */
|
|
|
- if (port_config.strap_state ==
|
|
|
- TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT ||
|
|
|
- port_config.strap_state ==
|
|
|
- TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT_G1)
|
|
|
- pcie_ports[trio_index][mac].allow_ep = 1;
|
|
|
-
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
/*
|
|
|
* Check for PCIe link-up status to decide if we need
|
|
|
* to force the link to come up.
|