From patchwork Tue Dec 23 07:58:44 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Baruch Siach X-Patchwork-Id: 5531281 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 37AB39F2F7 for ; Tue, 23 Dec 2014 08:04:26 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 29257200F4 for ; Tue, 23 Dec 2014 08:04:25 +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 2FBAF200F3 for ; Tue, 23 Dec 2014 08:04:24 +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 1Y3KPY-0004aM-U3; Tue, 23 Dec 2014 08:01:44 +0000 Received: from guitar.tcltek.co.il ([192.115.133.116] helo=mx.tkos.co.il) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Y3KO2-0002mF-2Z for linux-arm-kernel@lists.infradead.org; Tue, 23 Dec 2014 08:00:13 +0000 Received: from tarshish.tkos.co.il (unknown [10.0.8.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) by mx.tkos.co.il (Postfix) with ESMTPSA id 5FF32440C12; Tue, 23 Dec 2014 09:59:31 +0200 (IST) From: Baruch Siach To: Daniel Lezcano , Thomas Gleixner Subject: [PATCH 7/8] clocksource: driver for Conexant Digicolor SoC timer Date: Tue, 23 Dec 2014 09:58:44 +0200 Message-Id: <0e981c4f437df8754b55f96d1e8a720eb3facbc1.1419318109.git.baruch@tkos.co.il> X-Mailer: git-send-email 2.1.3 In-Reply-To: References: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20141223_000010_759317_723A1AC0 X-CRM114-Status: GOOD ( 17.30 ) X-Spam-Score: 0.0 (/) Cc: Baruch Siach , Russell King , linux-kernel@vger.kernel.org, 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: , MIME-Version: 1.0 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 Signed-off-by: Baruch Siach --- arch/arm/mach-digicolor/Kconfig | 1 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-digicolor.c | 155 ++++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 drivers/clocksource/timer-digicolor.c diff --git a/arch/arm/mach-digicolor/Kconfig b/arch/arm/mach-digicolor/Kconfig index 4830122a9dd0..1e53f684a522 100644 --- a/arch/arm/mach-digicolor/Kconfig +++ b/arch/arm/mach-digicolor/Kconfig @@ -1,3 +1,4 @@ config ARCH_DIGICOLOR bool "Conexant Digicolor SoC Support" depends on ARCH_MULTI_V7 + select CLKSRC_MMIO diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 94d90b24b56b..a993c108be67 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o obj-$(CONFIG_EM_TIMER_STI) += em_sti.o obj-$(CONFIG_CLKBLD_I8253) += i8253.o obj-$(CONFIG_CLKSRC_MMIO) += mmio.o +obj-$(CONFIG_ARCH_DIGICOLOR) += timer-digicolor.o obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o diff --git a/drivers/clocksource/timer-digicolor.c b/drivers/clocksource/timer-digicolor.c new file mode 100644 index 000000000000..16dc17894276 --- /dev/null +++ b/drivers/clocksource/timer-digicolor.c @@ -0,0 +1,155 @@ +/* + * Conexant Digicolor timer driver + * + * Author: Baruch Siach + * + * Copyright (C) 2014 Paradox Innovation Ltd. + * + * Based on: + * Allwinner SoCs hstimer driver + * + * Copyright (C) 2013 Maxime Ripard + * + * Maxime Ripard + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +/* + * Conexant Digicolor SoCs have 8 configurable timers, named from "Timer A" to + * "Timer H". Timer A is the only one with watchdog support, so it is dedicated + * to the watchdog driver. This driver uses Timer B for sched_clock(), and + * Timer C for clockevents. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AC_TIMER_B_CONTROL 0x0fc8 +#define AC_TIMER_B_COUNT_LO 0x0fcc +#define AC_TIMER_C_CONTROL 0x0fd0 +#define AC_TIMER_C_COUNT_LO 0x0fd4 + +static void __iomem *timer_base; +static u32 ticks_per_jiffy; + +static void digicolor_clkevt_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + writeb(0, timer_base + AC_TIMER_C_CONTROL); + writel(ticks_per_jiffy, timer_base + AC_TIMER_C_COUNT_LO); + writeb(0x21, timer_base + AC_TIMER_C_CONTROL); + break; + case CLOCK_EVT_MODE_ONESHOT: + writeb(0, timer_base + AC_TIMER_C_CONTROL); + writeb(0x11, timer_base + AC_TIMER_C_CONTROL); + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + default: + writeb(0, timer_base + AC_TIMER_C_CONTROL); + break; + } +} + +static int digicolor_clkevt_next_event(unsigned long evt, + struct clock_event_device *unused) +{ + writeb(0, timer_base + AC_TIMER_C_CONTROL); + writel(evt, timer_base + AC_TIMER_C_COUNT_LO); + writeb(0x11, timer_base + AC_TIMER_C_CONTROL); + + return 0; +} + +static struct clock_event_device digicolor_clockevent = { + .name = "digicolor_tick", + .rating = 340, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_mode = digicolor_clkevt_mode, + .set_next_event = digicolor_clkevt_next_event, +}; + + +static irqreturn_t digicolor_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = (struct clock_event_device *)dev_id; + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction digicolor_timer_irq = { + .name = "digicolor_timerC", + .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = digicolor_timer_interrupt, + .dev_id = &digicolor_clockevent, +}; + +static u64 digicolor_timer_sched_read(void) +{ + return ~readl(timer_base + AC_TIMER_B_COUNT_LO); +} + +static void __init digicolor_timer_init(struct device_node *node) +{ + unsigned long rate; + struct clk *clk; + int ret, irq; + + timer_base = of_iomap(node, 0); + if (!timer_base) { + pr_err("Can't map registers"); + return; + } + + irq = irq_of_parse_and_map(node, 2); /* Timer C */ + if (irq <= 0) { + pr_err("Can't parse IRQ"); + return; + } + + clk = of_clk_get(node, 0); + if (IS_ERR(clk)) { + pr_err("Can't get timer clock"); + return; + } + clk_prepare_enable(clk); + rate = clk_get_rate(clk); + + writeb(0, timer_base + AC_TIMER_B_CONTROL); + writel(~0, timer_base + AC_TIMER_B_COUNT_LO); + writeb(1, timer_base + AC_TIMER_B_CONTROL); + + sched_clock_register(digicolor_timer_sched_read, 32, rate); + clocksource_mmio_init(timer_base + AC_TIMER_B_COUNT_LO, node->name, + rate, 340, 32, clocksource_mmio_readl_down); + + ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); + + ret = setup_irq(irq, &digicolor_timer_irq); + if (ret) + pr_warn("failed to setup timer irq %d (%d)\n", irq, ret); + + digicolor_clockevent.cpumask = cpu_possible_mask; + digicolor_clockevent.irq = irq; + + clockevents_config_and_register(&digicolor_clockevent, rate, 0, + 0xffffffff); +} +CLOCKSOURCE_OF_DECLARE(conexant_digicolor, "cnxt,cx92755-timer", + digicolor_timer_init);