From: Jingbao Qiu <qiujingbao.dlmu@gmail.com>
To: a.zummo@towertech.it, alexandre.belloni@bootlin.com,
krzysztof.kozlowski+dt@linaro.org, chao.wei@sophgo.com,
unicorn_wang@outlook.com, conor+dt@kernel.org,
robh+dt@kernel.org, conor@kernel.org, paul.walmsley@sifive.com,
palmer@dabbelt.com, aou@eecs.berkeley.edu
Cc: linux-rtc@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
Jingbao Qiu <qiujingbao.dlmu@gmail.com>
Subject: [PATCH 2/3] rtc: add rtc controller support for Sophgo CV1800B SoC
Date: Tue, 21 Nov 2023 17:46:41 +0800 [thread overview]
Message-ID: <20231121094642.2973795-3-qiujingbao.dlmu@gmail.com> (raw)
In-Reply-To: <20231121094642.2973795-1-qiujingbao.dlmu@gmail.com>
Implement the RTC driver for CV1800B, which able to provide time and
alarm functionality.
Signed-off-by: Jingbao Qiu <qiujingbao.dlmu@gmail.com>
---
drivers/rtc/Kconfig | 10 ++
drivers/rtc/Makefile | 1 +
drivers/rtc/rtc-cv1800b.c | 293 ++++++++++++++++++++++++++++++++++++++
3 files changed, 304 insertions(+)
create mode 100644 drivers/rtc/rtc-cv1800b.c
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 3814e0845e77..2089cceea38c 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1103,6 +1103,16 @@ config RTC_DRV_DS2404
This driver can also be built as a module. If so, the module
will be called rtc-ds2404.
+config RTC_DRV_CV1800B
+ tristate "Sophgo CV1800B RTC"
+ depends on ARCH_SOPHGO || COMPILE_TEST
+ help
+ If you say yes here you will get support for the
+ RTC of the Sophgo CV1800B SOC.
+
+ This depend on ARCH_SOPHGO and COMPILE_TEST. Please
+ first config that.
+
config RTC_DRV_DA9052
tristate "Dialog DA9052/DA9053 RTC"
depends on PMIC_DA9052
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 7b03c3abfd78..3717d7ec8a4e 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_RTC_DRV_CADENCE) += rtc-cadence.o
obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
obj-$(CONFIG_RTC_DRV_CPCAP) += rtc-cpcap.o
obj-$(CONFIG_RTC_DRV_CROS_EC) += rtc-cros-ec.o
+obj-$(CONFIG_RTC_DRV_CV1800B) += rtc-cv1800b.o
obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o
obj-$(CONFIG_RTC_DRV_DA9055) += rtc-da9055.o
obj-$(CONFIG_RTC_DRV_DA9063) += rtc-da9063.o
diff --git a/drivers/rtc/rtc-cv1800b.c b/drivers/rtc/rtc-cv1800b.c
new file mode 100644
index 000000000000..d56132de30bb
--- /dev/null
+++ b/drivers/rtc/rtc-cv1800b.c
@@ -0,0 +1,293 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * rtc-cv1800b.c: RTC driver for Sophgo CV1800B RTC
+ *
+ * Author: Jingbao Qiu <qiujingbao.dlmu@gmail.com>
+ */
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#define RTC_ANA_CALIB 0x000
+#define RTC_SEC_PULSE_GEN 0x004
+#define RTC_ALARM_TIME 0x008
+#define RTC_ALARM_ENABLE 0x00c
+#define RTC_SET_SEC_CNTR_VALUE 0x010
+#define RTC_SET_SEC_CNTR_TRIG 0x014
+#define RTC_SEC_CNTR_VALUE 0x018
+#define RTC_INFO0 0x01c
+#define RTC_INFO1 0x020
+#define RTC_INFO2 0x024
+#define RTC_INFO3 0x028
+#define RTC_NOPOR_INFO0 0x02c
+#define RTC_NOPOR_INFO1 0x030
+#define RTC_NOPOR_INFO2 0x034
+#define RTC_NOPOR_INFO3 0x038
+#define RTC_DB_PWR_VBAT_DET 0x040
+#define RTC_DB_BUTTON1 0x048
+#define RTC_DB_PWR_ON 0x04c
+#define RTC_7SEC_RESET 0x050
+#define RTC_THM_SHDN_AUTO_REBOOT 0x064
+#define RTC_POR_DB_MAGIC_KEY 0x068
+#define RTC_DB_SEL_PWR 0x06c
+#define RTC_UP_SEQ0 0x070
+#define RTC_UP_SEQ1 0x074
+#define RTC_UP_SEQ2 0x078
+#define RTC_UP_SEQ3 0x07c
+#define RTC_UP_IF_EN 0x080
+#define RTC_UP_RSTN 0x084
+#define RTC_UP_MAX 0x088
+#define RTC_DN_SEQ0 0x090
+#define RTC_DN_SEQ1 0x094
+#define RTC_DN_SEQ2 0x098
+#define RTC_DN_SEQ3 0x09c
+#define RTC_DN_IF_EN 0x0a0
+#define RTC_DN_RSTN 0x0a4
+#define RTC_DN_MAX 0x0a8
+#define RTC_PWR_CYC_MAX 0x0b0
+#define RTC_WARM_RST_MAX 0x0b4
+#define RTC_EN_7SEC_RST 0x0b8
+#define RTC_EN_PWR_WAKEUP 0x0bc
+#define RTC_EN_SHDN_REQ 0x0c0
+#define RTC_EN_THM_SHDN 0x0c4
+#define RTC_EN_PWR_CYC_REQ 0x0c8
+#define RTC_EN_WARM_RST_REQ 0x0cc
+#define RTC_EN_PWR_VBAT_DET 0x0d0
+#define FSM_STATE 0x0d4
+#define RTC_EN_WDG_RST_REQ 0x0e0
+#define RTC_EN_SUSPEND_REQ 0x0e4
+#define RTC_DB_REQ_WDG_RST 0x0e8
+#define RTC_DB_REQ_SUSPEND 0x0ec
+#define RTC_PG_REG 0x0f0
+#define RTC_ST_ON_REASON 0x0f8
+#define RTC_ST_OFF_REASON 0x0fc
+#define RTC_EN_WAKEUP_REQ 0x120
+#define RTC_PWR_WAKEUP_POLARITY 0x128
+#define RTC_DB_SEL_REQ 0x130
+#define RTC_PWR_DET_SEL 0x140
+
+#define REG_DISABLE_FUN 0x00UL
+#define REG_ENABLE_FUN BIT(0)
+#define ACTIVATE_RTC_POR_DB_MAGIC_KEY 0x5af0
+#define INIT_LOAD_TIME 0xff
+
+struct cv1800b_rtc_priv {
+ struct rtc_device *rtc_dev;
+ void __iomem *core_map;
+ struct clk *clk;
+ int irq;
+};
+
+static int cv1800b_rtc_alarm_irq_enable(struct device *dev,
+ unsigned int enabled)
+{
+ struct cv1800b_rtc_priv *data = dev_get_drvdata(dev);
+
+ if (enabled)
+ writel_relaxed(REG_ENABLE_FUN, data->core_map + RTC_ALARM_ENABLE);
+ else
+ writel_relaxed(REG_DISABLE_FUN,
+ data->core_map + RTC_ALARM_ENABLE);
+
+ return 0;
+}
+
+static int cv1800b_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct cv1800b_rtc_priv *data = dev_get_drvdata(dev);
+ unsigned long time = rtc_tm_to_time64(&alrm->time);
+
+ writel_relaxed(time, data->core_map + RTC_ALARM_TIME);
+
+ cv1800b_rtc_alarm_irq_enable(dev, 1);
+
+ return 0;
+}
+
+static int cv1800b_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ u32 alrm_time, now_time;
+ struct cv1800b_rtc_priv *data = dev_get_drvdata(dev);
+
+ alrm_time = readl(data->core_map + RTC_ALARM_TIME);
+ now_time = readl(data->core_map + RTC_SEC_CNTR_VALUE);
+ rtc_time64_to_tm(alrm_time, &alrm->time);
+ alrm->pending = now_time > alrm_time ? 1 : 0;
+ alrm->enabled = readl(data->core_map + RTC_ALARM_ENABLE);
+
+ return 0;
+}
+
+static int cv1800b_rtc_softinit(struct cv1800b_rtc_priv *dev)
+{
+ u32 timeout = 20;
+
+ writel(ACTIVATE_RTC_POR_DB_MAGIC_KEY,
+ dev->core_map + RTC_POR_DB_MAGIC_KEY);
+ writel(INIT_LOAD_TIME, dev->core_map + RTC_SET_SEC_CNTR_VALUE);
+ writel(REG_DISABLE_FUN, dev->core_map + RTC_SET_SEC_CNTR_TRIG);
+
+ while (readl(dev->core_map + RTC_SEC_CNTR_VALUE) == INIT_LOAD_TIME
+ && timeout--)
+ udelay(5);
+
+ if (!timeout)
+ return -1;
+ return 0;
+}
+
+static int cv1800b_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct cv1800b_rtc_priv *data = dev_get_drvdata(dev);
+ u32 time = 0;
+
+ if (!data)
+ return -1;
+
+ time = readl_relaxed(data->core_map + RTC_SEC_CNTR_VALUE);
+ rtc_time64_to_tm(time, tm);
+
+ return 0;
+}
+
+static int cv1800b_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned long time = rtc_tm_to_time64(tm);
+ struct cv1800b_rtc_priv *data = dev_get_drvdata(dev);
+
+ if (!data)
+ return -1;
+
+ writel(time, data->core_map + RTC_SET_SEC_CNTR_VALUE);
+ writel(REG_ENABLE_FUN, data->core_map + RTC_SET_SEC_CNTR_TRIG);
+
+ return 0;
+}
+
+static irqreturn_t cv1800b_rtc_irq_handler(int irq, void *dev_id)
+{
+ struct device *dev = dev_id;
+ struct cv1800b_rtc_priv *data = dev_get_drvdata(dev);
+
+ if (!data)
+ return -1;
+ writel(REG_DISABLE_FUN, data->core_map + RTC_ALARM_ENABLE);
+
+ return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops cv800b_rtc_ops = {
+ .read_time = cv1800b_rtc_read_time,
+ .set_time = cv1800b_rtc_set_time,
+ .read_alarm = cv1800b_rtc_read_alarm,
+ .set_alarm = cv1800b_rtc_set_alarm,
+ .alarm_irq_enable = cv1800b_rtc_alarm_irq_enable,
+};
+
+static int cv1800b_rtc_probe(struct platform_device *pdev)
+{
+ struct cv1800b_rtc_priv *rtc;
+ struct resource *res;
+ int ret;
+
+ rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENODEV;
+ goto err;
+ }
+
+ rtc->core_map = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(rtc->core_map)) {
+ ret = PTR_ERR(rtc->core_map);
+ goto err;
+ }
+
+ rtc->irq = platform_get_irq(pdev, 0);
+ platform_set_drvdata(pdev, rtc);
+ if (rtc->irq < 0) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret =
+ devm_request_irq(&pdev->dev, rtc->irq, cv1800b_rtc_irq_handler,
+ IRQF_SHARED, "rtc alarm", &pdev->dev);
+ if (ret)
+ goto err;
+
+ rtc->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(rtc->clk)) {
+ dev_err(&pdev->dev, "no clock");
+ ret = PTR_ERR(rtc->clk);
+ goto err;
+ }
+ ret = clk_prepare_enable(rtc->clk);
+ if (ret)
+ goto err;
+ ret = cv1800b_rtc_softinit(rtc);
+ if (ret)
+ goto err;
+ cv1800b_rtc_alarm_irq_enable(&pdev->dev, 1);
+ rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(rtc->rtc_dev)) {
+ ret = PTR_ERR(rtc->rtc_dev);
+ goto err;
+ }
+ rtc->rtc_dev->range_max = U32_MAX;
+ rtc->rtc_dev->ops = &cv800b_rtc_ops;
+
+ return rtc_register_device(rtc->rtc_dev);
+err:
+ return dev_err_probe(&pdev->dev, ret, "Failed to init cv1800b rtc\n");
+}
+
+static int __maybe_unused cv1800b_rtc_suspend_noirq(struct device *dev)
+{
+ struct cv1800b_rtc_priv *data = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(data->clk);
+
+ return 0;
+}
+
+static int __maybe_unused cv1800b_rtc_resume_noirq(struct device *dev)
+{
+ struct cv1800b_rtc_priv *data = dev_get_drvdata(dev);
+
+ clk_prepare_enable(data->clk);
+
+ return 0;
+}
+
+static const struct dev_pm_ops cv1800b_rtc_pm_ops = {
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(cv1800b_rtc_suspend_noirq,
+ cv1800b_rtc_resume_noirq)
+};
+
+static const struct of_device_id cv1800b_dt_ids[] = {
+ { .compatible = "sophgo,cv800b-rtc" },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, cv1800b_dt_ids);
+
+static struct platform_driver cv1800b_rtc_driver = {
+ .driver = {
+ .name = "sophgo-cv800b-rtc",
+ .pm = &cv1800b_rtc_pm_ops,
+ .of_match_table = cv1800b_dt_ids,
+ },
+ .probe = cv1800b_rtc_probe,
+};
+
+module_platform_driver(cv1800b_rtc_driver);
+MODULE_AUTHOR("Jingbao Qiu");
+MODULE_DESCRIPTION("Sophgo CV1800B RTC Driver");
+MODULE_LICENSE("GPL");
--
2.25.1
next prev parent reply other threads:[~2023-11-21 9:47 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-21 9:46 [PATCH 0/3] riscv: sophgo: add rtc support for CV1800B Jingbao Qiu
2023-11-21 9:46 ` [PATCH 1/3] dt-bindings: rtc: add binding for Sophgo CV1800B rtc controller Jingbao Qiu
2023-11-21 9:57 ` Krzysztof Kozlowski
2023-11-28 13:20 ` jingbao qiu
2023-11-21 10:37 ` Rob Herring
2023-11-21 9:46 ` Jingbao Qiu [this message]
2023-11-21 10:01 ` [PATCH 2/3] rtc: add rtc controller support for Sophgo CV1800B SoC Krzysztof Kozlowski
2023-11-28 13:22 ` jingbao qiu
2023-11-28 13:59 ` Krzysztof Kozlowski
2023-11-28 14:34 ` jingbao qiu
2023-11-28 23:01 ` Alexandre Belloni
2023-11-21 17:58 ` kernel test robot
2023-11-21 22:52 ` kernel test robot
2023-11-21 9:46 ` [PATCH 3/3] riscv: dts: sophgo: add rtc dt node for CV1800B Jingbao Qiu
2023-11-21 10:00 ` Krzysztof Kozlowski
2023-11-28 13:23 ` jingbao qiu
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=20231121094642.2973795-3-qiujingbao.dlmu@gmail.com \
--to=qiujingbao.dlmu@gmail.com \
--cc=a.zummo@towertech.it \
--cc=alexandre.belloni@bootlin.com \
--cc=aou@eecs.berkeley.edu \
--cc=chao.wei@sophgo.com \
--cc=conor+dt@kernel.org \
--cc=conor@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rtc@vger.kernel.org \
--cc=palmer@dabbelt.com \
--cc=paul.walmsley@sifive.com \
--cc=robh+dt@kernel.org \
--cc=unicorn_wang@outlook.com \
/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.