From patchwork Mon Jan 8 13:28:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 10149635 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 82F05602CA for ; Mon, 8 Jan 2018 13:38:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 662422856B for ; Mon, 8 Jan 2018 13:38:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5B29728632; Mon, 8 Jan 2018 13:38:57 +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 E70812856B for ; Mon, 8 Jan 2018 13:38:56 +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=+JevXBKlcy9/Se0QieR5Y9xG18AalTQLlXomE04KmRg=; b=nXj3aclwR5Qbh/zznrMSBTqSVs lGwyZwWCVNSrD7FQ5WUP3zY7Xw0fikT2K3ziFYR7EPWQjaFqpS+w4frxzqioYVVOENWMFdtO0VeUQ i+nmE6M9apgutxrpAAWUUFRdWRhyn8OX/ZlRlxXwMKkQeZjXLVQFK8ScA4g9SZjPFIrMkZmh8tr3F Otb97ad0Yy/qflcpAUQQM166C3bMB6Qwu1EGqgYCUmkvN40p8duy6QwiQjJunqn/GBFL+0Gd4cN7H R/WxmGe0P7gpyEJGH2imUOEgICsWa/TaKn5wjpZYwihMiNOuafmeQ8ffCH3tSO/Hh2SgplDLDpOqc X9tempmQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1eYXdY-0001pv-GM; Mon, 08 Jan 2018 13:38:48 +0000 Received: from mail-wm0-x241.google.com ([2a00:1450:400c:c09::241]) by bombadil.infradead.org with esmtps (Exim 4.89 #1 (Red Hat Linux)) id 1eYXV1-0003MO-8N for linux-arm-kernel@lists.infradead.org; Mon, 08 Jan 2018 13:30:20 +0000 Received: by mail-wm0-x241.google.com with SMTP id i11so14200341wmf.4 for ; Mon, 08 Jan 2018 05:29:53 -0800 (PST) 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=WxW0wTXrQlL11cQloR5uFczaFJHJAFTucfu/a7Auct0=; b=UQ536CFx1KSNZwIcLAGAaAF8vgWhwaFTO7Zi/cFZoycBXhcJkugIZDnjAfh3byi9hP 75zsmzOrPInpXbWgHexOkgE02lRWFRBbbBOD9PhljG4D/vpQWwp4Nt2hyG1ZZY0tMYAu W9cPJN4jQLLgLb/QJ2rd/8CrccjvUoFsnVByM= 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=WxW0wTXrQlL11cQloR5uFczaFJHJAFTucfu/a7Auct0=; b=fixCArwBFWIRtp+mtaWzAUAn7Dy+eX94MU37L17WL2BvLmKHHFuSxnuIMBqW7PbCQA mBJ/SEb0wfQTx+AoOoVovVvGMV7echSkUeRgXg5IWx1cHebIxtYMDh6foRznOUVA4bvi LsoSsqtikLK68vOIKZ+nHJS2Vj9H4HNzFthc7Ae5sp5GJU9Wi5iDzzkZ3qxPBPOhfjh2 SPHstl69dZHzAGq+7clbTnXx1tGYVSpeEuP+QvB5ur6n/D9J5LvVVfJ1tD0Ef8Maf8OO 1UAeJ0YY5KgUB6rp9RGMT6OqtgX78BpPvkdwy+43HNRdoXuLtaExebg3h4Ujovi64Dx7 aVuw== X-Gm-Message-State: AKGB3mL9hyNomTocJYeuKm6BlHRaCh2uJoVc02FVqJFBG17YaEJMXjDo +ReKYyv4aY/HcBtwAXuQzzXAOg== X-Google-Smtp-Source: ACJfBot401ThAe1ScuF1upkobKl1ZTM+QrLfhhPdbiMzA3YhQUtQEG7T2XSK7unUqLv529WRe9W4DA== X-Received: by 10.28.228.132 with SMTP id b126mr8402889wmh.18.1515418191532; Mon, 08 Jan 2018 05:29:51 -0800 (PST) Received: from mai.lan ([2001:41d0:fe90:b800:312a:53a5:1bef:6622]) by smtp.gmail.com with ESMTPSA id q196sm14354222wmb.22.2018.01.08.05.29.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 08 Jan 2018 05:29:50 -0800 (PST) From: Daniel Lezcano To: tglx@linutronix.de Subject: [PATCH 16/20] clocksource/drivers/stm32: Add the oneshot mode Date: Mon, 8 Jan 2018 14:28:55 +0100 Message-Id: <1515418139-23276-16-git-send-email-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org> References: <1bbaef2e-4080-3f54-7db3-a8989acfd691@free.fr> <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180108_052959_767305_671D4AFC X-CRM114-Status: GOOD ( 15.66 ) 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: "moderated list:ARM/STM32 ARCHITECTURE" , Alexandre Torgue , linux-kernel@vger.kernel.org, Maxime Coquelin , Benjamin Gaignard 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 From: Benjamin Gaignard The stm32 timer block is able to have a counter and a comparator. Instead of using the auto-reload register for periodic event, we switch to the oneshot mode by using the comparator register. The timer is able to generate an interrupt when the counter overflows but we don't want that as this counter will be use as a clocksource in the next patches. So it is disabled by the UDIS bit of the control register. Signed-off-by: Benjamin Gaignard Signed-off-by: Daniel Lezcano Tested-by: Benjamin Gaignard Acked-by: Benjamin Gaignard --- drivers/clocksource/timer-stm32.c | 56 ++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c index ac55896..baca42c 100644 --- a/drivers/clocksource/timer-stm32.c +++ b/drivers/clocksource/timer-stm32.c @@ -24,14 +24,18 @@ #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_UDIS BIT(1) #define TIM_CR1_OPM BIT(3) #define TIM_CR1_ARPE BIT(7) #define TIM_DIER_UIE BIT(0) +#define TIM_DIER_CC1IE BIT(1) #define TIM_SR_UIF BIT(0) @@ -40,33 +44,57 @@ #define TIM_PSC_MAX USHRT_MAX #define TIM_PSC_CLKRATE 10000 +static void stm32_clock_event_disable(struct timer_of *to) +{ + writel_relaxed(0, timer_of_base(to) + TIM_DIER); +} + +static void stm32_clock_event_enable(struct timer_of *to) +{ + writel_relaxed(TIM_CR1_UDIS | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1); +} + static int stm32_clock_event_shutdown(struct clock_event_device *clkevt) { struct timer_of *to = to_timer_of(clkevt); - writel_relaxed(0, timer_of_base(to) + TIM_CR1); + stm32_clock_event_disable(to); return 0; } -static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt) +static int stm32_clock_event_set_next_event(unsigned long evt, + struct clock_event_device *clkevt) { struct timer_of *to = to_timer_of(clkevt); + unsigned long now, next; + + next = readl_relaxed(timer_of_base(to) + TIM_CNT) + evt; + writel_relaxed(next, timer_of_base(to) + TIM_CCR1); + now = readl_relaxed(timer_of_base(to) + TIM_CNT); + + if ((next - now) > evt) + return -ETIME; - 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); + 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 *clkevt) +{ + struct timer_of *to = to_timer_of(clkevt); + + stm32_clock_event_enable(to); + + return stm32_clock_event_set_next_event(timer_of_period(to), clkevt); +} + +static int stm32_clock_event_set_oneshot(struct clock_event_device *clkevt) { struct timer_of *to = to_timer_of(clkevt); - 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); + stm32_clock_event_enable(to); return 0; } @@ -78,6 +106,11 @@ 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(clkevt)) + stm32_clock_event_set_periodic(clkevt); + else + stm32_clock_event_shutdown(clkevt); + clkevt->event_handler(clkevt); return IRQ_HANDLED; @@ -108,9 +141,10 @@ static void __init stm32_clockevent_init(struct timer_of *to) to->clkevt.name = to->np->full_name; to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC; + to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; 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; @@ -129,12 +163,10 @@ static void __init stm32_clockevent_init(struct timer_of *to) prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX; to->clkevt.rating = 100; } - writel_relaxed(0, timer_of_base(to) + TIM_ARR); writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC); writel_relaxed(TIM_EGR_UG, timer_of_base(to) + TIM_EGR); writel_relaxed(0, timer_of_base(to) + TIM_SR); - writel_relaxed(TIM_DIER_UIE, timer_of_base(to) + TIM_DIER); /* Adjust rate and period given the prescaler value */ to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);