From patchwork Thu Apr 30 14:44:21 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shenwei Wang X-Patchwork-Id: 6304631 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A18F3BEEE1 for ; Thu, 30 Apr 2015 14:52:48 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A78E3201EC for ; Thu, 30 Apr 2015 14:52:47 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 972A7201BB for ; Thu, 30 Apr 2015 14:52:46 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YnpmS-0006p6-UC; Thu, 30 Apr 2015 14:49:36 +0000 Received: from mail-bl2on0108.outbound.protection.outlook.com ([65.55.169.108] helo=na01-bl2-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YnpjZ-0005Ew-U2 for linux-arm-kernel@lists.infradead.org; Thu, 30 Apr 2015 14:46:39 +0000 Received: from DM2PR0301MB1200.namprd03.prod.outlook.com (25.160.217.15) by DM2PR0301MB0895.namprd03.prod.outlook.com (25.160.216.145) with Microsoft SMTP Server (TLS) id 15.1.148.15; Thu, 30 Apr 2015 14:46:16 +0000 Received: from BY2PR03CA047.namprd03.prod.outlook.com (10.141.249.20) by DM2PR0301MB1200.namprd03.prod.outlook.com (25.160.217.15) with Microsoft SMTP Server (TLS) id 15.1.148.15; Thu, 30 Apr 2015 14:46:15 +0000 Received: from BL2FFO11FD039.protection.gbl (2a01:111:f400:7c09::177) by BY2PR03CA047.outlook.office365.com (2a01:111:e400:2c5d::20) with Microsoft SMTP Server (TLS) id 15.1.154.19 via Frontend Transport; Thu, 30 Apr 2015 14:46:15 +0000 Authentication-Results: spf=fail (sender IP is 192.88.158.2) smtp.mailfrom=freescale.com; lists.infradead.org; dkim=none (message not signed) header.d=none; Received-SPF: Fail (protection.outlook.com: domain of freescale.com does not designate 192.88.158.2 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.158.2; helo=az84smr01.freescale.net; Received: from az84smr01.freescale.net (192.88.158.2) by BL2FFO11FD039.mail.protection.outlook.com (10.173.161.135) with Microsoft SMTP Server (TLS) id 15.1.160.8 via Frontend Transport; Thu, 30 Apr 2015 14:46:14 +0000 Received: from [az84smr01.freescale.net (B38339-11.am.freescale.net [10.81.92.140]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id t3UEieiX026417; Thu, 30 Apr 2015 07:46:12 -0700 From: Shenwei Wang To: Subject: [PATCH 06/18] ARM: imx: New timer driver APIs based on IP block Date: Thu, 30 Apr 2015 09:44:21 -0500 Message-ID: <1430405073-13106-7-git-send-email-shenwei.wang@freescale.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1430405073-13106-1-git-send-email-shenwei.wang@freescale.com> References: <1430405073-13106-1-git-send-email-shenwei.wang@freescale.com> X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:192.88.158.2; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(339900001)(189002)(199003)(2351001)(77156002)(62966003)(92566002)(36756003)(33646002)(229853001)(104016003)(87936001)(106466001)(5001960100002)(76176999)(50986999)(110136002)(77096005)(2950100001)(47776003)(86362001)(105606002)(46102003)(48376002)(50466002)(19580405001)(85426001)(6806004)(19580395003)(50226001); DIR:OUT; SFP:1102; SCL:1; SRVR:DM2PR0301MB1200; H:az84smr01.freescale.net; FPR:; SPF:Fail; MLV:sfv; MX:1; A:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:; SRVR:DM2PR0301MB1200; UriScan:; BCL:0; PCL:0; RULEID:; SRVR:DM2PR0301MB0895; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(5005006)(3002001); SRVR:DM2PR0301MB1200; BCL:0; PCL:0; RULEID:; SRVR:DM2PR0301MB1200; X-Forefront-PRVS: 056297E276 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 30 Apr 2015 14:46:14.5044 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d; Ip=[192.88.158.2]; Helo=[az84smr01.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM2PR0301MB1200 X-OriginatorOrg: freescale.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150430_074638_186299_793DA02F X-CRM114-Status: GOOD ( 12.00 ) X-Spam-Score: -0.2 (/) Cc: linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Implemented the necessory imx timer driver APIs directly based on the version of IP block. These APIs are only relating to the version of the timer block, and are independent of the SoC. Signed-off-by: Shenwei Wang --- arch/arm/mach-imx/time.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c index 4db233f..811d50a 100644 --- a/arch/arm/mach-imx/time.c +++ b/arch/arm/mach-imx/time.c @@ -101,6 +101,54 @@ static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED; static void __iomem *timer_base; +static void gpt_irq_disable_v0_v1(struct imx_timer *tm) +{ + unsigned int tmp; + + tmp = __raw_readl(tm->timer_base + MXC_TCTL); + __raw_writel(tmp & ~MX1_2_TCTL_IRQEN, tm->timer_base + MXC_TCTL); + +} + +static void gpt_irq_disable_v2_v3(struct imx_timer *tm) +{ + __raw_writel(0, tm->timer_base + V2_IR); + +} + +static void gpt_irq_enable_v0_v1(struct imx_timer *tm) +{ + __raw_writel(__raw_readl(tm->timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN, + tm->timer_base + MXC_TCTL); +} + +static void gpt_irq_enable_v2_v3(struct imx_timer *tm) +{ + __raw_writel(1, tm->timer_base + V2_IR); +} + +static void gpt_irq_acknowledge_v0(struct imx_timer *tm) +{ + __raw_readl(tm->timer_base + MX1_2_TSTAT); + + __raw_writel(0, tm->timer_base + MX1_2_TSTAT); +} + +static void gpt_irq_acknowledge_v1(struct imx_timer *tm) +{ + __raw_readl(tm->timer_base + MX1_2_TSTAT); + + __raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP, + tm->timer_base + MX1_2_TSTAT); +} + +static void gpt_irq_acknowledge_v2_v3(struct imx_timer *tm) +{ + __raw_readl(tm->timer_base + V2_TSTAT); + + __raw_writel(V2_TSTAT_OF1, tm->timer_base + V2_TSTAT); +} + static inline void gpt_irq_disable(void) { unsigned int tmp; @@ -314,6 +362,129 @@ static int __init mxc_clockevent_init(struct clk *timer_clk, return 0; } +static void __init _mxc_timer_init_v0_v1(int irq, struct clk *clk_per, + struct clk *clk_ipg, struct imx_timer *tm) +{ + uint32_t tctl_val; + + if (IS_ERR(clk_per)) { + pr_err("i.MX timer: unable to get clk\n"); + return; + } + + if (!IS_ERR(clk_ipg)) + clk_prepare_enable(clk_ipg); + + clk_prepare_enable(clk_per); + + /* + * Initialise to a known state (all timers off, and timing reset) + */ + + __raw_writel(0, tm->timer_base + MXC_TCTL); + __raw_writel(0, tm->timer_base + MXC_TPRER); /* see datasheet note */ + + tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN; + + __raw_writel(tctl_val, tm->timer_base + MXC_TCTL); + + /* init and register the timer to the framework */ + mxc_clocksource_init(clk_per, tm->timer_base + MX1_2_TCN); + + tm->evt.set_next_event = mx1_2_set_next_event; + mxc_clockevent_init(clk_per, tm); + + /* Make irqs happen */ + setup_irq(irq, &tm->act); +} + +static void __init _mxc_timer_init_v2(int irq, struct clk *clk_per, + struct clk *clk_ipg, struct imx_timer *tm) +{ + uint32_t tctl_val; + + if (IS_ERR(clk_per)) { + pr_err("i.MX timer: unable to get clk\n"); + return; + } + + if (!IS_ERR(clk_ipg)) + clk_prepare_enable(clk_ipg); + + clk_prepare_enable(clk_per); + + /* + * Initialise to a known state (all timers off, and timing reset) + */ + + __raw_writel(0, tm->timer_base + MXC_TCTL); + __raw_writel(0, tm->timer_base + MXC_TPRER); /* see datasheet note */ + + tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN; + + if (clk_get_rate(clk_per) == V2_TIMER_RATE_OSC_DIV8) + tctl_val |= V2_TCTL_CLK_OSC_DIV8; + else + tctl_val |= V2_TCTL_CLK_PER; + + __raw_writel(tctl_val, tm->timer_base + MXC_TCTL); + + /* init and register the timer to the framework */ + mxc_clocksource_init(clk_per, tm->timer_base + V2_TCN); + + tm->evt.set_next_event = v2_set_next_event; + mxc_clockevent_init(clk_per, tm); + + /* Make irqs happen */ + setup_irq(irq, &tm->act); +} + +static void __init _mxc_timer_init_v3(int irq, struct clk *clk_per, + struct clk *clk_ipg, struct imx_timer *tm) +{ + uint32_t tctl_val; + + if (IS_ERR(clk_per)) { + pr_err("i.MX timer: unable to get clk\n"); + return; + } + + if (!IS_ERR(clk_ipg)) + clk_prepare_enable(clk_ipg); + + clk_prepare_enable(clk_per); + + /* + * Initialise to a known state (all timers off, and timing reset) + */ + + __raw_writel(0, tm->timer_base + MXC_TCTL); + __raw_writel(0, tm->timer_base + MXC_TPRER); /* see datasheet note */ + + tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN; + + if (clk_get_rate(clk_per) == V2_TIMER_RATE_OSC_DIV8) { + tctl_val |= V2_TCTL_CLK_OSC_DIV8; + /* 24 / 8 = 3 MHz */ + __raw_writel(7 << V2_TPRER_PRE24M, + tm->timer_base + MXC_TPRER); + tctl_val |= V2_TCTL_24MEN; + } else { + tctl_val |= V2_TCTL_CLK_PER; + } + + __raw_writel(tctl_val, tm->timer_base + MXC_TCTL); + + /* init and register the timer to the framework */ + mxc_clocksource_init(clk_per, tm->timer_base + V2_TCN); + + tm->evt.set_next_event = v2_set_next_event; + mxc_clockevent_init(clk_per, tm); + + /* Make irqs happen */ + setup_irq(irq, &tm->act); +} + static void __init _mxc_timer_init(int irq, struct clk *clk_per, struct clk *clk_ipg) {