44 * SPDX-License-Identifier: Apache-2.0
55 */
66
7+ /**
8+ * @file
9+ * @brief Microchip XEC Counter driver
10+ *
11+ * This is the driver for the 16/32-bit counters on the Microchip SoCs.
12+ *
13+ * Notes:
14+ * - The counters are running in down counting mode.
15+ * - Interrupts are triggered (if enabled) when the counter
16+ * reaches zero.
17+ * - These are not free running counters where there are separate
18+ * compare values for interrupts. When setting single shot alarms,
19+ * the counter values are changed so that interrupts are triggered
20+ * when the counters reach zero.
21+ */
22+
723#include <logging/log.h>
824LOG_MODULE_REGISTER (counter_mchp_xec , CONFIG_COUNTER_LOG_LEVEL );
925
1026#include <counter.h>
1127#include <soc.h>
1228#include <errno.h>
29+ #include <stdbool.h>
1330
1431struct counter_xec_config {
1532 struct counter_config_info info ;
@@ -46,7 +63,7 @@ static int counter_xec_start(struct device *dev)
4663 return - EALREADY ;
4764 }
4865
49- counter -> CTRL |= MCHP_BTMR_CTRL_ENABLE ;
66+ counter -> CTRL |= ( MCHP_BTMR_CTRL_ENABLE | MCHP_BTMR_CTRL_START ) ;
5067
5168 LOG_DBG ("%p Counter started" , dev );
5269
@@ -72,7 +89,7 @@ static int counter_xec_stop(struct device *dev)
7289 counter -> CTRL = reg ;
7390
7491 counter -> IEN = MCHP_BTMR_INTDIS ;
75- counter -> CNT = 0 ;
92+ counter -> CNT = counter -> PRLD ;
7693
7794 LOG_DBG ("%p Counter stopped" , dev );
7895
@@ -90,49 +107,40 @@ static int counter_xec_set_alarm(struct device *dev, u8_t chan_id,
90107 const struct counter_alarm_cfg * alarm_cfg )
91108{
92109 BTMR_Type * counter = COUNTER_XEC_REG_BASE (dev );
93- const struct counter_xec_config * counter_cfg = COUNTER_XEC_CONFIG (dev );
94110 struct counter_xec_data * data = COUNTER_XEC_DATA (dev );
95- u32_t ticks ;
96111
97112 if (chan_id != 0 ) {
98113 LOG_ERR ("Invalid channel id %u" , chan_id );
99114 return - ENOTSUP ;
100115 }
101116
102- if (!(counter -> CTRL & MCHP_BTMR_CTRL_ENABLE )) {
103- return - EIO ;
117+ /* Interrupts are only triggered when the counter reaches 0.
118+ * So only relative alarms are supported.
119+ */
120+ if (alarm_cfg -> flags & COUNTER_ALARM_CFG_ABSOLUTE ) {
121+ return - ENOTSUP ;
104122 }
105123
106- if (counter -> CTRL & MCHP_BTMR_CTRL_START ) {
124+ if (data -> alarm_cb != NULL ) {
107125 return - EBUSY ;
108126 }
109127
110128 if (!alarm_cfg -> callback ) {
111129 return - EINVAL ;
112130 }
113131
114- ticks = alarm_cfg -> ticks ;
115-
116- if (counter_cfg -> info .max_top_value == UINT16_MAX ) {
117- if (ticks > UINT16_MAX ) {
118- return - EINVAL ;
119- }
120- }
121-
122- if (!(alarm_cfg -> flags & COUNTER_ALARM_CFG_ABSOLUTE )) {
123- u64_t abs_cnt = ticks + counter -> CNT ;
124-
125- ticks = (u32_t ) abs_cnt % counter_cfg -> info .max_top_value ;
132+ if (alarm_cfg -> ticks > counter -> PRLD ) {
133+ return - EINVAL ;
126134 }
127135
128- counter -> CNT = ticks ;
136+ counter -> CNT = alarm_cfg -> ticks ;
129137
130138 data -> alarm_cb = alarm_cfg -> callback ;
131139 data -> user_data = alarm_cfg -> user_data ;
132140
133141 counter -> IEN = MCHP_BTMR_INTEN ;
134142
135- LOG_DBG ("%p Counter alarm set to %u ticks" , dev , ticks );
143+ LOG_DBG ("%p Counter alarm set to %u ticks" , dev , alarm_cfg -> ticks );
136144
137145 counter -> CTRL |= MCHP_BTMR_CTRL_START ;
138146
@@ -242,14 +250,23 @@ static void counter_xec_isr(struct device *dev)
242250 BTMR_Type * counter = COUNTER_XEC_REG_BASE (dev );
243251 const struct counter_xec_config * counter_cfg = COUNTER_XEC_CONFIG (dev );
244252 struct counter_xec_data * data = COUNTER_XEC_DATA (dev );
253+ counter_alarm_callback_t alarm_cb ;
254+ void * user_data ;
245255
246256 counter -> STS = MCHP_BTMR_STS_ACTIVE ;
247257 MCHP_GIRQ_SRC (counter_cfg -> girq_id ) = BIT (counter_cfg -> girq_bit );
248258
249259 LOG_DBG ("%p Counter ISR" , dev );
250260
251261 if (data -> alarm_cb ) {
252- data -> alarm_cb (dev , 0 , counter -> CNT , data -> user_data );
262+ /* Alarm is one-shot, so disable interrupt and callback */
263+ counter -> IEN = MCHP_BTMR_INTDIS ;
264+
265+ alarm_cb = data -> alarm_cb ;
266+ data -> alarm_cb = NULL ;
267+ user_data = data -> user_data ;
268+
269+ alarm_cb (dev , 0 , counter -> CNT , user_data );
253270 } else if (data -> top_cb ) {
254271 data -> top_cb (dev , data -> user_data );
255272 }
@@ -278,6 +295,10 @@ static int counter_xec_init(struct device *dev)
278295 counter -> CTRL |= (counter_cfg -> prescaler << MCHP_BTMR_CTRL_PRESCALE_POS ) &
279296 MCHP_BTMR_CTRL_PRESCALE_MASK ;
280297
298+ /* Set preload and actually pre-load the counter */
299+ counter -> PRLD = counter_cfg -> info .max_top_value ;
300+ counter -> CNT = counter_cfg -> info .max_top_value ;
301+
281302 MCHP_GIRQ_ENSET (counter_cfg -> girq_id ) = BIT (counter_cfg -> girq_bit );
282303
283304 counter_cfg -> config_func ();
0 commit comments