Merge tag 'v2022.01-rc4' into next
[platform/kernel/u-boot.git] / drivers / pci / pci-aardvark.c
index 591bc8b..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>
  *
  */
 
 #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(b, d, f)                      (PCI_BDF(b, d, f) << 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).
- * @sec_busno:   sec_busno stores the bus number for the device behind
- *               the PCIe root-port
- * @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;
-       int            sec_busno;
-       struct udevice *dev;
-       struct gpio_desc reset_gpio;
-       u32            cfgcache[0x34 - 0x10];
-       bool           cfgcrssve;
+       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)
@@ -388,20 +380,19 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf,
        }
 
        /*
-        * The configuration space of the PCI Bridge on primary (local) bus is
+        * 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. Moreover PCI Bridge registers in the
-        * range 0x10 - 0x34 are not available and register 0x38 (Expansion ROM
-        * Base Address) is at offset 0x30.
-        * We therefore read configuration space content of the primary PCI
-        * Bridge from our virtual cache.
+        * 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)
+               if ((offset >= 0x10 && offset < 0x34) || (offset >= 0x38 && offset < 0x3c))
                        data = pcie->cfgcache[(offset - 0x10) / 4];
-               else if ((offset & ~3) == PCI_ROM_ADDRESS1)
-                       data = advk_readl(pcie, PCIE_CORE_EXP_ROM_BAR_REG);
                else
                        data = advk_readl(pcie, offset & ~3);
 
@@ -444,7 +435,7 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf,
         * for returning CRS, so that if U-Boot does support CRS in the future,
         * it will work for Aardvark.
         */
-       allow_crs = pcie->cfgcrssve;
+       allow_crs = (offset == PCI_VENDOR_ID) && (size == PCI_SIZE_32) && pcie->cfgcrssve;
 
        if (advk_readl(pcie, PIO_START)) {
                dev_err(pcie->dev,
@@ -467,10 +458,13 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf,
        advk_writel(pcie, reg, PIO_CTRL);
 
        /* Program the address registers */
-       reg = PCIE_BDF(busno, PCI_DEV(bdf), PCI_FUNC(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:
@@ -572,19 +566,22 @@ static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf,
        }
 
        /*
-        * As explained in pcie_advk_read_config(), for the configuration
-        * space of the primary PCI Bridge, we write the content into virtual
-        * cache.
+        * 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) {
+               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 if ((offset & ~3) == PCI_ROM_ADDRESS1) {
-                       data = advk_readl(pcie, PCIE_CORE_EXP_ROM_BAR_REG);
-                       data = pci_conv_size_to_32(data, value, offset, size);
-                       advk_writel(pcie, data, PCIE_CORE_EXP_ROM_BAR_REG);
                } else {
                        data = advk_readl(pcie, offset & ~3);
                        data = pci_conv_size_to_32(data, value, offset, size);
@@ -620,7 +617,7 @@ static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf,
        advk_writel(pcie, reg, PIO_CTRL);
 
        /* Program the address registers */
-       reg = PCIE_BDF(busno, PCI_DEV(bdf), PCI_FUNC(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);
@@ -822,12 +819,20 @@ static int pcie_advk_setup_hw(struct pcie_advk *pcie)
         *
         * 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. Something like config space is
+        * PCI config space access method. Aardvark PCI Bridge Config space is
         * available in internal Aardvark registers starting at offset 0x0
-        * and is reported as Type 0. In range 0x10 - 0x34 it has totally
-        * different registers. So our driver reports Header Type as Type 1 and
-        * for the above mentioned range redirects access to the virtual
-        * cfgcache[] buffer, which avoids changing internal Aardvark registers.
+        * 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;