Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * PCIe endpoint controller driver for UniPhier SoCs
0004  * Copyright 2018 Socionext Inc.
0005  * Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
0006  */
0007 
0008 #include <linux/bitops.h>
0009 #include <linux/bitfield.h>
0010 #include <linux/clk.h>
0011 #include <linux/delay.h>
0012 #include <linux/init.h>
0013 #include <linux/iopoll.h>
0014 #include <linux/of_device.h>
0015 #include <linux/pci.h>
0016 #include <linux/phy/phy.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/reset.h>
0019 
0020 #include "pcie-designware.h"
0021 
0022 /* Link Glue registers */
0023 #define PCL_RSTCTRL0            0x0010
0024 #define PCL_RSTCTRL_AXI_REG     BIT(3)
0025 #define PCL_RSTCTRL_AXI_SLAVE       BIT(2)
0026 #define PCL_RSTCTRL_AXI_MASTER      BIT(1)
0027 #define PCL_RSTCTRL_PIPE3       BIT(0)
0028 
0029 #define PCL_RSTCTRL1            0x0020
0030 #define PCL_RSTCTRL_PERST       BIT(0)
0031 
0032 #define PCL_RSTCTRL2            0x0024
0033 #define PCL_RSTCTRL_PHY_RESET       BIT(0)
0034 
0035 #define PCL_PINCTRL0            0x002c
0036 #define PCL_PERST_PLDN_REGEN        BIT(12)
0037 #define PCL_PERST_NOE_REGEN     BIT(11)
0038 #define PCL_PERST_OUT_REGEN     BIT(8)
0039 #define PCL_PERST_PLDN_REGVAL       BIT(4)
0040 #define PCL_PERST_NOE_REGVAL        BIT(3)
0041 #define PCL_PERST_OUT_REGVAL        BIT(0)
0042 
0043 #define PCL_PIPEMON         0x0044
0044 #define PCL_PCLK_ALIVE          BIT(15)
0045 
0046 #define PCL_MODE            0x8000
0047 #define PCL_MODE_REGEN          BIT(8)
0048 #define PCL_MODE_REGVAL         BIT(0)
0049 
0050 #define PCL_APP_CLK_CTRL        0x8004
0051 #define PCL_APP_CLK_REQ         BIT(0)
0052 
0053 #define PCL_APP_READY_CTRL      0x8008
0054 #define PCL_APP_LTSSM_ENABLE        BIT(0)
0055 
0056 #define PCL_APP_MSI0            0x8040
0057 #define PCL_APP_VEN_MSI_TC_MASK     GENMASK(10, 8)
0058 #define PCL_APP_VEN_MSI_VECTOR_MASK GENMASK(4, 0)
0059 
0060 #define PCL_APP_MSI1            0x8044
0061 #define PCL_APP_MSI_REQ         BIT(0)
0062 
0063 #define PCL_APP_INTX            0x8074
0064 #define PCL_APP_INTX_SYS_INT        BIT(0)
0065 
0066 #define PCL_APP_PM0         0x8078
0067 #define PCL_SYS_AUX_PWR_DET     BIT(8)
0068 
0069 /* assertion time of INTx in usec */
0070 #define PCL_INTX_WIDTH_USEC     30
0071 
0072 struct uniphier_pcie_ep_priv {
0073     void __iomem *base;
0074     struct dw_pcie pci;
0075     struct clk *clk, *clk_gio;
0076     struct reset_control *rst, *rst_gio;
0077     struct phy *phy;
0078     const struct uniphier_pcie_ep_soc_data *data;
0079 };
0080 
0081 struct uniphier_pcie_ep_soc_data {
0082     bool has_gio;
0083     void (*init)(struct uniphier_pcie_ep_priv *priv);
0084     int (*wait)(struct uniphier_pcie_ep_priv *priv);
0085     const struct pci_epc_features features;
0086 };
0087 
0088 #define to_uniphier_pcie(x) dev_get_drvdata((x)->dev)
0089 
0090 static void uniphier_pcie_ltssm_enable(struct uniphier_pcie_ep_priv *priv,
0091                        bool enable)
0092 {
0093     u32 val;
0094 
0095     val = readl(priv->base + PCL_APP_READY_CTRL);
0096     if (enable)
0097         val |= PCL_APP_LTSSM_ENABLE;
0098     else
0099         val &= ~PCL_APP_LTSSM_ENABLE;
0100     writel(val, priv->base + PCL_APP_READY_CTRL);
0101 }
0102 
0103 static void uniphier_pcie_phy_reset(struct uniphier_pcie_ep_priv *priv,
0104                     bool assert)
0105 {
0106     u32 val;
0107 
0108     val = readl(priv->base + PCL_RSTCTRL2);
0109     if (assert)
0110         val |= PCL_RSTCTRL_PHY_RESET;
0111     else
0112         val &= ~PCL_RSTCTRL_PHY_RESET;
0113     writel(val, priv->base + PCL_RSTCTRL2);
0114 }
0115 
0116 static void uniphier_pcie_pro5_init_ep(struct uniphier_pcie_ep_priv *priv)
0117 {
0118     u32 val;
0119 
0120     /* set EP mode */
0121     val = readl(priv->base + PCL_MODE);
0122     val |= PCL_MODE_REGEN | PCL_MODE_REGVAL;
0123     writel(val, priv->base + PCL_MODE);
0124 
0125     /* clock request */
0126     val = readl(priv->base + PCL_APP_CLK_CTRL);
0127     val &= ~PCL_APP_CLK_REQ;
0128     writel(val, priv->base + PCL_APP_CLK_CTRL);
0129 
0130     /* deassert PIPE3 and AXI reset */
0131     val = readl(priv->base + PCL_RSTCTRL0);
0132     val |= PCL_RSTCTRL_AXI_REG | PCL_RSTCTRL_AXI_SLAVE
0133         | PCL_RSTCTRL_AXI_MASTER | PCL_RSTCTRL_PIPE3;
0134     writel(val, priv->base + PCL_RSTCTRL0);
0135 
0136     uniphier_pcie_ltssm_enable(priv, false);
0137 
0138     msleep(100);
0139 }
0140 
0141 static void uniphier_pcie_nx1_init_ep(struct uniphier_pcie_ep_priv *priv)
0142 {
0143     u32 val;
0144 
0145     /* set EP mode */
0146     val = readl(priv->base + PCL_MODE);
0147     val |= PCL_MODE_REGEN | PCL_MODE_REGVAL;
0148     writel(val, priv->base + PCL_MODE);
0149 
0150     /* use auxiliary power detection */
0151     val = readl(priv->base + PCL_APP_PM0);
0152     val |= PCL_SYS_AUX_PWR_DET;
0153     writel(val, priv->base + PCL_APP_PM0);
0154 
0155     /* assert PERST# */
0156     val = readl(priv->base + PCL_PINCTRL0);
0157     val &= ~(PCL_PERST_NOE_REGVAL | PCL_PERST_OUT_REGVAL
0158          | PCL_PERST_PLDN_REGVAL);
0159     val |= PCL_PERST_NOE_REGEN | PCL_PERST_OUT_REGEN
0160         | PCL_PERST_PLDN_REGEN;
0161     writel(val, priv->base + PCL_PINCTRL0);
0162 
0163     uniphier_pcie_ltssm_enable(priv, false);
0164 
0165     usleep_range(100000, 200000);
0166 
0167     /* deassert PERST# */
0168     val = readl(priv->base + PCL_PINCTRL0);
0169     val |= PCL_PERST_OUT_REGVAL | PCL_PERST_OUT_REGEN;
0170     writel(val, priv->base + PCL_PINCTRL0);
0171 }
0172 
0173 static int uniphier_pcie_nx1_wait_ep(struct uniphier_pcie_ep_priv *priv)
0174 {
0175     u32 status;
0176     int ret;
0177 
0178     /* wait PIPE clock */
0179     ret = readl_poll_timeout(priv->base + PCL_PIPEMON, status,
0180                  status & PCL_PCLK_ALIVE, 100000, 1000000);
0181     if (ret) {
0182         dev_err(priv->pci.dev,
0183             "Failed to initialize controller in EP mode\n");
0184         return ret;
0185     }
0186 
0187     return 0;
0188 }
0189 
0190 static int uniphier_pcie_start_link(struct dw_pcie *pci)
0191 {
0192     struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci);
0193 
0194     uniphier_pcie_ltssm_enable(priv, true);
0195 
0196     return 0;
0197 }
0198 
0199 static void uniphier_pcie_stop_link(struct dw_pcie *pci)
0200 {
0201     struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci);
0202 
0203     uniphier_pcie_ltssm_enable(priv, false);
0204 }
0205 
0206 static void uniphier_pcie_ep_init(struct dw_pcie_ep *ep)
0207 {
0208     struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
0209     enum pci_barno bar;
0210 
0211     for (bar = BAR_0; bar <= BAR_5; bar++)
0212         dw_pcie_ep_reset_bar(pci, bar);
0213 }
0214 
0215 static int uniphier_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep)
0216 {
0217     struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
0218     struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci);
0219     u32 val;
0220 
0221     /*
0222      * This makes pulse signal to send INTx to the RC, so this should
0223      * be cleared as soon as possible. This sequence is covered with
0224      * mutex in pci_epc_raise_irq().
0225      */
0226     /* assert INTx */
0227     val = readl(priv->base + PCL_APP_INTX);
0228     val |= PCL_APP_INTX_SYS_INT;
0229     writel(val, priv->base + PCL_APP_INTX);
0230 
0231     udelay(PCL_INTX_WIDTH_USEC);
0232 
0233     /* deassert INTx */
0234     val &= ~PCL_APP_INTX_SYS_INT;
0235     writel(val, priv->base + PCL_APP_INTX);
0236 
0237     return 0;
0238 }
0239 
0240 static int uniphier_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep,
0241                       u8 func_no, u16 interrupt_num)
0242 {
0243     struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
0244     struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci);
0245     u32 val;
0246 
0247     val = FIELD_PREP(PCL_APP_VEN_MSI_TC_MASK, func_no)
0248         | FIELD_PREP(PCL_APP_VEN_MSI_VECTOR_MASK, interrupt_num - 1);
0249     writel(val, priv->base + PCL_APP_MSI0);
0250 
0251     val = readl(priv->base + PCL_APP_MSI1);
0252     val |= PCL_APP_MSI_REQ;
0253     writel(val, priv->base + PCL_APP_MSI1);
0254 
0255     return 0;
0256 }
0257 
0258 static int uniphier_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
0259                       enum pci_epc_irq_type type,
0260                       u16 interrupt_num)
0261 {
0262     struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
0263 
0264     switch (type) {
0265     case PCI_EPC_IRQ_LEGACY:
0266         return uniphier_pcie_ep_raise_legacy_irq(ep);
0267     case PCI_EPC_IRQ_MSI:
0268         return uniphier_pcie_ep_raise_msi_irq(ep, func_no,
0269                               interrupt_num);
0270     default:
0271         dev_err(pci->dev, "UNKNOWN IRQ type (%d)\n", type);
0272     }
0273 
0274     return 0;
0275 }
0276 
0277 static const struct pci_epc_features*
0278 uniphier_pcie_get_features(struct dw_pcie_ep *ep)
0279 {
0280     struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
0281     struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci);
0282 
0283     return &priv->data->features;
0284 }
0285 
0286 static const struct dw_pcie_ep_ops uniphier_pcie_ep_ops = {
0287     .ep_init = uniphier_pcie_ep_init,
0288     .raise_irq = uniphier_pcie_ep_raise_irq,
0289     .get_features = uniphier_pcie_get_features,
0290 };
0291 
0292 static int uniphier_pcie_ep_enable(struct uniphier_pcie_ep_priv *priv)
0293 {
0294     int ret;
0295 
0296     ret = clk_prepare_enable(priv->clk);
0297     if (ret)
0298         return ret;
0299 
0300     ret = clk_prepare_enable(priv->clk_gio);
0301     if (ret)
0302         goto out_clk_disable;
0303 
0304     ret = reset_control_deassert(priv->rst);
0305     if (ret)
0306         goto out_clk_gio_disable;
0307 
0308     ret = reset_control_deassert(priv->rst_gio);
0309     if (ret)
0310         goto out_rst_assert;
0311 
0312     if (priv->data->init)
0313         priv->data->init(priv);
0314 
0315     uniphier_pcie_phy_reset(priv, true);
0316 
0317     ret = phy_init(priv->phy);
0318     if (ret)
0319         goto out_rst_gio_assert;
0320 
0321     uniphier_pcie_phy_reset(priv, false);
0322 
0323     if (priv->data->wait) {
0324         ret = priv->data->wait(priv);
0325         if (ret)
0326             goto out_phy_exit;
0327     }
0328 
0329     return 0;
0330 
0331 out_phy_exit:
0332     phy_exit(priv->phy);
0333 out_rst_gio_assert:
0334     reset_control_assert(priv->rst_gio);
0335 out_rst_assert:
0336     reset_control_assert(priv->rst);
0337 out_clk_gio_disable:
0338     clk_disable_unprepare(priv->clk_gio);
0339 out_clk_disable:
0340     clk_disable_unprepare(priv->clk);
0341 
0342     return ret;
0343 }
0344 
0345 static const struct dw_pcie_ops dw_pcie_ops = {
0346     .start_link = uniphier_pcie_start_link,
0347     .stop_link = uniphier_pcie_stop_link,
0348 };
0349 
0350 static int uniphier_pcie_ep_probe(struct platform_device *pdev)
0351 {
0352     struct device *dev = &pdev->dev;
0353     struct uniphier_pcie_ep_priv *priv;
0354     int ret;
0355 
0356     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0357     if (!priv)
0358         return -ENOMEM;
0359 
0360     priv->data = of_device_get_match_data(dev);
0361     if (WARN_ON(!priv->data))
0362         return -EINVAL;
0363 
0364     priv->pci.dev = dev;
0365     priv->pci.ops = &dw_pcie_ops;
0366 
0367     priv->base = devm_platform_ioremap_resource_byname(pdev, "link");
0368     if (IS_ERR(priv->base))
0369         return PTR_ERR(priv->base);
0370 
0371     if (priv->data->has_gio) {
0372         priv->clk_gio = devm_clk_get(dev, "gio");
0373         if (IS_ERR(priv->clk_gio))
0374             return PTR_ERR(priv->clk_gio);
0375 
0376         priv->rst_gio = devm_reset_control_get_shared(dev, "gio");
0377         if (IS_ERR(priv->rst_gio))
0378             return PTR_ERR(priv->rst_gio);
0379     }
0380 
0381     priv->clk = devm_clk_get(dev, "link");
0382     if (IS_ERR(priv->clk))
0383         return PTR_ERR(priv->clk);
0384 
0385     priv->rst = devm_reset_control_get_shared(dev, "link");
0386     if (IS_ERR(priv->rst))
0387         return PTR_ERR(priv->rst);
0388 
0389     priv->phy = devm_phy_optional_get(dev, "pcie-phy");
0390     if (IS_ERR(priv->phy)) {
0391         ret = PTR_ERR(priv->phy);
0392         dev_err(dev, "Failed to get phy (%d)\n", ret);
0393         return ret;
0394     }
0395 
0396     platform_set_drvdata(pdev, priv);
0397 
0398     ret = uniphier_pcie_ep_enable(priv);
0399     if (ret)
0400         return ret;
0401 
0402     priv->pci.ep.ops = &uniphier_pcie_ep_ops;
0403     return dw_pcie_ep_init(&priv->pci.ep);
0404 }
0405 
0406 static const struct uniphier_pcie_ep_soc_data uniphier_pro5_data = {
0407     .has_gio = true,
0408     .init = uniphier_pcie_pro5_init_ep,
0409     .wait = NULL,
0410     .features = {
0411         .linkup_notifier = false,
0412         .msi_capable = true,
0413         .msix_capable = false,
0414         .align = 1 << 16,
0415         .bar_fixed_64bit = BIT(BAR_0) | BIT(BAR_2) | BIT(BAR_4),
0416         .reserved_bar =  BIT(BAR_4),
0417     },
0418 };
0419 
0420 static const struct uniphier_pcie_ep_soc_data uniphier_nx1_data = {
0421     .has_gio = false,
0422     .init = uniphier_pcie_nx1_init_ep,
0423     .wait = uniphier_pcie_nx1_wait_ep,
0424     .features = {
0425         .linkup_notifier = false,
0426         .msi_capable = true,
0427         .msix_capable = false,
0428         .align = 1 << 12,
0429         .bar_fixed_64bit = BIT(BAR_0) | BIT(BAR_2) | BIT(BAR_4),
0430     },
0431 };
0432 
0433 static const struct of_device_id uniphier_pcie_ep_match[] = {
0434     {
0435         .compatible = "socionext,uniphier-pro5-pcie-ep",
0436         .data = &uniphier_pro5_data,
0437     },
0438     {
0439         .compatible = "socionext,uniphier-nx1-pcie-ep",
0440         .data = &uniphier_nx1_data,
0441     },
0442     { /* sentinel */ },
0443 };
0444 
0445 static struct platform_driver uniphier_pcie_ep_driver = {
0446     .probe  = uniphier_pcie_ep_probe,
0447     .driver = {
0448         .name = "uniphier-pcie-ep",
0449         .of_match_table = uniphier_pcie_ep_match,
0450         .suppress_bind_attrs = true,
0451     },
0452 };
0453 builtin_platform_driver(uniphier_pcie_ep_driver);