Lines Matching +full:usb +full:- +full:sdp

1 // SPDX-License-Identifier: GPL-2.0-or-later
9 #include <linux/clk-provider.h>
11 #include <linux/extcon-provider.h>
28 #include <linux/usb/of.h>
29 #include <linux/usb/otg.h>
49 * enum usb_chg_state - Different states involved in USB charger detection.
50 * @USB_CHG_STATE_UNDEFINED: USB charger is not connected or detection
55 * between SDP and DCP/CDP).
58 * @USB_CHG_STATE_DETECTED: USB charger type is determined.
88 * struct rockchip_chg_det_reg - usb charger detect registers
114 * struct rockchip_usb2phy_port_cfg - usb-phy port configuration.
150 * struct rockchip_usb2phy_cfg - usb-phy configuration.
151 * @reg: the address offset of grf for usb-phy config.
154 * @port_cfgs: usb-phy port configurations.
166 * struct rockchip_usb2phy_port - usb-phy port data.
174 * @otg_mux_irq: IRQ number which multiplex otg-id/otg-bvalid/linestate
175 * irqs to one irq in otg-port.
205 * struct rockchip_usb2phy - usb2.0 phy driver data.
208 * @usbgrf: USB General Register Files regmap.
212 * @chg_state: states involved in USB charger detection.
213 * @chg_type: USB charger types.
239 return rphy->usbgrf == NULL ? rphy->grf : rphy->usbgrf; in get_reg_base()
247 tmp = en ? reg->enable : reg->disable; in property_enable()
248 mask = GENMASK(reg->bitend, reg->bitstart); in property_enable()
249 val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); in property_enable()
251 return regmap_write(base, reg->offset, val); in property_enable()
259 unsigned int mask = GENMASK(reg->bitend, reg->bitstart); in property_enabled()
261 ret = regmap_read(base, reg->offset, &orig); in property_enabled()
265 tmp = (orig & mask) >> reg->bitstart; in property_enabled()
266 return tmp != reg->disable; in property_enabled()
277 if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) { in rockchip_usb2phy_clk480m_prepare()
278 ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true); in rockchip_usb2phy_clk480m_prepare()
296 property_enable(base, &rphy->phy_cfg->clkout_ctl, false); in rockchip_usb2phy_clk480m_unprepare()
305 return property_enabled(base, &rphy->phy_cfg->clkout_ctl); in rockchip_usb2phy_clk480m_prepared()
326 of_clk_del_provider(rphy->dev->of_node); in rockchip_usb2phy_clk480m_unregister()
327 clk_unregister(rphy->clk480m); in rockchip_usb2phy_clk480m_unregister()
333 struct device_node *node = rphy->dev->of_node; in rockchip_usb2phy_clk480m_register()
343 of_property_read_string(node, "clock-output-names", &init.name); in rockchip_usb2phy_clk480m_register()
345 if (rphy->clk) { in rockchip_usb2phy_clk480m_register()
346 clk_name = __clk_get_name(rphy->clk); in rockchip_usb2phy_clk480m_register()
354 rphy->clk480m_hw.init = &init; in rockchip_usb2phy_clk480m_register()
357 rphy->clk480m = clk_register(rphy->dev, &rphy->clk480m_hw); in rockchip_usb2phy_clk480m_register()
358 if (IS_ERR(rphy->clk480m)) { in rockchip_usb2phy_clk480m_register()
359 ret = PTR_ERR(rphy->clk480m); in rockchip_usb2phy_clk480m_register()
363 ret = of_clk_add_provider(node, of_clk_src_simple_get, rphy->clk480m); in rockchip_usb2phy_clk480m_register()
367 return devm_add_action_or_reset(rphy->dev, rockchip_usb2phy_clk480m_unregister, rphy); in rockchip_usb2phy_clk480m_register()
370 clk_unregister(rphy->clk480m); in rockchip_usb2phy_clk480m_register()
378 struct device_node *node = rphy->dev->of_node; in rockchip_usb2phy_extcon_register()
382 edev = extcon_get_edev_by_phandle(rphy->dev, 0); in rockchip_usb2phy_extcon_register()
384 if (PTR_ERR(edev) != -EPROBE_DEFER) in rockchip_usb2phy_extcon_register()
385 dev_err(rphy->dev, "Invalid or missing extcon\n"); in rockchip_usb2phy_extcon_register()
390 edev = devm_extcon_dev_allocate(rphy->dev, in rockchip_usb2phy_extcon_register()
394 return -ENOMEM; in rockchip_usb2phy_extcon_register()
396 ret = devm_extcon_dev_register(rphy->dev, edev); in rockchip_usb2phy_extcon_register()
398 dev_err(rphy->dev, "failed to register extcon device\n"); in rockchip_usb2phy_extcon_register()
403 rphy->edev = edev; in rockchip_usb2phy_extcon_register()
411 struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); in rockchip_usb2phy_init()
414 mutex_lock(&rport->mutex); in rockchip_usb2phy_init()
416 if (rport->port_id == USB2PHY_PORT_OTG) { in rockchip_usb2phy_init()
417 if (rport->mode != USB_DR_MODE_HOST && in rockchip_usb2phy_init()
418 rport->mode != USB_DR_MODE_UNKNOWN) { in rockchip_usb2phy_init()
420 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
421 &rport->port_cfg->bvalid_det_clr, in rockchip_usb2phy_init()
426 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
427 &rport->port_cfg->bvalid_det_en, in rockchip_usb2phy_init()
433 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
434 &rport->port_cfg->id_det_clr, in rockchip_usb2phy_init()
439 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
440 &rport->port_cfg->id_det_en, in rockchip_usb2phy_init()
445 schedule_delayed_work(&rport->otg_sm_work, in rockchip_usb2phy_init()
449 dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode); in rockchip_usb2phy_init()
451 } else if (rport->port_id == USB2PHY_PORT_HOST) { in rockchip_usb2phy_init()
453 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
454 &rport->port_cfg->ls_det_clr, true); in rockchip_usb2phy_init()
458 ret = property_enable(rphy->grf, in rockchip_usb2phy_init()
459 &rport->port_cfg->ls_det_en, true); in rockchip_usb2phy_init()
463 schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY); in rockchip_usb2phy_init()
467 mutex_unlock(&rport->mutex); in rockchip_usb2phy_init()
474 struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); in rockchip_usb2phy_power_on()
478 dev_dbg(&rport->phy->dev, "port power on\n"); in rockchip_usb2phy_power_on()
480 if (!rport->suspended) in rockchip_usb2phy_power_on()
483 ret = clk_prepare_enable(rphy->clk480m); in rockchip_usb2phy_power_on()
487 ret = property_enable(base, &rport->port_cfg->phy_sus, false); in rockchip_usb2phy_power_on()
494 rport->suspended = false; in rockchip_usb2phy_power_on()
501 struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); in rockchip_usb2phy_power_off()
505 dev_dbg(&rport->phy->dev, "port power off\n"); in rockchip_usb2phy_power_off()
507 if (rport->suspended) in rockchip_usb2phy_power_off()
510 ret = property_enable(base, &rport->port_cfg->phy_sus, true); in rockchip_usb2phy_power_off()
514 rport->suspended = true; in rockchip_usb2phy_power_off()
515 clk_disable_unprepare(rphy->clk480m); in rockchip_usb2phy_power_off()
524 if (rport->port_id == USB2PHY_PORT_OTG && in rockchip_usb2phy_exit()
525 rport->mode != USB_DR_MODE_HOST && in rockchip_usb2phy_exit()
526 rport->mode != USB_DR_MODE_UNKNOWN) { in rockchip_usb2phy_exit()
527 cancel_delayed_work_sync(&rport->otg_sm_work); in rockchip_usb2phy_exit()
528 cancel_delayed_work_sync(&rport->chg_work); in rockchip_usb2phy_exit()
529 } else if (rport->port_id == USB2PHY_PORT_HOST) in rockchip_usb2phy_exit()
530 cancel_delayed_work_sync(&rport->sm_work); in rockchip_usb2phy_exit()
548 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_otg_sm_work()
553 vbus_attach = property_enabled(rphy->grf, in rockchip_usb2phy_otg_sm_work()
554 &rport->port_cfg->utmi_bvalid); in rockchip_usb2phy_otg_sm_work()
559 dev_dbg(&rport->phy->dev, "%s otg sm work\n", in rockchip_usb2phy_otg_sm_work()
560 usb_otg_state_string(rport->state)); in rockchip_usb2phy_otg_sm_work()
562 switch (rport->state) { in rockchip_usb2phy_otg_sm_work()
564 rport->state = OTG_STATE_B_IDLE; in rockchip_usb2phy_otg_sm_work()
566 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
569 if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) > 0) { in rockchip_usb2phy_otg_sm_work()
570 dev_dbg(&rport->phy->dev, "usb otg host connect\n"); in rockchip_usb2phy_otg_sm_work()
571 rport->state = OTG_STATE_A_HOST; in rockchip_usb2phy_otg_sm_work()
572 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_otg_sm_work()
575 dev_dbg(&rport->phy->dev, "vbus_attach\n"); in rockchip_usb2phy_otg_sm_work()
576 switch (rphy->chg_state) { in rockchip_usb2phy_otg_sm_work()
578 schedule_delayed_work(&rport->chg_work, 0); in rockchip_usb2phy_otg_sm_work()
581 switch (rphy->chg_type) { in rockchip_usb2phy_otg_sm_work()
583 dev_dbg(&rport->phy->dev, "sdp cable is connected\n"); in rockchip_usb2phy_otg_sm_work()
584 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_otg_sm_work()
585 rport->state = OTG_STATE_B_PERIPHERAL; in rockchip_usb2phy_otg_sm_work()
591 dev_dbg(&rport->phy->dev, "dcp cable is connected\n"); in rockchip_usb2phy_otg_sm_work()
592 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
598 dev_dbg(&rport->phy->dev, "cdp cable is connected\n"); in rockchip_usb2phy_otg_sm_work()
599 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_otg_sm_work()
600 rport->state = OTG_STATE_B_PERIPHERAL; in rockchip_usb2phy_otg_sm_work()
614 rphy->chg_state = USB_CHG_STATE_UNDEFINED; in rockchip_usb2phy_otg_sm_work()
615 rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; in rockchip_usb2phy_otg_sm_work()
618 if (rport->vbus_attached != vbus_attach) { in rockchip_usb2phy_otg_sm_work()
619 rport->vbus_attached = vbus_attach; in rockchip_usb2phy_otg_sm_work()
621 if (notify_charger && rphy->edev) { in rockchip_usb2phy_otg_sm_work()
622 extcon_set_state_sync(rphy->edev, in rockchip_usb2phy_otg_sm_work()
625 extcon_set_state_sync(rphy->edev, in rockchip_usb2phy_otg_sm_work()
633 dev_dbg(&rport->phy->dev, "usb disconnect\n"); in rockchip_usb2phy_otg_sm_work()
634 rphy->chg_state = USB_CHG_STATE_UNDEFINED; in rockchip_usb2phy_otg_sm_work()
635 rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; in rockchip_usb2phy_otg_sm_work()
636 rport->state = OTG_STATE_B_IDLE; in rockchip_usb2phy_otg_sm_work()
638 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
643 if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) == 0) { in rockchip_usb2phy_otg_sm_work()
644 dev_dbg(&rport->phy->dev, "usb otg host disconnect\n"); in rockchip_usb2phy_otg_sm_work()
645 rport->state = OTG_STATE_B_IDLE; in rockchip_usb2phy_otg_sm_work()
646 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_otg_sm_work()
654 schedule_delayed_work(&rport->otg_sm_work, delay); in rockchip_usb2phy_otg_sm_work()
676 property_enable(base, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en); in rockchip_chg_enable_dcd()
677 property_enable(base, &rphy->phy_cfg->chg_det.idp_src_en, en); in rockchip_chg_enable_dcd()
685 property_enable(base, &rphy->phy_cfg->chg_det.vdp_src_en, en); in rockchip_chg_enable_primary_det()
686 property_enable(base, &rphy->phy_cfg->chg_det.idm_sink_en, en); in rockchip_chg_enable_primary_det()
694 property_enable(base, &rphy->phy_cfg->chg_det.vdm_src_en, en); in rockchip_chg_enable_secondary_det()
695 property_enable(base, &rphy->phy_cfg->chg_det.idp_sink_en, en); in rockchip_chg_enable_secondary_det()
706 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_chg_detect_work()
711 dev_dbg(&rport->phy->dev, "chg detection work state = %d\n", in rockchip_chg_detect_work()
712 rphy->chg_state); in rockchip_chg_detect_work()
713 switch (rphy->chg_state) { in rockchip_chg_detect_work()
715 if (!rport->suspended) in rockchip_chg_detect_work()
716 rockchip_usb2phy_power_off(rport->phy); in rockchip_chg_detect_work()
717 /* put the controller in non-driving mode */ in rockchip_chg_detect_work()
718 property_enable(base, &rphy->phy_cfg->chg_det.opmode, false); in rockchip_chg_detect_work()
721 rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; in rockchip_chg_detect_work()
722 rphy->dcd_retries = 0; in rockchip_chg_detect_work()
727 is_dcd = property_enabled(rphy->grf, in rockchip_chg_detect_work()
728 &rphy->phy_cfg->chg_det.dp_det); in rockchip_chg_detect_work()
729 tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES; in rockchip_chg_detect_work()
738 rphy->chg_state = USB_CHG_STATE_DCD_DONE; in rockchip_chg_detect_work()
745 vout = property_enabled(rphy->grf, in rockchip_chg_detect_work()
746 &rphy->phy_cfg->chg_det.cp_det); in rockchip_chg_detect_work()
752 rphy->chg_state = USB_CHG_STATE_PRIMARY_DONE; in rockchip_chg_detect_work()
754 if (rphy->dcd_retries == CHG_DCD_MAX_RETRIES) { in rockchip_chg_detect_work()
756 rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; in rockchip_chg_detect_work()
757 rphy->chg_state = USB_CHG_STATE_DETECTED; in rockchip_chg_detect_work()
760 rphy->chg_type = POWER_SUPPLY_TYPE_USB; in rockchip_chg_detect_work()
761 rphy->chg_state = USB_CHG_STATE_DETECTED; in rockchip_chg_detect_work()
767 vout = property_enabled(rphy->grf, in rockchip_chg_detect_work()
768 &rphy->phy_cfg->chg_det.dcp_det); in rockchip_chg_detect_work()
772 rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; in rockchip_chg_detect_work()
774 rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP; in rockchip_chg_detect_work()
777 rphy->chg_state = USB_CHG_STATE_DETECTED; in rockchip_chg_detect_work()
781 property_enable(base, &rphy->phy_cfg->chg_det.opmode, true); in rockchip_chg_detect_work()
782 rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); in rockchip_chg_detect_work()
783 dev_dbg(&rport->phy->dev, "charger = %s\n", in rockchip_chg_detect_work()
784 chg_to_string(rphy->chg_type)); in rockchip_chg_detect_work()
790 schedule_delayed_work(&rport->chg_work, delay); in rockchip_chg_detect_work()
794 * The function manage host-phy port state and suspend/resume phy port
810 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_sm_work()
811 unsigned int sh = rport->port_cfg->utmi_hstdet.bitend - in rockchip_usb2phy_sm_work()
812 rport->port_cfg->utmi_hstdet.bitstart + 1; in rockchip_usb2phy_sm_work()
817 mutex_lock(&rport->mutex); in rockchip_usb2phy_sm_work()
819 ret = regmap_read(rphy->grf, rport->port_cfg->utmi_ls.offset, &ul); in rockchip_usb2phy_sm_work()
823 ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd); in rockchip_usb2phy_sm_work()
827 uhd_mask = GENMASK(rport->port_cfg->utmi_hstdet.bitend, in rockchip_usb2phy_sm_work()
828 rport->port_cfg->utmi_hstdet.bitstart); in rockchip_usb2phy_sm_work()
829 ul_mask = GENMASK(rport->port_cfg->utmi_ls.bitend, in rockchip_usb2phy_sm_work()
830 rport->port_cfg->utmi_ls.bitstart); in rockchip_usb2phy_sm_work()
833 state = ((uhd & uhd_mask) >> rport->port_cfg->utmi_hstdet.bitstart) | in rockchip_usb2phy_sm_work()
834 (((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << sh); in rockchip_usb2phy_sm_work()
838 dev_dbg(&rport->phy->dev, "HS online\n"); in rockchip_usb2phy_sm_work()
846 * Plus, there are two cases, one is D- Line pull-up, and D+ in rockchip_usb2phy_sm_work()
847 * line pull-down, the state is 4; another is D+ line pull-up, in rockchip_usb2phy_sm_work()
848 * and D- line pull-down, the state is 2. in rockchip_usb2phy_sm_work()
850 if (!rport->suspended) { in rockchip_usb2phy_sm_work()
851 /* D- line pull-up, D+ line pull-down */ in rockchip_usb2phy_sm_work()
852 dev_dbg(&rport->phy->dev, "FS/LS online\n"); in rockchip_usb2phy_sm_work()
857 if (rport->suspended) { in rockchip_usb2phy_sm_work()
858 dev_dbg(&rport->phy->dev, "Connected\n"); in rockchip_usb2phy_sm_work()
859 rockchip_usb2phy_power_on(rport->phy); in rockchip_usb2phy_sm_work()
860 rport->suspended = false; in rockchip_usb2phy_sm_work()
862 /* D+ line pull-up, D- line pull-down */ in rockchip_usb2phy_sm_work()
863 dev_dbg(&rport->phy->dev, "FS/LS online\n"); in rockchip_usb2phy_sm_work()
867 if (!rport->suspended) { in rockchip_usb2phy_sm_work()
868 dev_dbg(&rport->phy->dev, "Disconnected\n"); in rockchip_usb2phy_sm_work()
869 rockchip_usb2phy_power_off(rport->phy); in rockchip_usb2phy_sm_work()
870 rport->suspended = true; in rockchip_usb2phy_sm_work()
875 * plug-in irq. in rockchip_usb2phy_sm_work()
877 property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true); in rockchip_usb2phy_sm_work()
878 property_enable(rphy->grf, &rport->port_cfg->ls_det_en, true); in rockchip_usb2phy_sm_work()
884 mutex_unlock(&rport->mutex); in rockchip_usb2phy_sm_work()
887 dev_dbg(&rport->phy->dev, "unknown phy state\n"); in rockchip_usb2phy_sm_work()
892 mutex_unlock(&rport->mutex); in rockchip_usb2phy_sm_work()
893 schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY); in rockchip_usb2phy_sm_work()
899 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_linestate_irq()
901 if (!property_enabled(rphy->grf, &rport->port_cfg->ls_det_st)) in rockchip_usb2phy_linestate_irq()
904 mutex_lock(&rport->mutex); in rockchip_usb2phy_linestate_irq()
907 property_enable(rphy->grf, &rport->port_cfg->ls_det_en, false); in rockchip_usb2phy_linestate_irq()
908 property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true); in rockchip_usb2phy_linestate_irq()
910 mutex_unlock(&rport->mutex); in rockchip_usb2phy_linestate_irq()
917 if (rport->suspended && rport->port_id == USB2PHY_PORT_HOST) in rockchip_usb2phy_linestate_irq()
918 rockchip_usb2phy_sm_work(&rport->sm_work.work); in rockchip_usb2phy_linestate_irq()
926 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_bvalid_irq()
928 if (!property_enabled(rphy->grf, &rport->port_cfg->bvalid_det_st)) in rockchip_usb2phy_bvalid_irq()
932 property_enable(rphy->grf, &rport->port_cfg->bvalid_det_clr, true); in rockchip_usb2phy_bvalid_irq()
934 rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); in rockchip_usb2phy_bvalid_irq()
942 struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); in rockchip_usb2phy_id_irq()
945 if (!property_enabled(rphy->grf, &rport->port_cfg->id_det_st)) in rockchip_usb2phy_id_irq()
949 property_enable(rphy->grf, &rport->port_cfg->id_det_clr, true); in rockchip_usb2phy_id_irq()
951 id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id); in rockchip_usb2phy_id_irq()
952 extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id); in rockchip_usb2phy_id_irq()
974 for (index = 0; index < rphy->phy_cfg->num_ports; index++) { in rockchip_usb2phy_irq()
975 rport = &rphy->ports[index]; in rockchip_usb2phy_irq()
976 if (!rport->phy) in rockchip_usb2phy_irq()
979 switch (rport->port_id) { in rockchip_usb2phy_irq()
981 if (rport->mode != USB_DR_MODE_HOST && in rockchip_usb2phy_irq()
982 rport->mode != USB_DR_MODE_UNKNOWN) in rockchip_usb2phy_irq()
1004 if (rphy->irq > 0) in rockchip_usb2phy_port_irq_init()
1007 switch (rport->port_id) { in rockchip_usb2phy_port_irq_init()
1009 rport->ls_irq = of_irq_get_byname(child_np, "linestate"); in rockchip_usb2phy_port_irq_init()
1010 if (rport->ls_irq < 0) { in rockchip_usb2phy_port_irq_init()
1011 dev_err(rphy->dev, "no linestate irq provided\n"); in rockchip_usb2phy_port_irq_init()
1012 return rport->ls_irq; in rockchip_usb2phy_port_irq_init()
1015 ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL, in rockchip_usb2phy_port_irq_init()
1020 dev_err(rphy->dev, "failed to request linestate irq handle\n"); in rockchip_usb2phy_port_irq_init()
1026 * Some SoCs use one interrupt with otg-id/otg-bvalid/linestate in rockchip_usb2phy_port_irq_init()
1027 * interrupts muxed together, so probe the otg-mux interrupt first, in rockchip_usb2phy_port_irq_init()
1030 rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux"); in rockchip_usb2phy_port_irq_init()
1031 if (rport->otg_mux_irq > 0) { in rockchip_usb2phy_port_irq_init()
1032 ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq, in rockchip_usb2phy_port_irq_init()
1039 dev_err(rphy->dev, in rockchip_usb2phy_port_irq_init()
1040 "failed to request otg-mux irq handle\n"); in rockchip_usb2phy_port_irq_init()
1044 rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid"); in rockchip_usb2phy_port_irq_init()
1045 if (rport->bvalid_irq < 0) { in rockchip_usb2phy_port_irq_init()
1046 dev_err(rphy->dev, "no vbus valid irq provided\n"); in rockchip_usb2phy_port_irq_init()
1047 ret = rport->bvalid_irq; in rockchip_usb2phy_port_irq_init()
1051 ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, in rockchip_usb2phy_port_irq_init()
1058 dev_err(rphy->dev, in rockchip_usb2phy_port_irq_init()
1059 "failed to request otg-bvalid irq handle\n"); in rockchip_usb2phy_port_irq_init()
1063 rport->id_irq = of_irq_get_byname(child_np, "otg-id"); in rockchip_usb2phy_port_irq_init()
1064 if (rport->id_irq < 0) { in rockchip_usb2phy_port_irq_init()
1065 dev_err(rphy->dev, "no otg-id irq provided\n"); in rockchip_usb2phy_port_irq_init()
1066 ret = rport->id_irq; in rockchip_usb2phy_port_irq_init()
1070 ret = devm_request_threaded_irq(rphy->dev, rport->id_irq, in rockchip_usb2phy_port_irq_init()
1077 dev_err(rphy->dev, in rockchip_usb2phy_port_irq_init()
1078 "failed to request otg-id irq handle\n"); in rockchip_usb2phy_port_irq_init()
1084 return -EINVAL; in rockchip_usb2phy_port_irq_init()
1096 rport->port_id = USB2PHY_PORT_HOST; in rockchip_usb2phy_host_port_init()
1097 rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_HOST]; in rockchip_usb2phy_host_port_init()
1098 rport->suspended = true; in rockchip_usb2phy_host_port_init()
1100 mutex_init(&rport->mutex); in rockchip_usb2phy_host_port_init()
1101 INIT_DELAYED_WORK(&rport->sm_work, rockchip_usb2phy_sm_work); in rockchip_usb2phy_host_port_init()
1105 dev_err(rphy->dev, "failed to setup host irq\n"); in rockchip_usb2phy_host_port_init()
1118 schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY); in rockchip_otg_event()
1129 rport->port_id = USB2PHY_PORT_OTG; in rockchip_usb2phy_otg_port_init()
1130 rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG]; in rockchip_usb2phy_otg_port_init()
1131 rport->state = OTG_STATE_UNDEFINED; in rockchip_usb2phy_otg_port_init()
1135 * put phy in suspend mode, it aims to enable usb in rockchip_usb2phy_otg_port_init()
1136 * phy and clock in power_on() called by usb controller in rockchip_usb2phy_otg_port_init()
1139 rport->suspended = true; in rockchip_usb2phy_otg_port_init()
1140 rport->vbus_attached = false; in rockchip_usb2phy_otg_port_init()
1142 mutex_init(&rport->mutex); in rockchip_usb2phy_otg_port_init()
1144 rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1); in rockchip_usb2phy_otg_port_init()
1145 if (rport->mode == USB_DR_MODE_HOST || in rockchip_usb2phy_otg_port_init()
1146 rport->mode == USB_DR_MODE_UNKNOWN) { in rockchip_usb2phy_otg_port_init()
1151 INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work); in rockchip_usb2phy_otg_port_init()
1152 INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work); in rockchip_usb2phy_otg_port_init()
1156 dev_err(rphy->dev, "failed to init irq for host port\n"); in rockchip_usb2phy_otg_port_init()
1160 if (!IS_ERR(rphy->edev)) { in rockchip_usb2phy_otg_port_init()
1161 rport->event_nb.notifier_call = rockchip_otg_event; in rockchip_usb2phy_otg_port_init()
1163 ret = devm_extcon_register_notifier(rphy->dev, rphy->edev, in rockchip_usb2phy_otg_port_init()
1164 EXTCON_USB_HOST, &rport->event_nb); in rockchip_usb2phy_otg_port_init()
1166 dev_err(rphy->dev, "register USB HOST notifier failed\n"); in rockchip_usb2phy_otg_port_init()
1170 if (!of_property_read_bool(rphy->dev->of_node, "extcon")) { in rockchip_usb2phy_otg_port_init()
1171 /* do initial sync of usb state */ in rockchip_usb2phy_otg_port_init()
1172 id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id); in rockchip_usb2phy_otg_port_init()
1173 extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id); in rockchip_usb2phy_otg_port_init()
1183 struct device *dev = &pdev->dev; in rockchip_usb2phy_probe()
1184 struct device_node *np = dev->of_node; in rockchip_usb2phy_probe()
1195 return -ENOMEM; in rockchip_usb2phy_probe()
1197 match = of_match_device(dev->driver->of_match_table, dev); in rockchip_usb2phy_probe()
1198 if (!match || !match->data) { in rockchip_usb2phy_probe()
1200 return -EINVAL; in rockchip_usb2phy_probe()
1203 if (!dev->parent || !dev->parent->of_node) { in rockchip_usb2phy_probe()
1204 rphy->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbgrf"); in rockchip_usb2phy_probe()
1205 if (IS_ERR(rphy->grf)) { in rockchip_usb2phy_probe()
1207 return PTR_ERR(rphy->grf); in rockchip_usb2phy_probe()
1212 rphy->grf = syscon_node_to_regmap(dev->parent->of_node); in rockchip_usb2phy_probe()
1213 if (IS_ERR(rphy->grf)) in rockchip_usb2phy_probe()
1214 return PTR_ERR(rphy->grf); in rockchip_usb2phy_probe()
1217 if (of_device_is_compatible(np, "rockchip,rv1108-usb2phy")) { in rockchip_usb2phy_probe()
1218 rphy->usbgrf = in rockchip_usb2phy_probe()
1219 syscon_regmap_lookup_by_phandle(dev->of_node, in rockchip_usb2phy_probe()
1221 if (IS_ERR(rphy->usbgrf)) in rockchip_usb2phy_probe()
1222 return PTR_ERR(rphy->usbgrf); in rockchip_usb2phy_probe()
1224 rphy->usbgrf = NULL; in rockchip_usb2phy_probe()
1230 return -EINVAL; in rockchip_usb2phy_probe()
1238 return -EINVAL; in rockchip_usb2phy_probe()
1242 rphy->dev = dev; in rockchip_usb2phy_probe()
1243 phy_cfgs = match->data; in rockchip_usb2phy_probe()
1244 rphy->chg_state = USB_CHG_STATE_UNDEFINED; in rockchip_usb2phy_probe()
1245 rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; in rockchip_usb2phy_probe()
1246 rphy->irq = platform_get_irq_optional(pdev, 0); in rockchip_usb2phy_probe()
1257 rphy->phy_cfg = &phy_cfgs[index]; in rockchip_usb2phy_probe()
1264 if (!rphy->phy_cfg) { in rockchip_usb2phy_probe()
1265 dev_err(dev, "no phy-config can be matched with %pOFn node\n", in rockchip_usb2phy_probe()
1267 return -EINVAL; in rockchip_usb2phy_probe()
1270 rphy->clk = of_clk_get_by_name(np, "phyclk"); in rockchip_usb2phy_probe()
1271 if (!IS_ERR(rphy->clk)) { in rockchip_usb2phy_probe()
1272 clk_prepare_enable(rphy->clk); in rockchip_usb2phy_probe()
1274 dev_info(&pdev->dev, "no phyclk specified\n"); in rockchip_usb2phy_probe()
1275 rphy->clk = NULL; in rockchip_usb2phy_probe()
1286 struct rockchip_usb2phy_port *rport = &rphy->ports[index]; in rockchip_usb2phy_probe()
1289 /* This driver aims to support both otg-port and host-port */ in rockchip_usb2phy_probe()
1290 if (!of_node_name_eq(child_np, "host-port") && in rockchip_usb2phy_probe()
1291 !of_node_name_eq(child_np, "otg-port")) in rockchip_usb2phy_probe()
1301 rport->phy = phy; in rockchip_usb2phy_probe()
1302 phy_set_drvdata(rport->phy, rport); in rockchip_usb2phy_probe()
1305 if (of_node_name_eq(child_np, "host-port")) { in rockchip_usb2phy_probe()
1319 if (++index >= rphy->phy_cfg->num_ports) { in rockchip_usb2phy_probe()
1327 if (rphy->irq > 0) { in rockchip_usb2phy_probe()
1328 ret = devm_request_threaded_irq(rphy->dev, rphy->irq, NULL, in rockchip_usb2phy_probe()
1334 dev_err(rphy->dev, in rockchip_usb2phy_probe()
1345 if (rphy->clk) { in rockchip_usb2phy_probe()
1346 clk_disable_unprepare(rphy->clk); in rockchip_usb2phy_probe()
1347 clk_put(rphy->clk); in rockchip_usb2phy_probe()
1708 { .compatible = "rockchip,px30-usb2phy", .data = &rk3328_phy_cfgs },
1709 { .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs },
1710 { .compatible = "rockchip,rk3308-usb2phy", .data = &rk3308_phy_cfgs },
1711 { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
1712 { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
1713 { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
1714 { .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs },
1715 { .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs },
1723 .name = "rockchip-usb2phy",
1729 MODULE_AUTHOR("Frank Wang <frank.wang@rock-chips.com>");