Lines Matching +full:iproc +full:- +full:msi
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2014 Hauke Mehrtens <hauke@hauke-m.de>
9 #include <linux/msi.h>
16 #include <linux/irqchip/arm-gic-v3.h>
24 #include "pcie-iproc.h"
99 * iProc PCIe outbound mapping controller specific parameters
146 * iProc PCIe inbound mapping type
160 * iProc PCIe inbound mapping controller specific parameters
169 * @imap_addr_offset: register offset between the upper and lower 32-bit
239 * iProc PCIe host registers
246 * To allow MSI to be steered to an external MSI controller (e.g., ARM
253 * window where the MSI posted writes are written, for the writes to be
254 * interpreted as MSI writes.
260 * To hold the address of the register where the MSI writes are
267 /* enable MSI */
316 /* iProc PCIe PAXB BCMA registers */
327 /* iProc PCIe PAXB registers */
343 /* iProc PCIe PAXB v2 registers */
374 /* iProc PCIe PAXC v1 registers */
383 /* iProc PCIe PAXC v2 registers */
410 struct iproc_pcie *pcie = bus->sysdata; in iproc_data()
422 return pcie->reg_offsets[reg]; in iproc_pcie_reg_offset()
433 return readl(pcie->base + offset); in iproc_pcie_read_reg()
444 writel(val, pcie->base + offset); in iproc_pcie_write_reg()
450 * (typically seen during enumeration with multi-function devices) from
459 if (bus->number && pcie->has_apb_err_disable) { in iproc_pcie_apb_err_disable()
491 return (pcie->base + offset); in iproc_pcie_map_ep_cfg_reg()
513 * Note that a non-Vendor ID config register may have a value of in iproc_pcie_cfg_retry()
519 while (data == CFG_RETRY_STATUS && timeout--) { in iproc_pcie_cfg_retry()
553 pcie->fix_paxc_cap = true; in iproc_pcie_fix_cap()
557 if (pcie->fix_paxc_cap) { in iproc_pcie_fix_cap()
565 if (pcie->fix_paxc_cap) { in iproc_pcie_fix_cap()
588 unsigned int busno = bus->number; in iproc_pcie_config_read()
611 *val = (data >> (8 * (where & 3))) & ((1 << (size * 8)) - 1); in iproc_pcie_config_read()
626 if (pcie->rej_unconfig_pf && in iproc_pcie_config_read()
658 return (pcie->base + offset); in iproc_pcie_map_cfg_bus()
668 return iproc_pcie_map_cfg_bus(iproc_data(bus), bus->number, devfn, in iproc_pcie_bus_map_cfg_bus()
687 *val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1); in iproc_pci_raw_config_read32()
708 mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8)); in iproc_pci_raw_config_write32()
723 if (pcie->iproc_cfg_read) in iproc_pcie_config_read32()
759 if (pcie->ep_is_internal) in iproc_pcie_perst_ctrl()
787 struct device *dev = pcie->dev; in iproc_pcie_check_link()
795 if (pcie->ep_is_internal) in iproc_pcie_check_link()
801 return -ENODEV; in iproc_pcie_check_link()
808 return -EFAULT; in iproc_pcie_check_link()
855 return link_is_active ? 0 : -ENODEV; in iproc_pcie_check_link()
876 struct device *dev = pcie->dev; in iproc_pcie_ob_write()
889 return -EINVAL; in iproc_pcie_ob_write()
892 * Program the OARR registers. The upper 32-bit OARR register is in iproc_pcie_ob_write()
893 * always right after the lower 32-bit OARR register. in iproc_pcie_ob_write()
896 OARR_VALID, pcie->base + oarr_offset); in iproc_pcie_ob_write()
897 writel(upper_32_bits(axi_addr), pcie->base + oarr_offset + 4); in iproc_pcie_ob_write()
900 writel(lower_32_bits(pci_addr), pcie->base + omap_offset); in iproc_pcie_ob_write()
901 writel(upper_32_bits(pci_addr), pcie->base + omap_offset + 4); in iproc_pcie_ob_write()
906 readl(pcie->base + oarr_offset), in iproc_pcie_ob_write()
907 readl(pcie->base + oarr_offset + 4)); in iproc_pcie_ob_write()
909 readl(pcie->base + omap_offset), in iproc_pcie_ob_write()
910 readl(pcie->base + omap_offset + 4)); in iproc_pcie_ob_write()
916 * Some iProc SoCs require the SW to configure the outbound address mapping
920 * iproc_pcie_address = axi_address - axi_offset
924 * axi_addr -> iproc_pcie_address -> OARR -> OMAP -> pci_address
929 struct iproc_pcie_ob *ob = &pcie->ob; in iproc_pcie_setup_ob()
930 struct device *dev = pcie->dev; in iproc_pcie_setup_ob()
931 int ret = -EINVAL, window_idx, size_idx; in iproc_pcie_setup_ob()
933 if (axi_addr < ob->axi_offset) { in iproc_pcie_setup_ob()
935 &axi_addr, &ob->axi_offset); in iproc_pcie_setup_ob()
936 return -EINVAL; in iproc_pcie_setup_ob()
940 * Translate the AXI address to the internal address used by the iProc in iproc_pcie_setup_ob()
943 axi_addr -= ob->axi_offset; in iproc_pcie_setup_ob()
946 for (window_idx = ob->nr_windows - 1; window_idx >= 0; window_idx--) { in iproc_pcie_setup_ob()
948 &pcie->ob_map[window_idx]; in iproc_pcie_setup_ob()
962 for (size_idx = ob_map->nr_sizes - 1; size_idx >= 0; in iproc_pcie_setup_ob()
963 size_idx--) { in iproc_pcie_setup_ob()
965 ob_map->window_sizes[size_idx] * SZ_1M; in iproc_pcie_setup_ob()
992 return -EINVAL; in iproc_pcie_setup_ob()
1004 size -= window_size; in iproc_pcie_setup_ob()
1023 &axi_addr, &ob->axi_offset, &pci_addr, &size); in iproc_pcie_setup_ob()
1031 struct device *dev = pcie->dev; in iproc_pcie_map_ranges()
1036 struct resource *res = window->res; in iproc_pcie_map_ranges()
1044 ret = iproc_pcie_setup_ob(pcie, res->start, in iproc_pcie_map_ranges()
1045 res->start - window->offset, in iproc_pcie_map_ranges()
1052 return -EINVAL; in iproc_pcie_map_ranges()
1062 const struct iproc_pcie_ib_map *ib_map = &pcie->ib_map[region_idx]; in iproc_pcie_ib_is_in_use()
1067 return !!(val & (BIT(ib_map->nr_sizes) - 1)); in iproc_pcie_ib_is_in_use()
1073 return !!(ib_map->type == type); in iproc_pcie_ib_check_type()
1080 struct device *dev = pcie->dev; in iproc_pcie_ib_write()
1081 const struct iproc_pcie_ib_map *ib_map = &pcie->ib_map[region_idx]; in iproc_pcie_ib_write()
1092 return -EINVAL; in iproc_pcie_ib_write()
1098 * Program the IARR registers. The upper 32-bit IARR register is in iproc_pcie_ib_write()
1099 * always right after the lower 32-bit IARR register. in iproc_pcie_ib_write()
1102 pcie->base + iarr_offset); in iproc_pcie_ib_write()
1103 writel(upper_32_bits(pci_addr), pcie->base + iarr_offset + 4); in iproc_pcie_ib_write()
1106 readl(pcie->base + iarr_offset), in iproc_pcie_ib_write()
1107 readl(pcie->base + iarr_offset + 4)); in iproc_pcie_ib_write()
1115 val = readl(pcie->base + imap_offset); in iproc_pcie_ib_write()
1117 writel(val, pcie->base + imap_offset); in iproc_pcie_ib_write()
1119 pcie->base + imap_offset + ib_map->imap_addr_offset); in iproc_pcie_ib_write()
1122 window_idx, readl(pcie->base + imap_offset), in iproc_pcie_ib_write()
1123 readl(pcie->base + imap_offset + in iproc_pcie_ib_write()
1124 ib_map->imap_addr_offset)); in iproc_pcie_ib_write()
1126 imap_offset += ib_map->imap_window_offset; in iproc_pcie_ib_write()
1137 struct device *dev = pcie->dev; in iproc_pcie_setup_ib()
1138 struct iproc_pcie_ib *ib = &pcie->ib; in iproc_pcie_setup_ib()
1141 u64 axi_addr = entry->res->start; in iproc_pcie_setup_ib()
1142 u64 pci_addr = entry->res->start - entry->offset; in iproc_pcie_setup_ib()
1143 resource_size_t size = resource_size(entry->res); in iproc_pcie_setup_ib()
1146 for (region_idx = 0; region_idx < ib->nr_regions; region_idx++) { in iproc_pcie_setup_ib()
1148 &pcie->ib_map[region_idx]; in iproc_pcie_setup_ib()
1159 for (size_idx = 0; size_idx < ib_map->nr_sizes; size_idx++) { in iproc_pcie_setup_ib()
1161 ib_map->region_sizes[size_idx] * ib_map->size_unit; in iproc_pcie_setup_ib()
1171 return -EINVAL; in iproc_pcie_setup_ib()
1176 ib_map->nr_windows, axi_addr, in iproc_pcie_setup_ib()
1185 ret = -EINVAL; in iproc_pcie_setup_ib()
1201 resource_list_for_each_entry(entry, &host->dma_ranges) { in iproc_pcie_map_dma_ranges()
1213 struct iproc_pcie_ib *ib = &pcie->ib; in iproc_pcie_invalidate_mapping()
1214 struct iproc_pcie_ob *ob = &pcie->ob; in iproc_pcie_invalidate_mapping()
1217 if (pcie->ep_is_internal) in iproc_pcie_invalidate_mapping()
1220 if (pcie->need_ob_cfg) { in iproc_pcie_invalidate_mapping()
1222 for (idx = ob->nr_windows - 1; idx >= 0; idx--) { in iproc_pcie_invalidate_mapping()
1228 if (pcie->need_ib_cfg) { in iproc_pcie_invalidate_mapping()
1230 for (idx = 0; idx < ib->nr_regions; idx++) { in iproc_pcie_invalidate_mapping()
1241 struct device *dev = pcie->dev; in iproce_pcie_get_msi()
1246 * Check if 'msi-map' points to ARM GICv3 ITS, which is the only in iproce_pcie_get_msi()
1247 * supported external MSI controller that requires steering. in iproce_pcie_get_msi()
1249 if (!of_device_is_compatible(msi_node, "arm,gic-v3-its")) { in iproce_pcie_get_msi()
1250 dev_err(dev, "unable to find compatible MSI controller\n"); in iproce_pcie_get_msi()
1251 return -ENODEV; in iproce_pcie_get_msi()
1257 dev_err(dev, "unable to obtain MSI controller resources\n"); in iproce_pcie_get_msi()
1273 msi_addr &= ~(SZ_32K - 1); in iproc_pcie_paxb_v2_msi_steer()
1274 entry.res->start = msi_addr; in iproc_pcie_paxb_v2_msi_steer()
1275 entry.res->end = msi_addr + SZ_32K - 1; in iproc_pcie_paxb_v2_msi_steer()
1288 * Disable PAXC MSI steering. All write transfers will be in iproc_pcie_paxc_v2_msi_steer()
1289 * treated as non-MSI transfers in iproc_pcie_paxc_v2_msi_steer()
1299 * bits [30:0] of the MSI base address register. In fact, in all iProc in iproc_pcie_paxc_v2_msi_steer()
1300 * based SoCs, all I/O register bases are well below the 32-bit in iproc_pcie_paxc_v2_msi_steer()
1309 /* steering MSI to GICv3 ITS */ in iproc_pcie_paxc_v2_msi_steer()
1316 * iProc MSI address registers. in iproc_pcie_paxc_v2_msi_steer()
1324 /* enable MSI */ in iproc_pcie_paxc_v2_msi_steer()
1333 struct device *dev = pcie->dev; in iproc_pcie_msi_steer()
1339 dev_err(dev, "msi steering failed\n"); in iproc_pcie_msi_steer()
1343 switch (pcie->type) { in iproc_pcie_msi_steer()
1353 return -EINVAL; in iproc_pcie_msi_steer()
1365 * Either the "msi-parent" or the "msi-map" phandle needs to exist in iproc_pcie_msi_enable()
1366 * for us to obtain the MSI node. in iproc_pcie_msi_enable()
1369 msi_node = of_parse_phandle(pcie->dev->of_node, "msi-parent", 0); in iproc_pcie_msi_enable()
1375 msi_map = of_get_property(pcie->dev->of_node, "msi-map", &len); in iproc_pcie_msi_enable()
1377 return -ENODEV; in iproc_pcie_msi_enable()
1382 return -ENODEV; in iproc_pcie_msi_enable()
1386 * Certain revisions of the iProc PCIe controller require additional in iproc_pcie_msi_enable()
1387 * configurations to steer the MSI writes towards an external MSI in iproc_pcie_msi_enable()
1390 if (pcie->need_msi_steer) { in iproc_pcie_msi_enable()
1397 * If another MSI controller is being used, the call below should fail in iproc_pcie_msi_enable()
1414 struct device *dev = pcie->dev; in iproc_pcie_rev_init()
1418 switch (pcie->type) { in iproc_pcie_rev_init()
1424 pcie->has_apb_err_disable = true; in iproc_pcie_rev_init()
1425 if (pcie->need_ob_cfg) { in iproc_pcie_rev_init()
1426 pcie->ob_map = paxb_ob_map; in iproc_pcie_rev_init()
1427 pcie->ob.nr_windows = ARRAY_SIZE(paxb_ob_map); in iproc_pcie_rev_init()
1432 pcie->iproc_cfg_read = true; in iproc_pcie_rev_init()
1433 pcie->has_apb_err_disable = true; in iproc_pcie_rev_init()
1434 if (pcie->need_ob_cfg) { in iproc_pcie_rev_init()
1435 pcie->ob_map = paxb_v2_ob_map; in iproc_pcie_rev_init()
1436 pcie->ob.nr_windows = ARRAY_SIZE(paxb_v2_ob_map); in iproc_pcie_rev_init()
1438 pcie->ib.nr_regions = ARRAY_SIZE(paxb_v2_ib_map); in iproc_pcie_rev_init()
1439 pcie->ib_map = paxb_v2_ib_map; in iproc_pcie_rev_init()
1440 pcie->need_msi_steer = true; in iproc_pcie_rev_init()
1446 pcie->ep_is_internal = true; in iproc_pcie_rev_init()
1447 pcie->iproc_cfg_read = true; in iproc_pcie_rev_init()
1448 pcie->rej_unconfig_pf = true; in iproc_pcie_rev_init()
1452 pcie->ep_is_internal = true; in iproc_pcie_rev_init()
1453 pcie->iproc_cfg_read = true; in iproc_pcie_rev_init()
1454 pcie->rej_unconfig_pf = true; in iproc_pcie_rev_init()
1455 pcie->need_msi_steer = true; in iproc_pcie_rev_init()
1458 dev_err(dev, "incompatible iProc PCIe interface\n"); in iproc_pcie_rev_init()
1459 return -EINVAL; in iproc_pcie_rev_init()
1462 pcie->reg_offsets = devm_kcalloc(dev, IPROC_PCIE_MAX_NUM_REG, in iproc_pcie_rev_init()
1463 sizeof(*pcie->reg_offsets), in iproc_pcie_rev_init()
1465 if (!pcie->reg_offsets) in iproc_pcie_rev_init()
1466 return -ENOMEM; in iproc_pcie_rev_init()
1469 pcie->reg_offsets[0] = (pcie->type == IPROC_PCIE_PAXC_V2) ? in iproc_pcie_rev_init()
1472 pcie->reg_offsets[reg_idx] = regs[reg_idx] ? in iproc_pcie_rev_init()
1484 dev = pcie->dev; in iproc_pcie_setup()
1492 ret = phy_init(pcie->phy); in iproc_pcie_setup()
1498 ret = phy_power_on(pcie->phy); in iproc_pcie_setup()
1509 if (pcie->need_ob_cfg) { in iproc_pcie_setup()
1517 if (pcie->need_ib_cfg) { in iproc_pcie_setup()
1519 if (ret && ret != -ENOENT) in iproc_pcie_setup()
1533 dev_info(dev, "not using iProc MSI\n"); in iproc_pcie_setup()
1535 host->ops = &iproc_pcie_ops; in iproc_pcie_setup()
1536 host->sysdata = pcie; in iproc_pcie_setup()
1537 host->map_irq = pcie->map_irq; in iproc_pcie_setup()
1548 phy_power_off(pcie->phy); in iproc_pcie_setup()
1550 phy_exit(pcie->phy); in iproc_pcie_setup()
1559 pci_stop_root_bus(host->bus); in iproc_pcie_remove()
1560 pci_remove_root_bus(host->bus); in iproc_pcie_remove()
1564 phy_power_off(pcie->phy); in iproc_pcie_remove()
1565 phy_exit(pcie->phy); in iproc_pcie_remove()
1572 * The MSI parsing logic in certain revisions of Broadcom PAXC based root
1577 struct iproc_pcie *pcie = iproc_data(pdev->bus); in quirk_paxc_disable_msi_parsing()
1579 if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) in quirk_paxc_disable_msi_parsing()
1596 if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) in quirk_paxc_bridge()
1597 pdev->class = PCI_CLASS_BRIDGE_PCI << 8; in quirk_paxc_bridge()
1605 pdev->pcie_mpss = 2; in quirk_paxc_bridge()
1614 MODULE_DESCRIPTION("Broadcom iPROC PCIe common driver");