From patchwork Tue Mar 28 12:05:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keguang Zhang X-Patchwork-Id: 13190955 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D5871C76195 for ; Tue, 28 Mar 2023 12:05:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232336AbjC1MFs (ORCPT ); Tue, 28 Mar 2023 08:05:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60952 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230280AbjC1MFr (ORCPT ); Tue, 28 Mar 2023 08:05:47 -0400 Received: from mail-pl1-x62a.google.com (mail-pl1-x62a.google.com [IPv6:2607:f8b0:4864:20::62a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9359793C3; Tue, 28 Mar 2023 05:05:22 -0700 (PDT) Received: by mail-pl1-x62a.google.com with SMTP id le6so11386805plb.12; Tue, 28 Mar 2023 05:05:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680005121; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=iCzXNIYQLlaRYU7ZogUgHF9j0l1HrLJQb1SPX081M7g=; b=gRr90qeL/gjfNQEgduUUbmJXYgfkRgGZ+TKTciuQTJRTN4qRxvEyOjEFztICyVdliD mH/NebAzrEgPcO80I5vDICNg8qNya4s9MW1zBMHWcYW0Yzww5cVgmBqhqpLgfKbziFOY 7vznpwkxW+fMC+VNNFVgIt05JhmFrIukJodmZ96UnLYuDmB6PVPmA+RG9mO0eQ20arX+ LSEb6CbSF5jA8Z6w1f8/MUYL6hkwdCHe9W6tVOUIYb2yui02gvg7aBSqbA1SamnAHv51 sGraEOEM5XNTMOwdkLktT+ljZ1ZA44ILUqAa+oW+VDBXZcQFUlq6NiBkbBz0q3Vogsdq NvcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680005121; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=iCzXNIYQLlaRYU7ZogUgHF9j0l1HrLJQb1SPX081M7g=; b=bOo3MyFRGStXaM5odSnhhJ47OmmXRdrfeEVqT1qzLBk9vMkVdtadYn+Q6vf4hWbCHs f/aphh3fZL1no/Y2HVjbzkJxZiHheFcs9pgX+H3iWS0m6l4dO7/C+ZbVoDTegKiqsn/D Qdns5NWrH3UQ5qHNW97MgI4plLRhdj1Q1vyz/SCncDYc0m47dKjGZ8hZOOjhZJPUvh3q uKXvtk7JrFlshb00wtdjg4phZMvfIwKa2NAdF8oKGr6glwO4hUg3LBWEMGDOvxHmHTUN PW/S4dVOp256sZSzE8ej+kqLTfGQA7xTAV+gF+IeHfxQY5G7JEbR7c6FsS2+XnvH8Ov7 FbEA== X-Gm-Message-State: AAQBX9dnnifN0WSjCWzLdwrcHCl7UP+2fajMLwWPEe/UtuSrMYpzdRPY uGEKkZ8wCHghJbw3MRlkk+cHml99mokLXQ== X-Google-Smtp-Source: AKy350aRXwHQRyB+t6HBqQ7anWxNo4R42W4+8V+izqoLlg4yBcC+ODpQL96UXAMpG8ovrSUwsk18lw== X-Received: by 2002:a17:903:124c:b0:19c:a9bc:ce57 with SMTP id u12-20020a170903124c00b0019ca9bcce57mr17280866plh.64.1680005121584; Tue, 28 Mar 2023 05:05:21 -0700 (PDT) Received: from kelvin-ThinkPad-L14-Gen-1.. (94.130.220.35.bc.googleusercontent.com. [35.220.130.94]) by smtp.gmail.com with ESMTPSA id ju10-20020a170903428a00b0019a83f2c99bsm21013956plb.28.2023.03.28.05.05.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Mar 2023 05:05:21 -0700 (PDT) From: Keguang Zhang To: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-mips@vger.kernel.org Cc: Daniel Lezcano , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Thomas Bogendoerfer , Stephen Boyd , Keguang Zhang Subject: [PATCH 1/3] MIPS: Loongson32: Remove deprecated PWM timer clocksource Date: Tue, 28 Mar 2023 20:05:04 +0800 Message-Id: <20230328120506.375864-2-keguang.zhang@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230328120506.375864-1-keguang.zhang@gmail.com> References: <20230328120506.375864-1-keguang.zhang@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mips@vger.kernel.org The Loongson1 PWM timer will be moved to clocksource framework. Then, the old driver is no longer needed. Remove the deprecated code and update the Kconfig accordingly. Signed-off-by: Keguang Zhang Acked-by: Thomas Bogendoerfer --- arch/mips/loongson32/Kconfig | 37 ----- arch/mips/loongson32/common/time.c | 210 ----------------------------- 2 files changed, 247 deletions(-) diff --git a/arch/mips/loongson32/Kconfig b/arch/mips/loongson32/Kconfig index 2ef9da0016df..a7c500959577 100644 --- a/arch/mips/loongson32/Kconfig +++ b/arch/mips/loongson32/Kconfig @@ -35,41 +35,4 @@ config LOONGSON1_LS1C select COMMON_CLK endchoice -menuconfig CEVT_CSRC_LS1X - bool "Use PWM Timer for clockevent/clocksource" - select MIPS_EXTERNAL_TIMER - depends on CPU_LOONGSON32 - help - This option changes the default clockevent/clocksource to PWM Timer, - and is required by Loongson1 CPUFreq support. - - If unsure, say N. - -choice - prompt "Select clockevent/clocksource" - depends on CEVT_CSRC_LS1X - default TIMER_USE_PWM0 - -config TIMER_USE_PWM0 - bool "Use PWM Timer 0" - help - Use PWM Timer 0 as the default clockevent/clocksourcer. - -config TIMER_USE_PWM1 - bool "Use PWM Timer 1" - help - Use PWM Timer 1 as the default clockevent/clocksourcer. - -config TIMER_USE_PWM2 - bool "Use PWM Timer 2" - help - Use PWM Timer 2 as the default clockevent/clocksourcer. - -config TIMER_USE_PWM3 - bool "Use PWM Timer 3" - help - Use PWM Timer 3 as the default clockevent/clocksourcer. - -endchoice - endif # MACH_LOONGSON32 diff --git a/arch/mips/loongson32/common/time.c b/arch/mips/loongson32/common/time.c index 965c04aa56fd..74ad2b17918d 100644 --- a/arch/mips/loongson32/common/time.c +++ b/arch/mips/loongson32/common/time.c @@ -5,208 +5,8 @@ #include #include -#include -#include #include -#include -#include - -#ifdef CONFIG_CEVT_CSRC_LS1X - -#if defined(CONFIG_TIMER_USE_PWM1) -#define LS1X_TIMER_BASE LS1X_PWM1_BASE -#define LS1X_TIMER_IRQ LS1X_PWM1_IRQ - -#elif defined(CONFIG_TIMER_USE_PWM2) -#define LS1X_TIMER_BASE LS1X_PWM2_BASE -#define LS1X_TIMER_IRQ LS1X_PWM2_IRQ - -#elif defined(CONFIG_TIMER_USE_PWM3) -#define LS1X_TIMER_BASE LS1X_PWM3_BASE -#define LS1X_TIMER_IRQ LS1X_PWM3_IRQ - -#else -#define LS1X_TIMER_BASE LS1X_PWM0_BASE -#define LS1X_TIMER_IRQ LS1X_PWM0_IRQ -#endif - -DEFINE_RAW_SPINLOCK(ls1x_timer_lock); - -static void __iomem *timer_reg_base; -static uint32_t ls1x_jiffies_per_tick; - -static inline void ls1x_pwmtimer_set_period(uint32_t period) -{ - __raw_writel(period, timer_reg_base + PWM_HRC); - __raw_writel(period, timer_reg_base + PWM_LRC); -} - -static inline void ls1x_pwmtimer_restart(void) -{ - __raw_writel(0x0, timer_reg_base + PWM_CNT); - __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL); -} - -void __init ls1x_pwmtimer_init(void) -{ - timer_reg_base = ioremap(LS1X_TIMER_BASE, SZ_16); - if (!timer_reg_base) - panic("Failed to remap timer registers"); - - ls1x_jiffies_per_tick = DIV_ROUND_CLOSEST(mips_hpt_frequency, HZ); - - ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick); - ls1x_pwmtimer_restart(); -} - -static u64 ls1x_clocksource_read(struct clocksource *cs) -{ - unsigned long flags; - int count; - u32 jifs; - static int old_count; - static u32 old_jifs; - - raw_spin_lock_irqsave(&ls1x_timer_lock, flags); - /* - * Although our caller may have the read side of xtime_lock, - * this is now a seqlock, and we are cheating in this routine - * by having side effects on state that we cannot undo if - * there is a collision on the seqlock and our caller has to - * retry. (Namely, old_jifs and old_count.) So we must treat - * jiffies as volatile despite the lock. We read jiffies - * before latching the timer count to guarantee that although - * the jiffies value might be older than the count (that is, - * the counter may underflow between the last point where - * jiffies was incremented and the point where we latch the - * count), it cannot be newer. - */ - jifs = jiffies; - /* read the count */ - count = __raw_readl(timer_reg_base + PWM_CNT); - - /* - * It's possible for count to appear to go the wrong way for this - * reason: - * - * The timer counter underflows, but we haven't handled the resulting - * interrupt and incremented jiffies yet. - * - * Previous attempts to handle these cases intelligently were buggy, so - * we just do the simple thing now. - */ - if (count < old_count && jifs == old_jifs) - count = old_count; - - old_count = count; - old_jifs = jifs; - - raw_spin_unlock_irqrestore(&ls1x_timer_lock, flags); - - return (u64) (jifs * ls1x_jiffies_per_tick) + count; -} - -static struct clocksource ls1x_clocksource = { - .name = "ls1x-pwmtimer", - .read = ls1x_clocksource_read, - .mask = CLOCKSOURCE_MASK(24), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static irqreturn_t ls1x_clockevent_isr(int irq, void *devid) -{ - struct clock_event_device *cd = devid; - - ls1x_pwmtimer_restart(); - cd->event_handler(cd); - - return IRQ_HANDLED; -} - -static int ls1x_clockevent_set_state_periodic(struct clock_event_device *cd) -{ - raw_spin_lock(&ls1x_timer_lock); - ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick); - ls1x_pwmtimer_restart(); - __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL); - raw_spin_unlock(&ls1x_timer_lock); - - return 0; -} - -static int ls1x_clockevent_tick_resume(struct clock_event_device *cd) -{ - raw_spin_lock(&ls1x_timer_lock); - __raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL); - raw_spin_unlock(&ls1x_timer_lock); - - return 0; -} - -static int ls1x_clockevent_set_state_shutdown(struct clock_event_device *cd) -{ - raw_spin_lock(&ls1x_timer_lock); - __raw_writel(__raw_readl(timer_reg_base + PWM_CTRL) & ~CNT_EN, - timer_reg_base + PWM_CTRL); - raw_spin_unlock(&ls1x_timer_lock); - - return 0; -} - -static int ls1x_clockevent_set_next(unsigned long evt, - struct clock_event_device *cd) -{ - raw_spin_lock(&ls1x_timer_lock); - ls1x_pwmtimer_set_period(evt); - ls1x_pwmtimer_restart(); - raw_spin_unlock(&ls1x_timer_lock); - - return 0; -} - -static struct clock_event_device ls1x_clockevent = { - .name = "ls1x-pwmtimer", - .features = CLOCK_EVT_FEAT_PERIODIC, - .rating = 300, - .irq = LS1X_TIMER_IRQ, - .set_next_event = ls1x_clockevent_set_next, - .set_state_shutdown = ls1x_clockevent_set_state_shutdown, - .set_state_periodic = ls1x_clockevent_set_state_periodic, - .set_state_oneshot = ls1x_clockevent_set_state_shutdown, - .tick_resume = ls1x_clockevent_tick_resume, -}; - -static void __init ls1x_time_init(void) -{ - struct clock_event_device *cd = &ls1x_clockevent; - int ret; - - if (!mips_hpt_frequency) - panic("Invalid timer clock rate"); - - ls1x_pwmtimer_init(); - - clockevent_set_clock(cd, mips_hpt_frequency); - cd->max_delta_ns = clockevent_delta2ns(0xffffff, cd); - cd->max_delta_ticks = 0xffffff; - cd->min_delta_ns = clockevent_delta2ns(0x000300, cd); - cd->min_delta_ticks = 0x000300; - cd->cpumask = cpumask_of(smp_processor_id()); - clockevents_register_device(cd); - - ls1x_clocksource.rating = 200 + mips_hpt_frequency / 10000000; - ret = clocksource_register_hz(&ls1x_clocksource, mips_hpt_frequency); - if (ret) - panic(KERN_ERR "Failed to register clocksource: %d\n", ret); - - if (request_irq(LS1X_TIMER_IRQ, ls1x_clockevent_isr, - IRQF_PERCPU | IRQF_TIMER, "ls1x-pwmtimer", - &ls1x_clockevent)) - pr_err("Failed to register ls1x-pwmtimer interrupt\n"); -} -#endif /* CONFIG_CEVT_CSRC_LS1X */ - void __init plat_time_init(void) { struct clk *clk = NULL; @@ -214,20 +14,10 @@ void __init plat_time_init(void) /* initialize LS1X clocks */ of_clk_init(NULL); -#ifdef CONFIG_CEVT_CSRC_LS1X - /* setup LS1X PWM timer */ - clk = clk_get(NULL, "ls1x-pwmtimer"); - if (IS_ERR(clk)) - panic("unable to get timer clock, err=%ld", PTR_ERR(clk)); - - mips_hpt_frequency = clk_get_rate(clk); - ls1x_time_init(); -#else /* setup mips r4k timer */ clk = clk_get(NULL, "cpu_clk"); if (IS_ERR(clk)) panic("unable to get cpu clock, err=%ld", PTR_ERR(clk)); mips_hpt_frequency = clk_get_rate(clk) / 2; -#endif /* CONFIG_CEVT_CSRC_LS1X */ } From patchwork Tue Mar 28 12:05:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keguang Zhang X-Patchwork-Id: 13190956 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8677BC76196 for ; Tue, 28 Mar 2023 12:05:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232795AbjC1MFu (ORCPT ); Tue, 28 Mar 2023 08:05:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32780 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231987AbjC1MFt (ORCPT ); Tue, 28 Mar 2023 08:05:49 -0400 Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 77B9693C8; Tue, 28 Mar 2023 05:05:27 -0700 (PDT) Received: by mail-pl1-x62d.google.com with SMTP id w4so11389716plg.9; Tue, 28 Mar 2023 05:05:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680005126; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=InVcb9dEGuOqkJ5tQQiGYBoCBqQROtEgUWP5Mr1cBac=; b=ijDg7+6b3/4eD/hrDqw/dshDiZdKfi/l9LVbQa/VgmDkor0MZIR6CMxyufZ4dSlrKz MLqFIIuDE41e/wIv2/lL/IvuXqC8Yh4SN0idxNKRi0Mbbpq8NEEIXLfuLrLwMTJAG3Gp +Nnb7M4fly0m+xxTOE0mAuFGPLLVK8rYAvZOFfm4lAuMNs0FnX28UD70XxgkcuGZJYYQ IoPzuMigfSh2v+5mTUZumXPlIpnmj+zAHTgiHYORBvbcPA/jYfRv/0RmvtLmBZswLYPe kpzFlQ1/MAFeRvvlTHxutb7N8SsLV2o6cReMXNSL6pkr/9LAqf9ZCwn2tfsNZmQDQ/iR 2H5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680005126; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=InVcb9dEGuOqkJ5tQQiGYBoCBqQROtEgUWP5Mr1cBac=; b=q2Htea2TrE0/KhLMSz2EkSRMBHbIxIl0i7CzenLnxW69VNGlpaYARjZiV+40NvFuEe 6jXg80MFQqPqlHTvKeBknGCnMljAfXfTf9OAFySg77Y6yakdjrhmHTKv0nU8kxIa7TvG CeegvGR7qoH1L2JOz4MM0836bbND0v9XBEFUeH6OveWTYgeSv1fdffhHtzSMX0Vp4K3c SYvQwGOFSTB5JFooLMdhBGluIYpHTei2h9aRulYR9yOdjaWhidK/O5Ak1Q99ov8SpWvu DldCUDK835TGURx7oA978MQHcNGrhy8LH+mwqktUuqn4XIMeef4Jc3aT+zT0YNftlCle hKrg== X-Gm-Message-State: AAQBX9feApyu8OgRhDeTUR9S418FN3xExoHjbVNipxrn13Agou0yuJ2F LnJ5zMn4o08qNhU+Mutu2jkFV02T5jlITQ== X-Google-Smtp-Source: AKy350atFytskDWjRzoiPrurLXOuGMqctYkYrfjQAp4QSh8NYsw9JADGValSwDko5qcJblVEh7ph9A== X-Received: by 2002:a17:902:e851:b0:1a0:549d:399e with SMTP id t17-20020a170902e85100b001a0549d399emr16605781plg.21.1680005126587; Tue, 28 Mar 2023 05:05:26 -0700 (PDT) Received: from kelvin-ThinkPad-L14-Gen-1.. (94.130.220.35.bc.googleusercontent.com. [35.220.130.94]) by smtp.gmail.com with ESMTPSA id ju10-20020a170903428a00b0019a83f2c99bsm21013956plb.28.2023.03.28.05.05.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Mar 2023 05:05:26 -0700 (PDT) From: Keguang Zhang To: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-mips@vger.kernel.org Cc: Daniel Lezcano , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Thomas Bogendoerfer , Stephen Boyd , Keguang Zhang Subject: [PATCH 2/3] dt-bindings: timer: Add Loongson-1 clocksource Date: Tue, 28 Mar 2023 20:05:05 +0800 Message-Id: <20230328120506.375864-3-keguang.zhang@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230328120506.375864-1-keguang.zhang@gmail.com> References: <20230328120506.375864-1-keguang.zhang@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mips@vger.kernel.org Add devicetree binding document for Loongson-1 clocksource. Signed-off-by: Keguang Zhang --- .../timer/loongson,ls1x-pwmtimer.yaml | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/loongson,ls1x-pwmtimer.yaml diff --git a/Documentation/devicetree/bindings/timer/loongson,ls1x-pwmtimer.yaml b/Documentation/devicetree/bindings/timer/loongson,ls1x-pwmtimer.yaml new file mode 100644 index 000000000000..c4771aab8d75 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/loongson,ls1x-pwmtimer.yaml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/timer/loongson,ls1x-pwmtimer.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Loongson-1 PWM timer + +maintainers: + - Keguang Zhang + +description: + Loongson-1 PWM timer can be used for system clock source + and clock event timers. + +properties: + compatible: + const: loongson,ls1x-pwmtimer + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - interrupts + +additionalProperties: false + +examples: + - | + #include + #include + clocksource: timer@1fe5c030 { + compatible = "loongson,ls1x-pwmtimer"; + reg = <0x1fe5c030 0x10>; + + clocks = <&clkc LS1X_CLKID_APB>; + interrupt-parent = <&intc0>; + interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; + }; From patchwork Tue Mar 28 12:05:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keguang Zhang X-Patchwork-Id: 13190957 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 59C84C76195 for ; Tue, 28 Mar 2023 12:06:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232993AbjC1MGL (ORCPT ); Tue, 28 Mar 2023 08:06:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33632 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232888AbjC1MGH (ORCPT ); Tue, 28 Mar 2023 08:06:07 -0400 Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5E92193F9; Tue, 28 Mar 2023 05:05:32 -0700 (PDT) Received: by mail-pj1-x1032.google.com with SMTP id lr16-20020a17090b4b9000b0023f187954acso12247780pjb.2; Tue, 28 Mar 2023 05:05:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680005131; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BSwVJnmt8b45SnByJtoBpZI8yP1oPog/3K70qzHc98Q=; b=Nisx7RU8wYdia8KcMec128ZYwYnL0AugSs0UOFvO7tfLXOw2UdyYH/5g75B4DzpuBY 2xYG8zakRkgJHJLwglWmPX58cWvjncUL8iN2VZYeK0xjysnGvqVZC0Fc1zsBVQnJMX65 tZZxdrk3MMMqo3HYyLRJVOsdljIuxI+NpbxT3TH27Q1QdQ0HLeYrMp1G5k+G56TibFmu AHAuezMliynxiVM9bqS7UnyIC+Ng4Omf7c6zi1Jy/egxtz+oQ9MMmcvktzRTHZEeFUdE GQ9hqT5EwhNvTfbk3YRVsjCzw/Jmr1gKKbjin7yZh2TXWblu9hSbygh5d0/F4dqmKv91 bEfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680005131; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BSwVJnmt8b45SnByJtoBpZI8yP1oPog/3K70qzHc98Q=; b=rQ+2n70lCCp8MQvyCLRaxOaD1Gn7fKvUNyl3D2xsRfY3r3dfdFazO/18mAOaBE4wpn 4o2HLYA0d1ZwV6usz0Tpgd9E0AtXFatw9abXg9uyM9Uprff+u5DeFepiC0DkyJzWLgyy oaoUrbpujpkwpgo7bNqO4l8bo0yX5zeyTJvAWhw0e7RrRFEggjeDoJir36/LljIaZ4PM bfUpF2WoN/WnFEih61CtreRx/5IWETrpj/tpUvM5j2o5ISiw0ec2Se+fH178fzoPZRf/ 0GcV1J6Io+hz1YEY6RYPKRnmutO6WVZH9Ro/9Iuu9TKjsEAJnfLaD+tF+M8DNs+AkT4+ zqpg== X-Gm-Message-State: AAQBX9frrxs/8FiNxYyf91ZEP474rTIVMndblBs7jDv4IGbPW2KwPJCi pxTKpYU4dZuq1angthwC+ynqhtM3a80BRw== X-Google-Smtp-Source: AKy350b9X5xUdtBgeQCRHIz6vU74B8Eqzv49/BTMB3xKF67DVuKwKMts4rFb0Yku2/Vix+M176iEIQ== X-Received: by 2002:a17:902:e0d5:b0:19d:abd:bb7e with SMTP id e21-20020a170902e0d500b0019d0abdbb7emr11272552pla.34.1680005131312; Tue, 28 Mar 2023 05:05:31 -0700 (PDT) Received: from kelvin-ThinkPad-L14-Gen-1.. (94.130.220.35.bc.googleusercontent.com. [35.220.130.94]) by smtp.gmail.com with ESMTPSA id ju10-20020a170903428a00b0019a83f2c99bsm21013956plb.28.2023.03.28.05.05.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Mar 2023 05:05:31 -0700 (PDT) From: Keguang Zhang To: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-mips@vger.kernel.org Cc: Daniel Lezcano , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Thomas Bogendoerfer , Stephen Boyd , Keguang Zhang Subject: [PATCH 3/3] clocksource: loongson1: Move PWM timer to clocksource framework Date: Tue, 28 Mar 2023 20:05:06 +0800 Message-Id: <20230328120506.375864-4-keguang.zhang@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230328120506.375864-1-keguang.zhang@gmail.com> References: <20230328120506.375864-1-keguang.zhang@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mips@vger.kernel.org This patch moves most part of arch/mips/loongson32/common/time.c into drivers/clocksource. Adapt the driver to clocksource framework and updates the Kconfig/Makefile options. Signed-off-by: Keguang Zhang --- drivers/clocksource/Kconfig | 9 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-loongson1-pwm.c | 236 ++++++++++++++++++++++ 3 files changed, 246 insertions(+) create mode 100644 drivers/clocksource/timer-loongson1-pwm.c diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 5fc8f0e7fb38..6e37b26d532d 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -603,6 +603,15 @@ config TIMER_IMX_SYS_CTR Enable this option to use i.MX system counter timer as a clockevent. +config CLKSRC_LOONGSON1_PWM + bool "Clocksource using Loongson1 PWM" + depends on MACH_LOONGSON32 || COMPILE_TEST + select MIPS_EXTERNAL_TIMER + select TIMER_OF + help + Enable this option to use Loongson1 PWM timer as clocksource + instead of the performance counter. + config CLKSRC_ST_LPC bool "Low power clocksource found in the LPC" if COMPILE_TEST select TIMER_OF if OF diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 64ab547de97b..f969a9eedfca 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -88,3 +88,4 @@ obj-$(CONFIG_MICROCHIP_PIT64B) += timer-microchip-pit64b.o obj-$(CONFIG_MSC313E_TIMER) += timer-msc313e.o obj-$(CONFIG_GOLDFISH_TIMER) += timer-goldfish.o obj-$(CONFIG_GXP_TIMER) += timer-gxp.o +obj-$(CONFIG_CLKSRC_LOONGSON1_PWM) += timer-loongson1-pwm.o diff --git a/drivers/clocksource/timer-loongson1-pwm.c b/drivers/clocksource/timer-loongson1-pwm.c new file mode 100644 index 000000000000..fe94c08afce2 --- /dev/null +++ b/drivers/clocksource/timer-loongson1-pwm.c @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Clocksource driver for Loongson-1 SoC + * + * Copyright (c) 2023 Keguang Zhang + */ + +#include +#include +#include +#include "timer-of.h" + +/* Loongson-1 PWM Timer Register Definitions */ +#define PWM_CNTR 0x0 +#define PWM_HRC 0x4 +#define PWM_LRC 0x8 +#define PWM_CTRL 0xc + +/* PWM Control Register Bits */ +#define INT_LRC_EN BIT(11) +#define INT_HRC_EN BIT(10) +#define CNTR_RST BIT(7) +#define INT_SR BIT(6) +#define INT_EN BIT(5) +#define PWM_SINGLE BIT(4) +#define PWM_OE BIT(3) +#define CNT_EN BIT(0) + +#define CNTR_WIDTH 24 + +DEFINE_RAW_SPINLOCK(ls1x_timer_lock); + +struct ls1x_clocksource { + void __iomem *reg_base; + unsigned long ticks_per_jiffy; + struct clocksource clksrc; +}; + +static inline struct ls1x_clocksource *to_ls1x_clksrc(struct clocksource *c) +{ + return container_of(c, struct ls1x_clocksource, clksrc); +} + +static inline void ls1x_pwmtimer_set_period(unsigned int period, + struct timer_of *to) +{ + writel(period, timer_of_base(to) + PWM_LRC); + writel(period, timer_of_base(to) + PWM_HRC); +} + +static inline void ls1x_pwmtimer_clear(struct timer_of *to) +{ + writel(0, timer_of_base(to) + PWM_CNTR); +} + +static inline void ls1x_pwmtimer_start(struct timer_of *to) +{ + writel((INT_EN | PWM_OE | CNT_EN), timer_of_base(to) + PWM_CTRL); +} + +static inline void ls1x_pwmtimer_stop(struct timer_of *to) +{ + writel(0, timer_of_base(to) + PWM_CTRL); +} + +static inline void ls1x_pwmtimer_irq_ack(struct timer_of *to) +{ + int val; + + val = readl(timer_of_base(to) + PWM_CTRL); + val |= INT_SR; + writel(val, timer_of_base(to) + PWM_CTRL); +} + +static irqreturn_t ls1x_clockevent_isr(int irq, void *dev_id) +{ + struct clock_event_device *clkevt = dev_id; + struct timer_of *to = to_timer_of(clkevt); + + ls1x_pwmtimer_irq_ack(to); + ls1x_pwmtimer_clear(to); + ls1x_pwmtimer_start(to); + + clkevt->event_handler(clkevt); + + return IRQ_HANDLED; +} + +static int ls1x_clockevent_set_state_periodic(struct clock_event_device *clkevt) +{ + struct timer_of *to = to_timer_of(clkevt); + + raw_spin_lock(&ls1x_timer_lock); + ls1x_pwmtimer_set_period(timer_of_period(to), to); + ls1x_pwmtimer_clear(to); + ls1x_pwmtimer_start(to); + raw_spin_unlock(&ls1x_timer_lock); + + return 0; +} + +static int ls1x_clockevent_tick_resume(struct clock_event_device *clkevt) +{ + raw_spin_lock(&ls1x_timer_lock); + ls1x_pwmtimer_start(to_timer_of(clkevt)); + raw_spin_unlock(&ls1x_timer_lock); + + return 0; +} + +static int ls1x_clockevent_set_state_shutdown(struct clock_event_device *clkevt) +{ + raw_spin_lock(&ls1x_timer_lock); + ls1x_pwmtimer_stop(to_timer_of(clkevt)); + raw_spin_unlock(&ls1x_timer_lock); + + return 0; +} + +static int ls1x_clockevent_set_next(unsigned long evt, + struct clock_event_device *clkevt) +{ + struct timer_of *to = to_timer_of(clkevt); + + raw_spin_lock(&ls1x_timer_lock); + ls1x_pwmtimer_set_period(evt, to); + ls1x_pwmtimer_clear(to); + ls1x_pwmtimer_start(to); + raw_spin_unlock(&ls1x_timer_lock); + + return 0; +} + +static struct timer_of ls1x_to = { + .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK, + .clkevt = { + .name = "ls1x-pwmtimer", + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .rating = 300, + .set_next_event = ls1x_clockevent_set_next, + .set_state_periodic = ls1x_clockevent_set_state_periodic, + .set_state_oneshot = ls1x_clockevent_set_state_shutdown, + .set_state_shutdown = ls1x_clockevent_set_state_shutdown, + .tick_resume = ls1x_clockevent_tick_resume, + }, + .of_irq = { + .handler = ls1x_clockevent_isr, + .flags = IRQF_TIMER, + }, +}; + +/* + * Since the PWM timer overflows every two ticks, its not very useful + * to just read by itself. So use jiffies to emulate a free + * running counter: + */ +static u64 ls1x_clocksource_read(struct clocksource *cs) +{ + struct ls1x_clocksource *ls1x_cs = to_ls1x_clksrc(cs); + unsigned long flags; + int count; + u32 jifs; + static int old_count; + static u32 old_jifs; + + raw_spin_lock_irqsave(&ls1x_timer_lock, flags); + /* + * Although our caller may have the read side of xtime_lock, + * this is now a seqlock, and we are cheating in this routine + * by having side effects on state that we cannot undo if + * there is a collision on the seqlock and our caller has to + * retry. (Namely, old_jifs and old_count.) So we must treat + * jiffies as volatile despite the lock. We read jiffies + * before latching the timer count to guarantee that although + * the jiffies value might be older than the count (that is, + * the counter may underflow between the last point where + * jiffies was incremented and the point where we latch the + * count), it cannot be newer. + */ + jifs = jiffies; + /* read the count */ + count = readl(ls1x_cs->reg_base + PWM_CNTR); + + /* + * It's possible for count to appear to go the wrong way for this + * reason: + * + * The timer counter underflows, but we haven't handled the resulting + * interrupt and incremented jiffies yet. + * + * Previous attempts to handle these cases intelligently were buggy, so + * we just do the simple thing now. + */ + if (count < old_count && jifs == old_jifs) + count = old_count; + + old_count = count; + old_jifs = jifs; + + raw_spin_unlock_irqrestore(&ls1x_timer_lock, flags); + + return (u64)(jifs * ls1x_cs->ticks_per_jiffy) + count; +} + +static struct ls1x_clocksource ls1x_clocksource = { + .clksrc = { + .name = "ls1x-pwmtimer", + .rating = 300, + .read = ls1x_clocksource_read, + .mask = CLOCKSOURCE_MASK(CNTR_WIDTH), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + }, +}; + +static int __init ls1x_pwm_clocksource_init(struct device_node *np) +{ + struct timer_of *to = &ls1x_to; + int ret; + + ret = timer_of_init(np, to); + if (ret) + return ret; + + clockevents_config_and_register(&to->clkevt, timer_of_rate(to), + 0x1, GENMASK(CNTR_WIDTH - 1, 0)); + + ls1x_clocksource.reg_base = timer_of_base(to); + ls1x_clocksource.ticks_per_jiffy = timer_of_period(to); + + return clocksource_register_hz(&ls1x_clocksource.clksrc, + timer_of_rate(to)); +} + +TIMER_OF_DECLARE(ls1x_pwm_clocksource, "loongson,ls1x-pwmtimer", + ls1x_pwm_clocksource_init);