Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * PCIe host controller driver for ST Microelectronics SPEAr13xx SoCs
0004  *
0005  * SPEAr13xx PCIe Glue Layer Source Code
0006  *
0007  * Copyright (C) 2010-2014 ST Microelectronics
0008  * Pratyush Anand <pratyush.anand@gmail.com>
0009  * Mohit Kumar <mohit.kumar.dhaka@gmail.com>
0010  */
0011 
0012 #include <linux/clk.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/kernel.h>
0015 #include <linux/init.h>
0016 #include <linux/of.h>
0017 #include <linux/pci.h>
0018 #include <linux/phy/phy.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/resource.h>
0021 
0022 #include "pcie-designware.h"
0023 
0024 struct spear13xx_pcie {
0025     struct dw_pcie      *pci;
0026     void __iomem        *app_base;
0027     struct phy      *phy;
0028     struct clk      *clk;
0029 };
0030 
0031 struct pcie_app_reg {
0032     u32 app_ctrl_0;     /* cr0 */
0033     u32 app_ctrl_1;     /* cr1 */
0034     u32 app_status_0;       /* cr2 */
0035     u32 app_status_1;       /* cr3 */
0036     u32 msg_status;     /* cr4 */
0037     u32 msg_payload;        /* cr5 */
0038     u32 int_sts;        /* cr6 */
0039     u32 int_clr;        /* cr7 */
0040     u32 int_mask;       /* cr8 */
0041     u32 mst_bmisc;      /* cr9 */
0042     u32 phy_ctrl;       /* cr10 */
0043     u32 phy_status;     /* cr11 */
0044     u32 cxpl_debug_info_0;  /* cr12 */
0045     u32 cxpl_debug_info_1;  /* cr13 */
0046     u32 ven_msg_ctrl_0;     /* cr14 */
0047     u32 ven_msg_ctrl_1;     /* cr15 */
0048     u32 ven_msg_data_0;     /* cr16 */
0049     u32 ven_msg_data_1;     /* cr17 */
0050     u32 ven_msi_0;      /* cr18 */
0051     u32 ven_msi_1;      /* cr19 */
0052     u32 mst_rmisc;      /* cr20 */
0053 };
0054 
0055 /* CR0 ID */
0056 #define APP_LTSSM_ENABLE_ID         3
0057 #define DEVICE_TYPE_RC              (4 << 25)
0058 #define MISCTRL_EN_ID               30
0059 #define REG_TRANSLATION_ENABLE          31
0060 
0061 /* CR3 ID */
0062 #define XMLH_LINK_UP                (1 << 6)
0063 
0064 /* CR6 */
0065 #define MSI_CTRL_INT                (1 << 26)
0066 
0067 #define to_spear13xx_pcie(x)    dev_get_drvdata((x)->dev)
0068 
0069 static int spear13xx_pcie_start_link(struct dw_pcie *pci)
0070 {
0071     struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
0072     struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base;
0073 
0074     /* enable ltssm */
0075     writel(DEVICE_TYPE_RC | (1 << MISCTRL_EN_ID)
0076             | (1 << APP_LTSSM_ENABLE_ID)
0077             | ((u32)1 << REG_TRANSLATION_ENABLE),
0078             &app_reg->app_ctrl_0);
0079 
0080     return 0;
0081 }
0082 
0083 static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg)
0084 {
0085     struct spear13xx_pcie *spear13xx_pcie = arg;
0086     struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base;
0087     struct dw_pcie *pci = spear13xx_pcie->pci;
0088     struct dw_pcie_rp *pp = &pci->pp;
0089     unsigned int status;
0090 
0091     status = readl(&app_reg->int_sts);
0092 
0093     if (status & MSI_CTRL_INT) {
0094         BUG_ON(!IS_ENABLED(CONFIG_PCI_MSI));
0095         dw_handle_msi_irq(pp);
0096     }
0097 
0098     writel(status, &app_reg->int_clr);
0099 
0100     return IRQ_HANDLED;
0101 }
0102 
0103 static void spear13xx_pcie_enable_interrupts(struct spear13xx_pcie *spear13xx_pcie)
0104 {
0105     struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base;
0106 
0107     /* Enable MSI interrupt */
0108     if (IS_ENABLED(CONFIG_PCI_MSI))
0109         writel(readl(&app_reg->int_mask) |
0110                 MSI_CTRL_INT, &app_reg->int_mask);
0111 }
0112 
0113 static int spear13xx_pcie_link_up(struct dw_pcie *pci)
0114 {
0115     struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
0116     struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base;
0117 
0118     if (readl(&app_reg->app_status_1) & XMLH_LINK_UP)
0119         return 1;
0120 
0121     return 0;
0122 }
0123 
0124 static int spear13xx_pcie_host_init(struct dw_pcie_rp *pp)
0125 {
0126     struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
0127     struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
0128     u32 exp_cap_off = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
0129     u32 val;
0130 
0131     spear13xx_pcie->app_base = pci->dbi_base + 0x2000;
0132 
0133     /*
0134      * this controller support only 128 bytes read size, however its
0135      * default value in capability register is 512 bytes. So force
0136      * it to 128 here.
0137      */
0138     val = dw_pcie_readw_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL);
0139     val &= ~PCI_EXP_DEVCTL_READRQ;
0140     dw_pcie_writew_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL, val);
0141 
0142     dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, 0x104A);
0143     dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, 0xCD80);
0144 
0145     spear13xx_pcie_enable_interrupts(spear13xx_pcie);
0146 
0147     return 0;
0148 }
0149 
0150 static const struct dw_pcie_host_ops spear13xx_pcie_host_ops = {
0151     .host_init = spear13xx_pcie_host_init,
0152 };
0153 
0154 static int spear13xx_add_pcie_port(struct spear13xx_pcie *spear13xx_pcie,
0155                    struct platform_device *pdev)
0156 {
0157     struct dw_pcie *pci = spear13xx_pcie->pci;
0158     struct dw_pcie_rp *pp = &pci->pp;
0159     struct device *dev = &pdev->dev;
0160     int ret;
0161 
0162     pp->irq = platform_get_irq(pdev, 0);
0163     if (pp->irq < 0)
0164         return pp->irq;
0165 
0166     ret = devm_request_irq(dev, pp->irq, spear13xx_pcie_irq_handler,
0167                    IRQF_SHARED | IRQF_NO_THREAD,
0168                    "spear1340-pcie", spear13xx_pcie);
0169     if (ret) {
0170         dev_err(dev, "failed to request irq %d\n", pp->irq);
0171         return ret;
0172     }
0173 
0174     pp->ops = &spear13xx_pcie_host_ops;
0175     pp->msi_irq[0] = -ENODEV;
0176 
0177     ret = dw_pcie_host_init(pp);
0178     if (ret) {
0179         dev_err(dev, "failed to initialize host\n");
0180         return ret;
0181     }
0182 
0183     return 0;
0184 }
0185 
0186 static const struct dw_pcie_ops dw_pcie_ops = {
0187     .link_up = spear13xx_pcie_link_up,
0188     .start_link = spear13xx_pcie_start_link,
0189 };
0190 
0191 static int spear13xx_pcie_probe(struct platform_device *pdev)
0192 {
0193     struct device *dev = &pdev->dev;
0194     struct dw_pcie *pci;
0195     struct spear13xx_pcie *spear13xx_pcie;
0196     struct device_node *np = dev->of_node;
0197     int ret;
0198 
0199     spear13xx_pcie = devm_kzalloc(dev, sizeof(*spear13xx_pcie), GFP_KERNEL);
0200     if (!spear13xx_pcie)
0201         return -ENOMEM;
0202 
0203     pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
0204     if (!pci)
0205         return -ENOMEM;
0206 
0207     pci->dev = dev;
0208     pci->ops = &dw_pcie_ops;
0209 
0210     spear13xx_pcie->pci = pci;
0211 
0212     spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy");
0213     if (IS_ERR(spear13xx_pcie->phy)) {
0214         ret = PTR_ERR(spear13xx_pcie->phy);
0215         if (ret == -EPROBE_DEFER)
0216             dev_info(dev, "probe deferred\n");
0217         else
0218             dev_err(dev, "couldn't get pcie-phy\n");
0219         return ret;
0220     }
0221 
0222     phy_init(spear13xx_pcie->phy);
0223 
0224     spear13xx_pcie->clk = devm_clk_get(dev, NULL);
0225     if (IS_ERR(spear13xx_pcie->clk)) {
0226         dev_err(dev, "couldn't get clk for pcie\n");
0227         return PTR_ERR(spear13xx_pcie->clk);
0228     }
0229     ret = clk_prepare_enable(spear13xx_pcie->clk);
0230     if (ret) {
0231         dev_err(dev, "couldn't enable clk for pcie\n");
0232         return ret;
0233     }
0234 
0235     if (of_property_read_bool(np, "st,pcie-is-gen1"))
0236         pci->link_gen = 1;
0237 
0238     platform_set_drvdata(pdev, spear13xx_pcie);
0239 
0240     ret = spear13xx_add_pcie_port(spear13xx_pcie, pdev);
0241     if (ret < 0)
0242         goto fail_clk;
0243 
0244     return 0;
0245 
0246 fail_clk:
0247     clk_disable_unprepare(spear13xx_pcie->clk);
0248 
0249     return ret;
0250 }
0251 
0252 static const struct of_device_id spear13xx_pcie_of_match[] = {
0253     { .compatible = "st,spear1340-pcie", },
0254     {},
0255 };
0256 
0257 static struct platform_driver spear13xx_pcie_driver = {
0258     .probe      = spear13xx_pcie_probe,
0259     .driver = {
0260         .name   = "spear-pcie",
0261         .of_match_table = spear13xx_pcie_of_match,
0262         .suppress_bind_attrs = true,
0263     },
0264 };
0265 
0266 builtin_platform_driver(spear13xx_pcie_driver);