Lines Matching +full:need +full:- +full:phy +full:- +full:for +full:- +full:wake
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * twl4030_usb - TWL4030 USB transceiver, talking to OMAP OTG controller
5 * Copyright (C) 2004-2007 Texas Instruments
10 * - HS USB ULPI mode works.
11 * - 3-pin mode support may be added in future.
22 #include <linux/phy/phy.h>
70 #define OTHER_INT_DM_HI (1 << 6) /* not valid for "latch" reg */
71 #define OTHER_INT_DP_HI (1 << 5) /* not valid for "latch" reg */
72 #define OTHER_INT_BDIS_ACON (1 << 3) /* not valid for "fall" regs */
137 * cable is present and we need to be runtime-enabled
146 struct usb_phy phy; member
154 /* for vbus reporting with irqs disabled */
170 #define phy_to_twl(x) container_of((x), struct twl4030_usb, phy)
172 /*-------------------------------------------------------------------------*/
183 dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", in twl4030_i2c_write_u8_verify()
191 dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", in twl4030_i2c_write_u8_verify()
195 return -EBUSY; in twl4030_i2c_write_u8_verify()
208 dev_dbg(twl->dev, in twl4030_usb_write()
222 dev_dbg(twl->dev, in twl4030_readb()
234 /*-------------------------------------------------------------------------*/
248 /*-------------------------------------------------------------------------*/
275 twl->vbus_supplied = false; in twl4030_usb_linkstat()
278 * For ID/VBUS sensing, see manual section 15.4.8 ... in twl4030_usb_linkstat()
285 * its interrupt may be raised (may wake the system). in twl4030_usb_linkstat()
289 dev_err(twl->dev, "USB link status err %d\n", status); in twl4030_usb_linkstat()
295 twl->vbus_supplied = true; in twl4030_usb_linkstat()
305 if (twl->linkstat != MUSB_UNKNOWN) in twl4030_usb_linkstat()
309 kobject_uevent(&twl->dev->kobj, linkstat == MUSB_VBUS_VALID in twl4030_usb_linkstat()
312 dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", in twl4030_usb_linkstat()
324 twl->usb_mode = mode; in twl4030_usb_set_mode()
335 case -1: in twl4030_usb_set_mode()
339 dev_err(twl->dev, "unsupported T2 transceiver mode %d\n", in twl4030_usb_set_mode()
352 /* enable DPLL to access PHY registers over I2C */ in twl4030_i2c_access()
364 dev_err(twl->dev, "Timeout setting T2 HSUSB " in twl4030_i2c_access()
365 "PHY DPLL clock\n"); in twl4030_i2c_access()
392 * we need enabled runtime on resume, in twl4030_usb_suspend()
396 dev_dbg(twl->dev, "%s\n", __func__); in twl4030_usb_suspend()
397 disable_irq(twl->irq); in twl4030_usb_suspend()
406 dev_dbg(twl->dev, "%s\n", __func__); in twl4030_usb_resume()
407 enable_irq(twl->irq); in twl4030_usb_resume()
418 dev_dbg(twl->dev, "%s\n", __func__); in twl4030_usb_runtime_suspend()
421 regulator_disable(twl->usb1v5); in twl4030_usb_runtime_suspend()
422 regulator_disable(twl->usb1v8); in twl4030_usb_runtime_suspend()
423 regulator_disable(twl->usb3v1); in twl4030_usb_runtime_suspend()
433 dev_dbg(twl->dev, "%s\n", __func__); in twl4030_usb_runtime_resume()
435 res = regulator_enable(twl->usb3v1); in twl4030_usb_runtime_resume()
437 dev_err(twl->dev, "Failed to enable usb3v1\n"); in twl4030_usb_runtime_resume()
439 res = regulator_enable(twl->usb1v8); in twl4030_usb_runtime_resume()
441 dev_err(twl->dev, "Failed to enable usb1v8\n"); in twl4030_usb_runtime_resume()
448 * is re-activated. This ensures that VUSB3V1 is really active. in twl4030_usb_runtime_resume()
452 res = regulator_enable(twl->usb1v5); in twl4030_usb_runtime_resume()
454 dev_err(twl->dev, "Failed to enable usb1v5\n"); in twl4030_usb_runtime_resume()
463 twl4030_usb_set_mode(twl, twl->usb_mode); in twl4030_usb_runtime_resume()
464 if (twl->usb_mode == T2_USB_MODE_ULPI) in twl4030_usb_runtime_resume()
469 * so wait here so that a fully enabled phy can be expected after in twl4030_usb_runtime_resume()
476 static int twl4030_phy_power_off(struct phy *phy) in twl4030_phy_power_off() argument
478 struct twl4030_usb *twl = phy_get_drvdata(phy); in twl4030_phy_power_off()
480 dev_dbg(twl->dev, "%s\n", __func__); in twl4030_phy_power_off()
485 static int twl4030_phy_power_on(struct phy *phy) in twl4030_phy_power_on() argument
487 struct twl4030_usb *twl = phy_get_drvdata(phy); in twl4030_phy_power_on()
489 dev_dbg(twl->dev, "%s\n", __func__); in twl4030_phy_power_on()
490 pm_runtime_get_sync(twl->dev); in twl4030_phy_power_on()
491 schedule_delayed_work(&twl->id_workaround_work, HZ); in twl4030_phy_power_on()
492 pm_runtime_mark_last_busy(twl->dev); in twl4030_phy_power_on()
493 pm_runtime_put_autosuspend(twl->dev); in twl4030_phy_power_on()
516 twl->usb3v1 = devm_regulator_get(twl->dev, "usb3v1"); in twl4030_usb_ldo_init()
517 if (IS_ERR(twl->usb3v1)) in twl4030_usb_ldo_init()
518 return -ENODEV; in twl4030_usb_ldo_init()
525 twl->usb1v5 = devm_regulator_get(twl->dev, "usb1v5"); in twl4030_usb_ldo_init()
526 if (IS_ERR(twl->usb1v5)) in twl4030_usb_ldo_init()
527 return -ENODEV; in twl4030_usb_ldo_init()
534 twl->usb1v8 = devm_regulator_get(twl->dev, "usb1v8"); in twl4030_usb_ldo_init()
535 if (IS_ERR(twl->usb1v8)) in twl4030_usb_ldo_init()
536 return -ENODEV; in twl4030_usb_ldo_init()
551 int ret = -EINVAL; in twl4030_usb_vbus_show()
553 mutex_lock(&twl->lock); in twl4030_usb_vbus_show()
555 twl->vbus_supplied ? "on" : "off"); in twl4030_usb_vbus_show()
556 mutex_unlock(&twl->lock); in twl4030_usb_vbus_show()
570 mutex_lock(&twl->lock); in twl4030_usb_irq()
571 twl->linkstat = status; in twl4030_usb_irq()
572 mutex_unlock(&twl->lock); in twl4030_usb_irq()
575 if (atomic_add_unless(&twl->connected, 1, 1)) { in twl4030_usb_irq()
576 dev_dbg(twl->dev, "%s: cable connected %i\n", in twl4030_usb_irq()
578 pm_runtime_get_sync(twl->dev); in twl4030_usb_irq()
579 twl->musb_mailbox_pending = true; in twl4030_usb_irq()
582 if (atomic_add_unless(&twl->connected, -1, 0)) { in twl4030_usb_irq()
583 dev_dbg(twl->dev, "%s: cable disconnected %i\n", in twl4030_usb_irq()
585 pm_runtime_mark_last_busy(twl->dev); in twl4030_usb_irq()
586 pm_runtime_put_autosuspend(twl->dev); in twl4030_usb_irq()
587 twl->musb_mailbox_pending = true; in twl4030_usb_irq()
590 if (twl->musb_mailbox_pending) { in twl4030_usb_irq()
593 twl->musb_mailbox_pending = false; in twl4030_usb_irq()
596 /* don't schedule during sleep - irq works right then */ in twl4030_usb_irq()
597 if (status == MUSB_ID_GROUND && pm_runtime_active(twl->dev)) { in twl4030_usb_irq()
598 cancel_delayed_work(&twl->id_workaround_work); in twl4030_usb_irq()
599 schedule_delayed_work(&twl->id_workaround_work, HZ); in twl4030_usb_irq()
603 sysfs_notify(&twl->dev->kobj, NULL, "vbus"); in twl4030_usb_irq()
616 static int twl4030_phy_init(struct phy *phy) in twl4030_phy_init() argument
618 struct twl4030_usb *twl = phy_get_drvdata(phy); in twl4030_phy_init()
620 pm_runtime_get_sync(twl->dev); in twl4030_phy_init()
621 twl->linkstat = MUSB_UNKNOWN; in twl4030_phy_init()
622 schedule_delayed_work(&twl->id_workaround_work, HZ); in twl4030_phy_init()
623 pm_runtime_mark_last_busy(twl->dev); in twl4030_phy_init()
624 pm_runtime_put_autosuspend(twl->dev); in twl4030_phy_init()
633 return -ENODEV; in twl4030_set_peripheral()
635 otg->gadget = gadget; in twl4030_set_peripheral()
637 otg->state = OTG_STATE_UNDEFINED; in twl4030_set_peripheral()
645 return -ENODEV; in twl4030_set_host()
647 otg->host = host; in twl4030_set_host()
649 otg->state = OTG_STATE_UNDEFINED; in twl4030_set_host()
669 struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev); in twl4030_usb_probe()
671 struct phy *phy; in twl4030_usb_probe() local
674 struct device_node *np = pdev->dev.of_node; in twl4030_usb_probe()
677 twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL); in twl4030_usb_probe()
679 return -ENOMEM; in twl4030_usb_probe()
683 (enum twl4030_usb_mode *)&twl->usb_mode); in twl4030_usb_probe()
685 twl->usb_mode = pdata->usb_mode; in twl4030_usb_probe()
687 dev_err(&pdev->dev, "twl4030 initialized without pdata\n"); in twl4030_usb_probe()
688 return -EINVAL; in twl4030_usb_probe()
691 otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL); in twl4030_usb_probe()
693 return -ENOMEM; in twl4030_usb_probe()
695 twl->dev = &pdev->dev; in twl4030_usb_probe()
696 twl->irq = platform_get_irq(pdev, 0); in twl4030_usb_probe()
697 twl->vbus_supplied = false; in twl4030_usb_probe()
698 twl->linkstat = MUSB_UNKNOWN; in twl4030_usb_probe()
699 twl->musb_mailbox_pending = false; in twl4030_usb_probe()
701 twl->phy.dev = twl->dev; in twl4030_usb_probe()
702 twl->phy.label = "twl4030"; in twl4030_usb_probe()
703 twl->phy.otg = otg; in twl4030_usb_probe()
704 twl->phy.type = USB_PHY_TYPE_USB2; in twl4030_usb_probe()
706 otg->usb_phy = &twl->phy; in twl4030_usb_probe()
707 otg->set_host = twl4030_set_host; in twl4030_usb_probe()
708 otg->set_peripheral = twl4030_set_peripheral; in twl4030_usb_probe()
710 phy = devm_phy_create(twl->dev, NULL, &ops); in twl4030_usb_probe()
711 if (IS_ERR(phy)) { in twl4030_usb_probe()
712 dev_dbg(&pdev->dev, "Failed to create PHY\n"); in twl4030_usb_probe()
713 return PTR_ERR(phy); in twl4030_usb_probe()
716 phy_set_drvdata(phy, twl); in twl4030_usb_probe()
718 phy_provider = devm_of_phy_provider_register(twl->dev, in twl4030_usb_probe()
723 /* init mutex for workqueue */ in twl4030_usb_probe()
724 mutex_init(&twl->lock); in twl4030_usb_probe()
726 INIT_DELAYED_WORK(&twl->id_workaround_work, twl4030_id_workaround_work); in twl4030_usb_probe()
730 dev_err(&pdev->dev, "ldo init failed\n"); in twl4030_usb_probe()
733 usb_add_phy_dev(&twl->phy); in twl4030_usb_probe()
736 if (device_create_file(&pdev->dev, &dev_attr_vbus)) in twl4030_usb_probe()
737 dev_warn(&pdev->dev, "could not create sysfs file\n"); in twl4030_usb_probe()
739 ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); in twl4030_usb_probe()
741 pm_runtime_use_autosuspend(&pdev->dev); in twl4030_usb_probe()
742 pm_runtime_set_autosuspend_delay(&pdev->dev, 2000); in twl4030_usb_probe()
743 pm_runtime_enable(&pdev->dev); in twl4030_usb_probe()
744 pm_runtime_get_sync(&pdev->dev); in twl4030_usb_probe()
752 * need both handles, otherwise just one suffices. in twl4030_usb_probe()
754 status = devm_request_threaded_irq(twl->dev, twl->irq, NULL, in twl4030_usb_probe()
758 dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n", in twl4030_usb_probe()
759 twl->irq, status); in twl4030_usb_probe()
764 err = phy_create_lookup(phy, "usb", "musb-hdrc.0"); in twl4030_usb_probe()
768 pm_runtime_mark_last_busy(&pdev->dev); in twl4030_usb_probe()
769 pm_runtime_put_autosuspend(twl->dev); in twl4030_usb_probe()
771 dev_info(&pdev->dev, "Initialized TWL4030 USB module\n"); in twl4030_usb_probe()
780 usb_remove_phy(&twl->phy); in twl4030_usb_remove()
781 pm_runtime_get_sync(twl->dev); in twl4030_usb_remove()
782 cancel_delayed_work(&twl->id_workaround_work); in twl4030_usb_remove()
783 device_remove_file(twl->dev, &dev_attr_vbus); in twl4030_usb_remove()
786 twl4030_usb_set_mode(twl, -1); in twl4030_usb_remove()
789 if (cable_present(twl->linkstat)) in twl4030_usb_remove()
790 pm_runtime_put_noidle(twl->dev); in twl4030_usb_remove()
791 pm_runtime_mark_last_busy(twl->dev); in twl4030_usb_remove()
792 pm_runtime_dont_use_autosuspend(&pdev->dev); in twl4030_usb_remove()
793 pm_runtime_put_sync(twl->dev); in twl4030_usb_remove()
794 pm_runtime_disable(twl->dev); in twl4030_usb_remove()
797 * clear dpll clock request for i2c access, in twl4030_usb_remove()
815 { .compatible = "ti,twl4030-usb" },