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 ipq5018_regs[] = {
79 {
80 .offset = SSCG_CTRL_REG_4,
81 .val = 0x1cb9,
82 }, {
83 .offset = SSCG_CTRL_REG_5,
84 .val = 0x023a,
85 }, {
86 .offset = SSCG_CTRL_REG_3,
87 .val = 0xd360,
88 }, {
89 .offset = SSCG_CTRL_REG_1,
90 .val = 0x1,
91 }, {
92 .offset = SSCG_CTRL_REG_2,
93 .val = 0xeb,
94 }, {
95 .offset = CDR_CTRL_REG_4,
96 .val = 0x3f9,
97 }, {
98 .offset = CDR_CTRL_REG_5,
99 .val = 0x1c9,
100 }, {
101 .offset = CDR_CTRL_REG_2,
102 .val = 0x419,
103 }, {
104 .offset = CDR_CTRL_REG_1,
105 .val = 0x200,
106 }, {
107 .offset = PCS_INTERNAL_CONTROL_2,
108 .val = 0xf101,
109 },
110 };
111
112 static const struct qcom_uniphy_pcie_regs ipq5332_regs[] = {
113 {
114 .offset = PHY_CFG_PLLCFG,
115 .val = 0x30,
116 }, {
117 .offset = PHY_CFG_EIOS_DTCT_REG,
118 .val = 0x53ef,
119 }, {
120 .offset = PHY_CFG_GEN3_ALIGN_HOLDOFF_TIME,
121 .val = 0xcf,
122 },
123 };
124
125 static const struct qcom_uniphy_pcie_data ipq5018_data = {
126 .lane_offset = 0x800,
127 .phy_type = PHY_TYPE_PCIE_GEN2,
128 .init_seq = ipq5018_regs,
129 .init_seq_num = ARRAY_SIZE(ipq5018_regs),
130 .pipe_clk_rate = 125 * MEGA,
131 };
132
133 static const struct qcom_uniphy_pcie_data ipq5332_data = {
134 .lane_offset = 0x800,
135 .phy_type = PHY_TYPE_PCIE_GEN3,
136 .init_seq = ipq5332_regs,
137 .init_seq_num = ARRAY_SIZE(ipq5332_regs),
138 .pipe_clk_rate = 250 * MEGA,
139 };
140
qcom_uniphy_pcie_init(struct qcom_uniphy_pcie * phy)141 static void qcom_uniphy_pcie_init(struct qcom_uniphy_pcie *phy)
142 {
143 const struct qcom_uniphy_pcie_data *data = phy->data;
144 const struct qcom_uniphy_pcie_regs *init_seq;
145 void __iomem *base = phy->base;
146 int lane, i;
147
148 for (lane = 0; lane < phy->lanes; lane++) {
149 init_seq = data->init_seq;
150
151 for (i = 0; i < data->init_seq_num; i++)
152 writel(init_seq[i].val, base + init_seq[i].offset);
153
154 base += data->lane_offset;
155 }
156 }
157
qcom_uniphy_pcie_power_off(struct phy * x)158 static int qcom_uniphy_pcie_power_off(struct phy *x)
159 {
160 struct qcom_uniphy_pcie *phy = phy_get_drvdata(x);
161
162 clk_bulk_disable_unprepare(phy->num_clks, phy->clks);
163
164 return reset_control_assert(phy->resets);
165 }
166
qcom_uniphy_pcie_power_on(struct phy * x)167 static int qcom_uniphy_pcie_power_on(struct phy *x)
168 {
169 struct qcom_uniphy_pcie *phy = phy_get_drvdata(x);
170 int ret;
171
172 ret = reset_control_assert(phy->resets);
173 if (ret) {
174 dev_err(phy->dev, "reset assert failed (%d)\n", ret);
175 return ret;
176 }
177
178 usleep_range(RST_ASSERT_DELAY_MIN_US, RST_ASSERT_DELAY_MAX_US);
179
180 ret = reset_control_deassert(phy->resets);
181 if (ret) {
182 dev_err(phy->dev, "reset deassert failed (%d)\n", ret);
183 return ret;
184 }
185
186 usleep_range(PIPE_CLK_DELAY_MIN_US, PIPE_CLK_DELAY_MAX_US);
187
188 ret = clk_bulk_prepare_enable(phy->num_clks, phy->clks);
189 if (ret) {
190 dev_err(phy->dev, "clk prepare and enable failed %d\n", ret);
191 return ret;
192 }
193
194 usleep_range(CLK_EN_DELAY_MIN_US, CLK_EN_DELAY_MAX_US);
195
196 qcom_uniphy_pcie_init(phy);
197
198 return 0;
199 }
200
qcom_uniphy_pcie_get_resources(struct platform_device * pdev,struct qcom_uniphy_pcie * phy)201 static inline int qcom_uniphy_pcie_get_resources(struct platform_device *pdev,
202 struct qcom_uniphy_pcie *phy)
203 {
204 struct resource *res;
205
206 phy->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
207 if (IS_ERR(phy->base))
208 return PTR_ERR(phy->base);
209
210 phy->num_clks = devm_clk_bulk_get_all(phy->dev, &phy->clks);
211 if (phy->num_clks < 0)
212 return phy->num_clks;
213
214 phy->resets = devm_reset_control_array_get_exclusive(phy->dev);
215 if (IS_ERR(phy->resets))
216 return PTR_ERR(phy->resets);
217
218 return 0;
219 }
220
221 /*
222 * Register a fixed rate pipe clock.
223 *
224 * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
225 * controls it. The <s>_pipe_clk coming out of the GCC is requested
226 * by the PHY driver for its operations.
227 * We register the <s>_pipe_clksrc here. The gcc driver takes care
228 * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk.
229 * Below picture shows this relationship.
230 *
231 * +---------------+
232 * | PHY block |<<---------------------------------------+
233 * | | |
234 * | +-------+ | +-----+ |
235 * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
236 * clk | +-------+ | +-----+
237 * +---------------+
238 */
phy_pipe_clk_register(struct qcom_uniphy_pcie * phy,int id)239 static inline int phy_pipe_clk_register(struct qcom_uniphy_pcie *phy, int id)
240 {
241 const struct qcom_uniphy_pcie_data *data = phy->data;
242 struct clk_hw *hw;
243 char name[64];
244
245 snprintf(name, sizeof(name), "phy%d_pipe_clk_src", id);
246 hw = devm_clk_hw_register_fixed_rate(phy->dev, name, NULL, 0,
247 data->pipe_clk_rate);
248 if (IS_ERR(hw))
249 return dev_err_probe(phy->dev, PTR_ERR(hw),
250 "Unable to register %s\n", name);
251
252 return devm_of_clk_add_hw_provider(phy->dev, of_clk_hw_simple_get, hw);
253 }
254
255 static const struct of_device_id qcom_uniphy_pcie_id_table[] = {
256 {
257 .compatible = "qcom,ipq5018-uniphy-pcie-phy",
258 .data = &ipq5018_data,
259 }, {
260 .compatible = "qcom,ipq5332-uniphy-pcie-phy",
261 .data = &ipq5332_data,
262 }, {
263 /* Sentinel */
264 },
265 };
266 MODULE_DEVICE_TABLE(of, qcom_uniphy_pcie_id_table);
267
268 static const struct phy_ops pcie_ops = {
269 .power_on = qcom_uniphy_pcie_power_on,
270 .power_off = qcom_uniphy_pcie_power_off,
271 .owner = THIS_MODULE,
272 };
273
qcom_uniphy_pcie_probe(struct platform_device * pdev)274 static int qcom_uniphy_pcie_probe(struct platform_device *pdev)
275 {
276 struct phy_provider *phy_provider;
277 struct device *dev = &pdev->dev;
278 struct qcom_uniphy_pcie *phy;
279 struct phy *generic_phy;
280 int ret;
281
282 phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
283 if (!phy)
284 return -ENOMEM;
285
286 platform_set_drvdata(pdev, phy);
287 phy->dev = &pdev->dev;
288
289 phy->data = of_device_get_match_data(dev);
290 if (!phy->data)
291 return -EINVAL;
292
293 ret = of_property_read_u32(dev_of_node(dev), "num-lanes", &phy->lanes);
294 if (ret)
295 return dev_err_probe(dev, ret, "Couldn't read num-lanes\n");
296
297 ret = qcom_uniphy_pcie_get_resources(pdev, phy);
298 if (ret < 0)
299 return dev_err_probe(&pdev->dev, ret,
300 "failed to get resources: %d\n", ret);
301
302 generic_phy = devm_phy_create(phy->dev, NULL, &pcie_ops);
303 if (IS_ERR(generic_phy))
304 return PTR_ERR(generic_phy);
305
306 phy_set_drvdata(generic_phy, phy);
307
308 ret = phy_pipe_clk_register(phy, generic_phy->id);
309 if (ret)
310 dev_err(&pdev->dev, "failed to register phy pipe clk\n");
311
312 phy_provider = devm_of_phy_provider_register(phy->dev,
313 of_phy_simple_xlate);
314 if (IS_ERR(phy_provider))
315 return PTR_ERR(phy_provider);
316
317 return 0;
318 }
319
320 static struct platform_driver qcom_uniphy_pcie_driver = {
321 .probe = qcom_uniphy_pcie_probe,
322 .driver = {
323 .name = "qcom-uniphy-pcie",
324 .of_match_table = qcom_uniphy_pcie_id_table,
325 },
326 };
327
328 module_platform_driver(qcom_uniphy_pcie_driver);
329
330 MODULE_DESCRIPTION("PCIE QCOM UNIPHY driver");
331 MODULE_LICENSE("GPL");
332