Lines Matching +full:init +full:- +full:delay
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2014 Yunzhi Li <lyz@rock-chips.com>
10 #include <linux/clk-provider.h>
11 #include <linux/delay.h>
12 #include <linux/extcon-provider.h>
165 return -EINVAL; in otg_mode_show()
168 switch (rk_phy->mode) { in otg_mode_show()
181 return -EINVAL; in otg_mode_show()
194 return -EINVAL; in otg_mode_store()
197 mutex_lock(&rk_phy->mutex); in otg_mode_store()
206 dev_err(&rk_phy->phy->dev, "Error mode! Input 'otg' or 'host' or 'peripheral'\n"); in otg_mode_store()
207 ret = -EINVAL; in otg_mode_store()
211 if (rk_phy->mode == new_dr_mode) { in otg_mode_store()
212 dev_warn(&rk_phy->phy->dev, "Same as current mode.\n"); in otg_mode_store()
216 rk_phy->mode = new_dr_mode; in otg_mode_store()
218 switch (rk_phy->mode) { in otg_mode_store()
235 regmap_write(rk_phy->base->reg_base, RK3288_UOC0_CON3, val); in otg_mode_store()
238 mutex_unlock(&rk_phy->mutex); in otg_mode_store()
261 return regmap_write(phy->base->reg_base, phy->reg_offset, val); in rockchip_usb_phy_power()
276 if (phy->vbus) in rockchip_usb_phy480m_disable()
277 regulator_disable(phy->vbus); in rockchip_usb_phy480m_disable()
301 ret = regmap_read(phy->base->reg_base, phy->reg_offset, &val); in rockchip_usb_phy480m_is_enabled()
321 if (phy->bvalid_irq > 0) { in rk3288_usb_phy_init()
322 mutex_lock(&phy->mutex); in rk3288_usb_phy_init()
329 ret = regmap_write(phy->base->reg_base, RK3288_UOC0_CON4, val); in rk3288_usb_phy_init()
331 dev_err(phy->base->dev, in rk3288_usb_phy_init()
336 schedule_delayed_work(&phy->otg_sm_work, OTG_SCHEDULE_DELAY); in rk3288_usb_phy_init()
339 mutex_unlock(&phy->mutex); in rk3288_usb_phy_init()
349 if (phy->bvalid_irq > 0) in rk3288_usb_phy_exit()
350 flush_delayed_work(&phy->otg_sm_work); in rk3288_usb_phy_exit()
359 if (phy->uart_enabled) in rockchip_usb_phy_power_off()
360 return -EBUSY; in rockchip_usb_phy_power_off()
362 clk_disable_unprepare(phy->clk480m); in rockchip_usb_phy_power_off()
371 if (phy->uart_enabled) in rockchip_usb_phy_power_on()
372 return -EBUSY; in rockchip_usb_phy_power_on()
374 if (phy->vbus) { in rockchip_usb_phy_power_on()
377 ret = regulator_enable(phy->vbus); in rockchip_usb_phy_power_on()
382 return clk_prepare_enable(phy->clk480m); in rockchip_usb_phy_power_on()
389 if (phy->reset) { in rockchip_usb_phy_reset()
390 reset_control_assert(phy->reset); in rockchip_usb_phy_reset()
392 reset_control_deassert(phy->reset); in rockchip_usb_phy_reset()
409 if (!rk_phy->uart_enabled) { in rockchip_usb_phy_action()
410 of_clk_del_provider(rk_phy->np); in rockchip_usb_phy_action()
411 clk_unregister(rk_phy->clk480m); in rockchip_usb_phy_action()
414 if (rk_phy->clk) in rockchip_usb_phy_action()
415 clk_put(rk_phy->clk); in rockchip_usb_phy_action()
421 struct device_node *node = base->dev->of_node; in rockchip_usb_phy_extcon_register()
425 edev = extcon_get_edev_by_phandle(base->dev, 0); in rockchip_usb_phy_extcon_register()
427 if (PTR_ERR(edev) != -EPROBE_DEFER) in rockchip_usb_phy_extcon_register()
428 dev_err(base->dev, in rockchip_usb_phy_extcon_register()
434 edev = devm_extcon_dev_allocate(base->dev, in rockchip_usb_phy_extcon_register()
438 return -ENOMEM; in rockchip_usb_phy_extcon_register()
440 ret = devm_extcon_dev_register(base->dev, edev); in rockchip_usb_phy_extcon_register()
442 dev_err(base->dev, in rockchip_usb_phy_extcon_register()
448 base->edev = edev; in rockchip_usb_phy_extcon_register()
465 mutex_lock(&rk_phy->mutex); in rk3288_usb_phy_otg_sm_work()
469 regmap_read(rk_phy->base->reg_base, RK3288_SOC_STATUS2, &val); in rk3288_usb_phy_otg_sm_work()
472 regmap_read(rk_phy->base->reg_base, RK3288_SOC_STATUS2, &val); in rk3288_usb_phy_otg_sm_work()
476 if (!vbus_attached || !id || rk_phy->mode == USB_DR_MODE_HOST) { in rk3288_usb_phy_otg_sm_work()
477 dev_dbg(&rk_phy->phy->dev, "peripheral disconnected\n"); in rk3288_usb_phy_otg_sm_work()
478 wake_unlock(&rk_phy->wakelock); in rk3288_usb_phy_otg_sm_work()
479 extcon_set_state_sync(rk_phy->base->edev, cable, false); in rk3288_usb_phy_otg_sm_work()
480 rk_phy->chg_state = USB_CHG_STATE_UNDEFINED; in rk3288_usb_phy_otg_sm_work()
490 switch (rk_phy->chg_state) { in rk3288_usb_phy_otg_sm_work()
492 mutex_unlock(&rk_phy->mutex); in rk3288_usb_phy_otg_sm_work()
493 schedule_delayed_work(&rk_phy->chg_work, 0); in rk3288_usb_phy_otg_sm_work()
496 switch (rk_phy->chg_type) { in rk3288_usb_phy_otg_sm_work()
498 dev_dbg(&rk_phy->phy->dev, "sdp cable is connected\n"); in rk3288_usb_phy_otg_sm_work()
499 wake_lock(&rk_phy->wakelock); in rk3288_usb_phy_otg_sm_work()
504 dev_dbg(&rk_phy->phy->dev, "dcp cable is connected\n"); in rk3288_usb_phy_otg_sm_work()
509 dev_dbg(&rk_phy->phy->dev, "cdp cable is connected\n"); in rk3288_usb_phy_otg_sm_work()
510 wake_lock(&rk_phy->wakelock); in rk3288_usb_phy_otg_sm_work()
523 if (extcon_get_state(rk_phy->base->edev, cable) != vbus_attached) in rk3288_usb_phy_otg_sm_work()
524 extcon_set_state_sync(rk_phy->base->edev, cable, in rk3288_usb_phy_otg_sm_work()
529 schedule_delayed_work(&rk_phy->otg_sm_work, OTG_SCHEDULE_DELAY); in rk3288_usb_phy_otg_sm_work()
531 mutex_unlock(&rk_phy->mutex); in rk3288_usb_phy_otg_sm_work()
555 unsigned long delay; in rk3288_chg_detect_work() local
560 dev_dbg(&rk_phy->phy->dev, "chg detection work state = %d\n", in rk3288_chg_detect_work()
561 rk_phy->chg_state); in rk3288_chg_detect_work()
563 switch (rk_phy->chg_state) { in rk3288_chg_detect_work()
565 mutex_lock(&rk_phy->mutex); in rk3288_chg_detect_work()
566 /* put the controller in non-driving mode */ in rk3288_chg_detect_work()
569 regmap_write(rk_phy->base->reg_base, RK3288_UOC0_CON2, val); in rk3288_chg_detect_work()
573 regmap_write(rk_phy->base->reg_base, RK3288_UOC0_CON3, val); in rk3288_chg_detect_work()
577 regmap_write(rk_phy->base->reg_base, RK3288_UOC0_CON2, val); in rk3288_chg_detect_work()
578 rk_phy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; in rk3288_chg_detect_work()
581 delay = CHG_DCD_POLL_TIME; in rk3288_chg_detect_work()
585 regmap_read(rk_phy->base->reg_base, RK3288_SOC_STATUS19, &val); in rk3288_chg_detect_work()
594 regmap_write(rk_phy->base->reg_base, in rk3288_chg_detect_work()
602 regmap_write(rk_phy->base->reg_base, in rk3288_chg_detect_work()
604 delay = CHG_PRIMARY_DET_TIME; in rk3288_chg_detect_work()
605 rk_phy->chg_state = USB_CHG_STATE_DCD_DONE; in rk3288_chg_detect_work()
608 delay = CHG_DCD_POLL_TIME; in rk3288_chg_detect_work()
612 regmap_read(rk_phy->base->reg_base, RK3288_SOC_STATUS19, &val); in rk3288_chg_detect_work()
617 regmap_write(rk_phy->base->reg_base, RK3288_UOC0_CON2, val); in rk3288_chg_detect_work()
626 regmap_write(rk_phy->base->reg_base, in rk3288_chg_detect_work()
628 delay = CHG_SECONDARY_DET_TIME; in rk3288_chg_detect_work()
629 rk_phy->chg_state = USB_CHG_STATE_PRIMARY_DONE; in rk3288_chg_detect_work()
633 rk_phy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; in rk3288_chg_detect_work()
634 rk_phy->chg_state = USB_CHG_STATE_DETECTED; in rk3288_chg_detect_work()
635 delay = 0; in rk3288_chg_detect_work()
640 rk_phy->chg_type = POWER_SUPPLY_TYPE_USB; in rk3288_chg_detect_work()
641 rk_phy->chg_state = USB_CHG_STATE_DETECTED; in rk3288_chg_detect_work()
642 delay = 0; in rk3288_chg_detect_work()
647 regmap_read(rk_phy->base->reg_base, RK3288_SOC_STATUS19, &val); in rk3288_chg_detect_work()
654 regmap_write(rk_phy->base->reg_base, RK3288_UOC0_CON2, val); in rk3288_chg_detect_work()
656 rk_phy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; in rk3288_chg_detect_work()
658 rk_phy->chg_type = POWER_SUPPLY_TYPE_USB_CDP; in rk3288_chg_detect_work()
661 rk_phy->chg_state = USB_CHG_STATE_DETECTED; in rk3288_chg_detect_work()
666 regmap_write(rk_phy->base->reg_base, RK3288_UOC0_CON2, val); in rk3288_chg_detect_work()
670 regmap_write(rk_phy->base->reg_base, RK3288_UOC0_CON3, val); in rk3288_chg_detect_work()
671 mutex_unlock(&rk_phy->mutex); in rk3288_chg_detect_work()
672 rk3288_usb_phy_otg_sm_work(&rk_phy->otg_sm_work.work); in rk3288_chg_detect_work()
673 dev_info(&rk_phy->phy->dev, "charger = %s\n", in rk3288_chg_detect_work()
674 chg_to_string(rk_phy->chg_type)); in rk3288_chg_detect_work()
677 mutex_unlock(&rk_phy->mutex); in rk3288_chg_detect_work()
686 schedule_delayed_work(&rk_phy->chg_work, delay); in rk3288_chg_detect_work()
695 ret = regmap_read(rk_phy->base->reg_base, RK3288_UOC0_CON4, &val); in rk3288_usb_phy_bvalid_irq()
699 mutex_lock(&rk_phy->mutex); in rk3288_usb_phy_bvalid_irq()
704 regmap_write(rk_phy->base->reg_base, RK3288_UOC0_CON4, val); in rk3288_usb_phy_bvalid_irq()
706 mutex_unlock(&rk_phy->mutex); in rk3288_usb_phy_bvalid_irq()
708 if (rk_phy->uart_enabled) in rk3288_usb_phy_bvalid_irq()
711 cancel_delayed_work_sync(&rk_phy->otg_sm_work); in rk3288_usb_phy_bvalid_irq()
712 rk3288_usb_phy_otg_sm_work(&rk_phy->otg_sm_work.work); in rk3288_usb_phy_bvalid_irq()
722 if (rk_phy->reg_offset == 0x320) { in rk3288_usb_phy_probe_init()
724 ops.init = rk3288_usb_phy_init; in rk3288_usb_phy_probe_init()
726 rk_phy->bvalid_irq = of_irq_get_byname(rk_phy->np, in rk3288_usb_phy_probe_init()
727 "otg-bvalid"); in rk3288_usb_phy_probe_init()
728 regmap_read(rk_phy->base->reg_base, RK3288_UOC0_CON4, &val); in rk3288_usb_phy_probe_init()
729 if (rk_phy->bvalid_irq <= 0) { in rk3288_usb_phy_probe_init()
730 dev_err(&rk_phy->phy->dev, in rk3288_usb_phy_probe_init()
732 ret = -EINVAL; in rk3288_usb_phy_probe_init()
736 ret = devm_request_threaded_irq(rk_phy->base->dev, in rk3288_usb_phy_probe_init()
737 rk_phy->bvalid_irq, in rk3288_usb_phy_probe_init()
744 dev_err(&rk_phy->phy->dev, in rk3288_usb_phy_probe_init()
745 "failed to request otg-bvalid irq handle\n"); in rk3288_usb_phy_probe_init()
749 rk_phy->chg_state = USB_CHG_STATE_UNDEFINED; in rk3288_usb_phy_probe_init()
750 wake_lock_init(&rk_phy->wakelock, WAKE_LOCK_SUSPEND, in rk3288_usb_phy_probe_init()
752 INIT_DELAYED_WORK(&rk_phy->chg_work, rk3288_chg_detect_work); in rk3288_usb_phy_probe_init()
753 INIT_DELAYED_WORK(&rk_phy->otg_sm_work, in rk3288_usb_phy_probe_init()
756 rk_phy->mode = of_usb_get_dr_mode_by_phy(rk_phy->np, -1); in rk3288_usb_phy_probe_init()
757 if (rk_phy->mode == USB_DR_MODE_OTG || in rk3288_usb_phy_probe_init()
758 rk_phy->mode == USB_DR_MODE_UNKNOWN) { in rk3288_usb_phy_probe_init()
759 ret = sysfs_create_group(&rk_phy->phy->dev.kobj, in rk3288_usb_phy_probe_init()
762 dev_err(&rk_phy->phy->dev, in rk3288_usb_phy_probe_init()
767 } else if (rk_phy->reg_offset == 0x334) { in rk3288_usb_phy_probe_init()
771 * EHCI (auto) suspend causes the corresponding usb-phy into in rk3288_usb_phy_probe_init()
773 * usb-phy if the COMMONONN is set to 1'b1. The PLL output in rk3288_usb_phy_probe_init()
778 * usb-phy always powered. in rk3288_usb_phy_probe_init()
780 regmap_write(rk_phy->base->reg_base, rk_phy->reg_offset, in rk3288_usb_phy_probe_init()
790 struct device_node *np = base->dev->of_node; in rockchip_usb_phy_init()
794 struct clk_init_data init = {}; in rockchip_usb_phy_init() local
797 rk_phy = devm_kzalloc(base->dev, sizeof(*rk_phy), GFP_KERNEL); in rockchip_usb_phy_init()
799 return -ENOMEM; in rockchip_usb_phy_init()
801 rk_phy->base = base; in rockchip_usb_phy_init()
802 rk_phy->np = child; in rockchip_usb_phy_init()
803 mutex_init(&rk_phy->mutex); in rockchip_usb_phy_init()
806 dev_err(base->dev, "missing reg property in node %pOFn\n", in rockchip_usb_phy_init()
808 return -EINVAL; in rockchip_usb_phy_init()
811 rk_phy->reset = of_reset_control_get(child, "phy-reset"); in rockchip_usb_phy_init()
812 if (IS_ERR(rk_phy->reset)) in rockchip_usb_phy_init()
813 rk_phy->reset = NULL; in rockchip_usb_phy_init()
815 rk_phy->reg_offset = reg_offset; in rockchip_usb_phy_init()
817 rk_phy->clk = of_clk_get_by_name(child, "phyclk"); in rockchip_usb_phy_init()
818 if (IS_ERR(rk_phy->clk)) in rockchip_usb_phy_init()
819 rk_phy->clk = NULL; in rockchip_usb_phy_init()
822 init.name = NULL; in rockchip_usb_phy_init()
823 while (base->pdata->phys[i].reg) { in rockchip_usb_phy_init()
824 if (base->pdata->phys[i].reg == reg_offset) { in rockchip_usb_phy_init()
825 init.name = base->pdata->phys[i].pll_name; in rockchip_usb_phy_init()
831 if (!init.name) { in rockchip_usb_phy_init()
832 dev_err(base->dev, "phy data not found\n"); in rockchip_usb_phy_init()
833 return -EINVAL; in rockchip_usb_phy_init()
836 if (enable_usb_uart && base->pdata->usb_uart_phy == i) { in rockchip_usb_phy_init()
837 dev_dbg(base->dev, "phy%d used as uart output\n", i); in rockchip_usb_phy_init()
838 rk_phy->uart_enabled = true; in rockchip_usb_phy_init()
840 if (rk_phy->clk) { in rockchip_usb_phy_init()
841 clk_name = __clk_get_name(rk_phy->clk); in rockchip_usb_phy_init()
842 init.flags = 0; in rockchip_usb_phy_init()
843 init.parent_names = &clk_name; in rockchip_usb_phy_init()
844 init.num_parents = 1; in rockchip_usb_phy_init()
846 init.flags = 0; in rockchip_usb_phy_init()
847 init.parent_names = NULL; in rockchip_usb_phy_init()
848 init.num_parents = 0; in rockchip_usb_phy_init()
851 init.ops = &rockchip_usb_phy480m_ops; in rockchip_usb_phy_init()
852 rk_phy->clk480m_hw.init = &init; in rockchip_usb_phy_init()
854 rk_phy->clk480m = clk_register(base->dev, &rk_phy->clk480m_hw); in rockchip_usb_phy_init()
855 if (IS_ERR(rk_phy->clk480m)) { in rockchip_usb_phy_init()
856 err = PTR_ERR(rk_phy->clk480m); in rockchip_usb_phy_init()
861 rk_phy->clk480m); in rockchip_usb_phy_init()
866 err = devm_add_action_or_reset(base->dev, rockchip_usb_phy_action, in rockchip_usb_phy_init()
871 rk_phy->phy = devm_phy_create(base->dev, child, &ops); in rockchip_usb_phy_init()
872 if (IS_ERR(rk_phy->phy)) { in rockchip_usb_phy_init()
873 dev_err(base->dev, "failed to create PHY\n"); in rockchip_usb_phy_init()
874 return PTR_ERR(rk_phy->phy); in rockchip_usb_phy_init()
876 phy_set_drvdata(rk_phy->phy, rk_phy); in rockchip_usb_phy_init()
878 if (of_device_is_compatible(np, "rockchip,rk3288-usb-phy")) { in rockchip_usb_phy_init()
884 rk_phy->vbus = devm_regulator_get_optional(&rk_phy->phy->dev, "vbus"); in rockchip_usb_phy_init()
885 if (IS_ERR(rk_phy->vbus)) { in rockchip_usb_phy_init()
886 if (PTR_ERR(rk_phy->vbus) == -EPROBE_DEFER) in rockchip_usb_phy_init()
887 return PTR_ERR(rk_phy->vbus); in rockchip_usb_phy_init()
888 rk_phy->vbus = NULL; in rockchip_usb_phy_init()
892 * When acting as uart-pipe, just keep clock on otherwise in rockchip_usb_phy_init()
893 * only power up usb phy when it use, so disable it when init in rockchip_usb_phy_init()
895 if (rk_phy->uart_enabled) in rockchip_usb_phy_init()
896 return clk_prepare_enable(rk_phy->clk); in rockchip_usb_phy_init()
901 if (!rk_phy->uart_enabled) in rockchip_usb_phy_init()
902 clk_unregister(rk_phy->clk480m); in rockchip_usb_phy_init()
904 if (rk_phy->clk) in rockchip_usb_phy_init()
905 clk_put(rk_phy->clk); in rockchip_usb_phy_init()
920 int regoffs = pdata->phys[pdata->usb_uart_phy].reg; in rockchip_init_usb_uart_common()
965 * See description of rk3288-variant for details.
1002 * 2. Disable the pull-up resistance on the D+ line by setting
1047 struct device *dev = &pdev->dev; in rockchip_usb_phy_probe()
1056 return -ENOMEM; in rockchip_usb_phy_probe()
1058 match = of_match_device(dev->driver->of_match_table, dev); in rockchip_usb_phy_probe()
1059 if (!match || !match->data) { in rockchip_usb_phy_probe()
1061 return -EINVAL; in rockchip_usb_phy_probe()
1064 phy_base->pdata = match->data; in rockchip_usb_phy_probe()
1066 phy_base->dev = dev; in rockchip_usb_phy_probe()
1067 phy_base->reg_base = ERR_PTR(-ENODEV); in rockchip_usb_phy_probe()
1068 if (dev->parent && dev->parent->of_node) in rockchip_usb_phy_probe()
1069 phy_base->reg_base = syscon_node_to_regmap( in rockchip_usb_phy_probe()
1070 dev->parent->of_node); in rockchip_usb_phy_probe()
1071 if (IS_ERR(phy_base->reg_base)) in rockchip_usb_phy_probe()
1072 phy_base->reg_base = syscon_regmap_lookup_by_phandle( in rockchip_usb_phy_probe()
1073 dev->of_node, "rockchip,grf"); in rockchip_usb_phy_probe()
1074 if (IS_ERR(phy_base->reg_base)) { in rockchip_usb_phy_probe()
1075 dev_err(&pdev->dev, "Missing rockchip,grf property\n"); in rockchip_usb_phy_probe()
1076 return PTR_ERR(phy_base->reg_base); in rockchip_usb_phy_probe()
1083 for_each_available_child_of_node(dev->of_node, child) { in rockchip_usb_phy_probe()
1097 { .compatible = "rockchip,rk3066a-usb-phy", .data = &rk3066a_pdata },
1098 { .compatible = "rockchip,rk3188-usb-phy", .data = &rk3188_pdata },
1099 { .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
1108 .name = "rockchip-usb-phy",
1131 return -ENOTSUPP; in rockchip_init_usb_uart()
1134 pr_debug("%s: using settings for %s\n", __func__, match->compatible); in rockchip_init_usb_uart()
1135 data = match->data; in rockchip_init_usb_uart()
1137 if (!data->init_usb_uart) { in rockchip_init_usb_uart()
1138 pr_err("%s: usb-uart not available on %s\n", in rockchip_init_usb_uart()
1139 __func__, match->compatible); in rockchip_init_usb_uart()
1140 return -ENOTSUPP; in rockchip_init_usb_uart()
1143 grf = ERR_PTR(-ENODEV); in rockchip_init_usb_uart()
1144 if (np->parent) in rockchip_init_usb_uart()
1145 grf = syscon_node_to_regmap(np->parent); in rockchip_init_usb_uart()
1154 ret = data->init_usb_uart(grf, data); in rockchip_init_usb_uart()
1156 pr_err("%s: could not init usb_uart, %d\n", __func__, ret); in rockchip_init_usb_uart()
1173 MODULE_AUTHOR("Yunzhi Li <lyz@rock-chips.com>");