From patchwork Thu Feb 8 16:20:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrice CHOTARD X-Patchwork-Id: 870936 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3zckBQ3lHVz9s72 for ; Fri, 9 Feb 2018 03:27:42 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 307B0C21EC2; Thu, 8 Feb 2018 16:23:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 95EAAC21EDC; Thu, 8 Feb 2018 16:21:50 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 3EFB7C21E2C; Thu, 8 Feb 2018 16:21:40 +0000 (UTC) Received: from mx07-00178001.pphosted.com (mx07-00178001.pphosted.com [62.209.51.94]) by lists.denx.de (Postfix) with ESMTPS id 843B3C21EB1 for ; Thu, 8 Feb 2018 16:21:36 +0000 (UTC) Received: from pps.filterd (m0046668.ppops.net [127.0.0.1]) by mx07-.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w18GIaeF028657; Thu, 8 Feb 2018 17:21:35 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 2fxmgpt0et-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Thu, 08 Feb 2018 17:21:35 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id D4BE734; Thu, 8 Feb 2018 16:21:34 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node3.st.com [10.75.127.18]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 98CDDA6F9; Thu, 8 Feb 2018 16:21:34 +0000 (GMT) Received: from localhost (10.75.127.48) by SFHDAG6NODE3.st.com (10.75.127.18) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Thu, 8 Feb 2018 17:21:34 +0100 From: To: , , , Date: Thu, 8 Feb 2018 17:20:50 +0100 Message-ID: <1518106851-18106-7-git-send-email-patrice.chotard@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1518106851-18106-1-git-send-email-patrice.chotard@st.com> References: <1518106851-18106-1-git-send-email-patrice.chotard@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.48] X-ClientProxiedBy: SFHDAG7NODE2.st.com (10.75.127.20) To SFHDAG6NODE3.st.com (10.75.127.18) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-02-08_08:, , signatures=0 Subject: [U-Boot] [PATCH 6/7] clk: clk_stm32f: Add set_rate for LTDC clock X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Patrice Chotard Implement set_rate() for LTDC clock only, set_rate for other clocks will be added if needed. This is needed by future LTDC driver improvements. Signed-off-by: Patrice Chotard --- drivers/clk/clk_stm32f.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/drivers/clk/clk_stm32f.c b/drivers/clk/clk_stm32f.c index a11d6dc242ba..a683911ebf00 100644 --- a/drivers/clk/clk_stm32f.c +++ b/drivers/clk/clk_stm32f.c @@ -136,6 +136,9 @@ struct stm32_clk { unsigned long hse_rate; }; +#ifdef CONFIG_VIDEO_STM32 +static const u8 plldivr_table[] = { 0, 0, 2, 3, 4, 5, 6, 7 }; +#endif static const u8 pllsaidivr_table[] = { 2, 4, 8, 16 }; static int configure_clocks(struct udevice *dev) @@ -484,7 +487,104 @@ static ulong stm32_clk_get_rate(struct clk *clk) static ulong stm32_set_rate(struct clk *clk, ulong rate) { +#ifdef CONFIG_VIDEO_STM32 + struct stm32_clk *priv = dev_get_priv(clk->dev); + struct stm32_rcc_regs *regs = priv->base; + u32 pllsair_rate, pllsai_vco_rate, current_rate; + u32 best_div, best_diff, diff; + u16 div; + u8 best_plldivr, best_pllsaidivr; + u8 i, j; + bool found = false; + + /* Only set_rate for LTDC clock is implemented */ + if (clk->id != STM32F7_APB2_CLOCK(LTDC)) { + pr_err("set_rate not implemented for clock index %ld\n", + clk->id); + return 0; + } + + if (rate == stm32_clk_get_rate(clk)) + /* already set to requested rate */ + return rate; + + /* get the current PLLSAIR output freq */ + pllsair_rate = stm32_clk_get_pllsai_rate(priv, PLLSAIR); + best_div = pllsair_rate / rate; + + /* look into pllsaidivr_table if this divider is available*/ + for (i = 0 ; i < sizeof(pllsaidivr_table); i++) + if (best_div == pllsaidivr_table[i]) { + /* set pll_saidivr with found value */ + clrsetbits_le32(®s->dckcfgr, + RCC_DCKCFGR_PLLSAIDIVR_MASK, + pllsaidivr_table[i]); + return rate; + } + + /* + * As no pllsaidivr value is suitable to obtain requested freq, + * test all combination of pllsaidivr * pllsair and find the one + * which give freq closest to requested rate. + */ + + pllsai_vco_rate = stm32_clk_get_pllsai_vco_rate(priv); + best_diff = ULONG_MAX; + best_pllsaidivr = 0; + best_plldivr = 0; + /* + * start at index 2 of plldivr_table as divider value at index 0 + * and 1 are 0) + */ + for (i = 2; i < sizeof(plldivr_table); i++) { + for (j = 0; j < sizeof(pllsaidivr_table); j++) { + div = plldivr_table[i] * pllsaidivr_table[j]; + current_rate = pllsai_vco_rate / div; + /* perfect combination is found ? */ + if (current_rate == rate) { + best_pllsaidivr = j; + best_plldivr = i; + found = true; + break; + } + + diff = (current_rate > rate) ? + current_rate - rate : rate - current_rate; + + /* found a better combination ? */ + if (diff < best_diff) { + best_diff = diff; + best_pllsaidivr = j; + best_plldivr = i; + } + } + + if (found) + break; + } + + /* Disable the SAI PLL */ + clrbits_le32(®s->cr, RCC_CR_PLLSAION); + + /* set pll_saidivr with found value */ + clrsetbits_le32(®s->dckcfgr, RCC_DCKCFGR_PLLSAIDIVR_MASK, + best_pllsaidivr << RCC_DCKCFGR_PLLSAIDIVR_SHIFT); + + /* set pllsair with found value */ + clrsetbits_le32(®s->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIR_MASK, + plldivr_table[best_plldivr] + << RCC_PLLSAICFGR_PLLSAIR_SHIFT); + + /* Enable the SAI PLL */ + setbits_le32(®s->cr, RCC_CR_PLLSAION); + while (!(readl(®s->cr) & RCC_CR_PLLSAIRDY)) + ; + + div = plldivr_table[best_plldivr] * pllsaidivr_table[best_pllsaidivr]; + return pllsai_vco_rate / div; +#else return 0; +#endif } static int stm32_clk_enable(struct clk *clk)