Adds dm_pci_flr API that issues a Function Level reset on a PCI-e function,
if FLR is supported.

Signed-off-by: Alex Marginean <alexm.ossl...@gmail.com>
---

Changes in v2:
        - Use kernel PCI_EXP macros for register offsets

 drivers/pci/pci-uclass.c | 24 ++++++++++++++++++++++++
 include/pci.h            | 14 ++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 389aec15ce..c74ebf6a76 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -1494,6 +1494,30 @@ int dm_pci_find_ext_capability(struct udevice *dev, int 
cap)
        return dm_pci_find_next_ext_capability(dev, 0, cap);
 }
 
+int dm_pci_flr(struct udevice *dev)
+{
+       int pcie_off;
+       u32 cap;
+
+       /* look for PCI Express Capability */
+       pcie_off = dm_pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (!pcie_off)
+               return -ENOENT;
+
+       /* check FLR capability */
+       dm_pci_read_config32(dev, pcie_off + PCI_EXP_DEVCAP, &cap);
+       if (!(cap & PCI_EXP_DEVCAP_FLR))
+               return -ENOENT;
+
+       dm_pci_clrset_config16(dev, pcie_off + PCI_EXP_DEVCTL, 0,
+                              PCI_EXP_DEVCTL_BCR_FLR);
+
+       /* wait 100ms, per PCI spec */
+       mdelay(100);
+
+       return 0;
+}
+
 UCLASS_DRIVER(pci) = {
        .id             = UCLASS_PCI,
        .name           = "pci",
diff --git a/include/pci.h b/include/pci.h
index 0aab438159..298d0d4355 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -466,6 +466,12 @@
 #define  PCI_EA_IS_64          0x00000002      /* 64-bit field flag */
 #define  PCI_EA_FIELD_MASK     0xfffffffc      /* For Base & Max Offset */
 
+/* PCI Express capabilities */
+#define PCI_EXP_DEVCAP         4       /* Device capabilities */
+#define  PCI_EXP_DEVCAP_FLR     0x10000000 /* Function Level Reset */
+#define PCI_EXP_DEVCTL         8       /* Device Control */
+#define  PCI_EXP_DEVCTL_BCR_FLR 0x8000  /* Bridge Configuration Retry / FLR */
+
 /* Include the ID list */
 
 #include <pci_ids.h>
@@ -1426,6 +1432,14 @@ int dm_pci_find_next_ext_capability(struct udevice *dev, 
int start, int cap);
  */
 int dm_pci_find_ext_capability(struct udevice *dev, int cap);
 
+/**
+ * dm_pci_flr() - Perform FLR if the device suppoorts it
+ *
+ * @dev:       PCI device to reset
+ * @return:    0 if OK, -ENOENT if FLR is not supported by dev
+ */
+int dm_pci_flr(struct udevice *dev);
+
 #define dm_pci_virt_to_bus(dev, addr, flags) \
        dm_pci_phys_to_bus(dev, (virt_to_phys(addr)), (flags))
 #define dm_pci_bus_to_virt(dev, addr, flags, len, map_flags) \
-- 
2.17.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to