power_controller: read gpio pins from device tree
authorSven Rademakers <sven.rademakers@gmail.com>
Thu, 15 Feb 2024 19:50:23 +0000 (19:50 +0000)
committerSven Rademakers <sven.rademakers@gmail.com>
Thu, 15 Feb 2024 19:56:21 +0000 (19:56 +0000)
This commit is part of the effort to move configuration of hardware more
closely to the linux platform

src/app/bmc_application.rs
src/authentication/authentication_errors.rs
src/hal/gpio_definitions.rs
src/hal/helpers.rs
src/hal/power_controller.rs
src/serial_service.rs

index f84aa9e283b2afcb7c17e2212557db335c82c32c..0648a0d793ac91fbec9e20af9cbc6a3ac48a457b 100644 (file)
@@ -168,7 +168,9 @@ impl BmcApplication {
         debug!("node activated bits updated:{:#06b}.", new_state);
 
         let led = new_state != 0;
-        self.power_controller.power_led(led).await?;
+        if let Err(e) = self.power_controller.power_led(led).await {
+            log::warn!("power LED error: {}", e);
+        }
 
         // also update the actual power state accordingly
         self.power_controller
index 7becc8b222653ec4d30e47c503ced1d45487f85f..196d4a26895c0eee606d020183e27f329738f010 100644 (file)
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 use humantime::format_duration;
-use std::str::Utf8Error;
+use std::{fmt::Display, str::Utf8Error};
 use thiserror::Error;
 use tokio::time::Instant;
 
@@ -92,8 +92,8 @@ impl SchemedAuthError {
     }
 }
 
-impl ToString for SchemedAuthError {
-    fn to_string(&self) -> String {
-        self.1.to_string()
+impl Display for SchemedAuthError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", self.1)
     }
 }
index 18e76f48314f1128de56f1037c78dcff54e04234..84ef8c188be5e734eefa910071b1646508e4595e 100644 (file)
@@ -34,11 +34,6 @@ pub const NODE2_USBOTG_DEV: u32 = 6;
 pub const NODE3_USBOTG_DEV: u32 = 10;
 pub const NODE4_USBOTG_DEV: u32 = 14;
 
-pub const PORT1_EN: u32 = 0;
-pub const PORT2_EN: u32 = 4;
-pub const PORT3_EN: u32 = 8;
-pub const PORT4_EN: u32 = 12;
-
 pub const PORT1_RPIBOOT: u32 = 3;
 pub const PORT2_RPIBOOT: u32 = 7;
 pub const PORT3_RPIBOOT: u32 = 11;
index 33f7e3f16b4451124078e5911a7a86ac5f5b1f23..c0699b5b411c254715e75f8d73044fbc09edb450 100644 (file)
@@ -11,6 +11,7 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+use std::collections::HashMap;
 const NODE_COUNT: u8 = 4;
 
 /// small helper macro which handles the code duplication of declaring gpio lines.
@@ -56,3 +57,11 @@ pub fn bit_iterator(nodes_state: u8, nodes_mask: u8) -> impl Iterator<Item = (us
         (mask != 0).then_some((n as usize, state))
     })
 }
+
+pub fn load_lines(chip: &gpiod::Chip) -> HashMap<String, gpiod::LineId> {
+    HashMap::from_iter((0..chip.num_lines()).filter_map(|i| {
+        chip.line_info(i)
+            .ok()
+            .map(|info| (info.name, i as gpiod::LineId))
+    }))
+}
index a5a5ef575496f5932627ec2f000a0cfead15fb96..5475466f4d82296c08025e1d2505ce800b8be1c4 100644 (file)
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
-use super::{gpio_definitions::*, helpers::bit_iterator, NodeId};
+use super::{
+    helpers::{bit_iterator, load_lines},
+    NodeId,
+};
 use crate::gpio_output_array;
 use anyhow::Context;
 use gpiod::{Chip, Lines, Output};
@@ -19,6 +22,11 @@ use log::{debug, trace};
 use std::time::Duration;
 use tokio::time::sleep;
 
+const PORT1_EN: &str = "node1-en";
+const PORT2_EN: &str = "node2-en";
+const PORT3_EN: &str = "node3-en";
+const PORT4_EN: &str = "node4-en";
+
 // This structure is a thin layer that abstracts away the interaction details
 // with Linux's power subsystem.
 pub struct PowerController {
@@ -28,7 +36,21 @@ pub struct PowerController {
 impl PowerController {
     pub fn new() -> anyhow::Result<Self> {
         let chip1 = Chip::new("/dev/gpiochip1").context("gpiod chip1")?;
-        let enable = gpio_output_array!(chip1, PORT1_EN, PORT2_EN, PORT3_EN, PORT4_EN);
+        let lines = load_lines(&chip1);
+        let port1 = *lines
+            .get(PORT1_EN)
+            .ok_or(anyhow::anyhow!("cannot find PORT1_EN"))?;
+        let port2 = *lines
+            .get(PORT2_EN)
+            .ok_or(anyhow::anyhow!("cannot find PORT2_EN"))?;
+        let port3 = *lines
+            .get(PORT3_EN)
+            .ok_or(anyhow::anyhow!("cannot find PORT3_EN"))?;
+        let port4 = *lines
+            .get(PORT4_EN)
+            .ok_or(anyhow::anyhow!("cannot find PORT4_EN"))?;
+
+        let enable = gpio_output_array!(chip1, port1, port2, port3, port4);
 
         Ok(PowerController { enable })
     }
@@ -71,9 +93,11 @@ impl PowerController {
         Ok(())
     }
 
-    pub async fn power_led(&self, on: bool) -> std::io::Result<()> {
+    pub async fn power_led(&self, on: bool) -> anyhow::Result<()> {
         const SYS_LED: &str = "/sys/class/leds/fp:sys/brightness";
-        tokio::fs::write(SYS_LED, if on { "1" } else { "0" }).await
+        tokio::fs::write(SYS_LED, if on { "1" } else { "0" })
+            .await
+            .context(SYS_LED)
     }
 }
 
index e0c33c23271e118f7bc0708d5796761c2e7a7931..5463d14e252f789fbc315bb91d38ae28d7925f35 100644 (file)
@@ -36,7 +36,7 @@ pub fn serial_config(cfg: &mut web::ServiceConfig) {
 
 #[post("/serial/status")]
 async fn serial_status(serials: web::Data<SerialConnections>) -> impl Responder {
-    serde_json::to_string(&serials.get_state()).map_or_else(|e| e.to_string(), |s| s)
+    serde_json::to_string(&serials.get_state()).unwrap_or_else(|e| e.to_string())
 }
 
 pub async fn legacy_serial_set_handler(