From patchwork Thu Jan 29 13:08:16 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 43930 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f198.google.com (mail-wi0-f198.google.com [209.85.212.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 29B2624119 for ; Thu, 29 Jan 2015 13:09:59 +0000 (UTC) Received: by mail-wi0-f198.google.com with SMTP id h11sf12579723wiw.1 for ; Thu, 29 Jan 2015 05:09:58 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=kdHlZ4TQkDgmkkJCUOVLDpWR+7W/DBKwfN3m4NpmYFs=; b=M4l9F8YnaOxcT3Y0335zDfJHeZ7v+jW/qGLJUtRwBQ3BV5WdYMwg72i/We0A1SzzCg iuxRXF3WyJQHWUeHu6F49jO0nDNSwamwPnT0Nm+uAX5KDgy3Lv5Nrp41zRktR0V3Yk7P OWnhTLHlisFyhZJPov2/j11NdsfxI7wNxTAotJjK0SXjUHvOzwMZA5OXF/0tEKOw11Bn 8/LflxbPIYenEtyLJDn/7MkzjkYrWBlxVIBpC3dth90ABl7RMiYZoIAWWMZq2gBAJ4ID grhOHvhxNFuSADtmYtD4WjxBp+lPI6C/iZrkHQ56UCTJi+OYw0oUVlft1H/lbxI89FzB COBQ== X-Gm-Message-State: ALoCoQlm3gUvjE12vyPM1S8THzHC81YQynOCpgliIdtM2wRdXm7tRsrY9VtcLmY7BaN/tQhTEbNX X-Received: by 10.180.108.197 with SMTP id hm5mr2931wib.4.1422536998462; Thu, 29 Jan 2015 05:09:58 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.88.70 with SMTP id be6ls299918lab.41.gmail; Thu, 29 Jan 2015 05:09:58 -0800 (PST) X-Received: by 10.152.22.129 with SMTP id d1mr695185laf.22.1422536998135; Thu, 29 Jan 2015 05:09:58 -0800 (PST) Received: from mail-lb0-f178.google.com (mail-lb0-f178.google.com. [209.85.217.178]) by mx.google.com with ESMTPS id pl3si7399722lac.8.2015.01.29.05.09.58 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 29 Jan 2015 05:09:58 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.178 as permitted sender) client-ip=209.85.217.178; Received: by mail-lb0-f178.google.com with SMTP id u10so27814112lbd.9 for ; Thu, 29 Jan 2015 05:09:58 -0800 (PST) X-Received: by 10.152.8.1 with SMTP id n1mr495800laa.47.1422536997988; Thu, 29 Jan 2015 05:09:57 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.35.133 with SMTP id h5csp1757401lbj; Thu, 29 Jan 2015 05:09:56 -0800 (PST) X-Received: by 10.66.174.165 with SMTP id bt5mr513904pac.53.1422536995228; Thu, 29 Jan 2015 05:09:55 -0800 (PST) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id bl1si9723140pbb.192.2015.01.29.05.09.25; Thu, 29 Jan 2015 05:09:55 -0800 (PST) Received-SPF: none (google.com: linux-kernel-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932222AbbA2NIo (ORCPT + 28 others); Thu, 29 Jan 2015 08:08:44 -0500 Received: from mail-we0-f176.google.com ([74.125.82.176]:33367 "EHLO mail-we0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932087AbbA2NIl (ORCPT ); Thu, 29 Jan 2015 08:08:41 -0500 Received: by mail-we0-f176.google.com with SMTP id w62so23332000wes.7 for ; Thu, 29 Jan 2015 05:08:40 -0800 (PST) X-Received: by 10.195.12.35 with SMTP id en3mr590754wjd.129.1422536919910; Thu, 29 Jan 2015 05:08:39 -0800 (PST) Received: from mai.lan (135-224-190-109.dsl.ovh.fr. [109.190.224.135]) by mx.google.com with ESMTPSA id fo17sm10415824wjc.19.2015.01.29.05.08.37 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 29 Jan 2015 05:08:39 -0800 (PST) From: Daniel Lezcano To: tglx@linutronix.de Cc: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Barry.Song@csr.com, baruch@tkos.co.il, linux@rempel-privat.de, rob.herring@linaro.org, thierry.reding@gmail.com Subject: [PATCH 6/9] clocksource: Driver for Conexant Digicolor SoC timer Date: Thu, 29 Jan 2015 14:08:16 +0100 Message-Id: <1422536899-16609-6-git-send-email-daniel.lezcano@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1422536899-16609-1-git-send-email-daniel.lezcano@linaro.org> References: <54CA3044.6070501@linaro.org> <1422536899-16609-1-git-send-email-daniel.lezcano@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: daniel.lezcano@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.178 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Baruch Siach Add clocksource driver to the Conexant CX92755 SoC, part of the Digicolor SoCs series. Hardware provides 8 timers, A to H. Timer A is dedicated to a future watchdog driver so we don't use it here. Use timer B for sched_clock, and timer C for clock_event. Signed-off-by: Baruch Siach Signed-off-by: Daniel Lezcano --- drivers/clocksource/Kconfig | 3 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-digicolor.c | 199 ++++++++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 drivers/clocksource/timer-digicolor.c diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index a89120b..72a3827 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -18,6 +18,9 @@ config CLKBLD_I8253 config CLKSRC_MMIO bool +config DIGICOLOR_TIMER + bool + config DW_APB_TIMER bool diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 21c11e2..0f8003d 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_DIGICOLOR_TIMER) += 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_ROCKCHIP_TIMER) += rockchip_timer.o diff --git a/drivers/clocksource/timer-digicolor.c b/drivers/clocksource/timer-digicolor.c new file mode 100644 index 0000000..7f8388c --- /dev/null +++ b/drivers/clocksource/timer-digicolor.c @@ -0,0 +1,199 @@ +/* + * 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 + +enum { + TIMER_A, + TIMER_B, + TIMER_C, + TIMER_D, + TIMER_E, + TIMER_F, + TIMER_G, + TIMER_H, +}; + +#define CONTROL(t) ((t)*8) +#define COUNT(t) ((t)*8 + 4) + +#define CONTROL_DISABLE 0 +#define CONTROL_ENABLE BIT(0) +#define CONTROL_MODE(m) ((m) << 4) +#define CONTROL_MODE_ONESHOT CONTROL_MODE(1) +#define CONTROL_MODE_PERIODIC CONTROL_MODE(2) + +struct digicolor_timer { + struct clock_event_device ce; + void __iomem *base; + u32 ticks_per_jiffy; + int timer_id; /* one of TIMER_* */ +}; + +struct digicolor_timer *dc_timer(struct clock_event_device *ce) +{ + return container_of(ce, struct digicolor_timer, ce); +} + +static inline void dc_timer_disable(struct clock_event_device *ce) +{ + struct digicolor_timer *dt = dc_timer(ce); + writeb(CONTROL_DISABLE, dt->base + CONTROL(dt->timer_id)); +} + +static inline void dc_timer_enable(struct clock_event_device *ce, u32 mode) +{ + struct digicolor_timer *dt = dc_timer(ce); + writeb(CONTROL_ENABLE | mode, dt->base + CONTROL(dt->timer_id)); +} + +static inline void dc_timer_set_count(struct clock_event_device *ce, + unsigned long count) +{ + struct digicolor_timer *dt = dc_timer(ce); + writel(count, dt->base + COUNT(dt->timer_id)); +} + +static void digicolor_clkevt_mode(enum clock_event_mode mode, + struct clock_event_device *ce) +{ + struct digicolor_timer *dt = dc_timer(ce); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + dc_timer_disable(ce); + dc_timer_set_count(ce, dt->ticks_per_jiffy); + dc_timer_enable(ce, CONTROL_MODE_PERIODIC); + break; + case CLOCK_EVT_MODE_ONESHOT: + dc_timer_disable(ce); + dc_timer_enable(ce, CONTROL_MODE_ONESHOT); + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + default: + dc_timer_disable(ce); + break; + } +} + +static int digicolor_clkevt_next_event(unsigned long evt, + struct clock_event_device *ce) +{ + dc_timer_disable(ce); + dc_timer_set_count(ce, evt); + dc_timer_enable(ce, CONTROL_MODE_ONESHOT); + + return 0; +} + +static struct digicolor_timer dc_timer_dev = { + .ce = { + .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, + }, + .timer_id = TIMER_C, +}; + +static irqreturn_t digicolor_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static u64 digicolor_timer_sched_read(void) +{ + return ~readl(dc_timer_dev.base + COUNT(TIMER_B)); +} + +static void __init digicolor_timer_init(struct device_node *node) +{ + unsigned long rate; + struct clk *clk; + int ret, irq; + + /* + * timer registers are shared with the watchdog timer; + * don't map exclusively + */ + dc_timer_dev.base = of_iomap(node, 0); + if (!dc_timer_dev.base) { + pr_err("Can't map registers"); + return; + } + + irq = irq_of_parse_and_map(node, dc_timer_dev.timer_id); + 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); + dc_timer_dev.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); + + writeb(CONTROL_DISABLE, dc_timer_dev.base + CONTROL(TIMER_B)); + writel(UINT_MAX, dc_timer_dev.base + COUNT(TIMER_B)); + writeb(CONTROL_ENABLE, dc_timer_dev.base + CONTROL(TIMER_B)); + + sched_clock_register(digicolor_timer_sched_read, 32, rate); + clocksource_mmio_init(dc_timer_dev.base + COUNT(TIMER_B), node->name, + rate, 340, 32, clocksource_mmio_readl_down); + + ret = request_irq(irq, digicolor_timer_interrupt, + IRQF_TIMER | IRQF_IRQPOLL, "digicolor_timerC", + &dc_timer_dev.ce); + if (ret) + pr_warn("request of timer irq %d failed (%d)\n", irq, ret); + + dc_timer_dev.ce.cpumask = cpu_possible_mask; + dc_timer_dev.ce.irq = irq; + + clockevents_config_and_register(&dc_timer_dev.ce, rate, 0, 0xffffffff); +} +CLOCKSOURCE_OF_DECLARE(conexant_digicolor, "cnxt,cx92755-timer", + digicolor_timer_init);