mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-17 13:58:46 +00:00
Merge branch 'pci/qcom'
- List platforms that use a single MSI host interrupt in qcom DT (Johan Hovold) - Add SC8280XP, SA8540P support to qcom DT binding and driver(Johan Hovold) - Make all optional clocks truly optional in the driver (Johan Hovold) - Rename per-IP structs to reflect the IP version (Johan Hovold) - Sort device ID match table by compatible string (Johan Hovold) - Add MODULE_DEVICE_TABLE to enable module autoloading (Dmitry Baryshkov) - Drop the unused .post_deinit() callback (Johan Hovold) - Rely on DT for clock information instead of hard-coding it in the driver (Manivannan Sadhasivam) - Disable IRQs when removing driver to avoid spurious IRQs later (Manivannan Sadhasivam) - Expose link transition counts via debugfs to help debug issues with low-power states (Manivannan Sadhasivam) - Gate Master AXI clock to the MHI bus while in L1 substates to save power (Manivannan Sadhasivam) - Disable Master AXI clock to save power when there is no traffic on PCIe (Manivannan Sadhasivam) - Make the "PERST separation" debug feature optional in the DT and the driver (Manivannan Sadhasivam) - Define clocks to be per-platform in DT to prepare for future SoCs (Manivannan Sadhasivam) - Add SM8450 SoC support (Manivannan Sadhasivam) - Check for platform_get_resource_byname() to avoid a NULL pointer dereference (Yang Yingliang) * pci/qcom: PCI: qcom-ep: Check platform_get_resource_byname() return value PCI: qcom-ep: Add support for SM8450 SoC dt-bindings: PCI: qcom-ep: Add support for SM8450 SoC dt-bindings: PCI: qcom-ep: Define clocks per platform PCI: qcom-ep: Make PERST separation optional dt-bindings: PCI: qcom-ep: Make PERST separation optional PCI: qcom-ep: Disable Master AXI Clock when there is no PCIe traffic PCI: qcom-ep: Gate Master AXI clock to MHI bus during L1SS PCI: qcom-ep: Expose link transition counts via debugfs PCI: qcom-ep: Disable IRQs during driver remove PCI: qcom-ep: Make use of the cached dev pointer PCI: qcom-ep: Rely on the clocks supplied by devicetree PCI: qcom-ep: Add kernel-doc for qcom_pcie_ep structure PCI: qcom: Rename host-init error label PCI: qcom: Drop unused post_deinit callback PCI: qcom-ep: Add MODULE_DEVICE_TABLE PCI: qcom: Sort device-id table PCI: qcom: Clean up IP configurations PCI: qcom: Make all optional clocks optional PCI: qcom: Add support for SA8540P PCI: qcom: Add support for SC8280XP dt-bindings: PCI: qcom: Add SA8540P to binding dt-bindings: PCI: qcom: Add SC8280XP to binding dt-bindings: PCI: qcom: Enumerate platforms with single msi interrupt
This commit is contained in:
commit
e302bafff6
@ -9,12 +9,11 @@ title: Qualcomm PCIe Endpoint Controller binding
|
||||
maintainers:
|
||||
- Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
|
||||
allOf:
|
||||
- $ref: "pci-ep.yaml#"
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sdx55-pcie-ep
|
||||
enum:
|
||||
- qcom,sdx55-pcie-ep
|
||||
- qcom,sm8450-pcie-ep
|
||||
|
||||
reg:
|
||||
items:
|
||||
@ -35,24 +34,12 @@ properties:
|
||||
- const: mmio
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: PCIe Auxiliary clock
|
||||
- description: PCIe CFG AHB clock
|
||||
- description: PCIe Master AXI clock
|
||||
- description: PCIe Slave AXI clock
|
||||
- description: PCIe Slave Q2A AXI clock
|
||||
- description: PCIe Sleep clock
|
||||
- description: PCIe Reference clock
|
||||
minItems: 7
|
||||
maxItems: 8
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg
|
||||
- const: bus_master
|
||||
- const: bus_slave
|
||||
- const: slave_q2a
|
||||
- const: sleep
|
||||
- const: ref
|
||||
minItems: 7
|
||||
maxItems: 8
|
||||
|
||||
qcom,perst-regs:
|
||||
description: Reference to a syscon representing TCSR followed by the two
|
||||
@ -105,7 +92,6 @@ required:
|
||||
- reg-names
|
||||
- clocks
|
||||
- clock-names
|
||||
- qcom,perst-regs
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- reset-gpios
|
||||
@ -113,6 +99,64 @@ required:
|
||||
- reset-names
|
||||
- power-domains
|
||||
|
||||
allOf:
|
||||
- $ref: pci-ep.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sdx55-pcie-ep
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: PCIe Auxiliary clock
|
||||
- description: PCIe CFG AHB clock
|
||||
- description: PCIe Master AXI clock
|
||||
- description: PCIe Slave AXI clock
|
||||
- description: PCIe Slave Q2A AXI clock
|
||||
- description: PCIe Sleep clock
|
||||
- description: PCIe Reference clock
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg
|
||||
- const: bus_master
|
||||
- const: bus_slave
|
||||
- const: slave_q2a
|
||||
- const: sleep
|
||||
- const: ref
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sm8450-pcie-ep
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: PCIe Auxiliary clock
|
||||
- description: PCIe CFG AHB clock
|
||||
- description: PCIe Master AXI clock
|
||||
- description: PCIe Slave AXI clock
|
||||
- description: PCIe Slave Q2A AXI clock
|
||||
- description: PCIe Reference clock
|
||||
- description: PCIe DDRSS SF TBU clock
|
||||
- description: PCIe AGGRE NOC AXI clock
|
||||
clock-names:
|
||||
items:
|
||||
- const: aux
|
||||
- const: cfg
|
||||
- const: bus_master
|
||||
- const: bus_slave
|
||||
- const: slave_q2a
|
||||
- const: ref
|
||||
- const: ddrss_sf_tbu
|
||||
- const: aggre_noc_axi
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
|
@ -25,8 +25,10 @@ properties:
|
||||
- qcom,pcie-ipq4019
|
||||
- qcom,pcie-ipq8074
|
||||
- qcom,pcie-qcs404
|
||||
- qcom,pcie-sa8540p
|
||||
- qcom,pcie-sc7280
|
||||
- qcom,pcie-sc8180x
|
||||
- qcom,pcie-sc8280xp
|
||||
- qcom,pcie-sdm845
|
||||
- qcom,pcie-sm8150
|
||||
- qcom,pcie-sm8250
|
||||
@ -181,6 +183,7 @@ allOf:
|
||||
enum:
|
||||
- qcom,pcie-sc7280
|
||||
- qcom,pcie-sc8180x
|
||||
- qcom,pcie-sc8280xp
|
||||
- qcom,pcie-sm8250
|
||||
- qcom,pcie-sm8450-pcie0
|
||||
- qcom,pcie-sm8450-pcie1
|
||||
@ -598,6 +601,36 @@ allOf:
|
||||
items:
|
||||
- const: pci # PCIe core reset
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,pcie-sa8540p
|
||||
- qcom,pcie-sc8280xp
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 8
|
||||
maxItems: 9
|
||||
clock-names:
|
||||
minItems: 8
|
||||
items:
|
||||
- const: aux # Auxiliary clock
|
||||
- const: cfg # Configuration clock
|
||||
- const: bus_master # Master AXI clock
|
||||
- const: bus_slave # Slave AXI clock
|
||||
- const: slave_q2a # Slave Q2A clock
|
||||
- const: ddrss_sf_tbu # PCIe SF TBU clock
|
||||
- const: noc_aggr_4 # NoC aggregate 4 clock
|
||||
- const: noc_aggr_south_sf # NoC aggregate South SF clock
|
||||
- const: cnoc_qx # Configuration NoC QX clock
|
||||
resets:
|
||||
maxItems: 1
|
||||
reset-names:
|
||||
items:
|
||||
- const: pci # PCIe core reset
|
||||
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
@ -626,8 +659,6 @@ allOf:
|
||||
- resets
|
||||
- reset-names
|
||||
|
||||
# Newer chipsets support either 1 or 8 MSI vectors
|
||||
# On older chipsets it's always 1 MSI vector
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
@ -662,7 +693,40 @@ allOf:
|
||||
- const: msi5
|
||||
- const: msi6
|
||||
- const: msi7
|
||||
else:
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,pcie-sc8280xp
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: msi0
|
||||
- const: msi1
|
||||
- const: msi2
|
||||
- const: msi3
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,pcie-apq8064
|
||||
- qcom,pcie-apq8084
|
||||
- qcom,pcie-ipq4019
|
||||
- qcom,pcie-ipq6018
|
||||
- qcom,pcie-ipq8064
|
||||
- qcom,pcie-ipq8064-v2
|
||||
- qcom,pcie-ipq8074
|
||||
- qcom,pcie-qcs404
|
||||
- qcom,pcie-sa8540p
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
@ -26,6 +27,7 @@
|
||||
#define PARF_SYS_CTRL 0x00
|
||||
#define PARF_DB_CTRL 0x10
|
||||
#define PARF_PM_CTRL 0x20
|
||||
#define PARF_MHI_CLOCK_RESET_CTRL 0x174
|
||||
#define PARF_MHI_BASE_ADDR_LOWER 0x178
|
||||
#define PARF_MHI_BASE_ADDR_UPPER 0x17c
|
||||
#define PARF_DEBUG_INT_EN 0x190
|
||||
@ -45,6 +47,11 @@
|
||||
#define PARF_ATU_BASE_ADDR 0x634
|
||||
#define PARF_ATU_BASE_ADDR_HI 0x638
|
||||
#define PARF_SRIS_MODE 0x644
|
||||
#define PARF_DEBUG_CNT_PM_LINKST_IN_L2 0xc04
|
||||
#define PARF_DEBUG_CNT_PM_LINKST_IN_L1 0xc0c
|
||||
#define PARF_DEBUG_CNT_PM_LINKST_IN_L0S 0xc10
|
||||
#define PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L1 0xc84
|
||||
#define PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L2 0xc88
|
||||
#define PARF_DEVICE_TYPE 0x1000
|
||||
#define PARF_BDF_TO_SID_CFG 0x2c00
|
||||
|
||||
@ -83,6 +90,9 @@
|
||||
#define PARF_PM_CTRL_READY_ENTR_L23 BIT(2)
|
||||
#define PARF_PM_CTRL_REQ_NOT_ENTR_L1 BIT(5)
|
||||
|
||||
/* PARF_MHI_CLOCK_RESET_CTRL fields */
|
||||
#define PARF_MSTR_AXI_CLK_EN BIT(1)
|
||||
|
||||
/* PARF_AXI_MSTR_RD_HALT_NO_WRITES register fields */
|
||||
#define PARF_AXI_MSTR_RD_HALT_NO_WRITE_EN BIT(0)
|
||||
|
||||
@ -95,6 +105,7 @@
|
||||
/* PARF_SYS_CTRL register fields */
|
||||
#define PARF_SYS_CTRL_AUX_PWR_DET BIT(4)
|
||||
#define PARF_SYS_CTRL_CORE_CLK_CGC_DIS BIT(6)
|
||||
#define PARF_SYS_CTRL_MSTR_ACLK_CGC_DIS BIT(10)
|
||||
#define PARF_SYS_CTRL_SLV_DBI_WAKE_DISABLE BIT(11)
|
||||
|
||||
/* PARF_DB_CTRL register fields */
|
||||
@ -130,21 +141,33 @@ enum qcom_pcie_ep_link_status {
|
||||
QCOM_PCIE_EP_LINK_DOWN,
|
||||
};
|
||||
|
||||
static struct clk_bulk_data qcom_pcie_ep_clks[] = {
|
||||
{ .id = "cfg" },
|
||||
{ .id = "aux" },
|
||||
{ .id = "bus_master" },
|
||||
{ .id = "bus_slave" },
|
||||
{ .id = "ref" },
|
||||
{ .id = "sleep" },
|
||||
{ .id = "slave_q2a" },
|
||||
};
|
||||
|
||||
/**
|
||||
* struct qcom_pcie_ep - Qualcomm PCIe Endpoint Controller
|
||||
* @pci: Designware PCIe controller struct
|
||||
* @parf: Qualcomm PCIe specific PARF register base
|
||||
* @elbi: Designware PCIe specific ELBI register base
|
||||
* @mmio: MMIO register base
|
||||
* @perst_map: PERST regmap
|
||||
* @mmio_res: MMIO region resource
|
||||
* @core_reset: PCIe Endpoint core reset
|
||||
* @reset: PERST# GPIO
|
||||
* @wake: WAKE# GPIO
|
||||
* @phy: PHY controller block
|
||||
* @debugfs: PCIe Endpoint Debugfs directory
|
||||
* @clks: PCIe clocks
|
||||
* @num_clks: PCIe clocks count
|
||||
* @perst_en: Flag for PERST enable
|
||||
* @perst_sep_en: Flag for PERST separation enable
|
||||
* @link_status: PCIe Link status
|
||||
* @global_irq: Qualcomm PCIe specific Global IRQ
|
||||
* @perst_irq: PERST# IRQ
|
||||
*/
|
||||
struct qcom_pcie_ep {
|
||||
struct dw_pcie pci;
|
||||
|
||||
void __iomem *parf;
|
||||
void __iomem *elbi;
|
||||
void __iomem *mmio;
|
||||
struct regmap *perst_map;
|
||||
struct resource *mmio_res;
|
||||
|
||||
@ -152,6 +175,10 @@ struct qcom_pcie_ep {
|
||||
struct gpio_desc *reset;
|
||||
struct gpio_desc *wake;
|
||||
struct phy *phy;
|
||||
struct dentry *debugfs;
|
||||
|
||||
struct clk_bulk_data *clks;
|
||||
int num_clks;
|
||||
|
||||
u32 perst_en;
|
||||
u32 perst_sep_en;
|
||||
@ -193,8 +220,10 @@ static int qcom_pcie_ep_core_reset(struct qcom_pcie_ep *pcie_ep)
|
||||
*/
|
||||
static void qcom_pcie_ep_configure_tcsr(struct qcom_pcie_ep *pcie_ep)
|
||||
{
|
||||
regmap_write(pcie_ep->perst_map, pcie_ep->perst_en, 0);
|
||||
regmap_write(pcie_ep->perst_map, pcie_ep->perst_sep_en, 0);
|
||||
if (pcie_ep->perst_map) {
|
||||
regmap_write(pcie_ep->perst_map, pcie_ep->perst_en, 0);
|
||||
regmap_write(pcie_ep->perst_map, pcie_ep->perst_sep_en, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int qcom_pcie_dw_link_up(struct dw_pcie *pci)
|
||||
@ -227,8 +256,7 @@ static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = clk_bulk_prepare_enable(ARRAY_SIZE(qcom_pcie_ep_clks),
|
||||
qcom_pcie_ep_clks);
|
||||
ret = clk_bulk_prepare_enable(pcie_ep->num_clks, pcie_ep->clks);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -249,8 +277,7 @@ static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)
|
||||
err_phy_exit:
|
||||
phy_exit(pcie_ep->phy);
|
||||
err_disable_clk:
|
||||
clk_bulk_disable_unprepare(ARRAY_SIZE(qcom_pcie_ep_clks),
|
||||
qcom_pcie_ep_clks);
|
||||
clk_bulk_disable_unprepare(pcie_ep->num_clks, pcie_ep->clks);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -259,8 +286,7 @@ static void qcom_pcie_disable_resources(struct qcom_pcie_ep *pcie_ep)
|
||||
{
|
||||
phy_power_off(pcie_ep->phy);
|
||||
phy_exit(pcie_ep->phy);
|
||||
clk_bulk_disable_unprepare(ARRAY_SIZE(qcom_pcie_ep_clks),
|
||||
qcom_pcie_ep_clks);
|
||||
clk_bulk_disable_unprepare(pcie_ep->num_clks, pcie_ep->clks);
|
||||
}
|
||||
|
||||
static int qcom_pcie_perst_deassert(struct dw_pcie *pci)
|
||||
@ -318,8 +344,14 @@ static int qcom_pcie_perst_deassert(struct dw_pcie *pci)
|
||||
val &= ~PARF_Q2A_FLUSH_EN;
|
||||
writel_relaxed(val, pcie_ep->parf + PARF_Q2A_FLUSH);
|
||||
|
||||
/* Disable DBI Wakeup, core clock CGC and enable AUX power */
|
||||
/*
|
||||
* Disable Master AXI clock during idle. Do not allow DBI access
|
||||
* to take the core out of L1. Disable core clock gating that
|
||||
* gates PIPE clock from propagating to core clock. Report to the
|
||||
* host that Vaux is present.
|
||||
*/
|
||||
val = readl_relaxed(pcie_ep->parf + PARF_SYS_CTRL);
|
||||
val &= ~PARF_SYS_CTRL_MSTR_ACLK_CGC_DIS;
|
||||
val |= PARF_SYS_CTRL_SLV_DBI_WAKE_DISABLE |
|
||||
PARF_SYS_CTRL_CORE_CLK_CGC_DIS |
|
||||
PARF_SYS_CTRL_AUX_PWR_DET;
|
||||
@ -375,6 +407,11 @@ static int qcom_pcie_perst_deassert(struct dw_pcie *pci)
|
||||
pcie_ep->parf + PARF_MHI_BASE_ADDR_LOWER);
|
||||
writel_relaxed(0, pcie_ep->parf + PARF_MHI_BASE_ADDR_UPPER);
|
||||
|
||||
/* Gate Master AXI clock to MHI bus during L1SS */
|
||||
val = readl_relaxed(pcie_ep->parf + PARF_MHI_CLOCK_RESET_CTRL);
|
||||
val &= ~PARF_MSTR_AXI_CLK_EN;
|
||||
val = readl_relaxed(pcie_ep->parf + PARF_MHI_CLOCK_RESET_CTRL);
|
||||
|
||||
dw_pcie_ep_init_notify(&pcie_ep->pci.ep);
|
||||
|
||||
/* Enable LTSSM */
|
||||
@ -437,11 +474,19 @@ static int qcom_pcie_ep_get_io_resources(struct platform_device *pdev,
|
||||
|
||||
pcie_ep->mmio_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
"mmio");
|
||||
if (!pcie_ep->mmio_res) {
|
||||
dev_err(dev, "Failed to get mmio resource\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pcie_ep->mmio = devm_pci_remap_cfg_resource(dev, pcie_ep->mmio_res);
|
||||
if (IS_ERR(pcie_ep->mmio))
|
||||
return PTR_ERR(pcie_ep->mmio);
|
||||
|
||||
syscon = of_parse_phandle(dev->of_node, "qcom,perst-regs", 0);
|
||||
if (!syscon) {
|
||||
dev_err(dev, "Failed to parse qcom,perst-regs\n");
|
||||
return -EINVAL;
|
||||
dev_dbg(dev, "PERST separation not available\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcie_ep->perst_map = syscon_node_to_regmap(syscon);
|
||||
@ -474,14 +519,15 @@ static int qcom_pcie_ep_get_resources(struct platform_device *pdev,
|
||||
|
||||
ret = qcom_pcie_ep_get_io_resources(pdev, pcie_ep);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to get io resources %d\n", ret);
|
||||
dev_err(dev, "Failed to get io resources %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_clk_bulk_get(dev, ARRAY_SIZE(qcom_pcie_ep_clks),
|
||||
qcom_pcie_ep_clks);
|
||||
if (ret)
|
||||
return ret;
|
||||
pcie_ep->num_clks = devm_clk_bulk_get_all(dev, &pcie_ep->clks);
|
||||
if (pcie_ep->num_clks < 0) {
|
||||
dev_err(dev, "Failed to get clocks\n");
|
||||
return pcie_ep->num_clks;
|
||||
}
|
||||
|
||||
pcie_ep->core_reset = devm_reset_control_get_exclusive(dev, "core");
|
||||
if (IS_ERR(pcie_ep->core_reset))
|
||||
@ -495,7 +541,7 @@ static int qcom_pcie_ep_get_resources(struct platform_device *pdev,
|
||||
if (IS_ERR(pcie_ep->wake))
|
||||
return PTR_ERR(pcie_ep->wake);
|
||||
|
||||
pcie_ep->phy = devm_phy_optional_get(&pdev->dev, "pciephy");
|
||||
pcie_ep->phy = devm_phy_optional_get(dev, "pciephy");
|
||||
if (IS_ERR(pcie_ep->phy))
|
||||
ret = PTR_ERR(pcie_ep->phy);
|
||||
|
||||
@ -571,13 +617,13 @@ static irqreturn_t qcom_pcie_ep_perst_irq_thread(int irq, void *data)
|
||||
static int qcom_pcie_ep_enable_irq_resources(struct platform_device *pdev,
|
||||
struct qcom_pcie_ep *pcie_ep)
|
||||
{
|
||||
int irq, ret;
|
||||
int ret;
|
||||
|
||||
irq = platform_get_irq_byname(pdev, "global");
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
pcie_ep->global_irq = platform_get_irq_byname(pdev, "global");
|
||||
if (pcie_ep->global_irq < 0)
|
||||
return pcie_ep->global_irq;
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
ret = devm_request_threaded_irq(&pdev->dev, pcie_ep->global_irq, NULL,
|
||||
qcom_pcie_ep_global_irq_thread,
|
||||
IRQF_ONESHOT,
|
||||
"global_irq", pcie_ep);
|
||||
@ -594,7 +640,7 @@ static int qcom_pcie_ep_enable_irq_resources(struct platform_device *pdev,
|
||||
"perst_irq", pcie_ep);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to request PERST IRQ\n");
|
||||
disable_irq(irq);
|
||||
disable_irq(pcie_ep->global_irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -617,6 +663,37 @@ static int qcom_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
|
||||
}
|
||||
}
|
||||
|
||||
static int qcom_pcie_ep_link_transition_count(struct seq_file *s, void *data)
|
||||
{
|
||||
struct qcom_pcie_ep *pcie_ep = (struct qcom_pcie_ep *)
|
||||
dev_get_drvdata(s->private);
|
||||
|
||||
seq_printf(s, "L0s transition count: %u\n",
|
||||
readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_PM_LINKST_IN_L0S));
|
||||
|
||||
seq_printf(s, "L1 transition count: %u\n",
|
||||
readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_PM_LINKST_IN_L1));
|
||||
|
||||
seq_printf(s, "L1.1 transition count: %u\n",
|
||||
readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L1));
|
||||
|
||||
seq_printf(s, "L1.2 transition count: %u\n",
|
||||
readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L2));
|
||||
|
||||
seq_printf(s, "L2 transition count: %u\n",
|
||||
readl_relaxed(pcie_ep->mmio + PARF_DEBUG_CNT_PM_LINKST_IN_L2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qcom_pcie_ep_init_debugfs(struct qcom_pcie_ep *pcie_ep)
|
||||
{
|
||||
struct dw_pcie *pci = &pcie_ep->pci;
|
||||
|
||||
debugfs_create_devm_seqfile(pci->dev, "link_transition_count", pcie_ep->debugfs,
|
||||
qcom_pcie_ep_link_transition_count);
|
||||
}
|
||||
|
||||
static const struct pci_epc_features qcom_pcie_epc_features = {
|
||||
.linkup_notifier = true,
|
||||
.core_init_notifier = true,
|
||||
@ -649,6 +726,7 @@ static int qcom_pcie_ep_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct qcom_pcie_ep *pcie_ep;
|
||||
char *name;
|
||||
int ret;
|
||||
|
||||
pcie_ep = devm_kzalloc(dev, sizeof(*pcie_ep), GFP_KERNEL);
|
||||
@ -680,8 +758,21 @@ static int qcom_pcie_ep_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto err_disable_resources;
|
||||
|
||||
name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node);
|
||||
if (!name) {
|
||||
ret = -ENOMEM;
|
||||
goto err_disable_irqs;
|
||||
}
|
||||
|
||||
pcie_ep->debugfs = debugfs_create_dir(name, NULL);
|
||||
qcom_pcie_ep_init_debugfs(pcie_ep);
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable_irqs:
|
||||
disable_irq(pcie_ep->global_irq);
|
||||
disable_irq(pcie_ep->perst_irq);
|
||||
|
||||
err_disable_resources:
|
||||
qcom_pcie_disable_resources(pcie_ep);
|
||||
|
||||
@ -692,6 +783,11 @@ static int qcom_pcie_ep_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_pcie_ep *pcie_ep = platform_get_drvdata(pdev);
|
||||
|
||||
disable_irq(pcie_ep->global_irq);
|
||||
disable_irq(pcie_ep->perst_irq);
|
||||
|
||||
debugfs_remove_recursive(pcie_ep->debugfs);
|
||||
|
||||
if (pcie_ep->link_status == QCOM_PCIE_EP_LINK_DISABLED)
|
||||
return 0;
|
||||
|
||||
@ -702,8 +798,10 @@ static int qcom_pcie_ep_remove(struct platform_device *pdev)
|
||||
|
||||
static const struct of_device_id qcom_pcie_ep_match[] = {
|
||||
{ .compatible = "qcom,sdx55-pcie-ep", },
|
||||
{ .compatible = "qcom,sm8450-pcie-ep", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qcom_pcie_ep_match);
|
||||
|
||||
static struct platform_driver qcom_pcie_ep_driver = {
|
||||
.probe = qcom_pcie_ep_probe,
|
||||
|
@ -180,7 +180,7 @@ struct qcom_pcie_resources_2_3_3 {
|
||||
|
||||
/* 6 clocks typically, 7 for sm8250 */
|
||||
struct qcom_pcie_resources_2_7_0 {
|
||||
struct clk_bulk_data clks[9];
|
||||
struct clk_bulk_data clks[12];
|
||||
int num_clks;
|
||||
struct regulator_bulk_data supplies[2];
|
||||
struct reset_control *pci_reset;
|
||||
@ -208,17 +208,12 @@ struct qcom_pcie_ops {
|
||||
int (*init)(struct qcom_pcie *pcie);
|
||||
int (*post_init)(struct qcom_pcie *pcie);
|
||||
void (*deinit)(struct qcom_pcie *pcie);
|
||||
void (*post_deinit)(struct qcom_pcie *pcie);
|
||||
void (*ltssm_enable)(struct qcom_pcie *pcie);
|
||||
int (*config_sid)(struct qcom_pcie *pcie);
|
||||
};
|
||||
|
||||
struct qcom_pcie_cfg {
|
||||
const struct qcom_pcie_ops *ops;
|
||||
unsigned int has_tbu_clk:1;
|
||||
unsigned int has_ddrss_sf_tbu_clk:1;
|
||||
unsigned int has_aggre0_clk:1;
|
||||
unsigned int has_aggre1_clk:1;
|
||||
};
|
||||
|
||||
struct qcom_pcie {
|
||||
@ -1175,6 +1170,7 @@ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie)
|
||||
struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
|
||||
struct dw_pcie *pci = pcie->pci;
|
||||
struct device *dev = pci->dev;
|
||||
unsigned int num_clks, num_opt_clks;
|
||||
unsigned int idx;
|
||||
int ret;
|
||||
|
||||
@ -1195,18 +1191,25 @@ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie)
|
||||
res->clks[idx++].id = "bus_master";
|
||||
res->clks[idx++].id = "bus_slave";
|
||||
res->clks[idx++].id = "slave_q2a";
|
||||
if (pcie->cfg->has_tbu_clk)
|
||||
res->clks[idx++].id = "tbu";
|
||||
if (pcie->cfg->has_ddrss_sf_tbu_clk)
|
||||
res->clks[idx++].id = "ddrss_sf_tbu";
|
||||
if (pcie->cfg->has_aggre0_clk)
|
||||
res->clks[idx++].id = "aggre0";
|
||||
if (pcie->cfg->has_aggre1_clk)
|
||||
res->clks[idx++].id = "aggre1";
|
||||
|
||||
num_clks = idx;
|
||||
|
||||
ret = devm_clk_bulk_get(dev, num_clks, res->clks);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
res->clks[idx++].id = "tbu";
|
||||
res->clks[idx++].id = "ddrss_sf_tbu";
|
||||
res->clks[idx++].id = "aggre0";
|
||||
res->clks[idx++].id = "aggre1";
|
||||
res->clks[idx++].id = "noc_aggr_4";
|
||||
res->clks[idx++].id = "noc_aggr_south_sf";
|
||||
res->clks[idx++].id = "cnoc_qx";
|
||||
|
||||
num_opt_clks = idx - num_clks;
|
||||
res->num_clks = idx;
|
||||
|
||||
ret = devm_clk_bulk_get(dev, res->num_clks, res->clks);
|
||||
ret = devm_clk_bulk_get_optional(dev, num_opt_clks, res->clks + num_clks);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -1509,15 +1512,13 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp)
|
||||
if (pcie->cfg->ops->config_sid) {
|
||||
ret = pcie->cfg->ops->config_sid(pcie);
|
||||
if (ret)
|
||||
goto err;
|
||||
goto err_assert_reset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
err_assert_reset:
|
||||
qcom_ep_reset_assert(pcie);
|
||||
if (pcie->cfg->ops->post_deinit)
|
||||
pcie->cfg->ops->post_deinit(pcie);
|
||||
err_disable_phy:
|
||||
phy_power_off(pcie->phy);
|
||||
err_deinit:
|
||||
@ -1601,68 +1602,35 @@ static const struct qcom_pcie_ops ops_2_9_0 = {
|
||||
.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_cfg apq8084_cfg = {
|
||||
static const struct qcom_pcie_cfg cfg_1_0_0 = {
|
||||
.ops = &ops_1_0_0,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_cfg ipq8064_cfg = {
|
||||
static const struct qcom_pcie_cfg cfg_1_9_0 = {
|
||||
.ops = &ops_1_9_0,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_cfg cfg_2_1_0 = {
|
||||
.ops = &ops_2_1_0,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_cfg msm8996_cfg = {
|
||||
static const struct qcom_pcie_cfg cfg_2_3_2 = {
|
||||
.ops = &ops_2_3_2,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_cfg ipq8074_cfg = {
|
||||
static const struct qcom_pcie_cfg cfg_2_3_3 = {
|
||||
.ops = &ops_2_3_3,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_cfg ipq4019_cfg = {
|
||||
static const struct qcom_pcie_cfg cfg_2_4_0 = {
|
||||
.ops = &ops_2_4_0,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_cfg sdm845_cfg = {
|
||||
static const struct qcom_pcie_cfg cfg_2_7_0 = {
|
||||
.ops = &ops_2_7_0,
|
||||
.has_tbu_clk = true,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_cfg sm8150_cfg = {
|
||||
/* sm8150 has qcom IP rev 1.5.0. However 1.5.0 ops are same as
|
||||
* 1.9.0, so reuse the same.
|
||||
*/
|
||||
.ops = &ops_1_9_0,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_cfg sm8250_cfg = {
|
||||
.ops = &ops_1_9_0,
|
||||
.has_tbu_clk = true,
|
||||
.has_ddrss_sf_tbu_clk = true,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_cfg sm8450_pcie0_cfg = {
|
||||
.ops = &ops_1_9_0,
|
||||
.has_ddrss_sf_tbu_clk = true,
|
||||
.has_aggre0_clk = true,
|
||||
.has_aggre1_clk = true,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_cfg sm8450_pcie1_cfg = {
|
||||
.ops = &ops_1_9_0,
|
||||
.has_ddrss_sf_tbu_clk = true,
|
||||
.has_aggre1_clk = true,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_cfg sc7280_cfg = {
|
||||
.ops = &ops_1_9_0,
|
||||
.has_tbu_clk = true,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_cfg sc8180x_cfg = {
|
||||
.ops = &ops_1_9_0,
|
||||
.has_tbu_clk = true,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_cfg ipq6018_cfg = {
|
||||
static const struct qcom_pcie_cfg cfg_2_9_0 = {
|
||||
.ops = &ops_2_9_0,
|
||||
};
|
||||
|
||||
@ -1761,22 +1729,24 @@ err_pm_runtime_put:
|
||||
}
|
||||
|
||||
static const struct of_device_id qcom_pcie_match[] = {
|
||||
{ .compatible = "qcom,pcie-apq8084", .data = &apq8084_cfg },
|
||||
{ .compatible = "qcom,pcie-ipq8064", .data = &ipq8064_cfg },
|
||||
{ .compatible = "qcom,pcie-ipq8064-v2", .data = &ipq8064_cfg },
|
||||
{ .compatible = "qcom,pcie-apq8064", .data = &ipq8064_cfg },
|
||||
{ .compatible = "qcom,pcie-msm8996", .data = &msm8996_cfg },
|
||||
{ .compatible = "qcom,pcie-ipq8074", .data = &ipq8074_cfg },
|
||||
{ .compatible = "qcom,pcie-ipq4019", .data = &ipq4019_cfg },
|
||||
{ .compatible = "qcom,pcie-qcs404", .data = &ipq4019_cfg },
|
||||
{ .compatible = "qcom,pcie-sdm845", .data = &sdm845_cfg },
|
||||
{ .compatible = "qcom,pcie-sm8150", .data = &sm8150_cfg },
|
||||
{ .compatible = "qcom,pcie-sm8250", .data = &sm8250_cfg },
|
||||
{ .compatible = "qcom,pcie-sc8180x", .data = &sc8180x_cfg },
|
||||
{ .compatible = "qcom,pcie-sm8450-pcie0", .data = &sm8450_pcie0_cfg },
|
||||
{ .compatible = "qcom,pcie-sm8450-pcie1", .data = &sm8450_pcie1_cfg },
|
||||
{ .compatible = "qcom,pcie-sc7280", .data = &sc7280_cfg },
|
||||
{ .compatible = "qcom,pcie-ipq6018", .data = &ipq6018_cfg },
|
||||
{ .compatible = "qcom,pcie-apq8064", .data = &cfg_2_1_0 },
|
||||
{ .compatible = "qcom,pcie-apq8084", .data = &cfg_1_0_0 },
|
||||
{ .compatible = "qcom,pcie-ipq4019", .data = &cfg_2_4_0 },
|
||||
{ .compatible = "qcom,pcie-ipq6018", .data = &cfg_2_9_0 },
|
||||
{ .compatible = "qcom,pcie-ipq8064", .data = &cfg_2_1_0 },
|
||||
{ .compatible = "qcom,pcie-ipq8064-v2", .data = &cfg_2_1_0 },
|
||||
{ .compatible = "qcom,pcie-ipq8074", .data = &cfg_2_3_3 },
|
||||
{ .compatible = "qcom,pcie-msm8996", .data = &cfg_2_3_2 },
|
||||
{ .compatible = "qcom,pcie-qcs404", .data = &cfg_2_4_0 },
|
||||
{ .compatible = "qcom,pcie-sa8540p", .data = &cfg_1_9_0 },
|
||||
{ .compatible = "qcom,pcie-sc7280", .data = &cfg_1_9_0 },
|
||||
{ .compatible = "qcom,pcie-sc8180x", .data = &cfg_1_9_0 },
|
||||
{ .compatible = "qcom,pcie-sc8280xp", .data = &cfg_1_9_0 },
|
||||
{ .compatible = "qcom,pcie-sdm845", .data = &cfg_2_7_0 },
|
||||
{ .compatible = "qcom,pcie-sm8150", .data = &cfg_1_9_0 },
|
||||
{ .compatible = "qcom,pcie-sm8250", .data = &cfg_1_9_0 },
|
||||
{ .compatible = "qcom,pcie-sm8450-pcie0", .data = &cfg_1_9_0 },
|
||||
{ .compatible = "qcom,pcie-sm8450-pcie1", .data = &cfg_1_9_0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user