Lines Matching +full:en +full:- +full:usb
1 // SPDX-License-Identifier: GPL-2.0-or-later
9 #include <linux/clk-provider.h>
11 #include <linux/extcon-provider.h>
27 #include <linux/usb/of.h>
28 #include <linux/usb/otg.h>
50 * enum usb_chg_state - Different states involved in USB charger detection.
51 * @USB_CHG_STATE_UNDEFINED: USB charger is not connected or detection
59 * @USB_CHG_STATE_DETECTED: USB charger type is determined.
89 * struct rockchip_chg_det_reg - usb charger detect registers
115 * struct rockchip_usb2phy_port_cfg - usb-phy port configuration.
169 * struct rockchip_usb2phy_cfg - usb-phy configuration.
170 * @reg: the address offset of grf for usb-phy config.
174 * @port_cfgs: usb-phy port configurations.
187 * struct rockchip_usb2phy_port - usb-phy port data.
192 * @host_disconnect: usb host disconnect status.
196 * @otg_mux_irq: IRQ number which multiplex otg-id/otg-bvalid/linestate
197 * irqs to one irq in otg-port.
228 * struct rockchip_usb2phy - usb2.0 phy driver data.
231 * @usbgrf: USB General Register Files regmap.
236 * @chg_state: states involved in USB charger detection.
237 * @chg_type: USB charger types.
264 return rphy->usbgrf == NULL ? rphy->grf : rphy->usbgrf; in get_reg_base()
268 const struct usb2phy_reg *reg, bool en) in property_enable() argument
272 tmp = en ? reg->enable : reg->disable; in property_enable()
273 mask = GENMASK(reg->bitend, reg->bitstart); in property_enable()
274 val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); in property_enable()
276 return regmap_write(base, reg->offset, val); in property_enable()
284 unsigned int mask = GENMASK(reg->bitend, reg->bitstart); in property_enabled()
286 ret = regmap_read(base, reg->offset, &orig); in property_enabled()
290 tmp = (orig & mask) >> reg->bitstart; in property_enabled()
291 return tmp != reg->disable; in property_enabled()
298 ret = reset_control_assert(rphy->phy_reset); in rockchip_usb2phy_reset()
304 ret = reset_control_deassert(rphy->phy_reset); in rockchip_usb2phy_reset()
321 if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) { in rockchip_usb2phy_clk480m_prepare()
322 ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true); in rockchip_usb2phy_clk480m_prepare()
340 property_enable(base, &rphy->phy_cfg->clkout_ctl, false); in rockchip_usb2phy_clk480m_unprepare()
349 return property_enabled(base, &rphy->phy_cfg->clkout_ctl); in rockchip_usb2phy_clk480m_prepared()
370 of_clk_del_provider(rphy->dev->of_node); in rockchip_usb2phy_clk480m_unregister()
371 clk_unregister(rphy->clk480m); in rockchip_usb2phy_clk480m_unregister()
377 struct device_node *node = rphy->dev->of_node; in rockchip_usb2phy_clk480m_register()
387 of_property_read_string(node, "clock-output-names", &init.name); in rockchip_usb2phy_clk480m_register()
389 if (rphy->clk) { in rockchip_usb2phy_clk480m_register()
390 clk_name = __clk_get_name(rphy->clk); in rockchip_usb2phy_clk480m_register()
398 rphy->clk480m_hw.init = &init; in rockchip_usb2phy_clk480m_register()
401 rphy->clk480m = clk_register(rphy->dev, &rphy->clk480m_hw); in rockchip_usb2phy_clk480m_register()
402 if (IS_ERR(rphy->clk480m)) { in rockchip_usb2phy_clk480m_register()
403 ret = PTR_ERR(rphy->clk480m); in rockchip_usb2phy_clk480m_register()
407 ret = of_clk_add_provider(node, of_clk_src_simple_get, rphy->clk480m); in rockchip_usb2phy_clk480m_register()
411 return devm_add_action_or_reset(rphy->dev, rockchip_usb2phy_clk480m_unregister, rphy); in rockchip_usb2phy_clk480m_register()
414 clk_unregister(rphy->clk480m); in rockchip_usb2phy_clk480m_register()
422 struct device_node *node = rphy->dev->of_node; in rockchip_usb2phy_extcon_register()
426 edev = extcon_get_edev_by_phandle(rphy->dev, 0); in rockchip_usb2phy_extcon_register()
428 if (PTR_ERR(edev) != -EPROBE_DEFER) in rockchip_usb2phy_extcon_register()
429 dev_err(rphy->dev, "Invalid or missing extcon\n"); in rockchip_usb2phy_extcon_register()
434 edev = devm_extcon_dev_allocate(rphy->dev, in rockchip_usb2phy_extcon_register()
438 return -ENOMEM; in rockchip_usb2phy_extcon_register()
440 ret = devm_extcon_dev_register(rphy->dev, edev); in rockchip_usb2phy_extcon_register()
442 dev_err(rphy->dev, "failed to register extcon device\n"); in rockchip_usb2phy_extcon_register()
447 rphy->edev = edev; in rockchip_usb2phy_extcon_register()
454 bool en) in rockchip_usb2phy_enable_host_disc_irq() argument
458 ret = property_enable(rphy->grf, &rport->port_cfg->disfall_clr, true); in rockchip_usb2phy_enable_host_disc_irq()
462 ret = property_enable(rphy->grf, &rport->port_cfg->disfall_en, en); in rockchip_usb2phy_enable_host_disc_irq()
466 ret = property_enable(rphy->grf, &rport->port_cfg->disrise_clr, true); in rockchip_usb2phy_enable_host_disc_irq()
470 return property_enable(rphy->grf, &rport->port_cfg->disrise_en, en); in rockchip_usb2phy_enable_host_disc_irq()
476 struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); in rockchip_usb2phy_init()
479 mutex_lock(&rport->mutex); in rockchip_usb2phy_init()
481 if (rport->port_id == USB2PHY_PORT_OTG) { in rockchip_usb2phy_init()
482 if (rport->mode != USB_DR_MODE_HOST && in rockchip_usb2phy_init()
483 rport->mode != USB_DR_MODE_UNKNOWN) { in rockchip_usb2phy_init()
485 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
486 &rport->port_cfg->bvalid_det_clr, in rockchip_usb2phy_init()
491 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
492 &rport->port_cfg->bvalid_det_en, in rockchip_usb2phy_init()
498 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
499 &rport->port_cfg->idfall_det_clr, in rockchip_usb2phy_init()
504 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
505 &rport->port_cfg->idrise_det_clr, in rockchip_usb2phy_init()
510 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
511 &rport->port_cfg->idfall_det_en, in rockchip_usb2phy_init()
516 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
517 &rport->port_cfg->idrise_det_en, in rockchip_usb2phy_init()
522 schedule_delayed_work(&rport->otg_sm_work, in rockchip_usb2phy_init()
526 dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode); in rockchip_usb2phy_init()
528 } else if (rport->port_id == USB2PHY_PORT_HOST) { in rockchip_usb2phy_init()
529 if (rport->port_cfg->disfall_en.offset) { in rockchip_usb2phy_init()
530 rport->host_disconnect = true; in rockchip_usb2phy_init()
533 dev_err(rphy->dev, "failed to enable disconnect irq\n"); in rockchip_usb2phy_init()
539 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
540 &rport->port_cfg->ls_det_clr, true); in rockchip_usb2phy_init()
544 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
545 &rport->port_cfg->ls_det_en, true); in rockchip_usb2phy_init()
549 schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY); in rockchip_usb2phy_init()
553 mutex_unlock(&rport->mutex); in rockchip_usb2phy_init()
560 struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); in rockchip_usb2phy_power_on()
564 dev_dbg(&rport->phy->dev, "port power on\n"); in rockchip_usb2phy_power_on()
566 if (!rport->suspended) in rockchip_usb2phy_power_on()
569 ret = clk_prepare_enable(rphy->clk480m); in rockchip_usb2phy_power_on()
573 ret = property_enable(base, &rport->port_cfg->phy_sus, false); in rockchip_usb2phy_power_on()
575 clk_disable_unprepare(rphy->clk480m); in rockchip_usb2phy_power_on()
594 rport->suspended = false; in rockchip_usb2phy_power_on()
601 struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); in rockchip_usb2phy_power_off()
605 dev_dbg(&rport->phy->dev, "port power off\n"); in rockchip_usb2phy_power_off()
607 if (rport->suspended) in rockchip_usb2phy_power_off()
610 ret = property_enable(base, &rport->port_cfg->phy_sus, true); in rockchip_usb2phy_power_off()
614 rport->suspended = true; in rockchip_usb2phy_power_off()
615 clk_disable_unprepare(rphy->clk480m); in rockchip_usb2phy_power_off()
624 if (rport->port_id == USB2PHY_PORT_OTG && in rockchip_usb2phy_exit()
625 rport->mode != USB_DR_MODE_HOST && in rockchip_usb2phy_exit()
626 rport->mode != USB_DR_MODE_UNKNOWN) { in rockchip_usb2phy_exit()
627 cancel_delayed_work_sync(&rport->otg_sm_work); in rockchip_usb2phy_exit()
628 cancel_delayed_work_sync(&rport->chg_work); in rockchip_usb2phy_exit()
629 } else if (rport->port_id == USB2PHY_PORT_HOST) in rockchip_usb2phy_exit()
630 cancel_delayed_work_sync(&rport->sm_work); in rockchip_usb2phy_exit()
648 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_otg_sm_work()
653 vbus_attach = property_enabled(rphy->grf, in rockchip_usb2phy_otg_sm_work()
654 &rport->port_cfg->utmi_bvalid); in rockchip_usb2phy_otg_sm_work()
659 dev_dbg(&rport->phy->dev, "%s otg sm work\n", in rockchip_usb2phy_otg_sm_work()
660 usb_otg_state_string(rport->state)); in rockchip_usb2phy_otg_sm_work()
662 switch (rport->state) { in rockchip_usb2phy_otg_sm_work()
664 rport->state = OTG_STATE_B_IDLE; in rockchip_usb2phy_otg_sm_work()
666 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
669 if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) > 0) { in rockchip_usb2phy_otg_sm_work()
670 dev_dbg(&rport->phy->dev, "usb otg host connect\n"); in rockchip_usb2phy_otg_sm_work()
671 rport->state = OTG_STATE_A_HOST; in rockchip_usb2phy_otg_sm_work()
672 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_otg_sm_work()
675 dev_dbg(&rport->phy->dev, "vbus_attach\n"); in rockchip_usb2phy_otg_sm_work()
676 switch (rphy->chg_state) { in rockchip_usb2phy_otg_sm_work()
678 schedule_delayed_work(&rport->chg_work, 0); in rockchip_usb2phy_otg_sm_work()
681 switch (rphy->chg_type) { in rockchip_usb2phy_otg_sm_work()
683 dev_dbg(&rport->phy->dev, "sdp cable is connected\n"); in rockchip_usb2phy_otg_sm_work()
684 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_otg_sm_work()
685 rport->state = OTG_STATE_B_PERIPHERAL; in rockchip_usb2phy_otg_sm_work()
691 dev_dbg(&rport->phy->dev, "dcp cable is connected\n"); in rockchip_usb2phy_otg_sm_work()
692 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
698 dev_dbg(&rport->phy->dev, "cdp cable is connected\n"); in rockchip_usb2phy_otg_sm_work()
699 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_otg_sm_work()
700 rport->state = OTG_STATE_B_PERIPHERAL; in rockchip_usb2phy_otg_sm_work()
714 rphy->chg_state = USB_CHG_STATE_UNDEFINED; in rockchip_usb2phy_otg_sm_work()
715 rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; in rockchip_usb2phy_otg_sm_work()
718 if (rport->vbus_attached != vbus_attach) { in rockchip_usb2phy_otg_sm_work()
719 rport->vbus_attached = vbus_attach; in rockchip_usb2phy_otg_sm_work()
721 if (notify_charger && rphy->edev) { in rockchip_usb2phy_otg_sm_work()
722 extcon_set_state_sync(rphy->edev, in rockchip_usb2phy_otg_sm_work()
725 extcon_set_state_sync(rphy->edev, in rockchip_usb2phy_otg_sm_work()
733 dev_dbg(&rport->phy->dev, "usb disconnect\n"); in rockchip_usb2phy_otg_sm_work()
734 rphy->chg_state = USB_CHG_STATE_UNDEFINED; in rockchip_usb2phy_otg_sm_work()
735 rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; in rockchip_usb2phy_otg_sm_work()
736 rport->state = OTG_STATE_B_IDLE; in rockchip_usb2phy_otg_sm_work()
738 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
743 if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) == 0) { in rockchip_usb2phy_otg_sm_work()
744 dev_dbg(&rport->phy->dev, "usb otg host disconnect\n"); in rockchip_usb2phy_otg_sm_work()
745 rport->state = OTG_STATE_B_IDLE; in rockchip_usb2phy_otg_sm_work()
746 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
754 schedule_delayed_work(&rport->otg_sm_work, delay); in rockchip_usb2phy_otg_sm_work()
772 bool en) in rockchip_chg_enable_dcd() argument
776 property_enable(base, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en); in rockchip_chg_enable_dcd()
777 property_enable(base, &rphy->phy_cfg->chg_det.idp_src_en, en); in rockchip_chg_enable_dcd()
781 bool en) in rockchip_chg_enable_primary_det() argument
785 property_enable(base, &rphy->phy_cfg->chg_det.vdp_src_en, en); in rockchip_chg_enable_primary_det()
786 property_enable(base, &rphy->phy_cfg->chg_det.idm_sink_en, en); in rockchip_chg_enable_primary_det()
790 bool en) in rockchip_chg_enable_secondary_det() argument
794 property_enable(base, &rphy->phy_cfg->chg_det.vdm_src_en, en); in rockchip_chg_enable_secondary_det()
795 property_enable(base, &rphy->phy_cfg->chg_det.idp_sink_en, en); in rockchip_chg_enable_secondary_det()
806 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_chg_detect_work()
811 dev_dbg(&rport->phy->dev, "chg detection work state = %d\n", in rockchip_chg_detect_work()
812 rphy->chg_state); in rockchip_chg_detect_work()
813 switch (rphy->chg_state) { in rockchip_chg_detect_work()
815 if (!rport->suspended) in rockchip_chg_detect_work()
816 rockchip_usb2phy_power_off(rport->phy); in rockchip_chg_detect_work()
817 /* put the controller in non-driving mode */ in rockchip_chg_detect_work()
818 property_enable(base, &rphy->phy_cfg->chg_det.opmode, false); in rockchip_chg_detect_work()
821 rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; in rockchip_chg_detect_work()
822 rphy->dcd_retries = 0; in rockchip_chg_detect_work()
827 is_dcd = property_enabled(rphy->grf, in rockchip_chg_detect_work()
828 &rphy->phy_cfg->chg_det.dp_det); in rockchip_chg_detect_work()
829 tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES; in rockchip_chg_detect_work()
838 rphy->chg_state = USB_CHG_STATE_DCD_DONE; in rockchip_chg_detect_work()
845 vout = property_enabled(rphy->grf, in rockchip_chg_detect_work()
846 &rphy->phy_cfg->chg_det.cp_det); in rockchip_chg_detect_work()
852 rphy->chg_state = USB_CHG_STATE_PRIMARY_DONE; in rockchip_chg_detect_work()
854 if (rphy->dcd_retries == CHG_DCD_MAX_RETRIES) { in rockchip_chg_detect_work()
856 rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; in rockchip_chg_detect_work()
857 rphy->chg_state = USB_CHG_STATE_DETECTED; in rockchip_chg_detect_work()
860 rphy->chg_type = POWER_SUPPLY_TYPE_USB; in rockchip_chg_detect_work()
861 rphy->chg_state = USB_CHG_STATE_DETECTED; in rockchip_chg_detect_work()
867 vout = property_enabled(rphy->grf, in rockchip_chg_detect_work()
868 &rphy->phy_cfg->chg_det.dcp_det); in rockchip_chg_detect_work()
872 rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; in rockchip_chg_detect_work()
874 rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP; in rockchip_chg_detect_work()
877 rphy->chg_state = USB_CHG_STATE_DETECTED; in rockchip_chg_detect_work()
881 property_enable(base, &rphy->phy_cfg->chg_det.opmode, true); in rockchip_chg_detect_work()
882 rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); in rockchip_chg_detect_work()
883 dev_dbg(&rport->phy->dev, "charger = %s\n", in rockchip_chg_detect_work()
884 chg_to_string(rphy->chg_type)); in rockchip_chg_detect_work()
890 schedule_delayed_work(&rport->chg_work, delay); in rockchip_chg_detect_work()
894 * The function manage host-phy port state and suspend/resume phy port
910 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_sm_work()
915 mutex_lock(&rport->mutex); in rockchip_usb2phy_sm_work()
917 ret = regmap_read(rphy->grf, rport->port_cfg->utmi_ls.offset, &ul); in rockchip_usb2phy_sm_work()
921 ul_mask = GENMASK(rport->port_cfg->utmi_ls.bitend, in rockchip_usb2phy_sm_work()
922 rport->port_cfg->utmi_ls.bitstart); in rockchip_usb2phy_sm_work()
924 if (rport->port_cfg->utmi_hstdet.offset) { in rockchip_usb2phy_sm_work()
925 ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd); in rockchip_usb2phy_sm_work()
929 uhd_mask = GENMASK(rport->port_cfg->utmi_hstdet.bitend, in rockchip_usb2phy_sm_work()
930 rport->port_cfg->utmi_hstdet.bitstart); in rockchip_usb2phy_sm_work()
932 sh = rport->port_cfg->utmi_hstdet.bitend - in rockchip_usb2phy_sm_work()
933 rport->port_cfg->utmi_hstdet.bitstart + 1; in rockchip_usb2phy_sm_work()
935 state = ((uhd & uhd_mask) >> rport->port_cfg->utmi_hstdet.bitstart) | in rockchip_usb2phy_sm_work()
936 (((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << sh); in rockchip_usb2phy_sm_work()
938 state = ((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << 1 | in rockchip_usb2phy_sm_work()
939 rport->host_disconnect; in rockchip_usb2phy_sm_work()
944 dev_dbg(&rport->phy->dev, "HS online\n"); in rockchip_usb2phy_sm_work()
952 * Plus, there are two cases, one is D- Line pull-up, and D+ in rockchip_usb2phy_sm_work()
953 * line pull-down, the state is 4; another is D+ line pull-up, in rockchip_usb2phy_sm_work()
954 * and D- line pull-down, the state is 2. in rockchip_usb2phy_sm_work()
956 if (!rport->suspended) { in rockchip_usb2phy_sm_work()
957 /* D- line pull-up, D+ line pull-down */ in rockchip_usb2phy_sm_work()
958 dev_dbg(&rport->phy->dev, "FS/LS online\n"); in rockchip_usb2phy_sm_work()
963 if (rport->suspended) { in rockchip_usb2phy_sm_work()
964 dev_dbg(&rport->phy->dev, "Connected\n"); in rockchip_usb2phy_sm_work()
965 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_sm_work()
966 rport->suspended = false; in rockchip_usb2phy_sm_work()
968 /* D+ line pull-up, D- line pull-down */ in rockchip_usb2phy_sm_work()
969 dev_dbg(&rport->phy->dev, "FS/LS online\n"); in rockchip_usb2phy_sm_work()
973 if (!rport->suspended) { in rockchip_usb2phy_sm_work()
974 dev_dbg(&rport->phy->dev, "Disconnected\n"); in rockchip_usb2phy_sm_work()
975 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_sm_work()
976 rport->suspended = true; in rockchip_usb2phy_sm_work()
981 * plug-in irq. in rockchip_usb2phy_sm_work()
983 property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true); in rockchip_usb2phy_sm_work()
984 property_enable(rphy->grf, &rport->port_cfg->ls_det_en, true); in rockchip_usb2phy_sm_work()
990 mutex_unlock(&rport->mutex); in rockchip_usb2phy_sm_work()
993 dev_dbg(&rport->phy->dev, "unknown phy state\n"); in rockchip_usb2phy_sm_work()
998 mutex_unlock(&rport->mutex); in rockchip_usb2phy_sm_work()
999 schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY); in rockchip_usb2phy_sm_work()
1005 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_linestate_irq()
1007 if (!property_enabled(rphy->grf, &rport->port_cfg->ls_det_st)) in rockchip_usb2phy_linestate_irq()
1010 mutex_lock(&rport->mutex); in rockchip_usb2phy_linestate_irq()
1013 property_enable(rphy->grf, &rport->port_cfg->ls_det_en, false); in rockchip_usb2phy_linestate_irq()
1014 property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true); in rockchip_usb2phy_linestate_irq()
1016 mutex_unlock(&rport->mutex); in rockchip_usb2phy_linestate_irq()
1023 if (rport->suspended && rport->port_id == USB2PHY_PORT_HOST) in rockchip_usb2phy_linestate_irq()
1024 rockchip_usb2phy_sm_work(&rport->sm_work.work); in rockchip_usb2phy_linestate_irq()
1032 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_bvalid_irq()
1034 if (!property_enabled(rphy->grf, &rport->port_cfg->bvalid_det_st)) in rockchip_usb2phy_bvalid_irq()
1038 property_enable(rphy->grf, &rport->port_cfg->bvalid_det_clr, true); in rockchip_usb2phy_bvalid_irq()
1040 rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); in rockchip_usb2phy_bvalid_irq()
1048 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_id_irq()
1051 if (!property_enabled(rphy->grf, &rport->port_cfg->idfall_det_st) && in rockchip_usb2phy_id_irq()
1052 !property_enabled(rphy->grf, &rport->port_cfg->idrise_det_st)) in rockchip_usb2phy_id_irq()
1056 if (property_enabled(rphy->grf, &rport->port_cfg->idfall_det_st)) in rockchip_usb2phy_id_irq()
1057 property_enable(rphy->grf, &rport->port_cfg->idfall_det_clr, true); in rockchip_usb2phy_id_irq()
1059 if (property_enabled(rphy->grf, &rport->port_cfg->idrise_det_st)) in rockchip_usb2phy_id_irq()
1060 property_enable(rphy->grf, &rport->port_cfg->idrise_det_clr, true); in rockchip_usb2phy_id_irq()
1062 id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id); in rockchip_usb2phy_id_irq()
1063 extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id); in rockchip_usb2phy_id_irq()
1081 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_host_disc_irq()
1083 if (!property_enabled(rphy->grf, &rport->port_cfg->disfall_st) && in rockchip_usb2phy_host_disc_irq()
1084 !property_enabled(rphy->grf, &rport->port_cfg->disrise_st)) in rockchip_usb2phy_host_disc_irq()
1087 mutex_lock(&rport->mutex); in rockchip_usb2phy_host_disc_irq()
1090 if (property_enabled(rphy->grf, &rport->port_cfg->disfall_st)) { in rockchip_usb2phy_host_disc_irq()
1091 property_enable(rphy->grf, &rport->port_cfg->disfall_clr, true); in rockchip_usb2phy_host_disc_irq()
1092 rport->host_disconnect = false; in rockchip_usb2phy_host_disc_irq()
1093 } else if (property_enabled(rphy->grf, &rport->port_cfg->disrise_st)) { in rockchip_usb2phy_host_disc_irq()
1094 property_enable(rphy->grf, &rport->port_cfg->disrise_clr, true); in rockchip_usb2phy_host_disc_irq()
1095 rport->host_disconnect = true; in rockchip_usb2phy_host_disc_irq()
1098 mutex_unlock(&rport->mutex); in rockchip_usb2phy_host_disc_irq()
1110 for (index = 0; index < rphy->phy_cfg->num_ports; index++) { in rockchip_usb2phy_irq()
1111 rport = &rphy->ports[index]; in rockchip_usb2phy_irq()
1112 if (!rport->phy) in rockchip_usb2phy_irq()
1115 if (rport->port_id == USB2PHY_PORT_HOST && in rockchip_usb2phy_irq()
1116 rport->port_cfg->disfall_en.offset) in rockchip_usb2phy_irq()
1119 switch (rport->port_id) { in rockchip_usb2phy_irq()
1121 if (rport->mode != USB_DR_MODE_HOST && in rockchip_usb2phy_irq()
1122 rport->mode != USB_DR_MODE_UNKNOWN) in rockchip_usb2phy_irq()
1144 if (rphy->irq > 0) in rockchip_usb2phy_port_irq_init()
1147 switch (rport->port_id) { in rockchip_usb2phy_port_irq_init()
1149 rport->ls_irq = of_irq_get_byname(child_np, "linestate"); in rockchip_usb2phy_port_irq_init()
1150 if (rport->ls_irq < 0) { in rockchip_usb2phy_port_irq_init()
1151 dev_err(rphy->dev, "no linestate irq provided\n"); in rockchip_usb2phy_port_irq_init()
1152 return rport->ls_irq; in rockchip_usb2phy_port_irq_init()
1155 ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL, in rockchip_usb2phy_port_irq_init()
1160 dev_err(rphy->dev, "failed to request linestate irq handle\n"); in rockchip_usb2phy_port_irq_init()
1166 * Some SoCs use one interrupt with otg-id/otg-bvalid/linestate in rockchip_usb2phy_port_irq_init()
1167 * interrupts muxed together, so probe the otg-mux interrupt first, in rockchip_usb2phy_port_irq_init()
1170 rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux"); in rockchip_usb2phy_port_irq_init()
1171 if (rport->otg_mux_irq > 0) { in rockchip_usb2phy_port_irq_init()
1172 ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq, in rockchip_usb2phy_port_irq_init()
1179 dev_err(rphy->dev, in rockchip_usb2phy_port_irq_init()
1180 "failed to request otg-mux irq handle\n"); in rockchip_usb2phy_port_irq_init()
1184 rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid"); in rockchip_usb2phy_port_irq_init()
1185 if (rport->bvalid_irq < 0) { in rockchip_usb2phy_port_irq_init()
1186 dev_err(rphy->dev, "no vbus valid irq provided\n"); in rockchip_usb2phy_port_irq_init()
1187 ret = rport->bvalid_irq; in rockchip_usb2phy_port_irq_init()
1191 ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, in rockchip_usb2phy_port_irq_init()
1198 dev_err(rphy->dev, in rockchip_usb2phy_port_irq_init()
1199 "failed to request otg-bvalid irq handle\n"); in rockchip_usb2phy_port_irq_init()
1203 rport->id_irq = of_irq_get_byname(child_np, "otg-id"); in rockchip_usb2phy_port_irq_init()
1204 if (rport->id_irq < 0) { in rockchip_usb2phy_port_irq_init()
1205 dev_err(rphy->dev, "no otg-id irq provided\n"); in rockchip_usb2phy_port_irq_init()
1206 ret = rport->id_irq; in rockchip_usb2phy_port_irq_init()
1210 ret = devm_request_threaded_irq(rphy->dev, rport->id_irq, in rockchip_usb2phy_port_irq_init()
1217 dev_err(rphy->dev, in rockchip_usb2phy_port_irq_init()
1218 "failed to request otg-id irq handle\n"); in rockchip_usb2phy_port_irq_init()
1224 return -EINVAL; in rockchip_usb2phy_port_irq_init()
1236 rport->port_id = USB2PHY_PORT_HOST; in rockchip_usb2phy_host_port_init()
1237 rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_HOST]; in rockchip_usb2phy_host_port_init()
1238 rport->suspended = true; in rockchip_usb2phy_host_port_init()
1240 mutex_init(&rport->mutex); in rockchip_usb2phy_host_port_init()
1241 INIT_DELAYED_WORK(&rport->sm_work, rockchip_usb2phy_sm_work); in rockchip_usb2phy_host_port_init()
1245 dev_err(rphy->dev, "failed to setup host irq\n"); in rockchip_usb2phy_host_port_init()
1258 schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY); in rockchip_otg_event()
1269 rport->port_id = USB2PHY_PORT_OTG; in rockchip_usb2phy_otg_port_init()
1270 rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG]; in rockchip_usb2phy_otg_port_init()
1271 rport->state = OTG_STATE_UNDEFINED; in rockchip_usb2phy_otg_port_init()
1275 * put phy in suspend mode, it aims to enable usb in rockchip_usb2phy_otg_port_init()
1276 * phy and clock in power_on() called by usb controller in rockchip_usb2phy_otg_port_init()
1279 rport->suspended = true; in rockchip_usb2phy_otg_port_init()
1280 rport->vbus_attached = false; in rockchip_usb2phy_otg_port_init()
1282 mutex_init(&rport->mutex); in rockchip_usb2phy_otg_port_init()
1284 rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1); in rockchip_usb2phy_otg_port_init()
1285 if (rport->mode == USB_DR_MODE_HOST || in rockchip_usb2phy_otg_port_init()
1286 rport->mode == USB_DR_MODE_UNKNOWN) { in rockchip_usb2phy_otg_port_init()
1291 INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work); in rockchip_usb2phy_otg_port_init()
1292 INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work); in rockchip_usb2phy_otg_port_init()
1296 dev_err(rphy->dev, "failed to init irq for host port\n"); in rockchip_usb2phy_otg_port_init()
1300 if (!IS_ERR(rphy->edev)) { in rockchip_usb2phy_otg_port_init()
1301 rport->event_nb.notifier_call = rockchip_otg_event; in rockchip_usb2phy_otg_port_init()
1303 ret = devm_extcon_register_notifier(rphy->dev, rphy->edev, in rockchip_usb2phy_otg_port_init()
1304 EXTCON_USB_HOST, &rport->event_nb); in rockchip_usb2phy_otg_port_init()
1306 dev_err(rphy->dev, "register USB HOST notifier failed\n"); in rockchip_usb2phy_otg_port_init()
1310 if (!of_property_read_bool(rphy->dev->of_node, "extcon")) { in rockchip_usb2phy_otg_port_init()
1311 /* do initial sync of usb state */ in rockchip_usb2phy_otg_port_init()
1312 id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id); in rockchip_usb2phy_otg_port_init()
1313 extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id); in rockchip_usb2phy_otg_port_init()
1323 struct device *dev = &pdev->dev; in rockchip_usb2phy_probe()
1324 struct device_node *np = dev->of_node; in rockchip_usb2phy_probe()
1334 return -ENOMEM; in rockchip_usb2phy_probe()
1336 if (!dev->parent || !dev->parent->of_node) { in rockchip_usb2phy_probe()
1337 rphy->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbgrf"); in rockchip_usb2phy_probe()
1338 if (IS_ERR(rphy->grf)) { in rockchip_usb2phy_probe()
1340 return PTR_ERR(rphy->grf); in rockchip_usb2phy_probe()
1345 rphy->grf = syscon_node_to_regmap(dev->parent->of_node); in rockchip_usb2phy_probe()
1346 if (IS_ERR(rphy->grf)) in rockchip_usb2phy_probe()
1347 return PTR_ERR(rphy->grf); in rockchip_usb2phy_probe()
1350 if (of_device_is_compatible(np, "rockchip,rv1108-usb2phy")) { in rockchip_usb2phy_probe()
1351 rphy->usbgrf = in rockchip_usb2phy_probe()
1352 syscon_regmap_lookup_by_phandle(dev->of_node, in rockchip_usb2phy_probe()
1354 if (IS_ERR(rphy->usbgrf)) in rockchip_usb2phy_probe()
1355 return PTR_ERR(rphy->usbgrf); in rockchip_usb2phy_probe()
1357 rphy->usbgrf = NULL; in rockchip_usb2phy_probe()
1363 return -EINVAL; in rockchip_usb2phy_probe()
1371 return -EINVAL; in rockchip_usb2phy_probe()
1375 rphy->dev = dev; in rockchip_usb2phy_probe()
1377 rphy->chg_state = USB_CHG_STATE_UNDEFINED; in rockchip_usb2phy_probe()
1378 rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; in rockchip_usb2phy_probe()
1379 rphy->irq = platform_get_irq_optional(pdev, 0); in rockchip_usb2phy_probe()
1383 return dev_err_probe(dev, -EINVAL, "phy configs are not assigned!\n"); in rockchip_usb2phy_probe()
1393 rphy->phy_cfg = &phy_cfgs[index]; in rockchip_usb2phy_probe()
1400 if (!rphy->phy_cfg) { in rockchip_usb2phy_probe()
1402 return -EINVAL; in rockchip_usb2phy_probe()
1405 rphy->phy_reset = devm_reset_control_get_optional(dev, "phy"); in rockchip_usb2phy_probe()
1406 if (IS_ERR(rphy->phy_reset)) in rockchip_usb2phy_probe()
1407 return PTR_ERR(rphy->phy_reset); in rockchip_usb2phy_probe()
1409 rphy->clk = devm_clk_get_optional_enabled(dev, "phyclk"); in rockchip_usb2phy_probe()
1410 if (IS_ERR(rphy->clk)) { in rockchip_usb2phy_probe()
1411 return dev_err_probe(&pdev->dev, PTR_ERR(rphy->clk), in rockchip_usb2phy_probe()
1421 if (rphy->phy_cfg->phy_tuning) { in rockchip_usb2phy_probe()
1422 ret = rphy->phy_cfg->phy_tuning(rphy); in rockchip_usb2phy_probe()
1429 struct rockchip_usb2phy_port *rport = &rphy->ports[index]; in rockchip_usb2phy_probe()
1432 /* This driver aims to support both otg-port and host-port */ in rockchip_usb2phy_probe()
1433 if (!of_node_name_eq(child_np, "host-port") && in rockchip_usb2phy_probe()
1434 !of_node_name_eq(child_np, "otg-port")) in rockchip_usb2phy_probe()
1444 rport->phy = phy; in rockchip_usb2phy_probe()
1445 phy_set_drvdata(rport->phy, rport); in rockchip_usb2phy_probe()
1448 if (of_node_name_eq(child_np, "host-port")) { in rockchip_usb2phy_probe()
1462 if (++index >= rphy->phy_cfg->num_ports) { in rockchip_usb2phy_probe()
1470 if (rphy->irq > 0) { in rockchip_usb2phy_probe()
1471 ret = devm_request_threaded_irq(rphy->dev, rphy->irq, NULL, in rockchip_usb2phy_probe()
1477 dev_err(rphy->dev, in rockchip_usb2phy_probe()
1493 return regmap_write_bits(rphy->grf, 0x298, in rk3128_usb2phy_tuning()
1503 * utmi_termselect = 1'b1 (en FS terminations) in rk3588_usb2phy_tuning()
1508 if (rphy->phy_cfg->reg == 0x0000 || rphy->phy_cfg->reg == 0x4000) { in rk3588_usb2phy_tuning()
1510 suspend_cfg |= 0x01; /* utmi_opmode = 2'b01 (no-driving) */ in rk3588_usb2phy_tuning()
1512 } else if (rphy->phy_cfg->reg == 0x8000 || rphy->phy_cfg->reg == 0xc000) { in rk3588_usb2phy_tuning()
1516 return -EINVAL; in rk3588_usb2phy_tuning()
1520 ret = regmap_write(rphy->grf, 0x0008, GENMASK(29, 29) | 0x0000); in rk3588_usb2phy_tuning()
1530 ret |= regmap_write(rphy->grf, 0x000c, GENMASK(20, 16) | suspend_cfg); in rk3588_usb2phy_tuning()
1533 ret |= regmap_write(rphy->grf, 0x0004, GENMASK(27, 24) | 0x0900); in rk3588_usb2phy_tuning()
1535 /* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */ in rk3588_usb2phy_tuning()
1536 ret |= regmap_write(rphy->grf, 0x0008, GENMASK(20, 19) | 0x0010); in rk3588_usb2phy_tuning()
1542 ret |= regmap_write(rphy->grf, 0x0010, GENMASK(17, 16) | 0x0003); in rk3588_usb2phy_tuning()
2089 { .compatible = "rockchip,px30-usb2phy", .data = &rk3328_phy_cfgs },
2090 { .compatible = "rockchip,rk3128-usb2phy", .data = &rk3128_phy_cfgs },
2091 { .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs },
2092 { .compatible = "rockchip,rk3308-usb2phy", .data = &rk3308_phy_cfgs },
2093 { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
2094 { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
2095 { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
2096 { .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs },
2097 { .compatible = "rockchip,rk3588-usb2phy", .data = &rk3588_phy_cfgs },
2098 { .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs },
2106 .name = "rockchip-usb2phy",
2112 MODULE_AUTHOR("Frank Wang <frank.wang@rock-chips.com>");