From patchwork Thu Oct 13 02:29:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yu-Chien Peter Lin X-Patchwork-Id: 1689348 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=Kqp7Sk2m; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4MntnQ1RMnz23jn for ; Thu, 13 Oct 2022 13:31:38 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=8OL1fMxDNjlOnZb36NXIxURQBCJcQyHOIlcVLLTKPP0=; b=Kqp7Sk2mdPX6Mc f2XyY0fthxuBAd6FyU2kxk2M4BgVaVg2Egbq8WlQ1Rg2Ebbe78RcApXCzwb9Ioal7UQ0xAgesh7K1 NTmkwcEgB/RClHpmW9KqNc+erZBGQBhG4VTNaoLIP2Br88HUrEd8clYRN4wKWmK69c5gRUPVNT5ev zRRZ1EOi/U5Gu2sMa8nI3bI/VTYw1MFiywymXGCWS2jCnXdcBFRTI0CvIPcreu3B02CfGOorOoPis iPzdP0RVlOeFi1Zs/m2iexAqxCHYgKCYqBCEXXIxuSTAEidDNL2813ORTwh+iiNGYxkRNeu9cIbOd 8paJdD/LMuivdf+yqDHQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oio0I-00ALcs-HY; Thu, 13 Oct 2022 02:31:22 +0000 Received: from 60-248-80-70.hinet-ip.hinet.net ([60.248.80.70] helo=Atcsqr.andestech.com) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oio0D-00ALaA-Sk for opensbi@lists.infradead.org; Thu, 13 Oct 2022 02:31:20 +0000 Received: from mail.andestech.com (ATCPCS16.andestech.com [10.0.1.222]) by Atcsqr.andestech.com with ESMTP id 29D2Ugpl047468; Thu, 13 Oct 2022 10:30:42 +0800 (+08) (envelope-from peterlin@andestech.com) Received: from atcfdc88.andestech.com (10.0.15.120) by ATCPCS16.andestech.com (10.0.1.222) with Microsoft SMTP Server id 14.3.498.0; Thu, 13 Oct 2022 10:30:38 +0800 From: Yu Chien Peter Lin To: CC: , , , Yu Chien Peter Lin , Anup Patel Subject: [PATCH v3 07/13] lib: utils/timer: Add Andes fdt timer support Date: Thu, 13 Oct 2022 10:29:45 +0800 Message-ID: <20221013022951.5206-8-peterlin@andestech.com> X-Mailer: git-send-email 2.38.GIT In-Reply-To: <20221013022951.5206-1-peterlin@andestech.com> References: <20221013022951.5206-1-peterlin@andestech.com> MIME-Version: 1.0 X-Originating-IP: [10.0.15.120] X-DNSRBL: X-MAIL: Atcsqr.andestech.com 29D2Ugpl047468 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20221012_193118_437159_EBFF7309 X-CRM114-Status: GOOD ( 23.11 ) X-Spam-Score: 0.4 (/) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Since we can get the PLMT base address and timer frequency from device tree, move plmt timer device to fdt timer framework. dts example (Quad-core AX45MP): cpus { ... timebase-frequency = <0x3938700>; ... } soc { ... plmt0@e6000000 { compatible = "andestech,plmt0"; reg = <0x00 0xe6000000 0x00 0x100000>; interrupts-extended = <&cpu0_intc 0x07 &cpu1_intc [...] Content analysis details: (0.4 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 TVD_RCVD_IP Message was received from an IP address -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.4 RDNS_DYNAMIC Delivered to internal network by host with dynamic-looking rDNS X-BeenThere: opensbi@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "opensbi" Errors-To: opensbi-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Since we can get the PLMT base address and timer frequency from device tree, move plmt timer device to fdt timer framework. dts example (Quad-core AX45MP): cpus { ... timebase-frequency = <0x3938700>; ... } soc { ... plmt0@e6000000 { compatible = "andestech,plmt0"; reg = <0x00 0xe6000000 0x00 0x100000>; interrupts-extended = <&cpu0_intc 0x07 &cpu1_intc 0x07 &cpu2_intc 0x07 &cpu3_intc 0x07>; }; ... } Signed-off-by: Yu Chien Peter Lin Reviewed-by: Anup Patel --- Changes v2 -> v3 - Use sbi_domain_root_add_memrange() to add PLMT region to root domain --- include/sbi_utils/fdt/fdt_helper.h | 3 + include/sbi_utils/timer/andes_plmt.h | 33 +++++++++ lib/utils/fdt/fdt_helper.c | 54 ++++++++++++++ lib/utils/timer/Kconfig | 9 +++ lib/utils/timer/andes_plmt.c | 54 ++++++++++++++ lib/utils/timer/fdt_timer_plmt.c | 79 ++++++++++++++++++++ lib/utils/timer/objects.mk | 4 + platform/andes/ae350/Kconfig | 2 + platform/andes/ae350/objects.mk | 2 +- platform/andes/ae350/platform.c | 19 +---- platform/andes/ae350/platform.h | 2 - platform/andes/ae350/plmt.c | 107 --------------------------- platform/andes/ae350/plmt.h | 17 ----- 13 files changed, 241 insertions(+), 144 deletions(-) create mode 100644 include/sbi_utils/timer/andes_plmt.h create mode 100644 lib/utils/timer/andes_plmt.c create mode 100644 lib/utils/timer/fdt_timer_plmt.c delete mode 100644 platform/andes/ae350/plmt.c delete mode 100644 platform/andes/ae350/plmt.h diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h index bcd4996..7ef63c9 100644 --- a/include/sbi_utils/fdt/fdt_helper.h +++ b/include/sbi_utils/fdt/fdt_helper.h @@ -95,6 +95,9 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer, unsigned long *out_addr2, unsigned long *out_size2, u32 *out_first_hartid, u32 *out_hart_count); +int fdt_parse_plmt_node(void *fdt, int nodeoffset, unsigned long *plmt_base, + unsigned long *plmt_size, u32 *hart_count); + int fdt_parse_compat_addr(void *fdt, uint64_t *addr, const char *compatible); diff --git a/include/sbi_utils/timer/andes_plmt.h b/include/sbi_utils/timer/andes_plmt.h new file mode 100644 index 0000000..427dc78 --- /dev/null +++ b/include/sbi_utils/timer/andes_plmt.h @@ -0,0 +1,33 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Andes Technology Corporation + * + * Authors: + * Zong Li + * Nylon Chen + * Yu Chien Peter Lin + */ + +#include +#include +#include + +#ifndef __TIMER_ANDES_PLMT_H__ +#define __TIMER_ANDES_PLMT_H__ + +#define DEFAULT_AE350_PLMT_FREQ 60000000 +#define PLMT_REGION_ALIGN 0x1000 + +struct plmt_data { + u32 hart_count; + unsigned long size; + volatile u64 *time_val; + volatile u64 *time_cmp; +}; + +u64 plmt_timer_value(void); +void plmt_timer_event_stop(void); +void plmt_timer_event_start(u64 next_event); + +#endif /* __TIMER_ANDES_PLMT_H__ */ diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c index 6a75d6f..ce52fca 100644 --- a/lib/utils/fdt/fdt_helper.c +++ b/lib/utils/fdt/fdt_helper.c @@ -835,6 +835,60 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer, return 0; } +int fdt_parse_plmt_node(void *fdt, int nodeoffset, unsigned long *plmt_base, + unsigned long *plmt_size, u32 *hart_count) +{ + const fdt32_t *val; + int rc, i, count; + uint64_t reg_addr, reg_size, cpu_offset, cpu_intc_offset; + u32 phandle, hwirq, hartid, hcount; + + if (nodeoffset < 0 || !fdt || !plmt_base || + !hart_count || !plmt_size) + return SBI_EINVAL; + + rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, + ®_addr, ®_size); + if (rc < 0 || !plmt_base || !plmt_size) + return SBI_ENODEV; + *plmt_base = reg_addr; + *plmt_size = reg_size; + + val = fdt_getprop(fdt, nodeoffset, "interrupts-extended", &count); + if (!val || count < sizeof(fdt32_t)) + return 0; + count = count / sizeof(fdt32_t); + + hcount = 0; + for (i = 0; i < (count / 2); i++) { + phandle = fdt32_to_cpu(val[2 * i]); + hwirq = fdt32_to_cpu(val[2 * i + 1]); + + cpu_intc_offset = fdt_node_offset_by_phandle(fdt, phandle); + if (cpu_intc_offset < 0) + continue; + + cpu_offset = fdt_parent_offset(fdt, cpu_intc_offset); + if (cpu_intc_offset < 0) + continue; + + rc = fdt_parse_hart_id(fdt, cpu_offset, &hartid); + + if (rc) + continue; + + if (SBI_HARTMASK_MAX_BITS <= hartid) + continue; + + if (hwirq == IRQ_M_TIMER) + hcount++; + } + + *hart_count = hcount; + + return 0; +} + int fdt_parse_compat_addr(void *fdt, uint64_t *addr, const char *compatible) { diff --git a/lib/utils/timer/Kconfig b/lib/utils/timer/Kconfig index 23c48c5..ba211b6 100644 --- a/lib/utils/timer/Kconfig +++ b/lib/utils/timer/Kconfig @@ -14,10 +14,19 @@ config FDT_TIMER_MTIMER select TIMER_MTIMER default n +config FDT_TIMER_PLMT + bool "Andes PLMT FDT driver" + select TIMER_PLMT + default n + endif config TIMER_MTIMER bool "ACLINT MTIMER support" default n +config TIMER_PLMT + bool "Andes PLMT support" + default n + endmenu diff --git a/lib/utils/timer/andes_plmt.c b/lib/utils/timer/andes_plmt.c new file mode 100644 index 0000000..ea4f311 --- /dev/null +++ b/lib/utils/timer/andes_plmt.c @@ -0,0 +1,54 @@ +#include + +struct plmt_data plmt; + +u64 plmt_timer_value(void) +{ +#if __riscv_xlen == 64 + return readq_relaxed(plmt.time_val); +#else + u32 lo, hi; + + do { + hi = readl_relaxed((void *)plmt.time_val + 0x04); + lo = readl_relaxed(plmt.time_val); + } while (hi != readl_relaxed((void *)plmt.time_val + 0x04)); + + return ((u64)hi << 32) | (u64)lo; +#endif +} + +void plmt_timer_event_stop(void) +{ + u32 target_hart = current_hartid(); + + if (plmt.hart_count <= target_hart) + ebreak(); + + /* Clear PLMT Time Compare */ +#if __riscv_xlen == 64 + writeq_relaxed(-1ULL, &plmt.time_cmp[target_hart]); +#else + writel_relaxed(-1UL, &plmt.time_cmp[target_hart]); + writel_relaxed(-1UL, (void *)(&plmt.time_cmp[target_hart]) + 0x04); +#endif +} + +void plmt_timer_event_start(u64 next_event) +{ + u32 target_hart = current_hartid(); + + if (plmt.hart_count <= target_hart) + ebreak(); + + /* Program PLMT Time Compare */ +#if __riscv_xlen == 64 + writeq_relaxed(next_event, &plmt.time_cmp[target_hart]); +#else + u32 mask = -1UL; + + writel_relaxed(next_event & mask, &plmt.time_cmp[target_hart]); + writel_relaxed(next_event >> 32, + (void *)(&plmt.time_cmp[target_hart]) + 0x04); +#endif +} diff --git a/lib/utils/timer/fdt_timer_plmt.c b/lib/utils/timer/fdt_timer_plmt.c new file mode 100644 index 0000000..8947fa5 --- /dev/null +++ b/lib/utils/timer/fdt_timer_plmt.c @@ -0,0 +1,79 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Andes Technology Corporation + * + * Authors: + * Yu Chien Peter Lin + */ + +#include +#include +#include +#include +#include +#include + +extern struct plmt_data plmt; + +static struct sbi_timer_device plmt_timer = { + .name = "andes_plmt", + .timer_freq = DEFAULT_AE350_PLMT_FREQ, + .timer_value = plmt_timer_value, + .timer_event_start = plmt_timer_event_start, + .timer_event_stop = plmt_timer_event_stop +}; + +static int plmt_warm_timer_init(void) +{ + if (!plmt.time_val) + return SBI_ENODEV; + + plmt_timer_event_stop(); + + return 0; +} + +static int plmt_cold_timer_init(void *fdt, int nodeoff, + const struct fdt_match *match) +{ + int rc; + unsigned long freq, plmt_base; + + rc = fdt_parse_plmt_node(fdt, nodeoff, &plmt_base, &plmt.size, + &plmt.hart_count); + if (rc) + return rc; + + plmt.time_val = (u64 *)plmt_base; + plmt.time_cmp = (u64 *)(plmt_base + 0x8); + + rc = fdt_parse_timebase_frequency(fdt, &freq); + if (rc) + return rc; + + plmt_timer.timer_freq = freq; + + /* Add PLMT region to the root domain */ + rc = sbi_domain_root_add_memrange( + plmt_base, plmt.size, PLMT_REGION_ALIGN, + SBI_DOMAIN_MEMREGION_MMIO | SBI_DOMAIN_MEMREGION_READABLE); + if (rc) + return rc; + + sbi_timer_set_device(&plmt_timer); + + return 0; +} + +static const struct fdt_match timer_plmt_match[] = { + { .compatible = "andestech,plmt0" }, + {}, +}; + +struct fdt_timer fdt_timer_plmt = { + .match_table = timer_plmt_match, + .cold_init = plmt_cold_timer_init, + .warm_init = plmt_warm_timer_init, + .exit = NULL, +}; diff --git a/lib/utils/timer/objects.mk b/lib/utils/timer/objects.mk index 7f5f3ce..9360a76 100644 --- a/lib/utils/timer/objects.mk +++ b/lib/utils/timer/objects.mk @@ -8,9 +8,13 @@ # libsbiutils-objs-$(CONFIG_TIMER_MTIMER) += timer/aclint_mtimer.o +libsbiutils-objs-$(CONFIG_TIMER_PLMT) += timer/andes_plmt.o libsbiutils-objs-$(CONFIG_FDT_TIMER) += timer/fdt_timer.o libsbiutils-objs-$(CONFIG_FDT_TIMER) += timer/fdt_timer_drivers.o carray-fdt_timer_drivers-$(CONFIG_FDT_TIMER_MTIMER) += fdt_timer_mtimer libsbiutils-objs-$(CONFIG_FDT_TIMER_MTIMER) += timer/fdt_timer_mtimer.o + +carray-fdt_timer_drivers-$(CONFIG_FDT_TIMER_PLMT) += fdt_timer_plmt +libsbiutils-objs-$(CONFIG_FDT_TIMER_PLMT) += timer/fdt_timer_plmt.o diff --git a/platform/andes/ae350/Kconfig b/platform/andes/ae350/Kconfig index 8dd8ebe..f6f50eb 100644 --- a/platform/andes/ae350/Kconfig +++ b/platform/andes/ae350/Kconfig @@ -6,6 +6,8 @@ config PLATFORM_ANDES_AE350 select IRQCHIP_PLIC select FDT_SERIAL select FDT_SERIAL_UART8250 + select FDT_TIMER + select FDT_TIMER_PLMT default y if PLATFORM_ANDES_AE350 diff --git a/platform/andes/ae350/objects.mk b/platform/andes/ae350/objects.mk index 80f0737..1ccb894 100644 --- a/platform/andes/ae350/objects.mk +++ b/platform/andes/ae350/objects.mk @@ -15,7 +15,7 @@ platform-asflags-y = platform-ldflags-y = # Objects to build -platform-objs-y += cache.o platform.o plicsw.o plmt.o +platform-objs-y += cache.o platform.o plicsw.o # Blobs to build FW_TEXT_START=0x00000000 diff --git a/platform/andes/ae350/platform.c b/platform/andes/ae350/platform.c index 04428d1..79736c0 100644 --- a/platform/andes/ae350/platform.c +++ b/platform/andes/ae350/platform.c @@ -19,9 +19,9 @@ #include #include #include +#include #include "platform.h" #include "plicsw.h" -#include "plmt.h" #include "cache.h" static struct plic_data plic = { @@ -81,21 +81,6 @@ static int ae350_ipi_init(bool cold_boot) return plicsw_warm_ipi_init(); } -/* Initialize platform timer for current HART. */ -static int ae350_timer_init(bool cold_boot) -{ - int ret; - - if (cold_boot) { - ret = plmt_cold_timer_init(AE350_PLMT_ADDR, - AE350_HART_COUNT); - if (ret) - return ret; - } - - return plmt_warm_timer_init(); -} - /* Vendor-Specific SBI handler */ static int ae350_vendor_ext_provider(long extid, long funcid, const struct sbi_trap_regs *regs, unsigned long *out_value, @@ -150,7 +135,7 @@ const struct sbi_platform_operations platform_ops = { .ipi_init = ae350_ipi_init, - .timer_init = ae350_timer_init, + .timer_init = fdt_timer_init, .vendor_ext_provider = ae350_vendor_ext_provider }; diff --git a/platform/andes/ae350/platform.h b/platform/andes/ae350/platform.h index c699b7f..6a29fe5 100644 --- a/platform/andes/ae350/platform.h +++ b/platform/andes/ae350/platform.h @@ -18,8 +18,6 @@ #define AE350_PLICSW_ADDR 0xe6400000 -#define AE350_PLMT_ADDR 0xe6000000 - #define AE350_L2C_ADDR 0xe0500000 /*Memory and Miscellaneous Registers*/ diff --git a/platform/andes/ae350/plmt.c b/platform/andes/ae350/plmt.c deleted file mode 100644 index 54dcb94..0000000 --- a/platform/andes/ae350/plmt.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 Andes Technology Corporation - * - * Authors: - * Zong Li - * Nylon Chen - */ - -#include -#include -#include - -static u32 plmt_time_hart_count; -static volatile void *plmt_time_base; -static volatile u64 *plmt_time_val; -static volatile u64 *plmt_time_cmp; - -static u64 plmt_timer_value(void) -{ -#if __riscv_xlen == 64 - return readq_relaxed(plmt_time_val); -#else - u32 lo, hi; - - do { - hi = readl_relaxed((void *)plmt_time_val + 0x04); - lo = readl_relaxed(plmt_time_val); - } while (hi != readl_relaxed((void *)plmt_time_val + 0x04)); - - return ((u64)hi << 32) | (u64)lo; -#endif -} - -static void plmt_timer_event_stop(void) -{ - u32 target_hart = current_hartid(); - - if (plmt_time_hart_count <= target_hart) - return; - - /* Clear PLMT Time Compare */ -#if __riscv_xlen == 64 - writeq_relaxed(-1ULL, &plmt_time_cmp[target_hart]); -#else - writel_relaxed(-1UL, &plmt_time_cmp[target_hart]); - writel_relaxed(-1UL, (void *)(&plmt_time_cmp[target_hart]) + 0x04); -#endif -} - -static void plmt_timer_event_start(u64 next_event) -{ - u32 target_hart = current_hartid(); - - if (plmt_time_hart_count <= target_hart) - return; - - /* Program PLMT Time Compare */ -#if __riscv_xlen == 64 - writeq_relaxed(next_event, &plmt_time_cmp[target_hart]); -#else - u32 mask = -1UL; - - writel_relaxed(next_event & mask, &plmt_time_cmp[target_hart]); - writel_relaxed(next_event >> 32, - (void *)(&plmt_time_cmp[target_hart]) + 0x04); -#endif - -} - -static struct sbi_timer_device plmt_timer = { - .name = "ae350_plmt", - .timer_value = plmt_timer_value, - .timer_event_start = plmt_timer_event_start, - .timer_event_stop = plmt_timer_event_stop -}; - -int plmt_warm_timer_init(void) -{ - u32 target_hart = current_hartid(); - - if (plmt_time_hart_count <= target_hart || !plmt_time_base) - return -1; - - /* Clear PLMT Time Compare */ -#if __riscv_xlen == 64 - writeq_relaxed(-1ULL, &plmt_time_cmp[target_hart]); -#else - writel_relaxed(-1UL, &plmt_time_cmp[target_hart]); - writel_relaxed(-1UL, (void *)(&plmt_time_cmp[target_hart]) + 0x04); -#endif - - return 0; -} - -int plmt_cold_timer_init(unsigned long base, u32 hart_count) -{ - plmt_time_hart_count = hart_count; - plmt_time_base = (void *)base; - plmt_time_val = (u64 *)(plmt_time_base); - plmt_time_cmp = (u64 *)(plmt_time_base + 0x8); - - sbi_timer_set_device(&plmt_timer); - - return 0; -} diff --git a/platform/andes/ae350/plmt.h b/platform/andes/ae350/plmt.h deleted file mode 100644 index db093e0..0000000 --- a/platform/andes/ae350/plmt.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 Andes Technology Corporation - * - * Authors: - * Zong Li - */ - -#ifndef _AE350_PLMT_H_ -#define _AE350_PLMT_H_ - -int plmt_warm_timer_init(void); - -int plmt_cold_timer_init(unsigned long base, u32 hart_count); - -#endif /* _AE350_PLMT_H_ */