Skip to content

Commit 01c03a2

Browse files
dcpleungnashif
authored andcommitted
counter: mchp_xec: update driver for counter tests
The counter driver tests have been updated so the driver needs to be updated too. () Test expects a free running counter. () Test expects any alarms cannot be set beyond the top value. () Also, the counter only triggers interrupts when counter reaches zero (as configured as counting down), it can be do relative alarms. So return -ENOTSUP when absolute alarms are requested. () The test expects the callback to be removed once alarm is triggered. Implement this too. Signed-off-by: Daniel Leung <[email protected]>
1 parent a5c53ff commit 01c03a2

File tree

1 file changed

+43
-22
lines changed

1 file changed

+43
-22
lines changed

drivers/counter/counter_mchp_xec.c

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,29 @@
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>
824
LOG_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

1431
struct 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

Comments
 (0)