Lines Matching +full:assert +full:- +full:falling +full:- +full:edge

1 // SPDX-License-Identifier: GPL-2.0-or-later
9 #include <linux/clk-provider.h>
11 #include <linux/extcon-provider.h>
50 * enum usb_chg_state - Different states involved in USB charger detection.
89 * struct rockchip_chg_det_reg - usb charger detect registers
92 * @dp_det: assert data pin connect successfully.
115 * struct rockchip_usb2phy_port_cfg - usb-phy port configuration.
120 * @disfall_en: host disconnect fall edge detection enable.
121 * @disfall_st: host disconnect fall edge detection state.
122 * @disfall_clr: host disconnect fall edge detection clear.
123 * @disrise_en: host disconnect rise edge detection enable.
124 * @disrise_st: host disconnect rise edge detection state.
125 * @disrise_clr: host disconnect rise edge detection clear.
126 * @idfall_det_en: id detection enable register, falling edge
127 * @idfall_det_st: id detection state register, falling edge
128 * @idfall_det_clr: id detection clear register, falling edge
129 * @idrise_det_en: id detection enable register, rising edge
130 * @idrise_det_st: id detection state register, rising edge
131 * @idrise_det_clr: id detection clear register, rising edge
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.
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.
266 return rphy->usbgrf == NULL ? rphy->grf : rphy->usbgrf; in get_reg_base()
274 tmp = en ? reg->enable : reg->disable; in property_enable()
275 mask = GENMASK(reg->bitend, reg->bitstart); in property_enable()
276 val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); in property_enable()
278 return regmap_write(base, reg->offset, val); in property_enable()
286 unsigned int mask = GENMASK(reg->bitend, reg->bitstart); in property_enabled()
288 ret = regmap_read(base, reg->offset, &orig); in property_enabled()
292 tmp = (orig & mask) >> reg->bitstart; in property_enabled()
293 return tmp != reg->disable; in property_enabled()
300 ret = reset_control_assert(rphy->phy_reset); in rockchip_usb2phy_reset()
306 ret = reset_control_deassert(rphy->phy_reset); in rockchip_usb2phy_reset()
319 clk_bulk_disable_unprepare(rphy->num_clks, rphy->clks); in rockchip_usb2phy_clk_bulk_disable()
330 if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) { in rockchip_usb2phy_clk480m_prepare()
331 ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true); in rockchip_usb2phy_clk480m_prepare()
349 property_enable(base, &rphy->phy_cfg->clkout_ctl, false); in rockchip_usb2phy_clk480m_unprepare()
358 return property_enabled(base, &rphy->phy_cfg->clkout_ctl); in rockchip_usb2phy_clk480m_prepared()
379 of_clk_del_provider(rphy->dev->of_node); in rockchip_usb2phy_clk480m_unregister()
380 clk_unregister(rphy->clk480m); in rockchip_usb2phy_clk480m_unregister()
386 struct device_node *node = rphy->dev->of_node; in rockchip_usb2phy_clk480m_register()
398 of_property_read_string(node, "clock-output-names", &init.name); in rockchip_usb2phy_clk480m_register()
400 for (i = 0; i < rphy->num_clks; i++) { in rockchip_usb2phy_clk480m_register()
401 if (!strncmp(rphy->clks[i].id, "phyclk", 6)) { in rockchip_usb2phy_clk480m_register()
402 refclk = rphy->clks[i].clk; in rockchip_usb2phy_clk480m_register()
416 rphy->clk480m_hw.init = &init; in rockchip_usb2phy_clk480m_register()
419 rphy->clk480m = clk_register(rphy->dev, &rphy->clk480m_hw); in rockchip_usb2phy_clk480m_register()
420 if (IS_ERR(rphy->clk480m)) { in rockchip_usb2phy_clk480m_register()
421 ret = PTR_ERR(rphy->clk480m); in rockchip_usb2phy_clk480m_register()
425 ret = of_clk_add_provider(node, of_clk_src_simple_get, rphy->clk480m); in rockchip_usb2phy_clk480m_register()
429 return devm_add_action_or_reset(rphy->dev, rockchip_usb2phy_clk480m_unregister, rphy); in rockchip_usb2phy_clk480m_register()
432 clk_unregister(rphy->clk480m); in rockchip_usb2phy_clk480m_register()
439 struct device_node *node = rphy->dev->of_node; in rockchip_usb2phy_extcon_register()
444 edev = extcon_get_edev_by_phandle(rphy->dev, 0); in rockchip_usb2phy_extcon_register()
446 return dev_err_probe(rphy->dev, PTR_ERR(edev), in rockchip_usb2phy_extcon_register()
450 edev = devm_extcon_dev_allocate(rphy->dev, in rockchip_usb2phy_extcon_register()
454 return dev_err_probe(rphy->dev, PTR_ERR(edev), in rockchip_usb2phy_extcon_register()
457 ret = devm_extcon_dev_register(rphy->dev, edev); in rockchip_usb2phy_extcon_register()
459 return dev_err_probe(rphy->dev, ret, in rockchip_usb2phy_extcon_register()
463 rphy->edev = edev; in rockchip_usb2phy_extcon_register()
474 ret = property_enable(rphy->grf, &rport->port_cfg->disfall_clr, true); in rockchip_usb2phy_enable_host_disc_irq()
478 ret = property_enable(rphy->grf, &rport->port_cfg->disfall_en, en); in rockchip_usb2phy_enable_host_disc_irq()
482 ret = property_enable(rphy->grf, &rport->port_cfg->disrise_clr, true); in rockchip_usb2phy_enable_host_disc_irq()
486 return property_enable(rphy->grf, &rport->port_cfg->disrise_en, en); in rockchip_usb2phy_enable_host_disc_irq()
492 struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); in rockchip_usb2phy_init()
495 mutex_lock(&rport->mutex); in rockchip_usb2phy_init()
497 if (rport->port_id == USB2PHY_PORT_OTG) { in rockchip_usb2phy_init()
498 if (rport->mode != USB_DR_MODE_HOST && in rockchip_usb2phy_init()
499 rport->mode != USB_DR_MODE_UNKNOWN) { in rockchip_usb2phy_init()
501 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
502 &rport->port_cfg->bvalid_det_clr, in rockchip_usb2phy_init()
507 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
508 &rport->port_cfg->bvalid_det_en, in rockchip_usb2phy_init()
514 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
515 &rport->port_cfg->idfall_det_clr, in rockchip_usb2phy_init()
520 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
521 &rport->port_cfg->idrise_det_clr, in rockchip_usb2phy_init()
526 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
527 &rport->port_cfg->idfall_det_en, in rockchip_usb2phy_init()
532 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
533 &rport->port_cfg->idrise_det_en, in rockchip_usb2phy_init()
538 schedule_delayed_work(&rport->otg_sm_work, in rockchip_usb2phy_init()
542 dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode); in rockchip_usb2phy_init()
544 } else if (rport->port_id == USB2PHY_PORT_HOST) { in rockchip_usb2phy_init()
545 if (rport->port_cfg->disfall_en.offset) { in rockchip_usb2phy_init()
546 rport->host_disconnect = true; in rockchip_usb2phy_init()
549 dev_err(rphy->dev, "failed to enable disconnect irq\n"); in rockchip_usb2phy_init()
555 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
556 &rport->port_cfg->ls_det_clr, true); in rockchip_usb2phy_init()
560 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
561 &rport->port_cfg->ls_det_en, true); in rockchip_usb2phy_init()
565 schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY); in rockchip_usb2phy_init()
569 mutex_unlock(&rport->mutex); in rockchip_usb2phy_init()
576 struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); in rockchip_usb2phy_power_on()
580 dev_dbg(&rport->phy->dev, "port power on\n"); in rockchip_usb2phy_power_on()
582 if (!rport->suspended) in rockchip_usb2phy_power_on()
585 ret = clk_prepare_enable(rphy->clk480m); in rockchip_usb2phy_power_on()
589 ret = property_enable(base, &rport->port_cfg->phy_sus, false); in rockchip_usb2phy_power_on()
591 clk_disable_unprepare(rphy->clk480m); in rockchip_usb2phy_power_on()
610 rport->suspended = false; in rockchip_usb2phy_power_on()
617 struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); in rockchip_usb2phy_power_off()
621 dev_dbg(&rport->phy->dev, "port power off\n"); in rockchip_usb2phy_power_off()
623 if (rport->suspended) in rockchip_usb2phy_power_off()
626 ret = property_enable(base, &rport->port_cfg->phy_sus, true); in rockchip_usb2phy_power_off()
630 rport->suspended = true; in rockchip_usb2phy_power_off()
631 clk_disable_unprepare(rphy->clk480m); in rockchip_usb2phy_power_off()
640 if (rport->port_id == USB2PHY_PORT_OTG && in rockchip_usb2phy_exit()
641 rport->mode != USB_DR_MODE_HOST && in rockchip_usb2phy_exit()
642 rport->mode != USB_DR_MODE_UNKNOWN) { in rockchip_usb2phy_exit()
643 cancel_delayed_work_sync(&rport->otg_sm_work); in rockchip_usb2phy_exit()
644 cancel_delayed_work_sync(&rport->chg_work); in rockchip_usb2phy_exit()
645 } else if (rport->port_id == USB2PHY_PORT_HOST) in rockchip_usb2phy_exit()
646 cancel_delayed_work_sync(&rport->sm_work); in rockchip_usb2phy_exit()
664 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_otg_sm_work()
669 vbus_attach = property_enabled(rphy->grf, in rockchip_usb2phy_otg_sm_work()
670 &rport->port_cfg->utmi_bvalid); in rockchip_usb2phy_otg_sm_work()
675 dev_dbg(&rport->phy->dev, "%s otg sm work\n", in rockchip_usb2phy_otg_sm_work()
676 usb_otg_state_string(rport->state)); in rockchip_usb2phy_otg_sm_work()
678 switch (rport->state) { in rockchip_usb2phy_otg_sm_work()
680 rport->state = OTG_STATE_B_IDLE; in rockchip_usb2phy_otg_sm_work()
682 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
685 if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) > 0) { in rockchip_usb2phy_otg_sm_work()
686 dev_dbg(&rport->phy->dev, "usb otg host connect\n"); in rockchip_usb2phy_otg_sm_work()
687 rport->state = OTG_STATE_A_HOST; in rockchip_usb2phy_otg_sm_work()
688 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_otg_sm_work()
691 dev_dbg(&rport->phy->dev, "vbus_attach\n"); in rockchip_usb2phy_otg_sm_work()
692 switch (rphy->chg_state) { in rockchip_usb2phy_otg_sm_work()
694 schedule_delayed_work(&rport->chg_work, 0); in rockchip_usb2phy_otg_sm_work()
697 switch (rphy->chg_type) { in rockchip_usb2phy_otg_sm_work()
699 dev_dbg(&rport->phy->dev, "sdp cable is connected\n"); in rockchip_usb2phy_otg_sm_work()
700 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_otg_sm_work()
701 rport->state = OTG_STATE_B_PERIPHERAL; in rockchip_usb2phy_otg_sm_work()
707 dev_dbg(&rport->phy->dev, "dcp cable is connected\n"); in rockchip_usb2phy_otg_sm_work()
708 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
714 dev_dbg(&rport->phy->dev, "cdp cable is connected\n"); in rockchip_usb2phy_otg_sm_work()
715 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_otg_sm_work()
716 rport->state = OTG_STATE_B_PERIPHERAL; in rockchip_usb2phy_otg_sm_work()
730 rphy->chg_state = USB_CHG_STATE_UNDEFINED; in rockchip_usb2phy_otg_sm_work()
731 rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; in rockchip_usb2phy_otg_sm_work()
734 if (rport->vbus_attached != vbus_attach) { in rockchip_usb2phy_otg_sm_work()
735 rport->vbus_attached = vbus_attach; in rockchip_usb2phy_otg_sm_work()
737 if (notify_charger && rphy->edev) { in rockchip_usb2phy_otg_sm_work()
738 extcon_set_state_sync(rphy->edev, in rockchip_usb2phy_otg_sm_work()
741 extcon_set_state_sync(rphy->edev, in rockchip_usb2phy_otg_sm_work()
749 dev_dbg(&rport->phy->dev, "usb disconnect\n"); in rockchip_usb2phy_otg_sm_work()
750 rphy->chg_state = USB_CHG_STATE_UNDEFINED; in rockchip_usb2phy_otg_sm_work()
751 rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; in rockchip_usb2phy_otg_sm_work()
752 rport->state = OTG_STATE_B_IDLE; in rockchip_usb2phy_otg_sm_work()
754 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
759 if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) == 0) { in rockchip_usb2phy_otg_sm_work()
760 dev_dbg(&rport->phy->dev, "usb otg host disconnect\n"); in rockchip_usb2phy_otg_sm_work()
761 rport->state = OTG_STATE_B_IDLE; in rockchip_usb2phy_otg_sm_work()
762 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
770 schedule_delayed_work(&rport->otg_sm_work, delay); in rockchip_usb2phy_otg_sm_work()
792 property_enable(base, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en); in rockchip_chg_enable_dcd()
793 property_enable(base, &rphy->phy_cfg->chg_det.idp_src_en, en); in rockchip_chg_enable_dcd()
801 property_enable(base, &rphy->phy_cfg->chg_det.vdp_src_en, en); in rockchip_chg_enable_primary_det()
802 property_enable(base, &rphy->phy_cfg->chg_det.idm_sink_en, en); in rockchip_chg_enable_primary_det()
810 property_enable(base, &rphy->phy_cfg->chg_det.vdm_src_en, en); in rockchip_chg_enable_secondary_det()
811 property_enable(base, &rphy->phy_cfg->chg_det.idp_sink_en, en); in rockchip_chg_enable_secondary_det()
822 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_chg_detect_work()
827 dev_dbg(&rport->phy->dev, "chg detection work state = %d\n", in rockchip_chg_detect_work()
828 rphy->chg_state); in rockchip_chg_detect_work()
829 switch (rphy->chg_state) { in rockchip_chg_detect_work()
831 if (!rport->suspended) in rockchip_chg_detect_work()
832 rockchip_usb2phy_power_off(rport->phy); in rockchip_chg_detect_work()
833 /* put the controller in non-driving mode */ in rockchip_chg_detect_work()
834 property_enable(base, &rphy->phy_cfg->chg_det.opmode, false); in rockchip_chg_detect_work()
837 rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; in rockchip_chg_detect_work()
838 rphy->dcd_retries = 0; in rockchip_chg_detect_work()
843 is_dcd = property_enabled(rphy->grf, in rockchip_chg_detect_work()
844 &rphy->phy_cfg->chg_det.dp_det); in rockchip_chg_detect_work()
845 tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES; in rockchip_chg_detect_work()
854 rphy->chg_state = USB_CHG_STATE_DCD_DONE; in rockchip_chg_detect_work()
861 vout = property_enabled(rphy->grf, in rockchip_chg_detect_work()
862 &rphy->phy_cfg->chg_det.cp_det); in rockchip_chg_detect_work()
868 rphy->chg_state = USB_CHG_STATE_PRIMARY_DONE; in rockchip_chg_detect_work()
870 if (rphy->dcd_retries == CHG_DCD_MAX_RETRIES) { in rockchip_chg_detect_work()
872 rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; in rockchip_chg_detect_work()
873 rphy->chg_state = USB_CHG_STATE_DETECTED; in rockchip_chg_detect_work()
876 rphy->chg_type = POWER_SUPPLY_TYPE_USB; in rockchip_chg_detect_work()
877 rphy->chg_state = USB_CHG_STATE_DETECTED; in rockchip_chg_detect_work()
883 vout = property_enabled(rphy->grf, in rockchip_chg_detect_work()
884 &rphy->phy_cfg->chg_det.dcp_det); in rockchip_chg_detect_work()
888 rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; in rockchip_chg_detect_work()
890 rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP; in rockchip_chg_detect_work()
893 rphy->chg_state = USB_CHG_STATE_DETECTED; in rockchip_chg_detect_work()
897 property_enable(base, &rphy->phy_cfg->chg_det.opmode, true); in rockchip_chg_detect_work()
898 rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); in rockchip_chg_detect_work()
899 dev_dbg(&rport->phy->dev, "charger = %s\n", in rockchip_chg_detect_work()
900 chg_to_string(rphy->chg_type)); in rockchip_chg_detect_work()
906 schedule_delayed_work(&rport->chg_work, delay); in rockchip_chg_detect_work()
910 * The function manage host-phy port state and suspend/resume phy port
926 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_sm_work()
931 mutex_lock(&rport->mutex); in rockchip_usb2phy_sm_work()
933 ret = regmap_read(rphy->grf, rport->port_cfg->utmi_ls.offset, &ul); in rockchip_usb2phy_sm_work()
937 ul_mask = GENMASK(rport->port_cfg->utmi_ls.bitend, in rockchip_usb2phy_sm_work()
938 rport->port_cfg->utmi_ls.bitstart); in rockchip_usb2phy_sm_work()
940 if (rport->port_cfg->utmi_hstdet.offset) { in rockchip_usb2phy_sm_work()
941 ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd); in rockchip_usb2phy_sm_work()
945 uhd_mask = GENMASK(rport->port_cfg->utmi_hstdet.bitend, in rockchip_usb2phy_sm_work()
946 rport->port_cfg->utmi_hstdet.bitstart); in rockchip_usb2phy_sm_work()
948 sh = rport->port_cfg->utmi_hstdet.bitend - in rockchip_usb2phy_sm_work()
949 rport->port_cfg->utmi_hstdet.bitstart + 1; in rockchip_usb2phy_sm_work()
951 state = ((uhd & uhd_mask) >> rport->port_cfg->utmi_hstdet.bitstart) | in rockchip_usb2phy_sm_work()
952 (((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << sh); in rockchip_usb2phy_sm_work()
954 state = ((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << 1 | in rockchip_usb2phy_sm_work()
955 rport->host_disconnect; in rockchip_usb2phy_sm_work()
960 dev_dbg(&rport->phy->dev, "HS online\n"); in rockchip_usb2phy_sm_work()
968 * Plus, there are two cases, one is D- Line pull-up, and D+ in rockchip_usb2phy_sm_work()
969 * line pull-down, the state is 4; another is D+ line pull-up, in rockchip_usb2phy_sm_work()
970 * and D- line pull-down, the state is 2. in rockchip_usb2phy_sm_work()
972 if (!rport->suspended) { in rockchip_usb2phy_sm_work()
973 /* D- line pull-up, D+ line pull-down */ in rockchip_usb2phy_sm_work()
974 dev_dbg(&rport->phy->dev, "FS/LS online\n"); in rockchip_usb2phy_sm_work()
979 if (rport->suspended) { in rockchip_usb2phy_sm_work()
980 dev_dbg(&rport->phy->dev, "Connected\n"); in rockchip_usb2phy_sm_work()
981 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_sm_work()
982 rport->suspended = false; in rockchip_usb2phy_sm_work()
984 /* D+ line pull-up, D- line pull-down */ in rockchip_usb2phy_sm_work()
985 dev_dbg(&rport->phy->dev, "FS/LS online\n"); in rockchip_usb2phy_sm_work()
989 if (!rport->suspended) { in rockchip_usb2phy_sm_work()
990 dev_dbg(&rport->phy->dev, "Disconnected\n"); in rockchip_usb2phy_sm_work()
991 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_sm_work()
992 rport->suspended = true; in rockchip_usb2phy_sm_work()
997 * plug-in irq. in rockchip_usb2phy_sm_work()
999 property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true); in rockchip_usb2phy_sm_work()
1000 property_enable(rphy->grf, &rport->port_cfg->ls_det_en, true); in rockchip_usb2phy_sm_work()
1006 mutex_unlock(&rport->mutex); in rockchip_usb2phy_sm_work()
1009 dev_dbg(&rport->phy->dev, "unknown phy state\n"); in rockchip_usb2phy_sm_work()
1014 mutex_unlock(&rport->mutex); in rockchip_usb2phy_sm_work()
1015 schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY); in rockchip_usb2phy_sm_work()
1021 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_linestate_irq()
1023 if (!property_enabled(rphy->grf, &rport->port_cfg->ls_det_st)) in rockchip_usb2phy_linestate_irq()
1026 mutex_lock(&rport->mutex); in rockchip_usb2phy_linestate_irq()
1029 property_enable(rphy->grf, &rport->port_cfg->ls_det_en, false); in rockchip_usb2phy_linestate_irq()
1030 property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true); in rockchip_usb2phy_linestate_irq()
1032 mutex_unlock(&rport->mutex); in rockchip_usb2phy_linestate_irq()
1039 if (rport->suspended && rport->port_id == USB2PHY_PORT_HOST) in rockchip_usb2phy_linestate_irq()
1040 rockchip_usb2phy_sm_work(&rport->sm_work.work); in rockchip_usb2phy_linestate_irq()
1048 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_bvalid_irq()
1050 if (!property_enabled(rphy->grf, &rport->port_cfg->bvalid_det_st)) in rockchip_usb2phy_bvalid_irq()
1054 property_enable(rphy->grf, &rport->port_cfg->bvalid_det_clr, true); in rockchip_usb2phy_bvalid_irq()
1056 rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); in rockchip_usb2phy_bvalid_irq()
1064 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_id_irq()
1067 if (!property_enabled(rphy->grf, &rport->port_cfg->idfall_det_st) && in rockchip_usb2phy_id_irq()
1068 !property_enabled(rphy->grf, &rport->port_cfg->idrise_det_st)) in rockchip_usb2phy_id_irq()
1072 if (property_enabled(rphy->grf, &rport->port_cfg->idfall_det_st)) in rockchip_usb2phy_id_irq()
1073 property_enable(rphy->grf, &rport->port_cfg->idfall_det_clr, true); in rockchip_usb2phy_id_irq()
1075 if (property_enabled(rphy->grf, &rport->port_cfg->idrise_det_st)) in rockchip_usb2phy_id_irq()
1076 property_enable(rphy->grf, &rport->port_cfg->idrise_det_clr, true); in rockchip_usb2phy_id_irq()
1078 id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id); in rockchip_usb2phy_id_irq()
1079 extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id); in rockchip_usb2phy_id_irq()
1097 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_host_disc_irq()
1099 if (!property_enabled(rphy->grf, &rport->port_cfg->disfall_st) && in rockchip_usb2phy_host_disc_irq()
1100 !property_enabled(rphy->grf, &rport->port_cfg->disrise_st)) in rockchip_usb2phy_host_disc_irq()
1103 mutex_lock(&rport->mutex); in rockchip_usb2phy_host_disc_irq()
1106 if (property_enabled(rphy->grf, &rport->port_cfg->disfall_st)) { in rockchip_usb2phy_host_disc_irq()
1107 property_enable(rphy->grf, &rport->port_cfg->disfall_clr, true); in rockchip_usb2phy_host_disc_irq()
1108 rport->host_disconnect = false; in rockchip_usb2phy_host_disc_irq()
1109 } else if (property_enabled(rphy->grf, &rport->port_cfg->disrise_st)) { in rockchip_usb2phy_host_disc_irq()
1110 property_enable(rphy->grf, &rport->port_cfg->disrise_clr, true); in rockchip_usb2phy_host_disc_irq()
1111 rport->host_disconnect = true; in rockchip_usb2phy_host_disc_irq()
1114 mutex_unlock(&rport->mutex); in rockchip_usb2phy_host_disc_irq()
1126 for (index = 0; index < rphy->phy_cfg->num_ports; index++) { in rockchip_usb2phy_irq()
1127 rport = &rphy->ports[index]; in rockchip_usb2phy_irq()
1128 if (!rport->phy) in rockchip_usb2phy_irq()
1131 if (rport->port_id == USB2PHY_PORT_HOST && in rockchip_usb2phy_irq()
1132 rport->port_cfg->disfall_en.offset) in rockchip_usb2phy_irq()
1135 switch (rport->port_id) { in rockchip_usb2phy_irq()
1137 if (rport->mode != USB_DR_MODE_HOST && in rockchip_usb2phy_irq()
1138 rport->mode != USB_DR_MODE_UNKNOWN) in rockchip_usb2phy_irq()
1160 if (rphy->irq > 0) in rockchip_usb2phy_port_irq_init()
1163 switch (rport->port_id) { in rockchip_usb2phy_port_irq_init()
1165 rport->ls_irq = of_irq_get_byname(child_np, "linestate"); in rockchip_usb2phy_port_irq_init()
1166 if (rport->ls_irq < 0) { in rockchip_usb2phy_port_irq_init()
1167 dev_err(rphy->dev, "no linestate irq provided\n"); in rockchip_usb2phy_port_irq_init()
1168 return rport->ls_irq; in rockchip_usb2phy_port_irq_init()
1171 ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL, in rockchip_usb2phy_port_irq_init()
1176 dev_err(rphy->dev, "failed to request linestate irq handle\n"); in rockchip_usb2phy_port_irq_init()
1182 * Some SoCs use one interrupt with otg-id/otg-bvalid/linestate in rockchip_usb2phy_port_irq_init()
1183 * interrupts muxed together, so probe the otg-mux interrupt first, in rockchip_usb2phy_port_irq_init()
1186 rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux"); in rockchip_usb2phy_port_irq_init()
1187 if (rport->otg_mux_irq > 0) { in rockchip_usb2phy_port_irq_init()
1188 ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq, in rockchip_usb2phy_port_irq_init()
1195 dev_err(rphy->dev, in rockchip_usb2phy_port_irq_init()
1196 "failed to request otg-mux irq handle\n"); in rockchip_usb2phy_port_irq_init()
1200 rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid"); in rockchip_usb2phy_port_irq_init()
1201 if (rport->bvalid_irq < 0) { in rockchip_usb2phy_port_irq_init()
1202 dev_err(rphy->dev, "no vbus valid irq provided\n"); in rockchip_usb2phy_port_irq_init()
1203 ret = rport->bvalid_irq; in rockchip_usb2phy_port_irq_init()
1207 ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, in rockchip_usb2phy_port_irq_init()
1214 dev_err(rphy->dev, in rockchip_usb2phy_port_irq_init()
1215 "failed to request otg-bvalid irq handle\n"); in rockchip_usb2phy_port_irq_init()
1219 rport->id_irq = of_irq_get_byname(child_np, "otg-id"); in rockchip_usb2phy_port_irq_init()
1220 if (rport->id_irq < 0) { in rockchip_usb2phy_port_irq_init()
1221 dev_err(rphy->dev, "no otg-id irq provided\n"); in rockchip_usb2phy_port_irq_init()
1222 ret = rport->id_irq; in rockchip_usb2phy_port_irq_init()
1226 ret = devm_request_threaded_irq(rphy->dev, rport->id_irq, in rockchip_usb2phy_port_irq_init()
1233 dev_err(rphy->dev, in rockchip_usb2phy_port_irq_init()
1234 "failed to request otg-id irq handle\n"); in rockchip_usb2phy_port_irq_init()
1240 return -EINVAL; in rockchip_usb2phy_port_irq_init()
1252 rport->port_id = USB2PHY_PORT_HOST; in rockchip_usb2phy_host_port_init()
1253 rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_HOST]; in rockchip_usb2phy_host_port_init()
1254 rport->suspended = true; in rockchip_usb2phy_host_port_init()
1256 mutex_init(&rport->mutex); in rockchip_usb2phy_host_port_init()
1257 INIT_DELAYED_WORK(&rport->sm_work, rockchip_usb2phy_sm_work); in rockchip_usb2phy_host_port_init()
1261 dev_err(rphy->dev, "failed to setup host irq\n"); in rockchip_usb2phy_host_port_init()
1274 schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY); in rockchip_otg_event()
1285 rport->port_id = USB2PHY_PORT_OTG; in rockchip_usb2phy_otg_port_init()
1286 rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG]; in rockchip_usb2phy_otg_port_init()
1287 rport->state = OTG_STATE_UNDEFINED; in rockchip_usb2phy_otg_port_init()
1295 rport->suspended = true; in rockchip_usb2phy_otg_port_init()
1296 rport->vbus_attached = false; in rockchip_usb2phy_otg_port_init()
1298 mutex_init(&rport->mutex); in rockchip_usb2phy_otg_port_init()
1300 rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1); in rockchip_usb2phy_otg_port_init()
1301 if (rport->mode == USB_DR_MODE_HOST || in rockchip_usb2phy_otg_port_init()
1302 rport->mode == USB_DR_MODE_UNKNOWN) { in rockchip_usb2phy_otg_port_init()
1307 INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work); in rockchip_usb2phy_otg_port_init()
1308 INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work); in rockchip_usb2phy_otg_port_init()
1312 dev_err(rphy->dev, "failed to init irq for host port\n"); in rockchip_usb2phy_otg_port_init()
1316 if (!IS_ERR(rphy->edev)) { in rockchip_usb2phy_otg_port_init()
1317 rport->event_nb.notifier_call = rockchip_otg_event; in rockchip_usb2phy_otg_port_init()
1319 ret = devm_extcon_register_notifier(rphy->dev, rphy->edev, in rockchip_usb2phy_otg_port_init()
1320 EXTCON_USB_HOST, &rport->event_nb); in rockchip_usb2phy_otg_port_init()
1322 dev_err(rphy->dev, "register USB HOST notifier failed\n"); in rockchip_usb2phy_otg_port_init()
1326 if (!of_property_read_bool(rphy->dev->of_node, "extcon")) { in rockchip_usb2phy_otg_port_init()
1328 id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id); in rockchip_usb2phy_otg_port_init()
1329 extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id); in rockchip_usb2phy_otg_port_init()
1339 struct device *dev = &pdev->dev; in rockchip_usb2phy_probe()
1340 struct device_node *np = dev->of_node; in rockchip_usb2phy_probe()
1350 return -ENOMEM; in rockchip_usb2phy_probe()
1352 if (!dev->parent || !dev->parent->of_node) { in rockchip_usb2phy_probe()
1353 rphy->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbgrf"); in rockchip_usb2phy_probe()
1354 if (IS_ERR(rphy->grf)) { in rockchip_usb2phy_probe()
1356 return PTR_ERR(rphy->grf); in rockchip_usb2phy_probe()
1359 rphy->grf = syscon_node_to_regmap(dev->parent->of_node); in rockchip_usb2phy_probe()
1360 if (IS_ERR(rphy->grf)) in rockchip_usb2phy_probe()
1361 return PTR_ERR(rphy->grf); in rockchip_usb2phy_probe()
1364 if (of_device_is_compatible(np, "rockchip,rv1108-usb2phy")) { in rockchip_usb2phy_probe()
1365 rphy->usbgrf = in rockchip_usb2phy_probe()
1366 syscon_regmap_lookup_by_phandle(dev->of_node, in rockchip_usb2phy_probe()
1368 if (IS_ERR(rphy->usbgrf)) in rockchip_usb2phy_probe()
1369 return PTR_ERR(rphy->usbgrf); in rockchip_usb2phy_probe()
1371 rphy->usbgrf = NULL; in rockchip_usb2phy_probe()
1376 return -EINVAL; in rockchip_usb2phy_probe()
1383 return -EINVAL; in rockchip_usb2phy_probe()
1387 rphy->dev = dev; in rockchip_usb2phy_probe()
1389 rphy->chg_state = USB_CHG_STATE_UNDEFINED; in rockchip_usb2phy_probe()
1390 rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; in rockchip_usb2phy_probe()
1391 rphy->irq = platform_get_irq_optional(pdev, 0); in rockchip_usb2phy_probe()
1395 return dev_err_probe(dev, -EINVAL, "phy configs are not assigned!\n"); in rockchip_usb2phy_probe()
1404 rphy->phy_cfg = &phy_cfgs[index]; in rockchip_usb2phy_probe()
1411 if (!rphy->phy_cfg) { in rockchip_usb2phy_probe()
1413 return -EINVAL; in rockchip_usb2phy_probe()
1416 rphy->phy_reset = devm_reset_control_get_optional(dev, "phy"); in rockchip_usb2phy_probe()
1417 if (IS_ERR(rphy->phy_reset)) in rockchip_usb2phy_probe()
1418 return PTR_ERR(rphy->phy_reset); in rockchip_usb2phy_probe()
1420 ret = devm_clk_bulk_get_all(dev, &rphy->clks); in rockchip_usb2phy_probe()
1421 if (ret == -EPROBE_DEFER) in rockchip_usb2phy_probe()
1422 return dev_err_probe(&pdev->dev, -EPROBE_DEFER, in rockchip_usb2phy_probe()
1426 rphy->num_clks = ret < 0 ? 0 : ret; in rockchip_usb2phy_probe()
1432 ret = clk_bulk_prepare_enable(rphy->num_clks, rphy->clks); in rockchip_usb2phy_probe()
1440 if (rphy->phy_cfg->phy_tuning) { in rockchip_usb2phy_probe()
1441 ret = rphy->phy_cfg->phy_tuning(rphy); in rockchip_usb2phy_probe()
1448 struct rockchip_usb2phy_port *rport = &rphy->ports[index]; in rockchip_usb2phy_probe()
1451 /* This driver aims to support both otg-port and host-port */ in rockchip_usb2phy_probe()
1452 if (!of_node_name_eq(child_np, "host-port") && in rockchip_usb2phy_probe()
1453 !of_node_name_eq(child_np, "otg-port")) in rockchip_usb2phy_probe()
1462 rport->phy = phy; in rockchip_usb2phy_probe()
1463 phy_set_drvdata(rport->phy, rport); in rockchip_usb2phy_probe()
1466 if (of_node_name_eq(child_np, "host-port")) { in rockchip_usb2phy_probe()
1478 if (++index >= rphy->phy_cfg->num_ports) { in rockchip_usb2phy_probe()
1486 if (rphy->irq > 0) { in rockchip_usb2phy_probe()
1487 ret = devm_request_threaded_irq(rphy->dev, rphy->irq, NULL, in rockchip_usb2phy_probe()
1493 dev_err_probe(rphy->dev, ret, "failed to request usb2phy irq handle\n"); in rockchip_usb2phy_probe()
1508 return regmap_write_bits(rphy->grf, 0x298, in rk3128_usb2phy_tuning()
1516 u32 reg = rphy->phy_cfg->reg; in rk3576_usb2phy_tuning()
1519 ret = regmap_write(rphy->grf, reg + 0x0010, GENMASK(29, 29) | 0x0000); in rk3576_usb2phy_tuning()
1529 ret |= regmap_write(rphy->grf, reg + 0x000c, GENMASK(27, 24) | 0x0900); in rk3576_usb2phy_tuning()
1531 /* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */ in rk3576_usb2phy_tuning()
1532 ret |= regmap_write(rphy->grf, reg + 0x0010, GENMASK(20, 19) | 0x0010); in rk3576_usb2phy_tuning()
1547 if (rphy->phy_cfg->reg == 0x0000 || rphy->phy_cfg->reg == 0x4000) { in rk3588_usb2phy_tuning()
1549 suspend_cfg |= 0x01; /* utmi_opmode = 2'b01 (no-driving) */ in rk3588_usb2phy_tuning()
1551 } else if (rphy->phy_cfg->reg == 0x8000 || rphy->phy_cfg->reg == 0xc000) { in rk3588_usb2phy_tuning()
1555 return -EINVAL; in rk3588_usb2phy_tuning()
1559 ret = regmap_write(rphy->grf, 0x0008, GENMASK(29, 29) | 0x0000); in rk3588_usb2phy_tuning()
1569 ret |= regmap_write(rphy->grf, 0x000c, GENMASK(20, 16) | suspend_cfg); in rk3588_usb2phy_tuning()
1572 ret |= regmap_write(rphy->grf, 0x0004, GENMASK(27, 24) | 0x0900); in rk3588_usb2phy_tuning()
1574 /* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */ in rk3588_usb2phy_tuning()
1575 ret |= regmap_write(rphy->grf, 0x0008, GENMASK(20, 19) | 0x0010); in rk3588_usb2phy_tuning()
1581 ret |= regmap_write(rphy->grf, 0x0010, GENMASK(17, 16) | 0x0003); in rk3588_usb2phy_tuning()
2206 { .compatible = "rockchip,px30-usb2phy", .data = &rk3328_phy_cfgs },
2207 { .compatible = "rockchip,rk3128-usb2phy", .data = &rk3128_phy_cfgs },
2208 { .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs },
2209 { .compatible = "rockchip,rk3308-usb2phy", .data = &rk3308_phy_cfgs },
2210 { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
2211 { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
2212 { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
2213 { .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs },
2214 { .compatible = "rockchip,rk3576-usb2phy", .data = &rk3576_phy_cfgs },
2215 { .compatible = "rockchip,rk3588-usb2phy", .data = &rk3588_phy_cfgs },
2216 { .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs },
2224 .name = "rockchip-usb2phy",
2230 MODULE_AUTHOR("Frank Wang <frank.wang@rock-chips.com>");