blob: ad38bccdf61c4f5e9cc96bb8d89e31f28a6ea580 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//! Useful modules for OpenTitanTool application development.
pub mod command;
pub mod conf;
use crate::io::gpio::GpioPin;
use crate::io::spi::Target;
use crate::io::uart::Uart;
use anyhow::Result;
use erased_serde::Serialize;
use std::any::Any;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
// This is the structure to be passed to each Command implementation,
// replacing the "bare" Transport argument. The fields other than
// transport will have been computed from a number ConfigurationFiles.
pub struct TransportWrapper {
transport: RefCell<Box<dyn crate::transport::Transport>>,
pub pin_map: HashMap<String, String>,
pub uart_map: HashMap<String, String>,
pub spi_map: HashMap<String, String>,
pub flash_map: HashMap<String, conf::FlashConfiguration>,
}
impl TransportWrapper {
pub fn new(transport: Box<dyn crate::transport::Transport>) -> Self {
Self {
transport: RefCell::new(transport),
pin_map: HashMap::new(),
uart_map: HashMap::new(),
spi_map: HashMap::new(),
flash_map: HashMap::new(),
}
}
/// Returns a `Capabilities` object to check the capabilities of this
/// transport object.
pub fn capabilities(&self) -> crate::transport::Capabilities {
self.transport.borrow().capabilities()
}
/// Returns a SPI [`Target`] implementation.
pub fn spi(&self, name: &str) -> Result<Rc<dyn Target>> {
self.transport
.borrow()
.spi(Self::map_name(&self.spi_map, name).as_str())
}
/// Returns a [`Uart`] implementation.
pub fn uart(&self, name: &str) -> Result<Rc<dyn Uart>> {
self.transport
.borrow()
.uart(Self::map_name(&self.uart_map, name).as_str())
}
/// Returns a [`GpioPin`] implementation.
pub fn gpio_pin(&self, name: &str) -> Result<Rc<dyn GpioPin>> {
self.transport
.borrow()
.gpio_pin(Self::map_name(&self.pin_map, name).as_str())
}
/// Invoke non-standard functionality of some Transport implementations.
pub fn dispatch(&self, action: &dyn Any) -> Result<Option<Box<dyn Serialize>>> {
self.transport.borrow().dispatch(action)
}
/// Given an pin/uart/spi port name, if the name is a known alias,
/// return the underlying name/number, otherwise return the string
/// as is.
fn map_name(map: &HashMap<String, String>, name: &str) -> String {
let name = name.to_uppercase();
// TODO(#8769): Support multi-level aliasing, either by
// flattening after parsing all files, or by repeated lookup
// here.
map.get(&name).cloned().unwrap_or(name)
}
pub fn add_configuration_file(&mut self, file: conf::ConfigurationFile) -> Result<()> {
// Merge content of configuration file into pin_map and other
// members.
for pin_conf in file.pins {
if let Some(alias_of) = pin_conf.alias_of {
self.pin_map.insert(pin_conf.name.to_uppercase(), alias_of);
}
// TODO(#8769): Apply input / open drain / push pull
// configuration to the pin.
}
for uart_conf in file.uarts {
if let Some(alias_of) = uart_conf.alias_of {
self.uart_map
.insert(uart_conf.name.to_uppercase(), alias_of);
}
// TODO(#8769): Record baud / parity configration for later
// use when opening uart.
}
for flash_conf in file.flash {
self.flash_map
.insert(flash_conf.name.clone(), flash_conf.clone());
}
Ok(())
}
}