Skip to content
Merged
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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "intel-spi"
version = "0.1.7"
authors = ["Jeremy Soller <jeremy@system76.com>"]
edition = "2021"
edition = "2024"
description = "Library for accessing Intel PCH SPI"
license = "MIT"

Expand Down
2 changes: 1 addition & 1 deletion examples/read.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT

extern crate libc;
extern crate intel_spi;
extern crate libc;

use intel_spi::Spi;
use std::fs;
Expand Down
52 changes: 31 additions & 21 deletions examples/util/mod.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
// SPDX-License-Identifier: MIT

use intel_spi::{Mapper, SpiDev, PhysicalAddress, VirtualAddress};
use intel_spi::{Mapper, PhysicalAddress, SpiDev, VirtualAddress};

use std::{fs, ptr};

pub struct LinuxMapper;

impl Mapper for LinuxMapper {
unsafe fn map_aligned(&mut self, address: PhysicalAddress, size: usize) -> Result<VirtualAddress, &'static str> {
let fd = libc::open(
b"/dev/mem\0".as_ptr() as *const libc::c_char,
libc::O_RDWR
);
if fd < 0 {
return Err("failed to open /dev/mem")
}
unsafe fn map_aligned(
&mut self,
address: PhysicalAddress,
size: usize,
) -> Result<VirtualAddress, &'static str> {
let ptr = unsafe {
let fd = libc::open(c"/dev/mem".as_ptr() as *const libc::c_char, libc::O_RDWR);
if fd < 0 {
return Err("failed to open /dev/mem");
}

let libc_ptr = libc::mmap(
ptr::null_mut(),
size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED,
fd,
address.0 as libc::off_t,
);

let ptr = libc::mmap(
ptr::null_mut(),
size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED,
fd,
address.0 as libc::off_t
);
libc::close(fd);

libc::close(fd);
libc_ptr
};

if ptr == libc::MAP_FAILED {
return Err("failed to map /dev/mem");
Expand All @@ -34,8 +39,12 @@ impl Mapper for LinuxMapper {
Ok(VirtualAddress(ptr as usize))
}

unsafe fn unmap_aligned(&mut self, address: VirtualAddress, size: usize) -> Result<(), &'static str> {
if libc::munmap(address.0 as *mut libc::c_void, size) == 0 {
unsafe fn unmap_aligned(
&mut self,
address: VirtualAddress,
size: usize,
) -> Result<(), &'static str> {
if unsafe { libc::munmap(address.0 as *mut libc::c_void, size) } == 0 {
Ok(())
} else {
Err("failed to unmap /dev/mem")
Expand All @@ -48,8 +57,9 @@ impl Mapper for LinuxMapper {
}
}

#[allow(static_mut_refs)]
pub unsafe fn get_spi() -> SpiDev<'static, LinuxMapper> {
static mut LINUX_MAPPER: LinuxMapper = LinuxMapper;
let mcfg = fs::read("/sys/firmware/acpi/tables/MCFG").expect("failed to read MCFG");
SpiDev::new(&mcfg, &mut LINUX_MAPPER).expect("failed to get SPI device")
unsafe { SpiDev::new(&mcfg, &mut LINUX_MAPPER).expect("failed to get SPI device") }
}
24 changes: 16 additions & 8 deletions src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ use core::cmp::PartialEq;
use core::ops::{BitAnd, BitOr, Not};

pub trait Io {
type Value: Copy + PartialEq + BitAnd<Output = Self::Value> + BitOr<Output = Self::Value> + Not<Output = Self::Value>;
type Value: Copy
+ PartialEq
+ BitAnd<Output = Self::Value>
+ BitOr<Output = Self::Value>
+ Not<Output = Self::Value>;

fn read(&self) -> Self::Value;
fn write(&mut self, value: Self::Value);

#[inline(always)]
fn readf(&self, flags: Self::Value) -> bool {
fn readf(&self, flags: Self::Value) -> bool {
(self.read() & flags) as Self::Value == flags
}

Expand All @@ -27,12 +31,14 @@ pub trait Io {
}

pub struct ReadOnly<I: Io> {
inner: I
inner: I,
}

impl<I: Io> ReadOnly<I> {
pub /* const */ fn new(inner: I) -> Self {
Self { inner }
pub fn new(inner: I) -> Self {
Self {
inner,
}
}

#[inline(always)]
Expand All @@ -47,12 +53,14 @@ impl<I: Io> ReadOnly<I> {
}

pub struct WriteOnly<I: Io> {
inner: I
inner: I,
}

impl<I: Io> WriteOnly<I> {
pub /* const */ fn new(inner: I) -> Self {
Self { inner }
pub fn new(inner: I) -> Self {
Self {
inner,
}
}

#[inline(always)]
Expand Down
110 changes: 49 additions & 61 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,28 @@ use core::{cmp, mem, slice};
pub use self::io::Io;
mod io;

pub use self::mapper::{PhysicalAddress, VirtualAddress, Mapper};
pub use self::mapper::{Mapper, PhysicalAddress, VirtualAddress};
mod mapper;

pub use self::mmio::Mmio;
mod mmio;

pub const PCI_VID_INTEL: u16 = 0x8086;

pub static PCI_IDS: &[(u16, u16)] = &[
(0x8086, 0x02A4), // Comet Lake
(0x8086, 0x06A4), // Comet Lake-H
(0x8086, 0x43A4), // Tiger Lake-H
(0x8086, 0x51A4), // Alder Lake-P
(0x8086, 0x7723), // Arrow Lake-HU
(0x8086, 0x7A24), // Alder Lake-S
(0x8086, 0x7E23), // Meteor Lake-HU
(0x8086, 0x9DA4), // Cannon Lake
(0x8086, 0xA0A4), // Tiger Lake
(0x8086, 0xA324), // Cannon Lake-H
(0x8086, 0xA324), // Cannon Lake-H
(PCI_VID_INTEL, 0x02A4), // Comet Lake
(PCI_VID_INTEL, 0x06A4), // Comet Lake-H
(PCI_VID_INTEL, 0x43A4), // Tiger Lake-H
(PCI_VID_INTEL, 0x51A4), // Alder Lake-P
(PCI_VID_INTEL, 0x7723), // Arrow Lake-HU
(PCI_VID_INTEL, 0x7A24), // Alder Lake-S
(PCI_VID_INTEL, 0x7E23), // Meteor Lake-HU
(PCI_VID_INTEL, 0x9DA4), // Cannon Lake
(PCI_VID_INTEL, 0xA0A4), // Tiger Lake
(PCI_VID_INTEL, 0xA324), // Cannon Lake-H
(PCI_VID_INTEL, 0xA324), // Cannon Lake-H
(PCI_VID_INTEL, 0xE323), // Panther Lake-UH
(PCI_VID_INTEL, 0xE423), // Panther Lake-H
];

#[derive(Debug)]
Expand Down Expand Up @@ -59,58 +63,50 @@ pub struct SpiDev<'m, M: Mapper> {
impl<'m, M: Mapper> SpiDev<'m, M> {
#[allow(clippy::missing_safety_doc)]
pub unsafe fn new(mcfg: &[u8], mapper: &'m mut M) -> Result<Self, &'static str> {
let pcie_base =
(mcfg[0x2c] as usize) |
(mcfg[0x2d] as usize) << 8 |
(mcfg[0x2e] as usize) << 16 |
(mcfg[0x2f] as usize) << 24 |
(mcfg[0x30] as usize) << 32 |
(mcfg[0x31] as usize) << 40 |
(mcfg[0x32] as usize) << 48 |
(mcfg[0x33] as usize) << 56;
let pcie_base = (mcfg[0x2c] as usize)
| ((mcfg[0x2d] as usize) << 8)
| ((mcfg[0x2e] as usize) << 16)
| ((mcfg[0x2f] as usize) << 24)
| ((mcfg[0x30] as usize) << 32)
| ((mcfg[0x31] as usize) << 40)
| ((mcfg[0x32] as usize) << 48)
| ((mcfg[0x33] as usize) << 56);

let mut phys_opt = None;
{
let (pcie_bus, pcie_dev, pcie_func) = (0x00, 0x1F, 0x05);
let pcie_size = 4096;

let pcie_phys = PhysicalAddress(
pcie_base |
(pcie_bus << 20) |
(pcie_dev << 15) |
(pcie_func << 12)
pcie_base | (pcie_bus << 20) | (pcie_dev << 15) | (pcie_func << 12),
);
let pcie_virt = mapper.map(pcie_phys, pcie_size)?;
let pcie_virt = unsafe { mapper.map(pcie_phys, pcie_size)? };
{
let pcie_space = slice::from_raw_parts_mut(pcie_virt.0 as *mut u8, pcie_size);

let vendor_id =
(pcie_space[0x00] as u16) |
(pcie_space[0x01] as u16) << 8;
let product_id =
(pcie_space[0x02] as u16) |
(pcie_space[0x03] as u16) << 8;
let pcie_space =
unsafe { slice::from_raw_parts_mut(pcie_virt.0 as *mut u8, pcie_size) };

let vendor_id = (pcie_space[0x00] as u16) | ((pcie_space[0x01] as u16) << 8);
let product_id = (pcie_space[0x02] as u16) | ((pcie_space[0x03] as u16) << 8);
for known_id in PCI_IDS.iter() {
if known_id.0 == vendor_id && known_id.1 == product_id {
let bar0 =
(pcie_space[0x10] as u32) |
(pcie_space[0x11] as u32) << 8 |
(pcie_space[0x12] as u32) << 16 |
(pcie_space[0x13] as u32) << 24;
let bar0 = (pcie_space[0x10] as u32)
| ((pcie_space[0x11] as u32) << 8)
| ((pcie_space[0x12] as u32) << 16)
| ((pcie_space[0x13] as u32) << 24);
phys_opt = Some(PhysicalAddress(bar0 as usize));
break;
}
}
}
mapper.unmap(pcie_virt, pcie_size)?;
unsafe { mapper.unmap(pcie_virt, pcie_size)? };
}

let phys = match phys_opt {
Some(some) => some,
None => return Err("no supported SPI device found"),
};
let virt = mapper.map(phys, mem::size_of::<SpiRegs>())?;
let regs = &mut *(virt.0 as *mut SpiRegs);
let virt = unsafe { mapper.map(phys, mem::size_of::<SpiRegs>())? };
let regs = unsafe { &mut *(virt.0 as *mut SpiRegs) };

Ok(Self {
mapper,
Expand All @@ -119,7 +115,7 @@ impl<'m, M: Mapper> SpiDev<'m, M> {
}
}

impl<'m, M: Mapper> Spi for SpiDev<'m, M> {
impl<M: Mapper> Spi for SpiDev<'_, M> {
fn len(&mut self) -> Result<usize, SpiError> {
self.regs.len()
}
Expand All @@ -137,7 +133,7 @@ impl<'m, M: Mapper> Spi for SpiDev<'m, M> {
}
}

impl<'m, M: Mapper> Drop for SpiDev<'m, M> {
impl<M: Mapper> Drop for SpiDev<'_, M> {
fn drop(&mut self) {
let virt = VirtualAddress(self.regs as *mut SpiRegs as usize);
let _ = unsafe { self.mapper.unmap(virt, mem::size_of::<SpiRegs>()) };
Expand Down Expand Up @@ -231,21 +227,16 @@ impl HsfStsCtl {
}

fn set_cycle(&mut self, value: HsfStsCtlCycle) {
*self = (*self & !Self::FCYCLE) | (
Self::from_bits_truncate(value as u32)
);
*self = (*self & !Self::FCYCLE) | (Self::from_bits_truncate(value as u32));
}

fn count(&self) -> u8 {
(((*self & Self::FDBC).bits() >> 24) + 1) as u8
}

fn set_count(&mut self, value: u8) {
*self = (*self & !Self::FDBC) | (
Self::from_bits_truncate(
(cmp::max(value, 64).saturating_sub(1) as u32) << 24
)
);
*self = (*self & !Self::FDBC)
| (Self::from_bits_truncate((cmp::max(value, 64).saturating_sub(1) as u32) << 24));
}
}

Expand Down Expand Up @@ -280,7 +271,7 @@ pub enum FdoSection {
Map = 0b000 << 12,
Component = 0b001 << 12,
Region = 0b010 << 12,
Master = 0b011 << 12
Master = 0b011 << 12,
}

#[allow(dead_code)]
Expand Down Expand Up @@ -337,10 +328,7 @@ impl SpiRegs {
}

pub fn fdo(&mut self, section: FdoSection, index: u16) -> u32 {
self.fdoc.write(
(section as u32) |
(((index & 0b1111111111) as u32) << 2)
);
self.fdoc.write((section as u32) | (((index & 0b1111111111) as u32) << 2));
self.fdod.read()
}
}
Expand All @@ -360,7 +348,7 @@ impl Spi for SpiRegs {
0b101 => 16 * mib,
0b110 => 32 * mib,
0b111 => 64 * mib,
_ => return Err(SpiError::Register)
_ => return Err(SpiError::Register),
})
}

Expand All @@ -372,7 +360,7 @@ impl Spi for SpiRegs {
// Wait for other transactions
loop {
hsfsts_ctl = self.hsfsts_ctl();
if ! hsfsts_ctl.contains(HsfStsCtl::H_SCIP) {
if !hsfsts_ctl.contains(HsfStsCtl::H_SCIP) {
break;
}
}
Expand Down Expand Up @@ -425,7 +413,7 @@ impl Spi for SpiRegs {
// Wait for other transactions
loop {
hsfsts_ctl = self.hsfsts_ctl();
if ! hsfsts_ctl.contains(HsfStsCtl::H_SCIP) {
if !hsfsts_ctl.contains(HsfStsCtl::H_SCIP) {
break;
}
}
Expand Down Expand Up @@ -470,7 +458,7 @@ impl Spi for SpiRegs {
// Wait for other transactions
loop {
hsfsts_ctl = self.hsfsts_ctl();
if ! hsfsts_ctl.contains(HsfStsCtl::H_SCIP) {
if !hsfsts_ctl.contains(HsfStsCtl::H_SCIP) {
break;
}
}
Expand Down
Loading