Lines Matching +full:syscon +full:- +full:phy +full:- +full:pll +full:- +full:refclk

1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd.
6 * Author: Algea Cao <algea.cao@rock-chips.com>
11 #include <linux/clk-provider.h>
13 #include <linux/mfd/syscon.h>
17 #include <linux/phy/phy.h>
278 /* PHY const config */
282 struct phy *phy; member
598 regmap_multi_reg_write((hdptx)->regmap, seq, ARRAY_SIZE(seq))
604 reset_control_assert(hdptx->rsts[RST_APB].rstc); in rk_hdptx_pre_power_up()
606 reset_control_deassert(hdptx->rsts[RST_APB].rstc); in rk_hdptx_pre_power_up()
608 reset_control_assert(hdptx->rsts[RST_LANE].rstc); in rk_hdptx_pre_power_up()
609 reset_control_assert(hdptx->rsts[RST_CMN].rstc); in rk_hdptx_pre_power_up()
610 reset_control_assert(hdptx->rsts[RST_INIT].rstc); in rk_hdptx_pre_power_up()
613 regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); in rk_hdptx_pre_power_up()
621 reset_control_deassert(hdptx->rsts[RST_LANE].rstc); in rk_hdptx_post_enable_lane()
625 regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); in rk_hdptx_post_enable_lane()
627 ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, val, in rk_hdptx_post_enable_lane()
632 dev_err(hdptx->dev, "Failed to get PHY lane lock: %d\n", ret); in rk_hdptx_post_enable_lane()
636 dev_dbg(hdptx->dev, "PHY lane locked\n"); in rk_hdptx_post_enable_lane()
648 regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); in rk_hdptx_post_enable_pll()
651 reset_control_deassert(hdptx->rsts[RST_INIT].rstc); in rk_hdptx_post_enable_pll()
655 regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); in rk_hdptx_post_enable_pll()
658 reset_control_deassert(hdptx->rsts[RST_CMN].rstc); in rk_hdptx_post_enable_pll()
660 ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, val, in rk_hdptx_post_enable_pll()
663 dev_err(hdptx->dev, "Failed to get PHY clk ready: %d\n", ret); in rk_hdptx_post_enable_pll()
667 dev_dbg(hdptx->dev, "PHY clk ready\n"); in rk_hdptx_post_enable_pll()
676 reset_control_assert(hdptx->rsts[RST_APB].rstc); in rk_hdptx_phy_disable()
678 reset_control_deassert(hdptx->rsts[RST_APB].rstc); in rk_hdptx_phy_disable()
680 regmap_write(hdptx->regmap, LANE_REG(0300), 0x82); in rk_hdptx_phy_disable()
681 regmap_write(hdptx->regmap, SB_REG(010f), 0xc1); in rk_hdptx_phy_disable()
682 regmap_write(hdptx->regmap, SB_REG(0110), 0x1); in rk_hdptx_phy_disable()
683 regmap_write(hdptx->regmap, LANE_REG(0301), 0x80); in rk_hdptx_phy_disable()
684 regmap_write(hdptx->regmap, LANE_REG(0401), 0x80); in rk_hdptx_phy_disable()
685 regmap_write(hdptx->regmap, LANE_REG(0501), 0x80); in rk_hdptx_phy_disable()
686 regmap_write(hdptx->regmap, LANE_REG(0601), 0x80); in rk_hdptx_phy_disable()
688 reset_control_assert(hdptx->rsts[RST_LANE].rstc); in rk_hdptx_phy_disable()
689 reset_control_assert(hdptx->rsts[RST_CMN].rstc); in rk_hdptx_phy_disable()
690 reset_control_assert(hdptx->rsts[RST_INIT].rstc); in rk_hdptx_phy_disable()
693 regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); in rk_hdptx_phy_disable()
707 for (sdiv = 16; sdiv >= 1; sdiv--) { in rk_hdptx_phy_clk_pll_calc()
720 if (fref * mdiv - fvco) { in rk_hdptx_phy_clk_pll_calc()
728 rational_best_approximation(fref * mdiv - fvco, in rk_hdptx_phy_clk_pll_calc()
734 rational_best_approximation(sdc * n - fref * mdiv, in rk_hdptx_phy_clk_pll_calc()
748 cfg->pms_mdiv = mdiv; in rk_hdptx_phy_clk_pll_calc()
749 cfg->pms_mdiv_afc = mdiv; in rk_hdptx_phy_clk_pll_calc()
750 cfg->pms_pdiv = 1; in rk_hdptx_phy_clk_pll_calc()
751 cfg->pms_refdiv = 1; in rk_hdptx_phy_clk_pll_calc()
752 cfg->pms_sdiv = sdiv - 1; in rk_hdptx_phy_clk_pll_calc()
754 cfg->sdm_en = k > 0 ? 1 : 0; in rk_hdptx_phy_clk_pll_calc()
755 if (cfg->sdm_en) { in rk_hdptx_phy_clk_pll_calc()
756 cfg->sdm_deno = lc; in rk_hdptx_phy_clk_pll_calc()
757 cfg->sdm_num_sign = 1; in rk_hdptx_phy_clk_pll_calc()
758 cfg->sdm_num = k; in rk_hdptx_phy_clk_pll_calc()
759 cfg->sdc_n = n - 3; in rk_hdptx_phy_clk_pll_calc()
760 cfg->sdc_num = k_sub; in rk_hdptx_phy_clk_pll_calc()
761 cfg->sdc_deno = lc_sub; in rk_hdptx_phy_clk_pll_calc()
775 hdptx->rate = rate * 100; in rk_hdptx_ropll_tmds_cmn_config()
787 dev_err(hdptx->dev, "%s cannot find pll cfg\n", __func__); in rk_hdptx_ropll_tmds_cmn_config()
788 return -EINVAL; in rk_hdptx_ropll_tmds_cmn_config()
792 dev_dbg(hdptx->dev, "mdiv=%u, sdiv=%u, sdm_en=%u, k_sign=%u, k=%u, lc=%u\n", in rk_hdptx_ropll_tmds_cmn_config()
793 cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en, in rk_hdptx_ropll_tmds_cmn_config()
794 cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno); in rk_hdptx_ropll_tmds_cmn_config()
801 regmap_write(hdptx->regmap, CMN_REG(0051), cfg->pms_mdiv); in rk_hdptx_ropll_tmds_cmn_config()
802 regmap_write(hdptx->regmap, CMN_REG(0055), cfg->pms_mdiv_afc); in rk_hdptx_ropll_tmds_cmn_config()
803 regmap_write(hdptx->regmap, CMN_REG(0059), in rk_hdptx_ropll_tmds_cmn_config()
804 (cfg->pms_pdiv << 4) | cfg->pms_refdiv); in rk_hdptx_ropll_tmds_cmn_config()
805 regmap_write(hdptx->regmap, CMN_REG(005a), cfg->pms_sdiv << 4); in rk_hdptx_ropll_tmds_cmn_config()
807 regmap_update_bits(hdptx->regmap, CMN_REG(005e), ROPLL_SDM_EN_MASK, in rk_hdptx_ropll_tmds_cmn_config()
808 FIELD_PREP(ROPLL_SDM_EN_MASK, cfg->sdm_en)); in rk_hdptx_ropll_tmds_cmn_config()
809 if (!cfg->sdm_en) in rk_hdptx_ropll_tmds_cmn_config()
810 regmap_update_bits(hdptx->regmap, CMN_REG(005e), 0xf, 0); in rk_hdptx_ropll_tmds_cmn_config()
812 regmap_update_bits(hdptx->regmap, CMN_REG(0064), ROPLL_SDM_NUM_SIGN_RBR_MASK, in rk_hdptx_ropll_tmds_cmn_config()
813 FIELD_PREP(ROPLL_SDM_NUM_SIGN_RBR_MASK, cfg->sdm_num_sign)); in rk_hdptx_ropll_tmds_cmn_config()
815 regmap_write(hdptx->regmap, CMN_REG(0060), cfg->sdm_deno); in rk_hdptx_ropll_tmds_cmn_config()
816 regmap_write(hdptx->regmap, CMN_REG(0065), cfg->sdm_num); in rk_hdptx_ropll_tmds_cmn_config()
818 regmap_update_bits(hdptx->regmap, CMN_REG(0069), ROPLL_SDC_N_RBR_MASK, in rk_hdptx_ropll_tmds_cmn_config()
819 FIELD_PREP(ROPLL_SDC_N_RBR_MASK, cfg->sdc_n)); in rk_hdptx_ropll_tmds_cmn_config()
821 regmap_write(hdptx->regmap, CMN_REG(006c), cfg->sdc_num); in rk_hdptx_ropll_tmds_cmn_config()
822 regmap_write(hdptx->regmap, CMN_REG(0070), cfg->sdc_deno); in rk_hdptx_ropll_tmds_cmn_config()
824 regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK, in rk_hdptx_ropll_tmds_cmn_config()
825 FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv)); in rk_hdptx_ropll_tmds_cmn_config()
827 regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN, in rk_hdptx_ropll_tmds_cmn_config()
838 regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06); in rk_hdptx_ropll_tmds_mode_config()
848 regmap_write(hdptx->regmap, LNTOP_REG(0206), 0x07); in rk_hdptx_ropll_tmds_mode_config()
849 regmap_write(hdptx->regmap, LNTOP_REG(0207), 0x0f); in rk_hdptx_ropll_tmds_mode_config()
863 if (atomic_inc_return(&hdptx->usage_count) > 1) in rk_hdptx_phy_consumer_get()
866 ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &status); in rk_hdptx_phy_consumer_get()
871 dev_warn(hdptx->dev, "PLL locked by unknown consumer!\n"); in rk_hdptx_phy_consumer_get()
882 atomic_dec(&hdptx->usage_count); in rk_hdptx_phy_consumer_get()
891 ret = atomic_dec_return(&hdptx->usage_count); in rk_hdptx_phy_consumer_put()
896 dev_warn(hdptx->dev, "Usage count underflow!\n"); in rk_hdptx_phy_consumer_put()
897 ret = -EINVAL; in rk_hdptx_phy_consumer_put()
899 ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &status); in rk_hdptx_phy_consumer_put()
909 atomic_inc(&hdptx->usage_count); in rk_hdptx_phy_consumer_put()
913 static int rk_hdptx_phy_power_on(struct phy *phy) in rk_hdptx_phy_power_on() argument
915 struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); in rk_hdptx_phy_power_on()
916 int bus_width = phy_get_bus_width(hdptx->phy); in rk_hdptx_phy_power_on()
922 * becomes available in the PHY API. in rk_hdptx_phy_power_on()
926 dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n", in rk_hdptx_phy_power_on()
940 static int rk_hdptx_phy_power_off(struct phy *phy) in rk_hdptx_phy_power_off() argument
942 struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); in rk_hdptx_phy_power_off()
962 return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate / 100); in rk_hdptx_phy_clk_prepare()
977 return hdptx->rate; in rk_hdptx_phy_clk_recalc_rate()
995 return -EINVAL; in rk_hdptx_phy_clk_round_rate()
1018 struct device *dev = hdptx->dev; in rk_hdptx_phy_clk_register()
1020 struct clk *refclk; in rk_hdptx_phy_clk_register() local
1023 refclk = devm_clk_get(dev, "ref"); in rk_hdptx_phy_clk_register()
1024 if (IS_ERR(refclk)) in rk_hdptx_phy_clk_register()
1025 return dev_err_probe(dev, PTR_ERR(refclk), in rk_hdptx_phy_clk_register()
1028 name = hdptx->phy_id > 0 ? "clk_hdmiphy_pixel1" : "clk_hdmiphy_pixel0"; in rk_hdptx_phy_clk_register()
1029 pname = __clk_get_name(refclk); in rk_hdptx_phy_clk_register()
1031 hdptx->hw.init = CLK_HW_INIT(name, pname, &hdptx_phy_clk_ops, in rk_hdptx_phy_clk_register()
1034 ret = devm_clk_hw_register(dev, &hdptx->hw); in rk_hdptx_phy_clk_register()
1038 ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &hdptx->hw); in rk_hdptx_phy_clk_register()
1049 clk_bulk_disable_unprepare(hdptx->nr_clks, hdptx->clks); in rk_hdptx_phy_runtime_suspend()
1059 ret = clk_bulk_prepare_enable(hdptx->nr_clks, hdptx->clks); in rk_hdptx_phy_runtime_resume()
1061 dev_err(hdptx->dev, "Failed to enable clocks: %d\n", ret); in rk_hdptx_phy_runtime_resume()
1069 struct device *dev = &pdev->dev; in rk_hdptx_phy_probe()
1077 return -ENOMEM; in rk_hdptx_phy_probe()
1079 hdptx->dev = dev; in rk_hdptx_phy_probe()
1086 hdptx->cfgs = device_get_match_data(dev); in rk_hdptx_phy_probe()
1087 if (!hdptx->cfgs) in rk_hdptx_phy_probe()
1088 return dev_err_probe(dev, -EINVAL, "missing match data\n"); in rk_hdptx_phy_probe()
1090 /* find the phy-id from the io address */ in rk_hdptx_phy_probe()
1091 hdptx->phy_id = -ENODEV; in rk_hdptx_phy_probe()
1092 for (id = 0; id < hdptx->cfgs->num_phys; id++) { in rk_hdptx_phy_probe()
1093 if (res->start == hdptx->cfgs->phy_ids[id]) { in rk_hdptx_phy_probe()
1094 hdptx->phy_id = id; in rk_hdptx_phy_probe()
1099 if (hdptx->phy_id < 0) in rk_hdptx_phy_probe()
1100 return dev_err_probe(dev, -ENODEV, "no matching device found\n"); in rk_hdptx_phy_probe()
1102 ret = devm_clk_bulk_get_all(dev, &hdptx->clks); in rk_hdptx_phy_probe()
1106 return dev_err_probe(dev, -EINVAL, "Missing clocks\n"); in rk_hdptx_phy_probe()
1108 hdptx->nr_clks = ret; in rk_hdptx_phy_probe()
1110 hdptx->regmap = devm_regmap_init_mmio(dev, regs, in rk_hdptx_phy_probe()
1112 if (IS_ERR(hdptx->regmap)) in rk_hdptx_phy_probe()
1113 return dev_err_probe(dev, PTR_ERR(hdptx->regmap), in rk_hdptx_phy_probe()
1116 hdptx->rsts[RST_APB].id = "apb"; in rk_hdptx_phy_probe()
1117 hdptx->rsts[RST_INIT].id = "init"; in rk_hdptx_phy_probe()
1118 hdptx->rsts[RST_CMN].id = "cmn"; in rk_hdptx_phy_probe()
1119 hdptx->rsts[RST_LANE].id = "lane"; in rk_hdptx_phy_probe()
1121 ret = devm_reset_control_bulk_get_exclusive(dev, RST_MAX, hdptx->rsts); in rk_hdptx_phy_probe()
1125 hdptx->grf = syscon_regmap_lookup_by_phandle(dev->of_node, in rk_hdptx_phy_probe()
1127 if (IS_ERR(hdptx->grf)) in rk_hdptx_phy_probe()
1128 return dev_err_probe(dev, PTR_ERR(hdptx->grf), in rk_hdptx_phy_probe()
1129 "Could not get GRF syscon\n"); in rk_hdptx_phy_probe()
1137 hdptx->phy = devm_phy_create(dev, NULL, &rk_hdptx_phy_ops); in rk_hdptx_phy_probe()
1138 if (IS_ERR(hdptx->phy)) in rk_hdptx_phy_probe()
1139 return dev_err_probe(dev, PTR_ERR(hdptx->phy), in rk_hdptx_phy_probe()
1140 "Failed to create HDMI PHY\n"); in rk_hdptx_phy_probe()
1142 phy_set_drvdata(hdptx->phy, hdptx); in rk_hdptx_phy_probe()
1143 phy_set_bus_width(hdptx->phy, 8); in rk_hdptx_phy_probe()
1148 "Failed to register PHY provider\n"); in rk_hdptx_phy_probe()
1150 reset_control_deassert(hdptx->rsts[RST_APB].rstc); in rk_hdptx_phy_probe()
1151 reset_control_deassert(hdptx->rsts[RST_CMN].rstc); in rk_hdptx_phy_probe()
1152 reset_control_deassert(hdptx->rsts[RST_INIT].rstc); in rk_hdptx_phy_probe()
1172 .compatible = "rockchip,rk3588-hdptx-phy",
1182 .name = "rockchip-hdptx-phy",
1189 MODULE_AUTHOR("Algea Cao <algea.cao@rock-chips.com>");
1191 MODULE_DESCRIPTION("Samsung HDMI/eDP Transmitter Combo PHY Driver");