1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2025, The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/clk.h> 7 #include <linux/clk-provider.h> 8 #include <linux/delay.h> 9 #include <linux/err.h> 10 #include <linux/io.h> 11 #include <linux/mfd/syscon.h> 12 #include <linux/module.h> 13 #include <linux/of_device.h> 14 #include <linux/of.h> 15 #include <linux/phy/phy.h> 16 #include <linux/platform_device.h> 17 #include <linux/regmap.h> 18 #include <linux/reset.h> 19 #include <linux/units.h> 20 21 #define RST_ASSERT_DELAY_MIN_US 100 22 #define RST_ASSERT_DELAY_MAX_US 150 23 #define PIPE_CLK_DELAY_MIN_US 5000 24 #define PIPE_CLK_DELAY_MAX_US 5100 25 #define CLK_EN_DELAY_MIN_US 30 26 #define CLK_EN_DELAY_MAX_US 50 27 #define CDR_CTRL_REG_1 0x80 28 #define CDR_CTRL_REG_2 0x84 29 #define CDR_CTRL_REG_3 0x88 30 #define CDR_CTRL_REG_4 0x8c 31 #define CDR_CTRL_REG_5 0x90 32 #define CDR_CTRL_REG_6 0x94 33 #define CDR_CTRL_REG_7 0x98 34 #define SSCG_CTRL_REG_1 0x9c 35 #define SSCG_CTRL_REG_2 0xa0 36 #define SSCG_CTRL_REG_3 0xa4 37 #define SSCG_CTRL_REG_4 0xa8 38 #define SSCG_CTRL_REG_5 0xac 39 #define SSCG_CTRL_REG_6 0xb0 40 #define PCS_INTERNAL_CONTROL_2 0x2d8 41 42 #define PHY_CFG_PLLCFG 0x220 43 #define PHY_CFG_EIOS_DTCT_REG 0x3e4 44 #define PHY_CFG_GEN3_ALIGN_HOLDOFF_TIME 0x3e8 45 46 enum qcom_uniphy_pcie_type { 47 PHY_TYPE_PCIE = 1, 48 PHY_TYPE_PCIE_GEN2, 49 PHY_TYPE_PCIE_GEN3, 50 }; 51 52 struct qcom_uniphy_pcie_regs { 53 u32 offset; 54 u32 val; 55 }; 56 57 struct qcom_uniphy_pcie_data { 58 int lane_offset; /* offset between the lane register bases */ 59 u32 phy_type; 60 const struct qcom_uniphy_pcie_regs *init_seq; 61 u32 init_seq_num; 62 u32 pipe_clk_rate; 63 }; 64 65 struct qcom_uniphy_pcie { 66 struct phy phy; 67 struct device *dev; 68 const struct qcom_uniphy_pcie_data *data; 69 struct clk_bulk_data *clks; 70 int num_clks; 71 struct reset_control *resets; 72 void __iomem *base; 73 int lanes; 74 }; 75 76 #define phy_to_dw_phy(x) container_of((x), struct qca_uni_pcie_phy, phy) 77 78 static const struct qcom_uniphy_pcie_regs ipq5332_regs[] = { 79 { 80 .offset = PHY_CFG_PLLCFG, 81 .val = 0x30, 82 }, { 83 .offset = PHY_CFG_EIOS_DTCT_REG, 84 .val = 0x53ef, 85 }, { 86 .offset = PHY_CFG_GEN3_ALIGN_HOLDOFF_TIME, 87 .val = 0xcf, 88 }, 89 }; 90 91 static const struct qcom_uniphy_pcie_data ipq5332_data = { 92 .lane_offset = 0x800, 93 .phy_type = PHY_TYPE_PCIE_GEN3, 94 .init_seq = ipq5332_regs, 95 .init_seq_num = ARRAY_SIZE(ipq5332_regs), 96 .pipe_clk_rate = 250 * MEGA, 97 }; 98 99 static void qcom_uniphy_pcie_init(struct qcom_uniphy_pcie *phy) 100 { 101 const struct qcom_uniphy_pcie_data *data = phy->data; 102 const struct qcom_uniphy_pcie_regs *init_seq; 103 void __iomem *base = phy->base; 104 int lane, i; 105 106 for (lane = 0; lane < phy->lanes; lane++) { 107 init_seq = data->init_seq; 108 109 for (i = 0; i < data->init_seq_num; i++) 110 writel(init_seq[i].val, base + init_seq[i].offset); 111 112 base += data->lane_offset; 113 } 114 } 115 116 static int qcom_uniphy_pcie_power_off(struct phy *x) 117 { 118 struct qcom_uniphy_pcie *phy = phy_get_drvdata(x); 119 120 clk_bulk_disable_unprepare(phy->num_clks, phy->clks); 121 122 return reset_control_assert(phy->resets); 123 } 124 125 static int qcom_uniphy_pcie_power_on(struct phy *x) 126 { 127 struct qcom_uniphy_pcie *phy = phy_get_drvdata(x); 128 int ret; 129 130 ret = reset_control_assert(phy->resets); 131 if (ret) { 132 dev_err(phy->dev, "reset assert failed (%d)\n", ret); 133 return ret; 134 } 135 136 usleep_range(RST_ASSERT_DELAY_MIN_US, RST_ASSERT_DELAY_MAX_US); 137 138 ret = reset_control_deassert(phy->resets); 139 if (ret) { 140 dev_err(phy->dev, "reset deassert failed (%d)\n", ret); 141 return ret; 142 } 143 144 usleep_range(PIPE_CLK_DELAY_MIN_US, PIPE_CLK_DELAY_MAX_US); 145 146 ret = clk_bulk_prepare_enable(phy->num_clks, phy->clks); 147 if (ret) { 148 dev_err(phy->dev, "clk prepare and enable failed %d\n", ret); 149 return ret; 150 } 151 152 usleep_range(CLK_EN_DELAY_MIN_US, CLK_EN_DELAY_MAX_US); 153 154 qcom_uniphy_pcie_init(phy); 155 156 return 0; 157 } 158 159 static inline int qcom_uniphy_pcie_get_resources(struct platform_device *pdev, 160 struct qcom_uniphy_pcie *phy) 161 { 162 struct resource *res; 163 164 phy->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 165 if (IS_ERR(phy->base)) 166 return PTR_ERR(phy->base); 167 168 phy->num_clks = devm_clk_bulk_get_all(phy->dev, &phy->clks); 169 if (phy->num_clks < 0) 170 return phy->num_clks; 171 172 phy->resets = devm_reset_control_array_get_exclusive(phy->dev); 173 if (IS_ERR(phy->resets)) 174 return PTR_ERR(phy->resets); 175 176 return 0; 177 } 178 179 /* 180 * Register a fixed rate pipe clock. 181 * 182 * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate 183 * controls it. The <s>_pipe_clk coming out of the GCC is requested 184 * by the PHY driver for its operations. 185 * We register the <s>_pipe_clksrc here. The gcc driver takes care 186 * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk. 187 * Below picture shows this relationship. 188 * 189 * +---------------+ 190 * | PHY block |<<---------------------------------------+ 191 * | | | 192 * | +-------+ | +-----+ | 193 * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+ 194 * clk | +-------+ | +-----+ 195 * +---------------+ 196 */ 197 static inline int phy_pipe_clk_register(struct qcom_uniphy_pcie *phy, int id) 198 { 199 const struct qcom_uniphy_pcie_data *data = phy->data; 200 struct clk_hw *hw; 201 char name[64]; 202 203 snprintf(name, sizeof(name), "phy%d_pipe_clk_src", id); 204 hw = devm_clk_hw_register_fixed_rate(phy->dev, name, NULL, 0, 205 data->pipe_clk_rate); 206 if (IS_ERR(hw)) 207 return dev_err_probe(phy->dev, PTR_ERR(hw), 208 "Unable to register %s\n", name); 209 210 return devm_of_clk_add_hw_provider(phy->dev, of_clk_hw_simple_get, hw); 211 } 212 213 static const struct of_device_id qcom_uniphy_pcie_id_table[] = { 214 { 215 .compatible = "qcom,ipq5332-uniphy-pcie-phy", 216 .data = &ipq5332_data, 217 }, { 218 /* Sentinel */ 219 }, 220 }; 221 MODULE_DEVICE_TABLE(of, qcom_uniphy_pcie_id_table); 222 223 static const struct phy_ops pcie_ops = { 224 .power_on = qcom_uniphy_pcie_power_on, 225 .power_off = qcom_uniphy_pcie_power_off, 226 .owner = THIS_MODULE, 227 }; 228 229 static int qcom_uniphy_pcie_probe(struct platform_device *pdev) 230 { 231 struct phy_provider *phy_provider; 232 struct device *dev = &pdev->dev; 233 struct qcom_uniphy_pcie *phy; 234 struct phy *generic_phy; 235 int ret; 236 237 phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); 238 if (!phy) 239 return -ENOMEM; 240 241 platform_set_drvdata(pdev, phy); 242 phy->dev = &pdev->dev; 243 244 phy->data = of_device_get_match_data(dev); 245 if (!phy->data) 246 return -EINVAL; 247 248 ret = of_property_read_u32(dev_of_node(dev), "num-lanes", &phy->lanes); 249 if (ret) 250 return dev_err_probe(dev, ret, "Couldn't read num-lanes\n"); 251 252 ret = qcom_uniphy_pcie_get_resources(pdev, phy); 253 if (ret < 0) 254 return dev_err_probe(&pdev->dev, ret, 255 "failed to get resources: %d\n", ret); 256 257 generic_phy = devm_phy_create(phy->dev, NULL, &pcie_ops); 258 if (IS_ERR(generic_phy)) 259 return PTR_ERR(generic_phy); 260 261 phy_set_drvdata(generic_phy, phy); 262 263 ret = phy_pipe_clk_register(phy, generic_phy->id); 264 if (ret) 265 dev_err(&pdev->dev, "failed to register phy pipe clk\n"); 266 267 phy_provider = devm_of_phy_provider_register(phy->dev, 268 of_phy_simple_xlate); 269 if (IS_ERR(phy_provider)) 270 return PTR_ERR(phy_provider); 271 272 return 0; 273 } 274 275 static struct platform_driver qcom_uniphy_pcie_driver = { 276 .probe = qcom_uniphy_pcie_probe, 277 .driver = { 278 .name = "qcom-uniphy-pcie", 279 .of_match_table = qcom_uniphy_pcie_id_table, 280 }, 281 }; 282 283 module_platform_driver(qcom_uniphy_pcie_driver); 284 285 MODULE_DESCRIPTION("PCIE QCOM UNIPHY driver"); 286 MODULE_LICENSE("GPL"); 287