power_controller: read gpio pins from device tree
[bmcd] / src / hal / power_controller.rs
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)
     }
 }