1 /* 2 * Samsung EXYNOS SoC series PCIe PHY driver 3 * 4 * Phy provider for PCIe controller on Exynos SoC series 5 * 6 * Copyright (C) 2017 Samsung Electronics Co., Ltd. 7 * Jaehoon Chung <jh80.chung@samsung.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14 #include <linux/delay.h> 15 #include <linux/io.h> 16 #include <linux/iopoll.h> 17 #include <linux/init.h> 18 #include <linux/mfd/syscon.h> 19 #include <linux/of.h> 20 #include <linux/of_address.h> 21 #include <linux/of_platform.h> 22 #include <linux/platform_device.h> 23 #include <linux/phy/phy.h> 24 #include <linux/regmap.h> 25 26 /* PCIe Purple registers */ 27 #define PCIE_PHY_GLOBAL_RESET 0x000 28 #define PCIE_PHY_COMMON_RESET 0x004 29 #define PCIE_PHY_CMN_REG 0x008 30 #define PCIE_PHY_MAC_RESET 0x00c 31 #define PCIE_PHY_PLL_LOCKED 0x010 32 #define PCIE_PHY_TRSVREG_RESET 0x020 33 #define PCIE_PHY_TRSV_RESET 0x024 34 35 /* PCIe PHY registers */ 36 #define PCIE_PHY_IMPEDANCE 0x004 37 #define PCIE_PHY_PLL_DIV_0 0x008 38 #define PCIE_PHY_PLL_BIAS 0x00c 39 #define PCIE_PHY_DCC_FEEDBACK 0x014 40 #define PCIE_PHY_PLL_DIV_1 0x05c 41 #define PCIE_PHY_COMMON_POWER 0x064 42 #define PCIE_PHY_COMMON_PD_CMN BIT(3) 43 #define PCIE_PHY_TRSV0_EMP_LVL 0x084 44 #define PCIE_PHY_TRSV0_DRV_LVL 0x088 45 #define PCIE_PHY_TRSV0_RXCDR 0x0ac 46 #define PCIE_PHY_TRSV0_POWER 0x0c4 47 #define PCIE_PHY_TRSV0_PD_TSV BIT(7) 48 #define PCIE_PHY_TRSV0_LVCC 0x0dc 49 #define PCIE_PHY_TRSV1_EMP_LVL 0x144 50 #define PCIE_PHY_TRSV1_RXCDR 0x16c 51 #define PCIE_PHY_TRSV1_POWER 0x184 52 #define PCIE_PHY_TRSV1_PD_TSV BIT(7) 53 #define PCIE_PHY_TRSV1_LVCC 0x19c 54 #define PCIE_PHY_TRSV2_EMP_LVL 0x204 55 #define PCIE_PHY_TRSV2_RXCDR 0x22c 56 #define PCIE_PHY_TRSV2_POWER 0x244 57 #define PCIE_PHY_TRSV2_PD_TSV BIT(7) 58 #define PCIE_PHY_TRSV2_LVCC 0x25c 59 #define PCIE_PHY_TRSV3_EMP_LVL 0x2c4 60 #define PCIE_PHY_TRSV3_RXCDR 0x2ec 61 #define PCIE_PHY_TRSV3_POWER 0x304 62 #define PCIE_PHY_TRSV3_PD_TSV BIT(7) 63 #define PCIE_PHY_TRSV3_LVCC 0x31c 64 65 struct exynos_pcie_phy_data { 66 const struct phy_ops *ops; 67 }; 68 69 /* For Exynos pcie phy */ 70 struct exynos_pcie_phy { 71 const struct exynos_pcie_phy_data *drv_data; 72 void __iomem *phy_base; 73 void __iomem *blk_base; /* For exynos5440 */ 74 }; 75 76 static void exynos_pcie_phy_writel(void __iomem *base, u32 val, u32 offset) 77 { 78 writel(val, base + offset); 79 } 80 81 static u32 exynos_pcie_phy_readl(void __iomem *base, u32 offset) 82 { 83 return readl(base + offset); 84 } 85 86 /* For Exynos5440 specific functions */ 87 static int exynos5440_pcie_phy_init(struct phy *phy) 88 { 89 struct exynos_pcie_phy *ep = phy_get_drvdata(phy); 90 91 /* DCC feedback control off */ 92 exynos_pcie_phy_writel(ep->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK); 93 94 /* set TX/RX impedance */ 95 exynos_pcie_phy_writel(ep->phy_base, 0xd5, PCIE_PHY_IMPEDANCE); 96 97 /* set 50Mhz PHY clock */ 98 exynos_pcie_phy_writel(ep->phy_base, 0x14, PCIE_PHY_PLL_DIV_0); 99 exynos_pcie_phy_writel(ep->phy_base, 0x12, PCIE_PHY_PLL_DIV_1); 100 101 /* set TX Differential output for lane 0 */ 102 exynos_pcie_phy_writel(ep->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL); 103 104 /* set TX Pre-emphasis Level Control for lane 0 to minimum */ 105 exynos_pcie_phy_writel(ep->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL); 106 107 /* set RX clock and data recovery bandwidth */ 108 exynos_pcie_phy_writel(ep->phy_base, 0xe7, PCIE_PHY_PLL_BIAS); 109 exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR); 110 exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR); 111 exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR); 112 exynos_pcie_phy_writel(ep->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR); 113 114 /* change TX Pre-emphasis Level Control for lanes */ 115 exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL); 116 exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL); 117 exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL); 118 exynos_pcie_phy_writel(ep->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL); 119 120 /* set LVCC */ 121 exynos_pcie_phy_writel(ep->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC); 122 exynos_pcie_phy_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC); 123 exynos_pcie_phy_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC); 124 exynos_pcie_phy_writel(ep->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC); 125 126 /* pulse for common reset */ 127 exynos_pcie_phy_writel(ep->blk_base, 1, PCIE_PHY_COMMON_RESET); 128 udelay(500); 129 exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_COMMON_RESET); 130 131 return 0; 132 } 133 134 static int exynos5440_pcie_phy_power_on(struct phy *phy) 135 { 136 struct exynos_pcie_phy *ep = phy_get_drvdata(phy); 137 u32 val; 138 139 exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_COMMON_RESET); 140 exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_CMN_REG); 141 exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_TRSVREG_RESET); 142 exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_TRSV_RESET); 143 144 val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_COMMON_POWER); 145 val &= ~PCIE_PHY_COMMON_PD_CMN; 146 exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER); 147 148 val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER); 149 val &= ~PCIE_PHY_TRSV0_PD_TSV; 150 exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER); 151 152 val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER); 153 val &= ~PCIE_PHY_TRSV1_PD_TSV; 154 exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER); 155 156 val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER); 157 val &= ~PCIE_PHY_TRSV2_PD_TSV; 158 exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER); 159 160 val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER); 161 val &= ~PCIE_PHY_TRSV3_PD_TSV; 162 exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER); 163 164 return 0; 165 } 166 167 static int exynos5440_pcie_phy_power_off(struct phy *phy) 168 { 169 struct exynos_pcie_phy *ep = phy_get_drvdata(phy); 170 u32 val; 171 172 if (readl_poll_timeout(ep->phy_base + PCIE_PHY_PLL_LOCKED, val, 173 (val != 0), 1, 500)) { 174 dev_err(&phy->dev, "PLL Locked: 0x%x\n", val); 175 return -ETIMEDOUT; 176 } 177 178 val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_COMMON_POWER); 179 val |= PCIE_PHY_COMMON_PD_CMN; 180 exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_COMMON_POWER); 181 182 val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV0_POWER); 183 val |= PCIE_PHY_TRSV0_PD_TSV; 184 exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV0_POWER); 185 186 val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV1_POWER); 187 val |= PCIE_PHY_TRSV1_PD_TSV; 188 exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV1_POWER); 189 190 val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV2_POWER); 191 val |= PCIE_PHY_TRSV2_PD_TSV; 192 exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV2_POWER); 193 194 val = exynos_pcie_phy_readl(ep->phy_base, PCIE_PHY_TRSV3_POWER); 195 val |= PCIE_PHY_TRSV3_PD_TSV; 196 exynos_pcie_phy_writel(ep->phy_base, val, PCIE_PHY_TRSV3_POWER); 197 198 return 0; 199 } 200 201 static int exynos5440_pcie_phy_reset(struct phy *phy) 202 { 203 struct exynos_pcie_phy *ep = phy_get_drvdata(phy); 204 205 exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_MAC_RESET); 206 exynos_pcie_phy_writel(ep->blk_base, 1, PCIE_PHY_GLOBAL_RESET); 207 exynos_pcie_phy_writel(ep->blk_base, 0, PCIE_PHY_GLOBAL_RESET); 208 209 return 0; 210 } 211 212 static const struct phy_ops exynos5440_phy_ops = { 213 .init = exynos5440_pcie_phy_init, 214 .power_on = exynos5440_pcie_phy_power_on, 215 .power_off = exynos5440_pcie_phy_power_off, 216 .reset = exynos5440_pcie_phy_reset, 217 .owner = THIS_MODULE, 218 }; 219 220 static const struct exynos_pcie_phy_data exynos5440_pcie_phy_data = { 221 .ops = &exynos5440_phy_ops, 222 }; 223 224 static const struct of_device_id exynos_pcie_phy_match[] = { 225 { 226 .compatible = "samsung,exynos5440-pcie-phy", 227 .data = &exynos5440_pcie_phy_data, 228 }, 229 {}, 230 }; 231 232 static int exynos_pcie_phy_probe(struct platform_device *pdev) 233 { 234 struct device *dev = &pdev->dev; 235 struct exynos_pcie_phy *exynos_phy; 236 struct phy *generic_phy; 237 struct phy_provider *phy_provider; 238 struct resource *res; 239 const struct exynos_pcie_phy_data *drv_data; 240 241 drv_data = of_device_get_match_data(dev); 242 if (!drv_data) 243 return -ENODEV; 244 245 exynos_phy = devm_kzalloc(dev, sizeof(*exynos_phy), GFP_KERNEL); 246 if (!exynos_phy) 247 return -ENOMEM; 248 249 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 250 exynos_phy->phy_base = devm_ioremap_resource(dev, res); 251 if (IS_ERR(exynos_phy->phy_base)) 252 return PTR_ERR(exynos_phy->phy_base); 253 254 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 255 exynos_phy->blk_base = devm_ioremap_resource(dev, res); 256 if (IS_ERR(exynos_phy->blk_base)) 257 return PTR_ERR(exynos_phy->blk_base); 258 259 exynos_phy->drv_data = drv_data; 260 261 generic_phy = devm_phy_create(dev, dev->of_node, drv_data->ops); 262 if (IS_ERR(generic_phy)) { 263 dev_err(dev, "failed to create PHY\n"); 264 return PTR_ERR(generic_phy); 265 } 266 267 phy_set_drvdata(generic_phy, exynos_phy); 268 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 269 270 return PTR_ERR_OR_ZERO(phy_provider); 271 } 272 273 static struct platform_driver exynos_pcie_phy_driver = { 274 .probe = exynos_pcie_phy_probe, 275 .driver = { 276 .of_match_table = exynos_pcie_phy_match, 277 .name = "exynos_pcie_phy", 278 } 279 }; 280 281 builtin_platform_driver(exynos_pcie_phy_driver); 282