Skip to content

Commit

Permalink
[opentitanlib] Add gpio implementation for ftdi transport
Browse files Browse the repository at this point in the history
Signed-off-by: Douglas Reis <[email protected]>
  • Loading branch information
engdoreis committed Dec 13, 2024
1 parent 06cd198 commit bf22735
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 1 deletion.
1 change: 1 addition & 0 deletions sw/host/opentitanlib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ rust_library(
"src/transport/dediprog/spi.rs",
"src/transport/errors.rs",
"src/transport/ftdi/chip.rs",
"src/transport/ftdi/gpio.rs",
"src/transport/ftdi/mod.rs",
"src/transport/hyperdebug/c2d2.rs",
"src/transport/hyperdebug/dfu.rs",
Expand Down
83 changes: 83 additions & 0 deletions sw/host/opentitanlib/src/transport/ftdi/gpio.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

use embedded_hal::digital::OutputPin;
use ftdi_embedded_hal as ftdi_hal;

use crate::io::gpio::{GpioError, GpioPin, PinMode, PullMode};
use crate::transport::ftdi::Chip;

pub struct Pin {
pin: Rc<RefCell<ftdi_hal::OutputPin<ftdi::Device>>>,
pinname: String,
}

impl Pin {
pub fn open<C: Chip>(
ftdi_interfaces: &HashMap<ftdi::Interface, ftdi_hal::FtHal<ftdi::Device>>,
pinname: String,
) -> Result<Self> {
let pinname = pinname.to_lowercase();
let (interface, pin) = pinname.split_at(1);
let interface = match interface {
"a" => ftdi::Interface::A,
"b" => ftdi::Interface::B,
"c" => ftdi::Interface::C,
"d" => ftdi::Interface::D,
&_ => panic!("{}", pinname.clone()),
};

let hal = ftdi_interfaces
.get(&interface)
.ok_or_else(|| GpioError::InvalidPinName(pinname.clone()))?;
let pin = match pin {
"dbus0" => hal.ad0(),
"dbus1" => hal.ad1(),
"dbus2" => hal.ad2(),
"dbus3" => hal.ad3(),
"dbus4" => hal.ad4(),
"dbus5" => hal.ad5(),
"dbus6" => hal.ad6(),
"dbus7" => hal.ad7(),
_ => return Err(GpioError::InvalidPinName(pinname).into()),
}?;

Ok(Self {
pin: Rc::new(RefCell::new(pin)),
pinname,
})
}
}

impl GpioPin for Pin {
fn read(&self) -> Result<bool> {
Ok(false)
}

fn write(&self, value: bool) -> Result<()> {
if value {
self.pin.borrow_mut().set_high()?;
} else {
self.pin.borrow_mut().set_low()?;
}
Ok(())
}

fn set_mode(&self, _mode: PinMode) -> Result<()> {
Ok(())
}

fn set_pull_mode(&self, _mode: PullMode) -> Result<()> {
Ok(())
}

fn get_internal_pin_name(&self) -> Option<&str> {
Some(&self.pinname)
}
}
13 changes: 12 additions & 1 deletion sw/host/opentitanlib/src/transport/ftdi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use chip::Chip;
use ftdi_embedded_hal as ftdi_hal;

pub mod chip;
pub mod gpio;

#[derive(Default)]
struct Inner {
Expand Down Expand Up @@ -101,7 +102,17 @@ impl<C: Chip> Transport for Ftdi<C> {
}

fn gpio_pin(&self, pinname: &str) -> Result<Rc<dyn GpioPin>> {
Err(TransportError::UnsupportedOperation.into())
let mut inner = self.inner.borrow_mut();
Ok(match inner.gpio.entry(pinname.to_string()) {
Entry::Vacant(v) => {
let u = v.insert(Rc::new(gpio::Pin::open::<C>(
&self.ftdi_interfaces,
pinname.to_string(),
)?));
Rc::clone(u)
}
Entry::Occupied(o) => Rc::clone(o.get()),
})
}

fn spi(&self, _instance: &str) -> Result<Rc<dyn Target>> {
Expand Down

0 comments on commit bf22735

Please sign in to comment.