mirror of
https://abf.rosa.ru/djam/kernel-5.15.git
synced 2025-02-23 18:42:55 +00:00
1229 lines
51 KiB
Diff
1229 lines
51 KiB
Diff
![]() |
From 72b2f9de7609df9b7e7a60e4a9bfca45463cfac5 Mon Sep 17 00:00:00 2001
|
||
|
From: Alexey Sheplyakov <asheplyakov@altlinux.org>
|
||
|
Date: Fri, 20 Mar 2020 13:57:57 +0400
|
||
|
Subject: [PATCH 616/625] Baikal-M: PCIe driver from SDK-M 4.3
|
||
|
|
||
|
Improvements:
|
||
|
|
||
|
* Adjusted the driver so it can built as a module. Hardware
|
||
|
initialization takes about 60 seconds on MBM1.0 board, and
|
||
|
the screen is blank during that time. When built as a module
|
||
|
probing runs concurrently with other boot activities (unless
|
||
|
booting from a PCIe device)
|
||
|
|
||
|
* Avoid loading the driver on boards with incompatible firmware
|
||
|
(from SDK-M 4.4) since it causes the kernel panic during probe:
|
||
|
|
||
|
[ 9.317236] SError Interrupt on CPU4, code 0xbf000002 -- SError
|
||
|
[ 9.317239] CPU: 4 PID: 899 Comm: systemd-udevd Not tainted 5.4.80-std-def-alt1 #1
|
||
|
[ 9.317241] Hardware name: Baikal Electronics Baikal-M mitx board (DT)
|
||
|
[ 9.317243] pstate: 20400085 (nzCv daIf +PAN -UAO)
|
||
|
[ 9.317246] pc : regmap_mmio_read32le+0x28/0x60
|
||
|
[ 9.317247] lr : regmap_mmio_read+0x48/0x70
|
||
|
[ 9.317249] sp : ffff800011ca3750
|
||
|
[ 9.317251] x29: ffff800011ca3750 x28: ffff800008e09258
|
||
|
[ 9.317254] x27: 0000000000000028 x26: ffff800008e07040
|
||
|
[ 9.317257] x25: ffff00097170c1c0 x24: ffff800008e08420
|
||
|
[ 9.317260] x23: ffff800011ca3874 x22: 00000000000500e8
|
||
|
[ 9.317262] x21: ffff800011ca3874 x20: ffff0009727d5980
|
||
|
[ 9.317265] x19: 00000000000500e8 x18: 0000000000000001
|
||
|
[ 9.317268] x17: 0000000000000000 x16: ffff800011ca37f4
|
||
|
[ 9.317270] x15: ffff00097170c6d8 x14: ffffffffffffffff
|
||
|
[ 9.317273] x13: ffff000974e747c0 x12: 0000000000000018
|
||
|
[ 9.317276] x11: 0101010101010101 x10: 7f7f7f7f7f7f7f7f
|
||
|
[ 9.317279] x9 : fefefefeff736472 x8 : 7f7f7f7f7f7f7f7f
|
||
|
[ 9.317281] x7 : 64712c2f6468626f x6 : ffff0009727d568c
|
||
|
[ 9.317284] x5 : ffff000972eee168 x4 : 0000000000000000
|
||
|
[ 9.317286] x3 : ffff800010813c38 x2 : ffff800010814100
|
||
|
[ 9.317289] x1 : 00000000000500e8 x0 : 0000000000000000
|
||
|
[ 9.317292] Kernel panic - not syncing: Asynchronous SError Interrupt
|
||
|
[ 9.317294] CPU: 4 PID: 899 Comm: systemd-udevd Not tainted 5.4.80-std-def-alt1 #1
|
||
|
[ 9.317296] Hardware name: Baikal Electronics Baikal-M mitx board (DT)
|
||
|
[ 9.317298] Call trace:
|
||
|
[ 9.317299] dump_backtrace+0x0/0x160
|
||
|
[ 9.317301] show_stack+0x24/0x30
|
||
|
[ 9.317302] dump_stack+0xb4/0x114
|
||
|
[ 9.317304] panic+0x150/0x368
|
||
|
[ 9.317306] nmi_panic+0x94/0x98
|
||
|
[ 9.317307] arm64_serror_panic+0x84/0x90
|
||
|
[ 9.317309] do_serror+0x11c/0x120
|
||
|
[ 9.317310] el1_error+0xbc/0x160
|
||
|
[ 9.317312] regmap_mmio_read32le+0x28/0x60
|
||
|
[ 9.317314] regmap_mmio_read+0x48/0x70
|
||
|
[ 9.317315] _regmap_bus_reg_read+0x38/0x48
|
||
|
[ 9.317317] _regmap_read+0x6c/0x168
|
||
|
[ 9.317319] regmap_read+0x50/0x78
|
||
|
[ 9.317320] baikal_pcie_hw_init_m+0xe4/0x170 [pcie_baikal]
|
||
|
[ 9.317322] baikal_pcie_probe+0x294/0x530 [pcie_baikal]
|
||
|
[ 9.317324] platform_drv_probe+0x58/0xa8
|
||
|
[ 9.317325] really_probe+0xe0/0x330
|
||
|
[ 9.317327] driver_probe_device+0x5c/0xf0
|
||
|
[ 9.317329] device_driver_attach+0x74/0x80
|
||
|
[ 9.317330] __driver_attach+0x64/0xe0
|
||
|
[ 9.317332] bus_for_each_dev+0x80/0xd0
|
||
|
[ 9.317334] driver_attach+0x30/0x40
|
||
|
[ 9.317335] bus_add_driver+0x154/0x1e8
|
||
|
[ 9.317337] driver_register+0x64/0x110
|
||
|
[ 9.317338] __platform_driver_register+0x54/0x60
|
||
|
[ 9.317340] baikal_pcie_driver_init+0x24/0x1000 [pcie_baikal]
|
||
|
[ 9.317342] do_one_initcall+0x50/0x24c
|
||
|
[ 9.317343] do_init_module+0x5c/0x248
|
||
|
[ 9.317345] load_module+0x1e08/0x2258
|
||
|
[ 9.317347] __do_sys_finit_module+0xd0/0xe8
|
||
|
[ 9.317348] __arm64_sys_finit_module+0x28/0x38
|
||
|
[ 9.317350] el0_svc_common.constprop.0+0x74/0x168
|
||
|
[ 9.317352] el0_svc_handler+0x34/0xa0
|
||
|
[ 9.317353] el0_svc+0x8/0x260
|
||
|
[ 9.324036] SMP: stopping secondary CPUs
|
||
|
[ 9.324038] Kernel Offset: disabled
|
||
|
[ 9.324039] CPU features: 0x0002,20006008
|
||
|
[ 9.324041] Memory Limit: none
|
||
|
|
||
|
Note: detection of new firmware is not 100% reliable.
|
||
|
---
|
||
|
drivers/pci/controller/Kconfig | 12 +
|
||
|
drivers/pci/controller/dwc/Makefile | 1 +
|
||
|
drivers/pci/controller/dwc/pcie-baikal.c | 722 +++++++++++++++++++++++
|
||
|
drivers/pci/controller/dwc/pcie-baikal.h | 217 +++++++
|
||
|
include/linux/mfd/baikal/lcru-pcie.h | 140 +++++
|
||
|
5 files changed, 1092 insertions(+)
|
||
|
create mode 100644 drivers/pci/controller/dwc/pcie-baikal.c
|
||
|
create mode 100644 drivers/pci/controller/dwc/pcie-baikal.h
|
||
|
create mode 100644 include/linux/mfd/baikal/lcru-pcie.h
|
||
|
|
||
|
diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
|
||
|
index 64e2f5e379aa..b8a5eb633259 100644
|
||
|
--- a/drivers/pci/controller/Kconfig
|
||
|
+++ b/drivers/pci/controller/Kconfig
|
||
|
@@ -281,6 +281,18 @@ config PCIE_BRCMSTB
|
||
|
Say Y here to enable PCIe host controller support for
|
||
|
Broadcom STB based SoCs, like the Raspberry Pi 4.
|
||
|
|
||
|
+config PCI_BAIKAL
|
||
|
+ tristate "Baikal SoC PCIe controller"
|
||
|
+ default m if ARCH_BAIKAL
|
||
|
+ depends on ARCH_BAIKAL
|
||
|
+ depends on OF && HAS_IOMEM
|
||
|
+ depends on PCI_MSI_IRQ_DOMAIN
|
||
|
+ select PCIE_DW
|
||
|
+ help
|
||
|
+ Enables support for the PCIe controller in the Baikal SoC. There
|
||
|
+ are three instances of PCIe controller in Baikal-M. Two of the controllers
|
||
|
+ support PCIe 3.0 x4 and the remaining one supports PCIe 3.0 x8.
|
||
|
+
|
||
|
config PCI_HYPERV_INTERFACE
|
||
|
tristate "Hyper-V PCI Interface"
|
||
|
depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
|
||
|
diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
|
||
|
index a751553fa0db..85e6ad1954e5 100644
|
||
|
--- a/drivers/pci/controller/dwc/Makefile
|
||
|
+++ b/drivers/pci/controller/dwc/Makefile
|
||
|
@@ -20,6 +20,7 @@ obj-$(CONFIG_PCI_MESON) += pci-meson.o
|
||
|
obj-$(CONFIG_PCIE_TEGRA194) += pcie-tegra194.o
|
||
|
obj-$(CONFIG_PCIE_UNIPHIER) += pcie-uniphier.o
|
||
|
obj-$(CONFIG_PCIE_UNIPHIER_EP) += pcie-uniphier-ep.o
|
||
|
+obj-$(CONFIG_PCI_BAIKAL) += pcie-baikal.o
|
||
|
|
||
|
# The following drivers are for devices that use the generic ACPI
|
||
|
# pci_root.c driver but don't support standard ECAM config access.
|
||
|
diff --git a/drivers/pci/controller/dwc/pcie-baikal.c b/drivers/pci/controller/dwc/pcie-baikal.c
|
||
|
new file mode 100644
|
||
|
index 000000000000..1eb5f0e780c4
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/pci/controller/dwc/pcie-baikal.c
|
||
|
@@ -0,0 +1,722 @@
|
||
|
+/*
|
||
|
+ * pcie-baikal - PCIe controller driver for Baikal SoCs
|
||
|
+ *
|
||
|
+ * Copyright (C) 2019 Baikal Electronics JSC
|
||
|
+ * Author: Pavel Parkhomenko <Pavel.Parkhomenko@baikalelectronics.ru>
|
||
|
+ *
|
||
|
+ * Parts of this file were based on sources as follows:
|
||
|
+ * Copyright (C) 2013-2014 Texas Instruments Incorporated - http://www.ti.com
|
||
|
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
|
||
|
+ *
|
||
|
+ * This program is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License version 2 as
|
||
|
+ * published by the Free Software Foundation.
|
||
|
+ */
|
||
|
+
|
||
|
+#define DEBUG 1
|
||
|
+
|
||
|
+#include <linux/err.h>
|
||
|
+#include <linux/interrupt.h>
|
||
|
+#include <linux/irq.h>
|
||
|
+#include <linux/irqchip/arm-gic-v3.h>
|
||
|
+#include <linux/irqdomain.h>
|
||
|
+#include <linux/init.h>
|
||
|
+#include <linux/kernel.h>
|
||
|
+#include <linux/module.h>
|
||
|
+#include <linux/mfd/syscon.h>
|
||
|
+#include <linux/mfd/baikal/lcru-pcie.h>
|
||
|
+#include <linux/msi.h>
|
||
|
+#include <linux/of_address.h>
|
||
|
+#include <linux/of_gpio.h>
|
||
|
+#include <linux/of_device.h>
|
||
|
+#include <linux/pci.h>
|
||
|
+#include <linux/phy/phy.h>
|
||
|
+#include <linux/platform_device.h>
|
||
|
+#include <linux/pm_runtime.h>
|
||
|
+#include <linux/regmap.h>
|
||
|
+#include <linux/resource.h>
|
||
|
+#include <linux/types.h>
|
||
|
+#include <linux/moduleparam.h>
|
||
|
+
|
||
|
+#include "pcie-designware.h"
|
||
|
+#include "pcie-baikal.h"
|
||
|
+
|
||
|
+
|
||
|
+#define PCIE_MSI_ADDR_LO 0x820
|
||
|
+#define PCIE_MSI_ADDR_HI 0x824
|
||
|
+
|
||
|
+
|
||
|
+struct baikal_pcie {
|
||
|
+ struct dw_pcie *pci;
|
||
|
+ int bus_nr;
|
||
|
+ struct regmap *lcru;
|
||
|
+ struct gpio_desc *reset_gpio;
|
||
|
+ char reset_name[32];
|
||
|
+};
|
||
|
+
|
||
|
+#define to_baikal_pcie(x) dev_get_drvdata((x)->dev)
|
||
|
+#define LINK_RETRAIN_TIMEOUT HZ
|
||
|
+
|
||
|
+#define PORT_LINK_FAST_LINK_MODE (1 << 7) /* Fast Link Mode. */
|
||
|
+
|
||
|
+#define PCIE_PHY_RETRIES 1000000
|
||
|
+#define PHY_ALL_LANES 0xF
|
||
|
+#define PHY_LANE0 0x1
|
||
|
+
|
||
|
+/* Baikal-specific registers. */
|
||
|
+#define PCIE_BK_MGMT_SEL_LANE (0xd04) /* Select lane. */
|
||
|
+#define PCIE_BK_MGMT_CTRL (0xd08) /* Control management register. */
|
||
|
+#define PCIE_BK_MGMT_WRITE_DATA (0xd0c) /* Data write register. */
|
||
|
+#define PCIE_BK_MGMT_READ_DATA (0xd10) /* Data read register. */
|
||
|
+
|
||
|
+#define PCIE_MISC_CONTROL_1_OFF (0x8bc) /* to open RO DBI register. */
|
||
|
+#define DBI_RO_RW_EN (1 << 0)
|
||
|
+
|
||
|
+#define PCIE_COHERENCE_CONTROL_3_OFF (0x8e8) /* to set cache coherence register. */
|
||
|
+
|
||
|
+/* PCIE_BK_MGMT_CTRL */
|
||
|
+#define BK_MGMT_CTRL_ADDR_MASK (0xFFFFF) /* bits [20:0] */
|
||
|
+#define BK_MGMT_CTRL_READ (0 << 29)
|
||
|
+#define BK_MGMT_CTRL_WRITE (1 << 29)
|
||
|
+#define BK_MGMT_CTRL_DONE (1 << 30)
|
||
|
+#define BK_MGMT_CTRL_BUSY (1 << 31)
|
||
|
+
|
||
|
+#define PCIE_LINK_CAPABILITIES_REG (0x7c) /* Link Capabilities Register. */
|
||
|
+#define PCIE_ROOT_CONTROL_ROOT_CAPABILITIES_REG (0x8c) /* Root Control and Capabilities Register. */
|
||
|
+
|
||
|
+#define PCIE_LINK_CONTROL_LINK_STATUS_REG (0x80) /* Link Control and Status Register. */
|
||
|
+/* LINK_CONTROL_LINK_STATUS_REG */
|
||
|
+#define PCIE_CAP_LINK_SPEED_SHIFT 16
|
||
|
+#define PCIE_CAP_LINK_SPEED_MASK 0xF0000
|
||
|
+#define PCIE_CAP_LINK_SPEED_GEN1 0x1
|
||
|
+#define PCIE_CAP_LINK_SPEED_GEN2 0x2
|
||
|
+#define PCIE_CAP_LINK_SPEED_GEN3 0x3
|
||
|
+#define PCIE_STA_LINK_TRAINING 0x8000000
|
||
|
+#define PCIE_STA_LINK_WIDTH_MASK 0x3f00000
|
||
|
+#define PCIE_STA_LINK_WIDTH_SHIFT (20)
|
||
|
+
|
||
|
+#define PCIE_LINK_CONTROL2_LINK_STATUS2_REG (0xa0) /* Link Control 2 and Status 2 Register. */
|
||
|
+/* PCIE_LINK_CONTROL2_LINK_STATUS2 */
|
||
|
+#define PCIE_LINK_CONTROL2_GEN_MASK (0xF)
|
||
|
+#define PCIE_LINK_CONTROL2_GEN1 (1)
|
||
|
+#define PCIE_LINK_CONTROL2_GEN2 (2)
|
||
|
+#define PCIE_LINK_CONTROL2_GEN3 (3)
|
||
|
+
|
||
|
+static inline int dw_pcie_link_is_training(struct dw_pcie *pci)
|
||
|
+{
|
||
|
+ int reg = dw_pcie_readl_dbi(pci, PCIE_LINK_CONTROL_LINK_STATUS_REG);
|
||
|
+ return reg & PCIE_STA_LINK_TRAINING;
|
||
|
+}
|
||
|
+
|
||
|
+static void dw_wait_pcie_link_training_done(struct dw_pcie *pci)
|
||
|
+{
|
||
|
+ unsigned long start_jiffies = jiffies;
|
||
|
+ while (dw_pcie_link_is_training(pci)) {
|
||
|
+ if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) {
|
||
|
+ pr_err("%s: link retrained for too long, timeout occured\n", __func__);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ udelay(100);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static int dw_report_link_performance(struct dw_pcie *pci)
|
||
|
+{
|
||
|
+ int reg = dw_pcie_readl_dbi(pci, PCIE_LINK_CONTROL_LINK_STATUS_REG);
|
||
|
+ int speed = (reg & PCIE_CAP_LINK_SPEED_MASK) >> PCIE_CAP_LINK_SPEED_SHIFT;
|
||
|
+ int width = (reg & PCIE_STA_LINK_WIDTH_MASK) >> PCIE_STA_LINK_WIDTH_SHIFT;
|
||
|
+ dev_info(pci->dev, "Link Status is GEN%d, x%d\n", speed, width);
|
||
|
+ return speed;
|
||
|
+}
|
||
|
+
|
||
|
+static inline void dw_pcie_link_retrain(struct dw_pcie *pci, int target_speed)
|
||
|
+{
|
||
|
+ int reg;
|
||
|
+ unsigned long start_jiffies;
|
||
|
+
|
||
|
+ // In case link is already training wait for training to complete
|
||
|
+ dw_wait_pcie_link_training_done(pci);
|
||
|
+
|
||
|
+ // Set desired speed
|
||
|
+ reg = dw_pcie_readl_dbi(pci, PCIE_LINK_CONTROL2_LINK_STATUS2_REG);
|
||
|
+ reg &= ~PCIE_LINK_CONTROL2_GEN_MASK;
|
||
|
+ reg |= target_speed;
|
||
|
+ dw_pcie_writel_dbi(pci, PCIE_LINK_CONTROL2_LINK_STATUS2_REG, reg);
|
||
|
+
|
||
|
+ // Set Retrain Link bit
|
||
|
+ reg = dw_pcie_readl_dbi(pci, PCIE_LINK_CONTROL_LINK_STATUS_REG);
|
||
|
+ reg |= PCI_EXP_LNKCTL_RL;
|
||
|
+ dw_pcie_writel_dbi(pci, PCIE_LINK_CONTROL_LINK_STATUS_REG, reg);
|
||
|
+
|
||
|
+ /* Wait for link training begin */
|
||
|
+ start_jiffies = jiffies;
|
||
|
+ while (!dw_pcie_link_is_training(pci)) {
|
||
|
+ if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) {
|
||
|
+ pr_err("%s: link retrained for too long, timeout occured\n", __func__);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ udelay(100);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Wait for link training end */
|
||
|
+ dw_wait_pcie_link_training_done(pci);
|
||
|
+
|
||
|
+ if(dw_pcie_wait_for_link(pci) == 0) {
|
||
|
+ dw_report_link_performance(pci);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+static void baikal_pcie_link_speed_fixup(struct pci_dev *pdev)
|
||
|
+{
|
||
|
+ int reg, speed, width, target_speed;
|
||
|
+ struct pcie_port *pp = pdev->bus->sysdata;
|
||
|
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
||
|
+
|
||
|
+ reg = dw_pcie_readl_dbi(pci, PCIE_LINK_CAPABILITIES_REG);
|
||
|
+ speed = reg & PCI_EXP_LNKCAP_SLS;
|
||
|
+ if (speed > PCI_EXP_LNKCAP_SLS_2_5GB) {
|
||
|
+ pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, ®);
|
||
|
+ speed = reg & PCI_EXP_LNKCAP_SLS;
|
||
|
+ width = (reg & PCI_EXP_LNKCAP_MLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
|
||
|
+ dev_info(&pdev->dev, "Link Capability is GEN%d, x%d\n", speed, width);
|
||
|
+ if (speed > PCI_EXP_LNKCAP_SLS_2_5GB) {
|
||
|
+ target_speed = speed;
|
||
|
+ if (dw_report_link_performance(pci) < target_speed) {
|
||
|
+ dev_info(&pdev->dev, "retrain link to GEN%d\n", target_speed);
|
||
|
+ dw_pcie_link_retrain(pci, target_speed);
|
||
|
+ dw_report_link_performance(pci);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static void baikal_pcie_retrain_links(const struct pci_bus *bus)
|
||
|
+{
|
||
|
+ struct pci_dev *dev;
|
||
|
+ struct pci_bus *child;
|
||
|
+
|
||
|
+ list_for_each_entry(dev, &bus->devices, bus_list)
|
||
|
+ baikal_pcie_link_speed_fixup(dev);
|
||
|
+
|
||
|
+ list_for_each_entry(dev, &bus->devices, bus_list) {
|
||
|
+ child = dev->subordinate;
|
||
|
+ if (child)
|
||
|
+ baikal_pcie_retrain_links(child);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static int baikal_pcie_link_up(struct dw_pcie *pci)
|
||
|
+{
|
||
|
+ struct baikal_pcie *rc = to_baikal_pcie(pci);
|
||
|
+ uint32_t misc_reg;
|
||
|
+ uint32_t class_reg;
|
||
|
+ u32 lcru_reg, reg;
|
||
|
+
|
||
|
+ // Set class
|
||
|
+ lcru_reg = baikal_pcie_lcru_readl(rc->lcru, BAIKAL_LCRU_PCIE_GEN_CTL(rc->bus_nr));
|
||
|
+ baikal_pcie_lcru_writel(rc->lcru, BAIKAL_LCRU_PCIE_GEN_CTL(rc->bus_nr), lcru_reg & (~BAIKAL_PCIE_DBI2_MODE));
|
||
|
+
|
||
|
+ misc_reg = dw_pcie_readl_dbi(pci, PCIE_MISC_CONTROL_1_OFF);
|
||
|
+ misc_reg |= DBI_RO_RW_EN;
|
||
|
+
|
||
|
+ dw_pcie_writel_dbi(pci, PCIE_MISC_CONTROL_1_OFF, misc_reg);
|
||
|
+ class_reg = dw_pcie_readl_dbi(pci, PCI_CLASS_REVISION);
|
||
|
+
|
||
|
+ class_reg = (0x604 << 16) | (class_reg & 0xff); // class PCI_PCI_BRIDGE=0x604
|
||
|
+ dw_pcie_writel_dbi(pci, PCI_CLASS_REVISION, class_reg);
|
||
|
+
|
||
|
+ misc_reg &= ~DBI_RO_RW_EN;
|
||
|
+ dw_pcie_writel_dbi(pci, PCIE_MISC_CONTROL_1_OFF, misc_reg);
|
||
|
+ baikal_pcie_lcru_writel(rc->lcru, BAIKAL_LCRU_PCIE_GEN_CTL(rc->bus_nr), lcru_reg);
|
||
|
+ reg = baikal_pcie_lcru_readl(rc->lcru, BAIKAL_LCRU_PCIE_STATUS(rc->bus_nr));
|
||
|
+ return !!(reg & (BAIKAL_PCIE_RDLH_LINKUP | BAIKAL_PCIE_SMLH_LINKUP));
|
||
|
+}
|
||
|
+
|
||
|
+static void baikal_pcie_cease_link(struct baikal_pcie *rc)
|
||
|
+{
|
||
|
+ u32 reg;
|
||
|
+ reg = baikal_pcie_lcru_readl(rc->lcru, BAIKAL_LCRU_PCIE_GEN_CTL(rc->bus_nr));
|
||
|
+ reg &= ~BAIKAL_PCIE_LTSSM_ENABLE;
|
||
|
+ baikal_pcie_lcru_writel(rc->lcru, BAIKAL_LCRU_PCIE_GEN_CTL(rc->bus_nr), reg);
|
||
|
+}
|
||
|
+
|
||
|
+static int baikal_pcie_establish_link(struct baikal_pcie *rc)
|
||
|
+{
|
||
|
+ struct dw_pcie *pci = rc->pci;
|
||
|
+ struct device *dev = pci->dev;
|
||
|
+ u32 reg;
|
||
|
+ int ok;
|
||
|
+
|
||
|
+ if (baikal_pcie_link_up(pci)) {
|
||
|
+ dev_err(dev, "link is already up\n");
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ reg = baikal_pcie_lcru_readl(rc->lcru, BAIKAL_LCRU_PCIE_GEN_CTL(rc->bus_nr));
|
||
|
+ reg |= BAIKAL_PCIE_LTSSM_ENABLE;
|
||
|
+ baikal_pcie_lcru_writel(rc->lcru, BAIKAL_LCRU_PCIE_GEN_CTL(rc->bus_nr), reg);
|
||
|
+
|
||
|
+ ok = dw_pcie_wait_for_link(pci);
|
||
|
+ if(ok == 0) {
|
||
|
+ dw_report_link_performance(pci);
|
||
|
+ }
|
||
|
+ return ok;
|
||
|
+}
|
||
|
+
|
||
|
+static int baikal_pcie_host_init(struct pcie_port *pp)
|
||
|
+{
|
||
|
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
||
|
+ struct baikal_pcie *baikal_pcie = to_baikal_pcie(pci);
|
||
|
+
|
||
|
+ dw_pcie_setup_rc(pp);
|
||
|
+ baikal_pcie_establish_link(baikal_pcie);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int baikal_pcie_msi_host_init(struct pcie_port *pp)
|
||
|
+{
|
||
|
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
||
|
+ struct device *dev = pci->dev;
|
||
|
+ struct device_node *np = dev->of_node;
|
||
|
+ struct device_node *msi_node;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * The MSI domain is set by the generic of_msi_configure(). This
|
||
|
+ * .msi_host_init() function keeps us from doing the default MSI
|
||
|
+ * domain setup in dw_pcie_host_init() and also enforces the
|
||
|
+ * requirement that "msi-parent" exists.
|
||
|
+ */
|
||
|
+ msi_node = of_parse_phandle(np, "msi-parent", 0);
|
||
|
+ if (!msi_node) {
|
||
|
+ dev_warn(dev, "failed to find msi-parent\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static const struct dw_pcie_host_ops baikal_pcie_host_ops = {
|
||
|
+ .host_init = baikal_pcie_host_init,
|
||
|
+ .msi_host_init = baikal_pcie_msi_host_init,
|
||
|
+};
|
||
|
+
|
||
|
+static const struct dw_pcie_ops baikal_pcie_ops = {
|
||
|
+ .link_up = baikal_pcie_link_up,
|
||
|
+};
|
||
|
+
|
||
|
+static int baikal_pcie_get_msi(struct baikal_pcie *rc,
|
||
|
+ struct device_node *msi_node,
|
||
|
+ u64 *msi_addr)
|
||
|
+{
|
||
|
+ struct dw_pcie *pci = rc->pci;
|
||
|
+ struct device *dev = pci->dev;
|
||
|
+ int ret;
|
||
|
+ struct resource res;
|
||
|
+ memset(&res, 0, sizeof(res));
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Check if 'msi-parent' points to ARM GICv3 ITS, which is the only
|
||
|
+ * supported MSI controller.
|
||
|
+ */
|
||
|
+ if (!of_device_is_compatible(msi_node, "arm,gic-v3-its")) {
|
||
|
+ dev_err(dev, "unable to find compatible MSI controller\n");
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* derive GITS_TRANSLATER address from GICv3 */
|
||
|
+ ret = of_address_to_resource(msi_node, 0, &res);
|
||
|
+ if (ret < 0) {
|
||
|
+ dev_err(dev, "unable to obtain MSI controller resources\n");
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ *msi_addr = res.start + GITS_TRANSLATER;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int baikal_pcie_msi_steer(struct baikal_pcie *rc,
|
||
|
+ struct device_node *msi_node)
|
||
|
+{
|
||
|
+ struct dw_pcie *pci = rc->pci;
|
||
|
+ struct device *dev = pci->dev;
|
||
|
+ int ret;
|
||
|
+ u64 msi_addr;
|
||
|
+
|
||
|
+ ret = baikal_pcie_get_msi(rc, msi_node, &msi_addr);
|
||
|
+ if (ret < 0) {
|
||
|
+ dev_err(dev, "MSI steering failed\n");
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Program the msi_data */
|
||
|
+ dw_pcie_write(pci->dbi_base + PCIE_MSI_ADDR_LO, 4,
|
||
|
+ lower_32_bits(msi_addr));
|
||
|
+ dw_pcie_write(pci->dbi_base + PCIE_MSI_ADDR_HI, 4,
|
||
|
+ upper_32_bits(msi_addr));
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+int baikal_msi_init(struct baikal_pcie *rc, struct device_node *node)
|
||
|
+{
|
||
|
+ if (!of_find_property(node, "msi-controller", NULL)) {
|
||
|
+ pr_err("%s: couldn't find msi-controller property in FDT\n", __func__);
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int baikal_pcie_msi_enable(struct baikal_pcie *rc)
|
||
|
+{
|
||
|
+ struct dw_pcie *pci = rc->pci;
|
||
|
+ struct device *dev = pci->dev;
|
||
|
+ struct device_node *msi_node;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * The "msi-parent" phandle needs to exist
|
||
|
+ * for us to obtain the MSI node.
|
||
|
+ */
|
||
|
+
|
||
|
+ msi_node = of_parse_phandle(dev->of_node, "msi-parent", 0);
|
||
|
+ if (!msi_node) {
|
||
|
+ dev_err(dev, "failed to read msi-parent from FDT\n");
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = baikal_pcie_msi_steer(rc, msi_node);
|
||
|
+ if (ret)
|
||
|
+ goto out_put_node;
|
||
|
+
|
||
|
+out_put_node:
|
||
|
+ of_node_put(msi_node);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static irqreturn_t baikal_pcie_handle_error_irq(struct baikal_pcie *rc)
|
||
|
+{
|
||
|
+ return IRQ_HANDLED;
|
||
|
+}
|
||
|
+
|
||
|
+static irqreturn_t baikal_pcie_err_irq_handler(int irq, void *priv)
|
||
|
+{
|
||
|
+ struct baikal_pcie *rc = priv;
|
||
|
+
|
||
|
+ return baikal_pcie_handle_error_irq(rc);
|
||
|
+}
|
||
|
+
|
||
|
+static int baikal_add_pcie_port(struct baikal_pcie *rc,
|
||
|
+ struct platform_device *pdev)
|
||
|
+{
|
||
|
+ struct dw_pcie *pci = rc->pci;
|
||
|
+ struct pcie_port *pp = &pci->pp;
|
||
|
+ struct resource *res;
|
||
|
+ int irq;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ pci->dev = &pdev->dev;
|
||
|
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
|
||
|
+ if (res) {
|
||
|
+ pci->dbi_base = devm_ioremap_resource(pci->dev, res);
|
||
|
+ if (IS_ERR(pci->dbi_base)) {
|
||
|
+ dev_err(pci->dev, "error with ioremap\n");
|
||
|
+ return PTR_ERR(pci->dbi_base);
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ dev_err(pci->dev, "missing *dbi* reg space\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ irq = platform_get_irq(pdev, 0);
|
||
|
+ if (irq < 0) {
|
||
|
+ dev_err(pci->dev, "missing IRQ resource: %d\n", irq);
|
||
|
+ return irq;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* TODO enable it later */
|
||
|
+ ret = request_irq(irq, baikal_pcie_err_irq_handler, IRQF_SHARED,
|
||
|
+ "baikal-pcie-error-irq", rc);
|
||
|
+ if (ret < 0) {
|
||
|
+ dev_err(pci->dev, "failed to request error IRQ %d\n",
|
||
|
+ irq);
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+ /* end TODO */
|
||
|
+
|
||
|
+ if (IS_ENABLED(CONFIG_PCI_MSI)) {
|
||
|
+ ret = baikal_pcie_msi_enable(rc);
|
||
|
+ if (ret) {
|
||
|
+ dev_err(pci->dev, "failed to initialize MSI\n");
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ pp->ops = &baikal_pcie_host_ops;
|
||
|
+
|
||
|
+ ret = dw_pcie_host_init(pp);
|
||
|
+ if (ret) {
|
||
|
+ dev_err(pci->dev, "failed to initialize host\n");
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+ baikal_pcie_retrain_links(pp->bridge->bus);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int baikal_pcie_hw_init_m(struct baikal_pcie *rc)
|
||
|
+{
|
||
|
+ u32 reg;
|
||
|
+
|
||
|
+ // TODO add PHY configuration if needed
|
||
|
+
|
||
|
+ /* Deassert PHY reset */
|
||
|
+ reg = baikal_pcie_lcru_readl(rc->lcru, BAIKAL_LCRU_PCIE_RESET(rc->bus_nr));
|
||
|
+ reg &= ~BAIKAL_PCIE_PHY_RESET;
|
||
|
+ baikal_pcie_lcru_writel(rc->lcru, BAIKAL_LCRU_PCIE_RESET(rc->bus_nr), reg);
|
||
|
+
|
||
|
+ // TODO timeout?
|
||
|
+
|
||
|
+ /* Enable access to the PHY registers */
|
||
|
+ reg = baikal_pcie_lcru_readl(rc->lcru, BAIKAL_LCRU_PCIE_GEN_CTL(rc->bus_nr));
|
||
|
+ reg |= (BAIKAL_PCIE_PHY_MGMT_ENABLE | BAIKAL_PCIE_DBI2_MODE);
|
||
|
+ baikal_pcie_lcru_writel(rc->lcru, BAIKAL_LCRU_PCIE_GEN_CTL(rc->bus_nr), reg);
|
||
|
+
|
||
|
+ // TODO timeout?
|
||
|
+
|
||
|
+ /* Clear all software controlled resets of the controller */
|
||
|
+ reg = baikal_pcie_lcru_readl(rc->lcru, BAIKAL_LCRU_PCIE_RESET(rc->bus_nr));
|
||
|
+ reg &= ~(BAIKAL_PCIE_ADB_PWRDWN | BAIKAL_PCIE_HOT_RESET |
|
||
|
+ BAIKAL_PCIE_NONSTICKY_RST | BAIKAL_PCIE_STICKY_RST |
|
||
|
+ BAIKAL_PCIE_PWR_RST | BAIKAL_PCIE_CORE_RST | BAIKAL_PCIE_PIPE_RESET);
|
||
|
+ baikal_pcie_lcru_writel(rc->lcru, BAIKAL_LCRU_PCIE_RESET(rc->bus_nr), reg);
|
||
|
+
|
||
|
+ // TODO timeout?
|
||
|
+
|
||
|
+ if (IS_ENABLED(CONFIG_PCI_MSI)) {
|
||
|
+
|
||
|
+ /* Set up the MSI translation mechanism: */
|
||
|
+
|
||
|
+ /* First, set MSI_AWUSER to 0 */
|
||
|
+ reg = baikal_pcie_lcru_readl(rc->lcru, BAIKAL_LCRU_PCIE_MSI_TRANS_CTL0);
|
||
|
+ reg &= ~BAIKAL_PCIE_MSI_AWUSER_MASK;
|
||
|
+ reg |= (0 << BAIKAL_PCIE_MSI_AWUSER_SHIFT);
|
||
|
+ baikal_pcie_lcru_writel(rc->lcru, BAIKAL_LCRU_PCIE_MSI_TRANS_CTL0, reg);
|
||
|
+
|
||
|
+ // TODO timeout?
|
||
|
+
|
||
|
+ /* Second, enable MSI, the RC number for all RC is 0*/
|
||
|
+ reg = baikal_pcie_lcru_readl(rc->lcru, BAIKAL_LCRU_PCIE_MSI_TRANS_CTL2);
|
||
|
+ reg |= BAIKAL_PCIE_MSI_TRANS_EN(rc->bus_nr);
|
||
|
+ reg &= ~BAIKAL_PCIE_MSI_RCNUM_MASK(rc->bus_nr);
|
||
|
+ baikal_pcie_lcru_writel(rc->lcru, BAIKAL_LCRU_PCIE_MSI_TRANS_CTL2, reg);
|
||
|
+
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+
|
||
|
+}
|
||
|
+
|
||
|
+static const struct of_device_id of_baikal_pcie_match[] = {
|
||
|
+ {
|
||
|
+ .compatible = "baikal,pcie-m",
|
||
|
+ .data = baikal_pcie_hw_init_m,
|
||
|
+ },
|
||
|
+ {},
|
||
|
+};
|
||
|
+
|
||
|
+/* XXX: this driver is incompatible with firmware from SDK-M version 4.4
|
||
|
+ * (and possibly later versions). Unfortunately the vendor does not provide
|
||
|
+ * any reasonable way to find out the firmware version. Hence this guess:
|
||
|
+ * if the "/soc" node exists - it's SDK-M 4.4
|
||
|
+ * otherwise it's SDK-M 4.3 (hopefully)
|
||
|
+ */
|
||
|
+static int guess_incompat_firmware(void)
|
||
|
+{
|
||
|
+ int ret = 0;
|
||
|
+ struct device_node *np = NULL;
|
||
|
+ np = of_find_node_by_path("/soc");
|
||
|
+ if (np) {
|
||
|
+ ret = 1;
|
||
|
+ of_node_put(np);
|
||
|
+ }
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+static int baikal_pcie_probe(struct platform_device *pdev)
|
||
|
+{
|
||
|
+ struct dw_pcie *pci;
|
||
|
+ struct baikal_pcie *pcie;
|
||
|
+ struct device *dev = &pdev->dev;
|
||
|
+ const struct of_device_id *of_id;
|
||
|
+ int err;
|
||
|
+ int (*hw_init_fn)(struct baikal_pcie *);
|
||
|
+ u32 index[2];
|
||
|
+ enum of_gpio_flags flags;
|
||
|
+ int reset_gpio;
|
||
|
+ pr_info("%s: ENTER\n", __func__);
|
||
|
+
|
||
|
+ if (guess_incompat_firmware()) {
|
||
|
+ dev_err(dev, "detected incompatible firmware, bailing out\n");
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
|
||
|
+ if (!pcie) {
|
||
|
+ dev_err(dev, "failed to allocate memory\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
|
||
|
+ if (!pci) {
|
||
|
+ dev_err(dev, "failed to allocate memory [2]\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+ pci->dev = dev;
|
||
|
+ pci->ops = &baikal_pcie_ops;
|
||
|
+
|
||
|
+ pcie->pci = pci;
|
||
|
+
|
||
|
+ pcie->lcru = syscon_regmap_lookup_by_phandle(dev->of_node,
|
||
|
+ "baikal,pcie-lcru");
|
||
|
+ if (IS_ERR(pcie->lcru)) {
|
||
|
+ dev_err(dev, "No LCRU phandle specified\n");
|
||
|
+ pcie->lcru = NULL;
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (of_property_read_u32_array(dev->of_node,
|
||
|
+ "baikal,pcie-lcru", index, 2)) {
|
||
|
+ dev_err(dev, "failed to read LCRU\n");
|
||
|
+ pcie->lcru = NULL;
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+ pcie->bus_nr = index[1];
|
||
|
+
|
||
|
+ of_id = of_match_device(of_baikal_pcie_match, dev);
|
||
|
+ if (!of_id || !of_id->data) {
|
||
|
+ dev_err(dev, "device can't be handled by pcie-baikal\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+ hw_init_fn = of_id->data;
|
||
|
+
|
||
|
+ pm_runtime_enable(dev);
|
||
|
+ err = pm_runtime_get_sync(dev);
|
||
|
+ if (err < 0) {
|
||
|
+ dev_err(dev, "pm_runtime_get_sync failed\n");
|
||
|
+ goto err_pm_disable;
|
||
|
+ }
|
||
|
+
|
||
|
+
|
||
|
+ baikal_pcie_cease_link(pcie);
|
||
|
+
|
||
|
+ /* LINK DISABLED */
|
||
|
+ reset_gpio = of_get_named_gpio_flags(dev->of_node, "reset-gpios", 0, &flags);
|
||
|
+ if (reset_gpio != -EPROBE_DEFER && gpio_is_valid(reset_gpio)) {
|
||
|
+ unsigned long gpio_flags;
|
||
|
+
|
||
|
+ snprintf(pcie->reset_name, 32, "pcie%d-reset", pcie->bus_nr);
|
||
|
+ if (flags & OF_GPIO_ACTIVE_LOW)
|
||
|
+ gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_LOW;
|
||
|
+ else
|
||
|
+ gpio_flags = GPIOF_OUT_INIT_HIGH;
|
||
|
+ err = devm_gpio_request_one(dev, reset_gpio, gpio_flags,
|
||
|
+ pcie->reset_name);
|
||
|
+ if (err) {
|
||
|
+ dev_err(dev, "request GPIO failed (%d)\n", err);
|
||
|
+ goto err_pm_disable;
|
||
|
+ }
|
||
|
+ pcie->reset_gpio = gpio_to_desc(reset_gpio);
|
||
|
+
|
||
|
+ udelay(100);
|
||
|
+//vvv: do it now or later in baikal_pcie_host_init()?
|
||
|
+ gpiod_set_value_cansleep(pcie->reset_gpio, 0);
|
||
|
+ }
|
||
|
+
|
||
|
+ err = hw_init_fn(pcie);
|
||
|
+ if (err) {
|
||
|
+ //dev_info(dev, "PCIe link down\n"); // TODO PHY not initialized!
|
||
|
+ err = 0;
|
||
|
+ goto err_pm_put;
|
||
|
+ }
|
||
|
+ /* PHY INITIALIZED */
|
||
|
+ platform_set_drvdata(pdev, pcie);
|
||
|
+
|
||
|
+ err = baikal_add_pcie_port(pcie, pdev);
|
||
|
+ if (err < 0)
|
||
|
+ //goto err_gpio; TODO
|
||
|
+ goto err_pm_put;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+
|
||
|
+err_pm_put:
|
||
|
+ pm_runtime_put(dev);
|
||
|
+
|
||
|
+err_pm_disable:
|
||
|
+ pm_runtime_disable(dev);
|
||
|
+
|
||
|
+err_phy:
|
||
|
+ return err;
|
||
|
+}
|
||
|
+
|
||
|
+#ifdef CONFIG_PM_SLEEP
|
||
|
+static int baikal_pcie_suspend(struct device *dev)
|
||
|
+{
|
||
|
+ struct baikal_pcie *rc = dev_get_drvdata(dev);
|
||
|
+ struct dw_pcie *pci = rc->pci;
|
||
|
+ u32 val;
|
||
|
+
|
||
|
+ /* clear MSE */
|
||
|
+ val = dw_pcie_readl_dbi(pci, PCI_COMMAND);
|
||
|
+ val &= ~PCI_COMMAND_MEMORY;
|
||
|
+ dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int baikal_pcie_resume(struct device *dev)
|
||
|
+{
|
||
|
+ struct baikal_pcie *rc = dev_get_drvdata(dev);
|
||
|
+ struct dw_pcie *pci = rc->pci;
|
||
|
+ u32 val;
|
||
|
+
|
||
|
+ /* set MSE */
|
||
|
+ val = dw_pcie_readl_dbi(pci, PCI_COMMAND);
|
||
|
+ val |= PCI_COMMAND_MEMORY;
|
||
|
+ dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int baikal_pcie_suspend_noirq(struct device *dev)
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int baikal_pcie_resume_noirq(struct device *dev)
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+#endif
|
||
|
+
|
||
|
+static const struct dev_pm_ops baikal_pcie_pm_ops = {
|
||
|
+ SET_SYSTEM_SLEEP_PM_OPS(baikal_pcie_suspend, baikal_pcie_resume)
|
||
|
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(baikal_pcie_suspend_noirq,
|
||
|
+ baikal_pcie_resume_noirq)
|
||
|
+};
|
||
|
+
|
||
|
+static struct platform_driver baikal_pcie_driver = {
|
||
|
+ .driver = {
|
||
|
+ .name = "baikal-pcie",
|
||
|
+ .of_match_table = of_baikal_pcie_match,
|
||
|
+ .suppress_bind_attrs = true,
|
||
|
+ .pm = &baikal_pcie_pm_ops,
|
||
|
+ },
|
||
|
+ .probe = baikal_pcie_probe,
|
||
|
+};
|
||
|
+
|
||
|
+MODULE_DEVICE_TABLE(of, of_baikal_pcie_match);
|
||
|
+module_platform_driver(baikal_pcie_driver);
|
||
|
+MODULE_LICENSE("GPL v2");
|
||
|
diff --git a/drivers/pci/controller/dwc/pcie-baikal.h b/drivers/pci/controller/dwc/pcie-baikal.h
|
||
|
new file mode 100644
|
||
|
index 000000000000..f59100cf0c6d
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/pci/controller/dwc/pcie-baikal.h
|
||
|
@@ -0,0 +1,217 @@
|
||
|
+/*
|
||
|
+ * pcie-baikal - PCIe controller driver for Baikal SoCs
|
||
|
+ *
|
||
|
+ * Copyright (C) 2019 Baikal Electronics JSC
|
||
|
+ * Author: Pavel Parkhomenko <Pavel.Parkhomenko@baikalelectronics.ru>
|
||
|
+ *
|
||
|
+ * Parts of this file were based on sources as follows:
|
||
|
+ * Copyright (C) 2013-2014 Texas Instruments Incorporated - http://www.ti.com
|
||
|
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
|
||
|
+ *
|
||
|
+ * This program is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License version 2 as
|
||
|
+ * published by the Free Software Foundation.
|
||
|
+ */
|
||
|
+
|
||
|
+#define PCI_VENDOR_ID_BAIKAL 0x1d39
|
||
|
+
|
||
|
+#define PCIE_GEN2_CTRL_OFF (0x80c) /* Link Width and Speed Change Control Register. */
|
||
|
+
|
||
|
+/* PHY control registers. */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_CFG_0 (0x1c000) /* PLL Global Configuration Register #0 */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_CFG_1 (0x1c001) /* PLL Global Configuration Register #1 */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_CFG_2 (0x1c002) /* PLL Global Configuration Register #2 */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_CFG_3 (0x1c003) /* PLL Global Configuration Register #3 */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_CFG_4 (0x1c004) /* PLL Global Configuration Register #4 */
|
||
|
+#define PCIE_PHY_DWC_GLBL_MISC_CONFIG_0 (0x1c005) /* Global Miscellaneous Configuration #0 */
|
||
|
+#define PCIE_PHY_DWC_GLBL_MISC_CONFIG_1 (0x1c006) /* Global Miscellaneous Configuration #1 */
|
||
|
+#define PCIE_PHY_DWC_SLICE_CFG (0x1c00c) /* Slice Configuration */
|
||
|
+#define PCIE_PHY_DWC_GLBL_REGU_CFG (0x1c00d) /* Global Regulator Configuration */
|
||
|
+#define PCIE_PHY_DWC_GLBL_TERM_CFG (0x1c00e) /* Global Termination Calibration Configuration */
|
||
|
+#define PCIE_PHY_DWC_GLBL_CAL_CFG (0x1c00f) /* Global PLL Calibration Configuration */
|
||
|
+#define PCIE_PHY_DWC_GLBL_RD_SYNC_STATUS (0x1c010) /* Global Read Synchronization Status */
|
||
|
+#define PCIE_PHY_DWC_RX_PWR_CTRL_P0 (0x1c014) /* RX Power Controls in Power State P0 */
|
||
|
+#define PCIE_PHY_DWC_RX_PWR_CTRL_P0S (0x1c015) /* RX Power Controls in Power State P0S */
|
||
|
+#define PCIE_PHY_DWC_RX_PWR_CTRL_P1 (0x1c016) /* RX Power Controls in Power State P1 */
|
||
|
+#define PCIE_PHY_DWC_RX_PWR_CTRL_P2 (0x1c017) /* RX Power Controls in Power State P2 */
|
||
|
+#define PCIE_PHY_DWC_TX_PWR_CTRL_P0_P0S (0x1c018) /* TX Power Controls in Power States P0 and POS */
|
||
|
+#define PCIE_PHY_DWC_TX_PWR_CTRL_P1_P2 (0x1c019) /* TX Power Controls in Power States P1 and P2 */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PWR_CTRL (0x1c01a) /* Global Power State Machine Control Override */
|
||
|
+#define PCIE_PHY_DWC_RX_TXDIR_CTRL_0 (0x1c01d) /* Far-end TX Direction Control Register #0 */
|
||
|
+#define PCIE_PHY_DWC_RX_TXDIR_CTRL_1 (0x1c01e) /* Far-end TX Direction Control Register #1 */
|
||
|
+#define PCIE_PHY_DWC_RX_TXDIR_CTRL_2 (0x1c01f) /* Far-end TX Direction Control Register #2 */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_MONITOR (0x1c020) /* Monitor for SerDes Global to Raw PCS Global Interface */
|
||
|
+#define PCIE_PHY_DWC_GLBL_TERM_MON_1 (0x1c022) /* Monitor for SerDes Global to Raw PCS Global Interface */
|
||
|
+#define PCIE_PHY_DWC_GLBL_SDS_PIN_MON_0 (0x1c023) /* Monitor for Raw PCS Global to SerDes Global to Raw PCS Interface */
|
||
|
+#define PCIE_PHY_DWC_GLBL_SDS_PIN_MON_1 (0x1c024) /* Monitor for Raw PCS Global to SerDes Global to Raw PCS Interface */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PWR_MON_0 (0x1c025) /* Monitor of Global Power State Machine Values */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PWR_MON_1 (0x1c026) /* Monitor of Global Power State Machine Values */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PWR_MON_2 (0x1c027) /* Monitor of Global Power State Machine Values */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_SSC_FRAC_BASE (0x1c060) /* Global PLL SSC Fractional Base */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_SSC_CYCLES (0x1c061) /* Global PLL SSC Cycles Configuration */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_SSC_FMFREQ (0x1c062) /* Global PLL SSC Modulation Frequency */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_SSC_FREF (0x1c063) /* Global PLL SSC Reference Frequency */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_SSC_PPM (0x1c064) /* Global PLL SSC PPM */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_SSC_CFG (0x1c065) /* Global PLL SSC Configuration */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_SSC_ALU_CMD (0x1c067) /* Global PLL SSC ALU Command */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_SSC_MON (0x1c069) /* Global PLL SSC Monitor */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_SSC_ALU_OUT_0 (0x1c06b) /* Global PLL SSC ALU Output Register #0 */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_SSC_ALU_OUT_1 (0x1c06c) /* Global PLL SSC ALU Output Register #1 */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_SSC_DIV (0x1c06d) /* Global PLL SSC Divider */
|
||
|
+#define PCIE_PHY_DWC_GLBL_PLL_SSC_FRAC (0x1c06e) /* Global PLL SSC Fraction */
|
||
|
+#define PCIE_PHY_DWC_GLBL_TAD (0x1c080) /* Global Test Analog and Digital Monitor */
|
||
|
+#define PCIE_PHY_DWC_GLBL_TM_ADMON (0x1c081) /* Global Test Mode Analog/Digital Monitor Enable */
|
||
|
+#define PCIE_PHY_DWC_EQ_WAIT_TIME (0x3c000) /* TX and RX Equalization Wait Times */
|
||
|
+#define PCIE_PHY_DWC_RDET_TIME (0x3c001) /* Receiver Detect Wait Times */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_LINK_CFG (0x3c002) /* Link Configuration Override */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_CTLIFC_0 (0x3c003) /* PLL Control Interface Override Register #0 */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_CTLIFC_1 (0x3c004) /* PLL Control Interface Override Register #1 */
|
||
|
+#define PCIE_PHY_DWC_PCS_REG_RD_TIMEOUT (0x3c005) /* Register Read Timeout */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_PCIE1_MODE_0 (0x3c006) /* PLL Configuration Register #0 for PCIe1 */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_PCIE1_MODE_1 (0x3c007) /* PLL Configuration Register #1 for PCIe1 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_PCIE1_MODE_0 (0x3c008) /* Lane Configuration Register #0 for PCIe1 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_PCIE1_MODE_1 (0x3c009) /* Lane Configuration Register #1 for PCIe1 */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_PCIE2_MODE_0 (0x3c00a) /* PLL Configuration Register #0 for PCIe2 */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_PCIE2_MODE_1 (0x3c00b) /* PLL Configuration Register #1 for PCIe2 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_PCIE2_MODE_0 (0x3c00c) /* Lane Configuration Register #0 for PCIe2 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_PCIE2_MODE_1 (0x3c00d) /* Lane Configuration Register #1 for PCIe2 */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_PCIE3_MODE_0 (0x3c00e) /* PLL Configuration Register #0 for PCIe3 */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_PCIE3_MODE_1 (0x3c00f) /* PLL Configuration Register #1 for PCIe3 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_PCIE3_MODE_0 (0x3c010) /* Lane Configuration Register #0 for PCIe3 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_PCIE3_MODE_1 (0x3c011) /* Lane Configuration Register #1 for PCIe3 */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_KX_MODE_1 (0x3c013) /* PLL Configuration Register #1 for KX */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_KX_MODE_0 (0x3c014) /* Lane Configuration Register #0 for KX */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_KX_MODE_1 (0x3c015) /* Lane Configuration Register #1 for KX */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_KX4_MODE_0 (0x3c016) /* PLL Configuration Register #0 for KX4 */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_KX4_MODE_1 (0x3c017) /* PLL Configuration Register #1 for KX4 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_KX4_MODE_0 (0x3c018) /* Lane Configuration Register #0 for KX4 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_KX4_MODE_1 (0x3c019) /* Lane Configuration Register #1 for KX4 */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_KR_MODE_0 (0x3c01a) /* PLL Configuration Register #0 for KR */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_KR_MODE_1 (0x3c01b) /* PLL Configuration Register #1 for KR */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_KR_MODE_0 (0x3c01c) /* Lane Configuration Register #0 for KR */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_KR_MODE_1 (0x3c01d) /* Lane Configuration Register #1 for KR */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_SGMII_MODE_0 (0x3c01e) /* PLL Configuration Register #0 for SGMII */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_SGMII_MODE_1 (0x3c01f) /* PLL Configuration Register #1 for SGMII */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_SGMII_MODE_0 (0x3c020) /* Lane Configuration Register #0 for SGMII */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_SGMII_MODE_1 (0x3c021) /* Lane Configuration Register #1 for SGMII */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_QSGMII_MODE_0 (0x3c022) /* PLL Configuration Register #0 for QSGMII */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_QSGMII_MODE_1 (0x3c023) /* PLL Configuration Register #1 for QSGMII */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_QSGMII_MODE_0 (0x3c024) /* Lane Configuration Register #0 for QSGMII */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_QSGMII_MODE_1 (0x3c025) /* Lane Configuration Register #1 for QSGMII */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_CEI_MODE_0 (0x3c026) /* PLL Configuration Register #0 for CEI */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_CEI_MODE_1 (0x3c027) /* PLL Configuration Register #1 for CEI */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_CEI_MODE_0 (0x3c028) /* Lane Configuration Register #0 for CEI */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_CEI_MODE_1 (0x3c029) /* Lane Configuration Register #1 for CEI */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_PCIE1_125M_MODE_0 (0x3c02a) /* PLL Configuration Register #0 for PCIe1 with 125MHz refclk */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_PCIE1_125M_MODE_1 (0x3c02b) /* PLL Configuration Register #1 for PCIe1 with 125MHz refclk */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_PCIE1_125M_MODE_0 (0x3c02c) /* Lane Configuration Register #0 for PCIe1 with 125MHz refclk */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_PCIE1_125M_MODE_1 (0x3c02d) /* Lane Configuration Register #1 for PCIe1 with 125MHz refclk */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_PCIE2_125M_MODE_0 (0x3c02e) /* PLL Configuration Register #0 for PCIe2 with 125MHz refclk */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_PCIE2_125M_MODE_1 (0x3c02f) /* PLL Configuration Register #1 for PCIe2 with 125MHz refclk */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_PCIE2_125M_MODE_0 (0x3c030) /* Lane Configuration Register #0 for PCIe2 with 125MHz refclk */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_PCIE2_125M_MODE_1 (0x3c031) /* Lane Configuration Register #1 for PCIe2 with 125MHz refclk */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_PCIE3_125M_MODE_0 (0x3c032) /* PLL Configuration Register #0 for PCIe3 with 125MHz refclk */
|
||
|
+#define PCIE_PHY_DWC_PCS_PLL_PCIE3_125M_MODE_1 (0x3c033) /* PLL Configuration Register #1 for PCIe3 with 125MHz refclk */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_PCIE3_125M_MODE_0 (0x3c034) /* Lane Configuration Register #0 for PCIe3 with 125MHz refclk */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_PCIE3_125M_MODE_1 (0x3c035) /* Lane Configuration Register #1 for PCIe3 with 125MHz refclk */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_VMA_COARSE_CTRL_0 (0x3c036) /* Lane VMA Coarse Control Register #0 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_VMA_COARSE_CTRL_1 (0x3c037) /* Lane VMA Coarse Control Register #1 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_VMA_COARSE_CTRL_2 (0x3c038) /* Lane VMA Coarse Control Register #2 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_VMA_FINE_CTRL_0 (0x3c039) /* Lane VMA Fine Control Register #0 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_VMA_FINE_CTRL_1 (0x3c03a) /* Lane VMA Fine Control Register #1 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_VMA_FINE_CTRL_2 (0x3c03b) /* Lane VMA Fine Control Register #2 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_MODE_OVRD (0x3c03c) /* Lane Mode Override in Raw PCS Global and Slice */
|
||
|
+#define PCIE_PHY_DWC_PCS_LANE_LINK_MON (0x3c040) /* Monitor of MAC to Raw PCS Link Configuration Interface */
|
||
|
+#define PCIE_PHY_DWC_PCS_MAC_PLLIFC_MON_2 (0x3c043) /* Monitor of MAC to Raw PCS PLL_PCS Divider Value */
|
||
|
+#define PCIE_PHY_DWC_PCS_MAC_PLLIFC_MON_3 (0x3c044) /* Monitor of MAC to Raw PCS PLL OP_Range and Divider Values */
|
||
|
+#define PCIE_PHY_DWC_SLICE_TRIM (0x1c040) /* Slice TX and RX Bias Trim Settings */
|
||
|
+#define PCIE_PHY_DWC_RX_LDLL_CTRL (0x1c043) /* RX Lane DLL Test Controls */
|
||
|
+#define PCIE_PHY_DWC_RX_SDLL_CTRL (0x1c044) /* RX Slice DLL test controls */
|
||
|
+#define PCIE_PHY_DWC_SLICE_PCIE1_MODE (0x1c045) /* Slice Configuration Settings for PCIE1 @ 100MHz */
|
||
|
+#define PCIE_PHY_DWC_SLICE_PCIE2_MODE (0x1c046) /* Slice Configuration Settings for PCIE2 @ 100Mhz */
|
||
|
+#define PCIE_PHY_DWC_SLICE_PCIE3_MODE (0x1c047) /* Slice Configuration Settings for PCIE3 @ 100Mhz */
|
||
|
+#define PCIE_PHY_DWC_SLICE_KX_MODE (0x1c048) /* Slice Configuration Settings for KX */
|
||
|
+#define PCIE_PHY_DWC_SLICE_KX4_MODE (0x1c049) /* Slice Configuration Settings for KX4 */
|
||
|
+#define PCIE_PHY_DWC_SLICE_KR_MODE (0x1c04a) /* Slice Configuration Settings for KR */
|
||
|
+#define PCIE_PHY_DWC_SLICE_SGMII_MODE (0x1c04b) /* Slice Configuration Settings for SGMII */
|
||
|
+#define PCIE_PHY_DWC_SLICE_QSGMII_MODE (0x1c04c) /* Slice Configuration Settings for QSGMII */
|
||
|
+#define PCIE_PHY_DWC_SLICE_CEI_MODE (0x1c04d) /* Slice Configuration Settings for CEI */
|
||
|
+#define PCIE_PHY_DWC_SLICE_PCIE1_125M_MODE (0x1c04e) /* Slice Configuration Settings for PCIE1 @ 125MHz */
|
||
|
+#define PCIE_PHY_DWC_SLICE_PCIE2_125M_MODE (0x1c04f) /* Slice Configuration Settings for PCIE2 @ 125MHz */
|
||
|
+#define PCIE_PHY_DWC_SLICE_PCIE3_125M_MODE (0x1c050) /* Slice Configuration Settings for PCIE3 @ 125MHz */
|
||
|
+#define PCIE_PHY_DWC_SLICE_OVRD_MODE (0x1c051) /* Slice Configuration Settings Override */
|
||
|
+#define PCIE_PHY_DWC_RX_CFG_0 (0x18000) /* Lane RX Configuration Register #0 */
|
||
|
+#define PCIE_PHY_DWC_RX_CFG_1 (0x18001) /* Lane RX Configuration Register #1 */
|
||
|
+#define PCIE_PHY_DWC_RX_CFG_2 (0x18002) /* Lane RX Configuration Register #2 */
|
||
|
+#define PCIE_PHY_DWC_RX_CFG_3 (0x18003) /* Lane RX Configuration Register #3 */
|
||
|
+#define PCIE_PHY_DWC_RX_CFG_4 (0x18004) /* Lane RX Configuration Register #4 */
|
||
|
+#define PCIE_PHY_DWC_RX_CFG_5 (0x18005) /* Lane RX Configuration Register #5 */
|
||
|
+#define PCIE_PHY_DWC_RX_CDR_CTRL_0 (0x18006) /* Lane RX CDR Control Register #0 */
|
||
|
+#define PCIE_PHY_DWC_RX_CDR_CTRL_1 (0x18007) /* Lane RX CDR Control Register #1 */
|
||
|
+#define PCIE_PHY_DWC_RX_CDR_CTRL_2 (0x18008) /* Lane RX CDR Control Register #2 */
|
||
|
+#define PCIE_PHY_DWC_RX_LOOP_CTRL (0x18009) /* Lane RX Loop Control */
|
||
|
+#define PCIE_PHY_DWC_RX_MISC_CTRL (0x1800a) /* Lane RX Miscellaneous Control */
|
||
|
+#define PCIE_PHY_DWC_RX_CTLE_CTRL (0x1800b) /* Lane RX CTLE Control */
|
||
|
+#define PCIE_PHY_DWC_RX_PRECORR_CTRL (0x1800c) /* Lane RX Pre-Correlation Control */
|
||
|
+#define PCIE_PHY_DWC_RX_PHS_ACCM_CTRL (0x1800d) /* Lane RX Phase Accumulator Control */
|
||
|
+#define PCIE_PHY_DWC_RX_PHS_ACCM_FR_VAL (0x1800e) /* Lane RX Phase Accumulator Frequency Portion Control */
|
||
|
+#define PCIE_PHY_DWC_RX_PRECORR_VAL (0x1800f) /* Lane RX Pre-Correlation Count */
|
||
|
+#define PCIE_PHY_DWC_RX_DELTA_PM_0 (0x18010) /* Lane RX VMA Performance Metric Register #0 */
|
||
|
+#define PCIE_PHY_DWC_RX_DELTA_PM_1 (0x18011) /* Lane RX VMA Performance Metric Register #1 */
|
||
|
+#define PCIE_PHY_DWC_TX_CAPT_CTRL (0x18012) /* Lane TX Latch Control */
|
||
|
+#define PCIE_PHY_DWC_TX_CFG_0 (0x18015) /* Lane TX Configuration Register #0 */
|
||
|
+#define PCIE_PHY_DWC_TX_CFG_1 (0x18016) /* Lane TX Configuration Register #1 */
|
||
|
+#define PCIE_PHY_DWC_TX_CFG_2 (0x18017) /* Lane TX Configuration Register #2 */
|
||
|
+#define PCIE_PHY_DWC_TX_CFG_3 (0x18018) /* Lane TX Configuration Register #3 */
|
||
|
+#define PCIE_PHY_DWC_TX_PREEMPH_0 (0x18019) /* Lane TX Pre-Emphasis */
|
||
|
+#define PCIE_PHY_DWC_PMA_LOOPBACK_CTRL (0x1801a) /* Lane PMA Loopback Control */
|
||
|
+#define PCIE_PHY_DWC_LANE_PWR_CTRL (0x1801b) /* Lane Power Control */
|
||
|
+#define PCIE_PHY_DWC_TERM_CTRL (0x1801c) /* Lane Termination Control */
|
||
|
+#define PCIE_PHY_DWC_RX_MISC_STATUS (0x18025) /* RX Miscellaneous Status */
|
||
|
+#define PCIE_PHY_DWC_SDS_PIN_MON_0 (0x18026) /* SerDes Pin Monitor 0 */
|
||
|
+#define PCIE_PHY_DWC_SDS_PIN_MON_1 (0x18027) /* SerDes Pin Monitor 1 */
|
||
|
+#define PCIE_PHY_DWC_SDS_PIN_MON_2 (0x18028) /* SerDes Pin Monitor 2 */
|
||
|
+#define PCIE_PHY_DWC_RX_PWR_MON_0 (0x18029) /* RX Power State Machine Monitor 0 */
|
||
|
+#define PCIE_PHY_DWC_RX_PWR_MON_1 (0x1802a) /* RX Power State Machine Monitor 1 */
|
||
|
+#define PCIE_PHY_DWC_RX_PWR_MON_2 (0x1802b) /* RX Power State Machine Monitor 2 */
|
||
|
+#define PCIE_PHY_DWC_TX_PWR_MON_0 (0x1802c) /* TX Power State Machine Monitor 0 */
|
||
|
+#define PCIE_PHY_DWC_TX_PWR_MON_1 (0x1802d) /* TX Power State Machine Monitor 1 */
|
||
|
+#define PCIE_PHY_DWC_TX_PWR_MON_2 (0x1802e) /* TX Power State Machine Monitor 2 */
|
||
|
+#define PCIE_PHY_DWC_RX_VMA_CTRL (0x18040) /* Lane RX VMA Control */
|
||
|
+#define PCIE_PHY_DWC_RX_CDR_MISC_CTRL_0 (0x18041) /* Lane RX CDR Miscellaneous Control Register #0 */
|
||
|
+#define PCIE_PHY_DWC_RX_CDR_MISC_CTRL_1 (0x18042) /* Lane RX CDR Miscellaneous Control Register #1 */
|
||
|
+#define PCIE_PHY_DWC_RX_PWR_CTRL (0x18043) /* Lane RX Power Control */
|
||
|
+#define PCIE_PHY_DWC_RX_OS_MVALBBD_0 (0x18045) /* Lane RX Offset Calibration Manual Control Register #0 */
|
||
|
+#define PCIE_PHY_DWC_RX_OS_MVALBBD_1 (0x18046) /* Lane RX Offset Calibration Manual Control Register #1 */
|
||
|
+#define PCIE_PHY_DWC_RX_OS_MVALBBD_2 (0x18047) /* Lane RX Offset Calibration Manual Control Register #2 */
|
||
|
+#define PCIE_PHY_DWC_RX_AEQ_VALBBD_0 (0x18048) /* Lane RX Adaptive Equalizer Control Register #0 */
|
||
|
+#define PCIE_PHY_DWC_RX_AEQ_VALBBD_1 (0x18049) /* Lane RX Adaptive Equalizer Control Register #1 */
|
||
|
+#define PCIE_PHY_DWC_RX_AEQ_VALBBD_2 (0x1804a) /* Lane RX Adaptive Equalizer Control Register #2 */
|
||
|
+#define PCIE_PHY_DWC_RX_MISC_OVRRD (0x1804b) /* Lane RX Miscellaneous Override Controls */
|
||
|
+#define PCIE_PHY_DWC_RX_OVRRD_PHASE_ACCUM_ADJ (0x1804c) /* Lane RX Phase Accumulator Adjust Override */
|
||
|
+#define PCIE_PHY_DWC_RX_AEQ_OUT_0 (0x18050) /* Lane RX Adaptive Equalizer Status Register #0 */
|
||
|
+#define PCIE_PHY_DWC_RX_AEQ_OUT_1 (0x18051) /* Lane RX Adaptive Equalizer Status Register #1 */
|
||
|
+#define PCIE_PHY_DWC_RX_AEQ_OUT_2 (0x18052) /* Lane RX Adaptive Equalizer Status Register #2 */
|
||
|
+#define PCIE_PHY_DWC_RX_OS_OUT_0 (0x18053) /* Lane RX Offset Calibration Status Register #0 */
|
||
|
+#define PCIE_PHY_DWC_RX_OS_OUT_1 (0x18054) /* Lane RX Offset Calibration Status Register #1 */
|
||
|
+#define PCIE_PHY_DWC_RX_OS_OUT_2 (0x18055) /* Lane RX Offset Calibration Status Register #2 */
|
||
|
+#define PCIE_PHY_DWC_RX_OS_OUT_3 (0x18056) /* Lane RX Offset Calibration Status Register #3 */
|
||
|
+#define PCIE_PHY_DWC_RX_VMA_STATUS_0 (0x18057) /* Lane RX CDR Status Register #0 */
|
||
|
+#define PCIE_PHY_DWC_RX_VMA_STATUS_1 (0x18058) /* Lane RX CDR Status Register #1 */
|
||
|
+#define PCIE_PHY_DWC_RX_CDR_STATUS_0 (0x18059) /* Lane RX CDR Status Register #0 */
|
||
|
+#define PCIE_PHY_DWC_RX_CDR_STATUS_1 (0x1805a) /* Lane RX CDR Status Register #1 */
|
||
|
+#define PCIE_PHY_DWC_RX_CDR_STATUS_2 (0x1805b) /* Lane RX CDR Status Register #2 */
|
||
|
+#define PCIE_PHY_DWC_PCS_MISC_CFG_0 (0x38000) /* Lane Miscellaneous Configuration Register #0 */
|
||
|
+#define PCIE_PHY_DWC_PCS_MISC_CFG_1 (0x38001) /* Lane Raw PCS Miscellaneous Configuration Register #1 */
|
||
|
+#define PCIE_PHY_DWC_PCS_LBERT_PAT_CFG (0x38003) /* LBERT Pattern Configuration */
|
||
|
+#define PCIE_PHY_DWC_PCS_LBERT_CFG (0x38004) /* LBERT Configuration */
|
||
|
+#define PCIE_PHY_DWC_PCS_LBERT_ECNT (0x38005) /* LBERT Error Counter */
|
||
|
+#define PCIE_PHY_DWC_PCS_RESET_0 (0x38006) /* Lane Raw PCS Reset Register #0 */
|
||
|
+#define PCIE_PHY_DWC_PCS_RESET_1 (0x38007) /* Lane Raw PCS Reset Register #1 */
|
||
|
+#define PCIE_PHY_DWC_PCS_RESET_2 (0x38008) /* Lane Raw PCS Reset Register #2 */
|
||
|
+#define PCIE_PHY_DWC_PCS_RESET_3 (0x38009) /* Lane Raw PCS Reset Register #3 */
|
||
|
+#define PCIE_PHY_DWC_PCS_CTLIFC_CTRL_0 (0x3800c) /* Lane Raw PCS Control Interface Configuration Register #0 */
|
||
|
+#define PCIE_PHY_DWC_PCS_CTLIFC_CTRL_1 (0x3800d) /* Lane Raw PCS Control Interface Configuration Register #1 */
|
||
|
+#define PCIE_PHY_DWC_PCS_CTLIFC_CTRL_2 (0x3800e) /* Lane Raw PCS Control Interface Configuration Register #2 */
|
||
|
+#define PCIE_PHY_DWC_PCS_MACIFC_MON_0 (0x38021) /* MAC to Raw PCS Interface Monitor Register #0 */
|
||
|
+#define PCIE_PHY_DWC_PCS_MACIFC_MON_2 (0x38023) /* MAC to Raw PCS Interface Monitor Register #1 */
|
||
|
diff --git a/include/linux/mfd/baikal/lcru-pcie.h b/include/linux/mfd/baikal/lcru-pcie.h
|
||
|
new file mode 100644
|
||
|
index 000000000000..40562d00ab85
|
||
|
--- /dev/null
|
||
|
+++ b/include/linux/mfd/baikal/lcru-pcie.h
|
||
|
@@ -0,0 +1,140 @@
|
||
|
+/*
|
||
|
+ * Baikal SoC series Local Clock and Reset Unit (LCRU) register offsets
|
||
|
+ * and bit definitions.
|
||
|
+ *
|
||
|
+ * Copyright (C) 2019 Baikal Electronics JSC.
|
||
|
+ *
|
||
|
+ * This program is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License version 2 as
|
||
|
+ * published by the Free Software Foundation.
|
||
|
+ */
|
||
|
+
|
||
|
+#ifndef _LINUX_MFD_SYSCON_BAIKAL_LCRU_H_
|
||
|
+#define _LINUX_MFD_SYSCON_BAIKAL_LCRU_H_
|
||
|
+
|
||
|
+#include <linux/regmap.h>
|
||
|
+
|
||
|
+//#define BAIKAL_CMU_PCIE_STEP 0x30
|
||
|
+
|
||
|
+//#define BAIKAL_CMU_PCIE_MSTRCLK 0x20
|
||
|
+//#define BAIKAL_CMU_PCIE_SLVCLK 0x30
|
||
|
+//#define BAIKAL_CMU_PCIE_CFGCLK 0x40
|
||
|
+
|
||
|
+#define BAIKAL_LCRU_PCIE_RESET_BASE 0x50000 /* GPR0_RW */
|
||
|
+#define BAIKAL_LCRU_PCIE_RESET(x) ((x * 0x20) + BAIKAL_LCRU_PCIE_RESET_BASE)
|
||
|
+#define BAIKAL_PCIE_ADB_PWRDWN (1 << 13)
|
||
|
+#define BAIKAL_PCIE_HOT_RESET (1 << 12)
|
||
|
+#define BAIKAL_PCIE_NONSTICKY_RST (1 << 11)
|
||
|
+#define BAIKAL_PCIE_STICKY_RST (1 << 10)
|
||
|
+#define BAIKAL_PCIE_PWR_RST (1 << 9)
|
||
|
+#define BAIKAL_PCIE_CORE_RST (1 << 8)
|
||
|
+#define BAIKAL_PCIE_PIPE1_RESET (1 << 5) /* x8 controller only */
|
||
|
+#define BAIKAL_PCIE_PIPE0_RESET (1 << 4) /* x8 controller only */
|
||
|
+#define BAIKAL_PCIE_PIPE_RESET (1 << 4) /* x4 controllers only */
|
||
|
+#define BAIKAL_PCIE_PHY_RESET (1 << 0)
|
||
|
+
|
||
|
+#define BAIKAL_LCRU_PCIE_STATUS_BASE 0x50004 /* GPR0_RO */
|
||
|
+#define BAIKAL_LCRU_PCIE_STATUS(x) ((x * 0x20) + BAIKAL_LCRU_PCIE_STATUS_BASE)
|
||
|
+#define BAIKAL_PCIE_TURNOFF_ACK (1 << 31)
|
||
|
+#define BAIKAL_PCIE_ADB_PWRACK (1 << 30)
|
||
|
+#define BAIKAL_PCIE_WAKE_DET (1 << 24)
|
||
|
+#define BAIKAL_PCIE_AUX_PM_EN (1 << 22)
|
||
|
+#define BAIKAL_PCIE_PM_PME_STATUS (1 << 21)
|
||
|
+#define BAIKAL_PCIE_PM_PME_EN (1 << 20)
|
||
|
+#define BAIKAL_PCIE_PM_DSTATE_SHIFT 16
|
||
|
+#define BAIKAL_PCIE_PM_DSTATE_MASK 0x7
|
||
|
+#define BAIKAL_PCIE_PM_DSTATE_D0 0
|
||
|
+#define BAIKAL_PCIE_PM_DSTATE_D1 1
|
||
|
+#define BAIKAL_PCIE_PM_DSTATE_D2 2
|
||
|
+#define BAIKAL_PCIE_PM_DSTATE_D3 3
|
||
|
+#define BAIKAL_PCIE_PM_DSTATE_UNINIT 4
|
||
|
+#define BAIKAL_PCIE_LTSSM_RCVRY_EQ (1 << 15)
|
||
|
+#define BAIKAL_PCIE_PIPE_CLK_REQ (1 << 14)
|
||
|
+#define BAIKAL_PCIE_SMLH_REQ_RST (1 << 13)
|
||
|
+#define BAIKAL_PCIE_LINK_REQ_RST (1 << 12)
|
||
|
+#define BAIKAL_PCIE_PM_LINKSTATE_L2 (1 << 10)
|
||
|
+#define BAIKAL_PCIE_PM_LINKSTATE_L1 (1 << 9)
|
||
|
+#define BAIKAL_PCIE_PM_LINKSTATE_L0S (1 << 8)
|
||
|
+#define BAIKAL_PCIE_RDLH_LINKUP (1 << 7)
|
||
|
+#define BAIKAL_PCIE_SMLH_LINKUP (1 << 6)
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_SHIFT 0
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_MASK 0x3F
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_DETECT_QUIET 0x00
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_DETECT_ACT 0x01
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_POLLING_ACTIVE 0x02
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_POLLING_COMPLIANCE 0x03
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_POLLING_CONFIG 0x04
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_PRE_DETECT_QUIET 0x05
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_DETECT_WAIT 0x06
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_CFG_LINK_WD_START 0x07
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_CFG_LINK_WD_ACCEPT 0x08
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_CFG_LANE_NUM_WAIT 0x09
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_CFG_LANE_NUM_ACCEPT 0x0A
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_CFG_COMPLETE 0x0B
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_CFG_IDLE 0x0C
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_RCVRY_LOCK 0x0D
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_RCVRY_SPEED 0x0E
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_RCVRY_RCVR_CFG 0x0F
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_RCVRY_IDLE 0x10
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_RCVRY_EQ0 0x20
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_RCVRY_EQ1 0x21
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_RCVRY_EQ2 0x22
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_RCVRY_EQ3 0x23
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_L0 0x11
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_L0S 0x12
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_L123_SEND_IDLE 0x13
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_L1_IDLE 0x14
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_L2_IDLE 0x15
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_L2_WAKE 0x16
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_DISABLED_ENTRY 0x17
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_DISABLED_IDLE 0x18
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_DISABLED 0x19
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_LOOPBACK_ENTRY 0x1A
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_LOOPBACK_ACTIVE 0x1B
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_LOOPBACK_EXIT 0x1C
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_LOOPBACK_EXIT_TIMEOUT 0x1D
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_HOT_RESET_ENTRY 0x1E
|
||
|
+#define BAIKAL_PCIE_LTSSM_STATE_HOT_RESET 0x1F
|
||
|
+
|
||
|
+#define BAIKAL_LCRU_PCIE_GEN_CTL_BASE 0x50008 /* GPR1_RW*/
|
||
|
+#define BAIKAL_LCRU_PCIE_GEN_CTL(x) ((x * 0x20) + BAIKAL_LCRU_PCIE_GEN_CTL_BASE)
|
||
|
+#define BAIKAL_PCIE_AUX_PWR_DET (1 << 24)
|
||
|
+#define BAIKAL_PCIE_TXLANE_FLIP_EN (1 << 17)
|
||
|
+#define BAIKAL_PCIE_RXLANE_FLIP_EN (1 << 16)
|
||
|
+#define BAIKAL_PCIE_PHY_MGMT_ENABLE (1 << 3)
|
||
|
+#define BAIKAL_PCIE_DBI2_MODE (1 << 2)
|
||
|
+#define BAIKAL_PCIE_LTSSM_ENABLE (1 << 1)
|
||
|
+
|
||
|
+#define BAIKAL_LCRU_PCIE_POWER_CTL_BASE 0x50010 /* GPR2_RW */
|
||
|
+#define BAIKAL_LCRU_PCIE_POWER_CTL(x) ((x * 0x20) + BAIKAL_LCRU_POWER_CTL_BASE)
|
||
|
+#define BAIKAL_PCIE_PHY_CLK_REQ (1 << 27)
|
||
|
+#define BAIKAL_PCIE_APP_CLK_REQ (1 << 26)
|
||
|
+#define BAIKAL_PCIE_PERSTN (1 << 25)
|
||
|
+#define BAIKAL_PCIE_TURNOFF_REQ (1 << 24)
|
||
|
+#define BAIKAL_PCIE_REQ_EXIT_L1 (1 << 17)
|
||
|
+#define BAIKAL_PCIE_L1_PENDING (1 << 16)
|
||
|
+#define BAIKAL_PCIE_MAC_CLK_REQ (1 << 5)
|
||
|
+#define BAIKAL_PCIE_PCS_CLK_REQ (1 << 4)
|
||
|
+
|
||
|
+#define BAIKAL_LCRU_PCIE_MSI_TRANS_CTL0 0x500E8
|
||
|
+#define BAIKAL_PCIE_MSI_AWUSER_SHIFT 0
|
||
|
+#define BAIKAL_PCIE_MSI_AWUSER_MASK 0xF
|
||
|
+
|
||
|
+#define BAIKAL_LCRU_PCIE_MSI_TRANS_CTL2 0x500F8
|
||
|
+#define BAIKAL_PCIE_MSI_TRANS_EN(x) (1 << (9 + (x)))
|
||
|
+#define BAIKAL_PCIE_MSI_RCNUM(x) ((x) << (2 * (x)))
|
||
|
+#define BAIKAL_PCIE_MSI_RCNUM_MASK(x) (0x3 << (2 * (x)))
|
||
|
+
|
||
|
+inline u32 baikal_pcie_lcru_readl(struct regmap *lcru, u32 offset)
|
||
|
+{
|
||
|
+ u32 val;
|
||
|
+ regmap_read(lcru, offset, &val);
|
||
|
+ return val;
|
||
|
+}
|
||
|
+
|
||
|
+inline void baikal_pcie_lcru_writel(struct regmap *lcru, u32 offset, u32 val)
|
||
|
+{
|
||
|
+ regmap_write(lcru, offset, val);
|
||
|
+}
|
||
|
+
|
||
|
+#endif /* _LINUX_MFD_SYSCON_BAIKAL_LCRU_H_ */
|
||
|
--
|
||
|
2.31.1
|
||
|
|