root/drivers/pci/controller/dwc/pcie-designware-plat.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dw_plat_pcie_host_init
  2. dw_plat_set_num_vectors
  3. dw_plat_pcie_establish_link
  4. dw_plat_pcie_ep_init
  5. dw_plat_pcie_ep_raise_irq
  6. dw_plat_pcie_get_features
  7. dw_plat_add_pcie_port
  8. dw_plat_add_pcie_ep
  9. dw_plat_pcie_probe

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * PCIe RC driver for Synopsys DesignWare Core
   4  *
   5  * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
   6  *
   7  * Authors: Joao Pinto <Joao.Pinto@synopsys.com>
   8  */
   9 #include <linux/clk.h>
  10 #include <linux/delay.h>
  11 #include <linux/gpio.h>
  12 #include <linux/interrupt.h>
  13 #include <linux/kernel.h>
  14 #include <linux/init.h>
  15 #include <linux/of_device.h>
  16 #include <linux/pci.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/resource.h>
  19 #include <linux/types.h>
  20 #include <linux/regmap.h>
  21 
  22 #include "pcie-designware.h"
  23 
  24 struct dw_plat_pcie {
  25         struct dw_pcie                  *pci;
  26         struct regmap                   *regmap;
  27         enum dw_pcie_device_mode        mode;
  28 };
  29 
  30 struct dw_plat_pcie_of_data {
  31         enum dw_pcie_device_mode        mode;
  32 };
  33 
  34 static const struct of_device_id dw_plat_pcie_of_match[];
  35 
  36 static int dw_plat_pcie_host_init(struct pcie_port *pp)
  37 {
  38         struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
  39 
  40         dw_pcie_setup_rc(pp);
  41         dw_pcie_wait_for_link(pci);
  42 
  43         if (IS_ENABLED(CONFIG_PCI_MSI))
  44                 dw_pcie_msi_init(pp);
  45 
  46         return 0;
  47 }
  48 
  49 static void dw_plat_set_num_vectors(struct pcie_port *pp)
  50 {
  51         pp->num_vectors = MAX_MSI_IRQS;
  52 }
  53 
  54 static const struct dw_pcie_host_ops dw_plat_pcie_host_ops = {
  55         .host_init = dw_plat_pcie_host_init,
  56         .set_num_vectors = dw_plat_set_num_vectors,
  57 };
  58 
  59 static int dw_plat_pcie_establish_link(struct dw_pcie *pci)
  60 {
  61         return 0;
  62 }
  63 
  64 static const struct dw_pcie_ops dw_pcie_ops = {
  65         .start_link = dw_plat_pcie_establish_link,
  66 };
  67 
  68 static void dw_plat_pcie_ep_init(struct dw_pcie_ep *ep)
  69 {
  70         struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
  71         enum pci_barno bar;
  72 
  73         for (bar = BAR_0; bar <= BAR_5; bar++)
  74                 dw_pcie_ep_reset_bar(pci, bar);
  75 }
  76 
  77 static int dw_plat_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
  78                                      enum pci_epc_irq_type type,
  79                                      u16 interrupt_num)
  80 {
  81         struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
  82 
  83         switch (type) {
  84         case PCI_EPC_IRQ_LEGACY:
  85                 return dw_pcie_ep_raise_legacy_irq(ep, func_no);
  86         case PCI_EPC_IRQ_MSI:
  87                 return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);
  88         case PCI_EPC_IRQ_MSIX:
  89                 return dw_pcie_ep_raise_msix_irq(ep, func_no, interrupt_num);
  90         default:
  91                 dev_err(pci->dev, "UNKNOWN IRQ type\n");
  92         }
  93 
  94         return 0;
  95 }
  96 
  97 static const struct pci_epc_features dw_plat_pcie_epc_features = {
  98         .linkup_notifier = false,
  99         .msi_capable = true,
 100         .msix_capable = true,
 101 };
 102 
 103 static const struct pci_epc_features*
 104 dw_plat_pcie_get_features(struct dw_pcie_ep *ep)
 105 {
 106         return &dw_plat_pcie_epc_features;
 107 }
 108 
 109 static const struct dw_pcie_ep_ops pcie_ep_ops = {
 110         .ep_init = dw_plat_pcie_ep_init,
 111         .raise_irq = dw_plat_pcie_ep_raise_irq,
 112         .get_features = dw_plat_pcie_get_features,
 113 };
 114 
 115 static int dw_plat_add_pcie_port(struct dw_plat_pcie *dw_plat_pcie,
 116                                  struct platform_device *pdev)
 117 {
 118         struct dw_pcie *pci = dw_plat_pcie->pci;
 119         struct pcie_port *pp = &pci->pp;
 120         struct device *dev = &pdev->dev;
 121         int ret;
 122 
 123         pp->irq = platform_get_irq(pdev, 1);
 124         if (pp->irq < 0)
 125                 return pp->irq;
 126 
 127         if (IS_ENABLED(CONFIG_PCI_MSI)) {
 128                 pp->msi_irq = platform_get_irq(pdev, 0);
 129                 if (pp->msi_irq < 0)
 130                         return pp->msi_irq;
 131         }
 132 
 133         pp->ops = &dw_plat_pcie_host_ops;
 134 
 135         ret = dw_pcie_host_init(pp);
 136         if (ret) {
 137                 dev_err(dev, "Failed to initialize host\n");
 138                 return ret;
 139         }
 140 
 141         return 0;
 142 }
 143 
 144 static int dw_plat_add_pcie_ep(struct dw_plat_pcie *dw_plat_pcie,
 145                                struct platform_device *pdev)
 146 {
 147         int ret;
 148         struct dw_pcie_ep *ep;
 149         struct resource *res;
 150         struct device *dev = &pdev->dev;
 151         struct dw_pcie *pci = dw_plat_pcie->pci;
 152 
 153         ep = &pci->ep;
 154         ep->ops = &pcie_ep_ops;
 155 
 156         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi2");
 157         pci->dbi_base2 = devm_ioremap_resource(dev, res);
 158         if (IS_ERR(pci->dbi_base2))
 159                 return PTR_ERR(pci->dbi_base2);
 160 
 161         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
 162         if (!res)
 163                 return -EINVAL;
 164 
 165         ep->phys_base = res->start;
 166         ep->addr_size = resource_size(res);
 167 
 168         ret = dw_pcie_ep_init(ep);
 169         if (ret) {
 170                 dev_err(dev, "Failed to initialize endpoint\n");
 171                 return ret;
 172         }
 173         return 0;
 174 }
 175 
 176 static int dw_plat_pcie_probe(struct platform_device *pdev)
 177 {
 178         struct device *dev = &pdev->dev;
 179         struct dw_plat_pcie *dw_plat_pcie;
 180         struct dw_pcie *pci;
 181         struct resource *res;  /* Resource from DT */
 182         int ret;
 183         const struct of_device_id *match;
 184         const struct dw_plat_pcie_of_data *data;
 185         enum dw_pcie_device_mode mode;
 186 
 187         match = of_match_device(dw_plat_pcie_of_match, dev);
 188         if (!match)
 189                 return -EINVAL;
 190 
 191         data = (struct dw_plat_pcie_of_data *)match->data;
 192         mode = (enum dw_pcie_device_mode)data->mode;
 193 
 194         dw_plat_pcie = devm_kzalloc(dev, sizeof(*dw_plat_pcie), GFP_KERNEL);
 195         if (!dw_plat_pcie)
 196                 return -ENOMEM;
 197 
 198         pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
 199         if (!pci)
 200                 return -ENOMEM;
 201 
 202         pci->dev = dev;
 203         pci->ops = &dw_pcie_ops;
 204 
 205         dw_plat_pcie->pci = pci;
 206         dw_plat_pcie->mode = mode;
 207 
 208         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
 209         if (!res)
 210                 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 211 
 212         pci->dbi_base = devm_ioremap_resource(dev, res);
 213         if (IS_ERR(pci->dbi_base))
 214                 return PTR_ERR(pci->dbi_base);
 215 
 216         platform_set_drvdata(pdev, dw_plat_pcie);
 217 
 218         switch (dw_plat_pcie->mode) {
 219         case DW_PCIE_RC_TYPE:
 220                 if (!IS_ENABLED(CONFIG_PCIE_DW_PLAT_HOST))
 221                         return -ENODEV;
 222 
 223                 ret = dw_plat_add_pcie_port(dw_plat_pcie, pdev);
 224                 if (ret < 0)
 225                         return ret;
 226                 break;
 227         case DW_PCIE_EP_TYPE:
 228                 if (!IS_ENABLED(CONFIG_PCIE_DW_PLAT_EP))
 229                         return -ENODEV;
 230 
 231                 ret = dw_plat_add_pcie_ep(dw_plat_pcie, pdev);
 232                 if (ret < 0)
 233                         return ret;
 234                 break;
 235         default:
 236                 dev_err(dev, "INVALID device type %d\n", dw_plat_pcie->mode);
 237         }
 238 
 239         return 0;
 240 }
 241 
 242 static const struct dw_plat_pcie_of_data dw_plat_pcie_rc_of_data = {
 243         .mode = DW_PCIE_RC_TYPE,
 244 };
 245 
 246 static const struct dw_plat_pcie_of_data dw_plat_pcie_ep_of_data = {
 247         .mode = DW_PCIE_EP_TYPE,
 248 };
 249 
 250 static const struct of_device_id dw_plat_pcie_of_match[] = {
 251         {
 252                 .compatible = "snps,dw-pcie",
 253                 .data = &dw_plat_pcie_rc_of_data,
 254         },
 255         {
 256                 .compatible = "snps,dw-pcie-ep",
 257                 .data = &dw_plat_pcie_ep_of_data,
 258         },
 259         {},
 260 };
 261 
 262 static struct platform_driver dw_plat_pcie_driver = {
 263         .driver = {
 264                 .name   = "dw-pcie",
 265                 .of_match_table = dw_plat_pcie_of_match,
 266                 .suppress_bind_attrs = true,
 267         },
 268         .probe = dw_plat_pcie_probe,
 269 };
 270 builtin_platform_driver(dw_plat_pcie_driver);

/* [<][>][^][v][top][bottom][index][help] */