From patchwork Mon Oct 2 15:51:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Gaignard X-Patchwork-Id: 9980965 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 14ED660384 for ; Mon, 2 Oct 2017 15:53:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 05C27274D0 for ; Mon, 2 Oct 2017 15:53:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EE9C928409; Mon, 2 Oct 2017 15:53:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 1115C274D0 for ; Mon, 2 Oct 2017 15:53:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=O2yZtzPSJg7lNWeH0vUmrAPTXkSxvINwp3yOodMkA1w=; b=d/mh6CO5Z1s8lERkJuG/Do/4XD cfIOPZEYRrJzpz+kwt/IjodaI3MbzC8z+JEVWuT1Azw5MizPSrMBio3SIToYNEq2IXVhxJ79kEFY1 2AG3WdnDl4YjAhSrbx+zw7Pna2YA/wkoIly6We1IL1+AjNznLPjTTL5lLK9x7COm85S3OAh0H9xX5 DhVEJKpvaSsvu8msB17dMoWDsQf+1gsOox0FJPb3NghVdCksI288xbptjkNX9ScnCekL2TydNF6Dh YGCQyctGZRSMn/sU9rMhtkNwsu7Yc78WiwoooYbJz6fa/9rw+KQex84IXO10z6e6TnLg74gmOs0GP eCJe+3DA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dz32H-0001bD-6h; Mon, 02 Oct 2017 15:53:37 +0000 Received: from mail-wm0-x233.google.com ([2a00:1450:400c:c09::233]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dz31K-0000ah-TR for linux-arm-kernel@lists.infradead.org; Mon, 02 Oct 2017 15:52:49 +0000 Received: by mail-wm0-x233.google.com with SMTP id b189so7599208wmd.4 for ; Mon, 02 Oct 2017 08:52:18 -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=ADuRWyMG7N2FJYUExchivn9fPQsNUrPQ2lkd2LV7at6UhhYPxmEf/MDRV4q2a/JTVo EQCoiN986wZYpDducMXZ6fYzl1CTIwhFBOxFURzB7irDcBXF9sDl+CTPX+G2ki6512lb FXdgez/SJ9udFY+b55kCyAejmq0g077jqtH3E= 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=nDo887/h2rW/C1vXvYgUIOdEsrBQpIVCIGc3BbpVpnSE4oAOD7E7y0k1/AyKBYdeNU Z5xpH/IgOZTUNtBNl2T3SaqatITrpJIF/hfjQUp5tp2IbtoTnlxkezbsKvqal/6ENJym 4MlepeGLK0e8pMJg/fnusqf6heIMaKdSqHVNIwdhuodjOSr5j3OXaXezAySwPksrEaxa mI40RQ37lb2a2ytzJYkwYvobcCeRWioElXZ2z+yIIqJ7NKDYfuUnDj08fXeQww3vOKMV 19DN313uD9eLYrUsVRLO66dbVwYl8MjTF6wlxV4IJvk1e7tiRUqzSoLEAda53IMe5ihR 5+Bg== X-Gm-Message-State: AHPjjUgs1pHtNjI5PSk6zhfsmdfjmiGxlJUTyUGf9BP1+3d2Bd6xMMEK E84fu5yeNgN9weJRh5034ut9KQ== X-Google-Smtp-Source: AOwi7QDft/dpo5QueLRvazv4jTm9FMMs5dqXisX7yVAVReKTGtD2UU8LJnRWBB4U9EMvzGEYYV7gNw== X-Received: by 10.28.144.206 with SMTP id s197mr12212595wmd.142.1506959537042; Mon, 02 Oct 2017 08:52:17 -0700 (PDT) Received: from lmecxl0911.lme.st.com ([80.215.74.152]) by smtp.gmail.com with ESMTPSA id w5sm6724879wrg.65.2017.10.02.08.52.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 02 Oct 2017 08:52:16 -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 Subject: [PATCH v4 3/4] clocksource: stm32: add clocksource support Date: Mon, 2 Oct 2017 17:51:52 +0200 Message-Id: <1506959513-16851-4-git-send-email-benjamin.gaignard@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1506959513-16851-1-git-send-email-benjamin.gaignard@linaro.org> References: <1506959513-16851-1-git-send-email-benjamin.gaignard@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171002_085239_486313_B154AF7D X-CRM114-Status: GOOD ( 16.73 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, Benjamin Gaignard , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP 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(-) 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);