drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver
PHY_CMN_CLK_CFG1 register is updated by the PHY driver and by a mux
clock from Common Clock Framework:
devm_clk_hw_register_mux_parent_hws(). There could be a path leading to
concurrent and conflicting updates between PHY driver and clock
framework, e.g. changing the mux and enabling PLL clocks.
Add dedicated spinlock to be sure all PHY_CMN_CLK_CFG1 updates are
synchronized.
While shuffling the code, define and use PHY_CMN_CLK_CFG1 bitfields to
make the code more readable and obvious.
Fixes: 1ef7c99d14
("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
Patchwork: https://patchwork.freedesktop.org/patch/637378/
Link: https://lore.kernel.org/r/20250214-drm-msm-phy-pll-cfg-reg-v3-2-0943b850722c@linaro.org
Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
This commit is contained in:
parent
5882578970
commit
5a97bc924a
2 changed files with 26 additions and 14 deletions
|
@ -83,6 +83,9 @@ struct dsi_pll_7nm {
|
|||
/* protects REG_DSI_7nm_PHY_CMN_CLK_CFG0 register */
|
||||
spinlock_t postdiv_lock;
|
||||
|
||||
/* protects REG_DSI_7nm_PHY_CMN_CLK_CFG1 register */
|
||||
spinlock_t pclk_mux_lock;
|
||||
|
||||
struct pll_7nm_cached_state cached_state;
|
||||
|
||||
struct dsi_pll_7nm *slave;
|
||||
|
@ -381,22 +384,32 @@ static void dsi_pll_cmn_clk_cfg0_write(struct dsi_pll_7nm *pll, u32 val)
|
|||
spin_unlock_irqrestore(&pll->postdiv_lock, flags);
|
||||
}
|
||||
|
||||
static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
|
||||
static void dsi_pll_cmn_clk_cfg1_update(struct dsi_pll_7nm *pll, u32 mask,
|
||||
u32 val)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 data;
|
||||
|
||||
spin_lock_irqsave(&pll->pclk_mux_lock, flags);
|
||||
data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
|
||||
writel(data & ~BIT(5), pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
|
||||
data &= ~mask;
|
||||
data |= val & mask;
|
||||
|
||||
writel(data, pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
|
||||
spin_unlock_irqrestore(&pll->pclk_mux_lock, flags);
|
||||
}
|
||||
|
||||
static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
|
||||
{
|
||||
dsi_pll_cmn_clk_cfg1_update(pll, DSI_7nm_PHY_CMN_CLK_CFG1_CLK_EN, 0);
|
||||
}
|
||||
|
||||
static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
|
||||
{
|
||||
u32 data;
|
||||
u32 cfg_1 = DSI_7nm_PHY_CMN_CLK_CFG1_CLK_EN | DSI_7nm_PHY_CMN_CLK_CFG1_CLK_EN_SEL;
|
||||
|
||||
writel(0x04, pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_3);
|
||||
|
||||
data = readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
|
||||
writel(data | BIT(5) | BIT(4), pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
|
||||
dsi_pll_cmn_clk_cfg1_update(pll, cfg_1, cfg_1);
|
||||
}
|
||||
|
||||
static void dsi_pll_phy_dig_reset(struct dsi_pll_7nm *pll)
|
||||
|
@ -574,7 +587,6 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
|
|||
{
|
||||
struct dsi_pll_7nm *pll_7nm = to_pll_7nm(phy->vco_hw);
|
||||
struct pll_7nm_cached_state *cached = &pll_7nm->cached_state;
|
||||
void __iomem *phy_base = pll_7nm->phy->base;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
|
@ -586,11 +598,7 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
|
|||
dsi_pll_cmn_clk_cfg0_write(pll_7nm,
|
||||
DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0(cached->bit_clk_div) |
|
||||
DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4(cached->pix_clk_div));
|
||||
|
||||
val = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
|
||||
val &= ~0x3;
|
||||
val |= cached->pll_mux;
|
||||
writel(val, phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
|
||||
dsi_pll_cmn_clk_cfg1_update(pll_7nm, 0x3, cached->pll_mux);
|
||||
|
||||
ret = dsi_pll_7nm_vco_set_rate(phy->vco_hw,
|
||||
pll_7nm->vco_current_rate,
|
||||
|
@ -743,7 +751,7 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide
|
|||
pll_by_2_bit,
|
||||
}), 2, 0, pll_7nm->phy->base +
|
||||
REG_DSI_7nm_PHY_CMN_CLK_CFG1,
|
||||
0, 1, 0, NULL);
|
||||
0, 1, 0, &pll_7nm->pclk_mux_lock);
|
||||
if (IS_ERR(hw)) {
|
||||
ret = PTR_ERR(hw);
|
||||
goto fail;
|
||||
|
@ -788,6 +796,7 @@ static int dsi_pll_7nm_init(struct msm_dsi_phy *phy)
|
|||
pll_7nm_list[phy->id] = pll_7nm;
|
||||
|
||||
spin_lock_init(&pll_7nm->postdiv_lock);
|
||||
spin_lock_init(&pll_7nm->pclk_mux_lock);
|
||||
|
||||
pll_7nm->phy = phy;
|
||||
|
||||
|
|
|
@ -13,7 +13,10 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<bitfield name="DIV_CTRL_3_0" low="0" high="3" type="uint"/>
|
||||
<bitfield name="DIV_CTRL_7_4" low="4" high="7" type="uint"/>
|
||||
</reg32>
|
||||
<reg32 offset="0x00014" name="CLK_CFG1"/>
|
||||
<reg32 offset="0x00014" name="CLK_CFG1">
|
||||
<bitfield name="CLK_EN" pos="5" type="boolean"/>
|
||||
<bitfield name="CLK_EN_SEL" pos="4" type="boolean"/>
|
||||
</reg32>
|
||||
<reg32 offset="0x00018" name="GLBL_CTRL"/>
|
||||
<reg32 offset="0x0001c" name="RBUF_CTRL"/>
|
||||
<reg32 offset="0x00020" name="VREG_CTRL_0"/>
|
||||
|
|
Loading…
Add table
Reference in a new issue