From patchwork Wed Oct 18 07:43:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Gaignard X-Patchwork-Id: 116235 Delivered-To: patch@linaro.org Received: by 10.140.22.163 with SMTP id 32csp5771755qgn; Wed, 18 Oct 2017 00:44:10 -0700 (PDT) X-Received: by 10.101.65.75 with SMTP id x11mr12910963pgp.388.1508312650635; Wed, 18 Oct 2017 00:44:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1508312650; cv=none; d=google.com; s=arc-20160816; b=YInnYCy9QtiF6Kc3JHJouOusD6+bTmctd8opFWEPWO/I/HlUrMhhMUV9lqt7Qm5nNk 3CsEg+Is8wjriDg4uH67+4l1F0Ng8vzcx/79pXa8qEgADsJ8lNLrK9Lj3US2CsKwaiLg zUJTTekpPyyCs3/V1+yg5rCfMW7TVTaCE9NTdXuhJ4vZIOdHE8F2puRu8+afWLseILcU gvjXBSBG81PTsqFNWlDRMAWROjzQJiUiK9XScEXMT30VaRz/GiVCZwpFoTdFCo4YxDgY /FX8lOJsUggH7WFLSeI4/p0tC6kZuRXZoWHWAl9WsqiFM7OO0//OfV3jIh4BlHYjLX9g h5OQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=6JH4Hn7ZCjUX0f12s9LItjzS3ACqz7dGI7sGncsOL7o=; b=pUEp6puUwiBB6F/pZ2k8DnXF7/506ibAuISpFp+yZ2qWeN9f+oYqfUGSNnUSW8gyMK 6JCIm4HMJ8G/7eWvrYJ/bw8AzI4ozh0dmdKXrTef+NLRRHTsJHJU/NVj1TPZEdvymxPm SMuMJQP+nlXAjB4jmQEAVDnWOm8qSICIO5Nblslqq5gNFkEjiQRSu/oK9OiU2gkQGZtj POEphgoVYGdjHCinbKSbU5+y6kfYiym3/LVBiEAur/7kpnKoqqK+ZBMxjJqL5UvPdHXs YF+pkUWqAo05/MYSfwSp4SHOGMFq/VsUHqBgiKWl0grncgc0wMjejEIyrCkYhzkPaFYQ yddA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=PEJBEgcs; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w18si6571656pgq.366.2017.10.18.00.44.10; Wed, 18 Oct 2017 00:44:10 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=PEJBEgcs; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S966868AbdJRHoI (ORCPT + 27 others); Wed, 18 Oct 2017 03:44:08 -0400 Received: from mail-wm0-f53.google.com ([74.125.82.53]:45802 "EHLO mail-wm0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935677AbdJRHoA (ORCPT ); Wed, 18 Oct 2017 03:44:00 -0400 Received: by mail-wm0-f53.google.com with SMTP id q124so8152693wmb.0 for ; Wed, 18 Oct 2017 00:43:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6JH4Hn7ZCjUX0f12s9LItjzS3ACqz7dGI7sGncsOL7o=; b=PEJBEgcsBfGD/oSexux4FdLzUiMDIZAVEzyUqCfKZkCjuxCZ69Q90ZJZgctANW0ZQh c2b6KvPkUwpyRnM68mTDMIl+RY5B8JNYG3lCVN/SmamYz602IwomaDLYNRp8fYGBdXfz 4mtUY2iXlM49CguOwV6wcdNV9hYx1I4V1Vxeg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6JH4Hn7ZCjUX0f12s9LItjzS3ACqz7dGI7sGncsOL7o=; b=II8kfgULdvjOJVsZakCt9Qps2ni8p1gk6kwDIg89fvZwfMM8oiDW8jn52cwZzsli+2 M5dqfsL4r0T8yjYN7LBJ/zpRcVGMPQEJEal/zyfdsbCsXniVSzD97KKToh5AoLbHe9JH dRoNb0ULZnRwHbS69reHhVt1SiQTTw+VheP4fJiT1CtT+T0+jAT3xgPV0FsBdf07AC6q 9MjjQqbpUTavH7+Ql8FF0HxtdJs5gD4roNY4lkQ4LKrz/vyoomlPUyXtGkrxlWWSrKEC z9ofre4v9UwfgWlPpelFwYRWlvVlY2DsQ9Za0cKP2cBKyWhOwqPkDmf1dbjSRTg3TUQM lDUg== X-Gm-Message-State: AMCzsaWJZ5EmJ6x5EYoWiKPhNyzHAqD6aWLJyoWbs4KdHFJ7bMYcFVTA HAyDe06WwXyBkVexscZQZ/ZSlg== X-Google-Smtp-Source: ABhQp+RMLZgbV4JrrajzJSUY1pkLcTGYWUzC/0WfzfQjR2oeheraeK9Y/04ZD9P/2PrvyJEiw+y4oA== X-Received: by 10.28.30.22 with SMTP id e22mr5438373wme.121.1508312639032; Wed, 18 Oct 2017 00:43:59 -0700 (PDT) Received: from lmecxl0911.lme.st.com ([80.215.78.118]) by smtp.gmail.com with ESMTPSA id v78sm7855063wmv.48.2017.10.18.00.43.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Oct 2017 00:43:58 -0700 (PDT) From: Benjamin Gaignard To: robh+dt@kernel.org, mark.rutland@arm.com, linux@armlinux.org.uk, mcoquelin.stm32@gmail.com, alexandre.torgue@st.com, daniel.lezcano@linaro.org, tglx@linutronix.de, ludovic.barre@st.com Cc: devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Benjamin Gaignard Subject: [PATCH v5 3/4] clocksource: stm32: add clocksource support Date: Wed, 18 Oct 2017 09:43:33 +0200 Message-Id: <1508312614-27750-4-git-send-email-benjamin.gaignard@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1508312614-27750-1-git-send-email-benjamin.gaignard@linaro.org> References: <1508312614-27750-1-git-send-email-benjamin.gaignard@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Rework driver code to be able to implement clocksource and clockevent on the same hardware block. Before this patch only the counter of the hardware block was used to generate clock events. Now counter will be used to provide a 32 bits clock source and a comparator will provide clock events. Signed-off-by: Benjamin Gaignard --- drivers/clocksource/timer-stm32.c | 104 ++++++++++++++++++++++++++++---------- 1 file changed, 76 insertions(+), 28 deletions(-) -- 2.7.4 diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c index f7e4eec..fb84252 100644 --- a/drivers/clocksource/timer-stm32.c +++ b/drivers/clocksource/timer-stm32.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include "timer-of.h" @@ -23,16 +25,16 @@ #define TIM_DIER 0x0c #define TIM_SR 0x10 #define TIM_EGR 0x14 +#define TIM_CNT 0x24 #define TIM_PSC 0x28 #define TIM_ARR 0x2c +#define TIM_CCR1 0x34 #define TIM_CR1_CEN BIT(0) -#define TIM_CR1_OPM BIT(3) +#define TIM_CR1_UDIS BIT(1) #define TIM_CR1_ARPE BIT(7) -#define TIM_DIER_UIE BIT(0) - -#define TIM_SR_UIF BIT(0) +#define TIM_DIER_CC1IE BIT(1) #define TIM_EGR_UG BIT(0) @@ -40,30 +42,34 @@ static int stm32_clock_event_shutdown(struct clock_event_device *evt) { struct timer_of *to = to_timer_of(evt); - writel_relaxed(0, timer_of_base(to) + TIM_CR1); + writel_relaxed(0, timer_of_base(to) + TIM_DIER); + return 0; } -static int stm32_clock_event_set_periodic(struct clock_event_device *evt) +static int stm32_clock_event_set_next_event(unsigned long evt, + struct clock_event_device *clkevt) { - struct timer_of *to = to_timer_of(evt); + struct timer_of *to = to_timer_of(clkevt); + unsigned long cnt; - writel_relaxed(timer_of_period(to), timer_of_base(to) + TIM_ARR); - writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1); + cnt = readl_relaxed(timer_of_base(to) + TIM_CNT); + writel_relaxed(cnt + evt, timer_of_base(to) + TIM_CCR1); + writel_relaxed(TIM_DIER_CC1IE, timer_of_base(to) + TIM_DIER); return 0; } -static int stm32_clock_event_set_next_event(unsigned long evt, - struct clock_event_device *clkevt) +static int stm32_clock_event_set_periodic(struct clock_event_device *evt) { - struct timer_of *to = to_timer_of(clkevt); + struct timer_of *to = to_timer_of(evt); - writel_relaxed(evt, timer_of_base(to) + TIM_ARR); - writel_relaxed(TIM_CR1_ARPE | TIM_CR1_OPM | TIM_CR1_CEN, - timer_of_base(to) + TIM_CR1); + return stm32_clock_event_set_next_event(timer_of_period(to), evt); +} - return 0; +static int stm32_clock_event_set_oneshot(struct clock_event_device *evt) +{ + return stm32_clock_event_set_next_event(0, evt); } static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id) @@ -73,12 +79,57 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id) writel_relaxed(0, timer_of_base(to) + TIM_SR); + if (clockevent_state_periodic(evt)) + stm32_clock_event_set_periodic(evt); + else + stm32_clock_event_shutdown(evt); + evt->event_handler(evt); return IRQ_HANDLED; } -static int __init stm32_clockevent_init(struct device_node *node) +static void __init stm32_clockevent_init(struct timer_of *to) +{ + writel_relaxed(0, timer_of_base(to) + TIM_DIER); + writel_relaxed(0, timer_of_base(to) + TIM_SR); + + clockevents_config_and_register(&to->clkevt, + timer_of_rate(to), 0x60, ~0U); +} + +static void __iomem *stm32_timer_cnt __read_mostly; +static u64 notrace stm32_read_sched_clock(void) +{ + return readl_relaxed(stm32_timer_cnt); +} + +static int __init stm32_clocksource_init(struct timer_of *to) +{ + writel_relaxed(~0U, timer_of_base(to) + TIM_ARR); + writel_relaxed(0, timer_of_base(to) + TIM_PSC); + writel_relaxed(0, timer_of_base(to) + TIM_SR); + writel_relaxed(0, timer_of_base(to) + TIM_DIER); + writel_relaxed(0, timer_of_base(to) + TIM_SR); + writel_relaxed(TIM_CR1_ARPE | TIM_CR1_UDIS, + timer_of_base(to) + TIM_CR1); + + /* Make sure that registers are updated */ + writel_relaxed(TIM_EGR_UG, timer_of_base(to) + TIM_EGR); + + /* Enable controller */ + writel_relaxed(TIM_CR1_ARPE | TIM_CR1_UDIS | TIM_CR1_CEN, + timer_of_base(to) + TIM_CR1); + + stm32_timer_cnt = timer_of_base(to) + TIM_CNT; + sched_clock_register(stm32_read_sched_clock, 32, timer_of_rate(to)); + + return clocksource_mmio_init(stm32_timer_cnt, "stm32_timer", + timer_of_rate(to), 250, 32, + clocksource_mmio_readl_up); +} + +static int __init stm32_timer_init(struct device_node *node) { struct reset_control *rstc; unsigned long max_arr; @@ -90,12 +141,13 @@ static int __init stm32_clockevent_init(struct device_node *node) return -ENOMEM; to->flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE; + to->clkevt.name = "stm32_clockevent"; to->clkevt.rating = 200; - to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC; + to->clkevt.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC; to->clkevt.set_state_shutdown = stm32_clock_event_shutdown; to->clkevt.set_state_periodic = stm32_clock_event_set_periodic; - to->clkevt.set_state_oneshot = stm32_clock_event_shutdown; + to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot; to->clkevt.tick_resume = stm32_clock_event_shutdown; to->clkevt.set_next_event = stm32_clock_event_set_next_event; @@ -119,17 +171,13 @@ static int __init stm32_clockevent_init(struct device_node *node) return -EINVAL; } - writel_relaxed(0, timer_of_base(to) + TIM_ARR); - - writel_relaxed(0, timer_of_base(to) + TIM_PSC); - writel_relaxed(TIM_EGR_UG, timer_of_base(to) + TIM_EGR); - writel_relaxed(TIM_DIER_UIE, timer_of_base(to) + TIM_DIER); - writel_relaxed(0, timer_of_base(to) + TIM_SR); + ret = stm32_clocksource_init(to); + if (ret) + return ret; - clockevents_config_and_register(&to->clkevt, - timer_of_period(to), 0x60, ~0U); + stm32_clockevent_init(to); return 0; } -TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_clockevent_init); +TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_timer_init);