From patchwork Mon Jul 16 18:21:48 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Shiyan X-Patchwork-Id: 1201541 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 021A9E0038 for ; Mon, 16 Jul 2012 18:38:21 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1SqqAD-0001fz-9l; Mon, 16 Jul 2012 18:36:58 +0000 Received: from smtp20.mail.ru ([94.100.176.173]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1Sqpvx-0007rZ-33 for linux-arm-kernel@lists.infradead.org; Mon, 16 Jul 2012 18:23:06 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mail.ru; s=mail; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=6hHKq3t6rrRRe9OKw5DqRCql4THOFKhG+EIPgScnOA4=; b=HtmG0idQJ3D2oOoOnG3OMVMVgju6FQqv1Zwrjg//0EE/p6MiNHdQ1PPFREVj9CPIvhKeRYr18p7IQCOZLm8Ehy6B7CTbxnHo+eG6Xp2hTZn7ZVn/ZLSY4RQQy5Mieve7; Received: from [188.134.41.72] (port=58601 helo=localhost.localdomain) by smtp20.mail.ru with esmtpa (envelope-from ) id 1SqpvW-0005nP-UP; Mon, 16 Jul 2012 22:21:47 +0400 From: Alexander Shiyan To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 4/4] ARM: clps711x: Added simple clkdev framework Date: Mon, 16 Jul 2012 22:21:48 +0400 Message-Id: <1342462908-18547-4-git-send-email-shc_work@mail.ru> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <1342462908-18547-1-git-send-email-shc_work@mail.ru> References: <1342462908-18547-1-git-send-email-shc_work@mail.ru> X-Spam: Not detected X-Spam-Note: CRM114 invocation failed X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (shc_work[at]mail.ru) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.0 T_DKIM_INVALID DKIM-Signature header exists but is not valid Cc: Alexander Shiyan , Arnd Bergmann 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: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Modern CPUs from CLPS711X-line can operate at frequencies other than 73 MHz. This patch adds simple clkdev framework for handling all possible CPU rates. Signed-off-by: Alexander Shiyan --- arch/arm/Kconfig | 1 + arch/arm/mach-clps711x/common.c | 104 +++++++++++++++++++++++++-- arch/arm/mach-clps711x/include/mach/timex.h | 23 +------ drivers/tty/serial/clps711x.c | 19 ++++- 4 files changed, 115 insertions(+), 32 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a91009c..fc2b454 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -361,6 +361,7 @@ config ARCH_HIGHBANK config ARCH_CLPS711X bool "Cirrus Logic CLPS711x/EP721x/EP731x-based" select CPU_ARM720T + select CLKDEV_LOOKUP select ARCH_USES_GETTIMEOFFSET select NEED_MACH_MEMORY_H help diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c index f15293b..daab6bf 100644 --- a/arch/arm/mach-clps711x/common.c +++ b/arch/arm/mach-clps711x/common.c @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #include #include @@ -37,6 +40,52 @@ #include #include +struct clk { + unsigned long rate; +}; + +static struct clk rtc_clk; +static struct clk osc_clk; +static struct clk ext_clk; +static struct clk pll_clk; +static struct clk cpu_clk; +static struct clk bus_clk; +static struct clk uart_clk; +static struct clk timer_h_clk; +static struct clk timer_l_clk; + +static unsigned long latch; + +/* Enable and Disable do nothing */ +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +static struct clk_lookup clps711x_lookups[] = { + CLKDEV_INIT( NULL, "rtc", &rtc_clk), + CLKDEV_INIT( NULL, "osc", &pll_clk), + CLKDEV_INIT( NULL, "ext", &ext_clk), + CLKDEV_INIT( NULL, "pll", &pll_clk), + CLKDEV_INIT( NULL, "cpu", &cpu_clk), + CLKDEV_INIT( NULL, "bus", &bus_clk), + CLKDEV_INIT( NULL, "uart", &uart_clk), + CLKDEV_INIT( NULL, "timer_h", &timer_h_clk), + CLKDEV_INIT( NULL, "timer_l", &timer_l_clk), +}; + /* * This maps the generic CLPS711x registers */ @@ -166,8 +215,8 @@ void __init clps711x_init_irq(void) static unsigned long clps711x_gettimeoffset(void) { unsigned long hwticks; - hwticks = LATCH - (clps_readl(TC2D) & 0xffff); /* since last underflow */ - return (hwticks * (tick_nsec / 1000)) / LATCH; + hwticks = latch - (clps_readl(TC2D) & 0xffff); + return (hwticks * (tick_nsec / 1000)) / latch; } /* @@ -187,13 +236,54 @@ static struct irqaction clps711x_timer_irq = { static void __init clps711x_timer_init(void) { - unsigned int syscon; + u32 tmp; + + rtc_clk.rate = 32768; + osc_clk.rate = 3686400; + ext_clk.rate = 13000000; + + tmp = clps_readl(PLLR) >> 24; + if (tmp) + pll_clk.rate = (osc_clk.rate * tmp) / 2; + else + pll_clk.rate = 73728000; /* Default value */ + + tmp = clps_readl(SYSFLG2); + if (tmp & SYSFLG2_CKMODE) { + cpu_clk.rate = ext_clk.rate; + bus_clk.rate = cpu_clk.rate; + } else { + cpu_clk.rate = pll_clk.rate; + if (cpu_clk.rate >= 36864000) + bus_clk.rate = cpu_clk.rate / 2; + else + bus_clk.rate = 36864000 / 2; + } + + uart_clk.rate = bus_clk.rate / 10; + + if (tmp & SYSFLG2_CKMODE) { + tmp = clps_readl(SYSCON2); + if (tmp & SYSCON2_OSTB) + timer_h_clk.rate = ext_clk.rate / 26; /* 500 kHz */ + else + timer_h_clk.rate = 541440; + } else + timer_h_clk.rate = cpu_clk.rate / 144; + + timer_l_clk.rate = timer_h_clk.rate / 256; + + latch = (timer_h_clk.rate + HZ / 2) / HZ; + + clkdev_add_table(clps711x_lookups, ARRAY_SIZE(clps711x_lookups)); + + pr_info("CPU frequency set at %lu Hz.\n", cpu_clk.rate); - syscon = clps_readl(SYSCON1); - syscon |= SYSCON1_TC2S | SYSCON1_TC2M; - clps_writel(syscon, SYSCON1); + tmp = clps_readl(SYSCON1); + tmp |= SYSCON1_TC2S | SYSCON1_TC2M; + clps_writel(tmp, SYSCON1); - clps_writel(LATCH-1, TC2D); /* 512kHz / 100Hz - 1 */ + clps_writel(latch - 1, TC2D); setup_irq(IRQ_TC2OI, &clps711x_timer_irq); } diff --git a/arch/arm/mach-clps711x/include/mach/timex.h b/arch/arm/mach-clps711x/include/mach/timex.h index ac8823c..3d98736 100644 --- a/arch/arm/mach-clps711x/include/mach/timex.h +++ b/arch/arm/mach-clps711x/include/mach/timex.h @@ -1,23 +1,2 @@ -/* - * arch/arm/mach-clps711x/include/mach/timex.h - * - * Prospector 720T architecture timex specifications - * - * Copyright (C) 2000 Deep Blue Solutions Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - +/* Bugus value */ #define CLOCK_TICK_RATE 512000 diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index d0f719f..d9f4983 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -401,7 +402,6 @@ static struct uart_port clps711x_ports[UART_NR] = { { .iobase = SYSCON1, .irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */ - .uartclk = 3686400, .fifosize = 16, .ops = &clps711x_pops, .line = 0, @@ -410,7 +410,6 @@ static struct uart_port clps711x_ports[UART_NR] = { { .iobase = SYSCON2, .irq = IRQ_UTXINT2, /* IRQ_URXINT2 */ - .uartclk = 3686400, .fifosize = 16, .ops = &clps711x_pops, .line = 1, @@ -418,6 +417,17 @@ static struct uart_port clps711x_ports[UART_NR] = { } }; +static unsigned long clps711xuart_get_uartclk(void) +{ + struct clk *uart_clk; + + uart_clk = clk_get(NULL, "uart"); + if (!IS_ERR(uart_clk)) + return clk_get_rate(uart_clk); + + return 3686400; /* Default value */ +} + #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE static void clps711xuart_console_putchar(struct uart_port *port, int ch) { @@ -501,6 +511,7 @@ static int __init clps711xuart_console_setup(struct console *co, char *options) * console support. */ port = uart_get_console(clps711x_ports, UART_NR, co); + port->uartclk = clps711xuart_get_uartclk(); if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -553,8 +564,10 @@ static int __init clps711xuart_init(void) if (ret) return ret; - for (i = 0; i < UART_NR; i++) + for (i = 0; i < UART_NR; i++) { + clps711x_ports[i].uartclk = clps711xuart_get_uartclk(); uart_add_one_port(&clps711x_reg, &clps711x_ports[i]); + } return 0; }