2018-09-21 10:23:16

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 00/40] Cleanup pci-keystone.c and Add AM654 PCIe Support

Add PCIe RC support for TI's AM654 SoC. The PCIe controller in AM654
uses Synopsys core revision 4.90a and uses the same TI wrapper as used
in keystone2 with certain modification. Hence AM654 will use the same
pci wrapper driver pci-keystone.c

The initial support for AM654 was merged recently [1]

[1] -> https://lore.kernel.org/lkml/[email protected]/

Patch series includes the following
*) Merge pci-keystone-dw.c into pci-keystone.c so that we have single
file for PCIe keystone driver.
*) Cleanup the pci-keystone driver. In certain cases the DT binding is
also modified since PCIe in keystone has never worked in mainline
due to lack of PHY support.
*) Included the PHY driver here for completeness (though the driver
might go via linux-phy tree)
*) Included the device tree patches here. Once this series is reviewed
it'll be sent to be merged via Tony's tree.
*) Patch to fix ATU identification for designware version >= 4.80 in
designware core is also included here.

TODO:
*) Add Endpoint Support for AM654
*) Send a patch to fix the MRRS after the correct value is identified.

Once this series is reviewed I'll split the series and send to
corresponding subsytem Maintainers after removing RFC in subject.

Thanks
Kishon

Benoit Parrot (1):
arm64: dts: k3-am6: Add Main System Control Module node

Kishon Vijay Abraham I (39):
PCI: keystone: Use quirk to limit MRRS for K2G
PCI: keystone: Use quirk to set MRRS for PCI host bridge
PCI: keystone: Move dw_pcie_setup_rc out of ks_pcie_establish_link()
PCI: keystone: Do not initiate link training multiple times
PCI: keystone: Remove unused argument from ks_dw_pcie_host_init()
PCI: keystone: Add start_link/stop_link dw_pcie_ops
PCI: keystone: Merge pci-keystone-dw.c and pci-keystone.c
PCI: keystone: Cleanup MSI/legacy interrupt configuration and handling
PCI: keystone: Remove redundant platform_set_drvdata
PCI: keystone: Use uniform function naming convention
dt-bindings: PCI: keystone: Add bindings to get device control module
PCI: keystone: Use syscon APIs to get device id from control module
dt-bindings: PCI: keystone: Add "reg-names" binding information
PCI: keystone: Use platform_get_resource_byname to get memory
resources
PCI: keystone: Cleanup PHY handling
PCI: keystone: Invoke pm_runtime APIs to enable clock
PCI: keystone: Cleanup configuration space access
PCI: keystone: Get number of OB windows from DT and cleanup MEM space
configuration
PCI: keystone: Cleanup set_dbi_mode and get_dbi_mode
PCI: keystone: Cleanup ks_pcie_link_up()
PCI: keystone: Add debug error message for all errors
PCI: keystone: Reorder header file in alphabetical order
PCI: keystone: Cleanup macros defined in pci-keystone.c
PCI: keystone: Move initializations to appropriate places
dt-bindings: PCI: Add dt-binding to configure PCIe mode
PCI: keystone: Explicitly set the PCIe mode
dt-bindings: PCI: Document "atu" reg-names
PCI: dwc: Fix ATU identification for designware version >= 4.80
PCI: keystone: Prevent ARM32 specific code to be compiled for ARM64
dt-bindings: PCI: Add PCI RC dt binding documentation for AM654
PCI: keystone: Add support for PCIe in AM654x Platforms
phy: core: Invoke pm_runtime_get_*/pm_runtime_put_* before invoking
reset callback
dt-bindings: phy: ti: Add dt binding documentation for SERDES in
AM654x SoC
phy: ti: Add a new SERDES driver for TI's AM654x SoC
ARM: dts: keystone-k2e: Use the updated binding to describe PCIe in
k2e
arm64: dts: k3-am6: Add "socionext,synquacer-pre-its" property to
gic_its
arm64: dts: k3-am6: Add mux-controller dt node required for muxing
SERDES
arm64: dts: k3-am6: Add SERDES DT node
arm64: dts: k3-am6: Add Root Complex PCIe dt node

.../bindings/pci/designware-pcie.txt | 7 +-
.../devicetree/bindings/pci/pci-keystone.txt | 17 +-
.../devicetree/bindings/phy/ti-phy.txt | 77 ++
MAINTAINERS | 2 +-
arch/arm/boot/dts/keystone-k2e.dtsi | 15 +-
arch/arm/boot/dts/keystone.dtsi | 18 +-
arch/arm64/boot/dts/ti/k3-am65-main.dtsi | 142 +++
arch/arm64/boot/dts/ti/k3-am65.dtsi | 1 +
drivers/pci/controller/dwc/Kconfig | 2 +-
drivers/pci/controller/dwc/Makefile | 2 +-
drivers/pci/controller/dwc/pci-keystone-dw.c | 484 --------
drivers/pci/controller/dwc/pci-keystone.c | 1059 +++++++++++++----
drivers/pci/controller/dwc/pci-keystone.h | 57 -
.../pci/controller/dwc/pcie-designware-host.c | 16 -
drivers/pci/controller/dwc/pcie-designware.c | 50 +-
drivers/pci/controller/dwc/pcie-designware.h | 13 +-
drivers/phy/phy-core.c | 6 +
drivers/phy/ti/Kconfig | 11 +
drivers/phy/ti/Makefile | 1 +
drivers/phy/ti/phy-am654-serdes.c | 513 ++++++++
include/dt-bindings/phy/phy-am654-serdes.h | 13 +
21 files changed, 1690 insertions(+), 816 deletions(-)
delete mode 100644 drivers/pci/controller/dwc/pci-keystone-dw.c
delete mode 100644 drivers/pci/controller/dwc/pci-keystone.h
create mode 100644 drivers/phy/ti/phy-am654-serdes.c
create mode 100644 include/dt-bindings/phy/phy-am654-serdes.h

--
2.17.1



2018-09-21 10:23:52

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 04/40] PCI: keystone: Do not initiate link training multiple times

commit 886bc5ceb5cc3ad4b219502d72 ("PCI: designware: Add generic
dw_pcie_wait_for_link()") while adding a generic dw_pcie_wait_for_link()
performed a special handling (initiate link training multiple times) for
keystone which is not required. This also resulted in unncessarily waiting
for more time to establish the link even when no PCI device is connected.

Remove it and make it look similar to other dwc based PCIe drivers.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index fec46cfccba5..aa7e706fc37d 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -86,21 +86,18 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, quirk_limit_mrrs);
static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
{
struct dw_pcie *pci = ks_pcie->pci;
- struct pcie_port *pp = &pci->pp;
struct device *dev = pci->dev;
- unsigned int retries;

if (dw_pcie_link_up(pci)) {
dev_info(dev, "Link already up\n");
return 0;
}

+ ks_dw_pcie_initiate_link_train(ks_pcie);
+
/* check if the link is up or not */
- for (retries = 0; retries < 5; retries++) {
- ks_dw_pcie_initiate_link_train(ks_pcie);
- if (!dw_pcie_wait_for_link(pci))
- return 0;
- }
+ if (!dw_pcie_wait_for_link(pci))
+ return 0;

dev_err(dev, "phy link never came up\n");
return -ETIMEDOUT;
--
2.17.1


2018-09-21 10:24:02

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 03/40] PCI: keystone: Move dw_pcie_setup_rc out of ks_pcie_establish_link()

No functional change. Move dw_pcie_setup_rc out of
ks_pcie_establish_link() so that ks_pcie_establish_link only does what it
is supposed to do. This will be required for adding EP support which
will invoke ks_pcie_establish_link as part of start_link ops.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 5d9c5d199ada..fec46cfccba5 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -90,8 +90,6 @@ static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
struct device *dev = pci->dev;
unsigned int retries;

- dw_pcie_setup_rc(pp);
-
if (dw_pcie_link_up(pci)) {
dev_info(dev, "Link already up\n");
return 0;
@@ -266,6 +264,8 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);

+ dw_pcie_setup_rc(pp);
+
ks_pcie_establish_link(ks_pcie);
ks_dw_pcie_setup_rc_app_regs(ks_pcie);
ks_pcie_setup_interrupts(ks_pcie);
--
2.17.1


2018-09-21 10:24:06

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 01/40] PCI: keystone: Use quirk to limit MRRS for K2G

PCI controller in K2G also has a limitation that memory read request
size (MRRS) must not exceed 256 bytes. Use the quirk to limit MRRS
(added for K2HK, K2L and K2E) for K2G as well.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index e88bd221fffe..7d43e10a03b0 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -36,6 +36,7 @@
#define PCIE_RC_K2HK 0xb008
#define PCIE_RC_K2E 0xb009
#define PCIE_RC_K2L 0xb00a
+#define PCIE_RC_K2G 0xb00b

#define to_keystone_pcie(x) dev_get_drvdata((x)->dev)

@@ -50,6 +51,8 @@ static void quirk_limit_mrrs(struct pci_dev *dev)
.class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCIE_RC_K2L),
.class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
+ { PCI_DEVICE(PCI_VENDOR_ID_TI, PCIE_RC_K2G),
+ .class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
{ 0, },
};

--
2.17.1


2018-09-21 10:24:12

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 02/40] PCI: keystone: Use quirk to set MRRS for PCI host bridge

Reuse the already existing quirk to set MRRS for PCI host bridge
instead of explicitly setting MRRS in ks_pcie_host_init.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 37 +++++++++--------------
1 file changed, 15 insertions(+), 22 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 7d43e10a03b0..5d9c5d199ada 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -43,7 +43,7 @@
static void quirk_limit_mrrs(struct pci_dev *dev)
{
struct pci_bus *bus = dev->bus;
- struct pci_dev *bridge = bus->self;
+ struct pci_dev *bridge;
static const struct pci_device_id rc_pci_devids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCIE_RC_K2HK),
.class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
@@ -57,7 +57,7 @@ static void quirk_limit_mrrs(struct pci_dev *dev)
};

if (pci_is_root_bus(bus))
- return;
+ bridge = dev;

/* look for the host bridge */
while (!pci_is_root_bus(bus)) {
@@ -65,18 +65,19 @@ static void quirk_limit_mrrs(struct pci_dev *dev)
bus = bus->parent;
}

- if (bridge) {
- /*
- * Keystone PCI controller has a h/w limitation of
- * 256 bytes maximum read request size. It can't handle
- * anything higher than this. So force this limit on
- * all downstream devices.
- */
- if (pci_match_id(rc_pci_devids, bridge)) {
- if (pcie_get_readrq(dev) > 256) {
- dev_info(&dev->dev, "limiting MRRS to 256\n");
- pcie_set_readrq(dev, 256);
- }
+ if (!bridge)
+ return;
+
+ /*
+ * Keystone PCI controller has a h/w limitation of
+ * 256 bytes maximum read request size. It can't handle
+ * anything higher than this. So force this limit on
+ * all downstream devices.
+ */
+ if (pci_match_id(rc_pci_devids, bridge)) {
+ if (pcie_get_readrq(dev) > 256) {
+ dev_info(&dev->dev, "limiting MRRS to 256\n");
+ pcie_set_readrq(dev, 256);
}
}
}
@@ -264,7 +265,6 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
- u32 val;

ks_pcie_establish_link(ks_pcie);
ks_dw_pcie_setup_rc_app_regs(ks_pcie);
@@ -275,13 +275,6 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)
/* update the Vendor ID */
writew(ks_pcie->device_id, pci->dbi_base + PCI_DEVICE_ID);

- /* update the DEV_STAT_CTRL to publish right mrrs */
- val = readl(pci->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL);
- val &= ~PCI_EXP_DEVCTL_READRQ;
- /* set the mrrs to 256 bytes */
- val |= BIT(12);
- writel(val, pci->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL);
-
/*
* PCIe access errors that result into OCP errors are caught by ARM as
* "External aborts"
--
2.17.1


2018-09-21 10:24:20

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 05/40] PCI: keystone: Remove unused argument from ks_dw_pcie_host_init()

No functional change. Remove unused "msi_intc_np" argument from
ks_dw_pcie_host_init().

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone-dw.c | 3 +--
drivers/pci/controller/dwc/pci-keystone.c | 2 +-
drivers/pci/controller/dwc/pci-keystone.h | 3 +--
3 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone-dw.c b/drivers/pci/controller/dwc/pci-keystone-dw.c
index 0682213328e9..4bd6c6e2b177 100644
--- a/drivers/pci/controller/dwc/pci-keystone-dw.c
+++ b/drivers/pci/controller/dwc/pci-keystone-dw.c
@@ -439,8 +439,7 @@ void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie)
* and call dw_pcie_v3_65_host_init() API to initialize the Keystone
* PCI host controller.
*/
-int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
- struct device_node *msi_intc_np)
+int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie)
{
struct dw_pcie *pci = ks_pcie->pci;
struct pcie_port *pp = &pci->pp;
diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index aa7e706fc37d..f87ade2de711 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -341,7 +341,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
}

pp->ops = &keystone_pcie_host_ops;
- ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
+ ret = ks_dw_pcie_host_init(ks_pcie);
if (ret) {
dev_err(dev, "failed to initialize host\n");
return ret;
diff --git a/drivers/pci/controller/dwc/pci-keystone.h b/drivers/pci/controller/dwc/pci-keystone.h
index 8a13da391543..4eacc263f157 100644
--- a/drivers/pci/controller/dwc/pci-keystone.h
+++ b/drivers/pci/controller/dwc/pci-keystone.h
@@ -41,8 +41,7 @@ void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie);
void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset);
void ks_dw_pcie_enable_error_irq(struct keystone_pcie *ks_pcie);
irqreturn_t ks_dw_pcie_handle_error_irq(struct keystone_pcie *ks_pcie);
-int ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
- struct device_node *msi_intc_np);
+int ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie);
int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 val);
int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
--
2.17.1


2018-09-21 10:24:30

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 06/40] PCI: keystone: Add start_link/stop_link dw_pcie_ops

Add start_link/stop_link dw_pcie_ops and invoke ks_pcie_start_link
directly from host_init. This will also be required for adding EP
support.

While at that also use BIT() for LTSSM_EN_VAL.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone-dw.c | 9 +++-
drivers/pci/controller/dwc/pci-keystone.c | 51 +++++++++++---------
drivers/pci/controller/dwc/pci-keystone.h | 3 +-
3 files changed, 38 insertions(+), 25 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone-dw.c b/drivers/pci/controller/dwc/pci-keystone-dw.c
index 4bd6c6e2b177..ce399232cd99 100644
--- a/drivers/pci/controller/dwc/pci-keystone-dw.c
+++ b/drivers/pci/controller/dwc/pci-keystone-dw.c
@@ -21,7 +21,7 @@
#include "pci-keystone.h"

/* Application register defines */
-#define LTSSM_EN_VAL 1
+#define LTSSM_EN_VAL BIT(0)
#define LTSSM_STATE_MASK 0x1f
#define LTSSM_STATE_L0 0x11
#define DBI_CS2_EN_VAL 0x20
@@ -418,7 +418,7 @@ int ks_dw_pcie_link_up(struct dw_pcie *pci)
return (val & LTSSM_STATE_MASK) == LTSSM_STATE_L0;
}

-void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie)
+void ks_dw_pcie_stop_link(struct keystone_pcie *ks_pcie)
{
u32 val;

@@ -426,6 +426,11 @@ void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie)
val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
val &= ~LTSSM_EN_VAL;
ks_dw_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
+}
+
+void ks_dw_pcie_start_link(struct keystone_pcie *ks_pcie)
+{
+ u32 val;

/* Initiate Link Training */
val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index f87ade2de711..24afc691443b 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -40,6 +40,9 @@

#define to_keystone_pcie(x) dev_get_drvdata((x)->dev)

+static int ks_pcie_start_link(struct dw_pcie *pci);
+static void ks_pcie_stop_link(struct dw_pcie *pci);
+
static void quirk_limit_mrrs(struct pci_dev *dev)
{
struct pci_bus *bus = dev->bus;
@@ -83,26 +86,6 @@ static void quirk_limit_mrrs(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, quirk_limit_mrrs);

-static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
-{
- struct dw_pcie *pci = ks_pcie->pci;
- struct device *dev = pci->dev;
-
- if (dw_pcie_link_up(pci)) {
- dev_info(dev, "Link already up\n");
- return 0;
- }
-
- ks_dw_pcie_initiate_link_train(ks_pcie);
-
- /* check if the link is up or not */
- if (!dw_pcie_wait_for_link(pci))
- return 0;
-
- dev_err(dev, "phy link never came up\n");
- return -ETIMEDOUT;
-}
-
static void ks_pcie_msi_irq_handler(struct irq_desc *desc)
{
unsigned int irq = irq_desc_get_irq(desc);
@@ -263,7 +246,6 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)

dw_pcie_setup_rc(pp);

- ks_pcie_establish_link(ks_pcie);
ks_dw_pcie_setup_rc_app_regs(ks_pcie);
ks_pcie_setup_interrupts(ks_pcie);
writew(PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8),
@@ -279,7 +261,8 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)
hook_fault_code(17, keystone_pcie_fault, SIGBUS, 0,
"Asynchronous external abort");

- return 0;
+ ks_pcie_start_link(pci);
+ return dw_pcie_wait_for_link(pci);
}

static const struct dw_pcie_host_ops keystone_pcie_host_ops = {
@@ -358,7 +341,31 @@ static const struct of_device_id ks_pcie_of_match[] = {
{ },
};

+static int ks_pcie_start_link(struct dw_pcie *pci)
+{
+ struct device *dev = pci->dev;
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+
+ if (dw_pcie_link_up(pci)) {
+ dev_WARN(dev, "Link already up\n");
+ return 0;
+ }
+
+ ks_dw_pcie_start_link(ks_pcie);
+
+ return 0;
+}
+
+static void ks_pcie_stop_link(struct dw_pcie *pci)
+{
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+
+ ks_dw_pcie_stop_link(ks_pcie);
+}
+
static const struct dw_pcie_ops dw_pcie_ops = {
+ .start_link = ks_pcie_start_link,
+ .stop_link = ks_pcie_stop_link,
.link_up = ks_dw_pcie_link_up,
};

diff --git a/drivers/pci/controller/dwc/pci-keystone.h b/drivers/pci/controller/dwc/pci-keystone.h
index 4eacc263f157..a66deab626aa 100644
--- a/drivers/pci/controller/dwc/pci-keystone.h
+++ b/drivers/pci/controller/dwc/pci-keystone.h
@@ -47,7 +47,8 @@ int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 *val);
void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie);
-void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie);
+void ks_dw_pcie_start_link(struct keystone_pcie *ks_pcie);
+void ks_dw_pcie_stop_link(struct keystone_pcie *ks_pcie);
void ks_dw_pcie_msi_irq_ack(int i, struct pcie_port *pp);
void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq);
void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq);
--
2.17.1


2018-09-21 10:24:45

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 13/40] dt-bindings: PCI: keystone: Add "reg-names" binding information

Add "reg-names" binding information in order for device tree node
to be populated with the correct register strings.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
Documentation/devicetree/bindings/pci/pci-keystone.txt | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/pci-keystone.txt b/Documentation/devicetree/bindings/pci/pci-keystone.txt
index 2030ee0dc4f9..3a551687cfa2 100644
--- a/Documentation/devicetree/bindings/pci/pci-keystone.txt
+++ b/Documentation/devicetree/bindings/pci/pci-keystone.txt
@@ -12,8 +12,10 @@ described here as well as properties that are not applicable.
Required Properties:-

compatibility: "ti,keystone-pcie"
-reg: index 1 is the base address and length of DW application registers.
- index 2 is the base address and length of PCI device ID register.
+reg: Three register ranges as listed in the reg-names property
+reg-names: "dbics" for the DesignWare PCIe registers, "app" for the
+ TI specific application registers, "config" for the
+ configuration space address

pcie_msi_intc : Interrupt controller device node for MSI IRQ chip
interrupt-cells: should be set to 1
--
2.17.1


2018-09-21 10:24:50

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 15/40] PCI: keystone: Cleanup PHY handling

Cleanup PHY handling by using devm_phy_optional_get to get PHYs if
the PHYs are optional, creating a device link between the PHY device
and the controller device and disable PHY on error cases here.
Also invoke phy_reset() as part of enabling PHY.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 133 +++++++++++++++++++---
1 file changed, 115 insertions(+), 18 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index fe522b8c981f..b013776d9256 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -96,6 +96,9 @@ static void ks_pcie_stop_link(struct dw_pcie *pci);
struct keystone_pcie {
struct dw_pcie *pci;
struct clk *clk;
+ int num_lanes;
+ struct phy **phy;
+ struct device_link **link;
int msi_host_irq;
struct device_node *msi_intc_np;
struct irq_domain *legacy_irq_domain;
@@ -748,23 +751,62 @@ static const struct dw_pcie_ops ks_pcie_dw_pcie_ops = {
.link_up = ks_pcie_link_up,
};

-static int __exit ks_pcie_remove(struct platform_device *pdev)
+static void ks_pcie_disable_phy(struct keystone_pcie *ks_pcie)
{
- struct keystone_pcie *ks_pcie = platform_get_drvdata(pdev);
+ int num_lanes = ks_pcie->num_lanes;

- clk_disable_unprepare(ks_pcie->clk);
+ while (num_lanes--) {
+ phy_power_off(ks_pcie->phy[num_lanes]);
+ phy_exit(ks_pcie->phy[num_lanes]);
+ }
+}
+
+static int ks_pcie_enable_phy(struct keystone_pcie *ks_pcie)
+{
+ int i;
+ int ret;
+ int num_lanes = ks_pcie->num_lanes;
+
+ for (i = 0; i < num_lanes; i++) {
+ ret = phy_reset(ks_pcie->phy[i]);
+ if (ret < 0)
+ goto err_phy;
+
+ ret = phy_init(ks_pcie->phy[i]);
+ if (ret < 0)
+ goto err_phy;
+
+ ret = phy_power_on(ks_pcie->phy[i]);
+ if (ret < 0) {
+ phy_exit(ks_pcie->phy[i]);
+ goto err_phy;
+ }
+ }

return 0;
+
+err_phy:
+ while (--i >= 0) {
+ phy_power_off(ks_pcie->phy[i]);
+ phy_exit(ks_pcie->phy[i]);
+ }
+
+ return ret;
}

static int __init ks_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
struct dw_pcie *pci;
struct keystone_pcie *ks_pcie;
- struct phy *phy;
+ struct device_link **link;
+ struct phy **phy;
+ u32 num_lanes;
+ char name[10];
int ret;
int irq;
+ int i;

ks_pcie = devm_kzalloc(dev, sizeof(*ks_pcie), GFP_KERNEL);
if (!ks_pcie)
@@ -777,43 +819,76 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
pci->dev = dev;
pci->ops = &ks_pcie_dw_pcie_ops;

- ks_pcie->pci = pci;
+ ret = of_property_read_u32(np, "num-lanes", &num_lanes);
+ if (ret)
+ num_lanes = 1;

- /* initialize SerDes Phy if present */
- phy = devm_phy_get(dev, "pcie-phy");
- if (PTR_ERR_OR_ZERO(phy) == -EPROBE_DEFER)
- return PTR_ERR(phy);
+ phy = devm_kzalloc(dev, sizeof(*phy) * num_lanes, GFP_KERNEL);
+ if (!phy)
+ return -ENOMEM;

- if (!IS_ERR_OR_NULL(phy)) {
- ret = phy_init(phy);
- if (ret < 0)
- return ret;
+ link = devm_kzalloc(dev, sizeof(*link) * num_lanes, GFP_KERNEL);
+ if (!link)
+ return -ENOMEM;
+
+ for (i = 0; i < num_lanes; i++) {
+ snprintf(name, sizeof(name), "pcie-phy%d", i);
+ phy[i] = devm_phy_optional_get(dev, name);
+ if (IS_ERR(phy[i])) {
+ ret = PTR_ERR(phy[i]);
+ goto err_link;
+ }
+
+ if (!phy[i])
+ continue;
+
+ link[i] = device_link_add(dev, &phy[i]->dev, DL_FLAG_STATELESS);
+ if (!link[i]) {
+ ret = -EINVAL;
+ goto err_link;
+ }
}

- ks_pcie->np = dev->of_node;
+ ks_pcie->num_lanes = num_lanes;
+ ks_pcie->phy = phy;
+
+ ret = ks_pcie_enable_phy(ks_pcie);
+ if (ret) {
+ dev_err(dev, "failed to enable phy\n");
+ goto err_link;
+ }
+
+ ks_pcie->pci = pci;
+ ks_pcie->link = link;
+ ks_pcie->np = np;
+ ks_pcie->num_lanes = num_lanes;
+ ks_pcie->phy = phy;

irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "missing IRQ resource: %d\n", irq);
- return irq;
+ ret = irq;
+ goto err_get_irq;
}

ret = devm_request_irq(dev, irq, ks_pcie_err_irq_handler, IRQF_SHARED,
"ks-pcie-error-irq", ks_pcie);
if (ret < 0) {
dev_err(dev, "failed to request error IRQ %d\n", irq);
- return ret;
+ goto err_get_irq;
}

platform_set_drvdata(pdev, ks_pcie);
ks_pcie->clk = devm_clk_get(dev, "pcie");
if (IS_ERR(ks_pcie->clk)) {
dev_err(dev, "Failed to get pcie rc clock\n");
- return PTR_ERR(ks_pcie->clk);
+ ret = PTR_ERR(ks_pcie->clk);
+ goto err_get_irq;
}
+
ret = clk_prepare_enable(ks_pcie->clk);
if (ret)
- return ret;
+ goto err_get_irq;

ret = ks_pcie_add_pcie_port(ks_pcie, pdev);
if (ret < 0)
@@ -825,9 +900,31 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
fail_clk:
clk_disable_unprepare(ks_pcie->clk);

+err_get_irq:
+ ks_pcie_disable_phy(ks_pcie);
+
+err_link:
+ while (--i >= 0 && link[i])
+ device_link_del(link[i]);
+
return ret;
}

+static int __exit ks_pcie_remove(struct platform_device *pdev)
+{
+ struct keystone_pcie *ks_pcie = platform_get_drvdata(pdev);
+ struct device_link **link = ks_pcie->link;
+ int num_lanes = ks_pcie->num_lanes;
+
+ clk_disable_unprepare(ks_pcie->clk);
+ ks_pcie_disable_phy(ks_pcie);
+
+ while (num_lanes--)
+ device_link_del(link[num_lanes]);
+
+ return 0;
+}
+
static struct platform_driver ks_pcie_driver __refdata = {
.probe = ks_pcie_probe,
.remove = __exit_p(ks_pcie_remove),
--
2.17.1


2018-09-21 10:25:13

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 20/40] PCI: keystone: Cleanup ks_pcie_link_up()

ks_pcie_link_up() uses registers from the designware core to get the
status of the link. Move the register defines to pcie-designware.h
and cleanup ks_pcie_link_up().

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 10 +++-------
drivers/pci/controller/dwc/pcie-designware.h | 4 ++++
2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 728b1e0db314..240c39c58b0f 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -38,8 +38,6 @@

/* Application register defines */
#define LTSSM_EN_VAL BIT(0)
-#define LTSSM_STATE_MASK 0x1f
-#define LTSSM_STATE_L0 0x11
#define DBI_CS2 BIT(5)
#define OB_XLAT_EN_VAL BIT(1)

@@ -87,9 +85,6 @@

#define OB_OFFSET_HI(n) (0x204 + (8 * (n)))

-/* Config space registers */
-#define DEBUG0 0x728
-
/* PCIE controller device IDs */
#define PCIE_RC_K2HK 0xb008
#define PCIE_RC_K2E 0xb009
@@ -308,8 +303,9 @@ static int ks_pcie_link_up(struct dw_pcie *pci)
{
u32 val;

- val = dw_pcie_readl_dbi(pci, DEBUG0);
- return (val & LTSSM_STATE_MASK) == LTSSM_STATE_L0;
+ val = dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0);
+ val &= PORT_LOGIC_LTSSM_STATE_MASK;
+ return (val == PORT_LOGIC_LTSSM_STATE_L0);
}

static void ks_pcie_quirk(struct pci_dev *dev)
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 96126fd8403c..a4d939536faf 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -37,6 +37,10 @@
#define PORT_LINK_MODE_4_LANES (0x7 << 16)
#define PORT_LINK_MODE_8_LANES (0xf << 16)

+#define PCIE_PORT_DEBUG0 0x728
+#define PORT_LOGIC_LTSSM_STATE_MASK 0x1f
+#define PORT_LOGIC_LTSSM_STATE_L0 0x11
+
#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
#define PORT_LOGIC_LINK_WIDTH_MASK (0x1f << 8)
--
2.17.1


2018-09-21 10:25:22

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 12/40] PCI: keystone: Use syscon APIs to get device id from control module

Control module registers should be read using syscon APIs.
pci-keystone.c uses platform_get_resource to get control module registers.
Fix it here by using syscon APIs to get device id from control module.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 46 +++++++++++++++--------
1 file changed, 31 insertions(+), 15 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index e19ba065ebd5..505e13b1197d 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -15,12 +15,14 @@
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/init.h>
+#include <linux/mfd/syscon.h>
#include <linux/msi.h>
#include <linux/of_irq.h>
#include <linux/of.h>
#include <linux/of_pci.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
+#include <linux/regmap.h>
#include <linux/resource.h>
#include <linux/signal.h>

@@ -28,6 +30,9 @@

#define DRIVER_NAME "keystone-pcie"

+#define PCIE_VENDORID_MASK 0xffff
+#define PCIE_DEVICEID_SHIFT 16
+
/* DEV_STAT_CTRL */
#define PCIE_CAP_BASE 0x70

@@ -92,8 +97,6 @@ static void ks_pcie_stop_link(struct dw_pcie *pci);
struct keystone_pcie {
struct dw_pcie *pci;
struct clk *clk;
- /* PCI Device ID */
- u32 device_id;
int msi_host_irq;
struct device_node *msi_intc_np;
struct irq_domain *legacy_irq_domain;
@@ -588,6 +591,29 @@ static int ks_pcie_fault(unsigned long addr, unsigned int fsr,
return 0;
}

+static int __init ks_pcie_init_id(struct keystone_pcie *ks_pcie)
+{
+ int ret;
+ unsigned int id;
+ struct regmap *devctrl_regs;
+ struct dw_pcie *pci = ks_pcie->pci;
+ struct device *dev = pci->dev;
+ struct device_node *np = dev->of_node;
+
+ devctrl_regs = syscon_regmap_lookup_by_phandle(np, "ti,syscon-pcie-id");
+ if (IS_ERR(devctrl_regs))
+ return PTR_ERR(devctrl_regs);
+
+ ret = regmap_read(devctrl_regs, 0, &id);
+ if (ret)
+ return ret;
+
+ dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, id & PCIE_VENDORID_MASK);
+ dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, id >> PCIE_DEVICEID_SHIFT);
+
+ return 0;
+}
+
static int __init ks_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -608,8 +634,9 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)
writew(PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8),
pci->dbi_base + PCI_IO_BASE);

- /* update the Vendor ID */
- writew(ks_pcie->device_id, pci->dbi_base + PCI_DEVICE_ID);
+ ret = ks_pcie_init_id(ks_pcie);
+ if (ret < 0)
+ return ret;

/*
* PCIe access errors that result into OCP errors are caught by ARM as
@@ -738,8 +765,6 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct dw_pcie *pci;
struct keystone_pcie *ks_pcie;
- struct resource *res;
- void __iomem *reg_p;
struct phy *phy;
int ret;
int irq;
@@ -768,15 +793,6 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
return ret;
}

- /* index 2 is to read PCI DEVICE_ID */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
- reg_p = devm_ioremap_resource(dev, res);
- if (IS_ERR(reg_p))
- return PTR_ERR(reg_p);
- ks_pcie->device_id = readl(reg_p) >> 16;
- devm_iounmap(dev, reg_p);
- devm_release_mem_region(dev, res->start, resource_size(res));
-
ks_pcie->np = dev->of_node;

irq = platform_get_irq(pdev, 0);
--
2.17.1


2018-09-21 10:25:22

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 23/40] PCI: keystone: Cleanup macros defined in pci-keystone.c

No functional change. Cleanup macros defined in pci-keystone.c
by removing unused macros, grouping the macros and aligning
it properly.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 41 +++++++++--------------
1 file changed, 16 insertions(+), 25 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index b1dfaea29530..75d007148804 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -28,21 +28,14 @@

#include "pcie-designware.h"

-#define DRIVER_NAME "keystone-pcie"
-
#define PCIE_VENDORID_MASK 0xffff
#define PCIE_DEVICEID_SHIFT 16

-/* DEV_STAT_CTRL */
-#define PCIE_CAP_BASE 0x70
-
-/* Application register defines */
-#define LTSSM_EN_VAL BIT(0)
-#define DBI_CS2 BIT(5)
-#define OB_XLAT_EN_VAL BIT(1)
-
/* Application registers */
#define CMD_STATUS 0x004
+#define LTSSM_EN_VAL BIT(0)
+#define OB_XLAT_EN_VAL BIT(1)
+#define DBI_CS2 BIT(5)

#define CFG_SETUP 0x008
#define CFG_BUS(x) (((x) & 0xff) << 16)
@@ -65,18 +58,16 @@
#define IRQ_ENABLE_SET(n) (0x188 + ((n) << 4))
#define INTx_EN BIT(0)

-/* Error IRQ bits */
-#define ERR_AER BIT(5) /* ECRC error */
-#define ERR_AXI BIT(4) /* AXI tag lookup fatal error */
-#define ERR_CORR BIT(3) /* Correctable error */
-#define ERR_NONFATAL BIT(2) /* Non-fatal error */
-#define ERR_FATAL BIT(1) /* Fatal error */
-#define ERR_SYS BIT(0) /* System (fatal, non-fatal, or correctable) */
-#define ERR_IRQ_ALL (ERR_AER | ERR_AXI | ERR_CORR | \
- ERR_NONFATAL | ERR_FATAL | ERR_SYS)
#define ERR_IRQ_STATUS 0x1c4
#define ERR_IRQ_ENABLE_SET 0x1c8
-#define ERR_IRQ_ENABLE_CLR 0x1cc
+#define ERR_AER BIT(5) /* ECRC error */
+#define ERR_AXI BIT(4) /* AXI tag lookup fatal error */
+#define ERR_CORR BIT(3) /* Correctable error */
+#define ERR_NONFATAL BIT(2) /* Non-fatal error */
+#define ERR_FATAL BIT(1) /* Fatal error */
+#define ERR_SYS BIT(0) /* System error */
+#define ERR_IRQ_ALL (ERR_AER | ERR_AXI | ERR_CORR | \
+ ERR_NONFATAL | ERR_FATAL | ERR_SYS)

#define OB_OFFSET_INDEX(n) (0x200 + (8 * (n)))
#define OB_ENABLEN BIT(0)
@@ -84,12 +75,12 @@
#define OB_OFFSET_HI(n) (0x204 + (8 * (n)))

/* PCIE controller device IDs */
-#define PCIE_RC_K2HK 0xb008
-#define PCIE_RC_K2E 0xb009
-#define PCIE_RC_K2L 0xb00a
-#define PCIE_RC_K2G 0xb00b
+#define PCIE_RC_K2HK 0xb008
+#define PCIE_RC_K2E 0xb009
+#define PCIE_RC_K2L 0xb00a
+#define PCIE_RC_K2G 0xb00b

-#define to_keystone_pcie(x) dev_get_drvdata((x)->dev)
+#define to_keystone_pcie(x) dev_get_drvdata((x)->dev)

static int ks_pcie_start_link(struct dw_pcie *pci);
static void ks_pcie_stop_link(struct dw_pcie *pci);
--
2.17.1


2018-09-21 10:25:22

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 22/40] PCI: keystone: Reorder header file in alphabetical order

No functional change. Reorder header file in alphabetical order.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index a3dec74da70c..b1dfaea29530 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -9,19 +9,19 @@
* Implementation based on pci-exynos.c and pcie-designware.c
*/

-#include <linux/irqchip/chained_irq.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
-#include <linux/init.h>
#include <linux/mfd/syscon.h>
#include <linux/msi.h>
-#include <linux/of_irq.h>
#include <linux/of.h>
+#include <linux/of_irq.h>
#include <linux/of_pci.h>
-#include <linux/platform_device.h>
#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/resource.h>
#include <linux/signal.h>
--
2.17.1


2018-09-21 10:25:32

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 24/40] PCI: keystone: Move initializations to appropriate places

No functional change. Move host specific platform_get_resource to
ks_add_pcie_port and the common platform_get_resource (applicable
to both host and endpoint) to probe. This is in preparation for
adding endpoint support to pci-keystone driver.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 27 +++++++++++++----------
1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 75d007148804..13e865f82f96 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -646,11 +646,6 @@ static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie,
struct resource *res;
int ret;

- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbics");
- pci->dbi_base = devm_pci_remap_cfg_resource(dev, res);
- if (IS_ERR(pci->dbi_base))
- return PTR_ERR(pci->dbi_base);
-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
pp->va_cfg0_base = devm_pci_remap_cfg_resource(dev, res);
if (IS_ERR(pp->va_cfg0_base))
@@ -658,13 +653,6 @@ static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie,

pp->va_cfg1_base = pp->va_cfg0_base;

- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "app");
- ks_pcie->va_app_base = devm_ioremap_resource(dev, res);
- if (IS_ERR(ks_pcie->va_app_base))
- return PTR_ERR(ks_pcie->va_app_base);
-
- ks_pcie->app = *res;
-
pp->ops = &ks_pcie_host_ops;
ret = dw_pcie_host_init(pp);
if (ret) {
@@ -768,6 +756,8 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
struct dw_pcie *pci;
struct keystone_pcie *ks_pcie;
struct device_link **link;
+ struct resource *res;
+ void __iomem *base;
u32 num_viewport;
struct phy **phy;
u32 num_lanes;
@@ -784,6 +774,19 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
if (!pci)
return -ENOMEM;

+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "app");
+ ks_pcie->va_app_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(ks_pcie->va_app_base))
+ return PTR_ERR(ks_pcie->va_app_base);
+
+ ks_pcie->app = *res;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbics");
+ base = devm_pci_remap_cfg_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ pci->dbi_base = base;
pci->dev = dev;
pci->ops = &ks_pcie_dw_pcie_ops;

--
2.17.1


2018-09-21 10:25:37

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 25/40] dt-bindings: PCI: Add dt-binding to configure PCIe mode

Add "ti,syscon-pcie-mode" dt-binding to hold phandle to the syscon
register that should be used to configure PCIe in RC mode or EP mode.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
Documentation/devicetree/bindings/pci/pci-keystone.txt | 2 ++
1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/pci-keystone.txt b/Documentation/devicetree/bindings/pci/pci-keystone.txt
index 3a551687cfa2..8ee07197a063 100644
--- a/Documentation/devicetree/bindings/pci/pci-keystone.txt
+++ b/Documentation/devicetree/bindings/pci/pci-keystone.txt
@@ -23,6 +23,8 @@ pcie_msi_intc : Interrupt controller device node for MSI IRQ chip

ti,syscon-pcie-id : phandle to the device control module required to set device
id and vendor id.
+ti,syscon-pcie-mode : phandle to the device control module required to configure
+ PCI in either RC mode or EP mode.

Example:
pcie_msi_intc: msi-interrupt-controller {
--
2.17.1


2018-09-21 10:25:42

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 07/40] PCI: keystone: Merge pci-keystone-dw.c and pci-keystone.c

No functional change. Having two different files for keystone PCI driver
doesn't serve any purpose. Merge pci-keystone-dw.c and pci-keystone.c
into a single pci-keystone.c file and remove pci-keystone.h

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
The "CHECK:" warnings here by checkpatch.pl will be fixed in the later
part of the series.
MAINTAINERS | 2 +-
drivers/pci/controller/dwc/Makefile | 2 +-
drivers/pci/controller/dwc/pci-keystone-dw.c | 488 ------------------
drivers/pci/controller/dwc/pci-keystone.c | 493 ++++++++++++++++++-
drivers/pci/controller/dwc/pci-keystone.h | 57 ---
5 files changed, 494 insertions(+), 548 deletions(-)
delete mode 100644 drivers/pci/controller/dwc/pci-keystone-dw.c
delete mode 100644 drivers/pci/controller/dwc/pci-keystone.h

diff --git a/MAINTAINERS b/MAINTAINERS
index a5b256b25905..3101b2fa3449 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11172,7 +11172,7 @@ M: Murali Karicheri <[email protected]>
L: [email protected]
L: [email protected] (moderated for non-subscribers)
S: Maintained
-F: drivers/pci/controller/dwc/*keystone*
+F: drivers/pci/controller/dwc/pci-keystone.c

PCI ENDPOINT SUBSYSTEM
M: Kishon Vijay Abraham I <[email protected]>
diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
index 5d2ce72c7a52..fcf91eacfc63 100644
--- a/drivers/pci/controller/dwc/Makefile
+++ b/drivers/pci/controller/dwc/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
-obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
+obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone.o
obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
diff --git a/drivers/pci/controller/dwc/pci-keystone-dw.c b/drivers/pci/controller/dwc/pci-keystone-dw.c
deleted file mode 100644
index ce399232cd99..000000000000
--- a/drivers/pci/controller/dwc/pci-keystone-dw.c
+++ /dev/null
@@ -1,488 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * DesignWare application register space functions for Keystone PCI controller
- *
- * Copyright (C) 2013-2014 Texas Instruments., Ltd.
- * http://www.ti.com
- *
- * Author: Murali Karicheri <[email protected]>
- */
-
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/irqreturn.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_pci.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-
-#include "pcie-designware.h"
-#include "pci-keystone.h"
-
-/* Application register defines */
-#define LTSSM_EN_VAL BIT(0)
-#define LTSSM_STATE_MASK 0x1f
-#define LTSSM_STATE_L0 0x11
-#define DBI_CS2_EN_VAL 0x20
-#define OB_XLAT_EN_VAL 2
-
-/* Application registers */
-#define CMD_STATUS 0x004
-#define CFG_SETUP 0x008
-#define OB_SIZE 0x030
-#define CFG_PCIM_WIN_SZ_IDX 3
-#define CFG_PCIM_WIN_CNT 32
-#define SPACE0_REMOTE_CFG_OFFSET 0x1000
-#define OB_OFFSET_INDEX(n) (0x200 + (8 * n))
-#define OB_OFFSET_HI(n) (0x204 + (8 * n))
-
-/* IRQ register defines */
-#define IRQ_EOI 0x050
-#define IRQ_STATUS 0x184
-#define IRQ_ENABLE_SET 0x188
-#define IRQ_ENABLE_CLR 0x18c
-
-#define MSI_IRQ 0x054
-#define MSI0_IRQ_STATUS 0x104
-#define MSI0_IRQ_ENABLE_SET 0x108
-#define MSI0_IRQ_ENABLE_CLR 0x10c
-#define IRQ_STATUS 0x184
-#define MSI_IRQ_OFFSET 4
-
-/* Error IRQ bits */
-#define ERR_AER BIT(5) /* ECRC error */
-#define ERR_AXI BIT(4) /* AXI tag lookup fatal error */
-#define ERR_CORR BIT(3) /* Correctable error */
-#define ERR_NONFATAL BIT(2) /* Non-fatal error */
-#define ERR_FATAL BIT(1) /* Fatal error */
-#define ERR_SYS BIT(0) /* System (fatal, non-fatal, or correctable) */
-#define ERR_IRQ_ALL (ERR_AER | ERR_AXI | ERR_CORR | \
- ERR_NONFATAL | ERR_FATAL | ERR_SYS)
-#define ERR_FATAL_IRQ (ERR_FATAL | ERR_AXI)
-#define ERR_IRQ_STATUS_RAW 0x1c0
-#define ERR_IRQ_STATUS 0x1c4
-#define ERR_IRQ_ENABLE_SET 0x1c8
-#define ERR_IRQ_ENABLE_CLR 0x1cc
-
-/* Config space registers */
-#define DEBUG0 0x728
-
-#define to_keystone_pcie(x) dev_get_drvdata((x)->dev)
-
-static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset,
- u32 *bit_pos)
-{
- *reg_offset = offset % 8;
- *bit_pos = offset >> 3;
-}
-
-phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp)
-{
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
-
- return ks_pcie->app.start + MSI_IRQ;
-}
-
-static u32 ks_dw_app_readl(struct keystone_pcie *ks_pcie, u32 offset)
-{
- return readl(ks_pcie->va_app_base + offset);
-}
-
-static void ks_dw_app_writel(struct keystone_pcie *ks_pcie, u32 offset, u32 val)
-{
- writel(val, ks_pcie->va_app_base + offset);
-}
-
-void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset)
-{
- struct dw_pcie *pci = ks_pcie->pci;
- struct pcie_port *pp = &pci->pp;
- struct device *dev = pci->dev;
- u32 pending, vector;
- int src, virq;
-
- pending = ks_dw_app_readl(ks_pcie, MSI0_IRQ_STATUS + (offset << 4));
-
- /*
- * MSI0 status bit 0-3 shows vectors 0, 8, 16, 24, MSI1 status bit
- * shows 1, 9, 17, 25 and so forth
- */
- for (src = 0; src < 4; src++) {
- if (BIT(src) & pending) {
- vector = offset + (src << 3);
- virq = irq_linear_revmap(pp->irq_domain, vector);
- dev_dbg(dev, "irq: bit %d, vector %d, virq %d\n",
- src, vector, virq);
- generic_handle_irq(virq);
- }
- }
-}
-
-void ks_dw_pcie_msi_irq_ack(int irq, struct pcie_port *pp)
-{
- u32 reg_offset, bit_pos;
- struct keystone_pcie *ks_pcie;
- struct dw_pcie *pci;
-
- pci = to_dw_pcie_from_pp(pp);
- ks_pcie = to_keystone_pcie(pci);
- update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
-
- ks_dw_app_writel(ks_pcie, MSI0_IRQ_STATUS + (reg_offset << 4),
- BIT(bit_pos));
- ks_dw_app_writel(ks_pcie, IRQ_EOI, reg_offset + MSI_IRQ_OFFSET);
-}
-
-void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
-{
- u32 reg_offset, bit_pos;
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
-
- update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
- ks_dw_app_writel(ks_pcie, MSI0_IRQ_ENABLE_SET + (reg_offset << 4),
- BIT(bit_pos));
-}
-
-void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
-{
- u32 reg_offset, bit_pos;
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
-
- update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
- ks_dw_app_writel(ks_pcie, MSI0_IRQ_ENABLE_CLR + (reg_offset << 4),
- BIT(bit_pos));
-}
-
-int ks_dw_pcie_msi_host_init(struct pcie_port *pp)
-{
- return dw_pcie_allocate_domains(pp);
-}
-
-void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie)
-{
- int i;
-
- for (i = 0; i < PCI_NUM_INTX; i++)
- ks_dw_app_writel(ks_pcie, IRQ_ENABLE_SET + (i << 4), 0x1);
-}
-
-void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset)
-{
- struct dw_pcie *pci = ks_pcie->pci;
- struct device *dev = pci->dev;
- u32 pending;
- int virq;
-
- pending = ks_dw_app_readl(ks_pcie, IRQ_STATUS + (offset << 4));
-
- if (BIT(0) & pending) {
- virq = irq_linear_revmap(ks_pcie->legacy_irq_domain, offset);
- dev_dbg(dev, ": irq: irq_offset %d, virq %d\n", offset, virq);
- generic_handle_irq(virq);
- }
-
- /* EOI the INTx interrupt */
- ks_dw_app_writel(ks_pcie, IRQ_EOI, offset);
-}
-
-void ks_dw_pcie_enable_error_irq(struct keystone_pcie *ks_pcie)
-{
- ks_dw_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL);
-}
-
-irqreturn_t ks_dw_pcie_handle_error_irq(struct keystone_pcie *ks_pcie)
-{
- u32 status;
-
- status = ks_dw_app_readl(ks_pcie, ERR_IRQ_STATUS_RAW) & ERR_IRQ_ALL;
- if (!status)
- return IRQ_NONE;
-
- if (status & ERR_FATAL_IRQ)
- dev_err(ks_pcie->pci->dev, "fatal error (status %#010x)\n",
- status);
-
- /* Ack the IRQ; status bits are RW1C */
- ks_dw_app_writel(ks_pcie, ERR_IRQ_STATUS, status);
- return IRQ_HANDLED;
-}
-
-static void ks_dw_pcie_ack_legacy_irq(struct irq_data *d)
-{
-}
-
-static void ks_dw_pcie_mask_legacy_irq(struct irq_data *d)
-{
-}
-
-static void ks_dw_pcie_unmask_legacy_irq(struct irq_data *d)
-{
-}
-
-static struct irq_chip ks_dw_pcie_legacy_irq_chip = {
- .name = "Keystone-PCI-Legacy-IRQ",
- .irq_ack = ks_dw_pcie_ack_legacy_irq,
- .irq_mask = ks_dw_pcie_mask_legacy_irq,
- .irq_unmask = ks_dw_pcie_unmask_legacy_irq,
-};
-
-static int ks_dw_pcie_init_legacy_irq_map(struct irq_domain *d,
- unsigned int irq, irq_hw_number_t hw_irq)
-{
- irq_set_chip_and_handler(irq, &ks_dw_pcie_legacy_irq_chip,
- handle_level_irq);
- irq_set_chip_data(irq, d->host_data);
-
- return 0;
-}
-
-static const struct irq_domain_ops ks_dw_pcie_legacy_irq_domain_ops = {
- .map = ks_dw_pcie_init_legacy_irq_map,
- .xlate = irq_domain_xlate_onetwocell,
-};
-
-/**
- * ks_dw_pcie_set_dbi_mode() - Set DBI mode to access overlaid BAR mask
- * registers
- *
- * Since modification of dbi_cs2 involves different clock domain, read the
- * status back to ensure the transition is complete.
- */
-static void ks_dw_pcie_set_dbi_mode(struct keystone_pcie *ks_pcie)
-{
- u32 val;
-
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- ks_dw_app_writel(ks_pcie, CMD_STATUS, DBI_CS2_EN_VAL | val);
-
- do {
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- } while (!(val & DBI_CS2_EN_VAL));
-}
-
-/**
- * ks_dw_pcie_clear_dbi_mode() - Disable DBI mode
- *
- * Since modification of dbi_cs2 involves different clock domain, read the
- * status back to ensure the transition is complete.
- */
-static void ks_dw_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie)
-{
- u32 val;
-
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- ks_dw_app_writel(ks_pcie, CMD_STATUS, ~DBI_CS2_EN_VAL & val);
-
- do {
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- } while (val & DBI_CS2_EN_VAL);
-}
-
-void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
-{
- struct dw_pcie *pci = ks_pcie->pci;
- struct pcie_port *pp = &pci->pp;
- u32 start = pp->mem->start, end = pp->mem->end;
- int i, tr_size;
- u32 val;
-
- /* Disable BARs for inbound access */
- ks_dw_pcie_set_dbi_mode(ks_pcie);
- dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0);
- dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0);
- ks_dw_pcie_clear_dbi_mode(ks_pcie);
-
- /* Set outbound translation size per window division */
- ks_dw_app_writel(ks_pcie, OB_SIZE, CFG_PCIM_WIN_SZ_IDX & 0x7);
-
- tr_size = (1 << (CFG_PCIM_WIN_SZ_IDX & 0x7)) * SZ_1M;
-
- /* Using Direct 1:1 mapping of RC <-> PCI memory space */
- for (i = 0; (i < CFG_PCIM_WIN_CNT) && (start < end); i++) {
- ks_dw_app_writel(ks_pcie, OB_OFFSET_INDEX(i), start | 1);
- ks_dw_app_writel(ks_pcie, OB_OFFSET_HI(i), 0);
- start += tr_size;
- }
-
- /* Enable OB translation */
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- ks_dw_app_writel(ks_pcie, CMD_STATUS, OB_XLAT_EN_VAL | val);
-}
-
-/**
- * ks_pcie_cfg_setup() - Set up configuration space address for a device
- *
- * @ks_pcie: ptr to keystone_pcie structure
- * @bus: Bus number the device is residing on
- * @devfn: device, function number info
- *
- * Forms and returns the address of configuration space mapped in PCIESS
- * address space 0. Also configures CFG_SETUP for remote configuration space
- * access.
- *
- * The address space has two regions to access configuration - local and remote.
- * We access local region for bus 0 (as RC is attached on bus 0) and remote
- * region for others with TYPE 1 access when bus > 1. As for device on bus = 1,
- * we will do TYPE 0 access as it will be on our secondary bus (logical).
- * CFG_SETUP is needed only for remote configuration access.
- */
-static void __iomem *ks_pcie_cfg_setup(struct keystone_pcie *ks_pcie, u8 bus,
- unsigned int devfn)
-{
- u8 device = PCI_SLOT(devfn), function = PCI_FUNC(devfn);
- struct dw_pcie *pci = ks_pcie->pci;
- struct pcie_port *pp = &pci->pp;
- u32 regval;
-
- if (bus == 0)
- return pci->dbi_base;
-
- regval = (bus << 16) | (device << 8) | function;
-
- /*
- * Since Bus#1 will be a virtual bus, we need to have TYPE0
- * access only.
- * TYPE 1
- */
- if (bus != 1)
- regval |= BIT(24);
-
- ks_dw_app_writel(ks_pcie, CFG_SETUP, regval);
- return pp->va_cfg0_base;
-}
-
-int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
- unsigned int devfn, int where, int size, u32 *val)
-{
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
- u8 bus_num = bus->number;
- void __iomem *addr;
-
- addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
-
- return dw_pcie_read(addr + where, size, val);
-}
-
-int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
- unsigned int devfn, int where, int size, u32 val)
-{
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
- u8 bus_num = bus->number;
- void __iomem *addr;
-
- addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
-
- return dw_pcie_write(addr + where, size, val);
-}
-
-/**
- * ks_dw_pcie_v3_65_scan_bus() - keystone scan_bus post initialization
- *
- * This sets BAR0 to enable inbound access for MSI_IRQ register
- */
-void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp)
-{
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
-
- /* Configure and set up BAR0 */
- ks_dw_pcie_set_dbi_mode(ks_pcie);
-
- /* Enable BAR0 */
- dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 1);
- dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, SZ_4K - 1);
-
- ks_dw_pcie_clear_dbi_mode(ks_pcie);
-
- /*
- * For BAR0, just setting bus address for inbound writes (MSI) should
- * be sufficient. Use physical address to avoid any conflicts.
- */
- dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, ks_pcie->app.start);
-}
-
-/**
- * ks_dw_pcie_link_up() - Check if link up
- */
-int ks_dw_pcie_link_up(struct dw_pcie *pci)
-{
- u32 val;
-
- val = dw_pcie_readl_dbi(pci, DEBUG0);
- return (val & LTSSM_STATE_MASK) == LTSSM_STATE_L0;
-}
-
-void ks_dw_pcie_stop_link(struct keystone_pcie *ks_pcie)
-{
- u32 val;
-
- /* Disable Link training */
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- val &= ~LTSSM_EN_VAL;
- ks_dw_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
-}
-
-void ks_dw_pcie_start_link(struct keystone_pcie *ks_pcie)
-{
- u32 val;
-
- /* Initiate Link Training */
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- ks_dw_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
-}
-
-/**
- * ks_dw_pcie_host_init() - initialize host for v3_65 dw hardware
- *
- * Ioremap the register resources, initialize legacy irq domain
- * and call dw_pcie_v3_65_host_init() API to initialize the Keystone
- * PCI host controller.
- */
-int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie)
-{
- struct dw_pcie *pci = ks_pcie->pci;
- struct pcie_port *pp = &pci->pp;
- struct device *dev = pci->dev;
- struct platform_device *pdev = to_platform_device(dev);
- struct resource *res;
-
- /* Index 0 is the config reg. space address */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- pci->dbi_base = devm_pci_remap_cfg_resource(dev, res);
- if (IS_ERR(pci->dbi_base))
- return PTR_ERR(pci->dbi_base);
-
- /*
- * We set these same and is used in pcie rd/wr_other_conf
- * functions
- */
- pp->va_cfg0_base = pci->dbi_base + SPACE0_REMOTE_CFG_OFFSET;
- pp->va_cfg1_base = pp->va_cfg0_base;
-
- /* Index 1 is the application reg. space address */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- ks_pcie->va_app_base = devm_ioremap_resource(dev, res);
- if (IS_ERR(ks_pcie->va_app_base))
- return PTR_ERR(ks_pcie->va_app_base);
-
- ks_pcie->app = *res;
-
- /* Create legacy IRQ domain */
- ks_pcie->legacy_irq_domain =
- irq_domain_add_linear(ks_pcie->legacy_intc_np,
- PCI_NUM_INTX,
- &ks_dw_pcie_legacy_irq_domain_ops,
- NULL);
- if (!ks_pcie->legacy_irq_domain) {
- dev_err(dev, "Failed to add irq domain for legacy irqs\n");
- return -EINVAL;
- }
-
- return dw_pcie_host_init(pp);
-}
diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 24afc691443b..65ff7a5566b4 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -25,13 +25,62 @@
#include <linux/signal.h>

#include "pcie-designware.h"
-#include "pci-keystone.h"

#define DRIVER_NAME "keystone-pcie"

/* DEV_STAT_CTRL */
#define PCIE_CAP_BASE 0x70

+/* Application register defines */
+#define LTSSM_EN_VAL BIT(0)
+#define LTSSM_STATE_MASK 0x1f
+#define LTSSM_STATE_L0 0x11
+#define DBI_CS2_EN_VAL 0x20
+#define OB_XLAT_EN_VAL 2
+
+/* Application registers */
+#define CMD_STATUS 0x004
+#define CFG_SETUP 0x008
+#define OB_SIZE 0x030
+#define CFG_PCIM_WIN_SZ_IDX 3
+#define CFG_PCIM_WIN_CNT 32
+#define SPACE0_REMOTE_CFG_OFFSET 0x1000
+#define OB_OFFSET_INDEX(n) (0x200 + (8 * n))
+#define OB_OFFSET_HI(n) (0x204 + (8 * n))
+
+/* IRQ register defines */
+#define IRQ_EOI 0x050
+#define IRQ_STATUS 0x184
+#define IRQ_ENABLE_SET 0x188
+#define IRQ_ENABLE_CLR 0x18c
+
+#define MSI_IRQ 0x054
+#define MSI0_IRQ_STATUS 0x104
+#define MSI0_IRQ_ENABLE_SET 0x108
+#define MSI0_IRQ_ENABLE_CLR 0x10c
+#define IRQ_STATUS 0x184
+#define MSI_IRQ_OFFSET 4
+
+/* Error IRQ bits */
+#define ERR_AER BIT(5) /* ECRC error */
+#define ERR_AXI BIT(4) /* AXI tag lookup fatal error */
+#define ERR_CORR BIT(3) /* Correctable error */
+#define ERR_NONFATAL BIT(2) /* Non-fatal error */
+#define ERR_FATAL BIT(1) /* Fatal error */
+#define ERR_SYS BIT(0) /* System (fatal, non-fatal, or correctable) */
+#define ERR_IRQ_ALL (ERR_AER | ERR_AXI | ERR_CORR | \
+ ERR_NONFATAL | ERR_FATAL | ERR_SYS)
+#define ERR_FATAL_IRQ (ERR_FATAL | ERR_AXI)
+#define ERR_IRQ_STATUS_RAW 0x1c0
+#define ERR_IRQ_STATUS 0x1c4
+#define ERR_IRQ_ENABLE_SET 0x1c8
+#define ERR_IRQ_ENABLE_CLR 0x1cc
+
+/* Config space registers */
+#define DEBUG0 0x728
+
+#define MAX_MSI_HOST_IRQS 8
+
/* PCIE controller device IDs */
#define PCIE_RC_K2HK 0xb008
#define PCIE_RC_K2E 0xb009
@@ -43,6 +92,448 @@
static int ks_pcie_start_link(struct dw_pcie *pci);
static void ks_pcie_stop_link(struct dw_pcie *pci);

+struct keystone_pcie {
+ struct dw_pcie *pci;
+ struct clk *clk;
+ /* PCI Device ID */
+ u32 device_id;
+ int num_legacy_host_irqs;
+ int legacy_host_irqs[PCI_NUM_INTX];
+ struct device_node *legacy_intc_np;
+
+ int num_msi_host_irqs;
+ int msi_host_irqs[MAX_MSI_HOST_IRQS];
+ struct device_node *msi_intc_np;
+ struct irq_domain *legacy_irq_domain;
+ struct device_node *np;
+
+ int error_irq;
+
+ /* Application register space */
+ void __iomem *va_app_base; /* DT 1st resource */
+ struct resource app;
+};
+
+static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset,
+ u32 *bit_pos)
+{
+ *reg_offset = offset % 8;
+ *bit_pos = offset >> 3;
+}
+
+static phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp)
+{
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+
+ return ks_pcie->app.start + MSI_IRQ;
+}
+
+static u32 ks_dw_app_readl(struct keystone_pcie *ks_pcie, u32 offset)
+{
+ return readl(ks_pcie->va_app_base + offset);
+}
+
+static void ks_dw_app_writel(struct keystone_pcie *ks_pcie, u32 offset, u32 val)
+{
+ writel(val, ks_pcie->va_app_base + offset);
+}
+
+static void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset)
+{
+ struct dw_pcie *pci = ks_pcie->pci;
+ struct pcie_port *pp = &pci->pp;
+ struct device *dev = pci->dev;
+ u32 pending, vector;
+ int src, virq;
+
+ pending = ks_dw_app_readl(ks_pcie, MSI0_IRQ_STATUS + (offset << 4));
+
+ /*
+ * MSI0 status bit 0-3 shows vectors 0, 8, 16, 24, MSI1 status bit
+ * shows 1, 9, 17, 25 and so forth
+ */
+ for (src = 0; src < 4; src++) {
+ if (BIT(src) & pending) {
+ vector = offset + (src << 3);
+ virq = irq_linear_revmap(pp->irq_domain, vector);
+ dev_dbg(dev, "irq: bit %d, vector %d, virq %d\n",
+ src, vector, virq);
+ generic_handle_irq(virq);
+ }
+ }
+}
+
+static void ks_dw_pcie_msi_irq_ack(int irq, struct pcie_port *pp)
+{
+ u32 reg_offset, bit_pos;
+ struct keystone_pcie *ks_pcie;
+ struct dw_pcie *pci;
+
+ pci = to_dw_pcie_from_pp(pp);
+ ks_pcie = to_keystone_pcie(pci);
+ update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
+
+ ks_dw_app_writel(ks_pcie, MSI0_IRQ_STATUS + (reg_offset << 4),
+ BIT(bit_pos));
+ ks_dw_app_writel(ks_pcie, IRQ_EOI, reg_offset + MSI_IRQ_OFFSET);
+}
+
+static void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
+{
+ u32 reg_offset, bit_pos;
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+
+ update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
+ ks_dw_app_writel(ks_pcie, MSI0_IRQ_ENABLE_SET + (reg_offset << 4),
+ BIT(bit_pos));
+}
+
+static void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
+{
+ u32 reg_offset, bit_pos;
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+
+ update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
+ ks_dw_app_writel(ks_pcie, MSI0_IRQ_ENABLE_CLR + (reg_offset << 4),
+ BIT(bit_pos));
+}
+
+static int ks_dw_pcie_msi_host_init(struct pcie_port *pp)
+{
+ return dw_pcie_allocate_domains(pp);
+}
+
+static void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie)
+{
+ int i;
+
+ for (i = 0; i < PCI_NUM_INTX; i++)
+ ks_dw_app_writel(ks_pcie, IRQ_ENABLE_SET + (i << 4), 0x1);
+}
+
+static void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie,
+ int offset)
+{
+ struct dw_pcie *pci = ks_pcie->pci;
+ struct device *dev = pci->dev;
+ u32 pending;
+ int virq;
+
+ pending = ks_dw_app_readl(ks_pcie, IRQ_STATUS + (offset << 4));
+
+ if (BIT(0) & pending) {
+ virq = irq_linear_revmap(ks_pcie->legacy_irq_domain, offset);
+ dev_dbg(dev, ": irq: irq_offset %d, virq %d\n", offset, virq);
+ generic_handle_irq(virq);
+ }
+
+ /* EOI the INTx interrupt */
+ ks_dw_app_writel(ks_pcie, IRQ_EOI, offset);
+}
+
+static void ks_dw_pcie_enable_error_irq(struct keystone_pcie *ks_pcie)
+{
+ ks_dw_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL);
+}
+
+static irqreturn_t ks_dw_pcie_handle_error_irq(struct keystone_pcie *ks_pcie)
+{
+ u32 status;
+
+ status = ks_dw_app_readl(ks_pcie, ERR_IRQ_STATUS_RAW) & ERR_IRQ_ALL;
+ if (!status)
+ return IRQ_NONE;
+
+ if (status & ERR_FATAL_IRQ)
+ dev_err(ks_pcie->pci->dev, "fatal error (status %#010x)\n",
+ status);
+
+ /* Ack the IRQ; status bits are RW1C */
+ ks_dw_app_writel(ks_pcie, ERR_IRQ_STATUS, status);
+ return IRQ_HANDLED;
+}
+
+static void ks_dw_pcie_ack_legacy_irq(struct irq_data *d)
+{
+}
+
+static void ks_dw_pcie_mask_legacy_irq(struct irq_data *d)
+{
+}
+
+static void ks_dw_pcie_unmask_legacy_irq(struct irq_data *d)
+{
+}
+
+static struct irq_chip ks_dw_pcie_legacy_irq_chip = {
+ .name = "Keystone-PCI-Legacy-IRQ",
+ .irq_ack = ks_dw_pcie_ack_legacy_irq,
+ .irq_mask = ks_dw_pcie_mask_legacy_irq,
+ .irq_unmask = ks_dw_pcie_unmask_legacy_irq,
+};
+
+static int ks_dw_pcie_init_legacy_irq_map(struct irq_domain *d,
+ unsigned int irq, irq_hw_number_t hw_irq)
+{
+ irq_set_chip_and_handler(irq, &ks_dw_pcie_legacy_irq_chip,
+ handle_level_irq);
+ irq_set_chip_data(irq, d->host_data);
+
+ return 0;
+}
+
+static const struct irq_domain_ops ks_dw_pcie_legacy_irq_domain_ops = {
+ .map = ks_dw_pcie_init_legacy_irq_map,
+ .xlate = irq_domain_xlate_onetwocell,
+};
+
+/**
+ * ks_dw_pcie_set_dbi_mode() - Set DBI mode to access overlaid BAR mask
+ * registers
+ *
+ * Since modification of dbi_cs2 involves different clock domain, read the
+ * status back to ensure the transition is complete.
+ */
+static void ks_dw_pcie_set_dbi_mode(struct keystone_pcie *ks_pcie)
+{
+ u32 val;
+
+ val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
+ ks_dw_app_writel(ks_pcie, CMD_STATUS, DBI_CS2_EN_VAL | val);
+
+ do {
+ val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
+ } while (!(val & DBI_CS2_EN_VAL));
+}
+
+/**
+ * ks_dw_pcie_clear_dbi_mode() - Disable DBI mode
+ *
+ * Since modification of dbi_cs2 involves different clock domain, read the
+ * status back to ensure the transition is complete.
+ */
+static void ks_dw_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie)
+{
+ u32 val;
+
+ val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
+ ks_dw_app_writel(ks_pcie, CMD_STATUS, ~DBI_CS2_EN_VAL & val);
+
+ do {
+ val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
+ } while (val & DBI_CS2_EN_VAL);
+}
+
+static void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
+{
+ struct dw_pcie *pci = ks_pcie->pci;
+ struct pcie_port *pp = &pci->pp;
+ u32 start = pp->mem->start, end = pp->mem->end;
+ int i, tr_size;
+ u32 val;
+
+ /* Disable BARs for inbound access */
+ ks_dw_pcie_set_dbi_mode(ks_pcie);
+ dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0);
+ dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0);
+ ks_dw_pcie_clear_dbi_mode(ks_pcie);
+
+ /* Set outbound translation size per window division */
+ ks_dw_app_writel(ks_pcie, OB_SIZE, CFG_PCIM_WIN_SZ_IDX & 0x7);
+
+ tr_size = (1 << (CFG_PCIM_WIN_SZ_IDX & 0x7)) * SZ_1M;
+
+ /* Using Direct 1:1 mapping of RC <-> PCI memory space */
+ for (i = 0; (i < CFG_PCIM_WIN_CNT) && (start < end); i++) {
+ ks_dw_app_writel(ks_pcie, OB_OFFSET_INDEX(i), start | 1);
+ ks_dw_app_writel(ks_pcie, OB_OFFSET_HI(i), 0);
+ start += tr_size;
+ }
+
+ /* Enable OB translation */
+ val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
+ ks_dw_app_writel(ks_pcie, CMD_STATUS, OB_XLAT_EN_VAL | val);
+}
+
+/**
+ * ks_pcie_cfg_setup() - Set up configuration space address for a device
+ *
+ * @ks_pcie: ptr to keystone_pcie structure
+ * @bus: Bus number the device is residing on
+ * @devfn: device, function number info
+ *
+ * Forms and returns the address of configuration space mapped in PCIESS
+ * address space 0. Also configures CFG_SETUP for remote configuration space
+ * access.
+ *
+ * The address space has two regions to access configuration - local and remote.
+ * We access local region for bus 0 (as RC is attached on bus 0) and remote
+ * region for others with TYPE 1 access when bus > 1. As for device on bus = 1,
+ * we will do TYPE 0 access as it will be on our secondary bus (logical).
+ * CFG_SETUP is needed only for remote configuration access.
+ */
+static void __iomem *ks_pcie_cfg_setup(struct keystone_pcie *ks_pcie, u8 bus,
+ unsigned int devfn)
+{
+ u8 device = PCI_SLOT(devfn), function = PCI_FUNC(devfn);
+ struct dw_pcie *pci = ks_pcie->pci;
+ struct pcie_port *pp = &pci->pp;
+ u32 regval;
+
+ if (bus == 0)
+ return pci->dbi_base;
+
+ regval = (bus << 16) | (device << 8) | function;
+
+ /*
+ * Since Bus#1 will be a virtual bus, we need to have TYPE0
+ * access only.
+ * TYPE 1
+ */
+ if (bus != 1)
+ regval |= BIT(24);
+
+ ks_dw_app_writel(ks_pcie, CFG_SETUP, regval);
+ return pp->va_cfg0_base;
+}
+
+static int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
+ unsigned int devfn, int where, int size,
+ u32 *val)
+{
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+ u8 bus_num = bus->number;
+ void __iomem *addr;
+
+ addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
+
+ return dw_pcie_read(addr + where, size, val);
+}
+
+static int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
+ unsigned int devfn, int where, int size,
+ u32 val)
+{
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+ u8 bus_num = bus->number;
+ void __iomem *addr;
+
+ addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
+
+ return dw_pcie_write(addr + where, size, val);
+}
+
+/**
+ * ks_dw_pcie_v3_65_scan_bus() - keystone scan_bus post initialization
+ *
+ * This sets BAR0 to enable inbound access for MSI_IRQ register
+ */
+static void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp)
+{
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+
+ /* Configure and set up BAR0 */
+ ks_dw_pcie_set_dbi_mode(ks_pcie);
+
+ /* Enable BAR0 */
+ dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 1);
+ dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, SZ_4K - 1);
+
+ ks_dw_pcie_clear_dbi_mode(ks_pcie);
+
+ /*
+ * For BAR0, just setting bus address for inbound writes (MSI) should
+ * be sufficient. Use physical address to avoid any conflicts.
+ */
+ dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, ks_pcie->app.start);
+}
+
+/**
+ * ks_dw_pcie_link_up() - Check if link up
+ */
+static int ks_dw_pcie_link_up(struct dw_pcie *pci)
+{
+ u32 val;
+
+ val = dw_pcie_readl_dbi(pci, DEBUG0);
+ return (val & LTSSM_STATE_MASK) == LTSSM_STATE_L0;
+}
+
+static void ks_dw_pcie_stop_link(struct keystone_pcie *ks_pcie)
+{
+ u32 val;
+
+ /* Disable Link training */
+ val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
+ val &= ~LTSSM_EN_VAL;
+ ks_dw_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
+}
+
+static void ks_dw_pcie_start_link(struct keystone_pcie *ks_pcie)
+{
+ u32 val;
+
+ /* Initiate Link Training */
+ val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
+ ks_dw_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
+}
+
+/**
+ * ks_dw_pcie_host_init() - initialize host for v3_65 dw hardware
+ *
+ * Ioremap the register resources, initialize legacy irq domain
+ * and call dw_pcie_v3_65_host_init() API to initialize the Keystone
+ * PCI host controller.
+ */
+static int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie)
+{
+ struct dw_pcie *pci = ks_pcie->pci;
+ struct pcie_port *pp = &pci->pp;
+ struct device *dev = pci->dev;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *res;
+
+ /* Index 0 is the config reg. space address */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pci->dbi_base = devm_pci_remap_cfg_resource(dev, res);
+ if (IS_ERR(pci->dbi_base))
+ return PTR_ERR(pci->dbi_base);
+
+ /*
+ * We set these same and is used in pcie rd/wr_other_conf
+ * functions
+ */
+ pp->va_cfg0_base = pci->dbi_base + SPACE0_REMOTE_CFG_OFFSET;
+ pp->va_cfg1_base = pp->va_cfg0_base;
+
+ /* Index 1 is the application reg. space address */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ ks_pcie->va_app_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(ks_pcie->va_app_base))
+ return PTR_ERR(ks_pcie->va_app_base);
+
+ ks_pcie->app = *res;
+
+ /* Create legacy IRQ domain */
+ ks_pcie->legacy_irq_domain =
+ irq_domain_add_linear(ks_pcie->legacy_intc_np,
+ PCI_NUM_INTX,
+ &ks_dw_pcie_legacy_irq_domain_ops,
+ NULL);
+ if (!ks_pcie->legacy_irq_domain) {
+ dev_err(dev, "Failed to add irq domain for legacy irqs\n");
+ return -EINVAL;
+ }
+
+ return dw_pcie_host_init(pp);
+}
+
static void quirk_limit_mrrs(struct pci_dev *dev)
{
struct pci_bus *bus = dev->bus;
diff --git a/drivers/pci/controller/dwc/pci-keystone.h b/drivers/pci/controller/dwc/pci-keystone.h
deleted file mode 100644
index a66deab626aa..000000000000
--- a/drivers/pci/controller/dwc/pci-keystone.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Keystone PCI Controller's common includes
- *
- * Copyright (C) 2013-2014 Texas Instruments., Ltd.
- * http://www.ti.com
- *
- * Author: Murali Karicheri <[email protected]>
- */
-
-#define MAX_MSI_HOST_IRQS 8
-
-struct keystone_pcie {
- struct dw_pcie *pci;
- struct clk *clk;
- /* PCI Device ID */
- u32 device_id;
- int num_legacy_host_irqs;
- int legacy_host_irqs[PCI_NUM_INTX];
- struct device_node *legacy_intc_np;
-
- int num_msi_host_irqs;
- int msi_host_irqs[MAX_MSI_HOST_IRQS];
- struct device_node *msi_intc_np;
- struct irq_domain *legacy_irq_domain;
- struct device_node *np;
-
- int error_irq;
-
- /* Application register space */
- void __iomem *va_app_base; /* DT 1st resource */
- struct resource app;
-};
-
-/* Keystone DW specific MSI controller APIs/definitions */
-void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset);
-phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp);
-
-/* Keystone specific PCI controller APIs */
-void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie);
-void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset);
-void ks_dw_pcie_enable_error_irq(struct keystone_pcie *ks_pcie);
-irqreturn_t ks_dw_pcie_handle_error_irq(struct keystone_pcie *ks_pcie);
-int ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie);
-int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
- unsigned int devfn, int where, int size, u32 val);
-int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
- unsigned int devfn, int where, int size, u32 *val);
-void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie);
-void ks_dw_pcie_start_link(struct keystone_pcie *ks_pcie);
-void ks_dw_pcie_stop_link(struct keystone_pcie *ks_pcie);
-void ks_dw_pcie_msi_irq_ack(int i, struct pcie_port *pp);
-void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq);
-void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq);
-void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp);
-int ks_dw_pcie_msi_host_init(struct pcie_port *pp);
-int ks_dw_pcie_link_up(struct dw_pcie *pci);
--
2.17.1


2018-09-21 10:25:48

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 27/40] dt-bindings: PCI: Document "atu" reg-names

Document "atu" reg-names required to get the register space for ATU in
Synopsys designware core version >= 4.80.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
Documentation/devicetree/bindings/pci/designware-pcie.txt | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/designware-pcie.txt b/Documentation/devicetree/bindings/pci/designware-pcie.txt
index c124f9bc11f3..5561a1c060d0 100644
--- a/Documentation/devicetree/bindings/pci/designware-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/designware-pcie.txt
@@ -4,8 +4,11 @@ Required properties:
- compatible:
"snps,dw-pcie" for RC mode;
"snps,dw-pcie-ep" for EP mode;
-- reg: Should contain the configuration address space.
-- reg-names: Must be "config" for the PCIe configuration space.
+- reg: For designware cores version < 4.80 contains the configuration
+ address space. For designware core version >= 4.80, contains
+ the configuration and ATU address space
+- reg-names: Must be "config" for the PCIe configuration space and "atu" for
+ the ATU address space.
(The old way of getting the configuration address space from "ranges"
is deprecated and should be avoided.)
- num-lanes: number of lanes to use
--
2.17.1


2018-09-21 10:25:55

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 31/40] PCI: keystone: Add support for PCIe in AM654x Platforms

Add PCIe RC support for AM654x Platforms in pci-keystone.c

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/Kconfig | 2 +-
drivers/pci/controller/dwc/pci-keystone.c | 118 +++++++++++++++++++---
2 files changed, 107 insertions(+), 13 deletions(-)

diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index 91b0194240a5..42f5bfa0f2fe 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -104,7 +104,7 @@ config PCIE_SPEAR13XX

config PCI_KEYSTONE
bool "TI Keystone PCIe controller"
- depends on ARCH_KEYSTONE || (ARM && COMPILE_TEST)
+ depends on ARCH_KEYSTONE || ARCH_K3 || (ARM && COMPILE_TEST)
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW_HOST
help
diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 91337e9c87a5..fe7daab6a518 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -18,6 +18,7 @@
#include <linux/mfd/syscon.h>
#include <linux/msi.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/of_pci.h>
#include <linux/phy/phy.h>
@@ -89,11 +90,19 @@

#define KS_PCIE_SYSCLOCKOUTEN BIT(0)

+#define AM654_PCIE_DEV_TYPE_MASK 0x3
+#define AM654_WIN_SIZE SZ_64K
+
#define to_keystone_pcie(x) dev_get_drvdata((x)->dev)

static int ks_pcie_start_link(struct dw_pcie *pci);
static void ks_pcie_stop_link(struct dw_pcie *pci);

+struct ks_pcie_of_data {
+ const struct dw_pcie_host_ops *host_ops;
+ unsigned int version;
+};
+
struct keystone_pcie {
struct dw_pcie *pci;
int num_lanes;
@@ -173,6 +182,16 @@ static int ks_pcie_msi_host_init(struct pcie_port *pp)
return dw_pcie_allocate_domains(pp);
}

+static int ks_pcie_am654_msi_host_init(struct pcie_port *pp)
+{
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct device *dev = pci->dev;
+
+ dev_vdbg(dev, "dummy function so that DW core doesn't configure MSI\n");
+
+ return 0;
+}
+
static void ks_pcie_enable_error_irq(struct keystone_pcie *ks_pcie)
{
ks_pcie_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL);
@@ -409,6 +428,8 @@ static int ks_pcie_config_msi_irq(struct keystone_pcie *ks_pcie)

intc_np = of_get_child_by_name(np, "msi-interrupt-controller");
if (!intc_np) {
+ if (of_device_is_compatible(np, "ti,am654-pcie-rc"))
+ return 0;
dev_WARN(dev, "msi-interrupt-controller node is absent\n");
return -EINVAL;
}
@@ -520,11 +541,16 @@ static void ks_pcie_setup_mem_space(struct keystone_pcie *ks_pcie)
u32 val;
u32 num_viewport = ks_pcie->num_viewport;
struct dw_pcie *pci = ks_pcie->pci;
+ struct device *dev = pci->dev;
+ struct device_node *np = dev->of_node;
struct pcie_port *pp = &pci->pp;
u64 start = pp->mem->start;
u64 end = pp->mem->end;
int i;

+ if (of_device_is_compatible(np, "ti,am654-pcie-rc"))
+ return;
+
val = ilog2(OB_WIN_SIZE);
ks_pcie_app_writel(ks_pcie, OB_SIZE, val);

@@ -559,8 +585,10 @@ static int __init ks_pcie_init_id(struct keystone_pcie *ks_pcie)
if (ret)
return ret;

+ dw_pcie_dbi_ro_wr_en(pci);
dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, id & PCIE_VENDORID_MASK);
dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, id >> PCIE_DEVICEID_SHIFT);
+ dw_pcie_dbi_ro_wr_dis(pci);

return 0;
}
@@ -619,6 +647,11 @@ static const struct dw_pcie_host_ops ks_pcie_host_ops = {
.scan_bus = ks_pcie_v3_65_scan_bus,
};

+static const struct dw_pcie_host_ops ks_pcie_am654_host_ops = {
+ .host_init = ks_pcie_host_init,
+ .msi_host_init = ks_pcie_am654_msi_host_init,
+};
+
static irqreturn_t ks_pcie_err_irq_handler(int irq, void *priv)
{
u32 reg;
@@ -666,7 +699,6 @@ static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie,

pp->va_cfg1_base = pp->va_cfg0_base;

- pp->ops = &ks_pcie_host_ops;
ret = dw_pcie_host_init(pp);
if (ret) {
dev_err(dev, "failed to initialize host\n");
@@ -676,14 +708,6 @@ static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie,
return 0;
}

-static const struct of_device_id ks_pcie_of_match[] = {
- {
- .type = "pci",
- .compatible = "ti,keystone-pcie",
- },
- { },
-};
-
static void ks_pcie_stop_link(struct dw_pcie *pci)
{
u32 val;
@@ -786,13 +810,59 @@ static int ks_pcie_set_mode(struct device *dev)
return 0;
}

+static int ks_pcie_am654_set_mode(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct regmap *syscon;
+ u32 val;
+ u32 mask;
+ int ret = 0;
+
+ syscon = syscon_regmap_lookup_by_phandle(np, "ti,syscon-pcie-mode");
+ if (IS_ERR(syscon))
+ return 0;
+
+ mask = AM654_PCIE_DEV_TYPE_MASK;
+ val = RC;
+
+ ret = regmap_update_bits(syscon, 0, mask, val);
+ if (ret) {
+ dev_err(dev, "failed to set pcie mode\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct ks_pcie_of_data ks_pcie_am654_rc_of_data = {
+ .host_ops = &ks_pcie_am654_host_ops,
+ .version = 0x490A,
+};
+
+static const struct of_device_id ks_pcie_of_match[] = {
+ {
+ .type = "pci",
+ .compatible = "ti,keystone-pcie",
+ },
+ {
+ .data = &ks_pcie_am654_rc_of_data,
+ .compatible = "ti,am654-pcie-rc",
+ },
+ { },
+};
+
static int __init ks_pcie_probe(struct platform_device *pdev)
{
+ const struct dw_pcie_host_ops *host_ops = &ks_pcie_host_ops;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
+ const struct ks_pcie_of_data *data;
+ const struct of_device_id *match;
struct dw_pcie *pci;
struct keystone_pcie *ks_pcie;
+ unsigned int version = 0x365A;
struct device_link **link;
+ void __iomem *atu_base;
struct resource *res;
void __iomem *base;
u32 num_viewport;
@@ -803,6 +873,13 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
int irq;
int i;

+ match = of_match_device(of_match_ptr(ks_pcie_of_match), dev);
+ data = (struct ks_pcie_of_data *)match->data;
+ if (data) {
+ version = data->version;
+ host_ops = data->host_ops;
+ }
+
ks_pcie = devm_kzalloc(dev, sizeof(*ks_pcie), GFP_KERNEL);
if (!ks_pcie)
return -ENOMEM;
@@ -826,6 +903,7 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
pci->dbi_base = base;
pci->dev = dev;
pci->ops = &ks_pcie_dw_pcie_ops;
+ pci->version = version;

ret = of_property_read_u32(np, "num-viewport", &num_viewport);
if (ret < 0) {
@@ -902,10 +980,26 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
goto err_get_sync;
}

- ret = ks_pcie_set_mode(dev);
- if (ret < 0)
- goto err_get_sync;
+ if (pci->version >= 0x480A) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "atu");
+ atu_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(atu_base)) {
+ ret = PTR_ERR(atu_base);
+ goto err_get_sync;
+ }
+
+ pci->atu_base = atu_base;
+
+ ret = ks_pcie_am654_set_mode(dev);
+ if (ret < 0)
+ goto err_get_sync;
+ } else {
+ ret = ks_pcie_set_mode(dev);
+ if (ret < 0)
+ goto err_get_sync;
+ }

+ pci->pp.ops = host_ops;
ret = ks_pcie_add_pcie_port(ks_pcie, pdev);
if (ret < 0)
goto err_get_sync;
--
2.17.1


2018-09-21 10:26:07

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 16/40] PCI: keystone: Invoke pm_runtime APIs to enable clock

Invoke pm_runtime APIs to enable clocks and remove explicit
clock enabling using clk_prepare_enable().

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 29 +++++++++++------------
1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index b013776d9256..f230344e1f4e 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -95,7 +95,6 @@ static void ks_pcie_stop_link(struct dw_pcie *pci);

struct keystone_pcie {
struct dw_pcie *pci;
- struct clk *clk;
int num_lanes;
struct phy **phy;
struct device_link **link;
@@ -879,26 +878,25 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
}

platform_set_drvdata(pdev, ks_pcie);
- ks_pcie->clk = devm_clk_get(dev, "pcie");
- if (IS_ERR(ks_pcie->clk)) {
- dev_err(dev, "Failed to get pcie rc clock\n");
- ret = PTR_ERR(ks_pcie->clk);
- goto err_get_irq;
- }

- ret = clk_prepare_enable(ks_pcie->clk);
- if (ret)
- goto err_get_irq;
+ pm_runtime_enable(dev);
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0) {
+ dev_err(dev, "pm_runtime_get_sync failed\n");
+ goto err_get_sync;
+ }

ret = ks_pcie_add_pcie_port(ks_pcie, pdev);
if (ret < 0)
- goto fail_clk;
+ goto err_get_sync;

ks_pcie_enable_error_irq(ks_pcie);

return 0;
-fail_clk:
- clk_disable_unprepare(ks_pcie->clk);
+
+err_get_sync:
+ pm_runtime_put(dev);
+ pm_runtime_disable(dev);

err_get_irq:
ks_pcie_disable_phy(ks_pcie);
@@ -915,10 +913,11 @@ static int __exit ks_pcie_remove(struct platform_device *pdev)
struct keystone_pcie *ks_pcie = platform_get_drvdata(pdev);
struct device_link **link = ks_pcie->link;
int num_lanes = ks_pcie->num_lanes;
+ struct device *dev = &pdev->dev;

- clk_disable_unprepare(ks_pcie->clk);
+ pm_runtime_put(dev);
+ pm_runtime_disable(dev);
ks_pcie_disable_phy(ks_pcie);
-
while (num_lanes--)
device_link_del(link[num_lanes]);

--
2.17.1


2018-09-21 10:26:19

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 32/40] phy: core: Invoke pm_runtime_get_*/pm_runtime_put_* before invoking reset callback

PHY drivers may try to access PHY registers in the ->reset() callback.
Invoke phy_pm_runtime_get_sync() before invoking the ->reset() callback
so that the PHY drivers don't have to enable clocks by themselves before
accessing PHY registers.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/phy/phy-core.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 35fd38c5a4a1..b2f863f0866e 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -384,10 +384,16 @@ int phy_reset(struct phy *phy)
if (!phy || !phy->ops->reset)
return 0;

+ ret = phy_pm_runtime_get_sync(phy);
+ if (ret < 0 && ret != -ENOTSUPP)
+ return ret;
+
mutex_lock(&phy->mutex);
ret = phy->ops->reset(phy);
mutex_unlock(&phy->mutex);

+ phy_pm_runtime_put(phy);
+
return ret;
}
EXPORT_SYMBOL_GPL(phy_reset);
--
2.17.1


2018-09-21 10:26:31

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 34/40] phy: ti: Add a new SERDES driver for TI's AM654x SoC

Add a new SERDES driver for TI's AM654x SoC which configures
the SERDES only for PCIe. Support fo USB3 will be added later.

SERDES in am654x has three input clocks (left input, externel reference
clock and right input) and two output clocks (left output and right
output) in addition to a PLL mux clock which the SERDES uses for Clock
Multiplier Unit (CMU refclock).

The PLL mux clock can select from one of the three input clocks.
The right output can select between left input and external reference
clock while the left output can select between the right input and
external reference clock.

The driver has support to select PLL mux and left/right output mux as
specified in device tree.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/phy/ti/Kconfig | 11 +
drivers/phy/ti/Makefile | 1 +
drivers/phy/ti/phy-am654-serdes.c | 513 ++++++++++++++++++++++++++++++
3 files changed, 525 insertions(+)
create mode 100644 drivers/phy/ti/phy-am654-serdes.c

diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig
index 20503562666c..8a556649de68 100644
--- a/drivers/phy/ti/Kconfig
+++ b/drivers/phy/ti/Kconfig
@@ -20,6 +20,17 @@ config PHY_DM816X_USB
help
Enable this for dm816x USB to work.

+config PHY_AM654_SERDES
+ tristate "TI AM654 SERDES support"
+ depends on OF && ARCH_K3 || COMPILE_TEST
+ select GENERIC_PHY
+ select MULTIPLEXER
+ select REGMAP_MMIO
+ select MUX_MMIO
+ help
+ This option enables support for TI AM654 SerDes PHY used for
+ PCIe.
+
config OMAP_CONTROL_PHY
tristate "OMAP CONTROL PHY Driver"
depends on ARCH_OMAP2PLUS || COMPILE_TEST
diff --git a/drivers/phy/ti/Makefile b/drivers/phy/ti/Makefile
index 9f361756eaf2..0df18acbbb60 100644
--- a/drivers/phy/ti/Makefile
+++ b/drivers/phy/ti/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o
obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o
obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
+obj-$(CONFIG_PHY_AM654_SERDES) += phy-am654-serdes.o
diff --git a/drivers/phy/ti/phy-am654-serdes.c b/drivers/phy/ti/phy-am654-serdes.c
new file mode 100644
index 000000000000..1a6216e7c69e
--- /dev/null
+++ b/drivers/phy/ti/phy-am654-serdes.c
@@ -0,0 +1,513 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * PCIe SERDES driver for AM654x SoC
+ *
+ * Copyright (C) 2018 Texas Instruments
+ * Author: Kishon Vijay Abraham I <[email protected]>
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mux/consumer.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+
+#define CMU_R07C 0x7c
+#define CMU_MASTER_CDN_O BIT(24)
+
+#define COMLANE_R138 0xb38
+#define CONFIG_VERSION_REG_MASK GENMASK(23, 16)
+#define CONFIG_VERSION_REG_SHIFT 16
+#define VERSION 0x70
+
+#define COMLANE_R190 0xb90
+#define L1_MASTER_CDN_O BIT(9)
+
+#define COMLANE_R194 0xb94
+#define CMU_OK_I_0 BIT(19)
+
+#define SERDES_CTRL 0x1fd0
+#define POR_EN BIT(29)
+
+#define WIZ_LANEXCTL_STS 0x1fe0
+#define TX0_ENABLE_OVL BIT(31)
+#define TX0_ENABLE_MASK GENMASK(30, 29)
+#define TX0_ENABLE_SHIFT 29
+#define TX0_DISABLE_STATE 0x0
+#define TX0_SLEEP_STATE 0x1
+#define TX0_SNOOZE_STATE 0x2
+#define TX0_ENABLE_STATE 0x3
+#define RX0_ENABLE_OVL BIT(15)
+#define RX0_ENABLE_MASK GENMASK(14, 13)
+#define RX0_ENABLE_SHIFT 13
+#define RX0_DISABLE_STATE 0x0
+#define RX0_SLEEP_STATE 0x1
+#define RX0_SNOOZE_STATE 0x2
+#define RX0_ENABLE_STATE 0x3
+
+#define WIZ_PLL_CTRL 0x1ff4
+#define PLL_ENABLE_OVL BIT(31)
+#define PLL_ENABLE_MASK GENMASK(30, 29)
+#define PLL_ENABLE_SHIFT 29
+#define PLL_DISABLE_STATE 0x0
+#define PLL_SLEEP_STATE 0x1
+#define PLL_SNOOZE_STATE 0x2
+#define PLL_ENABLE_STATE 0x3
+#define PLL_OK BIT(28)
+
+#define PLL_LOCK_TIME 100000 /* in microseconds */
+#define SLEEP_TIME 100 /* in microseconds */
+
+#define LANE_USB3 0x0
+#define LANE_PCIE0_LANE0 0x1
+
+#define LANE_PCIE1_LANE0 0x0
+#define LANE_PCIE0_LANE1 0x1
+
+#define SERDES_NUM_CLOCKS 3
+
+struct serdes_am654_clk_mux {
+ struct clk_hw hw;
+ struct regmap *regmap;
+ unsigned int reg;
+ int *table;
+ u32 mask;
+ u8 shift;
+};
+
+#define to_serdes_am654_clk_mux(_hw) \
+ container_of(_hw, struct serdes_am654_clk_mux, hw)
+
+static struct regmap_config serdes_am654_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .fast_io = true,
+};
+
+struct serdes_am654 {
+ struct regmap *regmap;
+ struct device *dev;
+ struct mux_control *control;
+ bool busy;
+ u32 type;
+ struct device_node *of_node;
+ struct clk_onecell_data clk_data;
+ struct clk *clks[SERDES_NUM_CLOCKS];
+};
+
+static int serdes_am654_enable_pll(struct serdes_am654 *phy)
+{
+ u32 mask = PLL_ENABLE_OVL | PLL_ENABLE_MASK;
+ u32 val = PLL_ENABLE_OVL | (PLL_ENABLE_STATE << PLL_ENABLE_SHIFT);
+
+ regmap_update_bits(phy->regmap, WIZ_PLL_CTRL, mask, val);
+
+ return regmap_read_poll_timeout(phy->regmap, WIZ_PLL_CTRL, val,
+ val & PLL_OK, 1000, PLL_LOCK_TIME);
+}
+
+static void serdes_am654_disable_pll(struct serdes_am654 *phy)
+{
+ u32 mask = PLL_ENABLE_OVL | PLL_ENABLE_MASK;
+
+ regmap_update_bits(phy->regmap, WIZ_PLL_CTRL, mask, 0);
+}
+
+static int serdes_am654_enable_txrx(struct serdes_am654 *phy)
+{
+ u32 mask;
+ u32 val;
+
+ /* Enable TX */
+ mask = TX0_ENABLE_OVL | TX0_ENABLE_MASK;
+ val = TX0_ENABLE_OVL | (TX0_ENABLE_STATE << TX0_ENABLE_SHIFT);
+ regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, val);
+
+ /* Enable RX */
+ mask = RX0_ENABLE_OVL | RX0_ENABLE_MASK;
+ val = RX0_ENABLE_OVL | (RX0_ENABLE_STATE << RX0_ENABLE_SHIFT);
+ regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, val);
+
+ return 0;
+}
+
+static int serdes_am654_disable_txrx(struct serdes_am654 *phy)
+{
+ u32 mask;
+
+ /* Disable TX */
+ mask = TX0_ENABLE_OVL | TX0_ENABLE_MASK;
+ regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, 0);
+
+ /* Disable RX */
+ mask = RX0_ENABLE_OVL | RX0_ENABLE_MASK;
+ regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, 0);
+
+ return 0;
+}
+
+static int serdes_am654_power_on(struct phy *x)
+{
+ struct serdes_am654 *phy = phy_get_drvdata(x);
+ struct device *dev = phy->dev;
+ int ret;
+ u32 val;
+
+ ret = serdes_am654_enable_pll(phy);
+ if (ret) {
+ dev_err(dev, "Failed to enable PLL\n");
+ return ret;
+ }
+
+ ret = serdes_am654_enable_txrx(phy);
+ if (ret) {
+ dev_err(dev, "Failed to enable TX RX\n");
+ return ret;
+ }
+
+ return regmap_read_poll_timeout(phy->regmap, COMLANE_R194, val,
+ val & CMU_OK_I_0, SLEEP_TIME,
+ PLL_LOCK_TIME);
+}
+
+static int serdes_am654_power_off(struct phy *x)
+{
+ struct serdes_am654 *phy = phy_get_drvdata(x);
+
+ serdes_am654_disable_txrx(phy);
+ serdes_am654_disable_pll(phy);
+
+ return 0;
+}
+
+static int serdes_am654_init(struct phy *x)
+{
+ struct serdes_am654 *phy = phy_get_drvdata(x);
+ u32 mask;
+ u32 val;
+
+ mask = CONFIG_VERSION_REG_MASK;
+ val = VERSION << CONFIG_VERSION_REG_SHIFT;
+ regmap_update_bits(phy->regmap, COMLANE_R138, mask, val);
+
+ val = CMU_MASTER_CDN_O;
+ regmap_update_bits(phy->regmap, CMU_R07C, val, val);
+
+ val = L1_MASTER_CDN_O;
+ regmap_update_bits(phy->regmap, COMLANE_R190, val, val);
+
+ return 0;
+}
+
+static int serdes_am654_reset(struct phy *x)
+{
+ struct serdes_am654 *phy = phy_get_drvdata(x);
+ u32 val;
+
+ val = POR_EN;
+ regmap_update_bits(phy->regmap, SERDES_CTRL, val, val);
+ mdelay(1);
+ regmap_update_bits(phy->regmap, SERDES_CTRL, val, 0);
+
+ return 0;
+}
+
+struct phy *serdes_am654_xlate(struct device *dev, struct of_phandle_args
+ *args)
+{
+ struct serdes_am654 *am654_phy;
+ struct phy *phy;
+ int ret;
+
+ phy = of_phy_simple_xlate(dev, args);
+ if (IS_ERR(phy))
+ return phy;
+
+ am654_phy = phy_get_drvdata(phy);
+ if (am654_phy->type != args->args[0] && am654_phy->busy)
+ return ERR_PTR(-EBUSY);
+
+ ret = mux_control_select(am654_phy->control, args->args[1]);
+ if (ret) {
+ dev_err(dev, "Failed to select SERDES Lane Function\n");
+ return ERR_PTR(ret);
+ }
+
+ am654_phy->busy = true;
+ am654_phy->type = args->args[0];
+
+ return phy;
+}
+
+static const struct phy_ops ops = {
+ .reset = serdes_am654_reset,
+ .init = serdes_am654_init,
+ .power_on = serdes_am654_power_on,
+ .power_off = serdes_am654_power_off,
+ .owner = THIS_MODULE,
+};
+
+static u8 serdes_am654_clk_mux_get_parent(struct clk_hw *hw)
+{
+ struct serdes_am654_clk_mux *mux = to_serdes_am654_clk_mux(hw);
+ unsigned int num_parents = clk_hw_get_num_parents(hw);
+ struct regmap *regmap = mux->regmap;
+ unsigned int reg = mux->reg;
+ unsigned int val;
+ int i;
+
+ regmap_read(regmap, reg, &val);
+ val >>= mux->shift;
+ val &= mux->mask;
+
+ for (i = 0; i < num_parents; i++)
+ if (mux->table[i] == val)
+ return i;
+
+ pr_err("Failed to find a parent of %s clock\n", hw->init->name);
+
+ return 0;
+}
+
+static int serdes_am654_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct serdes_am654_clk_mux *mux = to_serdes_am654_clk_mux(hw);
+ struct regmap *regmap = mux->regmap;
+ unsigned int reg = mux->reg;
+ int val;
+ int ret;
+
+ val = mux->table[index];
+
+ if (val == -1)
+ return -EINVAL;
+
+ val <<= mux->shift;
+ ret = regmap_update_bits(regmap, reg, mux->mask << mux->shift, val);
+
+ return ret;
+}
+
+static const struct clk_ops serdes_am654_clk_mux_ops = {
+ .set_parent = serdes_am654_clk_mux_set_parent,
+ .get_parent = serdes_am654_clk_mux_get_parent,
+};
+
+static int mux_table[SERDES_NUM_CLOCKS][3] = {
+ /*
+ * The entries represent values for selecting between
+ * {left input, external reference clock, right input}
+ * Only one of Left Output or Right Output should be used since
+ * both left and right output clock uses the same bits and modifying
+ * one clock will impact the other.
+ */
+ { BIT(2), 0, BIT(0) }, /* Mux of CMU refclk */
+ { -1, BIT(3), BIT(1) }, /* Mux of Left Output */
+ { BIT(1), BIT(3) | BIT(1), -1 }, /* Mux of Right Output */
+};
+
+static int mux_mask[SERDES_NUM_CLOCKS] = { 0x5, 0xa, 0xa };
+
+static int serdes_am654_clk_register(struct serdes_am654 *am654_phy,
+ const char *clock_name, int clock_num)
+{
+ struct device_node *node = am654_phy->of_node;
+ struct device *dev = am654_phy->dev;
+ struct serdes_am654_clk_mux *mux;
+ struct device_node *regmap_node;
+ const char **parent_names;
+ struct clk_init_data init;
+ unsigned int num_parents;
+ struct regmap *regmap;
+ const __be32 *addr;
+ unsigned int reg;
+ struct clk *clk;
+
+ mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+ if (!mux)
+ return -ENOMEM;
+
+ regmap_node = of_parse_phandle(node, "ti,serdes-clk", 0);
+ of_node_put(regmap_node);
+ if (!regmap_node) {
+ dev_err(dev, "Fail to get serdes-clk node\n");
+ return -ENODEV;
+ }
+
+ regmap = syscon_node_to_regmap(regmap_node->parent);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "Fail to get Syscon regmap\n");
+ return PTR_ERR(regmap);
+ }
+
+ num_parents = of_clk_get_parent_count(node);
+ if (num_parents < 2) {
+ dev_err(dev, "SERDES clock must have parents\n");
+ return -EINVAL;
+ }
+
+ parent_names = devm_kzalloc(dev, (sizeof(char *) * num_parents),
+ GFP_KERNEL);
+ if (!parent_names)
+ return -ENOMEM;
+
+ of_clk_parent_fill(node, parent_names, num_parents);
+
+ addr = of_get_address(regmap_node, 0, NULL, NULL);
+ if (!addr)
+ return -EINVAL;
+
+ reg = be32_to_cpu(*addr);
+
+ init.ops = &serdes_am654_clk_mux_ops;
+ init.flags = CLK_SET_RATE_NO_REPARENT;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.name = clock_name;
+
+ mux->table = mux_table[clock_num];
+ mux->regmap = regmap;
+ mux->reg = reg;
+ mux->shift = 4;
+ mux->mask = mux_mask[clock_num];
+ mux->hw.init = &init;
+
+ clk = devm_clk_register(dev, &mux->hw);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ am654_phy->clks[clock_num] = clk;
+
+ return 0;
+}
+
+static const struct of_device_id serdes_am654_id_table[] = {
+ {
+ .compatible = "ti,phy-am654-serdes",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, serdes_am654_id_table);
+
+static int serdes_am654_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ struct clk_onecell_data *clk_data;
+ struct serdes_am654 *am654_phy;
+ struct mux_control *control;
+ const char *clock_name;
+ struct regmap *regmap;
+ struct resource *res;
+ void __iomem *base;
+ struct phy *phy;
+ int ret;
+ int i;
+
+ am654_phy = devm_kzalloc(dev, sizeof(*am654_phy), GFP_KERNEL);
+ if (!am654_phy)
+ return -ENOMEM;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "serdes");
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ regmap = devm_regmap_init_mmio(dev, base, &serdes_am654_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "Failed to initialize regmap\n");
+ return PTR_ERR(regmap);
+ }
+
+ control = devm_mux_control_get(dev, NULL);
+ if (IS_ERR(control))
+ return PTR_ERR(control);
+
+ am654_phy->dev = dev;
+ am654_phy->of_node = node;
+ am654_phy->regmap = regmap;
+ am654_phy->control = control;
+
+ platform_set_drvdata(pdev, am654_phy);
+
+ for (i = 0; i < SERDES_NUM_CLOCKS; i++) {
+ ret = of_property_read_string_index(node, "clock-output-names",
+ i, &clock_name);
+ if (ret) {
+ dev_err(dev, "Failed to get clock name\n");
+ return ret;
+ }
+
+ ret = serdes_am654_clk_register(am654_phy, clock_name, i);
+ if (ret) {
+ dev_err(dev, "Failed to initialize clock %s\n",
+ clock_name);
+ return ret;
+ }
+ }
+
+ clk_data = &am654_phy->clk_data;
+ clk_data->clks = am654_phy->clks;
+ clk_data->clk_num = SERDES_NUM_CLOCKS;
+ ret = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (ret)
+ return ret;
+
+ pm_runtime_enable(dev);
+
+ phy = devm_phy_create(dev, NULL, &ops);
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ phy_set_drvdata(phy, am654_phy);
+ phy_provider = devm_of_phy_provider_register(dev, serdes_am654_xlate);
+ if (IS_ERR(phy_provider)) {
+ ret = PTR_ERR(phy_provider);
+ goto clk_err;
+ }
+
+ return 0;
+
+clk_err:
+ of_clk_del_provider(node);
+
+ return ret;
+}
+
+static int serdes_am654_remove(struct platform_device *pdev)
+{
+ struct serdes_am654 *am654_phy = platform_get_drvdata(pdev);
+ struct device_node *node = am654_phy->of_node;
+
+ pm_runtime_disable(&pdev->dev);
+ of_clk_del_provider(node);
+
+ return 0;
+}
+
+static struct platform_driver serdes_am654_driver = {
+ .probe = serdes_am654_probe,
+ .remove = serdes_am654_remove,
+ .driver = {
+ .name = "phy-am654",
+ .of_match_table = serdes_am654_id_table,
+ },
+};
+module_platform_driver(serdes_am654_driver);
+
+MODULE_ALIAS("platform:phy-am654");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("TI AM654x SERDES driver");
+MODULE_LICENSE("GPL v2");
--
2.17.1


2018-09-21 10:26:42

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 37/40] arm64: dts: k3-am6: Add Main System Control Module node

From: Benoit Parrot <[email protected]>

Main System control module support is added to the device tree to allow
driver to access to their control module registers.

Signed-off-by: Benoit Parrot <[email protected]>
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
arch/arm64/boot/dts/ti/k3-am65-main.dtsi | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
index 2df4acb198bd..957c9125a453 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
@@ -6,6 +6,11 @@
*/

&cbass_main {
+ scm_conf: scm_conf@100000 {
+ compatible = "syscon";
+ reg = <0 0x00100000 0 0x1c000>;
+ };
+
gic500: interrupt-controller@1800000 {
compatible = "arm,gic-v3";
#address-cells = <2>;
--
2.17.1


2018-09-21 10:26:46

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 10/40] PCI: keystone: Use uniform function naming convention

No functional change. Some function names begin with ks_dw_pcie_*
and some function names begin with ks_pcie_*. Modify it so that
all function names begin with ks_pcie_*.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 267 ++++++++++------------
1 file changed, 120 insertions(+), 147 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index c54d18ea263a..e19ba065ebd5 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -104,7 +104,7 @@ struct keystone_pcie {
struct resource app;
};

-static phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp)
+static phys_addr_t ks_pcie_get_msi_addr(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
@@ -112,17 +112,18 @@ static phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp)
return ks_pcie->app.start + MSI_IRQ;
}

-static u32 ks_dw_app_readl(struct keystone_pcie *ks_pcie, u32 offset)
+static u32 ks_pcie_app_readl(struct keystone_pcie *ks_pcie, u32 offset)
{
return readl(ks_pcie->va_app_base + offset);
}

-static void ks_dw_app_writel(struct keystone_pcie *ks_pcie, u32 offset, u32 val)
+static void ks_pcie_app_writel(struct keystone_pcie *ks_pcie, u32 offset,
+ u32 val)
{
writel(val, ks_pcie->va_app_base + offset);
}

-static void ks_dw_pcie_msi_irq_ack(int irq, struct pcie_port *pp)
+static void ks_pcie_msi_irq_ack(int irq, struct pcie_port *pp)
{
u32 reg_offset, bit_pos;
struct keystone_pcie *ks_pcie;
@@ -133,11 +134,11 @@ static void ks_dw_pcie_msi_irq_ack(int irq, struct pcie_port *pp)

reg_offset = irq % 8;
bit_pos = irq >> 3;
- ks_dw_app_writel(ks_pcie, MSI_IRQ_STATUS(reg_offset), BIT(bit_pos));
- ks_dw_app_writel(ks_pcie, IRQ_EOI, MSI_IRQ_OFFSET + reg_offset);
+ ks_pcie_app_writel(ks_pcie, MSI_IRQ_STATUS(reg_offset), BIT(bit_pos));
+ ks_pcie_app_writel(ks_pcie, IRQ_EOI, MSI_IRQ_OFFSET + reg_offset);
}

-static void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
+static void ks_pcie_msi_set_irq(struct pcie_port *pp, int irq)
{
u32 reg_offset, bit_pos;
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -145,11 +146,11 @@ static void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)

reg_offset = irq % 8;
bit_pos = irq >> 3;
- ks_dw_app_writel(ks_pcie, MSI_IRQ_ENABLE_SET(reg_offset),
- BIT(bit_pos));
+ ks_pcie_app_writel(ks_pcie, MSI_IRQ_ENABLE_SET(reg_offset),
+ BIT(bit_pos));
}

-static void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
+static void ks_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
{
u32 reg_offset, bit_pos;
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -157,25 +158,25 @@ static void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)

reg_offset = irq % 8;
bit_pos = irq >> 3;
- ks_dw_app_writel(ks_pcie, MSI_IRQ_ENABLE_CLR(reg_offset),
- BIT(bit_pos));
+ ks_pcie_app_writel(ks_pcie, MSI_IRQ_ENABLE_CLR(reg_offset),
+ BIT(bit_pos));
}

-static int ks_dw_pcie_msi_host_init(struct pcie_port *pp)
+static int ks_pcie_msi_host_init(struct pcie_port *pp)
{
return dw_pcie_allocate_domains(pp);
}

-static void ks_dw_pcie_enable_error_irq(struct keystone_pcie *ks_pcie)
+static void ks_pcie_enable_error_irq(struct keystone_pcie *ks_pcie)
{
- ks_dw_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL);
+ ks_pcie_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL);
}

-static irqreturn_t ks_dw_pcie_handle_error_irq(struct keystone_pcie *ks_pcie)
+static irqreturn_t ks_pcie_handle_error_irq(struct keystone_pcie *ks_pcie)
{
u32 status;

- status = ks_dw_app_readl(ks_pcie, ERR_IRQ_STATUS_RAW) & ERR_IRQ_ALL;
+ status = ks_pcie_app_readl(ks_pcie, ERR_IRQ_STATUS_RAW) & ERR_IRQ_ALL;
if (!status)
return IRQ_NONE;

@@ -184,48 +185,48 @@ static irqreturn_t ks_dw_pcie_handle_error_irq(struct keystone_pcie *ks_pcie)
status);

/* Ack the IRQ; status bits are RW1C */
- ks_dw_app_writel(ks_pcie, ERR_IRQ_STATUS, status);
+ ks_pcie_app_writel(ks_pcie, ERR_IRQ_STATUS, status);
return IRQ_HANDLED;
}

/**
- * ks_dw_pcie_set_dbi_mode() - Set DBI mode to access overlaid BAR mask
+ * ks_pcie_set_dbi_mode() - Set DBI mode to access overlaid BAR mask
* registers
*
* Since modification of dbi_cs2 involves different clock domain, read the
* status back to ensure the transition is complete.
*/
-static void ks_dw_pcie_set_dbi_mode(struct keystone_pcie *ks_pcie)
+static void ks_pcie_set_dbi_mode(struct keystone_pcie *ks_pcie)
{
u32 val;

- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- ks_dw_app_writel(ks_pcie, CMD_STATUS, DBI_CS2_EN_VAL | val);
+ val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
+ ks_pcie_app_writel(ks_pcie, CMD_STATUS, DBI_CS2_EN_VAL | val);

do {
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
+ val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
} while (!(val & DBI_CS2_EN_VAL));
}

/**
- * ks_dw_pcie_clear_dbi_mode() - Disable DBI mode
+ * ks_pcie_clear_dbi_mode() - Disable DBI mode
*
* Since modification of dbi_cs2 involves different clock domain, read the
* status back to ensure the transition is complete.
*/
-static void ks_dw_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie)
+static void ks_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie)
{
u32 val;

- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- ks_dw_app_writel(ks_pcie, CMD_STATUS, ~DBI_CS2_EN_VAL & val);
+ val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
+ ks_pcie_app_writel(ks_pcie, CMD_STATUS, ~DBI_CS2_EN_VAL & val);

do {
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
+ val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
} while (val & DBI_CS2_EN_VAL);
}

-static void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
+static void ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
{
struct dw_pcie *pci = ks_pcie->pci;
struct pcie_port *pp = &pci->pp;
@@ -234,26 +235,26 @@ static void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
u32 val;

/* Disable BARs for inbound access */
- ks_dw_pcie_set_dbi_mode(ks_pcie);
+ ks_pcie_set_dbi_mode(ks_pcie);
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0);
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0);
- ks_dw_pcie_clear_dbi_mode(ks_pcie);
+ ks_pcie_clear_dbi_mode(ks_pcie);

/* Set outbound translation size per window division */
- ks_dw_app_writel(ks_pcie, OB_SIZE, CFG_PCIM_WIN_SZ_IDX & 0x7);
+ ks_pcie_app_writel(ks_pcie, OB_SIZE, CFG_PCIM_WIN_SZ_IDX & 0x7);

tr_size = (1 << (CFG_PCIM_WIN_SZ_IDX & 0x7)) * SZ_1M;

/* Using Direct 1:1 mapping of RC <-> PCI memory space */
for (i = 0; (i < CFG_PCIM_WIN_CNT) && (start < end); i++) {
- ks_dw_app_writel(ks_pcie, OB_OFFSET_INDEX(i), start | 1);
- ks_dw_app_writel(ks_pcie, OB_OFFSET_HI(i), 0);
+ ks_pcie_app_writel(ks_pcie, OB_OFFSET_INDEX(i), start | 1);
+ ks_pcie_app_writel(ks_pcie, OB_OFFSET_HI(i), 0);
start += tr_size;
}

/* Enable OB translation */
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- ks_dw_app_writel(ks_pcie, CMD_STATUS, OB_XLAT_EN_VAL | val);
+ val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
+ ks_pcie_app_writel(ks_pcie, CMD_STATUS, OB_XLAT_EN_VAL | val);
}

/**
@@ -294,13 +295,13 @@ static void __iomem *ks_pcie_cfg_setup(struct keystone_pcie *ks_pcie, u8 bus,
if (bus != 1)
regval |= BIT(24);

- ks_dw_app_writel(ks_pcie, CFG_SETUP, regval);
+ ks_pcie_app_writel(ks_pcie, CFG_SETUP, regval);
return pp->va_cfg0_base;
}

-static int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
- unsigned int devfn, int where, int size,
- u32 *val)
+static int ks_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
+ unsigned int devfn, int where, int size,
+ u32 *val)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
@@ -312,9 +313,9 @@ static int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
return dw_pcie_read(addr + where, size, val);
}

-static int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
- unsigned int devfn, int where, int size,
- u32 val)
+static int ks_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
+ unsigned int devfn, int where, int size,
+ u32 val)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
@@ -327,23 +328,23 @@ static int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
}

/**
- * ks_dw_pcie_v3_65_scan_bus() - keystone scan_bus post initialization
+ * ks_pcie_v3_65_scan_bus() - keystone scan_bus post initialization
*
* This sets BAR0 to enable inbound access for MSI_IRQ register
*/
-static void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp)
+static void ks_pcie_v3_65_scan_bus(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);

/* Configure and set up BAR0 */
- ks_dw_pcie_set_dbi_mode(ks_pcie);
+ ks_pcie_set_dbi_mode(ks_pcie);

/* Enable BAR0 */
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 1);
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, SZ_4K - 1);

- ks_dw_pcie_clear_dbi_mode(ks_pcie);
+ ks_pcie_clear_dbi_mode(ks_pcie);

/*
* For BAR0, just setting bus address for inbound writes (MSI) should
@@ -353,9 +354,9 @@ static void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp)
}

/**
- * ks_dw_pcie_link_up() - Check if link up
+ * ks_pcie_link_up() - Check if link up
*/
-static int ks_dw_pcie_link_up(struct dw_pcie *pci)
+static int ks_pcie_link_up(struct dw_pcie *pci)
{
u32 val;

@@ -363,65 +364,7 @@ static int ks_dw_pcie_link_up(struct dw_pcie *pci)
return (val & LTSSM_STATE_MASK) == LTSSM_STATE_L0;
}

-static void ks_dw_pcie_stop_link(struct keystone_pcie *ks_pcie)
-{
- u32 val;
-
- /* Disable Link training */
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- val &= ~LTSSM_EN_VAL;
- ks_dw_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
-}
-
-static void ks_dw_pcie_start_link(struct keystone_pcie *ks_pcie)
-{
- u32 val;
-
- /* Initiate Link Training */
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- ks_dw_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
-}
-
-/**
- * ks_dw_pcie_host_init() - initialize host for v3_65 dw hardware
- *
- * Ioremap the register resources, initialize legacy irq domain
- * and call dw_pcie_v3_65_host_init() API to initialize the Keystone
- * PCI host controller.
- */
-static int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie)
-{
- struct dw_pcie *pci = ks_pcie->pci;
- struct pcie_port *pp = &pci->pp;
- struct device *dev = pci->dev;
- struct platform_device *pdev = to_platform_device(dev);
- struct resource *res;
-
- /* Index 0 is the config reg. space address */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- pci->dbi_base = devm_pci_remap_cfg_resource(dev, res);
- if (IS_ERR(pci->dbi_base))
- return PTR_ERR(pci->dbi_base);
-
- /*
- * We set these same and is used in pcie rd/wr_other_conf
- * functions
- */
- pp->va_cfg0_base = pci->dbi_base + SPACE0_REMOTE_CFG_OFFSET;
- pp->va_cfg1_base = pp->va_cfg0_base;
-
- /* Index 1 is the application reg. space address */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- ks_pcie->va_app_base = devm_ioremap_resource(dev, res);
- if (IS_ERR(ks_pcie->va_app_base))
- return PTR_ERR(ks_pcie->va_app_base);
-
- ks_pcie->app = *res;
-
- return dw_pcie_host_init(pp);
-}
-
-static void quirk_limit_mrrs(struct pci_dev *dev)
+static void ks_pcie_quirk(struct pci_dev *dev)
{
struct pci_bus *bus = dev->bus;
struct pci_dev *bridge;
@@ -462,7 +405,7 @@ static void quirk_limit_mrrs(struct pci_dev *dev)
}
}
}
-DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, quirk_limit_mrrs);
+DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, ks_pcie_quirk);

static void ks_pcie_msi_irq_handler(struct irq_desc *desc)
{
@@ -480,7 +423,7 @@ static void ks_pcie_msi_irq_handler(struct irq_desc *desc)

chained_irq_enter(chip, desc);

- reg = ks_dw_app_readl(ks_pcie, MSI_IRQ_STATUS(offset));
+ reg = ks_pcie_app_readl(ks_pcie, MSI_IRQ_STATUS(offset));
for (pos = 0; pos < 4; pos++) {
if (!(reg & BIT(pos)))
continue;
@@ -514,14 +457,14 @@ static void ks_pcie_legacy_irq_handler(struct irq_desc *desc)
chained_irq_enter(chip, desc);

for (i = 0; i < PCI_NUM_INTX; i++) {
- reg = ks_dw_app_readl(ks_pcie, IRQ_STATUS(i));
+ reg = ks_pcie_app_readl(ks_pcie, IRQ_STATUS(i));
if (!(reg & INTx_EN))
continue;

virq = irq_linear_revmap(ks_pcie->legacy_irq_domain, i);
generic_handle_irq(virq);
- ks_dw_app_writel(ks_pcie, IRQ_STATUS(i), INTx_EN);
- ks_dw_app_writel(ks_pcie, IRQ_EOI, i);
+ ks_pcie_app_writel(ks_pcie, IRQ_STATUS(i), INTx_EN);
+ ks_pcie_app_writel(ks_pcie, IRQ_EOI, i);
}

chained_irq_exit(chip, desc);
@@ -620,7 +563,7 @@ static int ks_pcie_config_legacy_irq(struct keystone_pcie *ks_pcie)
ks_pcie->legacy_irq_domain = legacy_irq_domain;

for (i = 0; i < PCI_NUM_INTX; i++)
- ks_dw_app_writel(ks_pcie, IRQ_ENABLE_SET(i), INTx_EN);
+ ks_pcie_app_writel(ks_pcie, IRQ_ENABLE_SET(i), INTx_EN);

return 0;
}
@@ -630,8 +573,8 @@ static int ks_pcie_config_legacy_irq(struct keystone_pcie *ks_pcie)
* bus error instead of returning 0xffffffff. This handler always returns 0
* for this kind of faults.
*/
-static int keystone_pcie_fault(unsigned long addr, unsigned int fsr,
- struct pt_regs *regs)
+static int ks_pcie_fault(unsigned long addr, unsigned int fsr,
+ struct pt_regs *regs)
{
unsigned long instr = *(unsigned long *) instruction_pointer(regs);

@@ -661,7 +604,7 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)

dw_pcie_setup_rc(pp);

- ks_dw_pcie_setup_rc_app_regs(ks_pcie);
+ ks_pcie_setup_rc_app_regs(ks_pcie);
writew(PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8),
pci->dbi_base + PCI_IO_BASE);

@@ -672,46 +615,69 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)
* PCIe access errors that result into OCP errors are caught by ARM as
* "External aborts"
*/
- hook_fault_code(17, keystone_pcie_fault, SIGBUS, 0,
+ hook_fault_code(17, ks_pcie_fault, SIGBUS, 0,
"Asynchronous external abort");

ks_pcie_start_link(pci);
return dw_pcie_wait_for_link(pci);
}

-static const struct dw_pcie_host_ops keystone_pcie_host_ops = {
- .rd_other_conf = ks_dw_pcie_rd_other_conf,
- .wr_other_conf = ks_dw_pcie_wr_other_conf,
+static const struct dw_pcie_host_ops ks_pcie_host_ops = {
+ .rd_other_conf = ks_pcie_rd_other_conf,
+ .wr_other_conf = ks_pcie_wr_other_conf,
.host_init = ks_pcie_host_init,
- .msi_set_irq = ks_dw_pcie_msi_set_irq,
- .msi_clear_irq = ks_dw_pcie_msi_clear_irq,
- .get_msi_addr = ks_dw_pcie_get_msi_addr,
- .msi_host_init = ks_dw_pcie_msi_host_init,
- .msi_irq_ack = ks_dw_pcie_msi_irq_ack,
- .scan_bus = ks_dw_pcie_v3_65_scan_bus,
+ .msi_set_irq = ks_pcie_msi_set_irq,
+ .msi_clear_irq = ks_pcie_msi_clear_irq,
+ .get_msi_addr = ks_pcie_get_msi_addr,
+ .msi_host_init = ks_pcie_msi_host_init,
+ .msi_irq_ack = ks_pcie_msi_irq_ack,
+ .scan_bus = ks_pcie_v3_65_scan_bus,
};

-static irqreturn_t pcie_err_irq_handler(int irq, void *priv)
+static irqreturn_t ks_pcie_err_irq_handler(int irq, void *priv)
{
struct keystone_pcie *ks_pcie = priv;

- return ks_dw_pcie_handle_error_irq(ks_pcie);
+ return ks_pcie_handle_error_irq(ks_pcie);
}

-static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
- struct platform_device *pdev)
+static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie,
+ struct platform_device *pdev)
{
struct dw_pcie *pci = ks_pcie->pci;
struct pcie_port *pp = &pci->pp;
struct device *dev = &pdev->dev;
+ struct resource *res;
int ret;

- pp->ops = &keystone_pcie_host_ops;
- ret = ks_dw_pcie_host_init(ks_pcie);
+ /* Index 0 is the config reg. space address */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pci->dbi_base = devm_pci_remap_cfg_resource(dev, res);
+ if (IS_ERR(pci->dbi_base))
+ return PTR_ERR(pci->dbi_base);
+
+ /*
+ * We set these same and is used in pcie rd/wr_other_conf
+ * functions
+ */
+ pp->va_cfg0_base = pci->dbi_base + SPACE0_REMOTE_CFG_OFFSET;
+ pp->va_cfg1_base = pp->va_cfg0_base;
+
+ /* Index 1 is the application reg. space address */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ ks_pcie->va_app_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(ks_pcie->va_app_base))
+ return PTR_ERR(ks_pcie->va_app_base);
+
+ ks_pcie->app = *res;
+
+ pp->ops = &ks_pcie_host_ops;
+ ret = dw_pcie_host_init(pp);
if (ret) {
dev_err(dev, "failed to initialize host\n");
return ret;
}
+
return 0;
}

@@ -723,8 +689,20 @@ static const struct of_device_id ks_pcie_of_match[] = {
{ },
};

+static void ks_pcie_stop_link(struct dw_pcie *pci)
+{
+ u32 val;
+ struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+
+ /* Disable Link training */
+ val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
+ val &= ~LTSSM_EN_VAL;
+ ks_pcie_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
+}
+
static int ks_pcie_start_link(struct dw_pcie *pci)
{
+ u32 val;
struct device *dev = pci->dev;
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);

@@ -733,22 +711,17 @@ static int ks_pcie_start_link(struct dw_pcie *pci)
return 0;
}

- ks_dw_pcie_start_link(ks_pcie);
+ /* Initiate Link Training */
+ val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
+ ks_pcie_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);

return 0;
}

-static void ks_pcie_stop_link(struct dw_pcie *pci)
-{
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
-
- ks_dw_pcie_stop_link(ks_pcie);
-}
-
-static const struct dw_pcie_ops dw_pcie_ops = {
+static const struct dw_pcie_ops ks_pcie_dw_pcie_ops = {
.start_link = ks_pcie_start_link,
.stop_link = ks_pcie_stop_link,
- .link_up = ks_dw_pcie_link_up,
+ .link_up = ks_pcie_link_up,
};

static int __exit ks_pcie_remove(struct platform_device *pdev)
@@ -780,7 +753,7 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
return -ENOMEM;

pci->dev = dev;
- pci->ops = &dw_pcie_ops;
+ pci->ops = &ks_pcie_dw_pcie_ops;

ks_pcie->pci = pci;

@@ -812,7 +785,7 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
return irq;
}

- ret = devm_request_irq(dev, irq, pcie_err_irq_handler, IRQF_SHARED,
+ ret = devm_request_irq(dev, irq, ks_pcie_err_irq_handler, IRQF_SHARED,
"ks-pcie-error-irq", ks_pcie);
if (ret < 0) {
dev_err(dev, "failed to request error IRQ %d\n", irq);
@@ -829,11 +802,11 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
if (ret)
return ret;

- ret = ks_add_pcie_port(ks_pcie, pdev);
+ ret = ks_pcie_add_pcie_port(ks_pcie, pdev);
if (ret < 0)
goto fail_clk;

- ks_dw_pcie_enable_error_irq(ks_pcie);
+ ks_pcie_enable_error_irq(ks_pcie);

return 0;
fail_clk:
--
2.17.1


2018-09-21 10:27:16

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 09/40] PCI: keystone: Remove redundant platform_set_drvdata

No functional change. Remove redundant platform_set_drvdata invocation
in ks_pcie_probe().

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 4554fdc6cce1..c54d18ea263a 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -829,8 +829,6 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
if (ret)
return ret;

- platform_set_drvdata(pdev, ks_pcie);
-
ret = ks_add_pcie_port(ks_pcie, pdev);
if (ret < 0)
goto fail_clk;
--
2.17.1


2018-09-21 10:27:28

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 29/40] PCI: keystone: Prevent ARM32 specific code to be compiled for ARM64

hook_fault_code is an ARM32 specific API for hooking into data abort.
Since pci-keystone.c will be used for AM65X platforms which is an
ARM64 platform, allow hook_fault_code to be compiled only for ARM32.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index e8328039a017..91337e9c87a5 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -493,6 +493,7 @@ static int ks_pcie_config_legacy_irq(struct keystone_pcie *ks_pcie)
return 0;
}

+#ifdef CONFIG_ARM
/*
* When a PCI device does not exist during config cycles, keystone host gets a
* bus error instead of returning 0xffffffff. This handler always returns 0
@@ -512,6 +513,7 @@ static int ks_pcie_fault(unsigned long addr, unsigned int fsr,

return 0;
}
+#endif

static void ks_pcie_setup_mem_space(struct keystone_pcie *ks_pcie)
{
@@ -592,12 +594,14 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)
if (ret < 0)
return ret;

+#ifdef CONFIG_ARM
/*
* PCIe access errors that result into OCP errors are caught by ARM as
* "External aborts"
*/
hook_fault_code(17, ks_pcie_fault, SIGBUS, 0,
"Asynchronous external abort");
+#endif

ks_pcie_start_link(pci);
return dw_pcie_wait_for_link(pci);
--
2.17.1


2018-09-21 10:27:28

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 19/40] PCI: keystone: Cleanup set_dbi_mode and get_dbi_mode

No functional change. Use BIT() macro for DBI_CS2 and cleanup
set_dbimode and get_dbi_mode

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index d5304c4a1eb5..728b1e0db314 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -40,7 +40,7 @@
#define LTSSM_EN_VAL BIT(0)
#define LTSSM_STATE_MASK 0x1f
#define LTSSM_STATE_L0 0x11
-#define DBI_CS2_EN_VAL 0x20
+#define DBI_CS2 BIT(5)
#define OB_XLAT_EN_VAL BIT(1)

/* Application registers */
@@ -214,11 +214,12 @@ static void ks_pcie_set_dbi_mode(struct keystone_pcie *ks_pcie)
u32 val;

val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
- ks_pcie_app_writel(ks_pcie, CMD_STATUS, DBI_CS2_EN_VAL | val);
+ val |= DBI_CS2;
+ ks_pcie_app_writel(ks_pcie, CMD_STATUS, val);

do {
val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
- } while (!(val & DBI_CS2_EN_VAL));
+ } while (!(val & DBI_CS2));
}

/**
@@ -232,11 +233,12 @@ static void ks_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie)
u32 val;

val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
- ks_pcie_app_writel(ks_pcie, CMD_STATUS, ~DBI_CS2_EN_VAL & val);
+ val &= ~DBI_CS2;
+ ks_pcie_app_writel(ks_pcie, CMD_STATUS, val);

do {
val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
- } while (val & DBI_CS2_EN_VAL);
+ } while (val & DBI_CS2);
}

static int ks_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
--
2.17.1


2018-09-21 10:27:35

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 33/40] dt-bindings: phy: ti: Add dt binding documentation for SERDES in AM654x SoC

AM654x has two SERDES instances. Each instance has three input clocks
(left input, externel reference clock and right input) and two output
clocks (left output and right output) in addition to a PLL mux clock
which the SERDES uses for Clock Multiplier Unit (CMU refclock).
The PLL mux clock can select from one of the three input clocks.
The right output can select between left input and external reference
clock while the left output can select between the right input and
external reference clock.

The left and right input reference clock of SERDES0 and SERDES1
respectively are connected to the SoC clock. In the case of two lane
SERDES personality card, the left input of SERDES1 is connected to
the right output of SERDES0 in a chained fashion.

See section "Reference Clock Distribution" of AM65x Sitara Processors
TRM (SPRUID7 – April 2018) for more details.

Add dt-binding documentation in order to represent all these different
configurations in device tree.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
.../devicetree/bindings/phy/ti-phy.txt | 77 +++++++++++++++++++
include/dt-bindings/phy/phy-am654-serdes.h | 13 ++++
2 files changed, 90 insertions(+)
create mode 100644 include/dt-bindings/phy/phy-am654-serdes.h

diff --git a/Documentation/devicetree/bindings/phy/ti-phy.txt b/Documentation/devicetree/bindings/phy/ti-phy.txt
index 57dfda8a7a1d..fc2fff6b2c37 100644
--- a/Documentation/devicetree/bindings/phy/ti-phy.txt
+++ b/Documentation/devicetree/bindings/phy/ti-phy.txt
@@ -132,3 +132,80 @@ sata_phy: phy@4a096000 {
syscon-pllreset = <&scm_conf 0x3fc>;
#phy-cells = <0>;
};
+
+
+TI AM654 SERDES
+
+Required properties:
+ - compatible: Should be "ti,phy-am654-serdes"
+ - reg : Address and length of the register set for the device.
+ - reg-names: Should be "serdes" which corresponds to the register space
+ populated in "reg".
+ - #phy-cells: determine the number of cells that should be given in the
+ phandle while referencing this phy. Should be "2". The 1st cell
+ corresponds to the phy type (should be one of the types specified in
+ include/dt-bindings/phy/phy.h) and the 2nd cell should be the serdes
+ lane function.
+ If SERDES0 is referenced 2nd cell should be:
+ 0 - USB3
+ 1 - PCIe0 Lane0
+ 2 - ICSS2 SGMII Lane0
+ If SERDES1 is referenced 2nd cell should be:
+ 0 - PCIe1 Lane0
+ 1 - PCIe0 Lane1
+ 2 - ICSS2 SGMII Lane1
+ - clocks: List of clock-specifiers representing the input to the SERDES.
+ Should have 3 items representing the left input clock, external
+ reference clock and right input clock in that order.
+ - clock-output-names: List of clock names for each of the clock outputs of
+ SERDES. Should have 3 items for CMU reference clock,
+ left output clock and right output clock in that order.
+ - assigned-clocks: As defined in
+ Documentation/devicetree/bindings/clock/clock-bindings.txt
+ - assigned-clock-parents: As defined in
+ Documentation/devicetree/bindings/clock/clock-bindings.txt
+ - #clock-cells: Should be <1> to choose between the 3 output clocks.
+ Defined in Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+ The following macros are defined in dt-bindings/phy/phy-am654-serdes.h
+ for selecting the correct reference clock. This can be used while
+ specifying the clocks created by SERDES.
+ => AM654_SERDES_CMU_REFCLK
+ => AM654_SERDES_LO_REFCLK
+ => AM654_SERDES_RO_REFCLK
+
+ - mux-controls: phandle to the multiplexer
+
+Example:
+
+Example for SERDES0 is given below. It has 3 clock inputs;
+left input reference clock as indicated by <&k3_clks 153 4>, external
+reference clock as indicated by <&k3_clks 153 1> and right input
+reference clock as indicated by <&serdes1 AM654_SERDES_LO_REFCLK>. (The
+right input of SERDES0 is connected to the left output of SERDES1).
+
+SERDES0 registers 3 clock outputs as indicated in clock-output-names. The
+first refers to the CMU reference clock, second refers to the left output
+reference clock and the third refers to the right output reference clock.
+
+The assigned-clocks and assigned-clock-parents is used here to set the
+parent of left input reference clock to MAINHSDIV_CLKOUT4 and parent of
+CMU reference clock to left input reference clock.
+
+serdes0: serdes@900000 {
+ compatible = "ti,phy-am654-serdes";
+ reg = <0x0 0x900000 0x0 0x2000>;
+ reg-names = "serdes";
+ #phy-cells = <2>;
+ power-domains = <&k3_pds 153>;
+ clocks = <&k3_clks 153 4>, <&k3_clks 153 1>,
+ <&serdes1 AM654_SERDES_LO_REFCLK>;
+ clock-output-names = "serdes0_cmu_refclk", "serdes0_lo_refclk",
+ "serdes0_ro_refclk";
+ assigned-clocks = <&k3_clks 153 4>, <&serdes0 AM654_SERDES_CMU_REFCLK>;
+ assigned-clock-parents = <&k3_clks 153 8>, <&k3_clks 153 4>;
+ ti,serdes-clk = <&serdes0_clk>;
+ mux-controls = <&serdes_mux 0>;
+ #clock-cells = <1>;
+ status = "disabled";
+};
diff --git a/include/dt-bindings/phy/phy-am654-serdes.h b/include/dt-bindings/phy/phy-am654-serdes.h
new file mode 100644
index 000000000000..e8d901729ed9
--- /dev/null
+++ b/include/dt-bindings/phy/phy-am654-serdes.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides constants for AM654 SERDES.
+ */
+
+#ifndef _DT_BINDINGS_AM654_SERDES
+#define _DT_BINDINGS_AM654_SERDES
+
+#define AM654_SERDES_CMU_REFCLK 0
+#define AM654_SERDES_LO_REFCLK 1
+#define AM654_SERDES_RO_REFCLK 2
+
+#endif /* _DT_BINDINGS_AM654_SERDES */
--
2.17.1


2018-09-21 10:28:03

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 36/40] arm64: dts: k3-am6: Add "socionext,synquacer-pre-its" property to gic_its

GIC_ITS used in AM65x platform has the same configuration as that of
GIC_ITS used in Socionext SoCs. Add "socionext,synquacer-pre-its"
property to get PCI MSI working.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
arch/arm64/boot/dts/ti/k3-am65-main.dtsi | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
index adcd6341e40c..2df4acb198bd 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
@@ -24,6 +24,7 @@
gic_its: gic-its@18200000 {
compatible = "arm,gic-v3-its";
reg = <0x00 0x01820000 0x00 0x10000>;
+ socionext,synquacer-pre-its = <0x1000000 0x400000>;
msi-controller;
#msi-cells = <1>;
};
--
2.17.1


2018-09-21 10:28:05

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 11/40] dt-bindings: PCI: keystone: Add bindings to get device control module

Add bindings to get device control module which has the device id and
vendor id to be configured in the keystone PCIe controller.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
Documentation/devicetree/bindings/pci/pci-keystone.txt | 3 +++
1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/pci-keystone.txt b/Documentation/devicetree/bindings/pci/pci-keystone.txt
index 4dd17de549a7..2030ee0dc4f9 100644
--- a/Documentation/devicetree/bindings/pci/pci-keystone.txt
+++ b/Documentation/devicetree/bindings/pci/pci-keystone.txt
@@ -19,6 +19,9 @@ pcie_msi_intc : Interrupt controller device node for MSI IRQ chip
interrupt-cells: should be set to 1
interrupts: GIC interrupt lines connected to PCI MSI interrupt lines

+ti,syscon-pcie-id : phandle to the device control module required to set device
+ id and vendor id.
+
Example:
pcie_msi_intc: msi-interrupt-controller {
interrupt-controller;
--
2.17.1


2018-09-21 10:28:37

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 30/40] dt-bindings: PCI: Add PCI RC dt binding documentation for AM654

Add devicetree binding documentation for PCIe in RC mode present in
AM654 SoC.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
Documentation/devicetree/bindings/pci/pci-keystone.txt | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/pci/pci-keystone.txt b/Documentation/devicetree/bindings/pci/pci-keystone.txt
index 8ee07197a063..5c60e911b8b1 100644
--- a/Documentation/devicetree/bindings/pci/pci-keystone.txt
+++ b/Documentation/devicetree/bindings/pci/pci-keystone.txt
@@ -11,7 +11,8 @@ described here as well as properties that are not applicable.

Required Properties:-

-compatibility: "ti,keystone-pcie"
+compatibility: Should be "ti,keystone-pcie" for RC on Keystone2 SoC
+ Should be "ti,am654-pcie-rc" for RC on AM654x SoC
reg: Three register ranges as listed in the reg-names property
reg-names: "dbics" for the DesignWare PCIe registers, "app" for the
TI specific application registers, "config" for the
@@ -20,6 +21,9 @@ reg-names: "dbics" for the DesignWare PCIe registers, "app" for the
pcie_msi_intc : Interrupt controller device node for MSI IRQ chip
interrupt-cells: should be set to 1
interrupts: GIC interrupt lines connected to PCI MSI interrupt lines
+ (required if the compatible is "ti,keystone-pcie")
+msi-map: As specified in Documentation/devicetree/bindings/pci/pci-msi.txt
+ (required if the compatible is "ti,am654-pcie-rc".

ti,syscon-pcie-id : phandle to the device control module required to set device
id and vendor id.
--
2.17.1


2018-09-21 10:28:38

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 28/40] PCI: dwc: Fix ATU identification for designware version >= 4.80

Synopsys designware version >= 4.80 uses a separate register space
for programming ATU. The current code identifies if there exists a
separate register space by accessing the register address of ATUs
in designware version < 4.80. Accessing this address results in
abort in the case of K2G.

Fix it here by adding "version" member to struct dw_pcie. This should
be set by platform specific drivers and designware core will use it
to identify if the platform has a separate ATU space. For platforms
which hasn't populated the version member, the old method of
identification will still be used.

Since identifying if iATU is enabled or not is specific to both
host mode and device mode, setting of iatu_unroll_enabled is moved
from pcie-designware-host.c to pcie-designware.c

Use the register space having reg-names as "atu" for the ATU
address space. For platforms which hasn't populated atu register space,
use the existing hard coded address.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
.../pci/controller/dwc/pcie-designware-host.c | 16 ------
drivers/pci/controller/dwc/pcie-designware.c | 50 +++++++++++++++++--
drivers/pci/controller/dwc/pcie-designware.h | 9 ++--
3 files changed, 52 insertions(+), 23 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 29a05759a294..37ea4f7e77b0 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -637,17 +637,6 @@ static struct pci_ops dw_pcie_ops = {
.write = dw_pcie_wr_conf,
};

-static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci)
-{
- u32 val;
-
- val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT);
- if (val == 0xffffffff)
- return 1;
-
- return 0;
-}
-
void dw_pcie_setup_rc(struct pcie_port *pp)
{
u32 val, ctrl, num_ctrls;
@@ -694,11 +683,6 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
* we should not program the ATU here.
*/
if (!pp->ops->rd_other_conf) {
- /* Get iATU unroll support */
- pci->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pci);
- dev_dbg(pci->dev, "iATU unroll: %s\n",
- pci->iatu_unroll_enabled ? "enabled" : "disabled");
-
dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0,
PCIE_ATU_TYPE_MEM, pp->mem_base,
pp->mem_bus_addr, pp->mem_size);
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 778c4f76a884..881f9c3786ae 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -92,16 +92,27 @@ void __dw_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
static u32 dw_pcie_readl_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg)
{
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
+ void __iomem *base = pci->atu_base;
+ u32 val;
+ int ret;
+
+ ret = dw_pcie_read(base + offset + reg, 0x4, &val);
+ if (ret)
+ dev_err(pci->dev, "read DBI address failed\n");

- return dw_pcie_readl_dbi(pci, offset + reg);
+ return val;
}

static void dw_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg,
u32 val)
{
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
+ void __iomem *base = pci->atu_base;
+ int ret;

- dw_pcie_writel_dbi(pci, offset + reg, val);
+ ret = dw_pcie_write(base + offset + reg, 0x4, val);
+ if (ret)
+ dev_err(pci->dev, "write DBI address failed\n");
}

static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,
@@ -186,16 +197,27 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
static u32 dw_pcie_readl_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg)
{
u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
+ void __iomem *base = pci->atu_base;
+ u32 val;
+ int ret;
+
+ ret = dw_pcie_read(base + offset + reg, 0x4, &val);
+ if (ret)
+ dev_err(pci->dev, "read DBI address failed\n");

- return dw_pcie_readl_dbi(pci, offset + reg);
+ return val;
}

static void dw_pcie_writel_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg,
u32 val)
{
u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
+ void __iomem *base = pci->atu_base;
+ int ret;

- dw_pcie_writel_dbi(pci, offset + reg, val);
+ ret = dw_pcie_write(base + offset + reg, 0x4, val);
+ if (ret)
+ dev_err(pci->dev, "write DBI address failed\n");
}

static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index,
@@ -339,6 +361,17 @@ int dw_pcie_link_up(struct dw_pcie *pci)
(!(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING)));
}

+static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci)
+{
+ u32 val;
+
+ val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT);
+ if (val == 0xffffffff)
+ return 1;
+
+ return 0;
+}
+
void dw_pcie_setup(struct dw_pcie *pci)
{
int ret;
@@ -347,6 +380,15 @@ void dw_pcie_setup(struct dw_pcie *pci)
struct device *dev = pci->dev;
struct device_node *np = dev->of_node;

+ if (pci->version >= 0x480A || (!pci->version &&
+ dw_pcie_iatu_unroll_enabled(pci))) {
+ pci->iatu_unroll_enabled = true;
+ if (!pci->atu_base)
+ pci->atu_base = pci->dbi_base + PCIE_ATU_BASE_OFFSET;
+ }
+ dev_dbg(pci->dev, "iATU unroll: %s\n", pci->iatu_unroll_enabled ?
+ "enabled" : "disabled");
+
ret = of_property_read_u32(np, "num-lanes", &lanes);
if (ret)
lanes = 0;
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index a4d939536faf..b8ff37d1563b 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -85,6 +85,7 @@
* iATU Unroll-specific register definitions
* From 4.80 core version the address translation will be made by unroll
*/
+#define PCIE_ATU_BASE_OFFSET (0x3 << 20)
#define PCIE_ATU_UNR_REGION_CTRL1 0x00
#define PCIE_ATU_UNR_REGION_CTRL2 0x04
#define PCIE_ATU_UNR_LOWER_BASE 0x08
@@ -95,10 +96,10 @@

/* Register address builder */
#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) \
- ((0x3 << 20) | ((region) << 9))
+ ((region) << 9)

-#define PCIE_GET_ATU_INB_UNR_REG_OFFSET(region) \
- ((0x3 << 20) | ((region) << 9) | (0x1 << 8))
+#define PCIE_GET_ATU_INB_UNR_REG_OFFSET(region) \
+ (((region) << 9) | (0x1 << 8))

#define MAX_MSI_IRQS 256
#define MAX_MSI_IRQS_PER_CTRL 32
@@ -220,11 +221,13 @@ struct dw_pcie {
struct device *dev;
void __iomem *dbi_base;
void __iomem *dbi_base2;
+ void __iomem *atu_base;
u32 num_viewport;
u8 iatu_unroll_enabled;
struct pcie_port pp;
struct dw_pcie_ep ep;
const struct dw_pcie_ops *ops;
+ unsigned int version;
};

#define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp)
--
2.17.1


2018-09-21 10:28:48

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 38/40] arm64: dts: k3-am6: Add mux-controller dt node required for muxing SERDES

Add mux-controller dt node as a child node of scm_conf. This is
required for muxing SERDES between USB, PCIe and ICSS2 SGMII. While
at that also add "simple-mfd" compatible string to scm_conf dt node
so that mux-controller device gets created.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
arch/arm64/boot/dts/ti/k3-am65-main.dtsi | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
index 957c9125a453..4379c370f6f8 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
@@ -7,8 +7,15 @@

&cbass_main {
scm_conf: scm_conf@100000 {
- compatible = "syscon";
+ compatible = "syscon", "simple-mfd";
reg = <0 0x00100000 0 0x1c000>;
+
+ serdes_mux: mux-controller {
+ compatible = "mmio-mux";
+ #mux-control-cells = <1>;
+ mux-reg-masks = <0x4080 0x3>, /* SERDES0 lane select */
+ <0x4090 0x3>; /* SERDES1 lane select */
+ };
};

gic500: interrupt-controller@1800000 {
--
2.17.1


2018-09-21 10:28:48

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 26/40] PCI: keystone: Explicitly set the PCIe mode

Explicitly set the PCIe mode to BOOTCFG_DEVCFG instead of always
relying on the default values. This is required when EP mode has to
be explicitly written to BOOTCFG_DEVCFG register.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 37 +++++++++++++++++++++++
1 file changed, 37 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 13e865f82f96..e8328039a017 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -80,6 +80,15 @@
#define PCIE_RC_K2L 0xb00a
#define PCIE_RC_K2G 0xb00b

+#define KS_PCIE_DEV_TYPE_MASK (0x3 << 1)
+#define KS_PCIE_DEV_TYPE(mode) ((mode) << 1)
+
+#define EP 0x0
+#define LEG_EP 0x1
+#define RC 0x2
+
+#define KS_PCIE_SYSCLOCKOUTEN BIT(0)
+
#define to_keystone_pcie(x) dev_get_drvdata((x)->dev)

static int ks_pcie_start_link(struct dw_pcie *pci);
@@ -749,6 +758,30 @@ static int ks_pcie_enable_phy(struct keystone_pcie *ks_pcie)
return ret;
}

+static int ks_pcie_set_mode(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct regmap *syscon;
+ u32 val;
+ u32 mask;
+ int ret = 0;
+
+ syscon = syscon_regmap_lookup_by_phandle(np, "ti,syscon-pcie-mode");
+ if (IS_ERR(syscon))
+ return 0;
+
+ mask = KS_PCIE_DEV_TYPE_MASK | KS_PCIE_SYSCLOCKOUTEN;
+ val = KS_PCIE_DEV_TYPE(RC) | KS_PCIE_SYSCLOCKOUTEN;
+
+ ret = regmap_update_bits(syscon, 0, mask, val);
+ if (ret) {
+ dev_err(dev, "failed to set pcie mode\n");
+ return ret;
+ }
+
+ return 0;
+}
+
static int __init ks_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -865,6 +898,10 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
goto err_get_sync;
}

+ ret = ks_pcie_set_mode(dev);
+ if (ret < 0)
+ goto err_get_sync;
+
ret = ks_pcie_add_pcie_port(ks_pcie, pdev);
if (ret < 0)
goto err_get_sync;
--
2.17.1


2018-09-21 10:28:53

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 39/40] arm64: dts: k3-am6: Add SERDES DT node

Add DT node for SERDES0 and SERDES1.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
arch/arm64/boot/dts/ti/k3-am65-main.dtsi | 46 ++++++++++++++++++++++++
1 file changed, 46 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
index 4379c370f6f8..b08d15fa110e 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
@@ -4,11 +4,25 @@
*
* Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/
*/
+#include <dt-bindings/phy/phy-am654-serdes.h>

&cbass_main {
scm_conf: scm_conf@100000 {
compatible = "syscon", "simple-mfd";
reg = <0 0x00100000 0 0x1c000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x0 0x00100000 0x1c000>;
+
+ serdes0_clk: serdes_clk@4080 {
+ compatible = "syscon";
+ reg = <0x00004080 0x4>;
+ };
+
+ serdes1_clk: serdes_clk@4090 {
+ compatible = "syscon";
+ reg = <0x00004090 0x4>;
+ };

serdes_mux: mux-controller {
compatible = "mmio-mux";
@@ -53,6 +67,38 @@
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
};

+ serdes0: serdes@900000 {
+ compatible = "ti,phy-am654-serdes";
+ reg = <0x0 0x900000 0x0 0x2000>;
+ reg-names = "serdes";
+ #phy-cells = <2>;
+ power-domains = <&k3_pds 153>;
+ clocks = <&k3_clks 153 4>, <&k3_clks 153 1>, <&serdes1 AM654_SERDES_LO_REFCLK>;
+ clock-output-names = "serdes0_cmu_refclk", "serdes0_lo_refclk", "serdes0_ro_refclk";
+ assigned-clocks = <&k3_clks 153 4>, <&serdes0 AM654_SERDES_CMU_REFCLK>;
+ assigned-clock-parents = <&k3_clks 153 8>, <&k3_clks 153 4>;
+ ti,serdes-clk = <&serdes0_clk>;
+ #clock-cells = <1>;
+ mux-controls = <&serdes_mux 0>;
+ status = "disabled";
+ };
+
+ serdes1: serdes@910000 {
+ compatible = "ti,phy-am654-serdes";
+ reg = <0x0 0x910000 0x0 0x2000>;
+ reg-names = "serdes";
+ #phy-cells = <2>;
+ power-domains = <&k3_pds 154>;
+ clocks = <&serdes0 AM654_SERDES_RO_REFCLK>, <&k3_clks 154 1>, <&k3_clks 154 5>;
+ clock-output-names = "serdes1_cmu_refclk", "serdes1_lo_refclk", "serdes1_ro_refclk";
+ assigned-clocks = <&k3_clks 154 5>, <&serdes1 AM654_SERDES_CMU_REFCLK>;
+ assigned-clock-parents = <&k3_clks 154 9>, <&k3_clks 154 5>;
+ ti,serdes-clk = <&serdes1_clk>;
+ #clock-cells = <1>;
+ mux-controls = <&serdes_mux 1>;
+ status = "disabled";
+ };
+
main_uart0: serial@2800000 {
compatible = "ti,am654-uart";
reg = <0x00 0x02800000 0x00 0x100>;
--
2.17.1


2018-09-21 10:29:08

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 40/40] arm64: dts: k3-am6: Add Root Complex PCIe dt node

Add Root Complex PCIe dt node.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
arch/arm64/boot/dts/ti/k3-am65-main.dtsi | 83 ++++++++++++++++++++++++
arch/arm64/boot/dts/ti/k3-am65.dtsi | 1 +
2 files changed, 84 insertions(+)

diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
index b08d15fa110e..0a5d74a8eef4 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
@@ -14,6 +14,21 @@
#size-cells = <1>;
ranges = <0x0 0x0 0x00100000 0x1c000>;

+ pcie0_mode: pcie-mode@4060 {
+ compatible = "syscon";
+ reg = <0x00004060 0x4>;
+ };
+
+ pcie1_mode: pcie-mode@4070 {
+ compatible = "syscon";
+ reg = <0x00004070 0x4>;
+ };
+
+ pcie_devid: pcie-devid@210 {
+ compatible = "syscon";
+ reg = <0x00000210 0x4>;
+ };
+
serdes0_clk: serdes_clk@4080 {
compatible = "syscon";
reg = <0x00004080 0x4>;
@@ -128,4 +143,72 @@
clock-frequency = <48000000>;
current-speed = <115200>;
};
+
+ pcie0_rc: pcie@5500000 {
+ compatible = "ti,am654-pcie-rc";
+ reg = <0x0 0x5500000 0x0 0x1000>, <0x0 0x5501000 0x0 0x1000>, <0x0 0x10000000 0x0 0x2000>, <0x0 0x5506000 0x0 0x1000>;
+ reg-names = "app", "dbics", "config", "atu";
+ power-domains = <&k3_pds 120>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x81000000 0 0 0x0 0x10020000 0 0x00010000
+ 0x82000000 0 0x10030000 0x0 0x10030000 0 0x07FD0000>;
+ ti,syscon-pcie-id = <&pcie_devid>;
+ ti,syscon-pcie-mode = <&pcie0_mode>;
+ bus-range = <0x0 0xff>;
+ device_type = "pci";
+ num-lanes = <1>;
+ num-ob-windows = <16>;
+ num-viewport = <16>;
+ interrupts = <GIC_SPI 340 IRQ_TYPE_EDGE_RISING>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie0_intc 0>, /* INT A */
+ <0 0 0 2 &pcie0_intc 0>, /* INT B */
+ <0 0 0 3 &pcie0_intc 0>, /* INT C */
+ <0 0 0 4 &pcie0_intc 0>; /* INT D */
+ msi-map = <0x0 &gic_its 0x0 0x10000>;
+ status = "disabled";
+
+ pcie0_intc: legacy-interrupt-controller@1 {
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gic500>;
+ interrupts = <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>;
+ };
+ };
+
+ pcie1_rc: pcie@5600000 {
+ compatible = "ti,am654-pcie-rc";
+ reg = <0x0 0x5600000 0x0 0x1000>, <0x0 0x5601000 0x0 0x1000>, <0x0 0x18000000 0x0 0x2000>, <0x0 0x5606000 0x0 0x1000>;
+ reg-names = "app", "dbics", "config", "atu";
+ power-domains = <&k3_pds 121>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x81000000 0 0 0x0 0x18020000 0 0x00010000
+ 0x82000000 0 0x18030000 0x0 0x18030000 0 0x07FD0000>;
+ ti,syscon-pcie-id = <&pcie_devid>;
+ ti,syscon-pcie-mode = <&pcie1_mode>;
+ bus-range = <0x0 0xff>;
+ status = "disabled";
+ device_type = "pci";
+ num-lanes = <1>;
+ num-ob-windows = <16>;
+ num-viewport = <16>;
+ interrupts = <GIC_SPI 355 IRQ_TYPE_EDGE_RISING>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie1_intc 0>, /* INT A */
+ <0 0 0 2 &pcie1_intc 0>, /* INT B */
+ <0 0 0 3 &pcie1_intc 0>, /* INT C */
+ <0 0 0 4 &pcie1_intc 0>; /* INT D */
+ msi-map = <0x0 &gic_its 0x10000 0x10000>;
+
+ pcie1_intc: legacy-interrupt-controller@1 {
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&gic500>;
+ interrupts = <GIC_SPI 343 IRQ_TYPE_EDGE_RISING>;
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/ti/k3-am65.dtsi b/arch/arm64/boot/dts/ti/k3-am65.dtsi
index 3d4bf369d030..b87081765894 100644
--- a/arch/arm64/boot/dts/ti/k3-am65.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65.dtsi
@@ -61,6 +61,7 @@
<0x00 0x00900000 0x00 0x00900000 0x00 0x00012000>, /* serdes */
<0x00 0x01000000 0x00 0x01000000 0x00 0x0af02400>, /* Most peripherals */
<0x00 0x30800000 0x00 0x30800000 0x00 0x0bc00000>, /* MAIN NAVSS */
+ <0x00 0x10000000 0x00 0x10000000 0x00 0x10000000>, /* PCIe DAT */
/* MCUSS Range */
<0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>,
<0x00 0x40200000 0x00 0x40200000 0x00 0x00900100>,
--
2.17.1


2018-09-21 10:29:11

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 21/40] PCI: keystone: Add debug error message for all errors

commit 025dd3daeda77f61a280da87ae701 ("PCI: keystone: Add error IRQ
handler") added dev_err() message only for ERR_AXI and ERR_FATAL. Add
debug error message for ERR_SYS, ERR_NONFATAL, ERR_CORR and ERR_AER here.

While at that avoid using ERR_IRQ_STATUS_RAW and use ERR_IRQ_STATUS
instead.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 45 +++++++++++++----------
1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 240c39c58b0f..a3dec74da70c 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -74,8 +74,6 @@
#define ERR_SYS BIT(0) /* System (fatal, non-fatal, or correctable) */
#define ERR_IRQ_ALL (ERR_AER | ERR_AXI | ERR_CORR | \
ERR_NONFATAL | ERR_FATAL | ERR_SYS)
-#define ERR_FATAL_IRQ (ERR_FATAL | ERR_AXI)
-#define ERR_IRQ_STATUS_RAW 0x1c0
#define ERR_IRQ_STATUS 0x1c4
#define ERR_IRQ_ENABLE_SET 0x1c8
#define ERR_IRQ_ENABLE_CLR 0x1cc
@@ -180,23 +178,6 @@ static void ks_pcie_enable_error_irq(struct keystone_pcie *ks_pcie)
ks_pcie_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL);
}

-static irqreturn_t ks_pcie_handle_error_irq(struct keystone_pcie *ks_pcie)
-{
- u32 status;
-
- status = ks_pcie_app_readl(ks_pcie, ERR_IRQ_STATUS_RAW) & ERR_IRQ_ALL;
- if (!status)
- return IRQ_NONE;
-
- if (status & ERR_FATAL_IRQ)
- dev_err(ks_pcie->pci->dev, "fatal error (status %#010x)\n",
- status);
-
- /* Ack the IRQ; status bits are RW1C */
- ks_pcie_app_writel(ks_pcie, ERR_IRQ_STATUS, status);
- return IRQ_HANDLED;
-}
-
/**
* ks_pcie_set_dbi_mode() - Set DBI mode to access overlaid BAR mask
* registers
@@ -636,9 +617,33 @@ static const struct dw_pcie_host_ops ks_pcie_host_ops = {

static irqreturn_t ks_pcie_err_irq_handler(int irq, void *priv)
{
+ u32 reg;
struct keystone_pcie *ks_pcie = priv;
+ struct device *dev = ks_pcie->pci->dev;

- return ks_pcie_handle_error_irq(ks_pcie);
+ reg = ks_pcie_app_readl(ks_pcie, ERR_IRQ_STATUS);
+
+ if (reg & ERR_SYS)
+ dev_err(dev, "System Error\n");
+
+ if (reg & ERR_FATAL)
+ dev_err(dev, "Fatal Error\n");
+
+ if (reg & ERR_NONFATAL)
+ dev_dbg(dev, "Non Fatal Error\n");
+
+ if (reg & ERR_CORR)
+ dev_dbg(dev, "Correctable Error\n");
+
+ if (reg & ERR_AXI)
+ dev_err(dev, "AXI tag lookup fatal Error\n");
+
+ if (reg & ERR_AER)
+ dev_err(dev, "ECRC Error\n");
+
+ ks_pcie_app_writel(ks_pcie, ERR_IRQ_STATUS, reg);
+
+ return IRQ_HANDLED;
}

static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie,
--
2.17.1


2018-09-21 10:29:46

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 35/40] ARM: dts: keystone-k2e: Use the updated binding to describe PCIe in k2e

Use the updated binding to describe PCIe in k2e. (The older binding has
never worked in upstream kernel since serdes driver was never upstreamed).

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
Signed-off-by: Sekhar Nori <[email protected]>
---
arch/arm/boot/dts/keystone-k2e.dtsi | 15 ++++++++-------
arch/arm/boot/dts/keystone.dtsi | 18 ++++++++++++++----
2 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/arch/arm/boot/dts/keystone-k2e.dtsi b/arch/arm/boot/dts/keystone-k2e.dtsi
index 085e7326ea8e..d9945d600c95 100644
--- a/arch/arm/boot/dts/keystone-k2e.dtsi
+++ b/arch/arm/boot/dts/keystone-k2e.dtsi
@@ -136,20 +136,21 @@
};

pcie1: pcie@21020000 {
- compatible = "ti,keystone-pcie","snps,dw-pcie";
+ compatible = "ti,keystone-pcie", "snps,dw-pcie";
+ reg = <0x21020000 0x1000>, <0x21021000 0x1000>, <0x21022000 0x1000>;
+ reg-names = "app", "dbics", "config";
clocks = <&clkpcie1>;
- clock-names = "pcie";
+ clock-names = "fck";
#address-cells = <3>;
#size-cells = <2>;
- reg = <0x21021000 0x2000>, <0x21020000 0x1000>, <0x02620128 4>;
- ranges = <0x82000000 0 0x60000000 0x60000000
- 0 0x10000000>;
-
+ ranges = <0x82000000 0 0x60000000 0x60000000 0 0x10000000>;
+ ti,syscon-pcie-id = <&pcie_devid>;
+ ti,syscon-pcie-mode = <&pcie_mode>;
status = "disabled";
device_type = "pci";
num-lanes = <2>;
+ num-viewport = <32>;
bus-range = <0x00 0xff>;
-
/* error interrupt */
interrupts = <GIC_SPI 385 IRQ_TYPE_EDGE_RISING>;
#interrupt-cells = <1>;
diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/keystone.dtsi
index c298675a29a5..0245fe854367 100644
--- a/arch/arm/boot/dts/keystone.dtsi
+++ b/arch/arm/boot/dts/keystone.dtsi
@@ -93,6 +93,16 @@
#size-cells = <1>;
ranges = <0x0 0x02620000 0x1000>;

+ pcie_devid: pcie-devid@128 {
+ compatible = "syscon";
+ reg = <0x00000128 0x4>;
+ };
+
+ pcie_mode: pcie-mode@14c {
+ compatible = "syscon";
+ reg = <0x0000014c 0x4>;
+ };
+
kirq0: keystone_irq@2a0 {
compatible = "ti,keystone-irq";
reg = <0x2a0 0x4>;
@@ -297,13 +307,13 @@

pcie0: pcie@21800000 {
compatible = "ti,keystone-pcie", "snps,dw-pcie";
+ reg = <0x21800000 0x1000>, <0x21801000 0x1000>, <0x21802000 0x1000>;
+ reg-names = "app", "dbics", "config";
clocks = <&clkpcie>;
- clock-names = "pcie";
+ clock-names = "fck";
#address-cells = <3>;
#size-cells = <2>;
- reg = <0x21801000 0x2000>, <0x21800000 0x1000>, <0x02620128 4>;
- ranges = <0x82000000 0 0x50000000 0x50000000
- 0 0x10000000>;
+ ranges = <0x82000000 0 0x50000000 0x50000000 0 0x10000000>;

status = "disabled";
device_type = "pci";
--
2.17.1


2018-09-21 10:29:53

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 08/40] PCI: keystone: Cleanup MSI/legacy interrupt configuration and handling

Now that all PCI keystone functionality has been moved to pci-keystone.c,
cleanup MSI/legacy interrupt configuration and handling.
*) Cleanup macros
*) Remove unnecessary structure variables (required when 2 files are
used)
*) Remove ks_dw_pcie_legacy_irq_chip and use dummy_irq_chip
*) Move request_irq of error irq from ks_add_pcie_port to ks_pcie_probe
as error_irq is common to both host mode and device mode

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 392 +++++++++-------------
1 file changed, 150 insertions(+), 242 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 65ff7a5566b4..4554fdc6cce1 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -50,17 +50,16 @@

/* IRQ register defines */
#define IRQ_EOI 0x050
-#define IRQ_STATUS 0x184
-#define IRQ_ENABLE_SET 0x188
-#define IRQ_ENABLE_CLR 0x18c
-
#define MSI_IRQ 0x054
-#define MSI0_IRQ_STATUS 0x104
-#define MSI0_IRQ_ENABLE_SET 0x108
-#define MSI0_IRQ_ENABLE_CLR 0x10c
-#define IRQ_STATUS 0x184
+#define MSI_IRQ_STATUS(n) (0x104 + ((n) << 4))
+#define MSI_IRQ_ENABLE_SET(n) (0x108 + ((n) << 4))
+#define MSI_IRQ_ENABLE_CLR(n) (0x10c + ((n) << 4))
#define MSI_IRQ_OFFSET 4

+#define IRQ_STATUS(n) (0x184 + ((n) << 4))
+#define IRQ_ENABLE_SET(n) (0x188 + ((n) << 4))
+#define INTx_EN BIT(0)
+
/* Error IRQ bits */
#define ERR_AER BIT(5) /* ECRC error */
#define ERR_AXI BIT(4) /* AXI tag lookup fatal error */
@@ -79,8 +78,6 @@
/* Config space registers */
#define DEBUG0 0x728

-#define MAX_MSI_HOST_IRQS 8
-
/* PCIE controller device IDs */
#define PCIE_RC_K2HK 0xb008
#define PCIE_RC_K2E 0xb009
@@ -97,30 +94,16 @@ struct keystone_pcie {
struct clk *clk;
/* PCI Device ID */
u32 device_id;
- int num_legacy_host_irqs;
- int legacy_host_irqs[PCI_NUM_INTX];
- struct device_node *legacy_intc_np;
-
- int num_msi_host_irqs;
- int msi_host_irqs[MAX_MSI_HOST_IRQS];
+ int msi_host_irq;
struct device_node *msi_intc_np;
struct irq_domain *legacy_irq_domain;
struct device_node *np;

- int error_irq;
-
/* Application register space */
void __iomem *va_app_base; /* DT 1st resource */
struct resource app;
};

-static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset,
- u32 *bit_pos)
-{
- *reg_offset = offset % 8;
- *bit_pos = offset >> 3;
-}
-
static phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -139,31 +122,6 @@ static void ks_dw_app_writel(struct keystone_pcie *ks_pcie, u32 offset, u32 val)
writel(val, ks_pcie->va_app_base + offset);
}

-static void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset)
-{
- struct dw_pcie *pci = ks_pcie->pci;
- struct pcie_port *pp = &pci->pp;
- struct device *dev = pci->dev;
- u32 pending, vector;
- int src, virq;
-
- pending = ks_dw_app_readl(ks_pcie, MSI0_IRQ_STATUS + (offset << 4));
-
- /*
- * MSI0 status bit 0-3 shows vectors 0, 8, 16, 24, MSI1 status bit
- * shows 1, 9, 17, 25 and so forth
- */
- for (src = 0; src < 4; src++) {
- if (BIT(src) & pending) {
- vector = offset + (src << 3);
- virq = irq_linear_revmap(pp->irq_domain, vector);
- dev_dbg(dev, "irq: bit %d, vector %d, virq %d\n",
- src, vector, virq);
- generic_handle_irq(virq);
- }
- }
-}
-
static void ks_dw_pcie_msi_irq_ack(int irq, struct pcie_port *pp)
{
u32 reg_offset, bit_pos;
@@ -172,11 +130,11 @@ static void ks_dw_pcie_msi_irq_ack(int irq, struct pcie_port *pp)

pci = to_dw_pcie_from_pp(pp);
ks_pcie = to_keystone_pcie(pci);
- update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);

- ks_dw_app_writel(ks_pcie, MSI0_IRQ_STATUS + (reg_offset << 4),
- BIT(bit_pos));
- ks_dw_app_writel(ks_pcie, IRQ_EOI, reg_offset + MSI_IRQ_OFFSET);
+ reg_offset = irq % 8;
+ bit_pos = irq >> 3;
+ ks_dw_app_writel(ks_pcie, MSI_IRQ_STATUS(reg_offset), BIT(bit_pos));
+ ks_dw_app_writel(ks_pcie, IRQ_EOI, MSI_IRQ_OFFSET + reg_offset);
}

static void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
@@ -185,8 +143,9 @@ static void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);

- update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
- ks_dw_app_writel(ks_pcie, MSI0_IRQ_ENABLE_SET + (reg_offset << 4),
+ reg_offset = irq % 8;
+ bit_pos = irq >> 3;
+ ks_dw_app_writel(ks_pcie, MSI_IRQ_ENABLE_SET(reg_offset),
BIT(bit_pos));
}

@@ -196,8 +155,9 @@ static void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);

- update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
- ks_dw_app_writel(ks_pcie, MSI0_IRQ_ENABLE_CLR + (reg_offset << 4),
+ reg_offset = irq % 8;
+ bit_pos = irq >> 3;
+ ks_dw_app_writel(ks_pcie, MSI_IRQ_ENABLE_CLR(reg_offset),
BIT(bit_pos));
}

@@ -206,34 +166,6 @@ static int ks_dw_pcie_msi_host_init(struct pcie_port *pp)
return dw_pcie_allocate_domains(pp);
}

-static void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie)
-{
- int i;
-
- for (i = 0; i < PCI_NUM_INTX; i++)
- ks_dw_app_writel(ks_pcie, IRQ_ENABLE_SET + (i << 4), 0x1);
-}
-
-static void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie,
- int offset)
-{
- struct dw_pcie *pci = ks_pcie->pci;
- struct device *dev = pci->dev;
- u32 pending;
- int virq;
-
- pending = ks_dw_app_readl(ks_pcie, IRQ_STATUS + (offset << 4));
-
- if (BIT(0) & pending) {
- virq = irq_linear_revmap(ks_pcie->legacy_irq_domain, offset);
- dev_dbg(dev, ": irq: irq_offset %d, virq %d\n", offset, virq);
- generic_handle_irq(virq);
- }
-
- /* EOI the INTx interrupt */
- ks_dw_app_writel(ks_pcie, IRQ_EOI, offset);
-}
-
static void ks_dw_pcie_enable_error_irq(struct keystone_pcie *ks_pcie)
{
ks_dw_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL);
@@ -256,40 +188,6 @@ static irqreturn_t ks_dw_pcie_handle_error_irq(struct keystone_pcie *ks_pcie)
return IRQ_HANDLED;
}

-static void ks_dw_pcie_ack_legacy_irq(struct irq_data *d)
-{
-}
-
-static void ks_dw_pcie_mask_legacy_irq(struct irq_data *d)
-{
-}
-
-static void ks_dw_pcie_unmask_legacy_irq(struct irq_data *d)
-{
-}
-
-static struct irq_chip ks_dw_pcie_legacy_irq_chip = {
- .name = "Keystone-PCI-Legacy-IRQ",
- .irq_ack = ks_dw_pcie_ack_legacy_irq,
- .irq_mask = ks_dw_pcie_mask_legacy_irq,
- .irq_unmask = ks_dw_pcie_unmask_legacy_irq,
-};
-
-static int ks_dw_pcie_init_legacy_irq_map(struct irq_domain *d,
- unsigned int irq, irq_hw_number_t hw_irq)
-{
- irq_set_chip_and_handler(irq, &ks_dw_pcie_legacy_irq_chip,
- handle_level_irq);
- irq_set_chip_data(irq, d->host_data);
-
- return 0;
-}
-
-static const struct irq_domain_ops ks_dw_pcie_legacy_irq_domain_ops = {
- .map = ks_dw_pcie_init_legacy_irq_map,
- .xlate = irq_domain_xlate_onetwocell,
-};
-
/**
* ks_dw_pcie_set_dbi_mode() - Set DBI mode to access overlaid BAR mask
* registers
@@ -520,17 +418,6 @@ static int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie)

ks_pcie->app = *res;

- /* Create legacy IRQ domain */
- ks_pcie->legacy_irq_domain =
- irq_domain_add_linear(ks_pcie->legacy_intc_np,
- PCI_NUM_INTX,
- &ks_dw_pcie_legacy_irq_domain_ops,
- NULL);
- if (!ks_pcie->legacy_irq_domain) {
- dev_err(dev, "Failed to add irq domain for legacy irqs\n");
- return -EINVAL;
- }
-
return dw_pcie_host_init(pp);
}

@@ -579,22 +466,32 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, quirk_limit_mrrs);

static void ks_pcie_msi_irq_handler(struct irq_desc *desc)
{
+ u32 reg;
+ u32 vector;
+ int pos;
+ int virq;
unsigned int irq = irq_desc_get_irq(desc);
struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
- u32 offset = irq - ks_pcie->msi_host_irqs[0];
+ u32 offset = irq - ks_pcie->msi_host_irq;
struct dw_pcie *pci = ks_pcie->pci;
+ struct pcie_port *pp = &pci->pp;
struct device *dev = pci->dev;
struct irq_chip *chip = irq_desc_get_chip(desc);

- dev_dbg(dev, "%s, irq %d\n", __func__, irq);
-
- /*
- * The chained irq handler installation would have replaced normal
- * interrupt driver handler so we need to take care of mask/unmask and
- * ack operation.
- */
chained_irq_enter(chip, desc);
- ks_dw_pcie_handle_msi_irq(ks_pcie, offset);
+
+ reg = ks_dw_app_readl(ks_pcie, MSI_IRQ_STATUS(offset));
+ for (pos = 0; pos < 4; pos++) {
+ if (!(reg & BIT(pos)))
+ continue;
+
+ vector = offset + (pos << 3);
+ virq = irq_linear_revmap(pp->irq_domain, vector);
+ dev_dbg(dev, "irq: bit %d, vector %d, virq %d\n", pos, vector,
+ virq);
+ generic_handle_irq(virq);
+ }
+
chained_irq_exit(chip, desc);
}

@@ -608,106 +505,124 @@ static void ks_pcie_msi_irq_handler(struct irq_desc *desc)
*/
static void ks_pcie_legacy_irq_handler(struct irq_desc *desc)
{
- unsigned int irq = irq_desc_get_irq(desc);
+ int i;
+ u32 reg;
+ int virq;
struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
- struct dw_pcie *pci = ks_pcie->pci;
- struct device *dev = pci->dev;
- u32 irq_offset = irq - ks_pcie->legacy_host_irqs[0];
struct irq_chip *chip = irq_desc_get_chip(desc);

- dev_dbg(dev, ": Handling legacy irq %d\n", irq);
-
- /*
- * The chained irq handler installation would have replaced normal
- * interrupt driver handler so we need to take care of mask/unmask and
- * ack operation.
- */
chained_irq_enter(chip, desc);
- ks_dw_pcie_handle_legacy_irq(ks_pcie, irq_offset);
+
+ for (i = 0; i < PCI_NUM_INTX; i++) {
+ reg = ks_dw_app_readl(ks_pcie, IRQ_STATUS(i));
+ if (!(reg & INTx_EN))
+ continue;
+
+ virq = irq_linear_revmap(ks_pcie->legacy_irq_domain, i);
+ generic_handle_irq(virq);
+ ks_dw_app_writel(ks_pcie, IRQ_STATUS(i), INTx_EN);
+ ks_dw_app_writel(ks_pcie, IRQ_EOI, i);
+ }
+
chained_irq_exit(chip, desc);
}

-static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie,
- char *controller, int *num_irqs)
+static int ks_pcie_config_msi_irq(struct keystone_pcie *ks_pcie)
{
- int temp, max_host_irqs, legacy = 1, *host_irqs;
struct device *dev = ks_pcie->pci->dev;
- struct device_node *np_pcie = dev->of_node, **np_temp;
-
- if (!strcmp(controller, "msi-interrupt-controller"))
- legacy = 0;
-
- if (legacy) {
- np_temp = &ks_pcie->legacy_intc_np;
- max_host_irqs = PCI_NUM_INTX;
- host_irqs = &ks_pcie->legacy_host_irqs[0];
- } else {
- np_temp = &ks_pcie->msi_intc_np;
- max_host_irqs = MAX_MSI_HOST_IRQS;
- host_irqs = &ks_pcie->msi_host_irqs[0];
- }
+ struct device_node *np = ks_pcie->np;
+ struct device_node *intc_np;
+ int irq_count;
+ int irq;
+ int i;
+
+ if (!IS_ENABLED(CONFIG_PCI_MSI))
+ return 0;

- /* interrupt controller is in a child node */
- *np_temp = of_get_child_by_name(np_pcie, controller);
- if (!(*np_temp)) {
- dev_err(dev, "Node for %s is absent\n", controller);
+ intc_np = of_get_child_by_name(np, "msi-interrupt-controller");
+ if (!intc_np) {
+ dev_WARN(dev, "msi-interrupt-controller node is absent\n");
return -EINVAL;
}

- temp = of_irq_count(*np_temp);
- if (!temp) {
- dev_err(dev, "No IRQ entries in %s\n", controller);
- of_node_put(*np_temp);
+ irq_count = of_irq_count(intc_np);
+ if (!irq_count) {
+ dev_err(dev, "No IRQ entries in msi-interrupt-controller\n");
return -EINVAL;
}

- if (temp > max_host_irqs)
- dev_warn(dev, "Too many %s interrupts defined %u\n",
- (legacy ? "legacy" : "MSI"), temp);
+ for (i = 0; i < irq_count; i++) {
+ irq = irq_of_parse_and_map(intc_np, i);
+ if (!irq)
+ return -EINVAL;

- /*
- * support upto max_host_irqs. In dt from index 0 to 3 (legacy) or 0 to
- * 7 (MSI)
- */
- for (temp = 0; temp < max_host_irqs; temp++) {
- host_irqs[temp] = irq_of_parse_and_map(*np_temp, temp);
- if (!host_irqs[temp])
- break;
+ if (!ks_pcie->msi_host_irq)
+ ks_pcie->msi_host_irq = irq;
+
+ irq_set_chained_handler_and_data(irq, ks_pcie_msi_irq_handler,
+ ks_pcie);
}

- of_node_put(*np_temp);
+ return 0;
+}

- if (temp) {
- *num_irqs = temp;
- return 0;
- }
+static int ks_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+ irq_set_chip_data(irq, domain->host_data);

- return -EINVAL;
+ return 0;
}

-static void ks_pcie_setup_interrupts(struct keystone_pcie *ks_pcie)
+static const struct irq_domain_ops ks_pcie_intx_domain_ops = {
+ .map = ks_pcie_intx_map,
+};
+
+static int ks_pcie_config_legacy_irq(struct keystone_pcie *ks_pcie)
{
+ struct device *dev = ks_pcie->pci->dev;
+ struct irq_domain *legacy_irq_domain;
+ struct device_node *np = ks_pcie->np;
+ struct device_node *intc_np;
+ int irq_count;
+ int irq;
int i;

- /* Legacy IRQ */
- for (i = 0; i < ks_pcie->num_legacy_host_irqs; i++) {
- irq_set_chained_handler_and_data(ks_pcie->legacy_host_irqs[i],
+ intc_np = of_get_child_by_name(np, "legacy-interrupt-controller");
+ if (!intc_np) {
+ dev_WARN(dev, "legacy-interrupt-controller node is absent\n");
+ return -EINVAL;
+ }
+
+ irq_count = of_irq_count(intc_np);
+ if (!irq_count) {
+ dev_err(dev, "No IRQ entries in legacy-interrupt-controller\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < irq_count; i++) {
+ irq = irq_of_parse_and_map(intc_np, i);
+ if (!irq)
+ return -EINVAL;
+ irq_set_chained_handler_and_data(irq,
ks_pcie_legacy_irq_handler,
ks_pcie);
}
- ks_dw_pcie_enable_legacy_irqs(ks_pcie);
-
- /* MSI IRQ */
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- for (i = 0; i < ks_pcie->num_msi_host_irqs; i++) {
- irq_set_chained_handler_and_data(ks_pcie->msi_host_irqs[i],
- ks_pcie_msi_irq_handler,
- ks_pcie);
- }
+
+ legacy_irq_domain = irq_domain_add_linear(intc_np, PCI_NUM_INTX,
+ &ks_pcie_intx_domain_ops,
+ NULL);
+ if (!legacy_irq_domain) {
+ dev_err(dev, "Failed to add irq domain for legacy irqs\n");
+ return -EINVAL;
}
+ ks_pcie->legacy_irq_domain = legacy_irq_domain;

- if (ks_pcie->error_irq > 0)
- ks_dw_pcie_enable_error_irq(ks_pcie);
+ for (i = 0; i < PCI_NUM_INTX; i++)
+ ks_dw_app_writel(ks_pcie, IRQ_ENABLE_SET(i), INTx_EN);
+
+ return 0;
}

/*
@@ -734,11 +649,19 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
+ int ret;
+
+ ret = ks_pcie_config_legacy_irq(ks_pcie);
+ if (ret)
+ return ret;
+
+ ret = ks_pcie_config_msi_irq(ks_pcie);
+ if (ret)
+ return ret;

dw_pcie_setup_rc(pp);

ks_dw_pcie_setup_rc_app_regs(ks_pcie);
- ks_pcie_setup_interrupts(ks_pcie);
writew(PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8),
pci->dbi_base + PCI_IO_BASE);

@@ -783,44 +706,12 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
struct device *dev = &pdev->dev;
int ret;

- ret = ks_pcie_get_irq_controller_info(ks_pcie,
- "legacy-interrupt-controller",
- &ks_pcie->num_legacy_host_irqs);
- if (ret)
- return ret;
-
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- ret = ks_pcie_get_irq_controller_info(ks_pcie,
- "msi-interrupt-controller",
- &ks_pcie->num_msi_host_irqs);
- if (ret)
- return ret;
- }
-
- /*
- * Index 0 is the platform interrupt for error interrupt
- * from RC. This is optional.
- */
- ks_pcie->error_irq = irq_of_parse_and_map(ks_pcie->np, 0);
- if (ks_pcie->error_irq <= 0)
- dev_info(dev, "no error IRQ defined\n");
- else {
- ret = request_irq(ks_pcie->error_irq, pcie_err_irq_handler,
- IRQF_SHARED, "pcie-error-irq", ks_pcie);
- if (ret < 0) {
- dev_err(dev, "failed to request error IRQ %d\n",
- ks_pcie->error_irq);
- return ret;
- }
- }
-
pp->ops = &keystone_pcie_host_ops;
ret = ks_dw_pcie_host_init(ks_pcie);
if (ret) {
dev_err(dev, "failed to initialize host\n");
return ret;
}
-
return 0;
}

@@ -878,6 +769,7 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
void __iomem *reg_p;
struct phy *phy;
int ret;
+ int irq;

ks_pcie = devm_kzalloc(dev, sizeof(*ks_pcie), GFP_KERNEL);
if (!ks_pcie)
@@ -913,6 +805,20 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
devm_release_mem_region(dev, res->start, resource_size(res));

ks_pcie->np = dev->of_node;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "missing IRQ resource: %d\n", irq);
+ return irq;
+ }
+
+ ret = devm_request_irq(dev, irq, pcie_err_irq_handler, IRQF_SHARED,
+ "ks-pcie-error-irq", ks_pcie);
+ if (ret < 0) {
+ dev_err(dev, "failed to request error IRQ %d\n", irq);
+ return ret;
+ }
+
platform_set_drvdata(pdev, ks_pcie);
ks_pcie->clk = devm_clk_get(dev, "pcie");
if (IS_ERR(ks_pcie->clk)) {
@@ -929,6 +835,8 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
if (ret < 0)
goto fail_clk;

+ ks_dw_pcie_enable_error_irq(ks_pcie);
+
return 0;
fail_clk:
clk_disable_unprepare(ks_pcie->clk);
--
2.17.1


2018-09-21 10:30:05

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 14/40] PCI: keystone: Use platform_get_resource_byname to get memory resources

Use platform_get_resource_byname() instead of platform_get_resource() which
uses index to get memory resources. While at that get the memory resource
defined specifically for configuration space instead of deriving the
configuration space address from dbics address space. Since pci-keystone
driver has never worked out of the box in mainline kernel, dt backward
compatibility is ignored.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 505e13b1197d..fe522b8c981f 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -49,7 +49,6 @@
#define OB_SIZE 0x030
#define CFG_PCIM_WIN_SZ_IDX 3
#define CFG_PCIM_WIN_CNT 32
-#define SPACE0_REMOTE_CFG_OFFSET 0x1000
#define OB_OFFSET_INDEX(n) (0x200 + (8 * n))
#define OB_OFFSET_HI(n) (0x204 + (8 * n))

@@ -677,21 +676,19 @@ static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie,
struct resource *res;
int ret;

- /* Index 0 is the config reg. space address */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbics");
pci->dbi_base = devm_pci_remap_cfg_resource(dev, res);
if (IS_ERR(pci->dbi_base))
return PTR_ERR(pci->dbi_base);

- /*
- * We set these same and is used in pcie rd/wr_other_conf
- * functions
- */
- pp->va_cfg0_base = pci->dbi_base + SPACE0_REMOTE_CFG_OFFSET;
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
+ pp->va_cfg0_base = devm_pci_remap_cfg_resource(dev, res);
+ if (IS_ERR(pp->va_cfg0_base))
+ return PTR_ERR(pp->va_cfg0_base);
+
pp->va_cfg1_base = pp->va_cfg0_base;

- /* Index 1 is the application reg. space address */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "app");
ks_pcie->va_app_base = devm_ioremap_resource(dev, res);
if (IS_ERR(ks_pcie->va_app_base))
return PTR_ERR(ks_pcie->va_app_base);
--
2.17.1


2018-09-21 10:30:57

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 17/40] PCI: keystone: Cleanup configuration space access

Cleanup configuration space access by removing ks_pcie_cfg_setup
which has an unncessary check of "if (bus == 0)" which will never be the
case of *_other_conf() and adding macros for configuring the CFG_SETUP
register required for accessing the configuration space of the device.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 70 +++++++----------------
1 file changed, 20 insertions(+), 50 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index f230344e1f4e..3ead1162235f 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -45,7 +45,13 @@

/* Application registers */
#define CMD_STATUS 0x004
+
#define CFG_SETUP 0x008
+#define CFG_BUS(x) (((x) & 0xff) << 16)
+#define CFG_DEVICE(x) (((x) & 0x1f) << 8)
+#define CFG_FUNC(x) ((x) & 0x7)
+#define CFG_TYPE1 BIT(24)
+
#define OB_SIZE 0x030
#define CFG_PCIM_WIN_SZ_IDX 3
#define CFG_PCIM_WIN_CNT 32
@@ -261,60 +267,21 @@ static void ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
ks_pcie_app_writel(ks_pcie, CMD_STATUS, OB_XLAT_EN_VAL | val);
}

-/**
- * ks_pcie_cfg_setup() - Set up configuration space address for a device
- *
- * @ks_pcie: ptr to keystone_pcie structure
- * @bus: Bus number the device is residing on
- * @devfn: device, function number info
- *
- * Forms and returns the address of configuration space mapped in PCIESS
- * address space 0. Also configures CFG_SETUP for remote configuration space
- * access.
- *
- * The address space has two regions to access configuration - local and remote.
- * We access local region for bus 0 (as RC is attached on bus 0) and remote
- * region for others with TYPE 1 access when bus > 1. As for device on bus = 1,
- * we will do TYPE 0 access as it will be on our secondary bus (logical).
- * CFG_SETUP is needed only for remote configuration access.
- */
-static void __iomem *ks_pcie_cfg_setup(struct keystone_pcie *ks_pcie, u8 bus,
- unsigned int devfn)
-{
- u8 device = PCI_SLOT(devfn), function = PCI_FUNC(devfn);
- struct dw_pcie *pci = ks_pcie->pci;
- struct pcie_port *pp = &pci->pp;
- u32 regval;
-
- if (bus == 0)
- return pci->dbi_base;
-
- regval = (bus << 16) | (device << 8) | function;
-
- /*
- * Since Bus#1 will be a virtual bus, we need to have TYPE0
- * access only.
- * TYPE 1
- */
- if (bus != 1)
- regval |= BIT(24);
-
- ks_pcie_app_writel(ks_pcie, CFG_SETUP, regval);
- return pp->va_cfg0_base;
-}
-
static int ks_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size,
u32 *val)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
- u8 bus_num = bus->number;
- void __iomem *addr;
+ u32 reg;

- addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
+ reg = CFG_BUS(bus->number) | CFG_DEVICE(PCI_SLOT(devfn)) |
+ CFG_FUNC(PCI_FUNC(devfn));
+ if (bus->parent->number != pp->root_bus_nr)
+ reg |= CFG_TYPE1;
+ ks_pcie_app_writel(ks_pcie, CFG_SETUP, reg);

- return dw_pcie_read(addr + where, size, val);
+ return dw_pcie_read(pp->va_cfg0_base + where, size, val);
}

static int ks_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
@@ -323,12 +290,15 @@ static int ks_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
- u8 bus_num = bus->number;
- void __iomem *addr;
+ u32 reg;

- addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
+ reg = CFG_BUS(bus->number) | CFG_DEVICE(PCI_SLOT(devfn)) |
+ CFG_FUNC(PCI_FUNC(devfn));
+ if (bus->parent->number != pp->root_bus_nr)
+ reg |= CFG_TYPE1;
+ ks_pcie_app_writel(ks_pcie, CFG_SETUP, reg);

- return dw_pcie_write(addr + where, size, val);
+ return dw_pcie_write(pp->va_cfg0_base + where, size, val);
}

/**
--
2.17.1


2018-09-21 10:31:00

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [RFC PATCH 18/40] PCI: keystone: Get number of OB windows from DT and cleanup MEM space configuration

Instead of having a fixed outbound window count, get the number of
outbound windows from device tree. Also cleanup memory space configuration
here by adding macros for constants.

While at that also use BIT() macro for OB_XLAT_EN_VAL.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/pci/controller/dwc/pci-keystone.c | 86 +++++++++++++----------
1 file changed, 49 insertions(+), 37 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 3ead1162235f..d5304c4a1eb5 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -41,7 +41,7 @@
#define LTSSM_STATE_MASK 0x1f
#define LTSSM_STATE_L0 0x11
#define DBI_CS2_EN_VAL 0x20
-#define OB_XLAT_EN_VAL 2
+#define OB_XLAT_EN_VAL BIT(1)

/* Application registers */
#define CMD_STATUS 0x004
@@ -53,10 +53,7 @@
#define CFG_TYPE1 BIT(24)

#define OB_SIZE 0x030
-#define CFG_PCIM_WIN_SZ_IDX 3
-#define CFG_PCIM_WIN_CNT 32
-#define OB_OFFSET_INDEX(n) (0x200 + (8 * n))
-#define OB_OFFSET_HI(n) (0x204 + (8 * n))
+#define OB_WIN_SIZE 8 /* 8MB */

/* IRQ register defines */
#define IRQ_EOI 0x050
@@ -85,6 +82,11 @@
#define ERR_IRQ_ENABLE_SET 0x1c8
#define ERR_IRQ_ENABLE_CLR 0x1cc

+#define OB_OFFSET_INDEX(n) (0x200 + (8 * (n)))
+#define OB_ENABLEN BIT(0)
+
+#define OB_OFFSET_HI(n) (0x204 + (8 * (n)))
+
/* Config space registers */
#define DEBUG0 0x728

@@ -102,6 +104,7 @@ static void ks_pcie_stop_link(struct dw_pcie *pci);
struct keystone_pcie {
struct dw_pcie *pci;
int num_lanes;
+ u32 num_viewport;
struct phy **phy;
struct device_link **link;
int msi_host_irq;
@@ -236,37 +239,6 @@ static void ks_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie)
} while (val & DBI_CS2_EN_VAL);
}

-static void ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
-{
- struct dw_pcie *pci = ks_pcie->pci;
- struct pcie_port *pp = &pci->pp;
- u32 start = pp->mem->start, end = pp->mem->end;
- int i, tr_size;
- u32 val;
-
- /* Disable BARs for inbound access */
- ks_pcie_set_dbi_mode(ks_pcie);
- dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0);
- dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0);
- ks_pcie_clear_dbi_mode(ks_pcie);
-
- /* Set outbound translation size per window division */
- ks_pcie_app_writel(ks_pcie, OB_SIZE, CFG_PCIM_WIN_SZ_IDX & 0x7);
-
- tr_size = (1 << (CFG_PCIM_WIN_SZ_IDX & 0x7)) * SZ_1M;
-
- /* Using Direct 1:1 mapping of RC <-> PCI memory space */
- for (i = 0; (i < CFG_PCIM_WIN_CNT) && (start < end); i++) {
- ks_pcie_app_writel(ks_pcie, OB_OFFSET_INDEX(i), start | 1);
- ks_pcie_app_writel(ks_pcie, OB_OFFSET_HI(i), 0);
- start += tr_size;
- }
-
- /* Enable OB translation */
- val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
- ks_pcie_app_writel(ks_pcie, CMD_STATUS, OB_XLAT_EN_VAL | val);
-}
-
static int ks_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size,
u32 *val)
@@ -562,6 +534,33 @@ static int ks_pcie_fault(unsigned long addr, unsigned int fsr,
return 0;
}

+static void ks_pcie_setup_mem_space(struct keystone_pcie *ks_pcie)
+{
+ u32 val;
+ u32 num_viewport = ks_pcie->num_viewport;
+ struct dw_pcie *pci = ks_pcie->pci;
+ struct pcie_port *pp = &pci->pp;
+ u64 start = pp->mem->start;
+ u64 end = pp->mem->end;
+ int i;
+
+ val = ilog2(OB_WIN_SIZE);
+ ks_pcie_app_writel(ks_pcie, OB_SIZE, val);
+
+ /* Using Direct 1:1 mapping of RC <-> PCI memory space */
+ for (i = 0; i < num_viewport && (start < end); i++) {
+ ks_pcie_app_writel(ks_pcie, OB_OFFSET_INDEX(i),
+ lower_32_bits(start) | OB_ENABLEN);
+ ks_pcie_app_writel(ks_pcie, OB_OFFSET_HI(i),
+ upper_32_bits(start));
+ start += OB_WIN_SIZE;
+ }
+
+ val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
+ val |= OB_XLAT_EN_VAL;
+ ks_pcie_app_writel(ks_pcie, CMD_STATUS, val);
+}
+
static int __init ks_pcie_init_id(struct keystone_pcie *ks_pcie)
{
int ret;
@@ -601,7 +600,12 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)

dw_pcie_setup_rc(pp);

- ks_pcie_setup_rc_app_regs(ks_pcie);
+ ks_pcie_set_dbi_mode(ks_pcie);
+ dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0);
+ dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0);
+ ks_pcie_clear_dbi_mode(ks_pcie);
+
+ ks_pcie_setup_mem_space(ks_pcie);
writew(PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8),
pci->dbi_base + PCI_IO_BASE);

@@ -770,6 +774,7 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
struct dw_pcie *pci;
struct keystone_pcie *ks_pcie;
struct device_link **link;
+ u32 num_viewport;
struct phy **phy;
u32 num_lanes;
char name[10];
@@ -788,6 +793,12 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
pci->dev = dev;
pci->ops = &ks_pcie_dw_pcie_ops;

+ ret = of_property_read_u32(np, "num-viewport", &num_viewport);
+ if (ret < 0) {
+ dev_err(dev, "unable to read *num-viewport* property\n");
+ return ret;
+ }
+
ret = of_property_read_u32(np, "num-lanes", &num_lanes);
if (ret)
num_lanes = 1;
@@ -831,6 +842,7 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
ks_pcie->link = link;
ks_pcie->np = np;
ks_pcie->num_lanes = num_lanes;
+ ks_pcie->num_viewport = num_viewport;
ks_pcie->phy = phy;

irq = platform_get_irq(pdev, 0);
--
2.17.1


2018-09-21 19:43:43

by Nishanth Menon

[permalink] [raw]
Subject: Re: [RFC PATCH 36/40] arm64: dts: k3-am6: Add "socionext,synquacer-pre-its" property to gic_its

On 10:21-20180921, Kishon Vijay Abraham I wrote:
> GIC_ITS used in AM65x platform has the same configuration as that of
> GIC_ITS used in Socionext SoCs. Add "socionext,synquacer-pre-its"
> property to get PCI MSI working.
>
> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> ---
> arch/arm64/boot/dts/ti/k3-am65-main.dtsi | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
> index adcd6341e40c..2df4acb198bd 100644
> --- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
> +++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
> @@ -24,6 +24,7 @@
> gic_its: gic-its@18200000 {
> compatible = "arm,gic-v3-its";
> reg = <0x00 0x01820000 0x00 0x10000>;
> + socionext,synquacer-pre-its = <0x1000000 0x400000>;
> msi-controller;
> #msi-cells = <1>;
> };
> --
> 2.17.1
>


Please post the DTS series separately. This specific patch is a GIC ITS
patch, and does'nt need to depend on rest of the PCI series. Also looks
like you missed the v4.20-rc1 bandwagon.


--
Regards,
Nishanth Menon

2018-10-12 13:48:11

by Lorenzo Pieralisi

[permalink] [raw]
Subject: Re: [RFC PATCH 00/40] Cleanup pci-keystone.c and Add AM654 PCIe Support

On Fri, Sep 21, 2018 at 03:51:15PM +0530, Kishon Vijay Abraham I wrote:
> Add PCIe RC support for TI's AM654 SoC. The PCIe controller in AM654
> uses Synopsys core revision 4.90a and uses the same TI wrapper as used
> in keystone2 with certain modification. Hence AM654 will use the same
> pci wrapper driver pci-keystone.c
>
> The initial support for AM654 was merged recently [1]
>
> [1] -> https://lore.kernel.org/lkml/[email protected]/
>
> Patch series includes the following
> *) Merge pci-keystone-dw.c into pci-keystone.c so that we have single
> file for PCIe keystone driver.
> *) Cleanup the pci-keystone driver. In certain cases the DT binding is
> also modified since PCIe in keystone has never worked in mainline
> due to lack of PHY support.
> *) Included the PHY driver here for completeness (though the driver
> might go via linux-phy tree)
> *) Included the device tree patches here. Once this series is reviewed
> it'll be sent to be merged via Tony's tree.
> *) Patch to fix ATU identification for designware version >= 4.80 in
> designware core is also included here.
>
> TODO:
> *) Add Endpoint Support for AM654
> *) Send a patch to fix the MRRS after the correct value is identified.
>
> Once this series is reviewed I'll split the series and send to
> corresponding subsytem Maintainers after removing RFC in subject.

Hi Kishon,

I started reviewing the series, I noticed that some patches are
clean-ups that I would like to queue to cut the delta so that you
can rebase on top of them, do you have time to post the clean-up
patches (no functional changes) stand-alone so that I can queue
them up please ?

I think you should drop the RFC tag from this series.

Thanks,
Lorenzo

2021-07-03 21:07:19

by Krzysztof Wilczyński

[permalink] [raw]
Subject: Re: [RFC PATCH 08/40] PCI: keystone: Cleanup MSI/legacy interrupt configuration and handling

Hi Kishon,

> Now that all PCI keystone functionality has been moved to pci-keystone.c,
> cleanup MSI/legacy interrupt configuration and handling.
> *) Cleanup macros
> *) Remove unnecessary structure variables (required when 2 files are
> used)
> *) Remove ks_dw_pcie_legacy_irq_chip and use dummy_irq_chip
> *) Move request_irq of error irq from ks_add_pcie_port to ks_pcie_probe
> as error_irq is common to both host mode and device mode
[...]

While looking at some small clean-ups for Bjorn, I stumbled upon this
series, and it seems a lot of your work here cover what Bjorn wanted to
do, thus I need to ask - do you recall, and I appreciate it's been
a while (three years actually), what happened and/or if you ever had the
time to work on this series?

Would it be possible to resurrect this? Do you need any help?

Thank you in advance!

Krzysztof

2021-07-05 08:25:37

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: Re: [RFC PATCH 08/40] PCI: keystone: Cleanup MSI/legacy interrupt configuration and handling

Hi Krzysztof,

On 04/07/21 2:31 am, Krzysztof Wilczyński wrote:
> Hi Kishon,
>
>> Now that all PCI keystone functionality has been moved to pci-keystone.c,
>> cleanup MSI/legacy interrupt configuration and handling.
>> *) Cleanup macros
>> *) Remove unnecessary structure variables (required when 2 files are
>> used)
>> *) Remove ks_dw_pcie_legacy_irq_chip and use dummy_irq_chip
>> *) Move request_irq of error irq from ks_add_pcie_port to ks_pcie_probe
>> as error_irq is common to both host mode and device mode
> [...]
>
> While looking at some small clean-ups for Bjorn, I stumbled upon this
> series, and it seems a lot of your work here cover what Bjorn wanted to
> do, thus I need to ask - do you recall, and I appreciate it's been
> a while (three years actually), what happened and/or if you ever had the
> time to work on this series?
>
> Would it be possible to resurrect this? Do you need any help?

A lot of patches in this series should already be merged (after
splitting into smaller ones)
http://patchwork.ozlabs.org/project/linux-pci/list/?series=71185

https://patchwork.kernel.org/project/linux-arm-kernel/cover/[email protected]/

The following series is still pending and is in my TODO list
https://lore.kernel.org/r/[email protected]

Are there any other clean-ups you are looking into?

Thanks and Regards
Kishon

2021-07-06 20:38:28

by Krzysztof Wilczyński

[permalink] [raw]
Subject: Re: [RFC PATCH 08/40] PCI: keystone: Cleanup MSI/legacy interrupt configuration and handling

Hi Kishon,

[...]
> > Would it be possible to resurrect this? Do you need any help?
>
> A lot of patches in this series should already be merged (after
> splitting into smaller ones)
> http://patchwork.ozlabs.org/project/linux-pci/list/?series=71185
>
> https://patchwork.kernel.org/project/linux-arm-kernel/cover/[email protected]/

Ah! Nice!

[...]
> Are there any other clean-ups you are looking into?

Bjorn was looking recently at struct keystone_pcie and suggested that
perhaps things such as for example the legacy_host_irqs member could be
refactored - in this particular case it seems to only store a single
item in the array, etc.

And this series of patches I found is refactoring a lot of the elements
of the driver and thus the struct keystone_pcie too in due process.

I suppose, it would be just better to wait for you to complete all the
work you have planned? What do you think?

Krzysztof