1
use enumset::EnumSet;
2

            
3
use super::{
4
    super::{DataMode, SpiInterrupt},
5
    Driver,
6
};
7
use crate::spi::{Error, Mode};
8

            
9
pub(super) fn abort_transfer(driver: &Driver) {
10
    driver.configure_datalen(1, 1);
11
}
12

            
13
pub(super) fn enable_peripheral_clock(driver: &Driver) {
14
    driver.regs().clk_gate().modify(|_, w| {
15
        w.clk_en().set_bit();
16
        w.mst_clk_active().set_bit()
17
    });
18
}
19

            
20
pub(super) fn init(driver: &Driver) {
21
    driver.regs().ctrl().modify(|_, w| {
22
        w.q_pol().clear_bit();
23
        w.d_pol().clear_bit();
24
        w.hold_pol().clear_bit();
25
        w
26
    });
27
    driver.regs().misc().write(|w| unsafe { w.bits(0) });
28
}
29

            
30
pub(super) fn init_spi_data_mode(
31
    driver: &Driver,
32
    cmd_mode: DataMode,
33
    address_mode: DataMode,
34
    data_mode: DataMode,
35
) -> Result<(), Error> {
36
    driver.regs().ctrl().modify(|_, w| {
37
        w.fcmd_dual().bit(cmd_mode == DataMode::Dual);
38
        w.fcmd_quad().bit(cmd_mode == DataMode::Quad);
39
        w.faddr_dual().bit(address_mode == DataMode::Dual);
40
        w.faddr_quad().bit(address_mode == DataMode::Quad);
41
        w.fread_dual().bit(data_mode == DataMode::Dual);
42
        w.fread_quad().bit(data_mode == DataMode::Quad)
43
    });
44
    driver.regs().user().modify(|_, w| {
45
        w.fwrite_dual().bit(data_mode == DataMode::Dual);
46
        w.fwrite_quad().bit(data_mode == DataMode::Quad)
47
    });
48
    Ok(())
49
}
50

            
51
pub(super) fn apply_config(_driver: &Driver) {}
52

            
53
pub(super) fn set_data_mode(driver: &Driver, data_mode: Mode) {
54
    driver.regs().misc().modify(|_, w| {
55
        w.ck_idle_edge()
56
90
            .bit(matches!(data_mode, Mode::_2 | Mode::_3))
57
    });
58
    driver.regs().user().modify(|_, w| {
59
        w.ck_out_edge()
60
90
            .bit(matches!(data_mode, Mode::_1 | Mode::_2))
61
    });
62
}
63

            
64
pub(super) fn setup_full_duplex(_driver: &Driver) {}
65

            
66
pub(super) fn prepare_half_duplex(_driver: &Driver, _is_write: bool, dummy: u8) -> u8 {
67
    dummy
68
}
69

            
70
pub(super) fn setup_half_duplex(driver: &Driver) {
71
    driver.regs().misc().write(|w| unsafe { w.bits(0) });
72
}
73

            
74
pub(super) fn set_cs_keep_active(driver: &Driver, keep_active: bool) {
75
    driver
76
        .regs()
77
        .misc()
78
        .modify(|_, w| w.cs_keep_active().bit(keep_active));
79
6
}
80

            
81
pub(super) fn write_address(driver: &Driver, addr: u32) {
82
    driver
83
        .regs()
84
        .addr()
85
        .write(|w| unsafe { w.usr_addr_value().bits(addr) });
86
}
87

            
88
pub(super) fn enable_listen(driver: &Driver, interrupts: EnumSet<SpiInterrupt>, enable: bool) {
89
    driver.regs().dma_int_ena().modify(|_, w| {
90
        for interrupt in interrupts {
91
            match interrupt {
92
                SpiInterrupt::TransferDone => w.trans_done().bit(enable),
93
                #[cfg(spi_master_has_dma_segmented_transfer)]
94
                SpiInterrupt::DmaSegmentedTransferDone => w.dma_seg_trans_done().bit(enable),
95
                #[cfg(spi_master_has_app_interrupts)]
96
                SpiInterrupt::App2 => w.app2().bit(enable),
97
                #[cfg(spi_master_has_app_interrupts)]
98
                SpiInterrupt::App1 => w.app1().bit(enable),
99
            };
100
        }
101
        w
102
    });
103
}
104

            
105
pub(super) fn interrupts(driver: &Driver) -> EnumSet<SpiInterrupt> {
106
    let ints = driver.regs().dma_int_raw().read();
107
    let mut res = EnumSet::new();
108

            
109
    if ints.trans_done().bit() {
110
        res.insert(SpiInterrupt::TransferDone);
111
    }
112
    #[cfg(spi_master_has_dma_segmented_transfer)]
113
    if ints.dma_seg_trans_done().bit() {
114
        res.insert(SpiInterrupt::DmaSegmentedTransferDone);
115
    }
116
    #[cfg(spi_master_has_app_interrupts)]
117
    if ints.app2().bit() {
118
        res.insert(SpiInterrupt::App2);
119
    }
120
    #[cfg(spi_master_has_app_interrupts)]
121
    if ints.app1().bit() {
122
        res.insert(SpiInterrupt::App1);
123
    }
124

            
125
    res
126
}
127

            
128
pub(super) fn clear_interrupts(driver: &Driver, interrupts: EnumSet<SpiInterrupt>) {
129
    driver.regs().dma_int_clr().write(|w| {
130
        for interrupt in interrupts {
131
            match interrupt {
132
                SpiInterrupt::TransferDone => w.trans_done().clear_bit_by_one(),
133
                #[cfg(spi_master_has_dma_segmented_transfer)]
134
                SpiInterrupt::DmaSegmentedTransferDone => w.dma_seg_trans_done().clear_bit_by_one(),
135
                #[cfg(spi_master_has_app_interrupts)]
136
                SpiInterrupt::App2 => w.app2().clear_bit_by_one(),
137
                #[cfg(spi_master_has_app_interrupts)]
138
                SpiInterrupt::App1 => w.app1().clear_bit_by_one(),
139
            };
140
        }
141
        w
142
    });
143
}
144

            
145
pub(super) fn configure_datalen(driver: &Driver, rx_len: u32, tx_len: u32) {
146
    driver
147
        .regs()
148
        .ms_dlen()
149
        .write(|w| unsafe { w.ms_data_bitlen().bits(rx_len.max(tx_len)) });
150
}