]> Git Repo - J-u-boot.git/blobdiff - drivers/pci/pcie_apple.c
Merge tag 'v2024.07-rc5' into next
[J-u-boot.git] / drivers / pci / pcie_apple.c
index b934fdbc35c2814d098784c28246bf3364e90e01..6a8e715d4b6e16da07c4623c1fc8a758d4e52795 100644 (file)
@@ -16,7 +16,6 @@
  * Author: Marc Zyngier <[email protected]>
  */
 
-#include <common.h>
 #include <dm.h>
 #include <dm/device_compat.h>
 #include <dm/devres.h>
 #define   CORE_RC_STAT_READY           BIT(0)
 #define CORE_FABRIC_STAT               0x04000
 #define   CORE_FABRIC_STAT_MASK                0x001F001F
-#define CORE_LANE_CFG(port)            (0x84000 + 0x4000 * (port))
-#define   CORE_LANE_CFG_REFCLK0REQ     BIT(0)
-#define   CORE_LANE_CFG_REFCLK1REQ     BIT(1)
-#define   CORE_LANE_CFG_REFCLK0ACK     BIT(2)
-#define   CORE_LANE_CFG_REFCLK1ACK     BIT(3)
-#define   CORE_LANE_CFG_REFCLKEN       (BIT(9) | BIT(10))
-#define CORE_LANE_CTL(port)            (0x84004 + 0x4000 * (port))
-#define   CORE_LANE_CTL_CFGACC         BIT(15)
+
+#define CORE_PHY_DEFAULT_BASE(port)    (0x84000 + 0x4000 * (port))
+
+#define PHY_LANE_CFG                   0x00000
+#define   PHY_LANE_CFG_REFCLK0REQ      BIT(0)
+#define   PHY_LANE_CFG_REFCLK1REQ      BIT(1)
+#define   PHY_LANE_CFG_REFCLK0ACK      BIT(2)
+#define   PHY_LANE_CFG_REFCLK1ACK      BIT(3)
+#define   PHY_LANE_CFG_REFCLKEN                (BIT(9) | BIT(10))
+#define   PHY_LANE_CFG_REFCLKCGEN      (BIT(30) | BIT(31))
+#define PHY_LANE_CTL                   0x00004
+#define   PHY_LANE_CTL_CFGACC          BIT(15)
 
 #define PORT_LTSSMCTL                  0x00080
 #define   PORT_LTSSMCTL_START          BIT(0)
 #define   PORT_TUNSTAT_PERST_ACK_PEND  BIT(1)
 #define PORT_PREFMEM_ENABLE            0x00994
 
+struct reg_info {
+       u32 phy_lane_ctl;
+       u32 port_refclk;
+       u32 port_perst;
+};
+
+const struct reg_info t8103_hw = {
+       .phy_lane_ctl = PHY_LANE_CTL,
+       .port_refclk = PORT_REFCLK,
+       .port_perst = PORT_PERST,
+};
+
+#define PORT_T602X_PERST               0x082c
+
+const struct reg_info t602x_hw = {
+       .phy_lane_ctl = 0,
+       .port_refclk = 0,
+       .port_perst = PORT_T602X_PERST,
+};
+
 struct apple_pcie_priv {
        struct udevice          *dev;
        void __iomem            *base;
        void __iomem            *cfg_base;
        struct list_head        ports;
+       const struct reg_info   *hw;
 };
 
 struct apple_pcie_port {
@@ -128,6 +152,7 @@ struct apple_pcie_port {
        struct gpio_desc        reset;
        ofnode                  np;
        void __iomem            *base;
+       void __iomem            *phy;
        struct list_head        entry;
        int                     idx;
 };
@@ -187,33 +212,32 @@ static int apple_pcie_setup_refclk(struct apple_pcie_priv *pcie,
        u32 stat;
        int res;
 
-       res = readl_poll_sleep_timeout(pcie->base + CORE_RC_PHYIF_STAT, stat,
-                                      stat & CORE_RC_PHYIF_STAT_REFCLK,
-                                      100, 50000);
-       if (res < 0)
-               return res;
+       if (pcie->hw->phy_lane_ctl)
+               rmw_set(PHY_LANE_CTL_CFGACC, port->phy + pcie->hw->phy_lane_ctl);
 
-       rmw_set(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx));
-       rmw_set(CORE_LANE_CFG_REFCLK0REQ, pcie->base + CORE_LANE_CFG(port->idx));
+       rmw_set(PHY_LANE_CFG_REFCLK0REQ, port->phy + PHY_LANE_CFG);
 
-       res = readl_poll_sleep_timeout(pcie->base + CORE_LANE_CFG(port->idx),
-                                      stat, stat & CORE_LANE_CFG_REFCLK0ACK,
+       res = readl_poll_sleep_timeout(port->phy + PHY_LANE_CFG,
+                                      stat, stat & PHY_LANE_CFG_REFCLK0ACK,
                                       100, 50000);
        if (res < 0)
                return res;
 
-       rmw_set(CORE_LANE_CFG_REFCLK1REQ, pcie->base + CORE_LANE_CFG(port->idx));
-       res = readl_poll_sleep_timeout(pcie->base + CORE_LANE_CFG(port->idx),
-                                      stat, stat & CORE_LANE_CFG_REFCLK1ACK,
+       rmw_set(PHY_LANE_CFG_REFCLK1REQ, port->phy + PHY_LANE_CFG);
+       res = readl_poll_sleep_timeout(port->phy + PHY_LANE_CFG,
+                                      stat, stat & PHY_LANE_CFG_REFCLK1ACK,
                                       100, 50000);
 
        if (res < 0)
                return res;
 
-       rmw_clear(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx));
+       if (pcie->hw->phy_lane_ctl)
+               rmw_clear(PHY_LANE_CTL_CFGACC, port->phy + pcie->hw->phy_lane_ctl);
+
+       rmw_set(PHY_LANE_CFG_REFCLKEN, port->phy + PHY_LANE_CFG);
 
-       rmw_set(CORE_LANE_CFG_REFCLKEN, pcie->base + CORE_LANE_CFG(port->idx));
-       rmw_set(PORT_REFCLK_EN, port->base + PORT_REFCLK);
+       if (pcie->hw->port_refclk)
+               rmw_set(PORT_REFCLK_EN, port->base + pcie->hw->port_refclk);
 
        return 0;
 }
@@ -225,6 +249,7 @@ static int apple_pcie_setup_port(struct apple_pcie_priv *pcie, ofnode np)
        fdt_addr_t addr;
        u32 stat, idx;
        int ret;
+       char name[16];
 
        ret = gpio_request_by_name_nodev(np, "reset-gpios", 0, &reset, 0);
        if (ret)
@@ -244,11 +269,21 @@ static int apple_pcie_setup_port(struct apple_pcie_priv *pcie, ofnode np)
        port->reset = reset;
        port->np = np;
 
-       addr = dev_read_addr_index(pcie->dev, port->idx + 2);
+       snprintf(name, sizeof(name), "port%d", port->idx);
+       addr = dev_read_addr_name(pcie->dev, name);
+       if (addr == FDT_ADDR_T_NONE)
+               addr = dev_read_addr_index(pcie->dev, port->idx + 2);
        if (addr == FDT_ADDR_T_NONE)
                return -EINVAL;
        port->base = map_sysmem(addr, 0);
 
+       snprintf(name, sizeof(name), "phy%d", port->idx);
+       addr = dev_read_addr_name(pcie->dev, name);
+       if (addr == FDT_ADDR_T_NONE)
+               port->phy = pcie->base + CORE_PHY_DEFAULT_BASE(port->idx);
+       else
+               port->phy = map_sysmem(addr, 0);
+
        rmw_set(PORT_APPCLK_EN, port->base + PORT_APPCLK);
 
        /* Assert PERST# before setting up the clock */
@@ -262,7 +297,7 @@ static int apple_pcie_setup_port(struct apple_pcie_priv *pcie, ofnode np)
        udelay(100);
 
        /* Deassert PERST# */
-       rmw_set(PORT_PERST_OFF, port->base + PORT_PERST);
+       rmw_set(PORT_PERST_OFF, port->base + pcie->hw->port_perst);
        dm_gpio_set_value(&reset, 0);
 
        /* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */
@@ -275,9 +310,6 @@ static int apple_pcie_setup_port(struct apple_pcie_priv *pcie, ofnode np)
                return ret;
        }
 
-       rmw_clear(PORT_REFCLK_CGDIS, port->base + PORT_REFCLK);
-       rmw_clear(PORT_APPCLK_CGDIS, port->base + PORT_APPCLK);
-
        list_add_tail(&port->entry, &pcie->ports);
 
        writel_relaxed(PORT_LTSSMCTL_START, port->base + PORT_LTSSMCTL);
@@ -289,6 +321,12 @@ static int apple_pcie_setup_port(struct apple_pcie_priv *pcie, ofnode np)
        readl_poll_sleep_timeout(port->base + PORT_LINKSTS, stat,
                                 (stat & PORT_LINKSTS_UP), 100, 100000);
 
+       if (pcie->hw->port_refclk)
+               rmw_clear(PORT_REFCLK_CGDIS, port->base + PORT_REFCLK);
+       else
+               rmw_set(PHY_LANE_CFG_REFCLKCGEN, port->phy + PHY_LANE_CFG);
+       rmw_clear(PORT_APPCLK_CGDIS, port->base + PORT_APPCLK);
+
        return 0;
 }
 
@@ -299,6 +337,8 @@ static int apple_pcie_probe(struct udevice *dev)
        ofnode of_port;
        int i, ret;
 
+       pcie->hw = (struct reg_info *)dev_get_driver_data(dev);
+
        pcie->dev = dev;
        addr = dev_read_addr_index(dev, 0);
        if (addr == FDT_ADDR_T_NONE)
@@ -341,7 +381,8 @@ static int apple_pcie_remove(struct udevice *dev)
 }
 
 static const struct udevice_id apple_pcie_of_match[] = {
-       { .compatible = "apple,pcie" },
+       { .compatible = "apple,t6020-pcie", .data = (ulong)&t602x_hw },
+       { .compatible = "apple,pcie", .data = (ulong)&t8103_hw },
        { /* sentinel */ }
 };
 
This page took 0.02696 seconds and 4 git commands to generate.