Skip to content

Commit 0241411

Browse files
committed
Add IMX3112 mux and APML devices to Grapefruit
1 parent 794bded commit 0241411

File tree

4 files changed

+147
-2
lines changed

4 files changed

+147
-2
lines changed

app/grapefruit/app.toml

+25
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,11 @@ sda.pin = 11
403403
scl.pin = 10
404404
af = 4
405405

406+
[[config.i2c.controllers.ports.B.muxes]]
407+
driver = "imx3112"
408+
address = 0x70
409+
# U6 on AMD Ruby schematic
410+
406411
[config.i2c.controllers.ports.F]
407412
name = "pcie"
408413
sda.pin = 0
@@ -528,6 +533,26 @@ sensors = { temperature = 1 }
528533
description = "LM75 (H)"
529534
refdes = "U104"
530535

536+
[[config.i2c.devices]]
537+
bus = "apml"
538+
address = 0x3c
539+
device = "sbrmi"
540+
name = "RMI"
541+
mux = 1
542+
segment = 1
543+
description = "CPU via SB-RMI"
544+
545+
[[config.i2c.devices]]
546+
bus = "apml"
547+
address = 0x4c
548+
device = "sbtsi"
549+
name = "CPU"
550+
mux = 1
551+
segment = 1
552+
description = "CPU temperature sensor"
553+
sensors = { temperature = 1 }
554+
555+
531556
################################################################################
532557

533558
[config.spi.spi2]

drv/stm32xx-i2c/src/imx3112.rs

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
//! Driver for the IMX3112 I2C mux
6+
7+
use crate::*;
8+
use drv_i2c_api::{ResponseCode, Segment};
9+
10+
use bitfield::bitfield;
11+
12+
#[allow(dead_code)]
13+
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
14+
pub enum Register {
15+
DeviceTypeLo = 0x0,
16+
DeviceTypeHi = 0x1,
17+
DeviceRevision = 0x2,
18+
VendorIdLo = 0x3,
19+
VendorIdHi = 0x4,
20+
LocalInterfaceCfg = 0xe,
21+
PullupResistorConfig = 0xf,
22+
DeviceCfg = 0x12,
23+
ClearTempSensorAlarm = 0x13,
24+
ClearEccError = 0x14,
25+
TempSensorCfg = 0x1a,
26+
InterruptCfg = 0x1b,
27+
TempHiLimitCfgLo = 0x1c,
28+
TempHiLimitCfgHi = 0x1d,
29+
TempLoLimitCfgLo = 0x1e,
30+
TempLoLimitCfgHi = 0x1f,
31+
TempCritHiLimitCfgLo = 0x20,
32+
TempCritHiLimitCfgHi = 0x21,
33+
TempCritLoLimitCfgLo = 0x22,
34+
TempCritLoLimitCfgHi = 0x23,
35+
DeviceStatus = 0x30,
36+
CurrentTemperatureLo = 0x31,
37+
CurrentTemperatureHi = 0x32,
38+
TemperatureStatus = 0x33,
39+
ErrorStatus = 0x34,
40+
MuxConfig = 0x40,
41+
MuxSelect = 0x41,
42+
}
43+
44+
bitfield! {
45+
#[derive(Copy, Clone, Eq, PartialEq)]
46+
pub struct MuxSelectRegister(u8);
47+
channel1_enabled, set_channel1_enabled: 6;
48+
channel0_enabled, set_channel0_enabled: 7;
49+
}
50+
51+
pub struct Imx3112;
52+
53+
fn write_reg_u8(
54+
mux: &I2cMux<'_>,
55+
controller: &I2cController<'_>,
56+
reg: Register,
57+
val: u8,
58+
ctrl: &I2cControl,
59+
) -> Result<(), ResponseCode> {
60+
controller
61+
.write_read(
62+
mux.address,
63+
2,
64+
|pos| Some(if pos == 0 { reg as u8 } else { val }),
65+
ReadLength::Fixed(0),
66+
|_, _| Some(()),
67+
ctrl,
68+
)
69+
.map_err(|e| mux.error_code(e))
70+
}
71+
72+
impl I2cMuxDriver for Imx3112 {
73+
fn configure(
74+
&self,
75+
mux: &I2cMux<'_>,
76+
_controller: &I2cController<'_>,
77+
gpio: &sys_api::Sys,
78+
_ctrl: &I2cControl,
79+
) -> Result<(), drv_i2c_api::ResponseCode> {
80+
// TODO configure registers?
81+
mux.configure(gpio)
82+
}
83+
84+
fn enable_segment(
85+
&self,
86+
mux: &I2cMux<'_>,
87+
controller: &I2cController<'_>,
88+
segment: Option<Segment>,
89+
ctrl: &I2cControl,
90+
) -> Result<(), ResponseCode> {
91+
let mut reg = MuxSelectRegister(0);
92+
match segment {
93+
Some(Segment::S1) => reg.set_channel0_enabled(true),
94+
Some(Segment::S2) => reg.set_channel1_enabled(true),
95+
None => (),
96+
_ => return Err(ResponseCode::SegmentNotFound),
97+
}
98+
// Disable both outputs
99+
write_reg_u8(mux, controller, Register::MuxConfig, 0, ctrl)?;
100+
// Select our desired output
101+
write_reg_u8(mux, controller, Register::MuxSelect, reg.0, ctrl)?;
102+
// Enable our desired output
103+
write_reg_u8(mux, controller, Register::MuxConfig, reg.0, ctrl)?;
104+
Ok(())
105+
}
106+
107+
fn reset(
108+
&self,
109+
mux: &I2cMux<'_>,
110+
gpio: &sys_api::Sys,
111+
) -> Result<(), drv_i2c_api::ResponseCode> {
112+
mux.reset(gpio)
113+
}
114+
}

drv/stm32xx-i2c/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub type RegisterBlock = device::i2c1::RegisterBlock;
3535
))]
3636
pub type Isr = device::i2c1::isr::R;
3737

38+
pub mod imx3112;
3839
pub mod ltc4306;
3940
pub mod max7358;
4041
pub mod pca9545;

task/thermal/src/bsp/grapefruit.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use i2c_config::sensors;
2222
// Constants!
2323

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

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

138-
const MISC_SENSORS: [TemperatureSensor; NUM_TEMPERATURE_SENSORS] = [];
138+
const MISC_SENSORS: [TemperatureSensor; NUM_TEMPERATURE_SENSORS] =
139+
[TemperatureSensor::new(
140+
Device::CPU,
141+
devices::sbtsi_cpu,
142+
sensors::SBTSI_CPU_TEMPERATURE_SENSOR,
143+
)];

0 commit comments

Comments
 (0)