[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200228154122.14164-3-prabhakar.mahadev-lad.rj@bp.renesas.com>
Date: Fri, 28 Feb 2020 15:41:17 +0000
From: Lad Prabhakar <prabhakar.csengg@...il.com>
To: Bjorn Helgaas <bhelgaas@...gle.com>,
Rob Herring <robh+dt@...nel.org>,
Mark Rutland <mark.rutland@....com>,
Catalin Marinas <catalin.marinas@....com>,
Will Deacon <will@...nel.org>,
Kishon Vijay Abraham I <kishon@...com>,
Lorenzo Pieralisi <lorenzo.pieralisi@....com>,
Arnd Bergmann <arnd@...db.de>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Jingoo Han <jingoohan1@...il.com>,
Gustavo Pimentel <gustavo.pimentel@...opsys.com>,
Marek Vasut <marek.vasut+renesas@...il.com>,
Yoshihiro Shimoda <yoshihiro.shimoda.uh@...esas.com>,
Shawn Lin <shawn.lin@...k-chips.com>,
Heiko Stuebner <heiko@...ech.de>
Cc: Andrew Murray <andrew.murray@....com>, linux-pci@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org,
linux-renesas-soc@...r.kernel.org,
linux-rockchip@...ts.infradead.org, linux-kernel@...r.kernel.org,
devicetree@...r.kernel.org,
Lad Prabhakar <prabhakar.mahadev-lad.rj@...renesas.com>
Subject: [PATCH v5 2/7] PCI: rcar: Move shareable code to a common file
This patch moves sharable code to common file pcie-rcar.c and the #defines
to pcie-rcar.h so that the common code can be reused with endpoint driver.
There are no functional changes with this patch for the host controller
driver.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@...renesas.com>
---
drivers/pci/controller/Makefile | 2 +-
drivers/pci/controller/pcie-rcar-host.c | 358 ++++++++------------------------
drivers/pci/controller/pcie-rcar.c | 117 +++++++++++
drivers/pci/controller/pcie-rcar.h | 125 +++++++++++
4 files changed, 324 insertions(+), 278 deletions(-)
create mode 100644 drivers/pci/controller/pcie-rcar.c
create mode 100644 drivers/pci/controller/pcie-rcar.h
diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
index 4ca2da6..b4ada32 100644
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
-obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar-host.o
+obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar.o pcie-rcar-host.o
obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c
index 759c654..93f22d8 100644
--- a/drivers/pci/controller/pcie-rcar-host.c
+++ b/drivers/pci/controller/pcie-rcar-host.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* PCIe driver for Renesas R-Car SoCs
- * Copyright (C) 2014 Renesas Electronics Europe Ltd
+ * Copyright (C) 2014-2020 Renesas Electronics Europe Ltd
*
* Based on:
* arch/sh/drivers/pci/pcie-sh7786.c
@@ -30,104 +30,7 @@
#include <linux/pm_runtime.h>
#include <linux/slab.h>
-#define PCIECAR 0x000010
-#define PCIECCTLR 0x000018
-#define CONFIG_SEND_ENABLE BIT(31)
-#define TYPE0 (0 << 8)
-#define TYPE1 BIT(8)
-#define PCIECDR 0x000020
-#define PCIEMSR 0x000028
-#define PCIEINTXR 0x000400
-#define PCIEPHYSR 0x0007f0
-#define PHYRDY BIT(0)
-#define PCIEMSITXR 0x000840
-
-/* Transfer control */
-#define PCIETCTLR 0x02000
-#define DL_DOWN BIT(3)
-#define CFINIT BIT(0)
-#define PCIETSTR 0x02004
-#define DATA_LINK_ACTIVE BIT(0)
-#define PCIEERRFR 0x02020
-#define UNSUPPORTED_REQUEST BIT(4)
-#define PCIEMSIFR 0x02044
-#define PCIEMSIALR 0x02048
-#define MSIFE BIT(0)
-#define PCIEMSIAUR 0x0204c
-#define PCIEMSIIER 0x02050
-
-/* root port address */
-#define PCIEPRAR(x) (0x02080 + ((x) * 0x4))
-
-/* local address reg & mask */
-#define PCIELAR(x) (0x02200 + ((x) * 0x20))
-#define PCIELAMR(x) (0x02208 + ((x) * 0x20))
-#define LAM_PREFETCH BIT(3)
-#define LAM_64BIT BIT(2)
-#define LAR_ENABLE BIT(1)
-
-/* PCIe address reg & mask */
-#define PCIEPALR(x) (0x03400 + ((x) * 0x20))
-#define PCIEPAUR(x) (0x03404 + ((x) * 0x20))
-#define PCIEPAMR(x) (0x03408 + ((x) * 0x20))
-#define PCIEPTCTLR(x) (0x0340c + ((x) * 0x20))
-#define PAR_ENABLE BIT(31)
-#define IO_SPACE BIT(8)
-
-/* Configuration */
-#define PCICONF(x) (0x010000 + ((x) * 0x4))
-#define PMCAP(x) (0x010040 + ((x) * 0x4))
-#define EXPCAP(x) (0x010070 + ((x) * 0x4))
-#define VCCAP(x) (0x010100 + ((x) * 0x4))
-
-/* link layer */
-#define IDSETR1 0x011004
-#define TLCTLR 0x011048
-#define MACSR 0x011054
-#define SPCHGFIN BIT(4)
-#define SPCHGFAIL BIT(6)
-#define SPCHGSUC BIT(7)
-#define LINK_SPEED (0xf << 16)
-#define LINK_SPEED_2_5GTS (1 << 16)
-#define LINK_SPEED_5_0GTS (2 << 16)
-#define MACCTLR 0x011058
-#define MACCTLR_NFTS_MASK GENMASK(23, 16) /* The name is from SH7786 */
-#define SPEED_CHANGE BIT(24)
-#define SCRAMBLE_DISABLE BIT(27)
-#define LTSMDIS BIT(31)
-#define MACCTLR_INIT_VAL (LTSMDIS | MACCTLR_NFTS_MASK)
-#define PMSR 0x01105c
-#define MACS2R 0x011078
-#define MACCGSPSETR 0x011084
-#define SPCNGRSN BIT(31)
-
-/* R-Car H1 PHY */
-#define H1_PCIEPHYADRR 0x04000c
-#define WRITE_CMD BIT(16)
-#define PHY_ACK BIT(24)
-#define RATE_POS 12
-#define LANE_POS 8
-#define ADR_POS 0
-#define H1_PCIEPHYDOUTR 0x040014
-
-/* R-Car Gen2 PHY */
-#define GEN2_PCIEPHYADDR 0x780
-#define GEN2_PCIEPHYDATA 0x784
-#define GEN2_PCIEPHYCTRL 0x78c
-
-#define INT_PCI_MSI_NR 32
-
-#define RCONF(x) (PCICONF(0) + (x))
-#define RPMCAP(x) (PMCAP(0) + (x))
-#define REXPCAP(x) (EXPCAP(0) + (x))
-#define RVCCAP(x) (VCCAP(0) + (x))
-
-#define PCIE_CONF_BUS(b) (((b) & 0xff) << 24)
-#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 19)
-#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 16)
-
-#define RCAR_PCI_MAX_RESOURCES 4
-#define MAX_NR_INBOUND_MAPS 6
+#include "pcie-rcar.h"
struct rcar_msi {
DECLARE_BITMAP(used, INT_PCI_MSI_NR);
@@ -155,36 +58,10 @@ struct rcar_pcie {
struct rcar_msi msi;
};
-static void rcar_pci_write_reg(struct rcar_pcie *pcie, u32 val,
- unsigned int reg)
-{
- writel(val, pcie->base + reg);
-}
-
-static u32 rcar_pci_read_reg(struct rcar_pcie *pcie, unsigned int reg)
-{
- return readl(pcie->base + reg);
-}
-
-enum {
- RCAR_PCI_ACCESS_READ,
- RCAR_PCI_ACCESS_WRITE,
-};
-
-static void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask, u32 data)
-{
- unsigned int shift = BITS_PER_BYTE * (where & 3);
- u32 val = rcar_pci_read_reg(pcie, where & ~3);
-
- val &= ~(mask << shift);
- val |= data << shift;
- rcar_pci_write_reg(pcie, val, where & ~3);
-}
-
static u32 rcar_read_conf(struct rcar_pcie *pcie, int where)
{
unsigned int shift = BITS_PER_BYTE * (where & 3);
- u32 val = rcar_pci_read_reg(pcie, where & ~3);
+ u32 val = rcar_pci_read_reg(pcie->base, where & ~3);
return val >> shift;
}
@@ -221,13 +98,13 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
return PCIBIOS_DEVICE_NOT_FOUND;
if (access_type == RCAR_PCI_ACCESS_READ) {
- *data = rcar_pci_read_reg(pcie, PCICONF(index));
+ *data = rcar_pci_read_reg(pcie->base, PCICONF(index));
} else {
/* Keep an eye out for changes to the root bus number */
if (pci_is_root_bus(bus) && (reg == PCI_PRIMARY_BUS))
pcie->root_bus_nr = *data & 0xff;
- rcar_pci_write_reg(pcie, *data, PCICONF(index));
+ rcar_pci_write_reg(pcie->base, *data, PCICONF(index));
}
return PCIBIOS_SUCCESSFUL;
@@ -237,20 +114,23 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
return PCIBIOS_DEVICE_NOT_FOUND;
/* Clear errors */
- rcar_pci_write_reg(pcie, rcar_pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
+ rcar_pci_write_reg(pcie->base, rcar_pci_read_reg(pcie->base, PCIEERRFR),
+ PCIEERRFR);
/* Set the PIO address */
- rcar_pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) |
+ rcar_pci_write_reg(pcie->base, PCIE_CONF_BUS(bus->number) |
PCIE_CONF_DEV(dev) | PCIE_CONF_FUNC(func) | reg, PCIECAR);
/* Enable the configuration access */
if (bus->parent->number == pcie->root_bus_nr)
- rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
+ rcar_pci_write_reg(pcie->base, CONFIG_SEND_ENABLE | TYPE0,
+ PCIECCTLR);
else
- rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
+ rcar_pci_write_reg(pcie->base, CONFIG_SEND_ENABLE | TYPE1,
+ PCIECCTLR);
/* Check for errors */
- if (rcar_pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
+ if (rcar_pci_read_reg(pcie->base, PCIEERRFR) & UNSUPPORTED_REQUEST)
return PCIBIOS_DEVICE_NOT_FOUND;
/* Check for master and target aborts */
@@ -259,12 +139,12 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
return PCIBIOS_DEVICE_NOT_FOUND;
if (access_type == RCAR_PCI_ACCESS_READ)
- *data = rcar_pci_read_reg(pcie, PCIECDR);
+ *data = rcar_pci_read_reg(pcie->base, PCIECDR);
else
- rcar_pci_write_reg(pcie, *data, PCIECDR);
+ rcar_pci_write_reg(pcie->base, *data, PCIECDR);
/* Disable the configuration access */
- rcar_pci_write_reg(pcie, 0, PCIECCTLR);
+ rcar_pci_write_reg(pcie->base, 0, PCIECCTLR);
return PCIBIOS_SUCCESSFUL;
}
@@ -332,41 +212,6 @@ static struct pci_ops rcar_pcie_ops = {
.write = rcar_pcie_write_conf,
};
-static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie,
- struct resource *res)
-{
- /* Setup PCIe address space mappings for each resource */
- resource_size_t size;
- resource_size_t res_start;
- u32 mask;
-
- rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
-
- /*
- * The PAMR mask is calculated in units of 128Bytes, which
- * keeps things pretty simple.
- */
- size = resource_size(res);
- mask = (roundup_pow_of_two(size) / SZ_128) - 1;
- rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
-
- if (res->flags & IORESOURCE_IO)
- res_start = pci_pio_to_address(res->start);
- else
- res_start = res->start;
-
- rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPAUR(win));
- rcar_pci_write_reg(pcie, lower_32_bits(res_start) & ~0x7F,
- PCIEPALR(win));
-
- /* First resource is for IO */
- mask = PAR_ENABLE;
- if (res->flags & IORESOURCE_IO)
- mask |= IO_SPACE;
-
- rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win));
-}
-
static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci)
{
struct resource_entry *win;
@@ -382,7 +227,7 @@ static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci)
switch (resource_type(res)) {
case IORESOURCE_IO:
case IORESOURCE_MEM:
- rcar_pcie_setup_window(i, pci, res);
+ rcar_pcie_set_outbound(i, pci->base, res);
i++;
break;
case IORESOURCE_BUS:
@@ -404,37 +249,38 @@ static void rcar_pcie_force_speedup(struct rcar_pcie *pcie)
unsigned int timeout = 1000;
u32 macsr;
- if ((rcar_pci_read_reg(pcie, MACS2R) & LINK_SPEED) != LINK_SPEED_5_0GTS)
+ if ((rcar_pci_read_reg(pcie->base, MACS2R) & LINK_SPEED) !=
+ LINK_SPEED_5_0GTS)
return;
- if (rcar_pci_read_reg(pcie, MACCTLR) & SPEED_CHANGE) {
+ if (rcar_pci_read_reg(pcie->base, MACCTLR) & SPEED_CHANGE) {
dev_err(dev, "Speed change already in progress\n");
return;
}
- macsr = rcar_pci_read_reg(pcie, MACSR);
+ macsr = rcar_pci_read_reg(pcie->base, MACSR);
if ((macsr & LINK_SPEED) == LINK_SPEED_5_0GTS)
goto done;
/* Set target link speed to 5.0 GT/s */
- rcar_rmw32(pcie, EXPCAP(12), PCI_EXP_LNKSTA_CLS,
+ rcar_rmw32(pcie->base, EXPCAP(12), PCI_EXP_LNKSTA_CLS,
PCI_EXP_LNKSTA_CLS_5_0GB);
/* Set speed change reason as intentional factor */
- rcar_rmw32(pcie, MACCGSPSETR, SPCNGRSN, 0);
+ rcar_rmw32(pcie->base, MACCGSPSETR, SPCNGRSN, 0);
/* Clear SPCHGFIN, SPCHGSUC, and SPCHGFAIL */
if (macsr & (SPCHGFIN | SPCHGSUC | SPCHGFAIL))
- rcar_pci_write_reg(pcie, macsr, MACSR);
+ rcar_pci_write_reg(pcie->base, macsr, MACSR);
/* Start link speed change */
- rcar_rmw32(pcie, MACCTLR, SPEED_CHANGE, SPEED_CHANGE);
+ rcar_rmw32(pcie->base, MACCTLR, SPEED_CHANGE, SPEED_CHANGE);
while (timeout--) {
- macsr = rcar_pci_read_reg(pcie, MACSR);
+ macsr = rcar_pci_read_reg(pcie->base, MACSR);
if (macsr & SPCHGFIN) {
/* Clear the interrupt bits */
- rcar_pci_write_reg(pcie, macsr, MACSR);
+ rcar_pci_write_reg(pcie->base, macsr, MACSR);
if (macsr & SPCHGFAIL)
dev_err(dev, "Speed change failed\n");
@@ -498,7 +344,7 @@ static int phy_wait_for_ack(struct rcar_pcie *pcie)
unsigned int timeout = 100;
while (timeout--) {
- if (rcar_pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK)
+ if (rcar_pci_read_reg(pcie->base, H1_PCIEPHYADRR) & PHY_ACK)
return 0;
udelay(100);
@@ -521,60 +367,31 @@ static void phy_write_reg(struct rcar_pcie *pcie,
((addr & 0xff) << ADR_POS);
/* Set write data */
- rcar_pci_write_reg(pcie, data, H1_PCIEPHYDOUTR);
- rcar_pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR);
+ rcar_pci_write_reg(pcie->base, data, H1_PCIEPHYDOUTR);
+ rcar_pci_write_reg(pcie->base, phyaddr, H1_PCIEPHYADRR);
/* Ignore errors as they will be dealt with if the data link is down */
phy_wait_for_ack(pcie);
/* Clear command */
- rcar_pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR);
- rcar_pci_write_reg(pcie, 0, H1_PCIEPHYADRR);
+ rcar_pci_write_reg(pcie->base, 0, H1_PCIEPHYDOUTR);
+ rcar_pci_write_reg(pcie->base, 0, H1_PCIEPHYADRR);
/* Ignore errors as they will be dealt with if the data link is down */
phy_wait_for_ack(pcie);
}
-static int rcar_pcie_wait_for_phyrdy(struct rcar_pcie *pcie)
-{
- unsigned int timeout = 10;
-
- while (timeout--) {
- if (rcar_pci_read_reg(pcie, PCIEPHYSR) & PHYRDY)
- return 0;
-
- msleep(5);
- }
-
- return -ETIMEDOUT;
-}
-
-static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
-{
- unsigned int timeout = 10000;
-
- while (timeout--) {
- if ((rcar_pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
- return 0;
-
- udelay(5);
- cpu_relax();
- }
-
- return -ETIMEDOUT;
-}
-
static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
{
int err;
/* Begin initialization */
- rcar_pci_write_reg(pcie, 0, PCIETCTLR);
+ rcar_pci_write_reg(pcie->base, 0, PCIETCTLR);
/* Set mode */
- rcar_pci_write_reg(pcie, 1, PCIEMSR);
+ rcar_pci_write_reg(pcie->base, 1, PCIEMSR);
- err = rcar_pcie_wait_for_phyrdy(pcie);
+ err = rcar_pcie_wait_for_phyrdy(pcie->base);
if (err)
return err;
@@ -583,51 +400,51 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
* class to match. Hardware takes care of propagating the IDSETR
* settings, so there is no need to bother with a quirk.
*/
- rcar_pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
+ rcar_pci_write_reg(pcie->base, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
/*
* Setup Secondary Bus Number & Subordinate Bus Number, even though
* they aren't used, to avoid bridge being detected as broken.
*/
- rcar_rmw32(pcie, RCONF(PCI_SECONDARY_BUS), 0xff, 1);
- rcar_rmw32(pcie, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
+ rcar_rmw32(pcie->base, RCONF(PCI_SECONDARY_BUS), 0xff, 1);
+ rcar_rmw32(pcie->base, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
/* Initialize default capabilities. */
- rcar_rmw32(pcie, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
- rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS),
- PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
- rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f,
- PCI_HEADER_TYPE_BRIDGE);
+ rcar_rmw32(pcie->base, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
+ rcar_rmw32(pcie->base, REXPCAP(PCI_EXP_FLAGS),
+ PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
+ rcar_rmw32(pcie->base, RCONF(PCI_HEADER_TYPE), 0x7f,
+ PCI_HEADER_TYPE_BRIDGE);
/* Enable data link layer active state reporting */
- rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), PCI_EXP_LNKCAP_DLLLARC,
- PCI_EXP_LNKCAP_DLLLARC);
+ rcar_rmw32(pcie->base, REXPCAP(PCI_EXP_LNKCAP), PCI_EXP_LNKCAP_DLLLARC,
+ PCI_EXP_LNKCAP_DLLLARC);
/* Write out the physical slot number = 0 */
- rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0);
+ rcar_rmw32(pcie->base, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0);
/* Set the completion timer timeout to the maximum 50ms. */
- rcar_rmw32(pcie, TLCTLR + 1, 0x3f, 50);
+ rcar_rmw32(pcie->base, TLCTLR + 1, 0x3f, 50);
/* Terminate list of capabilities (Next Capability Offset=0) */
- rcar_rmw32(pcie, RVCCAP(0), 0xfff00000, 0);
+ rcar_rmw32(pcie->base, RVCCAP(0), 0xfff00000, 0);
/* Enable MSI */
if (IS_ENABLED(CONFIG_PCI_MSI))
- rcar_pci_write_reg(pcie, 0x801f0000, PCIEMSITXR);
+ rcar_pci_write_reg(pcie->base, 0x801f0000, PCIEMSITXR);
- rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR);
+ rcar_pci_write_reg(pcie->base, MACCTLR_INIT_VAL, MACCTLR);
/* Finish initialization - establish a PCI Express link */
- rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
+ rcar_pci_write_reg(pcie->base, CFINIT, PCIETCTLR);
/* This will timeout if we don't have a link. */
- err = rcar_pcie_wait_for_dl(pcie);
+ err = rcar_pcie_wait_for_dl(pcie->base);
if (err)
return err;
/* Enable INTx interrupts */
- rcar_rmw32(pcie, PCIEINTXR, 0, 0xF << 8);
+ rcar_rmw32(pcie->base, PCIEINTXR, 0, 0xF << 8);
wmb();
@@ -663,16 +480,16 @@ static int rcar_pcie_phy_init_gen2(struct rcar_pcie *pcie)
* These settings come from the R-Car Series, 2nd Generation User's
* Manual, section 50.3.1 (2) Initialization of the physical layer.
*/
- rcar_pci_write_reg(pcie, 0x000f0030, GEN2_PCIEPHYADDR);
- rcar_pci_write_reg(pcie, 0x00381203, GEN2_PCIEPHYDATA);
- rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL);
- rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL);
+ rcar_pci_write_reg(pcie->base, 0x000f0030, GEN2_PCIEPHYADDR);
+ rcar_pci_write_reg(pcie->base, 0x00381203, GEN2_PCIEPHYDATA);
+ rcar_pci_write_reg(pcie->base, 0x00000001, GEN2_PCIEPHYCTRL);
+ rcar_pci_write_reg(pcie->base, 0x00000006, GEN2_PCIEPHYCTRL);
- rcar_pci_write_reg(pcie, 0x000f0054, GEN2_PCIEPHYADDR);
+ rcar_pci_write_reg(pcie->base, 0x000f0054, GEN2_PCIEPHYADDR);
/* The following value is for DC connection, no termination resistor */
- rcar_pci_write_reg(pcie, 0x13802007, GEN2_PCIEPHYDATA);
- rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL);
- rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL);
+ rcar_pci_write_reg(pcie->base, 0x13802007, GEN2_PCIEPHYDATA);
+ rcar_pci_write_reg(pcie->base, 0x00000001, GEN2_PCIEPHYCTRL);
+ rcar_pci_write_reg(pcie->base, 0x00000006, GEN2_PCIEPHYCTRL);
return 0;
}
@@ -735,7 +552,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
struct device *dev = pcie->dev;
unsigned long reg;
- reg = rcar_pci_read_reg(pcie, PCIEMSIFR);
+ reg = rcar_pci_read_reg(pcie->base, PCIEMSIFR);
/* MSI & INTx share an interrupt - we only handle MSI here */
if (!reg)
@@ -746,7 +563,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
unsigned int msi_irq;
/* clear the interrupt */
- rcar_pci_write_reg(pcie, 1 << index, PCIEMSIFR);
+ rcar_pci_write_reg(pcie->base, 1 << index, PCIEMSIFR);
msi_irq = irq_find_mapping(msi->domain, index);
if (msi_irq) {
@@ -760,7 +577,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
}
/* see if there's any more pending in this vector */
- reg = rcar_pci_read_reg(pcie, PCIEMSIFR);
+ reg = rcar_pci_read_reg(pcie->base, PCIEMSIFR);
}
return IRQ_HANDLED;
@@ -787,8 +604,8 @@ static int rcar_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
irq_set_msi_desc(irq, desc);
- msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
- msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR);
+ msg.address_lo = rcar_pci_read_reg(pcie->base, PCIEMSIALR) & ~MSIFE;
+ msg.address_hi = rcar_pci_read_reg(pcie->base, PCIEMSIAUR);
msg.data = hwirq;
pci_write_msi_msg(irq, &msg);
@@ -839,8 +656,8 @@ static int rcar_msi_setup_irqs(struct msi_controller *chip,
desc->nvec_used = nvec;
desc->msi_attrib.multiple = order_base_2(nvec);
- msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
- msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR);
+ msg.address_lo = rcar_pci_read_reg(pcie->base, PCIEMSIALR) & ~MSIFE;
+ msg.address_hi = rcar_pci_read_reg(pcie->base, PCIEMSIAUR);
msg.data = hwirq;
pci_write_msi_msg(irq, &msg);
@@ -940,11 +757,11 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
}
base = virt_to_phys((void *)msi->pages);
- rcar_pci_write_reg(pcie, lower_32_bits(base) | MSIFE, PCIEMSIALR);
- rcar_pci_write_reg(pcie, upper_32_bits(base), PCIEMSIAUR);
+ rcar_pci_write_reg(pcie->base, lower_32_bits(base) | MSIFE, PCIEMSIALR);
+ rcar_pci_write_reg(pcie->base, upper_32_bits(base), PCIEMSIAUR);
/* enable all MSI interrupts */
- rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
+ rcar_pci_write_reg(pcie->base, 0xffffffff, PCIEMSIIER);
return 0;
@@ -958,10 +775,10 @@ static void rcar_pcie_teardown_msi(struct rcar_pcie *pcie)
struct rcar_msi *msi = &pcie->msi;
/* Disable all MSI interrupts */
- rcar_pci_write_reg(pcie, 0, PCIEMSIIER);
+ rcar_pci_write_reg(pcie->base, 0, PCIEMSIIER);
/* Disable address decoding of the MSI interrupt, MSIFE */
- rcar_pci_write_reg(pcie, 0, PCIEMSIALR);
+ rcar_pci_write_reg(pcie->base, 0, PCIEMSIALR);
free_pages(msi->pages, 0);
@@ -1054,21 +871,8 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
mask = roundup_pow_of_two(size) - 1;
mask &= ~0xf;
- /*
- * Set up 64-bit inbound regions as the range parser doesn't
- * distinguish between 32 and 64-bit types.
- */
- rcar_pci_write_reg(pcie, lower_32_bits(pci_addr),
- PCIEPRAR(idx));
- rcar_pci_write_reg(pcie, lower_32_bits(cpu_addr), PCIELAR(idx));
- rcar_pci_write_reg(pcie, lower_32_bits(mask) | flags,
- PCIELAMR(idx));
-
- rcar_pci_write_reg(pcie, upper_32_bits(pci_addr),
- PCIEPRAR(idx + 1));
- rcar_pci_write_reg(pcie, upper_32_bits(cpu_addr),
- PCIELAR(idx + 1));
- rcar_pci_write_reg(pcie, 0, PCIELAMR(idx + 1));
+ rcar_pcie_set_inbound(pcie->base, cpu_addr, pci_addr,
+ lower_32_bits(mask) | flags, idx, true);
pci_addr += size;
cpu_addr += size;
@@ -1170,7 +974,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
goto err_phy_shutdown;
}
- data = rcar_pci_read_reg(pcie, MACSR);
+ data = rcar_pci_read_reg(pcie->base, MACSR);
dev_info(dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
if (IS_ENABLED(CONFIG_PCI_MSI)) {
@@ -1223,14 +1027,14 @@ static int rcar_pcie_resume_noirq(struct device *dev)
{
struct rcar_pcie *pcie = dev_get_drvdata(dev);
- if (rcar_pci_read_reg(pcie, PMSR) &&
- !(rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN))
+ if (rcar_pci_read_reg(pcie->base, PMSR) &&
+ !(rcar_pci_read_reg(pcie->base, PCIETCTLR) & DL_DOWN))
return 0;
/* Re-establish the PCIe link */
- rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR);
- rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
- return rcar_pcie_wait_for_dl(pcie);
+ rcar_pci_write_reg(pcie->base, MACCTLR_INIT_VAL, MACCTLR);
+ rcar_pci_write_reg(pcie->base, CFINIT, PCIETCTLR);
+ return rcar_pcie_wait_for_dl(pcie->base);
}
static const struct dev_pm_ops rcar_pcie_pm_ops = {
diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c
new file mode 100644
index 0000000..41275f9
--- /dev/null
+++ b/drivers/pci/controller/pcie-rcar.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe driver for Renesas R-Car SoCs
+ * Copyright (C) 2014-2020 Renesas Electronics Europe Ltd
+ *
+ * Author: Phil Edworthy <phil.edworthy@...esas.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include "pcie-rcar.h"
+
+void rcar_pci_write_reg(void __iomem *base, u32 val, unsigned int reg)
+{
+ writel(val, base + reg);
+}
+
+u32 rcar_pci_read_reg(void __iomem *base, unsigned int reg)
+{
+ return readl(base + reg);
+}
+
+void rcar_rmw32(void __iomem *base, int where, u32 mask, u32 data)
+{
+ unsigned int shift = BITS_PER_BYTE * (where & 3);
+ u32 val = rcar_pci_read_reg(base, where & ~3);
+
+ val &= ~(mask << shift);
+ val |= data << shift;
+ rcar_pci_write_reg(base, val, where & ~3);
+}
+
+int rcar_pcie_wait_for_phyrdy(void __iomem *base)
+{
+ unsigned int timeout = 10;
+
+ while (timeout--) {
+ if (rcar_pci_read_reg(base, PCIEPHYSR) & PHYRDY)
+ return 0;
+
+ msleep(5);
+ }
+
+ return -ETIMEDOUT;
+}
+
+int rcar_pcie_wait_for_dl(void __iomem *base)
+{
+ unsigned int timeout = 10000;
+
+ while (timeout--) {
+ if ((rcar_pci_read_reg(base, PCIETSTR) & DATA_LINK_ACTIVE))
+ return 0;
+
+ udelay(5);
+ cpu_relax();
+ }
+
+ return -ETIMEDOUT;
+}
+
+void rcar_pcie_set_outbound(int win, void __iomem *base,
+ struct resource *res)
+{
+ /* Setup PCIe address space mappings for each resource */
+ resource_size_t res_start;
+ resource_size_t size;
+ u32 mask;
+
+ rcar_pci_write_reg(base, 0x00000000, PCIEPTCTLR(win));
+
+ /*
+ * The PAMR mask is calculated in units of 128Bytes, which
+ * keeps things pretty simple.
+ */
+ size = resource_size(res);
+ mask = (roundup_pow_of_two(size) / SZ_128) - 1;
+ rcar_pci_write_reg(base, mask << 7, PCIEPAMR(win));
+
+ if (res->flags & IORESOURCE_IO)
+ res_start = pci_pio_to_address(res->start);
+ else
+ res_start = res->start;
+
+ rcar_pci_write_reg(base, upper_32_bits(res_start), PCIEPAUR(win));
+ rcar_pci_write_reg(base, lower_32_bits(res_start) & ~0x7F,
+ PCIEPALR(win));
+
+ /* First resource is for IO */
+ mask = PAR_ENABLE;
+ if (res->flags & IORESOURCE_IO)
+ mask |= IO_SPACE;
+
+ rcar_pci_write_reg(base, mask, PCIEPTCTLR(win));
+}
+
+void rcar_pcie_set_inbound(void __iomem *base,
+ u64 cpu_addr, u64 pci_addr,
+ u64 flags, int idx, bool host)
+{
+ /*
+ * Set up 64-bit inbound regions as the range parser doesn't
+ * distinguish between 32 and 64-bit types.
+ */
+ if (host)
+ rcar_pci_write_reg(base, lower_32_bits(pci_addr),
+ PCIEPRAR(idx));
+ rcar_pci_write_reg(base, lower_32_bits(cpu_addr), PCIELAR(idx));
+ rcar_pci_write_reg(base, flags, PCIELAMR(idx));
+
+ if (host)
+ rcar_pci_write_reg(base, upper_32_bits(pci_addr),
+ PCIEPRAR(idx + 1));
+ rcar_pci_write_reg(base, upper_32_bits(cpu_addr), PCIELAR(idx + 1));
+ rcar_pci_write_reg(base, 0, PCIELAMR(idx + 1));
+}
diff --git a/drivers/pci/controller/pcie-rcar.h b/drivers/pci/controller/pcie-rcar.h
new file mode 100644
index 0000000..b529d806
--- /dev/null
+++ b/drivers/pci/controller/pcie-rcar.h
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PCIe driver for Renesas R-Car SoCs
+ * Copyright (C) 2014-2020 Renesas Electronics Europe Ltd
+ *
+ * Author: Phil Edworthy <phil.edworthy@...esas.com>
+ */
+
+#ifndef _PCIE_RCAR_H
+#define _PCIE_RCAR_H
+
+#define PCIECAR 0x000010
+#define PCIECCTLR 0x000018
+#define CONFIG_SEND_ENABLE BIT(31)
+#define TYPE0 (0 << 8)
+#define TYPE1 BIT(8)
+#define PCIECDR 0x000020
+#define PCIEMSR 0x000028
+#define PCIEINTXR 0x000400
+#define PCIEPHYSR 0x0007f0
+#define PHYRDY BIT(0)
+#define PCIEMSITXR 0x000840
+
+/* Transfer control */
+#define PCIETCTLR 0x02000
+#define DL_DOWN BIT(3)
+#define CFINIT BIT(0)
+#define PCIETSTR 0x02004
+#define DATA_LINK_ACTIVE BIT(0)
+#define PCIEERRFR 0x02020
+#define UNSUPPORTED_REQUEST BIT(4)
+#define PCIEMSIFR 0x02044
+#define PCIEMSIALR 0x02048
+#define MSIFE BIT(0)
+#define PCIEMSIAUR 0x0204c
+#define PCIEMSIIER 0x02050
+
+/* root port address */
+#define PCIEPRAR(x) (0x02080 + ((x) * 0x4))
+
+/* local address reg & mask */
+#define PCIELAR(x) (0x02200 + ((x) * 0x20))
+#define PCIELAMR(x) (0x02208 + ((x) * 0x20))
+#define LAM_PREFETCH BIT(3)
+#define LAM_64BIT BIT(2)
+#define LAR_ENABLE BIT(1)
+
+/* PCIe address reg & mask */
+#define PCIEPALR(x) (0x03400 + ((x) * 0x20))
+#define PCIEPAUR(x) (0x03404 + ((x) * 0x20))
+#define PCIEPAMR(x) (0x03408 + ((x) * 0x20))
+#define PCIEPTCTLR(x) (0x0340c + ((x) * 0x20))
+#define PAR_ENABLE BIT(31)
+#define IO_SPACE BIT(8)
+
+/* Configuration */
+#define PCICONF(x) (0x010000 + ((x) * 0x4))
+#define PMCAP(x) (0x010040 + ((x) * 0x4))
+#define EXPCAP(x) (0x010070 + ((x) * 0x4))
+#define VCCAP(x) (0x010100 + ((x) * 0x4))
+
+/* link layer */
+#define IDSETR1 0x011004
+#define TLCTLR 0x011048
+#define MACSR 0x011054
+#define SPCHGFIN BIT(4)
+#define SPCHGFAIL BIT(6)
+#define SPCHGSUC BIT(7)
+#define LINK_SPEED (0xf << 16)
+#define LINK_SPEED_2_5GTS (1 << 16)
+#define LINK_SPEED_5_0GTS (2 << 16)
+#define MACCTLR 0x011058
+#define MACCTLR_NFTS_MASK GENMASK(23, 16) /* The name is from SH7786 */
+#define SPEED_CHANGE BIT(24)
+#define SCRAMBLE_DISABLE BIT(27)
+#define LTSMDIS BIT(31)
+#define MACCTLR_INIT_VAL (LTSMDIS | MACCTLR_NFTS_MASK)
+#define PMSR 0x01105c
+#define MACS2R 0x011078
+#define MACCGSPSETR 0x011084
+#define SPCNGRSN BIT(31)
+
+/* R-Car H1 PHY */
+#define H1_PCIEPHYADRR 0x04000c
+#define WRITE_CMD BIT(16)
+#define PHY_ACK BIT(24)
+#define RATE_POS 12
+#define LANE_POS 8
+#define ADR_POS 0
+#define H1_PCIEPHYDOUTR 0x040014
+
+/* R-Car Gen2 PHY */
+#define GEN2_PCIEPHYADDR 0x780
+#define GEN2_PCIEPHYDATA 0x784
+#define GEN2_PCIEPHYCTRL 0x78c
+
+#define INT_PCI_MSI_NR 32
+
+#define RCONF(x) (PCICONF(0) + (x))
+#define RPMCAP(x) (PMCAP(0) + (x))
+#define REXPCAP(x) (EXPCAP(0) + (x))
+#define RVCCAP(x) (VCCAP(0) + (x))
+
+#define PCIE_CONF_BUS(b) (((b) & 0xff) << 24)
+#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 19)
+#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 16)
+
+#define RCAR_PCI_MAX_RESOURCES 4
+#define MAX_NR_INBOUND_MAPS 6
+
+enum {
+ RCAR_PCI_ACCESS_READ,
+ RCAR_PCI_ACCESS_WRITE,
+};
+
+void rcar_pci_write_reg(void __iomem *base, u32 val, unsigned int reg);
+u32 rcar_pci_read_reg(void __iomem *base, unsigned int reg);
+void rcar_rmw32(void __iomem *base, int where, u32 mask, u32 data);
+int rcar_pcie_wait_for_phyrdy(void __iomem *base);
+int rcar_pcie_wait_for_dl(void __iomem *base);
+void rcar_pcie_set_outbound(int win, void __iomem *base, struct resource *res);
+void rcar_pcie_set_inbound(void __iomem *base, u64 cpu_addr, u64 pci_addr,
+ u64 mask, int idx, bool host);
+
+#endif
--
2.7.4
Powered by blists - more mailing lists