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>
15 #include <linux/phy/phy.h>
22 * The higher 16-bit of this register is used for write protection
68 struct phy *phy; member
81 phys[inst->index]); in to_pcie_phy()
84 static struct phy *rockchip_pcie_phy_of_xlate(struct device *dev, in rockchip_pcie_phy_of_xlate()
89 if (args->args_count == 0) in rockchip_pcie_phy_of_xlate()
90 return rk_phy->phys[0].phy; in rockchip_pcie_phy_of_xlate()
92 if (WARN_ON(args->args[0] >= PHY_MAX_LANE_NUM)) in rockchip_pcie_phy_of_xlate()
93 return ERR_PTR(-ENODEV); in rockchip_pcie_phy_of_xlate()
95 return rk_phy->phys[args->args[0]].phy; in rockchip_pcie_phy_of_xlate()
102 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, in phy_wr_cfg()
110 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, in phy_wr_cfg()
115 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, in phy_wr_cfg()
121 static int rockchip_pcie_phy_power_off(struct phy *phy) in rockchip_pcie_phy_power_off() argument
123 struct phy_pcie_instance *inst = phy_get_drvdata(phy); in rockchip_pcie_phy_power_off()
127 mutex_lock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_power_off()
129 regmap_write(rk_phy->reg_base, in rockchip_pcie_phy_power_off()
130 rk_phy->phy_data->pcie_laneoff, in rockchip_pcie_phy_power_off()
133 PHY_LANE_IDLE_A_SHIFT + inst->index)); in rockchip_pcie_phy_power_off()
135 if (--rk_phy->pwr_cnt) in rockchip_pcie_phy_power_off()
138 err = reset_control_assert(rk_phy->phy_rst); in rockchip_pcie_phy_power_off()
140 dev_err(&phy->dev, "assert phy_rst err %d\n", err); in rockchip_pcie_phy_power_off()
145 mutex_unlock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_power_off()
149 rk_phy->pwr_cnt++; in rockchip_pcie_phy_power_off()
150 regmap_write(rk_phy->reg_base, in rockchip_pcie_phy_power_off()
151 rk_phy->phy_data->pcie_laneoff, in rockchip_pcie_phy_power_off()
154 PHY_LANE_IDLE_A_SHIFT + inst->index)); in rockchip_pcie_phy_power_off()
155 mutex_unlock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_power_off()
159 static int rockchip_pcie_phy_power_on(struct phy *phy) in rockchip_pcie_phy_power_on() argument
161 struct phy_pcie_instance *inst = phy_get_drvdata(phy); in rockchip_pcie_phy_power_on()
167 mutex_lock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_power_on()
169 if (rk_phy->pwr_cnt++) in rockchip_pcie_phy_power_on()
172 err = reset_control_deassert(rk_phy->phy_rst); in rockchip_pcie_phy_power_on()
174 dev_err(&phy->dev, "deassert phy_rst err %d\n", err); in rockchip_pcie_phy_power_on()
178 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, in rockchip_pcie_phy_power_on()
183 regmap_write(rk_phy->reg_base, in rockchip_pcie_phy_power_on()
184 rk_phy->phy_data->pcie_laneoff, in rockchip_pcie_phy_power_on()
187 PHY_LANE_IDLE_A_SHIFT + inst->index)); in rockchip_pcie_phy_power_on()
190 * No documented timeout value for phy operation below, in rockchip_pcie_phy_power_on()
191 * so we make it large enough here. And we use loop-break in rockchip_pcie_phy_power_on()
196 err = -EINVAL; in rockchip_pcie_phy_power_on()
198 regmap_read(rk_phy->reg_base, in rockchip_pcie_phy_power_on()
199 rk_phy->phy_data->pcie_status, in rockchip_pcie_phy_power_on()
202 dev_dbg(&phy->dev, "pll locked!\n"); in rockchip_pcie_phy_power_on()
210 dev_err(&phy->dev, "pll lock timeout!\n"); in rockchip_pcie_phy_power_on()
217 err = -ETIMEDOUT; in rockchip_pcie_phy_power_on()
219 regmap_read(rk_phy->reg_base, in rockchip_pcie_phy_power_on()
220 rk_phy->phy_data->pcie_status, in rockchip_pcie_phy_power_on()
223 dev_dbg(&phy->dev, "pll output enable done!\n"); in rockchip_pcie_phy_power_on()
231 dev_err(&phy->dev, "pll output enable timeout!\n"); in rockchip_pcie_phy_power_on()
235 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, in rockchip_pcie_phy_power_on()
239 err = -EINVAL; in rockchip_pcie_phy_power_on()
241 regmap_read(rk_phy->reg_base, in rockchip_pcie_phy_power_on()
242 rk_phy->phy_data->pcie_status, in rockchip_pcie_phy_power_on()
245 dev_dbg(&phy->dev, "pll relocked!\n"); in rockchip_pcie_phy_power_on()
253 dev_err(&phy->dev, "pll relock timeout!\n"); in rockchip_pcie_phy_power_on()
258 mutex_unlock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_power_on()
262 reset_control_assert(rk_phy->phy_rst); in rockchip_pcie_phy_power_on()
264 rk_phy->pwr_cnt--; in rockchip_pcie_phy_power_on()
265 mutex_unlock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_power_on()
269 static int rockchip_pcie_phy_init(struct phy *phy) in rockchip_pcie_phy_init() argument
271 struct phy_pcie_instance *inst = phy_get_drvdata(phy); in rockchip_pcie_phy_init()
275 mutex_lock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_init()
277 if (rk_phy->init_cnt++) in rockchip_pcie_phy_init()
280 err = clk_prepare_enable(rk_phy->clk_pciephy_ref); in rockchip_pcie_phy_init()
282 dev_err(&phy->dev, "Fail to enable pcie ref clock.\n"); in rockchip_pcie_phy_init()
286 err = reset_control_assert(rk_phy->phy_rst); in rockchip_pcie_phy_init()
288 dev_err(&phy->dev, "assert phy_rst err %d\n", err); in rockchip_pcie_phy_init()
293 mutex_unlock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_init()
298 clk_disable_unprepare(rk_phy->clk_pciephy_ref); in rockchip_pcie_phy_init()
300 rk_phy->init_cnt--; in rockchip_pcie_phy_init()
301 mutex_unlock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_init()
305 static int rockchip_pcie_phy_exit(struct phy *phy) in rockchip_pcie_phy_exit() argument
307 struct phy_pcie_instance *inst = phy_get_drvdata(phy); in rockchip_pcie_phy_exit()
310 mutex_lock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_exit()
312 if (--rk_phy->init_cnt) in rockchip_pcie_phy_exit()
315 clk_disable_unprepare(rk_phy->clk_pciephy_ref); in rockchip_pcie_phy_exit()
318 mutex_unlock(&rk_phy->pcie_mutex); in rockchip_pcie_phy_exit()
338 .compatible = "rockchip,rk3399-pcie-phy",
348 struct device *dev = &pdev->dev; in rockchip_pcie_phy_probe()
351 struct regmap *grf; in rockchip_pcie_phy_probe() local
355 grf = syscon_node_to_regmap(dev->parent->of_node); in rockchip_pcie_phy_probe()
356 if (IS_ERR(grf)) { in rockchip_pcie_phy_probe()
357 dev_err(dev, "Cannot find GRF syscon\n"); in rockchip_pcie_phy_probe()
358 return PTR_ERR(grf); in rockchip_pcie_phy_probe()
363 return -ENOMEM; in rockchip_pcie_phy_probe()
365 rk_phy->phy_data = device_get_match_data(&pdev->dev); in rockchip_pcie_phy_probe()
366 if (!rk_phy->phy_data) in rockchip_pcie_phy_probe()
367 return -EINVAL; in rockchip_pcie_phy_probe()
369 rk_phy->reg_base = grf; in rockchip_pcie_phy_probe()
371 mutex_init(&rk_phy->pcie_mutex); in rockchip_pcie_phy_probe()
373 rk_phy->phy_rst = devm_reset_control_get(dev, "phy"); in rockchip_pcie_phy_probe()
374 if (IS_ERR(rk_phy->phy_rst)) { in rockchip_pcie_phy_probe()
375 if (PTR_ERR(rk_phy->phy_rst) != -EPROBE_DEFER) in rockchip_pcie_phy_probe()
377 "missing phy property for reset controller\n"); in rockchip_pcie_phy_probe()
378 return PTR_ERR(rk_phy->phy_rst); in rockchip_pcie_phy_probe()
381 rk_phy->clk_pciephy_ref = devm_clk_get(dev, "refclk"); in rockchip_pcie_phy_probe()
382 if (IS_ERR(rk_phy->clk_pciephy_ref)) { in rockchip_pcie_phy_probe()
384 return PTR_ERR(rk_phy->clk_pciephy_ref); in rockchip_pcie_phy_probe()
387 /* parse #phy-cells to see if it's legacy PHY model */ in rockchip_pcie_phy_probe()
388 if (of_property_read_u32(dev->of_node, "#phy-cells", &phy_num)) in rockchip_pcie_phy_probe()
389 return -ENOENT; in rockchip_pcie_phy_probe()
392 dev_dbg(dev, "phy number is %d\n", phy_num); in rockchip_pcie_phy_probe()
395 rk_phy->phys[i].phy = devm_phy_create(dev, dev->of_node, &ops); in rockchip_pcie_phy_probe()
396 if (IS_ERR(rk_phy->phys[i].phy)) { in rockchip_pcie_phy_probe()
397 dev_err(dev, "failed to create PHY%d\n", i); in rockchip_pcie_phy_probe()
398 return PTR_ERR(rk_phy->phys[i].phy); in rockchip_pcie_phy_probe()
400 rk_phy->phys[i].index = i; in rockchip_pcie_phy_probe()
401 phy_set_drvdata(rk_phy->phys[i].phy, &rk_phy->phys[i]); in rockchip_pcie_phy_probe()
414 .name = "rockchip-pcie-phy",
421 MODULE_AUTHOR("Shawn Lin <shawn.lin@rock-chips.com>");
422 MODULE_DESCRIPTION("Rockchip PCIe PHY driver");