mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-24 04:30:35 -04:00
Merge branch 'pci/controller/dwc-ultrarisc'
- Add UltraRISC DP1000 PCIe controller DT binding and driver (Jia Wang) * pci/controller/dwc-ultrarisc: PCI: ultrarisc: Add UltraRISC DP1000 PCIe Root Complex driver dt-bindings: PCI: Add UltraRISC DP1000 PCIe controller
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pci/ultrarisc,dp1000-pcie.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: UltraRISC DP1000 PCIe Host Controller
|
||||
|
||||
description:
|
||||
UltraRISC DP1000 SoC PCIe host controller is based on the DesignWare PCIe IP.
|
||||
|
||||
maintainers:
|
||||
- Xincheng Zhang <zhangxincheng@ultrarisc.com>
|
||||
- Jia Wang <wangjia@ultrarisc.com>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/pci/snps,dw-pcie.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ultrarisc,dp1000-pcie
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: Data Bus Interface (DBI) registers.
|
||||
- description: PCIe configuration space region.
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: dbi
|
||||
- const: config
|
||||
|
||||
num-lanes:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [4, 16]
|
||||
description: Number of lanes to use.
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: MSI interrupt
|
||||
- description: Legacy INTA interrupt
|
||||
- description: Legacy INTB interrupt
|
||||
- description: Legacy INTC interrupt
|
||||
- description: Legacy INTD interrupt
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: msi
|
||||
- const: inta
|
||||
- const: intb
|
||||
- const: intc
|
||||
- const: intd
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
pcie@21000000 {
|
||||
compatible = "ultrarisc,dp1000-pcie";
|
||||
reg = <0x0 0x21000000 0x0 0x01000000>,
|
||||
<0x0 0x4fff0000 0x0 0x00010000>;
|
||||
reg-names = "dbi", "config";
|
||||
ranges = <0x81000000 0x0 0x4fbf0000 0x0 0x4fbf0000 0x0 0x00400000>,
|
||||
<0x82000000 0x0 0x40000000 0x0 0x40000000 0x0 0x0fbf0000>,
|
||||
<0xc3000000 0x40 0x00000000 0x40 0x00000000 0xd 0x00000000>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
device_type = "pci";
|
||||
dma-coherent;
|
||||
bus-range = <0x0 0xff>;
|
||||
num-lanes = <16>;
|
||||
interrupt-parent = <&plic>;
|
||||
interrupts = <43>, <44>, <45>, <46>, <47>;
|
||||
interrupt-names = "msi", "inta", "intb", "intc", "intd";
|
||||
interrupt-map-mask = <0x0 0x0 0x0 0x7>;
|
||||
interrupt-map = <0x0 0x0 0x0 0x1 &plic 44>,
|
||||
<0x0 0x0 0x0 0x2 &plic 45>,
|
||||
<0x0 0x0 0x0 0x3 &plic 46>,
|
||||
<0x0 0x0 0x0 0x4 &plic 47>;
|
||||
};
|
||||
};
|
||||
@@ -20759,6 +20759,14 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml
|
||||
F: drivers/pci/controller/plda/pcie-starfive.c
|
||||
|
||||
PCIE DRIVER FOR ULTRARISC DP1000
|
||||
M: Xincheng Zhang <zhangxincheng@ultrarisc.com>
|
||||
M: Jia Wang <wangjia@ultrarisc.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/pci/ultrarisc,dp1000-pcie.yaml
|
||||
F: drivers/pci/controller/dwc/pcie-ultrarisc.c
|
||||
|
||||
PCIE ENDPOINT DRIVER FOR QUALCOMM
|
||||
M: Manivannan Sadhasivam <mani@kernel.org>
|
||||
L: linux-pci@vger.kernel.org
|
||||
|
||||
@@ -561,4 +561,17 @@ config PCIE_VISCONTI_HOST
|
||||
Say Y here if you want PCIe controller support on Toshiba Visconti SoC.
|
||||
This driver supports TMPV7708 SoC.
|
||||
|
||||
config PCIE_ULTRARISC
|
||||
tristate "UltraRISC PCIe host controller"
|
||||
depends on ARCH_ULTRARISC || COMPILE_TEST
|
||||
select PCIE_DW_HOST
|
||||
select PCI_MSI
|
||||
default y if ARCH_ULTRARISC
|
||||
help
|
||||
Enables support for the PCIe controller in the UltraRISC SoC.
|
||||
This driver supports UR-DP1000 SoC.
|
||||
|
||||
By default, this symbol is enabled when ARCH_ULTRARISC is active,
|
||||
requiring no further configuration on that platform.
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -39,6 +39,7 @@ obj-$(CONFIG_PCIE_RCAR_GEN4) += pcie-rcar-gen4.o
|
||||
obj-$(CONFIG_PCIE_SPACEMIT_K1) += pcie-spacemit-k1.o
|
||||
obj-$(CONFIG_PCIE_STM32_HOST) += pcie-stm32.o
|
||||
obj-$(CONFIG_PCIE_STM32_EP) += pcie-stm32-ep.o
|
||||
obj-$(CONFIG_PCIE_ULTRARISC) += pcie-ultrarisc.o
|
||||
|
||||
# The following drivers are for devices that use the generic ACPI
|
||||
# pci_root.c driver but don't support standard ECAM config access.
|
||||
|
||||
@@ -72,6 +72,8 @@
|
||||
|
||||
/* Synopsys-specific PCIe configuration registers */
|
||||
#define PCIE_PORT_FORCE 0x708
|
||||
/* Bit[7:0] LINK_NUM: Link Number. Not used for endpoint */
|
||||
#define PORT_LINK_NUM_MASK GENMASK(7, 0)
|
||||
#define PORT_FORCE_DO_DESKEW_FOR_SRIS BIT(23)
|
||||
|
||||
#define PCIE_PORT_AFR 0x70C
|
||||
@@ -99,6 +101,28 @@
|
||||
#define PCIE_PORT_LANE_SKEW 0x714
|
||||
#define PORT_LANE_SKEW_INSERT_MASK GENMASK(23, 0)
|
||||
|
||||
/*
|
||||
* PCIE_TIMER_CTRL_MAX_FUNC_NUM: Timer Control and Max Function Number
|
||||
* Register.
|
||||
*
|
||||
* This register holds the ack frequency, latency, replay, fast link
|
||||
* scaling timers, and max function number values.
|
||||
*
|
||||
* Bit[30:29] FAST_LINK_SCALING_FACTOR: Fast Link Timer Scaling Factor.
|
||||
* 0x0 (SF_1024): Scaling Factor is 1024 (1ms is 1us).
|
||||
* When the LTSSM is in Config or L12 Entry State, 1ms
|
||||
* timer is 2us, 2ms timer is 4us and 3ms timer is 6us.
|
||||
* 0x1 (SF_256): Scaling Factor is 256 (1ms is 4us)
|
||||
* 0x2 (SF_64): Scaling Factor is 64 (1ms is 16us)
|
||||
* 0x3 (SF_16): Scaling Factor is 16 (1ms is 64us)
|
||||
*/
|
||||
#define PCIE_TIMER_CTRL_MAX_FUNC_NUM 0x718
|
||||
#define PORT_FLT_SF_MASK GENMASK(30, 29)
|
||||
#define PORT_FLT_SF_VAL_1024 0x0
|
||||
#define PORT_FLT_SF_VAL_256 0x1
|
||||
#define PORT_FLT_SF_VAL_64 0x2
|
||||
#define PORT_FLT_SF_VAL_16 0x3
|
||||
|
||||
#define PCIE_PORT_DEBUG0 0x728
|
||||
#define PORT_LOGIC_LTSSM_STATE_MASK 0x3f
|
||||
#define PORT_LOGIC_LTSSM_STATE_L0 0x11
|
||||
|
||||
175
drivers/pci/controller/dwc/pcie-ultrarisc.c
Normal file
175
drivers/pci/controller/dwc/pcie-ultrarisc.c
Normal file
@@ -0,0 +1,175 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* DWC PCIe RC driver for UltraRISC SoCs
|
||||
*
|
||||
* Copyright (C) 2026 UltraRISC Technology (Shanghai) Co., Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/resource.h>
|
||||
|
||||
#include "pcie-designware.h"
|
||||
|
||||
#define PCIE_CUS_CORE 0x400000
|
||||
|
||||
#define LTSSM_ENABLE BIT(7)
|
||||
#define FAST_LINK_MODE BIT(12)
|
||||
#define HOLD_PHY_RST BIT(14)
|
||||
#define L1SUB_DISABLE BIT(15)
|
||||
|
||||
#define ULTRARISC_PCIE_COMP_TIMEOUT_65_210MS 0x6
|
||||
|
||||
static struct pci_ops ultrarisc_pci_ops = {
|
||||
.map_bus = dw_pcie_own_conf_map_bus,
|
||||
.read = pci_generic_config_read32,
|
||||
.write = pci_generic_config_write32,
|
||||
};
|
||||
|
||||
static int ultrarisc_pcie_host_init(struct dw_pcie_rp *pp)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
||||
struct pci_host_bridge *bridge = pp->bridge;
|
||||
u8 cap_exp;
|
||||
u32 val;
|
||||
|
||||
bridge->ops = &ultrarisc_pci_ops;
|
||||
|
||||
if (dw_pcie_link_up(pci))
|
||||
return 0;
|
||||
|
||||
val = dw_pcie_readl_dbi(pci, PCIE_CUS_CORE);
|
||||
val &= ~FAST_LINK_MODE;
|
||||
dw_pcie_writel_dbi(pci, PCIE_CUS_CORE, val);
|
||||
|
||||
val = dw_pcie_readl_dbi(pci, PCIE_TIMER_CTRL_MAX_FUNC_NUM);
|
||||
FIELD_MODIFY(PORT_FLT_SF_MASK, &val, PORT_FLT_SF_VAL_64);
|
||||
dw_pcie_writel_dbi(pci, PCIE_TIMER_CTRL_MAX_FUNC_NUM, val);
|
||||
|
||||
cap_exp = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
|
||||
val = dw_pcie_readl_dbi(pci, cap_exp + PCI_EXP_LNKCTL2);
|
||||
FIELD_MODIFY(PCI_EXP_LNKCTL2_TLS, &val, PCI_EXP_LNKCTL2_TLS_16_0GT);
|
||||
dw_pcie_writel_dbi(pci, cap_exp + PCI_EXP_LNKCTL2, val);
|
||||
|
||||
val = dw_pcie_readl_dbi(pci, PCIE_PORT_FORCE);
|
||||
FIELD_MODIFY(PORT_LINK_NUM_MASK, &val, 0);
|
||||
dw_pcie_writel_dbi(pci, PCIE_PORT_FORCE, val);
|
||||
|
||||
val = dw_pcie_readl_dbi(pci, cap_exp + PCI_EXP_DEVCTL2);
|
||||
FIELD_MODIFY(PCI_EXP_DEVCTL2_COMP_TIMEOUT, &val,
|
||||
ULTRARISC_PCIE_COMP_TIMEOUT_65_210MS);
|
||||
dw_pcie_writel_dbi(pci, cap_exp + PCI_EXP_DEVCTL2, val);
|
||||
|
||||
val = dw_pcie_readl_dbi(pci, PCIE_CUS_CORE);
|
||||
val &= ~(HOLD_PHY_RST | L1SUB_DISABLE);
|
||||
dw_pcie_writel_dbi(pci, PCIE_CUS_CORE, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ultrarisc_pcie_pme_turn_off(struct dw_pcie_rp *pp)
|
||||
{
|
||||
/*
|
||||
* DP1000 does not support sending PME_Turn_Off from the RC.
|
||||
* Keep this callback empty to skip the generic MSG TLP path.
|
||||
*/
|
||||
}
|
||||
|
||||
static const struct dw_pcie_host_ops ultrarisc_pcie_host_ops = {
|
||||
.init = ultrarisc_pcie_host_init,
|
||||
.pme_turn_off = ultrarisc_pcie_pme_turn_off,
|
||||
};
|
||||
|
||||
static int ultrarisc_pcie_start_link(struct dw_pcie *pci)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = dw_pcie_readl_dbi(pci, PCIE_CUS_CORE);
|
||||
val |= LTSSM_ENABLE;
|
||||
dw_pcie_writel_dbi(pci, PCIE_CUS_CORE, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dw_pcie_ops dw_pcie_ops = {
|
||||
.start_link = ultrarisc_pcie_start_link,
|
||||
};
|
||||
|
||||
static int ultrarisc_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dw_pcie_rp *pp;
|
||||
struct dw_pcie *pci;
|
||||
int ret;
|
||||
|
||||
pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
|
||||
if (!pci)
|
||||
return -ENOMEM;
|
||||
|
||||
pci->dev = dev;
|
||||
pci->ops = &dw_pcie_ops;
|
||||
|
||||
/* Set a default value suitable for at most 16 in and 16 out windows */
|
||||
pci->atu_size = SZ_8K;
|
||||
|
||||
pp = &pci->pp;
|
||||
|
||||
platform_set_drvdata(pdev, pci);
|
||||
|
||||
pp->num_vectors = MAX_MSI_IRQS;
|
||||
/* No L2/L3 Ready indication is available on this platform */
|
||||
pp->skip_l23_ready = true;
|
||||
pp->ops = &ultrarisc_pcie_host_ops;
|
||||
|
||||
ret = dw_pcie_host_init(pp);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to initialize host\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ultrarisc_pcie_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct dw_pcie *pci = dev_get_drvdata(dev);
|
||||
|
||||
return dw_pcie_suspend_noirq(pci);
|
||||
}
|
||||
|
||||
static int ultrarisc_pcie_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct dw_pcie *pci = dev_get_drvdata(dev);
|
||||
|
||||
return dw_pcie_resume_noirq(pci);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops ultrarisc_pcie_pm_ops = {
|
||||
NOIRQ_SYSTEM_SLEEP_PM_OPS(ultrarisc_pcie_suspend_noirq,
|
||||
ultrarisc_pcie_resume_noirq)
|
||||
};
|
||||
|
||||
static const struct of_device_id ultrarisc_pcie_of_match[] = {
|
||||
{
|
||||
.compatible = "ultrarisc,dp1000-pcie",
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ultrarisc_pcie_of_match);
|
||||
|
||||
static struct platform_driver ultrarisc_pcie_driver = {
|
||||
.driver = {
|
||||
.name = "ultrarisc-pcie",
|
||||
.of_match_table = ultrarisc_pcie_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
.pm = &ultrarisc_pcie_pm_ops,
|
||||
},
|
||||
.probe = ultrarisc_pcie_probe,
|
||||
};
|
||||
builtin_platform_driver(ultrarisc_pcie_driver);
|
||||
|
||||
MODULE_DESCRIPTION("UltraRISC DP1000 DWC PCIe host controller");
|
||||
MODULE_LICENSE("GPL");
|
||||
Reference in New Issue
Block a user