From nobody Sun Nov 24 23:53:31 2024 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 34C3F19CC27; Fri, 1 Nov 2024 10:39:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730457561; cv=none; b=WJVf4P6gh2G1jiuXj0rg0XuAFmEdvf6LgVHgEcIvxZNfL6nBXvf1TcoBDipBDkrt2D/9i4476prP+FdQtnJ4uCEpRU4Z3GEU/vlDkcMOu2snLdRBmYd9wzDUBFw8DEDP28FWRDhXqxtoDRVicAz9/V5IgpWer5b6VWxpNQWrxZM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730457561; c=relaxed/simple; bh=d26jP/muAdswNvuEVUiMeHzA+cD/piw24kILISvO+5s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=dWE28VeiayEVpQp/S2bmfdk4K2bhKePHKzJn2aI0Hb5AIJXrL7Ayn6V99vhLye8qkJAAVrURrlCmLuTspoIDG4Zu9GPux/2SHE/dI3CqYPeX5Ca2feY/gDxtv7/qCLIyVB2rRF48WR7whlS7W04uTE0pJpNXRQ7yS9Ju4X6kQkQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=Fk9M0QDu; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="Fk9M0QDu" Received: from pps.filterd (m0279865.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 49VMxlLp012383; Fri, 1 Nov 2024 10:38:44 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= rRiOosBlpTmaWohbv1dlmt4R9DZrCiMDP06cMwbvD/M=; b=Fk9M0QDu9B3D1E06 vTWJVUSz5P3/lK5QdbG9N4C2KKbMPAU6JxLT8yLiyEcRdAgr1gXpMDt1TaTZy+cf 6RIzlpo/uaYFUIj2KVDdcOH17xpGZjfzHKLqW0vKXrrxY7VVBlfOVcLXYHnzzQ/4 MH7s6rQ92xRjZwNrd60HNkaA/ZGTO7OsqQhDRf0Uqxha/tqCIp2YbzM/DCLt17hR fJTkvH5k9FasLiNw0744GtzjClELCzoMzce9vy6aMvFXQSby3Z8C9R/7lDYryWnH BU11UYmV4qbvYR6SzSpmeuG0WMYz4NWfaqaDW7No85ZdYzVnHFqjk7Nh9EsoptSM TS8cSg== Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 42m65pby77-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 01 Nov 2024 10:38:44 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA03.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 4A1AchTZ026178 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 1 Nov 2024 10:38:43 GMT Received: from hu-tdas-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Fri, 1 Nov 2024 03:38:38 -0700 From: Taniya Das Date: Fri, 1 Nov 2024 16:08:14 +0530 Subject: [PATCH v2 02/11] clk: qcom: clk-alpha-pll: Add support for dynamic update for slewing PLLs 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: <20241101-qcs615-mm-clockcontroller-v2-2-d1a4870a4aed@quicinc.com> References: <20241101-qcs615-mm-clockcontroller-v2-0-d1a4870a4aed@quicinc.com> In-Reply-To: <20241101-qcs615-mm-clockcontroller-v2-0-d1a4870a4aed@quicinc.com> To: Bjorn Andersson , Michael Turquette , Stephen Boyd , Abhishek Sahu , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon CC: Ajit Pandey , Imran Shaik , Jagadeesh Kona , , , , , , Taniya Das X-Mailer: b4 0.15-dev-aa3f6 X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: 0wOvyULRRWuvD2_7xor0w8p9BISbYZr4 X-Proofpoint-GUID: 0wOvyULRRWuvD2_7xor0w8p9BISbYZr4 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 spamscore=0 phishscore=0 malwarescore=0 clxscore=1015 priorityscore=1501 mlxlogscore=999 suspectscore=0 lowpriorityscore=0 bulkscore=0 adultscore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411010076 The alpha PLLs which slew to a new frequency at runtime would require the PLL to calibrate at the mid point of the VCO. Add the new PLL ops which can support the slewing of the PLL to a new frequency. Signed-off-by: Taniya Das Reviewed-by: Imran Shaik --- drivers/clk/qcom/clk-alpha-pll.c | 170 +++++++++++++++++++++++++++++++++++= ++++ drivers/clk/qcom/clk-alpha-pll.h | 1 + 2 files changed, 171 insertions(+) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-= pll.c index 03cc7aa092480bfdd9eaa986d44f0545944b3b89..fe9e5d5344d7fa9a8a1f220f898= 2fbafc875c4c1 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -2758,3 +2758,173 @@ const struct clk_ops clk_alpha_pll_regera_ops =3D { .set_rate =3D clk_zonda_pll_set_rate, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_regera_ops); + +static int clk_alpha_pll_slew_update(struct clk_alpha_pll *pll) +{ + int ret; + u32 val; + + regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_UPDATE, PLL_UPDAT= E); + regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); + + ret =3D wait_for_pll_update(pll); + if (ret) + return ret; + /* + * Hardware programming mandates a wait of at least 570ns before polling = the LOCK + * detect bit. Have a delay of 1us just to be safe. + */ + mb(); + udelay(1); + + return wait_for_pll_enable_lock(pll); +} + +static int clk_alpha_pll_slew_set_rate(struct clk_hw *hw, unsigned long ra= te, + unsigned long parent_rate) +{ + struct clk_alpha_pll *pll =3D to_clk_alpha_pll(hw); + unsigned long freq_hz; + const struct pll_vco *curr_vco, *vco; + u32 l, alpha_width =3D pll_alpha_width(pll); + u64 a; + + freq_hz =3D alpha_pll_round_rate(rate, parent_rate, &l, &a, alpha_width); + if (freq_hz !=3D rate) { + pr_err("alpha_pll: Call clk_set_rate with rounded rates!\n"); + return -EINVAL; + } + + curr_vco =3D alpha_pll_find_vco(pll, clk_hw_get_rate(hw)); + if (!curr_vco) { + pr_err("alpha pll: not in a valid vco range\n"); + return -EINVAL; + } + + vco =3D alpha_pll_find_vco(pll, freq_hz); + if (!vco) { + pr_err("alpha pll: not in a valid vco range\n"); + return -EINVAL; + } + + /* + * Dynamic pll update will not support switching frequencies across + * vco ranges. In those cases fall back to normal alpha set rate. + */ + if (curr_vco->val !=3D vco->val) + return clk_alpha_pll_set_rate(hw, rate, parent_rate); + + a =3D a << (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH); + + regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32); + + /* Ensure that the write above goes through before proceeding. */ + mb(); + + if (clk_hw_is_enabled(hw)) + return clk_alpha_pll_slew_update(pll); + + return 0; +} + +/* + * Slewing plls should be bought up at frequency which is in the middle of= the + * desired VCO range. So after bringing up the pll at calibration freq, se= t it + * back to desired frequency(that was set by previous clk_set_rate). + */ +static int clk_alpha_pll_calibrate(struct clk_hw *hw) +{ + unsigned long calibration_freq, freq_hz; + struct clk_alpha_pll *pll =3D to_clk_alpha_pll(hw); + struct clk_hw *parent; + const struct pll_vco *vco; + u32 l, alpha_width =3D pll_alpha_width(pll); + int rc; + u64 a; + + parent =3D clk_hw_get_parent(hw); + if (!parent) { + pr_err("alpha pll: no valid parent found\n"); + return -EINVAL; + } + + vco =3D alpha_pll_find_vco(pll, clk_hw_get_rate(hw)); + if (!vco) { + pr_err("alpha pll: not in a valid vco range\n"); + return -EINVAL; + } + + /* + * As during slewing plls vco_sel won't be allowed to change, vco table + * should have only one entry table, i.e. index =3D 0, find the + * calibration frequency. + */ + calibration_freq =3D (pll->vco_table[0].min_freq + pll->vco_table[0].max_= freq) / 2; + + freq_hz =3D alpha_pll_round_rate(calibration_freq, clk_hw_get_rate(parent= ), + &l, &a, alpha_width); + if (freq_hz !=3D calibration_freq) { + pr_err("alpha_pll: call clk_set_rate with rounded rates!\n"); + return -EINVAL; + } + + /* Setup PLL for calibration frequency */ + a <<=3D (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH); + + regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32); + + regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_VCO_MASK << P= LL_VCO_SHIFT, + vco->val << PLL_VCO_SHIFT); + + /* Bringup the pll at calibration frequency */ + rc =3D clk_alpha_pll_enable(hw); + if (rc) { + pr_err("alpha pll calibration failed\n"); + return rc; + } + + /* + * PLL is already running at calibration frequency. + * So slew pll to the previously set frequency. + */ + freq_hz =3D alpha_pll_round_rate(clk_hw_get_rate(hw), + clk_hw_get_rate(parent), &l, &a, alpha_width); + + pr_debug("pll %s: setting back to required rate %lu, freq_hz %ld\n", + clk_hw_get_name(hw), clk_hw_get_rate(hw), freq_hz); + + /* Setup the PLL for the new frequency */ + a <<=3D (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH); + + regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32); + + regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_ALPHA_EN, PLL= _ALPHA_EN); + + return clk_alpha_pll_slew_update(pll); +} + +static int clk_alpha_pll_slew_enable(struct clk_hw *hw) +{ + int rc; + + rc =3D clk_alpha_pll_calibrate(hw); + if (rc) + return rc; + + return clk_alpha_pll_enable(hw); +} + +const struct clk_ops clk_alpha_pll_slew_ops =3D { + .enable =3D clk_alpha_pll_slew_enable, + .disable =3D clk_alpha_pll_disable, + .recalc_rate =3D clk_alpha_pll_recalc_rate, + .round_rate =3D clk_alpha_pll_round_rate, + .set_rate =3D clk_alpha_pll_slew_set_rate, +}; +EXPORT_SYMBOL(clk_alpha_pll_slew_ops); diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-= pll.h index 55eca04b23a1fc3f3554f43a8fdd329a524dad0e..f149d10247bd4a85521940a1255= cd019bde4729a 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -195,6 +195,7 @@ extern const struct clk_ops clk_alpha_pll_rivian_evo_op= s; #define clk_alpha_pll_postdiv_rivian_evo_ops clk_alpha_pll_postdiv_fabia_o= ps =20 extern const struct clk_ops clk_alpha_pll_regera_ops; +extern const struct clk_ops clk_alpha_pll_slew_ops; =20 void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *reg= map, const struct alpha_pll_config *config); --=20 2.45.2