Skip to content

Commit 462d432

Browse files
committed
drivers: irtc: Updated rtc driver to support NXP RT700.
1. Update nxp irtc driver to fix issue in init and alarm function. 2. Update RTC device tree binding to support "share-counter". 3. Update RT700 dtsi to support rtc0 for cpu0 and rtc1 for cpu1. 4. Update readme. Signed-off-by: Holt Sun <[email protected]>
1 parent 4bd1d39 commit 462d432

File tree

8 files changed

+149
-40
lines changed

8 files changed

+149
-40
lines changed

boards/nxp/mimxrt700_evk/mimxrt700_evk_mimxrt798s_cm33_cpu0.dts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
pwm-0 = &sc_timer;
2525
i2s-codec-tx = &sai0;
2626
i2s-tx = &sai0;
27+
rtc = &rtc0;
2728
};
2829

2930
chosen {
@@ -245,3 +246,7 @@ zephyr_udc0: &usb0 {
245246
};
246247

247248
p3t1755dp_ard_i2c_interface: &flexcomm8_lpi2c8 {};
249+
250+
&rtc0 {
251+
status = "okay";
252+
};

boards/nxp/mimxrt700_evk/mimxrt700_evk_mimxrt798s_cm33_cpu1.dts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
led0 = &red_led;
2020
sw0 = &user_button_1;
2121
ambient-temp0 = &p3t1755;
22+
rtc = &rtc1;
2223
};
2324

2425
chosen {
@@ -97,3 +98,7 @@
9798
status = "okay";
9899
};
99100
};
101+
102+
&rtc1 {
103+
status = "okay";
104+
};

drivers/rtc/rtc_nxp_irtc.c

Lines changed: 99 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 NXP
2+
* Copyright 2024-2025 NXP
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -15,7 +15,9 @@ struct nxp_irtc_config {
1515
RTC_Type *base;
1616
void (*irq_config_func)(const struct device *dev);
1717
bool is_output_clock_enabled;
18+
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(clock_src)
1819
uint8_t clock_src;
20+
#endif
1921
uint8_t alarm_match_flag;
2022
};
2123

@@ -31,9 +33,8 @@ struct nxp_irtc_data {
3133
/* The IRTC Offset is 2112 instead of 1900 [2112 - 1900] -> [212] */
3234
#define RTC_NXP_IRTC_YEAR_OFFSET 212
3335

34-
#define RTC_NXP_GET_REG_FIELD(_reg, _name, _field) \
35-
((_reg->_name & RTC_##_name##_##_field##_MASK) >> \
36-
RTC_##_name##_##_field##_SHIFT)
36+
#define RTC_NXP_GET_REG_FIELD(_reg, _name, _field) \
37+
((_reg->_name & RTC_##_name##_##_field##_MASK) >> RTC_##_name##_##_field##_SHIFT)
3738

3839
/*
3940
* The runtime where this is accessed is unknown so we force a lock on the registers then force an
@@ -62,6 +63,12 @@ static void nxp_irtc_unlock_registers(RTC_Type *reg)
6263

6364
static int nxp_irtc_set_time(const struct device *dev, const struct rtc_time *timeptr)
6465
{
66+
#if DT_PROP(DT_ALIAS(rtc), share_counter)
67+
ARG_UNUSED(dev);
68+
ARG_UNUSED(timeptr);
69+
70+
return -EPERM;
71+
#else
6572
const struct nxp_irtc_config *config = dev->config;
6673
struct nxp_irtc_data *data = dev->data;
6774
RTC_Type *irtc_reg = config->base;
@@ -79,12 +86,12 @@ static int nxp_irtc_set_time(const struct device *dev, const struct rtc_time *ti
7986
nxp_irtc_unlock_registers(irtc_reg);
8087
irtc_reg->SECONDS = RTC_SECONDS_SEC_CNT(timeptr->tm_sec);
8188

82-
irtc_reg->HOURMIN = RTC_HOURMIN_MIN_CNT(timeptr->tm_min) |
83-
RTC_HOURMIN_HOUR_CNT(timeptr->tm_hour);
89+
irtc_reg->HOURMIN =
90+
RTC_HOURMIN_MIN_CNT(timeptr->tm_min) | RTC_HOURMIN_HOUR_CNT(timeptr->tm_hour);
8491

8592
/* 1 is valid for rtc_time.tm_wday property but is out of bounds for IRTC registers */
8693
irtc_reg->DAYS = RTC_DAYS_DAY_CNT(timeptr->tm_mday) |
87-
(timeptr->tm_wday == -1 ? 0 : RTC_DAYS_DOW(timeptr->tm_wday));
94+
(timeptr->tm_wday == -1 ? 0 : RTC_DAYS_DOW(timeptr->tm_wday));
8895

8996
irtc_reg->YEARMON = RTC_YEARMON_MON_CNT(calc_month) | RTC_YEARMON_YROFST(calc_year);
9097

@@ -96,6 +103,7 @@ static int nxp_irtc_set_time(const struct device *dev, const struct rtc_time *ti
96103
irq_unlock(key);
97104

98105
return 0;
106+
#endif
99107
}
100108

101109
static int nxp_irtc_get_time(const struct device *dev, struct rtc_time *timeptr)
@@ -112,8 +120,8 @@ static int nxp_irtc_get_time(const struct device *dev, struct rtc_time *timeptr)
112120
timeptr->tm_wday = RTC_NXP_GET_REG_FIELD(irtc_reg, DAYS, DOW);
113121
timeptr->tm_mday = RTC_NXP_GET_REG_FIELD(irtc_reg, DAYS, DAY_CNT);
114122
timeptr->tm_mon = RTC_NXP_GET_REG_FIELD(irtc_reg, YEARMON, MON_CNT) - 1;
115-
timeptr->tm_year = (int8_t)RTC_NXP_GET_REG_FIELD(irtc_reg, YEARMON, YROFST) +
116-
RTC_NXP_IRTC_YEAR_OFFSET;
123+
timeptr->tm_year =
124+
(int8_t)RTC_NXP_GET_REG_FIELD(irtc_reg, YEARMON, YROFST) + RTC_NXP_IRTC_YEAR_OFFSET;
117125
if (data->is_dst_enabled) {
118126
timeptr->tm_isdst =
119127
((irtc_reg->CTRL & RTC_CTRL_DST_EN_MASK) >> RTC_CTRL_DST_EN_SHIFT);
@@ -186,19 +194,25 @@ static int nxp_irtc_alarm_set_time(const struct device *dev, uint16_t id, uint16
186194
}
187195

188196
/* Clearing out the ALARM Flag Field then setting the correct value */
189-
irtc_reg->CTRL &= ~(0xC);
190-
switch (mask) {
191-
case 0x0F:
192-
irtc_reg->CTRL |= RTC_CTRL_ALM_MATCH(0x4);
197+
irtc_reg->CTRL &= ~((uint16_t)RTC_CTRL_ALM_MATCH_MASK);
198+
uint8_t year_month_day_mask = (mask & (BIT(3) | BIT(4) | BIT(5))) >> 3;
199+
200+
switch (year_month_day_mask) {
201+
case 0x00:
202+
irtc_reg->CTRL |= RTC_CTRL_ALM_MATCH(0x0);
193203
break;
194-
case 0x1F:
195-
irtc_reg->CTRL |= RTC_CTRL_ALM_MATCH(0x8);
204+
case 0x01:
205+
irtc_reg->CTRL |= RTC_CTRL_ALM_MATCH(0x1);
196206
break;
197-
case 0x3F:
198-
irtc_reg->CTRL |= RTC_CTRL_ALM_MATCH(0xC);
207+
case 0x03:
208+
irtc_reg->CTRL |= RTC_CTRL_ALM_MATCH(0x2);
209+
break;
210+
case 0x07:
211+
irtc_reg->CTRL |= RTC_CTRL_ALM_MATCH(0x3);
199212
break;
200213
default:
201-
irtc_reg->CTRL |= RTC_CTRL_ALM_MATCH(0x0);
214+
irq_unlock(key);
215+
return -EINVAL;
202216
}
203217

204218
/* Enabling Alarm Interrupts */
@@ -218,39 +232,45 @@ static int nxp_irtc_alarm_get_time(const struct device *dev, uint16_t id, uint16
218232
RTC_Type *irtc_reg = config->base;
219233
uint16_t curr_alarm_mask = data->alarm_mask;
220234
uint16_t return_mask = 0;
235+
uint16_t tmp_hourmin = irtc_reg->ALM_HOURMIN;
236+
uint16_t tmp_yearmon = irtc_reg->ALM_YEARMON;
221237

222238
if (id != 0 || !timeptr) {
223239
return -EINVAL;
224240
}
225241

242+
memset(timeptr, 0, sizeof(struct rtc_time));
243+
226244
if (curr_alarm_mask & RTC_ALARM_TIME_MASK_SECOND) {
227-
timeptr->tm_sec = RTC_NXP_GET_REG_FIELD(irtc_reg, ALM_SECONDS, ALM_SEC);
245+
timeptr->tm_sec = (irtc_reg->ALM_SECONDS) & RTC_ALM_SECONDS_ALM_SEC_MASK;
228246
return_mask |= RTC_ALARM_TIME_MASK_SECOND;
229247
}
230248

231249
if (curr_alarm_mask & RTC_ALARM_TIME_MASK_MINUTE) {
232-
timeptr->tm_min = RTC_NXP_GET_REG_FIELD(irtc_reg, HOURMIN, MIN_CNT);
250+
timeptr->tm_min = tmp_hourmin & RTC_ALM_HOURMIN_ALM_MIN_MASK;
233251
return_mask |= RTC_ALARM_TIME_MASK_MINUTE;
234252
}
235253

236254
if (curr_alarm_mask & RTC_ALARM_TIME_MASK_HOUR) {
237-
timeptr->tm_hour = RTC_NXP_GET_REG_FIELD(irtc_reg, HOURMIN, HOUR_CNT);
255+
timeptr->tm_hour = ((tmp_hourmin & RTC_ALM_HOURMIN_ALM_HOUR_MASK) >>
256+
RTC_ALM_HOURMIN_ALM_HOUR_SHIFT);
238257
return_mask |= RTC_ALARM_TIME_MASK_HOUR;
239258
}
240259

241260
if (curr_alarm_mask & RTC_ALARM_TIME_MASK_MONTHDAY) {
242-
timeptr->tm_mday = RTC_NXP_GET_REG_FIELD(irtc_reg, DAYS, DAY_CNT);
261+
timeptr->tm_mday = (irtc_reg->ALM_DAYS) & RTC_ALM_DAYS_ALM_DAY_MASK;
243262
return_mask |= RTC_ALARM_TIME_MASK_MONTHDAY;
244263
}
245264

246265
if (curr_alarm_mask & RTC_ALARM_TIME_MASK_MONTH) {
247-
timeptr->tm_mon = RTC_NXP_GET_REG_FIELD(irtc_reg, YEARMON, MON_CNT) - 1;
266+
timeptr->tm_mon = (tmp_yearmon & RTC_ALM_YEARMON_ALM_MON_MASK) - 1;
248267
return_mask |= RTC_ALARM_TIME_MASK_MONTH;
249268
}
250269

251270
if (curr_alarm_mask & RTC_ALARM_TIME_MASK_YEAR) {
252-
timeptr->tm_year = (int8_t)RTC_NXP_GET_REG_FIELD(irtc_reg, YEARMON, YROFST) +
253-
RTC_NXP_IRTC_YEAR_OFFSET;
271+
timeptr->tm_year = (int8_t)((tmp_yearmon & RTC_ALM_YEARMON_ALM_YEAR_MASK) >>
272+
RTC_ALM_YEARMON_ALM_YEAR_SHIFT) +
273+
RTC_NXP_IRTC_YEAR_OFFSET;
254274
return_mask |= RTC_ALARM_TIME_MASK_YEAR;
255275
}
256276

@@ -261,14 +281,23 @@ static int nxp_irtc_alarm_get_time(const struct device *dev, uint16_t id, uint16
261281

262282
static int nxp_irtc_alarm_is_pending(const struct device *dev, uint16_t id)
263283
{
264-
struct nxp_irtc_data *data = dev->data;
284+
const struct nxp_irtc_config *config = dev->config;
265285
RTC_Type *irtc_reg = config->base;
266286

267287
if (id != 0) {
268288
return -EINVAL;
269289
}
270290

271-
return RTC_ISR_ALM_IS(0x4);
291+
if ((irtc_reg->ISR & RTC_ISR_ALM_IS_MASK) != 0) {
292+
/* Clear the Alarm Interrupt */
293+
nxp_irtc_unlock_registers(irtc_reg);
294+
/* Alarm is pending */
295+
irtc_reg->ISR = RTC_ISR_ALM_IS_MASK;
296+
return 1;
297+
}
298+
299+
/* Alarm is not pending */
300+
return 0;
272301
}
273302

274303
static int nxp_irtc_alarm_set_callback(const struct device *dev, uint16_t id,
@@ -325,12 +354,22 @@ static int nxp_irtc_init(const struct device *dev)
325354
{
326355
const struct nxp_irtc_config *config = dev->config;
327356
RTC_Type *irtc_reg = config->base;
357+
uint16_t reg = 0;
328358

329359
nxp_irtc_unlock_registers(irtc_reg);
330360

331-
/* set the control register bits */
332-
irtc_reg->CTRL = RTC_CTRL_CLK_SEL(config->clock_src) |
333-
RTC_CTRL_CLKO_DIS(!config->is_output_clock_enabled);
361+
reg = irtc_reg->CTRL;
362+
reg &= ~(uint16_t)RTC_CTRL_CLKO_DIS_MASK;
363+
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(clock_src)
364+
reg &= ~(uint16_t)RTC_CTRL_CLK_SEL_MASK;
365+
#endif
366+
367+
reg |= RTC_CTRL_CLKO_DIS(!config->is_output_clock_enabled);
368+
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(clock_src)
369+
reg |= RTC_CTRL_CLK_SEL(config->clock_src);
370+
#endif
371+
372+
irtc_reg->CTRL = reg;
334373

335374
config->irq_config_func(dev);
336375

@@ -348,7 +387,6 @@ static void nxp_irtc_isr(const struct device *dev)
348387
nxp_irtc_unlock_registers(irtc_reg);
349388
/* Clearing ISR Register since w1c */
350389
irtc_reg->ISR = irtc_reg->ISR;
351-
352390
if (data->alarm_callback) {
353391
data->alarm_callback(dev, 0, data->alarm_user_data);
354392
}
@@ -375,17 +413,40 @@ static DEVICE_API(rtc, rtc_nxp_irtc_driver_api) = {
375413
#endif /* CONFIG_RTC_CALIBRATION */
376414
};
377415

378-
#define RTC_NXP_IRTC_DEVICE_INIT(n) \
416+
#define RTC_NXP_IRTC_IRQ_CONNECT(n, m) \
417+
do { \
418+
IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, m, irq), DT_INST_IRQ_BY_IDX(n, m, priority), \
419+
nxp_irtc_isr, DEVICE_DT_INST_GET(n), 0); \
420+
irq_enable(DT_INST_IRQ_BY_IDX(n, m, irq)); \
421+
} while (false)
422+
423+
#if DT_INST_IRQ_HAS_IDX(0, 1)
424+
#define NXP_IRTC_CONFIG_FUNC(n) \
425+
static void nxp_irtc_config_func_##n(const struct device *dev) \
426+
{ \
427+
RTC_NXP_IRTC_IRQ_CONNECT(n, 0); \
428+
RTC_NXP_IRTC_IRQ_CONNECT(n, 1); \
429+
}
430+
#else
431+
#define NXP_IRTC_CONFIG_FUNC(n) \
379432
static void nxp_irtc_config_func_##n(const struct device *dev) \
380433
{ \
381-
IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), nxp_irtc_isr, \
382-
DEVICE_DT_INST_GET(n), 0); \
383-
irq_enable(DT_INST_IRQN(n)); \
384-
} \
434+
RTC_NXP_IRTC_IRQ_CONNECT(n, 0); \
435+
}
436+
#endif
437+
438+
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(clock_src)
439+
#define NXP_IRTC_CLOCK_SELECTION_INIT(n) .clock_src = DT_INST_PROP(n, clock_src),
440+
#else
441+
#define NXP_IRTC_CLOCK_SELECTION_INIT(n)
442+
#endif
443+
444+
#define RTC_NXP_IRTC_DEVICE_INIT(n) \
445+
NXP_IRTC_CONFIG_FUNC(n) \
385446
static const struct nxp_irtc_config nxp_irtc_config_##n = { \
386447
.base = (RTC_Type *)DT_INST_REG_ADDR(n), \
387-
.clock_src = DT_INST_PROP(n, clock_src), \
388-
.is_output_clock_enabled = DT_INST_PROP(n, output_clk_en), \
448+
NXP_IRTC_CLOCK_SELECTION_INIT(n) \
449+
.is_output_clock_enabled = DT_INST_PROP(n, output_clk_en), \
389450
.irq_config_func = nxp_irtc_config_func_##n, \
390451
}; \
391452
\

dts/arm/nxp/nxp_rt7xx_cm33_cpu0.dtsi

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,16 @@
156156
#reset-cells = <1>;
157157
};
158158

159+
rtc0: rtc@68000 {
160+
compatible = "nxp,irtc";
161+
reg = <0x68000 0x1000>;
162+
interrupts = <26 0>, <27 0>;
163+
clock-frequency = <32768>;
164+
prescaler = <1>;
165+
alarms-count = <1>;
166+
status = "disabled";
167+
};
168+
159169
clkctl0: clkctl@1000 {
160170
compatible = "nxp,lpc-syscon";
161171
reg = <0x1000 0x1000>;

dts/arm/nxp/nxp_rt7xx_cm33_cpu1.dtsi

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,17 @@
131131
#reset-cells = <1>;
132132
};
133133

134+
rtc1: rtc@69000 {
135+
compatible = "nxp,irtc";
136+
reg = <0x69000 0x1000>;
137+
interrupts = <23 0>, <24 0>;
138+
clock-frequency = <32768>;
139+
prescaler = <1>;
140+
alarms-count = <1>;
141+
share-counter;
142+
status = "disabled";
143+
};
144+
134145
clkctl1: clkctl@41000 {
135146
compatible = "nxp,lpc-syscon";
136147
reg = <0x41000 0x1000>;

dts/bindings/rtc/nxp,irtc.yaml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2024 NXP
1+
# Copyright 2024-2025 NXP
22
# SPDX-License-Identifier: Apache-2.0
33

44
description: IRTC
@@ -15,7 +15,6 @@ properties:
1515

1616
clock-src:
1717
type: int
18-
required: true
1918
enum:
2019
- 0
2120
- 1
@@ -40,3 +39,9 @@ properties:
4039
3 <- Coarse 1Hz
4140
Default value ensures the output clock is turned off.
4241
This is the reset value.
42+
43+
share-counter:
44+
type: boolean
45+
description: |
46+
This secondary IRTC instance shares the data and time counters of the primary IRTC instance.
47+
This means the code cannot set the data and time counters, but can only read them.

samples/drivers/rtc/README.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ Build and flash as follows, replacing ``stm32f3_disco`` with your board:
2222
:goals: build flash
2323
:compact:
2424

25+
.. zephyr-app-commands::
26+
:zephyr-app: samples/drivers/rtc
27+
:board: mimxrt700_evk/mimxrt798s/cm33_cpu0
28+
:goals: build flash
29+
30+
.. zephyr-app-commands::
31+
:zephyr-app: samples/drivers/rtc
32+
:board: mimxrt700_evk/mimxrt798s/cm33_cpu1
33+
:goals: build ram
34+
2535
Sample Output
2636
=============
2737

samples/drivers/rtc/sample.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ tests:
44
sample.drivers.rtc:
55
platform_allow:
66
- stm32f3_disco
7+
- mimxrt700_evk/mimxrt798s/cm33_cpu0
8+
- mimxrt700_evk/mimxrt798s/cm33_cpu1
79
integration_platforms:
810
- stm32f3_disco
911
tags:

0 commit comments

Comments
 (0)