init commit

This commit is contained in:
2025-02-19 11:00:04 +01:00
commit f842673e3a
104 changed files with 21595 additions and 0 deletions

203
zynq7000/src/i2c.rs Normal file
View File

@ -0,0 +1,203 @@
//! SPI register module.
use arbitrary_int::{u2, u6, u10};
pub const I2C_0_BASE_ADDR: usize = 0xE000_4000;
pub const I2C_1_BASE_ADDR: usize = 0xE000_5000;
#[bitbybit::bitenum(u1, exhaustive = true)]
#[derive(Debug)]
pub enum Direction {
Receiver = 0b1,
Transmitter = 0b0,
}
#[bitbybit::bitenum(u1, exhaustive = true)]
#[derive(Debug)]
pub enum Mode {
Slave = 0b0,
Master = 0b1,
}
#[bitbybit::bitfield(u32, default = 0x0)]
pub struct Control {
/// Divides the input PCLK frequency by this value + 1
#[bits(14..=15, rw)]
div_a: u2,
/// Divides the output from divisor A by this value + 1
#[bits(8..=13, rw)]
div_b: u6,
#[bit(6, rw)]
clear_fifo: bool,
#[bit(5, rw)]
slv_mon: bool,
/// 0: Allow transfer to terminate as soon as all data has been transmitted or received.
/// 1: When no more data is avilable for transmit or no more data can be received, hold
/// the SCK line low until services by the host.
#[bit(4, rw)]
hold_bus: bool,
/// Should be set to 1. 0: Disabled, NACK transmitted. 1: Enabled, ACK transmitted.
#[bit(3, rw)]
acken: bool,
/// Only used in master mode. 0: Reserved. 1: Normal 7-bit address.
#[bit(2, rw)]
addressing: bool,
#[bit(1, rw)]
mode: Mode,
#[bit(0, rw)]
dir: Direction,
}
#[bitbybit::bitfield(u32)]
pub struct Status {
#[bit(8, r)]
bus_active: bool,
/// FIFO is full and new byte was received. The new byte is not acknowledged and the contents
/// of the FIFO remain unchanged.
#[bit(6, r)]
rx_overflow: bool,
/// 1: There is still a byte of data to be transmitted by the interface.
#[bit(6, r)]
tx_busy: bool,
/// Receiver data valid, ca be read from the interface.
#[bit(5, r)]
rx_valid: bool,
#[bit(3, r)]
rx_rw: bool,
}
#[bitbybit::bitfield(u32)]
pub struct Addr {
#[bits(0..=9, rw)]
addr: u10,
}
#[bitbybit::bitfield(u32)]
pub struct Fifo {
#[bits(0..=7, rw)]
data: u8,
}
#[bitbybit::bitfield(u32)]
pub struct InterruptStatus {
#[bit(9, rw)]
arbitration_lost: bool,
#[bit(7, rw)]
rx_underflow: bool,
#[bit(6, rw)]
tx_overflow: bool,
#[bit(5, rw)]
rx_overflow: bool,
#[bit(4, rw)]
slave_ready: bool,
#[bit(3, rw)]
timeout: bool,
#[bit(2, rw)]
nack: bool,
#[bit(1, rw)]
data: bool,
#[bit(0, rw)]
complete: bool,
}
#[bitbybit::bitfield(u32)]
pub struct InterruptMask {
#[bit(9, r)]
arbitration_lost: bool,
#[bit(7, r)]
rx_underflow: bool,
#[bit(6, r)]
tx_overflow: bool,
#[bit(5, r)]
rx_overflow: bool,
#[bit(4, r)]
slave_ready: bool,
#[bit(3, r)]
timeout: bool,
#[bit(2, r)]
nack: bool,
#[bit(1, r)]
data: bool,
#[bit(0, r)]
complete: bool,
}
#[bitbybit::bitfield(u32)]
pub struct InterruptControl {
#[bit(9, w)]
arbitration_lost: bool,
#[bit(7, w)]
rx_underflow: bool,
#[bit(6, w)]
tx_overflow: bool,
#[bit(5, w)]
rx_overflow: bool,
#[bit(4, w)]
slave_ready: bool,
#[bit(3, w)]
timeout: bool,
#[bit(2, w)]
nack: bool,
#[bit(1, w)]
data: bool,
#[bit(0, w)]
complete: bool,
}
#[bitbybit::bitfield(u32)]
pub struct Timeout {
/// Reset value: 0x1F.
#[bits(0..=7, rw)]
timeout: u8,
}
#[bitbybit::bitfield(u32, default = 0x0)]
pub struct TransferSize {
#[bits(0..=7, rw)]
size: u8,
}
#[derive(derive_mmio::Mmio)]
#[repr(C)]
pub struct I2c {
cr: Control,
#[mmio(PureRead)]
sr: Status,
addr: Addr,
#[mmio(Read, Write)]
data: Fifo,
#[mmio(PureRead, Write, Modify)]
isr: InterruptStatus,
transfer_size: TransferSize,
slave_pause: u32,
timeout: Timeout,
#[mmio(PureRead)]
imr: InterruptMask,
#[mmio(Write)]
ier: InterruptControl,
#[mmio(Write)]
idr: InterruptControl,
}
impl I2c {
/// Create a new I2C MMIO instance for I2C0 at address [I2C_0_BASE_ADDR].
///
/// # Safety
///
/// This API can be used to potentially create a driver to the same peripheral structure
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
/// interfere with each other.
pub const unsafe fn new_mmio_fixed_0() -> MmioI2c<'static> {
unsafe { Self::new_mmio_at(I2C_0_BASE_ADDR) }
}
/// Create a new I2C MMIO instance for I2C1 at address [I2C_1_BASE_ADDR].
///
/// # Safety
///
/// This API can be used to potentially create a driver to the same peripheral structure
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
/// interfere with each other.
pub const unsafe fn new_mmio_fixed_1() -> MmioI2c<'static> {
unsafe { Self::new_mmio_at(I2C_1_BASE_ADDR) }
}
}