sifive/
pwm.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Pulse Width Modulation (PWM) driver.
6
7use kernel::utilities::registers::interfaces::Writeable;
8use kernel::utilities::registers::{register_bitfields, ReadWrite};
9use kernel::utilities::StaticRef;
10
11#[repr(C)]
12pub struct PwmRegisters {
13    /// PWM Configuration Register
14    cfg: ReadWrite<u32, cfg::Register>,
15    _reserved0: [u8; 4],
16    /// Counter Register
17    count: ReadWrite<u32>,
18    _reserved1: [u8; 4],
19    /// Scaled Halfword Counter Register
20    pwms: ReadWrite<u32>,
21    _reserved2: [u8; 12],
22    /// Compare Register
23    cmp0: ReadWrite<u32>,
24    /// Compare Register
25    cmp1: ReadWrite<u32>,
26    /// Compare Register
27    cmp2: ReadWrite<u32>,
28    /// Compare Register
29    cmp3: ReadWrite<u32>,
30}
31
32register_bitfields![u32,
33    cfg [
34        cmp3ip OFFSET(31) NUMBITS(1) [],
35        cmp2ip OFFSET(30) NUMBITS(1) [],
36        cmp1ip OFFSET(29) NUMBITS(1) [],
37        cmp0ip OFFSET(28) NUMBITS(1) [],
38        cmp3gang OFFSET(27) NUMBITS(1) [],
39        cmp2gang OFFSET(26) NUMBITS(11) [],
40        cmp1gang OFFSET(25) NUMBITS(1) [],
41        cmp0gang OFFSET(24) NUMBITS(1) [],
42        cmp3center OFFSET(19) NUMBITS(1) [],
43        cmp2center OFFSET(18) NUMBITS(1) [],
44        cmp1center OFFSET(17) NUMBITS(1) [],
45        cmp0center OFFSET(16) NUMBITS(1) [],
46        enoneshot OFFSET(13) NUMBITS(1) [],
47        enalways OFFSET(12) NUMBITS(1) [],
48        deglitch OFFSET(10) NUMBITS(1) [],
49        zerocmp OFFSET(9) NUMBITS(1) [],
50        sticky OFFSET(8) NUMBITS(1) [],
51        scale OFFSET(0) NUMBITS(4) []
52    ]
53];
54
55pub struct Pwm {
56    registers: StaticRef<PwmRegisters>,
57}
58
59impl Pwm {
60    pub const fn new(base: StaticRef<PwmRegisters>) -> Pwm {
61        Pwm { registers: base }
62    }
63
64    /// Disable the PWM so it does not generate interrupts.
65    pub fn disable(&self) {
66        let regs = self.registers;
67
68        // Turn the interrupt compare off so we don't get any RTC interrupts.
69        regs.cfg.write(cfg::enalways::CLEAR + cfg::enoneshot::CLEAR);
70
71        // Set the comparitors high to make sure we don't get interrupts
72        regs.cmp0.set(0x0000_FFFF);
73        regs.cmp1.set(0x0000_FFFF);
74        regs.cmp2.set(0x0000_FFFF);
75        regs.cmp3.set(0x0000_FFFF);
76    }
77}