use super::{DMA_BASE, read_reg, reg_bit_check_clear, reg_bit_ops, reg_ro, reg_rw, write_reg};
pub const DMABUSMODE_OFFSET: usize = 0x00;
pub const DMATXPOLLDEMAND_OFFSET: usize = 0x04;
pub const DMARXPOLLDEMAND_OFFSET: usize = 0x08;
pub const DMARXBASEADDR_OFFSET: usize = 0x0C;
pub const DMATXBASEADDR_OFFSET: usize = 0x10;
pub const DMASTATUS_OFFSET: usize = 0x14;
pub const DMAOPERATION_OFFSET: usize = 0x18;
pub const DMAINTENABLE_OFFSET: usize = 0x1C;
pub const DMAMISSEDFR_OFFSET: usize = 0x20;
pub const DMARXWATCHDOG_OFFSET: usize = 0x24;
pub const DMACURTXDESC_OFFSET: usize = 0x48;
pub const DMACURRXDESC_OFFSET: usize = 0x4C;
pub const DMACURTXBUFADDR_OFFSET: usize = 0x50;
pub const DMACURRXBUFADDR_OFFSET: usize = 0x54;
pub const DMABUSMODE_SW_RST: u32 = 1 << 0;
pub const DMABUSMODE_DMA_ARB: u32 = 1 << 1;
pub const DMABUSMODE_DSL_SHIFT: u32 = 2;
pub const DMABUSMODE_DSL_MASK: u32 = 0x1F << 2;
pub const DMABUSMODE_ATDS: u32 = 1 << 7;
pub const DMABUSMODE_PBL_SHIFT: u32 = 8;
pub const DMABUSMODE_PBL_MASK: u32 = 0x3F << 8;
pub const DMABUSMODE_FB: u32 = 1 << 16;
pub const DMABUSMODE_RPBL_SHIFT: u32 = 17;
pub const DMABUSMODE_RPBL_MASK: u32 = 0x3F << 17;
pub const DMABUSMODE_USP: u32 = 1 << 23;
pub const DMABUSMODE_PBL_X8: u32 = 1 << 24;
pub const DMABUSMODE_AAL: u32 = 1 << 25;
pub const DMABUSMODE_MB: u32 = 1 << 26;
pub const DMABUSMODE_TXPR: u32 = 1 << 27;
pub const DMASTATUS_TI: u32 = 1 << 0;
pub const DMASTATUS_TPS: u32 = 1 << 1;
pub const DMASTATUS_TU: u32 = 1 << 2;
pub const DMASTATUS_TJT: u32 = 1 << 3;
pub const DMASTATUS_OVF: u32 = 1 << 4;
pub const DMASTATUS_UNF: u32 = 1 << 5;
pub const DMASTATUS_RI: u32 = 1 << 6;
pub const DMASTATUS_RU: u32 = 1 << 7;
pub const DMASTATUS_RPS: u32 = 1 << 8;
pub const DMASTATUS_RWT: u32 = 1 << 9;
pub const DMASTATUS_ETI: u32 = 1 << 10;
pub const DMASTATUS_FBI: u32 = 1 << 13;
pub const DMASTATUS_ERI: u32 = 1 << 14;
pub const DMASTATUS_AIS: u32 = 1 << 15;
pub const DMASTATUS_NIS: u32 = 1 << 16;
pub const DMASTATUS_RS_SHIFT: u32 = 17;
pub const DMASTATUS_RS_MASK: u32 = 0x7 << 17;
pub const DMASTATUS_TS_SHIFT: u32 = 20;
pub const DMASTATUS_TS_MASK: u32 = 0x7 << 20;
pub const DMASTATUS_EB_SHIFT: u32 = 23;
pub const DMASTATUS_EB_MASK: u32 = 0x7 << 23;
pub const DMASTATUS_ALL_INTERRUPTS: u32 = DMASTATUS_TI
| DMASTATUS_TPS
| DMASTATUS_TU
| DMASTATUS_TJT
| DMASTATUS_OVF
| DMASTATUS_UNF
| DMASTATUS_RI
| DMASTATUS_RU
| DMASTATUS_RPS
| DMASTATUS_RWT
| DMASTATUS_ETI
| DMASTATUS_FBI
| DMASTATUS_ERI
| DMASTATUS_AIS
| DMASTATUS_NIS;
pub const DMAOPERATION_SR: u32 = 1 << 1;
pub const DMAOPERATION_OSF: u32 = 1 << 2;
pub const DMAOPERATION_RTC_SHIFT: u32 = 3;
pub const DMAOPERATION_RTC_MASK: u32 = 0x3 << 3;
pub const DMAOPERATION_FUF: u32 = 1 << 6;
pub const DMAOPERATION_FEF: u32 = 1 << 7;
pub const DMAOPERATION_ST: u32 = 1 << 13;
pub const DMAOPERATION_TTC_SHIFT: u32 = 14;
pub const DMAOPERATION_TTC_MASK: u32 = 0x7 << 14;
pub const DMAOPERATION_FTF: u32 = 1 << 20;
pub const DMAOPERATION_TSF: u32 = 1 << 21;
pub const DMAOPERATION_DFF: u32 = 1 << 24;
pub const DMAOPERATION_RSF: u32 = 1 << 25;
pub const DMAOPERATION_DT: u32 = 1 << 26;
pub mod rtc {
pub const RTC_64: u32 = 0;
pub const RTC_32: u32 = 1;
pub const RTC_96: u32 = 2;
pub const RTC_128: u32 = 3;
}
pub mod ttc {
pub const TTC_64: u32 = 0;
pub const TTC_128: u32 = 1;
pub const TTC_192: u32 = 2;
pub const TTC_256: u32 = 3;
pub const TTC_40: u32 = 4;
pub const TTC_32: u32 = 5;
pub const TTC_24: u32 = 6;
pub const TTC_16: u32 = 7;
}
pub const DMAINTEN_TIE: u32 = 1 << 0;
pub const DMAINTEN_TSE: u32 = 1 << 1;
pub const DMAINTEN_TUE: u32 = 1 << 2;
pub const DMAINTEN_TJE: u32 = 1 << 3;
pub const DMAINTEN_OVE: u32 = 1 << 4;
pub const DMAINTEN_UNE: u32 = 1 << 5;
pub const DMAINTEN_RIE: u32 = 1 << 6;
pub const DMAINTEN_RUE: u32 = 1 << 7;
pub const DMAINTEN_RSE: u32 = 1 << 8;
pub const DMAINTEN_RWE: u32 = 1 << 9;
pub const DMAINTEN_ETE: u32 = 1 << 10;
pub const DMAINTEN_FBE: u32 = 1 << 13;
pub const DMAINTEN_ERE: u32 = 1 << 14;
pub const DMAINTEN_AIE: u32 = 1 << 15;
pub const DMAINTEN_NIE: u32 = 1 << 16;
pub const DMAINTEN_DEFAULT: u32 =
DMAINTEN_TIE | DMAINTEN_RIE | DMAINTEN_FBE | DMAINTEN_AIE | DMAINTEN_NIE;
pub struct DmaRegs;
impl DmaRegs {
#[inline(always)]
pub const fn base() -> usize {
DMA_BASE
}
reg_rw!(
bus_mode,
set_bus_mode,
DMA_BASE,
DMABUSMODE_OFFSET,
"Bus Mode register"
);
reg_rw!(
status,
set_status,
DMA_BASE,
DMASTATUS_OFFSET,
"Status register"
);
reg_rw!(
operation_mode,
set_operation_mode,
DMA_BASE,
DMAOPERATION_OFFSET,
"Operation Mode register"
);
reg_rw!(
interrupt_enable,
set_interrupt_enable,
DMA_BASE,
DMAINTENABLE_OFFSET,
"Interrupt Enable register"
);
reg_ro!(
missed_frames,
DMA_BASE,
DMAMISSEDFR_OFFSET,
"Missed Frame counter"
);
reg_ro!(
current_tx_desc,
DMA_BASE,
DMACURTXDESC_OFFSET,
"Current TX Descriptor address"
);
reg_ro!(
current_rx_desc,
DMA_BASE,
DMACURRXDESC_OFFSET,
"Current RX Descriptor address"
);
reg_ro!(
current_tx_buffer,
DMA_BASE,
DMACURTXBUFADDR_OFFSET,
"Current TX Buffer address"
);
reg_ro!(
current_rx_buffer,
DMA_BASE,
DMACURRXBUFADDR_OFFSET,
"Current RX Buffer address"
);
reg_bit_ops!(
start_tx,
stop_tx,
DMA_BASE,
DMAOPERATION_OFFSET,
DMAOPERATION_ST,
"TX DMA",
"Start",
"Stop"
);
reg_bit_ops!(
start_rx,
stop_rx,
DMA_BASE,
DMAOPERATION_OFFSET,
DMAOPERATION_SR,
"RX DMA",
"Start",
"Stop"
);
reg_bit_check_clear!(
is_tx_fifo_flush_complete,
DMA_BASE,
DMAOPERATION_OFFSET,
DMAOPERATION_FTF,
"Check if TX FIFO flush is complete"
);
reg_bit_check_clear!(
is_reset_complete,
DMA_BASE,
DMABUSMODE_OFFSET,
DMABUSMODE_SW_RST,
"Check if software reset is complete"
);
#[inline(always)]
pub fn tx_poll_demand() {
unsafe { write_reg(DMA_BASE + DMATXPOLLDEMAND_OFFSET, 0) }
}
#[inline(always)]
pub fn rx_poll_demand() {
unsafe { write_reg(DMA_BASE + DMARXPOLLDEMAND_OFFSET, 0) }
}
#[inline(always)]
pub fn set_rx_desc_list_addr(addr: u32) {
unsafe { write_reg(DMA_BASE + DMARXBASEADDR_OFFSET, addr) }
}
#[inline(always)]
pub fn set_tx_desc_list_addr(addr: u32) {
unsafe { write_reg(DMA_BASE + DMATXBASEADDR_OFFSET, addr) }
}
#[inline(always)]
pub fn clear_all_interrupts() {
Self::set_status(DMASTATUS_ALL_INTERRUPTS);
}
#[inline(always)]
pub fn flush_tx_fifo() {
unsafe {
let mode = read_reg(DMA_BASE + DMAOPERATION_OFFSET);
write_reg(DMA_BASE + DMAOPERATION_OFFSET, mode | DMAOPERATION_FTF);
}
}
#[inline(always)]
pub fn enable_default_interrupts() {
Self::set_interrupt_enable(DMAINTEN_DEFAULT);
}
#[inline(always)]
pub fn disable_all_interrupts() {
Self::set_interrupt_enable(0);
}
#[inline(always)]
pub fn set_rx_watchdog(value: u8) {
unsafe { write_reg(DMA_BASE + DMARXWATCHDOG_OFFSET, value as u32) }
}
#[inline(always)]
pub fn software_reset() {
Self::set_bus_mode(DMABUSMODE_SW_RST);
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum RxProcessState {
Stopped = 0,
FetchingDescriptor = 1,
Reserved2 = 2,
WaitingForPacket = 3,
Suspended = 4,
ClosingDescriptor = 5,
Reserved6 = 6,
TransferringData = 7,
}
impl From<u32> for RxProcessState {
fn from(value: u32) -> Self {
match (value & DMASTATUS_RS_MASK) >> DMASTATUS_RS_SHIFT {
0 => RxProcessState::Stopped,
1 => RxProcessState::FetchingDescriptor,
2 => RxProcessState::Reserved2,
3 => RxProcessState::WaitingForPacket,
4 => RxProcessState::Suspended,
5 => RxProcessState::ClosingDescriptor,
6 => RxProcessState::Reserved6,
_ => RxProcessState::TransferringData,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum TxProcessState {
Stopped = 0,
FetchingDescriptor = 1,
WaitingForStatus = 2,
ReadingData = 3,
Reserved4 = 4,
Reserved5 = 5,
Suspended = 6,
ClosingDescriptor = 7,
}
impl From<u32> for TxProcessState {
fn from(value: u32) -> Self {
match (value & DMASTATUS_TS_MASK) >> DMASTATUS_TS_SHIFT {
0 => TxProcessState::Stopped,
1 => TxProcessState::FetchingDescriptor,
2 => TxProcessState::WaitingForStatus,
3 => TxProcessState::ReadingData,
4 => TxProcessState::Reserved4,
5 => TxProcessState::Reserved5,
6 => TxProcessState::Suspended,
_ => TxProcessState::ClosingDescriptor,
}
}
}