Skip to content

Commit

Permalink
Add IMX3112 mux and APML devices to Grapefruit
Browse files Browse the repository at this point in the history
  • Loading branch information
mkeeter committed Jan 16, 2025
1 parent 794bded commit 0241411
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 2 deletions.
25 changes: 25 additions & 0 deletions app/grapefruit/app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,11 @@ sda.pin = 11
scl.pin = 10
af = 4

[[config.i2c.controllers.ports.B.muxes]]
driver = "imx3112"
address = 0x70
# U6 on AMD Ruby schematic

[config.i2c.controllers.ports.F]
name = "pcie"
sda.pin = 0
Expand Down Expand Up @@ -528,6 +533,26 @@ sensors = { temperature = 1 }
description = "LM75 (H)"
refdes = "U104"

[[config.i2c.devices]]
bus = "apml"
address = 0x3c
device = "sbrmi"
name = "RMI"
mux = 1
segment = 1
description = "CPU via SB-RMI"

[[config.i2c.devices]]
bus = "apml"
address = 0x4c
device = "sbtsi"
name = "CPU"
mux = 1
segment = 1
description = "CPU temperature sensor"
sensors = { temperature = 1 }


################################################################################

[config.spi.spi2]
Expand Down
114 changes: 114 additions & 0 deletions drv/stm32xx-i2c/src/imx3112.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//! Driver for the IMX3112 I2C mux
use crate::*;
use drv_i2c_api::{ResponseCode, Segment};

use bitfield::bitfield;

#[allow(dead_code)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Register {
DeviceTypeLo = 0x0,
DeviceTypeHi = 0x1,
DeviceRevision = 0x2,
VendorIdLo = 0x3,
VendorIdHi = 0x4,
LocalInterfaceCfg = 0xe,
PullupResistorConfig = 0xf,
DeviceCfg = 0x12,
ClearTempSensorAlarm = 0x13,
ClearEccError = 0x14,
TempSensorCfg = 0x1a,
InterruptCfg = 0x1b,
TempHiLimitCfgLo = 0x1c,
TempHiLimitCfgHi = 0x1d,
TempLoLimitCfgLo = 0x1e,
TempLoLimitCfgHi = 0x1f,
TempCritHiLimitCfgLo = 0x20,
TempCritHiLimitCfgHi = 0x21,
TempCritLoLimitCfgLo = 0x22,
TempCritLoLimitCfgHi = 0x23,
DeviceStatus = 0x30,
CurrentTemperatureLo = 0x31,
CurrentTemperatureHi = 0x32,
TemperatureStatus = 0x33,
ErrorStatus = 0x34,
MuxConfig = 0x40,
MuxSelect = 0x41,
}

bitfield! {
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct MuxSelectRegister(u8);
channel1_enabled, set_channel1_enabled: 6;
channel0_enabled, set_channel0_enabled: 7;
}

pub struct Imx3112;

fn write_reg_u8(
mux: &I2cMux<'_>,
controller: &I2cController<'_>,
reg: Register,
val: u8,
ctrl: &I2cControl,
) -> Result<(), ResponseCode> {
controller
.write_read(
mux.address,
2,
|pos| Some(if pos == 0 { reg as u8 } else { val }),
ReadLength::Fixed(0),
|_, _| Some(()),
ctrl,
)
.map_err(|e| mux.error_code(e))
}

impl I2cMuxDriver for Imx3112 {
fn configure(
&self,
mux: &I2cMux<'_>,
_controller: &I2cController<'_>,
gpio: &sys_api::Sys,
_ctrl: &I2cControl,
) -> Result<(), drv_i2c_api::ResponseCode> {
// TODO configure registers?
mux.configure(gpio)
}

fn enable_segment(
&self,
mux: &I2cMux<'_>,
controller: &I2cController<'_>,
segment: Option<Segment>,
ctrl: &I2cControl,
) -> Result<(), ResponseCode> {
let mut reg = MuxSelectRegister(0);
match segment {
Some(Segment::S1) => reg.set_channel0_enabled(true),
Some(Segment::S2) => reg.set_channel1_enabled(true),
None => (),
_ => return Err(ResponseCode::SegmentNotFound),
}
// Disable both outputs
write_reg_u8(mux, controller, Register::MuxConfig, 0, ctrl)?;
// Select our desired output
write_reg_u8(mux, controller, Register::MuxSelect, reg.0, ctrl)?;
// Enable our desired output
write_reg_u8(mux, controller, Register::MuxConfig, reg.0, ctrl)?;
Ok(())
}

fn reset(
&self,
mux: &I2cMux<'_>,
gpio: &sys_api::Sys,
) -> Result<(), drv_i2c_api::ResponseCode> {
mux.reset(gpio)
}
}
1 change: 1 addition & 0 deletions drv/stm32xx-i2c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub type RegisterBlock = device::i2c1::RegisterBlock;
))]
pub type Isr = device::i2c1::isr::R;

pub mod imx3112;
pub mod ltc4306;
pub mod max7358;
pub mod pca9545;
Expand Down
9 changes: 7 additions & 2 deletions task/thermal/src/bsp/grapefruit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use i2c_config::sensors;
// Constants!

// Air temperature sensors, which aren't used in the control loop
const NUM_TEMPERATURE_SENSORS: usize = 0;
const NUM_TEMPERATURE_SENSORS: usize = 1;

// Temperature inputs (I2C devices), which are used in the control loop.
pub const NUM_TEMPERATURE_INPUTS: usize = 1;
Expand Down Expand Up @@ -135,4 +135,9 @@ const INPUTS: [InputChannel; NUM_TEMPERATURE_INPUTS] = [InputChannel::new(
ChannelType::MustBePresent,
)];

const MISC_SENSORS: [TemperatureSensor; NUM_TEMPERATURE_SENSORS] = [];
const MISC_SENSORS: [TemperatureSensor; NUM_TEMPERATURE_SENSORS] =
[TemperatureSensor::new(
Device::CPU,
devices::sbtsi_cpu,
sensors::SBTSI_CPU_TEMPERATURE_SENSOR,
)];

0 comments on commit 0241411

Please sign in to comment.