Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * PCIe host controller driver for Marvell Armada-8K SoCs
0004  *
0005  * Armada-8K PCIe Glue Layer Source Code
0006  *
0007  * Copyright (C) 2016 Marvell Technology Group Ltd.
0008  *
0009  * Author: Yehuda Yitshak <yehuday@marvell.com>
0010  * Author: Shadi Ammouri <shadi@marvell.com>
0011  */
0012 
0013 #include <linux/clk.h>
0014 #include <linux/delay.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/kernel.h>
0017 #include <linux/init.h>
0018 #include <linux/of.h>
0019 #include <linux/pci.h>
0020 #include <linux/phy/phy.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/resource.h>
0023 #include <linux/of_pci.h>
0024 #include <linux/of_irq.h>
0025 
0026 #include "pcie-designware.h"
0027 
0028 #define ARMADA8K_PCIE_MAX_LANES PCIE_LNK_X4
0029 
0030 struct armada8k_pcie {
0031     struct dw_pcie *pci;
0032     struct clk *clk;
0033     struct clk *clk_reg;
0034     struct phy *phy[ARMADA8K_PCIE_MAX_LANES];
0035     unsigned int phy_count;
0036 };
0037 
0038 #define PCIE_VENDOR_REGS_OFFSET     0x8000
0039 
0040 #define PCIE_GLOBAL_CONTROL_REG     (PCIE_VENDOR_REGS_OFFSET + 0x0)
0041 #define PCIE_APP_LTSSM_EN       BIT(2)
0042 #define PCIE_DEVICE_TYPE_SHIFT      4
0043 #define PCIE_DEVICE_TYPE_MASK       0xF
0044 #define PCIE_DEVICE_TYPE_RC     0x4 /* Root complex */
0045 
0046 #define PCIE_GLOBAL_STATUS_REG      (PCIE_VENDOR_REGS_OFFSET + 0x8)
0047 #define PCIE_GLB_STS_RDLH_LINK_UP   BIT(1)
0048 #define PCIE_GLB_STS_PHY_LINK_UP    BIT(9)
0049 
0050 #define PCIE_GLOBAL_INT_CAUSE1_REG  (PCIE_VENDOR_REGS_OFFSET + 0x1C)
0051 #define PCIE_GLOBAL_INT_MASK1_REG   (PCIE_VENDOR_REGS_OFFSET + 0x20)
0052 #define PCIE_INT_A_ASSERT_MASK      BIT(9)
0053 #define PCIE_INT_B_ASSERT_MASK      BIT(10)
0054 #define PCIE_INT_C_ASSERT_MASK      BIT(11)
0055 #define PCIE_INT_D_ASSERT_MASK      BIT(12)
0056 
0057 #define PCIE_ARCACHE_TRC_REG        (PCIE_VENDOR_REGS_OFFSET + 0x50)
0058 #define PCIE_AWCACHE_TRC_REG        (PCIE_VENDOR_REGS_OFFSET + 0x54)
0059 #define PCIE_ARUSER_REG         (PCIE_VENDOR_REGS_OFFSET + 0x5C)
0060 #define PCIE_AWUSER_REG         (PCIE_VENDOR_REGS_OFFSET + 0x60)
0061 /*
0062  * AR/AW Cache defaults: Normal memory, Write-Back, Read / Write
0063  * allocate
0064  */
0065 #define ARCACHE_DEFAULT_VALUE       0x3511
0066 #define AWCACHE_DEFAULT_VALUE       0x5311
0067 
0068 #define DOMAIN_OUTER_SHAREABLE      0x2
0069 #define AX_USER_DOMAIN_MASK     0x3
0070 #define AX_USER_DOMAIN_SHIFT        4
0071 
0072 #define to_armada8k_pcie(x) dev_get_drvdata((x)->dev)
0073 
0074 static void armada8k_pcie_disable_phys(struct armada8k_pcie *pcie)
0075 {
0076     int i;
0077 
0078     for (i = 0; i < ARMADA8K_PCIE_MAX_LANES; i++) {
0079         phy_power_off(pcie->phy[i]);
0080         phy_exit(pcie->phy[i]);
0081     }
0082 }
0083 
0084 static int armada8k_pcie_enable_phys(struct armada8k_pcie *pcie)
0085 {
0086     int ret;
0087     int i;
0088 
0089     for (i = 0; i < ARMADA8K_PCIE_MAX_LANES; i++) {
0090         ret = phy_init(pcie->phy[i]);
0091         if (ret)
0092             return ret;
0093 
0094         ret = phy_set_mode_ext(pcie->phy[i], PHY_MODE_PCIE,
0095                        pcie->phy_count);
0096         if (ret) {
0097             phy_exit(pcie->phy[i]);
0098             return ret;
0099         }
0100 
0101         ret = phy_power_on(pcie->phy[i]);
0102         if (ret) {
0103             phy_exit(pcie->phy[i]);
0104             return ret;
0105         }
0106     }
0107 
0108     return 0;
0109 }
0110 
0111 static int armada8k_pcie_setup_phys(struct armada8k_pcie *pcie)
0112 {
0113     struct dw_pcie *pci = pcie->pci;
0114     struct device *dev = pci->dev;
0115     struct device_node *node = dev->of_node;
0116     int ret = 0;
0117     int i;
0118 
0119     for (i = 0; i < ARMADA8K_PCIE_MAX_LANES; i++) {
0120         pcie->phy[i] = devm_of_phy_get_by_index(dev, node, i);
0121         if (IS_ERR(pcie->phy[i])) {
0122             if (PTR_ERR(pcie->phy[i]) != -ENODEV)
0123                 return PTR_ERR(pcie->phy[i]);
0124 
0125             pcie->phy[i] = NULL;
0126             continue;
0127         }
0128 
0129         pcie->phy_count++;
0130     }
0131 
0132     /* Old bindings miss the PHY handle, so just warn if there is no PHY */
0133     if (!pcie->phy_count)
0134         dev_warn(dev, "No available PHY\n");
0135 
0136     ret = armada8k_pcie_enable_phys(pcie);
0137     if (ret)
0138         dev_err(dev, "Failed to initialize PHY(s) (%d)\n", ret);
0139 
0140     return ret;
0141 }
0142 
0143 static int armada8k_pcie_link_up(struct dw_pcie *pci)
0144 {
0145     u32 reg;
0146     u32 mask = PCIE_GLB_STS_RDLH_LINK_UP | PCIE_GLB_STS_PHY_LINK_UP;
0147 
0148     reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_STATUS_REG);
0149 
0150     if ((reg & mask) == mask)
0151         return 1;
0152 
0153     dev_dbg(pci->dev, "No link detected (Global-Status: 0x%08x).\n", reg);
0154     return 0;
0155 }
0156 
0157 static int armada8k_pcie_start_link(struct dw_pcie *pci)
0158 {
0159     u32 reg;
0160 
0161     /* Start LTSSM */
0162     reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG);
0163     reg |= PCIE_APP_LTSSM_EN;
0164     dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg);
0165 
0166     return 0;
0167 }
0168 
0169 static int armada8k_pcie_host_init(struct dw_pcie_rp *pp)
0170 {
0171     u32 reg;
0172     struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
0173 
0174     if (!dw_pcie_link_up(pci)) {
0175         /* Disable LTSSM state machine to enable configuration */
0176         reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG);
0177         reg &= ~(PCIE_APP_LTSSM_EN);
0178         dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg);
0179     }
0180 
0181     /* Set the device to root complex mode */
0182     reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG);
0183     reg &= ~(PCIE_DEVICE_TYPE_MASK << PCIE_DEVICE_TYPE_SHIFT);
0184     reg |= PCIE_DEVICE_TYPE_RC << PCIE_DEVICE_TYPE_SHIFT;
0185     dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg);
0186 
0187     /* Set the PCIe master AxCache attributes */
0188     dw_pcie_writel_dbi(pci, PCIE_ARCACHE_TRC_REG, ARCACHE_DEFAULT_VALUE);
0189     dw_pcie_writel_dbi(pci, PCIE_AWCACHE_TRC_REG, AWCACHE_DEFAULT_VALUE);
0190 
0191     /* Set the PCIe master AxDomain attributes */
0192     reg = dw_pcie_readl_dbi(pci, PCIE_ARUSER_REG);
0193     reg &= ~(AX_USER_DOMAIN_MASK << AX_USER_DOMAIN_SHIFT);
0194     reg |= DOMAIN_OUTER_SHAREABLE << AX_USER_DOMAIN_SHIFT;
0195     dw_pcie_writel_dbi(pci, PCIE_ARUSER_REG, reg);
0196 
0197     reg = dw_pcie_readl_dbi(pci, PCIE_AWUSER_REG);
0198     reg &= ~(AX_USER_DOMAIN_MASK << AX_USER_DOMAIN_SHIFT);
0199     reg |= DOMAIN_OUTER_SHAREABLE << AX_USER_DOMAIN_SHIFT;
0200     dw_pcie_writel_dbi(pci, PCIE_AWUSER_REG, reg);
0201 
0202     /* Enable INT A-D interrupts */
0203     reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_INT_MASK1_REG);
0204     reg |= PCIE_INT_A_ASSERT_MASK | PCIE_INT_B_ASSERT_MASK |
0205            PCIE_INT_C_ASSERT_MASK | PCIE_INT_D_ASSERT_MASK;
0206     dw_pcie_writel_dbi(pci, PCIE_GLOBAL_INT_MASK1_REG, reg);
0207 
0208     return 0;
0209 }
0210 
0211 static irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg)
0212 {
0213     struct armada8k_pcie *pcie = arg;
0214     struct dw_pcie *pci = pcie->pci;
0215     u32 val;
0216 
0217     /*
0218      * Interrupts are directly handled by the device driver of the
0219      * PCI device. However, they are also latched into the PCIe
0220      * controller, so we simply discard them.
0221      */
0222     val = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_INT_CAUSE1_REG);
0223     dw_pcie_writel_dbi(pci, PCIE_GLOBAL_INT_CAUSE1_REG, val);
0224 
0225     return IRQ_HANDLED;
0226 }
0227 
0228 static const struct dw_pcie_host_ops armada8k_pcie_host_ops = {
0229     .host_init = armada8k_pcie_host_init,
0230 };
0231 
0232 static int armada8k_add_pcie_port(struct armada8k_pcie *pcie,
0233                   struct platform_device *pdev)
0234 {
0235     struct dw_pcie *pci = pcie->pci;
0236     struct dw_pcie_rp *pp = &pci->pp;
0237     struct device *dev = &pdev->dev;
0238     int ret;
0239 
0240     pp->ops = &armada8k_pcie_host_ops;
0241 
0242     pp->irq = platform_get_irq(pdev, 0);
0243     if (pp->irq < 0)
0244         return pp->irq;
0245 
0246     ret = devm_request_irq(dev, pp->irq, armada8k_pcie_irq_handler,
0247                    IRQF_SHARED, "armada8k-pcie", pcie);
0248     if (ret) {
0249         dev_err(dev, "failed to request irq %d\n", pp->irq);
0250         return ret;
0251     }
0252 
0253     ret = dw_pcie_host_init(pp);
0254     if (ret) {
0255         dev_err(dev, "failed to initialize host: %d\n", ret);
0256         return ret;
0257     }
0258 
0259     return 0;
0260 }
0261 
0262 static const struct dw_pcie_ops dw_pcie_ops = {
0263     .link_up = armada8k_pcie_link_up,
0264     .start_link = armada8k_pcie_start_link,
0265 };
0266 
0267 static int armada8k_pcie_probe(struct platform_device *pdev)
0268 {
0269     struct dw_pcie *pci;
0270     struct armada8k_pcie *pcie;
0271     struct device *dev = &pdev->dev;
0272     struct resource *base;
0273     int ret;
0274 
0275     pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
0276     if (!pcie)
0277         return -ENOMEM;
0278 
0279     pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
0280     if (!pci)
0281         return -ENOMEM;
0282 
0283     pci->dev = dev;
0284     pci->ops = &dw_pcie_ops;
0285 
0286     pcie->pci = pci;
0287 
0288     pcie->clk = devm_clk_get(dev, NULL);
0289     if (IS_ERR(pcie->clk))
0290         return PTR_ERR(pcie->clk);
0291 
0292     ret = clk_prepare_enable(pcie->clk);
0293     if (ret)
0294         return ret;
0295 
0296     pcie->clk_reg = devm_clk_get(dev, "reg");
0297     if (pcie->clk_reg == ERR_PTR(-EPROBE_DEFER)) {
0298         ret = -EPROBE_DEFER;
0299         goto fail;
0300     }
0301     if (!IS_ERR(pcie->clk_reg)) {
0302         ret = clk_prepare_enable(pcie->clk_reg);
0303         if (ret)
0304             goto fail_clkreg;
0305     }
0306 
0307     /* Get the dw-pcie unit configuration/control registers base. */
0308     base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
0309     pci->dbi_base = devm_pci_remap_cfg_resource(dev, base);
0310     if (IS_ERR(pci->dbi_base)) {
0311         ret = PTR_ERR(pci->dbi_base);
0312         goto fail_clkreg;
0313     }
0314 
0315     ret = armada8k_pcie_setup_phys(pcie);
0316     if (ret)
0317         goto fail_clkreg;
0318 
0319     platform_set_drvdata(pdev, pcie);
0320 
0321     ret = armada8k_add_pcie_port(pcie, pdev);
0322     if (ret)
0323         goto disable_phy;
0324 
0325     return 0;
0326 
0327 disable_phy:
0328     armada8k_pcie_disable_phys(pcie);
0329 fail_clkreg:
0330     clk_disable_unprepare(pcie->clk_reg);
0331 fail:
0332     clk_disable_unprepare(pcie->clk);
0333 
0334     return ret;
0335 }
0336 
0337 static const struct of_device_id armada8k_pcie_of_match[] = {
0338     { .compatible = "marvell,armada8k-pcie", },
0339     {},
0340 };
0341 
0342 static struct platform_driver armada8k_pcie_driver = {
0343     .probe      = armada8k_pcie_probe,
0344     .driver = {
0345         .name   = "armada8k-pcie",
0346         .of_match_table = armada8k_pcie_of_match,
0347         .suppress_bind_attrs = true,
0348     },
0349 };
0350 builtin_platform_driver(armada8k_pcie_driver);