Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion protocol/usb/cdc_acm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ impl CdcAcmBuilder {
},
EpIn {
num: self.data_in_ep,
buf_pool_size: 1,
buf_pool_size: 4,
},
],
[EpOut {
Expand Down
22 changes: 22 additions & 0 deletions services/flash/opcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,25 @@ pub struct ReadOp {
/// The number of bytes to read.
pub length: u32,
}

/// IPC opcode for reading JEDEC ID from flash.
pub const IPC_OP_FLASH_READ_ID: Opcode = Opcode::new(*b"FLID");

/// Arguments for the `IPC_OP_FLASH_READ_ID` request.
#[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C)]
pub struct ReadIdOp {
/// Index of the SPI EEPROM (0 or 1).
pub eeprom_index: u8,
}

/// Response returned by `IPC_OP_FLASH_READ_ID`.
#[derive(
FromBytes, IntoBytes, KnownLayout, Immutable, Default, Clone, Copy, Debug, PartialEq, Eq,
)]
#[repr(C)]
pub struct JedecIdResp {
pub manufacturer: u8,
pub memory_type: u8,
pub capacity_code: u8,
}
8 changes: 8 additions & 0 deletions services/flash/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ impl<TFlash: Flash<Error = ErrorCode>> FlashIpcServer<TFlash> {
Self { flash }
}

pub fn flash(&self) -> &TFlash {
&self.flash
}

pub fn flash_mut(&mut self) -> &mut TFlash {
&mut self.flash
}

/// Handles the `IPC_OP_FLASH_GET_INFO` request.
///
/// Writes the flash geometry into the provided buffer and returns it.
Expand Down
9 changes: 9 additions & 0 deletions target/earlgrey/drivers/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ rust_library(
],
)

rust_test(
name = "pinmux_test",
crate = ":pinmux",
rustc_flags = [
"-C",
"debug-assertions",
],
)

rust_library(
name = "eflash_driver",
srcs = ["eflash_driver.rs"],
Expand Down
187 changes: 187 additions & 0 deletions target/earlgrey/drivers/pinmux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,79 @@ pub enum Pull {
Down,
}

#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
#[repr(u32)]
pub enum SlewRate {
#[default]
Slowest = 0,
Slow = 1,
Fast = 2,
Fastest = 3,
}

impl SlewRate {
pub const fn from_raw(val: u32) -> Self {
match val & 3 {
0 => Self::Slowest,
1 => Self::Slow,
2 => Self::Fast,
_ => Self::Fastest,
}
}
}

#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
#[repr(u32)]
pub enum DriveStrength {
#[default]
Drive0 = 0,
Drive1 = 1,
Drive2 = 2,
Drive3 = 3,
Drive4 = 4,
Drive5 = 5,
Drive6 = 6,
Drive7 = 7,
Drive8 = 8,
Drive9 = 9,
Drive10 = 10,
Drive11 = 11,
Drive12 = 12,
Drive13 = 13,
Drive14 = 14,
Drive15 = 15,
}

impl DriveStrength {
pub const fn from_raw(val: u32) -> Self {
match val & 0xf {
0 => Self::Drive0,
1 => Self::Drive1,
2 => Self::Drive2,
3 => Self::Drive3,
4 => Self::Drive4,
5 => Self::Drive5,
6 => Self::Drive6,
7 => Self::Drive7,
8 => Self::Drive8,
9 => Self::Drive9,
10 => Self::Drive10,
11 => Self::Drive11,
12 => Self::Drive12,
13 => Self::Drive13,
14 => Self::Drive14,
_ => Self::Drive15,
}
}
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct PadConfig {
pub pull: Pull,
pub open_drain: bool,
pub invert: bool,
pub slew_rate: SlewRate,
pub drive_strength: DriveStrength,
}

impl Default for PadConfig {
Expand All @@ -143,10 +212,39 @@ impl Default for PadConfig {
pull: Pull::None,
open_drain: false,
invert: false,
slew_rate: SlewRate::Slowest,
drive_strength: DriveStrength::Drive0,
}
}
}

impl PadConfig {
pub const fn with_pull(mut self, pull: Pull) -> Self {
self.pull = pull;
self
}

pub const fn with_open_drain(mut self, open_drain: bool) -> Self {
self.open_drain = open_drain;
self
}

pub const fn with_invert(mut self, invert: bool) -> Self {
self.invert = invert;
self
}

pub const fn with_slew_rate(mut self, slew_rate: SlewRate) -> Self {
self.slew_rate = slew_rate;
self
}

pub const fn with_drive_strength(mut self, drive_strength: DriveStrength) -> Self {
self.drive_strength = drive_strength;
self
}
}

pub struct EarlGreyPinmux {
registers: pinmux::RegisterBlock<ureg::RealMmioMut<'static>>,
}
Expand Down Expand Up @@ -202,6 +300,8 @@ impl EarlGreyPinmux {
})
.od_en(config.open_drain)
.invert(config.invert)
.slew_rate(config.slew_rate as u32)
.drive_strength(config.drive_strength as u32)
});
Ok(())
} else if let Some(mio_idx) = pad.mio_index() {
Expand All @@ -216,6 +316,8 @@ impl EarlGreyPinmux {
})
.od_en(config.open_drain)
.invert(config.invert)
.slew_rate(config.slew_rate as u32)
.drive_strength(config.drive_strength as u32)
});
Ok(())
} else if pad.as_insel().is_some() {
Expand All @@ -226,4 +328,89 @@ impl EarlGreyPinmux {
Err(EG_PINMUX_INVALID_PAD)
}
}

pub fn get_pad_config(&self, pad: Pad) -> Result<PadConfig, ErrorCode> {
let (pull_en, pull_sel, od_en, invert, slew_rate, drive_strength) =
if let Some(dio_idx) = pad.dio_index() {
let reg = self.registers.dio_pad_attr().at(dio_idx).read();
(
reg.pull_en(),
reg.pull_select(),
reg.od_en(),
reg.invert(),
reg.slew_rate(),
reg.drive_strength(),
)
} else if let Some(mio_idx) = pad.mio_index() {
let reg = self.registers.mio_pad_attr().at(mio_idx).read();
(
reg.pull_en(),
reg.pull_select(),
reg.od_en(),
reg.invert(),
reg.slew_rate(),
reg.drive_strength(),
)
} else if pad.as_insel().is_some() {
// Constant pads (ConstantZero, ConstantOne) have valid input selectors
// but no physical pad attributes to configure.
return Ok(PadConfig::default());
} else {
return Err(EG_PINMUX_INVALID_PAD);
};

let pull = if !pull_en {
Pull::None
} else if pull_sel == pinmux::enums::PullSelect::PullUp {
Pull::Up
} else {
Pull::Down
};

Ok(PadConfig {
pull,
open_drain: od_en,
invert,
slew_rate: SlewRate::from_raw(slew_rate),
drive_strength: DriveStrength::from_raw(drive_strength),
})
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_slew_rate_from_raw() {
assert_eq!(SlewRate::from_raw(0), SlewRate::Slowest);
assert_eq!(SlewRate::from_raw(1), SlewRate::Slow);
assert_eq!(SlewRate::from_raw(2), SlewRate::Fast);
assert_eq!(SlewRate::from_raw(3), SlewRate::Fastest);
assert_eq!(SlewRate::from_raw(4), SlewRate::Slowest);
}

#[test]
fn test_drive_strength_from_raw() {
assert_eq!(DriveStrength::from_raw(0), DriveStrength::Drive0);
assert_eq!(DriveStrength::from_raw(5), DriveStrength::Drive5);
assert_eq!(DriveStrength::from_raw(15), DriveStrength::Drive15);
assert_eq!(DriveStrength::from_raw(16), DriveStrength::Drive0);
}

#[test]
fn test_pad_config_builder() {
let config = PadConfig::default()
.with_pull(Pull::Up)
.with_open_drain(true)
.with_invert(true)
.with_slew_rate(SlewRate::Fast)
.with_drive_strength(DriveStrength::Drive7);

assert_eq!(config.pull, Pull::Up);
assert!(config.open_drain);
assert!(config.invert);
assert_eq!(config.slew_rate, SlewRate::Fast);
assert_eq!(config.drive_strength, DriveStrength::Drive7);
}
}
Loading