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 struct resource *res; 76 77 phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); 78 if (!phy) 79 return -ENOMEM; 80 81 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctl"); 82 phy->base = devm_ioremap_resource(dev, res); 83 if (IS_ERR(phy->base)) 84 return PTR_ERR(phy->base); 85 86 platform_set_drvdata(pdev, phy); 87 88 generic_phy = devm_phy_create(dev, NULL, &ops); 89 if (IS_ERR(generic_phy)) 90 return PTR_ERR(generic_phy); 91 92 phy_set_drvdata(generic_phy, phy); 93 94 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 95 if (IS_ERR(phy_provider)) 96 return PTR_ERR(phy_provider); 97 98 return 0; 99 } 100 101 static const struct of_device_id tegra_p2u_id_table[] = { 102 { 103 .compatible = "nvidia,tegra194-p2u", 104 }, 105 {} 106 }; 107 MODULE_DEVICE_TABLE(of, tegra_p2u_id_table); 108 109 static struct platform_driver tegra_p2u_driver = { 110 .probe = tegra_p2u_probe, 111 .driver = { 112 .name = "tegra194-p2u", 113 .of_match_table = tegra_p2u_id_table, 114 }, 115 }; 116 module_platform_driver(tegra_p2u_driver); 117 118 MODULE_AUTHOR("Vidya Sagar <vidyas@nvidia.com>"); 119 MODULE_DESCRIPTION("NVIDIA Tegra194 PIPE2UPHY PHY driver"); 120 MODULE_LICENSE("GPL v2"); 121