1 // SPDX-License-Identifier: GPL-2.0
3 * Amlogic G12A USB3 + PCIE Combo PHY driver
5 * Copyright (C) 2017 Amlogic, Inc. All rights reserved
6 * Copyright (C) 2019 BayLibre, SAS
7 * Author: Neil Armstrong <narmstrong@baylibre.com>
10 #include <linux/bitfield.h>
11 #include <linux/bitops.h>
12 #include <linux/clk.h>
13 #include <linux/module.h>
14 #include <linux/of_device.h>
15 #include <linux/phy/phy.h>
16 #include <linux/regmap.h>
17 #include <linux/reset.h>
18 #include <linux/platform_device.h>
19 #include <dt-bindings/phy/phy.h>
22 #define PHY_R0_PCIE_POWER_STATE GENMASK(4, 0)
23 #define PHY_R0_PCIE_USB3_SWITCH GENMASK(6, 5)
26 #define PHY_R1_PHY_TX1_TERM_OFFSET GENMASK(4, 0)
27 #define PHY_R1_PHY_TX0_TERM_OFFSET GENMASK(9, 5)
28 #define PHY_R1_PHY_RX1_EQ GENMASK(12, 10)
29 #define PHY_R1_PHY_RX0_EQ GENMASK(15, 13)
30 #define PHY_R1_PHY_LOS_LEVEL GENMASK(20, 16)
31 #define PHY_R1_PHY_LOS_BIAS GENMASK(23, 21)
32 #define PHY_R1_PHY_REF_CLKDIV2 BIT(24)
33 #define PHY_R1_PHY_MPLL_MULTIPLIER GENMASK(31, 25)
36 #define PHY_R2_PCS_TX_DEEMPH_GEN2_6DB GENMASK(5, 0)
37 #define PHY_R2_PCS_TX_DEEMPH_GEN2_3P5DB GENMASK(11, 6)
38 #define PHY_R2_PCS_TX_DEEMPH_GEN1 GENMASK(17, 12)
39 #define PHY_R2_PHY_TX_VBOOST_LVL GENMASK(20, 18)
42 #define PHY_R4_PHY_CR_WRITE BIT(0)
43 #define PHY_R4_PHY_CR_READ BIT(1)
44 #define PHY_R4_PHY_CR_DATA_IN GENMASK(17, 2)
45 #define PHY_R4_PHY_CR_CAP_DATA BIT(18)
46 #define PHY_R4_PHY_CR_CAP_ADDR BIT(19)
49 #define PHY_R5_PHY_CR_DATA_OUT GENMASK(15, 0)
50 #define PHY_R5_PHY_CR_ACK BIT(16)
51 #define PHY_R5_PHY_BS_OUT BIT(17)
53 #define PCIE_RESET_DELAY 500
55 struct phy_g12a_usb3_pcie_priv
{
56 struct regmap
*regmap
;
57 struct regmap
*regmap_cr
;
59 struct reset_control
*reset
;
64 static const struct regmap_config phy_g12a_usb3_pcie_regmap_conf
= {
68 .max_register
= PHY_R5
,
71 static int phy_g12a_usb3_pcie_cr_bus_addr(struct phy_g12a_usb3_pcie_priv
*priv
,
74 unsigned int val
, reg
;
77 reg
= FIELD_PREP(PHY_R4_PHY_CR_DATA_IN
, addr
);
79 regmap_write(priv
->regmap
, PHY_R4
, reg
);
80 regmap_write(priv
->regmap
, PHY_R4
, reg
);
82 regmap_write(priv
->regmap
, PHY_R4
, reg
| PHY_R4_PHY_CR_CAP_ADDR
);
84 ret
= regmap_read_poll_timeout(priv
->regmap
, PHY_R5
, val
,
85 (val
& PHY_R5_PHY_CR_ACK
),
90 regmap_write(priv
->regmap
, PHY_R4
, reg
);
92 ret
= regmap_read_poll_timeout(priv
->regmap
, PHY_R5
, val
,
93 !(val
& PHY_R5_PHY_CR_ACK
),
101 static int phy_g12a_usb3_pcie_cr_bus_read(void *context
, unsigned int addr
,
104 struct phy_g12a_usb3_pcie_priv
*priv
= context
;
108 ret
= phy_g12a_usb3_pcie_cr_bus_addr(priv
, addr
);
112 regmap_write(priv
->regmap
, PHY_R4
, 0);
113 regmap_write(priv
->regmap
, PHY_R4
, PHY_R4_PHY_CR_READ
);
115 ret
= regmap_read_poll_timeout(priv
->regmap
, PHY_R5
, val
,
116 (val
& PHY_R5_PHY_CR_ACK
),
121 *data
= FIELD_GET(PHY_R5_PHY_CR_DATA_OUT
, val
);
123 regmap_write(priv
->regmap
, PHY_R4
, 0);
125 ret
= regmap_read_poll_timeout(priv
->regmap
, PHY_R5
, val
,
126 !(val
& PHY_R5_PHY_CR_ACK
),
134 static int phy_g12a_usb3_pcie_cr_bus_write(void *context
, unsigned int addr
,
137 struct phy_g12a_usb3_pcie_priv
*priv
= context
;
138 unsigned int val
, reg
;
141 ret
= phy_g12a_usb3_pcie_cr_bus_addr(priv
, addr
);
145 reg
= FIELD_PREP(PHY_R4_PHY_CR_DATA_IN
, data
);
147 regmap_write(priv
->regmap
, PHY_R4
, reg
);
148 regmap_write(priv
->regmap
, PHY_R4
, reg
);
150 regmap_write(priv
->regmap
, PHY_R4
, reg
| PHY_R4_PHY_CR_CAP_DATA
);
152 ret
= regmap_read_poll_timeout(priv
->regmap
, PHY_R5
, val
,
153 (val
& PHY_R5_PHY_CR_ACK
),
158 regmap_write(priv
->regmap
, PHY_R4
, reg
);
160 ret
= regmap_read_poll_timeout(priv
->regmap
, PHY_R5
, val
,
161 (val
& PHY_R5_PHY_CR_ACK
) == 0,
166 regmap_write(priv
->regmap
, PHY_R4
, reg
);
168 regmap_write(priv
->regmap
, PHY_R4
, reg
| PHY_R4_PHY_CR_WRITE
);
170 ret
= regmap_read_poll_timeout(priv
->regmap
, PHY_R5
, val
,
171 (val
& PHY_R5_PHY_CR_ACK
),
176 regmap_write(priv
->regmap
, PHY_R4
, reg
);
178 ret
= regmap_read_poll_timeout(priv
->regmap
, PHY_R5
, val
,
179 (val
& PHY_R5_PHY_CR_ACK
) == 0,
187 static const struct regmap_config phy_g12a_usb3_pcie_cr_regmap_conf
= {
190 .reg_read
= phy_g12a_usb3_pcie_cr_bus_read
,
191 .reg_write
= phy_g12a_usb3_pcie_cr_bus_write
,
192 .max_register
= 0xffff,
193 .disable_locking
= true,
196 static int phy_g12a_usb3_init(struct phy
*phy
)
198 struct phy_g12a_usb3_pcie_priv
*priv
= phy_get_drvdata(phy
);
201 ret
= reset_control_reset(priv
->reset
);
205 /* Switch PHY to USB3 */
206 /* TODO figure out how to handle when PCIe was set in the bootloader */
207 regmap_update_bits(priv
->regmap
, PHY_R0
,
208 PHY_R0_PCIE_USB3_SWITCH
,
209 PHY_R0_PCIE_USB3_SWITCH
);
212 * WORKAROUND: There is SSPHY suspend bug due to
213 * which USB enumerates
214 * in HS mode instead of SS mode. Workaround it by asserting
215 * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus
218 ret
= regmap_update_bits(priv
->regmap_cr
, 0x102d, BIT(7), BIT(7));
222 ret
= regmap_update_bits(priv
->regmap_cr
, 0x1010, 0xff0, 20);
227 * Fix RX Equalization setting as follows
228 * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0
229 * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1
230 * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3
231 * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1
233 ret
= regmap_read(priv
->regmap_cr
, 0x1006, &data
);
242 ret
= regmap_write(priv
->regmap_cr
, 0x1006, data
);
247 * Set EQ and TX launch amplitudes as follows
248 * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22
249 * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127
250 * LANE0.TX_OVRD_DRV_LO.EN set to 1.
252 ret
= regmap_read(priv
->regmap_cr
, 0x1002, &data
);
259 data
|= (0x7f | BIT(14));
260 ret
= regmap_write(priv
->regmap_cr
, 0x1002, data
);
264 /* MPLL_LOOP_CTL.PROP_CNTRL = 8 */
265 ret
= regmap_update_bits(priv
->regmap_cr
, 0x30, 0xf << 4, 8 << 4);
269 regmap_update_bits(priv
->regmap
, PHY_R2
,
270 PHY_R2_PHY_TX_VBOOST_LVL
,
271 FIELD_PREP(PHY_R2_PHY_TX_VBOOST_LVL
, 0x4));
273 regmap_update_bits(priv
->regmap
, PHY_R1
,
274 PHY_R1_PHY_LOS_BIAS
| PHY_R1_PHY_LOS_LEVEL
,
275 FIELD_PREP(PHY_R1_PHY_LOS_BIAS
, 4) |
276 FIELD_PREP(PHY_R1_PHY_LOS_LEVEL
, 9));
281 static int phy_g12a_usb3_pcie_power_on(struct phy
*phy
)
283 struct phy_g12a_usb3_pcie_priv
*priv
= phy_get_drvdata(phy
);
285 if (priv
->mode
== PHY_TYPE_USB3
)
288 regmap_update_bits(priv
->regmap
, PHY_R0
,
289 PHY_R0_PCIE_POWER_STATE
,
290 FIELD_PREP(PHY_R0_PCIE_POWER_STATE
, 0x1c));
295 static int phy_g12a_usb3_pcie_power_off(struct phy
*phy
)
297 struct phy_g12a_usb3_pcie_priv
*priv
= phy_get_drvdata(phy
);
299 if (priv
->mode
== PHY_TYPE_USB3
)
302 regmap_update_bits(priv
->regmap
, PHY_R0
,
303 PHY_R0_PCIE_POWER_STATE
,
304 FIELD_PREP(PHY_R0_PCIE_POWER_STATE
, 0x1d));
309 static int phy_g12a_usb3_pcie_reset(struct phy
*phy
)
311 struct phy_g12a_usb3_pcie_priv
*priv
= phy_get_drvdata(phy
);
314 if (priv
->mode
== PHY_TYPE_USB3
)
317 ret
= reset_control_assert(priv
->reset
);
321 udelay(PCIE_RESET_DELAY
);
323 ret
= reset_control_deassert(priv
->reset
);
327 udelay(PCIE_RESET_DELAY
);
332 static int phy_g12a_usb3_pcie_init(struct phy
*phy
)
334 struct phy_g12a_usb3_pcie_priv
*priv
= phy_get_drvdata(phy
);
336 if (priv
->mode
== PHY_TYPE_USB3
)
337 return phy_g12a_usb3_init(phy
);
342 static int phy_g12a_usb3_pcie_exit(struct phy
*phy
)
344 struct phy_g12a_usb3_pcie_priv
*priv
= phy_get_drvdata(phy
);
346 if (priv
->mode
== PHY_TYPE_USB3
)
347 return reset_control_reset(priv
->reset
);
352 static struct phy
*phy_g12a_usb3_pcie_xlate(struct device
*dev
,
353 struct of_phandle_args
*args
)
355 struct phy_g12a_usb3_pcie_priv
*priv
= dev_get_drvdata(dev
);
358 if (args
->args_count
< 1) {
359 dev_err(dev
, "invalid number of arguments\n");
360 return ERR_PTR(-EINVAL
);
363 mode
= args
->args
[0];
365 if (mode
!= PHY_TYPE_USB3
&& mode
!= PHY_TYPE_PCIE
) {
366 dev_err(dev
, "invalid phy mode select argument\n");
367 return ERR_PTR(-EINVAL
);
375 static const struct phy_ops phy_g12a_usb3_pcie_ops
= {
376 .init
= phy_g12a_usb3_pcie_init
,
377 .exit
= phy_g12a_usb3_pcie_exit
,
378 .power_on
= phy_g12a_usb3_pcie_power_on
,
379 .power_off
= phy_g12a_usb3_pcie_power_off
,
380 .reset
= phy_g12a_usb3_pcie_reset
,
381 .owner
= THIS_MODULE
,
384 static int phy_g12a_usb3_pcie_probe(struct platform_device
*pdev
)
386 struct device
*dev
= &pdev
->dev
;
387 struct device_node
*np
= dev
->of_node
;
388 struct phy_g12a_usb3_pcie_priv
*priv
;
389 struct phy_provider
*phy_provider
;
393 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
397 base
= devm_platform_ioremap_resource(pdev
, 0);
399 return PTR_ERR(base
);
401 priv
->regmap
= devm_regmap_init_mmio(dev
, base
,
402 &phy_g12a_usb3_pcie_regmap_conf
);
403 if (IS_ERR(priv
->regmap
))
404 return PTR_ERR(priv
->regmap
);
406 priv
->regmap_cr
= devm_regmap_init(dev
, NULL
, priv
,
407 &phy_g12a_usb3_pcie_cr_regmap_conf
);
408 if (IS_ERR(priv
->regmap_cr
))
409 return PTR_ERR(priv
->regmap_cr
);
411 priv
->clk_ref
= devm_clk_get(dev
, "ref_clk");
412 if (IS_ERR(priv
->clk_ref
))
413 return PTR_ERR(priv
->clk_ref
);
415 ret
= clk_prepare_enable(priv
->clk_ref
);
417 goto err_disable_clk_ref
;
419 priv
->reset
= devm_reset_control_array_get_exclusive(dev
);
420 if (IS_ERR(priv
->reset
))
421 return PTR_ERR(priv
->reset
);
423 priv
->phy
= devm_phy_create(dev
, np
, &phy_g12a_usb3_pcie_ops
);
424 if (IS_ERR(priv
->phy
)) {
425 ret
= PTR_ERR(priv
->phy
);
426 if (ret
!= -EPROBE_DEFER
)
427 dev_err(dev
, "failed to create PHY\n");
432 phy_set_drvdata(priv
->phy
, priv
);
433 dev_set_drvdata(dev
, priv
);
435 phy_provider
= devm_of_phy_provider_register(dev
,
436 phy_g12a_usb3_pcie_xlate
);
438 return PTR_ERR_OR_ZERO(phy_provider
);
441 clk_disable_unprepare(priv
->clk_ref
);
446 static const struct of_device_id phy_g12a_usb3_pcie_of_match
[] = {
447 { .compatible
= "amlogic,g12a-usb3-pcie-phy", },
450 MODULE_DEVICE_TABLE(of
, phy_g12a_usb3_pcie_of_match
);
452 static struct platform_driver phy_g12a_usb3_pcie_driver
= {
453 .probe
= phy_g12a_usb3_pcie_probe
,
455 .name
= "phy-g12a-usb3-pcie",
456 .of_match_table
= phy_g12a_usb3_pcie_of_match
,
459 module_platform_driver(phy_g12a_usb3_pcie_driver
);
461 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
462 MODULE_DESCRIPTION("Amlogic G12A USB3 + PCIE Combo PHY driver");
463 MODULE_LICENSE("GPL v2");