From: Josua Mayer <josua@solid-run.com>
To: Tom Rini <trini@konsulko.com>, Stefan Roese <sr@denx.de>
Cc: u-boot@lists.denx.de, Josua Mayer <josua@solid-run.com>,
Alex Leibovich <alexl@marvell.com>,
Kostya Porotchkin <kostap@marvell.com>
Subject: [PATCH 1/3] u-boot: drivers: marvell: rtc: adding rtc driver
Date: Sun, 09 Feb 2025 21:23:52 +0100 [thread overview]
Message-ID: <20250209-cn9130-board-v1-1-b94ab83e141b@solid-run.com> (raw)
In-Reply-To: <20250209-cn9130-board-v1-0-b94ab83e141b@solid-run.com>
From: Alex Leibovich <alexl@marvell.com>
Adding missing marvell-rtc driver and configuration,
in order to support "date" command.
Signed-off-by: Alex Leibovich <alexl@marvell.com>
Reviewed-on: https://sj1git1.cavium.com/c/IP/SW/boot/u-boot/+/6322
Reviewed-by: Kostya Porotchkin <kostap@marvell.com>
Tested-by: Kostya Porotchkin <kostap@marvell.com>
Signed-off-by: Josua Mayer <josua@solid-run.com>
---
drivers/rtc/Kconfig | 9 +++
drivers/rtc/Makefile | 1 +
drivers/rtc/marvell_rtc.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/rtc/marvell_rtc.h | 52 +++++++++++++
4 files changed, 247 insertions(+)
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 6467f20422bec546fd96b5e76643209870c8f255..aa2b292c57243f84d99d09b45aa271d66cd15a66 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -14,6 +14,15 @@ config DM_RTC
drivers to perform the actual functions. See rtc.h for a
description of the API.
+config MARVELL_RTC
+ bool "MARVELL RTC support"
+ depends on DM_RTC
+ help
+ Choose this option to add
+ support for Marvell's
+ RTC driver, which is used
+ by Armada 7K, 8K and OcteonTX2 CN913x.
+
config SPL_DM_RTC
bool "Enable Driver Model for RTC drivers in SPL"
depends on SPL_DM
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 99b5a2a346a9680ee33249597cec398c33e8d657..65c4d875d885546efb230bc5abd78e5d056ee863 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -7,6 +7,7 @@
obj-$(CONFIG_$(PHASE_)DM_RTC) += rtc-uclass.o
obj-$(CONFIG_RTC_ARMADA38X) += armada38x.o
+obj-$(CONFIG_MARVELL_RTC) += marvell_rtc.o
obj-$(CONFIG_RTC_DAVINCI) += davinci.o
obj-$(CONFIG_RTC_DS1307) += ds1307.o
obj-$(CONFIG_RTC_DS1338) += ds1307.o
diff --git a/drivers/rtc/marvell_rtc.c b/drivers/rtc/marvell_rtc.c
new file mode 100644
index 0000000000000000000000000000000000000000..842aeb84eb26ec79ff889d0484bcdb050da35b40
--- /dev/null
+++ b/drivers/rtc/marvell_rtc.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Marvell International Ltd.
+ */
+
+#include <asm/io.h>
+#include <rtc.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include "marvell_rtc.h"
+#include <linux/delay.h>
+
+static int marvell_rtc_get(struct udevice *dev, struct rtc_time *time)
+{
+ struct rtc_unit_config *rtc_cfg = dev_get_priv(dev);
+ uintptr_t rtc_base = (uintptr_t)rtc_cfg->rtc_base;
+
+ rtc_to_tm(RTC_READ_REG(rtc_base, RTC_TIME_REG_OFFS), time);
+
+ return 0;
+}
+
+static int marvell_rtc_set(struct udevice *dev, const struct rtc_time *time)
+{
+ unsigned long tm;
+ struct rtc_unit_config *rtc_cfg = dev_get_priv(dev);
+ uintptr_t rtc_base = (uintptr_t)rtc_cfg->rtc_base;
+
+ tm = rtc_mktime(time);
+
+#ifdef ERRATA_FE_3124064
+ RTC_WRITE_REG(0, rtc_base, RTC_STATUS_REG_OFFS);
+ RTC_WRITE_REG(0, rtc_base, RTC_STATUS_REG_OFFS);
+#endif
+ RTC_WRITE_REG(tm, rtc_base, RTC_TIME_REG_OFFS);
+
+ /* Give registers time to stabilize */
+ mdelay(100);
+
+ return 0;
+}
+
+static int marvell_rtc_reset(struct udevice *dev)
+{
+ struct rtc_unit_config *rtc_cfg = dev_get_priv(dev);
+ uintptr_t rtc_base = (uintptr_t)rtc_cfg->rtc_base;
+
+ /* Reset Test register */
+ RTC_WRITE_REG(0, rtc_base, RTC_TEST_CONFIG_REG_OFFS);
+ /* Oscillator startup time */
+ mdelay(500);
+
+ /* Reset time register */
+#ifdef ERRATA_FE_3124064
+ RTC_WRITE_REG(0, rtc_base, RTC_STATUS_REG_OFFS);
+ RTC_WRITE_REG(0, rtc_base, RTC_STATUS_REG_OFFS);
+#endif
+ RTC_WRITE_REG(0, rtc_base, RTC_TIME_REG_OFFS);
+ udelay(62);
+
+ /* Reset Status register */
+ RTC_WRITE_REG((RTC_SZ_STATUS_ALARM1_MASK | RTC_SZ_STATUS_ALARM2_MASK),
+ rtc_base, RTC_STATUS_REG_OFFS);
+ udelay(62);
+
+ /* Turn off Int1 and Int2 sources & clear the Alarm count */
+ RTC_WRITE_REG(0, rtc_base, RTC_IRQ_1_CONFIG_REG_OFFS);
+ RTC_WRITE_REG(0, rtc_base, RTC_IRQ_2_CONFIG_REG_OFFS);
+ RTC_WRITE_REG(0, rtc_base, RTC_ALARM_1_REG_OFFS);
+ RTC_WRITE_REG(0, rtc_base, RTC_ALARM_2_REG_OFFS);
+
+ /* Setup nominal register access timing */
+ RTC_WRITE_REG(RTC_NOMINAL_TIMING, rtc_base, RTC_CLOCK_CORR_REG_OFFS);
+
+ /* Reset time register */
+#ifdef ERRATA_FE_3124064
+ RTC_WRITE_REG(0, rtc_base, RTC_STATUS_REG_OFFS);
+ RTC_WRITE_REG(0, rtc_base, RTC_STATUS_REG_OFFS);
+#endif
+ RTC_WRITE_REG(0, rtc_base, RTC_TIME_REG_OFFS);
+ udelay(10);
+
+ /* Reset Status register */
+ RTC_WRITE_REG((RTC_SZ_STATUS_ALARM1_MASK | RTC_SZ_STATUS_ALARM2_MASK),
+ rtc_base, RTC_STATUS_REG_OFFS);
+ udelay(50);
+
+ return 0;
+}
+
+void marvell_rtc_errata(struct udevice *dev)
+{
+ unsigned long reg;
+
+ /* Get the rtc register base address */
+ struct rtc_unit_config *rtc_cfg = dev_get_priv(dev);
+ uintptr_t rtc_base;
+
+ rtc_cfg->rtc_base = (void *)devfdt_get_addr_index(dev, 0);
+ rtc_base = (uintptr_t)rtc_cfg->rtc_base;
+
+ /* Update RTC-MBUS bridge timing parameters */
+ /* Functional Errata Ref #:
+ * FE-3124064 - WA for failing time read attempts.
+ * Description:
+ * The device supports CPU write and read access
+ * to the RTC Time register.
+ * However, due to this erratum,
+ * Write to RTC TIME register may fail.
+ * Read from RTC TIME register may fail.
+ * Workaround:
+ * 1. Configure the RTC Mbus Bridge Timing Control register
+ * (offset 0x284080 and 0x284084)
+ * - Write RTC WRCLK Period 0x3FF (default value is 0xFA)
+ * - Write RTC WRCLK setup to 0x29 (default value is 0x53)
+ * - Write RTC Read Output Delay to 0x3F (default value is 0x10)
+ * - Write RTC WRCLK High Time to 0x53 (default value)
+ * - Mbus - Read All Byte Enable to 0x1 (default value)
+ * 2. Configure the RTC Test Configuration Register (offset 0x28401C)
+ * bit3 to '1' (Reserved, Marvell internal)
+ *
+ * RTC Time register write operation:
+ * - Issue two dummy writes of 0x0 to the RTC Status register
+ * (offset 0x284000).
+ * - Write the time to the RTC Time register (offset 0x28400C).
+ */
+ reg = RTC_READ_REG(rtc_base, MV_RTC0_SOC_OFFSET);
+ reg &= ~RTC_WRCLK_PERIOD_MASK;
+ reg |= 0x3FF << RTC_WRCLK_PERIOD_OFFS;
+ reg &= ~RTC_WRCLK_SETUP_MASK;
+ reg |= 0x29 << RTC_WRCLK_SETUP_OFFS;
+ RTC_WRITE_REG(reg, rtc_base, MV_RTC0_SOC_OFFSET);
+
+ reg = RTC_READ_REG(rtc_base, MV_RTC1_SOC_OFFSET);
+ reg &= ~RTC_READ_OUTPUT_DELAY_MASK;
+ reg |= 0x3F << RTC_READ_OUTPUT_DELAY_OFFS;
+ RTC_WRITE_REG(reg, rtc_base, MV_RTC1_SOC_OFFSET);
+
+ reg = RTC_READ_REG(rtc_base, RTC_TEST_CONFIG_REG_OFFS);
+ reg |= 0x8;
+ RTC_WRITE_REG(reg, rtc_base, RTC_TEST_CONFIG_REG_OFFS);
+}
+
+static int marvell_rtc_probe(struct udevice *dev)
+{
+#ifdef ERRATA_FE_3124064
+ marvell_rtc_errata(dev);
+#else
+ /* Get the rtc register base address */
+ struct rtc_unit_config *rtc_cfg = dev_get_priv(dev);
+ uintptr_t rtc_base;
+ unsigned long reg;
+
+ rtc_cfg->rtc_base = (void *)devfdt_get_addr_index(dev, 0);
+ rtc_base = (uintptr_t)rtc_cfg->rtc_base;
+
+ /* Update RTC-MBUS bridge timing parameters */
+ reg = RTC_READ_REG(rtc_base, MV_RTC1_SOC_OFFSET);
+ reg &= ~RTC_READ_OUTPUT_DELAY_MASK;
+ reg |= 0x1F << RTC_READ_OUTPUT_DELAY_OFFS;
+ RTC_WRITE_REG(reg, rtc_base, MV_RTC1_SOC_OFFSET);
+#endif
+
+ return 0;
+}
+
+static const struct rtc_ops marvell_rtc_ops = {
+ .get = marvell_rtc_get,
+ .set = marvell_rtc_set,
+ .reset = marvell_rtc_reset,
+};
+
+static const struct udevice_id marvell_rtc_ids[] = {
+ { .compatible = "marvell,armada-8k-rtc" },
+ { }
+};
+
+U_BOOT_DRIVER(marvell_rtc) = {
+ .name = "marvell_rtc",
+ .id = UCLASS_RTC,
+ .of_match = marvell_rtc_ids,
+ .ops = &marvell_rtc_ops,
+ .probe = marvell_rtc_probe,
+ .priv_auto = sizeof(struct rtc_unit_config),
+};
diff --git a/drivers/rtc/marvell_rtc.h b/drivers/rtc/marvell_rtc.h
new file mode 100644
index 0000000000000000000000000000000000000000..f93b03bd2c954f1be9b645fb4de23a89e92e9dbc
--- /dev/null
+++ b/drivers/rtc/marvell_rtc.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Marvell International Ltd.
+ */
+
+#ifndef _MARVELL_RTC_H
+#define _MARVELL_RTC_H
+
+/* The RTC DRS revision 1.2 indicates that firmware should wait
+ * 5us after every register write to the RTC hard macro,
+ * so that the required update can occur without holding off the system bus
+ */
+#define RTC_READ_REG(rtc_base, reg) readl((rtc_base) + (reg))
+#define RTC_WRITE_REG(val, rtc_base, reg) \
+ { writel((val), (rtc_base) + (reg)); udelay(5); }
+
+#define RTC_NOMINAL_TIMING 0x2000
+
+#define RTC_STATUS_REG_OFFS 0x0
+#define RTC_IRQ_1_CONFIG_REG_OFFS 0x4
+#define RTC_IRQ_2_CONFIG_REG_OFFS 0x8
+#define RTC_TIME_REG_OFFS 0xC
+#define RTC_ALARM_1_REG_OFFS 0x10
+#define RTC_ALARM_2_REG_OFFS 0x14
+#define RTC_CLOCK_CORR_REG_OFFS 0x18
+#define RTC_TEST_CONFIG_REG_OFFS 0x1C
+#define MV_RTC0_SOC_OFFSET 0x80
+#define MV_RTC1_SOC_OFFSET 0x84
+
+#define RTC_WRCLK_PERIOD_OFFS 0
+#define RTC_WRCLK_PERIOD_MASK (0xFFFF << RTC_WRCLK_PERIOD_OFFS)
+#define RTC_WRCLK_SETUP_OFFS 16
+#define RTC_WRCLK_SETUP_MASK (0xFFFF << RTC_WRCLK_SETUP_OFFS)
+
+#define RTC_READ_OUTPUT_DELAY_OFFS 0
+#define RTC_READ_OUTPUT_DELAY_MASK (0xFFFF << RTC_READ_OUTPUT_DELAY_OFFS)
+#define RTC_WRCLK_CLOCK_HIGH_OFFS 16
+#define RTC_WRCLK_CLOCK_HIGH_MASK (0xFFFF << RTC_WRCLK_CLOCK_HIGH_OFFS)
+
+#define RTC_SZ_STATUS_ALARM1_MASK 0x1
+#define RTC_SZ_STATUS_ALARM2_MASK 0x2
+#define RTC_SZ_TIMING_RESERVED1_MASK 0xFFFF0000
+#define RTC_SZ_INTERRUPT1_INT1AE_MASK 0x1
+#define RTC_SZ_INTERRUPT1_RESERVED1_MASK 0xFFFFFFC0
+#define RTC_SZ_INTERRUPT2_INT2FE_MASK 0x2
+#define RTC_SZ_INTERRUPT2_RESERVED1_MASK 0xFFFFFFC0
+
+struct rtc_unit_config {
+ void __iomem *rtc_base;
+};
+
+#endif /* _MARVELL_RTC_H */
--
2.43.0
next prev parent reply other threads:[~2025-02-09 20:24 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-09 20:23 [PATCH 0/3] arm: mvebu: add solidrun cn913x based boards Josua Mayer
2025-02-09 20:23 ` Josua Mayer [this message]
2025-02-27 10:13 ` [PATCH 1/3] u-boot: drivers: marvell: rtc: adding rtc driver Stefan Roese
2025-02-09 20:23 ` [PATCH 2/3] mvebu: armada-8k: set fdtfile env from DEFAULT_FDT_FILE Josua Mayer
2025-02-27 10:39 ` Stefan Roese
2025-02-09 20:23 ` [PATCH 3/3] board: solidrun: add cn9130 based boards Josua Mayer
2025-02-27 10:42 ` Stefan Roese
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250209-cn9130-board-v1-1-b94ab83e141b@solid-run.com \
--to=josua@solid-run.com \
--cc=alexl@marvell.com \
--cc=kostap@marvell.com \
--cc=sr@denx.de \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.