Lines Matching +full:phy +full:- +full:mode
1 // SPDX-License-Identifier: GPL-2.0-only
3 * PCIe PHY driver for Lantiq VRX200 and ARX300 SoCs.
8 * Copyright (C) 2009-2015 Lei Chuanhua <chuanhua.lei@lantiq.com>
11 * TODO: PHY modes other than 36MHz (without "SSC")
21 #include <linux/phy/phy.h>
27 #include <dt-bindings/phy/phy-lantiq-vrx200-pcie.h>
85 struct phy *phy; member
86 unsigned int mode; member
98 static void ltq_vrx200_pcie_phy_common_setup(struct phy *phy) in ltq_vrx200_pcie_phy_common_setup() argument
100 struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); in ltq_vrx200_pcie_phy_common_setup()
103 regmap_write(priv->phy_regmap, PCIE_PHY_PLL_A_CTRL1, 0x120e); in ltq_vrx200_pcie_phy_common_setup()
106 regmap_write(priv->phy_regmap, PCIE_PHY_PLL_A_CTRL2, 0x39d7); in ltq_vrx200_pcie_phy_common_setup()
107 regmap_write(priv->phy_regmap, PCIE_PHY_PLL_A_CTRL3, 0x0900); in ltq_vrx200_pcie_phy_common_setup()
110 regmap_write(priv->phy_regmap, PCIE_PHY_RX1_EI, 0x0004); in ltq_vrx200_pcie_phy_common_setup()
111 regmap_write(priv->phy_regmap, PCIE_PHY_RX1_A_CTRL, 0x6803); in ltq_vrx200_pcie_phy_common_setup()
113 regmap_update_bits(priv->phy_regmap, PCIE_PHY_TX1_CTRL1, in ltq_vrx200_pcie_phy_common_setup()
118 regmap_write(priv->phy_regmap, PCIE_PHY_TX1_A_CTRL2, 0x0706); in ltq_vrx200_pcie_phy_common_setup()
121 regmap_write(priv->phy_regmap, PCIE_PHY_TX1_CTRL3, 0x1fff); in ltq_vrx200_pcie_phy_common_setup()
124 regmap_write(priv->phy_regmap, PCIE_PHY_TX1_A_CTRL1, 0x0810); in ltq_vrx200_pcie_phy_common_setup()
127 regmap_update_bits(priv->phy_regmap, PCIE_PHY_TX2_A_CTRL2, 0x7f00, in ltq_vrx200_pcie_phy_common_setup()
131 regmap_write(priv->phy_regmap, PCIE_PHY_TX1_CTRL2, 0x2e00); in ltq_vrx200_pcie_phy_common_setup()
134 regmap_write(priv->phy_regmap, PCIE_PHY_TX2_CTRL2, 0x3096); in ltq_vrx200_pcie_phy_common_setup()
135 regmap_write(priv->phy_regmap, PCIE_PHY_TX2_A_CTRL2, 0x4707); in ltq_vrx200_pcie_phy_common_setup()
138 regmap_write(priv->phy_regmap, PCIE_PHY_RX1_CDR, 0x0235); in ltq_vrx200_pcie_phy_common_setup()
141 static void pcie_phy_36mhz_mode_setup(struct phy *phy) in pcie_phy_36mhz_mode_setup() argument
143 struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); in pcie_phy_36mhz_mode_setup()
145 regmap_update_bits(priv->phy_regmap, PCIE_PHY_PLL_CTRL3, in pcie_phy_36mhz_mode_setup()
148 regmap_update_bits(priv->phy_regmap, PCIE_PHY_PLL_CTRL3, in pcie_phy_36mhz_mode_setup()
151 regmap_update_bits(priv->phy_regmap, PCIE_PHY_PLL_CTRL2, in pcie_phy_36mhz_mode_setup()
155 regmap_update_bits(priv->phy_regmap, PCIE_PHY_PLL_CTRL2, in pcie_phy_36mhz_mode_setup()
159 regmap_update_bits(priv->phy_regmap, PCIE_PHY_PLL_A_CTRL3, in pcie_phy_36mhz_mode_setup()
163 regmap_update_bits(priv->phy_regmap, PCIE_PHY_PLL_A_CTRL2, in pcie_phy_36mhz_mode_setup()
167 regmap_write(priv->phy_regmap, PCIE_PHY_PLL_CTRL1, 0x38e4); in pcie_phy_36mhz_mode_setup()
169 regmap_update_bits(priv->phy_regmap, PCIE_PHY_PLL_CTRL2, in pcie_phy_36mhz_mode_setup()
175 regmap_write(priv->phy_regmap, PCIE_PHY_PLL_CTRL7, 0x0002); in pcie_phy_36mhz_mode_setup()
176 regmap_write(priv->phy_regmap, PCIE_PHY_PLL_CTRL6, 0x3a04); in pcie_phy_36mhz_mode_setup()
177 regmap_write(priv->phy_regmap, PCIE_PHY_PLL_CTRL5, 0xfae3); in pcie_phy_36mhz_mode_setup()
178 regmap_write(priv->phy_regmap, PCIE_PHY_PLL_CTRL4, 0x1b72); in pcie_phy_36mhz_mode_setup()
181 static int ltq_vrx200_pcie_phy_wait_for_pll(struct phy *phy) in ltq_vrx200_pcie_phy_wait_for_pll() argument
183 struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); in ltq_vrx200_pcie_phy_wait_for_pll()
187 ret = regmap_read_poll_timeout(priv->phy_regmap, PCIE_PHY_PLL_STATUS, in ltq_vrx200_pcie_phy_wait_for_pll()
191 dev_err(priv->dev, "PLL Link timeout, PLL status = 0x%04x\n", in ltq_vrx200_pcie_phy_wait_for_pll()
199 static void ltq_vrx200_pcie_phy_apply_workarounds(struct phy *phy) in ltq_vrx200_pcie_phy_apply_workarounds() argument
201 struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); in ltq_vrx200_pcie_phy_apply_workarounds()
220 regmap_update_bits(priv->phy_regmap, slices[i].reg, in ltq_vrx200_pcie_phy_apply_workarounds()
226 regmap_update_bits(priv->phy_regmap, slices[i].reg, in ltq_vrx200_pcie_phy_apply_workarounds()
232 regmap_write(priv->phy_regmap, PCIE_PHY_TX2_MOD1, 0x1ffe); in ltq_vrx200_pcie_phy_apply_workarounds()
233 regmap_write(priv->phy_regmap, PCIE_PHY_TX2_MOD2, 0xfffe); in ltq_vrx200_pcie_phy_apply_workarounds()
234 regmap_write(priv->phy_regmap, PCIE_PHY_TX2_MOD3, 0x0601); in ltq_vrx200_pcie_phy_apply_workarounds()
236 regmap_write(priv->phy_regmap, PCIE_PHY_TX2_MOD3, 0x0001); in ltq_vrx200_pcie_phy_apply_workarounds()
239 regmap_write(priv->phy_regmap, PCIE_PHY_TX1_MOD1, 0x1ffe); in ltq_vrx200_pcie_phy_apply_workarounds()
240 regmap_write(priv->phy_regmap, PCIE_PHY_TX1_MOD2, 0xfffe); in ltq_vrx200_pcie_phy_apply_workarounds()
241 regmap_write(priv->phy_regmap, PCIE_PHY_TX1_MOD3, 0x0601); in ltq_vrx200_pcie_phy_apply_workarounds()
243 regmap_write(priv->phy_regmap, PCIE_PHY_TX1_MOD3, 0x0001); in ltq_vrx200_pcie_phy_apply_workarounds()
247 static int ltq_vrx200_pcie_phy_init(struct phy *phy) in ltq_vrx200_pcie_phy_init() argument
249 struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); in ltq_vrx200_pcie_phy_init()
252 if (of_device_is_big_endian(priv->dev->of_node)) in ltq_vrx200_pcie_phy_init()
253 regmap_update_bits(priv->rcu_regmap, in ltq_vrx200_pcie_phy_init()
254 priv->rcu_ahb_endian_offset, in ltq_vrx200_pcie_phy_init()
255 priv->rcu_ahb_endian_big_endian_mask, in ltq_vrx200_pcie_phy_init()
256 priv->rcu_ahb_endian_big_endian_mask); in ltq_vrx200_pcie_phy_init()
258 regmap_update_bits(priv->rcu_regmap, in ltq_vrx200_pcie_phy_init()
259 priv->rcu_ahb_endian_offset, in ltq_vrx200_pcie_phy_init()
260 priv->rcu_ahb_endian_big_endian_mask, 0x0); in ltq_vrx200_pcie_phy_init()
262 ret = reset_control_assert(priv->phy_reset); in ltq_vrx200_pcie_phy_init()
268 ret = reset_control_deassert(priv->phy_reset); in ltq_vrx200_pcie_phy_init()
274 ret = reset_control_deassert(priv->pcie_reset); in ltq_vrx200_pcie_phy_init()
278 /* Make sure PHY PLL is stable */ in ltq_vrx200_pcie_phy_init()
284 reset_control_assert(priv->phy_reset); in ltq_vrx200_pcie_phy_init()
289 static int ltq_vrx200_pcie_phy_exit(struct phy *phy) in ltq_vrx200_pcie_phy_exit() argument
291 struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); in ltq_vrx200_pcie_phy_exit()
294 ret = reset_control_assert(priv->pcie_reset); in ltq_vrx200_pcie_phy_exit()
298 ret = reset_control_assert(priv->phy_reset); in ltq_vrx200_pcie_phy_exit()
305 static int ltq_vrx200_pcie_phy_power_on(struct phy *phy) in ltq_vrx200_pcie_phy_power_on() argument
307 struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); in ltq_vrx200_pcie_phy_power_on()
310 /* Enable PDI to access PCIe PHY register */ in ltq_vrx200_pcie_phy_power_on()
311 ret = clk_prepare_enable(priv->pdi_clk); in ltq_vrx200_pcie_phy_power_on()
315 /* Configure PLL and PHY clock */ in ltq_vrx200_pcie_phy_power_on()
316 ltq_vrx200_pcie_phy_common_setup(phy); in ltq_vrx200_pcie_phy_power_on()
318 pcie_phy_36mhz_mode_setup(phy); in ltq_vrx200_pcie_phy_power_on()
320 /* Enable the PCIe PHY and make PLL setting take effect */ in ltq_vrx200_pcie_phy_power_on()
321 ret = clk_prepare_enable(priv->phy_clk); in ltq_vrx200_pcie_phy_power_on()
326 if (ltq_vrx200_pcie_phy_wait_for_pll(phy) != 0) in ltq_vrx200_pcie_phy_power_on()
329 ltq_vrx200_pcie_phy_apply_workarounds(phy); in ltq_vrx200_pcie_phy_power_on()
334 clk_disable_unprepare(priv->phy_clk); in ltq_vrx200_pcie_phy_power_on()
336 clk_disable_unprepare(priv->pdi_clk); in ltq_vrx200_pcie_phy_power_on()
341 static int ltq_vrx200_pcie_phy_power_off(struct phy *phy) in ltq_vrx200_pcie_phy_power_off() argument
343 struct ltq_vrx200_pcie_phy_priv *priv = phy_get_drvdata(phy); in ltq_vrx200_pcie_phy_power_off()
345 clk_disable_unprepare(priv->phy_clk); in ltq_vrx200_pcie_phy_power_off()
346 clk_disable_unprepare(priv->pdi_clk); in ltq_vrx200_pcie_phy_power_off()
359 static struct phy *ltq_vrx200_pcie_phy_xlate(struct device *dev, in ltq_vrx200_pcie_phy_xlate()
363 unsigned int mode; in ltq_vrx200_pcie_phy_xlate() local
365 if (args->args_count != 1) { in ltq_vrx200_pcie_phy_xlate()
367 return ERR_PTR(-EINVAL); in ltq_vrx200_pcie_phy_xlate()
370 mode = args->args[0]; in ltq_vrx200_pcie_phy_xlate()
372 switch (mode) { in ltq_vrx200_pcie_phy_xlate()
374 priv->mode = mode; in ltq_vrx200_pcie_phy_xlate()
382 dev_err(dev, "PHY mode not implemented yet: %u\n", mode); in ltq_vrx200_pcie_phy_xlate()
383 return ERR_PTR(-EINVAL); in ltq_vrx200_pcie_phy_xlate()
386 dev_err(dev, "invalid PHY mode %u\n", mode); in ltq_vrx200_pcie_phy_xlate()
387 return ERR_PTR(-EINVAL); in ltq_vrx200_pcie_phy_xlate()
390 return priv->phy; in ltq_vrx200_pcie_phy_xlate()
402 struct device *dev = &pdev->dev; in ltq_vrx200_pcie_phy_probe()
410 return -ENOMEM; in ltq_vrx200_pcie_phy_probe()
417 priv->phy_regmap = devm_regmap_init_mmio(dev, base, ®map_config); in ltq_vrx200_pcie_phy_probe()
418 if (IS_ERR(priv->phy_regmap)) in ltq_vrx200_pcie_phy_probe()
419 return PTR_ERR(priv->phy_regmap); in ltq_vrx200_pcie_phy_probe()
421 priv->rcu_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, in ltq_vrx200_pcie_phy_probe()
423 if (IS_ERR(priv->rcu_regmap)) in ltq_vrx200_pcie_phy_probe()
424 return PTR_ERR(priv->rcu_regmap); in ltq_vrx200_pcie_phy_probe()
426 ret = device_property_read_u32(dev, "lantiq,rcu-endian-offset", in ltq_vrx200_pcie_phy_probe()
427 &priv->rcu_ahb_endian_offset); in ltq_vrx200_pcie_phy_probe()
430 "failed to parse the 'lantiq,rcu-endian-offset' property\n"); in ltq_vrx200_pcie_phy_probe()
434 ret = device_property_read_u32(dev, "lantiq,rcu-big-endian-mask", in ltq_vrx200_pcie_phy_probe()
435 &priv->rcu_ahb_endian_big_endian_mask); in ltq_vrx200_pcie_phy_probe()
438 "failed to parse the 'lantiq,rcu-big-endian-mask' property\n"); in ltq_vrx200_pcie_phy_probe()
442 priv->pdi_clk = devm_clk_get(dev, "pdi"); in ltq_vrx200_pcie_phy_probe()
443 if (IS_ERR(priv->pdi_clk)) in ltq_vrx200_pcie_phy_probe()
444 return PTR_ERR(priv->pdi_clk); in ltq_vrx200_pcie_phy_probe()
446 priv->phy_clk = devm_clk_get(dev, "phy"); in ltq_vrx200_pcie_phy_probe()
447 if (IS_ERR(priv->phy_clk)) in ltq_vrx200_pcie_phy_probe()
448 return PTR_ERR(priv->phy_clk); in ltq_vrx200_pcie_phy_probe()
450 priv->phy_reset = devm_reset_control_get_exclusive(dev, "phy"); in ltq_vrx200_pcie_phy_probe()
451 if (IS_ERR(priv->phy_reset)) in ltq_vrx200_pcie_phy_probe()
452 return PTR_ERR(priv->phy_reset); in ltq_vrx200_pcie_phy_probe()
454 priv->pcie_reset = devm_reset_control_get_shared(dev, "pcie"); in ltq_vrx200_pcie_phy_probe()
455 if (IS_ERR(priv->pcie_reset)) in ltq_vrx200_pcie_phy_probe()
456 return PTR_ERR(priv->pcie_reset); in ltq_vrx200_pcie_phy_probe()
458 priv->dev = dev; in ltq_vrx200_pcie_phy_probe()
460 priv->phy = devm_phy_create(dev, dev->of_node, in ltq_vrx200_pcie_phy_probe()
462 if (IS_ERR(priv->phy)) { in ltq_vrx200_pcie_phy_probe()
463 dev_err(dev, "failed to create PHY\n"); in ltq_vrx200_pcie_phy_probe()
464 return PTR_ERR(priv->phy); in ltq_vrx200_pcie_phy_probe()
467 phy_set_drvdata(priv->phy, priv); in ltq_vrx200_pcie_phy_probe()
477 { .compatible = "lantiq,vrx200-pcie-phy", },
478 { .compatible = "lantiq,arx300-pcie-phy", },
486 .name = "ltq-vrx200-pcie-phy",
493 MODULE_DESCRIPTION("Lantiq VRX200 and ARX300 PCIe PHY driver");