root/drivers/pci/controller/dwc/pci-layerscape.c

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

DEFINITIONS

This source file includes following definitions.
  1. ls_pcie_is_bridge
  2. ls_pcie_clear_multifunction
  3. ls_pcie_drop_msg_tlp
  4. ls_pcie_disable_outbound_atus
  5. ls1021_pcie_link_up
  6. ls_pcie_link_up
  7. ls_pcie_fix_error_response
  8. ls_pcie_host_init
  9. ls1021_pcie_host_init
  10. ls_pcie_msi_host_init
  11. ls_add_pcie_port
  12. ls_pcie_probe

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * PCIe host controller driver for Freescale Layerscape SoCs
   4  *
   5  * Copyright (C) 2014 Freescale Semiconductor.
   6  *
   7  * Author: Minghuan Lian <Minghuan.Lian@freescale.com>
   8  */
   9 
  10 #include <linux/kernel.h>
  11 #include <linux/interrupt.h>
  12 #include <linux/init.h>
  13 #include <linux/of_pci.h>
  14 #include <linux/of_platform.h>
  15 #include <linux/of_irq.h>
  16 #include <linux/of_address.h>
  17 #include <linux/pci.h>
  18 #include <linux/platform_device.h>
  19 #include <linux/resource.h>
  20 #include <linux/mfd/syscon.h>
  21 #include <linux/regmap.h>
  22 
  23 #include "pcie-designware.h"
  24 
  25 /* PEX1/2 Misc Ports Status Register */
  26 #define SCFG_PEXMSCPORTSR(pex_idx)      (0x94 + (pex_idx) * 4)
  27 #define LTSSM_STATE_SHIFT       20
  28 #define LTSSM_STATE_MASK        0x3f
  29 #define LTSSM_PCIE_L0           0x11 /* L0 state */
  30 
  31 /* PEX Internal Configuration Registers */
  32 #define PCIE_STRFMR1            0x71c /* Symbol Timer & Filter Mask Register1 */
  33 #define PCIE_ABSERR             0x8d0 /* Bridge Slave Error Response Register */
  34 #define PCIE_ABSERR_SETTING     0x9401 /* Forward error of non-posted request */
  35 
  36 #define PCIE_IATU_NUM           6
  37 
  38 struct ls_pcie_drvdata {
  39         u32 lut_offset;
  40         u32 ltssm_shift;
  41         u32 lut_dbg;
  42         const struct dw_pcie_host_ops *ops;
  43         const struct dw_pcie_ops *dw_pcie_ops;
  44 };
  45 
  46 struct ls_pcie {
  47         struct dw_pcie *pci;
  48         void __iomem *lut;
  49         struct regmap *scfg;
  50         const struct ls_pcie_drvdata *drvdata;
  51         int index;
  52 };
  53 
  54 #define to_ls_pcie(x)   dev_get_drvdata((x)->dev)
  55 
  56 static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
  57 {
  58         struct dw_pcie *pci = pcie->pci;
  59         u32 header_type;
  60 
  61         header_type = ioread8(pci->dbi_base + PCI_HEADER_TYPE);
  62         header_type &= 0x7f;
  63 
  64         return header_type == PCI_HEADER_TYPE_BRIDGE;
  65 }
  66 
  67 /* Clear multi-function bit */
  68 static void ls_pcie_clear_multifunction(struct ls_pcie *pcie)
  69 {
  70         struct dw_pcie *pci = pcie->pci;
  71 
  72         iowrite8(PCI_HEADER_TYPE_BRIDGE, pci->dbi_base + PCI_HEADER_TYPE);
  73 }
  74 
  75 /* Drop MSG TLP except for Vendor MSG */
  76 static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
  77 {
  78         u32 val;
  79         struct dw_pcie *pci = pcie->pci;
  80 
  81         val = ioread32(pci->dbi_base + PCIE_STRFMR1);
  82         val &= 0xDFFFFFFF;
  83         iowrite32(val, pci->dbi_base + PCIE_STRFMR1);
  84 }
  85 
  86 static void ls_pcie_disable_outbound_atus(struct ls_pcie *pcie)
  87 {
  88         int i;
  89 
  90         for (i = 0; i < PCIE_IATU_NUM; i++)
  91                 dw_pcie_disable_atu(pcie->pci, i, DW_PCIE_REGION_OUTBOUND);
  92 }
  93 
  94 static int ls1021_pcie_link_up(struct dw_pcie *pci)
  95 {
  96         u32 state;
  97         struct ls_pcie *pcie = to_ls_pcie(pci);
  98 
  99         if (!pcie->scfg)
 100                 return 0;
 101 
 102         regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), &state);
 103         state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK;
 104 
 105         if (state < LTSSM_PCIE_L0)
 106                 return 0;
 107 
 108         return 1;
 109 }
 110 
 111 static int ls_pcie_link_up(struct dw_pcie *pci)
 112 {
 113         struct ls_pcie *pcie = to_ls_pcie(pci);
 114         u32 state;
 115 
 116         state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >>
 117                  pcie->drvdata->ltssm_shift) &
 118                  LTSSM_STATE_MASK;
 119 
 120         if (state < LTSSM_PCIE_L0)
 121                 return 0;
 122 
 123         return 1;
 124 }
 125 
 126 /* Forward error response of outbound non-posted requests */
 127 static void ls_pcie_fix_error_response(struct ls_pcie *pcie)
 128 {
 129         struct dw_pcie *pci = pcie->pci;
 130 
 131         iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
 132 }
 133 
 134 static int ls_pcie_host_init(struct pcie_port *pp)
 135 {
 136         struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 137         struct ls_pcie *pcie = to_ls_pcie(pci);
 138 
 139         /*
 140          * Disable outbound windows configured by the bootloader to avoid
 141          * one transaction hitting multiple outbound windows.
 142          * dw_pcie_setup_rc() will reconfigure the outbound windows.
 143          */
 144         ls_pcie_disable_outbound_atus(pcie);
 145         ls_pcie_fix_error_response(pcie);
 146 
 147         dw_pcie_dbi_ro_wr_en(pci);
 148         ls_pcie_clear_multifunction(pcie);
 149         dw_pcie_dbi_ro_wr_dis(pci);
 150 
 151         ls_pcie_drop_msg_tlp(pcie);
 152 
 153         dw_pcie_setup_rc(pp);
 154 
 155         return 0;
 156 }
 157 
 158 static int ls1021_pcie_host_init(struct pcie_port *pp)
 159 {
 160         struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 161         struct ls_pcie *pcie = to_ls_pcie(pci);
 162         struct device *dev = pci->dev;
 163         u32 index[2];
 164         int ret;
 165 
 166         pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node,
 167                                                      "fsl,pcie-scfg");
 168         if (IS_ERR(pcie->scfg)) {
 169                 ret = PTR_ERR(pcie->scfg);
 170                 dev_err(dev, "No syscfg phandle specified\n");
 171                 pcie->scfg = NULL;
 172                 return ret;
 173         }
 174 
 175         if (of_property_read_u32_array(dev->of_node,
 176                                        "fsl,pcie-scfg", index, 2)) {
 177                 pcie->scfg = NULL;
 178                 return -EINVAL;
 179         }
 180         pcie->index = index[1];
 181 
 182         return ls_pcie_host_init(pp);
 183 }
 184 
 185 static int ls_pcie_msi_host_init(struct pcie_port *pp)
 186 {
 187         struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 188         struct device *dev = pci->dev;
 189         struct device_node *np = dev->of_node;
 190         struct device_node *msi_node;
 191 
 192         /*
 193          * The MSI domain is set by the generic of_msi_configure().  This
 194          * .msi_host_init() function keeps us from doing the default MSI
 195          * domain setup in dw_pcie_host_init() and also enforces the
 196          * requirement that "msi-parent" exists.
 197          */
 198         msi_node = of_parse_phandle(np, "msi-parent", 0);
 199         if (!msi_node) {
 200                 dev_err(dev, "failed to find msi-parent\n");
 201                 return -EINVAL;
 202         }
 203 
 204         of_node_put(msi_node);
 205         return 0;
 206 }
 207 
 208 static const struct dw_pcie_host_ops ls1021_pcie_host_ops = {
 209         .host_init = ls1021_pcie_host_init,
 210         .msi_host_init = ls_pcie_msi_host_init,
 211 };
 212 
 213 static const struct dw_pcie_host_ops ls_pcie_host_ops = {
 214         .host_init = ls_pcie_host_init,
 215         .msi_host_init = ls_pcie_msi_host_init,
 216 };
 217 
 218 static const struct dw_pcie_ops dw_ls1021_pcie_ops = {
 219         .link_up = ls1021_pcie_link_up,
 220 };
 221 
 222 static const struct dw_pcie_ops dw_ls_pcie_ops = {
 223         .link_up = ls_pcie_link_up,
 224 };
 225 
 226 static const struct ls_pcie_drvdata ls1021_drvdata = {
 227         .ops = &ls1021_pcie_host_ops,
 228         .dw_pcie_ops = &dw_ls1021_pcie_ops,
 229 };
 230 
 231 static const struct ls_pcie_drvdata ls1043_drvdata = {
 232         .lut_offset = 0x10000,
 233         .ltssm_shift = 24,
 234         .lut_dbg = 0x7fc,
 235         .ops = &ls_pcie_host_ops,
 236         .dw_pcie_ops = &dw_ls_pcie_ops,
 237 };
 238 
 239 static const struct ls_pcie_drvdata ls1046_drvdata = {
 240         .lut_offset = 0x80000,
 241         .ltssm_shift = 24,
 242         .lut_dbg = 0x407fc,
 243         .ops = &ls_pcie_host_ops,
 244         .dw_pcie_ops = &dw_ls_pcie_ops,
 245 };
 246 
 247 static const struct ls_pcie_drvdata ls2080_drvdata = {
 248         .lut_offset = 0x80000,
 249         .ltssm_shift = 0,
 250         .lut_dbg = 0x7fc,
 251         .ops = &ls_pcie_host_ops,
 252         .dw_pcie_ops = &dw_ls_pcie_ops,
 253 };
 254 
 255 static const struct ls_pcie_drvdata ls2088_drvdata = {
 256         .lut_offset = 0x80000,
 257         .ltssm_shift = 0,
 258         .lut_dbg = 0x407fc,
 259         .ops = &ls_pcie_host_ops,
 260         .dw_pcie_ops = &dw_ls_pcie_ops,
 261 };
 262 
 263 static const struct of_device_id ls_pcie_of_match[] = {
 264         { .compatible = "fsl,ls1012a-pcie", .data = &ls1046_drvdata },
 265         { .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata },
 266         { .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata },
 267         { .compatible = "fsl,ls1046a-pcie", .data = &ls1046_drvdata },
 268         { .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata },
 269         { .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata },
 270         { .compatible = "fsl,ls2088a-pcie", .data = &ls2088_drvdata },
 271         { .compatible = "fsl,ls1088a-pcie", .data = &ls2088_drvdata },
 272         { },
 273 };
 274 
 275 static int __init ls_add_pcie_port(struct ls_pcie *pcie)
 276 {
 277         struct dw_pcie *pci = pcie->pci;
 278         struct pcie_port *pp = &pci->pp;
 279         struct device *dev = pci->dev;
 280         int ret;
 281 
 282         pp->ops = pcie->drvdata->ops;
 283 
 284         ret = dw_pcie_host_init(pp);
 285         if (ret) {
 286                 dev_err(dev, "failed to initialize host\n");
 287                 return ret;
 288         }
 289 
 290         return 0;
 291 }
 292 
 293 static int __init ls_pcie_probe(struct platform_device *pdev)
 294 {
 295         struct device *dev = &pdev->dev;
 296         struct dw_pcie *pci;
 297         struct ls_pcie *pcie;
 298         struct resource *dbi_base;
 299         int ret;
 300 
 301         pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
 302         if (!pcie)
 303                 return -ENOMEM;
 304 
 305         pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
 306         if (!pci)
 307                 return -ENOMEM;
 308 
 309         pcie->drvdata = of_device_get_match_data(dev);
 310 
 311         pci->dev = dev;
 312         pci->ops = pcie->drvdata->dw_pcie_ops;
 313 
 314         pcie->pci = pci;
 315 
 316         dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
 317         pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base);
 318         if (IS_ERR(pci->dbi_base))
 319                 return PTR_ERR(pci->dbi_base);
 320 
 321         pcie->lut = pci->dbi_base + pcie->drvdata->lut_offset;
 322 
 323         if (!ls_pcie_is_bridge(pcie))
 324                 return -ENODEV;
 325 
 326         platform_set_drvdata(pdev, pcie);
 327 
 328         ret = ls_add_pcie_port(pcie);
 329         if (ret < 0)
 330                 return ret;
 331 
 332         return 0;
 333 }
 334 
 335 static struct platform_driver ls_pcie_driver = {
 336         .driver = {
 337                 .name = "layerscape-pcie",
 338                 .of_match_table = ls_pcie_of_match,
 339                 .suppress_bind_attrs = true,
 340         },
 341 };
 342 builtin_platform_driver_probe(ls_pcie_driver, ls_pcie_probe);

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