Lines Matching +full:usb2 +full:- +full:phy +full:- +full:r8a7795

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:
15 #include <linux/extcon-provider.h>
21 #include <linux/phy/phy.h>
30 /******* USB2.0 Host registers (original offset is +0x200) *******/
123 struct phy *phy; member
160 * ---------------------+---------------++--------------+------------
171 if (ch->extcon_host) { in rcar_gen3_phy_usb2_work()
172 extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, true); in rcar_gen3_phy_usb2_work()
173 extcon_set_state_sync(ch->extcon, EXTCON_USB, false); in rcar_gen3_phy_usb2_work()
175 extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, false); in rcar_gen3_phy_usb2_work()
176 extcon_set_state_sync(ch->extcon, EXTCON_USB, true); in rcar_gen3_phy_usb2_work()
182 void __iomem *usb2_base = ch->base; in rcar_gen3_set_host_mode()
185 dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, host); in rcar_gen3_set_host_mode()
195 void __iomem *usb2_base = ch->base; in rcar_gen3_set_linectrl()
198 dev_vdbg(ch->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm); in rcar_gen3_set_linectrl()
209 void __iomem *usb2_base = ch->base; in rcar_gen3_enable_vbus_ctrl()
214 if (ch->phy_data->no_adp_ctrl || ch->phy_data->vblvl_ctrl) { in rcar_gen3_enable_vbus_ctrl()
215 if (ch->vbus) in rcar_gen3_enable_vbus_ctrl()
216 regulator_hardware_enable(ch->vbus, vbus); in rcar_gen3_enable_vbus_ctrl()
227 dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, vbus); in rcar_gen3_enable_vbus_ctrl()
233 void __iomem *usb2_base = ch->base; in rcar_gen3_control_otg_irq()
236 if (ch->uses_otg_pins && enable) in rcar_gen3_control_otg_irq()
237 val |= ch->phy_data->obint_enable_bits; in rcar_gen3_control_otg_irq()
239 val &= ~ch->phy_data->obint_enable_bits; in rcar_gen3_control_otg_irq()
249 ch->extcon_host = true; in rcar_gen3_init_for_host()
250 schedule_work(&ch->work); in rcar_gen3_init_for_host()
259 ch->extcon_host = false; in rcar_gen3_init_for_peri()
260 schedule_work(&ch->work); in rcar_gen3_init_for_peri()
265 void __iomem *usb2_base = ch->base; in rcar_gen3_init_for_b_host()
298 if (ch->phy_data->vblvl_ctrl) { in rcar_gen3_check_id()
302 device = !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG); in rcar_gen3_check_id()
303 vbus_valid = !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_VBUSVALID); in rcar_gen3_check_id()
308 if (!ch->uses_otg_pins) in rcar_gen3_check_id()
309 return ch->dr_mode != USB_DR_MODE_HOST; in rcar_gen3_check_id()
311 if (ch->phy_data->no_adp_ctrl) in rcar_gen3_check_id()
312 return !!(readl(ch->base + USB2_LINECTRL1) & USB2_LINECTRL1_USB2_IDMON); in rcar_gen3_check_id()
314 return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG); in rcar_gen3_check_id()
327 return !(readl(ch->base + USB2_COMMCTRL) & USB2_COMMCTRL_OTG_PERI); in rcar_gen3_is_host()
343 if (ch->rphys[i].initialized) in rcar_gen3_is_any_rphy_initialized()
354 if (ch->rphys[i].initialized) in rcar_gen3_is_any_otg_rphy_initialized()
366 if (ch->rphys[i].powered) in rcar_gen3_are_all_rphys_power_off()
380 guard(spinlock_irqsave)(&ch->lock); in role_store()
382 if (!ch->is_otg_channel || !rcar_gen3_is_any_otg_rphy_initialized(ch)) in role_store()
383 return -EIO; in role_store()
390 return -EINVAL; in role_store()
392 /* is_b_device: true is B-Device. false is A-Device. */ in role_store()
398 return -EINVAL; in role_store()
401 if (!is_b_device) /* A-Peripheral */ in role_store()
403 else /* B-Peripheral */ in role_store()
406 if (!is_b_device) /* A-Host */ in role_store()
408 else /* B-Host */ in role_store()
420 if (!ch->is_otg_channel || !rcar_gen3_is_any_otg_rphy_initialized(ch)) in role_show()
421 return -EIO; in role_show()
430 void __iomem *usb2_base = ch->base; in rcar_gen3_init_otg()
433 if (!ch->is_otg_channel || rcar_gen3_is_any_otg_rphy_initialized(ch)) in rcar_gen3_init_otg()
436 /* Should not use functions of read-modify-write a register */ in rcar_gen3_init_otg()
442 if (!ch->phy_data->no_adp_ctrl) { in rcar_gen3_init_otg()
443 if (ch->phy_data->vblvl_ctrl) { in rcar_gen3_init_otg()
461 writel(ch->phy_data->obint_enable_bits, usb2_base + USB2_OBINTEN); in rcar_gen3_init_otg()
468 void __iomem *usb2_base = ch->base; in rcar_gen3_configure_vblvl_ctrl()
471 if (!ch->phy_data->vblvl_ctrl) in rcar_gen3_configure_vblvl_ctrl()
486 void __iomem *usb2_base = ch->base; in rcar_gen3_phy_usb2_irq()
487 struct device *dev = ch->dev; in rcar_gen3_phy_usb2_irq()
496 scoped_guard(spinlock, &ch->lock) { in rcar_gen3_phy_usb2_irq()
498 if (status & ch->phy_data->obint_enable_bits) { in rcar_gen3_phy_usb2_irq()
500 if (ch->phy_data->vblvl_ctrl) in rcar_gen3_phy_usb2_irq()
503 writel(ch->phy_data->obint_enable_bits, usb2_base + USB2_OBINTSTA); in rcar_gen3_phy_usb2_irq()
515 static int rcar_gen3_phy_usb2_init(struct phy *p) in rcar_gen3_phy_usb2_init()
518 struct rcar_gen3_chan *channel = rphy->ch; in rcar_gen3_phy_usb2_init()
519 void __iomem *usb2_base = channel->base; in rcar_gen3_phy_usb2_init()
522 guard(spinlock_irqsave)(&channel->lock); in rcar_gen3_phy_usb2_init()
524 /* Initialize USB2 part */ in rcar_gen3_phy_usb2_init()
526 val |= USB2_INT_ENABLE_UCOM_INTEN | rphy->int_enable_bits; in rcar_gen3_phy_usb2_init()
534 /* Initialize otg part (only if we initialize a PHY with IRQs). */ in rcar_gen3_phy_usb2_init()
535 if (rphy->int_enable_bits) in rcar_gen3_phy_usb2_init()
538 if (channel->phy_data->vblvl_ctrl) { in rcar_gen3_phy_usb2_init()
545 if (channel->phy_data->utmi_ctrl) { in rcar_gen3_phy_usb2_init()
553 rphy->initialized = true; in rcar_gen3_phy_usb2_init()
558 static int rcar_gen3_phy_usb2_exit(struct phy *p) in rcar_gen3_phy_usb2_exit()
561 struct rcar_gen3_chan *channel = rphy->ch; in rcar_gen3_phy_usb2_exit()
562 void __iomem *usb2_base = channel->base; in rcar_gen3_phy_usb2_exit()
565 guard(spinlock_irqsave)(&channel->lock); in rcar_gen3_phy_usb2_exit()
567 rphy->initialized = false; in rcar_gen3_phy_usb2_exit()
570 val &= ~rphy->int_enable_bits; in rcar_gen3_phy_usb2_exit()
578 static int rcar_gen3_phy_usb2_power_on(struct phy *p) in rcar_gen3_phy_usb2_power_on()
581 struct rcar_gen3_chan *channel = rphy->ch; in rcar_gen3_phy_usb2_power_on()
582 void __iomem *usb2_base = channel->base; in rcar_gen3_phy_usb2_power_on()
586 if (channel->vbus) { in rcar_gen3_phy_usb2_power_on()
587 ret = regulator_enable(channel->vbus); in rcar_gen3_phy_usb2_power_on()
592 guard(spinlock_irqsave)(&channel->lock); in rcar_gen3_phy_usb2_power_on()
605 rphy->powered = true; in rcar_gen3_phy_usb2_power_on()
610 static int rcar_gen3_phy_usb2_power_off(struct phy *p) in rcar_gen3_phy_usb2_power_off()
613 struct rcar_gen3_chan *channel = rphy->ch; in rcar_gen3_phy_usb2_power_off()
616 scoped_guard(spinlock_irqsave, &channel->lock) { in rcar_gen3_phy_usb2_power_off()
617 rphy->powered = false; in rcar_gen3_phy_usb2_power_off()
620 u32 val = readl(channel->base + USB2_USBCTR); in rcar_gen3_phy_usb2_power_off()
623 writel(val, channel->base + USB2_USBCTR); in rcar_gen3_phy_usb2_power_off()
627 if (channel->vbus) in rcar_gen3_phy_usb2_power_off()
628 ret = regulator_disable(channel->vbus); in rcar_gen3_phy_usb2_power_off()
689 .compatible = "renesas,usb2-phy-r8a77470",
693 .compatible = "renesas,usb2-phy-r8a7795",
697 .compatible = "renesas,usb2-phy-r8a7796",
701 .compatible = "renesas,usb2-phy-r8a77965",
705 .compatible = "renesas,usb2-phy-r9a08g045",
709 .compatible = "renesas,usb2-phy-r9a09g057",
713 .compatible = "renesas,usb2-phy-r9a09g077",
717 .compatible = "renesas,rzg2l-usb2-phy",
721 .compatible = "renesas,rcar-gen3-usb2-phy",
734 static struct phy *rcar_gen3_phy_usb2_xlate(struct device *dev, in rcar_gen3_phy_usb2_xlate()
739 if (args->args_count == 0) /* For old version dts */ in rcar_gen3_phy_usb2_xlate()
740 return ch->rphys[PHY_INDEX_BOTH_HC].phy; in rcar_gen3_phy_usb2_xlate()
741 else if (args->args_count > 1) /* Prevent invalid args count */ in rcar_gen3_phy_usb2_xlate()
742 return ERR_PTR(-ENODEV); in rcar_gen3_phy_usb2_xlate()
744 if (args->args[0] >= NUM_OF_PHYS) in rcar_gen3_phy_usb2_xlate()
745 return ERR_PTR(-ENODEV); in rcar_gen3_phy_usb2_xlate()
747 return ch->rphys[args->args[0]].phy; in rcar_gen3_phy_usb2_xlate()
776 struct device *dev = channel->dev; in rcar_gen3_phy_usb2_init_bus()
780 channel->rstc = devm_reset_control_array_get_shared(dev); in rcar_gen3_phy_usb2_init_bus()
781 if (IS_ERR(channel->rstc)) in rcar_gen3_phy_usb2_init_bus()
782 return PTR_ERR(channel->rstc); in rcar_gen3_phy_usb2_init_bus()
788 ret = reset_control_deassert(channel->rstc); in rcar_gen3_phy_usb2_init_bus()
792 val = readl(channel->base + USB2_AHB_BUS_CTR); in rcar_gen3_phy_usb2_init_bus()
795 writel(val, channel->base + USB2_AHB_BUS_CTR); in rcar_gen3_phy_usb2_init_bus()
805 struct device *dev = &pdev->dev; in rcar_gen3_phy_usb2_probe()
810 if (!dev->of_node) { in rcar_gen3_phy_usb2_probe()
812 return -EINVAL; in rcar_gen3_phy_usb2_probe()
817 return -ENOMEM; in rcar_gen3_phy_usb2_probe()
819 channel->base = devm_platform_ioremap_resource(pdev, 0); in rcar_gen3_phy_usb2_probe()
820 if (IS_ERR(channel->base)) in rcar_gen3_phy_usb2_probe()
821 return PTR_ERR(channel->base); in rcar_gen3_phy_usb2_probe()
823 channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node); in rcar_gen3_phy_usb2_probe()
824 if (channel->dr_mode != USB_DR_MODE_UNKNOWN) { in rcar_gen3_phy_usb2_probe()
825 channel->is_otg_channel = true; in rcar_gen3_phy_usb2_probe()
826 channel->uses_otg_pins = !of_property_read_bool(dev->of_node, in rcar_gen3_phy_usb2_probe()
827 "renesas,no-otg-pins"); in rcar_gen3_phy_usb2_probe()
828 channel->extcon = devm_extcon_dev_allocate(dev, in rcar_gen3_phy_usb2_probe()
830 if (IS_ERR(channel->extcon)) in rcar_gen3_phy_usb2_probe()
831 return PTR_ERR(channel->extcon); in rcar_gen3_phy_usb2_probe()
833 ret = devm_extcon_dev_register(dev, channel->extcon); in rcar_gen3_phy_usb2_probe()
841 * devm_phy_create() will call pm_runtime_enable(&phy->dev); in rcar_gen3_phy_usb2_probe()
842 * And then, phy-core will manage runtime pm for this device. in rcar_gen3_phy_usb2_probe()
846 channel->phy_data = of_device_get_match_data(dev); in rcar_gen3_phy_usb2_probe()
847 if (!channel->phy_data) { in rcar_gen3_phy_usb2_probe()
848 ret = -EINVAL; in rcar_gen3_phy_usb2_probe()
853 channel->dev = dev; in rcar_gen3_phy_usb2_probe()
855 if (channel->phy_data->init_bus) { in rcar_gen3_phy_usb2_probe()
861 spin_lock_init(&channel->lock); in rcar_gen3_phy_usb2_probe()
863 channel->rphys[i].phy = devm_phy_create(dev, NULL, in rcar_gen3_phy_usb2_probe()
864 channel->phy_data->phy_usb2_ops); in rcar_gen3_phy_usb2_probe()
865 if (IS_ERR(channel->rphys[i].phy)) { in rcar_gen3_phy_usb2_probe()
866 dev_err(dev, "Failed to create USB2 PHY\n"); in rcar_gen3_phy_usb2_probe()
867 ret = PTR_ERR(channel->rphys[i].phy); in rcar_gen3_phy_usb2_probe()
870 channel->rphys[i].ch = channel; in rcar_gen3_phy_usb2_probe()
871 channel->rphys[i].int_enable_bits = rcar_gen3_int_enable[i]; in rcar_gen3_phy_usb2_probe()
872 phy_set_drvdata(channel->rphys[i].phy, &channel->rphys[i]); in rcar_gen3_phy_usb2_probe()
875 if (channel->phy_data->no_adp_ctrl && channel->is_otg_channel) in rcar_gen3_phy_usb2_probe()
876 channel->vbus = devm_regulator_get_exclusive(dev, "vbus"); in rcar_gen3_phy_usb2_probe()
878 channel->vbus = devm_regulator_get_optional(dev, "vbus"); in rcar_gen3_phy_usb2_probe()
879 if (IS_ERR(channel->vbus)) { in rcar_gen3_phy_usb2_probe()
880 if (PTR_ERR(channel->vbus) == -EPROBE_DEFER) { in rcar_gen3_phy_usb2_probe()
881 ret = PTR_ERR(channel->vbus); in rcar_gen3_phy_usb2_probe()
884 channel->vbus = NULL; in rcar_gen3_phy_usb2_probe()
888 if (irq < 0 && irq != -ENXIO) { in rcar_gen3_phy_usb2_probe()
892 INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work); in rcar_gen3_phy_usb2_probe()
903 dev_err(dev, "Failed to register PHY provider\n"); in rcar_gen3_phy_usb2_probe()
906 } else if (channel->is_otg_channel) { in rcar_gen3_phy_usb2_probe()
924 if (channel->is_otg_channel) in rcar_gen3_phy_usb2_remove()
925 device_remove_file(&pdev->dev, &dev_attr_role); in rcar_gen3_phy_usb2_remove()
927 reset_control_assert(channel->rstc); in rcar_gen3_phy_usb2_remove()
928 pm_runtime_disable(&pdev->dev); in rcar_gen3_phy_usb2_remove()
942 MODULE_DESCRIPTION("Renesas R-Car Gen3 USB 2.0 PHY");