Lines Matching +full:rockchip +full:- +full:pcie +full:- +full:phy
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Rockchip PCIe PHY driver
5 * Copyright (C) 2016 Shawn Lin <shawn.lin@rock-chips.com>
6 * Copyright (C) 2016 ROCKCHIP, Inc.
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 guard(mutex)(&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()
139 err = reset_control_assert(rk_phy->phy_rst); in rockchip_pcie_phy_power_off()
141 dev_err(&phy->dev, "assert phy_rst err %d\n", err); in rockchip_pcie_phy_power_off()
142 rk_phy->pwr_cnt++; in rockchip_pcie_phy_power_off()
143 regmap_write(rk_phy->reg_base, in rockchip_pcie_phy_power_off()
144 rk_phy->phy_data->pcie_laneoff, in rockchip_pcie_phy_power_off()
147 PHY_LANE_IDLE_A_SHIFT + inst->index)); in rockchip_pcie_phy_power_off()
154 static int rockchip_pcie_phy_power_on(struct phy *phy) in rockchip_pcie_phy_power_on() argument
156 struct phy_pcie_instance *inst = phy_get_drvdata(phy); in rockchip_pcie_phy_power_on()
161 guard(mutex)(&rk_phy->pcie_mutex); in rockchip_pcie_phy_power_on()
163 if (rk_phy->pwr_cnt++) { in rockchip_pcie_phy_power_on()
167 err = reset_control_deassert(rk_phy->phy_rst); in rockchip_pcie_phy_power_on()
169 dev_err(&phy->dev, "deassert phy_rst err %d\n", err); in rockchip_pcie_phy_power_on()
170 rk_phy->pwr_cnt--; in rockchip_pcie_phy_power_on()
174 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, in rockchip_pcie_phy_power_on()
179 regmap_write(rk_phy->reg_base, in rockchip_pcie_phy_power_on()
180 rk_phy->phy_data->pcie_laneoff, in rockchip_pcie_phy_power_on()
183 PHY_LANE_IDLE_A_SHIFT + inst->index)); in rockchip_pcie_phy_power_on()
186 * No documented timeout value for phy operation below, in rockchip_pcie_phy_power_on()
187 * so we make it large enough here. And we use loop-break in rockchip_pcie_phy_power_on()
190 err = regmap_read_poll_timeout(rk_phy->reg_base, in rockchip_pcie_phy_power_on()
191 rk_phy->phy_data->pcie_status, in rockchip_pcie_phy_power_on()
196 dev_err(&phy->dev, "pll lock timeout!\n"); in rockchip_pcie_phy_power_on()
203 err = regmap_read_poll_timeout(rk_phy->reg_base, in rockchip_pcie_phy_power_on()
204 rk_phy->phy_data->pcie_status, in rockchip_pcie_phy_power_on()
209 dev_err(&phy->dev, "pll output enable timeout!\n"); in rockchip_pcie_phy_power_on()
213 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, in rockchip_pcie_phy_power_on()
218 err = regmap_read_poll_timeout(rk_phy->reg_base, in rockchip_pcie_phy_power_on()
219 rk_phy->phy_data->pcie_status, in rockchip_pcie_phy_power_on()
224 dev_err(&phy->dev, "pll relock timeout!\n"); in rockchip_pcie_phy_power_on()
231 reset_control_assert(rk_phy->phy_rst); in rockchip_pcie_phy_power_on()
232 rk_phy->pwr_cnt--; in rockchip_pcie_phy_power_on()
236 static int rockchip_pcie_phy_init(struct phy *phy) in rockchip_pcie_phy_init() argument
238 struct phy_pcie_instance *inst = phy_get_drvdata(phy); in rockchip_pcie_phy_init()
242 guard(mutex)(&rk_phy->pcie_mutex); in rockchip_pcie_phy_init()
244 if (rk_phy->init_cnt++) { in rockchip_pcie_phy_init()
248 err = reset_control_assert(rk_phy->phy_rst); in rockchip_pcie_phy_init()
250 dev_err(&phy->dev, "assert phy_rst err %d\n", err); in rockchip_pcie_phy_init()
251 rk_phy->init_cnt--; in rockchip_pcie_phy_init()
258 static int rockchip_pcie_phy_exit(struct phy *phy) in rockchip_pcie_phy_exit() argument
260 struct phy_pcie_instance *inst = phy_get_drvdata(phy); in rockchip_pcie_phy_exit()
263 guard(mutex)(&rk_phy->pcie_mutex); in rockchip_pcie_phy_exit()
265 if (--rk_phy->init_cnt) in rockchip_pcie_phy_exit()
288 .compatible = "rockchip,rk3399-pcie-phy",
298 struct device *dev = &pdev->dev; in rockchip_pcie_phy_probe()
305 grf = syscon_node_to_regmap(dev->parent->of_node); in rockchip_pcie_phy_probe()
313 return -ENOMEM; in rockchip_pcie_phy_probe()
315 rk_phy->phy_data = device_get_match_data(&pdev->dev); in rockchip_pcie_phy_probe()
316 if (!rk_phy->phy_data) in rockchip_pcie_phy_probe()
317 return -EINVAL; in rockchip_pcie_phy_probe()
319 rk_phy->reg_base = grf; in rockchip_pcie_phy_probe()
321 mutex_init(&rk_phy->pcie_mutex); in rockchip_pcie_phy_probe()
323 rk_phy->phy_rst = devm_reset_control_get(dev, "phy"); in rockchip_pcie_phy_probe()
324 if (IS_ERR(rk_phy->phy_rst)) in rockchip_pcie_phy_probe()
325 return dev_err_probe(&pdev->dev, PTR_ERR(rk_phy->phy_rst), in rockchip_pcie_phy_probe()
326 "missing phy property for reset controller\n"); in rockchip_pcie_phy_probe()
328 rk_phy->clk_pciephy_ref = devm_clk_get_enabled(dev, "refclk"); in rockchip_pcie_phy_probe()
329 if (IS_ERR(rk_phy->clk_pciephy_ref)) in rockchip_pcie_phy_probe()
330 return dev_err_probe(&pdev->dev, PTR_ERR(rk_phy->clk_pciephy_ref), in rockchip_pcie_phy_probe()
333 /* parse #phy-cells to see if it's legacy PHY model */ in rockchip_pcie_phy_probe()
334 if (of_property_read_u32(dev->of_node, "#phy-cells", &phy_num)) in rockchip_pcie_phy_probe()
335 return -ENOENT; in rockchip_pcie_phy_probe()
338 dev_dbg(dev, "phy number is %d\n", phy_num); in rockchip_pcie_phy_probe()
341 rk_phy->phys[i].phy = devm_phy_create(dev, dev->of_node, &ops); in rockchip_pcie_phy_probe()
342 if (IS_ERR(rk_phy->phys[i].phy)) { in rockchip_pcie_phy_probe()
343 dev_err(dev, "failed to create PHY%d\n", i); in rockchip_pcie_phy_probe()
344 return PTR_ERR(rk_phy->phys[i].phy); in rockchip_pcie_phy_probe()
346 rk_phy->phys[i].index = i; in rockchip_pcie_phy_probe()
347 phy_set_drvdata(rk_phy->phys[i].phy, &rk_phy->phys[i]); in rockchip_pcie_phy_probe()
360 .name = "rockchip-pcie-phy",
367 MODULE_AUTHOR("Shawn Lin <shawn.lin@rock-chips.com>");
368 MODULE_DESCRIPTION("Rockchip PCIe PHY driver");