linux-rtc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v8 0/2] riscv: rtc: sophgo: add rtc support for CV1800
@ 2024-02-04  4:41 Jingbao Qiu
  2024-02-04  4:41 ` [PATCH v8 1/2] dt-bindings: rtc: sophgo: add RTC support for Sophgo CV1800 series SoC Jingbao Qiu
  2024-02-04  4:41 ` [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC Jingbao Qiu
  0 siblings, 2 replies; 12+ messages in thread
From: Jingbao Qiu @ 2024-02-04  4:41 UTC (permalink / raw)
  To: alexandre.belloni, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	paul.walmsley, palmer, aou
  Cc: linux-rtc, devicetree, linux-kernel, dlan, inochiama, Jingbao Qiu

Real Time Clock (RTC) is an independently powered module
within the chip, which includes a 32KHz oscillator and
a Power On Reset/POR submodule. It can be used for time
display and timed alarm generation.

Power On Reset/POR submodule only using register resources
so it should be empty. The 32KHz oscillator only provides
pulses for RTC in hardware.

Changes since v7:
- pass checkpatch.pl --strict
- using u32 replace uint32
- using devm_kzalloc(*) replace
  devm_kzalloc(sizeof())
- sort header files alphabetically
- delete unnecessary header files
- fix wrap error
- drop dependent description
- using hardware automatic calibration replace
  software calibration. see documentation 197 page

v7: https://lore.kernel.org/all/20240122080500.2621-1-qiujingbao.dlmu@gmail.com/
documentation: https://github.com/milkv-duo/duo-files/blob/main/duo/datasheet/CV1800B-CV1801B-Preliminary-Datasheet-full-en.pdf

Changes since v6:
- completely delete POR dt node
- remove syscon tag
- use devm_regmap_init_mmio() replace
  syscon_node_to_regmap

v6: https://lore.kernel.org/all/20240115160600.5444-1-qiujingbao.dlmu@gmail.com/

Changes since v5:
- remove unnecessary lock
- fix cv1800_rtc_alarm_irq_enable()
- remove duplicate checks
- using alrm->enabled instead of unconditionally
  enabling
- remove disable alarms on probe
- using rtc_update_irq() replace mess of alarm
- remove leak clk
- useing devm_rtc_allocate_device() and
  devm_rtc_register_device() instead old way
- add judgment for rtc_enable_sec_counter()
- add POR nodes in DTS. This POR device shares
  the register region with the RTC device

v5: https://lore.kernel.org/all/20240108072253.30183-1-qiujingbao.dlmu@gmail.com/

Changes since v4:
- remove POR dt-bindings because it empty
- remove MFD dt-bindings because SoC does
  not have MFDs
- add syscon attribute to share registers
  with POR

v4: https://lore.kernel.org/all/20231229090643.116575-1-qiujingbao.dlmu@gmail.com/

Changes since v3:
- temporarily not submitting RTC driver code
  waiting for communication with IC designer
- add MFD dt-bindings
- add POR dt-bindings

v3: https://lore.kernel.org/all/20231226100431.331616-1-qiujingbao.dlmu@gmail.com/

Changes since v2:
- add mfd support for CV1800
- add rtc to mfd
- using regmap replace iomap
- merge register address in dts

v2: https://lore.kernel.org/lkml/20231217110952.78784-1-qiujingbao.dlmu@gmail.com/

Changes since v1
- fix duplicate names in subject
- using RTC replace RTC controller
- improve the properties of dt-bindings
- using `unevaluatedProperties` replace `additionalProperties`
- dt-bindings passed the test
- using `devm_platform_ioremap_resource()` replace
  `platform_get_resource()` and `devm_ioremap_resource()`
- fix random order of the code
- fix wrong wrapping of the `devm_request_irq()` and map the flag with dts
- using devm_clk_get_enabled replace `devm_clk_get()` and
  `clk_prepare_enable()`
- fix return style
- add rtc clock calibration function
- use spinlock when write register on read/set time

v1: https://lore.kernel.org/lkml/20231121094642.2973795-1-qiujingbao.dlmu@gmail.com/

Jingbao Qiu (2):
  dt-bindings: rtc: sophgo: add RTC support for Sophgo CV1800 series SoC
  rtc: sophgo: add rtc support for Sophgo CV1800 SoC

 .../bindings/rtc/sophgo,cv1800-rtc.yaml       |  53 ++++
 drivers/rtc/Kconfig                           |  10 +
 drivers/rtc/Makefile                          |   1 +
 drivers/rtc/rtc-cv1800.c                      | 244 ++++++++++++++++++
 4 files changed, 308 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/rtc/sophgo,cv1800-rtc.yaml
 create mode 100644 drivers/rtc/rtc-cv1800.c


base-commit: 14688f1a91e1f37bc6bf50ff5241e857f24338e0
-- 
2.25.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v8 1/2] dt-bindings: rtc: sophgo: add RTC support for Sophgo CV1800 series SoC
  2024-02-04  4:41 [PATCH v8 0/2] riscv: rtc: sophgo: add rtc support for CV1800 Jingbao Qiu
@ 2024-02-04  4:41 ` Jingbao Qiu
  2024-02-04  4:41 ` [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC Jingbao Qiu
  1 sibling, 0 replies; 12+ messages in thread
From: Jingbao Qiu @ 2024-02-04  4:41 UTC (permalink / raw)
  To: alexandre.belloni, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	paul.walmsley, palmer, aou
  Cc: linux-rtc, devicetree, linux-kernel, dlan, inochiama,
	Jingbao Qiu, Krzysztof Kozlowski

Add RTC devicetree binding for Sophgo CV1800 SoC.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Jingbao Qiu <qiujingbao.dlmu@gmail.com>
---
 .../bindings/rtc/sophgo,cv1800-rtc.yaml       | 53 +++++++++++++++++++
 1 file changed, 53 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/rtc/sophgo,cv1800-rtc.yaml

diff --git a/Documentation/devicetree/bindings/rtc/sophgo,cv1800-rtc.yaml b/Documentation/devicetree/bindings/rtc/sophgo,cv1800-rtc.yaml
new file mode 100644
index 000000000000..b36b51a69166
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/sophgo,cv1800-rtc.yaml
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/sophgo,cv1800-rtc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Real Time Clock of the Sophgo CV1800 SoC
+
+description:
+  Real Time Clock (RTC) is an independently powered module
+  within the chip, which includes a 32KHz oscillator and a
+  Power On Reset/POR submodule. It can be used for time display
+  and timed alarm generation. In addition, the hardware state
+  machine provides triggering and timing control for chip
+  power on, off, and reset.
+
+maintainers:
+  - Jingbao Qiu <qiujingbao.dlmu@gmail.com>
+
+allOf:
+  - $ref: rtc.yaml#
+
+properties:
+  compatible:
+    const: sophgo,cv1800-rtc
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    rtc@5025000 {
+        compatible = "sophgo,cv1800-rtc";
+        reg = <0x5025000 0x2000>;
+        interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&osc>;
+    };
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC
  2024-02-04  4:41 [PATCH v8 0/2] riscv: rtc: sophgo: add rtc support for CV1800 Jingbao Qiu
  2024-02-04  4:41 ` [PATCH v8 1/2] dt-bindings: rtc: sophgo: add RTC support for Sophgo CV1800 series SoC Jingbao Qiu
@ 2024-02-04  4:41 ` Jingbao Qiu
  2024-03-05 10:25   ` Jingbao Qiu
                     ` (2 more replies)
  1 sibling, 3 replies; 12+ messages in thread
From: Jingbao Qiu @ 2024-02-04  4:41 UTC (permalink / raw)
  To: alexandre.belloni, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	paul.walmsley, palmer, aou
  Cc: linux-rtc, devicetree, linux-kernel, dlan, inochiama, Jingbao Qiu

Implement the RTC driver for CV1800, which able to provide time alarm.

Signed-off-by: Jingbao Qiu <qiujingbao.dlmu@gmail.com>
---
 drivers/rtc/Kconfig      |  10 ++
 drivers/rtc/Makefile     |   1 +
 drivers/rtc/rtc-cv1800.c | 244 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 255 insertions(+)
 create mode 100644 drivers/rtc/rtc-cv1800.c

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index e37a4341f442..3c6ed45a3b03 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1128,6 +1128,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_CV1800
+	tristate "Sophgo CV1800 RTC"
+	depends on ARCH_SOPHGO || COMPILE_TEST
+	help
+	  If you say yes here you get support the RTC driver
+	  for Sophgo CV1800 chip.
+
+	  This driver can also be built as a module.If so, the
+	  module will be called rtc-cv1800.
+
 config RTC_DRV_DA9052
 	tristate "Dialog DA9052/DA9053 RTC"
 	depends on PMIC_DA9052
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 6efff381c484..4efdd2d1e963 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_CV1800)	+= rtc-cv1800.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-cv1800.c b/drivers/rtc/rtc-cv1800.c
new file mode 100644
index 000000000000..60a7192659f5
--- /dev/null
+++ b/drivers/rtc/rtc-cv1800.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * rtc-cv1800.c: RTC driver for Sophgo cv1800 RTC
+ *
+ * Author: Jingbao Qiu <qiujingbao.dlmu@gmail.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+
+#define CTRL                   0x08
+#define ANA_CALIB              0x1000
+#define SEC_PULSE_GEN          0x1004
+#define ALARM_TIME             0x1008
+#define ALARM_ENABLE           0x100C
+#define SET_SEC_CNTR_VAL       0x1010
+#define SET_SEC_CNTR_TRIG      0x1014
+#define SEC_CNTR_VAL           0x1018
+#define APB_RDATA_SEL          0x103C
+#define POR_DB_MAGIC_KEY       0x1068
+#define EN_PWR_WAKEUP          0x10BC
+
+/*
+ * When in VDDBKUP domain, this MACRO register
+ * does not power down
+ */
+#define MACRO_DA_CLEAR_ALL     0x1480
+#define MACRO_DA_SOC_READY     0x148C
+#define MACRO_RO_T             0x14A8
+#define MACRO_RG_SET_T         0x1498
+
+#define CTRL_MODE_MASK         BIT(10)
+#define CTRL_MODE_OSC32K       0x00UL
+#define CTRL_MODE_XTAL32K      BIT(0)
+#define REG_ENABLE_FUN         BIT(0)
+#define REG_DISABLE_FUN        0x00UL
+#define ALARM_ENABLE_MASK      BIT(0)
+#define SET_SEC_CNTR_VAL_INIT  (BIT(28) || BIT(29))
+#define SEC_PULSE_SEL_INNER    BIT(31)
+#define SEC_PULSE_GEN_SEL_MASK GENMASK(30, 0)
+#define CALIB_SEL_FTUNE_MASK   GENMASK(30, 0)
+#define CALIB_SEL_FTUNE_INNER  0x00UL
+
+struct cv1800_rtc_priv {
+	struct rtc_device *rtc_dev;
+	struct regmap *rtc_map;
+	struct clk *clk;
+	int irq;
+};
+
+static const struct regmap_config cv1800_rtc_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+};
+
+static int cv1800_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+	struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
+
+	regmap_write(info->rtc_map, ALARM_ENABLE, enabled);
+
+	return 0;
+}
+
+static int cv1800_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
+	unsigned long alarm_time;
+
+	alarm_time = rtc_tm_to_time64(&alrm->time);
+
+	cv1800_rtc_alarm_irq_enable(dev, REG_DISABLE_FUN);
+
+	regmap_write(info->rtc_map, ALARM_TIME, alarm_time);
+
+	cv1800_rtc_alarm_irq_enable(dev, alrm->enabled);
+
+	return 0;
+}
+
+static int cv1800_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
+	u32 enabled;
+	u32 time;
+
+	regmap_read(info->rtc_map, ALARM_ENABLE, &enabled);
+
+	alarm->enabled = enabled & ALARM_ENABLE_MASK;
+
+	regmap_read(info->rtc_map, ALARM_TIME, &time);
+
+	rtc_time64_to_tm(time, &alarm->time);
+
+	return 0;
+}
+
+static void rtc_enable_sec_counter(struct cv1800_rtc_priv *info)
+{
+	u32 sec_ro_t;
+	u32 sec;
+
+	/* select inner sec pulse */
+	regmap_update_bits(info->rtc_map, SEC_PULSE_GEN,
+			   (u32)(~SEC_PULSE_GEN_SEL_MASK),
+			   (u32)(~SEC_PULSE_SEL_INNER));
+
+	regmap_update_bits(info->rtc_map, ANA_CALIB,
+			   (u32)(~CALIB_SEL_FTUNE_MASK),
+			   CALIB_SEL_FTUNE_INNER);
+
+	sec = SET_SEC_CNTR_VAL_INIT;
+
+	/* load from MACRO register */
+	regmap_read(info->rtc_map, MACRO_RO_T, &sec_ro_t);
+	if (sec_ro_t > (SET_SEC_CNTR_VAL_INIT))
+		sec = sec_ro_t;
+
+	regmap_write(info->rtc_map, SET_SEC_CNTR_VAL, sec);
+	regmap_write(info->rtc_map, SET_SEC_CNTR_TRIG, REG_ENABLE_FUN);
+}
+
+static int cv1800_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
+	u32 sec;
+
+	regmap_read(info->rtc_map, SEC_CNTR_VAL, &sec);
+
+	rtc_time64_to_tm(sec, tm);
+
+	return 0;
+}
+
+static int cv1800_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
+	unsigned long sec;
+
+	sec = rtc_tm_to_time64(tm);
+
+	regmap_write(info->rtc_map, SET_SEC_CNTR_VAL, sec);
+	regmap_write(info->rtc_map, SET_SEC_CNTR_TRIG, REG_ENABLE_FUN);
+
+	regmap_write(info->rtc_map, MACRO_RG_SET_T, sec);
+
+	return 0;
+}
+
+static irqreturn_t cv1800_rtc_irq_handler(int irq, void *dev_id)
+{
+	struct rtc_device *rtc = dev_id;
+
+	rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
+
+	return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops cv1800_rtc_ops = {
+	.read_time = cv1800_rtc_read_time,
+	.set_time = cv1800_rtc_set_time,
+	.read_alarm = cv1800_rtc_read_alarm,
+	.set_alarm = cv1800_rtc_set_alarm,
+	.alarm_irq_enable = cv1800_rtc_alarm_irq_enable,
+};
+
+static int cv1800_rtc_probe(struct platform_device *pdev)
+{
+	struct cv1800_rtc_priv *rtc;
+	u32 ctrl_val;
+	void __iomem *base;
+	int ret;
+
+	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+	if (!rtc)
+		return -ENOMEM;
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	rtc->rtc_map = devm_regmap_init_mmio(&pdev->dev, base,
+					     &cv1800_rtc_regmap_config);
+	if (IS_ERR(rtc->rtc_map))
+		return PTR_ERR(rtc->rtc_map);
+
+	rtc->irq = platform_get_irq(pdev, 0);
+	if (rtc->irq < 0)
+		return rtc->irq;
+
+	ret = devm_request_irq(&pdev->dev, rtc->irq, cv1800_rtc_irq_handler,
+			       IRQF_TRIGGER_HIGH, "alarm", &pdev->dev);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret,
+				     "cannot register interrupt handler\n");
+
+	rtc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
+	if (IS_ERR(rtc->clk))
+		return dev_err_probe(&pdev->dev, PTR_ERR(rtc->clk),
+				     "clk not found\n");
+
+	rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
+	if (IS_ERR(rtc->rtc_dev))
+		return PTR_ERR(rtc->rtc_dev);
+
+	platform_set_drvdata(pdev, rtc);
+
+	rtc->rtc_dev->ops = &cv1800_rtc_ops;
+	rtc->rtc_dev->range_max = U32_MAX;
+
+	regmap_read(rtc->rtc_map, CTRL, &ctrl_val);
+	ctrl_val &= CTRL_MODE_MASK;
+
+	if (ctrl_val == CTRL_MODE_OSC32K)
+		rtc_enable_sec_counter(rtc);
+
+	return devm_rtc_register_device(rtc->rtc_dev);
+}
+
+static const struct of_device_id cv1800_dt_ids[] = {
+	{ .compatible = "sophgo,cv1800-rtc" },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, cv1800_dt_ids);
+
+static struct platform_driver cv1800_rtc_driver = {
+	.driver = {
+		.name = "sophgo-cv1800-rtc",
+		.of_match_table = cv1800_dt_ids,
+	},
+	.probe = cv1800_rtc_probe,
+};
+
+module_platform_driver(cv1800_rtc_driver);
+MODULE_AUTHOR("Jingbao Qiu");
+MODULE_DESCRIPTION("Sophgo cv1800 RTC Driver");
+MODULE_LICENSE("GPL");
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC
  2024-02-04  4:41 ` [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC Jingbao Qiu
@ 2024-03-05 10:25   ` Jingbao Qiu
  2024-04-17 21:23   ` Alexandre Belloni
  2024-05-01  2:19   ` Inochi Amaoto
  2 siblings, 0 replies; 12+ messages in thread
From: Jingbao Qiu @ 2024-03-05 10:25 UTC (permalink / raw)
  To: alexandre.belloni, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	paul.walmsley, palmer, aou
  Cc: linux-rtc, devicetree, linux-kernel, dlan, inochiama

Hi Alexandre,

Gentle ping!

On Sun, Feb 4, 2024 at 12:41 PM Jingbao Qiu <qiujingbao.dlmu@gmail.com> wrote:
>
> Implement the RTC driver for CV1800, which able to provide time alarm.
>
> Signed-off-by: Jingbao Qiu <qiujingbao.dlmu@gmail.com>
> ---
>  drivers/rtc/Kconfig      |  10 ++
>  drivers/rtc/Makefile     |   1 +
>  drivers/rtc/rtc-cv1800.c | 244 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 255 insertions(+)
>  create mode 100644 drivers/rtc/rtc-cv1800.c
>
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index e37a4341f442..3c6ed45a3b03 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -1128,6 +1128,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_CV1800
> +       tristate "Sophgo CV1800 RTC"
> +       depends on ARCH_SOPHGO || COMPILE_TEST
> +       help
> +         If you say yes here you get support the RTC driver
> +         for Sophgo CV1800 chip.
> +
> +         This driver can also be built as a module.If so, the
> +         module will be called rtc-cv1800.
> +
>  config RTC_DRV_DA9052
>         tristate "Dialog DA9052/DA9053 RTC"
>         depends on PMIC_DA9052
> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
> index 6efff381c484..4efdd2d1e963 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_CV1800)   += rtc-cv1800.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-cv1800.c b/drivers/rtc/rtc-cv1800.c
> new file mode 100644
> index 000000000000..60a7192659f5
> --- /dev/null
> +++ b/drivers/rtc/rtc-cv1800.c
> @@ -0,0 +1,244 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * rtc-cv1800.c: RTC driver for Sophgo cv1800 RTC
> + *
> + * Author: Jingbao Qiu <qiujingbao.dlmu@gmail.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/irq.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/rtc.h>
> +
> +#define CTRL                   0x08
> +#define ANA_CALIB              0x1000
> +#define SEC_PULSE_GEN          0x1004
> +#define ALARM_TIME             0x1008
> +#define ALARM_ENABLE           0x100C
> +#define SET_SEC_CNTR_VAL       0x1010
> +#define SET_SEC_CNTR_TRIG      0x1014
> +#define SEC_CNTR_VAL           0x1018
> +#define APB_RDATA_SEL          0x103C
> +#define POR_DB_MAGIC_KEY       0x1068
> +#define EN_PWR_WAKEUP          0x10BC
> +
> +/*
> + * When in VDDBKUP domain, this MACRO register
> + * does not power down
> + */
> +#define MACRO_DA_CLEAR_ALL     0x1480
> +#define MACRO_DA_SOC_READY     0x148C
> +#define MACRO_RO_T             0x14A8
> +#define MACRO_RG_SET_T         0x1498
> +
> +#define CTRL_MODE_MASK         BIT(10)
> +#define CTRL_MODE_OSC32K       0x00UL
> +#define CTRL_MODE_XTAL32K      BIT(0)
> +#define REG_ENABLE_FUN         BIT(0)
> +#define REG_DISABLE_FUN        0x00UL
> +#define ALARM_ENABLE_MASK      BIT(0)
> +#define SET_SEC_CNTR_VAL_INIT  (BIT(28) || BIT(29))
> +#define SEC_PULSE_SEL_INNER    BIT(31)
> +#define SEC_PULSE_GEN_SEL_MASK GENMASK(30, 0)
> +#define CALIB_SEL_FTUNE_MASK   GENMASK(30, 0)
> +#define CALIB_SEL_FTUNE_INNER  0x00UL
> +
> +struct cv1800_rtc_priv {
> +       struct rtc_device *rtc_dev;
> +       struct regmap *rtc_map;
> +       struct clk *clk;
> +       int irq;
> +};
> +
> +static const struct regmap_config cv1800_rtc_regmap_config = {
> +       .reg_bits = 32,
> +       .val_bits = 32,
> +       .reg_stride = 4,
> +};
> +
> +static int cv1800_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
> +{
> +       struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> +
> +       regmap_write(info->rtc_map, ALARM_ENABLE, enabled);
> +
> +       return 0;
> +}
> +
> +static int cv1800_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> +       struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> +       unsigned long alarm_time;
> +
> +       alarm_time = rtc_tm_to_time64(&alrm->time);
> +
> +       cv1800_rtc_alarm_irq_enable(dev, REG_DISABLE_FUN);
> +
> +       regmap_write(info->rtc_map, ALARM_TIME, alarm_time);
> +
> +       cv1800_rtc_alarm_irq_enable(dev, alrm->enabled);
> +
> +       return 0;
> +}
> +
> +static int cv1800_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
> +{
> +       struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> +       u32 enabled;
> +       u32 time;
> +
> +       regmap_read(info->rtc_map, ALARM_ENABLE, &enabled);
> +
> +       alarm->enabled = enabled & ALARM_ENABLE_MASK;
> +
> +       regmap_read(info->rtc_map, ALARM_TIME, &time);
> +
> +       rtc_time64_to_tm(time, &alarm->time);
> +
> +       return 0;
> +}
> +
> +static void rtc_enable_sec_counter(struct cv1800_rtc_priv *info)
> +{
> +       u32 sec_ro_t;
> +       u32 sec;
> +
> +       /* select inner sec pulse */
> +       regmap_update_bits(info->rtc_map, SEC_PULSE_GEN,
> +                          (u32)(~SEC_PULSE_GEN_SEL_MASK),
> +                          (u32)(~SEC_PULSE_SEL_INNER));
> +
> +       regmap_update_bits(info->rtc_map, ANA_CALIB,
> +                          (u32)(~CALIB_SEL_FTUNE_MASK),
> +                          CALIB_SEL_FTUNE_INNER);
> +
> +       sec = SET_SEC_CNTR_VAL_INIT;
> +
> +       /* load from MACRO register */
> +       regmap_read(info->rtc_map, MACRO_RO_T, &sec_ro_t);
> +       if (sec_ro_t > (SET_SEC_CNTR_VAL_INIT))
> +               sec = sec_ro_t;
> +
> +       regmap_write(info->rtc_map, SET_SEC_CNTR_VAL, sec);
> +       regmap_write(info->rtc_map, SET_SEC_CNTR_TRIG, REG_ENABLE_FUN);
> +}
> +
> +static int cv1800_rtc_read_time(struct device *dev, struct rtc_time *tm)
> +{
> +       struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> +       u32 sec;
> +
> +       regmap_read(info->rtc_map, SEC_CNTR_VAL, &sec);
> +
> +       rtc_time64_to_tm(sec, tm);
> +
> +       return 0;
> +}
> +
> +static int cv1800_rtc_set_time(struct device *dev, struct rtc_time *tm)
> +{
> +       struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> +       unsigned long sec;
> +
> +       sec = rtc_tm_to_time64(tm);
> +
> +       regmap_write(info->rtc_map, SET_SEC_CNTR_VAL, sec);
> +       regmap_write(info->rtc_map, SET_SEC_CNTR_TRIG, REG_ENABLE_FUN);
> +
> +       regmap_write(info->rtc_map, MACRO_RG_SET_T, sec);
> +
> +       return 0;
> +}
> +
> +static irqreturn_t cv1800_rtc_irq_handler(int irq, void *dev_id)
> +{
> +       struct rtc_device *rtc = dev_id;
> +
> +       rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static const struct rtc_class_ops cv1800_rtc_ops = {
> +       .read_time = cv1800_rtc_read_time,
> +       .set_time = cv1800_rtc_set_time,
> +       .read_alarm = cv1800_rtc_read_alarm,
> +       .set_alarm = cv1800_rtc_set_alarm,
> +       .alarm_irq_enable = cv1800_rtc_alarm_irq_enable,
> +};
> +
> +static int cv1800_rtc_probe(struct platform_device *pdev)
> +{
> +       struct cv1800_rtc_priv *rtc;
> +       u32 ctrl_val;
> +       void __iomem *base;
> +       int ret;
> +
> +       rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
> +       if (!rtc)
> +               return -ENOMEM;
> +
> +       base = devm_platform_ioremap_resource(pdev, 0);
> +       if (IS_ERR(base))
> +               return PTR_ERR(base);
> +
> +       rtc->rtc_map = devm_regmap_init_mmio(&pdev->dev, base,
> +                                            &cv1800_rtc_regmap_config);
> +       if (IS_ERR(rtc->rtc_map))
> +               return PTR_ERR(rtc->rtc_map);
> +
> +       rtc->irq = platform_get_irq(pdev, 0);
> +       if (rtc->irq < 0)
> +               return rtc->irq;
> +
> +       ret = devm_request_irq(&pdev->dev, rtc->irq, cv1800_rtc_irq_handler,
> +                              IRQF_TRIGGER_HIGH, "alarm", &pdev->dev);
> +       if (ret)
> +               return dev_err_probe(&pdev->dev, ret,
> +                                    "cannot register interrupt handler\n");
> +
> +       rtc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
> +       if (IS_ERR(rtc->clk))
> +               return dev_err_probe(&pdev->dev, PTR_ERR(rtc->clk),
> +                                    "clk not found\n");
> +
> +       rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
> +       if (IS_ERR(rtc->rtc_dev))
> +               return PTR_ERR(rtc->rtc_dev);
> +
> +       platform_set_drvdata(pdev, rtc);
> +
> +       rtc->rtc_dev->ops = &cv1800_rtc_ops;
> +       rtc->rtc_dev->range_max = U32_MAX;
> +
> +       regmap_read(rtc->rtc_map, CTRL, &ctrl_val);
> +       ctrl_val &= CTRL_MODE_MASK;
> +
> +       if (ctrl_val == CTRL_MODE_OSC32K)
> +               rtc_enable_sec_counter(rtc);
> +
> +       return devm_rtc_register_device(rtc->rtc_dev);
> +}
> +
> +static const struct of_device_id cv1800_dt_ids[] = {
> +       { .compatible = "sophgo,cv1800-rtc" },
> +       { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, cv1800_dt_ids);
> +
> +static struct platform_driver cv1800_rtc_driver = {
> +       .driver = {
> +               .name = "sophgo-cv1800-rtc",
> +               .of_match_table = cv1800_dt_ids,
> +       },
> +       .probe = cv1800_rtc_probe,
> +};
> +
> +module_platform_driver(cv1800_rtc_driver);
> +MODULE_AUTHOR("Jingbao Qiu");
> +MODULE_DESCRIPTION("Sophgo cv1800 RTC Driver");
> +MODULE_LICENSE("GPL");
> --
> 2.25.1
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC
  2024-02-04  4:41 ` [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC Jingbao Qiu
  2024-03-05 10:25   ` Jingbao Qiu
@ 2024-04-17 21:23   ` Alexandre Belloni
  2024-04-24  7:35     ` Jingbao Qiu
  2024-05-01  2:19   ` Inochi Amaoto
  2 siblings, 1 reply; 12+ messages in thread
From: Alexandre Belloni @ 2024-04-17 21:23 UTC (permalink / raw)
  To: Jingbao Qiu
  Cc: robh+dt, krzysztof.kozlowski+dt, conor+dt, paul.walmsley, palmer,
	aou, linux-rtc, devicetree, linux-kernel, dlan, inochiama

Hello,

On 04/02/2024 12:41:43+0800, Jingbao Qiu wrote:
> +#define REG_ENABLE_FUN         BIT(0)
> +#define REG_DISABLE_FUN        0x00UL

I don't feel like these two macros make your code clearer, you should
probably simply use 0 and 1 in the proper locations.

> +static irqreturn_t cv1800_rtc_irq_handler(int irq, void *dev_id)
> +{
> +	struct rtc_device *rtc = dev_id;
> +
> +	rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);

I'm pretty sure this would result in a crash...

> +
> +	return IRQ_HANDLED;
> +}
> +
> +	ret = devm_request_irq(&pdev->dev, rtc->irq, cv1800_rtc_irq_handler,
> +			       IRQF_TRIGGER_HIGH, "alarm", &pdev->dev);

... you probably want to use rtc->rtc_dev here to fix this.

This also means that you have to request the irq late, else you are open
t a race condition anyway.

> +	if (ret)
> +		return dev_err_probe(&pdev->dev, ret,
> +				     "cannot register interrupt handler\n");
> +

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC
  2024-04-17 21:23   ` Alexandre Belloni
@ 2024-04-24  7:35     ` Jingbao Qiu
  0 siblings, 0 replies; 12+ messages in thread
From: Jingbao Qiu @ 2024-04-24  7:35 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: robh+dt, krzysztof.kozlowski+dt, conor+dt, paul.walmsley, palmer,
	aou, linux-rtc, devicetree, linux-kernel, dlan, inochiama

Hi, Alexandre

I'm glad to receive your reply.

> I don't feel like these two macros make your code clearer, you should
> probably simply use 0 and 1 in the proper locations.
>

I will use 0/1 replace this macros.

> > +static irqreturn_t cv1800_rtc_irq_handler(int irq, void *dev_id)
> > +{
> > +     struct rtc_device *rtc = dev_id;
> > +
> > +     rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
>
> I'm pretty sure this would result in a crash...

Yes, it did happen. Because I inserted an incorrect pointer.

>
> > +
> > +     return IRQ_HANDLED;
> > +}
> > +
> > +     ret = devm_request_irq(&pdev->dev, rtc->irq, cv1800_rtc_irq_handler,
> > +                            IRQF_TRIGGER_HIGH, "alarm", &pdev->dev);
>
> ... you probably want to use rtc->rtc_dev here to fix this.
>
> This also means that you have to request the irq late, else you are open
> t a race condition anyway.

I am very sorry about this bug.
I will use rtc->rtc_dev to fix it and request irq after
devm_rtc_allocate_device.

Best regards
Jingbao Qiu

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC
  2024-02-04  4:41 ` [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC Jingbao Qiu
  2024-03-05 10:25   ` Jingbao Qiu
  2024-04-17 21:23   ` Alexandre Belloni
@ 2024-05-01  2:19   ` Inochi Amaoto
  2024-05-01  5:03     ` Jingbao Qiu
  2 siblings, 1 reply; 12+ messages in thread
From: Inochi Amaoto @ 2024-05-01  2:19 UTC (permalink / raw)
  To: Jingbao Qiu, alexandre.belloni, robh+dt, krzysztof.kozlowski+dt,
	conor+dt, paul.walmsley, palmer, aou
  Cc: linux-rtc, devicetree, linux-kernel, dlan, inochiama

On Sun, Feb 04, 2024 at 12:41:43PM GMT, Jingbao Qiu wrote:
> Implement the RTC driver for CV1800, which able to provide time alarm.
> 
> Signed-off-by: Jingbao Qiu <qiujingbao.dlmu@gmail.com>
> ---
>  drivers/rtc/Kconfig      |  10 ++
>  drivers/rtc/Makefile     |   1 +
>  drivers/rtc/rtc-cv1800.c | 244 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 255 insertions(+)
>  create mode 100644 drivers/rtc/rtc-cv1800.c
> 
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index e37a4341f442..3c6ed45a3b03 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -1128,6 +1128,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_CV1800
> +	tristate "Sophgo CV1800 RTC"
> +	depends on ARCH_SOPHGO || COMPILE_TEST
> +	help
> +	  If you say yes here you get support the RTC driver
> +	  for Sophgo CV1800 chip.
> +
> +	  This driver can also be built as a module.If so, the
> +	  module will be called rtc-cv1800.
> +
>  config RTC_DRV_DA9052
>  	tristate "Dialog DA9052/DA9053 RTC"
>  	depends on PMIC_DA9052
> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
> index 6efff381c484..4efdd2d1e963 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_CV1800)	+= rtc-cv1800.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-cv1800.c b/drivers/rtc/rtc-cv1800.c
> new file mode 100644
> index 000000000000..60a7192659f5
> --- /dev/null
> +++ b/drivers/rtc/rtc-cv1800.c
> @@ -0,0 +1,244 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * rtc-cv1800.c: RTC driver for Sophgo cv1800 RTC
> + *
> + * Author: Jingbao Qiu <qiujingbao.dlmu@gmail.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/irq.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/rtc.h>
> +
> +#define CTRL                   0x08
> +#define ANA_CALIB              0x1000
> +#define SEC_PULSE_GEN          0x1004
> +#define ALARM_TIME             0x1008
> +#define ALARM_ENABLE           0x100C
> +#define SET_SEC_CNTR_VAL       0x1010
> +#define SET_SEC_CNTR_TRIG      0x1014
> +#define SEC_CNTR_VAL           0x1018
> +#define APB_RDATA_SEL          0x103C
> +#define POR_DB_MAGIC_KEY       0x1068
> +#define EN_PWR_WAKEUP          0x10BC
> +
> +/*
> + * When in VDDBKUP domain, this MACRO register
> + * does not power down
> + */
> +#define MACRO_DA_CLEAR_ALL     0x1480
> +#define MACRO_DA_SOC_READY     0x148C
> +#define MACRO_RO_T             0x14A8
> +#define MACRO_RG_SET_T         0x1498
> +
> +#define CTRL_MODE_MASK         BIT(10)
> +#define CTRL_MODE_OSC32K       0x00UL
> +#define CTRL_MODE_XTAL32K      BIT(0)
> +#define REG_ENABLE_FUN         BIT(0)
> +#define REG_DISABLE_FUN        0x00UL
> +#define ALARM_ENABLE_MASK      BIT(0)
> +#define SET_SEC_CNTR_VAL_INIT  (BIT(28) || BIT(29))
> +#define SEC_PULSE_SEL_INNER    BIT(31)
> +#define SEC_PULSE_GEN_SEL_MASK GENMASK(30, 0)
> +#define CALIB_SEL_FTUNE_MASK   GENMASK(30, 0)
> +#define CALIB_SEL_FTUNE_INNER  0x00UL
> +
> +struct cv1800_rtc_priv {
> +	struct rtc_device *rtc_dev;
> +	struct regmap *rtc_map;
> +	struct clk *clk;
> +	int irq;
> +};
> +
> +static const struct regmap_config cv1800_rtc_regmap_config = {
> +	.reg_bits = 32,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +};
> +
> +static int cv1800_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
> +{
> +	struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> +
> +	regmap_write(info->rtc_map, ALARM_ENABLE, enabled);
> +
> +	return 0;
> +}
> +
> +static int cv1800_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> +{
> +	struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> +	unsigned long alarm_time;
> +
> +	alarm_time = rtc_tm_to_time64(&alrm->time);
> +
> +	cv1800_rtc_alarm_irq_enable(dev, REG_DISABLE_FUN);
> +
> +	regmap_write(info->rtc_map, ALARM_TIME, alarm_time);
> +
> +	cv1800_rtc_alarm_irq_enable(dev, alrm->enabled);
> +
> +	return 0;
> +}
> +
> +static int cv1800_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
> +{
> +	struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> +	u32 enabled;
> +	u32 time;
> +
> +	regmap_read(info->rtc_map, ALARM_ENABLE, &enabled);
> +
> +	alarm->enabled = enabled & ALARM_ENABLE_MASK;
> +
> +	regmap_read(info->rtc_map, ALARM_TIME, &time);
> +
> +	rtc_time64_to_tm(time, &alarm->time);
> +
> +	return 0;
> +}
> +
> +static void rtc_enable_sec_counter(struct cv1800_rtc_priv *info)
> +{
> +	u32 sec_ro_t;
> +	u32 sec;
> +
> +	/* select inner sec pulse */
> +	regmap_update_bits(info->rtc_map, SEC_PULSE_GEN,
> +			   (u32)(~SEC_PULSE_GEN_SEL_MASK),
> +			   (u32)(~SEC_PULSE_SEL_INNER));
> +
> +	regmap_update_bits(info->rtc_map, ANA_CALIB,
> +			   (u32)(~CALIB_SEL_FTUNE_MASK),
> +			   CALIB_SEL_FTUNE_INNER);
> +
> +	sec = SET_SEC_CNTR_VAL_INIT;
> +
> +	/* load from MACRO register */
> +	regmap_read(info->rtc_map, MACRO_RO_T, &sec_ro_t);
> +	if (sec_ro_t > (SET_SEC_CNTR_VAL_INIT))
> +		sec = sec_ro_t;
> +
> +	regmap_write(info->rtc_map, SET_SEC_CNTR_VAL, sec);
> +	regmap_write(info->rtc_map, SET_SEC_CNTR_TRIG, REG_ENABLE_FUN);
> +}
> +
> +static int cv1800_rtc_read_time(struct device *dev, struct rtc_time *tm)
> +{
> +	struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> +	u32 sec;
> +
> +	regmap_read(info->rtc_map, SEC_CNTR_VAL, &sec);
> +
> +	rtc_time64_to_tm(sec, tm);
> +
> +	return 0;
> +}
> +
> +static int cv1800_rtc_set_time(struct device *dev, struct rtc_time *tm)
> +{
> +	struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> +	unsigned long sec;
> +
> +	sec = rtc_tm_to_time64(tm);
> +
> +	regmap_write(info->rtc_map, SET_SEC_CNTR_VAL, sec);
> +	regmap_write(info->rtc_map, SET_SEC_CNTR_TRIG, REG_ENABLE_FUN);
> +
> +	regmap_write(info->rtc_map, MACRO_RG_SET_T, sec);
> +
> +	return 0;
> +}
> +
> +static irqreturn_t cv1800_rtc_irq_handler(int irq, void *dev_id)
> +{
> +	struct rtc_device *rtc = dev_id;
> +
> +	rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static const struct rtc_class_ops cv1800_rtc_ops = {
> +	.read_time = cv1800_rtc_read_time,
> +	.set_time = cv1800_rtc_set_time,
> +	.read_alarm = cv1800_rtc_read_alarm,
> +	.set_alarm = cv1800_rtc_set_alarm,
> +	.alarm_irq_enable = cv1800_rtc_alarm_irq_enable,
> +};
> +
> +static int cv1800_rtc_probe(struct platform_device *pdev)
> +{
> +	struct cv1800_rtc_priv *rtc;
> +	u32 ctrl_val;
> +	void __iomem *base;
> +	int ret;
> +
> +	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
> +	if (!rtc)
> +		return -ENOMEM;
> +
> +	base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	rtc->rtc_map = devm_regmap_init_mmio(&pdev->dev, base,
> +					     &cv1800_rtc_regmap_config);
> +	if (IS_ERR(rtc->rtc_map))
> +		return PTR_ERR(rtc->rtc_map);
> +
> +	rtc->irq = platform_get_irq(pdev, 0);
> +	if (rtc->irq < 0)
> +		return rtc->irq;
> +
> +	ret = devm_request_irq(&pdev->dev, rtc->irq, cv1800_rtc_irq_handler,
> +			       IRQF_TRIGGER_HIGH, "alarm", &pdev->dev);
> +	if (ret)
> +		return dev_err_probe(&pdev->dev, ret,
> +				     "cannot register interrupt handler\n");
> +
> +	rtc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
> +	if (IS_ERR(rtc->clk))
> +		return dev_err_probe(&pdev->dev, PTR_ERR(rtc->clk),
> +				     "clk not found\n");
> +
> +	rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
> +	if (IS_ERR(rtc->rtc_dev))
> +		return PTR_ERR(rtc->rtc_dev);
> +
> +	platform_set_drvdata(pdev, rtc);
> +
> +	rtc->rtc_dev->ops = &cv1800_rtc_ops;
> +	rtc->rtc_dev->range_max = U32_MAX;
> +

> +	regmap_read(rtc->rtc_map, CTRL, &ctrl_val);
> +	ctrl_val &= CTRL_MODE_MASK;
> +
> +	if (ctrl_val == CTRL_MODE_OSC32K)
> +		rtc_enable_sec_counter(rtc);
> +

use (ctrl_val & CTRL_MODE_OSC32K).

Another thing is that I do not think is a good way to let the
rtc driver access RTC_CTRL area directly. You have already
know there is a 8051 device in the 0x05025000. It is necessary
to make some room for this device. Maybe you want to implement
them all in the rtc driver? If so, I do think it is a bad idea.

> +	return devm_rtc_register_device(rtc->rtc_dev);
> +}
> +
> +static const struct of_device_id cv1800_dt_ids[] = {
> +	{ .compatible = "sophgo,cv1800-rtc" },
> +	{ /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, cv1800_dt_ids);
> +
> +static struct platform_driver cv1800_rtc_driver = {
> +	.driver = {
> +		.name = "sophgo-cv1800-rtc",
> +		.of_match_table = cv1800_dt_ids,
> +	},
> +	.probe = cv1800_rtc_probe,
> +};
> +
> +module_platform_driver(cv1800_rtc_driver);
> +MODULE_AUTHOR("Jingbao Qiu");
> +MODULE_DESCRIPTION("Sophgo cv1800 RTC Driver");
> +MODULE_LICENSE("GPL");
> -- 
> 2.25.1
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC
  2024-05-01  2:19   ` Inochi Amaoto
@ 2024-05-01  5:03     ` Jingbao Qiu
  2024-05-01  7:43       ` Inochi Amaoto
  0 siblings, 1 reply; 12+ messages in thread
From: Jingbao Qiu @ 2024-05-01  5:03 UTC (permalink / raw)
  To: Inochi Amaoto
  Cc: alexandre.belloni, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	paul.walmsley, palmer, aou, linux-rtc, devicetree, linux-kernel,
	dlan

Hi, Inochi

On Wed, May 1, 2024 at 10:19 AM Inochi Amaoto <inochiama@outlook.com> wrote:
>
> On Sun, Feb 04, 2024 at 12:41:43PM GMT, Jingbao Qiu wrote:
> > Implement the RTC driver for CV1800, which able to provide time alarm.
> >
> > Signed-off-by: Jingbao Qiu <qiujingbao.dlmu@gmail.com>
> > ---
> >  drivers/rtc/Kconfig      |  10 ++
> >  drivers/rtc/Makefile     |   1 +
> >  drivers/rtc/rtc-cv1800.c | 244 +++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 255 insertions(+)
> >  create mode 100644 drivers/rtc/rtc-cv1800.c
> >
> > diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> > index e37a4341f442..3c6ed45a3b03 100644
> > --- a/drivers/rtc/Kconfig
> > +++ b/drivers/rtc/Kconfig
> > @@ -1128,6 +1128,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_CV1800
> > +     tristate "Sophgo CV1800 RTC"
> > +     depends on ARCH_SOPHGO || COMPILE_TEST
> > +     help
> > +       If you say yes here you get support the RTC driver
> > +       for Sophgo CV1800 chip.
> > +
> > +       This driver can also be built as a module.If so, the
> > +       module will be called rtc-cv1800.
> > +
> >  config RTC_DRV_DA9052
> >       tristate "Dialog DA9052/DA9053 RTC"
> >       depends on PMIC_DA9052
> > diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
> > index 6efff381c484..4efdd2d1e963 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_CV1800) += rtc-cv1800.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-cv1800.c b/drivers/rtc/rtc-cv1800.c
> > new file mode 100644
> > index 000000000000..60a7192659f5
> > --- /dev/null
> > +++ b/drivers/rtc/rtc-cv1800.c
> > @@ -0,0 +1,244 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * rtc-cv1800.c: RTC driver for Sophgo cv1800 RTC
> > + *
> > + * Author: Jingbao Qiu <qiujingbao.dlmu@gmail.com>
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/irq.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +#include <linux/rtc.h>
> > +
> > +#define CTRL                   0x08
> > +#define ANA_CALIB              0x1000
> > +#define SEC_PULSE_GEN          0x1004
> > +#define ALARM_TIME             0x1008
> > +#define ALARM_ENABLE           0x100C
> > +#define SET_SEC_CNTR_VAL       0x1010
> > +#define SET_SEC_CNTR_TRIG      0x1014
> > +#define SEC_CNTR_VAL           0x1018
> > +#define APB_RDATA_SEL          0x103C
> > +#define POR_DB_MAGIC_KEY       0x1068
> > +#define EN_PWR_WAKEUP          0x10BC
> > +
> > +/*
> > + * When in VDDBKUP domain, this MACRO register
> > + * does not power down
> > + */
> > +#define MACRO_DA_CLEAR_ALL     0x1480
> > +#define MACRO_DA_SOC_READY     0x148C
> > +#define MACRO_RO_T             0x14A8
> > +#define MACRO_RG_SET_T         0x1498
> > +
> > +#define CTRL_MODE_MASK         BIT(10)
> > +#define CTRL_MODE_OSC32K       0x00UL
> > +#define CTRL_MODE_XTAL32K      BIT(0)
> > +#define REG_ENABLE_FUN         BIT(0)
> > +#define REG_DISABLE_FUN        0x00UL
> > +#define ALARM_ENABLE_MASK      BIT(0)
> > +#define SET_SEC_CNTR_VAL_INIT  (BIT(28) || BIT(29))
> > +#define SEC_PULSE_SEL_INNER    BIT(31)
> > +#define SEC_PULSE_GEN_SEL_MASK GENMASK(30, 0)
> > +#define CALIB_SEL_FTUNE_MASK   GENMASK(30, 0)
> > +#define CALIB_SEL_FTUNE_INNER  0x00UL
> > +
> > +struct cv1800_rtc_priv {
> > +     struct rtc_device *rtc_dev;
> > +     struct regmap *rtc_map;
> > +     struct clk *clk;
> > +     int irq;
> > +};
> > +
> > +static const struct regmap_config cv1800_rtc_regmap_config = {
> > +     .reg_bits = 32,
> > +     .val_bits = 32,
> > +     .reg_stride = 4,
> > +};
> > +
> > +static int cv1800_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
> > +{
> > +     struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> > +
> > +     regmap_write(info->rtc_map, ALARM_ENABLE, enabled);
> > +
> > +     return 0;
> > +}
> > +
> > +static int cv1800_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> > +{
> > +     struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> > +     unsigned long alarm_time;
> > +
> > +     alarm_time = rtc_tm_to_time64(&alrm->time);
> > +
> > +     cv1800_rtc_alarm_irq_enable(dev, REG_DISABLE_FUN);
> > +
> > +     regmap_write(info->rtc_map, ALARM_TIME, alarm_time);
> > +
> > +     cv1800_rtc_alarm_irq_enable(dev, alrm->enabled);
> > +
> > +     return 0;
> > +}
> > +
> > +static int cv1800_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
> > +{
> > +     struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> > +     u32 enabled;
> > +     u32 time;
> > +
> > +     regmap_read(info->rtc_map, ALARM_ENABLE, &enabled);
> > +
> > +     alarm->enabled = enabled & ALARM_ENABLE_MASK;
> > +
> > +     regmap_read(info->rtc_map, ALARM_TIME, &time);
> > +
> > +     rtc_time64_to_tm(time, &alarm->time);
> > +
> > +     return 0;
> > +}
> > +
> > +static void rtc_enable_sec_counter(struct cv1800_rtc_priv *info)
> > +{
> > +     u32 sec_ro_t;
> > +     u32 sec;
> > +
> > +     /* select inner sec pulse */
> > +     regmap_update_bits(info->rtc_map, SEC_PULSE_GEN,
> > +                        (u32)(~SEC_PULSE_GEN_SEL_MASK),
> > +                        (u32)(~SEC_PULSE_SEL_INNER));
> > +
> > +     regmap_update_bits(info->rtc_map, ANA_CALIB,
> > +                        (u32)(~CALIB_SEL_FTUNE_MASK),
> > +                        CALIB_SEL_FTUNE_INNER);
> > +
> > +     sec = SET_SEC_CNTR_VAL_INIT;
> > +
> > +     /* load from MACRO register */
> > +     regmap_read(info->rtc_map, MACRO_RO_T, &sec_ro_t);
> > +     if (sec_ro_t > (SET_SEC_CNTR_VAL_INIT))
> > +             sec = sec_ro_t;
> > +
> > +     regmap_write(info->rtc_map, SET_SEC_CNTR_VAL, sec);
> > +     regmap_write(info->rtc_map, SET_SEC_CNTR_TRIG, REG_ENABLE_FUN);
> > +}
> > +
> > +static int cv1800_rtc_read_time(struct device *dev, struct rtc_time *tm)
> > +{
> > +     struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> > +     u32 sec;
> > +
> > +     regmap_read(info->rtc_map, SEC_CNTR_VAL, &sec);
> > +
> > +     rtc_time64_to_tm(sec, tm);
> > +
> > +     return 0;
> > +}
> > +
> > +static int cv1800_rtc_set_time(struct device *dev, struct rtc_time *tm)
> > +{
> > +     struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> > +     unsigned long sec;
> > +
> > +     sec = rtc_tm_to_time64(tm);
> > +
> > +     regmap_write(info->rtc_map, SET_SEC_CNTR_VAL, sec);
> > +     regmap_write(info->rtc_map, SET_SEC_CNTR_TRIG, REG_ENABLE_FUN);
> > +
> > +     regmap_write(info->rtc_map, MACRO_RG_SET_T, sec);
> > +
> > +     return 0;
> > +}
> > +
> > +static irqreturn_t cv1800_rtc_irq_handler(int irq, void *dev_id)
> > +{
> > +     struct rtc_device *rtc = dev_id;
> > +
> > +     rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
> > +
> > +     return IRQ_HANDLED;
> > +}
> > +
> > +static const struct rtc_class_ops cv1800_rtc_ops = {
> > +     .read_time = cv1800_rtc_read_time,
> > +     .set_time = cv1800_rtc_set_time,
> > +     .read_alarm = cv1800_rtc_read_alarm,
> > +     .set_alarm = cv1800_rtc_set_alarm,
> > +     .alarm_irq_enable = cv1800_rtc_alarm_irq_enable,
> > +};
> > +
> > +static int cv1800_rtc_probe(struct platform_device *pdev)
> > +{
> > +     struct cv1800_rtc_priv *rtc;
> > +     u32 ctrl_val;
> > +     void __iomem *base;
> > +     int ret;
> > +
> > +     rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
> > +     if (!rtc)
> > +             return -ENOMEM;
> > +
> > +     base = devm_platform_ioremap_resource(pdev, 0);
> > +     if (IS_ERR(base))
> > +             return PTR_ERR(base);
> > +
> > +     rtc->rtc_map = devm_regmap_init_mmio(&pdev->dev, base,
> > +                                          &cv1800_rtc_regmap_config);
> > +     if (IS_ERR(rtc->rtc_map))
> > +             return PTR_ERR(rtc->rtc_map);
> > +
> > +     rtc->irq = platform_get_irq(pdev, 0);
> > +     if (rtc->irq < 0)
> > +             return rtc->irq;
> > +
> > +     ret = devm_request_irq(&pdev->dev, rtc->irq, cv1800_rtc_irq_handler,
> > +                            IRQF_TRIGGER_HIGH, "alarm", &pdev->dev);
> > +     if (ret)
> > +             return dev_err_probe(&pdev->dev, ret,
> > +                                  "cannot register interrupt handler\n");
> > +
> > +     rtc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
> > +     if (IS_ERR(rtc->clk))
> > +             return dev_err_probe(&pdev->dev, PTR_ERR(rtc->clk),
> > +                                  "clk not found\n");
> > +
> > +     rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
> > +     if (IS_ERR(rtc->rtc_dev))
> > +             return PTR_ERR(rtc->rtc_dev);
> > +
> > +     platform_set_drvdata(pdev, rtc);
> > +
> > +     rtc->rtc_dev->ops = &cv1800_rtc_ops;
> > +     rtc->rtc_dev->range_max = U32_MAX;
> > +
>
> > +     regmap_read(rtc->rtc_map, CTRL, &ctrl_val);
> > +     ctrl_val &= CTRL_MODE_MASK;
> > +
> > +     if (ctrl_val == CTRL_MODE_OSC32K)
> > +             rtc_enable_sec_counter(rtc);
> > +
>
> use (ctrl_val & CTRL_MODE_OSC32K).
>
> Another thing is that I do not think is a good way to let the
> rtc driver access RTC_CTRL area directly. You have already
> know there is a 8051 device in the 0x05025000. It is necessary
> to make some room for this device. Maybe you want to implement
> them all in the rtc driver? If so, I do think it is a bad idea.


Do you mean that RTC drivers should not directly access the 0x05025000 address?
Because there is an 8051 subsystem on this address.
Firstly, I do not intend to implement 8051 in the RTC driver,
but the 8051 subsystem is located within a module independently
powered by the RTC.
So if we want to implement the 8051 subsystem in the future, it can be
used as a node in RTC? I'm not sure.
Then, Alexandre told me that there are operations related to PM in
RTC, such as the following files.
This matches the description of address 0x05025000.

drivers/rtc/rtc jz4740. c

>
> > +     return devm_rtc_register_device(rtc->rtc_dev);
> > +}
> > +
> > +static const struct of_device_id cv1800_dt_ids[] = {
> > +     { .compatible = "sophgo,cv1800-rtc" },
> > +     { /* sentinel */ },
> > +};
> > +MODULE_DEVICE_TABLE(of, cv1800_dt_ids);
> > +
> > +static struct platform_driver cv1800_rtc_driver = {
> > +     .driver = {
> > +             .name = "sophgo-cv1800-rtc",
> > +             .of_match_table = cv1800_dt_ids,
> > +     },
> > +     .probe = cv1800_rtc_probe,
> > +};
> > +
> > +module_platform_driver(cv1800_rtc_driver);
> > +MODULE_AUTHOR("Jingbao Qiu");
> > +MODULE_DESCRIPTION("Sophgo cv1800 RTC Driver");
> > +MODULE_LICENSE("GPL");
> > --
> > 2.25.1
> >

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC
  2024-05-01  5:03     ` Jingbao Qiu
@ 2024-05-01  7:43       ` Inochi Amaoto
  2024-05-01  9:14         ` Jingbao Qiu
  0 siblings, 1 reply; 12+ messages in thread
From: Inochi Amaoto @ 2024-05-01  7:43 UTC (permalink / raw)
  To: Jingbao Qiu, Inochi Amaoto
  Cc: alexandre.belloni, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	paul.walmsley, palmer, aou, linux-rtc, devicetree, linux-kernel,
	dlan

On Wed, May 01, 2024 at 01:03:58PM GMT, Jingbao Qiu wrote:
> Hi, Inochi
> 
> On Wed, May 1, 2024 at 10:19 AM Inochi Amaoto <inochiama@outlook.com> wrote:
> >
> > On Sun, Feb 04, 2024 at 12:41:43PM GMT, Jingbao Qiu wrote:
> > > Implement the RTC driver for CV1800, which able to provide time alarm.
> > >
> > > Signed-off-by: Jingbao Qiu <qiujingbao.dlmu@gmail.com>
> > > ---
> > >  drivers/rtc/Kconfig      |  10 ++
> > >  drivers/rtc/Makefile     |   1 +
> > >  drivers/rtc/rtc-cv1800.c | 244 +++++++++++++++++++++++++++++++++++++++
> > >  3 files changed, 255 insertions(+)
> > >  create mode 100644 drivers/rtc/rtc-cv1800.c
> > >
> > > diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> > > index e37a4341f442..3c6ed45a3b03 100644
> > > --- a/drivers/rtc/Kconfig
> > > +++ b/drivers/rtc/Kconfig
> > > @@ -1128,6 +1128,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_CV1800
> > > +     tristate "Sophgo CV1800 RTC"
> > > +     depends on ARCH_SOPHGO || COMPILE_TEST
> > > +     help
> > > +       If you say yes here you get support the RTC driver
> > > +       for Sophgo CV1800 chip.
> > > +
> > > +       This driver can also be built as a module.If so, the
> > > +       module will be called rtc-cv1800.
> > > +
> > >  config RTC_DRV_DA9052
> > >       tristate "Dialog DA9052/DA9053 RTC"
> > >       depends on PMIC_DA9052
> > > diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
> > > index 6efff381c484..4efdd2d1e963 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_CV1800) += rtc-cv1800.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-cv1800.c b/drivers/rtc/rtc-cv1800.c
> > > new file mode 100644
> > > index 000000000000..60a7192659f5
> > > --- /dev/null
> > > +++ b/drivers/rtc/rtc-cv1800.c
> > > @@ -0,0 +1,244 @@
> > > +// SPDX-License-Identifier: GPL-2.0-only
> > > +/*
> > > + * rtc-cv1800.c: RTC driver for Sophgo cv1800 RTC
> > > + *
> > > + * Author: Jingbao Qiu <qiujingbao.dlmu@gmail.com>
> > > + */
> > > +
> > > +#include <linux/clk.h>
> > > +#include <linux/irq.h>
> > > +#include <linux/kernel.h>
> > > +#include <linux/module.h>
> > > +#include <linux/of.h>
> > > +#include <linux/platform_device.h>
> > > +#include <linux/regmap.h>
> > > +#include <linux/rtc.h>
> > > +
> > > +#define CTRL                   0x08
> > > +#define ANA_CALIB              0x1000
> > > +#define SEC_PULSE_GEN          0x1004
> > > +#define ALARM_TIME             0x1008
> > > +#define ALARM_ENABLE           0x100C
> > > +#define SET_SEC_CNTR_VAL       0x1010
> > > +#define SET_SEC_CNTR_TRIG      0x1014
> > > +#define SEC_CNTR_VAL           0x1018
> > > +#define APB_RDATA_SEL          0x103C
> > > +#define POR_DB_MAGIC_KEY       0x1068
> > > +#define EN_PWR_WAKEUP          0x10BC
> > > +
> > > +/*
> > > + * When in VDDBKUP domain, this MACRO register
> > > + * does not power down
> > > + */
> > > +#define MACRO_DA_CLEAR_ALL     0x1480
> > > +#define MACRO_DA_SOC_READY     0x148C
> > > +#define MACRO_RO_T             0x14A8
> > > +#define MACRO_RG_SET_T         0x1498
> > > +
> > > +#define CTRL_MODE_MASK         BIT(10)
> > > +#define CTRL_MODE_OSC32K       0x00UL
> > > +#define CTRL_MODE_XTAL32K      BIT(0)
> > > +#define REG_ENABLE_FUN         BIT(0)
> > > +#define REG_DISABLE_FUN        0x00UL
> > > +#define ALARM_ENABLE_MASK      BIT(0)
> > > +#define SET_SEC_CNTR_VAL_INIT  (BIT(28) || BIT(29))
> > > +#define SEC_PULSE_SEL_INNER    BIT(31)
> > > +#define SEC_PULSE_GEN_SEL_MASK GENMASK(30, 0)
> > > +#define CALIB_SEL_FTUNE_MASK   GENMASK(30, 0)
> > > +#define CALIB_SEL_FTUNE_INNER  0x00UL
> > > +
> > > +struct cv1800_rtc_priv {
> > > +     struct rtc_device *rtc_dev;
> > > +     struct regmap *rtc_map;
> > > +     struct clk *clk;
> > > +     int irq;
> > > +};
> > > +
> > > +static const struct regmap_config cv1800_rtc_regmap_config = {
> > > +     .reg_bits = 32,
> > > +     .val_bits = 32,
> > > +     .reg_stride = 4,
> > > +};
> > > +
> > > +static int cv1800_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
> > > +{
> > > +     struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> > > +
> > > +     regmap_write(info->rtc_map, ALARM_ENABLE, enabled);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static int cv1800_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
> > > +{
> > > +     struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> > > +     unsigned long alarm_time;
> > > +
> > > +     alarm_time = rtc_tm_to_time64(&alrm->time);
> > > +
> > > +     cv1800_rtc_alarm_irq_enable(dev, REG_DISABLE_FUN);
> > > +
> > > +     regmap_write(info->rtc_map, ALARM_TIME, alarm_time);
> > > +
> > > +     cv1800_rtc_alarm_irq_enable(dev, alrm->enabled);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static int cv1800_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
> > > +{
> > > +     struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> > > +     u32 enabled;
> > > +     u32 time;
> > > +
> > > +     regmap_read(info->rtc_map, ALARM_ENABLE, &enabled);
> > > +
> > > +     alarm->enabled = enabled & ALARM_ENABLE_MASK;
> > > +
> > > +     regmap_read(info->rtc_map, ALARM_TIME, &time);
> > > +
> > > +     rtc_time64_to_tm(time, &alarm->time);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static void rtc_enable_sec_counter(struct cv1800_rtc_priv *info)
> > > +{
> > > +     u32 sec_ro_t;
> > > +     u32 sec;
> > > +
> > > +     /* select inner sec pulse */
> > > +     regmap_update_bits(info->rtc_map, SEC_PULSE_GEN,
> > > +                        (u32)(~SEC_PULSE_GEN_SEL_MASK),
> > > +                        (u32)(~SEC_PULSE_SEL_INNER));
> > > +
> > > +     regmap_update_bits(info->rtc_map, ANA_CALIB,
> > > +                        (u32)(~CALIB_SEL_FTUNE_MASK),
> > > +                        CALIB_SEL_FTUNE_INNER);
> > > +
> > > +     sec = SET_SEC_CNTR_VAL_INIT;
> > > +
> > > +     /* load from MACRO register */
> > > +     regmap_read(info->rtc_map, MACRO_RO_T, &sec_ro_t);
> > > +     if (sec_ro_t > (SET_SEC_CNTR_VAL_INIT))
> > > +             sec = sec_ro_t;
> > > +
> > > +     regmap_write(info->rtc_map, SET_SEC_CNTR_VAL, sec);
> > > +     regmap_write(info->rtc_map, SET_SEC_CNTR_TRIG, REG_ENABLE_FUN);
> > > +}
> > > +
> > > +static int cv1800_rtc_read_time(struct device *dev, struct rtc_time *tm)
> > > +{
> > > +     struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> > > +     u32 sec;
> > > +
> > > +     regmap_read(info->rtc_map, SEC_CNTR_VAL, &sec);
> > > +
> > > +     rtc_time64_to_tm(sec, tm);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static int cv1800_rtc_set_time(struct device *dev, struct rtc_time *tm)
> > > +{
> > > +     struct cv1800_rtc_priv *info = dev_get_drvdata(dev);
> > > +     unsigned long sec;
> > > +
> > > +     sec = rtc_tm_to_time64(tm);
> > > +
> > > +     regmap_write(info->rtc_map, SET_SEC_CNTR_VAL, sec);
> > > +     regmap_write(info->rtc_map, SET_SEC_CNTR_TRIG, REG_ENABLE_FUN);
> > > +
> > > +     regmap_write(info->rtc_map, MACRO_RG_SET_T, sec);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static irqreturn_t cv1800_rtc_irq_handler(int irq, void *dev_id)
> > > +{
> > > +     struct rtc_device *rtc = dev_id;
> > > +
> > > +     rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
> > > +
> > > +     return IRQ_HANDLED;
> > > +}
> > > +
> > > +static const struct rtc_class_ops cv1800_rtc_ops = {
> > > +     .read_time = cv1800_rtc_read_time,
> > > +     .set_time = cv1800_rtc_set_time,
> > > +     .read_alarm = cv1800_rtc_read_alarm,
> > > +     .set_alarm = cv1800_rtc_set_alarm,
> > > +     .alarm_irq_enable = cv1800_rtc_alarm_irq_enable,
> > > +};
> > > +
> > > +static int cv1800_rtc_probe(struct platform_device *pdev)
> > > +{
> > > +     struct cv1800_rtc_priv *rtc;
> > > +     u32 ctrl_val;
> > > +     void __iomem *base;
> > > +     int ret;
> > > +
> > > +     rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
> > > +     if (!rtc)
> > > +             return -ENOMEM;
> > > +
> > > +     base = devm_platform_ioremap_resource(pdev, 0);
> > > +     if (IS_ERR(base))
> > > +             return PTR_ERR(base);
> > > +
> > > +     rtc->rtc_map = devm_regmap_init_mmio(&pdev->dev, base,
> > > +                                          &cv1800_rtc_regmap_config);
> > > +     if (IS_ERR(rtc->rtc_map))
> > > +             return PTR_ERR(rtc->rtc_map);
> > > +
> > > +     rtc->irq = platform_get_irq(pdev, 0);
> > > +     if (rtc->irq < 0)
> > > +             return rtc->irq;
> > > +
> > > +     ret = devm_request_irq(&pdev->dev, rtc->irq, cv1800_rtc_irq_handler,
> > > +                            IRQF_TRIGGER_HIGH, "alarm", &pdev->dev);
> > > +     if (ret)
> > > +             return dev_err_probe(&pdev->dev, ret,
> > > +                                  "cannot register interrupt handler\n");
> > > +
> > > +     rtc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
> > > +     if (IS_ERR(rtc->clk))
> > > +             return dev_err_probe(&pdev->dev, PTR_ERR(rtc->clk),
> > > +                                  "clk not found\n");
> > > +
> > > +     rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
> > > +     if (IS_ERR(rtc->rtc_dev))
> > > +             return PTR_ERR(rtc->rtc_dev);
> > > +
> > > +     platform_set_drvdata(pdev, rtc);
> > > +
> > > +     rtc->rtc_dev->ops = &cv1800_rtc_ops;
> > > +     rtc->rtc_dev->range_max = U32_MAX;
> > > +
> >
> > > +     regmap_read(rtc->rtc_map, CTRL, &ctrl_val);
> > > +     ctrl_val &= CTRL_MODE_MASK;
> > > +
> > > +     if (ctrl_val == CTRL_MODE_OSC32K)
> > > +             rtc_enable_sec_counter(rtc);
> > > +
> >
> > use (ctrl_val & CTRL_MODE_OSC32K).
> >
> > Another thing is that I do not think is a good way to let the
> > rtc driver access RTC_CTRL area directly. You have already
> > know there is a 8051 device in the 0x05025000. It is necessary
> > to make some room for this device. Maybe you want to implement
> > them all in the rtc driver? If so, I do think it is a bad idea.
> 
> 
> Do you mean that RTC drivers should not directly access the 0x05025000 address?
> Because there is an 8051 subsystem on this address.

Yes. At least we need some mechanism to share these address between
this devices.

> Firstly, I do not intend to implement 8051 in the RTC driver,
> but the 8051 subsystem is located within a module independently
> powered by the RTC.
> So if we want to implement the 8051 subsystem in the future, it can be
> used as a node in RTC? I'm not sure.

Yes, this is what I care about.

> Then, Alexandre told me that there are operations related to PM in
> RTC, such as the following files.
> This matches the description of address 0x05025000.
> 
> drivers/rtc/rtc jz4740. c
> 

I do not think this is something related to the PM. 8051 is more
like remoteproc. So it is necessary to arrange them carefully.

> >
> > > +     return devm_rtc_register_device(rtc->rtc_dev);
> > > +}
> > > +
> > > +static const struct of_device_id cv1800_dt_ids[] = {
> > > +     { .compatible = "sophgo,cv1800-rtc" },
> > > +     { /* sentinel */ },
> > > +};
> > > +MODULE_DEVICE_TABLE(of, cv1800_dt_ids);
> > > +
> > > +static struct platform_driver cv1800_rtc_driver = {
> > > +     .driver = {
> > > +             .name = "sophgo-cv1800-rtc",
> > > +             .of_match_table = cv1800_dt_ids,
> > > +     },
> > > +     .probe = cv1800_rtc_probe,
> > > +};
> > > +
> > > +module_platform_driver(cv1800_rtc_driver);
> > > +MODULE_AUTHOR("Jingbao Qiu");
> > > +MODULE_DESCRIPTION("Sophgo cv1800 RTC Driver");
> > > +MODULE_LICENSE("GPL");
> > > --
> > > 2.25.1
> > >

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC
  2024-05-01  7:43       ` Inochi Amaoto
@ 2024-05-01  9:14         ` Jingbao Qiu
  2024-05-01 11:20           ` Alexandre Belloni
  0 siblings, 1 reply; 12+ messages in thread
From: Jingbao Qiu @ 2024-05-01  9:14 UTC (permalink / raw)
  To: Inochi Amaoto
  Cc: alexandre.belloni, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	paul.walmsley, palmer, aou, linux-rtc, devicetree, linux-kernel,
	dlan

On Wed, May 1, 2024 at 3:43 PM Inochi Amaoto <inochiama@outlook.com> wrote:
>
> On Wed, May 01, 2024 at 01:03:58PM GMT, Jingbao Qiu wrote:
> > Hi, Inochi
> >
> > On Wed, May 1, 2024 at 10:19 AM Inochi Amaoto <inochiama@outlook.com> wrote:

> > > Another thing is that I do not think is a good way to let the
> > > rtc driver access RTC_CTRL area directly. You have already
> > > know there is a 8051 device in the 0x05025000. It is necessary
> > > to make some room for this device. Maybe you want to implement
> > > them all in the rtc driver? If so, I do think it is a bad idea.
> >
> >
> > Do you mean that RTC drivers should not directly access the 0x05025000 address?
> > Because there is an 8051 subsystem on this address.
>
> Yes. At least we need some mechanism to share these address between
> this devices.
>
> > Firstly, I do not intend to implement 8051 in the RTC driver,
> > but the 8051 subsystem is located within a module independently
> > powered by the RTC.
> > So if we want to implement the 8051 subsystem in the future, it can be
> > used as a node in RTC? I'm not sure.
>
> Yes, this is what I care about.
>
> > Then, Alexandre told me that there are operations related to PM in
> > RTC, such as the following files.
> > This matches the description of address 0x05025000.
> >
> > drivers/rtc/rtc jz4740. c
> >
>
> I do not think this is something related to the PM. 8051 is more
> like remoteproc. So it is necessary to arrange them carefully.
>

You are right.
I learned from official documents that 8051 works in the RTC domain.
Linux does not provide relevant interfaces to operate 8051,
Just providing a mailbox for communication between them, or through
interruptions.
I don't understand how 8051 works, so I shouldn't write to the
corresponding registers in RTC.

https://milkv.io/docs/duo/getting-started/8051core


> > > > 2.25.1
> > > >

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC
  2024-05-01  9:14         ` Jingbao Qiu
@ 2024-05-01 11:20           ` Alexandre Belloni
  2024-05-02  7:39             ` Jingbao Qiu
  0 siblings, 1 reply; 12+ messages in thread
From: Alexandre Belloni @ 2024-05-01 11:20 UTC (permalink / raw)
  To: Jingbao Qiu
  Cc: Inochi Amaoto, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	paul.walmsley, palmer, aou, linux-rtc, devicetree, linux-kernel,
	dlan

On 01/05/2024 17:14:43+0800, Jingbao Qiu wrote:
> On Wed, May 1, 2024 at 3:43 PM Inochi Amaoto <inochiama@outlook.com> wrote:
> >
> > On Wed, May 01, 2024 at 01:03:58PM GMT, Jingbao Qiu wrote:
> > > Hi, Inochi
> > >
> > > On Wed, May 1, 2024 at 10:19 AM Inochi Amaoto <inochiama@outlook.com> wrote:
> 
> > > > Another thing is that I do not think is a good way to let the
> > > > rtc driver access RTC_CTRL area directly. You have already
> > > > know there is a 8051 device in the 0x05025000. It is necessary
> > > > to make some room for this device. Maybe you want to implement
> > > > them all in the rtc driver? If so, I do think it is a bad idea.
> > >
> > >
> > > Do you mean that RTC drivers should not directly access the 0x05025000 address?
> > > Because there is an 8051 subsystem on this address.
> >
> > Yes. At least we need some mechanism to share these address between
> > this devices.
> >
> > > Firstly, I do not intend to implement 8051 in the RTC driver,
> > > but the 8051 subsystem is located within a module independently
> > > powered by the RTC.
> > > So if we want to implement the 8051 subsystem in the future, it can be
> > > used as a node in RTC? I'm not sure.
> >
> > Yes, this is what I care about.
> >
> > > Then, Alexandre told me that there are operations related to PM in
> > > RTC, such as the following files.
> > > This matches the description of address 0x05025000.
> > >
> > > drivers/rtc/rtc jz4740. c
> > >
> >
> > I do not think this is something related to the PM. 8051 is more
> > like remoteproc. So it is necessary to arrange them carefully.
> >
> 
> You are right.
> I learned from official documents that 8051 works in the RTC domain.
> Linux does not provide relevant interfaces to operate 8051,
> Just providing a mailbox for communication between them, or through
> interruptions.
> I don't understand how 8051 works, so I shouldn't write to the
> corresponding registers in RTC.
> 
> https://milkv.io/docs/duo/getting-started/8051core

Then you will have to have a driver for the 8051 firmware before being
able to access registers that are outside of the RTC range. However, I
se the firmware is using RTC_INFOx without any form of locking but I
guess this just means Linux will have to ensure it never writes to
those.

> 
> 
> > > > > 2.25.1
> > > > >

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC
  2024-05-01 11:20           ` Alexandre Belloni
@ 2024-05-02  7:39             ` Jingbao Qiu
  0 siblings, 0 replies; 12+ messages in thread
From: Jingbao Qiu @ 2024-05-02  7:39 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Inochi Amaoto, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	paul.walmsley, palmer, aou, linux-rtc, devicetree, linux-kernel,
	dlan

On Wed, May 1, 2024 at 7:20 PM Alexandre Belloni
<alexandre.belloni@bootlin.com> wrote:
>
> On 01/05/2024 17:14:43+0800, Jingbao Qiu wrote:
> > On Wed, May 1, 2024 at 3:43 PM Inochi Amaoto <inochiama@outlook.com> wrote:
> > >
> > > On Wed, May 01, 2024 at 01:03:58PM GMT, Jingbao Qiu wrote:
> > > > Hi, Inochi
> > > >
> > > > On Wed, May 1, 2024 at 10:19 AM Inochi Amaoto <inochiama@outlook.com> wrote:
> >
> > > > > Another thing is that I do not think is a good way to let the
> > > > > rtc driver access RTC_CTRL area directly. You have already
> > > > > know there is a 8051 device in the 0x05025000. It is necessary
> > > > > to make some room for this device. Maybe you want to implement
> > > > > them all in the rtc driver? If so, I do think it is a bad idea.
> > > >
> > > >
> > > > Do you mean that RTC drivers should not directly access the 0x05025000 address?
> > > > Because there is an 8051 subsystem on this address.
> > >
> > > Yes. At least we need some mechanism to share these address between
> > > this devices.
> > >
> > > > Firstly, I do not intend to implement 8051 in the RTC driver,
> > > > but the 8051 subsystem is located within a module independently
> > > > powered by the RTC.
> > > > So if we want to implement the 8051 subsystem in the future, it can be
> > > > used as a node in RTC? I'm not sure.
> > >
> > > Yes, this is what I care about.
> > >
> > > > Then, Alexandre told me that there are operations related to PM in
> > > > RTC, such as the following files.
> > > > This matches the description of address 0x05025000.
> > > >
> > > > drivers/rtc/rtc jz4740. c
> > > >
> > >
> > > I do not think this is something related to the PM. 8051 is more
> > > like remoteproc. So it is necessary to arrange them carefully.
> > >
> >
> > You are right.
> > I learned from official documents that 8051 works in the RTC domain.
> > Linux does not provide relevant interfaces to operate 8051,
> > Just providing a mailbox for communication between them, or through
> > interruptions.
> > I don't understand how 8051 works, so I shouldn't write to the
> > corresponding registers in RTC.
> >
> > https://milkv.io/docs/duo/getting-started/8051core
>
> Then you will have to have a driver for the 8051 firmware before being
> able to access registers that are outside of the RTC range. However, I
> se the firmware is using RTC_INFOx without any form of locking but I
> guess this just means Linux will have to ensure it never writes to
> those.
>

Yes, you are right. Not only are the registers on 0x05025000 used by 8051,
but some of the registers on 0x05026000 are shared by the C906 and 8051 cores,
such as the RTC_INFOx you mentioned. The reference link is as follows.
So it is necessary to ensure that registers that implement RTC
functions can be read and written,
registers that are accessed together with 8051 can only be read but
not written, and registers
that are private to 8051 cannot be read or written.


https://github.com/milkv-duo/duo-8051/blob/main/sdcc/mars/include/chip_cv1822.h

Best regards
Jingbao Qiu

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2024-05-02  7:40 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-04  4:41 [PATCH v8 0/2] riscv: rtc: sophgo: add rtc support for CV1800 Jingbao Qiu
2024-02-04  4:41 ` [PATCH v8 1/2] dt-bindings: rtc: sophgo: add RTC support for Sophgo CV1800 series SoC Jingbao Qiu
2024-02-04  4:41 ` [PATCH v8 2/2] rtc: sophgo: add rtc support for Sophgo CV1800 SoC Jingbao Qiu
2024-03-05 10:25   ` Jingbao Qiu
2024-04-17 21:23   ` Alexandre Belloni
2024-04-24  7:35     ` Jingbao Qiu
2024-05-01  2:19   ` Inochi Amaoto
2024-05-01  5:03     ` Jingbao Qiu
2024-05-01  7:43       ` Inochi Amaoto
2024-05-01  9:14         ` Jingbao Qiu
2024-05-01 11:20           ` Alexandre Belloni
2024-05-02  7:39             ` Jingbao Qiu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).