diff --git a/arch/arm64/src/qemu/CMakeLists.txt b/arch/arm64/src/qemu/CMakeLists.txt index 141673930a1..05c43928518 100644 --- a/arch/arm64/src/qemu/CMakeLists.txt +++ b/arch/arm64/src/qemu/CMakeLists.txt @@ -30,4 +30,7 @@ endif() if(CONFIG_PM) list(APPEND SRCS qemu_initialize.c) endif() +if(CONFIG_RTC_PL031) + list(APPEND SRCS qemu_rtc.c) +endif() target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/arm64/src/qemu/Kconfig b/arch/arm64/src/qemu/Kconfig index 668b9c564d9..89e0b4b6b2a 100644 --- a/arch/arm64/src/qemu/Kconfig +++ b/arch/arm64/src/qemu/Kconfig @@ -47,4 +47,29 @@ config ARCH_CHIP_QEMU_WITH_HV endmenu # "Qemu Chip Selection" +config QEMU_RTC_PL031_BASE + hex "PL031 RTC base address" + default 0x09010000 + depends on RTC_PL031 + ---help--- + Physical address of the PL031 RTC of the QEMU virt machine. + +config QEMU_RTC_PL031_IRQ + int "PL031 RTC interrupt" + default 34 + depends on RTC_PL031 + ---help--- + Interrupt of the PL031 RTC of the QEMU virt machine (SPI 2). + +config QEMU_RTC_PL031_SYNC + bool "Start the system time at an RTC second boundary" + default n + depends on RTC_PL031 + ---help--- + The PL031 counts whole seconds, so the system time starts up to a + second behind the host. Files that the host writes then look + up to a second in the future, and make warns about clock skew. + With this option the boot waits (up to a second) for the RTC + second to change, so the time is correct to a few milliseconds. + endif # ARCH_CHIP_QEMU diff --git a/arch/arm64/src/qemu/Make.defs b/arch/arm64/src/qemu/Make.defs index 83c77512f22..da73b158d87 100644 --- a/arch/arm64/src/qemu/Make.defs +++ b/arch/arm64/src/qemu/Make.defs @@ -36,3 +36,7 @@ endif ifeq ($(CONFIG_PM),y) CHIP_CSRCS += qemu_initialize.c endif + +ifeq ($(CONFIG_RTC_PL031),y) +CHIP_CSRCS += qemu_rtc.c +endif diff --git a/arch/arm64/src/qemu/qemu_rtc.c b/arch/arm64/src/qemu/qemu_rtc.c new file mode 100644 index 00000000000..6c91e317f33 --- /dev/null +++ b/arch/arm64/src/qemu/qemu_rtc.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * arch/arm64/src/qemu/qemu_rtc.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "arm64_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_rtc_initialize + * + * Description: + * Register the PL031 RTC of the QEMU virt machine. QEMU sets it from the + * host clock (-rtc base=utc by default), so the system time starts at the + * host's time. + * + ****************************************************************************/ + +int up_rtc_initialize(void) +{ + FAR struct rtc_lowerhalf_s *lower; + +#ifdef CONFIG_QEMU_RTC_PL031_SYNC + /* The PL031 counts whole seconds, so the system time would start up to a + * second late. Wait until the second changes: the time read next is + * then correct to a few milliseconds. Register 0 is the data register. + */ + + uint32_t second = getreg32(CONFIG_QEMU_RTC_PL031_BASE); + + while (getreg32(CONFIG_QEMU_RTC_PL031_BASE) == second); +#endif + + lower = pl031_initialize(CONFIG_QEMU_RTC_PL031_BASE, + CONFIG_QEMU_RTC_PL031_IRQ); + up_rtc_set_lowerhalf(lower, true); + return rtc_initialize(0, lower); +}