1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * P2U (PIPE to UPHY) driver for Tegra T194 SoC 4 * 5 * Copyright (C) 2019 NVIDIA Corporation. 6 * 7 * Author: Vidya Sagar <vidyas@nvidia.com> 8 */ 9 10 #include <linux/err.h> 11 #include <linux/io.h> 12 #include <linux/module.h> 13 #include <linux/of.h> 14 #include <linux/of_platform.h> 15 #include <linux/phy/phy.h> 16 17 #define P2U_PERIODIC_EQ_CTRL_GEN3 0xc0 18 #define P2U_PERIODIC_EQ_CTRL_GEN3_PERIODIC_EQ_EN BIT(0) 19 #define P2U_PERIODIC_EQ_CTRL_GEN3_INIT_PRESET_EQ_TRAIN_EN BIT(1) 20 #define P2U_PERIODIC_EQ_CTRL_GEN4 0xc4 21 #define P2U_PERIODIC_EQ_CTRL_GEN4_INIT_PRESET_EQ_TRAIN_EN BIT(1) 22 23 #define P2U_RX_DEBOUNCE_TIME 0xa4 24 #define P2U_RX_DEBOUNCE_TIME_DEBOUNCE_TIMER_MASK 0xffff 25 #define P2U_RX_DEBOUNCE_TIME_DEBOUNCE_TIMER_VAL 160 26 27 struct tegra_p2u { 28 void __iomem *base; 29 }; 30 31 static inline void p2u_writel(struct tegra_p2u *phy, const u32 value, 32 const u32 reg) 33 { 34 writel_relaxed(value, phy->base + reg); 35 } 36 37 static inline u32 p2u_readl(struct tegra_p2u *phy, const u32 reg) 38 { 39 return readl_relaxed(phy->base + reg); 40 } 41 42 static int tegra_p2u_power_on(struct phy *x) 43 { 44 struct tegra_p2u *phy = phy_get_drvdata(x); 45 u32 val; 46 47 val = p2u_readl(phy, P2U_PERIODIC_EQ_CTRL_GEN3); 48 val &= ~P2U_PERIODIC_EQ_CTRL_GEN3_PERIODIC_EQ_EN; 49 val |= P2U_PERIODIC_EQ_CTRL_GEN3_INIT_PRESET_EQ_TRAIN_EN; 50 p2u_writel(phy, val, P2U_PERIODIC_EQ_CTRL_GEN3); 51 52 val = p2u_readl(phy, P2U_PERIODIC_EQ_CTRL_GEN4); 53 val |= P2U_PERIODIC_EQ_CTRL_GEN4_INIT_PRESET_EQ_TRAIN_EN; 54 p2u_writel(phy, val, P2U_PERIODIC_EQ_CTRL_GEN4); 55 56 val = p2u_readl(phy, P2U_RX_DEBOUNCE_TIME); 57 val &= ~P2U_RX_DEBOUNCE_TIME_DEBOUNCE_TIMER_MASK; 58 val |= P2U_RX_DEBOUNCE_TIME_DEBOUNCE_TIMER_VAL; 59 p2u_writel(phy, val, P2U_RX_DEBOUNCE_TIME); 60 61 return 0; 62 } 63 64 static const struct phy_ops ops = { 65 .power_on = tegra_p2u_power_on, 66 .owner = THIS_MODULE, 67 }; 68 69 static int tegra_p2u_probe(struct platform_device *pdev) 70 { 71 struct phy_provider *phy_provider; 72 struct device *dev = &pdev->dev; 73 struct phy *generic_phy; 74 struct tegra_p2u *phy; 75 76 phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); 77 if (!phy) 78 return -ENOMEM; 79 80 phy->base = devm_platform_ioremap_resource_byname(pdev, "ctl"); 81 if (IS_ERR(phy->base)) 82 return PTR_ERR(phy->base); 83 84 platform_set_drvdata(pdev, phy); 85 86 generic_phy = devm_phy_create(dev, NULL, &ops); 87 if (IS_ERR(generic_phy)) 88 return PTR_ERR(generic_phy); 89 90 phy_set_drvdata(generic_phy, phy); 91 92 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 93 if (IS_ERR(phy_provider)) 94 return PTR_ERR(phy_provider); 95 96 return 0; 97 } 98 99 static const struct of_device_id tegra_p2u_id_table[] = { 100 { 101 .compatible = "nvidia,tegra194-p2u", 102 }, 103 {} 104 }; 105 MODULE_DEVICE_TABLE(of, tegra_p2u_id_table); 106 107 static struct platform_driver tegra_p2u_driver = { 108 .probe = tegra_p2u_probe, 109 .driver = { 110 .name = "tegra194-p2u", 111 .of_match_table = tegra_p2u_id_table, 112 }, 113 }; 114 module_platform_driver(tegra_p2u_driver); 115 116 MODULE_AUTHOR("Vidya Sagar <vidyas@nvidia.com>"); 117 MODULE_DESCRIPTION("NVIDIA Tegra194 PIPE2UPHY PHY driver"); 118 MODULE_LICENSE("GPL v2"); 119