mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/
synced 2026-04-06 08:47:40 -04:00
drm/msm/dsi/phy: Add support for SM8750
Add support for DSI PHY v7.0 on Qualcomm SM8750 SoC which comes with an incompatible hardware interface change: ICODE_ACCUM_STATUS_LOW and ALOG_OBSV_BUS_STATUS_1 registers - their offsets were just switched. Currently these registers are not used in the driver, so the easiest is to document both but keep them commented out to avoid conflict. Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Patchwork: https://patchwork.freedesktop.org/patch/659616/ Link: https://lore.kernel.org/r/20250618-b4-sm8750-display-v7-6-a591c609743d@linaro.org Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
This commit is contained in:
committed by
Dmitry Baryshkov
parent
6b93840116
commit
1337d7ebfb
@@ -597,6 +597,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
|
||||
.data = &dsi_phy_4nm_8550_cfgs },
|
||||
{ .compatible = "qcom,sm8650-dsi-phy-4nm",
|
||||
.data = &dsi_phy_4nm_8650_cfgs },
|
||||
{ .compatible = "qcom,sm8750-dsi-phy-3nm",
|
||||
.data = &dsi_phy_3nm_8750_cfgs },
|
||||
#endif
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -63,6 +63,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8775p_cfgs;
|
||||
extern const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs;
|
||||
extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs;
|
||||
extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8650_cfgs;
|
||||
extern const struct msm_dsi_phy_cfg dsi_phy_3nm_8750_cfgs;
|
||||
|
||||
struct msm_dsi_dphy_timing {
|
||||
u32 clk_zero;
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
#define DSI_PHY_7NM_QUIRK_V4_3 BIT(3)
|
||||
/* Hardware is V5.2 */
|
||||
#define DSI_PHY_7NM_QUIRK_V5_2 BIT(4)
|
||||
/* Hardware is V7.0 */
|
||||
#define DSI_PHY_7NM_QUIRK_V7_0 BIT(5)
|
||||
|
||||
struct dsi_pll_config {
|
||||
bool enable_ssc;
|
||||
@@ -129,9 +131,30 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll, struct dsi_pll_config
|
||||
dec_multiple = div_u64(pll_freq * multiplier, divider);
|
||||
dec = div_u64_rem(dec_multiple, multiplier, &frac);
|
||||
|
||||
if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1)
|
||||
if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1) {
|
||||
config->pll_clock_inverters = 0x28;
|
||||
else if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) {
|
||||
} else if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) {
|
||||
if (pll_freq < 163000000ULL)
|
||||
config->pll_clock_inverters = 0xa0;
|
||||
else if (pll_freq < 175000000ULL)
|
||||
config->pll_clock_inverters = 0x20;
|
||||
else if (pll_freq < 325000000ULL)
|
||||
config->pll_clock_inverters = 0xa0;
|
||||
else if (pll_freq < 350000000ULL)
|
||||
config->pll_clock_inverters = 0x20;
|
||||
else if (pll_freq < 650000000ULL)
|
||||
config->pll_clock_inverters = 0xa0;
|
||||
else if (pll_freq < 700000000ULL)
|
||||
config->pll_clock_inverters = 0x20;
|
||||
else if (pll_freq < 1300000000ULL)
|
||||
config->pll_clock_inverters = 0xa0;
|
||||
else if (pll_freq < 2500000000ULL)
|
||||
config->pll_clock_inverters = 0x20;
|
||||
else if (pll_freq < 4000000000ULL)
|
||||
config->pll_clock_inverters = 0x00;
|
||||
else
|
||||
config->pll_clock_inverters = 0x40;
|
||||
} else if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) {
|
||||
if (pll_freq <= 1300000000ULL)
|
||||
config->pll_clock_inverters = 0xa0;
|
||||
else if (pll_freq <= 2500000000ULL)
|
||||
@@ -250,7 +273,8 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll)
|
||||
vco_config_1 = 0x01;
|
||||
}
|
||||
|
||||
if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) {
|
||||
if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) ||
|
||||
(pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) {
|
||||
if (pll->vco_current_rate < 1557000000ULL)
|
||||
vco_config_1 = 0x08;
|
||||
else
|
||||
@@ -620,6 +644,7 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
|
||||
static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy)
|
||||
{
|
||||
struct dsi_pll_7nm *pll_7nm = to_pll_7nm(phy->vco_hw);
|
||||
void __iomem *base = phy->base;
|
||||
u32 data = 0x0; /* internal PLL */
|
||||
|
||||
DBG("DSI PLL%d", pll_7nm->phy->id);
|
||||
@@ -629,6 +654,9 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy)
|
||||
break;
|
||||
case MSM_DSI_PHY_MASTER:
|
||||
pll_7nm->slave = pll_7nm_list[(pll_7nm->phy->id + 1) % DSI_MAX];
|
||||
/* v7.0: Enable ATB_EN0 and alternate clock output to external phy */
|
||||
if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)
|
||||
writel(0x07, base + REG_DSI_7nm_PHY_CMN_CTRL_5);
|
||||
break;
|
||||
case MSM_DSI_PHY_SLAVE:
|
||||
data = 0x1; /* external PLL */
|
||||
@@ -907,7 +935,8 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
|
||||
|
||||
/* Request for REFGEN READY */
|
||||
if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_3) ||
|
||||
(phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) {
|
||||
(phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) ||
|
||||
(phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) {
|
||||
writel(0x1, phy->base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10);
|
||||
udelay(500);
|
||||
}
|
||||
@@ -941,7 +970,20 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
|
||||
lane_ctrl0 = 0x1f;
|
||||
}
|
||||
|
||||
if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) {
|
||||
if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) {
|
||||
if (phy->cphy_mode) {
|
||||
/* TODO: different for second phy */
|
||||
vreg_ctrl_0 = 0x57;
|
||||
vreg_ctrl_1 = 0x41;
|
||||
glbl_rescode_top_ctrl = 0x3d;
|
||||
glbl_rescode_bot_ctrl = 0x38;
|
||||
} else {
|
||||
vreg_ctrl_0 = 0x56;
|
||||
vreg_ctrl_1 = 0x19;
|
||||
glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3c : 0x03;
|
||||
glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x38 : 0x3c;
|
||||
}
|
||||
} else if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) {
|
||||
if (phy->cphy_mode) {
|
||||
vreg_ctrl_0 = 0x45;
|
||||
vreg_ctrl_1 = 0x41;
|
||||
@@ -1003,6 +1045,7 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
|
||||
|
||||
/* program CMN_CTRL_4 for minor_ver 2 chipsets*/
|
||||
if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) ||
|
||||
(phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0) ||
|
||||
(readl(base + REG_DSI_7nm_PHY_CMN_REVISION_ID0) & (0xf0)) == 0x20)
|
||||
writel(0x04, base + REG_DSI_7nm_PHY_CMN_CTRL_4);
|
||||
|
||||
@@ -1117,7 +1160,8 @@ static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy)
|
||||
|
||||
/* Turn off REFGEN Vote */
|
||||
if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_3) ||
|
||||
(phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) {
|
||||
(phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) ||
|
||||
(phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) {
|
||||
writel(0x0, base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10);
|
||||
wmb();
|
||||
/* Delay to ensure HW removes vote before PHY shut down */
|
||||
@@ -1384,3 +1428,26 @@ const struct msm_dsi_phy_cfg dsi_phy_4nm_8650_cfgs = {
|
||||
.num_dsi_phy = 2,
|
||||
.quirks = DSI_PHY_7NM_QUIRK_V5_2,
|
||||
};
|
||||
|
||||
const struct msm_dsi_phy_cfg dsi_phy_3nm_8750_cfgs = {
|
||||
.has_phy_lane = true,
|
||||
.regulator_data = dsi_phy_7nm_98000uA_regulators,
|
||||
.num_regulators = ARRAY_SIZE(dsi_phy_7nm_98000uA_regulators),
|
||||
.ops = {
|
||||
.enable = dsi_7nm_phy_enable,
|
||||
.disable = dsi_7nm_phy_disable,
|
||||
.pll_init = dsi_pll_7nm_init,
|
||||
.save_pll_state = dsi_7nm_pll_save_state,
|
||||
.restore_pll_state = dsi_7nm_pll_restore_state,
|
||||
.set_continuous_clock = dsi_7nm_set_continuous_clock,
|
||||
},
|
||||
.min_pll_rate = 600000000UL,
|
||||
#ifdef CONFIG_64BIT
|
||||
.max_pll_rate = 5000000000UL,
|
||||
#else
|
||||
.max_pll_rate = ULONG_MAX,
|
||||
#endif
|
||||
.io_start = { 0xae95000, 0xae97000 },
|
||||
.num_dsi_phy = 2,
|
||||
.quirks = DSI_PHY_7NM_QUIRK_V7_0,
|
||||
};
|
||||
|
||||
@@ -26,6 +26,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
||||
<reg32 offset="0x00028" name="CTRL_1"/>
|
||||
<reg32 offset="0x0002c" name="CTRL_2"/>
|
||||
<reg32 offset="0x00030" name="CTRL_3"/>
|
||||
<reg32 offset="0x001b0" name="CTRL_5"/>
|
||||
<reg32 offset="0x00034" name="LANE_CFG0"/>
|
||||
<reg32 offset="0x00038" name="LANE_CFG1"/>
|
||||
<reg32 offset="0x0003c" name="PLL_CNTRL"/>
|
||||
@@ -191,11 +192,24 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
||||
<reg32 offset="0x01b0" name="COMMON_STATUS_ONE"/>
|
||||
<reg32 offset="0x01b4" name="COMMON_STATUS_TWO"/>
|
||||
<reg32 offset="0x01b8" name="BAND_SEL_CAL"/>
|
||||
<!--
|
||||
Starting with SM8750, offset moved from 0x01bc to 0x01cc, however
|
||||
we keep only one register map. That's not a problem, so far,
|
||||
because this register is not used. The register map should be split
|
||||
once it is going to be used. Comment out the code to prevent
|
||||
any misuse due to the change in the offset.
|
||||
<reg32 offset="0x01bc" name="ICODE_ACCUM_STATUS_LOW"/>
|
||||
<reg32 offset="0x01cc" name="ICODE_ACCUM_STATUS_LOW"/>
|
||||
-->
|
||||
<reg32 offset="0x01c0" name="ICODE_ACCUM_STATUS_HIGH"/>
|
||||
<reg32 offset="0x01c4" name="FD_OUT_LOW"/>
|
||||
<reg32 offset="0x01c8" name="FD_OUT_HIGH"/>
|
||||
<!--
|
||||
Starting with SM8750, offset moved from 0x01cc to 0x01bc, however
|
||||
we keep only one register map. See above comment.
|
||||
<reg32 offset="0x01cc" name="ALOG_OBSV_BUS_STATUS_1"/>
|
||||
<reg32 offset="0x01bc" name="ALOG_OBSV_BUS_STATUS_1"/>
|
||||
-->
|
||||
<reg32 offset="0x01d0" name="PLL_MISC_CONFIG"/>
|
||||
<reg32 offset="0x01d4" name="FLL_CONFIG"/>
|
||||
<reg32 offset="0x01d8" name="FLL_FREQ_ACQ_TIME"/>
|
||||
|
||||
Reference in New Issue
Block a user