Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * PCIe host controller driver for Amazon's Annapurna Labs IP (used in chips
0004  * such as Graviton and Alpine)
0005  *
0006  * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
0007  *
0008  * Author: Jonathan Chocron <jonnyc@amazon.com>
0009  */
0010 
0011 #include <linux/pci.h>
0012 #include <linux/pci-ecam.h>
0013 #include <linux/pci-acpi.h>
0014 #include "../../pci.h"
0015 
0016 #if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
0017 
0018 struct al_pcie_acpi  {
0019     void __iomem *dbi_base;
0020 };
0021 
0022 static void __iomem *al_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
0023                      int where)
0024 {
0025     struct pci_config_window *cfg = bus->sysdata;
0026     struct al_pcie_acpi *pcie = cfg->priv;
0027     void __iomem *dbi_base = pcie->dbi_base;
0028 
0029     if (bus->number == cfg->busr.start) {
0030         /*
0031          * The DW PCIe core doesn't filter out transactions to other
0032          * devices/functions on the root bus num, so we do this here.
0033          */
0034         if (PCI_SLOT(devfn) > 0)
0035             return NULL;
0036         else
0037             return dbi_base + where;
0038     }
0039 
0040     return pci_ecam_map_bus(bus, devfn, where);
0041 }
0042 
0043 static int al_pcie_init(struct pci_config_window *cfg)
0044 {
0045     struct device *dev = cfg->parent;
0046     struct acpi_device *adev = to_acpi_device(dev);
0047     struct acpi_pci_root *root = acpi_driver_data(adev);
0048     struct al_pcie_acpi *al_pcie;
0049     struct resource *res;
0050     int ret;
0051 
0052     al_pcie = devm_kzalloc(dev, sizeof(*al_pcie), GFP_KERNEL);
0053     if (!al_pcie)
0054         return -ENOMEM;
0055 
0056     res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
0057     if (!res)
0058         return -ENOMEM;
0059 
0060     ret = acpi_get_rc_resources(dev, "AMZN0001", root->segment, res);
0061     if (ret) {
0062         dev_err(dev, "can't get rc dbi base address for SEG %d\n",
0063             root->segment);
0064         return ret;
0065     }
0066 
0067     dev_dbg(dev, "Root port dbi res: %pR\n", res);
0068 
0069     al_pcie->dbi_base = devm_pci_remap_cfg_resource(dev, res);
0070     if (IS_ERR(al_pcie->dbi_base))
0071         return PTR_ERR(al_pcie->dbi_base);
0072 
0073     cfg->priv = al_pcie;
0074 
0075     return 0;
0076 }
0077 
0078 const struct pci_ecam_ops al_pcie_ops = {
0079     .init         =  al_pcie_init,
0080     .pci_ops      = {
0081         .map_bus    = al_pcie_map_bus,
0082         .read       = pci_generic_config_read,
0083         .write      = pci_generic_config_write,
0084     }
0085 };
0086 
0087 #endif /* defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) */
0088 
0089 #ifdef CONFIG_PCIE_AL
0090 
0091 #include <linux/of_pci.h>
0092 #include "pcie-designware.h"
0093 
0094 #define AL_PCIE_REV_ID_2    2
0095 #define AL_PCIE_REV_ID_3    3
0096 #define AL_PCIE_REV_ID_4    4
0097 
0098 #define AXI_BASE_OFFSET     0x0
0099 
0100 #define DEVICE_ID_OFFSET    0x16c
0101 
0102 #define DEVICE_REV_ID           0x0
0103 #define DEVICE_REV_ID_DEV_ID_MASK   GENMASK(31, 16)
0104 
0105 #define DEVICE_REV_ID_DEV_ID_X4     0
0106 #define DEVICE_REV_ID_DEV_ID_X8     2
0107 #define DEVICE_REV_ID_DEV_ID_X16    4
0108 
0109 #define OB_CTRL_REV1_2_OFFSET   0x0040
0110 #define OB_CTRL_REV3_5_OFFSET   0x0030
0111 
0112 #define CFG_TARGET_BUS          0x0
0113 #define CFG_TARGET_BUS_MASK_MASK    GENMASK(7, 0)
0114 #define CFG_TARGET_BUS_BUSNUM_MASK  GENMASK(15, 8)
0115 
0116 #define CFG_CONTROL         0x4
0117 #define CFG_CONTROL_SUBBUS_MASK     GENMASK(15, 8)
0118 #define CFG_CONTROL_SEC_BUS_MASK    GENMASK(23, 16)
0119 
0120 struct al_pcie_reg_offsets {
0121     unsigned int ob_ctrl;
0122 };
0123 
0124 struct al_pcie_target_bus_cfg {
0125     u8 reg_val;
0126     u8 reg_mask;
0127     u8 ecam_mask;
0128 };
0129 
0130 struct al_pcie {
0131     struct dw_pcie *pci;
0132     void __iomem *controller_base; /* base of PCIe unit (not DW core) */
0133     struct device *dev;
0134     resource_size_t ecam_size;
0135     unsigned int controller_rev_id;
0136     struct al_pcie_reg_offsets reg_offsets;
0137     struct al_pcie_target_bus_cfg target_bus_cfg;
0138 };
0139 
0140 #define to_al_pcie(x)       dev_get_drvdata((x)->dev)
0141 
0142 static inline u32 al_pcie_controller_readl(struct al_pcie *pcie, u32 offset)
0143 {
0144     return readl_relaxed(pcie->controller_base + offset);
0145 }
0146 
0147 static inline void al_pcie_controller_writel(struct al_pcie *pcie, u32 offset,
0148                          u32 val)
0149 {
0150     writel_relaxed(val, pcie->controller_base + offset);
0151 }
0152 
0153 static int al_pcie_rev_id_get(struct al_pcie *pcie, unsigned int *rev_id)
0154 {
0155     u32 dev_rev_id_val;
0156     u32 dev_id_val;
0157 
0158     dev_rev_id_val = al_pcie_controller_readl(pcie, AXI_BASE_OFFSET +
0159                           DEVICE_ID_OFFSET +
0160                           DEVICE_REV_ID);
0161     dev_id_val = FIELD_GET(DEVICE_REV_ID_DEV_ID_MASK, dev_rev_id_val);
0162 
0163     switch (dev_id_val) {
0164     case DEVICE_REV_ID_DEV_ID_X4:
0165         *rev_id = AL_PCIE_REV_ID_2;
0166         break;
0167     case DEVICE_REV_ID_DEV_ID_X8:
0168         *rev_id = AL_PCIE_REV_ID_3;
0169         break;
0170     case DEVICE_REV_ID_DEV_ID_X16:
0171         *rev_id = AL_PCIE_REV_ID_4;
0172         break;
0173     default:
0174         dev_err(pcie->dev, "Unsupported dev_id_val (0x%x)\n",
0175             dev_id_val);
0176         return -EINVAL;
0177     }
0178 
0179     dev_dbg(pcie->dev, "dev_id_val: 0x%x\n", dev_id_val);
0180 
0181     return 0;
0182 }
0183 
0184 static int al_pcie_reg_offsets_set(struct al_pcie *pcie)
0185 {
0186     switch (pcie->controller_rev_id) {
0187     case AL_PCIE_REV_ID_2:
0188         pcie->reg_offsets.ob_ctrl = OB_CTRL_REV1_2_OFFSET;
0189         break;
0190     case AL_PCIE_REV_ID_3:
0191     case AL_PCIE_REV_ID_4:
0192         pcie->reg_offsets.ob_ctrl = OB_CTRL_REV3_5_OFFSET;
0193         break;
0194     default:
0195         dev_err(pcie->dev, "Unsupported controller rev_id: 0x%x\n",
0196             pcie->controller_rev_id);
0197         return -EINVAL;
0198     }
0199 
0200     return 0;
0201 }
0202 
0203 static inline void al_pcie_target_bus_set(struct al_pcie *pcie,
0204                       u8 target_bus,
0205                       u8 mask_target_bus)
0206 {
0207     u32 reg;
0208 
0209     reg = FIELD_PREP(CFG_TARGET_BUS_MASK_MASK, mask_target_bus) |
0210           FIELD_PREP(CFG_TARGET_BUS_BUSNUM_MASK, target_bus);
0211 
0212     al_pcie_controller_writel(pcie, AXI_BASE_OFFSET +
0213                   pcie->reg_offsets.ob_ctrl + CFG_TARGET_BUS,
0214                   reg);
0215 }
0216 
0217 static void __iomem *al_pcie_conf_addr_map_bus(struct pci_bus *bus,
0218                            unsigned int devfn, int where)
0219 {
0220     struct dw_pcie_rp *pp = bus->sysdata;
0221     struct al_pcie *pcie = to_al_pcie(to_dw_pcie_from_pp(pp));
0222     unsigned int busnr = bus->number;
0223     struct al_pcie_target_bus_cfg *target_bus_cfg = &pcie->target_bus_cfg;
0224     unsigned int busnr_ecam = busnr & target_bus_cfg->ecam_mask;
0225     unsigned int busnr_reg = busnr & target_bus_cfg->reg_mask;
0226 
0227     if (busnr_reg != target_bus_cfg->reg_val) {
0228         dev_dbg(pcie->pci->dev, "Changing target bus busnum val from 0x%x to 0x%x\n",
0229             target_bus_cfg->reg_val, busnr_reg);
0230         target_bus_cfg->reg_val = busnr_reg;
0231         al_pcie_target_bus_set(pcie,
0232                        target_bus_cfg->reg_val,
0233                        target_bus_cfg->reg_mask);
0234     }
0235 
0236     return pp->va_cfg0_base + PCIE_ECAM_OFFSET(busnr_ecam, devfn, where);
0237 }
0238 
0239 static struct pci_ops al_child_pci_ops = {
0240     .map_bus = al_pcie_conf_addr_map_bus,
0241     .read = pci_generic_config_read,
0242     .write = pci_generic_config_write,
0243 };
0244 
0245 static void al_pcie_config_prepare(struct al_pcie *pcie)
0246 {
0247     struct al_pcie_target_bus_cfg *target_bus_cfg;
0248     struct dw_pcie_rp *pp = &pcie->pci->pp;
0249     unsigned int ecam_bus_mask;
0250     u32 cfg_control_offset;
0251     u8 subordinate_bus;
0252     u8 secondary_bus;
0253     u32 cfg_control;
0254     u32 reg;
0255     struct resource *bus = resource_list_first_type(&pp->bridge->windows, IORESOURCE_BUS)->res;
0256 
0257     target_bus_cfg = &pcie->target_bus_cfg;
0258 
0259     ecam_bus_mask = (pcie->ecam_size >> PCIE_ECAM_BUS_SHIFT) - 1;
0260     if (ecam_bus_mask > 255) {
0261         dev_warn(pcie->dev, "ECAM window size is larger than 256MB. Cutting off at 256\n");
0262         ecam_bus_mask = 255;
0263     }
0264 
0265     /* This portion is taken from the transaction address */
0266     target_bus_cfg->ecam_mask = ecam_bus_mask;
0267     /* This portion is taken from the cfg_target_bus reg */
0268     target_bus_cfg->reg_mask = ~target_bus_cfg->ecam_mask;
0269     target_bus_cfg->reg_val = bus->start & target_bus_cfg->reg_mask;
0270 
0271     al_pcie_target_bus_set(pcie, target_bus_cfg->reg_val,
0272                    target_bus_cfg->reg_mask);
0273 
0274     secondary_bus = bus->start + 1;
0275     subordinate_bus = bus->end;
0276 
0277     /* Set the valid values of secondary and subordinate buses */
0278     cfg_control_offset = AXI_BASE_OFFSET + pcie->reg_offsets.ob_ctrl +
0279                  CFG_CONTROL;
0280 
0281     cfg_control = al_pcie_controller_readl(pcie, cfg_control_offset);
0282 
0283     reg = cfg_control &
0284           ~(CFG_CONTROL_SEC_BUS_MASK | CFG_CONTROL_SUBBUS_MASK);
0285 
0286     reg |= FIELD_PREP(CFG_CONTROL_SUBBUS_MASK, subordinate_bus) |
0287            FIELD_PREP(CFG_CONTROL_SEC_BUS_MASK, secondary_bus);
0288 
0289     al_pcie_controller_writel(pcie, cfg_control_offset, reg);
0290 }
0291 
0292 static int al_pcie_host_init(struct dw_pcie_rp *pp)
0293 {
0294     struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
0295     struct al_pcie *pcie = to_al_pcie(pci);
0296     int rc;
0297 
0298     pp->bridge->child_ops = &al_child_pci_ops;
0299 
0300     rc = al_pcie_rev_id_get(pcie, &pcie->controller_rev_id);
0301     if (rc)
0302         return rc;
0303 
0304     rc = al_pcie_reg_offsets_set(pcie);
0305     if (rc)
0306         return rc;
0307 
0308     al_pcie_config_prepare(pcie);
0309 
0310     return 0;
0311 }
0312 
0313 static const struct dw_pcie_host_ops al_pcie_host_ops = {
0314     .host_init = al_pcie_host_init,
0315 };
0316 
0317 static int al_pcie_probe(struct platform_device *pdev)
0318 {
0319     struct device *dev = &pdev->dev;
0320     struct resource *controller_res;
0321     struct resource *ecam_res;
0322     struct al_pcie *al_pcie;
0323     struct dw_pcie *pci;
0324 
0325     al_pcie = devm_kzalloc(dev, sizeof(*al_pcie), GFP_KERNEL);
0326     if (!al_pcie)
0327         return -ENOMEM;
0328 
0329     pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
0330     if (!pci)
0331         return -ENOMEM;
0332 
0333     pci->dev = dev;
0334     pci->pp.ops = &al_pcie_host_ops;
0335 
0336     al_pcie->pci = pci;
0337     al_pcie->dev = dev;
0338 
0339     ecam_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
0340     if (!ecam_res) {
0341         dev_err(dev, "couldn't find 'config' reg in DT\n");
0342         return -ENOENT;
0343     }
0344     al_pcie->ecam_size = resource_size(ecam_res);
0345 
0346     controller_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
0347                               "controller");
0348     al_pcie->controller_base = devm_ioremap_resource(dev, controller_res);
0349     if (IS_ERR(al_pcie->controller_base)) {
0350         dev_err(dev, "couldn't remap controller base %pR\n",
0351             controller_res);
0352         return PTR_ERR(al_pcie->controller_base);
0353     }
0354 
0355     dev_dbg(dev, "From DT: controller_base: %pR\n", controller_res);
0356 
0357     platform_set_drvdata(pdev, al_pcie);
0358 
0359     return dw_pcie_host_init(&pci->pp);
0360 }
0361 
0362 static const struct of_device_id al_pcie_of_match[] = {
0363     { .compatible = "amazon,al-alpine-v2-pcie",
0364     },
0365     { .compatible = "amazon,al-alpine-v3-pcie",
0366     },
0367     {},
0368 };
0369 
0370 static struct platform_driver al_pcie_driver = {
0371     .driver = {
0372         .name   = "al-pcie",
0373         .of_match_table = al_pcie_of_match,
0374         .suppress_bind_attrs = true,
0375     },
0376     .probe = al_pcie_probe,
0377 };
0378 builtin_platform_driver(al_pcie_driver);
0379 
0380 #endif /* CONFIG_PCIE_AL*/