Skip to content

Commit 0157e11

Browse files
committed
Merge branch 'pci/controller/sophgo'
- Check for existence of struct cdns_pcie.ops before using it to allow Cadence drivers that don't need to supply ops (Chen Wang) - Add DT binding and driver for the Sophgo SG2042 PCIe controller (Chen Wang) * pci/controller/sophgo: PCI: sg2042: Add Sophgo SG2042 PCIe driver PCI: cadence: Check for the existence of cdns_pcie::ops before using it dt-bindings: pci: Add Sophgo SG2042 PCIe host
2 parents 2ee6181 + 1c72774 commit 0157e11

File tree

7 files changed

+215
-6
lines changed

7 files changed

+215
-6
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/pci/sophgo,sg2042-pcie-host.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: Sophgo SG2042 PCIe Host (Cadence PCIe Wrapper)
8+
9+
description:
10+
Sophgo SG2042 PCIe host controller is based on the Cadence PCIe core.
11+
12+
maintainers:
13+
- Chen Wang <unicorn_wang@outlook.com>
14+
15+
properties:
16+
compatible:
17+
const: sophgo,sg2042-pcie-host
18+
19+
reg:
20+
maxItems: 2
21+
22+
reg-names:
23+
items:
24+
- const: reg
25+
- const: cfg
26+
27+
vendor-id:
28+
const: 0x1f1c
29+
30+
device-id:
31+
const: 0x2042
32+
33+
msi-parent: true
34+
35+
allOf:
36+
- $ref: cdns-pcie-host.yaml#
37+
38+
required:
39+
- compatible
40+
- reg
41+
- reg-names
42+
43+
unevaluatedProperties: false
44+
45+
examples:
46+
- |
47+
#include <dt-bindings/interrupt-controller/irq.h>
48+
49+
pcie@62000000 {
50+
compatible = "sophgo,sg2042-pcie-host";
51+
device_type = "pci";
52+
reg = <0x62000000 0x00800000>,
53+
<0x48000000 0x00001000>;
54+
reg-names = "reg", "cfg";
55+
#address-cells = <3>;
56+
#size-cells = <2>;
57+
ranges = <0x81000000 0 0x00000000 0xde000000 0 0x00010000>,
58+
<0x82000000 0 0xd0400000 0xd0400000 0 0x0d000000>;
59+
bus-range = <0x00 0xff>;
60+
vendor-id = <0x1f1c>;
61+
device-id = <0x2042>;
62+
cdns,no-bar-match-nbits = <48>;
63+
msi-parent = <&msi>;
64+
};

drivers/pci/controller/cadence/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ config PCIE_CADENCE_PLAT_EP
4242
endpoint mode. This PCIe controller may be embedded into many
4343
different vendors SoCs.
4444

45+
config PCIE_SG2042_HOST
46+
tristate "Sophgo SG2042 PCIe controller (host mode)"
47+
depends on OF && (ARCH_SOPHGO || COMPILE_TEST)
48+
select PCIE_CADENCE_HOST
49+
help
50+
Say Y here if you want to support the Sophgo SG2042 PCIe platform
51+
controller in host mode. Sophgo SG2042 PCIe controller uses Cadence
52+
PCIe core.
53+
4554
config PCI_J721E
4655
tristate
4756
select PCIE_CADENCE_HOST if PCI_J721E_HOST != n
@@ -67,4 +76,5 @@ config PCI_J721E_EP
6776
Say Y here if you want to support the TI J721E PCIe platform
6877
controller in endpoint mode. TI J721E PCIe controller uses Cadence PCIe
6978
core.
79+
7080
endmenu

drivers/pci/controller/cadence/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ obj-$(CONFIG_PCIE_CADENCE_HOST) += pcie-cadence-host.o
44
obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep.o
55
obj-$(CONFIG_PCIE_CADENCE_PLAT) += pcie-cadence-plat.o
66
obj-$(CONFIG_PCI_J721E) += pci-j721e.o
7+
obj-$(CONFIG_PCIE_SG2042_HOST) += pcie-sg2042.o

drivers/pci/controller/cadence/pcie-cadence-host.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
531531
cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR1(0), addr1);
532532
cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC1(0), desc1);
533533

534-
if (pcie->ops->cpu_addr_fixup)
534+
if (pcie->ops && pcie->ops->cpu_addr_fixup)
535535
cpu_addr = pcie->ops->cpu_addr_fixup(pcie, cpu_addr);
536536

537537
addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(12) |

drivers/pci/controller/cadence/pcie-cadence.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ void cdns_pcie_set_outbound_region(struct cdns_pcie *pcie, u8 busnr, u8 fn,
106106
cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC1(r), desc1);
107107

108108
/* Set the CPU address */
109-
if (pcie->ops->cpu_addr_fixup)
109+
if (pcie->ops && pcie->ops->cpu_addr_fixup)
110110
cpu_addr = pcie->ops->cpu_addr_fixup(pcie, cpu_addr);
111111

112112
addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(nbits) |
@@ -137,7 +137,7 @@ void cdns_pcie_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie,
137137
}
138138

139139
/* Set the CPU address */
140-
if (pcie->ops->cpu_addr_fixup)
140+
if (pcie->ops && pcie->ops->cpu_addr_fixup)
141141
cpu_addr = pcie->ops->cpu_addr_fixup(pcie, cpu_addr);
142142

143143
addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(17) |

drivers/pci/controller/cadence/pcie-cadence.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -494,21 +494,21 @@ static inline u32 cdns_pcie_ep_fn_readl(struct cdns_pcie *pcie, u8 fn, u32 reg)
494494

495495
static inline int cdns_pcie_start_link(struct cdns_pcie *pcie)
496496
{
497-
if (pcie->ops->start_link)
497+
if (pcie->ops && pcie->ops->start_link)
498498
return pcie->ops->start_link(pcie);
499499

500500
return 0;
501501
}
502502

503503
static inline void cdns_pcie_stop_link(struct cdns_pcie *pcie)
504504
{
505-
if (pcie->ops->stop_link)
505+
if (pcie->ops && pcie->ops->stop_link)
506506
pcie->ops->stop_link(pcie);
507507
}
508508

509509
static inline bool cdns_pcie_link_up(struct cdns_pcie *pcie)
510510
{
511-
if (pcie->ops->link_up)
511+
if (pcie->ops && pcie->ops->link_up)
512512
return pcie->ops->link_up(pcie);
513513

514514
return true;
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* pcie-sg2042 - PCIe controller driver for Sophgo SG2042 SoC
4+
*
5+
* Copyright (C) 2025 Sophgo Technology Inc.
6+
* Copyright (C) 2025 Chen Wang <unicorn_wang@outlook.com>
7+
*/
8+
9+
#include <linux/mod_devicetable.h>
10+
#include <linux/pci.h>
11+
#include <linux/platform_device.h>
12+
#include <linux/pm_runtime.h>
13+
14+
#include "pcie-cadence.h"
15+
16+
/*
17+
* SG2042 only supports 4-byte aligned access, so for the rootbus (i.e. to
18+
* read/write the Root Port itself, read32/write32 is required. For
19+
* non-rootbus (i.e. to read/write the PCIe peripheral registers, supports
20+
* 1/2/4 byte aligned access, so directly using read/write should be fine.
21+
*/
22+
23+
static struct pci_ops sg2042_pcie_root_ops = {
24+
.map_bus = cdns_pci_map_bus,
25+
.read = pci_generic_config_read32,
26+
.write = pci_generic_config_write32,
27+
};
28+
29+
static struct pci_ops sg2042_pcie_child_ops = {
30+
.map_bus = cdns_pci_map_bus,
31+
.read = pci_generic_config_read,
32+
.write = pci_generic_config_write,
33+
};
34+
35+
static int sg2042_pcie_probe(struct platform_device *pdev)
36+
{
37+
struct device *dev = &pdev->dev;
38+
struct pci_host_bridge *bridge;
39+
struct cdns_pcie *pcie;
40+
struct cdns_pcie_rc *rc;
41+
int ret;
42+
43+
bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc));
44+
if (!bridge)
45+
return dev_err_probe(dev, -ENOMEM, "Failed to alloc host bridge!\n");
46+
47+
bridge->ops = &sg2042_pcie_root_ops;
48+
bridge->child_ops = &sg2042_pcie_child_ops;
49+
50+
rc = pci_host_bridge_priv(bridge);
51+
pcie = &rc->pcie;
52+
pcie->dev = dev;
53+
54+
platform_set_drvdata(pdev, pcie);
55+
56+
pm_runtime_set_active(dev);
57+
pm_runtime_no_callbacks(dev);
58+
devm_pm_runtime_enable(dev);
59+
60+
ret = cdns_pcie_init_phy(dev, pcie);
61+
if (ret)
62+
return dev_err_probe(dev, ret, "Failed to init phy!\n");
63+
64+
ret = cdns_pcie_host_setup(rc);
65+
if (ret) {
66+
dev_err_probe(dev, ret, "Failed to setup host!\n");
67+
cdns_pcie_disable_phy(pcie);
68+
return ret;
69+
}
70+
71+
return 0;
72+
}
73+
74+
static void sg2042_pcie_remove(struct platform_device *pdev)
75+
{
76+
struct cdns_pcie *pcie = platform_get_drvdata(pdev);
77+
struct device *dev = &pdev->dev;
78+
struct cdns_pcie_rc *rc;
79+
80+
rc = container_of(pcie, struct cdns_pcie_rc, pcie);
81+
cdns_pcie_host_disable(rc);
82+
83+
cdns_pcie_disable_phy(pcie);
84+
85+
pm_runtime_disable(dev);
86+
}
87+
88+
static int sg2042_pcie_suspend_noirq(struct device *dev)
89+
{
90+
struct cdns_pcie *pcie = dev_get_drvdata(dev);
91+
92+
cdns_pcie_disable_phy(pcie);
93+
94+
return 0;
95+
}
96+
97+
static int sg2042_pcie_resume_noirq(struct device *dev)
98+
{
99+
struct cdns_pcie *pcie = dev_get_drvdata(dev);
100+
int ret;
101+
102+
ret = cdns_pcie_enable_phy(pcie);
103+
if (ret) {
104+
dev_err(dev, "failed to enable PHY\n");
105+
return ret;
106+
}
107+
108+
return 0;
109+
}
110+
111+
static DEFINE_NOIRQ_DEV_PM_OPS(sg2042_pcie_pm_ops,
112+
sg2042_pcie_suspend_noirq,
113+
sg2042_pcie_resume_noirq);
114+
115+
static const struct of_device_id sg2042_pcie_of_match[] = {
116+
{ .compatible = "sophgo,sg2042-pcie-host" },
117+
{},
118+
};
119+
MODULE_DEVICE_TABLE(of, sg2042_pcie_of_match);
120+
121+
static struct platform_driver sg2042_pcie_driver = {
122+
.driver = {
123+
.name = "sg2042-pcie",
124+
.of_match_table = sg2042_pcie_of_match,
125+
.pm = pm_sleep_ptr(&sg2042_pcie_pm_ops),
126+
},
127+
.probe = sg2042_pcie_probe,
128+
.remove = sg2042_pcie_remove,
129+
};
130+
module_platform_driver(sg2042_pcie_driver);
131+
132+
MODULE_LICENSE("GPL");
133+
MODULE_DESCRIPTION("PCIe controller driver for SG2042 SoCs");
134+
MODULE_AUTHOR("Chen Wang <unicorn_wang@outlook.com>");

0 commit comments

Comments
 (0)