Lines Matching +full:loop +full:- +full:powered
1 // SPDX-License-Identifier: GPL-2.0
3 * Renesas R-Car Gen3 for USB2.0 PHY driver
5 * Copyright (C) 2015-2017 Renesas Electronics Corporation
7 * This is based on the phy-rcar-gen2 driver:
13 #include <linux/extcon-provider.h>
111 bool powered; member
142 * ---------------------+---------------++--------------+------------
153 if (ch->extcon_host) { in rcar_gen3_phy_usb2_work()
154 extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, true); in rcar_gen3_phy_usb2_work()
155 extcon_set_state_sync(ch->extcon, EXTCON_USB, false); in rcar_gen3_phy_usb2_work()
157 extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, false); in rcar_gen3_phy_usb2_work()
158 extcon_set_state_sync(ch->extcon, EXTCON_USB, true); in rcar_gen3_phy_usb2_work()
164 void __iomem *usb2_base = ch->base; in rcar_gen3_set_host_mode()
167 dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, host); in rcar_gen3_set_host_mode()
177 void __iomem *usb2_base = ch->base; in rcar_gen3_set_linectrl()
180 dev_vdbg(ch->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm); in rcar_gen3_set_linectrl()
191 void __iomem *usb2_base = ch->base; in rcar_gen3_enable_vbus_ctrl()
196 dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, vbus); in rcar_gen3_enable_vbus_ctrl()
197 if (ch->soc_no_adp_ctrl) { in rcar_gen3_enable_vbus_ctrl()
212 void __iomem *usb2_base = ch->base; in rcar_gen3_control_otg_irq()
215 if (ch->uses_otg_pins && enable) in rcar_gen3_control_otg_irq()
216 val |= ch->obint_enable_bits; in rcar_gen3_control_otg_irq()
218 val &= ~ch->obint_enable_bits; in rcar_gen3_control_otg_irq()
228 ch->extcon_host = true; in rcar_gen3_init_for_host()
229 schedule_work(&ch->work); in rcar_gen3_init_for_host()
238 ch->extcon_host = false; in rcar_gen3_init_for_peri()
239 schedule_work(&ch->work); in rcar_gen3_init_for_peri()
244 void __iomem *usb2_base = ch->base; in rcar_gen3_init_for_b_host()
277 if (!ch->uses_otg_pins) in rcar_gen3_check_id()
278 return (ch->dr_mode == USB_DR_MODE_HOST) ? false : true; in rcar_gen3_check_id()
280 if (ch->soc_no_adp_ctrl) in rcar_gen3_check_id()
281 return !!(readl(ch->base + USB2_LINECTRL1) & USB2_LINECTRL1_USB2_IDMON); in rcar_gen3_check_id()
283 return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG); in rcar_gen3_check_id()
296 return !(readl(ch->base + USB2_COMMCTRL) & USB2_COMMCTRL_OTG_PERI); in rcar_gen3_is_host()
312 if (ch->rphys[i].initialized) in rcar_gen3_is_any_rphy_initialized()
323 if (ch->rphys[i].initialized) in rcar_gen3_is_any_otg_rphy_initialized()
335 if (ch->rphys[i].powered) in rcar_gen3_are_all_rphys_power_off()
349 guard(spinlock_irqsave)(&ch->lock); in role_store()
351 if (!ch->is_otg_channel || !rcar_gen3_is_any_otg_rphy_initialized(ch)) in role_store()
352 return -EIO; in role_store()
359 return -EINVAL; in role_store()
361 /* is_b_device: true is B-Device. false is A-Device. */ in role_store()
367 return -EINVAL; in role_store()
370 if (!is_b_device) /* A-Peripheral */ in role_store()
372 else /* B-Peripheral */ in role_store()
375 if (!is_b_device) /* A-Host */ in role_store()
377 else /* B-Host */ in role_store()
389 if (!ch->is_otg_channel || !rcar_gen3_is_any_otg_rphy_initialized(ch)) in role_show()
390 return -EIO; in role_show()
399 void __iomem *usb2_base = ch->base; in rcar_gen3_init_otg()
402 if (!ch->is_otg_channel || rcar_gen3_is_any_otg_rphy_initialized(ch)) in rcar_gen3_init_otg()
405 /* Should not use functions of read-modify-write a register */ in rcar_gen3_init_otg()
411 if (!ch->soc_no_adp_ctrl) { in rcar_gen3_init_otg()
421 writel(ch->obint_enable_bits, usb2_base + USB2_OBINTEN); in rcar_gen3_init_otg()
429 void __iomem *usb2_base = ch->base; in rcar_gen3_phy_usb2_irq()
430 struct device *dev = ch->dev; in rcar_gen3_phy_usb2_irq()
439 scoped_guard(spinlock, &ch->lock) { in rcar_gen3_phy_usb2_irq()
441 if (status & ch->obint_enable_bits) { in rcar_gen3_phy_usb2_irq()
443 writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA); in rcar_gen3_phy_usb2_irq()
457 struct rcar_gen3_chan *channel = rphy->ch; in rcar_gen3_phy_usb2_init()
458 void __iomem *usb2_base = channel->base; in rcar_gen3_phy_usb2_init()
461 guard(spinlock_irqsave)(&channel->lock); in rcar_gen3_phy_usb2_init()
465 val |= USB2_INT_ENABLE_UCOM_INTEN | rphy->int_enable_bits; in rcar_gen3_phy_usb2_init()
474 if (rphy->int_enable_bits) in rcar_gen3_phy_usb2_init()
477 rphy->initialized = true; in rcar_gen3_phy_usb2_init()
485 struct rcar_gen3_chan *channel = rphy->ch; in rcar_gen3_phy_usb2_exit()
486 void __iomem *usb2_base = channel->base; in rcar_gen3_phy_usb2_exit()
489 guard(spinlock_irqsave)(&channel->lock); in rcar_gen3_phy_usb2_exit()
491 rphy->initialized = false; in rcar_gen3_phy_usb2_exit()
494 val &= ~rphy->int_enable_bits; in rcar_gen3_phy_usb2_exit()
505 struct rcar_gen3_chan *channel = rphy->ch; in rcar_gen3_phy_usb2_power_on()
506 void __iomem *usb2_base = channel->base; in rcar_gen3_phy_usb2_power_on()
510 if (channel->vbus) { in rcar_gen3_phy_usb2_power_on()
511 ret = regulator_enable(channel->vbus); in rcar_gen3_phy_usb2_power_on()
516 guard(spinlock_irqsave)(&channel->lock); in rcar_gen3_phy_usb2_power_on()
528 /* The powered flag should be set for any other phys anyway */ in rcar_gen3_phy_usb2_power_on()
529 rphy->powered = true; in rcar_gen3_phy_usb2_power_on()
537 struct rcar_gen3_chan *channel = rphy->ch; in rcar_gen3_phy_usb2_power_off()
540 scoped_guard(spinlock_irqsave, &channel->lock) { in rcar_gen3_phy_usb2_power_off()
541 rphy->powered = false; in rcar_gen3_phy_usb2_power_off()
544 u32 val = readl(channel->base + USB2_USBCTR); in rcar_gen3_phy_usb2_power_off()
547 writel(val, channel->base + USB2_USBCTR); in rcar_gen3_phy_usb2_power_off()
551 if (channel->vbus) in rcar_gen3_phy_usb2_power_off()
552 ret = regulator_disable(channel->vbus); in rcar_gen3_phy_usb2_power_off()
588 .compatible = "renesas,usb2-phy-r8a77470",
592 .compatible = "renesas,usb2-phy-r8a7795",
596 .compatible = "renesas,usb2-phy-r8a7796",
600 .compatible = "renesas,usb2-phy-r8a77965",
604 .compatible = "renesas,rzg2l-usb2-phy",
608 .compatible = "renesas,rcar-gen3-usb2-phy",
626 if (args->args_count == 0) /* For old version dts */ in rcar_gen3_phy_usb2_xlate()
627 return ch->rphys[PHY_INDEX_BOTH_HC].phy; in rcar_gen3_phy_usb2_xlate()
628 else if (args->args_count > 1) /* Prevent invalid args count */ in rcar_gen3_phy_usb2_xlate()
629 return ERR_PTR(-ENODEV); in rcar_gen3_phy_usb2_xlate()
631 if (args->args[0] >= NUM_OF_PHYS) in rcar_gen3_phy_usb2_xlate()
632 return ERR_PTR(-ENODEV); in rcar_gen3_phy_usb2_xlate()
634 return ch->rphys[args->args[0]].phy; in rcar_gen3_phy_usb2_xlate()
645 * this loop starts the index as 0. in rcar_gen3_get_dr_mode()
663 struct device *dev = channel->dev; in rcar_gen3_phy_usb2_init_bus()
667 channel->rstc = devm_reset_control_array_get_shared(dev); in rcar_gen3_phy_usb2_init_bus()
668 if (IS_ERR(channel->rstc)) in rcar_gen3_phy_usb2_init_bus()
669 return PTR_ERR(channel->rstc); in rcar_gen3_phy_usb2_init_bus()
675 ret = reset_control_deassert(channel->rstc); in rcar_gen3_phy_usb2_init_bus()
679 val = readl(channel->base + USB2_AHB_BUS_CTR); in rcar_gen3_phy_usb2_init_bus()
682 writel(val, channel->base + USB2_AHB_BUS_CTR); in rcar_gen3_phy_usb2_init_bus()
693 struct device *dev = &pdev->dev; in rcar_gen3_phy_usb2_probe()
698 if (!dev->of_node) { in rcar_gen3_phy_usb2_probe()
700 return -EINVAL; in rcar_gen3_phy_usb2_probe()
705 return -ENOMEM; in rcar_gen3_phy_usb2_probe()
707 channel->base = devm_platform_ioremap_resource(pdev, 0); in rcar_gen3_phy_usb2_probe()
708 if (IS_ERR(channel->base)) in rcar_gen3_phy_usb2_probe()
709 return PTR_ERR(channel->base); in rcar_gen3_phy_usb2_probe()
711 channel->obint_enable_bits = USB2_OBINT_BITS; in rcar_gen3_phy_usb2_probe()
712 channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node); in rcar_gen3_phy_usb2_probe()
713 if (channel->dr_mode != USB_DR_MODE_UNKNOWN) { in rcar_gen3_phy_usb2_probe()
714 channel->is_otg_channel = true; in rcar_gen3_phy_usb2_probe()
715 channel->uses_otg_pins = !of_property_read_bool(dev->of_node, in rcar_gen3_phy_usb2_probe()
716 "renesas,no-otg-pins"); in rcar_gen3_phy_usb2_probe()
717 channel->extcon = devm_extcon_dev_allocate(dev, in rcar_gen3_phy_usb2_probe()
719 if (IS_ERR(channel->extcon)) in rcar_gen3_phy_usb2_probe()
720 return PTR_ERR(channel->extcon); in rcar_gen3_phy_usb2_probe()
722 ret = devm_extcon_dev_register(dev, channel->extcon); in rcar_gen3_phy_usb2_probe()
730 * devm_phy_create() will call pm_runtime_enable(&phy->dev); in rcar_gen3_phy_usb2_probe()
731 * And then, phy-core will manage runtime pm for this device. in rcar_gen3_phy_usb2_probe()
737 ret = -EINVAL; in rcar_gen3_phy_usb2_probe()
742 channel->dev = dev; in rcar_gen3_phy_usb2_probe()
744 if (phy_data->init_bus) { in rcar_gen3_phy_usb2_probe()
750 channel->soc_no_adp_ctrl = phy_data->no_adp_ctrl; in rcar_gen3_phy_usb2_probe()
751 if (phy_data->no_adp_ctrl) in rcar_gen3_phy_usb2_probe()
752 channel->obint_enable_bits = USB2_OBINT_IDCHG_EN; in rcar_gen3_phy_usb2_probe()
754 spin_lock_init(&channel->lock); in rcar_gen3_phy_usb2_probe()
756 channel->rphys[i].phy = devm_phy_create(dev, NULL, in rcar_gen3_phy_usb2_probe()
757 phy_data->phy_usb2_ops); in rcar_gen3_phy_usb2_probe()
758 if (IS_ERR(channel->rphys[i].phy)) { in rcar_gen3_phy_usb2_probe()
760 ret = PTR_ERR(channel->rphys[i].phy); in rcar_gen3_phy_usb2_probe()
763 channel->rphys[i].ch = channel; in rcar_gen3_phy_usb2_probe()
764 channel->rphys[i].int_enable_bits = rcar_gen3_int_enable[i]; in rcar_gen3_phy_usb2_probe()
765 phy_set_drvdata(channel->rphys[i].phy, &channel->rphys[i]); in rcar_gen3_phy_usb2_probe()
768 channel->vbus = devm_regulator_get_optional(dev, "vbus"); in rcar_gen3_phy_usb2_probe()
769 if (IS_ERR(channel->vbus)) { in rcar_gen3_phy_usb2_probe()
770 if (PTR_ERR(channel->vbus) == -EPROBE_DEFER) { in rcar_gen3_phy_usb2_probe()
771 ret = PTR_ERR(channel->vbus); in rcar_gen3_phy_usb2_probe()
774 channel->vbus = NULL; in rcar_gen3_phy_usb2_probe()
778 if (irq < 0 && irq != -ENXIO) { in rcar_gen3_phy_usb2_probe()
782 INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work); in rcar_gen3_phy_usb2_probe()
796 } else if (channel->is_otg_channel) { in rcar_gen3_phy_usb2_probe()
814 if (channel->is_otg_channel) in rcar_gen3_phy_usb2_remove()
815 device_remove_file(&pdev->dev, &dev_attr_role); in rcar_gen3_phy_usb2_remove()
817 reset_control_assert(channel->rstc); in rcar_gen3_phy_usb2_remove()
818 pm_runtime_disable(&pdev->dev); in rcar_gen3_phy_usb2_remove()
832 MODULE_DESCRIPTION("Renesas R-Car Gen3 USB 2.0 PHY");