mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 22:14:03 +02:00
Merge branch 'pci/controller/dwc-rcar-gen4'
- When MSI is enabled but iMSI-RX is not used, configure AXIINTC to allow GIT ITS to handle MSI (Marek Vasut) - Refactor GIC600 implementation to make it easier to add platforms that only support 32-bit addressing (Marek Vasut) - Add Renesas R-Car Gen4 S4/V4H/V4M to the list of GIC600 integrations that only support 32-bit addressing (Marek Vasut) * pci/controller/dwc-rcar-gen4: irqchip/gic-v3: Add Renesas R-Car Gen4 erratum workaround irqchip/gic-v3: Refactor GIC600 limited to 32bit PA erratum handling PCI: rcar-gen4: Configure AXIINTC if iMSI-RX is not used PCI: dwc: Move iMSI-RX check before calling 'pp->ops->init()'
This commit is contained in:
commit
45b3d1baf4
|
|
@ -352,6 +352,7 @@ stable kernels.
|
|||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| Qualcomm Tech. | Kryo4xx Gold | N/A | ARM64_ERRATUM_1286807 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| Renesas | S4/V4H/V4M | N/A | RENESAS_ERRATUM_GEN4GICITS1 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| Rockchip | RK3588 | #3588001 | ROCKCHIP_ERRATUM_3588001 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
|
|
|
|||
|
|
@ -1382,6 +1382,15 @@ config NVIDIA_CARMEL_CNP_ERRATUM
|
|||
|
||||
If unsure, say Y.
|
||||
|
||||
config RENESAS_ERRATUM_GEN4GICITS1
|
||||
bool "Renesas R-Car Gen4: GIC600 can not access physical addresses above 4 GiB"
|
||||
default y
|
||||
help
|
||||
The Renesas R-Car Gen4 S4/V4H/V4M GIC600 SoC integrations have AXI
|
||||
addressing limited to the first 32-bit of physical address space.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config ROCKCHIP_ERRATUM_3568002
|
||||
bool "Rockchip 3568002: GIC600 can not access physical addresses higher than 4GB"
|
||||
default y
|
||||
|
|
|
|||
|
|
@ -4890,10 +4890,22 @@ static bool __maybe_unused its_enable_quirk_hip09_162100801(void *data)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool __maybe_unused its_enable_rk3568002(void *data)
|
||||
static const char * const dma_32bit_impaired_platforms[] = {
|
||||
#ifdef CONFIG_RENESAS_ERRATUM_GEN4GICITS1
|
||||
"renesas,r8a779f0",
|
||||
"renesas,r8a779g0",
|
||||
"renesas,r8a779h0",
|
||||
#endif
|
||||
#ifdef CONFIG_ROCKCHIP_ERRATUM_3568002
|
||||
"rockchip,rk3566",
|
||||
"rockchip,rk3568",
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
static bool its_enable_dma32(void *data)
|
||||
{
|
||||
if (!of_machine_is_compatible("rockchip,rk3566") &&
|
||||
!of_machine_is_compatible("rockchip,rk3568"))
|
||||
if (!of_machine_compatible_match(dma_32bit_impaired_platforms))
|
||||
return false;
|
||||
|
||||
gfp_flags_quirk |= GFP_DMA32;
|
||||
|
|
@ -4968,14 +4980,12 @@ static const struct gic_quirk its_quirks[] = {
|
|||
.property = "dma-noncoherent",
|
||||
.init = its_set_non_coherent,
|
||||
},
|
||||
#ifdef CONFIG_ROCKCHIP_ERRATUM_3568002
|
||||
{
|
||||
.desc = "ITS: Rockchip erratum RK3568002",
|
||||
.desc = "ITS: Broken GIC600 integration limited to 32bit PA",
|
||||
.iidr = 0x0201743b,
|
||||
.mask = 0xffffffff,
|
||||
.init = its_enable_rk3568002,
|
||||
.init = its_enable_dma32,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ config PCIE_RCAR_GEN4
|
|||
|
||||
config PCIE_RCAR_GEN4_HOST
|
||||
tristate "Renesas R-Car Gen4 PCIe controller (host mode)"
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
depends on ARM64 && (ARCH_RENESAS || COMPILE_TEST)
|
||||
depends on PCI_MSI
|
||||
select PCIE_DW_HOST
|
||||
select PCIE_RCAR_GEN4
|
||||
|
|
@ -357,7 +357,7 @@ config PCIE_RCAR_GEN4_HOST
|
|||
|
||||
config PCIE_RCAR_GEN4_EP
|
||||
tristate "Renesas R-Car Gen4 PCIe controller (endpoint mode)"
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
depends on ARM64 && (ARCH_RENESAS || COMPILE_TEST)
|
||||
depends on PCI_ENDPOINT
|
||||
select PCIE_DW_EP
|
||||
select PCIE_RCAR_GEN4
|
||||
|
|
|
|||
|
|
@ -587,6 +587,12 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (pci_msi_enabled()) {
|
||||
pp->use_imsi_rx = !(pp->ops->msi_init ||
|
||||
of_property_present(np, "msi-parent") ||
|
||||
of_property_present(np, "msi-map"));
|
||||
}
|
||||
|
||||
if (pp->ops->init) {
|
||||
ret = pp->ops->init(pp);
|
||||
if (ret)
|
||||
|
|
@ -594,10 +600,6 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
|
|||
}
|
||||
|
||||
if (pci_msi_enabled()) {
|
||||
pp->use_imsi_rx = !(pp->ops->msi_init ||
|
||||
of_property_present(np, "msi-parent") ||
|
||||
of_property_present(np, "msi-map"));
|
||||
|
||||
/*
|
||||
* For the use_imsi_rx case the default assignment is handled
|
||||
* in the dw_pcie_msi_host_init().
|
||||
|
|
|
|||
|
|
@ -13,8 +13,11 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/irqchip/arm-gic-v3.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
|
@ -31,6 +34,10 @@
|
|||
#define DEVICE_TYPE_RC BIT(4)
|
||||
#define BIFUR_MOD_SET_ON BIT(0)
|
||||
|
||||
/* MSI Capability */
|
||||
#define MSICAP0 0x0050
|
||||
#define MSICAP0_MSIE BIT(16)
|
||||
|
||||
/* PCIe Interrupt Status 0 */
|
||||
#define PCIEINTSTS0 0x0084
|
||||
|
||||
|
|
@ -55,6 +62,14 @@
|
|||
#define APP_HOLD_PHY_RST BIT(16)
|
||||
#define APP_LTSSM_ENABLE BIT(0)
|
||||
|
||||
/* INTC address */
|
||||
#define AXIINTCADDR 0x0a00
|
||||
|
||||
/* INTC control & mask */
|
||||
#define AXIINTCCONT 0x0a04
|
||||
#define INTC_EN BIT(31)
|
||||
#define INTC_MASK GENMASK(11, 3)
|
||||
|
||||
/* PCIe Power Management Control */
|
||||
#define PCIEPWRMNGCTRL 0x0070
|
||||
#define APP_CLK_REQ_N BIT(11)
|
||||
|
|
@ -305,13 +320,103 @@ static struct rcar_gen4_pcie *rcar_gen4_pcie_alloc(struct platform_device *pdev)
|
|||
return rcar;
|
||||
}
|
||||
|
||||
static int rcar_gen4_pcie_host_msi_addr(struct dw_pcie_rp *pp, u32 *msi_addr)
|
||||
{
|
||||
struct dw_pcie *dw = to_dw_pcie_from_pp(pp);
|
||||
struct device_node *msi_node = NULL;
|
||||
struct device *dev = dw->dev;
|
||||
struct resource res;
|
||||
u64 addr;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Either the "msi-parent" or the "msi-map" phandle needs to exist
|
||||
* to obtain the MSI node.
|
||||
*/
|
||||
of_msi_xlate(dev, &msi_node, 0);
|
||||
if (!msi_node)
|
||||
return -ENODEV;
|
||||
|
||||
/* Check if "msi-parent" or the "msi-map" points to ARM GICv3 ITS. */
|
||||
if (!of_device_is_compatible(msi_node, "arm,gic-v3-its"))
|
||||
return dev_err_probe(dev, -ENODEV, "Compatible MSI controller not found\n");
|
||||
|
||||
/* Derive GITS_TRANSLATER address from GICv3 */
|
||||
ret = of_address_to_resource(msi_node, 0, &res);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "MSI controller resources not obtained\n");
|
||||
|
||||
addr = res.start + GITS_TRANSLATER;
|
||||
if (addr >= SZ_4G)
|
||||
return dev_err_probe(dev, -EINVAL, "MSI controller address above 32bit range\n");
|
||||
|
||||
*msi_addr = addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rcar_gen4_pcie_host_msi_init(struct dw_pcie_rp *pp)
|
||||
{
|
||||
struct dw_pcie *dw = to_dw_pcie_from_pp(pp);
|
||||
struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
/* Make sure MSICAP0 MSIE is configured. */
|
||||
val = dw_pcie_readl_dbi(dw, MSICAP0);
|
||||
if (pci_msi_enabled())
|
||||
val |= MSICAP0_MSIE;
|
||||
else
|
||||
val &= ~MSICAP0_MSIE;
|
||||
dw_pcie_writel_dbi(dw, MSICAP0, val);
|
||||
|
||||
if (!pci_msi_enabled() || pp->use_imsi_rx) {
|
||||
/* Clear AXIINTC mapping. */
|
||||
writel(0, rcar->base + AXIINTCADDR);
|
||||
writel(0, rcar->base + AXIINTCCONT);
|
||||
} else {
|
||||
ret = rcar_gen4_pcie_host_msi_addr(pp, &val);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* Point AXIINTC to GIC ITS and enable. */
|
||||
writel(val, rcar->base + AXIINTCADDR);
|
||||
writel(INTC_EN | INTC_MASK, rcar->base + AXIINTCCONT);
|
||||
}
|
||||
|
||||
/* Configure MSI interrupt signal */
|
||||
val = readl(rcar->base + PCIEINTSTS0EN);
|
||||
if (pci_msi_enabled())
|
||||
val |= MSI_CTRL_INT;
|
||||
else
|
||||
val &= ~MSI_CTRL_INT;
|
||||
writel(val, rcar->base + PCIEINTSTS0EN);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
/* Deconfigure MSICAP0 MSIE. */
|
||||
val = dw_pcie_readl_dbi(dw, MSICAP0);
|
||||
val &= ~MSICAP0_MSIE;
|
||||
dw_pcie_writel_dbi(dw, MSICAP0, val);
|
||||
|
||||
/* Clear AXIINTC mapping. */
|
||||
writel(0, rcar->base + AXIINTCADDR);
|
||||
writel(0, rcar->base + AXIINTCCONT);
|
||||
|
||||
/* Deconfigure MSI interrupt signal */
|
||||
val = readl(rcar->base + PCIEINTSTS0EN);
|
||||
val &= ~MSI_CTRL_INT;
|
||||
writel(val, rcar->base + PCIEINTSTS0EN);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Host mode */
|
||||
static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
|
||||
{
|
||||
struct dw_pcie *dw = to_dw_pcie_from_pp(pp);
|
||||
struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
gpiod_set_value_cansleep(dw->pe_rst, 1);
|
||||
|
||||
|
|
@ -328,16 +433,19 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
|
|||
dw_pcie_writel_dbi2(dw, PCI_BASE_ADDRESS_0, 0x0);
|
||||
dw_pcie_writel_dbi2(dw, PCI_BASE_ADDRESS_1, 0x0);
|
||||
|
||||
/* Enable MSI interrupt signal */
|
||||
val = readl(rcar->base + PCIEINTSTS0EN);
|
||||
val |= MSI_CTRL_INT;
|
||||
writel(val, rcar->base + PCIEINTSTS0EN);
|
||||
ret = rcar_gen4_pcie_host_msi_init(pp);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
msleep(PCIE_T_PVPERL_MS); /* pe_rst requires 100msec delay */
|
||||
|
||||
gpiod_set_value_cansleep(dw->pe_rst, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
rcar_gen4_pcie_common_deinit(rcar);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rcar_gen4_pcie_host_deinit(struct dw_pcie_rp *pp)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user