From patchwork Fri May 12 10:37:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keguang Zhang X-Patchwork-Id: 13239105 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 099AAC77B7C for ; Fri, 12 May 2023 10:38:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240733AbjELKiL (ORCPT ); Fri, 12 May 2023 06:38:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38190 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240744AbjELKiI (ORCPT ); Fri, 12 May 2023 06:38:08 -0400 Received: from mail-pf1-x42f.google.com (mail-pf1-x42f.google.com [IPv6:2607:f8b0:4864:20::42f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3B9E3106CC; Fri, 12 May 2023 03:37:35 -0700 (PDT) Received: by mail-pf1-x42f.google.com with SMTP id d2e1a72fcca58-6439d505274so5916068b3a.0; Fri, 12 May 2023 03:37:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683887854; x=1686479854; 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=KyTRdFhMQkZMi74FtFWI8tp3ORyz1h0EXHOiGUuSXR8=; b=LntJWuI6gOkYZIMC4oWG/GlvEqMv4fCta03dHdyFQDOmlQWTto6YFWGYEO9kQGzwZd 1A347tW7qF8Mt0NjWcdH+wimWKJhDtf3lJ0yWC/NgJClRxG7eDe44I2Rcas8oA3VJAg9 Pz36Sx+vE/yo5MAcjr4aLIEHI3v1SHaWYsnLk2P9QymwVpCYjqRiMty4TtM1KHvkQG0T aJwq0N3tA/Pq3ewLyW7bCy95uzRbF1gF+tXmlYwmRlSK7DMvOYCeeUU4c08Xr9X/5ZxU XSa1UAhZQ7l0hp1STO4kuvNms06dd/8S29WLKlcVeJTn2S0obFL9FdVl5LXyXjN3TepW BQuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683887854; x=1686479854; 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=KyTRdFhMQkZMi74FtFWI8tp3ORyz1h0EXHOiGUuSXR8=; b=Fo9ePP7z5mCQrRFssoEvmI0KEFtzmN+FSkUXG4NiBN0rGhTxteCmpuxNnLC2F/GA6k MvG1bA3LbdyIISynrRIO/FaoT8XkT12vSTWhHw+yui15xd1oC60l2ZsBB2J7vNC4U12N l/bNkeXjLls0FSToOa3E1cf+8wtBPKN4HnLaaPXILCOdDhpyvtZ5T3a4NLeI24hOmUuR goEdinBRqemKHsD9LwWE+dg0kSkqB651ZcufHUaq8zRCv7A75wyT3XjqXUKorAvVBAiW Feon0Usu5e2bLgPtHzjiJ9+gNHpov8MQ6QUkQSCemWLAoNlvfBVB9RZVV6iOwVbOzZdn spiQ== X-Gm-Message-State: AC+VfDwdpyKjAH+jGvGFQDsKMCRnN2DY4Q4sy04TYKQ1XhyVAVvcmEhy +JzwUt4pTGw8CjuWJ+1hnPSa5VGeC61l5S3Y X-Google-Smtp-Source: ACHHUZ5HflYACmdndtfWmVOXmEAaReZ5wh5jtbPgwFQAoRM0bMJPGAA5P3wRdtbRXD2TOFFdBdJTeQ== X-Received: by 2002:a05:6a20:9193:b0:ec:7c4f:ed7a with SMTP id v19-20020a056a20919300b000ec7c4fed7amr31061083pzd.34.1683887854063; Fri, 12 May 2023 03:37:34 -0700 (PDT) Received: from kelvin-ThinkPad-L14-Gen-1.lan ([103.184.129.7]) by smtp.gmail.com with ESMTPSA id k5-20020aa792c5000000b0063b89300347sm7009485pfa.142.2023.05.12.03.37.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 12 May 2023 03:37:33 -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 v4 1/3] MIPS: Loongson32: Remove deprecated PWM timer clocksource Date: Fri, 12 May 2023 18:37:22 +0800 Message-Id: <20230512103724.587760-2-keguang.zhang@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230512103724.587760-1-keguang.zhang@gmail.com> References: <20230512103724.587760-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. Signed-off-by: Keguang Zhang --- V3 -> V4: None V2 -> V3: Remove the reference to regs-pwm.h V1 -> V2: Delete the obsolete header file regs-pwm.h --- .../include/asm/mach-loongson32/loongson1.h | 1 - .../include/asm/mach-loongson32/regs-pwm.h | 25 --- arch/mips/loongson32/Kconfig | 37 --- arch/mips/loongson32/common/time.c | 210 ------------------ 4 files changed, 273 deletions(-) delete mode 100644 arch/mips/include/asm/mach-loongson32/regs-pwm.h diff --git a/arch/mips/include/asm/mach-loongson32/loongson1.h b/arch/mips/include/asm/mach-loongson32/loongson1.h index eb3ddbec1752..d8f9dec0ecc3 100644 --- a/arch/mips/include/asm/mach-loongson32/loongson1.h +++ b/arch/mips/include/asm/mach-loongson32/loongson1.h @@ -47,7 +47,6 @@ #include #include -#include #include #include diff --git a/arch/mips/include/asm/mach-loongson32/regs-pwm.h b/arch/mips/include/asm/mach-loongson32/regs-pwm.h deleted file mode 100644 index ec870c82d492..000000000000 --- a/arch/mips/include/asm/mach-loongson32/regs-pwm.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (c) 2014 Zhang, Keguang - * - * Loongson 1 PWM Register Definitions. - */ - -#ifndef __ASM_MACH_LOONGSON32_REGS_PWM_H -#define __ASM_MACH_LOONGSON32_REGS_PWM_H - -/* Loongson 1 PWM Timer Register Definitions */ -#define PWM_CNT 0x0 -#define PWM_HRC 0x4 -#define PWM_LRC 0x8 -#define PWM_CTRL 0xc - -/* PWM Control Register Bits */ -#define CNT_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) - -#endif /* __ASM_MACH_LOONGSON32_REGS_PWM_H */ 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 Fri May 12 10:37:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keguang Zhang X-Patchwork-Id: 13239104 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 28F91C7EE25 for ; Fri, 12 May 2023 10:38:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240734AbjELKiM (ORCPT ); Fri, 12 May 2023 06:38:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38188 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240707AbjELKiJ (ORCPT ); Fri, 12 May 2023 06:38:09 -0400 Received: from mail-pf1-x42d.google.com (mail-pf1-x42d.google.com [IPv6:2607:f8b0:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5618D59D1; Fri, 12 May 2023 03:37:38 -0700 (PDT) Received: by mail-pf1-x42d.google.com with SMTP id d2e1a72fcca58-6434e263962so7280552b3a.2; Fri, 12 May 2023 03:37:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683887857; x=1686479857; 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=O4pkWtf5ZbvB3Mwr1DSQ73VhT77HryuyM9DctWSrkJQ=; b=H7uyjFa2PQA21s7dZHna6CDOrkAJ1pbPcQPEJE6y4lY7fXow3TYcfSJo2hlc2Gv07R m11qvMNRrigLnTGxhLv68NITruFcPp25OZJLWr3tyCJStQJwMA+MXlac0WGgJSBsEdEi 7f/8HSLYBwLGRp74MK1eX8LfdXRjeAcBpFR8SN2z2VMJ30ssgq4fdslhBGRyH7uDo56c DAFv6URrKny/4ze/s9GJQXszLrb5rg0K9d3icMCPziNl9jKvbgjwIypH50HVoNmnGXc9 pt8ncfVGPbeQnmkJf5UXXAooO4pnzVnG1Ry6H8+6vDdAOuEhsb7PPH8/x0Uq20KrxAUq wXJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683887857; x=1686479857; 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=O4pkWtf5ZbvB3Mwr1DSQ73VhT77HryuyM9DctWSrkJQ=; b=fSopqB13Iti7QOLC3/f/tZiGLUx9d6T1UWDKBGKDIj2jzNpiubvR4pg/272becGLCk P6CdzIECLQTRPrK3bdy+z3RzLQ4yG79F/eBarp48tByyr9Mn70cJ67crC3xH2DIJWIyC uwC/FFzQWCwQilS7X1lmAYjuZoZsqsb6brLzXr/yOsx3gxyJ3DNQ38iqBHiqN5b2SCNY UJjGk7mI3Z1gaIMtCnljL+SoFwkfdizydrRFlkrITjpA/PNmc76sVyR3B78Glx8OQctC JIEtql1Dkf8KoGB7UCI6CUDYqLcKKbdatdBLmkFCgo3ZrtOHqii7x1mq5w2CchhE5QHZ jp7g== X-Gm-Message-State: AC+VfDwzB06xUq4aLHcQEIKJmKjIcZcMLXVS0yGktbK1H1ySrTmICbIL hhF0RRwKlClbcU04hHC/DVp9SbQtotIkY7dk X-Google-Smtp-Source: ACHHUZ6UYkantohKHOwH1sweJxcQcbFw0OgVlZhvmpXs4SaMqrMlnA544OMSqnS1dc2LJlhdQMfSrQ== X-Received: by 2002:a05:6a00:2448:b0:63d:3789:733f with SMTP id d8-20020a056a00244800b0063d3789733fmr30478169pfj.15.1683887857081; Fri, 12 May 2023 03:37:37 -0700 (PDT) Received: from kelvin-ThinkPad-L14-Gen-1.lan ([103.184.129.7]) by smtp.gmail.com with ESMTPSA id k5-20020aa792c5000000b0063b89300347sm7009485pfa.142.2023.05.12.03.37.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 12 May 2023 03:37:36 -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 v4 2/3] dt-bindings: timer: Add Loongson-1 clocksource Date: Fri, 12 May 2023 18:37:23 +0800 Message-Id: <20230512103724.587760-3-keguang.zhang@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230512103724.587760-1-keguang.zhang@gmail.com> References: <20230512103724.587760-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 Reviewed-by: Krzysztof Kozlowski --- V3 -> V4: Replaced the wildcard compatible string with specific one V2 -> V3: None V1 -> V2: None --- .../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..ad61ae55850b --- /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,ls1b-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,ls1b-pwmtimer"; + reg = <0x1fe5c030 0x10>; + + clocks = <&clkc LS1X_CLKID_APB>; + interrupt-parent = <&intc0>; + interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; + }; From patchwork Fri May 12 10:37:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keguang Zhang X-Patchwork-Id: 13239106 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 57382C77B75 for ; Fri, 12 May 2023 10:38:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240773AbjELKiQ (ORCPT ); Fri, 12 May 2023 06:38:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38332 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240555AbjELKiO (ORCPT ); Fri, 12 May 2023 06:38:14 -0400 Received: from mail-pf1-x42d.google.com (mail-pf1-x42d.google.com [IPv6:2607:f8b0:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6F1A611D80; Fri, 12 May 2023 03:37:41 -0700 (PDT) Received: by mail-pf1-x42d.google.com with SMTP id d2e1a72fcca58-643557840e4so10478478b3a.2; Fri, 12 May 2023 03:37:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683887860; x=1686479860; 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=JvtB4ZaRRF7BmNq4bmx+beZGtGWCkhMFyaEsvLCR/zc=; b=W6TKdECpAr8ftr1aWRqKe6c2mfwhQ+fFXJm319nGgrOJfuyCLgPcdXr+qTvO6X+fOn x0D847hNDOKPeZFPyayVeGO8qiW9kgco9OEwlKc7gDnt8smN4pRmExIAEkQL1d9cEhSL 0B2fWNDu3s4adZDJ2g5w9IinE+Rpy41x8AN/t5VWQxCAgdfpJT8V7wA9x8VvDmIH3ff8 4fZ21+Zm+R8+HG3dzLTedSSkrZMBHS8EO2EIXenNqpFoqCB69yUiMsnzPIB3nPg+UnE9 ot2esLKQpHZpq69OxtmmBBlUCNJeEH/2UCfoM8Yc23FUFa5G7fdOV+lYIcHNxsKy3bsv gEbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683887860; x=1686479860; 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=JvtB4ZaRRF7BmNq4bmx+beZGtGWCkhMFyaEsvLCR/zc=; b=PdKURa+gH1lsOH50G1qo0LrC50MnMKKIJ8AEAsqcenSok2cyhuHy8ozVjUI5VEmy3h vnuzjeKL3u6W0Qlvzo9avxm8P7ehRejJVyRnRdUe0m8BBBQ9WxVjR7I4macgArZLfdgh w+9qiKVqSO8dC9gcxjNqN1MA7Vw2yahXXSa2UyN7wYvJ0IY5NnUfyPy7PC32jT4oaJwp tw4LA8lhBrqI7PMED3McQdo0Ne5H5v+rIBlOM2So+F2w2vDhMR4xAj3Z+UqB7rUTJ8A7 E5dNDNHEelQLyWB/UHkN1O7Ob92xzrEVI0ZI8IVUrJx0/ZJ4sD3NM6jgMmRFrzapVGGh 7hkA== X-Gm-Message-State: AC+VfDzrvFJg85rcigfqttyo6TcumQHe/GwXH+LyB+M0tHSWTO6PsJ38 ggruKGy8nr5i2WjDGPw9zvjvVBkpaZLr8Fu0 X-Google-Smtp-Source: ACHHUZ7TduvNhxsFn52wZmQHK9J4Q4gbGK+4urStXiNzTlhWgcRp3uEKsMcBIcRe21TXNkFOkNL/tA== X-Received: by 2002:a05:6a00:1820:b0:64a:ea46:3b7d with SMTP id y32-20020a056a00182000b0064aea463b7dmr1505005pfa.23.1683887860098; Fri, 12 May 2023 03:37:40 -0700 (PDT) Received: from kelvin-ThinkPad-L14-Gen-1.lan ([103.184.129.7]) by smtp.gmail.com with ESMTPSA id k5-20020aa792c5000000b0063b89300347sm7009485pfa.142.2023.05.12.03.37.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 12 May 2023 03:37:39 -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 v4 3/3] clocksource: loongson1: Move PWM timer to clocksource framework Date: Fri, 12 May 2023 18:37:24 +0800 Message-Id: <20230512103724.587760-4-keguang.zhang@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230512103724.587760-1-keguang.zhang@gmail.com> References: <20230512103724.587760-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 with devicetree support and updates Kconfig/Makefile options. Signed-off-by: Keguang Zhang --- V3 -> V4: Change the wildcard compatible string to the specific one V2 -> V3: None V1 -> V2: None --- 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..6335fee03017 --- /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,ls1b-pwmtimer", + ls1x_pwm_clocksource_init);