Lines Matching +full:phy +full:- +full:grf
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Rockchip PCIe PHY driver
5 * Copyright (C) 2016 Shawn Lin <shawn.lin@rock-chips.com>
17 #include <linux/phy/phy.h>
23 * The higher 16-bit of this register is used for write protection
69 struct phy *phy; member
82 phys[inst->index]); in to_pcie_phy()
85 static struct phy *rockchip_pcie_phy_of_xlate(struct device *dev, in rockchip_pcie_phy_of_xlate()
90 if (args->args_count == 0) in rockchip_pcie_phy_of_xlate()
91 return rk_phy->phys[0].phy; in rockchip_pcie_phy_of_xlate()
93 if (WARN_ON(args->args[0] >= PHY_MAX_LANE_NUM)) in rockchip_pcie_phy_of_xlate()
94 return ERR_PTR(-ENODEV); in rockchip_pcie_phy_of_xlate()
96 return rk_phy->phys[args->args[0]].phy; in rockchip_pcie_phy_of_xlate()
103 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, in phy_wr_cfg()
111 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, in phy_wr_cfg()
116 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, in phy_wr_cfg()
127 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, in phy_rd_cfg()
131 regmap_read(rk_phy->reg_base, in phy_rd_cfg()
132 rk_phy->phy_data->pcie_status, in phy_rd_cfg()
137 static int rockchip_pcie_phy_power_off(struct phy *phy) in rockchip_pcie_phy_power_off() argument
139 struct phy_pcie_instance *inst = phy_get_drvdata(phy); in rockchip_pcie_phy_power_off()
143 mutex_lock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_power_off()
145 regmap_write(rk_phy->reg_base, in rockchip_pcie_phy_power_off()
146 rk_phy->phy_data->pcie_laneoff, in rockchip_pcie_phy_power_off()
149 PHY_LANE_IDLE_A_SHIFT + inst->index)); in rockchip_pcie_phy_power_off()
151 if (--rk_phy->pwr_cnt) in rockchip_pcie_phy_power_off()
154 err = reset_control_assert(rk_phy->phy_rst); in rockchip_pcie_phy_power_off()
156 dev_err(&phy->dev, "assert phy_rst err %d\n", err); in rockchip_pcie_phy_power_off()
161 mutex_unlock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_power_off()
165 rk_phy->pwr_cnt++; in rockchip_pcie_phy_power_off()
166 regmap_write(rk_phy->reg_base, in rockchip_pcie_phy_power_off()
167 rk_phy->phy_data->pcie_laneoff, in rockchip_pcie_phy_power_off()
170 PHY_LANE_IDLE_A_SHIFT + inst->index)); in rockchip_pcie_phy_power_off()
171 mutex_unlock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_power_off()
175 static int rockchip_pcie_phy_power_on(struct phy *phy) in rockchip_pcie_phy_power_on() argument
177 struct phy_pcie_instance *inst = phy_get_drvdata(phy); in rockchip_pcie_phy_power_on()
183 mutex_lock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_power_on()
185 if (rk_phy->pwr_cnt++) in rockchip_pcie_phy_power_on()
188 err = reset_control_deassert(rk_phy->phy_rst); in rockchip_pcie_phy_power_on()
190 dev_err(&phy->dev, "deassert phy_rst err %d\n", err); in rockchip_pcie_phy_power_on()
194 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, in rockchip_pcie_phy_power_on()
199 regmap_write(rk_phy->reg_base, in rockchip_pcie_phy_power_on()
200 rk_phy->phy_data->pcie_laneoff, in rockchip_pcie_phy_power_on()
203 PHY_LANE_IDLE_A_SHIFT + inst->index)); in rockchip_pcie_phy_power_on()
206 * No documented timeout value for phy operation below, in rockchip_pcie_phy_power_on()
207 * so we make it large enough here. And we use loop-break in rockchip_pcie_phy_power_on()
212 err = -EINVAL; in rockchip_pcie_phy_power_on()
214 regmap_read(rk_phy->reg_base, in rockchip_pcie_phy_power_on()
215 rk_phy->phy_data->pcie_status, in rockchip_pcie_phy_power_on()
218 dev_dbg(&phy->dev, "pll locked!\n"); in rockchip_pcie_phy_power_on()
226 dev_err(&phy->dev, "pll lock timeout!\n"); in rockchip_pcie_phy_power_on()
233 err = -ETIMEDOUT; in rockchip_pcie_phy_power_on()
235 regmap_read(rk_phy->reg_base, in rockchip_pcie_phy_power_on()
236 rk_phy->phy_data->pcie_status, in rockchip_pcie_phy_power_on()
239 dev_dbg(&phy->dev, "pll output enable done!\n"); in rockchip_pcie_phy_power_on()
247 dev_err(&phy->dev, "pll output enable timeout!\n"); in rockchip_pcie_phy_power_on()
251 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, in rockchip_pcie_phy_power_on()
255 err = -EINVAL; in rockchip_pcie_phy_power_on()
257 regmap_read(rk_phy->reg_base, in rockchip_pcie_phy_power_on()
258 rk_phy->phy_data->pcie_status, in rockchip_pcie_phy_power_on()
261 dev_dbg(&phy->dev, "pll relocked!\n"); in rockchip_pcie_phy_power_on()
269 dev_err(&phy->dev, "pll relock timeout!\n"); in rockchip_pcie_phy_power_on()
274 mutex_unlock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_power_on()
278 reset_control_assert(rk_phy->phy_rst); in rockchip_pcie_phy_power_on()
280 rk_phy->pwr_cnt--; in rockchip_pcie_phy_power_on()
281 mutex_unlock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_power_on()
285 static int rockchip_pcie_phy_init(struct phy *phy) in rockchip_pcie_phy_init() argument
287 struct phy_pcie_instance *inst = phy_get_drvdata(phy); in rockchip_pcie_phy_init()
291 mutex_lock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_init()
293 if (rk_phy->init_cnt++) in rockchip_pcie_phy_init()
296 err = clk_prepare_enable(rk_phy->clk_pciephy_ref); in rockchip_pcie_phy_init()
298 dev_err(&phy->dev, "Fail to enable pcie ref clock.\n"); in rockchip_pcie_phy_init()
302 err = reset_control_assert(rk_phy->phy_rst); in rockchip_pcie_phy_init()
304 dev_err(&phy->dev, "assert phy_rst err %d\n", err); in rockchip_pcie_phy_init()
309 mutex_unlock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_init()
314 clk_disable_unprepare(rk_phy->clk_pciephy_ref); in rockchip_pcie_phy_init()
316 rk_phy->init_cnt--; in rockchip_pcie_phy_init()
317 mutex_unlock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_init()
321 static int rockchip_pcie_phy_exit(struct phy *phy) in rockchip_pcie_phy_exit() argument
323 struct phy_pcie_instance *inst = phy_get_drvdata(phy); in rockchip_pcie_phy_exit()
326 mutex_lock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_exit()
328 if (--rk_phy->init_cnt) in rockchip_pcie_phy_exit()
331 clk_disable_unprepare(rk_phy->clk_pciephy_ref); in rockchip_pcie_phy_exit()
334 mutex_unlock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_exit()
354 .compatible = "rockchip,rk3399-pcie-phy",
364 struct device *dev = &pdev->dev; in rockchip_pcie_phy_probe()
367 struct regmap *grf; in rockchip_pcie_phy_probe() local
372 grf = syscon_node_to_regmap(dev->parent->of_node); in rockchip_pcie_phy_probe()
373 if (IS_ERR(grf)) { in rockchip_pcie_phy_probe()
374 dev_err(dev, "Cannot find GRF syscon\n"); in rockchip_pcie_phy_probe()
375 return PTR_ERR(grf); in rockchip_pcie_phy_probe()
380 return -ENOMEM; in rockchip_pcie_phy_probe()
382 of_id = of_match_device(rockchip_pcie_phy_dt_ids, &pdev->dev); in rockchip_pcie_phy_probe()
384 return -EINVAL; in rockchip_pcie_phy_probe()
386 rk_phy->phy_data = (struct rockchip_pcie_data *)of_id->data; in rockchip_pcie_phy_probe()
387 rk_phy->reg_base = grf; in rockchip_pcie_phy_probe()
389 mutex_init(&rk_phy->pcie_mutex); in rockchip_pcie_phy_probe()
391 rk_phy->phy_rst = devm_reset_control_get(dev, "phy"); in rockchip_pcie_phy_probe()
392 if (IS_ERR(rk_phy->phy_rst)) { in rockchip_pcie_phy_probe()
393 if (PTR_ERR(rk_phy->phy_rst) != -EPROBE_DEFER) in rockchip_pcie_phy_probe()
395 "missing phy property for reset controller\n"); in rockchip_pcie_phy_probe()
396 return PTR_ERR(rk_phy->phy_rst); in rockchip_pcie_phy_probe()
399 rk_phy->clk_pciephy_ref = devm_clk_get(dev, "refclk"); in rockchip_pcie_phy_probe()
400 if (IS_ERR(rk_phy->clk_pciephy_ref)) { in rockchip_pcie_phy_probe()
402 return PTR_ERR(rk_phy->clk_pciephy_ref); in rockchip_pcie_phy_probe()
405 /* parse #phy-cells to see if it's legacy PHY model */ in rockchip_pcie_phy_probe()
406 if (of_property_read_u32(dev->of_node, "#phy-cells", &phy_num)) in rockchip_pcie_phy_probe()
407 return -ENOENT; in rockchip_pcie_phy_probe()
410 dev_dbg(dev, "phy number is %d\n", phy_num); in rockchip_pcie_phy_probe()
413 rk_phy->phys[i].phy = devm_phy_create(dev, dev->of_node, &ops); in rockchip_pcie_phy_probe()
414 if (IS_ERR(rk_phy->phys[i].phy)) { in rockchip_pcie_phy_probe()
415 dev_err(dev, "failed to create PHY%d\n", i); in rockchip_pcie_phy_probe()
416 return PTR_ERR(rk_phy->phys[i].phy); in rockchip_pcie_phy_probe()
418 rk_phy->phys[i].index = i; in rockchip_pcie_phy_probe()
419 phy_set_drvdata(rk_phy->phys[i].phy, &rk_phy->phys[i]); in rockchip_pcie_phy_probe()
432 .name = "rockchip-pcie-phy",
439 MODULE_AUTHOR("Shawn Lin <shawn.lin@rock-chips.com>");
440 MODULE_DESCRIPTION("Rockchip PCIe PHY driver");