diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-22 12:41:00 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-22 12:41:00 -0700 |
commit | 00937f36b09e89c74e4a059dbb8acbf4b971d5eb (patch) | |
tree | ff2e5f5fa6736460437f57680405a20124d1e969 /drivers/pci/controller/dwc/pci-meson.c | |
parent | 96485e4462604744d66bf4301557d996d80b85eb (diff) | |
parent | 28e34e751f6c50098d9bcecb30c97634b6126730 (diff) | |
download | linux-00937f36b09e89c74e4a059dbb8acbf4b971d5eb.tar.bz2 |
Merge tag 'pci-v5.10-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas:
"Enumeration:
- Print IRQ number used by PCIe Link Bandwidth Notification (Dongdong
Liu)
- Add schedule point in pci_read_config() to reduce max latency
(Jiang Biao)
- Add Kconfig options for MPS/MRRS strategy (Jim Quinlan)
Resource management:
- Fix pci_iounmap() memory leak when !CONFIG_GENERIC_IOMAP (Lorenzo
Pieralisi)
PCIe native device hotplug:
- Reduce noisiness on hot removal (Lukas Wunner)
Power management:
- Revert "PCI/PM: Apply D2 delay as milliseconds, not microseconds"
that was done on the basis of spec typo (Bjorn Helgaas)
- Rename pci_dev.d3_delay to d3hot_delay to remove D3hot/D3cold
ambiguity (Krzysztof Wilczyński)
- Remove unused pcibios_pm_ops (Vaibhav Gupta)
IOMMU:
- Enable Translation Blocking for external devices to harden against
DMA attacks (Rajat Jain)
Error handling:
- Add an ACPI APEI notifier chain for vendor CPER records to enable
device-specific error handling (Shiju Jose)
ASPM:
- Remove struct aspm_register_info to simplify code (Saheed O.
Bolarinwa)
Amlogic Meson PCIe controller driver:
- Build as module by default (Kevin Hilman)
Ampere Altra PCIe controller driver:
- Add MCFG quirk to work around non-standard ECAM implementation
(Tuan Phan)
Broadcom iProc PCIe controller driver:
- Set affinity mask on MSI interrupts (Mark Tomlinson)
Broadcom STB PCIe controller driver:
- Make PCIE_BRCMSTB depend on ARCH_BRCMSTB (Jim Quinlan)
- Add DT bindings for more Brcmstb chips (Jim Quinlan)
- Add bcm7278 register info (Jim Quinlan)
- Add bcm7278 PERST# support (Jim Quinlan)
- Add suspend and resume pm_ops (Jim Quinlan)
- Add control of rescal reset (Jim Quinlan)
- Set additional internal memory DMA viewport sizes (Jim Quinlan)
- Accommodate MSI for older chips (Jim Quinlan)
- Set bus max burst size by chip type (Jim Quinlan)
- Add support for bcm7211, bcm7216, bcm7445, bcm7278 (Jim Quinlan)
Freescale i.MX6 PCIe controller driver:
- Use dev_err_probe() to reduce redundant messages (Anson Huang)
Freescale Layerscape PCIe controller driver:
- Enforce 4K DMA buffer alignment in endpoint test (Hou Zhiqiang)
- Add DT compatible strings for ls1088a, ls2088a (Xiaowei Bao)
- Add endpoint support for ls1088a, ls2088a (Xiaowei Bao)
- Add endpoint test support for lS1088a (Xiaowei Bao)
- Add MSI-X support for ls1088a (Xiaowei Bao)
HiSilicon HIP PCIe controller driver:
- Handle HIP-specific errors via ACPI APEI (Yicong Yang)
HiSilicon Kirin PCIe controller driver:
- Return -EPROBE_DEFER if the GPIO isn't ready (Bean Huo)
Intel VMD host bridge driver:
- Factor out physical offset, bus offset, IRQ domain, IRQ allocation
(Jon Derrick)
- Use generic PCI PM correctly (Jon Derrick)
Marvell Aardvark PCIe controller driver:
- Fix compilation on s390 (Pali Rohár)
- Implement driver 'remove' function and allow to build it as module
(Pali Rohár)
- Move PCIe reset card code to advk_pcie_train_link() (Pali Rohár)
- Convert mvebu a3700 internal SMCC firmware return codes to errno
(Pali Rohár)
- Fix initialization with old Marvell's Arm Trusted Firmware (Pali
Rohár)
Microsoft Hyper-V host bridge driver:
- Fix hibernation in case interrupts are not re-created (Dexuan Cui)
NVIDIA Tegra PCIe controller driver:
- Stop checking return value of debugfs_create() functions (Greg
Kroah-Hartman)
- Convert to use DEFINE_SEQ_ATTRIBUTE macro (Liu Shixin)
Qualcomm PCIe controller driver:
- Reset PCIe to work around Qsdk U-Boot issue (Ansuel Smith)
Renesas R-Car PCIe controller driver:
- Add DT documentation for r8a774a1, r8a774b1, r8a774e1 endpoints
(Lad Prabhakar)
- Add RZ/G2M, RZ/G2N, RZ/G2H IDs to endpoint test (Lad Prabhakar)
- Add DT support for r8a7742 (Lad Prabhakar)
Socionext UniPhier Pro5 controller driver:
- Add DT descriptions of iATU register (host and endpoint) (Kunihiko
Hayashi)
Synopsys DesignWare PCIe controller driver:
- Add link up check in dw_child_pcie_ops.map_bus() (racy, but seems
unavoidable) (Hou Zhiqiang)
- Fix endpoint Header Type check so multi-function devices work (Hou
Zhiqiang)
- Skip PCIE_MSI_INTR0* programming if MSI is disabled (Jisheng Zhang)
- Stop leaking MSI page in suspend/resume (Jisheng Zhang)
- Add common iATU register support instead of keystone-specific code
(Kunihiko Hayashi)
- Major config space access and other cleanups in dwc core and
drivers that use it (al, exynos, histb, imx6, intel-gw, keystone,
kirin, meson, qcom, tegra) (Rob Herring)
- Add multiple PFs support for endpoint (Xiaowei Bao)
- Add MSI-X doorbell mode in endpoint mode (Xiaowei Bao)
Miscellaneous:
- Use fallthrough pseudo-keyword (Gustavo A. R. Silva)
- Fix "0 used as NULL pointer" warnings (Gustavo Pimentel)
- Fix "cast truncates bits from constant value" warnings (Gustavo
Pimentel)
- Remove redundant zeroing for sg_init_table() (Julia Lawall)
- Use scnprintf(), not snprintf(), in sysfs "show" functions
(Krzysztof Wilczyński)
- Remove unused assignments (Krzysztof Wilczyński)
- Fix "0 used as NULL pointer" warning (Krzysztof Wilczyński)
- Simplify bool comparisons (Krzysztof Wilczyński)
- Use for_each_child_of_node() and for_each_node_by_name() (Qinglang
Miao)
- Simplify return expressions (Qinglang Miao)"
* tag 'pci-v5.10-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (147 commits)
PCI: vmd: Update VMD PM to correctly use generic PCI PM
PCI: vmd: Create IRQ allocation helper
PCI: vmd: Create IRQ Domain configuration helper
PCI: vmd: Create bus offset configuration helper
PCI: vmd: Create physical offset helper
PCI: v3-semi: Remove unneeded break
PCI: dwc: Add link up check in dw_child_pcie_ops.map_bus()
PCI/ASPM: Remove struct pcie_link_state.l1ss
PCI/ASPM: Remove struct aspm_register_info.l1ss_cap
PCI/ASPM: Pass L1SS Capabilities value, not struct aspm_register_info
PCI/ASPM: Remove struct aspm_register_info.l1ss_ctl1
PCI/ASPM: Remove struct aspm_register_info.l1ss_ctl2 (unused)
PCI/ASPM: Remove struct aspm_register_info.l1ss_cap_ptr
PCI/ASPM: Remove struct aspm_register_info.latency_encoding
PCI/ASPM: Remove struct aspm_register_info.enabled
PCI/ASPM: Remove struct aspm_register_info.support
PCI/ASPM: Use 'parent' and 'child' for readability
PCI/ASPM: Move LTR path check to where it's used
PCI/ASPM: Move pci_clear_and_set_dword() earlier
PCI: dwc: Fix MSI page leakage in suspend/resume
...
Diffstat (limited to 'drivers/pci/controller/dwc/pci-meson.c')
-rw-r--r-- | drivers/pci/controller/dwc/pci-meson.c | 164 |
1 files changed, 44 insertions, 120 deletions
diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c index 4f183b96afbb..1913dc2c8fa0 100644 --- a/drivers/pci/controller/dwc/pci-meson.c +++ b/drivers/pci/controller/dwc/pci-meson.c @@ -17,37 +17,13 @@ #include <linux/resource.h> #include <linux/types.h> #include <linux/phy/phy.h> +#include <linux/module.h> #include "pcie-designware.h" #define to_meson_pcie(x) dev_get_drvdata((x)->dev) -/* External local bus interface registers */ -#define PLR_OFFSET 0x700 -#define PCIE_PORT_LINK_CTRL_OFF (PLR_OFFSET + 0x10) -#define FAST_LINK_MODE BIT(7) -#define LINK_CAPABLE_MASK GENMASK(21, 16) -#define LINK_CAPABLE_X1 BIT(16) - -#define PCIE_GEN2_CTRL_OFF (PLR_OFFSET + 0x10c) -#define NUM_OF_LANES_MASK GENMASK(12, 8) -#define NUM_OF_LANES_X1 BIT(8) -#define DIRECT_SPEED_CHANGE BIT(17) - -#define TYPE1_HDR_OFFSET 0x0 -#define PCIE_STATUS_COMMAND (TYPE1_HDR_OFFSET + 0x04) -#define PCI_IO_EN BIT(0) -#define PCI_MEM_SPACE_EN BIT(1) -#define PCI_BUS_MASTER_EN BIT(2) - -#define PCIE_BASE_ADDR0 (TYPE1_HDR_OFFSET + 0x10) -#define PCIE_BASE_ADDR1 (TYPE1_HDR_OFFSET + 0x14) - -#define PCIE_CAP_OFFSET 0x70 -#define PCIE_DEV_CTRL_DEV_STUS (PCIE_CAP_OFFSET + 0x08) -#define PCIE_CAP_MAX_PAYLOAD_MASK GENMASK(7, 5) #define PCIE_CAP_MAX_PAYLOAD_SIZE(x) ((x) << 5) -#define PCIE_CAP_MAX_READ_REQ_MASK GENMASK(14, 12) #define PCIE_CAP_MAX_READ_REQ_SIZE(x) ((x) << 12) /* PCIe specific config registers */ @@ -77,11 +53,6 @@ enum pcie_data_rate { PCIE_GEN4 }; -struct meson_pcie_mem_res { - void __iomem *elbi_base; - void __iomem *cfg_base; -}; - struct meson_pcie_clk_res { struct clk *clk; struct clk *port_clk; @@ -95,7 +66,7 @@ struct meson_pcie_rc_reset { struct meson_pcie { struct dw_pcie pci; - struct meson_pcie_mem_res mem_res; + void __iomem *cfg_base; struct meson_pcie_clk_res clk_res; struct meson_pcie_rc_reset mrst; struct gpio_desc *reset_gpio; @@ -134,28 +105,18 @@ static int meson_pcie_get_resets(struct meson_pcie *mp) return 0; } -static void __iomem *meson_pcie_get_mem(struct platform_device *pdev, - struct meson_pcie *mp, - const char *id) -{ - struct device *dev = mp->pci.dev; - struct resource *res; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, id); - - return devm_ioremap_resource(dev, res); -} - static int meson_pcie_get_mems(struct platform_device *pdev, struct meson_pcie *mp) { - mp->mem_res.elbi_base = meson_pcie_get_mem(pdev, mp, "elbi"); - if (IS_ERR(mp->mem_res.elbi_base)) - return PTR_ERR(mp->mem_res.elbi_base); + struct dw_pcie *pci = &mp->pci; + + pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "elbi"); + if (IS_ERR(pci->dbi_base)) + return PTR_ERR(pci->dbi_base); - mp->mem_res.cfg_base = meson_pcie_get_mem(pdev, mp, "cfg"); - if (IS_ERR(mp->mem_res.cfg_base)) - return PTR_ERR(mp->mem_res.cfg_base); + mp->cfg_base = devm_platform_ioremap_resource_byname(pdev, "cfg"); + if (IS_ERR(mp->cfg_base)) + return PTR_ERR(mp->cfg_base); return 0; } @@ -253,24 +214,14 @@ static int meson_pcie_probe_clocks(struct meson_pcie *mp) return 0; } -static inline void meson_elb_writel(struct meson_pcie *mp, u32 val, u32 reg) -{ - writel(val, mp->mem_res.elbi_base + reg); -} - -static inline u32 meson_elb_readl(struct meson_pcie *mp, u32 reg) -{ - return readl(mp->mem_res.elbi_base + reg); -} - static inline u32 meson_cfg_readl(struct meson_pcie *mp, u32 reg) { - return readl(mp->mem_res.cfg_base + reg); + return readl(mp->cfg_base + reg); } static inline void meson_cfg_writel(struct meson_pcie *mp, u32 val, u32 reg) { - writel(val, mp->mem_res.cfg_base + reg); + writel(val, mp->cfg_base + reg); } static void meson_pcie_assert_reset(struct meson_pcie *mp) @@ -287,25 +238,6 @@ static void meson_pcie_init_dw(struct meson_pcie *mp) val = meson_cfg_readl(mp, PCIE_CFG0); val |= APP_LTSSM_ENABLE; meson_cfg_writel(mp, val, PCIE_CFG0); - - val = meson_elb_readl(mp, PCIE_PORT_LINK_CTRL_OFF); - val &= ~(LINK_CAPABLE_MASK | FAST_LINK_MODE); - meson_elb_writel(mp, val, PCIE_PORT_LINK_CTRL_OFF); - - val = meson_elb_readl(mp, PCIE_PORT_LINK_CTRL_OFF); - val |= LINK_CAPABLE_X1; - meson_elb_writel(mp, val, PCIE_PORT_LINK_CTRL_OFF); - - val = meson_elb_readl(mp, PCIE_GEN2_CTRL_OFF); - val &= ~NUM_OF_LANES_MASK; - meson_elb_writel(mp, val, PCIE_GEN2_CTRL_OFF); - - val = meson_elb_readl(mp, PCIE_GEN2_CTRL_OFF); - val |= NUM_OF_LANES_X1 | DIRECT_SPEED_CHANGE; - meson_elb_writel(mp, val, PCIE_GEN2_CTRL_OFF); - - meson_elb_writel(mp, 0x0, PCIE_BASE_ADDR0); - meson_elb_writel(mp, 0x0, PCIE_BASE_ADDR1); } static int meson_size_to_payload(struct meson_pcie *mp, int size) @@ -327,37 +259,34 @@ static int meson_size_to_payload(struct meson_pcie *mp, int size) static void meson_set_max_payload(struct meson_pcie *mp, int size) { + struct dw_pcie *pci = &mp->pci; u32 val; + u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); int max_payload_size = meson_size_to_payload(mp, size); - val = meson_elb_readl(mp, PCIE_DEV_CTRL_DEV_STUS); - val &= ~PCIE_CAP_MAX_PAYLOAD_MASK; - meson_elb_writel(mp, val, PCIE_DEV_CTRL_DEV_STUS); + val = dw_pcie_readl_dbi(pci, offset + PCI_EXP_DEVCTL); + val &= ~PCI_EXP_DEVCTL_PAYLOAD; + dw_pcie_writel_dbi(pci, offset + PCI_EXP_DEVCTL, val); - val = meson_elb_readl(mp, PCIE_DEV_CTRL_DEV_STUS); + val = dw_pcie_readl_dbi(pci, offset + PCI_EXP_DEVCTL); val |= PCIE_CAP_MAX_PAYLOAD_SIZE(max_payload_size); - meson_elb_writel(mp, val, PCIE_DEV_CTRL_DEV_STUS); + dw_pcie_writel_dbi(pci, offset + PCI_EXP_DEVCTL, val); } static void meson_set_max_rd_req_size(struct meson_pcie *mp, int size) { + struct dw_pcie *pci = &mp->pci; u32 val; + u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); int max_rd_req_size = meson_size_to_payload(mp, size); - val = meson_elb_readl(mp, PCIE_DEV_CTRL_DEV_STUS); - val &= ~PCIE_CAP_MAX_READ_REQ_MASK; - meson_elb_writel(mp, val, PCIE_DEV_CTRL_DEV_STUS); + val = dw_pcie_readl_dbi(pci, offset + PCI_EXP_DEVCTL); + val &= ~PCI_EXP_DEVCTL_READRQ; + dw_pcie_writel_dbi(pci, offset + PCI_EXP_DEVCTL, val); - val = meson_elb_readl(mp, PCIE_DEV_CTRL_DEV_STUS); + val = dw_pcie_readl_dbi(pci, offset + PCI_EXP_DEVCTL); val |= PCIE_CAP_MAX_READ_REQ_SIZE(max_rd_req_size); - meson_elb_writel(mp, val, PCIE_DEV_CTRL_DEV_STUS); -} - -static inline void meson_enable_memory_space(struct meson_pcie *mp) -{ - /* Set the RC Bus Master, Memory Space and I/O Space enables */ - meson_elb_writel(mp, PCI_IO_EN | PCI_MEM_SPACE_EN | PCI_BUS_MASTER_EN, - PCIE_STATUS_COMMAND); + dw_pcie_writel_dbi(pci, offset + PCI_EXP_DEVCTL, val); } static int meson_pcie_establish_link(struct meson_pcie *mp) @@ -370,26 +299,18 @@ static int meson_pcie_establish_link(struct meson_pcie *mp) meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE); dw_pcie_setup_rc(pp); - meson_enable_memory_space(mp); meson_pcie_assert_reset(mp); return dw_pcie_wait_for_link(pci); } -static void meson_pcie_enable_interrupts(struct meson_pcie *mp) +static int meson_pcie_rd_own_conf(struct pci_bus *bus, u32 devfn, + int where, int size, u32 *val) { - if (IS_ENABLED(CONFIG_PCI_MSI)) - dw_pcie_msi_init(&mp->pci.pp); -} - -static int meson_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, - u32 *val) -{ - struct dw_pcie *pci = to_dw_pcie_from_pp(pp); int ret; - ret = dw_pcie_read(pci->dbi_base + where, size, val); + ret = pci_generic_config_read(bus, devfn, where, size, val); if (ret != PCIBIOS_SUCCESSFUL) return ret; @@ -410,13 +331,11 @@ static int meson_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, return PCIBIOS_SUCCESSFUL; } -static int meson_pcie_wr_own_conf(struct pcie_port *pp, int where, - int size, u32 val) -{ - struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - - return dw_pcie_write(pci->dbi_base + where, size, val); -} +static struct pci_ops meson_pci_ops = { + .map_bus = dw_pcie_own_conf_map_bus, + .read = meson_pcie_rd_own_conf, + .write = pci_generic_config_write, +}; static int meson_pcie_link_up(struct dw_pcie *pci) { @@ -463,18 +382,18 @@ static int meson_pcie_host_init(struct pcie_port *pp) struct meson_pcie *mp = to_meson_pcie(pci); int ret; + pp->bridge->ops = &meson_pci_ops; + ret = meson_pcie_establish_link(mp); if (ret) return ret; - meson_pcie_enable_interrupts(mp); + dw_pcie_msi_init(pp); return 0; } static const struct dw_pcie_host_ops meson_pcie_host_ops = { - .rd_own_conf = meson_pcie_rd_own_conf, - .wr_own_conf = meson_pcie_wr_own_conf, .host_init = meson_pcie_host_init, }; @@ -493,7 +412,6 @@ static int meson_add_pcie_port(struct meson_pcie *mp, } pp->ops = &meson_pcie_host_ops; - pci->dbi_base = mp->mem_res.elbi_base; ret = dw_pcie_host_init(pp); if (ret) { @@ -522,6 +440,7 @@ static int meson_pcie_probe(struct platform_device *pdev) pci = &mp->pci; pci->dev = dev; pci->ops = &dw_pcie_ops; + pci->num_lanes = 1; mp->phy = devm_phy_get(dev, "pcie"); if (IS_ERR(mp->phy)) { @@ -589,6 +508,7 @@ static const struct of_device_id meson_pcie_of_match[] = { }, {}, }; +MODULE_DEVICE_TABLE(of, meson_pcie_of_match); static struct platform_driver meson_pcie_driver = { .probe = meson_pcie_probe, @@ -598,4 +518,8 @@ static struct platform_driver meson_pcie_driver = { }, }; -builtin_platform_driver(meson_pcie_driver); +module_platform_driver(meson_pcie_driver); + +MODULE_AUTHOR("Yue Wang <yue.wang@amlogic.com>"); +MODULE_DESCRIPTION("Amlogic PCIe Controller driver"); +MODULE_LICENSE("GPL v2"); |