From 27015a711c1e7fbe7f7a1915b8f69dd765d42560 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Mon, 8 Apr 2024 10:21:32 -0700 Subject: [PATCH] WIP: start wiring alert pins to thermal task --- Cargo.lock | 1 + app/gimlet/base.toml | 15 +++++- task/thermal/Cargo.toml | 3 +- task/thermal/src/bsp/gimlet_bcdef.rs | 73 +++++++++++++++++++++++++++- task/thermal/src/bsp/sidecar_bcd.rs | 9 ++++ task/thermal/src/main.rs | 27 ++++++++-- 6 files changed, 119 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a580ead37..8fc4ba79d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4866,6 +4866,7 @@ dependencies = [ "drv-onewire", "drv-onewire-devices", "drv-sidecar-seq-api", + "drv-stm32xx-sys-api", "drv-transceivers-api", "hubpack", "idol", diff --git a/app/gimlet/base.toml b/app/gimlet/base.toml index e9503eb01..87a46a199 100644 --- a/app/gimlet/base.toml +++ b/app/gimlet/base.toml @@ -71,6 +71,17 @@ port = "E" pin = 3 owner = {name = "sprot", notification = "rot_irq"} +[tasks.sys.config.gpio-irqs.sp3_to_sp_alert_l] +port = "D" +pin = 6 +owner = {name = "thermal", notification = "sp3_to_sp_alert_l"} + +[tasks.sys.config.gpio-irqs.smbus_nic_temp_to_sp_alert_l] +port = "D" +pin = 15 +owner = {name = "thermal", notification = "smbus_nic_temp_to_sp_alert_l"} + + [tasks.spi2_driver] name = "drv-stm32h7-spi-server" priority = 3 @@ -131,8 +142,8 @@ priority = 5 max-sizes = {flash = 32768, ram = 8192 } stacksize = 6000 start = true -task-slots = ["i2c_driver", "sensor", "gimlet_seq", "jefe"] -notifications = ["timer"] +task-slots = ["i2c_driver", "sensor", "gimlet_seq", "jefe", "sys"] +notifications = ["timer", "sp3_to_sp_alert_l", "smbus_nic_temp_to_sp_alert_l"] [tasks.power] name = "task-power" diff --git a/task/thermal/Cargo.toml b/task/thermal/Cargo.toml index eadbe6849..c3ce95570 100644 --- a/task/thermal/Cargo.toml +++ b/task/thermal/Cargo.toml @@ -14,6 +14,7 @@ zerocopy.workspace = true drv-gimlet-seq-api = { path = "../../drv/gimlet-seq-api", optional = true } drv-sidecar-seq-api = { path = "../../drv/sidecar-seq-api", optional = true } +drv-stm32xx-sys-api = { path = "../../drv/stm32xx-sys-api", optional = true } drv-transceivers-api = { path = "../../drv/transceivers-api", optional = true } userlib = { path = "../../sys/userlib", features = ["panic-messages"] } @@ -35,7 +36,7 @@ build-i2c = { path = "../../build/i2c" } build-util = { path = "../../build/util" } [features] -gimlet = ["drv-gimlet-seq-api", "h753"] +gimlet = ["drv-gimlet-seq-api", "drv-stm32xx-sys-api/h753", "h753"] sidecar = ["drv-sidecar-seq-api", "drv-transceivers-api", "h753"] h743 = ["build-i2c/h743"] h753 = ["build-i2c/h753"] diff --git a/task/thermal/src/bsp/gimlet_bcdef.rs b/task/thermal/src/bsp/gimlet_bcdef.rs index 3f3d11ca1..f27e2850f 100644 --- a/task/thermal/src/bsp/gimlet_bcdef.rs +++ b/task/thermal/src/bsp/gimlet_bcdef.rs @@ -10,15 +10,18 @@ use crate::{ TemperatureSensor, }, i2c_config::{devices, sensors}, + notifications, }; pub use drv_gimlet_seq_api::SeqError; use drv_gimlet_seq_api::{PowerState, Sequencer}; use drv_i2c_devices::max31790::Max31790; +use drv_stm32xx_sys_api::{self as sys_api, Sys}; use task_sensor_api::SensorId; use task_thermal_api::ThermalProperties; -use userlib::{task_slot, units::Celsius, TaskId}; +use userlib::{task_slot, units::Celsius, TaskId, UnwrapLite}; task_slot!(SEQ, gimlet_seq); +task_slot!(SYS, sys); // We monitor the TMP117 air temperature sensors, but don't use them as part of // the control loop. @@ -53,6 +56,10 @@ pub const NUM_FANS: usize = drv_i2c_devices::max31790::MAX_FANS as usize; /// This controller is tuned and ready to go pub const USE_CONTROLLER: bool = true; +pub(crate) const ALERT_MASK: u32 = + notifications::SMBUS_NIC_TEMP_TO_SP_ALERT_L_MASK + | notifications::SP3_TO_SP_ALERT_L_MASK; + pub(crate) struct Bsp { /// Controlled sensors pub inputs: &'static [InputChannel], @@ -67,6 +74,9 @@ pub(crate) struct Bsp { /// Handle to the sequencer task, to query power state seq: Sequencer, + /// Handle to the sys task for GPIO alert interrupt control. + sys: Sys, + /// Id of the I2C task, to query MAX5970 status i2c_task: TaskId, @@ -74,6 +84,14 @@ pub(crate) struct Bsp { pub pid_config: PidConfig, } +#[derive(Copy, Clone, PartialEq, Eq, counters::Count)] +pub(crate) enum Alert { + /// Alert from the CPU on `SP3_TO_SP_ALERT_L` + SmbusSbTsiAlert, + /// Alert from the T6 on `SMBUS_NIC_TEMP_TO_SP_ALERT_L` + SmbusNicTemp, +} + bitflags::bitflags! { #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct PowerBitmask: u32 { @@ -93,6 +111,36 @@ bitflags::bitflags! { } impl Bsp { + pub fn is_alerted(&self, notif: u32) -> Option { + if notif & notifications::SP3_TO_SP_ALERT_L_MASK != 0 + && self + .sys + .gpio_irq_control( + notifications::SP3_TO_SP_ALERT_L_MASK, + sys_api::IrqControl::Enable, + ) + .unwrap_lite() + { + return Some(Alert::SmbusSbTsiAlert); + } + + if notif & notifications::SMBUS_NIC_TEMP_TO_SP_ALERT_L_MASK != 0 { + if self.seq.get_state() == PowerState::A0PlusHP + && self + .sys + .gpio_irq_control( + notifications::SMBUS_NIC_TEMP_TO_SP_ALERT_L_MASK, + sys_api::IrqControl::Enable, + ) + .unwrap_lite() + { + return Some(Alert::SmbusNicTemp); + } + } + + None + } + pub fn fan_control(&self, fan: crate::Fan) -> FanControl<'_> { FanControl::Max31790(&self.fctrl, fan.0.try_into().unwrap()) } @@ -163,9 +211,32 @@ impl Bsp { // Handle for the sequencer task, which we check for power state let seq = Sequencer::from(SEQ.get_task_id()); + let sys = Sys::from(SYS.get_task_id()); + + // Configure GPIO IRQs for thermal alert pins. + // Leave this alone for now; we only want to get an IRQ from it once the + // NIC is up. + // sys.gpio_configure_input( + // sys_api::gpio_irqs::SMBUS_NIC_TEMP_TO_SP_ALERT_L, + // sys_api::Pull::None, + // ); + // sys.gpio_irq_configure( + // notifications::SMBUS_NIC_TEMP_TO_SP_ALERT_L, + // sys_api::Edge::Falling, + // ); + sys.gpio_configure_input( + sys_api::gpio_irq_pins::SP3_TO_SP_ALERT_L, + // XXX(eliza): IS THIS RIGHT??? + sys_api::Pull::None, + ); + sys.gpio_irq_configure( + notifications::SP3_TO_SP_ALERT_L_MASK, + sys_api::Edge::Falling, + ); Self { seq, + sys, i2c_task, fctrl, diff --git a/task/thermal/src/bsp/sidecar_bcd.rs b/task/thermal/src/bsp/sidecar_bcd.rs index 38809c0d7..220697f08 100644 --- a/task/thermal/src/bsp/sidecar_bcd.rs +++ b/task/thermal/src/bsp/sidecar_bcd.rs @@ -43,6 +43,8 @@ pub const NUM_FANS: usize = sensors::NUM_MAX31790_SPEED_SENSORS; // Run the PID loop on startup pub const USE_CONTROLLER: bool = true; +pub(crate) const ALERT_MASK: u32 = 0; + //////////////////////////////////////////////////////////////////////////////// bitflags::bitflags! { @@ -73,7 +75,14 @@ pub(crate) struct Bsp { pub pid_config: PidConfig, } +#[derive(Copy, Clone, PartialEq, Eq, counters::Count)] +pub(crate) enum Alert {} + impl Bsp { + pub fn is_alerted(&mut self, notif: u32) -> Option { + None + } + pub fn fan_control( &self, fan: crate::Fan, diff --git a/task/thermal/src/main.rs b/task/thermal/src/main.rs index ed6fe2e10..d86feeae8 100644 --- a/task/thermal/src/main.rs +++ b/task/thermal/src/main.rs @@ -63,7 +63,7 @@ impl From for Fan { task_slot!(I2C, i2c_driver); task_slot!(SENSOR, sensor); -#[derive(Copy, Clone, Debug, Eq, PartialEq, counters::Count)] +#[derive(Copy, Clone, Eq, PartialEq, counters::Count)] enum Trace { #[count(skip)] None, @@ -83,12 +83,18 @@ enum Trace { PowerDownAt(u64), AddedDynamicInput(usize), RemovedDynamicInput(usize), + Alert { + now: u64, + #[count(children)] + alert: bsp::Alert, + }, } counted_ringbuf!(Trace, 32, Trace::None); //////////////////////////////////////////////////////////////////////////////// struct ServerImpl<'a> { + bsp: &'a Bsp, mode: ThermalMode, control: ThermalControl<'a>, deadline: u64, @@ -291,13 +297,24 @@ impl<'a> idl::InOrderThermalImpl for ServerImpl<'a> { impl<'a> NotificationHandler for ServerImpl<'a> { fn current_notification_mask(&self) -> u32 { - notifications::TIMER_MASK + notifications::TIMER_MASK | bsp::ALERT_MASK } - fn handle_notification(&mut self, _bits: u32) { + fn handle_notification(&mut self, bits: u32) { let now = sys_get_timer().now; - if now >= self.deadline { + let should_do_work = if let Some(alert) = self.bsp.is_alerted(bits) { + ringbuf_entry!(Trace::Alert { now, alert }); + true + } else if now >= self.deadline { + self.deadline = now + TIMER_INTERVAL; + true + } else { + false + }; + + if should_do_work { // See if any fans were removed or added since last iteration + // TODO(eliza): should we still do this if woken by an alert? self.control.update_fan_presence(); // We *always* read sensor data, which does not touch the control @@ -327,7 +344,6 @@ impl<'a> NotificationHandler for ServerImpl<'a> { panic!("Mode must not be 'Off' when server is running") } } - self.deadline = now + TIMER_INTERVAL; } self.runtime = sys_get_timer().now - now; sys_set_timer(Some(self.deadline), notifications::TIMER_MASK); @@ -351,6 +367,7 @@ fn main() -> ! { sys_set_timer(Some(deadline), notifications::TIMER_MASK); let mut server = ServerImpl { + bsp: &bsp, mode: ThermalMode::Off, control, deadline,