* [PATCH v2 0/4] drm/msm/dsi/phy: Improvements around concurrent PHY_CMN_CLK_CFG[01]
@ 2025-02-03 17:29 Krzysztof Kozlowski
2025-02-03 17:29 ` [PATCH v2 1/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG0 updated from driver side Krzysztof Kozlowski
` (3 more replies)
0 siblings, 4 replies; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-03 17:29 UTC (permalink / raw)
To: Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
Marijn Suijten, David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Krzysztof Kozlowski
Changes in v2:
- Add Fixes tag
- New patch #4
- Link to v1: https://lore.kernel.org/r/20250131-drm-msm-phy-pll-cfg-reg-v1-0-3b99efeb2e8d@linaro.org
Calling these improvements, not fixes, because I don't think we ever hit
actual concurrency issue. Although if we ever hit it, it would be very
tricky to debug and find the cause.
Best regards,
Krzysztof
---
Krzysztof Kozlowski (4):
drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG0 updated from driver side
drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver
drm/msm/dsi/phy: Do not overwite PHY_CMN_CLK_CFG1 when choosing bitclk source
drm/msm/dsi/phy: Define PHY_CMN_CLK_CFG[01] bitfields and simplify saving
drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 70 ++++++++++++++--------
.../gpu/drm/msm/registers/display/dsi_phy_7nm.xml | 12 +++-
2 files changed, 55 insertions(+), 27 deletions(-)
---
base-commit: 3270483b5a99a2ada44c72d6c2ae20d77c6e5c28
change-id: 20250131-drm-msm-phy-pll-cfg-reg-7e5bf5aa9df6
Best regards,
--
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2 1/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG0 updated from driver side
2025-02-03 17:29 [PATCH v2 0/4] drm/msm/dsi/phy: Improvements around concurrent PHY_CMN_CLK_CFG[01] Krzysztof Kozlowski
@ 2025-02-03 17:29 ` Krzysztof Kozlowski
2025-02-03 17:42 ` Dmitry Baryshkov
2025-02-11 0:26 ` Abhinav Kumar
2025-02-03 17:29 ` [PATCH v2 2/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver Krzysztof Kozlowski
` (2 subsequent siblings)
3 siblings, 2 replies; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-03 17:29 UTC (permalink / raw)
To: Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
Marijn Suijten, David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Krzysztof Kozlowski
PHY_CMN_CLK_CFG0 register is updated by the PHY driver and by two
divider clocks from Common Clock Framework:
devm_clk_hw_register_divider_parent_hw(). Concurrent access by the
clocks side is protected with spinlock, however driver's side in
restoring state is not. Restoring state is called from
msm_dsi_phy_enable(), so there could be a path leading to concurrent and
conflicting updates with clock framework.
Add missing lock usage on the PHY driver side, encapsulated in its own
function so the code will be still readable.
Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
index 031446c87daec0af3f81df324158311f5a80014e..c164f845653816291ad96c863257f75462ef58e7 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -372,6 +372,15 @@ static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll)
ndelay(250);
}
+static void dsi_pll_cmn_clk_cfg0_write(struct dsi_pll_7nm *pll, u32 val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pll->postdiv_lock, flags);
+ writel(val, pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
+ spin_unlock_irqrestore(&pll->postdiv_lock, flags);
+}
+
static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
{
u32 data;
@@ -574,8 +583,8 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
val |= cached->pll_out_div;
writel(val, pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
- writel(cached->bit_clk_div | (cached->pix_clk_div << 4),
- phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
+ dsi_pll_cmn_clk_cfg0_write(pll_7nm,
+ cached->bit_clk_div | (cached->pix_clk_div << 4));
val = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
val &= ~0x3;
--
2.43.0
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2 2/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver
2025-02-03 17:29 [PATCH v2 0/4] drm/msm/dsi/phy: Improvements around concurrent PHY_CMN_CLK_CFG[01] Krzysztof Kozlowski
2025-02-03 17:29 ` [PATCH v2 1/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG0 updated from driver side Krzysztof Kozlowski
@ 2025-02-03 17:29 ` Krzysztof Kozlowski
2025-02-03 17:41 ` Dmitry Baryshkov
2025-02-03 17:29 ` [PATCH v2 3/4] drm/msm/dsi/phy: Do not overwite PHY_CMN_CLK_CFG1 when choosing bitclk source Krzysztof Kozlowski
2025-02-03 17:29 ` [PATCH v2 4/4] drm/msm/dsi/phy: Define PHY_CMN_CLK_CFG[01] bitfields and simplify saving Krzysztof Kozlowski
3 siblings, 1 reply; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-03 17:29 UTC (permalink / raw)
To: Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
Marijn Suijten, David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Krzysztof Kozlowski
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.
Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
Changes in v2:
1. Store BIT(4) and BIT(5) in local var in dsi_pll_enable_global_clk()
---
drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 35 +++++++++++++++++++------------
1 file changed, 22 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
index c164f845653816291ad96c863257f75462ef58e7..e26f53f7cde8f0f6419a633f5d39784dc2e5bb98 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -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, BIT(5), 0);
}
static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
{
- u32 data;
+ u32 cfg_1 = BIT(5) | BIT(4);
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;
@@ -585,11 +597,7 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
dsi_pll_cmn_clk_cfg0_write(pll_7nm,
cached->bit_clk_div | (cached->pix_clk_div << 4));
-
- 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,
@@ -742,7 +750,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;
@@ -787,6 +795,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;
--
2.43.0
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2 3/4] drm/msm/dsi/phy: Do not overwite PHY_CMN_CLK_CFG1 when choosing bitclk source
2025-02-03 17:29 [PATCH v2 0/4] drm/msm/dsi/phy: Improvements around concurrent PHY_CMN_CLK_CFG[01] Krzysztof Kozlowski
2025-02-03 17:29 ` [PATCH v2 1/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG0 updated from driver side Krzysztof Kozlowski
2025-02-03 17:29 ` [PATCH v2 2/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver Krzysztof Kozlowski
@ 2025-02-03 17:29 ` Krzysztof Kozlowski
2025-02-03 17:40 ` Dmitry Baryshkov
2025-02-03 17:29 ` [PATCH v2 4/4] drm/msm/dsi/phy: Define PHY_CMN_CLK_CFG[01] bitfields and simplify saving Krzysztof Kozlowski
3 siblings, 1 reply; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-03 17:29 UTC (permalink / raw)
To: Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
Marijn Suijten, David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Krzysztof Kozlowski
PHY_CMN_CLK_CFG1 register has four fields being used in the driver: DSI
clock divider, source of bitclk and two for enabling the DSI PHY PLL
clocks.
dsi_7nm_set_usecase() sets only the source of bitclk, so should leave
all other bits untouched. Use newly introduced
dsi_pll_cmn_clk_cfg1_update() to update respective bits without
overwriting the rest.
Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
index e26f53f7cde8f0f6419a633f5d39784dc2e5bb98..926fd8e3330b2cdfc69d1e0e5d3930abae77b7d8 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -616,7 +616,6 @@ 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);
@@ -635,7 +634,7 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy)
}
/* set PLL src */
- writel(data << 2, base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
+ dsi_pll_cmn_clk_cfg1_update(pll_7nm, GENMASK(3, 2), data << 2);
return 0;
}
--
2.43.0
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2 4/4] drm/msm/dsi/phy: Define PHY_CMN_CLK_CFG[01] bitfields and simplify saving
2025-02-03 17:29 [PATCH v2 0/4] drm/msm/dsi/phy: Improvements around concurrent PHY_CMN_CLK_CFG[01] Krzysztof Kozlowski
` (2 preceding siblings ...)
2025-02-03 17:29 ` [PATCH v2 3/4] drm/msm/dsi/phy: Do not overwite PHY_CMN_CLK_CFG1 when choosing bitclk source Krzysztof Kozlowski
@ 2025-02-03 17:29 ` Krzysztof Kozlowski
2025-02-03 17:58 ` Dmitry Baryshkov
3 siblings, 1 reply; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-03 17:29 UTC (permalink / raw)
To: Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
Marijn Suijten, David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Krzysztof Kozlowski
Add bitfields for PHY_CMN_CLK_CFG0 and PHY_CMN_CLK_CFG1 registers to
avoid hard-coding bit masks and shifts and make the code a bit more
readable. While touching the lines in dsi_7nm_pll_save_state()
resulting cached->pix_clk_div assignment would be too big, so just
combine pix_clk_div and bit_clk_div into one cached state to make
everything simpler.
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
Changes in v2:
1. New patch
---
drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 31 ++++++++++++----------
.../gpu/drm/msm/registers/display/dsi_phy_7nm.xml | 12 +++++++--
2 files changed, 27 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
index 926fd8e3330b2cdfc69d1e0e5d3930abae77b7d8..b61e75a01e1b69f33548ff0adefc5c92980a15d7 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -67,8 +67,7 @@ struct dsi_pll_config {
struct pll_7nm_cached_state {
unsigned long vco_rate;
- u8 bit_clk_div;
- u8 pix_clk_div;
+ u8 clk_div;
u8 pll_out_div;
u8 pll_mux;
};
@@ -401,12 +400,12 @@ static void dsi_pll_cmn_clk_cfg1_update(struct dsi_pll_7nm *pll, u32 mask,
static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
{
- dsi_pll_cmn_clk_cfg1_update(pll, BIT(5), 0);
+ 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 cfg_1 = BIT(5) | BIT(4);
+ 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);
dsi_pll_cmn_clk_cfg1_update(pll, cfg_1, cfg_1);
@@ -572,15 +571,17 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *phy)
cached->pll_out_div &= 0x3;
cmn_clk_cfg0 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
- cached->bit_clk_div = cmn_clk_cfg0 & 0xf;
- cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;
+ cached->clk_div = cmn_clk_cfg0 & (DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__MASK |
+ DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__MASK);
cmn_clk_cfg1 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
- cached->pll_mux = cmn_clk_cfg1 & 0x3;
+ cached->pll_mux = cmn_clk_cfg1 & DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK;
DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",
- pll_7nm->phy->id, cached->pll_out_div, cached->bit_clk_div,
- cached->pix_clk_div, cached->pll_mux);
+ pll_7nm->phy->id, cached->pll_out_div,
+ cached->clk_div & DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__MASK,
+ cached->clk_div >> DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__SHIFT,
+ cached->pll_mux);
}
static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
@@ -595,9 +596,9 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
val |= cached->pll_out_div;
writel(val, pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
- dsi_pll_cmn_clk_cfg0_write(pll_7nm,
- cached->bit_clk_div | (cached->pix_clk_div << 4));
- dsi_pll_cmn_clk_cfg1_update(pll_7nm, 0x3, cached->pll_mux);
+ dsi_pll_cmn_clk_cfg0_write(pll_7nm, cached->clk_div);
+ dsi_pll_cmn_clk_cfg1_update(pll_7nm, DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK,
+ cached->pll_mux);
ret = dsi_pll_7nm_vco_set_rate(phy->vco_hw,
pll_7nm->vco_current_rate,
@@ -634,7 +635,8 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy)
}
/* set PLL src */
- dsi_pll_cmn_clk_cfg1_update(pll_7nm, GENMASK(3, 2), data << 2);
+ dsi_pll_cmn_clk_cfg1_update(pll_7nm, DSI_7nm_PHY_CMN_CLK_CFG1_BITCLK_SEL__MASK,
+ data << DSI_7nm_PHY_CMN_CLK_CFG1_BITCLK_SEL__SHIFT);
return 0;
}
@@ -737,7 +739,8 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide
u32 data;
data = readl(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
- writel(data | 3, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
+ writel(data | DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK,
+ pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
phy_pll_out_dsi_parent = pll_post_out_div;
} else {
diff --git a/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml b/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml
index d54b72f924493b4bf0925c287366f7b1e18eb46b..d2c8c46bb04159da6e539bfe80a4b5dc9ffdf367 100644
--- a/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml
+++ b/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml
@@ -9,8 +9,16 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
<reg32 offset="0x00004" name="REVISION_ID1"/>
<reg32 offset="0x00008" name="REVISION_ID2"/>
<reg32 offset="0x0000c" name="REVISION_ID3"/>
- <reg32 offset="0x00010" name="CLK_CFG0"/>
- <reg32 offset="0x00014" name="CLK_CFG1"/>
+ <reg32 offset="0x00010" name="CLK_CFG0">
+ <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">
+ <bitfield name="CLK_EN" pos="5" type="boolean"/>
+ <bitfield name="CLK_EN_SEL" pos="4" type="boolean"/>
+ <bitfield name="BITCLK_SEL" low="2" high="3" type="uint"/>
+ <bitfield name="DSICLK_SEL" low="0" high="1" type="uint"/>
+ </reg32>
<reg32 offset="0x00018" name="GLBL_CTRL"/>
<reg32 offset="0x0001c" name="RBUF_CTRL"/>
<reg32 offset="0x00020" name="VREG_CTRL_0"/>
--
2.43.0
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 3/4] drm/msm/dsi/phy: Do not overwite PHY_CMN_CLK_CFG1 when choosing bitclk source
2025-02-03 17:29 ` [PATCH v2 3/4] drm/msm/dsi/phy: Do not overwite PHY_CMN_CLK_CFG1 when choosing bitclk source Krzysztof Kozlowski
@ 2025-02-03 17:40 ` Dmitry Baryshkov
2025-02-04 9:22 ` Krzysztof Kozlowski
0 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2025-02-03 17:40 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On Mon, Feb 03, 2025 at 06:29:20PM +0100, Krzysztof Kozlowski wrote:
> PHY_CMN_CLK_CFG1 register has four fields being used in the driver: DSI
> clock divider, source of bitclk and two for enabling the DSI PHY PLL
> clocks.
>
> dsi_7nm_set_usecase() sets only the source of bitclk, so should leave
> all other bits untouched. Use newly introduced
> dsi_pll_cmn_clk_cfg1_update() to update respective bits without
> overwriting the rest.
>
> Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> ---
> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> index e26f53f7cde8f0f6419a633f5d39784dc2e5bb98..926fd8e3330b2cdfc69d1e0e5d3930abae77b7d8 100644
> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> @@ -616,7 +616,6 @@ 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);
> @@ -635,7 +634,7 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy)
> }
>
> /* set PLL src */
> - writel(data << 2, base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
> + dsi_pll_cmn_clk_cfg1_update(pll_7nm, GENMASK(3, 2), data << 2);
The mask is not defined, still.
>
> return 0;
> }
>
> --
> 2.43.0
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 2/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver
2025-02-03 17:29 ` [PATCH v2 2/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver Krzysztof Kozlowski
@ 2025-02-03 17:41 ` Dmitry Baryshkov
2025-02-04 9:21 ` Krzysztof Kozlowski
0 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2025-02-03 17:41 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On Mon, Feb 03, 2025 at 06:29:19PM +0100, Krzysztof Kozlowski wrote:
> 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.
>
> Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>
> ---
>
> Changes in v2:
> 1. Store BIT(4) and BIT(5) in local var in dsi_pll_enable_global_clk()
> ---
> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 35 +++++++++++++++++++------------
> 1 file changed, 22 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> index c164f845653816291ad96c863257f75462ef58e7..e26f53f7cde8f0f6419a633f5d39784dc2e5bb98 100644
> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> @@ -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, BIT(5), 0);
> }
>
> static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
> {
> - u32 data;
> + u32 cfg_1 = BIT(5) | BIT(4);
Please define these two bits too.
>
> 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;
>
> @@ -585,11 +597,7 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
>
> dsi_pll_cmn_clk_cfg0_write(pll_7nm,
> cached->bit_clk_div | (cached->pix_clk_div << 4));
> -
> - 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,
> @@ -742,7 +750,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;
> @@ -787,6 +795,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;
>
>
> --
> 2.43.0
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG0 updated from driver side
2025-02-03 17:29 ` [PATCH v2 1/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG0 updated from driver side Krzysztof Kozlowski
@ 2025-02-03 17:42 ` Dmitry Baryshkov
2025-02-04 9:20 ` Krzysztof Kozlowski
2025-02-11 0:26 ` Abhinav Kumar
1 sibling, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2025-02-03 17:42 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On Mon, Feb 03, 2025 at 06:29:18PM +0100, Krzysztof Kozlowski wrote:
> PHY_CMN_CLK_CFG0 register is updated by the PHY driver and by two
> divider clocks from Common Clock Framework:
> devm_clk_hw_register_divider_parent_hw(). Concurrent access by the
> clocks side is protected with spinlock, however driver's side in
> restoring state is not. Restoring state is called from
> msm_dsi_phy_enable(), so there could be a path leading to concurrent and
> conflicting updates with clock framework.
>
> Add missing lock usage on the PHY driver side, encapsulated in its own
> function so the code will be still readable.
>
> Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> ---
> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 13 +++++++++++--
> 1 file changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> index 031446c87daec0af3f81df324158311f5a80014e..c164f845653816291ad96c863257f75462ef58e7 100644
> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> @@ -372,6 +372,15 @@ static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll)
> ndelay(250);
> }
>
> +static void dsi_pll_cmn_clk_cfg0_write(struct dsi_pll_7nm *pll, u32 val)
> +{
> + unsigned long flags;
> +
> + spin_lock_irqsave(&pll->postdiv_lock, flags);
> + writel(val, pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
> + spin_unlock_irqrestore(&pll->postdiv_lock, flags);
> +}
> +
> static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
> {
> u32 data;
> @@ -574,8 +583,8 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
> val |= cached->pll_out_div;
> writel(val, pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
>
> - writel(cached->bit_clk_div | (cached->pix_clk_div << 4),
> - phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
> + dsi_pll_cmn_clk_cfg0_write(pll_7nm,
> + cached->bit_clk_div | (cached->pix_clk_div << 4));
Ideally this would be FIELD_PREP or a special function generated for you
in the header.
>
> val = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
> val &= ~0x3;
>
> --
> 2.43.0
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 4/4] drm/msm/dsi/phy: Define PHY_CMN_CLK_CFG[01] bitfields and simplify saving
2025-02-03 17:29 ` [PATCH v2 4/4] drm/msm/dsi/phy: Define PHY_CMN_CLK_CFG[01] bitfields and simplify saving Krzysztof Kozlowski
@ 2025-02-03 17:58 ` Dmitry Baryshkov
2025-02-04 9:24 ` Krzysztof Kozlowski
0 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2025-02-03 17:58 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On Mon, Feb 03, 2025 at 06:29:21PM +0100, Krzysztof Kozlowski wrote:
> Add bitfields for PHY_CMN_CLK_CFG0 and PHY_CMN_CLK_CFG1 registers to
> avoid hard-coding bit masks and shifts and make the code a bit more
> readable. While touching the lines in dsi_7nm_pll_save_state()
> resulting cached->pix_clk_div assignment would be too big, so just
> combine pix_clk_div and bit_clk_div into one cached state to make
> everything simpler.
>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>
> ---
>
> Changes in v2:
> 1. New patch
> ---
> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 31 ++++++++++++----------
> .../gpu/drm/msm/registers/display/dsi_phy_7nm.xml | 12 +++++++--
> 2 files changed, 27 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> index 926fd8e3330b2cdfc69d1e0e5d3930abae77b7d8..b61e75a01e1b69f33548ff0adefc5c92980a15d7 100644
> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> @@ -67,8 +67,7 @@ struct dsi_pll_config {
>
> struct pll_7nm_cached_state {
> unsigned long vco_rate;
> - u8 bit_clk_div;
> - u8 pix_clk_div;
> + u8 clk_div;
> u8 pll_out_div;
> u8 pll_mux;
> };
> @@ -401,12 +400,12 @@ static void dsi_pll_cmn_clk_cfg1_update(struct dsi_pll_7nm *pll, u32 mask,
>
> static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
> {
> - dsi_pll_cmn_clk_cfg1_update(pll, BIT(5), 0);
> + 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 cfg_1 = BIT(5) | BIT(4);
> + 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);
> dsi_pll_cmn_clk_cfg1_update(pll, cfg_1, cfg_1);
> @@ -572,15 +571,17 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *phy)
> cached->pll_out_div &= 0x3;
>
> cmn_clk_cfg0 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
> - cached->bit_clk_div = cmn_clk_cfg0 & 0xf;
> - cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;
> + cached->clk_div = cmn_clk_cfg0 & (DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__MASK |
> + DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__MASK);
Could you rather store these two fields separately by using FIELD_GET?
>
> cmn_clk_cfg1 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
> - cached->pll_mux = cmn_clk_cfg1 & 0x3;
> + cached->pll_mux = cmn_clk_cfg1 & DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK;
FIELD_GET
>
> DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",
> - pll_7nm->phy->id, cached->pll_out_div, cached->bit_clk_div,
> - cached->pix_clk_div, cached->pll_mux);
> + pll_7nm->phy->id, cached->pll_out_div,
> + cached->clk_div & DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__MASK,
> + cached->clk_div >> DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__SHIFT,
> + cached->pll_mux);
> }
>
> static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
> @@ -595,9 +596,9 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
> val |= cached->pll_out_div;
> writel(val, pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
>
> - dsi_pll_cmn_clk_cfg0_write(pll_7nm,
> - cached->bit_clk_div | (cached->pix_clk_div << 4));
> - dsi_pll_cmn_clk_cfg1_update(pll_7nm, 0x3, cached->pll_mux);
> + dsi_pll_cmn_clk_cfg0_write(pll_7nm, cached->clk_div);
> + dsi_pll_cmn_clk_cfg1_update(pll_7nm, DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK,
> + cached->pll_mux);
>
> ret = dsi_pll_7nm_vco_set_rate(phy->vco_hw,
> pll_7nm->vco_current_rate,
> @@ -634,7 +635,8 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy)
> }
>
> /* set PLL src */
> - dsi_pll_cmn_clk_cfg1_update(pll_7nm, GENMASK(3, 2), data << 2);
> + dsi_pll_cmn_clk_cfg1_update(pll_7nm, DSI_7nm_PHY_CMN_CLK_CFG1_BITCLK_SEL__MASK,
> + data << DSI_7nm_PHY_CMN_CLK_CFG1_BITCLK_SEL__SHIFT);
use accessor function from the header.
>
> return 0;
> }
> @@ -737,7 +739,8 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide
> u32 data;
>
> data = readl(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
> - writel(data | 3, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
> + writel(data | DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK,
> + pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
>
> phy_pll_out_dsi_parent = pll_post_out_div;
> } else {
> diff --git a/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml b/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml
> index d54b72f924493b4bf0925c287366f7b1e18eb46b..d2c8c46bb04159da6e539bfe80a4b5dc9ffdf367 100644
> --- a/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml
> +++ b/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml
> @@ -9,8 +9,16 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
> <reg32 offset="0x00004" name="REVISION_ID1"/>
> <reg32 offset="0x00008" name="REVISION_ID2"/>
> <reg32 offset="0x0000c" name="REVISION_ID3"/>
> - <reg32 offset="0x00010" name="CLK_CFG0"/>
> - <reg32 offset="0x00014" name="CLK_CFG1"/>
> + <reg32 offset="0x00010" name="CLK_CFG0">
> + <bitfield name="DIV_CTRL_3_0" low="0" high="3" type="uint"/>
> + <bitfield name="DIV_CTRL_7_4" low="4" high="7" type="uint"/>
Are there any sensible names for these two regs? It looks ther are
not...
> + </reg32>
> + <reg32 offset="0x00014" name="CLK_CFG1">
> + <bitfield name="CLK_EN" pos="5" type="boolean"/>
> + <bitfield name="CLK_EN_SEL" pos="4" type="boolean"/>
> + <bitfield name="BITCLK_SEL" low="2" high="3" type="uint"/>
> + <bitfield name="DSICLK_SEL" low="0" high="1" type="uint"/>
> + </reg32>
> <reg32 offset="0x00018" name="GLBL_CTRL"/>
> <reg32 offset="0x0001c" name="RBUF_CTRL"/>
> <reg32 offset="0x00020" name="VREG_CTRL_0"/>
>
> --
> 2.43.0
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG0 updated from driver side
2025-02-03 17:42 ` Dmitry Baryshkov
@ 2025-02-04 9:20 ` Krzysztof Kozlowski
2025-02-04 14:21 ` Dmitry Baryshkov
0 siblings, 1 reply; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-04 9:20 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On 03/02/2025 18:42, Dmitry Baryshkov wrote:
> On Mon, Feb 03, 2025 at 06:29:18PM +0100, Krzysztof Kozlowski wrote:
>> PHY_CMN_CLK_CFG0 register is updated by the PHY driver and by two
>> divider clocks from Common Clock Framework:
>> devm_clk_hw_register_divider_parent_hw(). Concurrent access by the
>> clocks side is protected with spinlock, however driver's side in
>> restoring state is not. Restoring state is called from
>> msm_dsi_phy_enable(), so there could be a path leading to concurrent and
>> conflicting updates with clock framework.
>>
>> Add missing lock usage on the PHY driver side, encapsulated in its own
>> function so the code will be still readable.
>>
>> Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
>> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>> ---
>> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 13 +++++++++++--
>> 1 file changed, 11 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>> index 031446c87daec0af3f81df324158311f5a80014e..c164f845653816291ad96c863257f75462ef58e7 100644
>> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>> @@ -372,6 +372,15 @@ static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll)
>> ndelay(250);
>> }
>>
>> +static void dsi_pll_cmn_clk_cfg0_write(struct dsi_pll_7nm *pll, u32 val)
>> +{
>> + unsigned long flags;
>> +
>> + spin_lock_irqsave(&pll->postdiv_lock, flags);
>> + writel(val, pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
>> + spin_unlock_irqrestore(&pll->postdiv_lock, flags);
>> +}
>> +
>> static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
>> {
>> u32 data;
>> @@ -574,8 +583,8 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
>> val |= cached->pll_out_div;
>> writel(val, pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
>>
>> - writel(cached->bit_clk_div | (cached->pix_clk_div << 4),
>> - phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
>> + dsi_pll_cmn_clk_cfg0_write(pll_7nm,
>> + cached->bit_clk_div | (cached->pix_clk_div << 4));
>
> Ideally this would be FIELD_PREP or a special function generated for you
> in the header.
There is no header. That's patch #1 and I do not see how changing this
to FIELDPREP is anyhow related to the actual problem being solved here.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 2/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver
2025-02-03 17:41 ` Dmitry Baryshkov
@ 2025-02-04 9:21 ` Krzysztof Kozlowski
2025-02-04 14:26 ` Dmitry Baryshkov
0 siblings, 1 reply; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-04 9:21 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On 03/02/2025 18:41, Dmitry Baryshkov wrote:
> On Mon, Feb 03, 2025 at 06:29:19PM +0100, Krzysztof Kozlowski wrote:
>> 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.
>>
>> Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
>> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>>
>> ---
>>
>> Changes in v2:
>> 1. Store BIT(4) and BIT(5) in local var in dsi_pll_enable_global_clk()
>> ---
>> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 35 +++++++++++++++++++------------
>> 1 file changed, 22 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>> index c164f845653816291ad96c863257f75462ef58e7..e26f53f7cde8f0f6419a633f5d39784dc2e5bb98 100644
>> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>> @@ -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, BIT(5), 0);
>> }
>>
>> static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
>> {
>> - u32 data;
>> + u32 cfg_1 = BIT(5) | BIT(4);
>
> Please define these two bits too.
Why? They were not defined before. This only moving existing code.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 3/4] drm/msm/dsi/phy: Do not overwite PHY_CMN_CLK_CFG1 when choosing bitclk source
2025-02-03 17:40 ` Dmitry Baryshkov
@ 2025-02-04 9:22 ` Krzysztof Kozlowski
2025-02-04 14:27 ` Dmitry Baryshkov
0 siblings, 1 reply; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-04 9:22 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On 03/02/2025 18:40, Dmitry Baryshkov wrote:
> On Mon, Feb 03, 2025 at 06:29:20PM +0100, Krzysztof Kozlowski wrote:
>> PHY_CMN_CLK_CFG1 register has four fields being used in the driver: DSI
>> clock divider, source of bitclk and two for enabling the DSI PHY PLL
>> clocks.
>>
>> dsi_7nm_set_usecase() sets only the source of bitclk, so should leave
>> all other bits untouched. Use newly introduced
>> dsi_pll_cmn_clk_cfg1_update() to update respective bits without
>> overwriting the rest.
>>
>> Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
>> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>> ---
>> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 3 +--
>> 1 file changed, 1 insertion(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>> index e26f53f7cde8f0f6419a633f5d39784dc2e5bb98..926fd8e3330b2cdfc69d1e0e5d3930abae77b7d8 100644
>> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>> @@ -616,7 +616,6 @@ 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);
>> @@ -635,7 +634,7 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy)
>> }
>>
>> /* set PLL src */
>> - writel(data << 2, base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
>> + dsi_pll_cmn_clk_cfg1_update(pll_7nm, GENMASK(3, 2), data << 2);
>
> The mask is not defined, still.
Why would it be? That's old/existing code. Commit is doing only one
thing - fixing something. Not introducing some masks or defines and
changing hard-coded values into defines.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 4/4] drm/msm/dsi/phy: Define PHY_CMN_CLK_CFG[01] bitfields and simplify saving
2025-02-03 17:58 ` Dmitry Baryshkov
@ 2025-02-04 9:24 ` Krzysztof Kozlowski
2025-02-04 14:28 ` Dmitry Baryshkov
0 siblings, 1 reply; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-04 9:24 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On 03/02/2025 18:58, Dmitry Baryshkov wrote:
> On Mon, Feb 03, 2025 at 06:29:21PM +0100, Krzysztof Kozlowski wrote:
>> Add bitfields for PHY_CMN_CLK_CFG0 and PHY_CMN_CLK_CFG1 registers to
>> avoid hard-coding bit masks and shifts and make the code a bit more
>> readable. While touching the lines in dsi_7nm_pll_save_state()
>> resulting cached->pix_clk_div assignment would be too big, so just
>> combine pix_clk_div and bit_clk_div into one cached state to make
>> everything simpler.
>>
>> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>>
>> ---
>>
>> Changes in v2:
>> 1. New patch
>> ---
>> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 31 ++++++++++++----------
>> .../gpu/drm/msm/registers/display/dsi_phy_7nm.xml | 12 +++++++--
>> 2 files changed, 27 insertions(+), 16 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>> index 926fd8e3330b2cdfc69d1e0e5d3930abae77b7d8..b61e75a01e1b69f33548ff0adefc5c92980a15d7 100644
>> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>> @@ -67,8 +67,7 @@ struct dsi_pll_config {
>>
>> struct pll_7nm_cached_state {
>> unsigned long vco_rate;
>> - u8 bit_clk_div;
>> - u8 pix_clk_div;
>> + u8 clk_div;
>> u8 pll_out_div;
>> u8 pll_mux;
>> };
>> @@ -401,12 +400,12 @@ static void dsi_pll_cmn_clk_cfg1_update(struct dsi_pll_7nm *pll, u32 mask,
>>
>> static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
>> {
>> - dsi_pll_cmn_clk_cfg1_update(pll, BIT(5), 0);
>> + 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 cfg_1 = BIT(5) | BIT(4);
>> + 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);
>> dsi_pll_cmn_clk_cfg1_update(pll, cfg_1, cfg_1);
>> @@ -572,15 +571,17 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *phy)
>> cached->pll_out_div &= 0x3;
>>
>> cmn_clk_cfg0 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
>> - cached->bit_clk_div = cmn_clk_cfg0 & 0xf;
>> - cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;
>> + cached->clk_div = cmn_clk_cfg0 & (DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__MASK |
>> + DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__MASK);
>
> Could you rather store these two fields separately by using FIELD_GET?
So make the code again more complicated? OK.
>
>>
>> cmn_clk_cfg1 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
>> - cached->pll_mux = cmn_clk_cfg1 & 0x3;
>> + cached->pll_mux = cmn_clk_cfg1 & DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK;
>
> FIELD_GET
>
>>
>> DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",
>> - pll_7nm->phy->id, cached->pll_out_div, cached->bit_clk_div,
>> - cached->pix_clk_div, cached->pll_mux);
>> + pll_7nm->phy->id, cached->pll_out_div,
>> + cached->clk_div & DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__MASK,
>> + cached->clk_div >> DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__SHIFT,
>> + cached->pll_mux);
>> }
>>
>> static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
>> @@ -595,9 +596,9 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
>> val |= cached->pll_out_div;
>> writel(val, pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
>>
>> - dsi_pll_cmn_clk_cfg0_write(pll_7nm,
>> - cached->bit_clk_div | (cached->pix_clk_div << 4));
>> - dsi_pll_cmn_clk_cfg1_update(pll_7nm, 0x3, cached->pll_mux);
>> + dsi_pll_cmn_clk_cfg0_write(pll_7nm, cached->clk_div);
>> + dsi_pll_cmn_clk_cfg1_update(pll_7nm, DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK,
>> + cached->pll_mux);
>>
>> ret = dsi_pll_7nm_vco_set_rate(phy->vco_hw,
>> pll_7nm->vco_current_rate,
>> @@ -634,7 +635,8 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy)
>> }
>>
>> /* set PLL src */
>> - dsi_pll_cmn_clk_cfg1_update(pll_7nm, GENMASK(3, 2), data << 2);
>> + dsi_pll_cmn_clk_cfg1_update(pll_7nm, DSI_7nm_PHY_CMN_CLK_CFG1_BITCLK_SEL__MASK,
>> + data << DSI_7nm_PHY_CMN_CLK_CFG1_BITCLK_SEL__SHIFT);
>
> use accessor function from the header.
For which part? for last argument? It will be almost pointless, but sure.
>
>>
>> return 0;
>> }
>> @@ -737,7 +739,8 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide
>> u32 data;
>>
>> data = readl(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
>> - writel(data | 3, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
>> + writel(data | DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK,
>> + pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
>>
>> phy_pll_out_dsi_parent = pll_post_out_div;
>> } else {
>> diff --git a/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml b/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml
>> index d54b72f924493b4bf0925c287366f7b1e18eb46b..d2c8c46bb04159da6e539bfe80a4b5dc9ffdf367 100644
>> --- a/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml
>> +++ b/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml
>> @@ -9,8 +9,16 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
>> <reg32 offset="0x00004" name="REVISION_ID1"/>
>> <reg32 offset="0x00008" name="REVISION_ID2"/>
>> <reg32 offset="0x0000c" name="REVISION_ID3"/>
>> - <reg32 offset="0x00010" name="CLK_CFG0"/>
>> - <reg32 offset="0x00014" name="CLK_CFG1"/>
>> + <reg32 offset="0x00010" name="CLK_CFG0">
>> + <bitfield name="DIV_CTRL_3_0" low="0" high="3" type="uint"/>
>> + <bitfield name="DIV_CTRL_7_4" low="4" high="7" type="uint"/>
>
> Are there any sensible names for these two regs? It looks ther are
> not...
These are the sensible names. That's how they are called in datasheet.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG0 updated from driver side
2025-02-04 9:20 ` Krzysztof Kozlowski
@ 2025-02-04 14:21 ` Dmitry Baryshkov
0 siblings, 0 replies; 27+ messages in thread
From: Dmitry Baryshkov @ 2025-02-04 14:21 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On Tue, Feb 04, 2025 at 10:20:51AM +0100, Krzysztof Kozlowski wrote:
> On 03/02/2025 18:42, Dmitry Baryshkov wrote:
> > On Mon, Feb 03, 2025 at 06:29:18PM +0100, Krzysztof Kozlowski wrote:
> >> PHY_CMN_CLK_CFG0 register is updated by the PHY driver and by two
> >> divider clocks from Common Clock Framework:
> >> devm_clk_hw_register_divider_parent_hw(). Concurrent access by the
> >> clocks side is protected with spinlock, however driver's side in
> >> restoring state is not. Restoring state is called from
> >> msm_dsi_phy_enable(), so there could be a path leading to concurrent and
> >> conflicting updates with clock framework.
> >>
> >> Add missing lock usage on the PHY driver side, encapsulated in its own
> >> function so the code will be still readable.
> >>
> >> Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
> >> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> >> ---
> >> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 13 +++++++++++--
> >> 1 file changed, 11 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >> index 031446c87daec0af3f81df324158311f5a80014e..c164f845653816291ad96c863257f75462ef58e7 100644
> >> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >> @@ -372,6 +372,15 @@ static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll)
> >> ndelay(250);
> >> }
> >>
> >> +static void dsi_pll_cmn_clk_cfg0_write(struct dsi_pll_7nm *pll, u32 val)
> >> +{
> >> + unsigned long flags;
> >> +
> >> + spin_lock_irqsave(&pll->postdiv_lock, flags);
> >> + writel(val, pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
> >> + spin_unlock_irqrestore(&pll->postdiv_lock, flags);
> >> +}
> >> +
> >> static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
> >> {
> >> u32 data;
> >> @@ -574,8 +583,8 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
> >> val |= cached->pll_out_div;
> >> writel(val, pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
> >>
> >> - writel(cached->bit_clk_div | (cached->pix_clk_div << 4),
> >> - phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
> >> + dsi_pll_cmn_clk_cfg0_write(pll_7nm,
> >> + cached->bit_clk_div | (cached->pix_clk_div << 4));
> >
> > Ideally this would be FIELD_PREP or a special function generated for you
> > in the header.
>
> There is no header. That's patch #1 and I do not see how changing this
> to FIELDPREP is anyhow related to the actual problem being solved here.
Ack, this just moves the code.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 2/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver
2025-02-04 9:21 ` Krzysztof Kozlowski
@ 2025-02-04 14:26 ` Dmitry Baryshkov
2025-02-04 15:46 ` Krzysztof Kozlowski
0 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2025-02-04 14:26 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On Tue, Feb 04, 2025 at 10:21:25AM +0100, Krzysztof Kozlowski wrote:
> On 03/02/2025 18:41, Dmitry Baryshkov wrote:
> > On Mon, Feb 03, 2025 at 06:29:19PM +0100, Krzysztof Kozlowski wrote:
> >> 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.
> >>
> >> Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
> >> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> >>
> >> ---
> >>
> >> Changes in v2:
> >> 1. Store BIT(4) and BIT(5) in local var in dsi_pll_enable_global_clk()
> >> ---
> >> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 35 +++++++++++++++++++------------
> >> 1 file changed, 22 insertions(+), 13 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >> index c164f845653816291ad96c863257f75462ef58e7..e26f53f7cde8f0f6419a633f5d39784dc2e5bb98 100644
> >> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >> @@ -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, BIT(5), 0);
> >> }
> >>
> >> static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
> >> {
> >> - u32 data;
> >> + u32 cfg_1 = BIT(5) | BIT(4);
> >
> > Please define these two bits too.
>
> Why? They were not defined before. This only moving existing code.
Previously it was just a bit magic. Currently you are adding them as
masks. I want to know if BIT(4) and BIT(5) are parts of the same
bitfield (2 bits wide) or if they define two different bits.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 3/4] drm/msm/dsi/phy: Do not overwite PHY_CMN_CLK_CFG1 when choosing bitclk source
2025-02-04 9:22 ` Krzysztof Kozlowski
@ 2025-02-04 14:27 ` Dmitry Baryshkov
2025-02-04 15:47 ` Krzysztof Kozlowski
0 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2025-02-04 14:27 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On Tue, Feb 04, 2025 at 10:22:19AM +0100, Krzysztof Kozlowski wrote:
> On 03/02/2025 18:40, Dmitry Baryshkov wrote:
> > On Mon, Feb 03, 2025 at 06:29:20PM +0100, Krzysztof Kozlowski wrote:
> >> PHY_CMN_CLK_CFG1 register has four fields being used in the driver: DSI
> >> clock divider, source of bitclk and two for enabling the DSI PHY PLL
> >> clocks.
> >>
> >> dsi_7nm_set_usecase() sets only the source of bitclk, so should leave
> >> all other bits untouched. Use newly introduced
> >> dsi_pll_cmn_clk_cfg1_update() to update respective bits without
> >> overwriting the rest.
> >>
> >> Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
> >> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> >> ---
> >> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 3 +--
> >> 1 file changed, 1 insertion(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >> index e26f53f7cde8f0f6419a633f5d39784dc2e5bb98..926fd8e3330b2cdfc69d1e0e5d3930abae77b7d8 100644
> >> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >> @@ -616,7 +616,6 @@ 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);
> >> @@ -635,7 +634,7 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy)
> >> }
> >>
> >> /* set PLL src */
> >> - writel(data << 2, base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
> >> + dsi_pll_cmn_clk_cfg1_update(pll_7nm, GENMASK(3, 2), data << 2);
> >
> > The mask is not defined, still.
>
> Why would it be? That's old/existing code. Commit is doing only one
> thing - fixing something. Not introducing some masks or defines and
> changing hard-coded values into defines.
GENMASK(3, 2) needs to be defined in the XML file. It was not there
beforehand, you have just introduced it.
>
> Best regards,
> Krzysztof
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 4/4] drm/msm/dsi/phy: Define PHY_CMN_CLK_CFG[01] bitfields and simplify saving
2025-02-04 9:24 ` Krzysztof Kozlowski
@ 2025-02-04 14:28 ` Dmitry Baryshkov
2025-02-04 15:48 ` Krzysztof Kozlowski
0 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2025-02-04 14:28 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On Tue, Feb 04, 2025 at 10:24:28AM +0100, Krzysztof Kozlowski wrote:
> On 03/02/2025 18:58, Dmitry Baryshkov wrote:
> > On Mon, Feb 03, 2025 at 06:29:21PM +0100, Krzysztof Kozlowski wrote:
> >> Add bitfields for PHY_CMN_CLK_CFG0 and PHY_CMN_CLK_CFG1 registers to
> >> avoid hard-coding bit masks and shifts and make the code a bit more
> >> readable. While touching the lines in dsi_7nm_pll_save_state()
> >> resulting cached->pix_clk_div assignment would be too big, so just
> >> combine pix_clk_div and bit_clk_div into one cached state to make
> >> everything simpler.
> >>
> >> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> >>
> >> ---
> >>
> >> Changes in v2:
> >> 1. New patch
> >> ---
> >> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 31 ++++++++++++----------
> >> .../gpu/drm/msm/registers/display/dsi_phy_7nm.xml | 12 +++++++--
> >> 2 files changed, 27 insertions(+), 16 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >> index 926fd8e3330b2cdfc69d1e0e5d3930abae77b7d8..b61e75a01e1b69f33548ff0adefc5c92980a15d7 100644
> >> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >> @@ -67,8 +67,7 @@ struct dsi_pll_config {
> >>
> >> struct pll_7nm_cached_state {
> >> unsigned long vco_rate;
> >> - u8 bit_clk_div;
> >> - u8 pix_clk_div;
> >> + u8 clk_div;
> >> u8 pll_out_div;
> >> u8 pll_mux;
> >> };
> >> @@ -401,12 +400,12 @@ static void dsi_pll_cmn_clk_cfg1_update(struct dsi_pll_7nm *pll, u32 mask,
> >>
> >> static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
> >> {
> >> - dsi_pll_cmn_clk_cfg1_update(pll, BIT(5), 0);
> >> + 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 cfg_1 = BIT(5) | BIT(4);
> >> + 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);
> >> dsi_pll_cmn_clk_cfg1_update(pll, cfg_1, cfg_1);
> >> @@ -572,15 +571,17 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *phy)
> >> cached->pll_out_div &= 0x3;
> >>
> >> cmn_clk_cfg0 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
> >> - cached->bit_clk_div = cmn_clk_cfg0 & 0xf;
> >> - cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;
> >> + cached->clk_div = cmn_clk_cfg0 & (DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__MASK |
> >> + DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__MASK);
> >
> > Could you rather store these two fields separately by using FIELD_GET?
>
> So make the code again more complicated? OK.
It was already there, bit_clk_div and pix_clk_div.
>
> >
> >>
> >> cmn_clk_cfg1 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
> >> - cached->pll_mux = cmn_clk_cfg1 & 0x3;
> >> + cached->pll_mux = cmn_clk_cfg1 & DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK;
> >
> > FIELD_GET
> >
> >>
> >> DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x",
> >> - pll_7nm->phy->id, cached->pll_out_div, cached->bit_clk_div,
> >> - cached->pix_clk_div, cached->pll_mux);
> >> + pll_7nm->phy->id, cached->pll_out_div,
> >> + cached->clk_div & DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__MASK,
> >> + cached->clk_div >> DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__SHIFT,
> >> + cached->pll_mux);
> >> }
> >>
> >> static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
> >> @@ -595,9 +596,9 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)
> >> val |= cached->pll_out_div;
> >> writel(val, pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE);
> >>
> >> - dsi_pll_cmn_clk_cfg0_write(pll_7nm,
> >> - cached->bit_clk_div | (cached->pix_clk_div << 4));
> >> - dsi_pll_cmn_clk_cfg1_update(pll_7nm, 0x3, cached->pll_mux);
> >> + dsi_pll_cmn_clk_cfg0_write(pll_7nm, cached->clk_div);
> >> + dsi_pll_cmn_clk_cfg1_update(pll_7nm, DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK,
> >> + cached->pll_mux);
> >>
> >> ret = dsi_pll_7nm_vco_set_rate(phy->vco_hw,
> >> pll_7nm->vco_current_rate,
> >> @@ -634,7 +635,8 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy)
> >> }
> >>
> >> /* set PLL src */
> >> - dsi_pll_cmn_clk_cfg1_update(pll_7nm, GENMASK(3, 2), data << 2);
> >> + dsi_pll_cmn_clk_cfg1_update(pll_7nm, DSI_7nm_PHY_CMN_CLK_CFG1_BITCLK_SEL__MASK,
> >> + data << DSI_7nm_PHY_CMN_CLK_CFG1_BITCLK_SEL__SHIFT);
> >
> > use accessor function from the header.
>
> For which part? for last argument? It will be almost pointless, but sure.
>
>
> >
> >>
> >> return 0;
> >> }
> >> @@ -737,7 +739,8 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide
> >> u32 data;
> >>
> >> data = readl(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
> >> - writel(data | 3, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
> >> + writel(data | DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK,
> >> + pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
> >>
> >> phy_pll_out_dsi_parent = pll_post_out_div;
> >> } else {
> >> diff --git a/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml b/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml
> >> index d54b72f924493b4bf0925c287366f7b1e18eb46b..d2c8c46bb04159da6e539bfe80a4b5dc9ffdf367 100644
> >> --- a/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml
> >> +++ b/drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml
> >> @@ -9,8 +9,16 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
> >> <reg32 offset="0x00004" name="REVISION_ID1"/>
> >> <reg32 offset="0x00008" name="REVISION_ID2"/>
> >> <reg32 offset="0x0000c" name="REVISION_ID3"/>
> >> - <reg32 offset="0x00010" name="CLK_CFG0"/>
> >> - <reg32 offset="0x00014" name="CLK_CFG1"/>
> >> + <reg32 offset="0x00010" name="CLK_CFG0">
> >> + <bitfield name="DIV_CTRL_3_0" low="0" high="3" type="uint"/>
> >> + <bitfield name="DIV_CTRL_7_4" low="4" high="7" type="uint"/>
> >
> > Are there any sensible names for these two regs? It looks ther are
> > not...
>
> These are the sensible names. That's how they are called in datasheet.
Yeah, that's what I had in the register file too. Then this part is
okay.
>
> Best regards,
> Krzysztof
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 2/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver
2025-02-04 14:26 ` Dmitry Baryshkov
@ 2025-02-04 15:46 ` Krzysztof Kozlowski
2025-02-05 2:51 ` Dmitry Baryshkov
0 siblings, 1 reply; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-04 15:46 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On 04/02/2025 15:26, Dmitry Baryshkov wrote:
> On Tue, Feb 04, 2025 at 10:21:25AM +0100, Krzysztof Kozlowski wrote:
>> On 03/02/2025 18:41, Dmitry Baryshkov wrote:
>>> On Mon, Feb 03, 2025 at 06:29:19PM +0100, Krzysztof Kozlowski wrote:
>>>> 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.
>>>>
>>>> Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
>>>> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>>>>
>>>> ---
>>>>
>>>> Changes in v2:
>>>> 1. Store BIT(4) and BIT(5) in local var in dsi_pll_enable_global_clk()
>>>> ---
>>>> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 35 +++++++++++++++++++------------
>>>> 1 file changed, 22 insertions(+), 13 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>>>> index c164f845653816291ad96c863257f75462ef58e7..e26f53f7cde8f0f6419a633f5d39784dc2e5bb98 100644
>>>> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>>>> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>>>> @@ -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, BIT(5), 0);
>>>> }
>>>>
>>>> static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
>>>> {
>>>> - u32 data;
>>>> + u32 cfg_1 = BIT(5) | BIT(4);
>>>
>>> Please define these two bits too.
>>
>> Why? They were not defined before. This only moving existing code.
>
> Previously it was just a bit magic. Currently you are adding them as
No, previous code:
writel(data | BIT(5) | BIT(4), pll->phy->base +
REG_DSI_7nm_PHY_CMN_CLK_CFG1);
This is a mask and update in the same time, because:
(data & (BIT(5) | BIT(4)) | BIT(5) | BIT(4)
is just redudant.
I did not do any logical change, I did not add any mask or field.
Everything was already there.
> masks. I want to know if BIT(4) and BIT(5) are parts of the same
> bitfield (2 bits wide) or if they define two different bits.
While in general you are right, it does not matter for this fix. If this
are separate bitfields - fix is correct. If this is one bitfield - fix
is still correct. You could claim that if this was one bitfield, using
2xBIT() is not logical, but this was there already, so again my fix is
only fixing and keeping entire logic or inconsistencies intact.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 3/4] drm/msm/dsi/phy: Do not overwite PHY_CMN_CLK_CFG1 when choosing bitclk source
2025-02-04 14:27 ` Dmitry Baryshkov
@ 2025-02-04 15:47 ` Krzysztof Kozlowski
0 siblings, 0 replies; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-04 15:47 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On 04/02/2025 15:27, Dmitry Baryshkov wrote:
>>>> 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);
>>>> @@ -635,7 +634,7 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy)
>>>> }
>>>>
>>>> /* set PLL src */
>>>> - writel(data << 2, base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
>>>> + dsi_pll_cmn_clk_cfg1_update(pll_7nm, GENMASK(3, 2), data << 2);
>>>
>>> The mask is not defined, still.
>>
>> Why would it be? That's old/existing code. Commit is doing only one
>> thing - fixing something. Not introducing some masks or defines and
>> changing hard-coded values into defines.
>
> GENMASK(3, 2) needs to be defined in the XML file. It was not there
> beforehand, you have just introduced it.
You are right.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 4/4] drm/msm/dsi/phy: Define PHY_CMN_CLK_CFG[01] bitfields and simplify saving
2025-02-04 14:28 ` Dmitry Baryshkov
@ 2025-02-04 15:48 ` Krzysztof Kozlowski
2025-02-04 16:06 ` Dmitry Baryshkov
0 siblings, 1 reply; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-04 15:48 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On 04/02/2025 15:28, Dmitry Baryshkov wrote:
>>>> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 31 ++++++++++++----------
>>>> .../gpu/drm/msm/registers/display/dsi_phy_7nm.xml | 12 +++++++--
>>>> 2 files changed, 27 insertions(+), 16 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>>>> index 926fd8e3330b2cdfc69d1e0e5d3930abae77b7d8..b61e75a01e1b69f33548ff0adefc5c92980a15d7 100644
>>>> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>>>> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>>>> @@ -67,8 +67,7 @@ struct dsi_pll_config {
>>>>
>>>> struct pll_7nm_cached_state {
>>>> unsigned long vco_rate;
>>>> - u8 bit_clk_div;
>>>> - u8 pix_clk_div;
>>>> + u8 clk_div;
>>>> u8 pll_out_div;
>>>> u8 pll_mux;
>>>> };
>>>> @@ -401,12 +400,12 @@ static void dsi_pll_cmn_clk_cfg1_update(struct dsi_pll_7nm *pll, u32 mask,
>>>>
>>>> static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
>>>> {
>>>> - dsi_pll_cmn_clk_cfg1_update(pll, BIT(5), 0);
>>>> + 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 cfg_1 = BIT(5) | BIT(4);
>>>> + 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);
>>>> dsi_pll_cmn_clk_cfg1_update(pll, cfg_1, cfg_1);
>>>> @@ -572,15 +571,17 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *phy)
>>>> cached->pll_out_div &= 0x3;
>>>>
>>>> cmn_clk_cfg0 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
>>>> - cached->bit_clk_div = cmn_clk_cfg0 & 0xf;
>>>> - cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;
>>>> + cached->clk_div = cmn_clk_cfg0 & (DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__MASK |
>>>> + DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__MASK);
>>>
>>> Could you rather store these two fields separately by using FIELD_GET?
>>
>> So make the code again more complicated? OK.
>
> It was already there, bit_clk_div and pix_clk_div.
Yes and I (believe) simplified it. It is subjective, so I don't mind
going back to two fields, as you asked.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 4/4] drm/msm/dsi/phy: Define PHY_CMN_CLK_CFG[01] bitfields and simplify saving
2025-02-04 15:48 ` Krzysztof Kozlowski
@ 2025-02-04 16:06 ` Dmitry Baryshkov
0 siblings, 0 replies; 27+ messages in thread
From: Dmitry Baryshkov @ 2025-02-04 16:06 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On Tue, Feb 04, 2025 at 04:48:43PM +0100, Krzysztof Kozlowski wrote:
> On 04/02/2025 15:28, Dmitry Baryshkov wrote:
> >>>> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 31 ++++++++++++----------
> >>>> .../gpu/drm/msm/registers/display/dsi_phy_7nm.xml | 12 +++++++--
> >>>> 2 files changed, 27 insertions(+), 16 deletions(-)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >>>> index 926fd8e3330b2cdfc69d1e0e5d3930abae77b7d8..b61e75a01e1b69f33548ff0adefc5c92980a15d7 100644
> >>>> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >>>> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >>>> @@ -67,8 +67,7 @@ struct dsi_pll_config {
> >>>>
> >>>> struct pll_7nm_cached_state {
> >>>> unsigned long vco_rate;
> >>>> - u8 bit_clk_div;
> >>>> - u8 pix_clk_div;
> >>>> + u8 clk_div;
> >>>> u8 pll_out_div;
> >>>> u8 pll_mux;
> >>>> };
> >>>> @@ -401,12 +400,12 @@ static void dsi_pll_cmn_clk_cfg1_update(struct dsi_pll_7nm *pll, u32 mask,
> >>>>
> >>>> static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
> >>>> {
> >>>> - dsi_pll_cmn_clk_cfg1_update(pll, BIT(5), 0);
> >>>> + 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 cfg_1 = BIT(5) | BIT(4);
> >>>> + 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);
> >>>> dsi_pll_cmn_clk_cfg1_update(pll, cfg_1, cfg_1);
> >>>> @@ -572,15 +571,17 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *phy)
> >>>> cached->pll_out_div &= 0x3;
> >>>>
> >>>> cmn_clk_cfg0 = readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0);
> >>>> - cached->bit_clk_div = cmn_clk_cfg0 & 0xf;
> >>>> - cached->pix_clk_div = (cmn_clk_cfg0 & 0xf0) >> 4;
> >>>> + cached->clk_div = cmn_clk_cfg0 & (DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0__MASK |
> >>>> + DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4__MASK);
> >>>
> >>> Could you rather store these two fields separately by using FIELD_GET?
> >>
> >> So make the code again more complicated? OK.
> >
> > It was already there, bit_clk_div and pix_clk_div.
>
>
> Yes and I (believe) simplified it. It is subjective, so I don't mind
> going back to two fields, as you asked.
I'd prefer it this way, thank you.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 2/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver
2025-02-04 15:46 ` Krzysztof Kozlowski
@ 2025-02-05 2:51 ` Dmitry Baryshkov
2025-02-05 9:34 ` Krzysztof Kozlowski
0 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2025-02-05 2:51 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On Tue, Feb 04, 2025 at 04:46:04PM +0100, Krzysztof Kozlowski wrote:
> On 04/02/2025 15:26, Dmitry Baryshkov wrote:
> > On Tue, Feb 04, 2025 at 10:21:25AM +0100, Krzysztof Kozlowski wrote:
> >> On 03/02/2025 18:41, Dmitry Baryshkov wrote:
> >>> On Mon, Feb 03, 2025 at 06:29:19PM +0100, Krzysztof Kozlowski wrote:
> >>>> 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.
> >>>>
> >>>> Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
> >>>> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> >>>>
> >>>> ---
> >>>>
> >>>> Changes in v2:
> >>>> 1. Store BIT(4) and BIT(5) in local var in dsi_pll_enable_global_clk()
> >>>> ---
> >>>> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 35 +++++++++++++++++++------------
> >>>> 1 file changed, 22 insertions(+), 13 deletions(-)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >>>> index c164f845653816291ad96c863257f75462ef58e7..e26f53f7cde8f0f6419a633f5d39784dc2e5bb98 100644
> >>>> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >>>> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >>>> @@ -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, BIT(5), 0);
> >>>> }
> >>>>
> >>>> static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
> >>>> {
> >>>> - u32 data;
> >>>> + u32 cfg_1 = BIT(5) | BIT(4);
> >>>
> >>> Please define these two bits too.
> >>
> >> Why? They were not defined before. This only moving existing code.
> >
> > Previously it was just a bit magic. Currently you are adding them as
>
> No, previous code:
>
> writel(data | BIT(5) | BIT(4), pll->phy->base +
> REG_DSI_7nm_PHY_CMN_CLK_CFG1);
>
> This is a mask and update in the same time, because:
> (data & (BIT(5) | BIT(4)) | BIT(5) | BIT(4)
> is just redudant.
>
> I did not do any logical change, I did not add any mask or field.
> Everything was already there.
Yes... and no. Previously it was just writel(foo | BIT(5) | BIT(4)). Now
your code adds BIT(5) as a 'mask' parameter. Is it a correct mask for
that field? That's why I'm asking you to define those - you have changed
bitwrites to the masked bit writes. Masks should be defined.
>
>
> > masks. I want to know if BIT(4) and BIT(5) are parts of the same
> > bitfield (2 bits wide) or if they define two different bits.
>
> While in general you are right, it does not matter for this fix. If this
> are separate bitfields - fix is correct. If this is one bitfield - fix
> is still correct. You could claim that if this was one bitfield, using
> 2xBIT() is not logical, but this was there already, so again my fix is
> only fixing and keeping entire logic or inconsistencies intact.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 2/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver
2025-02-05 2:51 ` Dmitry Baryshkov
@ 2025-02-05 9:34 ` Krzysztof Kozlowski
2025-02-05 11:23 ` Dmitry Baryshkov
0 siblings, 1 reply; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-05 9:34 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On 05/02/2025 03:51, Dmitry Baryshkov wrote:
> On Tue, Feb 04, 2025 at 04:46:04PM +0100, Krzysztof Kozlowski wrote:
>> On 04/02/2025 15:26, Dmitry Baryshkov wrote:
>>> On Tue, Feb 04, 2025 at 10:21:25AM +0100, Krzysztof Kozlowski wrote:
>>>> On 03/02/2025 18:41, Dmitry Baryshkov wrote:
>>>>> On Mon, Feb 03, 2025 at 06:29:19PM +0100, Krzysztof Kozlowski wrote:
>>>>>> 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.
>>>>>>
>>>>>> Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
>>>>>> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>>>>>>
>>>>>> ---
>>>>>>
>>>>>> Changes in v2:
>>>>>> 1. Store BIT(4) and BIT(5) in local var in dsi_pll_enable_global_clk()
>>>>>> ---
>>>>>> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 35 +++++++++++++++++++------------
>>>>>> 1 file changed, 22 insertions(+), 13 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>>>>>> index c164f845653816291ad96c863257f75462ef58e7..e26f53f7cde8f0f6419a633f5d39784dc2e5bb98 100644
>>>>>> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>>>>>> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
>>>>>> @@ -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, BIT(5), 0);
>>>>>> }
>>>>>>
>>>>>> static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
>>>>>> {
>>>>>> - u32 data;
>>>>>> + u32 cfg_1 = BIT(5) | BIT(4);
>>>>>
>>>>> Please define these two bits too.
>>>>
>>>> Why? They were not defined before. This only moving existing code.
>>>
>>> Previously it was just a bit magic. Currently you are adding them as
>>
>> No, previous code:
>>
>> writel(data | BIT(5) | BIT(4), pll->phy->base +
>> REG_DSI_7nm_PHY_CMN_CLK_CFG1);
>>
>> This is a mask and update in the same time, because:
>> (data & (BIT(5) | BIT(4)) | BIT(5) | BIT(4)
>> is just redudant.
>>
>> I did not do any logical change, I did not add any mask or field.
>> Everything was already there.
>
> Yes... and no. Previously it was just writel(foo | BIT(5) | BIT(4)). Now
You did not address my comment. Previous code was:
(foo & (BIT(5) | BIT(4)) | BIT(5) | BIT(4)
Just for shorter syntax it was written different way:
foo | BIT(5) | BIT(4)
> your code adds BIT(5) as a 'mask' parameter. Is it a correct mask for
No, my code does not add it. It was already there, look:
foo | BIT(5) | BIT(4)
^^^^^^^ here
> that field? That's why I'm asking you to define those - you have changed
No, I did not change bitwrites. The code is 100% equivalent, both
logically and assembly.
You mistake maybe with some other part doing "writel(data & ~BIT(5)" in
dsi_pll_disable_global_clk() but that's just poor diff.
> bitwrites to the masked bit writes. Masks should be defined.
>
>>
>>
>>> masks. I want to know if BIT(4) and BIT(5) are parts of the same
>>> bitfield (2 bits wide) or if they define two different bits.
>>
>> While in general you are right, it does not matter for this fix. If this
>> are separate bitfields - fix is correct. If this is one bitfield - fix
>> is still correct. You could claim that if this was one bitfield, using
>> 2xBIT() is not logical, but this was there already, so again my fix is
>> only fixing and keeping entire logic or inconsistencies intact.
>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 2/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver
2025-02-05 9:34 ` Krzysztof Kozlowski
@ 2025-02-05 11:23 ` Dmitry Baryshkov
2025-02-05 13:42 ` Krzysztof Kozlowski
0 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2025-02-05 11:23 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
Hi,
On Wed, 5 Feb 2025 at 11:34, Krzysztof Kozlowski
<krzysztof.kozlowski@linaro.org> wrote:
>
> On 05/02/2025 03:51, Dmitry Baryshkov wrote:
> > On Tue, Feb 04, 2025 at 04:46:04PM +0100, Krzysztof Kozlowski wrote:
> >> On 04/02/2025 15:26, Dmitry Baryshkov wrote:
> >>> On Tue, Feb 04, 2025 at 10:21:25AM +0100, Krzysztof Kozlowski wrote:
> >>>> On 03/02/2025 18:41, Dmitry Baryshkov wrote:
> >>>>> On Mon, Feb 03, 2025 at 06:29:19PM +0100, Krzysztof Kozlowski wrote:
> >>>>>> 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.
> >>>>>>
> >>>>>> Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
> >>>>>> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> >>>>>>
> >>>>>> ---
> >>>>>>
> >>>>>> Changes in v2:
> >>>>>> 1. Store BIT(4) and BIT(5) in local var in dsi_pll_enable_global_clk()
> >>>>>> ---
> >>>>>> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 35 +++++++++++++++++++------------
> >>>>>> 1 file changed, 22 insertions(+), 13 deletions(-)
> >>>>>>
> >>>>>> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >>>>>> index c164f845653816291ad96c863257f75462ef58e7..e26f53f7cde8f0f6419a633f5d39784dc2e5bb98 100644
> >>>>>> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >>>>>> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> >>>>>> @@ -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, BIT(5), 0);
> >>>>>> }
> >>>>>>
> >>>>>> static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
> >>>>>> {
> >>>>>> - u32 data;
> >>>>>> + u32 cfg_1 = BIT(5) | BIT(4);
> >>>>>
> >>>>> Please define these two bits too.
> >>>>
> >>>> Why? They were not defined before. This only moving existing code.
> >>>
> >>> Previously it was just a bit magic. Currently you are adding them as
> >>
> >> No, previous code:
> >>
> >> writel(data | BIT(5) | BIT(4), pll->phy->base +
> >> REG_DSI_7nm_PHY_CMN_CLK_CFG1);
> >>
> >> This is a mask and update in the same time, because:
> >> (data & (BIT(5) | BIT(4)) | BIT(5) | BIT(4)
> >> is just redudant.
> >>
> >> I did not do any logical change, I did not add any mask or field.
> >> Everything was already there.
> >
> > Yes... and no. Previously it was just writel(foo | BIT(5) | BIT(4)). Now
>
> You did not address my comment. Previous code was:
>
> (foo & (BIT(5) | BIT(4)) | BIT(5) | BIT(4)
>
> Just for shorter syntax it was written different way:
>
> foo | BIT(5) | BIT(4)
Previously it was a simple writel() with some bit magic. Now you call
dsi_pll_cmn_clk_cfg1_update() passing the register bit field through
the 'mask' argument. I'm asking to get those masks defined. Is it
possible?
Yes, the code is equivalent and results in the same values being
written to the same registers.
At the same time you have added a logical entity, a masked write. I
want to be able to understand if bits 4 and 5 are a part of the same
register field or they belong to two different fields and can be
written separately. I really don't understand why are we spending so
much time arguing about a simple #define. Okay, in case of drm/msm it
is not a #define, it is <reg><bitfield/></reg>. The net result is the
same.
>
> > your code adds BIT(5) as a 'mask' parameter. Is it a correct mask for
>
> No, my code does not add it. It was already there, look:
>
> foo | BIT(5) | BIT(4)
> ^^^^^^^ here
>
>
> > that field? That's why I'm asking you to define those - you have changed
>
> No, I did not change bitwrites. The code is 100% equivalent, both
> logically and assembly.
>
> You mistake maybe with some other part doing "writel(data & ~BIT(5)" in
> dsi_pll_disable_global_clk() but that's just poor diff.
>
> > bitwrites to the masked bit writes. Masks should be defined.
> >
> >>
> >>
> >>> masks. I want to know if BIT(4) and BIT(5) are parts of the same
> >>> bitfield (2 bits wide) or if they define two different bits.
> >>
> >> While in general you are right, it does not matter for this fix. If this
> >> are separate bitfields - fix is correct. If this is one bitfield - fix
> >> is still correct. You could claim that if this was one bitfield, using
> >> 2xBIT() is not logical, but this was there already, so again my fix is
> >> only fixing and keeping entire logic or inconsistencies intact.
> >
>
>
> Best regards,
> Krzysztof
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 2/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver
2025-02-05 11:23 ` Dmitry Baryshkov
@ 2025-02-05 13:42 ` Krzysztof Kozlowski
2025-02-05 14:51 ` Dmitry Baryshkov
0 siblings, 1 reply; 27+ messages in thread
From: Krzysztof Kozlowski @ 2025-02-05 13:42 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On 05/02/2025 12:23, Dmitry Baryshkov wrote:
>>>>>>>> +
>>>>>>>> +static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
>>>>>>>> +{
>>>>>>>> + dsi_pll_cmn_clk_cfg1_update(pll, BIT(5), 0);
>>>>>>>> }
>>>>>>>>
>>>>>>>> static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
>>>>>>>> {
>>>>>>>> - u32 data;
>>>>>>>> + u32 cfg_1 = BIT(5) | BIT(4);
>>>>>>>
>>>>>>> Please define these two bits too.
>>>>>>
>>>>>> Why? They were not defined before. This only moving existing code.
>>>>>
>>>>> Previously it was just a bit magic. Currently you are adding them as
>>>>
>>>> No, previous code:
>>>>
>>>> writel(data | BIT(5) | BIT(4), pll->phy->base +
>>>> REG_DSI_7nm_PHY_CMN_CLK_CFG1);
>>>>
>>>> This is a mask and update in the same time, because:
>>>> (data & (BIT(5) | BIT(4)) | BIT(5) | BIT(4)
>>>> is just redudant.
>>>>
>>>> I did not do any logical change, I did not add any mask or field.
>>>> Everything was already there.
>>>
>>> Yes... and no. Previously it was just writel(foo | BIT(5) | BIT(4)). Now
>>
>> You did not address my comment. Previous code was:
>>
>> (foo & (BIT(5) | BIT(4)) | BIT(5) | BIT(4)
>>
>> Just for shorter syntax it was written different way:
>>
>> foo | BIT(5) | BIT(4)
>
> Previously it was a simple writel() with some bit magic. Now you call
The mask was already there, just implied.
> dsi_pll_cmn_clk_cfg1_update() passing the register bit field through
> the 'mask' argument. I'm asking to get those masks defined. Is it
> possible?
Just like before, because implied mask is being removed due to code
redundancy.
I repeat it for third time already.
>
> Yes, the code is equivalent and results in the same values being
> written to the same registers.
> At the same time you have added a logical entity, a masked write. I
> want to be able to understand if bits 4 and 5 are a part of the same
> register field or they belong to two different fields and can be
I know you want to understand it and this is achieved in separate patch,
because understanding this is not related to this commit.
> written separately. I really don't understand why are we spending so
> much time arguing about a simple #define. Okay, in case of drm/msm it
> is not a #define, it is <reg><bitfield/></reg>. The net result is the
> same.
I also don't get why simple fix could not be just applied and it has to
become some sort of big refactoring.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 2/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver
2025-02-05 13:42 ` Krzysztof Kozlowski
@ 2025-02-05 14:51 ` Dmitry Baryshkov
0 siblings, 0 replies; 27+ messages in thread
From: Dmitry Baryshkov @ 2025-02-05 14:51 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Clark, Abhinav Kumar, Sean Paul, Marijn Suijten,
David Airlie, Simona Vetter, linux-arm-msm, dri-devel, freedreno,
linux-kernel
On Wed, Feb 05, 2025 at 02:42:03PM +0100, Krzysztof Kozlowski wrote:
> On 05/02/2025 12:23, Dmitry Baryshkov wrote:
> >>>>>>>> +
> >>>>>>>> +static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll)
> >>>>>>>> +{
> >>>>>>>> + dsi_pll_cmn_clk_cfg1_update(pll, BIT(5), 0);
> >>>>>>>> }
> >>>>>>>>
> >>>>>>>> static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll)
> >>>>>>>> {
> >>>>>>>> - u32 data;
> >>>>>>>> + u32 cfg_1 = BIT(5) | BIT(4);
> >>>>>>>
> >>>>>>> Please define these two bits too.
> >>>>>>
> >>>>>> Why? They were not defined before. This only moving existing code.
> >>>>>
> >>>>> Previously it was just a bit magic. Currently you are adding them as
> >>>>
> >>>> No, previous code:
> >>>>
> >>>> writel(data | BIT(5) | BIT(4), pll->phy->base +
> >>>> REG_DSI_7nm_PHY_CMN_CLK_CFG1);
> >>>>
> >>>> This is a mask and update in the same time, because:
> >>>> (data & (BIT(5) | BIT(4)) | BIT(5) | BIT(4)
> >>>> is just redudant.
> >>>>
> >>>> I did not do any logical change, I did not add any mask or field.
> >>>> Everything was already there.
> >>>
> >>> Yes... and no. Previously it was just writel(foo | BIT(5) | BIT(4)). Now
> >>
> >> You did not address my comment. Previous code was:
> >>
> >> (foo & (BIT(5) | BIT(4)) | BIT(5) | BIT(4)
> >>
> >> Just for shorter syntax it was written different way:
> >>
> >> foo | BIT(5) | BIT(4)
> >
> > Previously it was a simple writel() with some bit magic. Now you call
>
>
> The mask was already there, just implied.
>
> > dsi_pll_cmn_clk_cfg1_update() passing the register bit field through
> > the 'mask' argument. I'm asking to get those masks defined. Is it
> > possible?
>
> Just like before, because implied mask is being removed due to code
> redundancy.
>
> I repeat it for third time already.
>
> >
> > Yes, the code is equivalent and results in the same values being
> > written to the same registers.
> > At the same time you have added a logical entity, a masked write. I
> > want to be able to understand if bits 4 and 5 are a part of the same
> > register field or they belong to two different fields and can be
>
> I know you want to understand it and this is achieved in separate patch,
> because understanding this is not related to this commit.
>
> > written separately. I really don't understand why are we spending so
> > much time arguing about a simple #define. Okay, in case of drm/msm it
> > is not a #define, it is <reg><bitfield/></reg>. The net result is the
> > same.
>
> I also don't get why simple fix could not be just applied and it has to
> become some sort of big refactoring.
Well, you have refactored that in this patch. Anyway. Please post the
next iteration, let's continue the dicussion there.
>
> Best regards,
> Krzysztof
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG0 updated from driver side
2025-02-03 17:29 ` [PATCH v2 1/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG0 updated from driver side Krzysztof Kozlowski
2025-02-03 17:42 ` Dmitry Baryshkov
@ 2025-02-11 0:26 ` Abhinav Kumar
1 sibling, 0 replies; 27+ messages in thread
From: Abhinav Kumar @ 2025-02-11 0:26 UTC (permalink / raw)
To: Krzysztof Kozlowski, Rob Clark, Dmitry Baryshkov, Sean Paul,
Marijn Suijten, David Airlie, Simona Vetter
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 2/3/2025 9:29 AM, Krzysztof Kozlowski wrote:
> PHY_CMN_CLK_CFG0 register is updated by the PHY driver and by two
> divider clocks from Common Clock Framework:
> devm_clk_hw_register_divider_parent_hw(). Concurrent access by the
> clocks side is protected with spinlock, however driver's side in
> restoring state is not. Restoring state is called from
> msm_dsi_phy_enable(), so there could be a path leading to concurrent and
> conflicting updates with clock framework.
>
> Add missing lock usage on the PHY driver side, encapsulated in its own
> function so the code will be still readable.
>
> Fixes: 1ef7c99d145c ("drm/msm/dsi: add support for 7nm DSI PHY/PLL")
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> ---
> drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 13 +++++++++++--
> 1 file changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> index 031446c87daec0af3f81df324158311f5a80014e..c164f845653816291ad96c863257f75462ef58e7 100644
> --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
> @@ -372,6 +372,15 @@ static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll)
> ndelay(250);
> }
>
Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2025-02-11 0:26 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-02-03 17:29 [PATCH v2 0/4] drm/msm/dsi/phy: Improvements around concurrent PHY_CMN_CLK_CFG[01] Krzysztof Kozlowski
2025-02-03 17:29 ` [PATCH v2 1/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG0 updated from driver side Krzysztof Kozlowski
2025-02-03 17:42 ` Dmitry Baryshkov
2025-02-04 9:20 ` Krzysztof Kozlowski
2025-02-04 14:21 ` Dmitry Baryshkov
2025-02-11 0:26 ` Abhinav Kumar
2025-02-03 17:29 ` [PATCH v2 2/4] drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver Krzysztof Kozlowski
2025-02-03 17:41 ` Dmitry Baryshkov
2025-02-04 9:21 ` Krzysztof Kozlowski
2025-02-04 14:26 ` Dmitry Baryshkov
2025-02-04 15:46 ` Krzysztof Kozlowski
2025-02-05 2:51 ` Dmitry Baryshkov
2025-02-05 9:34 ` Krzysztof Kozlowski
2025-02-05 11:23 ` Dmitry Baryshkov
2025-02-05 13:42 ` Krzysztof Kozlowski
2025-02-05 14:51 ` Dmitry Baryshkov
2025-02-03 17:29 ` [PATCH v2 3/4] drm/msm/dsi/phy: Do not overwite PHY_CMN_CLK_CFG1 when choosing bitclk source Krzysztof Kozlowski
2025-02-03 17:40 ` Dmitry Baryshkov
2025-02-04 9:22 ` Krzysztof Kozlowski
2025-02-04 14:27 ` Dmitry Baryshkov
2025-02-04 15:47 ` Krzysztof Kozlowski
2025-02-03 17:29 ` [PATCH v2 4/4] drm/msm/dsi/phy: Define PHY_CMN_CLK_CFG[01] bitfields and simplify saving Krzysztof Kozlowski
2025-02-03 17:58 ` Dmitry Baryshkov
2025-02-04 9:24 ` Krzysztof Kozlowski
2025-02-04 14:28 ` Dmitry Baryshkov
2025-02-04 15:48 ` Krzysztof Kozlowski
2025-02-04 16:06 ` Dmitry Baryshkov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®