From patchwork Mon Dec 17 12:08:18 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laxman Dewangan X-Patchwork-Id: 1886981 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 79FC3DF266 for ; Mon, 17 Dec 2012 12:13:06 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TkZW9-00025K-AA; Mon, 17 Dec 2012 12:09:57 +0000 Received: from hqemgate04.nvidia.com ([216.228.121.35]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TkZVF-0001qF-Vu for linux-arm-kernel@lists.infradead.org; Mon, 17 Dec 2012 12:09:04 +0000 Received: from hqnvupgp06.nvidia.com (Not Verified[216.228.121.13]) by hqemgate04.nvidia.com id ; Mon, 17 Dec 2012 04:08:14 -0800 Received: from hqemhub01.nvidia.com ([172.17.108.22]) by hqnvupgp06.nvidia.com (PGP Universal service); Mon, 17 Dec 2012 04:07:09 -0800 X-PGP-Universal: processed; by hqnvupgp06.nvidia.com on Mon, 17 Dec 2012 04:07:09 -0800 Received: from hqnvemgw01.nvidia.com (172.20.150.20) by hqemhub01.nvidia.com (172.20.150.30) with Microsoft SMTP Server id 8.3.279.1; Mon, 17 Dec 2012 04:08:33 -0800 Received: from thelma.nvidia.com (Not Verified[172.16.212.77]) by hqnvemgw01.nvidia.com with MailMarshal (v6,7,2,8378) id ; Mon, 17 Dec 2012 04:08:46 -0800 Received: from ldewangan-ubuntu.nvidia.com ([10.19.65.30]) by thelma.nvidia.com (8.13.8+Sun/8.8.8) with ESMTP id qBHC8SxW014291; Mon, 17 Dec 2012 04:08:31 -0800 (PST) From: Laxman Dewangan To: Subject: [PATCH 1/4] ARM: tegra30: Add support for Uart clock source divider as 15.1 Date: Mon, 17 Dec 2012 17:38:18 +0530 Message-ID: <1355746101-15291-2-git-send-email-ldewangan@nvidia.com> X-Mailer: git-send-email 1.7.1.1 In-Reply-To: <1355746101-15291-1-git-send-email-ldewangan@nvidia.com> References: <1355746101-15291-1-git-send-email-ldewangan@nvidia.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121217_070902_848795_EB22627F X-CRM114-Status: GOOD ( 15.62 ) X-Spam-Score: -7.6 (-------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-7.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [216.228.121.35 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record -0.7 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: linux-tegra@vger.kernel.org, Laxman Dewangan , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Tegra20 uart clock source have the 15.1 clock divider in place of 7.1. Add support for 15.1 clock divider and change the uart clock divider flag to DIV_U151. Signed-off-by: Laxman Dewangan --- arch/arm/mach-tegra/clock.h | 3 +- arch/arm/mach-tegra/tegra30_clocks.c | 70 ++++++++++++++++++++++------ arch/arm/mach-tegra/tegra30_clocks_data.c | 10 ++-- 3 files changed, 62 insertions(+), 21 deletions(-) diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h index 2aa37f5..26e9253 100644 --- a/arch/arm/mach-tegra/clock.h +++ b/arch/arm/mach-tegra/clock.h @@ -45,11 +45,12 @@ #define PLLX (1 << 15) #define MUX_PWM (1 << 16) #define MUX8 (1 << 17) -#define DIV_U71_UART (1 << 18) +#define DIV_U151_UART (1 << 18) #define MUX_CLK_OUT (1 << 19) #define PLLM (1 << 20) #define DIV_U71_INT (1 << 21) #define DIV_U71_IDLE (1 << 22) +#define DIV_U151 (1 << 23) #define ENABLE_ON_INIT (1 << 28) #define PERIPH_ON_APB (1 << 29) diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c index d714777..795ea87 100644 --- a/arch/arm/mach-tegra/tegra30_clocks.c +++ b/arch/arm/mach-tegra/tegra30_clocks.c @@ -466,28 +466,45 @@ static unsigned long clk_measure_input_freq(void) } } -static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate, - u32 flags, u32 round_mode) +static int clk_div_x1_get_divider(unsigned long parent_rate, unsigned long rate, + u32 max_x, u32 flags, u32 round_mode) { - s64 divider_u71 = parent_rate; + s64 divider_ux1 = parent_rate; + if (!rate) return -EINVAL; if (!(flags & DIV_U71_INT)) - divider_u71 *= 2; + divider_ux1 *= 2; + if (round_mode == ROUND_DIVIDER_UP) - divider_u71 += rate - 1; - do_div(divider_u71, rate); + divider_ux1 += rate - 1; + do_div(divider_ux1, rate); + if (flags & DIV_U71_INT) - divider_u71 *= 2; + divider_ux1 *= 2; - if (divider_u71 - 2 < 0) + if (divider_ux1 - 2 < 0) return 0; - if (divider_u71 - 2 > 255) + if (divider_ux1 - 2 > max_x) return -EINVAL; - return divider_u71 - 2; + return divider_ux1 - 2; +} + +static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate, + u32 flags, u32 round_mode) +{ + return clk_div_x1_get_divider(parent_rate, rate, 0xFF, + flags, round_mode); +} + +static int clk_div151_get_divider(unsigned long parent_rate, unsigned long rate, + u32 flags, u32 round_mode) +{ + return clk_div_x1_get_divider(parent_rate, rate, 0xFFFF, + flags, round_mode); } static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate) @@ -1936,7 +1953,19 @@ static int tegra30_periph_clk_set_rate(struct clk_hw *hw, unsigned long rate, val = clk_readl(c->reg); val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK; val |= divider; - if (c->flags & DIV_U71_UART) { + clk_writel_delay(val, c->reg); + c->div = divider + 2; + c->mul = 2; + return 0; + } + } else if (c->flags & DIV_U151) { + divider = clk_div151_get_divider( + parent_rate, rate, c->flags, ROUND_DIVIDER_UP); + if (divider >= 0) { + val = clk_readl(c->reg); + val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK; + val |= divider; + if (c->flags & DIV_U151_UART) { if (divider) val |= PERIPH_CLK_UART_DIV_ENB; else @@ -1983,6 +2012,13 @@ static long tegra30_periph_clk_round_rate(struct clk_hw *hw, unsigned long rate, return divider; return DIV_ROUND_UP(parent_rate * 2, divider + 2); + } else if (c->flags & DIV_U151) { + divider = clk_div151_get_divider( + parent_rate, rate, c->flags, ROUND_DIVIDER_UP); + if (divider < 0) + return divider; + + return DIV_ROUND_UP(parent_rate * 2, divider + 2); } else if (c->flags & DIV_U16) { divider = clk_div16_get_divider(parent_rate, rate); if (divider < 0) @@ -2001,10 +2037,6 @@ static unsigned long tegra30_periph_clk_recalc_rate(struct clk_hw *hw, if (c->flags & DIV_U71) { u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK; - if ((c->flags & DIV_U71_UART) && - (!(val & PERIPH_CLK_UART_DIV_ENB))) { - divu71 = 0; - } if (c->flags & DIV_U71_IDLE) { val &= ~(PERIPH_CLK_SOURCE_DIVU71_MASK << PERIPH_CLK_SOURCE_DIVIDLE_SHIFT); @@ -2014,6 +2046,14 @@ static unsigned long tegra30_periph_clk_recalc_rate(struct clk_hw *hw, } c->div = divu71 + 2; c->mul = 2; + } else if (c->flags & DIV_U151) { + u32 divu151 = val & PERIPH_CLK_SOURCE_DIVU16_MASK; + if ((c->flags & DIV_U151_UART) && + (!(val & PERIPH_CLK_UART_DIV_ENB))) { + divu151 = 0; + } + c->div = divu151 + 2; + c->mul = 2; } else if (c->flags & DIV_U16) { u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK; c->div = divu16 + 1; diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c index 6942c7a..e2e6022 100644 --- a/arch/arm/mach-tegra/tegra30_clocks_data.c +++ b/arch/arm/mach-tegra/tegra30_clocks_data.c @@ -1120,11 +1120,11 @@ PERIPH_CLK(i2c2, "tegra-i2c.1", "div-clk", 54, 0x198, 26000000, mux_pllp_clkm, PERIPH_CLK(i2c3, "tegra-i2c.2", "div-clk", 67, 0x1b8, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); PERIPH_CLK(i2c4, "tegra-i2c.3", "div-clk", 103, 0x3c4, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); PERIPH_CLK(i2c5, "tegra-i2c.4", "div-clk", 47, 0x128, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); -PERIPH_CLK(uarta, "tegra-uart.0", NULL, 6, 0x178, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB); -PERIPH_CLK(uartb, "tegra-uart.1", NULL, 7, 0x17c, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB); -PERIPH_CLK(uartc, "tegra-uart.2", NULL, 55, 0x1a0, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB); -PERIPH_CLK(uartd, "tegra-uart.3", NULL, 65, 0x1c0, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB); -PERIPH_CLK(uarte, "tegra-uart.4", NULL, 66, 0x1c4, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB); +PERIPH_CLK(uarta, "tegra-uart.0", NULL, 6, 0x178, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB); +PERIPH_CLK(uartb, "tegra-uart.1", NULL, 7, 0x17c, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB); +PERIPH_CLK(uartc, "tegra-uart.2", NULL, 55, 0x1a0, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB); +PERIPH_CLK(uartd, "tegra-uart.3", NULL, 65, 0x1c0, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB); +PERIPH_CLK(uarte, "tegra-uart.4", NULL, 66, 0x1c4, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB); PERIPH_CLK(vi, "tegra_camera", "vi", 20, 0x148, 425000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT); PERIPH_CLK(3d, "3d", NULL, 24, 0x158, 520000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET); PERIPH_CLK(3d2, "3d2", NULL, 98, 0x3b0, 520000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET);