Lines Matching +full:usb +full:- +full:grf
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Rockchip usb PHY driver
5 * Copyright (C) 2014 Yunzhi Li <lyz@rock-chips.com>
10 #include <linux/clk-provider.h>
55 int (*init_usb_uart)(struct regmap *grf,
84 return regmap_write(phy->base->reg_base, phy->reg_offset, val); in rockchip_usb_phy_power()
99 if (phy->vbus) in rockchip_usb_phy480m_disable()
100 regulator_disable(phy->vbus); in rockchip_usb_phy480m_disable()
102 /* Power down usb phy analog blocks by set siddq 1 */ in rockchip_usb_phy480m_disable()
112 /* Power up usb phy analog blocks by set siddq 0 */ in rockchip_usb_phy480m_enable()
124 ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val); in rockchip_usb_phy480m_is_enabled()
142 if (phy->uart_enabled) in rockchip_usb_phy_power_off()
143 return -EBUSY; in rockchip_usb_phy_power_off()
145 clk_disable_unprepare(phy->clk480m); in rockchip_usb_phy_power_off()
154 if (phy->uart_enabled) in rockchip_usb_phy_power_on()
155 return -EBUSY; in rockchip_usb_phy_power_on()
157 if (phy->vbus) { in rockchip_usb_phy_power_on()
160 ret = regulator_enable(phy->vbus); in rockchip_usb_phy_power_on()
165 return clk_prepare_enable(phy->clk480m); in rockchip_usb_phy_power_on()
172 if (phy->reset) { in rockchip_usb_phy_reset()
173 reset_control_assert(phy->reset); in rockchip_usb_phy_reset()
175 reset_control_deassert(phy->reset); in rockchip_usb_phy_reset()
192 if (!rk_phy->uart_enabled) { in rockchip_usb_phy_action()
193 of_clk_del_provider(rk_phy->np); in rockchip_usb_phy_action()
194 clk_unregister(rk_phy->clk480m); in rockchip_usb_phy_action()
197 if (rk_phy->clk) in rockchip_usb_phy_action()
198 clk_put(rk_phy->clk); in rockchip_usb_phy_action()
210 rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL); in rockchip_usb_phy_init()
212 return -ENOMEM; in rockchip_usb_phy_init()
214 rk_phy->base = base; in rockchip_usb_phy_init()
215 rk_phy->np = child; in rockchip_usb_phy_init()
218 dev_err(base->dev, "missing reg property in node %pOFn\n", in rockchip_usb_phy_init()
220 return -EINVAL; in rockchip_usb_phy_init()
223 rk_phy->reset = of_reset_control_get(child, "phy-reset"); in rockchip_usb_phy_init()
224 if (IS_ERR(rk_phy->reset)) in rockchip_usb_phy_init()
225 rk_phy->reset = NULL; in rockchip_usb_phy_init()
227 rk_phy->reg_offset = reg_offset; in rockchip_usb_phy_init()
229 rk_phy->clk = of_clk_get_by_name(child, "phyclk"); in rockchip_usb_phy_init()
230 if (IS_ERR(rk_phy->clk)) in rockchip_usb_phy_init()
231 rk_phy->clk = NULL; in rockchip_usb_phy_init()
235 while (base->pdata->phys[i].reg) { in rockchip_usb_phy_init()
236 if (base->pdata->phys[i].reg == reg_offset) { in rockchip_usb_phy_init()
237 init.name = base->pdata->phys[i].pll_name; in rockchip_usb_phy_init()
244 dev_err(base->dev, "phy data not found\n"); in rockchip_usb_phy_init()
245 return -EINVAL; in rockchip_usb_phy_init()
248 if (enable_usb_uart && base->pdata->usb_uart_phy == i) { in rockchip_usb_phy_init()
249 dev_dbg(base->dev, "phy%d used as uart output\n", i); in rockchip_usb_phy_init()
250 rk_phy->uart_enabled = true; in rockchip_usb_phy_init()
252 if (rk_phy->clk) { in rockchip_usb_phy_init()
253 clk_name = __clk_get_name(rk_phy->clk); in rockchip_usb_phy_init()
264 rk_phy->clk480m_hw.init = &init; in rockchip_usb_phy_init()
266 rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw); in rockchip_usb_phy_init()
267 if (IS_ERR(rk_phy->clk480m)) { in rockchip_usb_phy_init()
268 err = PTR_ERR(rk_phy->clk480m); in rockchip_usb_phy_init()
273 rk_phy->clk480m); in rockchip_usb_phy_init()
278 err = devm_add_action_or_reset(base->dev, rockchip_usb_phy_action, in rockchip_usb_phy_init()
283 rk_phy->phy = devm_phy_create(base->dev, child, &ops); in rockchip_usb_phy_init()
284 if (IS_ERR(rk_phy->phy)) { in rockchip_usb_phy_init()
285 dev_err(base->dev, "failed to create PHY\n"); in rockchip_usb_phy_init()
286 return PTR_ERR(rk_phy->phy); in rockchip_usb_phy_init()
288 phy_set_drvdata(rk_phy->phy, rk_phy); in rockchip_usb_phy_init()
290 rk_phy->vbus = devm_regulator_get_optional(&rk_phy->phy->dev, "vbus"); in rockchip_usb_phy_init()
291 if (IS_ERR(rk_phy->vbus)) { in rockchip_usb_phy_init()
292 if (PTR_ERR(rk_phy->vbus) == -EPROBE_DEFER) in rockchip_usb_phy_init()
293 return PTR_ERR(rk_phy->vbus); in rockchip_usb_phy_init()
294 rk_phy->vbus = NULL; in rockchip_usb_phy_init()
298 * When acting as uart-pipe, just keep clock on otherwise in rockchip_usb_phy_init()
299 * only power up usb phy when it use, so disable it when init in rockchip_usb_phy_init()
301 if (rk_phy->uart_enabled) in rockchip_usb_phy_init()
302 return clk_prepare_enable(rk_phy->clk); in rockchip_usb_phy_init()
307 if (!rk_phy->uart_enabled) in rockchip_usb_phy_init()
308 clk_unregister(rk_phy->clk480m); in rockchip_usb_phy_init()
310 if (rk_phy->clk) in rockchip_usb_phy_init()
311 clk_put(rk_phy->clk); in rockchip_usb_phy_init()
323 static int __init rockchip_init_usb_uart_common(struct regmap *grf, in rockchip_init_usb_uart_common() argument
326 int regoffs = pdata->phys[pdata->usb_uart_phy].reg; in rockchip_init_usb_uart_common()
341 ret = regmap_write(grf, regoffs + UOC_CON0, val); in rockchip_init_usb_uart_common()
347 ret = regmap_write(grf, regoffs + UOC_CON2, val); in rockchip_init_usb_uart_common()
358 ret = regmap_write(grf, UOC_CON3, val); in rockchip_init_usb_uart_common()
370 * Enable the bypass of uart2 data through the otg usb phy.
371 * See description of rk3288-variant for details.
373 static int __init rk3188_init_usb_uart(struct regmap *grf, in rk3188_init_usb_uart() argument
379 ret = rockchip_init_usb_uart_common(grf, pdata); in rk3188_init_usb_uart()
387 ret = regmap_write(grf, RK3188_UOC0_CON0, val); in rk3188_init_usb_uart()
409 * Enable the bypass of uart2 data through the otg usb phy.
412 * 2. Disable the pull-up resistance on the D+ line by setting
416 * 4. Place the USB PHY in Suspend mode by setting SUSPENDM0 to 1’b0.
423 static int __init rk3288_init_usb_uart(struct regmap *grf, in rk3288_init_usb_uart() argument
429 ret = rockchip_init_usb_uart_common(grf, pdata); in rk3288_init_usb_uart()
437 ret = regmap_write(grf, RK3288_UOC0_CON3, val); in rk3288_init_usb_uart()
457 struct device *dev = &pdev->dev; in rockchip_usb_phy_probe()
465 return -ENOMEM; in rockchip_usb_phy_probe()
467 phy_base->pdata = device_get_match_data(dev); in rockchip_usb_phy_probe()
468 if (!phy_base->pdata) { in rockchip_usb_phy_probe()
470 return -EINVAL; in rockchip_usb_phy_probe()
473 phy_base->dev = dev; in rockchip_usb_phy_probe()
474 phy_base->reg_base = ERR_PTR(-ENODEV); in rockchip_usb_phy_probe()
475 if (dev->parent && dev->parent->of_node) in rockchip_usb_phy_probe()
476 phy_base->reg_base = syscon_node_to_regmap( in rockchip_usb_phy_probe()
477 dev->parent->of_node); in rockchip_usb_phy_probe()
478 if (IS_ERR(phy_base->reg_base)) in rockchip_usb_phy_probe()
479 phy_base->reg_base = syscon_regmap_lookup_by_phandle( in rockchip_usb_phy_probe()
480 dev->of_node, "rockchip,grf"); in rockchip_usb_phy_probe()
481 if (IS_ERR(phy_base->reg_base)) { in rockchip_usb_phy_probe()
482 dev_err(&pdev->dev, "Missing rockchip,grf property\n"); in rockchip_usb_phy_probe()
483 return PTR_ERR(phy_base->reg_base); in rockchip_usb_phy_probe()
486 for_each_available_child_of_node(dev->of_node, child) { in rockchip_usb_phy_probe()
499 { .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata },
500 { .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata },
501 { .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
510 .name = "rockchip-usb-phy",
523 struct regmap *grf; in rockchip_init_usb_uart() local
533 return -ENOTSUPP; in rockchip_init_usb_uart()
536 pr_debug("%s: using settings for %s\n", __func__, match->compatible); in rockchip_init_usb_uart()
537 data = match->data; in rockchip_init_usb_uart()
539 if (!data->init_usb_uart) { in rockchip_init_usb_uart()
540 pr_err("%s: usb-uart not available on %s\n", in rockchip_init_usb_uart()
541 __func__, match->compatible); in rockchip_init_usb_uart()
542 return -ENOTSUPP; in rockchip_init_usb_uart()
545 grf = ERR_PTR(-ENODEV); in rockchip_init_usb_uart()
546 if (np->parent) in rockchip_init_usb_uart()
547 grf = syscon_node_to_regmap(np->parent); in rockchip_init_usb_uart()
548 if (IS_ERR(grf)) in rockchip_init_usb_uart()
549 grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); in rockchip_init_usb_uart()
550 if (IS_ERR(grf)) { in rockchip_init_usb_uart()
551 pr_err("%s: Missing rockchip,grf property, %lu\n", in rockchip_init_usb_uart()
552 __func__, PTR_ERR(grf)); in rockchip_init_usb_uart()
553 return PTR_ERR(grf); in rockchip_init_usb_uart()
556 ret = data->init_usb_uart(grf, data); in rockchip_init_usb_uart()
575 MODULE_AUTHOR("Yunzhi Li <lyz@rock-chips.com>");
576 MODULE_DESCRIPTION("Rockchip USB 2.0 PHY driver");