Lines Matching +full:usb2 +full:- +full:device +full:- +full:4
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:
12 #include <linux/extcon-provider.h>
28 /******* USB2.0 Host registers (original offset is +0x200) *******/
80 #define USB2_ADPCTRL_DRVVBUS BIT(4)
86 #define NUM_OF_PHYS 4
112 struct device *dev; /* platform_device's device */
137 * ---------------------+---------------++--------------+------------
148 if (ch->extcon_host) { in rcar_gen3_phy_usb2_work()
149 extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, true); in rcar_gen3_phy_usb2_work()
150 extcon_set_state_sync(ch->extcon, EXTCON_USB, false); in rcar_gen3_phy_usb2_work()
152 extcon_set_state_sync(ch->extcon, EXTCON_USB_HOST, false); in rcar_gen3_phy_usb2_work()
153 extcon_set_state_sync(ch->extcon, EXTCON_USB, true); in rcar_gen3_phy_usb2_work()
159 void __iomem *usb2_base = ch->base; in rcar_gen3_set_host_mode()
162 dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, host); in rcar_gen3_set_host_mode()
172 void __iomem *usb2_base = ch->base; in rcar_gen3_set_linectrl()
175 dev_vdbg(ch->dev, "%s: %08x, %d, %d\n", __func__, val, dp, dm); in rcar_gen3_set_linectrl()
186 void __iomem *usb2_base = ch->base; in rcar_gen3_enable_vbus_ctrl()
191 dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, vbus); in rcar_gen3_enable_vbus_ctrl()
192 if (ch->soc_no_adp_ctrl) { in rcar_gen3_enable_vbus_ctrl()
207 void __iomem *usb2_base = ch->base; in rcar_gen3_control_otg_irq()
210 if (ch->uses_otg_pins && enable) in rcar_gen3_control_otg_irq()
211 val |= ch->obint_enable_bits; in rcar_gen3_control_otg_irq()
213 val &= ~ch->obint_enable_bits; in rcar_gen3_control_otg_irq()
223 ch->extcon_host = true; in rcar_gen3_init_for_host()
224 schedule_work(&ch->work); in rcar_gen3_init_for_host()
233 ch->extcon_host = false; in rcar_gen3_init_for_peri()
234 schedule_work(&ch->work); in rcar_gen3_init_for_peri()
239 void __iomem *usb2_base = ch->base; in rcar_gen3_init_for_b_host()
272 if (!ch->uses_otg_pins) in rcar_gen3_check_id()
273 return (ch->dr_mode == USB_DR_MODE_HOST) ? false : true; in rcar_gen3_check_id()
275 if (ch->soc_no_adp_ctrl) in rcar_gen3_check_id()
276 return !!(readl(ch->base + USB2_LINECTRL1) & USB2_LINECTRL1_USB2_IDMON); in rcar_gen3_check_id()
278 return !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG); in rcar_gen3_check_id()
291 return !(readl(ch->base + USB2_COMMCTRL) & USB2_COMMCTRL_OTG_PERI); in rcar_gen3_is_host()
307 if (ch->rphys[i].initialized) in rcar_gen3_is_any_rphy_initialized()
319 if (ch->rphys[i].otg_initialized) in rcar_gen3_needs_init_otg()
331 if (ch->rphys[i].powered) in rcar_gen3_are_all_rphys_power_off()
338 static ssize_t role_store(struct device *dev, struct device_attribute *attr, in role_store()
345 if (!ch->is_otg_channel || !rcar_gen3_is_any_rphy_initialized(ch)) in role_store()
346 return -EIO; in role_store()
353 return -EINVAL; in role_store()
355 /* is_b_device: true is B-Device. false is A-Device. */ in role_store()
361 return -EINVAL; in role_store()
364 if (!is_b_device) /* A-Peripheral */ in role_store()
366 else /* B-Peripheral */ in role_store()
369 if (!is_b_device) /* A-Host */ in role_store()
371 else /* B-Host */ in role_store()
378 static ssize_t role_show(struct device *dev, struct device_attribute *attr, in role_show()
383 if (!ch->is_otg_channel || !rcar_gen3_is_any_rphy_initialized(ch)) in role_show()
384 return -EIO; in role_show()
393 void __iomem *usb2_base = ch->base; in rcar_gen3_init_otg()
396 /* Should not use functions of read-modify-write a register */ in rcar_gen3_init_otg()
402 if (!ch->soc_no_adp_ctrl) { in rcar_gen3_init_otg()
412 writel(ch->obint_enable_bits, usb2_base + USB2_OBINTEN); in rcar_gen3_init_otg()
420 void __iomem *usb2_base = ch->base; in rcar_gen3_phy_usb2_irq()
424 if (status & ch->obint_enable_bits) { in rcar_gen3_phy_usb2_irq()
425 dev_vdbg(ch->dev, "%s: %08x\n", __func__, status); in rcar_gen3_phy_usb2_irq()
426 writel(ch->obint_enable_bits, usb2_base + USB2_OBINTSTA); in rcar_gen3_phy_usb2_irq()
437 struct rcar_gen3_chan *channel = rphy->ch; in rcar_gen3_phy_usb2_init()
438 void __iomem *usb2_base = channel->base; in rcar_gen3_phy_usb2_init()
442 if (!rcar_gen3_is_any_rphy_initialized(channel) && channel->irq >= 0) { in rcar_gen3_phy_usb2_init()
443 INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work); in rcar_gen3_phy_usb2_init()
444 ret = request_irq(channel->irq, rcar_gen3_phy_usb2_irq, in rcar_gen3_phy_usb2_init()
445 IRQF_SHARED, dev_name(channel->dev), channel); in rcar_gen3_phy_usb2_init()
447 dev_err(channel->dev, "No irq handler (%d)\n", channel->irq); in rcar_gen3_phy_usb2_init()
452 /* Initialize USB2 part */ in rcar_gen3_phy_usb2_init()
454 val |= USB2_INT_ENABLE_UCOM_INTEN | rphy->int_enable_bits; in rcar_gen3_phy_usb2_init()
460 if (channel->is_otg_channel) { in rcar_gen3_phy_usb2_init()
463 rphy->otg_initialized = true; in rcar_gen3_phy_usb2_init()
466 rphy->initialized = true; in rcar_gen3_phy_usb2_init()
474 struct rcar_gen3_chan *channel = rphy->ch; in rcar_gen3_phy_usb2_exit()
475 void __iomem *usb2_base = channel->base; in rcar_gen3_phy_usb2_exit()
478 rphy->initialized = false; in rcar_gen3_phy_usb2_exit()
480 if (channel->is_otg_channel) in rcar_gen3_phy_usb2_exit()
481 rphy->otg_initialized = false; in rcar_gen3_phy_usb2_exit()
484 val &= ~rphy->int_enable_bits; in rcar_gen3_phy_usb2_exit()
489 if (channel->irq >= 0 && !rcar_gen3_is_any_rphy_initialized(channel)) in rcar_gen3_phy_usb2_exit()
490 free_irq(channel->irq, channel); in rcar_gen3_phy_usb2_exit()
498 struct rcar_gen3_chan *channel = rphy->ch; in rcar_gen3_phy_usb2_power_on()
499 void __iomem *usb2_base = channel->base; in rcar_gen3_phy_usb2_power_on()
503 mutex_lock(&channel->lock); in rcar_gen3_phy_usb2_power_on()
507 if (channel->vbus) { in rcar_gen3_phy_usb2_power_on()
508 ret = regulator_enable(channel->vbus); in rcar_gen3_phy_usb2_power_on()
521 rphy->powered = true; in rcar_gen3_phy_usb2_power_on()
522 mutex_unlock(&channel->lock); in rcar_gen3_phy_usb2_power_on()
530 struct rcar_gen3_chan *channel = rphy->ch; in rcar_gen3_phy_usb2_power_off()
533 mutex_lock(&channel->lock); in rcar_gen3_phy_usb2_power_off()
534 rphy->powered = false; in rcar_gen3_phy_usb2_power_off()
539 if (channel->vbus) in rcar_gen3_phy_usb2_power_off()
540 ret = regulator_disable(channel->vbus); in rcar_gen3_phy_usb2_power_off()
543 mutex_unlock(&channel->lock); in rcar_gen3_phy_usb2_power_off()
579 .compatible = "renesas,usb2-phy-r8a77470",
583 .compatible = "renesas,usb2-phy-r8a7795",
587 .compatible = "renesas,usb2-phy-r8a7796",
591 .compatible = "renesas,usb2-phy-r8a77965",
595 .compatible = "renesas,rzg2l-usb2-phy",
599 .compatible = "renesas,rcar-gen3-usb2-phy",
612 static struct phy *rcar_gen3_phy_usb2_xlate(struct device *dev, in rcar_gen3_phy_usb2_xlate()
617 if (args->args_count == 0) /* For old version dts */ in rcar_gen3_phy_usb2_xlate()
618 return ch->rphys[PHY_INDEX_BOTH_HC].phy; in rcar_gen3_phy_usb2_xlate()
619 else if (args->args_count > 1) /* Prevent invalid args count */ in rcar_gen3_phy_usb2_xlate()
620 return ERR_PTR(-ENODEV); in rcar_gen3_phy_usb2_xlate()
622 if (args->args[0] >= NUM_OF_PHYS) in rcar_gen3_phy_usb2_xlate()
623 return ERR_PTR(-ENODEV); in rcar_gen3_phy_usb2_xlate()
625 return ch->rphys[args->args[0]].phy; in rcar_gen3_phy_usb2_xlate()
634 * If one of device nodes has other dr_mode except UNKNOWN, in rcar_gen3_get_dr_mode()
655 struct device *dev = &pdev->dev; in rcar_gen3_phy_usb2_probe()
660 if (!dev->of_node) { in rcar_gen3_phy_usb2_probe()
661 dev_err(dev, "This driver needs device tree\n"); in rcar_gen3_phy_usb2_probe()
662 return -EINVAL; in rcar_gen3_phy_usb2_probe()
667 return -ENOMEM; in rcar_gen3_phy_usb2_probe()
669 channel->base = devm_platform_ioremap_resource(pdev, 0); in rcar_gen3_phy_usb2_probe()
670 if (IS_ERR(channel->base)) in rcar_gen3_phy_usb2_probe()
671 return PTR_ERR(channel->base); in rcar_gen3_phy_usb2_probe()
673 channel->obint_enable_bits = USB2_OBINT_BITS; in rcar_gen3_phy_usb2_probe()
675 channel->irq = platform_get_irq_optional(pdev, 0); in rcar_gen3_phy_usb2_probe()
676 channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node); in rcar_gen3_phy_usb2_probe()
677 if (channel->dr_mode != USB_DR_MODE_UNKNOWN) { in rcar_gen3_phy_usb2_probe()
680 channel->is_otg_channel = true; in rcar_gen3_phy_usb2_probe()
681 channel->uses_otg_pins = !of_property_read_bool(dev->of_node, in rcar_gen3_phy_usb2_probe()
682 "renesas,no-otg-pins"); in rcar_gen3_phy_usb2_probe()
683 channel->extcon = devm_extcon_dev_allocate(dev, in rcar_gen3_phy_usb2_probe()
685 if (IS_ERR(channel->extcon)) in rcar_gen3_phy_usb2_probe()
686 return PTR_ERR(channel->extcon); in rcar_gen3_phy_usb2_probe()
688 ret = devm_extcon_dev_register(dev, channel->extcon); in rcar_gen3_phy_usb2_probe()
696 * devm_phy_create() will call pm_runtime_enable(&phy->dev); in rcar_gen3_phy_usb2_probe()
697 * And then, phy-core will manage runtime pm for this device. in rcar_gen3_phy_usb2_probe()
703 ret = -EINVAL; in rcar_gen3_phy_usb2_probe()
707 channel->soc_no_adp_ctrl = phy_data->no_adp_ctrl; in rcar_gen3_phy_usb2_probe()
708 if (phy_data->no_adp_ctrl) in rcar_gen3_phy_usb2_probe()
709 channel->obint_enable_bits = USB2_OBINT_IDCHG_EN; in rcar_gen3_phy_usb2_probe()
711 mutex_init(&channel->lock); in rcar_gen3_phy_usb2_probe()
713 channel->rphys[i].phy = devm_phy_create(dev, NULL, in rcar_gen3_phy_usb2_probe()
714 phy_data->phy_usb2_ops); in rcar_gen3_phy_usb2_probe()
715 if (IS_ERR(channel->rphys[i].phy)) { in rcar_gen3_phy_usb2_probe()
716 dev_err(dev, "Failed to create USB2 PHY\n"); in rcar_gen3_phy_usb2_probe()
717 ret = PTR_ERR(channel->rphys[i].phy); in rcar_gen3_phy_usb2_probe()
720 channel->rphys[i].ch = channel; in rcar_gen3_phy_usb2_probe()
721 channel->rphys[i].int_enable_bits = rcar_gen3_int_enable[i]; in rcar_gen3_phy_usb2_probe()
722 phy_set_drvdata(channel->rphys[i].phy, &channel->rphys[i]); in rcar_gen3_phy_usb2_probe()
725 channel->vbus = devm_regulator_get_optional(dev, "vbus"); in rcar_gen3_phy_usb2_probe()
726 if (IS_ERR(channel->vbus)) { in rcar_gen3_phy_usb2_probe()
727 if (PTR_ERR(channel->vbus) == -EPROBE_DEFER) { in rcar_gen3_phy_usb2_probe()
728 ret = PTR_ERR(channel->vbus); in rcar_gen3_phy_usb2_probe()
731 channel->vbus = NULL; in rcar_gen3_phy_usb2_probe()
735 channel->dev = dev; in rcar_gen3_phy_usb2_probe()
742 } else if (channel->is_otg_channel) { in rcar_gen3_phy_usb2_probe()
762 if (channel->is_otg_channel) in rcar_gen3_phy_usb2_remove()
763 device_remove_file(&pdev->dev, &dev_attr_role); in rcar_gen3_phy_usb2_remove()
765 pm_runtime_disable(&pdev->dev); in rcar_gen3_phy_usb2_remove()
781 MODULE_DESCRIPTION("Renesas R-Car Gen3 USB 2.0 PHY");