From: Sasha Levin <sashal@kernel.org> To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Quanyang Wang <quanyang.wang@windriver.com>, Shubhrajyoti Datta <shubhrajyoti.datta@amd.com>, Stephen Boyd <sboyd@kernel.org>, Sasha Levin <sashal@kernel.org>, mturquette@baylibre.com, michal.simek@xilinx.com, m.tretter@pengutronix.de, linux-clk@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH AUTOSEL 5.19 05/63] clk: zynqmp: pll: rectify rate rounding in zynqmp_pll_round_rate Date: Wed, 12 Oct 2022 20:17:39 -0400 [thread overview] Message-ID: <20221013001842.1893243-5-sashal@kernel.org> (raw) In-Reply-To: <20221013001842.1893243-1-sashal@kernel.org> From: Quanyang Wang <quanyang.wang@windriver.com> [ Upstream commit 30eaf02149ecc3c5815e45d27187bf09e925071d ] The function zynqmp_pll_round_rate is used to find a most appropriate PLL frequency which the hardware can generate according to the desired frequency. For example, if the desired frequency is 297MHz, considering the limited range from PS_PLL_VCO_MIN (1.5GHz) to PS_PLL_VCO_MAX (3.0GHz) of PLL, zynqmp_pll_round_rate should return 1.872GHz (297MHz * 5). There are two problems with the current code of zynqmp_pll_round_rate: 1) When the rate is below PS_PLL_VCO_MIN, it can't find a correct rate when the parameter "rate" is an integer multiple of *prate, in other words, if "f" is zero, zynqmp_pll_round_rate won't return a valid frequency which is from PS_PLL_VCO_MIN to PS_PLL_VCO_MAX. For example, *prate is 33MHz and the rate is 660MHz, zynqmp_pll_round_rate will not boost up rate and just return 660MHz, and this will cause clk_calc_new_rates failure since zynqmp_pll_round_rate returns an invalid rate out of its boundaries. 2) Even if the rate is higher than PS_PLL_VCO_MIN, there is still a risk that zynqmp_pll_round_rate returns an invalid rate because the function DIV_ROUND_CLOSEST makes some loss in the fractional part. If the parent clock *prate is 33333333Hz and we want to set the PLL rate to 1.5GHz, this function will return 1499999985Hz by using the formula below: value = *prate * DIV_ROUND_CLOSEST(rate, *prate)). This value is also invalid since it's slightly smaller than PS_PLL_VCO_MIN. because DIV_ROUND_CLOSEST makes some loss in the fractional part. Signed-off-by: Quanyang Wang <quanyang.wang@windriver.com> Link: https://lore.kernel.org/r/20220826142030.213805-1-quanyang.wang@windriver.com Reviewed-by: Shubhrajyoti Datta <shubhrajyoti.datta@amd.com> Signed-off-by: Stephen Boyd <sboyd@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> --- drivers/clk/zynqmp/pll.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/clk/zynqmp/pll.c b/drivers/clk/zynqmp/pll.c index 91a6b4cc910e..0d3e1377b092 100644 --- a/drivers/clk/zynqmp/pll.c +++ b/drivers/clk/zynqmp/pll.c @@ -102,26 +102,25 @@ static long zynqmp_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { u32 fbdiv; - long rate_div, f; + u32 mult, div; - /* Enable the fractional mode if needed */ - rate_div = (rate * FRAC_DIV) / *prate; - f = rate_div % FRAC_DIV; - if (f) { - if (rate > PS_PLL_VCO_MAX) { - fbdiv = rate / PS_PLL_VCO_MAX; - rate = rate / (fbdiv + 1); - } - if (rate < PS_PLL_VCO_MIN) { - fbdiv = DIV_ROUND_UP(PS_PLL_VCO_MIN, rate); - rate = rate * fbdiv; - } - return rate; + /* Let rate fall inside the range PS_PLL_VCO_MIN ~ PS_PLL_VCO_MAX */ + if (rate > PS_PLL_VCO_MAX) { + div = DIV_ROUND_UP(rate, PS_PLL_VCO_MAX); + rate = rate / div; + } + if (rate < PS_PLL_VCO_MIN) { + mult = DIV_ROUND_UP(PS_PLL_VCO_MIN, rate); + rate = rate * mult; } fbdiv = DIV_ROUND_CLOSEST(rate, *prate); - fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX); - return *prate * fbdiv; + if (fbdiv < PLL_FBDIV_MIN || fbdiv > PLL_FBDIV_MAX) { + fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX); + rate = *prate * fbdiv; + } + + return rate; } /** -- 2.35.1
WARNING: multiple messages have this Message-ID (diff)
From: Sasha Levin <sashal@kernel.org> To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Quanyang Wang <quanyang.wang@windriver.com>, Shubhrajyoti Datta <shubhrajyoti.datta@amd.com>, Stephen Boyd <sboyd@kernel.org>, Sasha Levin <sashal@kernel.org>, mturquette@baylibre.com, michal.simek@xilinx.com, m.tretter@pengutronix.de, linux-clk@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH AUTOSEL 5.19 05/63] clk: zynqmp: pll: rectify rate rounding in zynqmp_pll_round_rate Date: Wed, 12 Oct 2022 20:17:39 -0400 [thread overview] Message-ID: <20221013001842.1893243-5-sashal@kernel.org> (raw) In-Reply-To: <20221013001842.1893243-1-sashal@kernel.org> From: Quanyang Wang <quanyang.wang@windriver.com> [ Upstream commit 30eaf02149ecc3c5815e45d27187bf09e925071d ] The function zynqmp_pll_round_rate is used to find a most appropriate PLL frequency which the hardware can generate according to the desired frequency. For example, if the desired frequency is 297MHz, considering the limited range from PS_PLL_VCO_MIN (1.5GHz) to PS_PLL_VCO_MAX (3.0GHz) of PLL, zynqmp_pll_round_rate should return 1.872GHz (297MHz * 5). There are two problems with the current code of zynqmp_pll_round_rate: 1) When the rate is below PS_PLL_VCO_MIN, it can't find a correct rate when the parameter "rate" is an integer multiple of *prate, in other words, if "f" is zero, zynqmp_pll_round_rate won't return a valid frequency which is from PS_PLL_VCO_MIN to PS_PLL_VCO_MAX. For example, *prate is 33MHz and the rate is 660MHz, zynqmp_pll_round_rate will not boost up rate and just return 660MHz, and this will cause clk_calc_new_rates failure since zynqmp_pll_round_rate returns an invalid rate out of its boundaries. 2) Even if the rate is higher than PS_PLL_VCO_MIN, there is still a risk that zynqmp_pll_round_rate returns an invalid rate because the function DIV_ROUND_CLOSEST makes some loss in the fractional part. If the parent clock *prate is 33333333Hz and we want to set the PLL rate to 1.5GHz, this function will return 1499999985Hz by using the formula below: value = *prate * DIV_ROUND_CLOSEST(rate, *prate)). This value is also invalid since it's slightly smaller than PS_PLL_VCO_MIN. because DIV_ROUND_CLOSEST makes some loss in the fractional part. Signed-off-by: Quanyang Wang <quanyang.wang@windriver.com> Link: https://lore.kernel.org/r/20220826142030.213805-1-quanyang.wang@windriver.com Reviewed-by: Shubhrajyoti Datta <shubhrajyoti.datta@amd.com> Signed-off-by: Stephen Boyd <sboyd@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> --- drivers/clk/zynqmp/pll.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/clk/zynqmp/pll.c b/drivers/clk/zynqmp/pll.c index 91a6b4cc910e..0d3e1377b092 100644 --- a/drivers/clk/zynqmp/pll.c +++ b/drivers/clk/zynqmp/pll.c @@ -102,26 +102,25 @@ static long zynqmp_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { u32 fbdiv; - long rate_div, f; + u32 mult, div; - /* Enable the fractional mode if needed */ - rate_div = (rate * FRAC_DIV) / *prate; - f = rate_div % FRAC_DIV; - if (f) { - if (rate > PS_PLL_VCO_MAX) { - fbdiv = rate / PS_PLL_VCO_MAX; - rate = rate / (fbdiv + 1); - } - if (rate < PS_PLL_VCO_MIN) { - fbdiv = DIV_ROUND_UP(PS_PLL_VCO_MIN, rate); - rate = rate * fbdiv; - } - return rate; + /* Let rate fall inside the range PS_PLL_VCO_MIN ~ PS_PLL_VCO_MAX */ + if (rate > PS_PLL_VCO_MAX) { + div = DIV_ROUND_UP(rate, PS_PLL_VCO_MAX); + rate = rate / div; + } + if (rate < PS_PLL_VCO_MIN) { + mult = DIV_ROUND_UP(PS_PLL_VCO_MIN, rate); + rate = rate * mult; } fbdiv = DIV_ROUND_CLOSEST(rate, *prate); - fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX); - return *prate * fbdiv; + if (fbdiv < PLL_FBDIV_MIN || fbdiv > PLL_FBDIV_MAX) { + fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX); + rate = *prate * fbdiv; + } + + return rate; } /** -- 2.35.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2022-10-13 0:27 UTC|newest] Thread overview: 84+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-10-13 0:17 [PATCH AUTOSEL 5.19 01/63] staging: r8188eu: do not spam the kernel log Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 02/63] clk: zynqmp: Fix stack-out-of-bounds in strncpy` Sasha Levin 2022-10-13 0:17 ` Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 03/63] media: cx88: Fix a null-ptr-deref bug in buffer_prepare() Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 04/63] media: platform: fix some double free in meson-ge2d and mtk-jpeg and s5p-mfc Sasha Levin 2022-10-13 0:17 ` Sasha Levin 2022-10-13 0:17 ` Sasha Levin 2022-10-13 0:17 ` Sasha Levin [this message] 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 05/63] clk: zynqmp: pll: rectify rate rounding in zynqmp_pll_round_rate Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 06/63] RDMA/rxe: Delete error messages triggered by incoming Read requests Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 07/63] usb: host: xhci-plat: suspend and resume clocks Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 08/63] usb: host: xhci-plat: suspend/resume clks for brcm Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 09/63] scsi: lpfc: Fix null ndlp ptr dereference in abnormal exit path for GFT_ID Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 10/63] dmaengine: ti: k3-udma: Reset UDMA_CHAN_RT byte counters to prevent overflow Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 11/63] scsi: 3w-9xxx: Avoid disabling device if failing to enable it Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 12/63] nbd: Fix hung when signal interrupts nbd_start_device_ioctl() Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 13/63] iommu/arm-smmu-v3: Make default domain type of HiSilicon PTT device to identity Sasha Levin 2022-10-13 0:17 ` Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 14/63] usb: gadget: uvc: increase worker prio to WQ_HIGHPRI Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 15/63] staging: rtl8712: Fix return type for implementation of ndo_start_xmit Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 16/63] staging: rtl8192e: " Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 17/63] power: supply: adp5061: fix out-of-bounds read in adp5061_get_chg_type() Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 18/63] staging: vt6655: fix potential memory leak Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 19/63] blk-throttle: prevent overflow while calculating wait time Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 20/63] clk: microchip: mpfs: add MSS pll's set & round rate Sasha Levin 2022-10-13 0:17 ` Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 21/63] gpiolib: of: do not ignore requested index when applying quirks Sasha Levin 2022-10-14 9:27 ` Bartosz Golaszewski 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 22/63] gpiolib: of: make Freescale SPI quirk similar to all others Sasha Levin 2022-10-14 9:28 ` Bartosz Golaszewski 2022-10-16 13:35 ` Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 23/63] gpiolib: rework quirk handling in of_find_gpio() Sasha Levin 2022-10-14 9:26 ` Bartosz Golaszewski 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 24/63] ata: libahci_platform: Sanity check the DT child nodes number Sasha Levin 2022-10-13 0:17 ` [PATCH AUTOSEL 5.19 25/63] habanalabs: ignore EEPROM errors during boot Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 26/63] bcache: fix set_at_max_writeback_rate() for multiple attached devices Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 27/63] soundwire: cadence: Don't overwrite msg->buf during write commands Sasha Levin 2022-10-13 0:18 ` Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 28/63] soundwire: intel: fix error handling on dai registration issues Sasha Levin 2022-10-13 0:18 ` Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 29/63] hid: topre: Add driver fixing report descriptor Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 30/63] habanalabs: remove some f/w descriptor validations Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 31/63] HID: roccat: Fix use-after-free in roccat_read() Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 32/63] HSI: ssi_protocol: fix potential resource leak in ssip_pn_open() Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 33/63] HID: nintendo: check analog user calibration for plausibility Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 34/63] eventfd: guard wake_up in eventfd fs calls as well Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 35/63] md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 36/63] usb: host: xhci: Fix potential memory leak in xhci_alloc_stream_info() Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 37/63] usb: musb: Fix musb_gadget.c rxstate overflow bug Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 38/63] usb: dwc3: core: add gfladj_refclk_lpm_sel quirk Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 39/63] arm64: dts: imx8mp: Add snps,gfladj-refclk-lpm-sel quirk to USB nodes Sasha Levin 2022-10-13 0:18 ` Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 40/63] usb: dwc3: core: Enable GUCTL1 bit 10 for fixing termination error after resume bug Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 41/63] Revert "usb: storage: Add quirk for Samsung Fit flash" Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 42/63] tty: n_gsm: replace use of gsm_read_ea() with gsm_read_ea_val() Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 43/63] staging: rtl8723bs: fix potential memory leak in rtw_init_drv_sw() Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 44/63] staging: rtl8723bs: fix a potential memory leak in rtw_init_cmd_priv() Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 45/63] staging: rtl8192u: Fix return type of ieee80211_xmit Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 46/63] staging: octeon: Fix return type of cvm_oct_xmit and cvm_oct_xmit_pow Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 47/63] staging: r8188eu: fix a potential memory leak in rtw_init_cmd_priv() Sasha Levin 2022-10-13 4:46 ` Greg Kroah-Hartman 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 48/63] scsi: tracing: Fix compile error in trace_array calls when TRACING is disabled Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 49/63] ext2: Use kvmalloc() for group descriptor array Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 50/63] nvme: handle effects after freeing the request Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 51/63] nvme: copy firmware_rev on each init Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 52/63] nvmet-tcp: add bounds check on Transfer Tag Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 53/63] usb: idmouse: fix an uninit-value in idmouse_open Sasha Levin 2022-10-13 0:18 ` [dm-devel] [PATCH AUTOSEL 5.19 54/63] block: replace blk_queue_nowait with bdev_nowait Sasha Levin 2022-10-13 0:18 ` Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 55/63] blk-mq: use quiesced elevator switch when reinitializing queues Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 56/63] nvmet: don't look at the request_queue in nvmet_bdev_set_limits Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 57/63] hwmon (occ): Retry for checksum failure Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 58/63] fsi: occ: Prevent use after free Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 59/63] fsi: master-ast-cf: Fix missing of_node_put in fsi_master_acf_probe Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 60/63] sbitmap: fix lockup while swapping Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 61/63] usb: typec: ucsi: Don't warn on probe deferral Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 62/63] clk: bcm2835: Make peripheral PLLC critical Sasha Levin 2022-10-13 0:18 ` Sasha Levin 2022-10-13 0:18 ` [PATCH AUTOSEL 5.19 63/63] clk: bcm2835: Round UART input clock up Sasha Levin 2022-10-13 0:18 ` Sasha Levin 2022-10-13 3:08 ` [PATCH AUTOSEL 5.19 01/63] staging: r8188eu: do not spam the kernel log Joe Perches 2022-10-13 4:46 ` Greg Kroah-Hartman 2022-10-16 13:32 ` Sasha Levin 2022-10-16 14:57 ` Greg Kroah-Hartman
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20221013001842.1893243-5-sashal@kernel.org \ --to=sashal@kernel.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-clk@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=m.tretter@pengutronix.de \ --cc=michal.simek@xilinx.com \ --cc=mturquette@baylibre.com \ --cc=quanyang.wang@windriver.com \ --cc=sboyd@kernel.org \ --cc=shubhrajyoti.datta@amd.com \ --cc=stable@vger.kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.