rp2040/
spi.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
5use crate::clocks;
6use core::cell::Cell;
7use core::cmp;
8use kernel::hil;
9use kernel::hil::spi::cs::ChipSelectPolar;
10use kernel::hil::spi::SpiMaster;
11use kernel::hil::spi::SpiMasterClient;
12use kernel::hil::spi::{ClockPhase, ClockPolarity};
13use kernel::utilities::cells::MapCell;
14use kernel::utilities::cells::OptionalCell;
15use kernel::utilities::leasable_buffer::SubSliceMut;
16use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
17use kernel::utilities::registers::{register_bitfields, register_structs, ReadOnly, ReadWrite};
18use kernel::utilities::StaticRef;
19use kernel::ErrorCode;
20
21const SPI_READ_IN_PROGRESS: u8 = 0b001;
22const SPI_WRITE_IN_PROGRESS: u8 = 0b010;
23const SPI_IN_PROGRESS: u8 = 0b100;
24const SPI_IDLE: u8 = 0b000;
25
26register_structs! {
27    /// controls SPI port
28    SpiRegisters {
29        /// Control register 0, SSPCR0 on page 3-4
30        (0x000 => sspcr0: ReadWrite<u32, SSPCR0::Register>),
31        /// Control register 1, SSPCR1 on page 3-5
32        (0x004 => sspcr1: ReadWrite<u32, SSPCR1::Register>),
33        /// Data register, SSPDR on page 3-6
34        (0x008 => sspdr: ReadWrite<u32, SSPDR::Register>),
35        /// Status register, SSPSR on page 3-7
36        (0x00C => sspsr: ReadOnly<u32, SSPSR::Register>),
37        /// Clock prescale register, SSPCPSR on page 3-8
38        (0x010 => sspcpsr: ReadWrite<u32, SSPCPSR::Register>),
39        /// Interrupt mask set or clear register, SSPIMSC on page 3-9
40        (0x014 => sspimsc: ReadWrite<u32, SSPIMSC::Register>),
41        /// Raw interrupt status register, SSPRIS on page 3-10
42        (0x018 => sspris: ReadOnly<u32, SSPRIS::Register>),
43        /// Masked interrupt status register, SSPMIS on page 3-11
44        (0x01C => sspmis: ReadOnly<u32, SSPMIS::Register>),
45        /// Interrupt clear register, SSPICR on page 3-11
46        (0x020 => sspicr: ReadWrite<u32, SSPICR::Register>),
47        /// DMA control register, SSPDMACR on page 3-12
48        (0x024 => sspdmacr: ReadWrite<u32, SSPDMACR::Register>),
49        (0x028 => _reserved0),
50        /// Peripheral identification registers
51        (0xFE0 => sspperiphid0: ReadOnly<u32, SSPPERIPHID0::Register>),
52        /// Peripheral identification registers
53        (0xFE4 => sspperiphid1: ReadOnly<u32, SSPPERIPHID1::Register>),
54        /// Peripheral identification registers
55        (0xFE8 => sspperiphid2: ReadOnly<u32, SSPPERIPHID2::Register>),
56        /// Peripheral identification registers
57        (0xFEC => sspperiphid3: ReadOnly<u32, SSPPERIPHID3::Register>),
58        /// PrimeCell identification registers
59        (0xFF0 => ssppcellid0: ReadOnly<u32, SSPPCELLID0::Register>),
60        /// PrimeCell identification registers
61        (0xFF4 => ssppcellid1: ReadOnly<u32, SSPPCELLID1::Register>),
62        /// PrimeCell identification registers
63        (0xFF8 => ssppcellid2: ReadOnly<u32, SSPPCELLID2::Register>),
64        /// PrimeCell identification registers
65        (0xFFC => ssppcellid3: ReadOnly<u32, SSPPCELLID3::Register>),
66        (0x1000 => @END),
67    }
68}
69
70register_bitfields![u32,
71    /// Control register 0
72    SSPCR0 [
73        /// Serial clock rate.
74        SCR OFFSET(8) NUMBITS(8) [],
75        /// SSPCLKOUT phase
76        SPH OFFSET(7) NUMBITS(1) [],
77        /// SSPCLKOUT polarity
78        SPO OFFSET(6) NUMBITS(1) [],
79        /// Frame format
80        FRF OFFSET(4) NUMBITS(2) [
81            MOTOROLA_SPI = 0b00,
82            TI_SINC_SERIAL = 0b01,
83            NAT_MICROWIRE = 0b10,
84            RESERVED = 0b11
85        ],
86        /// Data Size Select
87        DSS OFFSET(0) NUMBITS(4) [
88            RESERVED_0 = 0b0000,
89            RESERVED_1 = 0b0001,
90            RESERVED_2 = 0b0010,
91            DATA_4_BIT = 0b0011,
92            DATA_5_BIT = 0b0100,
93            DATA_6_BIT = 0b0101,
94            DATA_7_BIT = 0b0110,
95            DATA_8_BIT = 0b0111,
96            DATA_9_BIT = 0b1000,
97            DATA_10_BIT = 0b1001,
98            DATA_11_BIT = 0b1010,
99            DATA_12_BIT = 0b1011,
100            DATA_13_BIT = 0b1100,
101            DATA_14_BIT = 0b1101,
102            DATA_15_BIT = 0b1110,
103            DATA_16_BIT = 0b1111
104        ]
105    ],
106    /// Control register 1
107    SSPCR1 [
108        /// Slave-mode output disable
109        SOD OFFSET(3) NUMBITS(1) [],
110        /// Master or slave mode select
111        MS OFFSET(2) NUMBITS(1) [],
112        /// Synchronous serial port enable
113        SSE OFFSET(1) NUMBITS(1) [],
114        /// Loop back mode
115        LBM OFFSET(0) NUMBITS(1) []
116    ],
117    /// Data register
118    SSPDR [
119        /// Transmit/Receive FIFO: Read Receive FIFO. Write Transmit FIFO.
120        DATA OFFSET(0) NUMBITS(16) []
121    ],
122    /// Status register
123    SSPSR [
124        /// PrimeCell SSP busy flag
125        BSY OFFSET(4) NUMBITS(1) [],
126        /// Receive FIFO full, RO
127        RFF OFFSET(3) NUMBITS(1) [],
128        /// Receive FIFO not empty
129        RNE OFFSET(2) NUMBITS(1) [],
130        /// Transmit FIFO not full
131        TNF OFFSET(1) NUMBITS(1) [],
132        /// Transmit FIFO empty
133        TFE OFFSET(0) NUMBITS(1) []
134    ],
135    /// Clock prescale register
136    SSPCPSR [
137        /// Clock prescale divisor
138        CPSDVSR OFFSET(0) NUMBITS(8) []
139    ],
140    /// Interrupt mask set or clear register
141    SSPIMSC [
142        /// Transmit FIFO interrupt mask
143        TXIM OFFSET(3) NUMBITS(1) [],
144        /// Receive FIFO interrupt mask
145        RXIM OFFSET(2) NUMBITS(1) [],
146        /// Receive timeout interrupt mask
147        RTIM OFFSET(1) NUMBITS(1) [],
148        /// Receive overrun interrupt mask
149        RORIM OFFSET(0) NUMBITS(1) []
150    ],
151    /// Raw interrupt status register
152    SSPRIS [
153        /// Gives the raw interrupt state, prior to masking, of the SSPTXINTR interrupt
154        TXRIS OFFSET(3) NUMBITS(1) [],
155        /// Gives the raw interrupt state, prior to masking, of the SSPRXINTR interrupt
156        RXRIS OFFSET(2) NUMBITS(1) [],
157        /// Gives the raw interrupt state, prior to masking, of the SSPRTINTR interrupt
158        RTRIS OFFSET(1) NUMBITS(1) [],
159        /// Gives the raw interrupt state, prior to masking, of the SSPRORINTR interrupt
160        RORRIS OFFSET(0) NUMBITS(1) []
161    ],
162    /// Masked interrupt status register
163    SSPMIS [
164        /// Gives the transmit FIFO masked interrupt state, after masking, of the SSPTXINTR
165        TXMIS OFFSET(3) NUMBITS(1) [],
166        /// Gives the receive FIFO masked interrupt state, after masking, of the SSPRXINTR i
167        RXMIS OFFSET(2) NUMBITS(1) [],
168        /// Gives the receive timeout masked interrupt state, after masking, of the SSPRTINT
169        RTMIS OFFSET(1) NUMBITS(1) [],
170        /// Gives the receive over run masked interrupt status, after masking, of the SSPROR
171        RORMIS OFFSET(0) NUMBITS(1) []
172    ],
173    /// Interrupt clear register
174    SSPICR [
175        /// Clears the SSPRTINTR interrupt
176        RTIC OFFSET(1) NUMBITS(1) [],
177        /// Clears the SSPRORINTR interrupt
178        RORIC OFFSET(0) NUMBITS(1) []
179    ],
180    /// DMA control register
181    SSPDMACR [
182        /// Transmit DMA Enable
183        TXDMAE OFFSET(1) NUMBITS(1) [],
184        /// Receive DMA Enable
185        RXDMAE OFFSET(0) NUMBITS(1) []
186    ],
187    /// Peripheral identification registers
188    SSPPERIPHID0 [
189        /// These bits read back as 0x22
190        PARTNUMBER0 OFFSET(0) NUMBITS(8) []
191    ],
192    /// Peripheral identification registers
193    SSPPERIPHID1 [
194        /// These bits read back as 0x1
195        DESIGNER0 OFFSET(4) NUMBITS(4) [],
196        /// These bits read back as 0x0
197        PARTNUMBER1 OFFSET(0) NUMBITS(4) []
198    ],
199    /// Peripheral identification registers
200    SSPPERIPHID2 [
201        /// These bits return the peripheral revision
202        REVISION OFFSET(4) NUMBITS(4) [],
203        /// These bits read back as 0x4
204        DESIGNER1 OFFSET(0) NUMBITS(4) []
205    ],
206    /// Peripheral identification registers
207    SSPPERIPHID3 [
208        /// These bits read back as 0x00
209        CONFIGURATION OFFSET(0) NUMBITS(8) []
210    ],
211    /// PrimeCell identification registers
212    SSPPCELLID0 [
213        /// These bits read back as 0x0D
214        SSPPCELLID0 OFFSET(0) NUMBITS(8) []
215    ],
216    /// PrimeCell identification registers
217    SSPPCELLID1 [
218        /// These bits read back as 0xF0
219        SSPPCELLID1 OFFSET(0) NUMBITS(8) []
220    ],
221    /// PrimeCell identification registers
222    SSPPCELLID2 [
223        /// These bits read back as 0x05
224        SSPPCELLID2 OFFSET(0) NUMBITS(8) []
225    ],
226    /// PrimeCell identification registers
227    SSPPCELLID3 [
228        /// These bits read back as 0xB1
229        SSPPCELLID3 OFFSET(0) NUMBITS(8) []
230    ]
231];
232
233const SPI0_BASE: StaticRef<SpiRegisters> =
234    unsafe { StaticRef::new(0x4003C000 as *const SpiRegisters) };
235
236const SPI1_BASE: StaticRef<SpiRegisters> =
237    unsafe { StaticRef::new(0x40040000 as *const SpiRegisters) };
238
239pub struct Spi<'a> {
240    registers: StaticRef<SpiRegisters>,
241    clocks: OptionalCell<&'a clocks::Clocks>,
242    master_client: OptionalCell<&'a dyn hil::spi::SpiMasterClient>,
243    active_slave: OptionalCell<ChipSelectPolar<'a, crate::gpio::RPGpioPin<'a>>>,
244
245    tx_buffer: MapCell<SubSliceMut<'static, u8>>,
246    tx_position: Cell<usize>,
247
248    rx_buffer: MapCell<SubSliceMut<'static, u8>>,
249    rx_position: Cell<usize>,
250    len: Cell<usize>,
251
252    transfers: Cell<u8>,
253    active_after: Cell<bool>,
254}
255
256impl<'a> Spi<'a> {
257    pub fn new_spi0() -> Self {
258        Self {
259            registers: SPI0_BASE,
260            clocks: OptionalCell::empty(),
261            master_client: OptionalCell::empty(),
262            active_slave: OptionalCell::empty(),
263
264            tx_buffer: MapCell::empty(),
265            tx_position: Cell::new(0),
266
267            rx_buffer: MapCell::empty(),
268            rx_position: Cell::new(0),
269
270            len: Cell::new(0),
271
272            transfers: Cell::new(SPI_IDLE),
273            active_after: Cell::new(false),
274        }
275    }
276
277    pub fn new_spi1() -> Self {
278        Self {
279            registers: SPI1_BASE,
280            clocks: OptionalCell::empty(),
281            master_client: OptionalCell::empty(),
282            active_slave: OptionalCell::empty(),
283
284            tx_buffer: MapCell::empty(),
285            tx_position: Cell::new(0),
286
287            rx_buffer: MapCell::empty(),
288            rx_position: Cell::new(0),
289
290            len: Cell::new(0),
291
292            transfers: Cell::new(SPI_IDLE),
293            active_after: Cell::new(false),
294        }
295    }
296
297    pub(crate) fn set_clocks(&self, clocks: &'a clocks::Clocks) {
298        self.clocks.set(clocks);
299    }
300
301    fn enable(&self) {
302        self.registers.sspcr1.modify(SSPCR1::SSE::SET);
303    }
304
305    fn disable(&self) {
306        self.registers.sspcr1.modify(SSPCR1::SSE::CLEAR);
307    }
308
309    pub fn handle_interrupt(&self) {
310        if self.registers.sspsr.is_set(SSPSR::TFE) {
311            // if transmit fifo empty is set
312            if self.tx_buffer.is_some() {
313                while self.registers.sspsr.is_set(SSPSR::TNF)
314                    && self.tx_position.get() < self.len.get()
315                {
316                    self.tx_buffer.map(|buf| {
317                        // debug!("position {} of {}", self.tx_position.get(), self.len.get());
318                        self.registers
319                            .sspdr
320                            .write(SSPDR::DATA.val(buf[self.tx_position.get()].into()));
321                        self.tx_position.set(self.tx_position.get() + 1);
322                    });
323                }
324                if self.tx_position.get() >= self.len.get() {
325                    self.transfers
326                        .set(self.transfers.get() & !SPI_WRITE_IN_PROGRESS);
327                }
328            } else {
329                self.registers.sspimsc.modify(SSPIMSC::TXIM::CLEAR);
330            }
331        }
332
333        while self.registers.sspsr.is_set(SSPSR::RNE) {
334            let byte = self.registers.sspdr.read(SSPDR::DATA) as u8;
335            if self.rx_buffer.is_some() {
336                if self.rx_position.get() < self.len.get() {
337                    self.rx_buffer.map(|buf| {
338                        buf[self.rx_position.get()] = byte;
339                    });
340                    self.rx_position.set(self.rx_position.get() + 1);
341                } else {
342                    self.transfers
343                        .set(self.transfers.get() & !SPI_READ_IN_PROGRESS);
344                }
345            }
346        }
347
348        if self.transfers.get() == SPI_IN_PROGRESS {
349            if !self.active_after.get() {
350                self.active_slave.map(|p| {
351                    p.deactivate();
352                });
353            }
354            self.master_client.map(|client| {
355                self.registers.sspimsc.modify(SSPIMSC::TXIM::CLEAR);
356                self.registers.sspimsc.modify(SSPIMSC::RXIM::CLEAR);
357                self.disable();
358                self.transfers.set(SPI_IDLE);
359                self.tx_buffer.take().map(|buf| {
360                    client.read_write_done(buf, self.rx_buffer.take(), Ok(self.len.get()))
361                });
362            });
363        }
364    }
365
366    fn read_write_bytes(
367        &self,
368        write_buffer: Option<SubSliceMut<'static, u8>>,
369        read_buffer: Option<SubSliceMut<'static, u8>>,
370    ) -> Result<
371        (),
372        (
373            ErrorCode,
374            Option<SubSliceMut<'static, u8>>,
375            Option<SubSliceMut<'static, u8>>,
376        ),
377    > {
378        if write_buffer.is_none() && read_buffer.is_none() {
379            return Err((ErrorCode::INVAL, write_buffer, read_buffer));
380        }
381
382        if self.transfers.get() == SPI_IDLE {
383            self.enable();
384            self.registers.sspimsc.modify(SSPIMSC::TXIM::CLEAR);
385            self.registers.sspimsc.modify(SSPIMSC::RXIM::CLEAR);
386            self.active_slave.map(|p| {
387                p.activate();
388            });
389
390            self.transfers.set(SPI_IN_PROGRESS);
391
392            let len = match (
393                write_buffer.as_ref().map(|b| b.len()),
394                read_buffer.as_ref().map(|b| b.len()),
395            ) {
396                (Some(wl), Some(rl)) => cmp::min(wl, rl),
397                (Some(wl), None) => wl,
398                (None, Some(rl)) => rl,
399                (None, None) => 0,
400            };
401
402            if write_buffer.is_some() {
403                self.transfers
404                    .set(self.transfers.get() | SPI_WRITE_IN_PROGRESS);
405            }
406
407            if read_buffer.is_some() {
408                self.transfers
409                    .set(self.transfers.get() | SPI_READ_IN_PROGRESS);
410            }
411
412            read_buffer.map(|buf| {
413                self.rx_buffer.replace(buf);
414                self.len.set(len);
415                self.rx_position.set(0);
416                self.registers.sspimsc.modify(SSPIMSC::RXIM::SET);
417            });
418
419            write_buffer.map(|buf| {
420                self.tx_buffer.replace(buf);
421                self.len.set(len);
422                self.tx_position.set(0);
423                self.registers.sspimsc.modify(SSPIMSC::TXIM::SET);
424            });
425
426            Ok(())
427        } else {
428            Err((ErrorCode::BUSY, write_buffer, read_buffer))
429        }
430    }
431
432    // IdleLow  = SPO = 0
433    // IdleHigh = SPO = 1
434    fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode> {
435        if !self.is_busy() {
436            self.enable();
437            match polarity {
438                ClockPolarity::IdleHigh => self.registers.sspcr0.modify(SSPCR0::SPO::SET),
439                ClockPolarity::IdleLow => self.registers.sspcr0.modify(SSPCR0::SPO::CLEAR),
440            }
441            self.disable();
442            Ok(())
443        } else {
444            Err(ErrorCode::BUSY)
445        }
446    }
447
448    fn get_polarity(&self) -> ClockPolarity {
449        if !self.registers.sspcr0.is_set(SSPCR0::SPO) {
450            ClockPolarity::IdleLow
451        } else {
452            ClockPolarity::IdleHigh
453        }
454    }
455
456    // SampleLeading  = SPH = 0
457    // SampleTrailing = SPH = 1
458    fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode> {
459        if !self.is_busy() {
460            self.enable();
461            match phase {
462                ClockPhase::SampleLeading => self.registers.sspcr0.modify(SSPCR0::SPH::CLEAR),
463                ClockPhase::SampleTrailing => self.registers.sspcr0.modify(SSPCR0::SPH::SET),
464            }
465            self.disable();
466            Ok(())
467        } else {
468            Err(ErrorCode::BUSY)
469        }
470    }
471
472    fn get_phase(&self) -> ClockPhase {
473        if !self.registers.sspcr0.is_set(SSPCR0::SPH) {
474            ClockPhase::SampleLeading
475        } else {
476            ClockPhase::SampleTrailing
477        }
478    }
479
480    fn set_format(&self) {
481        self.registers.sspcr0.modify(SSPCR0::DSS::DATA_8_BIT);
482        self.registers.sspcr0.modify(SSPCR0::SPO::CLEAR);
483        self.registers.sspcr0.modify(SSPCR0::SPH::CLEAR);
484    }
485}
486
487impl<'a> SpiMaster<'a> for Spi<'a> {
488    type ChipSelect = ChipSelectPolar<'a, crate::gpio::RPGpioPin<'a>>;
489
490    fn set_client(&self, client: &'a dyn SpiMasterClient) {
491        self.master_client.set(client);
492    }
493
494    fn init(&self) -> Result<(), ErrorCode> {
495        match self.set_rate(16 * 1000 * 1000) {
496            Err(error) => Err(error),
497            Ok(_) => Ok(()),
498        }?;
499        // set format: 8 bit mode, SSPCLKOUT polarity and phase on 0
500        self.set_format();
501
502        // Always enable DREQ signals -- harmless if DMA is not listening
503        self.registers.sspdmacr.modify(SSPDMACR::TXDMAE::SET);
504        self.registers.sspdmacr.modify(SSPDMACR::RXDMAE::SET);
505
506        // set device on master
507        self.registers.sspcr1.modify(SSPCR1::MS::CLEAR);
508
509        Ok(())
510    }
511
512    fn is_busy(&self) -> bool {
513        // self.registers.sspsr.is_set(SSPSR::BSY)
514        self.transfers.get() != SPI_IDLE
515    }
516
517    fn read_write_bytes(
518        &self,
519        write_buffer: SubSliceMut<'static, u8>,
520        read_buffer: Option<SubSliceMut<'static, u8>>,
521    ) -> Result<
522        (),
523        (
524            ErrorCode,
525            SubSliceMut<'static, u8>,
526            Option<SubSliceMut<'static, u8>>,
527        ),
528    > {
529        if self.is_busy() {
530            return Err((ErrorCode::BUSY, write_buffer, read_buffer));
531        }
532
533        match self.read_write_bytes(Some(write_buffer), read_buffer) {
534            // some_write_buffer should always be Some(write_buffer)
535            Err((error, some_write_buffer, read_buffer)) => {
536                Err((error, some_write_buffer.unwrap(), read_buffer))
537            }
538            Ok(()) => Ok(()),
539        }
540    }
541
542    fn write_byte(&self, out_val: u8) -> Result<(), ErrorCode> {
543        if !self.is_busy() {
544            while !self.registers.sspsr.is_set(SSPSR::TFE) {}
545
546            self.registers.sspdr.modify(SSPDR::DATA.val(out_val as u32));
547
548            Ok(())
549        } else {
550            Err(ErrorCode::BUSY)
551        }
552    }
553
554    fn read_byte(&self) -> Result<u8, ErrorCode> {
555        self.read_write_byte(0)
556    }
557
558    fn read_write_byte(&self, val: u8) -> Result<u8, ErrorCode> {
559        if !self.is_busy() {
560            self.write_byte(val)?;
561
562            while !self.registers.sspsr.is_set(SSPSR::RNE) {}
563
564            Ok(self.registers.sspdr.read(SSPDR::DATA) as u8)
565        } else {
566            Err(ErrorCode::BUSY)
567        }
568    }
569
570    fn specify_chip_select(&self, cs: Self::ChipSelect) -> Result<(), ErrorCode> {
571        if !self.is_busy() {
572            self.active_slave.set(cs);
573            Ok(())
574        } else {
575            Err(ErrorCode::BUSY)
576        }
577    }
578
579    fn set_rate(&self, baudrate: u32) -> Result<u32, ErrorCode> {
580        let freq_in = self.clocks.map_or(125_000_000, |clocks| {
581            clocks.get_frequency(clocks::Clock::Peripheral)
582        });
583
584        if baudrate > freq_in {
585            return Err(ErrorCode::INVAL);
586        }
587
588        let mut prescale = 0;
589        let mut postdiv = 0;
590
591        for p in (2..254).step_by(2) {
592            if (freq_in as u64) < (((p + 2) * 256) as u64 * baudrate as u64) {
593                prescale = p;
594                break;
595            }
596        }
597
598        for p in (2..256).rev() {
599            if (freq_in / (prescale * (p - 1))) > baudrate {
600                postdiv = p;
601                break;
602            }
603        }
604
605        if prescale > 0 && postdiv > 0 {
606            self.registers
607                .sspcpsr
608                .modify(SSPCPSR::CPSDVSR.val(prescale));
609            self.registers.sspcr0.modify(SSPCR0::SCR.val(postdiv - 1));
610
611            Ok(freq_in / (prescale * postdiv))
612        } else {
613            Err(ErrorCode::INVAL)
614        }
615    }
616
617    fn get_rate(&self) -> u32 {
618        let freq_in = self.clocks.map_or(125_000_000, |clocks| {
619            clocks.get_frequency(clocks::Clock::Peripheral)
620        });
621        let prescale = self.registers.sspcpsr.read(SSPCPSR::CPSDVSR);
622        let postdiv = self.registers.sspcr0.read(SSPCR0::SCR) + 1;
623        freq_in / (prescale * postdiv)
624    }
625
626    fn set_polarity(&self, polarity: ClockPolarity) -> Result<(), ErrorCode> {
627        self.set_polarity(polarity)
628    }
629
630    fn get_polarity(&self) -> ClockPolarity {
631        self.get_polarity()
632    }
633
634    fn set_phase(&self, phase: ClockPhase) -> Result<(), ErrorCode> {
635        self.set_phase(phase)
636    }
637
638    fn get_phase(&self) -> ClockPhase {
639        self.get_phase()
640    }
641
642    fn hold_low(&self) {
643        self.active_after.set(true);
644    }
645    fn release_low(&self) {
646        self.active_after.set(false);
647    }
648}