diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2020-10-21 09:58:39 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2020-10-21 09:58:39 -0500 |
commit | 924bb1f9b014bec2d38ebe98d5ee37f448dac691 (patch) | |
tree | 97c8a3ba07d6ba109a8dfa0df18a7cdd4cf5bb36 /drivers/pci/controller/dwc/pci-keystone.c | |
parent | a78f2e07d047bcb3d7b9155449b7c6ea8bc65092 (diff) | |
parent | 15b23906347c0af8778d1d4edeea415290342d35 (diff) |
Merge branch 'remotes/lorenzo/pci/dwc'
- Fix designware-ep Header Type check (Hou Zhiqiang)
- Use DBI accessors instead of own config accessors (Rob Herring)
- Allow overriding bridge pci_ops (Rob Herring)
- Allow root and child buses to have different pci_ops (Rob Herring)
- Add default dwc pci_ops.map_bus (Rob Herring)
- Use pci_ops for root config space accessors in al, exynos, histb,
keystone, kirin, meson, tegra (Rob Herring)
- Remove dwc own/other config accessor ops (Rob Herring)
- Use generic config accessors in dwc (Rob Herring)
- Also call .add_bus() callback for root bus (Rob Herring)
- Convert keystone .scan_bus() callback to use pci_ops.add_bus (Rob
Herring)
- Convert dwc to use pci_host_probe() (Rob Herring)
- Remove dwc root_bus pointer (Rob Herring)
- Remove storing of PCI resources in dwc-specific structs (Rob Herring)
- Simplify config space handling (Rob Herring)
- Drop keystone duplicated DT num-viewport handling (Rob Herring)
- Check CONFIG_PCI_MSI in dw_pcie_msi_init() instead of duplicating it in
all the drivers (Rob Herring)
- Remove imx6 duplicate PCIE_LINK_WIDTH_SPEED_CONTROL definition (Rob
Herring)
- Add dwc num_lanes for use when it's lacking from DT (Rob Herring)
- Ensure "Fast Link Mode" simulation environment setting is cleared (Rob
Herring)
- Drop meson duplicate number of lanes setup (Rob Herring)
- Drop meson unnecessary RC config space init (Rob Herring)
- Rework meson config and dwc port logic register accesses (Rob Herring)
- Use common PCI register definitions in imx6 and qcom (Rob Herring)
- Search for DesignWare PCIe Capability instead of hard-coding its location
(Rob Herring)
- Use common DesignWare register definitions in tegra (Rob Herring)
- Drop keystone unused DBI2 code (Rob Herring)
- Make dwc ATU accessors private (Rob Herring)
- Centralize link gen setting in dwc (Rob Herring)
- Set PORT_LINK_DLL_LINK_EN in common dwc setup code (Rob Herring)
- Drop intel-gw unnecessary DT 'device_type' checking (Rob Herring)
- Move intel-gw PCI_CAP_ID_EXP discovery to the single place it's used (Rob
Herring)
- Drop intel-gw unused max_width (Rob Herring)
- Move N_FTS (fast training sequence) setup to common dwc setup (Rob
Herring)
- Convert spear13xx, tegra194 to use DBI accessors (Rob Herring)
- Add multiple PFs support for DWC (Xiaowei Bao)
- Add MSI-X doorbell mode for endpoint mode (Xiaowei Bao)
- Update MSI/MSI-X capability management for endpoints (Xiaowei Bao)
- Add layerscape ls1088a and ls2088a compatible strings (Xiaowei Bao)
- Update layerscape MSI/MSI-X management (Xiaowei Bao)
- Use doorbell to support MSI-X on layerscape (Xiaowei Bao)
- Add layerscape endpoint mode support for ls1088a and ls2088a (Xiaowei
Bao)
- Add layerscape ls1088a node to DT (Xiaowei Bao)
- Add Freescale/Layerscape ls1088a to endpoint test (Xiaowei Bao)
- Add endpoint test driver data for Layerscape PCIe controllers (Hou
Zhiqiang)
- Fix 'cast truncates bits from constant value' warning (Gustavo Pimentel)
- Add uniphier iATU register description (Kunihiko Hayashi)
- Add common iATU register support (Kunihiko Hayashi)
- Remove keystone iATU register mapping in favor of generic dwc support
(Kunihiko Hayashi)
- Skip PCIE_MSI_INTR0* programming if MSI is disabled (Jisheng Zhang)
- Fix MSI page leakage in suspend/resume (Jisheng Zhang)
- Check whether link is up before attempting config access (best-effort fix
even though it's racy) (Hou Zhiqiang)
* remotes/lorenzo/pci/dwc:
PCI: dwc: Add link up check in dw_child_pcie_ops.map_bus()
PCI: dwc: Fix MSI page leakage in suspend/resume
PCI: dwc: Skip PCIE_MSI_INTR0* programming if MSI is disabled
PCI: keystone: Remove iATU register mapping
PCI: dwc: Add common iATU register support
dt-bindings: PCI: uniphier-ep: Add iATU register description
dt-bindings: PCI: uniphier: Add iATU register description
PCI: dwc: Fix 'cast truncates bits from constant value'
misc: pci_endpoint_test: Add driver data for Layerscape PCIe controllers
misc: pci_endpoint_test: Add LS1088a in pci_device_id table
PCI: layerscape: Add EP mode support for ls1088a and ls2088a
PCI: layerscape: Modify the MSIX to the doorbell mode
PCI: layerscape: Modify the way of getting capability with different PEX
PCI: layerscape: Fix some format issue of the code
dt-bindings: pci: layerscape-pci: Add compatible strings for ls1088a and ls2088a
PCI: designware-ep: Modify MSI and MSIX CAP way of finding
PCI: designware-ep: Move the function of getting MSI capability forward
PCI: designware-ep: Add the doorbell mode of MSI-X in EP mode
PCI: designware-ep: Add multiple PFs support for DWC
PCI: dwc: Use DBI accessors
PCI: dwc: Move N_FTS setup to common setup
PCI: dwc/intel-gw: Drop unused max_width
PCI: dwc/intel-gw: Move getting PCI_CAP_ID_EXP offset to intel_pcie_link_setup()
PCI: dwc/intel-gw: Drop unnecessary checking of DT 'device_type' property
PCI: dwc: Set PORT_LINK_DLL_LINK_EN in common setup code
PCI: dwc: Centralize link gen setting
PCI: dwc: Make ATU accessors private
PCI: dwc: Remove read_dbi2 code
PCI: dwc/tegra: Use common Designware port logic register definitions
PCI: dwc: Remove hardcoded PCI_CAP_ID_EXP offset
PCI: dwc/qcom: Use common PCI register definitions
PCI: dwc/imx6: Use common PCI register definitions
PCI: dwc/meson: Rework PCI config and DW port logic register accesses
PCI: dwc/meson: Drop unnecessary RC config space initialization
PCI: dwc/meson: Drop the duplicate number of lanes setup
PCI: dwc: Ensure FAST_LINK_MODE is cleared
PCI: dwc: Add a 'num_lanes' field to struct dw_pcie
PCI: dwc/imx6: Remove duplicate define PCIE_LINK_WIDTH_SPEED_CONTROL
PCI: dwc: Check CONFIG_PCI_MSI inside dw_pcie_msi_init()
PCI: dwc/keystone: Drop duplicated 'num-viewport'
PCI: dwc: Simplify config space handling
PCI: dwc: Remove storing of PCI resources
PCI: dwc: Remove root_bus pointer
PCI: dwc: Convert to use pci_host_probe()
PCI: dwc: keystone: Convert .scan_bus() callback to use add_bus
PCI: Also call .add_bus() callback for root bus
PCI: dwc: Use generic config accessors
PCI: dwc: Remove dwc specific config accessor ops
PCI: dwc: histb: Use pci_ops for root config space accessors
PCI: dwc: exynos: Use pci_ops for root config space accessors
PCI: dwc: kirin: Use pci_ops for root config space accessors
PCI: dwc: meson: Use pci_ops for root config space accessors
PCI: dwc: tegra: Use pci_ops for root config space accessors
PCI: dwc: keystone: Use pci_ops for config space accessors
PCI: dwc: al: Use pci_ops for child config space accessors
PCI: dwc: Add a default pci_ops.map_bus for root port
PCI: dwc: Allow overriding bridge pci_ops
PCI: dwc: Use DBI accessors instead of own config accessors
PCI: Allow root and child buses to have different pci_ops
PCI: designware-ep: Fix the Header Type check
Diffstat (limited to 'drivers/pci/controller/dwc/pci-keystone.c')
-rw-r--r-- | drivers/pci/controller/dwc/pci-keystone.c | 146 |
1 files changed, 38 insertions, 108 deletions
diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c index c8c9d6a75f17..a222728238ca 100644 --- a/drivers/pci/controller/dwc/pci-keystone.c +++ b/drivers/pci/controller/dwc/pci-keystone.c @@ -96,8 +96,6 @@ #define LEG_EP 0x1 #define RC 0x2 -#define EXP_CAP_ID_OFFSET 0x70 - #define KS_PCIE_SYSCLOCKOUTEN BIT(0) #define AM654_PCIE_DEV_TYPE_MASK 0x3 @@ -123,7 +121,6 @@ struct keystone_pcie { int msi_host_irq; int num_lanes; - u32 num_viewport; struct phy **phy; struct device_link **link; struct device_node *msi_intc_np; @@ -397,13 +394,17 @@ static void ks_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie) static void ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie) { u32 val; - u32 num_viewport = ks_pcie->num_viewport; struct dw_pcie *pci = ks_pcie->pci; struct pcie_port *pp = &pci->pp; - u64 start = pp->mem->start; - u64 end = pp->mem->end; + u32 num_viewport = pci->num_viewport; + u64 start, end; + struct resource *mem; int i; + mem = resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM)->res; + start = mem->start; + end = mem->end; + /* Disable BARs for inbound access */ ks_pcie_set_dbi_mode(ks_pcie); dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0); @@ -430,10 +431,10 @@ static void ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie) ks_pcie_app_writel(ks_pcie, CMD_STATUS, val); } -static int ks_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, - unsigned int devfn, int where, int size, - u32 *val) +static void __iomem *ks_pcie_other_map_bus(struct pci_bus *bus, + unsigned int devfn, int where) { + struct pcie_port *pp = bus->sysdata; struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); u32 reg; @@ -444,36 +445,29 @@ static int ks_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, reg |= CFG_TYPE1; ks_pcie_app_writel(ks_pcie, CFG_SETUP, reg); - return dw_pcie_read(pp->va_cfg0_base + where, size, val); + return pp->va_cfg0_base + where; } -static int ks_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, - unsigned int devfn, int where, int size, - u32 val) -{ - struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); - u32 reg; - - reg = CFG_BUS(bus->number) | CFG_DEVICE(PCI_SLOT(devfn)) | - CFG_FUNC(PCI_FUNC(devfn)); - if (!pci_is_root_bus(bus->parent)) - reg |= CFG_TYPE1; - ks_pcie_app_writel(ks_pcie, CFG_SETUP, reg); - - return dw_pcie_write(pp->va_cfg0_base + where, size, val); -} +static struct pci_ops ks_child_pcie_ops = { + .map_bus = ks_pcie_other_map_bus, + .read = pci_generic_config_read, + .write = pci_generic_config_write, +}; /** - * ks_pcie_v3_65_scan_bus() - keystone scan_bus post initialization + * ks_pcie_v3_65_add_bus() - keystone add_bus post initialization * * This sets BAR0 to enable inbound access for MSI_IRQ register */ -static void ks_pcie_v3_65_scan_bus(struct pcie_port *pp) +static int ks_pcie_v3_65_add_bus(struct pci_bus *bus) { + struct pcie_port *pp = bus->sysdata; struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); + if (!pci_is_root_bus(bus)) + return 0; + /* Configure and set up BAR0 */ ks_pcie_set_dbi_mode(ks_pcie); @@ -488,8 +482,17 @@ static void ks_pcie_v3_65_scan_bus(struct pcie_port *pp) * be sufficient. Use physical address to avoid any conflicts. */ dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, ks_pcie->app.start); + + return 0; } +static struct pci_ops ks_pcie_ops = { + .map_bus = dw_pcie_own_conf_map_bus, + .read = pci_generic_config_read, + .write = pci_generic_config_write, + .add_bus = ks_pcie_v3_65_add_bus, +}; + /** * ks_pcie_link_up() - Check if link up */ @@ -807,6 +810,9 @@ static int __init ks_pcie_host_init(struct pcie_port *pp) struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); int ret; + pp->bridge->ops = &ks_pcie_ops; + pp->bridge->child_ops = &ks_child_pcie_ops; + ret = ks_pcie_config_legacy_irq(ks_pcie); if (ret) return ret; @@ -842,11 +848,8 @@ static int __init ks_pcie_host_init(struct pcie_port *pp) } static const struct dw_pcie_host_ops ks_pcie_host_ops = { - .rd_other_conf = ks_pcie_rd_other_conf, - .wr_other_conf = ks_pcie_wr_other_conf, .host_init = ks_pcie_host_init, .msi_host_init = ks_pcie_msi_host_init, - .scan_bus = ks_pcie_v3_65_scan_bus, }; static const struct dw_pcie_host_ops ks_pcie_am654_host_ops = { @@ -867,16 +870,8 @@ static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie, struct dw_pcie *pci = ks_pcie->pci; struct pcie_port *pp = &pci->pp; struct device *dev = &pdev->dev; - struct resource *res; int ret; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); - pp->va_cfg0_base = devm_pci_remap_cfg_resource(dev, res); - if (IS_ERR(pp->va_cfg0_base)) - return PTR_ERR(pp->va_cfg0_base); - - pp->va_cfg1_base = pp->va_cfg0_base; - ret = dw_pcie_host_init(pp); if (ret) { dev_err(dev, "failed to initialize host\n"); @@ -886,18 +881,6 @@ static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie, return 0; } -static u32 ks_pcie_am654_read_dbi2(struct dw_pcie *pci, void __iomem *base, - u32 reg, size_t size) -{ - struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); - u32 val; - - ks_pcie_set_dbi_mode(ks_pcie); - dw_pcie_read(base + reg, size, &val); - ks_pcie_clear_dbi_mode(ks_pcie); - return val; -} - static void ks_pcie_am654_write_dbi2(struct dw_pcie *pci, void __iomem *base, u32 reg, size_t size, u32 val) { @@ -912,7 +895,6 @@ static const struct dw_pcie_ops ks_pcie_dw_pcie_ops = { .start_link = ks_pcie_start_link, .stop_link = ks_pcie_stop_link, .link_up = ks_pcie_link_up, - .read_dbi2 = ks_pcie_am654_read_dbi2, .write_dbi2 = ks_pcie_am654_write_dbi2, }; @@ -1125,31 +1107,6 @@ static int ks_pcie_am654_set_mode(struct device *dev, return 0; } -static void ks_pcie_set_link_speed(struct dw_pcie *pci, int link_speed) -{ - u32 val; - - dw_pcie_dbi_ro_wr_en(pci); - - val = dw_pcie_readl_dbi(pci, EXP_CAP_ID_OFFSET + PCI_EXP_LNKCAP); - if ((val & PCI_EXP_LNKCAP_SLS) != link_speed) { - val &= ~((u32)PCI_EXP_LNKCAP_SLS); - val |= link_speed; - dw_pcie_writel_dbi(pci, EXP_CAP_ID_OFFSET + PCI_EXP_LNKCAP, - val); - } - - val = dw_pcie_readl_dbi(pci, EXP_CAP_ID_OFFSET + PCI_EXP_LNKCTL2); - if ((val & PCI_EXP_LNKCAP_SLS) != link_speed) { - val &= ~((u32)PCI_EXP_LNKCAP_SLS); - val |= link_speed; - dw_pcie_writel_dbi(pci, EXP_CAP_ID_OFFSET + PCI_EXP_LNKCTL2, - val); - } - - dw_pcie_dbi_ro_wr_dis(pci); -} - static const struct ks_pcie_of_data ks_pcie_rc_of_data = { .host_ops = &ks_pcie_host_ops, .version = 0x365A, @@ -1197,13 +1154,10 @@ static int __init ks_pcie_probe(struct platform_device *pdev) struct keystone_pcie *ks_pcie; struct device_link **link; struct gpio_desc *gpiod; - void __iomem *atu_base; struct resource *res; unsigned int version; void __iomem *base; - u32 num_viewport; struct phy **phy; - int link_speed; u32 num_lanes; char name[10]; int ret; @@ -1320,29 +1274,12 @@ static int __init ks_pcie_probe(struct platform_device *pdev) goto err_get_sync; } - if (pci->version >= 0x480A) { - atu_base = devm_platform_ioremap_resource_byname(pdev, "atu"); - if (IS_ERR(atu_base)) { - ret = PTR_ERR(atu_base); - goto err_get_sync; - } - - pci->atu_base = atu_base; - + if (pci->version >= 0x480A) ret = ks_pcie_am654_set_mode(dev, mode); - if (ret < 0) - goto err_get_sync; - } else { + else ret = ks_pcie_set_mode(dev); - if (ret < 0) - goto err_get_sync; - } - - link_speed = of_pci_get_max_link_speed(np); - if (link_speed < 0) - link_speed = 2; - - ks_pcie_set_link_speed(pci, link_speed); + if (ret < 0) + goto err_get_sync; switch (mode) { case DW_PCIE_RC_TYPE: @@ -1351,12 +1288,6 @@ static int __init ks_pcie_probe(struct platform_device *pdev) goto err_get_sync; } - ret = of_property_read_u32(np, "num-viewport", &num_viewport); - if (ret < 0) { - dev_err(dev, "unable to read *num-viewport* property\n"); - goto err_get_sync; - } - /* * "Power Sequencing and Reset Signal Timings" table in * PCI EXPRESS CARD ELECTROMECHANICAL SPECIFICATION, REV. 2.0 @@ -1370,7 +1301,6 @@ static int __init ks_pcie_probe(struct platform_device *pdev) gpiod_set_value_cansleep(gpiod, 1); } - ks_pcie->num_viewport = num_viewport; pci->pp.ops = host_ops; ret = ks_pcie_add_pcie_port(ks_pcie, pdev); if (ret < 0) |