From mboxrd@z Thu Jan 1 00:00:00 1970 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 29933C433F5 for ; Thu, 21 Oct 2021 08:01:59 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D6D3C611CB for ; Thu, 21 Oct 2021 08:01:58 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org D6D3C611CB Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=samsung.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:References:Content-Type: In-Reply-To:MIME-Version:Message-ID:Subject:Cc:To:From:Date:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=I+M9LjZpNmja6Mm8BjZwjsBi97fjOGlMPxQGPYOjTmE=; b=ZC71wOQzc5fWJXW4CPwPo6B/Ry TKce5LuNES4Wjuy2RN/u4BAnR6DLUl906gIVf7m4NcgBwe4FOe48kFb0gjt3nQUqLDgzIDxypvCJ2 wR36xu3Qqw+CabbwBPzfmZ/P4LVO7AMMkCpUvxouC+P74/RMS8hWhF+7lB0hPcQpjoCmwJyVigWtK wDihIRs+RKuq14zQMaUhCLIy34yHsrIIMA8egPDYJ7Idy4Jkgmyb8pn8S51ZRpT8y2BhnKGHfci8p uTcTJKXVtJIx5Dy536xDjfFyWC+jg4Zp8Cd0vnPoVdVhCn7KdB0/fMdcqkY8AiGUV/TqCCTC4Usci DeAd05zA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mdSzs-006nwK-7O; Thu, 21 Oct 2021 08:00:20 +0000 Received: from mailout4.samsung.com ([203.254.224.34]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mdSzm-006nvO-B2 for linux-arm-kernel@lists.infradead.org; Thu, 21 Oct 2021 08:00:17 +0000 Received: from epcas2p3.samsung.com (unknown [182.195.41.55]) by mailout4.samsung.com (KnoxPortal) with ESMTP id 20211021080006epoutp04e16ce615018285ce6c2d788c604d8be2~v-NrTFcFR1465614656epoutp04F for ; Thu, 21 Oct 2021 08:00:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout4.samsung.com 20211021080006epoutp04e16ce615018285ce6c2d788c604d8be2~v-NrTFcFR1465614656epoutp04F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1634803206; bh=VyYwwV7nvg3QXiGib56sQBxkzHlvvbOPce4b0gQKE9E=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=Io1LZ/s+SMUNHaDsl7Dzcj/jkUe11KU25O/0BEwX8CQz39u69hFxiUxAOQZqYem8r BdctYcQqcF994ssRAv2/oR/sb+kIdE0E1Nhjy8qIy7ARWPa2zOhqFVWPZ9xbef/MLa uZJCf5Q3WW9uQd/GPba6E0fgsgJ/mwq8AlPUkImw= Received: from epsnrtp4.localdomain (unknown [182.195.42.165]) by epcas2p2.samsung.com (KnoxPortal) with ESMTP id 20211021080006epcas2p2d9fd3d3e032d8f929209455b905984be~v-Nq4ErJx0089800898epcas2p2P; Thu, 21 Oct 2021 08:00:06 +0000 (GMT) Received: from epsmges2p1.samsung.com (unknown [182.195.36.99]) by epsnrtp4.localdomain (Postfix) with ESMTP id 4HZfyy08Cmz4x9Q9; Thu, 21 Oct 2021 07:59:54 +0000 (GMT) Received: from epcas2p4.samsung.com ( [182.195.41.56]) by epsmges2p1.samsung.com (Symantec Messaging Gateway) with SMTP id B9.A4.09868.1FD11716; Thu, 21 Oct 2021 16:59:45 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas2p3.samsung.com (KnoxPortal) with ESMTPA id 20211021075945epcas2p3bbc1a5645296bc1e4e026f2a3c38403e~v-NXdb4p63205532055epcas2p3W; Thu, 21 Oct 2021 07:59:45 +0000 (GMT) Received: from epsmgms1p2.samsung.com (unknown [182.195.42.42]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20211021075945epsmtrp1ade2c37e423f68c169c3506b9986330b~v-NXcm1YO0084000840epsmtrp1F; Thu, 21 Oct 2021 07:59:45 +0000 (GMT) X-AuditID: b6c32a45-9b9ff7000000268c-96-61711df1ebf3 Received: from epsmtip1.samsung.com ( [182.195.34.30]) by epsmgms1p2.samsung.com (Symantec Messaging Gateway) with SMTP id C2.A7.08738.1FD11716; Thu, 21 Oct 2021 16:59:45 +0900 (KST) Received: from perf (unknown [12.36.155.123]) by epsmtip1.samsung.com (KnoxPortal) with ESMTPA id 20211021075944epsmtip1a127c2b70b3649934aa78054e386ef38~v-NXPFtg50409004090epsmtip10; Thu, 21 Oct 2021 07:59:44 +0000 (GMT) Date: Thu, 21 Oct 2021 17:26:50 +0900 From: Youngmin Nam To: Krzysztof Kozlowski Cc: daniel.lezcano@linaro.org, tglx@linutronix.de, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, pullip.cho@samsung.com, hoony.yu@samsung.com, hajun.sung@samsung.com, myung-su.cha@samsung.com Subject: Re: [PATCH v1 1/2] clocksource/drivers/exynos_mct_v2: introduce Exynos MCT version 2 driver for next Exynos SoC Message-ID: <20211021082650.GA30741@perf> MIME-Version: 1.0 In-Reply-To: <0c5dcdab-7aa3-a98f-e615-acbe98489935@canonical.com> User-Agent: Mutt/1.9.4 (2018-02-28) X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrLJsWRmVeSWpSXmKPExsWy7bCmhe5H2cJEg7l92hbzPstaNO2/xGxx fO1rVouNb38wWWx6fI3V4vKuOWwWM87vY7JY/HgFk8W/3oOMFps3TWV24PKY1dDL5nHn2h42 j3fnzrF7bF5S79G3ZRWjx+dNcgFsUdk2GamJKalFCql5yfkpmXnptkrewfHO8aZmBoa6hpYW 5koKeYm5qbZKLj4Bum6ZOUCHKSmUJeaUAoUCEouLlfTtbIryS0tSFTLyi0tslVILUnIKzAv0 ihNzi0vz0vXyUkusDA0MjEyBChOyM7Y2vmMtuN/GWHFmwwWmBsZTOV2MnBwSAiYSu14dZ+1i 5OIQEtjBKPF9cic7hPOJUeLDnl4o5zOjRPP9n8wwLdNX3oBK7GKUeNx9gw3CecQocWFvGyNI FYuAqkTDr4PsIDabgK7EthP/wOIiAtYSR7fOZwZpYBb4xyjRMHUNE0hCWKBK4trTBWwgNq+A psTvh/tZIGxBiZMzn4DZnAKOEqeWXwM7Q1RAWeLAtuNMIIMkBOZySPzd0wx1n4vE6v0vmSBs YYlXx7ewQ9hSEi/726DseonF25YyQzRPYJSYv+kDVMJYYtazdrBTmQUyJO7M3g90EQdQXFni yC0WiDCfRMfhv+wQYV6JjjYhiE41iV9TNjBC2DISuxevgDrHQ2LXloOMkBD6wyjx/uV6tgmM 8rOQ/DYLyTYIW0diwe5PQDYHkC0tsfwfB4SpKbF+l/4CRtZVjGKpBcW56anFRgWG8AhPzs/d xAhOt1quOxgnv/2gd4iRiYPxEKMEB7OSCO/uivxEId6UxMqq1KL8+KLSnNTiQ4ymwJiayCwl mpwPTPh5JfGGJpYGJmZmhuZGpgbmSuK8lqLZiUIC6YklqdmpqQWpRTB9TBycUg1MtQFJl4Rd Vb2X/vqTUrPrh3lZ5clrFry9tmej15sy++x40lYR5Tw5L/H086io32rXq3xCGl132M2MEVs7 L5V3F6/Ro6eMwTItHBprjNOfLGAr2Jmtm/PAwOTd9Jk/FT11WO//iT9rW1B/mOn+27D3/you Ta/ZyfG1wOCg98Oz57559Fo95VP8y/Jlw9atersaj5zk9nVaVLls7qNdvqvF5TQ/fcnI3Hxz 6xOGX+fv8xz++cB2olVxjUd1082azfJzzu7SYHNY5vbsLEukV/OHiqAnAv9WPHMtShbgSn+7 +mP9Arb9ar5MH7n87q+7fWOr0r2a5/ekK3j/G2z58dp8rXmbeiZXYviJCSz/31rfUmIpzkg0 1GIuKk4EAPL+5K1ABAAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrELMWRmVeSWpSXmKPExsWy7bCSnO5H2cJEg9ZHrBbzPstaNO2/xGxx fO1rVouNb38wWWx6fI3V4vKuOWwWM87vY7JY/HgFk8W/3oOMFps3TWV24PKY1dDL5nHn2h42 j3fnzrF7bF5S79G3ZRWjx+dNcgFsUVw2Kak5mWWpRfp2CVwZy6+cYymY38JYMafpPmMD4+Ks LkZODgkBE4npK2+wdzFycQgJ7GCU2LewhREiISNxe+VlVghbWOJ+yxFWiKIHjBJ3j7WDFbEI qEo0/DrIDmKzCehKbDvxDywuImAtcXTrfGaQBmaBBiaJA1dmgiWEBaokrj1dwAZi8wpoSvx+ uJ8FYuofRomFFy4xQiQEJU7OfMICYjMLaEnc+PeSqYuRA8iWllj+jwMkzCngKHFq+TVmEFtU QFniwLbjTBMYBWch6Z6FpHsWQvcCRuZVjJKpBcW56bnFhgVGeanlesWJucWleel6yfm5mxjB 0aKltYNxz6oPeocYmTgYDzFKcDArifDurshPFOJNSaysSi3Kjy8qzUktPsQozcGiJM57oetk vJBAemJJanZqakFqEUyWiYNTqoFph5MiJ7+B0/3swnSW2zp7Rf5+PdCnzMqpeS+J++zOAFXr fSVnZ0y+q/wtJ4+vbH1YmGuR4ldf5UNOnHGrVzyNPrgrRnpuQ8Lkmh1Pzil8CZN+btkTZnbx 2tVym9SF6SulbvyKVipLuLNDPK5fpjkmrn6CgMbxwkwOPa/VsxJCXCQCqx+y125V10x7Put2 am3kU91Tl7hehd0+vOzv4zPionpPPTrnlzJ/5j28d8kJXWYF5kK3QCbeZUKvolRu/lu74EDc 1pKqD2V2Zb3xJpM5GW/zNq22zEtY9e7u5kvbqxgfGk/+KnSqLJY1eK7DjX1rmJf6XJP+6jBV 5HKFQ7n6K6Xk0/dzk/7VBp0XZVZiKc5INNRiLipOBABqEuIdBQMAAA== X-CMS-MailID: 20211021075945epcas2p3bbc1a5645296bc1e4e026f2a3c38403e X-Msg-Generator: CA Content-Type: multipart/mixed; boundary="----TI73IYgzdP03rYJ9SiN0qM3o3mlayfAqXHuFFMbUzbY.6Ea-=_3116b_" X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20211021055112epcas2p278145beb21cd6cc4217813a41c1e1407 References: <20211021061804.39118-1-youngmin.nam@samsung.com> <20211021061804.39118-2-youngmin.nam@samsung.com> <0c5dcdab-7aa3-a98f-e615-acbe98489935@canonical.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211021_010014_833509_D71FEF28 X-CRM114-Status: GOOD ( 40.81 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org ------TI73IYgzdP03rYJ9SiN0qM3o3mlayfAqXHuFFMbUzbY.6Ea-=_3116b_ Content-Type: text/plain; charset="us-ascii" Content-Disposition: inline On Thu, Oct 21, 2021 at 08:18:36AM +0200, Krzysztof Kozlowski wrote: > On 21/10/2021 08:18, Youngmin Nam wrote: > > Exynos MCT version 2 is composed of 1 FRC and 12 comparators. > > The 12 comparators can produces interrupts independently, > > so they can be used as local timer of each CPU. > > > > Signed-off-by: Youngmin Nam > > --- > > drivers/clocksource/Kconfig | 6 + > > drivers/clocksource/Makefile | 1 + > > drivers/clocksource/exynos_mct_v2.c | 336 ++++++++++++++++++++++++++++ > > drivers/clocksource/exynos_mct_v2.h | 74 ++++++ > > 4 files changed, 417 insertions(+) > > create mode 100644 drivers/clocksource/exynos_mct_v2.c > > create mode 100644 drivers/clocksource/exynos_mct_v2.h > > > > diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig > > index 0f5e3983951a..8ac04dd7f713 100644 > > --- a/drivers/clocksource/Kconfig > > +++ b/drivers/clocksource/Kconfig > > @@ -421,6 +421,12 @@ config CLKSRC_EXYNOS_MCT > > help > > Support for Multi Core Timer controller on Exynos SoCs. > > > > +config CLKSRC_EXYNOS_MCT_V2 > > + bool "Exynos multi core timer (ver 2) driver" if COMPILE_TEST > > + depends on ARM64 > > depends on ARCH_EXYNOS. > Okay > > + help > > + Support for Multi Core Timer controller on Exynos SoCs. > > + > > config CLKSRC_SAMSUNG_PWM > > bool "PWM timer driver for Samsung S3C, S5P" if COMPILE_TEST > > depends on HAS_IOMEM > > diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile > > index c17ee32a7151..dc7d5cf27516 100644 > > --- a/drivers/clocksource/Makefile > > +++ b/drivers/clocksource/Makefile > > @@ -43,6 +43,7 @@ obj-$(CONFIG_CADENCE_TTC_TIMER) += timer-cadence-ttc.o > > obj-$(CONFIG_CLKSRC_STM32) += timer-stm32.o > > obj-$(CONFIG_CLKSRC_STM32_LP) += timer-stm32-lp.o > > obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o > > +obj-$(CONFIG_CLKSRC_EXYNOS_MCT_V2) += exynos_mct_v2.o > > obj-$(CONFIG_CLKSRC_LPC32XX) += timer-lpc32xx.o > > obj-$(CONFIG_CLKSRC_MPS2) += mps2-timer.o > > obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o > > diff --git a/drivers/clocksource/exynos_mct_v2.c b/drivers/clocksource/exynos_mct_v2.c > > new file mode 100644 > > index 000000000000..2da6d5401629 > > --- /dev/null > > +++ b/drivers/clocksource/exynos_mct_v2.c > > @@ -0,0 +1,336 @@ > > +// SPDX-License-Identifier: GPL-2.0-only > > +/* > > + * Copyright (c) 2022 Samsung Electronics Co., Ltd. > > + * http://www.samsung.com > > + * > > + * Exynos MCT(Multi-Core Timer) version 2 support > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include "exynos_mct_v2.h" > > + > > +static void __iomem *reg_base; > > +static unsigned long osc_clk_rate; > > +static int mct_irqs[MCT_NR_COMPS]; > > + > > +static void exynos_mct_set_compensation(unsigned long osc, unsigned long rtc) > > +{ > > + unsigned int osc_rtc; > > + unsigned int incr_rtcclk; > > + unsigned int compen_val; > > + > > + osc_rtc = (unsigned int)(osc * 1000 / rtc); > > + > > + /* MCT_INCR_RTCCLK is integer part of (OSCCLK frequency/RTCCLK frequency). */ > > + incr_rtcclk = (osc / rtc) + ((osc % rtc) ? 1 : 0); > > + > > + /* MCT_COMPENSATE_VALUE is decimal part of (OSCCLK frequency/RTCCLK frequency). */ > > + compen_val = ((osc_rtc + 5) / 10) % 100; > > + if (compen_val) > > + compen_val = 100 - compen_val; > > + > > + pr_info("MCT: osc-%lu rtc-%lu incr_rtcclk:0x%08x compen_val:0x%08x\n", > > + osc, rtc, incr_rtcclk, compen_val); > > + > > + writel_relaxed(incr_rtcclk, reg_base + EXYNOS_MCT_MCT_INCR_RTCCLK); > > + writel_relaxed(compen_val, reg_base + EXYNOS_MCT_COMPENSATE_VALUE); > > +} > > + > > +/* Clocksource handling */ > > +static void exynos_mct_frc_start(void) > > +{ > > + writel_relaxed(MCT_FRC_ENABLE, reg_base + EXYNOS_MCT_MCT_FRC_ENABLE); > > +} > > + > > +/** > > + * exynos_read_count_32 - Read the lower 32-bits of the global counter > > + * > > + * This will read just the lower 32-bits of the global counter. > > + * > > + * Returns the number of cycles in the global counter (lower 32 bits). > > + */ > > All this looks like a modification of Exynos MCT driver, so you should > extend that one instead. It does not look like we need two drivers. > Please integrate it into existing driver instead of sending a new piece > of code copied from vendor tree. > MCT version 2 is a completely different HW IP compared to previous MCT. The new MCT has a lot of different resister sets and there are many changes on programming guide. So we cannot share the previous code. At first, I also considered that way you mentioned, but it would be better to implement the driver seperately to maintain the new driver cleanly. > > +static u32 exynos_read_count_32(void) > > +{ > > + return readl_relaxed(reg_base + EXYNOS_MCT_CNT_L); > > +} > > + > > +static u64 exynos_frc_read(struct clocksource *cs) > > +{ > > + return exynos_read_count_32(); > > +} > > + > > +static struct clocksource mct_frc = { > > + .name = "mct-frc", > > + .rating = 350, /* use value lower than ARM arch timer */ > > + .read = exynos_frc_read, > > + .mask = CLOCKSOURCE_MASK(32), > > + .flags = CLOCK_SOURCE_IS_CONTINUOUS, > > +}; > > + > > +static int __init exynos_clocksource_init(void) > > +{ > > + if (clocksource_register_hz(&mct_frc, osc_clk_rate)) > > + panic("%s: can't register clocksource\n", mct_frc.name); > > + > > + return 0; > > +} > > + > > +static void exynos_mct_comp_stop(struct mct_clock_event_device *mevt) > > +{ > > + unsigned int index = mevt->comp_index; > > + unsigned int comp_enable; > > + unsigned int loop_cnt = 0; > > + > > + writel_relaxed(MCT_COMP_DISABLE, reg_base + EXYNOS_MCT_COMP_ENABLE(index)); > > + > > + /* Wait maximum 1 ms until COMP_ENABLE_n = 0 */ > > + do { > > + comp_enable = readl_relaxed(reg_base + EXYNOS_MCT_COMP_ENABLE(index)); > > + loop_cnt++; > > + } while (comp_enable != MCT_COMP_DISABLE && loop_cnt < WAIT_LOOP_CNT); > > + > > + if (loop_cnt == WAIT_LOOP_CNT) > > + panic("MCT(comp%d) disable timeout\n", index); > > + > > + writel_relaxed(MCT_COMP_NON_CIRCULAR_MODE, reg_base + EXYNOS_MCT_COMP_MODE(index)); > > + writel_relaxed(MCT_INT_DISABLE, reg_base + EXYNOS_MCT_INT_ENB(index)); > > + writel_relaxed(MCT_CSTAT_CLEAR, reg_base + EXYNOS_MCT_INT_CSTAT(index)); > > +} > > + > > +static void exynos_mct_comp_start(struct mct_clock_event_device *mevt, > > + bool periodic, unsigned long cycles) > > +{ > > + unsigned int index = mevt->comp_index; > > + unsigned int comp_enable; > > + unsigned int loop_cnt = 0; > > + > > + comp_enable = readl_relaxed(reg_base + EXYNOS_MCT_COMP_ENABLE(index)); > > + if (comp_enable == MCT_COMP_ENABLE) > > + exynos_mct_comp_stop(mevt); > > + > > + if (periodic) > > + writel_relaxed(MCT_COMP_CIRCULAR_MODE, reg_base + EXYNOS_MCT_COMP_MODE(index)); > > + > > + writel_relaxed(cycles, reg_base + EXYNOS_MCT_COMP_PERIOD(index)); > > + writel_relaxed(MCT_INT_ENABLE, reg_base + EXYNOS_MCT_INT_ENB(index)); > > + writel_relaxed(MCT_COMP_ENABLE, reg_base + EXYNOS_MCT_COMP_ENABLE(index)); > > + > > + /* Wait maximum 1 ms until COMP_ENABLE_n = 1 */ > > + do { > > + comp_enable = readl_relaxed(reg_base + EXYNOS_MCT_COMP_ENABLE(index)); > > + loop_cnt++; > > + } while (comp_enable != MCT_COMP_ENABLE && loop_cnt < WAIT_LOOP_CNT); > > + > > + if (loop_cnt == WAIT_LOOP_CNT) > > + panic("MCT(comp%d) enable timeout\n", index); > > +} > > + > > +static int exynos_comp_set_next_event(unsigned long cycles, struct clock_event_device *evt) > > +{ > > + struct mct_clock_event_device *mevt; > > + > > + mevt = container_of(evt, struct mct_clock_event_device, evt); > > + > > + exynos_mct_comp_start(mevt, false, cycles); > > + > > + return 0; > > +} > > + > > +static int mct_set_state_shutdown(struct clock_event_device *evt) > > +{ > > + struct mct_clock_event_device *mevt; > > + > > + mevt = container_of(evt, struct mct_clock_event_device, evt); > > + > > + exynos_mct_comp_stop(mevt); > > + > > + return 0; > > +} > > + > > +static int mct_set_state_periodic(struct clock_event_device *evt) > > +{ > > + unsigned long cycles_per_jiffy; > > + struct mct_clock_event_device *mevt; > > + > > + mevt = container_of(evt, struct mct_clock_event_device, evt); > > + > > + cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult) >> evt->shift); > > + exynos_mct_comp_start(mevt, true, cycles_per_jiffy); > > + > > + return 0; > > +} > > + > > +static irqreturn_t exynos_mct_comp_isr(int irq, void *dev_id) > > +{ > > + struct mct_clock_event_device *mevt = dev_id; > > + struct clock_event_device *evt = &mevt->evt; > > + unsigned int index = mevt->comp_index; > > + > > + writel_relaxed(MCT_CSTAT_CLEAR, reg_base + EXYNOS_MCT_INT_CSTAT(index)); > > + > > + evt->event_handler(evt); > > + > > + return IRQ_HANDLED; > > +} > > + > > +static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick); > > + > > +static int exynos_mct_starting_cpu(unsigned int cpu) > > +{ > > + struct mct_clock_event_device *mevt = per_cpu_ptr(&percpu_mct_tick, cpu); > > + struct clock_event_device *evt = &mevt->evt; > > + > > + snprintf(mevt->name, sizeof(mevt->name), "mct_comp%d", cpu); > > + > > + evt->name = mevt->name; > > + evt->cpumask = cpumask_of(cpu); > > + evt->set_next_event = exynos_comp_set_next_event; > > + evt->set_state_periodic = mct_set_state_periodic; > > + evt->set_state_shutdown = mct_set_state_shutdown; > > + evt->set_state_oneshot = mct_set_state_shutdown; > > + evt->set_state_oneshot_stopped = mct_set_state_shutdown; > > + evt->tick_resume = mct_set_state_shutdown; > > + evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; > > + evt->rating = 500; /* use value higher than ARM arch timer */ > > + > > + if (evt->irq == -1) > > + return -EIO; > > + > > + irq_force_affinity(evt->irq, cpumask_of(cpu)); > > + enable_irq(evt->irq); > > + clockevents_config_and_register(evt, osc_clk_rate, 0xf, 0x7fffffff); > > + > > + return 0; > > +} > > + > > +static int exynos_mct_dying_cpu(unsigned int cpu) > > +{ > > + struct mct_clock_event_device *mevt = per_cpu_ptr(&percpu_mct_tick, cpu); > > + struct clock_event_device *evt = &mevt->evt; > > + unsigned int index = mevt->comp_index; > > + > > + evt->set_state_shutdown(evt); > > + if (evt->irq != -1) > > + disable_irq_nosync(evt->irq); > > + > > + writel_relaxed(MCT_CSTAT_CLEAR, reg_base + EXYNOS_MCT_INT_CSTAT(index)); > > + > > + return 0; > > +} > > + > > +static int __init exynos_timer_resources(struct device_node *np, void __iomem *base) > > +{ > > + int err, cpu; > > + > > + struct clk *mct_clk, *tick_clk, *rtc_clk; > > + unsigned long rtc_clk_rate; > > + int div; > > + int ret; > > + > > + ret = of_property_read_u32(np, "div", &div); > > + if (ret || !div) { > > + pr_warn("MCT: fail to get the div value. set div to the default\n"); > > + div = DEFAULT_CLK_DIV; > > + } > > + > > + tick_clk = of_clk_get_by_name(np, "fin_pll"); > > + if (IS_ERR(tick_clk)) > > + panic("%s: unable to determine tick clock rate\n", __func__); > > + osc_clk_rate = clk_get_rate(tick_clk) / div; > > + > > + mct_clk = of_clk_get_by_name(np, "mct"); > > + if (IS_ERR(mct_clk)) > > + panic("%s: unable to retrieve mct clock instance\n", __func__); > > + clk_prepare_enable(mct_clk); > > + > > + rtc_clk = of_clk_get_by_name(np, "rtc"); > > Why timer needs a RTC clock? > On the new MCT, RTC clock can be used as backup clock instead of OSC clock. > > + if (IS_ERR(rtc_clk)) { > > + pr_warn("MCT: fail to get rtc clock. set to the default\n"); > > + rtc_clk_rate = DEFAULT_RTC_CLK_RATE; > > + } else { > > + rtc_clk_rate = clk_get_rate(rtc_clk); > > + } > > + > > + reg_base = base; > > + if (!reg_base) > > + panic("%s: unable to ioremap mct address space\n", __func__); > > + > > + exynos_mct_set_compensation(osc_clk_rate, rtc_clk_rate); > > + exynos_mct_frc_start(); > > + > > + for_each_possible_cpu(cpu) { > > + int mct_irq = mct_irqs[cpu]; > > + struct mct_clock_event_device *pcpu_mevt = per_cpu_ptr(&percpu_mct_tick, cpu); > > + > > + pcpu_mevt->evt.irq = -1; > > + pcpu_mevt->comp_index = cpu; > > + > > + irq_set_status_flags(mct_irq, IRQ_NOAUTOEN); > > + if (request_irq(mct_irq, > > + exynos_mct_comp_isr, > > + IRQF_TIMER | IRQF_NOBALANCING | IRQF_PERCPU, > > + "exynos-mct", pcpu_mevt)) { > > + pr_err("exynos-mct: cannot register IRQ (cpu%d)\n", cpu); > > + continue; > > + } > > + pcpu_mevt->evt.irq = mct_irq; > > + } > > + > > + /* Install hotplug callbacks which configure the timer on this CPU */ > > + err = cpuhp_setup_state(CPUHP_AP_EXYNOS4_MCT_TIMER_STARTING, > > + "clockevents/exynos/mct_timer_v2:starting", > > + exynos_mct_starting_cpu, > > + exynos_mct_dying_cpu); > > + if (err) > > + goto out_irq; > > + > > + return 0; > > + > > +out_irq: > > + for_each_possible_cpu(cpu) { > > + struct mct_clock_event_device *pcpu_mevt = per_cpu_ptr(&percpu_mct_tick, cpu); > > + > > + if (pcpu_mevt->evt.irq != -1) { > > + free_irq(pcpu_mevt->evt.irq, pcpu_mevt); > > + pcpu_mevt->evt.irq = -1; > > + } > > + } > > + return err; > > +} > > + > > +static int __init mct_init_dt(struct device_node *np) > > +{ > > + u32 nr_irqs = 0, i; > > + int ret; > > + > > + /* > > + * Find out the total number of irqs which can be produced by comparators. > > + */ > > + nr_irqs = of_irq_count(np); > > + > > + for (i = MCT_COMP0; i < nr_irqs; i++) > > + mct_irqs[i] = irq_of_parse_and_map(np, i); > > + > > + pr_info("## exynos_timer_resources\n"); > > Not a Linux kernel style of debug message. > Okay > > + ret = exynos_timer_resources(np, of_iomap(np, 0)); > > + if (ret) > > + return ret; > > + > > + pr_info("## exynos_clocksource_init\n"); > > + ret = exynos_clocksource_init(); > > + > > + return ret; > > +} > > + > > +TIMER_OF_DECLARE(s5e99xx, "samsung,s5e99xx-mct", mct_init_dt); > > diff --git a/drivers/clocksource/exynos_mct_v2.h b/drivers/clocksource/exynos_mct_v2.h > > new file mode 100644 > > index 000000000000..377421803bbe > > --- /dev/null > > +++ b/drivers/clocksource/exynos_mct_v2.h > > @@ -0,0 +1,74 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +/** > > + * exynos_mct_v2.h - Samsung Exynos MCT(Multi-Core Timer) Driver Header file > > + * > > + * Copyright (C) 2021 Samsung Electronics Co., Ltd. > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License version 2 as > > + * published by the Free Software Foundation. > > No need for license text. > Okay > > + */ > > + > > +#ifndef __EXYNOS_MCT_V2_H__ > > +#define __EXYNOS_MCT_V2_H__ > > + > > +#define EXYNOS_MCTREG(x) (x) > > +#define EXYNOS_MCT_MCT_CFG EXYNOS_MCTREG(0x000) > > +#define EXYNOS_MCT_MCT_INCR_RTCCLK EXYNOS_MCTREG(0x004) > > +#define EXYNOS_MCT_MCT_FRC_ENABLE EXYNOS_MCTREG(0x100) > > +#define EXYNOS_MCT_CNT_L EXYNOS_MCTREG(0x110) > > +#define EXYNOS_MCT_CNT_U EXYNOS_MCTREG(0x114) > > +#define EXYNOS_MCT_CLKMUX_SEL EXYNOS_MCTREG(0x120) > > +#define EXYNOS_MCT_COMPENSATE_VALUE EXYNOS_MCTREG(0x124) > > +#define EXYNOS_MCT_VER EXYNOS_MCTREG(0x128) > > +#define EXYNOS_MCT_DIVCHG_ACK EXYNOS_MCTREG(0x12C) > > +#define EXYNOS_MCT_COMP_L(i) EXYNOS_MCTREG(0x200 + ((i) * 0x100)) > > +#define EXYNOS_MCT_COMP_U(i) EXYNOS_MCTREG(0x204 + ((i) * 0x100)) > > +#define EXYNOS_MCT_COMP_MODE(i) EXYNOS_MCTREG(0x208 + ((i) * 0x100)) > > +#define EXYNOS_MCT_COMP_PERIOD(i) EXYNOS_MCTREG(0x20C + ((i) * 0x100)) > > +#define EXYNOS_MCT_COMP_ENABLE(i) EXYNOS_MCTREG(0x210 + ((i) * 0x100)) > > +#define EXYNOS_MCT_INT_ENB(i) EXYNOS_MCTREG(0x214 + ((i) * 0x100)) > > +#define EXYNOS_MCT_INT_CSTAT(i) EXYNOS_MCTREG(0x218 + ((i) * 0x100)) > > + > > +#define MCT_FRC_ENABLE (0x1) > > +#define MCT_COMP_ENABLE (0x1) > > +#define MCT_COMP_DISABLE (0x0) > > + > > +#define MCT_COMP_CIRCULAR_MODE (0x1) > > +#define MCT_COMP_NON_CIRCULAR_MODE (0x0) > > + > > +#define MCT_INT_ENABLE (0x1) > > +#define MCT_INT_DISABLE (0x0) > > + > > +#define MCT_CSTAT_CLEAR (0x1) > > + > > +#define DEFAULT_RTC_CLK_RATE 32768 // 32.768Khz > > +#define DEFAULT_CLK_DIV 3 // 1/3 > > Such comments are not useful. > Okay > Best regards, > Krzysztof > ------TI73IYgzdP03rYJ9SiN0qM3o3mlayfAqXHuFFMbUzbY.6Ea-=_3116b_ Content-Type: text/plain; charset="utf-8" ------TI73IYgzdP03rYJ9SiN0qM3o3mlayfAqXHuFFMbUzbY.6Ea-=_3116b_ Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ------TI73IYgzdP03rYJ9SiN0qM3o3mlayfAqXHuFFMbUzbY.6Ea-=_3116b_-- From mboxrd@z Thu Jan 1 00:00:00 1970 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 34E13C433EF for ; Thu, 21 Oct 2021 08:03:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1AF3D60EB2 for ; Thu, 21 Oct 2021 08:03:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231336AbhJUIF1 (ORCPT ); Thu, 21 Oct 2021 04:05:27 -0400 Received: from mailout2.samsung.com ([203.254.224.25]:38341 "EHLO mailout2.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231330AbhJUICY (ORCPT ); Thu, 21 Oct 2021 04:02:24 -0400 Received: from epcas2p3.samsung.com (unknown [182.195.41.55]) by mailout2.samsung.com (KnoxPortal) with ESMTP id 20211021080006epoutp02ff0c3f151c0cb7e00d26c3fc16f83224~v-NrWh5-Y2219322193epoutp02j for ; Thu, 21 Oct 2021 08:00:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.samsung.com 20211021080006epoutp02ff0c3f151c0cb7e00d26c3fc16f83224~v-NrWh5-Y2219322193epoutp02j DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1634803206; bh=VyYwwV7nvg3QXiGib56sQBxkzHlvvbOPce4b0gQKE9E=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=Io1LZ/s+SMUNHaDsl7Dzcj/jkUe11KU25O/0BEwX8CQz39u69hFxiUxAOQZqYem8r BdctYcQqcF994ssRAv2/oR/sb+kIdE0E1Nhjy8qIy7ARWPa2zOhqFVWPZ9xbef/MLa uZJCf5Q3WW9uQd/GPba6E0fgsgJ/mwq8AlPUkImw= Received: from epsnrtp4.localdomain (unknown [182.195.42.165]) by epcas2p2.samsung.com (KnoxPortal) with ESMTP id 20211021080006epcas2p2d9fd3d3e032d8f929209455b905984be~v-Nq4ErJx0089800898epcas2p2P; Thu, 21 Oct 2021 08:00:06 +0000 (GMT) Received: from epsmges2p1.samsung.com (unknown [182.195.36.99]) by epsnrtp4.localdomain (Postfix) with ESMTP id 4HZfyy08Cmz4x9Q9; Thu, 21 Oct 2021 07:59:54 +0000 (GMT) Received: from epcas2p4.samsung.com ( [182.195.41.56]) by epsmges2p1.samsung.com (Symantec Messaging Gateway) with SMTP id B9.A4.09868.1FD11716; Thu, 21 Oct 2021 16:59:45 +0900 (KST) Received: from epsmtrp1.samsung.com (unknown [182.195.40.13]) by epcas2p3.samsung.com (KnoxPortal) with ESMTPA id 20211021075945epcas2p3bbc1a5645296bc1e4e026f2a3c38403e~v-NXdb4p63205532055epcas2p3W; Thu, 21 Oct 2021 07:59:45 +0000 (GMT) Received: from epsmgms1p2.samsung.com (unknown [182.195.42.42]) by epsmtrp1.samsung.com (KnoxPortal) with ESMTP id 20211021075945epsmtrp1ade2c37e423f68c169c3506b9986330b~v-NXcm1YO0084000840epsmtrp1F; Thu, 21 Oct 2021 07:59:45 +0000 (GMT) X-AuditID: b6c32a45-9b9ff7000000268c-96-61711df1ebf3 Received: from epsmtip1.samsung.com ( [182.195.34.30]) by epsmgms1p2.samsung.com (Symantec Messaging Gateway) with SMTP id C2.A7.08738.1FD11716; Thu, 21 Oct 2021 16:59:45 +0900 (KST) Received: from perf (unknown [12.36.155.123]) by epsmtip1.samsung.com (KnoxPortal) with ESMTPA id 20211021075944epsmtip1a127c2b70b3649934aa78054e386ef38~v-NXPFtg50409004090epsmtip10; Thu, 21 Oct 2021 07:59:44 +0000 (GMT) Date: Thu, 21 Oct 2021 17:26:50 +0900 From: Youngmin Nam To: Krzysztof Kozlowski Cc: daniel.lezcano@linaro.org, tglx@linutronix.de, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, pullip.cho@samsung.com, hoony.yu@samsung.com, hajun.sung@samsung.com, myung-su.cha@samsung.com Subject: Re: [PATCH v1 1/2] clocksource/drivers/exynos_mct_v2: introduce Exynos MCT version 2 driver for next Exynos SoC Message-ID: <20211021082650.GA30741@perf> MIME-Version: 1.0 In-Reply-To: <0c5dcdab-7aa3-a98f-e615-acbe98489935@canonical.com> User-Agent: Mutt/1.9.4 (2018-02-28) X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrLJsWRmVeSWpSXmKPExsWy7bCmhe5H2cJEg7l92hbzPstaNO2/xGxx fO1rVouNb38wWWx6fI3V4vKuOWwWM87vY7JY/HgFk8W/3oOMFps3TWV24PKY1dDL5nHn2h42 j3fnzrF7bF5S79G3ZRWjx+dNcgFsUdk2GamJKalFCql5yfkpmXnptkrewfHO8aZmBoa6hpYW 5koKeYm5qbZKLj4Bum6ZOUCHKSmUJeaUAoUCEouLlfTtbIryS0tSFTLyi0tslVILUnIKzAv0 ihNzi0vz0vXyUkusDA0MjEyBChOyM7Y2vmMtuN/GWHFmwwWmBsZTOV2MnBwSAiYSu14dZ+1i 5OIQEtjBKPF9cic7hPOJUeLDnl4o5zOjRPP9n8wwLdNX3oBK7GKUeNx9gw3CecQocWFvGyNI FYuAqkTDr4PsIDabgK7EthP/wOIiAtYSR7fOZwZpYBb4xyjRMHUNE0hCWKBK4trTBWwgNq+A psTvh/tZIGxBiZMzn4DZnAKOEqeWXwM7Q1RAWeLAtuNMIIMkBOZySPzd0wx1n4vE6v0vmSBs YYlXx7ewQ9hSEi/726DseonF25YyQzRPYJSYv+kDVMJYYtazdrBTmQUyJO7M3g90EQdQXFni yC0WiDCfRMfhv+wQYV6JjjYhiE41iV9TNjBC2DISuxevgDrHQ2LXloOMkBD6wyjx/uV6tgmM 8rOQ/DYLyTYIW0diwe5PQDYHkC0tsfwfB4SpKbF+l/4CRtZVjGKpBcW56anFRgWG8AhPzs/d xAhOt1quOxgnv/2gd4iRiYPxEKMEB7OSCO/uivxEId6UxMqq1KL8+KLSnNTiQ4ymwJiayCwl mpwPTPh5JfGGJpYGJmZmhuZGpgbmSuK8lqLZiUIC6YklqdmpqQWpRTB9TBycUg1MtQFJl4Rd Vb2X/vqTUrPrh3lZ5clrFry9tmej15sy++x40lYR5Tw5L/H086io32rXq3xCGl132M2MEVs7 L5V3F6/Ro6eMwTItHBprjNOfLGAr2Jmtm/PAwOTd9Jk/FT11WO//iT9rW1B/mOn+27D3/you Ta/ZyfG1wOCg98Oz57559Fo95VP8y/Jlw9atersaj5zk9nVaVLls7qNdvqvF5TQ/fcnI3Hxz 6xOGX+fv8xz++cB2olVxjUd1082azfJzzu7SYHNY5vbsLEukV/OHiqAnAv9WPHMtShbgSn+7 +mP9Arb9ar5MH7n87q+7fWOr0r2a5/ekK3j/G2z58dp8rXmbeiZXYviJCSz/31rfUmIpzkg0 1GIuKk4EAPL+5K1ABAAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrELMWRmVeSWpSXmKPExsWy7bCSnO5H2cJEg9ZHrBbzPstaNO2/xGxx fO1rVouNb38wWWx6fI3V4vKuOWwWM87vY7JY/HgFk8W/3oOMFps3TWV24PKY1dDL5nHn2h42 j3fnzrF7bF5S79G3ZRWjx+dNcgFsUVw2Kak5mWWpRfp2CVwZy6+cYymY38JYMafpPmMD4+Ks LkZODgkBE4npK2+wdzFycQgJ7GCU2LewhREiISNxe+VlVghbWOJ+yxFWiKIHjBJ3j7WDFbEI qEo0/DrIDmKzCehKbDvxDywuImAtcXTrfGaQBmaBBiaJA1dmgiWEBaokrj1dwAZi8wpoSvx+ uJ8FYuofRomFFy4xQiQEJU7OfMICYjMLaEnc+PeSqYuRA8iWllj+jwMkzCngKHFq+TVmEFtU QFniwLbjTBMYBWch6Z6FpHsWQvcCRuZVjJKpBcW56bnFhgVGeanlesWJucWleel6yfm5mxjB 0aKltYNxz6oPeocYmTgYDzFKcDArifDurshPFOJNSaysSi3Kjy8qzUktPsQozcGiJM57oetk vJBAemJJanZqakFqEUyWiYNTqoFph5MiJ7+B0/3swnSW2zp7Rf5+PdCnzMqpeS+J++zOAFXr fSVnZ0y+q/wtJ4+vbH1YmGuR4ldf5UNOnHGrVzyNPrgrRnpuQ8Lkmh1Pzil8CZN+btkTZnbx 2tVym9SF6SulbvyKVipLuLNDPK5fpjkmrn6CgMbxwkwOPa/VsxJCXCQCqx+y125V10x7Put2 am3kU91Tl7hehd0+vOzv4zPionpPPTrnlzJ/5j28d8kJXWYF5kK3QCbeZUKvolRu/lu74EDc 1pKqD2V2Zb3xJpM5GW/zNq22zEtY9e7u5kvbqxgfGk/+KnSqLJY1eK7DjX1rmJf6XJP+6jBV 5HKFQ7n6K6Xk0/dzk/7VBp0XZVZiKc5INNRiLipOBABqEuIdBQMAAA== X-CMS-MailID: 20211021075945epcas2p3bbc1a5645296bc1e4e026f2a3c38403e X-Msg-Generator: CA Content-Type: multipart/mixed; boundary="----TI73IYgzdP03rYJ9SiN0qM3o3mlayfAqXHuFFMbUzbY.6Ea-=_3116b_" X-Sendblock-Type: AUTO_CONFIDENTIAL CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20211021055112epcas2p278145beb21cd6cc4217813a41c1e1407 References: <20211021061804.39118-1-youngmin.nam@samsung.com> <20211021061804.39118-2-youngmin.nam@samsung.com> <0c5dcdab-7aa3-a98f-e615-acbe98489935@canonical.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org ------TI73IYgzdP03rYJ9SiN0qM3o3mlayfAqXHuFFMbUzbY.6Ea-=_3116b_ Content-Type: text/plain; charset="us-ascii" Content-Disposition: inline On Thu, Oct 21, 2021 at 08:18:36AM +0200, Krzysztof Kozlowski wrote: > On 21/10/2021 08:18, Youngmin Nam wrote: > > Exynos MCT version 2 is composed of 1 FRC and 12 comparators. > > The 12 comparators can produces interrupts independently, > > so they can be used as local timer of each CPU. > > > > Signed-off-by: Youngmin Nam > > --- > > drivers/clocksource/Kconfig | 6 + > > drivers/clocksource/Makefile | 1 + > > drivers/clocksource/exynos_mct_v2.c | 336 ++++++++++++++++++++++++++++ > > drivers/clocksource/exynos_mct_v2.h | 74 ++++++ > > 4 files changed, 417 insertions(+) > > create mode 100644 drivers/clocksource/exynos_mct_v2.c > > create mode 100644 drivers/clocksource/exynos_mct_v2.h > > > > diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig > > index 0f5e3983951a..8ac04dd7f713 100644 > > --- a/drivers/clocksource/Kconfig > > +++ b/drivers/clocksource/Kconfig > > @@ -421,6 +421,12 @@ config CLKSRC_EXYNOS_MCT > > help > > Support for Multi Core Timer controller on Exynos SoCs. > > > > +config CLKSRC_EXYNOS_MCT_V2 > > + bool "Exynos multi core timer (ver 2) driver" if COMPILE_TEST > > + depends on ARM64 > > depends on ARCH_EXYNOS. > Okay > > + help > > + Support for Multi Core Timer controller on Exynos SoCs. > > + > > config CLKSRC_SAMSUNG_PWM > > bool "PWM timer driver for Samsung S3C, S5P" if COMPILE_TEST > > depends on HAS_IOMEM > > diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile > > index c17ee32a7151..dc7d5cf27516 100644 > > --- a/drivers/clocksource/Makefile > > +++ b/drivers/clocksource/Makefile > > @@ -43,6 +43,7 @@ obj-$(CONFIG_CADENCE_TTC_TIMER) += timer-cadence-ttc.o > > obj-$(CONFIG_CLKSRC_STM32) += timer-stm32.o > > obj-$(CONFIG_CLKSRC_STM32_LP) += timer-stm32-lp.o > > obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o > > +obj-$(CONFIG_CLKSRC_EXYNOS_MCT_V2) += exynos_mct_v2.o > > obj-$(CONFIG_CLKSRC_LPC32XX) += timer-lpc32xx.o > > obj-$(CONFIG_CLKSRC_MPS2) += mps2-timer.o > > obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o > > diff --git a/drivers/clocksource/exynos_mct_v2.c b/drivers/clocksource/exynos_mct_v2.c > > new file mode 100644 > > index 000000000000..2da6d5401629 > > --- /dev/null > > +++ b/drivers/clocksource/exynos_mct_v2.c > > @@ -0,0 +1,336 @@ > > +// SPDX-License-Identifier: GPL-2.0-only > > +/* > > + * Copyright (c) 2022 Samsung Electronics Co., Ltd. > > + * http://www.samsung.com > > + * > > + * Exynos MCT(Multi-Core Timer) version 2 support > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include "exynos_mct_v2.h" > > + > > +static void __iomem *reg_base; > > +static unsigned long osc_clk_rate; > > +static int mct_irqs[MCT_NR_COMPS]; > > + > > +static void exynos_mct_set_compensation(unsigned long osc, unsigned long rtc) > > +{ > > + unsigned int osc_rtc; > > + unsigned int incr_rtcclk; > > + unsigned int compen_val; > > + > > + osc_rtc = (unsigned int)(osc * 1000 / rtc); > > + > > + /* MCT_INCR_RTCCLK is integer part of (OSCCLK frequency/RTCCLK frequency). */ > > + incr_rtcclk = (osc / rtc) + ((osc % rtc) ? 1 : 0); > > + > > + /* MCT_COMPENSATE_VALUE is decimal part of (OSCCLK frequency/RTCCLK frequency). */ > > + compen_val = ((osc_rtc + 5) / 10) % 100; > > + if (compen_val) > > + compen_val = 100 - compen_val; > > + > > + pr_info("MCT: osc-%lu rtc-%lu incr_rtcclk:0x%08x compen_val:0x%08x\n", > > + osc, rtc, incr_rtcclk, compen_val); > > + > > + writel_relaxed(incr_rtcclk, reg_base + EXYNOS_MCT_MCT_INCR_RTCCLK); > > + writel_relaxed(compen_val, reg_base + EXYNOS_MCT_COMPENSATE_VALUE); > > +} > > + > > +/* Clocksource handling */ > > +static void exynos_mct_frc_start(void) > > +{ > > + writel_relaxed(MCT_FRC_ENABLE, reg_base + EXYNOS_MCT_MCT_FRC_ENABLE); > > +} > > + > > +/** > > + * exynos_read_count_32 - Read the lower 32-bits of the global counter > > + * > > + * This will read just the lower 32-bits of the global counter. > > + * > > + * Returns the number of cycles in the global counter (lower 32 bits). > > + */ > > All this looks like a modification of Exynos MCT driver, so you should > extend that one instead. It does not look like we need two drivers. > Please integrate it into existing driver instead of sending a new piece > of code copied from vendor tree. > MCT version 2 is a completely different HW IP compared to previous MCT. The new MCT has a lot of different resister sets and there are many changes on programming guide. So we cannot share the previous code. At first, I also considered that way you mentioned, but it would be better to implement the driver seperately to maintain the new driver cleanly. > > +static u32 exynos_read_count_32(void) > > +{ > > + return readl_relaxed(reg_base + EXYNOS_MCT_CNT_L); > > +} > > + > > +static u64 exynos_frc_read(struct clocksource *cs) > > +{ > > + return exynos_read_count_32(); > > +} > > + > > +static struct clocksource mct_frc = { > > + .name = "mct-frc", > > + .rating = 350, /* use value lower than ARM arch timer */ > > + .read = exynos_frc_read, > > + .mask = CLOCKSOURCE_MASK(32), > > + .flags = CLOCK_SOURCE_IS_CONTINUOUS, > > +}; > > + > > +static int __init exynos_clocksource_init(void) > > +{ > > + if (clocksource_register_hz(&mct_frc, osc_clk_rate)) > > + panic("%s: can't register clocksource\n", mct_frc.name); > > + > > + return 0; > > +} > > + > > +static void exynos_mct_comp_stop(struct mct_clock_event_device *mevt) > > +{ > > + unsigned int index = mevt->comp_index; > > + unsigned int comp_enable; > > + unsigned int loop_cnt = 0; > > + > > + writel_relaxed(MCT_COMP_DISABLE, reg_base + EXYNOS_MCT_COMP_ENABLE(index)); > > + > > + /* Wait maximum 1 ms until COMP_ENABLE_n = 0 */ > > + do { > > + comp_enable = readl_relaxed(reg_base + EXYNOS_MCT_COMP_ENABLE(index)); > > + loop_cnt++; > > + } while (comp_enable != MCT_COMP_DISABLE && loop_cnt < WAIT_LOOP_CNT); > > + > > + if (loop_cnt == WAIT_LOOP_CNT) > > + panic("MCT(comp%d) disable timeout\n", index); > > + > > + writel_relaxed(MCT_COMP_NON_CIRCULAR_MODE, reg_base + EXYNOS_MCT_COMP_MODE(index)); > > + writel_relaxed(MCT_INT_DISABLE, reg_base + EXYNOS_MCT_INT_ENB(index)); > > + writel_relaxed(MCT_CSTAT_CLEAR, reg_base + EXYNOS_MCT_INT_CSTAT(index)); > > +} > > + > > +static void exynos_mct_comp_start(struct mct_clock_event_device *mevt, > > + bool periodic, unsigned long cycles) > > +{ > > + unsigned int index = mevt->comp_index; > > + unsigned int comp_enable; > > + unsigned int loop_cnt = 0; > > + > > + comp_enable = readl_relaxed(reg_base + EXYNOS_MCT_COMP_ENABLE(index)); > > + if (comp_enable == MCT_COMP_ENABLE) > > + exynos_mct_comp_stop(mevt); > > + > > + if (periodic) > > + writel_relaxed(MCT_COMP_CIRCULAR_MODE, reg_base + EXYNOS_MCT_COMP_MODE(index)); > > + > > + writel_relaxed(cycles, reg_base + EXYNOS_MCT_COMP_PERIOD(index)); > > + writel_relaxed(MCT_INT_ENABLE, reg_base + EXYNOS_MCT_INT_ENB(index)); > > + writel_relaxed(MCT_COMP_ENABLE, reg_base + EXYNOS_MCT_COMP_ENABLE(index)); > > + > > + /* Wait maximum 1 ms until COMP_ENABLE_n = 1 */ > > + do { > > + comp_enable = readl_relaxed(reg_base + EXYNOS_MCT_COMP_ENABLE(index)); > > + loop_cnt++; > > + } while (comp_enable != MCT_COMP_ENABLE && loop_cnt < WAIT_LOOP_CNT); > > + > > + if (loop_cnt == WAIT_LOOP_CNT) > > + panic("MCT(comp%d) enable timeout\n", index); > > +} > > + > > +static int exynos_comp_set_next_event(unsigned long cycles, struct clock_event_device *evt) > > +{ > > + struct mct_clock_event_device *mevt; > > + > > + mevt = container_of(evt, struct mct_clock_event_device, evt); > > + > > + exynos_mct_comp_start(mevt, false, cycles); > > + > > + return 0; > > +} > > + > > +static int mct_set_state_shutdown(struct clock_event_device *evt) > > +{ > > + struct mct_clock_event_device *mevt; > > + > > + mevt = container_of(evt, struct mct_clock_event_device, evt); > > + > > + exynos_mct_comp_stop(mevt); > > + > > + return 0; > > +} > > + > > +static int mct_set_state_periodic(struct clock_event_device *evt) > > +{ > > + unsigned long cycles_per_jiffy; > > + struct mct_clock_event_device *mevt; > > + > > + mevt = container_of(evt, struct mct_clock_event_device, evt); > > + > > + cycles_per_jiffy = (((unsigned long long)NSEC_PER_SEC / HZ * evt->mult) >> evt->shift); > > + exynos_mct_comp_start(mevt, true, cycles_per_jiffy); > > + > > + return 0; > > +} > > + > > +static irqreturn_t exynos_mct_comp_isr(int irq, void *dev_id) > > +{ > > + struct mct_clock_event_device *mevt = dev_id; > > + struct clock_event_device *evt = &mevt->evt; > > + unsigned int index = mevt->comp_index; > > + > > + writel_relaxed(MCT_CSTAT_CLEAR, reg_base + EXYNOS_MCT_INT_CSTAT(index)); > > + > > + evt->event_handler(evt); > > + > > + return IRQ_HANDLED; > > +} > > + > > +static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick); > > + > > +static int exynos_mct_starting_cpu(unsigned int cpu) > > +{ > > + struct mct_clock_event_device *mevt = per_cpu_ptr(&percpu_mct_tick, cpu); > > + struct clock_event_device *evt = &mevt->evt; > > + > > + snprintf(mevt->name, sizeof(mevt->name), "mct_comp%d", cpu); > > + > > + evt->name = mevt->name; > > + evt->cpumask = cpumask_of(cpu); > > + evt->set_next_event = exynos_comp_set_next_event; > > + evt->set_state_periodic = mct_set_state_periodic; > > + evt->set_state_shutdown = mct_set_state_shutdown; > > + evt->set_state_oneshot = mct_set_state_shutdown; > > + evt->set_state_oneshot_stopped = mct_set_state_shutdown; > > + evt->tick_resume = mct_set_state_shutdown; > > + evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; > > + evt->rating = 500; /* use value higher than ARM arch timer */ > > + > > + if (evt->irq == -1) > > + return -EIO; > > + > > + irq_force_affinity(evt->irq, cpumask_of(cpu)); > > + enable_irq(evt->irq); > > + clockevents_config_and_register(evt, osc_clk_rate, 0xf, 0x7fffffff); > > + > > + return 0; > > +} > > + > > +static int exynos_mct_dying_cpu(unsigned int cpu) > > +{ > > + struct mct_clock_event_device *mevt = per_cpu_ptr(&percpu_mct_tick, cpu); > > + struct clock_event_device *evt = &mevt->evt; > > + unsigned int index = mevt->comp_index; > > + > > + evt->set_state_shutdown(evt); > > + if (evt->irq != -1) > > + disable_irq_nosync(evt->irq); > > + > > + writel_relaxed(MCT_CSTAT_CLEAR, reg_base + EXYNOS_MCT_INT_CSTAT(index)); > > + > > + return 0; > > +} > > + > > +static int __init exynos_timer_resources(struct device_node *np, void __iomem *base) > > +{ > > + int err, cpu; > > + > > + struct clk *mct_clk, *tick_clk, *rtc_clk; > > + unsigned long rtc_clk_rate; > > + int div; > > + int ret; > > + > > + ret = of_property_read_u32(np, "div", &div); > > + if (ret || !div) { > > + pr_warn("MCT: fail to get the div value. set div to the default\n"); > > + div = DEFAULT_CLK_DIV; > > + } > > + > > + tick_clk = of_clk_get_by_name(np, "fin_pll"); > > + if (IS_ERR(tick_clk)) > > + panic("%s: unable to determine tick clock rate\n", __func__); > > + osc_clk_rate = clk_get_rate(tick_clk) / div; > > + > > + mct_clk = of_clk_get_by_name(np, "mct"); > > + if (IS_ERR(mct_clk)) > > + panic("%s: unable to retrieve mct clock instance\n", __func__); > > + clk_prepare_enable(mct_clk); > > + > > + rtc_clk = of_clk_get_by_name(np, "rtc"); > > Why timer needs a RTC clock? > On the new MCT, RTC clock can be used as backup clock instead of OSC clock. > > + if (IS_ERR(rtc_clk)) { > > + pr_warn("MCT: fail to get rtc clock. set to the default\n"); > > + rtc_clk_rate = DEFAULT_RTC_CLK_RATE; > > + } else { > > + rtc_clk_rate = clk_get_rate(rtc_clk); > > + } > > + > > + reg_base = base; > > + if (!reg_base) > > + panic("%s: unable to ioremap mct address space\n", __func__); > > + > > + exynos_mct_set_compensation(osc_clk_rate, rtc_clk_rate); > > + exynos_mct_frc_start(); > > + > > + for_each_possible_cpu(cpu) { > > + int mct_irq = mct_irqs[cpu]; > > + struct mct_clock_event_device *pcpu_mevt = per_cpu_ptr(&percpu_mct_tick, cpu); > > + > > + pcpu_mevt->evt.irq = -1; > > + pcpu_mevt->comp_index = cpu; > > + > > + irq_set_status_flags(mct_irq, IRQ_NOAUTOEN); > > + if (request_irq(mct_irq, > > + exynos_mct_comp_isr, > > + IRQF_TIMER | IRQF_NOBALANCING | IRQF_PERCPU, > > + "exynos-mct", pcpu_mevt)) { > > + pr_err("exynos-mct: cannot register IRQ (cpu%d)\n", cpu); > > + continue; > > + } > > + pcpu_mevt->evt.irq = mct_irq; > > + } > > + > > + /* Install hotplug callbacks which configure the timer on this CPU */ > > + err = cpuhp_setup_state(CPUHP_AP_EXYNOS4_MCT_TIMER_STARTING, > > + "clockevents/exynos/mct_timer_v2:starting", > > + exynos_mct_starting_cpu, > > + exynos_mct_dying_cpu); > > + if (err) > > + goto out_irq; > > + > > + return 0; > > + > > +out_irq: > > + for_each_possible_cpu(cpu) { > > + struct mct_clock_event_device *pcpu_mevt = per_cpu_ptr(&percpu_mct_tick, cpu); > > + > > + if (pcpu_mevt->evt.irq != -1) { > > + free_irq(pcpu_mevt->evt.irq, pcpu_mevt); > > + pcpu_mevt->evt.irq = -1; > > + } > > + } > > + return err; > > +} > > + > > +static int __init mct_init_dt(struct device_node *np) > > +{ > > + u32 nr_irqs = 0, i; > > + int ret; > > + > > + /* > > + * Find out the total number of irqs which can be produced by comparators. > > + */ > > + nr_irqs = of_irq_count(np); > > + > > + for (i = MCT_COMP0; i < nr_irqs; i++) > > + mct_irqs[i] = irq_of_parse_and_map(np, i); > > + > > + pr_info("## exynos_timer_resources\n"); > > Not a Linux kernel style of debug message. > Okay > > + ret = exynos_timer_resources(np, of_iomap(np, 0)); > > + if (ret) > > + return ret; > > + > > + pr_info("## exynos_clocksource_init\n"); > > + ret = exynos_clocksource_init(); > > + > > + return ret; > > +} > > + > > +TIMER_OF_DECLARE(s5e99xx, "samsung,s5e99xx-mct", mct_init_dt); > > diff --git a/drivers/clocksource/exynos_mct_v2.h b/drivers/clocksource/exynos_mct_v2.h > > new file mode 100644 > > index 000000000000..377421803bbe > > --- /dev/null > > +++ b/drivers/clocksource/exynos_mct_v2.h > > @@ -0,0 +1,74 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +/** > > + * exynos_mct_v2.h - Samsung Exynos MCT(Multi-Core Timer) Driver Header file > > + * > > + * Copyright (C) 2021 Samsung Electronics Co., Ltd. > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License version 2 as > > + * published by the Free Software Foundation. > > No need for license text. > Okay > > + */ > > + > > +#ifndef __EXYNOS_MCT_V2_H__ > > +#define __EXYNOS_MCT_V2_H__ > > + > > +#define EXYNOS_MCTREG(x) (x) > > +#define EXYNOS_MCT_MCT_CFG EXYNOS_MCTREG(0x000) > > +#define EXYNOS_MCT_MCT_INCR_RTCCLK EXYNOS_MCTREG(0x004) > > +#define EXYNOS_MCT_MCT_FRC_ENABLE EXYNOS_MCTREG(0x100) > > +#define EXYNOS_MCT_CNT_L EXYNOS_MCTREG(0x110) > > +#define EXYNOS_MCT_CNT_U EXYNOS_MCTREG(0x114) > > +#define EXYNOS_MCT_CLKMUX_SEL EXYNOS_MCTREG(0x120) > > +#define EXYNOS_MCT_COMPENSATE_VALUE EXYNOS_MCTREG(0x124) > > +#define EXYNOS_MCT_VER EXYNOS_MCTREG(0x128) > > +#define EXYNOS_MCT_DIVCHG_ACK EXYNOS_MCTREG(0x12C) > > +#define EXYNOS_MCT_COMP_L(i) EXYNOS_MCTREG(0x200 + ((i) * 0x100)) > > +#define EXYNOS_MCT_COMP_U(i) EXYNOS_MCTREG(0x204 + ((i) * 0x100)) > > +#define EXYNOS_MCT_COMP_MODE(i) EXYNOS_MCTREG(0x208 + ((i) * 0x100)) > > +#define EXYNOS_MCT_COMP_PERIOD(i) EXYNOS_MCTREG(0x20C + ((i) * 0x100)) > > +#define EXYNOS_MCT_COMP_ENABLE(i) EXYNOS_MCTREG(0x210 + ((i) * 0x100)) > > +#define EXYNOS_MCT_INT_ENB(i) EXYNOS_MCTREG(0x214 + ((i) * 0x100)) > > +#define EXYNOS_MCT_INT_CSTAT(i) EXYNOS_MCTREG(0x218 + ((i) * 0x100)) > > + > > +#define MCT_FRC_ENABLE (0x1) > > +#define MCT_COMP_ENABLE (0x1) > > +#define MCT_COMP_DISABLE (0x0) > > + > > +#define MCT_COMP_CIRCULAR_MODE (0x1) > > +#define MCT_COMP_NON_CIRCULAR_MODE (0x0) > > + > > +#define MCT_INT_ENABLE (0x1) > > +#define MCT_INT_DISABLE (0x0) > > + > > +#define MCT_CSTAT_CLEAR (0x1) > > + > > +#define DEFAULT_RTC_CLK_RATE 32768 // 32.768Khz > > +#define DEFAULT_CLK_DIV 3 // 1/3 > > Such comments are not useful. > Okay > Best regards, > Krzysztof > ------TI73IYgzdP03rYJ9SiN0qM3o3mlayfAqXHuFFMbUzbY.6Ea-=_3116b_ Content-Type: text/plain; charset="utf-8" ------TI73IYgzdP03rYJ9SiN0qM3o3mlayfAqXHuFFMbUzbY.6Ea-=_3116b_--