From patchwork Tue Nov 29 12:15:16 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kochetkov X-Patchwork-Id: 9451881 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 DD3A860710 for ; Tue, 29 Nov 2016 12:17:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D532D28304 for ; Tue, 29 Nov 2016 12:17:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C993C28307; Tue, 29 Nov 2016 12:17:22 +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.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 6DC6028304 for ; Tue, 29 Nov 2016 12:17:21 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1cBhKJ-0005Im-Fu; Tue, 29 Nov 2016 12:15:59 +0000 Received: from mail-lf0-x241.google.com ([2a00:1450:4010:c07::241]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1cBhK2-0004v2-Eg for linux-arm-kernel@lists.infradead.org; Tue, 29 Nov 2016 12:15:43 +0000 Received: by mail-lf0-x241.google.com with SMTP id p100so12449446lfg.2 for ; Tue, 29 Nov 2016 04:15:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+yR1amQujJed4B7e+Vk7BP3mqyJsiBHiufQwzxuxieg=; b=HGP/BDBfXiWsznS9paW9+oTiiGirTwoT3uhDZxlZO4DmZi91jinRUksm2soHdhAiUV dX0XPU/tlK5UeBUcnvyy1rFKW7UCslZyVCywoX777Vw34GsQdZuChscYig8ITkc0rJCM qHAUHOD0KEjiOZSPiJRC4Xp8pSPzbWnIn91ypoSVdGXXfvGbfwC3meCQGcb664P1Fek2 pTNUrlWqP7GI12lo6rb0H2c01CkOhmGfU8D9LJb3+eZaTb/17GOK2l4mUx5QClJ+IFt9 s2iOdgkWr6YUJdjPDmoM3Dwo6D4xYWVZy9XDpYJrz5NTBigY5qI95tmSLmndPnn4hP32 gLuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+yR1amQujJed4B7e+Vk7BP3mqyJsiBHiufQwzxuxieg=; b=fuY9SIu0/gH7zQrk9BKmQOuIIA7V6lV4NkdhQISxNE3ny4swN1VPQfaGXjn2KjaB4k T/cvOEsXKn1bAdmsWzU91mLcLasanorLuEQC/GlJUrk8ddTVAWLEZl2bsmArJL5RyrrI gFS0YMwxWXMXIYBNPx/ghllSb5nUjsOXFf0i1NBcGwe27hqrTfzDx5tJBIHUvndVXssC ztyGQodFD/4JbCV6IrbGhHWw3PVs827CkJi7gHMG5RfMgzQqcZg4nTNgQFHBdSfeOlNw olBbutOrtQSWpuH/FK5vPMcSRG9E9VQJ+KVITWUrs2EWInqtJKqBbqkDQp7vGqe7zbO+ UTSA== X-Gm-Message-State: AKaTC03+dXPb18VRIDVdVf2Fss9k8Jhud9AeudozRSCYhAutKECgc/jY2026edPJpvIWuw== X-Received: by 10.46.8.25 with SMTP id 25mr13334663lji.21.1480421724949; Tue, 29 Nov 2016 04:15:24 -0800 (PST) Received: from ubuntu.lintech.local ([185.35.119.87]) by smtp.gmail.com with ESMTPSA id l141sm13609602lfl.0.2016.11.29.04.15.23 (version=TLS1_1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 29 Nov 2016 04:15:24 -0800 (PST) From: Alexander Kochetkov To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@stlinux.com Subject: [PATCH] clocksource/arm_global_timer: reconfigure clockevents after cpufreq change Date: Tue, 29 Nov 2016 15:15:16 +0300 Message-Id: <1480421716-30782-2-git-send-email-al.kochet@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1480421716-30782-1-git-send-email-al.kochet@gmail.com> References: <1480421716-30782-1-git-send-email-al.kochet@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20161129_041542_825431_99CABA26 X-CRM114-Status: GOOD ( 17.18 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Gleixner , Daniel Lezcano , Patrice Chotard , Alexander Kochetkov 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 After a cpufreq transition, update the clockevent's frequency by fetching the new clock rate from the clock framework and reprogram the next clock event. The clock supplying the arm-global-timer on the rk3188 is coming from the the cpu clock itself and thus changes its rate everytime cpufreq adjusts the cpu frequency. Found by code review, real impact not known. Assume what actual HZ value will be different from expected on platforms using arm-global-timer as clockevent. The patch is port of commit 4fd7f9b12810 ("ARM: 7212/1: smp_twd: reconfigure clockevents after cpufreq change") and commit 2b25d9f64b54 ("ARM: 7535/1: Reprogram smp_twd based on new common clk framework notifiers"). Signed-off-by: Alexander Kochetkov --- drivers/clocksource/arm_global_timer.c | 93 +++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index 8da0329..55addeb 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -49,6 +49,7 @@ * the units for all operations. */ static void __iomem *gt_base; +static struct clk *gt_clk; static unsigned long gt_clk_rate; static int gt_ppi; static struct clock_event_device __percpu *gt_evt; @@ -137,6 +138,97 @@ static int gt_clockevent_set_next_event(unsigned long evt, return 0; } +#ifdef CONFIG_COMMON_CLK + +/* + * Updates clockevent frequency when the cpu frequency changes. + * Called on the cpu that is changing frequency with interrupts disabled. + */ +static void gt_update_frequency(void *new_rate) +{ + gt_clk_rate = *((unsigned long *) new_rate); + + clockevents_update_freq(raw_cpu_ptr(gt_evt), gt_clk_rate); +} + +static int gt_rate_change(struct notifier_block *nb, + unsigned long flags, void *data) +{ + struct clk_notifier_data *cnd = data; + + /* + * The gt clock events must be reprogrammed to account for the new + * frequency. The timer is local to a cpu, so cross-call to the + * changing cpu. + */ + if (flags == POST_RATE_CHANGE) + on_each_cpu(gt_update_frequency, + (void *)&cnd->new_rate, 1); + + return NOTIFY_OK; +} + +static struct notifier_block gt_clk_nb = { + .notifier_call = gt_rate_change, +}; + +static int gt_clk_init(void) +{ + if (gt_evt && raw_cpu_ptr(gt_evt) && !IS_ERR(gt_clk)) + return clk_notifier_register(gt_clk, >_clk_nb); + + return 0; +} +core_initcall(gt_clk_init); + +#elif defined (CONFIG_CPU_FREQ) + +#include + +/* + * Updates clockevent frequency when the cpu frequency changes. + * Called on the cpu that is changing frequency with interrupts disabled. + */ +static void gt_update_frequency(void *data) +{ + gt_clk_rate = clk_get_rate(gt_clk); + + clockevents_update_freq(raw_cpu_ptr(gt_evt), gt_clk_rate); +} + +static int gt_cpufreq_transition(struct notifier_block *nb, + unsigned long state, void *data) +{ + struct cpufreq_freqs *freqs = data; + + /* + * The gt clock events must be reprogrammed to account for the new + * frequency. The timer is local to a cpu, so cross-call to the + * changing cpu. + */ + if (state == CPUFREQ_POSTCHANGE) + smp_call_function_single(freqs->cpu, gt_update_frequency, + NULL, 1); + + return NOTIFY_OK; +} + +static struct notifier_block gt_cpufreq_nb = { + .notifier_call = gt_cpufreq_transition, +}; + +static int gt_cpufreq_init(void) +{ + if (gt_evt && raw_cpu_ptr(gt_evt) && !IS_ERR(gt_clk)) + return cpufreq_register_notifier(>_cpufreq_nb, + CPUFREQ_TRANSITION_NOTIFIER); + + return 0; +} +core_initcall(gt_cpufreq_init); + +#endif + static irqreturn_t gt_clockevent_interrupt(int irq, void *dev_id) { struct clock_event_device *evt = dev_id; @@ -257,7 +349,6 @@ static int __init gt_clocksource_init(void) static int __init global_timer_of_register(struct device_node *np) { - struct clk *gt_clk; int err = 0; /*