Lines Matching +full:dp +full:- +full:phy
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Rockchip USBDP Combo PHY with Samsung IP block driver
10 #include <linux/clk-provider.h>
22 #include <linux/phy/phy.h>
30 #include <linux/phy/phy-rockchip-usbdp.h>
57 /* u2phy-grf */
61 /* usb-grf */
65 /* usbdpphy-grf */
71 /* vo-grf */
95 struct phy_configure_opts_dp *dp);
97 struct phy_configure_opts_dp *dp);
120 /* PHY status management */
127 bool hs; /* flag for high-speed */
129 /* utilized for DP */
141 /* PHY const config */
146 /* voltage swing 0, pre-emphasis 0->3 */
154 /* voltage swing 1, pre-emphasis 0->2 */
161 /* voltage swing 2, pre-emphasis 0->1 */
167 /* voltage swing 3, pre-emphasis 0 */
174 /* voltage swing 0, pre-emphasis 0->3 */
182 /* voltage swing 1, pre-emphasis 0->2 */
189 /* voltage swing 2, pre-emphasis 0->1 */
195 /* voltage swing 3, pre-emphasis 0 */
202 /* voltage swing 0, pre-emphasis 0->3 */
210 /* voltage swing 1, pre-emphasis 0->2 */
217 /* voltage swing 2, pre-emphasis 0->1 */
223 /* voltage swing 3, pre-emphasis 0 */
230 /* voltage swing 0, pre-emphasis 0->3 */
238 /* voltage swing 1, pre-emphasis 0->2 */
245 /* voltage swing 2, pre-emphasis 0->1 */
251 /* voltage swing 3, pre-emphasis 0 */
364 tmp = en ? reg->enable : reg->disable; in grfreg_write()
365 mask = GENMASK(reg->bitend, reg->bitstart); in grfreg_write()
366 val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); in grfreg_write()
368 return regmap_write(base, reg->offset, val); in grfreg_write()
375 udphy->num_clks = devm_clk_bulk_get_all(dev, &udphy->clks); in udphy_clk_init()
376 if (udphy->num_clks < 1) in udphy_clk_init()
377 return -ENODEV; in udphy_clk_init()
379 /* used for configure phy reference clock frequency */ in udphy_clk_init()
380 for (i = 0; i < udphy->num_clks; i++) { in udphy_clk_init()
381 if (!strncmp(udphy->clks[i].id, "refclk", 6)) { in udphy_clk_init()
382 udphy->refclk = udphy->clks[i].clk; in udphy_clk_init()
387 if (!udphy->refclk) in udphy_clk_init()
388 dev_warn(udphy->dev, "no refclk found\n"); in udphy_clk_init()
395 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in udphy_reset_init()
398 udphy->rsts = devm_kcalloc(dev, cfg->num_rsts, in udphy_reset_init()
399 sizeof(*udphy->rsts), GFP_KERNEL); in udphy_reset_init()
400 if (!udphy->rsts) in udphy_reset_init()
401 return -ENOMEM; in udphy_reset_init()
403 for (idx = 0; idx < cfg->num_rsts; idx++) { in udphy_reset_init()
405 const char *name = cfg->rst_list[idx]; in udphy_reset_init()
410 devm_kfree(dev, (void *)udphy->rsts); in udphy_reset_init()
414 udphy->rsts[idx] = rst; in udphy_reset_init()
429 return -EINVAL; in udphy_get_rst_idx()
434 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in udphy_reset_assert()
437 idx = udphy_get_rst_idx(cfg->rst_list, cfg->num_rsts, name); in udphy_reset_assert()
441 return reset_control_assert(udphy->rsts[idx]); in udphy_reset_assert()
446 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in udphy_reset_deassert()
449 idx = udphy_get_rst_idx(cfg->rst_list, cfg->num_rsts, name); in udphy_reset_deassert()
453 return reset_control_deassert(udphy->rsts[idx]); in udphy_reset_deassert()
458 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in udphy_u3_port_disable()
461 preg = udphy->id ? &cfg->grfcfg.usb3otg1_cfg : &cfg->grfcfg.usb3otg0_cfg; in udphy_u3_port_disable()
462 grfreg_write(udphy->usbgrf, preg, disable); in udphy_u3_port_disable()
467 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in udphy_usb_bvalid_enable()
469 grfreg_write(udphy->u2phygrf, &cfg->grfcfg.bvalid_phy_con, enable); in udphy_usb_bvalid_enable()
470 grfreg_write(udphy->u2phygrf, &cfg->grfcfg.bvalid_grf_con, enable); in udphy_usb_bvalid_enable()
474 * In usb/dp combo phy driver, here are 2 ways to mapping lanes.
476 * 1 Type-C Mapping table (DP_Alt_Mode V1.0b remove ABF pin mapping)
477 * ---------------------------------------------------------------------------
478 * Type-C Pin B11-B10 A2-A3 A11-A10 B2-B3
479 * PHY Pad ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx)
488 * ---------------------------------------------------------------------------
491 * if all 4 lane assignment for dp function, define rockchip,dp-lane-mux = <x x x x>;
493 * ---------------------------------------------------------------------------
494 * B11-B10 A2-A3 A11-A10 B2-B3
495 * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx)
498 * ---------------------------------------------------------------------------
499 * if 2 lane for dp function, 2 lane for usb function, define rockchip,dp-lane-mux = <x x>;
501 * ---------------------------------------------------------------------------
502 * B11-B10 A2-A3 A11-A10 B2-B3
503 * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx)
506 * ---------------------------------------------------------------------------
511 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in udphy_dplane_select()
513 if (cfg->dplane_select) in udphy_dplane_select()
514 return cfg->dplane_select(udphy); in udphy_dplane_select()
523 switch (udphy->mode) { in udphy_dplane_get()
542 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in udphy_dplane_enable()
545 if (cfg->dplane_enable) in udphy_dplane_enable()
546 ret = cfg->dplane_enable(udphy, dp_lanes); in udphy_dplane_enable()
553 if (udphy->flip) { in upphy_set_typec_default_mapping()
554 udphy->dp_lane_sel[0] = 0; in upphy_set_typec_default_mapping()
555 udphy->dp_lane_sel[1] = 1; in upphy_set_typec_default_mapping()
556 udphy->dp_lane_sel[2] = 3; in upphy_set_typec_default_mapping()
557 udphy->dp_lane_sel[3] = 2; in upphy_set_typec_default_mapping()
558 udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; in upphy_set_typec_default_mapping()
559 udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; in upphy_set_typec_default_mapping()
560 udphy->lane_mux_sel[2] = PHY_LANE_MUX_USB; in upphy_set_typec_default_mapping()
561 udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB; in upphy_set_typec_default_mapping()
562 udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_INVERT; in upphy_set_typec_default_mapping()
563 udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_INVERT; in upphy_set_typec_default_mapping()
564 gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 1); in upphy_set_typec_default_mapping()
565 gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0); in upphy_set_typec_default_mapping()
567 udphy->dp_lane_sel[0] = 2; in upphy_set_typec_default_mapping()
568 udphy->dp_lane_sel[1] = 3; in upphy_set_typec_default_mapping()
569 udphy->dp_lane_sel[2] = 1; in upphy_set_typec_default_mapping()
570 udphy->dp_lane_sel[3] = 0; in upphy_set_typec_default_mapping()
571 udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB; in upphy_set_typec_default_mapping()
572 udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB; in upphy_set_typec_default_mapping()
573 udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; in upphy_set_typec_default_mapping()
574 udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; in upphy_set_typec_default_mapping()
575 udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_NORMAL; in upphy_set_typec_default_mapping()
576 udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_NORMAL; in upphy_set_typec_default_mapping()
577 gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0); in upphy_set_typec_default_mapping()
578 gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 1); in upphy_set_typec_default_mapping()
581 udphy->mode = UDPHY_MODE_DP_USB; in upphy_set_typec_default_mapping()
591 mutex_lock(&udphy->mutex); in udphy_orien_sw_set()
594 gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0); in udphy_orien_sw_set()
595 gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0); in udphy_orien_sw_set()
601 udphy->flip = (orien == TYPEC_ORIENTATION_REVERSE) ? true : false; in udphy_orien_sw_set()
606 mutex_unlock(&udphy->mutex); in udphy_orien_sw_set()
615 sw_desc.fwnode = dev_fwnode(udphy->dev); in udphy_setup_orien_switch()
618 udphy->sw = typec_switch_register(udphy->dev, &sw_desc); in udphy_setup_orien_switch()
619 if (IS_ERR(udphy->sw)) { in udphy_setup_orien_switch()
620 dev_err(udphy->dev, "Error register typec orientation switch: %ld\n", in udphy_setup_orien_switch()
621 PTR_ERR(udphy->sw)); in udphy_setup_orien_switch()
622 return PTR_ERR(udphy->sw); in udphy_setup_orien_switch()
632 typec_switch_unregister(udphy->sw); in udphy_orien_switch_unregister()
637 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in udphy_setup()
640 ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks); in udphy_setup()
642 dev_err(udphy->dev, "failed to enable clk\n"); in udphy_setup()
646 if (cfg->combophy_init) { in udphy_setup()
647 ret = cfg->combophy_init(udphy); in udphy_setup()
649 dev_err(udphy->dev, "failed to init combophy\n"); in udphy_setup()
650 clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks); in udphy_setup()
660 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in udphy_disable()
663 clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks); in udphy_disable()
665 for (i = 0; i < cfg->num_rsts; i++) in udphy_disable()
666 reset_control_assert(udphy->rsts[i]); in udphy_disable()
673 struct device_node *np = dev->of_node; in udphy_parse_lane_mux_data()
677 prop = of_find_property(np, "rockchip,dp-lane-mux", &len); in udphy_parse_lane_mux_data()
679 dev_dbg(dev, "failed to find dp lane mux, following dp alt mode\n"); in udphy_parse_lane_mux_data()
680 udphy->mode = UDPHY_MODE_USB; in udphy_parse_lane_mux_data()
688 return -EINVAL; in udphy_parse_lane_mux_data()
691 ret = of_property_read_u32_array(np, "rockchip,dp-lane-mux", udphy->dp_lane_sel, num_lanes); in udphy_parse_lane_mux_data()
693 dev_err(dev, "get dp lane mux failed\n"); in udphy_parse_lane_mux_data()
694 return -EINVAL; in udphy_parse_lane_mux_data()
700 if (udphy->dp_lane_sel[i] > 3) { in udphy_parse_lane_mux_data()
702 return -EINVAL; in udphy_parse_lane_mux_data()
705 udphy->lane_mux_sel[udphy->dp_lane_sel[i]] = PHY_LANE_MUX_DP; in udphy_parse_lane_mux_data()
708 if (udphy->dp_lane_sel[i] == udphy->dp_lane_sel[j]) { in udphy_parse_lane_mux_data()
710 return -EINVAL; in udphy_parse_lane_mux_data()
715 udphy->mode = UDPHY_MODE_DP; in udphy_parse_lane_mux_data()
717 udphy->mode |= UDPHY_MODE_USB; in udphy_parse_lane_mux_data()
718 udphy->flip = udphy->lane_mux_sel[0] == PHY_LANE_MUX_DP ? true : false; in udphy_parse_lane_mux_data()
726 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in udphy_get_initial_status()
730 ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks); in udphy_get_initial_status()
732 dev_err(udphy->dev, "failed to enable clk\n"); in udphy_get_initial_status()
736 for (i = 0; i < cfg->num_rsts; i++) in udphy_get_initial_status()
737 reset_control_deassert(udphy->rsts[i]); in udphy_get_initial_status()
739 regmap_read(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, &value); in udphy_get_initial_status()
741 udphy->status = UDPHY_MODE_DP; in udphy_get_initial_status()
750 struct device_node *np = dev->of_node; in udphy_parse_dt()
754 udphy->u2phygrf = syscon_regmap_lookup_by_phandle(np, "rockchip,u2phy-grf"); in udphy_parse_dt()
755 if (IS_ERR(udphy->u2phygrf)) { in udphy_parse_dt()
756 if (PTR_ERR(udphy->u2phygrf) == -ENODEV) { in udphy_parse_dt()
757 dev_warn(dev, "missing u2phy-grf dt node\n"); in udphy_parse_dt()
758 udphy->u2phygrf = NULL; in udphy_parse_dt()
760 return PTR_ERR(udphy->u2phygrf); in udphy_parse_dt()
764 udphy->udphygrf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbdpphy-grf"); in udphy_parse_dt()
765 if (IS_ERR(udphy->udphygrf)) { in udphy_parse_dt()
766 if (PTR_ERR(udphy->udphygrf) == -ENODEV) { in udphy_parse_dt()
767 dev_warn(dev, "missing usbdpphy-grf dt node\n"); in udphy_parse_dt()
768 udphy->udphygrf = NULL; in udphy_parse_dt()
770 return PTR_ERR(udphy->udphygrf); in udphy_parse_dt()
774 udphy->usbgrf = syscon_regmap_lookup_by_phandle(np, "rockchip,usb-grf"); in udphy_parse_dt()
775 if (IS_ERR(udphy->usbgrf)) { in udphy_parse_dt()
776 if (PTR_ERR(udphy->usbgrf) == -ENODEV) { in udphy_parse_dt()
777 dev_warn(dev, "missing usb-grf dt node\n"); in udphy_parse_dt()
778 udphy->usbgrf = NULL; in udphy_parse_dt()
780 return PTR_ERR(udphy->usbgrf); in udphy_parse_dt()
784 udphy->vogrf = syscon_regmap_lookup_by_phandle(np, "rockchip,vo-grf"); in udphy_parse_dt()
785 if (IS_ERR(udphy->vogrf)) { in udphy_parse_dt()
786 if (PTR_ERR(udphy->vogrf) == -ENODEV) { in udphy_parse_dt()
787 dev_warn(dev, "missing vo-grf dt node\n"); in udphy_parse_dt()
788 udphy->vogrf = NULL; in udphy_parse_dt()
790 return PTR_ERR(udphy->vogrf); in udphy_parse_dt()
798 udphy->sbu1_dc_gpio = devm_gpiod_get_optional(dev, "sbu1-dc", GPIOD_OUT_LOW); in udphy_parse_dt()
799 if (IS_ERR(udphy->sbu1_dc_gpio)) in udphy_parse_dt()
800 return PTR_ERR(udphy->sbu1_dc_gpio); in udphy_parse_dt()
802 udphy->sbu2_dc_gpio = devm_gpiod_get_optional(dev, "sbu2-dc", GPIOD_OUT_LOW); in udphy_parse_dt()
803 if (IS_ERR(udphy->sbu2_dc_gpio)) in udphy_parse_dt()
804 return PTR_ERR(udphy->sbu2_dc_gpio); in udphy_parse_dt()
806 if (device_property_present(dev, "maximum-speed")) { in udphy_parse_dt()
808 udphy->hs = maximum_speed <= USB_SPEED_HIGH ? true : false; in udphy_parse_dt()
826 if (!(udphy->mode & mode)) { in udphy_power_on()
827 dev_info(udphy->dev, "mode 0x%02x is not support\n", mode); in udphy_power_on()
831 if (udphy->status == UDPHY_MODE_NONE) { in udphy_power_on()
832 udphy->mode_change = false; in udphy_power_on()
837 if (udphy->mode & UDPHY_MODE_USB) in udphy_power_on()
839 } else if (udphy->mode_change) { in udphy_power_on()
840 udphy->mode_change = false; in udphy_power_on()
841 udphy->status = UDPHY_MODE_NONE; in udphy_power_on()
842 if (udphy->mode == UDPHY_MODE_DP) in udphy_power_on()
853 udphy->status |= mode; in udphy_power_on()
862 if (!(udphy->mode & mode)) { in udphy_power_off()
863 dev_info(udphy->dev, "mode 0x%02x is not support\n", mode); in udphy_power_off()
867 if (!udphy->status) in udphy_power_off()
870 udphy->status &= ~mode; in udphy_power_off()
872 if (udphy->status == UDPHY_MODE_NONE) { in udphy_power_off()
881 static int rockchip_dp_phy_power_on(struct phy *phy) in rockchip_dp_phy_power_on() argument
883 struct rockchip_udphy *udphy = phy_get_drvdata(phy); in rockchip_dp_phy_power_on()
886 mutex_lock(&udphy->mutex); in rockchip_dp_phy_power_on()
889 phy_set_bus_width(phy, dp_lanes); in rockchip_dp_phy_power_on()
902 mutex_unlock(&udphy->mutex); in rockchip_dp_phy_power_on()
904 * If data send by aux channel too fast after phy power on, in rockchip_dp_phy_power_on()
912 static int rockchip_dp_phy_power_off(struct phy *phy) in rockchip_dp_phy_power_off() argument
914 struct rockchip_udphy *udphy = phy_get_drvdata(phy); in rockchip_dp_phy_power_off()
917 mutex_lock(&udphy->mutex); in rockchip_dp_phy_power_off()
925 mutex_unlock(&udphy->mutex); in rockchip_dp_phy_power_off()
938 return -EINVAL; in rockchip_dp_phy_verify_link_rate()
945 struct phy_configure_opts_dp *dp) in rockchip_dp_phy_verify_config() argument
950 ret = rockchip_dp_phy_verify_link_rate(dp->link_rate); in rockchip_dp_phy_verify_config()
955 switch (dp->lanes) { in rockchip_dp_phy_verify_config()
962 return -EINVAL; in rockchip_dp_phy_verify_config()
966 * If changing voltages is required, check swing and pre-emphasis in rockchip_dp_phy_verify_config()
967 * levels, per-lane. in rockchip_dp_phy_verify_config()
969 if (dp->set_voltages) { in rockchip_dp_phy_verify_config()
971 for (i = 0; i < dp->lanes; i++) { in rockchip_dp_phy_verify_config()
972 if (dp->voltage[i] > 3 || dp->pre[i] > 3) in rockchip_dp_phy_verify_config()
973 return -EINVAL; in rockchip_dp_phy_verify_config()
976 * Sum of voltage swing and pre-emphasis levels cannot in rockchip_dp_phy_verify_config()
979 if (dp->voltage[i] + dp->pre[i] > 3) in rockchip_dp_phy_verify_config()
980 return -EINVAL; in rockchip_dp_phy_verify_config()
987 static int rockchip_dp_phy_configure(struct phy *phy, in rockchip_dp_phy_configure() argument
990 struct rockchip_udphy *udphy = phy_get_drvdata(phy); in rockchip_dp_phy_configure()
991 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in rockchip_dp_phy_configure()
994 ret = rockchip_dp_phy_verify_config(udphy, &opts->dp); in rockchip_dp_phy_configure()
998 if (opts->dp.set_rate && cfg->dp_phy_set_rate) { in rockchip_dp_phy_configure()
999 ret = cfg->dp_phy_set_rate(udphy, &opts->dp); in rockchip_dp_phy_configure()
1001 dev_err(udphy->dev, in rockchip_dp_phy_configure()
1007 if (opts->dp.set_voltages && cfg->dp_phy_set_voltages) { in rockchip_dp_phy_configure()
1008 ret = cfg->dp_phy_set_voltages(udphy, &opts->dp); in rockchip_dp_phy_configure()
1010 dev_err(udphy->dev, in rockchip_dp_phy_configure()
1026 static int rockchip_u3phy_init(struct phy *phy) in rockchip_u3phy_init() argument
1028 struct rockchip_udphy *udphy = phy_get_drvdata(phy); in rockchip_u3phy_init()
1031 mutex_lock(&udphy->mutex); in rockchip_u3phy_init()
1032 /* DP only or high-speed, disable U3 port */ in rockchip_u3phy_init()
1033 if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs) { in rockchip_u3phy_init()
1041 mutex_unlock(&udphy->mutex); in rockchip_u3phy_init()
1045 static int rockchip_u3phy_exit(struct phy *phy) in rockchip_u3phy_exit() argument
1047 struct rockchip_udphy *udphy = phy_get_drvdata(phy); in rockchip_u3phy_exit()
1050 mutex_lock(&udphy->mutex); in rockchip_u3phy_exit()
1051 /* DP only or high-speed */ in rockchip_u3phy_exit()
1052 if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs) in rockchip_u3phy_exit()
1058 mutex_unlock(&udphy->mutex); in rockchip_u3phy_exit()
1072 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in usbdp_typec_mux_set()
1075 mutex_lock(&udphy->mutex); in usbdp_typec_mux_set()
1077 switch (state->mode) { in usbdp_typec_mux_set()
1081 udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; in usbdp_typec_mux_set()
1082 udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; in usbdp_typec_mux_set()
1083 udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; in usbdp_typec_mux_set()
1084 udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; in usbdp_typec_mux_set()
1090 if (udphy->flip) { in usbdp_typec_mux_set()
1091 udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; in usbdp_typec_mux_set()
1092 udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; in usbdp_typec_mux_set()
1093 udphy->lane_mux_sel[2] = PHY_LANE_MUX_USB; in usbdp_typec_mux_set()
1094 udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB; in usbdp_typec_mux_set()
1096 udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB; in usbdp_typec_mux_set()
1097 udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB; in usbdp_typec_mux_set()
1098 udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; in usbdp_typec_mux_set()
1099 udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; in usbdp_typec_mux_set()
1105 if (state->alt && state->alt->svid == USB_TYPEC_DP_SID) { in usbdp_typec_mux_set()
1106 struct typec_displayport_data *data = state->data; in usbdp_typec_mux_set()
1109 if (cfg->hpd_event_trigger) in usbdp_typec_mux_set()
1110 cfg->hpd_event_trigger(udphy, false); in usbdp_typec_mux_set()
1111 } else if (data->status & DP_STATUS_IRQ_HPD) { in usbdp_typec_mux_set()
1112 if (cfg->hpd_event_trigger) { in usbdp_typec_mux_set()
1113 cfg->hpd_event_trigger(udphy, false); in usbdp_typec_mux_set()
1115 cfg->hpd_event_trigger(udphy, true); in usbdp_typec_mux_set()
1117 } else if (data->status & DP_STATUS_HPD_STATE) { in usbdp_typec_mux_set()
1118 if (udphy->mode != mode) { in usbdp_typec_mux_set()
1119 udphy->mode = mode; in usbdp_typec_mux_set()
1120 udphy->mode_change = true; in usbdp_typec_mux_set()
1122 if (cfg->hpd_event_trigger) in usbdp_typec_mux_set()
1123 cfg->hpd_event_trigger(udphy, true); in usbdp_typec_mux_set()
1125 if (cfg->hpd_event_trigger) in usbdp_typec_mux_set()
1126 cfg->hpd_event_trigger(udphy, false); in usbdp_typec_mux_set()
1130 mutex_unlock(&udphy->mutex); in usbdp_typec_mux_set()
1139 mux_desc.fwnode = dev_fwnode(udphy->dev); in udphy_setup_typec_mux()
1142 udphy->mux = typec_mux_register(udphy->dev, &mux_desc); in udphy_setup_typec_mux()
1143 if (IS_ERR(udphy->mux)) { in udphy_setup_typec_mux()
1144 dev_err(udphy->dev, "Error register typec mux: %ld\n", in udphy_setup_typec_mux()
1145 PTR_ERR(udphy->mux)); in udphy_setup_typec_mux()
1146 return PTR_ERR(udphy->mux); in udphy_setup_typec_mux()
1156 typec_mux_unregister(udphy->mux); in udphy_typec_mux_unregister()
1164 ret = of_property_read_u32(np, "max-link-rate", &max_link_rate); in udphy_dp_get_max_link_rate()
1170 dev_warn(udphy->dev, "invalid max-link-rate value:%d\n", max_link_rate); in udphy_dp_get_max_link_rate()
1187 struct device *dev = &pdev->dev; in rockchip_udphy_probe()
1188 struct device_node *np = dev->of_node; in rockchip_udphy_probe()
1199 return -ENOMEM; in rockchip_udphy_probe()
1201 id = of_alias_get_id(dev->of_node, "usbdp"); in rockchip_udphy_probe()
1204 udphy->id = id; in rockchip_udphy_probe()
1209 return -EINVAL; in rockchip_udphy_probe()
1212 udphy->cfgs = phy_cfgs; in rockchip_udphy_probe()
1219 udphy->pma_regmap = devm_regmap_init_mmio(dev, base + UDPHY_PMA, in rockchip_udphy_probe()
1221 if (IS_ERR(udphy->pma_regmap)) in rockchip_udphy_probe()
1222 return PTR_ERR(udphy->pma_regmap); in rockchip_udphy_probe()
1232 mutex_init(&udphy->mutex); in rockchip_udphy_probe()
1233 udphy->dev = dev; in rockchip_udphy_probe()
1236 if (device_property_present(dev, "orientation-switch")) { in rockchip_udphy_probe()
1257 struct phy *phy; in rockchip_udphy_probe() local
1259 if (of_node_name_eq(child_np, "dp-port")) { in rockchip_udphy_probe()
1260 phy = devm_phy_create(dev, child_np, &rockchip_dp_phy_ops); in rockchip_udphy_probe()
1261 if (IS_ERR(phy)) { in rockchip_udphy_probe()
1262 dev_err(dev, "failed to create dp phy: %pOFn\n", child_np); in rockchip_udphy_probe()
1266 phy_set_bus_width(phy, udphy_dplane_get(udphy)); in rockchip_udphy_probe()
1267 phy->attrs.max_link_rate = udphy_dp_get_max_link_rate(udphy, child_np); in rockchip_udphy_probe()
1268 } else if (of_node_name_eq(child_np, "u3-port")) { in rockchip_udphy_probe()
1269 phy = devm_phy_create(dev, child_np, &rockchip_u3phy_ops); in rockchip_udphy_probe()
1270 if (IS_ERR(phy)) { in rockchip_udphy_probe()
1271 dev_err(dev, "failed to create usb phy: %pOFn\n", child_np); in rockchip_udphy_probe()
1277 phy_set_drvdata(phy, udphy); in rockchip_udphy_probe()
1282 dev_err(dev, "failed to register phy provider\n"); in rockchip_udphy_probe()
1298 /* configure phy reference clock */ in rk3588_udphy_refclk_set()
1299 rate = clk_get_rate(udphy->refclk); in rk3588_udphy_refclk_set()
1300 dev_dbg(udphy->dev, "refclk freq %ld\n", rate); in rk3588_udphy_refclk_set()
1304 ret = regmap_multi_reg_write(udphy->pma_regmap, rk3588_udphy_24m_refclk_cfg, in rk3588_udphy_refclk_set()
1311 ret = regmap_multi_reg_write(udphy->pma_regmap, rk3588_udphy_26m_refclk_cfg, in rk3588_udphy_refclk_set()
1317 dev_err(udphy->dev, "unsupported refclk freq %ld\n", rate); in rk3588_udphy_refclk_set()
1318 return -EINVAL; in rk3588_udphy_refclk_set()
1330 if (udphy->mode & UDPHY_MODE_USB) { in rk3588_udphy_status_check()
1331 ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_LCPLL_DONE_OFFSET, in rk3588_udphy_status_check()
1335 dev_err(udphy->dev, "cmn ana lcpll lock timeout\n"); in rk3588_udphy_status_check()
1340 if (udphy->mode & UDPHY_MODE_USB) { in rk3588_udphy_status_check()
1341 if (!udphy->flip) { in rk3588_udphy_status_check()
1342 ret = regmap_read_poll_timeout(udphy->pma_regmap, in rk3588_udphy_status_check()
1347 dev_notice(udphy->dev, "trsv ln0 mon rx cdr lock timeout\n"); in rk3588_udphy_status_check()
1349 ret = regmap_read_poll_timeout(udphy->pma_regmap, in rk3588_udphy_status_check()
1354 dev_notice(udphy->dev, "trsv ln2 mon rx cdr lock timeout\n"); in rk3588_udphy_status_check()
1363 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in rk3588_udphy_init()
1367 if (udphy->mode & UDPHY_MODE_USB) in rk3588_udphy_init()
1368 grfreg_write(udphy->udphygrf, &cfg->grfcfg.rx_lfps, true); in rk3588_udphy_init()
1371 grfreg_write(udphy->udphygrf, &cfg->grfcfg.low_pwrn, true); in rk3588_udphy_init()
1376 /* Step 2: set init sequence and phy refclk */ in rk3588_udphy_init()
1377 ret = regmap_multi_reg_write(udphy->pma_regmap, rk3588_udphy_init_sequence, in rk3588_udphy_init()
1380 dev_err(udphy->dev, "init sequence set error %d\n", ret); in rk3588_udphy_init()
1386 dev_err(udphy->dev, "refclk set error %d\n", ret); in rk3588_udphy_init()
1391 regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, in rk3588_udphy_init()
1393 FIELD_PREP(CMN_DP_LANE_MUX_N(3), udphy->lane_mux_sel[3]) | in rk3588_udphy_init()
1394 FIELD_PREP(CMN_DP_LANE_MUX_N(2), udphy->lane_mux_sel[2]) | in rk3588_udphy_init()
1395 FIELD_PREP(CMN_DP_LANE_MUX_N(1), udphy->lane_mux_sel[1]) | in rk3588_udphy_init()
1396 FIELD_PREP(CMN_DP_LANE_MUX_N(0), udphy->lane_mux_sel[0]) | in rk3588_udphy_init()
1400 if (udphy->mode & UDPHY_MODE_USB) in rk3588_udphy_init()
1403 if (udphy->mode & UDPHY_MODE_DP) { in rk3588_udphy_init()
1404 regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, in rk3588_udphy_init()
1412 if (udphy->mode & UDPHY_MODE_USB) { in rk3588_udphy_init()
1437 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in rk3588_udphy_hpd_event_trigger()
1439 udphy->dp_sink_hpd_sel = true; in rk3588_udphy_hpd_event_trigger()
1440 udphy->dp_sink_hpd_cfg = hpd; in rk3588_udphy_hpd_event_trigger()
1442 grfreg_write(udphy->vogrf, &cfg->vogrfcfg[udphy->id].hpd_trigger, hpd); in rk3588_udphy_hpd_event_trigger()
1453 val |= BIT(udphy->dp_lane_sel[i]); in rk3588_udphy_dplane_enable()
1455 regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, CMN_DP_LANE_EN_ALL, in rk3588_udphy_dplane_enable()
1459 regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, in rk3588_udphy_dplane_enable()
1469 switch (udphy->mode) { in rk3588_udphy_dplane_select()
1471 value |= 2 << udphy->dp_lane_sel[2] * 2; in rk3588_udphy_dplane_select()
1472 value |= 3 << udphy->dp_lane_sel[3] * 2; in rk3588_udphy_dplane_select()
1475 value |= 0 << udphy->dp_lane_sel[0] * 2; in rk3588_udphy_dplane_select()
1476 value |= 1 << udphy->dp_lane_sel[1] * 2; in rk3588_udphy_dplane_select()
1484 regmap_write(udphy->vogrf, udphy->id ? RK3588_GRF_VO0_CON2 : RK3588_GRF_VO0_CON0, in rk3588_udphy_dplane_select()
1486 FIELD_PREP(DP_AUX_DIN_SEL, udphy->dp_aux_din_sel) | in rk3588_udphy_dplane_select()
1487 FIELD_PREP(DP_AUX_DOUT_SEL, udphy->dp_aux_dout_sel) | value); in rk3588_udphy_dplane_select()
1493 struct phy_configure_opts_dp *dp) in rk3588_dp_phy_set_rate() argument
1498 regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, in rk3588_dp_phy_set_rate()
1501 switch (dp->link_rate) { in rk3588_dp_phy_set_rate()
1503 udphy->bw = DP_BW_RBR; in rk3588_dp_phy_set_rate()
1506 udphy->bw = DP_BW_HBR; in rk3588_dp_phy_set_rate()
1509 udphy->bw = DP_BW_HBR2; in rk3588_dp_phy_set_rate()
1512 udphy->bw = DP_BW_HBR3; in rk3588_dp_phy_set_rate()
1515 return -EINVAL; in rk3588_dp_phy_set_rate()
1518 regmap_update_bits(udphy->pma_regmap, CMN_DP_LINK_OFFSET, CMN_DP_TX_LINK_BW, in rk3588_dp_phy_set_rate()
1519 FIELD_PREP(CMN_DP_TX_LINK_BW, udphy->bw)); in rk3588_dp_phy_set_rate()
1520 regmap_update_bits(udphy->pma_regmap, CMN_SSC_EN_OFFSET, CMN_ROPLL_SSC_EN, in rk3588_dp_phy_set_rate()
1521 FIELD_PREP(CMN_ROPLL_SSC_EN, dp->ssc)); in rk3588_dp_phy_set_rate()
1522 regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, CMN_DP_CMN_RSTN, in rk3588_dp_phy_set_rate()
1525 ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_ROPLL_DONE_OFFSET, val, in rk3588_dp_phy_set_rate()
1530 dev_err(udphy->dev, "ROPLL is not lock\n"); in rk3588_dp_phy_set_rate()
1542 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in rk3588_dp_phy_set_voltage()
1545 dp_ctrl = udphy->mux ? cfg->dp_tx_ctrl_cfg_typec[bw] : cfg->dp_tx_ctrl_cfg[bw]; in rk3588_dp_phy_set_voltage()
1547 regmap_write(udphy->pma_regmap, 0x0810 + offset, val); in rk3588_dp_phy_set_voltage()
1550 regmap_write(udphy->pma_regmap, 0x0814 + offset, val); in rk3588_dp_phy_set_voltage()
1553 regmap_write(udphy->pma_regmap, 0x0818 + offset, val); in rk3588_dp_phy_set_voltage()
1556 regmap_write(udphy->pma_regmap, 0x081c + offset, val); in rk3588_dp_phy_set_voltage()
1560 struct phy_configure_opts_dp *dp) in rk3588_dp_phy_set_voltages() argument
1564 for (i = 0; i < dp->lanes; i++) { in rk3588_dp_phy_set_voltages()
1565 lane = udphy->dp_lane_sel[i]; in rk3588_dp_phy_set_voltages()
1566 switch (dp->link_rate) { in rk3588_dp_phy_set_voltages()
1569 regmap_update_bits(udphy->pma_regmap, TRSV_ANA_TX_CLK_OFFSET_N(lane), in rk3588_dp_phy_set_voltages()
1572 udphy->lane_mux_sel[lane])); in rk3588_dp_phy_set_voltages()
1576 regmap_update_bits(udphy->pma_regmap, TRSV_ANA_TX_CLK_OFFSET_N(lane), in rk3588_dp_phy_set_voltages()
1582 rk3588_dp_phy_set_voltage(udphy, udphy->bw, dp->voltage[i], dp->pre[i], lane); in rk3588_dp_phy_set_voltages()
1591 const struct rockchip_udphy_cfg *cfg = udphy->cfgs; in udphy_resume()
1593 if (udphy->dp_sink_hpd_sel) in udphy_resume()
1594 cfg->hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg); in udphy_resume()
1611 /* u2phy-grf */
1615 /* usb-grf */
1619 /* usbdpphy-grf */
1653 .compatible = "rockchip,rk3588-usbdp-phy",
1664 .name = "rockchip-usbdp-phy",
1672 MODULE_AUTHOR("Frank Wang <frank.wang@rock-chips.com>");
1673 MODULE_AUTHOR("Zhang Yubing <yubing.zhang@rock-chips.com>");
1674 MODULE_DESCRIPTION("Rockchip USBDP Combo PHY driver");