init commit
This commit is contained in:
203
zynq7000/src/i2c.rs
Normal file
203
zynq7000/src/i2c.rs
Normal 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) }
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user