Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753987AbbEGKPT (ORCPT ); Thu, 7 May 2015 06:15:19 -0400 Received: from youngberry.canonical.com ([91.189.89.112]:47922 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752685AbbEGJsp (ORCPT ); Thu, 7 May 2015 05:48:45 -0400 From: Luis Henriques To: linux-kernel@vger.kernel.org, stable@vger.kernel.org, kernel-team@lists.ubuntu.com Cc: Boris Brezillon , Michael Turquette , Luis Henriques Subject: [PATCH 3.16.y-ckt 118/180] clk: at91: usb: fix at91sam9x5 recalc, round and set rate Date: Thu, 7 May 2015 10:45:27 +0100 Message-Id: <1430991989-23170-119-git-send-email-luis.henriques@canonical.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1430991989-23170-1-git-send-email-luis.henriques@canonical.com> References: <1430991989-23170-1-git-send-email-luis.henriques@canonical.com> X-Extended-Stable: 3.16 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2908 Lines: 86 3.16.7-ckt11 -stable review patch. If anyone has any objections, please let me know. ------------------ From: Boris Brezillon commit 69daf75aafc8410ef046c70be65c71f2dd4e08f9 upstream. First check for rate == 0 in set_rate and round_rate to avoid div by zero. Then, in order to get the closest rate, round all divisions to the closest result instead of rounding them down. Signed-off-by: Boris Brezillon Acked-by: Nicolas Ferre Signed-off-by: Michael Turquette [ luis: 3.16 prereq for: 4591243102fa "clk: at91: usb: propagate rate modification to the parent clk" ] Signed-off-by: Luis Henriques --- drivers/clk/at91/clk-usb.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c index 7d1d26a4bd04..03fda404bb96 100644 --- a/drivers/clk/at91/clk-usb.c +++ b/drivers/clk/at91/clk-usb.c @@ -52,29 +52,26 @@ static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw, tmp = pmc_read(pmc, AT91_PMC_USB); usbdiv = (tmp & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT; - return parent_rate / (usbdiv + 1); + + return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1)); } static long at91sam9x5_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { unsigned long div; - unsigned long bestrate; - unsigned long tmp; + + if (!rate) + return -EINVAL; if (rate >= *parent_rate) return *parent_rate; - div = *parent_rate / rate; - if (div >= SAM9X5_USB_MAX_DIV) - return *parent_rate / (SAM9X5_USB_MAX_DIV + 1); + div = DIV_ROUND_CLOSEST(*parent_rate, rate); + if (div > SAM9X5_USB_MAX_DIV + 1) + div = SAM9X5_USB_MAX_DIV + 1; - bestrate = *parent_rate / div; - tmp = *parent_rate / (div + 1); - if (bestrate - rate > rate - tmp) - bestrate = tmp; - - return bestrate; + return DIV_ROUND_CLOSEST(*parent_rate, div); } static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index) @@ -106,9 +103,13 @@ static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, u32 tmp; struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); struct at91_pmc *pmc = usb->pmc; - unsigned long div = parent_rate / rate; + unsigned long div; + + if (!rate) + return -EINVAL; - if (parent_rate % rate || div < 1 || div >= SAM9X5_USB_MAX_DIV) + div = DIV_ROUND_CLOSEST(parent_rate, rate); + if (div > SAM9X5_USB_MAX_DIV + 1 || !div) return -EINVAL; tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_OHCIUSBDIV; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/