Merge tag 'v2022.01-rc4' into next
[platform/kernel/u-boot.git] / drivers / pci / pci-aardvark.c
index 74797e9..22b6d8b 100644 (file)
@@ -21,6 +21,7 @@
  *
  * Author: Victor Gu <xigu@marvell.com>
  *         Hezi Shahmoon <hezi.shahmoon@marvell.com>
+ *         Pali Rohár <pali@kernel.org>
  *
  */
 
@@ -39,6 +40,9 @@
 #define     PCIE_CORE_CMD_IO_ACCESS_EN                         BIT(0)
 #define     PCIE_CORE_CMD_MEM_ACCESS_EN                                BIT(1)
 #define     PCIE_CORE_CMD_MEM_IO_REQ_EN                                BIT(2)
+#define PCIE_CORE_DEV_REV_REG                                  0x8
+#define PCIE_CORE_EXP_ROM_BAR_REG                              0x30
+#define PCIE_CORE_PCIEXP_CAP_OFF                               0xc0
 #define PCIE_CORE_DEV_CTRL_STATS_REG                           0xc8
 #define     PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE       (0 << 4)
 #define     PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE             (0 << 11)
 #define     LTSSM_SHIFT                                24
 #define     LTSSM_MASK                         0x3f
 #define     LTSSM_L0                           0x10
+#define     LTSSM_DISABLED                     0x20
 #define VENDOR_ID_REG                          (LMI_BASE_ADDR + 0x44)
 
 /* PCIe core controller registers */
 #define PCIE_CONFIG_WR_TYPE0                   0xa
 #define PCIE_CONFIG_WR_TYPE1                   0xb
 
-/* PCI_BDF shifts 8bit, so we need extra 4bit shift */
-#define PCIE_BDF(dev)                          (dev << 4)
-#define PCIE_CONF_BUS(bus)                     (((bus) & 0xff) << 20)
-#define PCIE_CONF_DEV(dev)                     (((dev) & 0x1f) << 15)
-#define PCIE_CONF_FUNC(fun)                    (((fun) & 0x7)  << 12)
-#define PCIE_CONF_REG(reg)                     ((reg) & 0xffc)
-#define PCIE_CONF_ADDR(bus, devfn, where)      \
-       (PCIE_CONF_BUS(bus) | PCIE_CONF_DEV(PCI_SLOT(devfn))    | \
-        PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where))
-
 /* PCIe Retries & Timeout definitions */
 #define PIO_MAX_RETRIES                                1500
 #define PIO_WAIT_TIMEOUT                       1000
 /**
  * struct pcie_advk - Advk PCIe controller state
  *
- * @reg_base:    The base address of the register space.
- * @first_busno: This driver supports multiple PCIe controllers.
- *               first_busno stores the bus number of the PCIe root-port
- *               number which may vary depending on the PCIe setup
- *               (PEX switches etc).
- * @device:      The pointer to PCI uclass device.
+ * @base:        The base address of the register space.
+ * @first_busno: Bus number of the PCIe root-port.
+ *               This may vary depending on the PCIe setup.
+ * @sec_busno:   Bus number for the device behind the PCIe root-port.
+ * @dev:         The pointer to PCI uclass device.
+ * @reset_gpio:  GPIO descriptor for PERST.
+ * @cfgcache:    Buffer for emulation of PCIe Root Port's PCI Bridge registers
+ *               that are not available on Aardvark.
+ * @cfgcrssve:   For CRSSVE emulation.
  */
 struct pcie_advk {
-       void           *base;
-       int            first_busno;
-       struct udevice *dev;
-       struct gpio_desc reset_gpio;
+       void                    *base;
+       int                     first_busno;
+       int                     sec_busno;
+       struct udevice          *dev;
+       struct gpio_desc        reset_gpio;
+       u32                     cfgcache[(0x3c - 0x10) / 4];
+       bool                    cfgcrssve;
 };
 
 static inline void advk_writel(struct pcie_advk *pcie, uint val, uint reg)
@@ -209,22 +210,30 @@ static inline uint advk_readl(struct pcie_advk *pcie, uint reg)
 /**
  * pcie_advk_addr_valid() - Check for valid bus address
  *
+ * @pcie: Pointer to the PCI bus
+ * @busno: Bus number of PCI device
+ * @dev: Device number of PCI device
+ * @func: Function number of PCI device
  * @bdf: The PCI device to access
- * @first_busno: Bus number of the PCIe controller root complex
  *
- * Return: 1 on valid, 0 on invalid
+ * Return: true on valid, false on invalid
  */
-static int pcie_advk_addr_valid(pci_dev_t bdf, int first_busno)
+static bool pcie_advk_addr_valid(struct pcie_advk *pcie,
+                                int busno, u8 dev, u8 func)
 {
+       /* On the primary (local) bus there is only one PCI Bridge */
+       if (busno == pcie->first_busno && (dev != 0 || func != 0))
+               return false;
+
        /*
-        * In PCIE-E only a single device (0) can exist
-        * on the local bus. Beyound the local bus, there might be
-        * a Switch and everything is possible.
+        * In PCI-E only a single device (0) can exist on the secondary bus.
+        * Beyond the secondary bus, there might be a Switch and anything is
+        * possible.
         */
-       if ((PCI_BUS(bdf) == first_busno) && (PCI_DEV(bdf) > 0))
-               return 0;
+       if (busno == pcie->sec_busno && dev != 0)
+               return false;
 
-       return 1;
+       return true;
 }
 
 /**
@@ -327,7 +336,7 @@ static int pcie_advk_check_pio_status(struct pcie_advk *pcie,
        else
                str_posted = "Posted";
 
-       dev_err(pcie->dev, "%s PIO Response Status: %s, %#x @ %#x\n",
+       dev_dbg(pcie->dev, "%s PIO Response Status: %s, %#x @ %#x\n",
                str_posted, strcomp_status, reg,
                advk_readl(pcie, PIO_ADDR_LS));
 
@@ -354,32 +363,79 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf,
                                 enum pci_size_t size)
 {
        struct pcie_advk *pcie = dev_get_priv(bus);
+       int busno = PCI_BUS(bdf) - dev_seq(bus);
        int retry_count;
        bool allow_crs;
+       ulong data;
        uint reg;
        int ret;
 
        dev_dbg(pcie->dev, "PCIE CFG read:  (b,d,f)=(%2d,%2d,%2d) ",
                PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
 
-       if (!pcie_advk_addr_valid(bdf, pcie->first_busno)) {
+       if (!pcie_advk_addr_valid(pcie, busno, PCI_DEV(bdf), PCI_FUNC(bdf))) {
                dev_dbg(pcie->dev, "- out of range\n");
                *valuep = pci_get_ff(size);
                return 0;
        }
 
        /*
+        * The configuration space of the PCI Bridge on primary (first) bus is
+        * not accessible via PIO transfers like all other PCIe devices. PCI
+        * Bridge config registers are available directly in Aardvark memory
+        * space starting at offset zero. The PCI Bridge config space is of
+        * Type 0, but the BAR registers (including ROM BAR) don't have the same
+        * meaning as in the PCIe specification. Therefore do not access BAR
+        * registers and non-common registers (those which have different
+        * meaning for Type 0 and Type 1 config space) of the primary PCI Bridge
+        * and instead read their content from driver virtual cfgcache[].
+        */
+       if (busno == pcie->first_busno) {
+               if ((offset >= 0x10 && offset < 0x34) || (offset >= 0x38 && offset < 0x3c))
+                       data = pcie->cfgcache[(offset - 0x10) / 4];
+               else
+                       data = advk_readl(pcie, offset & ~3);
+
+               if ((offset & ~3) == (PCI_HEADER_TYPE & ~3)) {
+                       /*
+                        * Change Header Type of PCI Bridge device to Type 1
+                        * (0x01, used by PCI Bridges) because hardwired value
+                        * is Type 0 (0x00, used by Endpoint devices).
+                        */
+                       data &= ~0x007f0000;
+                       data |= PCI_HEADER_TYPE_BRIDGE << 16;
+               }
+
+               if ((offset & ~3) == PCIE_CORE_PCIEXP_CAP_OFF + PCI_EXP_RTCTL) {
+                       /* CRSSVE bit is stored only in cache */
+                       if (pcie->cfgcrssve)
+                               data |= PCI_EXP_RTCTL_CRSSVE;
+               }
+
+               if ((offset & ~3) == PCIE_CORE_PCIEXP_CAP_OFF +
+                                    (PCI_EXP_RTCAP & ~3)) {
+                       /* CRS is emulated below, so set CRSVIS capability */
+                       data |= PCI_EXP_RTCAP_CRSVIS << 16;
+               }
+
+               *valuep = pci_conv_32_to_size(data, offset, size);
+
+               return 0;
+       }
+
+       /*
         * Returning fabricated CRS value (0xFFFF0001) by PCIe Root Complex to
         * OS is allowed only for 4-byte PCI_VENDOR_ID config read request and
         * only when CRSSVE bit in Root Port PCIe device is enabled. In all
         * other error PCIe Root Complex must return all-ones.
-        * Aardvark HW does not have Root Port PCIe device and U-Boot does not
-        * implement emulation of this device.
+        *
         * U-Boot currently does not support handling of CRS return value for
         * PCI_VENDOR_ID config read request and also does not set CRSSVE bit.
-        * Therefore disable returning CRS response for now.
+        * So it means that pcie->cfgcrssve is false. But the code is prepared
+        * for returning CRS, so that if U-Boot does support CRS in the future,
+        * it will work for Aardvark.
         */
-       allow_crs = false;
+       allow_crs = (offset == PCI_VENDOR_ID) && (size == PCI_SIZE_32) && pcie->cfgcrssve;
 
        if (advk_readl(pcie, PIO_START)) {
                dev_err(pcie->dev,
@@ -395,17 +451,20 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf,
        /* Program the control register */
        reg = advk_readl(pcie, PIO_CTRL);
        reg &= ~PIO_CTRL_TYPE_MASK;
-       if (PCI_BUS(bdf) == pcie->first_busno)
+       if (busno == pcie->sec_busno)
                reg |= PCIE_CONFIG_RD_TYPE0;
        else
                reg |= PCIE_CONFIG_RD_TYPE1;
        advk_writel(pcie, reg, PIO_CTRL);
 
        /* Program the address registers */
-       reg = PCIE_BDF(bdf) | PCIE_CONF_REG(offset);
+       reg = PCIE_ECAM_OFFSET(busno, PCI_DEV(bdf), PCI_FUNC(bdf), (offset & ~0x3));
        advk_writel(pcie, reg, PIO_ADDR_LS);
        advk_writel(pcie, 0, PIO_ADDR_MS);
 
+       /* Program the data strobe */
+       advk_writel(pcie, 0xf, PIO_WR_DATA_STRB);
+
        retry_count = 0;
 
 retry:
@@ -490,7 +549,9 @@ static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf,
                                  enum pci_size_t size)
 {
        struct pcie_advk *pcie = dev_get_priv(bus);
+       int busno = PCI_BUS(bdf) - dev_seq(bus);
        int retry_count;
+       ulong data;
        uint reg;
        int ret;
 
@@ -499,11 +560,47 @@ static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf,
        dev_dbg(pcie->dev, "(addr,size,val)=(0x%04x, %d, 0x%08lx)\n",
                offset, size, value);
 
-       if (!pcie_advk_addr_valid(bdf, pcie->first_busno)) {
+       if (!pcie_advk_addr_valid(pcie, busno, PCI_DEV(bdf), PCI_FUNC(bdf))) {
                dev_dbg(pcie->dev, "- out of range\n");
                return 0;
        }
 
+       /*
+        * As explained in pcie_advk_read_config(), PCI Bridge config registers
+        * are available directly in Aardvark memory space starting at offset
+        * zero. Type 1 specific registers are not available, so we write their
+        * content only into driver virtual cfgcache[].
+        */
+       if (busno == pcie->first_busno) {
+               if ((offset >= 0x10 && offset < 0x34) ||
+                   (offset >= 0x38 && offset < 0x3c)) {
+                       data = pcie->cfgcache[(offset - 0x10) / 4];
+                       data = pci_conv_size_to_32(data, value, offset, size);
+                       /* This PCI bridge does not have configurable bars */
+                       if ((offset & ~3) == PCI_BASE_ADDRESS_0 ||
+                           (offset & ~3) == PCI_BASE_ADDRESS_1 ||
+                           (offset & ~3) == PCI_ROM_ADDRESS1)
+                               data = 0x0;
+                       pcie->cfgcache[(offset - 0x10) / 4] = data;
+               } else {
+                       data = advk_readl(pcie, offset & ~3);
+                       data = pci_conv_size_to_32(data, value, offset, size);
+                       advk_writel(pcie, data, offset & ~3);
+               }
+
+               if (offset == PCI_PRIMARY_BUS)
+                       pcie->first_busno = data & 0xff;
+
+               if (offset == PCI_SECONDARY_BUS ||
+                   (offset == PCI_PRIMARY_BUS && size != PCI_SIZE_8))
+                       pcie->sec_busno = (data >> 8) & 0xff;
+
+               if ((offset & ~3) == PCIE_CORE_PCIEXP_CAP_OFF + PCI_EXP_RTCTL)
+                       pcie->cfgcrssve = data & PCI_EXP_RTCTL_CRSSVE;
+
+               return 0;
+       }
+
        if (advk_readl(pcie, PIO_START)) {
                dev_err(pcie->dev,
                        "Previous PIO read/write transfer is still running\n");
@@ -513,14 +610,14 @@ static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf,
        /* Program the control register */
        reg = advk_readl(pcie, PIO_CTRL);
        reg &= ~PIO_CTRL_TYPE_MASK;
-       if (PCI_BUS(bdf) == pcie->first_busno)
+       if (busno == pcie->sec_busno)
                reg |= PCIE_CONFIG_WR_TYPE0;
        else
                reg |= PCIE_CONFIG_WR_TYPE1;
        advk_writel(pcie, reg, PIO_CTRL);
 
        /* Program the address registers */
-       reg = PCIE_BDF(bdf) | PCIE_CONF_REG(offset);
+       reg = PCIE_ECAM_OFFSET(busno, PCI_DEV(bdf), PCI_FUNC(bdf), (offset & ~0x3));
        advk_writel(pcie, reg, PIO_ADDR_LS);
        advk_writel(pcie, 0, PIO_ADDR_MS);
        dev_dbg(pcie->dev, "\tPIO req. - addr = 0x%08x\n", reg);
@@ -569,7 +666,7 @@ static int pcie_advk_link_up(struct pcie_advk *pcie)
 
        val = advk_readl(pcie, CFG_REG);
        ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK;
-       return ltssm_state >= LTSSM_L0;
+       return ltssm_state >= LTSSM_L0 && ltssm_state < LTSSM_DISABLED;
 }
 
 /**
@@ -589,14 +686,14 @@ static int pcie_advk_wait_for_link(struct pcie_advk *pcie)
        /* check if the link is up or not */
        for (retries = 0; retries < LINK_MAX_RETRIES; retries++) {
                if (pcie_advk_link_up(pcie)) {
-                       printf("PCIE-%d: Link up\n", pcie->first_busno);
+                       printf("PCIe: Link up\n");
                        return 0;
                }
 
                udelay(LINK_WAIT_TIMEOUT);
        }
 
-       printf("PCIE-%d: Link down\n", pcie->first_busno);
+       printf("PCIe: Link down\n");
 
        return -ETIMEDOUT;
 }
@@ -715,6 +812,33 @@ static int pcie_advk_setup_hw(struct pcie_advk *pcie)
         */
        advk_writel(pcie, 0x11ab11ab, VENDOR_ID_REG);
 
+       /*
+        * Change Class Code of PCI Bridge device to PCI Bridge (0x600400),
+        * because default value is Mass Storage Controller (0x010400), causing
+        * U-Boot to fail to recognize it as P2P Bridge.
+        *
+        * Note that this Aardvark PCI Bridge does not have a compliant Type 1
+        * Configuration Space and it even cannot be accessed via Aardvark's
+        * PCI config space access method. Aardvark PCI Bridge Config space is
+        * available in internal Aardvark registers starting at offset 0x0
+        * and has format of Type 0 config space.
+        *
+        * Moreover Type 0 BAR registers (ranges 0x10 - 0x28 and 0x30 - 0x34)
+        * have the same format in Marvell's specification as in PCIe
+        * specification, but their meaning is totally different (and not even
+        * the same meaning as explained in the corresponding comment in the
+        * pci_mvebu driver; aardvark is still different).
+        *
+        * So our driver converts Type 0 config space to Type 1 and reports
+        * Header Type as Type 1. Access to BAR registers and to non-existent
+        * Type 1 registers is redirected to the virtual cfgcache[] buffer,
+        * which avoids changing unrelated registers.
+        */
+       reg = advk_readl(pcie, PCIE_CORE_DEV_REV_REG);
+       reg &= ~0xffffff00;
+       reg |= (PCI_CLASS_BRIDGE_PCI << 8) << 8;
+       advk_writel(pcie, reg, PCIE_CORE_DEV_REV_REG);
+
        /* Set Advanced Error Capabilities and Control PF0 register */
        reg = PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX |
                PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN |
@@ -809,12 +933,6 @@ static int pcie_advk_setup_hw(struct pcie_advk *pcie)
        if (pcie_advk_wait_for_link(pcie))
                return -ENXIO;
 
-       reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
-       reg |= PCIE_CORE_CMD_MEM_ACCESS_EN |
-               PCIE_CORE_CMD_IO_ACCESS_EN |
-               PCIE_CORE_CMD_MEM_IO_REQ_EN;
-       advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG);
-
        return 0;
 }
 
@@ -856,9 +974,14 @@ static int pcie_advk_probe(struct udevice *dev)
                dev_warn(dev, "PCIE Reset on GPIO support is missing\n");
        }
 
-       pcie->first_busno = dev_seq(dev);
        pcie->dev = pci_get_controller(dev);
 
+       /* PCI Bridge support 32-bit I/O and 64-bit prefetch mem addressing */
+       pcie->cfgcache[(PCI_IO_BASE - 0x10) / 4] =
+               PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8);
+       pcie->cfgcache[(PCI_PREF_MEMORY_BASE - 0x10) / 4] =
+               PCI_PREF_RANGE_TYPE_64 | (PCI_PREF_RANGE_TYPE_64 << 16);
+
        return pcie_advk_setup_hw(pcie);
 }