From nobody Tue Feb 10 06:10:05 2026 Received: from mail-wm1-f52.google.com (mail-wm1-f52.google.com [209.85.128.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 04CD22D0289 for ; Tue, 10 Jun 2025 14:06:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749564390; cv=none; b=BN8Zbcxx5DEnNk5HbLzvaQvJuVWF0trajc1fAnFi0jz/qy4ODtl36yeJg9bBOyWgRMS2+fC8D8xxX3skRFvyAfgSjMt3HK9TpOi+vkxdoQaJN3f1rU0Sq8lOiqZSFIqxs+0p3Z48Ut6ARYJHn8QRmkejIxolwoxusLZ+kxm32fE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749564390; c=relaxed/simple; bh=JEggE4aGkw0e9clcohgBckgczcMgMJlvG2hLK8vTaTQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dkBD1bqHXJ9pNOrMkTkZQUj9c2xqXsh0d5AxA+4ImFUw2yN8s+QLXeL/cZwnghY+jEGU/MpsHmYcr8N9nMzz88oEhTWkwUylTw+mJvY9bGKOUbKvBwUdCQACNrk6fCsp305uwAqQqk6ckmBkfJMOiWDbKawEEBhrDRfvd6tJaNI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=pGk7n5Cr; arc=none smtp.client-ip=209.85.128.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="pGk7n5Cr" Received: by mail-wm1-f52.google.com with SMTP id 5b1f17b1804b1-45306976410so630795e9.3 for ; Tue, 10 Jun 2025 07:06:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1749564386; x=1750169186; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=c1KnLM1NPxNXZz/8JZFIjv2R+0TiPb/2BYtiypsnLxI=; b=pGk7n5CrbX373Yx8bi8FiXY3eJ0NYgX7DDqeR0obLo2T326I5i6w8jzWS0dzAjPXp/ /7QG8iSJ+FLVORiRgIhIaxDF/1Gch9qdRKhSiVB2ayEI4eLfhSCp2TByA+OURn7JwXAA Ct0396iqcz73ZHQj9z7DBZMCtzMjl//0lneF9U9FYH+2nb5NTu917cSIvabV4+28mbqF rjZHQP6o/40V+Eh8hwU1KOxaI0/LTSq0bDEjLYo10AJeD3HH74X45htOBZbFSgObTEq+ eRQPcsAJ3eqlQqgN4Gw7encIDhCDDZDN8DegK08qx31rR1ukeZjr78Z3IRi9n5rEO+ee XQRA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749564386; x=1750169186; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=c1KnLM1NPxNXZz/8JZFIjv2R+0TiPb/2BYtiypsnLxI=; b=Fku2AhUnR8VASFXaGXwN/T8vk/vzOWU4+ereGkzQgcu1YF8puklMxNh50+di4mTQkK obEDDRJjR/f1E3u0fiyzab5oSHGLDiV9ILsHGLoHzYa0Orte29pB6Tf18mWj0NQWVA3L zGNldufIdNxfZceMHxRvzbWC2sbh/xJw8oDXrKW7omKYnkcY3GakK6VdZn4hBjm2log6 ZepU2uCoIZyFRULqhzarCenifeWYrY+HDaImu8isX7szzEftEbXuwsSikREFVwkiKVMX j8nHwko6t8aKaZqdRMsWnTb/iReq7hw2pSItSuTh0ZFoQ8bQrZMLmkjaiWPgpsGX5UHg B8LA== X-Forwarded-Encrypted: i=1; AJvYcCUZur6cBMIFOVAvPfFQm9pkY7SyQZyELiR83kNxBm4Fy7ndGIOHtWMEza59g1AqVav8dUUaDEgv/oL3aAg=@vger.kernel.org X-Gm-Message-State: AOJu0Yz/W8mqZvxRxvO78OK4KCdjNSd+Xjqlct0ydOaQe1PYP7Lmkapt wmtDRSUaN+zfSr7Rd3u8Y1JlIiXmi1/35XAeX+3eZRmz4p9iSMBZBFi2CQqKcKHk7Cw= X-Gm-Gg: ASbGncv/Z4H5sZqBlzWGIMcq1ih/FtNDvl1WiD6nL2AJpgIpR8EUeARtg1QW3iNUSMX O8RojvM0nm3tkTJqqQAmmPEtFugBfkD2H75OObZsfv3QpygQTyw9eCBrdA37DRIjj++D6H+Rm/V Ufa9Qkp7NW7iiXpdRL4zkHrkAoRuLmjpEy0s/w1g9LRV1eLdkUpH8FimVBq2Zm4r98do4FEsZBx PlNVWHkBDrNouoolLhR2OUGDC1xphCOxIW7i+ITZpfVYw4ZCU1WYgEwmfcfCS4e2Z3vsae3Zm9D 5xaLkJmSc8U9zUaogKcT98zKLkxxxgWin5Ccg7+ZXfYOpA3fgXxZoZIXloUoHoF7bbLXVrqPbPT keHlbyg== X-Google-Smtp-Source: AGHT+IEwWcvYaimoww5hM1GBZ3AEqmQUQ5RJD+K72W8jKVRT3hyLsep9VyFM47tqr7v/rXlXGRe5sg== X-Received: by 2002:a05:600c:350f:b0:451:eed7:6d76 with SMTP id 5b1f17b1804b1-4530538bc36mr37681375e9.8.1749564386213; Tue, 10 Jun 2025 07:06:26 -0700 (PDT) Received: from [192.168.1.29] ([178.197.223.125]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a53244df06sm12734469f8f.69.2025.06.10.07.06.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 10 Jun 2025 07:06:25 -0700 (PDT) From: Krzysztof Kozlowski Date: Tue, 10 Jun 2025 16:05:46 +0200 Subject: [PATCH v6 08/17] drm/msm/dsi/phy: Fix reading zero as PLL rates when unprepared Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250610-b4-sm8750-display-v6-8-ee633e3ddbff@linaro.org> References: <20250610-b4-sm8750-display-v6-0-ee633e3ddbff@linaro.org> In-Reply-To: <20250610-b4-sm8750-display-v6-0-ee633e3ddbff@linaro.org> To: Abhinav Kumar , Sean Paul , Marijn Suijten , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Krishna Manikandan , Jonathan Marek , Kuogee Hsieh , Neil Armstrong , Dmitry Baryshkov , Bjorn Andersson , Michael Turquette , Stephen Boyd , Rob Clark Cc: linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Krzysztof Kozlowski , linux-clk@vger.kernel.org, Abel Vesa , Srinivas Kandagatla , Rob Clark X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=8466; i=krzysztof.kozlowski@linaro.org; h=from:subject:message-id; bh=JEggE4aGkw0e9clcohgBckgczcMgMJlvG2hLK8vTaTQ=; b=owEBbQKS/ZANAwAKAcE3ZuaGi4PXAcsmYgBoSDvGiQKQC/7r4PPleERPmdWoG8uIMN39/Siti IjU1gMyb5CJAjMEAAEKAB0WIQTd0mIoPREbIztuuKjBN2bmhouD1wUCaEg7xgAKCRDBN2bmhouD 110hD/4jJB2SuxaT5PB9fySSb4OSXk43iif0GUV+JRpbsLOlXL1dvUFFc+O/gYf2qppQ10L9Nnw ZHnw4E60dYCzRvwyFBDtRZkgBjyZnFgiL10/1R6rrSan27IPiJ6CHRIESiFLHUrv3M+dmMscQLB DM7wfVkopFxOMgFD9fH1Umw8NNYWAjCy2+U6TyLB6nxaTs6eUUGlEEjEGlE3kXpSIrjaJc86Ozw aAHdPqjdeUjDDy4Curi2ymKMnndcbVIxHTf6cK3MbAvCFOyg2rB5GnpRkbbKcvK9ammiZGomvkz 4aHttLnObh2jN0JE58h1Tt1CPzy3Z2kGZtdYW2qLUp7bdYsEvktu7ee7P3tG6PblW6TPb0CFXCb swLjiewCjfsJqkUEFkQ7kQoG1RmTbHmkBLZdP3Y2ejBgDnBr4hLpZeFYn5JTDjYCLHcD1x344rp r5q2PDLBE3/kCISSRAJmFrtCk2VQ8B2LkL4kKG/Bf6qKwiV6GUV84m71NncwGD7d8/5fj/oT8VT suiV+7oOdh4u9KBXKUoNPOupzq1ve+bEuJJtebx4rpdvNC5SV/iA4ju0oIRQpVrJyMJPRbDznBX z9c64HMpEFh9315j52fcSrqX/GV9x+8QrWrVKLszuy5SoASwg2VIp0KGp3QlGmwsaOJLitpB2b5 mL0CG2i7a0dpuZw== X-Developer-Key: i=krzysztof.kozlowski@linaro.org; a=openpgp; fpr=9BD07E0E0C51F8D59677B7541B93437D3B41629B Hardware Programming Guide for DSI PHY says that PLL_SHUTDOWNB and DIGTOP_PWRDN_B have to be asserted for any PLL register access. Whenever dsi_pll_7nm_vco_recalc_rate() or dsi_pll_7nm_vco_set_rate() were called on unprepared PLL, driver read values of zero leading to all sort of further troubles, like failing to set pixel and byte clock rates. Asserting the PLL shutdown bit is done by dsi_pll_enable_pll_bias() (and corresponding dsi_pll_disable_pll_bias()) which are called through the code, including from PLL .prepare() and .unprepare() callbacks. The .set_rate() and .recalc_rate() can be called almost anytime from external users including times when PLL is or is not prepared, thus driver should not interfere with the prepare status. Implement simple reference counting for the PLL bias, so set_rate/recalc_rate will not change the status of prepared PLL. Issue of reading 0 in .recalc_rate() did not show up on existing devices, but only after re-ordering the code for SM8750. Signed-off-by: Krzysztof Kozlowski --- Changes in v6: 1. Print error on pll bias enable/disable imbalance refcnt Changes in v5: 1. New patch --- drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 1 + drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 53 +++++++++++++++++++++++++++= ++++ 2 files changed, 54 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/ds= i/phy/dsi_phy.h index 7ea608f620fe17ae4ccc41ba9e52ba043af0c022..82baec385b3224c8b3e36742230= d806c4fe68cbb 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h @@ -109,6 +109,7 @@ struct msm_dsi_phy { struct msm_dsi_dphy_timing timing; const struct msm_dsi_phy_cfg *cfg; void *tuning_cfg; + void *pll_data; =20 enum msm_dsi_phy_usecase usecase; bool regulator_ldo_mode; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/ms= m/dsi/phy/dsi_phy_7nm.c index 4df865dfe6fe111297f0d08199c515d3b5e5a0b6..22f80e99a7a7514085ef80ced1c= f78876bcc6ba3 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -88,6 +88,13 @@ struct dsi_pll_7nm { /* protects REG_DSI_7nm_PHY_CMN_CLK_CFG1 register */ spinlock_t pclk_mux_lock; =20 + /* + * protects REG_DSI_7nm_PHY_CMN_CTRL_0 register and pll_enable_cnt + * member + */ + spinlock_t pll_enable_lock; + int pll_enable_cnt; + struct pll_7nm_cached_state cached_state; =20 struct dsi_pll_7nm *slave; @@ -101,6 +108,9 @@ struct dsi_pll_7nm { */ static struct dsi_pll_7nm *pll_7nm_list[DSI_MAX]; =20 +static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll); +static void dsi_pll_disable_pll_bias(struct dsi_pll_7nm *pll); + static void dsi_pll_setup_config(struct dsi_pll_config *config) { config->ssc_freq =3D 31500; @@ -316,6 +326,7 @@ static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, = unsigned long rate, struct dsi_pll_7nm *pll_7nm =3D to_pll_7nm(hw); struct dsi_pll_config config; =20 + dsi_pll_enable_pll_bias(pll_7nm); DBG("DSI PLL%d rate=3D%lu, parent's=3D%lu", pll_7nm->phy->id, rate, parent_rate); =20 @@ -333,6 +344,7 @@ static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, = unsigned long rate, =20 dsi_pll_ssc_commit(pll_7nm, &config); =20 + dsi_pll_disable_pll_bias(pll_7nm); /* flush, ensure all register writes are done*/ wmb(); =20 @@ -361,24 +373,47 @@ static int dsi_pll_7nm_lock_status(struct dsi_pll_7nm= *pll) =20 static void dsi_pll_disable_pll_bias(struct dsi_pll_7nm *pll) { + unsigned long flags; u32 data; =20 + spin_lock_irqsave(&pll->pll_enable_lock, flags); + --pll->pll_enable_cnt; + if (pll->pll_enable_cnt < 0) { + spin_unlock_irqrestore(&pll->pll_enable_lock, flags); + DRM_DEV_ERROR_RATELIMITED(&pll->phy->pdev->dev, + "bug: imbalance in disabling PLL bias\n"); + return; + } else if (pll->pll_enable_cnt > 0) { + spin_unlock_irqrestore(&pll->pll_enable_lock, flags); + return; + } /* else: =3D=3D 0 */ + data =3D readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); data &=3D ~DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB; writel(0, pll->phy->pll_base + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES); writel(data, pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); + spin_unlock_irqrestore(&pll->pll_enable_lock, flags); ndelay(250); } =20 static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll) { + unsigned long flags; u32 data; =20 + spin_lock_irqsave(&pll->pll_enable_lock, flags); + if (pll->pll_enable_cnt++) { + spin_unlock_irqrestore(&pll->pll_enable_lock, flags); + WARN_ON(pll->pll_enable_cnt =3D=3D INT_MAX); + return; + } + data =3D readl(pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); data |=3D DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB; writel(data, pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_0); =20 writel(0xc0, pll->phy->pll_base + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES); + spin_unlock_irqrestore(&pll->pll_enable_lock, flags); ndelay(250); } =20 @@ -519,6 +554,7 @@ static unsigned long dsi_pll_7nm_vco_recalc_rate(struct= clk_hw *hw, u32 dec; u64 pll_freq, tmp64; =20 + dsi_pll_enable_pll_bias(pll_7nm); dec =3D readl(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1); dec &=3D 0xff; =20 @@ -543,6 +579,8 @@ static unsigned long dsi_pll_7nm_vco_recalc_rate(struct= clk_hw *hw, DBG("DSI PLL%d returning vco rate =3D %lu, dec =3D %x, frac =3D %x", pll_7nm->phy->id, (unsigned long)vco_rate, dec, frac); =20 + dsi_pll_disable_pll_bias(pll_7nm); + return (unsigned long)vco_rate; } =20 @@ -578,6 +616,7 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *= phy) void __iomem *phy_base =3D pll_7nm->phy->base; u32 cmn_clk_cfg0, cmn_clk_cfg1; =20 + dsi_pll_enable_pll_bias(pll_7nm); cached->pll_out_div =3D readl(pll_7nm->phy->pll_base + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE); cached->pll_out_div &=3D 0x3; @@ -589,6 +628,7 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *= phy) cmn_clk_cfg1 =3D readl(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); cached->pll_mux =3D FIELD_GET(DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK, = cmn_clk_cfg1); =20 + dsi_pll_disable_pll_bias(pll_7nm); 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); @@ -807,8 +847,10 @@ static int dsi_pll_7nm_init(struct msm_dsi_phy *phy) =20 spin_lock_init(&pll_7nm->postdiv_lock); spin_lock_init(&pll_7nm->pclk_mux_lock); + spin_lock_init(&pll_7nm->pll_enable_lock); =20 pll_7nm->phy =3D phy; + phy->pll_data =3D pll_7nm; =20 ret =3D pll_7nm_register(pll_7nm, phy->provided_clocks->hws); if (ret) { @@ -891,8 +933,10 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, u32 const delay_us =3D 5; u32 const timeout_us =3D 1000; struct msm_dsi_dphy_timing *timing =3D &phy->timing; + struct dsi_pll_7nm *pll =3D phy->pll_data; void __iomem *base =3D phy->base; bool less_than_1500_mhz; + unsigned long flags; u32 vreg_ctrl_0, vreg_ctrl_1, lane_ctrl0; u32 glbl_pemph_ctrl_0; u32 glbl_str_swi_cal_sel_ctrl, glbl_hstx_str_ctrl_0; @@ -1000,10 +1044,13 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *p= hy, glbl_rescode_bot_ctrl =3D 0x3c; } =20 + spin_lock_irqsave(&pll->pll_enable_lock, flags); + pll->pll_enable_cnt =3D 1; /* de-assert digital and pll power down */ data =3D DSI_7nm_PHY_CMN_CTRL_0_DIGTOP_PWRDN_B | DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB; writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0); + spin_unlock_irqrestore(&pll->pll_enable_lock, flags); =20 /* Assert PLL core reset */ writel(0x00, base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL); @@ -1115,7 +1162,9 @@ static bool dsi_7nm_set_continuous_clock(struct msm_d= si_phy *phy, bool enable) =20 static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) { + struct dsi_pll_7nm *pll =3D phy->pll_data; void __iomem *base =3D phy->base; + unsigned long flags; u32 data; =20 DBG(""); @@ -1141,8 +1190,12 @@ static void dsi_7nm_phy_disable(struct msm_dsi_phy *= phy) writel(data, base + REG_DSI_7nm_PHY_CMN_CTRL_0); writel(0, base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0); =20 + spin_lock_irqsave(&pll->pll_enable_lock, flags); + pll->pll_enable_cnt =3D 0; /* Turn off all PHY blocks */ writel(0x00, base + REG_DSI_7nm_PHY_CMN_CTRL_0); + spin_unlock_irqrestore(&pll->pll_enable_lock, flags); + /* make sure phy is turned off */ wmb(); =20 --=20 2.45.2