1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
4 * Copyright (c) 2019, Linaro Ltd.
7 #include <linux/clk-provider.h>
9 #include <linux/iopoll.h>
10 #include <linux/module.h>
11 #include <linux/phy/phy.h>
12 #include <linux/platform_device.h>
13 #include <linux/reset.h>
14 #include <linux/slab.h>
16 #include <dt-bindings/phy/phy.h>
18 #define PCIE20_PARF_PHY_STTS 0x3c
19 #define PCIE2_PHY_RESET_CTRL 0x44
20 #define PCIE20_PARF_PHY_REFCLK_CTRL2 0xa0
21 #define PCIE20_PARF_PHY_REFCLK_CTRL3 0xa4
22 #define PCIE20_PARF_PCS_SWING_CTRL1 0x88
23 #define PCIE20_PARF_PCS_SWING_CTRL2 0x8c
24 #define PCIE20_PARF_PCS_DEEMPH1 0x74
25 #define PCIE20_PARF_PCS_DEEMPH2 0x78
26 #define PCIE20_PARF_PCS_DEEMPH3 0x7c
27 #define PCIE20_PARF_CONFIGBITS 0x84
28 #define PCIE20_PARF_PHY_CTRL3 0x94
29 #define PCIE20_PARF_PCS_CTRL 0x80
31 #define TX_AMP_VAL 120
32 #define PHY_RX0_EQ_GEN1_VAL 0
33 #define PHY_RX0_EQ_GEN2_VAL 4
34 #define TX_DEEMPH_GEN1_VAL 24
35 #define TX_DEEMPH_GEN2_3_5DB_VAL 26
36 #define TX_DEEMPH_GEN2_6DB_VAL 36
37 #define PHY_TX0_TERM_OFFST_VAL 0
43 struct regulator_bulk_data vregs
[2];
45 struct reset_control
*phy_reset
;
46 struct reset_control
*pipe_reset
;
50 static int qcom_pcie2_phy_init(struct phy
*phy
)
52 struct qcom_phy
*qphy
= phy_get_drvdata(phy
);
55 ret
= reset_control_deassert(qphy
->phy_reset
);
57 dev_err(qphy
->dev
, "cannot deassert pipe reset\n");
61 ret
= regulator_bulk_enable(ARRAY_SIZE(qphy
->vregs
), qphy
->vregs
);
63 reset_control_assert(qphy
->phy_reset
);
68 static int qcom_pcie2_phy_power_on(struct phy
*phy
)
70 struct qcom_phy
*qphy
= phy_get_drvdata(phy
);
74 /* Program REF_CLK source */
75 val
= readl(qphy
->base
+ PCIE20_PARF_PHY_REFCLK_CTRL2
);
77 writel(val
, qphy
->base
+ PCIE20_PARF_PHY_REFCLK_CTRL2
);
79 usleep_range(1000, 2000);
81 /* Don't use PAD for refclock */
82 val
= readl(qphy
->base
+ PCIE20_PARF_PHY_REFCLK_CTRL2
);
84 writel(val
, qphy
->base
+ PCIE20_PARF_PHY_REFCLK_CTRL2
);
86 /* Program SSP ENABLE */
87 val
= readl(qphy
->base
+ PCIE20_PARF_PHY_REFCLK_CTRL3
);
89 writel(val
, qphy
->base
+ PCIE20_PARF_PHY_REFCLK_CTRL3
);
91 usleep_range(1000, 2000);
93 /* Assert Phy SW Reset */
94 val
= readl(qphy
->base
+ PCIE2_PHY_RESET_CTRL
);
96 writel(val
, qphy
->base
+ PCIE2_PHY_RESET_CTRL
);
98 /* Program Tx Amplitude */
99 val
= readl(qphy
->base
+ PCIE20_PARF_PCS_SWING_CTRL1
);
102 writel(val
, qphy
->base
+ PCIE20_PARF_PCS_SWING_CTRL1
);
104 val
= readl(qphy
->base
+ PCIE20_PARF_PCS_SWING_CTRL2
);
107 writel(val
, qphy
->base
+ PCIE20_PARF_PCS_SWING_CTRL2
);
109 /* Program De-Emphasis */
110 val
= readl(qphy
->base
+ PCIE20_PARF_PCS_DEEMPH1
);
112 val
|= TX_DEEMPH_GEN2_6DB_VAL
;
113 writel(val
, qphy
->base
+ PCIE20_PARF_PCS_DEEMPH1
);
115 val
= readl(qphy
->base
+ PCIE20_PARF_PCS_DEEMPH2
);
117 val
|= TX_DEEMPH_GEN2_3_5DB_VAL
;
118 writel(val
, qphy
->base
+ PCIE20_PARF_PCS_DEEMPH2
);
120 val
= readl(qphy
->base
+ PCIE20_PARF_PCS_DEEMPH3
);
122 val
|= TX_DEEMPH_GEN1_VAL
;
123 writel(val
, qphy
->base
+ PCIE20_PARF_PCS_DEEMPH3
);
126 val
= readl(qphy
->base
+ PCIE20_PARF_CONFIGBITS
);
128 val
|= PHY_RX0_EQ_GEN2_VAL
;
129 writel(val
, qphy
->base
+ PCIE20_PARF_CONFIGBITS
);
131 /* Program Tx0_term_offset */
132 val
= readl(qphy
->base
+ PCIE20_PARF_PHY_CTRL3
);
134 val
|= PHY_TX0_TERM_OFFST_VAL
;
135 writel(val
, qphy
->base
+ PCIE20_PARF_PHY_CTRL3
);
137 /* disable Tx2Rx Loopback */
138 val
= readl(qphy
->base
+ PCIE20_PARF_PCS_CTRL
);
140 writel(val
, qphy
->base
+ PCIE20_PARF_PCS_CTRL
);
142 /* De-assert Phy SW Reset */
143 val
= readl(qphy
->base
+ PCIE2_PHY_RESET_CTRL
);
145 writel(val
, qphy
->base
+ PCIE2_PHY_RESET_CTRL
);
147 usleep_range(1000, 2000);
149 ret
= reset_control_deassert(qphy
->pipe_reset
);
151 dev_err(qphy
->dev
, "cannot deassert pipe reset\n");
155 clk_set_rate(qphy
->pipe_clk
, 250000000);
157 ret
= clk_prepare_enable(qphy
->pipe_clk
);
159 dev_err(qphy
->dev
, "failed to enable pipe clock\n");
163 ret
= readl_poll_timeout(qphy
->base
+ PCIE20_PARF_PHY_STTS
, val
,
164 !(val
& BIT(0)), 1000, 10);
166 dev_err(qphy
->dev
, "phy initialization failed\n");
172 static int qcom_pcie2_phy_power_off(struct phy
*phy
)
174 struct qcom_phy
*qphy
= phy_get_drvdata(phy
);
177 val
= readl(qphy
->base
+ PCIE2_PHY_RESET_CTRL
);
179 writel(val
, qphy
->base
+ PCIE2_PHY_RESET_CTRL
);
181 clk_disable_unprepare(qphy
->pipe_clk
);
182 reset_control_assert(qphy
->pipe_reset
);
187 static int qcom_pcie2_phy_exit(struct phy
*phy
)
189 struct qcom_phy
*qphy
= phy_get_drvdata(phy
);
191 regulator_bulk_disable(ARRAY_SIZE(qphy
->vregs
), qphy
->vregs
);
192 reset_control_assert(qphy
->phy_reset
);
197 static const struct phy_ops qcom_pcie2_ops
= {
198 .init
= qcom_pcie2_phy_init
,
199 .power_on
= qcom_pcie2_phy_power_on
,
200 .power_off
= qcom_pcie2_phy_power_off
,
201 .exit
= qcom_pcie2_phy_exit
,
202 .owner
= THIS_MODULE
,
206 * Register a fixed rate pipe clock.
208 * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
209 * controls it. The <s>_pipe_clk coming out of the GCC is requested
210 * by the PHY driver for its operations.
211 * We register the <s>_pipe_clksrc here. The gcc driver takes care
212 * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk.
213 * Below picture shows this relationship.
216 * | PHY block |<<---------------------------------------+
218 * | +-------+ | +-----+ |
219 * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
220 * clk | +-------+ | +-----+
223 static int phy_pipe_clksrc_register(struct qcom_phy
*qphy
)
225 struct device_node
*np
= qphy
->dev
->of_node
;
226 struct clk_fixed_rate
*fixed
;
227 struct clk_init_data init
= { };
230 ret
= of_property_read_string(np
, "clock-output-names", &init
.name
);
232 dev_err(qphy
->dev
, "%s: No clock-output-names\n", np
->name
);
236 fixed
= devm_kzalloc(qphy
->dev
, sizeof(*fixed
), GFP_KERNEL
);
240 init
.ops
= &clk_fixed_rate_ops
;
242 /* controllers using QMP phys use 250MHz pipe clock interface */
243 fixed
->fixed_rate
= 250000000;
244 fixed
->hw
.init
= &init
;
246 return devm_clk_hw_register(qphy
->dev
, &fixed
->hw
);
249 static int qcom_pcie2_phy_probe(struct platform_device
*pdev
)
251 struct phy_provider
*phy_provider
;
252 struct qcom_phy
*qphy
;
253 struct resource
*res
;
254 struct device
*dev
= &pdev
->dev
;
258 qphy
= devm_kzalloc(dev
, sizeof(*qphy
), GFP_KERNEL
);
264 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
265 qphy
->base
= devm_ioremap_resource(dev
, res
);
266 if (IS_ERR(qphy
->base
))
267 return PTR_ERR(qphy
->base
);
269 ret
= phy_pipe_clksrc_register(qphy
);
271 dev_err(dev
, "failed to register pipe_clk\n");
275 qphy
->vregs
[0].supply
= "vdda-vp";
276 qphy
->vregs
[1].supply
= "vdda-vph";
277 ret
= devm_regulator_bulk_get(dev
, ARRAY_SIZE(qphy
->vregs
), qphy
->vregs
);
281 qphy
->pipe_clk
= devm_clk_get(dev
, NULL
);
282 if (IS_ERR(qphy
->pipe_clk
)) {
283 dev_err(dev
, "failed to acquire pipe clock\n");
284 return PTR_ERR(qphy
->pipe_clk
);
287 qphy
->phy_reset
= devm_reset_control_get_exclusive(dev
, "phy");
288 if (IS_ERR(qphy
->phy_reset
)) {
289 dev_err(dev
, "failed to acquire phy reset\n");
290 return PTR_ERR(qphy
->phy_reset
);
293 qphy
->pipe_reset
= devm_reset_control_get_exclusive(dev
, "pipe");
294 if (IS_ERR(qphy
->pipe_reset
)) {
295 dev_err(dev
, "failed to acquire pipe reset\n");
296 return PTR_ERR(qphy
->pipe_reset
);
299 phy
= devm_phy_create(dev
, dev
->of_node
, &qcom_pcie2_ops
);
301 dev_err(dev
, "failed to create phy\n");
305 phy_set_drvdata(phy
, qphy
);
307 phy_provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
308 if (IS_ERR(phy_provider
))
309 dev_err(dev
, "failed to register phy provider\n");
311 return PTR_ERR_OR_ZERO(phy_provider
);
314 static const struct of_device_id qcom_pcie2_phy_match_table
[] = {
315 { .compatible
= "qcom,pcie2-phy" },
318 MODULE_DEVICE_TABLE(of
, qcom_pcie2_phy_match_table
);
320 static struct platform_driver qcom_pcie2_phy_driver
= {
321 .probe
= qcom_pcie2_phy_probe
,
323 .name
= "phy-qcom-pcie2",
324 .of_match_table
= qcom_pcie2_phy_match_table
,
328 module_platform_driver(qcom_pcie2_phy_driver
);
330 MODULE_DESCRIPTION("Qualcomm PCIe PHY driver");
331 MODULE_LICENSE("GPL v2");