879 lines
26 KiB
Diff
879 lines
26 KiB
Diff
From b0e70738cf7a9a1c9b4e10c3aec7cea6004ed9a4 Mon Sep 17 00:00:00 2001
|
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
|
Date: Thu, 3 Nov 2022 16:04:20 +0100
|
|
Subject: [PATCH 18/22] v5.15-stm32mp-r2 RESET-RTC
|
|
|
|
Signed-off-by: Romuald JEANNE <romuald.jeanne@st.com>
|
|
---
|
|
.../devicetree/bindings/rtc/st,stm32-rtc.yaml | 37 ++
|
|
drivers/rtc/Kconfig | 1 +
|
|
drivers/rtc/rtc-stm32.c | 365 ++++++++++++++----
|
|
include/dt-bindings/reset/stm32mp1-resets.h | 24 +-
|
|
include/dt-bindings/reset/stm32mp13-resets.h | 100 +++++
|
|
include/dt-bindings/rtc/rtc-stm32.h | 14 +
|
|
6 files changed, 459 insertions(+), 82 deletions(-)
|
|
create mode 100644 include/dt-bindings/reset/stm32mp13-resets.h
|
|
create mode 100644 include/dt-bindings/rtc/rtc-stm32.h
|
|
|
|
diff --git a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml
|
|
index 5456604b1c14..d94e1d13d908 100644
|
|
--- a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml
|
|
+++ b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml
|
|
@@ -52,6 +52,20 @@ properties:
|
|
override default rtc_ck parent clock phandle of the new parent clock of rtc_ck
|
|
maxItems: 1
|
|
|
|
+ st,lsco:
|
|
+ $ref: "/schemas/types.yaml#/definitions/uint32"
|
|
+ description: |
|
|
+ To select and enable RTC Low Speed Clock Output.
|
|
+ Refer to <include/dt-bindings/rtc/rtc-stm32.h> for the supported values.
|
|
+ Pinctrl state named "default" may be defined to reserve pin for RTC output.
|
|
+
|
|
+ st,alarm:
|
|
+ $ref: "/schemas/types.yaml#/definitions/uint32"
|
|
+ description: |
|
|
+ To select and enable RTC Alarm A output.
|
|
+ Refer to <include/dt-bindings/rtc/rtc-stm32.h> for the supported values.
|
|
+ Pinctrl state named "default" may be defined to reserve pin for RTC output.
|
|
+
|
|
allOf:
|
|
- if:
|
|
properties:
|
|
@@ -65,6 +79,12 @@ allOf:
|
|
minItems: 1
|
|
maxItems: 1
|
|
|
|
+ st,lsco:
|
|
+ maxItems: 0
|
|
+
|
|
+ st,alarm:
|
|
+ maxItems: 0
|
|
+
|
|
clock-names: false
|
|
|
|
required:
|
|
@@ -82,6 +102,12 @@ allOf:
|
|
minItems: 2
|
|
maxItems: 2
|
|
|
|
+ st,lsco:
|
|
+ maxItems: 0
|
|
+
|
|
+ st,alarm:
|
|
+ maxItems: 0
|
|
+
|
|
required:
|
|
- clock-names
|
|
- st,syscfg
|
|
@@ -101,6 +127,12 @@ allOf:
|
|
assigned-clocks: false
|
|
assigned-clock-parents: false
|
|
|
|
+ st,lsco:
|
|
+ maxItems: 1
|
|
+
|
|
+ st,alarm:
|
|
+ maxItems: 1
|
|
+
|
|
required:
|
|
- clock-names
|
|
|
|
@@ -129,12 +161,17 @@ examples:
|
|
|
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
|
#include <dt-bindings/clock/stm32mp1-clks.h>
|
|
+ #include <dt-bindings/rtc/rtc-stm32.h>
|
|
rtc@5c004000 {
|
|
compatible = "st,stm32mp1-rtc";
|
|
reg = <0x5c004000 0x400>;
|
|
clocks = <&rcc RTCAPB>, <&rcc RTC>;
|
|
clock-names = "pclk", "rtc_ck";
|
|
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
|
|
+ st,alarm = <RTC_OUT1>;
|
|
+ st,lsco = <RTC_OUT2_RMP>;
|
|
+ pinctrl-0 = <&rtc_out1_pins_a &rtc_out2_rmp_pins_a>;
|
|
+ pinctrl-names = "default";
|
|
};
|
|
|
|
...
|
|
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
|
|
index e1bc5214494e..57ef1efdfc3c 100644
|
|
--- a/drivers/rtc/Kconfig
|
|
+++ b/drivers/rtc/Kconfig
|
|
@@ -1867,6 +1867,7 @@ config RTC_DRV_R7301
|
|
config RTC_DRV_STM32
|
|
tristate "STM32 RTC"
|
|
select REGMAP_MMIO
|
|
+ depends on COMMON_CLK
|
|
depends on ARCH_STM32 || COMPILE_TEST
|
|
help
|
|
If you say yes here you get support for the STM32 On-Chip
|
|
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
|
|
index ac9e228b56d0..20896b4b4641 100644
|
|
--- a/drivers/rtc/rtc-stm32.c
|
|
+++ b/drivers/rtc/rtc-stm32.c
|
|
@@ -5,7 +5,10 @@
|
|
*/
|
|
|
|
#include <linux/bcd.h>
|
|
+#include <linux/bitfield.h>
|
|
#include <linux/clk.h>
|
|
+#include <linux/clk-provider.h>
|
|
+#include <linux/errno.h>
|
|
#include <linux/iopoll.h>
|
|
#include <linux/ioport.h>
|
|
#include <linux/mfd/syscon.h>
|
|
@@ -15,6 +18,8 @@
|
|
#include <linux/regmap.h>
|
|
#include <linux/rtc.h>
|
|
|
|
+#include <dt-bindings/rtc/rtc-stm32.h>
|
|
+
|
|
#define DRIVER_NAME "stm32_rtc"
|
|
|
|
/* STM32_RTC_TR bit fields */
|
|
@@ -39,6 +44,13 @@
|
|
#define STM32_RTC_CR_FMT BIT(6)
|
|
#define STM32_RTC_CR_ALRAE BIT(8)
|
|
#define STM32_RTC_CR_ALRAIE BIT(12)
|
|
+#define STM32_RTC_CR_COSEL BIT(19)
|
|
+#define STM32_RTC_CR_OSEL GENMASK(22, 21)
|
|
+#define STM32_RTC_CR_OSEL_ALARM_A FIELD_PREP(STM32_RTC_CR_OSEL, 0x01)
|
|
+#define STM32_RTC_CR_COE BIT(23)
|
|
+#define STM32_RTC_CR_TAMPOE BIT(26)
|
|
+#define STM32_RTC_CR_TAMPALRM_TYPE BIT(30)
|
|
+#define STM32_RTC_CR_OUT2EN BIT(31)
|
|
|
|
/* STM32_RTC_ISR/STM32_RTC_ICSR bit fields */
|
|
#define STM32_RTC_ISR_ALRAWF BIT(0)
|
|
@@ -75,6 +87,12 @@
|
|
/* STM32_RTC_SR/_SCR bit fields */
|
|
#define STM32_RTC_SR_ALRA BIT(0)
|
|
|
|
+/* STM32_RTC_CFGR bit fields */
|
|
+#define STM32_RTC_CFGR_OUT2_RMP BIT(0)
|
|
+#define STM32_RTC_CFGR_LSCOEN GENMASK(2, 1)
|
|
+#define STM32_RTC_CFGR_LSCOEN_OUT1 1
|
|
+#define STM32_RTC_CFGR_LSCOEN_OUT2_RMP 2
|
|
+
|
|
/* STM32_RTC_VERR bit fields */
|
|
#define STM32_RTC_VERR_MINREV_SHIFT 0
|
|
#define STM32_RTC_VERR_MINREV GENMASK(3, 0)
|
|
@@ -89,6 +107,9 @@
|
|
/* Max STM32 RTC register offset is 0x3FC */
|
|
#define UNDEF_REG 0xFFFF
|
|
|
|
+/* STM32 RTC driver time helpers */
|
|
+#define SEC_PER_DAY (24 * 60 * 60)
|
|
+
|
|
struct stm32_rtc;
|
|
|
|
struct stm32_rtc_registers {
|
|
@@ -101,6 +122,7 @@ struct stm32_rtc_registers {
|
|
u16 wpr;
|
|
u16 sr;
|
|
u16 scr;
|
|
+ u16 cfgr;
|
|
u16 verr;
|
|
};
|
|
|
|
@@ -114,7 +136,9 @@ struct stm32_rtc_data {
|
|
void (*clear_events)(struct stm32_rtc *rtc, unsigned int flags);
|
|
bool has_pclk;
|
|
bool need_dbp;
|
|
- bool has_wakeirq;
|
|
+ bool has_lsco;
|
|
+ bool has_alarm_out;
|
|
+ bool need_accuracy;
|
|
};
|
|
|
|
struct stm32_rtc {
|
|
@@ -127,9 +151,88 @@ struct stm32_rtc {
|
|
struct clk *rtc_ck;
|
|
const struct stm32_rtc_data *data;
|
|
int irq_alarm;
|
|
- int wakeirq_alarm;
|
|
+ int lsco;
|
|
+ struct clk *clk_lsco;
|
|
+ int out_alarm;
|
|
};
|
|
|
|
+/*
|
|
+ * -------------------------------------------------------------------------
|
|
+ * | TAMPOE | OSEL[1:0] | COE | OUT2EN | RTC_OUT1 | RTC_OUT2 |
|
|
+ * | | | | | | or RTC_OUT2_RMP |
|
|
+ * |-------------------------------------------------------------------------|
|
|
+ * | 0 | 00 | 0 | 0 or 1 | - | - |
|
|
+ * |--------|-----------|-----|--------|------------------|------------------|
|
|
+ * | 0 | 00 | 1 | 0 | CALIB | - |
|
|
+ * |--------|-----------|-----|--------|------------------|------------------|
|
|
+ * | 0 or 1 | !=00 | 0 | 0 | TAMPALRM | - |
|
|
+ * |--------|-----------|-----|--------|------------------|------------------|
|
|
+ * | 0 | 00 | 1 | 1 | - | CALIB |
|
|
+ * |--------|-----------|-----|--------|------------------|------------------|
|
|
+ * | 0 or 1 | !=00 | 0 | 1 | - | TAMPALRM |
|
|
+ * |--------|-----------|-----|--------|------------------|------------------|
|
|
+ * | 0 or 1 | !=00 | 1 | 1 | TAMPALRM | CALIB |
|
|
+ * -------------------------------------------------------------------------
|
|
+ */
|
|
+static int stm32_rtc_clk_lsco_check_availability(struct stm32_rtc *rtc)
|
|
+{
|
|
+ struct stm32_rtc_registers regs = rtc->data->regs;
|
|
+ unsigned int cr = readl_relaxed(rtc->base + regs.cr);
|
|
+ unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr);
|
|
+ unsigned int calib = STM32_RTC_CR_COE;
|
|
+ unsigned int tampalrm = STM32_RTC_CR_TAMPOE | STM32_RTC_CR_OSEL;
|
|
+
|
|
+ switch (rtc->lsco) {
|
|
+ case RTC_OUT1:
|
|
+ if ((!(cr & STM32_RTC_CR_OUT2EN) &&
|
|
+ ((cr & calib) || cr & tampalrm)) ||
|
|
+ ((cr & calib) && (cr & tampalrm)))
|
|
+ return -EBUSY;
|
|
+ break;
|
|
+ case RTC_OUT2_RMP:
|
|
+ if ((cr & STM32_RTC_CR_OUT2EN) &&
|
|
+ (cfgr & STM32_RTC_CFGR_OUT2_RMP) &&
|
|
+ ((cr & calib) || (cr & tampalrm)))
|
|
+ return -EBUSY;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (clk_get_rate(rtc->rtc_ck) != 32768)
|
|
+ return -ERANGE;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int stm32_rtc_clk_lsco_register(struct platform_device *pdev)
|
|
+{
|
|
+ struct stm32_rtc *rtc = platform_get_drvdata(pdev);
|
|
+ struct stm32_rtc_registers regs = rtc->data->regs;
|
|
+ u8 lscoen;
|
|
+ int ret;
|
|
+
|
|
+ ret = stm32_rtc_clk_lsco_check_availability(rtc);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ lscoen = (rtc->lsco == RTC_OUT1) ? STM32_RTC_CFGR_LSCOEN_OUT1 :
|
|
+ STM32_RTC_CFGR_LSCOEN_OUT2_RMP;
|
|
+
|
|
+ rtc->clk_lsco = clk_register_gate(&pdev->dev, "rtc_lsco",
|
|
+ __clk_get_name(rtc->rtc_ck),
|
|
+ CLK_IGNORE_UNUSED | CLK_IS_CRITICAL,
|
|
+ rtc->base + regs.cfgr, lscoen,
|
|
+ 0, NULL);
|
|
+ if (IS_ERR(rtc->clk_lsco))
|
|
+ return PTR_ERR(rtc->clk_lsco);
|
|
+
|
|
+ of_clk_add_provider(pdev->dev.of_node,
|
|
+ of_clk_src_simple_get, rtc->clk_lsco);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc)
|
|
{
|
|
const struct stm32_rtc_registers *regs = &rtc->data->regs;
|
|
@@ -145,6 +248,73 @@ static void stm32_rtc_wpr_lock(struct stm32_rtc *rtc)
|
|
writel_relaxed(RTC_WPR_WRONG_KEY, rtc->base + regs->wpr);
|
|
}
|
|
|
|
+static void stm32_rtc_clk_lsco_disable(struct platform_device *pdev)
|
|
+{
|
|
+ struct stm32_rtc *rtc = platform_get_drvdata(pdev);
|
|
+ struct stm32_rtc_registers regs = rtc->data->regs;
|
|
+ unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr);
|
|
+
|
|
+ writel_relaxed(cfgr &= ~STM32_RTC_CFGR_LSCOEN, rtc->base + regs.cfgr);
|
|
+}
|
|
+
|
|
+static int stm32_rtc_out_alarm_config(struct platform_device *pdev)
|
|
+{
|
|
+ struct stm32_rtc *rtc = platform_get_drvdata(pdev);
|
|
+ struct stm32_rtc_registers regs = rtc->data->regs;
|
|
+ unsigned int cr = readl_relaxed(rtc->base + regs.cr);
|
|
+ unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr);
|
|
+
|
|
+ cr &= ~STM32_RTC_CR_OSEL;
|
|
+ cr |= STM32_RTC_CR_OSEL_ALARM_A;
|
|
+ cr &= ~STM32_RTC_CR_TAMPOE;
|
|
+ cr &= ~STM32_RTC_CR_COE;
|
|
+ cr &= ~STM32_RTC_CR_TAMPALRM_TYPE;
|
|
+
|
|
+ switch (rtc->out_alarm) {
|
|
+ case RTC_OUT1:
|
|
+ cr &= ~STM32_RTC_CR_OUT2EN;
|
|
+ cfgr &= ~STM32_RTC_CFGR_OUT2_RMP;
|
|
+ break;
|
|
+ case RTC_OUT2:
|
|
+ cr |= STM32_RTC_CR_OUT2EN;
|
|
+ cfgr &= ~STM32_RTC_CFGR_OUT2_RMP;
|
|
+ break;
|
|
+ case RTC_OUT2_RMP:
|
|
+ cr |= STM32_RTC_CR_OUT2EN;
|
|
+ cfgr |= STM32_RTC_CFGR_OUT2_RMP;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ stm32_rtc_wpr_unlock(rtc);
|
|
+ writel_relaxed(cr, rtc->base + regs.cr);
|
|
+ writel_relaxed(cfgr, rtc->base + regs.cfgr);
|
|
+ stm32_rtc_wpr_lock(rtc);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void stm32_rtc_out_alarm_disable(struct platform_device *pdev)
|
|
+{
|
|
+ struct stm32_rtc *rtc = platform_get_drvdata(pdev);
|
|
+ struct stm32_rtc_registers regs = rtc->data->regs;
|
|
+ unsigned int cr = readl_relaxed(rtc->base + regs.cr);
|
|
+ unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr);
|
|
+
|
|
+ cr &= ~STM32_RTC_CR_OSEL;
|
|
+ cr &= ~STM32_RTC_CR_TAMPOE;
|
|
+ cr &= ~STM32_RTC_CR_COE;
|
|
+ cr &= ~STM32_RTC_CR_TAMPALRM_TYPE;
|
|
+ cr &= ~STM32_RTC_CR_OUT2EN;
|
|
+ cfgr &= ~STM32_RTC_CFGR_OUT2_RMP;
|
|
+
|
|
+ stm32_rtc_wpr_unlock(rtc);
|
|
+ writel_relaxed(cr, rtc->base + regs.cr);
|
|
+ writel_relaxed(cfgr, rtc->base + regs.cfgr);
|
|
+ stm32_rtc_wpr_lock(rtc);
|
|
+}
|
|
+
|
|
static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
|
|
{
|
|
const struct stm32_rtc_registers *regs = &rtc->data->regs;
|
|
@@ -160,10 +330,9 @@ static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
|
|
* slowest rtc_ck frequency may be 32kHz and highest should be
|
|
* 1MHz, we poll every 10 us with a timeout of 100ms.
|
|
*/
|
|
- return readl_relaxed_poll_timeout_atomic(
|
|
- rtc->base + regs->isr,
|
|
- isr, (isr & STM32_RTC_ISR_INITF),
|
|
- 10, 100000);
|
|
+ return readl_relaxed_poll_timeout_atomic(rtc->base + regs->isr, isr,
|
|
+ (isr & STM32_RTC_ISR_INITF),
|
|
+ 10, 100000);
|
|
}
|
|
|
|
return 0;
|
|
@@ -427,40 +596,42 @@ static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
|
return 0;
|
|
}
|
|
|
|
-static int stm32_rtc_valid_alrm(struct stm32_rtc *rtc, struct rtc_time *tm)
|
|
+static int stm32_rtc_valid_alrm(struct device *dev, struct rtc_time *tm)
|
|
{
|
|
- const struct stm32_rtc_registers *regs = &rtc->data->regs;
|
|
- int cur_day, cur_mon, cur_year, cur_hour, cur_min, cur_sec;
|
|
- unsigned int dr = readl_relaxed(rtc->base + regs->dr);
|
|
- unsigned int tr = readl_relaxed(rtc->base + regs->tr);
|
|
-
|
|
- cur_day = (dr & STM32_RTC_DR_DATE) >> STM32_RTC_DR_DATE_SHIFT;
|
|
- cur_mon = (dr & STM32_RTC_DR_MONTH) >> STM32_RTC_DR_MONTH_SHIFT;
|
|
- cur_year = (dr & STM32_RTC_DR_YEAR) >> STM32_RTC_DR_YEAR_SHIFT;
|
|
- cur_sec = (tr & STM32_RTC_TR_SEC) >> STM32_RTC_TR_SEC_SHIFT;
|
|
- cur_min = (tr & STM32_RTC_TR_MIN) >> STM32_RTC_TR_MIN_SHIFT;
|
|
- cur_hour = (tr & STM32_RTC_TR_HOUR) >> STM32_RTC_TR_HOUR_SHIFT;
|
|
+ static struct rtc_time now;
|
|
+ time64_t max_alarm_time64;
|
|
+ int max_day_forward;
|
|
+ int next_month;
|
|
+ int next_year;
|
|
|
|
/*
|
|
* Assuming current date is M-D-Y H:M:S.
|
|
* RTC alarm can't be set on a specific month and year.
|
|
* So the valid alarm range is:
|
|
* M-D-Y H:M:S < alarm <= (M+1)-D-Y H:M:S
|
|
- * with a specific case for December...
|
|
*/
|
|
- if ((((tm->tm_year > cur_year) &&
|
|
- (tm->tm_mon == 0x1) && (cur_mon == 0x12)) ||
|
|
- ((tm->tm_year == cur_year) &&
|
|
- (tm->tm_mon <= cur_mon + 1))) &&
|
|
- ((tm->tm_mday > cur_day) ||
|
|
- ((tm->tm_mday == cur_day) &&
|
|
- ((tm->tm_hour > cur_hour) ||
|
|
- ((tm->tm_hour == cur_hour) && (tm->tm_min > cur_min)) ||
|
|
- ((tm->tm_hour == cur_hour) && (tm->tm_min == cur_min) &&
|
|
- (tm->tm_sec >= cur_sec))))))
|
|
- return 0;
|
|
+ stm32_rtc_read_time(dev, &now);
|
|
|
|
- return -EINVAL;
|
|
+ /*
|
|
+ * Find the next month and the year of the next month.
|
|
+ * Note: tm_mon and next_month are from 0 to 11
|
|
+ */
|
|
+ next_month = now.tm_mon + 1;
|
|
+ if (next_month == 12) {
|
|
+ next_month = 0;
|
|
+ next_year = now.tm_year + 1;
|
|
+ } else {
|
|
+ next_year = now.tm_year;
|
|
+ }
|
|
+
|
|
+ /* Find the maximum limit of alarm in days. */
|
|
+ max_day_forward = rtc_month_days(now.tm_mon, now.tm_year)
|
|
+ - now.tm_mday
|
|
+ + min(rtc_month_days(next_month, next_year), now.tm_mday);
|
|
+
|
|
+ /* Convert to timestamp and compare the alarm time and its upper limit */
|
|
+ max_alarm_time64 = rtc_tm_to_time64(&now) + max_day_forward * SEC_PER_DAY;
|
|
+ return rtc_tm_to_time64(tm) <= max_alarm_time64 ? 0 : -EINVAL;
|
|
}
|
|
|
|
static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|
@@ -471,17 +642,17 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|
unsigned int cr, isr, alrmar;
|
|
int ret = 0;
|
|
|
|
- tm2bcd(tm);
|
|
-
|
|
/*
|
|
* RTC alarm can't be set on a specific date, unless this date is
|
|
* up to the same day of month next month.
|
|
*/
|
|
- if (stm32_rtc_valid_alrm(rtc, tm) < 0) {
|
|
+ if (stm32_rtc_valid_alrm(dev, tm) < 0) {
|
|
dev_err(dev, "Alarm can be set only on upcoming month.\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
+ tm2bcd(tm);
|
|
+
|
|
alrmar = 0;
|
|
/* tm_year and tm_mon are not used because not supported by RTC */
|
|
alrmar |= (tm->tm_mday << STM32_RTC_ALRMXR_DATE_SHIFT) &
|
|
@@ -547,7 +718,9 @@ static void stm32_rtc_clear_events(struct stm32_rtc *rtc,
|
|
static const struct stm32_rtc_data stm32_rtc_data = {
|
|
.has_pclk = false,
|
|
.need_dbp = true,
|
|
- .has_wakeirq = false,
|
|
+ .has_lsco = false,
|
|
+ .has_alarm_out = false,
|
|
+ .need_accuracy = false,
|
|
.regs = {
|
|
.tr = 0x00,
|
|
.dr = 0x04,
|
|
@@ -558,6 +731,7 @@ static const struct stm32_rtc_data stm32_rtc_data = {
|
|
.wpr = 0x24,
|
|
.sr = 0x0C, /* set to ISR offset to ease alarm management */
|
|
.scr = UNDEF_REG,
|
|
+ .cfgr = UNDEF_REG,
|
|
.verr = UNDEF_REG,
|
|
},
|
|
.events = {
|
|
@@ -569,7 +743,9 @@ static const struct stm32_rtc_data stm32_rtc_data = {
|
|
static const struct stm32_rtc_data stm32h7_rtc_data = {
|
|
.has_pclk = true,
|
|
.need_dbp = true,
|
|
- .has_wakeirq = false,
|
|
+ .has_lsco = false,
|
|
+ .has_alarm_out = false,
|
|
+ .need_accuracy = false,
|
|
.regs = {
|
|
.tr = 0x00,
|
|
.dr = 0x04,
|
|
@@ -580,6 +756,7 @@ static const struct stm32_rtc_data stm32h7_rtc_data = {
|
|
.wpr = 0x24,
|
|
.sr = 0x0C, /* set to ISR offset to ease alarm management */
|
|
.scr = UNDEF_REG,
|
|
+ .cfgr = UNDEF_REG,
|
|
.verr = UNDEF_REG,
|
|
},
|
|
.events = {
|
|
@@ -600,7 +777,9 @@ static void stm32mp1_rtc_clear_events(struct stm32_rtc *rtc,
|
|
static const struct stm32_rtc_data stm32mp1_data = {
|
|
.has_pclk = true,
|
|
.need_dbp = false,
|
|
- .has_wakeirq = true,
|
|
+ .has_lsco = true,
|
|
+ .has_alarm_out = true,
|
|
+ .need_accuracy = true,
|
|
.regs = {
|
|
.tr = 0x00,
|
|
.dr = 0x04,
|
|
@@ -611,6 +790,7 @@ static const struct stm32_rtc_data stm32mp1_data = {
|
|
.wpr = 0x24,
|
|
.sr = 0x50,
|
|
.scr = 0x5C,
|
|
+ .cfgr = 0x60,
|
|
.verr = 0x3F4,
|
|
},
|
|
.events = {
|
|
@@ -633,7 +813,7 @@ static int stm32_rtc_init(struct platform_device *pdev,
|
|
const struct stm32_rtc_registers *regs = &rtc->data->regs;
|
|
unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr;
|
|
unsigned int rate;
|
|
- int ret = 0;
|
|
+ int ret;
|
|
|
|
rate = clk_get_rate(rtc->rtc_ck);
|
|
|
|
@@ -641,18 +821,32 @@ static int stm32_rtc_init(struct platform_device *pdev,
|
|
pred_a_max = STM32_RTC_PRER_PRED_A >> STM32_RTC_PRER_PRED_A_SHIFT;
|
|
pred_s_max = STM32_RTC_PRER_PRED_S >> STM32_RTC_PRER_PRED_S_SHIFT;
|
|
|
|
- for (pred_a = pred_a_max; pred_a + 1 > 0; pred_a--) {
|
|
- pred_s = (rate / (pred_a + 1)) - 1;
|
|
+ if (rate > (pred_a_max + 1) * (pred_s_max + 1)) {
|
|
+ dev_err(&pdev->dev, "rtc_ck rate is too high: %dHz\n", rate);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (rtc->data->need_accuracy) {
|
|
+ for (pred_a = 0; pred_a <= pred_a_max; pred_a++) {
|
|
+ pred_s = (rate / (pred_a + 1)) - 1;
|
|
+
|
|
+ if (pred_s <= pred_s_max && ((pred_s + 1) * (pred_a + 1)) == rate)
|
|
+ break;
|
|
+ }
|
|
+ } else {
|
|
+ for (pred_a = pred_a_max; pred_a + 1 > 0; pred_a--) {
|
|
+ pred_s = (rate / (pred_a + 1)) - 1;
|
|
|
|
- if (((pred_s + 1) * (pred_a + 1)) == rate)
|
|
- break;
|
|
+ if (((pred_s + 1) * (pred_a + 1)) == rate)
|
|
+ break;
|
|
+ }
|
|
}
|
|
|
|
/*
|
|
* Can't find a 1Hz, so give priority to RTC power consumption
|
|
* by choosing the higher possible value for prediv_a
|
|
*/
|
|
- if ((pred_s > pred_s_max) || (pred_a > pred_a_max)) {
|
|
+ if (pred_s > pred_s_max || pred_a > pred_a_max) {
|
|
pred_a = pred_a_max;
|
|
pred_s = (rate / (pred_a + 1)) - 1;
|
|
|
|
@@ -661,6 +855,20 @@ static int stm32_rtc_init(struct platform_device *pdev,
|
|
"fast" : "slow");
|
|
}
|
|
|
|
+ cr = readl_relaxed(rtc->base + regs->cr);
|
|
+
|
|
+ prer = readl_relaxed(rtc->base + regs->prer);
|
|
+ prer &= STM32_RTC_PRER_PRED_S | STM32_RTC_PRER_PRED_A;
|
|
+
|
|
+ pred_s = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) &
|
|
+ STM32_RTC_PRER_PRED_S;
|
|
+ pred_a = (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) &
|
|
+ STM32_RTC_PRER_PRED_A;
|
|
+
|
|
+ /* quit if there is nothing to initialize */
|
|
+ if ((cr & STM32_RTC_CR_FMT) == 0 && prer == (pred_s | pred_a))
|
|
+ return 0;
|
|
+
|
|
stm32_rtc_wpr_unlock(rtc);
|
|
|
|
ret = stm32_rtc_enter_init_mode(rtc);
|
|
@@ -670,13 +878,10 @@ static int stm32_rtc_init(struct platform_device *pdev,
|
|
goto end;
|
|
}
|
|
|
|
- prer = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) & STM32_RTC_PRER_PRED_S;
|
|
- writel_relaxed(prer, rtc->base + regs->prer);
|
|
- prer |= (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) & STM32_RTC_PRER_PRED_A;
|
|
- writel_relaxed(prer, rtc->base + regs->prer);
|
|
+ writel_relaxed(pred_s, rtc->base + regs->prer);
|
|
+ writel_relaxed(pred_a | pred_s, rtc->base + regs->prer);
|
|
|
|
/* Force 24h time format */
|
|
- cr = readl_relaxed(rtc->base + regs->cr);
|
|
cr &= ~STM32_RTC_CR_FMT;
|
|
writel_relaxed(cr, rtc->base + regs->cr);
|
|
|
|
@@ -736,13 +941,15 @@ static int stm32_rtc_probe(struct platform_device *pdev)
|
|
} else {
|
|
rtc->pclk = devm_clk_get(&pdev->dev, "pclk");
|
|
if (IS_ERR(rtc->pclk)) {
|
|
- dev_err(&pdev->dev, "no pclk clock");
|
|
+ if (PTR_ERR(rtc->pclk) != -EPROBE_DEFER)
|
|
+ dev_err(&pdev->dev, "no pclk clock");
|
|
return PTR_ERR(rtc->pclk);
|
|
}
|
|
rtc->rtc_ck = devm_clk_get(&pdev->dev, "rtc_ck");
|
|
}
|
|
if (IS_ERR(rtc->rtc_ck)) {
|
|
- dev_err(&pdev->dev, "no rtc_ck clock");
|
|
+ if (PTR_ERR(rtc->rtc_ck) != -EPROBE_DEFER)
|
|
+ dev_err(&pdev->dev, "no rtc_ck clock");
|
|
return PTR_ERR(rtc->rtc_ck);
|
|
}
|
|
|
|
@@ -779,19 +986,12 @@ static int stm32_rtc_probe(struct platform_device *pdev)
|
|
}
|
|
|
|
ret = device_init_wakeup(&pdev->dev, true);
|
|
- if (rtc->data->has_wakeirq) {
|
|
- rtc->wakeirq_alarm = platform_get_irq(pdev, 1);
|
|
- if (rtc->wakeirq_alarm > 0) {
|
|
- ret = dev_pm_set_dedicated_wake_irq(&pdev->dev,
|
|
- rtc->wakeirq_alarm);
|
|
- } else {
|
|
- ret = rtc->wakeirq_alarm;
|
|
- if (rtc->wakeirq_alarm == -EPROBE_DEFER)
|
|
- goto err;
|
|
- }
|
|
- }
|
|
if (ret)
|
|
- dev_warn(&pdev->dev, "alarm can't wake up the system: %d", ret);
|
|
+ goto err;
|
|
+
|
|
+ ret = dev_pm_set_wake_irq(&pdev->dev, rtc->irq_alarm);
|
|
+ if (ret)
|
|
+ goto err;
|
|
|
|
platform_set_drvdata(pdev, rtc);
|
|
|
|
@@ -814,6 +1014,33 @@ static int stm32_rtc_probe(struct platform_device *pdev)
|
|
goto err;
|
|
}
|
|
|
|
+ if (rtc->data->has_alarm_out) {
|
|
+ ret = of_property_read_s32(pdev->dev.of_node, "st,alarm", &rtc->out_alarm);
|
|
+ if (!ret) {
|
|
+ ret = stm32_rtc_out_alarm_config(pdev);
|
|
+ } else {
|
|
+ stm32_rtc_out_alarm_disable(pdev);
|
|
+ rtc->out_alarm = ret;
|
|
+ dev_dbg(&pdev->dev, "No alarm out: %d\n", ret);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (rtc->data->has_lsco) {
|
|
+ ret = of_property_read_s32(pdev->dev.of_node,
|
|
+ "st,lsco", &rtc->lsco);
|
|
+ if (!ret) {
|
|
+ ret = stm32_rtc_clk_lsco_register(pdev);
|
|
+ if (ret)
|
|
+ dev_warn(&pdev->dev,
|
|
+ "LSCO clock registration failed: %d\n",
|
|
+ ret);
|
|
+ } else {
|
|
+ stm32_rtc_clk_lsco_disable(pdev);
|
|
+ rtc->lsco = ret;
|
|
+ dev_dbg(&pdev->dev, "No LSCO clock: %d\n", ret);
|
|
+ }
|
|
+ }
|
|
+
|
|
/*
|
|
* If INITS flag is reset (calendar year field set to 0x00), calendar
|
|
* must be initialized
|
|
@@ -852,6 +1079,9 @@ static int stm32_rtc_remove(struct platform_device *pdev)
|
|
const struct stm32_rtc_registers *regs = &rtc->data->regs;
|
|
unsigned int cr;
|
|
|
|
+ if (!IS_ERR_OR_NULL(rtc->clk_lsco))
|
|
+ clk_unregister_gate(rtc->clk_lsco);
|
|
+
|
|
/* Disable interrupts */
|
|
stm32_rtc_wpr_unlock(rtc);
|
|
cr = readl_relaxed(rtc->base + regs->cr);
|
|
@@ -881,9 +1111,6 @@ static int stm32_rtc_suspend(struct device *dev)
|
|
if (rtc->data->has_pclk)
|
|
clk_disable_unprepare(rtc->pclk);
|
|
|
|
- if (device_may_wakeup(dev))
|
|
- return enable_irq_wake(rtc->irq_alarm);
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
@@ -905,15 +1132,13 @@ static int stm32_rtc_resume(struct device *dev)
|
|
return ret;
|
|
}
|
|
|
|
- if (device_may_wakeup(dev))
|
|
- return disable_irq_wake(rtc->irq_alarm);
|
|
-
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
-static SIMPLE_DEV_PM_OPS(stm32_rtc_pm_ops,
|
|
- stm32_rtc_suspend, stm32_rtc_resume);
|
|
+static const struct dev_pm_ops stm32_rtc_pm_ops = {
|
|
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_rtc_suspend, stm32_rtc_resume)
|
|
+};
|
|
|
|
static struct platform_driver stm32_rtc_driver = {
|
|
.probe = stm32_rtc_probe,
|
|
diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h
|
|
index f3a0ed317835..bdbf9e253015 100644
|
|
--- a/include/dt-bindings/reset/stm32mp1-resets.h
|
|
+++ b/include/dt-bindings/reset/stm32mp1-resets.h
|
|
@@ -107,17 +107,17 @@
|
|
#define GPIOK_R 19786
|
|
|
|
/* SCMI reset domain identifiers */
|
|
-#define RST_SCMI0_SPI6 0
|
|
-#define RST_SCMI0_I2C4 1
|
|
-#define RST_SCMI0_I2C6 2
|
|
-#define RST_SCMI0_USART1 3
|
|
-#define RST_SCMI0_STGEN 4
|
|
-#define RST_SCMI0_GPIOZ 5
|
|
-#define RST_SCMI0_CRYP1 6
|
|
-#define RST_SCMI0_HASH1 7
|
|
-#define RST_SCMI0_RNG1 8
|
|
-#define RST_SCMI0_MDMA 9
|
|
-#define RST_SCMI0_MCU 10
|
|
-#define RST_SCMI0_MCU_HOLD_BOOT 11
|
|
+#define RST_SCMI_SPI6 0
|
|
+#define RST_SCMI_I2C4 1
|
|
+#define RST_SCMI_I2C6 2
|
|
+#define RST_SCMI_USART1 3
|
|
+#define RST_SCMI_STGEN 4
|
|
+#define RST_SCMI_GPIOZ 5
|
|
+#define RST_SCMI_CRYP1 6
|
|
+#define RST_SCMI_HASH1 7
|
|
+#define RST_SCMI_RNG1 8
|
|
+#define RST_SCMI_MDMA 9
|
|
+#define RST_SCMI_MCU 10
|
|
+#define RST_SCMI_MCU_HOLD_BOOT 11
|
|
|
|
#endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */
|
|
diff --git a/include/dt-bindings/reset/stm32mp13-resets.h b/include/dt-bindings/reset/stm32mp13-resets.h
|
|
new file mode 100644
|
|
index 000000000000..934864e90da6
|
|
--- /dev/null
|
|
+++ b/include/dt-bindings/reset/stm32mp13-resets.h
|
|
@@ -0,0 +1,100 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
|
|
+/*
|
|
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
|
|
+ * Author: Gabriel Fernandez <gabriel.fernandez@st.com> for STMicroelectronics.
|
|
+ */
|
|
+
|
|
+#ifndef _DT_BINDINGS_STM32MP13_RESET_H_
|
|
+#define _DT_BINDINGS_STM32MP13_RESET_H_
|
|
+
|
|
+#define TIM2_R 13568
|
|
+#define TIM3_R 13569
|
|
+#define TIM4_R 13570
|
|
+#define TIM5_R 13571
|
|
+#define TIM6_R 13572
|
|
+#define TIM7_R 13573
|
|
+#define LPTIM1_R 13577
|
|
+#define SPI2_R 13579
|
|
+#define SPI3_R 13580
|
|
+#define USART3_R 13583
|
|
+#define UART4_R 13584
|
|
+#define UART5_R 13585
|
|
+#define UART7_R 13586
|
|
+#define UART8_R 13587
|
|
+#define I2C1_R 13589
|
|
+#define I2C2_R 13590
|
|
+#define SPDIF_R 13594
|
|
+#define TIM1_R 13632
|
|
+#define TIM8_R 13633
|
|
+#define SPI1_R 13640
|
|
+#define USART6_R 13645
|
|
+#define SAI1_R 13648
|
|
+#define SAI2_R 13649
|
|
+#define DFSDM_R 13652
|
|
+#define FDCAN_R 13656
|
|
+#define LPTIM2_R 13696
|
|
+#define LPTIM3_R 13697
|
|
+#define LPTIM4_R 13698
|
|
+#define LPTIM5_R 13699
|
|
+#define SYSCFG_R 13707
|
|
+#define VREF_R 13709
|
|
+#define DTS_R 13712
|
|
+#define PMBCTRL_R 13713
|
|
+#define LTDC_R 13760
|
|
+#define DCMIPP_R 13761
|
|
+#define DDRPERFM_R 13768
|
|
+#define USBPHY_R 13776
|
|
+#define STGEN_R 13844
|
|
+#define USART1_R 13888
|
|
+#define USART2_R 13889
|
|
+#define SPI4_R 13890
|
|
+#define SPI5_R 13891
|
|
+#define I2C3_R 13892
|
|
+#define I2C4_R 13893
|
|
+#define I2C5_R 13894
|
|
+#define TIM12_R 13895
|
|
+#define TIM13_R 13896
|
|
+#define TIM14_R 13897
|
|
+#define TIM15_R 13898
|
|
+#define TIM16_R 13899
|
|
+#define TIM17_R 13900
|
|
+#define DMA1_R 13952
|
|
+#define DMA2_R 13953
|
|
+#define DMAMUX1_R 13954
|
|
+#define DMA3_R 13955
|
|
+#define DMAMUX2_R 13956
|
|
+#define ADC1_R 13957
|
|
+#define ADC2_R 13958
|
|
+#define USBO_R 13960
|
|
+#define GPIOA_R 14080
|
|
+#define GPIOB_R 14081
|
|
+#define GPIOC_R 14082
|
|
+#define GPIOD_R 14083
|
|
+#define GPIOE_R 14084
|
|
+#define GPIOF_R 14085
|
|
+#define GPIOG_R 14086
|
|
+#define GPIOH_R 14087
|
|
+#define GPIOI_R 14088
|
|
+#define TSC_R 14095
|
|
+#define PKA_R 14146
|
|
+#define SAES_R 14147
|
|
+#define CRYP1_R 14148
|
|
+#define HASH1_R 14149
|
|
+#define RNG1_R 14150
|
|
+#define AXIMC_R 14160
|
|
+#define MDMA_R 14208
|
|
+#define MCE_R 14209
|
|
+#define ETH1MAC_R 14218
|
|
+#define FMC_R 14220
|
|
+#define QSPI_R 14222
|
|
+#define SDMMC1_R 14224
|
|
+#define SDMMC2_R 14225
|
|
+#define CRC1_R 14228
|
|
+#define USBH_R 14232
|
|
+#define ETH2MAC_R 14238
|
|
+
|
|
+/* SCMI reset domain identifiers */
|
|
+#define RST_SCMI_LTDC 0
|
|
+#define RST_SCMI_MDMA 1
|
|
+
|
|
+#endif /* _DT_BINDINGS_STM32MP13_RESET_H_ */
|
|
diff --git a/include/dt-bindings/rtc/rtc-stm32.h b/include/dt-bindings/rtc/rtc-stm32.h
|
|
new file mode 100644
|
|
index 000000000000..2fd78c2e62d4
|
|
--- /dev/null
|
|
+++ b/include/dt-bindings/rtc/rtc-stm32.h
|
|
@@ -0,0 +1,14 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 */
|
|
+/*
|
|
+ * This header provides constants for STM32_RTC bindings.
|
|
+ */
|
|
+
|
|
+#ifndef _DT_BINDINGS_RTC_RTC_STM32_H
|
|
+#define _DT_BINDINGS_RTC_RTC_STM32_H
|
|
+
|
|
+#define RTC_NO_OUT 0
|
|
+#define RTC_OUT1 1
|
|
+#define RTC_OUT2 2
|
|
+#define RTC_OUT2_RMP 3
|
|
+
|
|
+#endif
|
|
--
|
|
2.17.1
|
|
|