All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/2] rtc: microchip: Add driver for PolarFire SoC
@ 2021-05-12 11:11 daire.mcnamara
  2021-05-12 11:11 ` [PATCH v1 1/2] dt-bindings: rtc: microchip: Add Microchip PolarFire host binding daire.mcnamara
  2021-05-12 11:11 ` [PATCH v1 2/2] rtc: microchip: Add driver for Microchip PolarFire SoC daire.mcnamara
  0 siblings, 2 replies; 6+ messages in thread
From: daire.mcnamara @ 2021-05-12 11:11 UTC (permalink / raw)
  To: a.zummo, alexandre.belloni, linux-rtc, robh+dt, devicetree
  Cc: palmer, cyril.jean, padmarao.begari, lewis.hanly, conor.dooley,
	david.abdurachmanov, Daire McNamara

From: Daire McNamara <daire.mcnamara@microchip.com>

This patchset adds support for the Microchip PolarFire SoC RTC
hardware block.

Daire McNamara (2):
  dt-bindings: rtc: microchip: Add Microchip PolarFire host binding
  rtc: microchip: Add driver for Microchip PolarFire SoC

 .../bindings/rtc/microchip,mfps-rtc.yaml      |  61 +++
 drivers/rtc/Kconfig                           |   7 +
 drivers/rtc/Makefile                          |   1 +
 drivers/rtc/rtc-mpfs.c                        | 449 ++++++++++++++++++
 4 files changed, 518 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml
 create mode 100644 drivers/rtc/rtc-mpfs.c


base-commit: acd3d28594536e9096c1ea76c5867d8a68babef6
prerequisite-patch-id: 6f7f70120adfa8e938b97517f0c664e43e8745a0
prerequisite-patch-id: 4ea37008d23838aa2e0658811fe15462f6cdbd87
prerequisite-patch-id: 378c9d7495e56454b7bffbdbc430185dc4e36b90
prerequisite-patch-id: b547bbdf0a800c652cdd1a542b8ce725dfd6fcc9
prerequisite-patch-id: 98fc35868a9b0e284ba666422770fb3a4fe27ed9
prerequisite-patch-id: 28006f331625d755e92cc87ae194e05138f26909
prerequisite-patch-id: 26afc006e51cf743902bf609b537e1558e70f69c
-- 
2.25.1


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

* [PATCH v1 1/2] dt-bindings: rtc: microchip: Add Microchip PolarFire host binding
  2021-05-12 11:11 [PATCH v1 0/2] rtc: microchip: Add driver for PolarFire SoC daire.mcnamara
@ 2021-05-12 11:11 ` daire.mcnamara
  2021-05-12 18:35   ` Rob Herring
  2021-05-13  2:22   ` Rob Herring
  2021-05-12 11:11 ` [PATCH v1 2/2] rtc: microchip: Add driver for Microchip PolarFire SoC daire.mcnamara
  1 sibling, 2 replies; 6+ messages in thread
From: daire.mcnamara @ 2021-05-12 11:11 UTC (permalink / raw)
  To: a.zummo, alexandre.belloni, linux-rtc, robh+dt, devicetree
  Cc: palmer, cyril.jean, padmarao.begari, lewis.hanly, conor.dooley,
	david.abdurachmanov, Daire McNamara

From: Daire McNamara <daire.mcnamara@microchip.com>

Add device tree bindings for the Microchip PolarFire real-time
clock controller

Signed-off-by: Daire McNamara <daire.mcnamara@microchip.com>
---
 .../bindings/rtc/microchip,mfps-rtc.yaml      | 61 +++++++++++++++++++
 1 file changed, 61 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml

diff --git a/Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml b/Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml
new file mode 100644
index 000000000000..c82b3e7351e0
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/microchip,mfps-rtc.yaml#
+
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip PolarFire Soc (MPFS) RTC Device Tree Bindings
+
+allOf:
+  - $ref: "rtc.yaml#"
+
+maintainers:
+  - Daire McNamara <daire.mcnamara@microchip.com>
+  - Lewis Hanly <lewis.hanly@microchip.com>
+
+properties:
+  compatible:
+    enum:
+      - microchip,mpfs-rtc
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  prescaler:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+      - const: rtc
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/microchip,mpfs-clock.h>
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+        rtc@20124000 {
+            compatible = "microchip,mpfs-rtc";
+            reg = <0 0x20124000 0 0x1000>;
+            clocks = <&clkcfg CLK_RTC>;
+            clock-names = "rtc";
+            interrupts = <80>;
+        };
+    };
+...
-- 
2.25.1


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

* [PATCH v1 2/2] rtc: microchip: Add driver for Microchip PolarFire SoC
  2021-05-12 11:11 [PATCH v1 0/2] rtc: microchip: Add driver for PolarFire SoC daire.mcnamara
  2021-05-12 11:11 ` [PATCH v1 1/2] dt-bindings: rtc: microchip: Add Microchip PolarFire host binding daire.mcnamara
@ 2021-05-12 11:11 ` daire.mcnamara
  2021-05-12 22:18   ` Alexandre Belloni
  1 sibling, 1 reply; 6+ messages in thread
From: daire.mcnamara @ 2021-05-12 11:11 UTC (permalink / raw)
  To: a.zummo, alexandre.belloni, linux-rtc, robh+dt, devicetree
  Cc: palmer, cyril.jean, padmarao.begari, lewis.hanly, conor.dooley,
	david.abdurachmanov, Daire McNamara

From: Daire McNamara <daire.mcnamara@microchip.com>

Add support for built-in RTC on Microchip PolarFire SoC

Signed-off-by: Daire McNamara <daire.mcnamara@microchip.com>
---
 drivers/rtc/Kconfig    |   7 +
 drivers/rtc/Makefile   |   1 +
 drivers/rtc/rtc-mpfs.c | 449 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 457 insertions(+)
 create mode 100644 drivers/rtc/rtc-mpfs.c

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index ce723dc54aa4..12e2308423ee 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1655,6 +1655,13 @@ config RTC_DRV_MPC5121
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-mpc5121.
 
+config RTC_DRV_MPFS
+	tristate "Microchip PolarFire SoC built-in RTC"
+	depends on SOC_MICROCHIP_POLARFIRE
+	help
+	  If you say yes here you will get support for the
+	  built-in RTC on MPFS.
+
 config RTC_DRV_JZ4740
 	tristate "Ingenic JZ4740 SoC"
 	depends on MIPS || COMPILE_TEST
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 4e930183c170..4a02d3d0278d 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -101,6 +101,7 @@ obj-$(CONFIG_RTC_DRV_MCP795)	+= rtc-mcp795.o
 obj-$(CONFIG_RTC_DRV_MESON)	+= rtc-meson.o
 obj-$(CONFIG_RTC_DRV_MOXART)	+= rtc-moxart.o
 obj-$(CONFIG_RTC_DRV_MPC5121)	+= rtc-mpc5121.o
+obj-$(CONFIG_RTC_DRV_MPFS)	+= rtc-mpfs.o
 obj-$(CONFIG_RTC_DRV_MSM6242)	+= rtc-msm6242.o
 obj-$(CONFIG_RTC_DRV_MT2712)	+= rtc-mt2712.o
 obj-$(CONFIG_RTC_DRV_MT6397)	+= rtc-mt6397.o
diff --git a/drivers/rtc/rtc-mpfs.c b/drivers/rtc/rtc-mpfs.c
new file mode 100644
index 000000000000..f054d1770b78
--- /dev/null
+++ b/drivers/rtc/rtc-mpfs.c
@@ -0,0 +1,449 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Microchip MPFS RTC driver
+ *
+ * Copyright (c) 2021 Microchip Corporation. All rights reserved.
+ *
+ * Author: Daire McNamara <daire.mcnamara@microchip.com>
+ *
+ */
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/rtc.h>
+#include <linux/io.h>
+
+/*
+ * Device Specific Peripheral registers structures
+ */
+#define CONTROL_REG		0x00
+#define  CONTROL_RUNNING_BIT		BIT(0)
+#define  CONTROL_START_BIT		BIT(0)
+#define  CONTROL_STOP_BIT		BIT(1)
+#define  CONTROL_ALARM_ON_BIT		BIT(2)
+#define  CONTROL_ALARM_OFF_BIT		BIT(3)
+#define  CONTROL_RESET_BIT		BIT(4)
+#define  CONTROL_UPLOAD_BIT		BIT(5)
+#define  CONTROL_WAKEUP_CLR_BIT		BIT(8)
+#define  CONTROL_WAKEUP_SET_BIT		BIT(9)
+#define  CONTROL_UPDATED_BIT		BIT(10)
+#define  MPFS_RTC_NUM_IRQS		2
+#define MODE_REG		0x04
+#define  MODE_CLOCK_BIT			BIT(0)
+#define   MODE_CLOCK_CALENDAR		1
+#define  MODE_WAKE_EN_BIT		BIT(1)
+#define  MODE_WAKE_RESET_BIT		BIT(2)
+#define  MODE_WAKE_CONTINUE_BIT		BIT(3)
+#define PRESCALER_REG		0x08
+#define ALARM_LOWER_REG		0x0c
+#define ALARM_UPPER_REG		0x10
+#define COMPARE_LOWER_REG	0x14
+#define COMPARE_UPPER_REG	0x18
+#define DATETIME_LOWER_REG	0x20
+#define DATETIME_UPPER_REG	0x24
+#define SECONDS_REG		0x30
+#define MINUTES_REG		0x34
+#define HOURS_REG		0x38
+#define DAY_REG			0x3c
+#define MONTH_REG		0x40
+#define YEAR_REG		0x44
+#define WEEKDAY_REG		0x48
+#define WEEK_REG		0x4c
+
+/*
+ * Linux counts from 1970 but tm_year starts at 1900, MPFS RTC counts from 2000
+ * Account for this difference
+ */
+#define YEAR_OFFSET		(100)
+
+#define MAX_PRESCALER_COUNT	GENMASK(21, 0)
+#define DEFAULT_PRESCALER	999999  /* (1Mhz / prescaler) -1 = 1Hz */
+
+struct mpfs_rtc_dev {
+	struct rtc_device *rtc;
+	void __iomem *base;
+	int wakeup_irq;
+	u32 prescaler;
+};
+
+static void mpfs_rtc_stop(struct mpfs_rtc_dev *rtcdev)
+{
+	u32 ctrl;
+
+	ctrl = readl(rtcdev->base + CONTROL_REG);
+	ctrl &= ~(CONTROL_STOP_BIT | CONTROL_START_BIT);
+	ctrl |= CONTROL_STOP_BIT;
+	ctrl |= CONTROL_ALARM_OFF_BIT;
+	writel(ctrl, rtcdev->base + CONTROL_REG);
+}
+
+static void mpfs_rtc_start(struct mpfs_rtc_dev *rtcdev)
+{
+	u32 ctrl;
+
+	ctrl = readl(rtcdev->base + CONTROL_REG);
+	ctrl &= ~(CONTROL_STOP_BIT | CONTROL_START_BIT);
+	ctrl |= CONTROL_START_BIT;
+	writel(ctrl, rtcdev->base + CONTROL_REG);
+}
+
+static void mpfs_rtc_clear_irq(struct mpfs_rtc_dev *rtcdev)
+{
+	u32 val = readl(rtcdev->base + CONTROL_REG);
+
+	val &= ~(CONTROL_ALARM_ON_BIT | CONTROL_STOP_BIT);
+	val |= CONTROL_ALARM_OFF_BIT;
+	writel(val, rtcdev->base + CONTROL_REG);
+	/*
+	 * Ensure that the posted write to the CONTROL_REG register completed before
+	 * returning from this function. Not doing this may result in the interrupt
+	 * only being cleared some time after this function returns.
+	 */
+	(void)readl(rtcdev->base + CONTROL_REG);
+}
+
+static void mpfs_rtc_calendar_mode(struct mpfs_rtc_dev *rtcdev)
+{
+	u32 val;
+	u32 rtc_running;
+
+	val = readl(rtcdev->base + MODE_REG);
+	val |= MODE_CLOCK_CALENDAR;
+
+	rtc_running = readl(rtcdev->base + CONTROL_REG);
+	if (rtc_running & CONTROL_RUNNING_BIT) {
+		/* Stop the RTC in order to change the mode register content. */
+		mpfs_rtc_stop(rtcdev);
+		writel(val, rtcdev->base + MODE_REG);
+		mpfs_rtc_start(rtcdev);
+	} else {
+		writel(val, rtcdev->base + MODE_REG);
+	}
+}
+
+static int mpfs_rtc_readtime(struct device *dev, struct rtc_time *tm)
+{
+	struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
+
+	tm->tm_sec = readl(rtcdev->base + SECONDS_REG);
+	tm->tm_min = readl(rtcdev->base + MINUTES_REG);
+	tm->tm_hour = readl(rtcdev->base + HOURS_REG);
+	tm->tm_mday = readl(rtcdev->base + DAY_REG);
+	tm->tm_mon   = readl(rtcdev->base + MONTH_REG) - 1;
+	tm->tm_wday  = readl(rtcdev->base + WEEKDAY_REG) - 1;
+	tm->tm_year  = readl(rtcdev->base + YEAR_REG) + YEAR_OFFSET;
+
+	return 0;
+}
+
+static int mpfs_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+	struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
+	u32 val;
+	u32 prog;
+
+	writel(tm->tm_year - YEAR_OFFSET, rtcdev->base + YEAR_REG);
+	writel(tm->tm_wday + 1, rtcdev->base + WEEKDAY_REG);
+	writel(tm->tm_mon + 1, rtcdev->base + MONTH_REG);
+	writel(tm->tm_mday, rtcdev->base + DAY_REG);
+	writel(tm->tm_hour, rtcdev->base + HOURS_REG);
+	writel(tm->tm_min, rtcdev->base + MINUTES_REG);
+	writel(tm->tm_sec, rtcdev->base + SECONDS_REG);
+
+	val = readl(rtcdev->base + CONTROL_REG);
+	val &= ~CONTROL_STOP_BIT;
+	val |= CONTROL_UPLOAD_BIT;
+	writel(val, rtcdev->base + CONTROL_REG);
+
+	do {
+		prog = readl(rtcdev->base + CONTROL_REG);
+		prog &= CONTROL_UPLOAD_BIT;
+	} while (prog);
+
+	mpfs_rtc_start(rtcdev);
+	return 0;
+}
+
+static int mpfs_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
+	u32 mode = readl(rtcdev->base + MODE_REG);
+	u32 val;
+
+	if (mode & MODE_WAKE_EN_BIT)
+		alrm->enabled = true;
+	else
+		alrm->enabled = false;
+
+	val = readl(rtcdev->base + ALARM_LOWER_REG);
+	alrm->time.tm_sec = (val & 0xff);
+	val >>= 8;
+	alrm->time.tm_min = (val & 0xff);
+	val >>= 8;
+	alrm->time.tm_hour = (val & 0xff);
+	val >>= 8;
+	alrm->time.tm_mday = (val & 0xff);
+
+	val = readl(rtcdev->base + ALARM_UPPER_REG);
+	alrm->time.tm_mon = (val & 0xff) - 1;
+	val >>= 8;
+	alrm->time.tm_year = (val & 0xff) + YEAR_OFFSET;
+	val >>= 8;
+	alrm->time.tm_wday = (val & 0xff) - 1;
+
+	return 0;
+}
+
+static int mpfs_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
+	u32 val;
+	u32 mode;
+	u32 mask;
+	u32 ctrl;
+
+	/* Disable the alarm before updating */
+	ctrl = readl(rtcdev->base + CONTROL_REG);
+	ctrl |= CONTROL_ALARM_OFF_BIT;
+	writel(ctrl, rtcdev->base + CONTROL_REG);
+
+	/* Set alarm and compare lower registers. */
+	val = alrm->time.tm_sec |
+	      alrm->time.tm_min << 8 |
+	      alrm->time.tm_hour << 16 |
+	      alrm->time.tm_mday << 24;
+	mask = 0xffffffff;
+
+	writel(val, rtcdev->base + ALARM_LOWER_REG);
+	writel(mask, rtcdev->base + COMPARE_LOWER_REG);
+
+	val = (alrm->time.tm_mon + 1) |
+	      (alrm->time.tm_year - YEAR_OFFSET) << 8;
+	mask = 0x000ffff;
+
+	writel(val, rtcdev->base + ALARM_UPPER_REG);
+	writel(mask, rtcdev->base + COMPARE_UPPER_REG);
+
+	/* Configure the RTC to enable the alarm. */
+	if (alrm->enabled) {
+		mode = MODE_CLOCK_CALENDAR | MODE_WAKE_EN_BIT | MODE_WAKE_CONTINUE_BIT;
+		/* Enable the alarm */
+		ctrl &= ~CONTROL_ALARM_OFF_BIT;
+		ctrl |= CONTROL_ALARM_ON_BIT;
+	}
+	ctrl &= ~CONTROL_STOP_BIT;
+	ctrl |= CONTROL_START_BIT;
+	writel(ctrl, rtcdev->base + CONTROL_REG);
+	writel(mode, rtcdev->base + MODE_REG);
+
+	return 0;
+}
+
+static int mpfs_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+	struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
+	u32 ctrl;
+	u32 mode;
+
+	ctrl = readl(rtcdev->base + CONTROL_REG);
+	mode = readl(rtcdev->base + MODE_REG);
+	ctrl &= ~(CONTROL_ALARM_ON_BIT | CONTROL_ALARM_OFF_BIT | CONTROL_STOP_BIT);
+
+	if (enabled)
+		ctrl |= CONTROL_ALARM_ON_BIT;
+	else
+		ctrl |= CONTROL_ALARM_OFF_BIT;
+
+	writel(ctrl, rtcdev->base + CONTROL_REG);
+
+	return 0;
+}
+
+static void mpfs_rtc_set_prescaler(struct mpfs_rtc_dev *rtcdev, unsigned int prescaler)
+{
+	writel(prescaler, rtcdev->base + PRESCALER_REG);
+}
+
+static inline struct clk *mpfs_rtc_init_clk(struct device *dev)
+{
+	struct clk *clk;
+	int ret;
+
+	clk = devm_clk_get(dev, "rtc");
+	if (IS_ERR(clk))
+		return clk;
+
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		return ERR_PTR(ret);
+
+	devm_add_action_or_reset(dev, (void (*) (void *))clk_disable_unprepare, clk);
+
+	return clk;
+}
+
+static irqreturn_t mpfs_rtc_wakeup_irq_handler(int irq, void *d)
+{
+	struct mpfs_rtc_dev *rtcdev = d;
+	unsigned long pending;
+
+	pending = readl(rtcdev->base + CONTROL_REG);
+	pending &= CONTROL_ALARM_ON_BIT;
+	mpfs_rtc_clear_irq(rtcdev);
+
+	/* its an alarm */
+	rtc_update_irq(rtcdev->rtc, 1, RTC_IRQF | RTC_AF);
+
+	return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops mpfs_rtc_ops = {
+	.read_time		= mpfs_rtc_readtime,
+	.set_time		= mpfs_rtc_settime,
+	.read_alarm		= mpfs_rtc_readalarm,
+	.set_alarm		= mpfs_rtc_setalarm,
+	.alarm_irq_enable	= mpfs_rtc_alarm_irq_enable,
+};
+
+static void mpfs_rtc_init(struct mpfs_rtc_dev *rtcdev)
+{
+	u32 ctrl;
+
+	mpfs_rtc_set_prescaler(rtcdev, rtcdev->prescaler);
+
+	mpfs_rtc_stop(rtcdev);
+	mpfs_rtc_calendar_mode(rtcdev);
+
+	writel(0, rtcdev->base + ALARM_LOWER_REG);
+	writel(0, rtcdev->base + ALARM_UPPER_REG);
+	writel(0, rtcdev->base + COMPARE_LOWER_REG);
+	writel(0, rtcdev->base + COMPARE_UPPER_REG);
+
+	ctrl = readl(rtcdev->base + CONTROL_REG);
+	ctrl &= ~(CONTROL_RESET_BIT | CONTROL_STOP_BIT | CONTROL_START_BIT);
+	ctrl |= CONTROL_RESET_BIT | CONTROL_START_BIT;
+	writel(ctrl, rtcdev->base + CONTROL_REG);
+}
+
+static int __init mpfs_rtc_probe(struct platform_device *pdev)
+{
+	struct mpfs_rtc_dev *rtcdev;
+	struct clk *clk;
+	int ret;
+
+	rtcdev = devm_kzalloc(&pdev->dev, sizeof(struct mpfs_rtc_dev), GFP_KERNEL);
+	if (!rtcdev)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, rtcdev);
+
+	rtcdev->rtc = devm_rtc_allocate_device(&pdev->dev);
+	if (IS_ERR(rtcdev->rtc))
+		return PTR_ERR(rtcdev->rtc);
+
+	rtcdev->rtc->ops = &mpfs_rtc_ops;
+	rtcdev->rtc->range_max = U32_MAX;
+
+	clk = mpfs_rtc_init_clk(&pdev->dev);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	rtcdev->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(rtcdev->base)) {
+		dev_dbg(&pdev->dev, "invalid ioremap resources\n");
+		return PTR_ERR(rtcdev->base);
+	}
+
+	rtcdev->wakeup_irq = platform_get_irq(pdev, 0);
+	if (rtcdev->wakeup_irq <= 0) {
+		dev_dbg(&pdev->dev, "could not get wakeup irq\n");
+		return rtcdev->wakeup_irq;
+	}
+	ret = devm_request_irq(&pdev->dev, rtcdev->wakeup_irq, mpfs_rtc_wakeup_irq_handler, 0,
+			       dev_name(&pdev->dev), rtcdev);
+	if (ret) {
+		dev_dbg(&pdev->dev, "could not request wakeup irq\n");
+		return ret;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node, "prescaler", &rtcdev->prescaler);
+	if (ret)
+		rtcdev->prescaler = DEFAULT_PRESCALER;
+
+	if (rtcdev->prescaler > MAX_PRESCALER_COUNT) {
+		dev_dbg(&pdev->dev, "invalid prescaler %d\n", rtcdev->prescaler);
+		return -EPERM;
+	}
+
+	mpfs_rtc_init(rtcdev);
+
+	dev_info(&pdev->dev, "Microchip Polarfire SoC RTC\n");
+
+	device_init_wakeup(&pdev->dev, 1);
+
+	return devm_rtc_register_device(rtcdev->rtc);
+}
+
+static int mpfs_rtc_remove(struct platform_device *pdev)
+{
+	mpfs_rtc_alarm_irq_enable(&pdev->dev, 0);
+	device_init_wakeup(&pdev->dev, 0);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mpfs_rtc_suspend(struct device *dev)
+{
+	struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
+
+	/* leave the alarm on as a wake source */
+	if (device_may_wakeup(dev))
+		enable_irq_wake(rtcdev->wakeup_irq);
+	else
+		mpfs_rtc_alarm_irq_enable(dev, 0);
+
+	return 0;
+}
+
+static int mpfs_rtc_resume(struct device *dev)
+{
+	struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
+
+	/* alarms were left on as a wake source, turn them off */
+	if (device_may_wakeup(dev))
+		disable_irq_wake(rtcdev->wakeup_irq);
+	else
+		mpfs_rtc_alarm_irq_enable(dev, 1);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(mpfs_rtc_pm_ops, mpfs_rtc_suspend, mpfs_rtc_resume);
+
+static const struct of_device_id mpfs_rtc_of_match[] = {
+	{ .compatible = "microchip,mpfs-rtc" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, mpfs_rtc_of_match);
+
+static struct platform_driver mpfs_rtc_driver = {
+	.probe = mpfs_rtc_probe,
+	.remove = mpfs_rtc_remove,
+	.driver	= {
+		.name = "mpfs_rtc",
+		.pm = &mpfs_rtc_pm_ops,
+		.of_match_table = mpfs_rtc_of_match,
+	},
+};
+
+module_platform_driver(mpfs_rtc_driver);
+
+MODULE_DESCRIPTION("Real time clock for Microchip Polarfire SoC");
+MODULE_AUTHOR("Daire McNamara <daire.mcnamara@microchip.com>");
+MODULE_LICENSE("GPL v2");
-- 
2.25.1


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

* Re: [PATCH v1 1/2] dt-bindings: rtc: microchip: Add Microchip PolarFire host binding
  2021-05-12 11:11 ` [PATCH v1 1/2] dt-bindings: rtc: microchip: Add Microchip PolarFire host binding daire.mcnamara
@ 2021-05-12 18:35   ` Rob Herring
  2021-05-13  2:22   ` Rob Herring
  1 sibling, 0 replies; 6+ messages in thread
From: Rob Herring @ 2021-05-12 18:35 UTC (permalink / raw)
  To: daire.mcnamara
  Cc: lewis.hanly, david.abdurachmanov, conor.dooley, palmer,
	devicetree, a.zummo, alexandre.belloni, linux-rtc,
	padmarao.begari, cyril.jean, robh+dt

On Wed, 12 May 2021 12:11:32 +0100, daire.mcnamara@microchip.com wrote:
> From: Daire McNamara <daire.mcnamara@microchip.com>
> 
> Add device tree bindings for the Microchip PolarFire real-time
> clock controller
> 
> Signed-off-by: Daire McNamara <daire.mcnamara@microchip.com>
> ---
>  .../bindings/rtc/microchip,mfps-rtc.yaml      | 61 +++++++++++++++++++
>  1 file changed, 61 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.example.dts:19:18: fatal error: dt-bindings/clock/microchip,mpfs-clock.h: No such file or directory
   19 |         #include <dt-bindings/clock/microchip,mpfs-clock.h>
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[1]: *** [scripts/Makefile.lib:380: Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.example.dt.yaml] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1416: dt_binding_check] Error 2

See https://patchwork.ozlabs.org/patch/1477539

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


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

* Re: [PATCH v1 2/2] rtc: microchip: Add driver for Microchip PolarFire SoC
  2021-05-12 11:11 ` [PATCH v1 2/2] rtc: microchip: Add driver for Microchip PolarFire SoC daire.mcnamara
@ 2021-05-12 22:18   ` Alexandre Belloni
  0 siblings, 0 replies; 6+ messages in thread
From: Alexandre Belloni @ 2021-05-12 22:18 UTC (permalink / raw)
  To: daire.mcnamara
  Cc: a.zummo, linux-rtc, robh+dt, devicetree, palmer, cyril.jean,
	padmarao.begari, lewis.hanly, conor.dooley, david.abdurachmanov

Hello,

The subject should be:
rtc: Add driver for Microchip PolarFire SoC

On 12/05/2021 12:11:33+0100, daire.mcnamara@microchip.com wrote:
> From: Daire McNamara <daire.mcnamara@microchip.com>
> 
> Add support for built-in RTC on Microchip PolarFire SoC
> 
> Signed-off-by: Daire McNamara <daire.mcnamara@microchip.com>
> ---
>  drivers/rtc/Kconfig    |   7 +
>  drivers/rtc/Makefile   |   1 +
>  drivers/rtc/rtc-mpfs.c | 449 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 457 insertions(+)
>  create mode 100644 drivers/rtc/rtc-mpfs.c
> 
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index ce723dc54aa4..12e2308423ee 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -1655,6 +1655,13 @@ config RTC_DRV_MPC5121
>  	  This driver can also be built as a module. If so, the module
>  	  will be called rtc-mpc5121.
>  
> +config RTC_DRV_MPFS
> +	tristate "Microchip PolarFire SoC built-in RTC"
> +	depends on SOC_MICROCHIP_POLARFIRE
> +	help
> +	  If you say yes here you will get support for the
> +	  built-in RTC on MPFS.

MPFS is not really descriptive, can you spell it out completely?

> +++ b/drivers/rtc/rtc-mpfs.c

Same comment, rtc-mpfs.c is not very descriptive...

> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/rtc.h>
> +#include <linux/io.h>

Includes should be sorted alphabetically

> +
> +/*
> + * Device Specific Peripheral registers structures

Those are not structures, I don't think this comment is useful

> + */
> +#define CONTROL_REG		0x00
> +#define  CONTROL_RUNNING_BIT		BIT(0)
> +#define  CONTROL_START_BIT		BIT(0)
> +#define  CONTROL_STOP_BIT		BIT(1)
> +#define  CONTROL_ALARM_ON_BIT		BIT(2)
> +#define  CONTROL_ALARM_OFF_BIT		BIT(3)
> +#define  CONTROL_RESET_BIT		BIT(4)
> +#define  CONTROL_UPLOAD_BIT		BIT(5)
> +#define  CONTROL_WAKEUP_CLR_BIT		BIT(8)
> +#define  CONTROL_WAKEUP_SET_BIT		BIT(9)
> +#define  CONTROL_UPDATED_BIT		BIT(10)
> +#define  MPFS_RTC_NUM_IRQS		2
> +#define MODE_REG		0x04
> +#define  MODE_CLOCK_BIT			BIT(0)
> +#define   MODE_CLOCK_CALENDAR		1
> +#define  MODE_WAKE_EN_BIT		BIT(1)
> +#define  MODE_WAKE_RESET_BIT		BIT(2)
> +#define  MODE_WAKE_CONTINUE_BIT		BIT(3)
> +#define PRESCALER_REG		0x08
> +#define ALARM_LOWER_REG		0x0c
> +#define ALARM_UPPER_REG		0x10
> +#define COMPARE_LOWER_REG	0x14
> +#define COMPARE_UPPER_REG	0x18
> +#define DATETIME_LOWER_REG	0x20
> +#define DATETIME_UPPER_REG	0x24
> +#define SECONDS_REG		0x30
> +#define MINUTES_REG		0x34
> +#define HOURS_REG		0x38
> +#define DAY_REG			0x3c
> +#define MONTH_REG		0x40
> +#define YEAR_REG		0x44
> +#define WEEKDAY_REG		0x48
> +#define WEEK_REG		0x4c
> +
> +/*
> + * Linux counts from 1970 but tm_year starts at 1900, MPFS RTC counts from 2000
> + * Account for this difference
> + */
> +#define YEAR_OFFSET		(100)
> +
> +#define MAX_PRESCALER_COUNT	GENMASK(21, 0)
> +#define DEFAULT_PRESCALER	999999  /* (1Mhz / prescaler) -1 = 1Hz */
> +
> +struct mpfs_rtc_dev {
> +	struct rtc_device *rtc;
> +	void __iomem *base;
> +	int wakeup_irq;
> +	u32 prescaler;
> +};
> +
> +static void mpfs_rtc_stop(struct mpfs_rtc_dev *rtcdev)
> +{
> +	u32 ctrl;
> +
> +	ctrl = readl(rtcdev->base + CONTROL_REG);
> +	ctrl &= ~(CONTROL_STOP_BIT | CONTROL_START_BIT);
> +	ctrl |= CONTROL_STOP_BIT;
> +	ctrl |= CONTROL_ALARM_OFF_BIT;

stop and start then has the unexpected side effect that it disables the
alarm and this happens at boot time.

> +	writel(ctrl, rtcdev->base + CONTROL_REG);
> +}
> +
> +static void mpfs_rtc_start(struct mpfs_rtc_dev *rtcdev)
> +{
> +	u32 ctrl;
> +
> +	ctrl = readl(rtcdev->base + CONTROL_REG);
> +	ctrl &= ~(CONTROL_STOP_BIT | CONTROL_START_BIT);
> +	ctrl |= CONTROL_START_BIT;
> +	writel(ctrl, rtcdev->base + CONTROL_REG);
> +}
> +
> +static void mpfs_rtc_clear_irq(struct mpfs_rtc_dev *rtcdev)
> +{
> +	u32 val = readl(rtcdev->base + CONTROL_REG);
> +
> +	val &= ~(CONTROL_ALARM_ON_BIT | CONTROL_STOP_BIT);
> +	val |= CONTROL_ALARM_OFF_BIT;
> +	writel(val, rtcdev->base + CONTROL_REG);
> +	/*
> +	 * Ensure that the posted write to the CONTROL_REG register completed before
> +	 * returning from this function. Not doing this may result in the interrupt
> +	 * only being cleared some time after this function returns.
> +	 */
> +	(void)readl(rtcdev->base + CONTROL_REG);
> +}
> +
> +static void mpfs_rtc_calendar_mode(struct mpfs_rtc_dev *rtcdev)
> +{
> +	u32 val;
> +	u32 rtc_running;
> +
> +	val = readl(rtcdev->base + MODE_REG);
> +	val |= MODE_CLOCK_CALENDAR;
> +
> +	rtc_running = readl(rtcdev->base + CONTROL_REG);
> +	if (rtc_running & CONTROL_RUNNING_BIT) {
> +		/* Stop the RTC in order to change the mode register content. */
> +		mpfs_rtc_stop(rtcdev);

There is now way it is running at this point as your are stopping the
RTC unconditionally before calling the function.

> +		writel(val, rtcdev->base + MODE_REG);
> +		mpfs_rtc_start(rtcdev);
> +	} else {
> +		writel(val, rtcdev->base + MODE_REG);
> +	}
> +}
> +


> +static void mpfs_rtc_set_prescaler(struct mpfs_rtc_dev *rtcdev, unsigned int prescaler)
> +{
> +	writel(prescaler, rtcdev->base + PRESCALER_REG);
> +}
> +
> +static inline struct clk *mpfs_rtc_init_clk(struct device *dev)

Why is that inline? This should probably be simply part of the probe
function.

> +{
> +	struct clk *clk;
> +	int ret;
> +
> +	clk = devm_clk_get(dev, "rtc");
> +	if (IS_ERR(clk))
> +		return clk;
> +
> +	ret = clk_prepare_enable(clk);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	devm_add_action_or_reset(dev, (void (*) (void *))clk_disable_unprepare, clk);
> +
> +	return clk;
> +}
> +
> +static irqreturn_t mpfs_rtc_wakeup_irq_handler(int irq, void *d)
> +{
> +	struct mpfs_rtc_dev *rtcdev = d;
> +	unsigned long pending;
> +
> +	pending = readl(rtcdev->base + CONTROL_REG);
> +	pending &= CONTROL_ALARM_ON_BIT;
> +	mpfs_rtc_clear_irq(rtcdev);
> +
> +	/* its an alarm */

This comment is not really useful.

> +	rtc_update_irq(rtcdev->rtc, 1, RTC_IRQF | RTC_AF);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static const struct rtc_class_ops mpfs_rtc_ops = {
> +	.read_time		= mpfs_rtc_readtime,
> +	.set_time		= mpfs_rtc_settime,
> +	.read_alarm		= mpfs_rtc_readalarm,
> +	.set_alarm		= mpfs_rtc_setalarm,
> +	.alarm_irq_enable	= mpfs_rtc_alarm_irq_enable,
> +};
> +
> +static void mpfs_rtc_init(struct mpfs_rtc_dev *rtcdev)
> +{
> +	u32 ctrl;
> +
> +	mpfs_rtc_set_prescaler(rtcdev, rtcdev->prescaler);
> +
> +	mpfs_rtc_stop(rtcdev);
> +	mpfs_rtc_calendar_mode(rtcdev);
> +
> +	writel(0, rtcdev->base + ALARM_LOWER_REG);
> +	writel(0, rtcdev->base + ALARM_UPPER_REG);
> +	writel(0, rtcdev->base + COMPARE_LOWER_REG);
> +	writel(0, rtcdev->base + COMPARE_UPPER_REG);
> +
> +	ctrl = readl(rtcdev->base + CONTROL_REG);
> +	ctrl &= ~(CONTROL_RESET_BIT | CONTROL_STOP_BIT | CONTROL_START_BIT);
> +	ctrl |= CONTROL_RESET_BIT | CONTROL_START_BIT;
> +	writel(ctrl, rtcdev->base + CONTROL_REG);

Is this resetting the RTC? If this is the case, then the RTC and the
driver are basically useless as the whole goal of the RTC is to keep
time when the platform is off.

> +}
> +
> +static int __init mpfs_rtc_probe(struct platform_device *pdev)

__init on a probe function is a bug

> +{
> +	struct mpfs_rtc_dev *rtcdev;
> +	struct clk *clk;
> +	int ret;
> +
> +	rtcdev = devm_kzalloc(&pdev->dev, sizeof(struct mpfs_rtc_dev), GFP_KERNEL);
> +	if (!rtcdev)
> +		return -ENOMEM;
> +
> +	platform_set_drvdata(pdev, rtcdev);
> +
> +	rtcdev->rtc = devm_rtc_allocate_device(&pdev->dev);
> +	if (IS_ERR(rtcdev->rtc))
> +		return PTR_ERR(rtcdev->rtc);
> +
> +	rtcdev->rtc->ops = &mpfs_rtc_ops;
> +	rtcdev->rtc->range_max = U32_MAX;

Are you sure about that? I guess this is wrong, especially since you are
opencoding the offset instead of properly setting range_min and I think
this is the whole goal of switching to calendar mode which seems to be
2000 to 2255.

Actually, I'm not sure why you are using calendar mode as binary mode
would be more efficient, won't require offsetting and goes up to year 280707

> +
> +	clk = mpfs_rtc_init_clk(&pdev->dev);
> +	if (IS_ERR(clk))
> +		return PTR_ERR(clk);
> +
> +	rtcdev->base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(rtcdev->base)) {
> +		dev_dbg(&pdev->dev, "invalid ioremap resources\n");
> +		return PTR_ERR(rtcdev->base);
> +	}
> +
> +	rtcdev->wakeup_irq = platform_get_irq(pdev, 0);
> +	if (rtcdev->wakeup_irq <= 0) {
> +		dev_dbg(&pdev->dev, "could not get wakeup irq\n");
> +		return rtcdev->wakeup_irq;
> +	}
> +	ret = devm_request_irq(&pdev->dev, rtcdev->wakeup_irq, mpfs_rtc_wakeup_irq_handler, 0,
> +			       dev_name(&pdev->dev), rtcdev);
> +	if (ret) {
> +		dev_dbg(&pdev->dev, "could not request wakeup irq\n");
> +		return ret;
> +	}
> +
> +	ret = of_property_read_u32(pdev->dev.of_node, "prescaler", &rtcdev->prescaler);
> +	if (ret)
> +		rtcdev->prescaler = DEFAULT_PRESCALER;
> +
> +	if (rtcdev->prescaler > MAX_PRESCALER_COUNT) {
> +		dev_dbg(&pdev->dev, "invalid prescaler %d\n", rtcdev->prescaler);
> +		return -EPERM;
> +	}
> +

You don't have to read the prescaler value from the device tree,
instead, you should provide a second clock, RTCCLK and use its rate to
calculate the prescaler.


> +	mpfs_rtc_init(rtcdev);
> +

Again don't do that, this renders the RTC useless.

> +	dev_info(&pdev->dev, "Microchip Polarfire SoC RTC\n");
> +

The core already prints out messages, don't litter the kernel logs.

> +	device_init_wakeup(&pdev->dev, 1);
> +
> +	return devm_rtc_register_device(rtcdev->rtc);
> +}
> +
> +static int mpfs_rtc_remove(struct platform_device *pdev)
> +{
> +	mpfs_rtc_alarm_irq_enable(&pdev->dev, 0);

If the RTC can power up the platform, this should not be done.

> +	device_init_wakeup(&pdev->dev, 0);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int mpfs_rtc_suspend(struct device *dev)
> +{
> +	struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
> +
> +	/* leave the alarm on as a wake source */
> +	if (device_may_wakeup(dev))
> +		enable_irq_wake(rtcdev->wakeup_irq);
> +	else
> +		mpfs_rtc_alarm_irq_enable(dev, 0);

Because you call device_init_wakeup(), device_may_wakeup will always be
true.

> +
> +	return 0;
> +}
> +
> +static int mpfs_rtc_resume(struct device *dev)
> +{
> +	struct mpfs_rtc_dev *rtcdev = dev_get_drvdata(dev);
> +
> +	/* alarms were left on as a wake source, turn them off */
> +	if (device_may_wakeup(dev))
> +		disable_irq_wake(rtcdev->wakeup_irq);
> +	else
> +		mpfs_rtc_alarm_irq_enable(dev, 1);
> +

ditto

> +	return 0;
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(mpfs_rtc_pm_ops, mpfs_rtc_suspend, mpfs_rtc_resume);

Please use dev_pm_set_wake_irq to avoid opencoding all of that.

> +
> +static const struct of_device_id mpfs_rtc_of_match[] = {
> +	{ .compatible = "microchip,mpfs-rtc" },
> +	{ }
> +};
> +
> +MODULE_DEVICE_TABLE(of, mpfs_rtc_of_match);
> +
> +static struct platform_driver mpfs_rtc_driver = {
> +	.probe = mpfs_rtc_probe,
> +	.remove = mpfs_rtc_remove,
> +	.driver	= {
> +		.name = "mpfs_rtc",
> +		.pm = &mpfs_rtc_pm_ops,
> +		.of_match_table = mpfs_rtc_of_match,
> +	},
> +};
> +
> +module_platform_driver(mpfs_rtc_driver);
> +
> +MODULE_DESCRIPTION("Real time clock for Microchip Polarfire SoC");
> +MODULE_AUTHOR("Daire McNamara <daire.mcnamara@microchip.com>");
> +MODULE_LICENSE("GPL v2");
> -- 
> 2.25.1
> 

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

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

* Re: [PATCH v1 1/2] dt-bindings: rtc: microchip: Add Microchip PolarFire host binding
  2021-05-12 11:11 ` [PATCH v1 1/2] dt-bindings: rtc: microchip: Add Microchip PolarFire host binding daire.mcnamara
  2021-05-12 18:35   ` Rob Herring
@ 2021-05-13  2:22   ` Rob Herring
  1 sibling, 0 replies; 6+ messages in thread
From: Rob Herring @ 2021-05-13  2:22 UTC (permalink / raw)
  To: daire.mcnamara
  Cc: a.zummo, alexandre.belloni, linux-rtc, devicetree, palmer,
	cyril.jean, padmarao.begari, lewis.hanly, conor.dooley,
	david.abdurachmanov

On Wed, May 12, 2021 at 12:11:32PM +0100, daire.mcnamara@microchip.com wrote:
> From: Daire McNamara <daire.mcnamara@microchip.com>
> 
> Add device tree bindings for the Microchip PolarFire real-time
> clock controller
> 
> Signed-off-by: Daire McNamara <daire.mcnamara@microchip.com>
> ---
>  .../bindings/rtc/microchip,mfps-rtc.yaml      | 61 +++++++++++++++++++
>  1 file changed, 61 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml
> 
> diff --git a/Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml b/Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml
> new file mode 100644
> index 000000000000..c82b3e7351e0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml
> @@ -0,0 +1,61 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/rtc/microchip,mfps-rtc.yaml#
> +
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Microchip PolarFire Soc (MPFS) RTC Device Tree Bindings
> +
> +allOf:
> +  - $ref: "rtc.yaml#"
> +
> +maintainers:
> +  - Daire McNamara <daire.mcnamara@microchip.com>
> +  - Lewis Hanly <lewis.hanly@microchip.com>
> +
> +properties:
> +  compatible:
> +    enum:
> +      - microchip,mpfs-rtc
> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  prescaler:
> +    maxItems: 1

An array?

Needs a type, constraints, and vendor prefix.

> +
> +  clocks:
> +    maxItems: 1
> +
> +  clock-names:
> +    items:
> +      - const: rtc

Kind of a pointless name. You don't need *-names when there is only 1.

> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +  - clocks
> +  - clock-names
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/microchip,mpfs-clock.h>
> +    soc {
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +        rtc@20124000 {
> +            compatible = "microchip,mpfs-rtc";
> +            reg = <0 0x20124000 0 0x1000>;
> +            clocks = <&clkcfg CLK_RTC>;
> +            clock-names = "rtc";
> +            interrupts = <80>;
> +        };
> +    };
> +...
> -- 
> 2.25.1
> 

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

end of thread, other threads:[~2021-05-13  2:22 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-12 11:11 [PATCH v1 0/2] rtc: microchip: Add driver for PolarFire SoC daire.mcnamara
2021-05-12 11:11 ` [PATCH v1 1/2] dt-bindings: rtc: microchip: Add Microchip PolarFire host binding daire.mcnamara
2021-05-12 18:35   ` Rob Herring
2021-05-13  2:22   ` Rob Herring
2021-05-12 11:11 ` [PATCH v1 2/2] rtc: microchip: Add driver for Microchip PolarFire SoC daire.mcnamara
2021-05-12 22:18   ` Alexandre Belloni

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.