1 /* 2 * Rockchip PCIe PHY driver 3 * 4 * Copyright (C) 2016 Shawn Lin <shawn.lin@rock-chips.com> 5 * Copyright (C) 2016 ROCKCHIP, Inc. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17 #include <linux/clk.h> 18 #include <linux/delay.h> 19 #include <linux/io.h> 20 #include <linux/mfd/syscon.h> 21 #include <linux/module.h> 22 #include <linux/of.h> 23 #include <linux/of_address.h> 24 #include <linux/of_platform.h> 25 #include <linux/phy/phy.h> 26 #include <linux/platform_device.h> 27 #include <linux/regmap.h> 28 #include <linux/reset.h> 29 30 /* 31 * The higher 16-bit of this register is used for write protection 32 * only if BIT(x + 16) set to 1 the BIT(x) can be written. 33 */ 34 #define HIWORD_UPDATE(val, mask, shift) \ 35 ((val) << (shift) | (mask) << ((shift) + 16)) 36 37 #define PHY_MAX_LANE_NUM 4 38 #define PHY_CFG_DATA_SHIFT 7 39 #define PHY_CFG_ADDR_SHIFT 1 40 #define PHY_CFG_DATA_MASK 0xf 41 #define PHY_CFG_ADDR_MASK 0x3f 42 #define PHY_CFG_RD_MASK 0x3ff 43 #define PHY_CFG_WR_ENABLE 1 44 #define PHY_CFG_WR_DISABLE 1 45 #define PHY_CFG_WR_SHIFT 0 46 #define PHY_CFG_WR_MASK 1 47 #define PHY_CFG_PLL_LOCK 0x10 48 #define PHY_CFG_CLK_TEST 0x10 49 #define PHY_CFG_CLK_SCC 0x12 50 #define PHY_CFG_SEPE_RATE BIT(3) 51 #define PHY_CFG_PLL_100M BIT(3) 52 #define PHY_PLL_LOCKED BIT(9) 53 #define PHY_PLL_OUTPUT BIT(10) 54 #define PHY_LANE_A_STATUS 0x30 55 #define PHY_LANE_B_STATUS 0x31 56 #define PHY_LANE_C_STATUS 0x32 57 #define PHY_LANE_D_STATUS 0x33 58 #define PHY_LANE_RX_DET_SHIFT 11 59 #define PHY_LANE_RX_DET_TH 0x1 60 #define PHY_LANE_IDLE_OFF 0x1 61 #define PHY_LANE_IDLE_MASK 0x1 62 #define PHY_LANE_IDLE_A_SHIFT 3 63 #define PHY_LANE_IDLE_B_SHIFT 4 64 #define PHY_LANE_IDLE_C_SHIFT 5 65 #define PHY_LANE_IDLE_D_SHIFT 6 66 67 struct rockchip_pcie_data { 68 unsigned int pcie_conf; 69 unsigned int pcie_status; 70 unsigned int pcie_laneoff; 71 }; 72 73 struct rockchip_pcie_phy { 74 struct rockchip_pcie_data *phy_data; 75 struct regmap *reg_base; 76 struct reset_control *phy_rst; 77 struct clk *clk_pciephy_ref; 78 }; 79 80 static inline void phy_wr_cfg(struct rockchip_pcie_phy *rk_phy, 81 u32 addr, u32 data) 82 { 83 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, 84 HIWORD_UPDATE(data, 85 PHY_CFG_DATA_MASK, 86 PHY_CFG_DATA_SHIFT) | 87 HIWORD_UPDATE(addr, 88 PHY_CFG_ADDR_MASK, 89 PHY_CFG_ADDR_SHIFT)); 90 udelay(1); 91 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, 92 HIWORD_UPDATE(PHY_CFG_WR_ENABLE, 93 PHY_CFG_WR_MASK, 94 PHY_CFG_WR_SHIFT)); 95 udelay(1); 96 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, 97 HIWORD_UPDATE(PHY_CFG_WR_DISABLE, 98 PHY_CFG_WR_MASK, 99 PHY_CFG_WR_SHIFT)); 100 } 101 102 static inline u32 phy_rd_cfg(struct rockchip_pcie_phy *rk_phy, 103 u32 addr) 104 { 105 u32 val; 106 107 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, 108 HIWORD_UPDATE(addr, 109 PHY_CFG_RD_MASK, 110 PHY_CFG_ADDR_SHIFT)); 111 regmap_read(rk_phy->reg_base, 112 rk_phy->phy_data->pcie_status, 113 &val); 114 return val; 115 } 116 117 static int rockchip_pcie_phy_power_off(struct phy *phy) 118 { 119 struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy); 120 int err = 0; 121 122 err = reset_control_assert(rk_phy->phy_rst); 123 if (err) { 124 dev_err(&phy->dev, "assert phy_rst err %d\n", err); 125 return err; 126 } 127 128 return 0; 129 } 130 131 static int rockchip_pcie_phy_power_on(struct phy *phy) 132 { 133 struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy); 134 int err = 0; 135 u32 status; 136 unsigned long timeout; 137 138 err = reset_control_deassert(rk_phy->phy_rst); 139 if (err) { 140 dev_err(&phy->dev, "deassert phy_rst err %d\n", err); 141 return err; 142 } 143 144 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, 145 HIWORD_UPDATE(PHY_CFG_PLL_LOCK, 146 PHY_CFG_ADDR_MASK, 147 PHY_CFG_ADDR_SHIFT)); 148 149 /* 150 * No documented timeout value for phy operation below, 151 * so we make it large enough here. And we use loop-break 152 * method which should not be harmful. 153 */ 154 timeout = jiffies + msecs_to_jiffies(1000); 155 156 err = -EINVAL; 157 while (time_before(jiffies, timeout)) { 158 regmap_read(rk_phy->reg_base, 159 rk_phy->phy_data->pcie_status, 160 &status); 161 if (status & PHY_PLL_LOCKED) { 162 dev_dbg(&phy->dev, "pll locked!\n"); 163 err = 0; 164 break; 165 } 166 msleep(20); 167 } 168 169 if (err) { 170 dev_err(&phy->dev, "pll lock timeout!\n"); 171 goto err_pll_lock; 172 } 173 174 phy_wr_cfg(rk_phy, PHY_CFG_CLK_TEST, PHY_CFG_SEPE_RATE); 175 phy_wr_cfg(rk_phy, PHY_CFG_CLK_SCC, PHY_CFG_PLL_100M); 176 177 err = -ETIMEDOUT; 178 while (time_before(jiffies, timeout)) { 179 regmap_read(rk_phy->reg_base, 180 rk_phy->phy_data->pcie_status, 181 &status); 182 if (!(status & PHY_PLL_OUTPUT)) { 183 dev_dbg(&phy->dev, "pll output enable done!\n"); 184 err = 0; 185 break; 186 } 187 msleep(20); 188 } 189 190 if (err) { 191 dev_err(&phy->dev, "pll output enable timeout!\n"); 192 goto err_pll_lock; 193 } 194 195 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, 196 HIWORD_UPDATE(PHY_CFG_PLL_LOCK, 197 PHY_CFG_ADDR_MASK, 198 PHY_CFG_ADDR_SHIFT)); 199 err = -EINVAL; 200 while (time_before(jiffies, timeout)) { 201 regmap_read(rk_phy->reg_base, 202 rk_phy->phy_data->pcie_status, 203 &status); 204 if (status & PHY_PLL_LOCKED) { 205 dev_dbg(&phy->dev, "pll relocked!\n"); 206 err = 0; 207 break; 208 } 209 msleep(20); 210 } 211 212 if (err) { 213 dev_err(&phy->dev, "pll relock timeout!\n"); 214 goto err_pll_lock; 215 } 216 217 return 0; 218 219 err_pll_lock: 220 reset_control_assert(rk_phy->phy_rst); 221 return err; 222 } 223 224 static int rockchip_pcie_phy_init(struct phy *phy) 225 { 226 struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy); 227 int err = 0; 228 229 err = clk_prepare_enable(rk_phy->clk_pciephy_ref); 230 if (err) { 231 dev_err(&phy->dev, "Fail to enable pcie ref clock.\n"); 232 goto err_refclk; 233 } 234 235 err = reset_control_assert(rk_phy->phy_rst); 236 if (err) { 237 dev_err(&phy->dev, "assert phy_rst err %d\n", err); 238 goto err_reset; 239 } 240 241 return err; 242 243 err_reset: 244 clk_disable_unprepare(rk_phy->clk_pciephy_ref); 245 err_refclk: 246 return err; 247 } 248 249 static int rockchip_pcie_phy_exit(struct phy *phy) 250 { 251 struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy); 252 253 clk_disable_unprepare(rk_phy->clk_pciephy_ref); 254 255 return 0; 256 } 257 258 static const struct phy_ops ops = { 259 .init = rockchip_pcie_phy_init, 260 .exit = rockchip_pcie_phy_exit, 261 .power_on = rockchip_pcie_phy_power_on, 262 .power_off = rockchip_pcie_phy_power_off, 263 .owner = THIS_MODULE, 264 }; 265 266 static const struct rockchip_pcie_data rk3399_pcie_data = { 267 .pcie_conf = 0xe220, 268 .pcie_status = 0xe2a4, 269 .pcie_laneoff = 0xe214, 270 }; 271 272 static const struct of_device_id rockchip_pcie_phy_dt_ids[] = { 273 { 274 .compatible = "rockchip,rk3399-pcie-phy", 275 .data = &rk3399_pcie_data, 276 }, 277 {} 278 }; 279 280 MODULE_DEVICE_TABLE(of, rockchip_pcie_phy_dt_ids); 281 282 static int rockchip_pcie_phy_probe(struct platform_device *pdev) 283 { 284 struct device *dev = &pdev->dev; 285 struct rockchip_pcie_phy *rk_phy; 286 struct phy *generic_phy; 287 struct phy_provider *phy_provider; 288 struct regmap *grf; 289 const struct of_device_id *of_id; 290 291 grf = syscon_node_to_regmap(dev->parent->of_node); 292 if (IS_ERR(grf)) { 293 dev_err(dev, "Cannot find GRF syscon\n"); 294 return PTR_ERR(grf); 295 } 296 297 rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL); 298 if (!rk_phy) 299 return -ENOMEM; 300 301 of_id = of_match_device(rockchip_pcie_phy_dt_ids, &pdev->dev); 302 if (!of_id) 303 return -EINVAL; 304 305 rk_phy->phy_data = (struct rockchip_pcie_data *)of_id->data; 306 rk_phy->reg_base = grf; 307 308 rk_phy->phy_rst = devm_reset_control_get(dev, "phy"); 309 if (IS_ERR(rk_phy->phy_rst)) { 310 if (PTR_ERR(rk_phy->phy_rst) != -EPROBE_DEFER) 311 dev_err(dev, 312 "missing phy property for reset controller\n"); 313 return PTR_ERR(rk_phy->phy_rst); 314 } 315 316 rk_phy->clk_pciephy_ref = devm_clk_get(dev, "refclk"); 317 if (IS_ERR(rk_phy->clk_pciephy_ref)) { 318 dev_err(dev, "refclk not found.\n"); 319 return PTR_ERR(rk_phy->clk_pciephy_ref); 320 } 321 322 generic_phy = devm_phy_create(dev, dev->of_node, &ops); 323 if (IS_ERR(generic_phy)) { 324 dev_err(dev, "failed to create PHY\n"); 325 return PTR_ERR(generic_phy); 326 } 327 328 phy_set_drvdata(generic_phy, rk_phy); 329 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 330 331 return PTR_ERR_OR_ZERO(phy_provider); 332 } 333 334 static struct platform_driver rockchip_pcie_driver = { 335 .probe = rockchip_pcie_phy_probe, 336 .driver = { 337 .name = "rockchip-pcie-phy", 338 .of_match_table = rockchip_pcie_phy_dt_ids, 339 }, 340 }; 341 342 module_platform_driver(rockchip_pcie_driver); 343 344 MODULE_AUTHOR("Shawn Lin <shawn.lin@rock-chips.com>"); 345 MODULE_DESCRIPTION("Rockchip PCIe PHY driver"); 346 MODULE_LICENSE("GPL v2"); 347