162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * PCIe host controller driver for Intel Gateway SoCs 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2019 Intel Corporation. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/bitfield.h> 962306a36Sopenharmony_ci#include <linux/clk.h> 1062306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 1162306a36Sopenharmony_ci#include <linux/iopoll.h> 1262306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 1362306a36Sopenharmony_ci#include <linux/pci_regs.h> 1462306a36Sopenharmony_ci#include <linux/phy/phy.h> 1562306a36Sopenharmony_ci#include <linux/platform_device.h> 1662306a36Sopenharmony_ci#include <linux/property.h> 1762306a36Sopenharmony_ci#include <linux/reset.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "../../pci.h" 2062306a36Sopenharmony_ci#include "pcie-designware.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define PORT_AFR_N_FTS_GEN12_DFT (SZ_128 - 1) 2362306a36Sopenharmony_ci#define PORT_AFR_N_FTS_GEN3 180 2462306a36Sopenharmony_ci#define PORT_AFR_N_FTS_GEN4 196 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* PCIe Application logic Registers */ 2762306a36Sopenharmony_ci#define PCIE_APP_CCR 0x10 2862306a36Sopenharmony_ci#define PCIE_APP_CCR_LTSSM_ENABLE BIT(0) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define PCIE_APP_MSG_CR 0x30 3162306a36Sopenharmony_ci#define PCIE_APP_MSG_XMT_PM_TURNOFF BIT(0) 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define PCIE_APP_PMC 0x44 3462306a36Sopenharmony_ci#define PCIE_APP_PMC_IN_L2 BIT(20) 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define PCIE_APP_IRNEN 0xF4 3762306a36Sopenharmony_ci#define PCIE_APP_IRNCR 0xF8 3862306a36Sopenharmony_ci#define PCIE_APP_IRN_AER_REPORT BIT(0) 3962306a36Sopenharmony_ci#define PCIE_APP_IRN_PME BIT(2) 4062306a36Sopenharmony_ci#define PCIE_APP_IRN_RX_VDM_MSG BIT(4) 4162306a36Sopenharmony_ci#define PCIE_APP_IRN_PM_TO_ACK BIT(9) 4262306a36Sopenharmony_ci#define PCIE_APP_IRN_LINK_AUTO_BW_STAT BIT(11) 4362306a36Sopenharmony_ci#define PCIE_APP_IRN_BW_MGT BIT(12) 4462306a36Sopenharmony_ci#define PCIE_APP_IRN_INTA BIT(13) 4562306a36Sopenharmony_ci#define PCIE_APP_IRN_INTB BIT(14) 4662306a36Sopenharmony_ci#define PCIE_APP_IRN_INTC BIT(15) 4762306a36Sopenharmony_ci#define PCIE_APP_IRN_INTD BIT(16) 4862306a36Sopenharmony_ci#define PCIE_APP_IRN_MSG_LTR BIT(18) 4962306a36Sopenharmony_ci#define PCIE_APP_IRN_SYS_ERR_RC BIT(29) 5062306a36Sopenharmony_ci#define PCIE_APP_INTX_OFST 12 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#define PCIE_APP_IRN_INT \ 5362306a36Sopenharmony_ci (PCIE_APP_IRN_AER_REPORT | PCIE_APP_IRN_PME | \ 5462306a36Sopenharmony_ci PCIE_APP_IRN_RX_VDM_MSG | PCIE_APP_IRN_SYS_ERR_RC | \ 5562306a36Sopenharmony_ci PCIE_APP_IRN_PM_TO_ACK | PCIE_APP_IRN_MSG_LTR | \ 5662306a36Sopenharmony_ci PCIE_APP_IRN_BW_MGT | PCIE_APP_IRN_LINK_AUTO_BW_STAT | \ 5762306a36Sopenharmony_ci PCIE_APP_IRN_INTA | PCIE_APP_IRN_INTB | \ 5862306a36Sopenharmony_ci PCIE_APP_IRN_INTC | PCIE_APP_IRN_INTD) 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define BUS_IATU_OFFSET SZ_256M 6162306a36Sopenharmony_ci#define RESET_INTERVAL_MS 100 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistruct intel_pcie { 6462306a36Sopenharmony_ci struct dw_pcie pci; 6562306a36Sopenharmony_ci void __iomem *app_base; 6662306a36Sopenharmony_ci struct gpio_desc *reset_gpio; 6762306a36Sopenharmony_ci u32 rst_intrvl; 6862306a36Sopenharmony_ci struct clk *core_clk; 6962306a36Sopenharmony_ci struct reset_control *core_rst; 7062306a36Sopenharmony_ci struct phy *phy; 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic void pcie_update_bits(void __iomem *base, u32 ofs, u32 mask, u32 val) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci u32 old; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci old = readl(base + ofs); 7862306a36Sopenharmony_ci val = (old & ~mask) | (val & mask); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci if (val != old) 8162306a36Sopenharmony_ci writel(val, base + ofs); 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic inline void pcie_app_wr(struct intel_pcie *pcie, u32 ofs, u32 val) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci writel(val, pcie->app_base + ofs); 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic void pcie_app_wr_mask(struct intel_pcie *pcie, u32 ofs, 9062306a36Sopenharmony_ci u32 mask, u32 val) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci pcie_update_bits(pcie->app_base, ofs, mask, val); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic inline u32 pcie_rc_cfg_rd(struct intel_pcie *pcie, u32 ofs) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci return dw_pcie_readl_dbi(&pcie->pci, ofs); 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic inline void pcie_rc_cfg_wr(struct intel_pcie *pcie, u32 ofs, u32 val) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci dw_pcie_writel_dbi(&pcie->pci, ofs, val); 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic void pcie_rc_cfg_wr_mask(struct intel_pcie *pcie, u32 ofs, 10662306a36Sopenharmony_ci u32 mask, u32 val) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci pcie_update_bits(pcie->pci.dbi_base, ofs, mask, val); 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic void intel_pcie_ltssm_enable(struct intel_pcie *pcie) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci pcie_app_wr_mask(pcie, PCIE_APP_CCR, PCIE_APP_CCR_LTSSM_ENABLE, 11462306a36Sopenharmony_ci PCIE_APP_CCR_LTSSM_ENABLE); 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic void intel_pcie_ltssm_disable(struct intel_pcie *pcie) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci pcie_app_wr_mask(pcie, PCIE_APP_CCR, PCIE_APP_CCR_LTSSM_ENABLE, 0); 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic void intel_pcie_link_setup(struct intel_pcie *pcie) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci u32 val; 12562306a36Sopenharmony_ci u8 offset = dw_pcie_find_capability(&pcie->pci, PCI_CAP_ID_EXP); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci val = pcie_rc_cfg_rd(pcie, offset + PCI_EXP_LNKCTL); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci val &= ~(PCI_EXP_LNKCTL_LD | PCI_EXP_LNKCTL_ASPMC); 13062306a36Sopenharmony_ci pcie_rc_cfg_wr(pcie, offset + PCI_EXP_LNKCTL, val); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic void intel_pcie_init_n_fts(struct dw_pcie *pci) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci switch (pci->link_gen) { 13662306a36Sopenharmony_ci case 3: 13762306a36Sopenharmony_ci pci->n_fts[1] = PORT_AFR_N_FTS_GEN3; 13862306a36Sopenharmony_ci break; 13962306a36Sopenharmony_ci case 4: 14062306a36Sopenharmony_ci pci->n_fts[1] = PORT_AFR_N_FTS_GEN4; 14162306a36Sopenharmony_ci break; 14262306a36Sopenharmony_ci default: 14362306a36Sopenharmony_ci pci->n_fts[1] = PORT_AFR_N_FTS_GEN12_DFT; 14462306a36Sopenharmony_ci break; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci pci->n_fts[0] = PORT_AFR_N_FTS_GEN12_DFT; 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic int intel_pcie_ep_rst_init(struct intel_pcie *pcie) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci struct device *dev = pcie->pci.dev; 15262306a36Sopenharmony_ci int ret; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci pcie->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 15562306a36Sopenharmony_ci if (IS_ERR(pcie->reset_gpio)) { 15662306a36Sopenharmony_ci ret = PTR_ERR(pcie->reset_gpio); 15762306a36Sopenharmony_ci if (ret != -EPROBE_DEFER) 15862306a36Sopenharmony_ci dev_err(dev, "Failed to request PCIe GPIO: %d\n", ret); 15962306a36Sopenharmony_ci return ret; 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci /* Make initial reset last for 100us */ 16362306a36Sopenharmony_ci usleep_range(100, 200); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci return 0; 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic void intel_pcie_core_rst_assert(struct intel_pcie *pcie) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci reset_control_assert(pcie->core_rst); 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cistatic void intel_pcie_core_rst_deassert(struct intel_pcie *pcie) 17462306a36Sopenharmony_ci{ 17562306a36Sopenharmony_ci /* 17662306a36Sopenharmony_ci * One micro-second delay to make sure the reset pulse 17762306a36Sopenharmony_ci * wide enough so that core reset is clean. 17862306a36Sopenharmony_ci */ 17962306a36Sopenharmony_ci udelay(1); 18062306a36Sopenharmony_ci reset_control_deassert(pcie->core_rst); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci /* 18362306a36Sopenharmony_ci * Some SoC core reset also reset PHY, more delay needed 18462306a36Sopenharmony_ci * to make sure the reset process is done. 18562306a36Sopenharmony_ci */ 18662306a36Sopenharmony_ci usleep_range(1000, 2000); 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic void intel_pcie_device_rst_assert(struct intel_pcie *pcie) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci gpiod_set_value_cansleep(pcie->reset_gpio, 1); 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistatic void intel_pcie_device_rst_deassert(struct intel_pcie *pcie) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci msleep(pcie->rst_intrvl); 19762306a36Sopenharmony_ci gpiod_set_value_cansleep(pcie->reset_gpio, 0); 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic void intel_pcie_core_irq_disable(struct intel_pcie *pcie) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci pcie_app_wr(pcie, PCIE_APP_IRNEN, 0); 20362306a36Sopenharmony_ci pcie_app_wr(pcie, PCIE_APP_IRNCR, PCIE_APP_IRN_INT); 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic int intel_pcie_get_resources(struct platform_device *pdev) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci struct intel_pcie *pcie = platform_get_drvdata(pdev); 20962306a36Sopenharmony_ci struct dw_pcie *pci = &pcie->pci; 21062306a36Sopenharmony_ci struct device *dev = pci->dev; 21162306a36Sopenharmony_ci int ret; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci pcie->core_clk = devm_clk_get(dev, NULL); 21462306a36Sopenharmony_ci if (IS_ERR(pcie->core_clk)) { 21562306a36Sopenharmony_ci ret = PTR_ERR(pcie->core_clk); 21662306a36Sopenharmony_ci if (ret != -EPROBE_DEFER) 21762306a36Sopenharmony_ci dev_err(dev, "Failed to get clks: %d\n", ret); 21862306a36Sopenharmony_ci return ret; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci pcie->core_rst = devm_reset_control_get(dev, NULL); 22262306a36Sopenharmony_ci if (IS_ERR(pcie->core_rst)) { 22362306a36Sopenharmony_ci ret = PTR_ERR(pcie->core_rst); 22462306a36Sopenharmony_ci if (ret != -EPROBE_DEFER) 22562306a36Sopenharmony_ci dev_err(dev, "Failed to get resets: %d\n", ret); 22662306a36Sopenharmony_ci return ret; 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci ret = device_property_read_u32(dev, "reset-assert-ms", 23062306a36Sopenharmony_ci &pcie->rst_intrvl); 23162306a36Sopenharmony_ci if (ret) 23262306a36Sopenharmony_ci pcie->rst_intrvl = RESET_INTERVAL_MS; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci pcie->app_base = devm_platform_ioremap_resource_byname(pdev, "app"); 23562306a36Sopenharmony_ci if (IS_ERR(pcie->app_base)) 23662306a36Sopenharmony_ci return PTR_ERR(pcie->app_base); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci pcie->phy = devm_phy_get(dev, "pcie"); 23962306a36Sopenharmony_ci if (IS_ERR(pcie->phy)) { 24062306a36Sopenharmony_ci ret = PTR_ERR(pcie->phy); 24162306a36Sopenharmony_ci if (ret != -EPROBE_DEFER) 24262306a36Sopenharmony_ci dev_err(dev, "Couldn't get pcie-phy: %d\n", ret); 24362306a36Sopenharmony_ci return ret; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci return 0; 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic int intel_pcie_wait_l2(struct intel_pcie *pcie) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci u32 value; 25262306a36Sopenharmony_ci int ret; 25362306a36Sopenharmony_ci struct dw_pcie *pci = &pcie->pci; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci if (pci->link_gen < 3) 25662306a36Sopenharmony_ci return 0; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci /* Send PME_TURN_OFF message */ 25962306a36Sopenharmony_ci pcie_app_wr_mask(pcie, PCIE_APP_MSG_CR, PCIE_APP_MSG_XMT_PM_TURNOFF, 26062306a36Sopenharmony_ci PCIE_APP_MSG_XMT_PM_TURNOFF); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci /* Read PMC status and wait for falling into L2 link state */ 26362306a36Sopenharmony_ci ret = readl_poll_timeout(pcie->app_base + PCIE_APP_PMC, value, 26462306a36Sopenharmony_ci value & PCIE_APP_PMC_IN_L2, 20, 26562306a36Sopenharmony_ci jiffies_to_usecs(5 * HZ)); 26662306a36Sopenharmony_ci if (ret) 26762306a36Sopenharmony_ci dev_err(pcie->pci.dev, "PCIe link enter L2 timeout!\n"); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci return ret; 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic void intel_pcie_turn_off(struct intel_pcie *pcie) 27362306a36Sopenharmony_ci{ 27462306a36Sopenharmony_ci if (dw_pcie_link_up(&pcie->pci)) 27562306a36Sopenharmony_ci intel_pcie_wait_l2(pcie); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci /* Put endpoint device in reset state */ 27862306a36Sopenharmony_ci intel_pcie_device_rst_assert(pcie); 27962306a36Sopenharmony_ci pcie_rc_cfg_wr_mask(pcie, PCI_COMMAND, PCI_COMMAND_MEMORY, 0); 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic int intel_pcie_host_setup(struct intel_pcie *pcie) 28362306a36Sopenharmony_ci{ 28462306a36Sopenharmony_ci int ret; 28562306a36Sopenharmony_ci struct dw_pcie *pci = &pcie->pci; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci intel_pcie_core_rst_assert(pcie); 28862306a36Sopenharmony_ci intel_pcie_device_rst_assert(pcie); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci ret = phy_init(pcie->phy); 29162306a36Sopenharmony_ci if (ret) 29262306a36Sopenharmony_ci return ret; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci intel_pcie_core_rst_deassert(pcie); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci ret = clk_prepare_enable(pcie->core_clk); 29762306a36Sopenharmony_ci if (ret) { 29862306a36Sopenharmony_ci dev_err(pcie->pci.dev, "Core clock enable failed: %d\n", ret); 29962306a36Sopenharmony_ci goto clk_err; 30062306a36Sopenharmony_ci } 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci pci->atu_base = pci->dbi_base + 0xC0000; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci intel_pcie_ltssm_disable(pcie); 30562306a36Sopenharmony_ci intel_pcie_link_setup(pcie); 30662306a36Sopenharmony_ci intel_pcie_init_n_fts(pci); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci ret = dw_pcie_setup_rc(&pci->pp); 30962306a36Sopenharmony_ci if (ret) 31062306a36Sopenharmony_ci goto app_init_err; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci dw_pcie_upconfig_setup(pci); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci intel_pcie_device_rst_deassert(pcie); 31562306a36Sopenharmony_ci intel_pcie_ltssm_enable(pcie); 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci ret = dw_pcie_wait_for_link(pci); 31862306a36Sopenharmony_ci if (ret) 31962306a36Sopenharmony_ci goto app_init_err; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci /* Enable integrated interrupts */ 32262306a36Sopenharmony_ci pcie_app_wr_mask(pcie, PCIE_APP_IRNEN, PCIE_APP_IRN_INT, 32362306a36Sopenharmony_ci PCIE_APP_IRN_INT); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci return 0; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ciapp_init_err: 32862306a36Sopenharmony_ci clk_disable_unprepare(pcie->core_clk); 32962306a36Sopenharmony_ciclk_err: 33062306a36Sopenharmony_ci intel_pcie_core_rst_assert(pcie); 33162306a36Sopenharmony_ci phy_exit(pcie->phy); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci return ret; 33462306a36Sopenharmony_ci} 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_cistatic void __intel_pcie_remove(struct intel_pcie *pcie) 33762306a36Sopenharmony_ci{ 33862306a36Sopenharmony_ci intel_pcie_core_irq_disable(pcie); 33962306a36Sopenharmony_ci intel_pcie_turn_off(pcie); 34062306a36Sopenharmony_ci clk_disable_unprepare(pcie->core_clk); 34162306a36Sopenharmony_ci intel_pcie_core_rst_assert(pcie); 34262306a36Sopenharmony_ci phy_exit(pcie->phy); 34362306a36Sopenharmony_ci} 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_cistatic void intel_pcie_remove(struct platform_device *pdev) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci struct intel_pcie *pcie = platform_get_drvdata(pdev); 34862306a36Sopenharmony_ci struct dw_pcie_rp *pp = &pcie->pci.pp; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci dw_pcie_host_deinit(pp); 35162306a36Sopenharmony_ci __intel_pcie_remove(pcie); 35262306a36Sopenharmony_ci} 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_cistatic int intel_pcie_suspend_noirq(struct device *dev) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci struct intel_pcie *pcie = dev_get_drvdata(dev); 35762306a36Sopenharmony_ci int ret; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci intel_pcie_core_irq_disable(pcie); 36062306a36Sopenharmony_ci ret = intel_pcie_wait_l2(pcie); 36162306a36Sopenharmony_ci if (ret) 36262306a36Sopenharmony_ci return ret; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci phy_exit(pcie->phy); 36562306a36Sopenharmony_ci clk_disable_unprepare(pcie->core_clk); 36662306a36Sopenharmony_ci return ret; 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic int intel_pcie_resume_noirq(struct device *dev) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci struct intel_pcie *pcie = dev_get_drvdata(dev); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci return intel_pcie_host_setup(pcie); 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistatic int intel_pcie_rc_init(struct dw_pcie_rp *pp) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 37962306a36Sopenharmony_ci struct intel_pcie *pcie = dev_get_drvdata(pci->dev); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci return intel_pcie_host_setup(pcie); 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_cistatic u64 intel_pcie_cpu_addr(struct dw_pcie *pcie, u64 cpu_addr) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci return cpu_addr + BUS_IATU_OFFSET; 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_cistatic const struct dw_pcie_ops intel_pcie_ops = { 39062306a36Sopenharmony_ci .cpu_addr_fixup = intel_pcie_cpu_addr, 39162306a36Sopenharmony_ci}; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_cistatic const struct dw_pcie_host_ops intel_pcie_dw_ops = { 39462306a36Sopenharmony_ci .host_init = intel_pcie_rc_init, 39562306a36Sopenharmony_ci}; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_cistatic int intel_pcie_probe(struct platform_device *pdev) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci struct device *dev = &pdev->dev; 40062306a36Sopenharmony_ci struct intel_pcie *pcie; 40162306a36Sopenharmony_ci struct dw_pcie_rp *pp; 40262306a36Sopenharmony_ci struct dw_pcie *pci; 40362306a36Sopenharmony_ci int ret; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); 40662306a36Sopenharmony_ci if (!pcie) 40762306a36Sopenharmony_ci return -ENOMEM; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci platform_set_drvdata(pdev, pcie); 41062306a36Sopenharmony_ci pci = &pcie->pci; 41162306a36Sopenharmony_ci pci->dev = dev; 41262306a36Sopenharmony_ci pp = &pci->pp; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci ret = intel_pcie_get_resources(pdev); 41562306a36Sopenharmony_ci if (ret) 41662306a36Sopenharmony_ci return ret; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci ret = intel_pcie_ep_rst_init(pcie); 41962306a36Sopenharmony_ci if (ret) 42062306a36Sopenharmony_ci return ret; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci pci->ops = &intel_pcie_ops; 42362306a36Sopenharmony_ci pp->ops = &intel_pcie_dw_ops; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci ret = dw_pcie_host_init(pp); 42662306a36Sopenharmony_ci if (ret) { 42762306a36Sopenharmony_ci dev_err(dev, "Cannot initialize host\n"); 42862306a36Sopenharmony_ci return ret; 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci return 0; 43262306a36Sopenharmony_ci} 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_cistatic const struct dev_pm_ops intel_pcie_pm_ops = { 43562306a36Sopenharmony_ci NOIRQ_SYSTEM_SLEEP_PM_OPS(intel_pcie_suspend_noirq, 43662306a36Sopenharmony_ci intel_pcie_resume_noirq) 43762306a36Sopenharmony_ci}; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic const struct of_device_id of_intel_pcie_match[] = { 44062306a36Sopenharmony_ci { .compatible = "intel,lgm-pcie" }, 44162306a36Sopenharmony_ci {} 44262306a36Sopenharmony_ci}; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cistatic struct platform_driver intel_pcie_driver = { 44562306a36Sopenharmony_ci .probe = intel_pcie_probe, 44662306a36Sopenharmony_ci .remove_new = intel_pcie_remove, 44762306a36Sopenharmony_ci .driver = { 44862306a36Sopenharmony_ci .name = "intel-gw-pcie", 44962306a36Sopenharmony_ci .of_match_table = of_intel_pcie_match, 45062306a36Sopenharmony_ci .pm = &intel_pcie_pm_ops, 45162306a36Sopenharmony_ci }, 45262306a36Sopenharmony_ci}; 45362306a36Sopenharmony_cibuiltin_platform_driver(intel_pcie_driver); 454