Lines Matching +full:resume +full:- +full:hs +full:- +full:terminations

1 // SPDX-License-Identifier: GPL-2.0-or-later
9 #include <linux/clk-provider.h>
11 #include <linux/extcon-provider.h>
52 * enum usb_chg_state - Different states involved in USB charger detection.
91 * struct rockchip_chg_det_reg - usb charger detect registers
117 * struct rockchip_usb2phy_port_cfg - usb-phy port configuration.
165 * struct rockchip_usb2phy_cfg - usb-phy configuration.
166 * @reg: the address offset of grf for usb-phy config.
170 * @port_cfgs: usb-phy port configurations.
183 * struct rockchip_usb2phy_port - usb-phy port data.
192 * @otg_mux_irq: IRQ number which multiplex otg-id/otg-bvalid/linestate
193 * irqs to one irq in otg-port.
224 * struct rockchip_usb2phy - usb2.0 phy driver data.
260 return rphy->usbgrf == NULL ? rphy->grf : rphy->usbgrf; in get_reg_base()
268 tmp = en ? reg->enable : reg->disable; in property_enable()
269 mask = GENMASK(reg->bitend, reg->bitstart); in property_enable()
270 val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); in property_enable()
272 return regmap_write(base, reg->offset, val); in property_enable()
280 unsigned int mask = GENMASK(reg->bitend, reg->bitstart); in property_enabled()
282 ret = regmap_read(base, reg->offset, &orig); in property_enabled()
286 tmp = (orig & mask) >> reg->bitstart; in property_enabled()
287 return tmp != reg->disable; in property_enabled()
294 ret = reset_control_assert(rphy->phy_reset); in rockchip_usb2phy_reset()
300 ret = reset_control_deassert(rphy->phy_reset); in rockchip_usb2phy_reset()
317 if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) { in rockchip_usb2phy_clk480m_prepare()
318 ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true); in rockchip_usb2phy_clk480m_prepare()
336 property_enable(base, &rphy->phy_cfg->clkout_ctl, false); in rockchip_usb2phy_clk480m_unprepare()
345 return property_enabled(base, &rphy->phy_cfg->clkout_ctl); in rockchip_usb2phy_clk480m_prepared()
366 of_clk_del_provider(rphy->dev->of_node); in rockchip_usb2phy_clk480m_unregister()
367 clk_unregister(rphy->clk480m); in rockchip_usb2phy_clk480m_unregister()
373 struct device_node *node = rphy->dev->of_node; in rockchip_usb2phy_clk480m_register()
383 of_property_read_string(node, "clock-output-names", &init.name); in rockchip_usb2phy_clk480m_register()
385 if (rphy->clk) { in rockchip_usb2phy_clk480m_register()
386 clk_name = __clk_get_name(rphy->clk); in rockchip_usb2phy_clk480m_register()
394 rphy->clk480m_hw.init = &init; in rockchip_usb2phy_clk480m_register()
397 rphy->clk480m = clk_register(rphy->dev, &rphy->clk480m_hw); in rockchip_usb2phy_clk480m_register()
398 if (IS_ERR(rphy->clk480m)) { in rockchip_usb2phy_clk480m_register()
399 ret = PTR_ERR(rphy->clk480m); in rockchip_usb2phy_clk480m_register()
403 ret = of_clk_add_provider(node, of_clk_src_simple_get, rphy->clk480m); in rockchip_usb2phy_clk480m_register()
407 return devm_add_action_or_reset(rphy->dev, rockchip_usb2phy_clk480m_unregister, rphy); in rockchip_usb2phy_clk480m_register()
410 clk_unregister(rphy->clk480m); in rockchip_usb2phy_clk480m_register()
418 struct device_node *node = rphy->dev->of_node; in rockchip_usb2phy_extcon_register()
422 edev = extcon_get_edev_by_phandle(rphy->dev, 0); in rockchip_usb2phy_extcon_register()
424 if (PTR_ERR(edev) != -EPROBE_DEFER) in rockchip_usb2phy_extcon_register()
425 dev_err(rphy->dev, "Invalid or missing extcon\n"); in rockchip_usb2phy_extcon_register()
430 edev = devm_extcon_dev_allocate(rphy->dev, in rockchip_usb2phy_extcon_register()
434 return -ENOMEM; in rockchip_usb2phy_extcon_register()
436 ret = devm_extcon_dev_register(rphy->dev, edev); in rockchip_usb2phy_extcon_register()
438 dev_err(rphy->dev, "failed to register extcon device\n"); in rockchip_usb2phy_extcon_register()
443 rphy->edev = edev; in rockchip_usb2phy_extcon_register()
454 ret = property_enable(rphy->grf, &rport->port_cfg->disfall_clr, true); in rockchip_usb2phy_enable_host_disc_irq()
458 ret = property_enable(rphy->grf, &rport->port_cfg->disfall_en, en); in rockchip_usb2phy_enable_host_disc_irq()
462 ret = property_enable(rphy->grf, &rport->port_cfg->disrise_clr, true); in rockchip_usb2phy_enable_host_disc_irq()
466 return property_enable(rphy->grf, &rport->port_cfg->disrise_en, en); in rockchip_usb2phy_enable_host_disc_irq()
472 struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); in rockchip_usb2phy_init()
475 mutex_lock(&rport->mutex); in rockchip_usb2phy_init()
477 if (rport->port_id == USB2PHY_PORT_OTG) { in rockchip_usb2phy_init()
478 if (rport->mode != USB_DR_MODE_HOST && in rockchip_usb2phy_init()
479 rport->mode != USB_DR_MODE_UNKNOWN) { in rockchip_usb2phy_init()
481 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
482 &rport->port_cfg->bvalid_det_clr, in rockchip_usb2phy_init()
487 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
488 &rport->port_cfg->bvalid_det_en, in rockchip_usb2phy_init()
494 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
495 &rport->port_cfg->id_det_clr, in rockchip_usb2phy_init()
500 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
501 &rport->port_cfg->id_det_en, in rockchip_usb2phy_init()
506 schedule_delayed_work(&rport->otg_sm_work, in rockchip_usb2phy_init()
510 dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode); in rockchip_usb2phy_init()
512 } else if (rport->port_id == USB2PHY_PORT_HOST) { in rockchip_usb2phy_init()
513 if (rport->port_cfg->disfall_en.offset) { in rockchip_usb2phy_init()
514 rport->host_disconnect = true; in rockchip_usb2phy_init()
517 dev_err(rphy->dev, "failed to enable disconnect irq\n"); in rockchip_usb2phy_init()
523 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
524 &rport->port_cfg->ls_det_clr, true); in rockchip_usb2phy_init()
528 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
529 &rport->port_cfg->ls_det_en, true); in rockchip_usb2phy_init()
533 schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY); in rockchip_usb2phy_init()
537 mutex_unlock(&rport->mutex); in rockchip_usb2phy_init()
544 struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); in rockchip_usb2phy_power_on()
548 dev_dbg(&rport->phy->dev, "port power on\n"); in rockchip_usb2phy_power_on()
550 if (!rport->suspended) in rockchip_usb2phy_power_on()
553 ret = clk_prepare_enable(rphy->clk480m); in rockchip_usb2phy_power_on()
557 ret = property_enable(base, &rport->port_cfg->phy_sus, false); in rockchip_usb2phy_power_on()
559 clk_disable_unprepare(rphy->clk480m); in rockchip_usb2phy_power_on()
578 rport->suspended = false; in rockchip_usb2phy_power_on()
585 struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); in rockchip_usb2phy_power_off()
589 dev_dbg(&rport->phy->dev, "port power off\n"); in rockchip_usb2phy_power_off()
591 if (rport->suspended) in rockchip_usb2phy_power_off()
594 ret = property_enable(base, &rport->port_cfg->phy_sus, true); in rockchip_usb2phy_power_off()
598 rport->suspended = true; in rockchip_usb2phy_power_off()
599 clk_disable_unprepare(rphy->clk480m); in rockchip_usb2phy_power_off()
608 if (rport->port_id == USB2PHY_PORT_OTG && in rockchip_usb2phy_exit()
609 rport->mode != USB_DR_MODE_HOST && in rockchip_usb2phy_exit()
610 rport->mode != USB_DR_MODE_UNKNOWN) { in rockchip_usb2phy_exit()
611 cancel_delayed_work_sync(&rport->otg_sm_work); in rockchip_usb2phy_exit()
612 cancel_delayed_work_sync(&rport->chg_work); in rockchip_usb2phy_exit()
613 } else if (rport->port_id == USB2PHY_PORT_HOST) in rockchip_usb2phy_exit()
614 cancel_delayed_work_sync(&rport->sm_work); in rockchip_usb2phy_exit()
632 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_otg_sm_work()
637 vbus_attach = property_enabled(rphy->grf, in rockchip_usb2phy_otg_sm_work()
638 &rport->port_cfg->utmi_bvalid); in rockchip_usb2phy_otg_sm_work()
643 dev_dbg(&rport->phy->dev, "%s otg sm work\n", in rockchip_usb2phy_otg_sm_work()
644 usb_otg_state_string(rport->state)); in rockchip_usb2phy_otg_sm_work()
646 switch (rport->state) { in rockchip_usb2phy_otg_sm_work()
648 rport->state = OTG_STATE_B_IDLE; in rockchip_usb2phy_otg_sm_work()
650 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
653 if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) > 0) { in rockchip_usb2phy_otg_sm_work()
654 dev_dbg(&rport->phy->dev, "usb otg host connect\n"); in rockchip_usb2phy_otg_sm_work()
655 rport->state = OTG_STATE_A_HOST; in rockchip_usb2phy_otg_sm_work()
656 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_otg_sm_work()
659 dev_dbg(&rport->phy->dev, "vbus_attach\n"); in rockchip_usb2phy_otg_sm_work()
660 switch (rphy->chg_state) { in rockchip_usb2phy_otg_sm_work()
662 schedule_delayed_work(&rport->chg_work, 0); in rockchip_usb2phy_otg_sm_work()
665 switch (rphy->chg_type) { in rockchip_usb2phy_otg_sm_work()
667 dev_dbg(&rport->phy->dev, "sdp cable is connected\n"); in rockchip_usb2phy_otg_sm_work()
668 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_otg_sm_work()
669 rport->state = OTG_STATE_B_PERIPHERAL; in rockchip_usb2phy_otg_sm_work()
675 dev_dbg(&rport->phy->dev, "dcp cable is connected\n"); in rockchip_usb2phy_otg_sm_work()
676 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
682 dev_dbg(&rport->phy->dev, "cdp cable is connected\n"); in rockchip_usb2phy_otg_sm_work()
683 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_otg_sm_work()
684 rport->state = OTG_STATE_B_PERIPHERAL; in rockchip_usb2phy_otg_sm_work()
698 rphy->chg_state = USB_CHG_STATE_UNDEFINED; in rockchip_usb2phy_otg_sm_work()
699 rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; in rockchip_usb2phy_otg_sm_work()
702 if (rport->vbus_attached != vbus_attach) { in rockchip_usb2phy_otg_sm_work()
703 rport->vbus_attached = vbus_attach; in rockchip_usb2phy_otg_sm_work()
705 if (notify_charger && rphy->edev) { in rockchip_usb2phy_otg_sm_work()
706 extcon_set_state_sync(rphy->edev, in rockchip_usb2phy_otg_sm_work()
709 extcon_set_state_sync(rphy->edev, in rockchip_usb2phy_otg_sm_work()
717 dev_dbg(&rport->phy->dev, "usb disconnect\n"); in rockchip_usb2phy_otg_sm_work()
718 rphy->chg_state = USB_CHG_STATE_UNDEFINED; in rockchip_usb2phy_otg_sm_work()
719 rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; in rockchip_usb2phy_otg_sm_work()
720 rport->state = OTG_STATE_B_IDLE; in rockchip_usb2phy_otg_sm_work()
722 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
727 if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) == 0) { in rockchip_usb2phy_otg_sm_work()
728 dev_dbg(&rport->phy->dev, "usb otg host disconnect\n"); in rockchip_usb2phy_otg_sm_work()
729 rport->state = OTG_STATE_B_IDLE; in rockchip_usb2phy_otg_sm_work()
730 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
738 schedule_delayed_work(&rport->otg_sm_work, delay); in rockchip_usb2phy_otg_sm_work()
760 property_enable(base, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en); in rockchip_chg_enable_dcd()
761 property_enable(base, &rphy->phy_cfg->chg_det.idp_src_en, en); in rockchip_chg_enable_dcd()
769 property_enable(base, &rphy->phy_cfg->chg_det.vdp_src_en, en); in rockchip_chg_enable_primary_det()
770 property_enable(base, &rphy->phy_cfg->chg_det.idm_sink_en, en); in rockchip_chg_enable_primary_det()
778 property_enable(base, &rphy->phy_cfg->chg_det.vdm_src_en, en); in rockchip_chg_enable_secondary_det()
779 property_enable(base, &rphy->phy_cfg->chg_det.idp_sink_en, en); in rockchip_chg_enable_secondary_det()
790 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_chg_detect_work()
795 dev_dbg(&rport->phy->dev, "chg detection work state = %d\n", in rockchip_chg_detect_work()
796 rphy->chg_state); in rockchip_chg_detect_work()
797 switch (rphy->chg_state) { in rockchip_chg_detect_work()
799 if (!rport->suspended) in rockchip_chg_detect_work()
800 rockchip_usb2phy_power_off(rport->phy); in rockchip_chg_detect_work()
801 /* put the controller in non-driving mode */ in rockchip_chg_detect_work()
802 property_enable(base, &rphy->phy_cfg->chg_det.opmode, false); in rockchip_chg_detect_work()
805 rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; in rockchip_chg_detect_work()
806 rphy->dcd_retries = 0; in rockchip_chg_detect_work()
811 is_dcd = property_enabled(rphy->grf, in rockchip_chg_detect_work()
812 &rphy->phy_cfg->chg_det.dp_det); in rockchip_chg_detect_work()
813 tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES; in rockchip_chg_detect_work()
822 rphy->chg_state = USB_CHG_STATE_DCD_DONE; in rockchip_chg_detect_work()
829 vout = property_enabled(rphy->grf, in rockchip_chg_detect_work()
830 &rphy->phy_cfg->chg_det.cp_det); in rockchip_chg_detect_work()
836 rphy->chg_state = USB_CHG_STATE_PRIMARY_DONE; in rockchip_chg_detect_work()
838 if (rphy->dcd_retries == CHG_DCD_MAX_RETRIES) { in rockchip_chg_detect_work()
840 rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; in rockchip_chg_detect_work()
841 rphy->chg_state = USB_CHG_STATE_DETECTED; in rockchip_chg_detect_work()
844 rphy->chg_type = POWER_SUPPLY_TYPE_USB; in rockchip_chg_detect_work()
845 rphy->chg_state = USB_CHG_STATE_DETECTED; in rockchip_chg_detect_work()
851 vout = property_enabled(rphy->grf, in rockchip_chg_detect_work()
852 &rphy->phy_cfg->chg_det.dcp_det); in rockchip_chg_detect_work()
856 rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; in rockchip_chg_detect_work()
858 rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP; in rockchip_chg_detect_work()
861 rphy->chg_state = USB_CHG_STATE_DETECTED; in rockchip_chg_detect_work()
865 property_enable(base, &rphy->phy_cfg->chg_det.opmode, true); in rockchip_chg_detect_work()
866 rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); in rockchip_chg_detect_work()
867 dev_dbg(&rport->phy->dev, "charger = %s\n", in rockchip_chg_detect_work()
868 chg_to_string(rphy->chg_type)); in rockchip_chg_detect_work()
874 schedule_delayed_work(&rport->chg_work, delay); in rockchip_chg_detect_work()
878 * The function manage host-phy port state and suspend/resume phy port
883 * disconnected or HS disconnected, actually, we just only need get the
894 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_sm_work()
899 mutex_lock(&rport->mutex); in rockchip_usb2phy_sm_work()
901 ret = regmap_read(rphy->grf, rport->port_cfg->utmi_ls.offset, &ul); in rockchip_usb2phy_sm_work()
905 ul_mask = GENMASK(rport->port_cfg->utmi_ls.bitend, in rockchip_usb2phy_sm_work()
906 rport->port_cfg->utmi_ls.bitstart); in rockchip_usb2phy_sm_work()
908 if (rport->port_cfg->utmi_hstdet.offset) { in rockchip_usb2phy_sm_work()
909 ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd); in rockchip_usb2phy_sm_work()
913 uhd_mask = GENMASK(rport->port_cfg->utmi_hstdet.bitend, in rockchip_usb2phy_sm_work()
914 rport->port_cfg->utmi_hstdet.bitstart); in rockchip_usb2phy_sm_work()
916 sh = rport->port_cfg->utmi_hstdet.bitend - in rockchip_usb2phy_sm_work()
917 rport->port_cfg->utmi_hstdet.bitstart + 1; in rockchip_usb2phy_sm_work()
919 state = ((uhd & uhd_mask) >> rport->port_cfg->utmi_hstdet.bitstart) | in rockchip_usb2phy_sm_work()
920 (((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << sh); in rockchip_usb2phy_sm_work()
922 state = ((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << 1 | in rockchip_usb2phy_sm_work()
923 rport->host_disconnect; in rockchip_usb2phy_sm_work()
928 dev_dbg(&rport->phy->dev, "HS online\n"); in rockchip_usb2phy_sm_work()
936 * Plus, there are two cases, one is D- Line pull-up, and D+ in rockchip_usb2phy_sm_work()
937 * line pull-down, the state is 4; another is D+ line pull-up, in rockchip_usb2phy_sm_work()
938 * and D- line pull-down, the state is 2. in rockchip_usb2phy_sm_work()
940 if (!rport->suspended) { in rockchip_usb2phy_sm_work()
941 /* D- line pull-up, D+ line pull-down */ in rockchip_usb2phy_sm_work()
942 dev_dbg(&rport->phy->dev, "FS/LS online\n"); in rockchip_usb2phy_sm_work()
947 if (rport->suspended) { in rockchip_usb2phy_sm_work()
948 dev_dbg(&rport->phy->dev, "Connected\n"); in rockchip_usb2phy_sm_work()
949 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_sm_work()
950 rport->suspended = false; in rockchip_usb2phy_sm_work()
952 /* D+ line pull-up, D- line pull-down */ in rockchip_usb2phy_sm_work()
953 dev_dbg(&rport->phy->dev, "FS/LS online\n"); in rockchip_usb2phy_sm_work()
957 if (!rport->suspended) { in rockchip_usb2phy_sm_work()
958 dev_dbg(&rport->phy->dev, "Disconnected\n"); in rockchip_usb2phy_sm_work()
959 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_sm_work()
960 rport->suspended = true; in rockchip_usb2phy_sm_work()
965 * plug-in irq. in rockchip_usb2phy_sm_work()
967 property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true); in rockchip_usb2phy_sm_work()
968 property_enable(rphy->grf, &rport->port_cfg->ls_det_en, true); in rockchip_usb2phy_sm_work()
974 mutex_unlock(&rport->mutex); in rockchip_usb2phy_sm_work()
977 dev_dbg(&rport->phy->dev, "unknown phy state\n"); in rockchip_usb2phy_sm_work()
982 mutex_unlock(&rport->mutex); in rockchip_usb2phy_sm_work()
983 schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY); in rockchip_usb2phy_sm_work()
989 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_linestate_irq()
991 if (!property_enabled(rphy->grf, &rport->port_cfg->ls_det_st)) in rockchip_usb2phy_linestate_irq()
994 mutex_lock(&rport->mutex); in rockchip_usb2phy_linestate_irq()
997 property_enable(rphy->grf, &rport->port_cfg->ls_det_en, false); in rockchip_usb2phy_linestate_irq()
998 property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true); in rockchip_usb2phy_linestate_irq()
1000 mutex_unlock(&rport->mutex); in rockchip_usb2phy_linestate_irq()
1005 * resume it and mange its states; otherwise, we do nothing about that. in rockchip_usb2phy_linestate_irq()
1007 if (rport->suspended && rport->port_id == USB2PHY_PORT_HOST) in rockchip_usb2phy_linestate_irq()
1008 rockchip_usb2phy_sm_work(&rport->sm_work.work); in rockchip_usb2phy_linestate_irq()
1016 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_bvalid_irq()
1018 if (!property_enabled(rphy->grf, &rport->port_cfg->bvalid_det_st)) in rockchip_usb2phy_bvalid_irq()
1022 property_enable(rphy->grf, &rport->port_cfg->bvalid_det_clr, true); in rockchip_usb2phy_bvalid_irq()
1024 rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); in rockchip_usb2phy_bvalid_irq()
1032 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_id_irq()
1035 if (!property_enabled(rphy->grf, &rport->port_cfg->id_det_st)) in rockchip_usb2phy_id_irq()
1039 property_enable(rphy->grf, &rport->port_cfg->id_det_clr, true); in rockchip_usb2phy_id_irq()
1041 id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id); in rockchip_usb2phy_id_irq()
1042 extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id); in rockchip_usb2phy_id_irq()
1060 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_host_disc_irq()
1062 if (!property_enabled(rphy->grf, &rport->port_cfg->disfall_st) && in rockchip_usb2phy_host_disc_irq()
1063 !property_enabled(rphy->grf, &rport->port_cfg->disrise_st)) in rockchip_usb2phy_host_disc_irq()
1066 mutex_lock(&rport->mutex); in rockchip_usb2phy_host_disc_irq()
1069 if (property_enabled(rphy->grf, &rport->port_cfg->disfall_st)) { in rockchip_usb2phy_host_disc_irq()
1070 property_enable(rphy->grf, &rport->port_cfg->disfall_clr, true); in rockchip_usb2phy_host_disc_irq()
1071 rport->host_disconnect = false; in rockchip_usb2phy_host_disc_irq()
1072 } else if (property_enabled(rphy->grf, &rport->port_cfg->disrise_st)) { in rockchip_usb2phy_host_disc_irq()
1073 property_enable(rphy->grf, &rport->port_cfg->disrise_clr, true); in rockchip_usb2phy_host_disc_irq()
1074 rport->host_disconnect = true; in rockchip_usb2phy_host_disc_irq()
1077 mutex_unlock(&rport->mutex); in rockchip_usb2phy_host_disc_irq()
1089 for (index = 0; index < rphy->phy_cfg->num_ports; index++) { in rockchip_usb2phy_irq()
1090 rport = &rphy->ports[index]; in rockchip_usb2phy_irq()
1091 if (!rport->phy) in rockchip_usb2phy_irq()
1094 if (rport->port_id == USB2PHY_PORT_HOST && in rockchip_usb2phy_irq()
1095 rport->port_cfg->disfall_en.offset) in rockchip_usb2phy_irq()
1098 switch (rport->port_id) { in rockchip_usb2phy_irq()
1100 if (rport->mode != USB_DR_MODE_HOST && in rockchip_usb2phy_irq()
1101 rport->mode != USB_DR_MODE_UNKNOWN) in rockchip_usb2phy_irq()
1123 if (rphy->irq > 0) in rockchip_usb2phy_port_irq_init()
1126 switch (rport->port_id) { in rockchip_usb2phy_port_irq_init()
1128 rport->ls_irq = of_irq_get_byname(child_np, "linestate"); in rockchip_usb2phy_port_irq_init()
1129 if (rport->ls_irq < 0) { in rockchip_usb2phy_port_irq_init()
1130 dev_err(rphy->dev, "no linestate irq provided\n"); in rockchip_usb2phy_port_irq_init()
1131 return rport->ls_irq; in rockchip_usb2phy_port_irq_init()
1134 ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL, in rockchip_usb2phy_port_irq_init()
1139 dev_err(rphy->dev, "failed to request linestate irq handle\n"); in rockchip_usb2phy_port_irq_init()
1145 * Some SoCs use one interrupt with otg-id/otg-bvalid/linestate in rockchip_usb2phy_port_irq_init()
1146 * interrupts muxed together, so probe the otg-mux interrupt first, in rockchip_usb2phy_port_irq_init()
1149 rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux"); in rockchip_usb2phy_port_irq_init()
1150 if (rport->otg_mux_irq > 0) { in rockchip_usb2phy_port_irq_init()
1151 ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq, in rockchip_usb2phy_port_irq_init()
1158 dev_err(rphy->dev, in rockchip_usb2phy_port_irq_init()
1159 "failed to request otg-mux irq handle\n"); in rockchip_usb2phy_port_irq_init()
1163 rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid"); in rockchip_usb2phy_port_irq_init()
1164 if (rport->bvalid_irq < 0) { in rockchip_usb2phy_port_irq_init()
1165 dev_err(rphy->dev, "no vbus valid irq provided\n"); in rockchip_usb2phy_port_irq_init()
1166 ret = rport->bvalid_irq; in rockchip_usb2phy_port_irq_init()
1170 ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, in rockchip_usb2phy_port_irq_init()
1177 dev_err(rphy->dev, in rockchip_usb2phy_port_irq_init()
1178 "failed to request otg-bvalid irq handle\n"); in rockchip_usb2phy_port_irq_init()
1182 rport->id_irq = of_irq_get_byname(child_np, "otg-id"); in rockchip_usb2phy_port_irq_init()
1183 if (rport->id_irq < 0) { in rockchip_usb2phy_port_irq_init()
1184 dev_err(rphy->dev, "no otg-id irq provided\n"); in rockchip_usb2phy_port_irq_init()
1185 ret = rport->id_irq; in rockchip_usb2phy_port_irq_init()
1189 ret = devm_request_threaded_irq(rphy->dev, rport->id_irq, in rockchip_usb2phy_port_irq_init()
1196 dev_err(rphy->dev, in rockchip_usb2phy_port_irq_init()
1197 "failed to request otg-id irq handle\n"); in rockchip_usb2phy_port_irq_init()
1203 return -EINVAL; in rockchip_usb2phy_port_irq_init()
1215 rport->port_id = USB2PHY_PORT_HOST; in rockchip_usb2phy_host_port_init()
1216 rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_HOST]; in rockchip_usb2phy_host_port_init()
1217 rport->suspended = true; in rockchip_usb2phy_host_port_init()
1219 mutex_init(&rport->mutex); in rockchip_usb2phy_host_port_init()
1220 INIT_DELAYED_WORK(&rport->sm_work, rockchip_usb2phy_sm_work); in rockchip_usb2phy_host_port_init()
1224 dev_err(rphy->dev, "failed to setup host irq\n"); in rockchip_usb2phy_host_port_init()
1237 schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY); in rockchip_otg_event()
1248 rport->port_id = USB2PHY_PORT_OTG; in rockchip_usb2phy_otg_port_init()
1249 rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG]; in rockchip_usb2phy_otg_port_init()
1250 rport->state = OTG_STATE_UNDEFINED; in rockchip_usb2phy_otg_port_init()
1258 rport->suspended = true; in rockchip_usb2phy_otg_port_init()
1259 rport->vbus_attached = false; in rockchip_usb2phy_otg_port_init()
1261 mutex_init(&rport->mutex); in rockchip_usb2phy_otg_port_init()
1263 rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1); in rockchip_usb2phy_otg_port_init()
1264 if (rport->mode == USB_DR_MODE_HOST || in rockchip_usb2phy_otg_port_init()
1265 rport->mode == USB_DR_MODE_UNKNOWN) { in rockchip_usb2phy_otg_port_init()
1270 INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work); in rockchip_usb2phy_otg_port_init()
1271 INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work); in rockchip_usb2phy_otg_port_init()
1275 dev_err(rphy->dev, "failed to init irq for host port\n"); in rockchip_usb2phy_otg_port_init()
1279 if (!IS_ERR(rphy->edev)) { in rockchip_usb2phy_otg_port_init()
1280 rport->event_nb.notifier_call = rockchip_otg_event; in rockchip_usb2phy_otg_port_init()
1282 ret = devm_extcon_register_notifier(rphy->dev, rphy->edev, in rockchip_usb2phy_otg_port_init()
1283 EXTCON_USB_HOST, &rport->event_nb); in rockchip_usb2phy_otg_port_init()
1285 dev_err(rphy->dev, "register USB HOST notifier failed\n"); in rockchip_usb2phy_otg_port_init()
1289 if (!of_property_read_bool(rphy->dev->of_node, "extcon")) { in rockchip_usb2phy_otg_port_init()
1291 id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id); in rockchip_usb2phy_otg_port_init()
1292 extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id); in rockchip_usb2phy_otg_port_init()
1302 struct device *dev = &pdev->dev; in rockchip_usb2phy_probe()
1303 struct device_node *np = dev->of_node; in rockchip_usb2phy_probe()
1313 return -ENOMEM; in rockchip_usb2phy_probe()
1315 if (!dev->parent || !dev->parent->of_node) { in rockchip_usb2phy_probe()
1316 rphy->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbgrf"); in rockchip_usb2phy_probe()
1317 if (IS_ERR(rphy->grf)) { in rockchip_usb2phy_probe()
1319 return PTR_ERR(rphy->grf); in rockchip_usb2phy_probe()
1324 rphy->grf = syscon_node_to_regmap(dev->parent->of_node); in rockchip_usb2phy_probe()
1325 if (IS_ERR(rphy->grf)) in rockchip_usb2phy_probe()
1326 return PTR_ERR(rphy->grf); in rockchip_usb2phy_probe()
1329 if (of_device_is_compatible(np, "rockchip,rv1108-usb2phy")) { in rockchip_usb2phy_probe()
1330 rphy->usbgrf = in rockchip_usb2phy_probe()
1331 syscon_regmap_lookup_by_phandle(dev->of_node, in rockchip_usb2phy_probe()
1333 if (IS_ERR(rphy->usbgrf)) in rockchip_usb2phy_probe()
1334 return PTR_ERR(rphy->usbgrf); in rockchip_usb2phy_probe()
1336 rphy->usbgrf = NULL; in rockchip_usb2phy_probe()
1342 return -EINVAL; in rockchip_usb2phy_probe()
1350 return -EINVAL; in rockchip_usb2phy_probe()
1354 rphy->dev = dev; in rockchip_usb2phy_probe()
1356 rphy->chg_state = USB_CHG_STATE_UNDEFINED; in rockchip_usb2phy_probe()
1357 rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; in rockchip_usb2phy_probe()
1358 rphy->irq = platform_get_irq_optional(pdev, 0); in rockchip_usb2phy_probe()
1362 return dev_err_probe(dev, -EINVAL, "phy configs are not assigned!\n"); in rockchip_usb2phy_probe()
1372 rphy->phy_cfg = &phy_cfgs[index]; in rockchip_usb2phy_probe()
1379 if (!rphy->phy_cfg) { in rockchip_usb2phy_probe()
1381 return -EINVAL; in rockchip_usb2phy_probe()
1384 rphy->phy_reset = devm_reset_control_get_optional(dev, "phy"); in rockchip_usb2phy_probe()
1385 if (IS_ERR(rphy->phy_reset)) in rockchip_usb2phy_probe()
1386 return PTR_ERR(rphy->phy_reset); in rockchip_usb2phy_probe()
1388 rphy->clk = devm_clk_get_optional_enabled(dev, "phyclk"); in rockchip_usb2phy_probe()
1389 if (IS_ERR(rphy->clk)) { in rockchip_usb2phy_probe()
1390 return dev_err_probe(&pdev->dev, PTR_ERR(rphy->clk), in rockchip_usb2phy_probe()
1400 if (rphy->phy_cfg->phy_tuning) { in rockchip_usb2phy_probe()
1401 ret = rphy->phy_cfg->phy_tuning(rphy); in rockchip_usb2phy_probe()
1408 struct rockchip_usb2phy_port *rport = &rphy->ports[index]; in rockchip_usb2phy_probe()
1411 /* This driver aims to support both otg-port and host-port */ in rockchip_usb2phy_probe()
1412 if (!of_node_name_eq(child_np, "host-port") && in rockchip_usb2phy_probe()
1413 !of_node_name_eq(child_np, "otg-port")) in rockchip_usb2phy_probe()
1423 rport->phy = phy; in rockchip_usb2phy_probe()
1424 phy_set_drvdata(rport->phy, rport); in rockchip_usb2phy_probe()
1427 if (of_node_name_eq(child_np, "host-port")) { in rockchip_usb2phy_probe()
1441 if (++index >= rphy->phy_cfg->num_ports) { in rockchip_usb2phy_probe()
1449 if (rphy->irq > 0) { in rockchip_usb2phy_probe()
1450 ret = devm_request_threaded_irq(rphy->dev, rphy->irq, NULL, in rockchip_usb2phy_probe()
1456 dev_err(rphy->dev, in rockchip_usb2phy_probe()
1474 * utmi_termselect = 1'b1 (en FS terminations) in rk3588_usb2phy_tuning()
1479 if (rphy->phy_cfg->reg == 0x0000 || rphy->phy_cfg->reg == 0x4000) { in rk3588_usb2phy_tuning()
1481 suspend_cfg |= 0x01; /* utmi_opmode = 2'b01 (no-driving) */ in rk3588_usb2phy_tuning()
1483 } else if (rphy->phy_cfg->reg == 0x8000 || rphy->phy_cfg->reg == 0xc000) { in rk3588_usb2phy_tuning()
1487 return -EINVAL; in rk3588_usb2phy_tuning()
1491 ret = regmap_write(rphy->grf, 0x0008, GENMASK(29, 29) | 0x0000); in rk3588_usb2phy_tuning()
1501 ret |= regmap_write(rphy->grf, 0x000c, GENMASK(20, 16) | suspend_cfg); in rk3588_usb2phy_tuning()
1503 /* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */ in rk3588_usb2phy_tuning()
1504 ret |= regmap_write(rphy->grf, 0x0004, GENMASK(27, 24) | 0x0900); in rk3588_usb2phy_tuning()
1506 /* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */ in rk3588_usb2phy_tuning()
1507 ret |= regmap_write(rphy->grf, 0x0008, GENMASK(20, 19) | 0x0010); in rk3588_usb2phy_tuning()
1513 ret |= regmap_write(rphy->grf, 0x0010, GENMASK(17, 16) | 0x0003); in rk3588_usb2phy_tuning()
1994 { .compatible = "rockchip,px30-usb2phy", .data = &rk3328_phy_cfgs },
1995 { .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs },
1996 { .compatible = "rockchip,rk3308-usb2phy", .data = &rk3308_phy_cfgs },
1997 { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
1998 { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
1999 { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
2000 { .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs },
2001 { .compatible = "rockchip,rk3588-usb2phy", .data = &rk3588_phy_cfgs },
2002 { .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs },
2010 .name = "rockchip-usb2phy",
2016 MODULE_AUTHOR("Frank Wang <frank.wang@rock-chips.com>");