1 /*
2 * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT espressif_esp32_rtc_timer
8
9 /*
10 * Include esp-idf headers first to avoid
11 * redefining BIT() macro
12 */
13 #include "soc/rtc_cntl_reg.h"
14 #include "soc/rtc.h"
15 #include <esp_rom_sys.h>
16 #include <hal/rtc_cntl_ll.h>
17
18 #include <zephyr/device.h>
19 #include <zephyr/drivers/counter.h>
20 #include <zephyr/spinlock.h>
21 #include <zephyr/kernel.h>
22 #include <zephyr/drivers/clock_control.h>
23 #include <zephyr/drivers/clock_control/esp32_clock_control.h>
24
25 #if defined(CONFIG_SOC_SERIES_ESP32C2) || defined(CONFIG_SOC_SERIES_ESP32C3)
26 #include <zephyr/drivers/interrupt_controller/intc_esp32c3.h>
27 #else
28 #include <zephyr/drivers/interrupt_controller/intc_esp32.h>
29 #endif
30
31 #include <zephyr/logging/log.h>
32 LOG_MODULE_REGISTER(esp32_counter_rtc, CONFIG_COUNTER_LOG_LEVEL);
33
34 #if defined(CONFIG_SOC_SERIES_ESP32C2) || defined(CONFIG_SOC_SERIES_ESP32C3)
35 #define ESP32_COUNTER_RTC_ISR_HANDLER isr_handler_t
36 #else
37 #define ESP32_COUNTER_RTC_ISR_HANDLER intr_handler_t
38 #endif
39
40 static void counter_esp32_isr(void *arg);
41
42 struct counter_esp32_config {
43 struct counter_config_info counter_info;
44 int irq_source;
45 int irq_priority;
46 int irq_flags;
47 const struct device *clock_dev;
48 };
49
50 struct counter_esp32_data {
51 struct counter_alarm_cfg alarm_cfg;
52 uint32_t ticks;
53 uint32_t clk_src_freq;
54 };
55
counter_esp32_init(const struct device * dev)56 static int counter_esp32_init(const struct device *dev)
57 {
58 const struct counter_esp32_config *cfg = dev->config;
59 struct counter_esp32_data *data = dev->data;
60 int ret, flags;
61
62 /* RTC_SLOW_CLK is the default clk source */
63 clock_control_get_rate(cfg->clock_dev,
64 (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW,
65 &data->clk_src_freq);
66
67 flags = ESP_PRIO_TO_FLAGS(cfg->irq_priority) | ESP_INT_FLAGS_CHECK(cfg->irq_flags) |
68 ESP_INTR_FLAG_SHARED;
69 ret = esp_intr_alloc(cfg->irq_source, flags,
70 (ESP32_COUNTER_RTC_ISR_HANDLER)counter_esp32_isr, (void *)dev, NULL);
71
72 if (ret != 0) {
73 LOG_ERR("could not allocate interrupt (err %d)", ret);
74 }
75
76 return ret;
77 }
78
counter_esp32_start(const struct device * dev)79 static int counter_esp32_start(const struct device *dev)
80 {
81 ARG_UNUSED(dev);
82
83 /* RTC main timer runs after power-on reset */
84 return 0;
85 }
86
counter_esp32_stop(const struct device * dev)87 static int counter_esp32_stop(const struct device *dev)
88 {
89 ARG_UNUSED(dev);
90
91 /*
92 * Any reset/sleep mode, except for the power-up
93 * reset, will not stop or reset the RTC timer
94 * ESP32 TRM v4.6 sec. 31.3.11
95 */
96 return 0;
97 }
98
counter_esp32_get_value(const struct device * dev,uint32_t * ticks)99 static int counter_esp32_get_value(const struct device *dev, uint32_t *ticks)
100 {
101 ARG_UNUSED(dev);
102
103 *ticks = (uint32_t) rtc_cntl_ll_get_rtc_time();
104
105 return 0;
106 }
107
counter_esp32_set_alarm(const struct device * dev,uint8_t chan_id,const struct counter_alarm_cfg * alarm_cfg)108 static int counter_esp32_set_alarm(const struct device *dev, uint8_t chan_id,
109 const struct counter_alarm_cfg *alarm_cfg)
110 {
111 ARG_UNUSED(chan_id);
112 struct counter_esp32_data *data = dev->data;
113 uint32_t now;
114 uint32_t ticks = 0;
115
116 #if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32C2) || \
117 defined(CONFIG_SOC_SERIES_ESP32C3)
118 /* In ESP32/C3 Series the min possible value is 30+ us*/
119 if (counter_ticks_to_us(dev, alarm_cfg->ticks) <= 30) {
120 return -EINVAL;
121 }
122 #endif
123 data->alarm_cfg.callback = alarm_cfg->callback;
124 data->alarm_cfg.user_data = alarm_cfg->user_data;
125
126 counter_esp32_get_value(dev, &now);
127
128 ticks = (alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) ? alarm_cfg->ticks
129 : now + alarm_cfg->ticks;
130
131 rtc_cntl_ll_set_wakeup_timer(ticks);
132
133 /* RTC main timer set alarm value */
134 CLEAR_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, 0xffffffff);
135
136 /* RTC main timer set alarm enable */
137 SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN);
138
139 /* RTC main timer interrupt enable */
140 SET_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, RTC_CNTL_MAIN_TIMER_INT_ENA);
141
142 return 0;
143 }
144
counter_esp32_cancel_alarm(const struct device * dev,uint8_t chan_id)145 static int counter_esp32_cancel_alarm(const struct device *dev, uint8_t chan_id)
146 {
147 ARG_UNUSED(dev);
148 ARG_UNUSED(chan_id);
149
150 /* RTC main timer set alarm disable */
151 CLEAR_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN);
152
153 /* RTC main timer interrupt disable */
154 SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_MAIN_TIMER_INT_CLR);
155
156 return 0;
157 }
158
counter_esp32_set_top_value(const struct device * dev,const struct counter_top_cfg * cfg)159 static int counter_esp32_set_top_value(const struct device *dev,
160 const struct counter_top_cfg *cfg)
161 {
162 const struct counter_esp32_config *config = dev->config;
163
164 if (cfg->ticks != config->counter_info.max_top_value) {
165 return -ENOTSUP;
166 }
167
168 return 0;
169 }
170
counter_esp32_get_pending_int(const struct device * dev)171 static uint32_t counter_esp32_get_pending_int(const struct device *dev)
172 {
173 ARG_UNUSED(dev);
174
175 uint32_t rc = READ_PERI_REG(RTC_CNTL_INT_ST_REG) & RTC_CNTL_MAIN_TIMER_INT_ST;
176
177 return (rc >> RTC_CNTL_MAIN_TIMER_INT_ST_S);
178 }
179
180 /*
181 * Espressif's RTC Timer is actually 48-bits in resolution
182 * However, the top value returned is limited to UINT32_MAX
183 * as per the counter API.
184 */
counter_esp32_get_top_value(const struct device * dev)185 static uint32_t counter_esp32_get_top_value(const struct device *dev)
186 {
187 const struct counter_esp32_config *cfg = dev->config;
188
189 return cfg->counter_info.max_top_value;
190 }
191
counter_esp32_get_freq(const struct device * dev)192 static uint32_t counter_esp32_get_freq(const struct device *dev)
193 {
194 struct counter_esp32_data *data = dev->data;
195
196 return data->clk_src_freq;
197 }
198
199 static struct counter_esp32_data counter_data;
200
201 static const struct counter_esp32_config counter_config = {
202 .counter_info = {
203 .max_top_value = UINT32_MAX,
204 .flags = COUNTER_CONFIG_INFO_COUNT_UP,
205 .channels = 1
206 },
207 .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)),
208 .irq_source = DT_INST_IRQ_BY_IDX(0, 0, irq),
209 .irq_priority = DT_INST_IRQ_BY_IDX(0, 0, priority),
210 .irq_flags = DT_INST_IRQ_BY_IDX(0, 0, flags)
211 };
212
213 static DEVICE_API(counter, rtc_timer_esp32_api) = {
214 .start = counter_esp32_start,
215 .stop = counter_esp32_stop,
216 .get_value = counter_esp32_get_value,
217 .set_alarm = counter_esp32_set_alarm,
218 .cancel_alarm = counter_esp32_cancel_alarm,
219 .set_top_value = counter_esp32_set_top_value,
220 .get_pending_int = counter_esp32_get_pending_int,
221 .get_top_value = counter_esp32_get_top_value,
222 .get_freq = counter_esp32_get_freq,
223 };
224
counter_esp32_isr(void * arg)225 static void counter_esp32_isr(void *arg)
226 {
227 const struct device *dev = (const struct device *)arg;
228 struct counter_esp32_data *data = dev->data;
229 uint32_t now;
230 uint32_t status = REG_READ(RTC_CNTL_INT_ST_REG);
231
232 if (!(status & RTC_CNTL_MAIN_TIMER_INT_ST_M)) {
233 return;
234 }
235
236 counter_esp32_cancel_alarm(dev, 0);
237 counter_esp32_get_value(dev, &now);
238
239 if (data->alarm_cfg.callback) {
240 data->alarm_cfg.callback(dev, 0, now, data->alarm_cfg.user_data);
241 }
242 }
243
244 DEVICE_DT_INST_DEFINE(0,
245 &counter_esp32_init,
246 NULL,
247 &counter_data,
248 &counter_config,
249 POST_KERNEL,
250 CONFIG_COUNTER_INIT_PRIORITY,
251 &rtc_timer_esp32_api);
252