Skip to content

Commit 67a25f2

Browse files
ghostMan-pachenrikbrixandersen
authored andcommitted
drivers: pwm: sam0: Add support for tc 32 bit mode
- Added logic for updating the registers for 32 bit when 32-bit counter size is selected. Signed-off-by: Muhammed Asif <[email protected]>
1 parent b26252b commit 67a25f2

File tree

1 file changed

+34
-6
lines changed

1 file changed

+34
-6
lines changed

drivers/pwm/pwm_sam0_tc.c

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,21 @@ struct pwm_sam0_config {
4545
};
4646

4747
#define COUNTER_8BITS 8U
48+
#define COUNTER_16BITS 16U
49+
#define SYNC_WAIT_TIMEOUT 5U
50+
4851

4952
/* Wait for the peripheral to finish all commands */
5053
static void wait_synchronization(Tc *regs, uint8_t counter_size)
5154
{
5255
if (COUNTER_8BITS == counter_size) {
5356
while (regs->COUNT8.SYNCBUSY.reg != 0) {
5457
}
55-
} else {
58+
} else if (COUNTER_16BITS == counter_size) {
5659
while (regs->COUNT16.SYNCBUSY.reg != 0) {
5760
}
61+
} else {
62+
WAIT_FOR((regs->COUNT32.SYNCBUSY.reg != 0), SYNC_WAIT_TIMEOUT, NULL);
5863
}
5964
}
6065

@@ -78,15 +83,14 @@ static int pwm_sam0_set_cycles(const struct device *dev, uint32_t channel, uint3
7883
const struct pwm_sam0_config *const cfg = dev->config;
7984
Tc *regs = cfg->regs;
8085
uint8_t counter_size = cfg->counter_size;
81-
uint32_t top = 1 << counter_size;
86+
uint64_t top = BIT64(counter_size);
8287
uint32_t invert_mask = 1 << channel;
8388
bool invert = ((flags & PWM_POLARITY_INVERTED) != 0);
8489
bool inverted;
85-
8690
if (channel >= cfg->channels) {
8791
return -EINVAL;
8892
}
89-
if (period_cycles >= top || pulse_cycles >= top) {
93+
if ((uint64_t)period_cycles >= top || pulse_cycles >= top) {
9094
return -EINVAL;
9195
}
9296

@@ -108,7 +112,7 @@ static int pwm_sam0_set_cycles(const struct device *dev, uint32_t channel, uint3
108112
regs->COUNT8.CTRLA.bit.ENABLE = 1;
109113
wait_synchronization(regs, counter_size);
110114
}
111-
} else {
115+
} else if (COUNTER_16BITS == counter_size) {
112116
inverted = ((regs->COUNT16.DRVCTRL.vec.INVEN & invert_mask) != 0);
113117
regs->COUNT16.CCBUF[0].reg = TC_COUNT16_CCBUF_CCBUF(period_cycles);
114118
regs->COUNT16.CCBUF[1].reg = TC_COUNT16_CCBUF_CCBUF(pulse_cycles);
@@ -122,6 +126,20 @@ static int pwm_sam0_set_cycles(const struct device *dev, uint32_t channel, uint3
122126
regs->COUNT16.CTRLA.bit.ENABLE = 1;
123127
wait_synchronization(regs, counter_size);
124128
}
129+
} else {
130+
inverted = ((regs->COUNT32.DRVCTRL.vec.INVEN & invert_mask) != 0);
131+
regs->COUNT32.CCBUF[0].reg = TC_COUNT32_CCBUF_CCBUF(period_cycles);
132+
regs->COUNT32.CCBUF[1].reg = TC_COUNT32_CCBUF_CCBUF(pulse_cycles);
133+
wait_synchronization(regs, counter_size);
134+
135+
if (invert != inverted) {
136+
regs->COUNT32.CTRLA.bit.ENABLE = 0;
137+
wait_synchronization(regs, counter_size);
138+
139+
regs->COUNT32.DRVCTRL.vec.INVEN ^= invert_mask;
140+
regs->COUNT32 .CTRLA.bit.ENABLE = 1;
141+
wait_synchronization(regs, counter_size);
142+
}
125143
}
126144

127145
return 0;
@@ -161,7 +179,7 @@ static int pwm_sam0_init(const struct device *dev)
161179

162180
regs->COUNT8.CTRLA.bit.ENABLE = 1;
163181
wait_synchronization(regs, counter_size);
164-
} else {
182+
} else if (COUNTER_16BITS == counter_size) {
165183
regs->COUNT16.CTRLA.bit.SWRST = 1;
166184
wait_synchronization(regs, counter_size);
167185

@@ -172,6 +190,16 @@ static int pwm_sam0_init(const struct device *dev)
172190

173191
regs->COUNT16.CTRLA.bit.ENABLE = 1;
174192
wait_synchronization(regs, cfg->counter_size);
193+
} else {
194+
regs->COUNT32.CTRLA.bit.SWRST = 1;
195+
wait_synchronization(regs, counter_size);
196+
regs->COUNT32.CTRLA.reg = cfg->prescaler | TC_CTRLA_MODE_COUNT32 |
197+
TC_CTRLA_PRESCSYNC_PRESC;
198+
regs->COUNT32.WAVE.reg = TC_WAVE_WAVEGEN_MPWM;
199+
regs->COUNT32.CC[0].reg = TC_COUNT32_CC_CC(1);
200+
201+
regs->COUNT32.CTRLA.bit.ENABLE = 1;
202+
wait_synchronization(regs, counter_size);
175203
}
176204

177205
return 0;

0 commit comments

Comments
 (0)