opentitanlib/transport/hyperdebug/
c2d2.rs1use anyhow::{Result, bail};
6use std::rc::Rc;
7
8use crate::io::gpio::{GpioPin, PinMode, PullMode};
9use crate::transport::hyperdebug::{Flavor, Inner, StandardFlavor, VID_GOOGLE};
10use crate::transport::{TransportError, TransportInterfaceType};
11
12pub struct C2d2Flavor {}
18
19impl C2d2Flavor {
20 const PID_C2D2: u16 = 0x5041;
21}
22
23impl Flavor for C2d2Flavor {
24 fn gpio_pin(inner: &Rc<Inner>, pinname: &str) -> Result<Rc<dyn GpioPin>> {
25 if pinname == "SPIVREF_RSVD_H1VREF_H1_RST_ODL" {
26 return Ok(Rc::new(C2d2ResetPin::open(inner)?));
27 }
28 StandardFlavor::gpio_pin(inner, pinname)
29 }
30
31 fn spi_index(_inner: &Rc<Inner>, instance: &str) -> Result<(u8, u8)> {
32 if instance == "0" {
33 return Ok((super::spi::USB_SPI_REQ_ENABLE, 0));
34 }
35 bail!(TransportError::InvalidInstance(
36 TransportInterfaceType::Spi,
37 instance.to_string()
38 ))
39 }
40
41 fn get_default_usb_vid() -> u16 {
42 VID_GOOGLE
43 }
44
45 fn get_default_usb_pid() -> u16 {
46 Self::PID_C2D2
47 }
48 fn perform_initial_fw_check() -> bool {
49 false
51 }
52}
53
54pub struct C2d2ResetPin {
55 inner: Rc<Inner>,
56}
57
58impl C2d2ResetPin {
59 pub fn open(inner: &Rc<Inner>) -> Result<Self> {
60 Ok(Self {
61 inner: Rc::clone(inner),
62 })
63 }
64}
65
66impl GpioPin for C2d2ResetPin {
67 fn read(&self) -> Result<bool> {
69 let line = self
70 .inner
71 .cmd_one_line_output("gpioget SPIVREF_RSVD_H1VREF_H1_RST_ODL")
72 .map_err(|_| {
73 TransportError::CommunicationError("No output from gpioget".to_string())
74 })?;
75 Ok(line.trim_start().starts_with('1'))
76 }
77
78 fn write(&self, value: bool) -> Result<()> {
80 self.inner
81 .cmd_one_line_output(&format!("h1_reset {}", if value { 0 } else { 1 }))?;
82 Ok(())
83 }
84
85 fn set_mode(&self, _mode: PinMode) -> Result<()> {
87 bail!(TransportError::UnsupportedOperation)
88 }
89
90 fn set_pull_mode(&self, _mode: PullMode) -> Result<()> {
92 bail!(TransportError::UnsupportedOperation)
93 }
94}