]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
microblaze: pcie: Fix rescan issues
authorSrikanth Thokala <srikanth.thokala@xilinx.com>
Fri, 8 Mar 2013 12:29:13 +0000 (17:59 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Mon, 11 Mar 2013 13:28:17 +0000 (14:28 +0100)
This commit addresses following issues:
.  Initially, end point is up and running. When a reset is triggered,
   it clears the bridge-enable bit (it resets on transition from link
   up to down) resulting in failure of rescan.
.  Link is not up (EP is in reset state), during kernel boot.  Then EP
   comes to normal state and Link is up (after kernel boot). User
   cannot issue rescan, as the root port device entry doesn't
   list in /sys/bus/pci.

Signed-off-by: Srikanth Thokala <sthokal@xilinx.com>
arch/microblaze/pci/pci-common.c
arch/microblaze/pci/xilinx_axipcie.c

index 26afc2fe2a30b0d334900039e2e9d19b0aac768d..58c974bbee4e4d8097c0e5cb77e48c17117f4e65 100644 (file)
@@ -187,10 +187,12 @@ int pcibios_add_platform_entries(struct pci_dev *pdev)
        return device_create_file(&pdev->dev, &dev_attr_devspec);
 }
 
+#ifndef CONFIG_XILINX_AXIPCIE
 void pcibios_set_master(struct pci_dev *dev)
 {
        /* No special bus mastering setup handling */
 }
+#endif
 
 /*
  * Reads the interrupt pin to determine if interrupt is use by card.
index 22bd466920a6027a4e33f8d39d930fcc88f261b7..895ed15cae747c4dca98ed05fba5bae294caa95c 100644 (file)
@@ -52,6 +52,16 @@ static int last_bus_on_record;
 unsigned long msg_addr;
 #endif
 
+/* Macros */
+#define is_link_up(base_address)       \
+       ((in_le32(((u8 *)base_address) + AXIPCIE_REG_PSCR) &    \
+       AXIPCIE_REG_PSCR_LNKUP) ? 1 : 0)
+
+#define bridge_enable(base_address)    \
+       out_le32((((u8 *)base_address) + AXIPCIE_REG_RPSC),     \
+               (in_le32(((u8 *)base_address) + AXIPCIE_REG_RPSC) |     \
+               AXIPCIE_REG_RPSC_BEN))
+
 /**
  * xilinx_get_axipcie_ip_config_info - Read info from device tree
  * @dev: A pointer to device node to read from
@@ -169,7 +179,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_xilinx_axipcie_bridge);
  */
 static int xilinx_init_axipcie_port(struct xilinx_axipcie_port *port)
 {
-       u32 val = 0;
        void __iomem *base_addr_remap = NULL;
 
        /* base_addr_remap = ioremap(port->reg_base, PORT_REG_SIZE); */
@@ -195,16 +204,11 @@ static int xilinx_init_axipcie_port(struct xilinx_axipcie_port *port)
                                                        msg_addr);
 #endif
 
-       /* make sure link is up */
-       val = in_le32(((u8 *)port->base_addr_remap) + AXIPCIE_REG_PSCR);
-
-       if (!(val & AXIPCIE_REG_PSCR_LNKUP)) {
-               printk(KERN_ERR "PCIE: Link is Down\n");
-               iounmap(base_addr_remap);
-               return -ENODEV;
-       }
-
-       port->link = 1;
+       port->link = is_link_up(port->base_addr_remap);
+       if (!port->link)
+               pr_info("LINK IS DOWN\n");
+       else
+               pr_info("LINK IS UP\n");
 
        /* Disable all interrupts*/
        out_le32((((u8 *)port->base_addr_remap) + AXIPCIE_REG_IMR),
@@ -219,9 +223,7 @@ static int xilinx_init_axipcie_port(struct xilinx_axipcie_port *port)
 
        /* Bridge enable must be done after enumeration,
                but there is no callback defined */
-       val = in_le32(((u8 *)port->base_addr_remap) + AXIPCIE_REG_RPSC);
-       val |= AXIPCIE_REG_RPSC_BEN;
-       out_le32((((u8 *)port->base_addr_remap) + AXIPCIE_REG_RPSC), val);
+       bridge_enable(port->base_addr_remap);
 
        return 0;
 }
@@ -263,6 +265,9 @@ static int xilinx_axipcie_verify_config(struct xilinx_axipcie_port *port,
                return PCIBIOS_DEVICE_NOT_FOUND;
 
        /* Check if we have a link */
+       if (!port->link)
+               port->link = is_link_up(port->base_addr_remap);
+
        if ((bus->number != port->hose->first_busno) && !port->link)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -791,6 +796,24 @@ static int __init xilinx_probe_axipcie_node(struct device_node *np)
        return 0;
 }
 
+/**
+ * pcibios_set_master - Architecture specific function
+ * @dev: A pointer to device pcie device struct
+ *
+ * @return: Error / no error
+ * @note: Enables Bridge Enable bit during the rescan process
+ */
+void pcibios_set_master(struct pci_dev *dev)
+{
+       struct pci_controller *hose =
+                       (struct pci_controller *) dev->bus->sysdata;
+       struct xilinx_axipcie_port *port =
+                       &xilinx_axipcie_ports[hose->indirect_type];
+
+       if (port->link)
+               bridge_enable(port->base_addr_remap);
+}
+
 /**
  * xilinx_find_axipcie_nodes - Entry function
  * void