1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2012-2014,2017 The Linux Foundation. All rights reserved.
4 * Copyright (c) 2018-2020, Linaro Limited
8 #include <linux/delay.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
14 #include <linux/phy/phy.h>
15 #include <linux/platform_device.h>
16 #include <linux/regulator/consumer.h>
17 #include <linux/reset.h>
18 #include <linux/slab.h>
20 #define PHY_CTRL0 0x6C
21 #define PHY_CTRL1 0x70
22 #define PHY_CTRL2 0x74
23 #define PHY_CTRL4 0x7C
26 #define REF_PHY_EN BIT(0)
27 #define LANE0_PWR_ON BIT(2)
28 #define SWI_PCS_CLK_SEL BIT(4)
29 #define TST_PWR_DOWN BIT(4)
30 #define PHY_RESET BIT(7)
32 #define NUM_BULK_CLKS 3
33 #define NUM_BULK_REGS 2
38 struct reset_control
*reset_com
;
39 struct reset_control
*reset_phy
;
40 struct regulator_bulk_data regs
[NUM_BULK_REGS
];
41 struct clk_bulk_data clks
[NUM_BULK_CLKS
];
45 static inline void qcom_ssphy_updatel(void __iomem
*addr
, u32 mask
, u32 val
)
47 writel((readl(addr
) & ~mask
) | val
, addr
);
50 static int qcom_ssphy_do_reset(struct ssphy_priv
*priv
)
54 if (!priv
->reset_com
) {
55 qcom_ssphy_updatel(priv
->base
+ PHY_CTRL1
, PHY_RESET
,
58 qcom_ssphy_updatel(priv
->base
+ PHY_CTRL1
, PHY_RESET
, 0);
60 ret
= reset_control_assert(priv
->reset_com
);
62 dev_err(priv
->dev
, "Failed to assert reset com\n");
66 ret
= reset_control_assert(priv
->reset_phy
);
68 dev_err(priv
->dev
, "Failed to assert reset phy\n");
74 ret
= reset_control_deassert(priv
->reset_com
);
76 dev_err(priv
->dev
, "Failed to deassert reset com\n");
80 ret
= reset_control_deassert(priv
->reset_phy
);
82 dev_err(priv
->dev
, "Failed to deassert reset phy\n");
90 static int qcom_ssphy_power_on(struct phy
*phy
)
92 struct ssphy_priv
*priv
= phy_get_drvdata(phy
);
95 ret
= regulator_bulk_enable(NUM_BULK_REGS
, priv
->regs
);
99 ret
= clk_bulk_prepare_enable(NUM_BULK_CLKS
, priv
->clks
);
101 goto err_disable_regulator
;
103 ret
= qcom_ssphy_do_reset(priv
);
105 goto err_disable_clock
;
107 writeb(SWI_PCS_CLK_SEL
, priv
->base
+ PHY_CTRL0
);
108 qcom_ssphy_updatel(priv
->base
+ PHY_CTRL4
, LANE0_PWR_ON
, LANE0_PWR_ON
);
109 qcom_ssphy_updatel(priv
->base
+ PHY_CTRL2
, REF_PHY_EN
, REF_PHY_EN
);
110 qcom_ssphy_updatel(priv
->base
+ PHY_CTRL4
, TST_PWR_DOWN
, 0);
114 clk_bulk_disable_unprepare(NUM_BULK_CLKS
, priv
->clks
);
115 err_disable_regulator
:
116 regulator_bulk_disable(NUM_BULK_REGS
, priv
->regs
);
121 static int qcom_ssphy_power_off(struct phy
*phy
)
123 struct ssphy_priv
*priv
= phy_get_drvdata(phy
);
125 qcom_ssphy_updatel(priv
->base
+ PHY_CTRL4
, LANE0_PWR_ON
, 0);
126 qcom_ssphy_updatel(priv
->base
+ PHY_CTRL2
, REF_PHY_EN
, 0);
127 qcom_ssphy_updatel(priv
->base
+ PHY_CTRL4
, TST_PWR_DOWN
, TST_PWR_DOWN
);
129 clk_bulk_disable_unprepare(NUM_BULK_CLKS
, priv
->clks
);
130 regulator_bulk_disable(NUM_BULK_REGS
, priv
->regs
);
135 static int qcom_ssphy_init_clock(struct ssphy_priv
*priv
)
137 priv
->clks
[0].id
= "ref";
138 priv
->clks
[1].id
= "ahb";
139 priv
->clks
[2].id
= "pipe";
141 return devm_clk_bulk_get(priv
->dev
, NUM_BULK_CLKS
, priv
->clks
);
144 static int qcom_ssphy_init_regulator(struct ssphy_priv
*priv
)
148 priv
->regs
[0].supply
= "vdd";
149 priv
->regs
[1].supply
= "vdda1p8";
150 ret
= devm_regulator_bulk_get(priv
->dev
, NUM_BULK_REGS
, priv
->regs
);
152 if (ret
!= -EPROBE_DEFER
)
153 dev_err(priv
->dev
, "Failed to get regulators\n");
160 static int qcom_ssphy_init_reset(struct ssphy_priv
*priv
)
162 priv
->reset_com
= devm_reset_control_get_optional_exclusive(priv
->dev
, "com");
163 if (IS_ERR(priv
->reset_com
)) {
164 dev_err(priv
->dev
, "Failed to get reset control com\n");
165 return PTR_ERR(priv
->reset_com
);
168 if (priv
->reset_com
) {
169 /* if reset_com is present, reset_phy is no longer optional */
170 priv
->reset_phy
= devm_reset_control_get_exclusive(priv
->dev
, "phy");
171 if (IS_ERR(priv
->reset_phy
)) {
172 dev_err(priv
->dev
, "Failed to get reset control phy\n");
173 return PTR_ERR(priv
->reset_phy
);
180 static const struct phy_ops qcom_ssphy_ops
= {
181 .power_off
= qcom_ssphy_power_off
,
182 .power_on
= qcom_ssphy_power_on
,
183 .owner
= THIS_MODULE
,
186 static int qcom_ssphy_probe(struct platform_device
*pdev
)
188 struct device
*dev
= &pdev
->dev
;
189 struct phy_provider
*provider
;
190 struct ssphy_priv
*priv
;
194 priv
= devm_kzalloc(dev
, sizeof(struct ssphy_priv
), GFP_KERNEL
);
199 priv
->mode
= PHY_MODE_INVALID
;
201 priv
->base
= devm_platform_ioremap_resource(pdev
, 0);
202 if (IS_ERR(priv
->base
))
203 return PTR_ERR(priv
->base
);
205 ret
= qcom_ssphy_init_clock(priv
);
209 ret
= qcom_ssphy_init_reset(priv
);
213 ret
= qcom_ssphy_init_regulator(priv
);
217 phy
= devm_phy_create(dev
, dev
->of_node
, &qcom_ssphy_ops
);
219 dev_err(dev
, "Failed to create the SS phy\n");
223 phy_set_drvdata(phy
, priv
);
225 provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
227 return PTR_ERR_OR_ZERO(provider
);
230 static const struct of_device_id qcom_ssphy_match
[] = {
231 { .compatible
= "qcom,usb-ss-28nm-phy", },
234 MODULE_DEVICE_TABLE(of
, qcom_ssphy_match
);
236 static struct platform_driver qcom_ssphy_driver
= {
237 .probe
= qcom_ssphy_probe
,
239 .name
= "qcom-usb-ssphy",
240 .of_match_table
= qcom_ssphy_match
,
243 module_platform_driver(qcom_ssphy_driver
);
245 MODULE_DESCRIPTION("Qualcomm SuperSpeed USB PHY driver");
246 MODULE_LICENSE("GPL v2");