1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * DWC PCIe RC driver for UltraRISC SoCs 4 * 5 * Copyright (C) 2026 UltraRISC Technology (Shanghai) Co., Ltd. 6 */ 7 8 #include <linux/clk.h> 9 #include <linux/kernel.h> 10 #include <linux/module.h> 11 #include <linux/of_device.h> 12 #include <linux/pci.h> 13 #include <linux/platform_device.h> 14 #include <linux/resource.h> 15 16 #include "pcie-designware.h" 17 18 #define PCIE_CUS_CORE 0x400000 19 20 #define LTSSM_ENABLE BIT(7) 21 #define FAST_LINK_MODE BIT(12) 22 #define HOLD_PHY_RST BIT(14) 23 #define L1SUB_DISABLE BIT(15) 24 25 #define ULTRARISC_PCIE_COMP_TIMEOUT_65_210MS 0x6 26 27 struct ultrarisc_pcie { 28 struct dw_pcie pci; 29 struct clk_bulk_data *clks; 30 int num_clks; 31 }; 32 33 static struct pci_ops ultrarisc_pci_ops = { 34 .map_bus = dw_pcie_own_conf_map_bus, 35 .read = pci_generic_config_read32, 36 .write = pci_generic_config_write32, 37 }; 38 39 static int ultrarisc_pcie_host_init(struct dw_pcie_rp *pp) 40 { 41 struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 42 struct pci_host_bridge *bridge = pp->bridge; 43 u8 cap_exp; 44 u32 val; 45 46 bridge->ops = &ultrarisc_pci_ops; 47 48 if (dw_pcie_link_up(pci)) 49 return 0; 50 51 val = dw_pcie_readl_dbi(pci, PCIE_CUS_CORE); 52 val &= ~FAST_LINK_MODE; 53 dw_pcie_writel_dbi(pci, PCIE_CUS_CORE, val); 54 55 val = dw_pcie_readl_dbi(pci, PCIE_TIMER_CTRL_MAX_FUNC_NUM); 56 FIELD_MODIFY(PORT_FLT_SF_MASK, &val, PORT_FLT_SF_VAL_64); 57 dw_pcie_writel_dbi(pci, PCIE_TIMER_CTRL_MAX_FUNC_NUM, val); 58 59 cap_exp = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); 60 val = dw_pcie_readl_dbi(pci, cap_exp + PCI_EXP_LNKCTL2); 61 FIELD_MODIFY(PCI_EXP_LNKCTL2_TLS, &val, PCI_EXP_LNKCTL2_TLS_16_0GT); 62 dw_pcie_writel_dbi(pci, cap_exp + PCI_EXP_LNKCTL2, val); 63 64 val = dw_pcie_readl_dbi(pci, PCIE_PORT_FORCE); 65 FIELD_MODIFY(PORT_LINK_NUM_MASK, &val, 0); 66 dw_pcie_writel_dbi(pci, PCIE_PORT_FORCE, val); 67 68 val = dw_pcie_readl_dbi(pci, cap_exp + PCI_EXP_DEVCTL2); 69 FIELD_MODIFY(PCI_EXP_DEVCTL2_COMP_TIMEOUT, &val, 70 ULTRARISC_PCIE_COMP_TIMEOUT_65_210MS); 71 dw_pcie_writel_dbi(pci, cap_exp + PCI_EXP_DEVCTL2, val); 72 73 val = dw_pcie_readl_dbi(pci, PCIE_CUS_CORE); 74 val &= ~(HOLD_PHY_RST | L1SUB_DISABLE); 75 dw_pcie_writel_dbi(pci, PCIE_CUS_CORE, val); 76 77 return 0; 78 } 79 80 static void ultrarisc_pcie_pme_turn_off(struct dw_pcie_rp *pp) 81 { 82 /* 83 * DP1000 does not support sending PME_Turn_Off from the RC. 84 * Keep this callback empty to skip the generic MSG TLP path. 85 */ 86 } 87 88 static const struct dw_pcie_host_ops ultrarisc_pcie_host_ops = { 89 .init = ultrarisc_pcie_host_init, 90 .pme_turn_off = ultrarisc_pcie_pme_turn_off, 91 }; 92 93 static int ultrarisc_pcie_start_link(struct dw_pcie *pci) 94 { 95 u32 val; 96 97 val = dw_pcie_readl_dbi(pci, PCIE_CUS_CORE); 98 val |= LTSSM_ENABLE; 99 dw_pcie_writel_dbi(pci, PCIE_CUS_CORE, val); 100 101 return 0; 102 } 103 104 static const struct dw_pcie_ops dw_pcie_ops = { 105 .start_link = ultrarisc_pcie_start_link, 106 }; 107 108 static int ultrarisc_pcie_enable_clks(struct ultrarisc_pcie *ultra) 109 { 110 return clk_bulk_prepare_enable(ultra->num_clks, ultra->clks); 111 } 112 113 static void ultrarisc_pcie_disable_clks(void *data) 114 { 115 struct ultrarisc_pcie *ultra = data; 116 117 clk_bulk_disable_unprepare(ultra->num_clks, ultra->clks); 118 } 119 120 static int ultrarisc_pcie_init_clks(struct ultrarisc_pcie *ultra) 121 { 122 struct device *dev = ultra->pci.dev; 123 int ret; 124 125 ultra->num_clks = devm_clk_bulk_get_all(dev, &ultra->clks); 126 if (ultra->num_clks < 0) 127 return dev_err_probe(dev, ultra->num_clks, "Failed to get clocks\n"); 128 129 ret = ultrarisc_pcie_enable_clks(ultra); 130 if (ret) 131 return dev_err_probe(dev, ret, "Failed to enable clocks\n"); 132 133 return devm_add_action_or_reset(dev, ultrarisc_pcie_disable_clks, ultra); 134 } 135 136 static int ultrarisc_pcie_probe(struct platform_device *pdev) 137 { 138 struct ultrarisc_pcie *ultra; 139 struct device *dev = &pdev->dev; 140 struct dw_pcie_rp *pp; 141 struct dw_pcie *pci; 142 int ret; 143 144 ultra = devm_kzalloc(dev, sizeof(*ultra), GFP_KERNEL); 145 if (!ultra) 146 return -ENOMEM; 147 148 pci = &ultra->pci; 149 pci->dev = dev; 150 pci->ops = &dw_pcie_ops; 151 152 /* Set a default value suitable for at most 16 in and 16 out windows */ 153 pci->atu_size = SZ_8K; 154 155 pp = &pci->pp; 156 157 platform_set_drvdata(pdev, ultra); 158 159 ret = ultrarisc_pcie_init_clks(ultra); 160 if (ret) 161 return ret; 162 163 pp->num_vectors = MAX_MSI_IRQS; 164 /* No L2/L3 Ready indication is available on this platform */ 165 pp->skip_l23_ready = true; 166 pp->ops = &ultrarisc_pcie_host_ops; 167 168 ret = dw_pcie_host_init(pp); 169 if (ret) { 170 dev_err(dev, "Failed to initialize host\n"); 171 return ret; 172 } 173 174 return 0; 175 } 176 177 static int ultrarisc_pcie_suspend_noirq(struct device *dev) 178 { 179 struct ultrarisc_pcie *ultra = dev_get_drvdata(dev); 180 struct dw_pcie *pci = &ultra->pci; 181 int ret; 182 183 /* 184 * A failed resume leaves the DWC suspended and the clocks disabled. 185 * A later suspend must not access the controller or disable them again. 186 */ 187 if (pci->suspended) 188 return 0; 189 190 ret = dw_pcie_suspend_noirq(pci); 191 if (ret) 192 return ret; 193 194 if (pci->suspended) 195 ultrarisc_pcie_disable_clks(ultra); 196 197 return 0; 198 } 199 200 static int ultrarisc_pcie_resume_noirq(struct device *dev) 201 { 202 struct ultrarisc_pcie *ultra = dev_get_drvdata(dev); 203 struct dw_pcie *pci = &ultra->pci; 204 int ret; 205 206 if (pci->suspended) { 207 ret = ultrarisc_pcie_enable_clks(ultra); 208 if (ret) 209 return ret; 210 211 ret = dw_pcie_resume_noirq(pci); 212 if (ret) { 213 ultrarisc_pcie_disable_clks(ultra); 214 return ret; 215 } 216 } 217 218 return 0; 219 } 220 221 static const struct dev_pm_ops ultrarisc_pcie_pm_ops = { 222 NOIRQ_SYSTEM_SLEEP_PM_OPS(ultrarisc_pcie_suspend_noirq, 223 ultrarisc_pcie_resume_noirq) 224 }; 225 226 static const struct of_device_id ultrarisc_pcie_of_match[] = { 227 { 228 .compatible = "ultrarisc,dp1000-pcie", 229 }, 230 {}, 231 }; 232 MODULE_DEVICE_TABLE(of, ultrarisc_pcie_of_match); 233 234 static struct platform_driver ultrarisc_pcie_driver = { 235 .driver = { 236 .name = "ultrarisc-pcie", 237 .of_match_table = ultrarisc_pcie_of_match, 238 .suppress_bind_attrs = true, 239 .pm = &ultrarisc_pcie_pm_ops, 240 }, 241 .probe = ultrarisc_pcie_probe, 242 }; 243 module_platform_driver(ultrarisc_pcie_driver); 244 245 MODULE_DESCRIPTION("UltraRISC DP1000 DWC PCIe host controller"); 246 MODULE_LICENSE("GPL"); 247