Port io_expander code from Kasli #214

Merged
sb10q merged 4 commits from esavkin/artiq-zynq:213-sfp-fiber-support into master 2023-02-16 10:29:06 +08:00
3 changed files with 46 additions and 18 deletions
Showing only changes of commit b4b7912c40 - Show all commits

View File

@ -32,6 +32,7 @@ use crate::moninj;
use crate::mgmt;
use crate::analyzer;
use crate::rtio_mgt::{self, resolve_channel_name};
use crate::io_expander;
#[cfg(has_drtio)]
use crate::pl;
@ -380,7 +381,7 @@ async fn handle_connection(stream: &mut TcpStream, control: Rc<RefCell<kernel::C
}
}
pub fn main(timer: GlobalTimer, cfg: Config) {
pub fn main(timer: GlobalTimer, cfg: Config, mut io_expander0: io_expander::IoExpander, mut io_expander1: io_expander::IoExpander) {
let net_addresses = net_settings::get_addresses(&cfg);
info!("network addresses: {}", net_addresses);
@ -494,6 +495,11 @@ pub fn main(timer: GlobalTimer, cfg: Config) {
let _ = stream.flush().await;
let _ = stream.abort().await;
});
#[cfg(feature = "target_kasli_soc")]
{
io_expander0.service().expect("I2C I/O expander #0 service failed");
io_expander1.service().expect("I2C I/O expander #1 service failed");
}
}
});

View File

@ -1,7 +1,8 @@
use crate::pl::csr;
use crate::i2c;
use log::info;
// Only the bare minimum registers. Bits/IO connections equivalent between IC types.
#[cfg(feature = "target_kasli_soc")]
struct Registers {
// PCA9539 equivalent register names in comments
iodira: u8, // Configuration Port 0
@ -10,6 +11,7 @@ struct Registers {
gpiob: u8, // Output Port 1
}
#[cfg(feature = "target_kasli_soc")]
pub struct IoExpander {
busno: i32,
port: u8,
@ -21,8 +23,18 @@ pub struct IoExpander {
registers: Registers,
}
#[cfg(not(feature = "target_kasli_soc"))]
pub struct IoExpander;
#[cfg(not(feature = "target_kasli_soc"))]
impl IoExpander {
pub fn new(index: u8) -> Result<Self, &'static str> {
Ok(IoExpander {})
}
}
#[cfg(feature = "target_kasli_soc")]
impl IoExpander {
pub fn new(index: u8) -> Result<Self, &'static str> {
const VIRTUAL_LED_MAPPING0: [(u8, u8, u8); 2] = [(0, 0, 6), (1, 1, 6)];
const VIRTUAL_LED_MAPPING1: [(u8, u8, u8); 2] = [(2, 0, 6), (3, 1, 6)];
@ -62,8 +74,7 @@ impl IoExpander {
_ => return Err("incorrect I/O expander index"),
};
if !io_expander.check_ack()? {
#[cfg(feature = "log")]
log::info!(
info!(
"MCP23017 io expander {} not found. Checking for PCA9539.",
index
);
@ -81,19 +92,13 @@ impl IoExpander {
Ok(io_expander)
}
#[cfg(feature = "target_kasli_soc")]
fn select(&self) -> Result<(), &'static str> {
let mask: i32 = 1 << self.port;
i2c::switch_select(self.busno, 0x70, mask);
i2c::switch_select(self.busno, 0x71, (mask >> 8));
let mask: u16 = 1 << self.port;
i2c::switch_select(self.busno, 0x70, mask as u8 as i32);
i2c::switch_select(self.busno, 0x71, (mask >> 8) as u8 as i32);
Ok(())
}
#[cfg(not(feature = "target_kasli_soc"))]
fn select(&self) -> Result<(), &'static str> {
Err("the target is not supported yet")
}
fn write(&self, addr: u8, value: u8) -> Result<(), &'static str> {
i2c::start(self.busno);
i2c::write(self.busno, self.address as i32);
@ -148,8 +153,7 @@ impl IoExpander {
}
pub fn service(&mut self) -> Result<(), &'static str> {
for (led, port, bit) in self.virtual_led_mapping.iter() {
//let level = unsafe { (csr::virtual_leds::status_read() >> led) & 1 };
for (_led, port, bit) in self.virtual_led_mapping.iter() {
self.set(*port, *bit, true);
}

View File

@ -46,7 +46,6 @@ mod mgmt;
mod analyzer;
mod irq;
mod i2c;
#[cfg(feature = "target_kasli_soc")]
mod io_expander;
static mut SEEN_ASYNC_ERRORS: u8 = 0;
@ -116,6 +115,25 @@ pub fn main_core0() {
i2c::init();
let (mut io_expander0, mut io_expander1) = (io_expander::IoExpander::new(0).unwrap(), io_expander::IoExpander::new(1).unwrap());
#[cfg(feature = "target_kasli_soc")]
{
io_expander0.init().expect("I2C I/O expander #0 initialization failed");
io_expander1.init().expect("I2C I/O expander #1 initialization failed");
// Actively drive TX_DISABLE to false on SFP0..3
io_expander0.set_oe(0, 1 << 1).unwrap();
Review

Needs to be done in satman as well.

Needs to be done in satman as well.
Review

Maybe do it in another PR? It looks like i2c logic in satman needs to be refactored to make io_expander shared

Maybe do it in another PR? It looks like i2c logic in satman needs to be refactored to make io_expander shared
Review

Looks like it's a super simple "refactoring" but ok if you want...

Looks like it's a super simple "refactoring" but ok if you want...
io_expander0.set_oe(1, 1 << 1).unwrap();
io_expander1.set_oe(0, 1 << 1).unwrap();
io_expander1.set_oe(1, 1 << 1).unwrap();
io_expander0.set(0, 1, false);
io_expander0.set(1, 1, false);
io_expander1.set(0, 1, false);
io_expander1.set(1, 1, false);
io_expander0.service().unwrap();
io_expander1.service().unwrap();
}
let cfg = match Config::new() {
Ok(cfg) => cfg,
Err(err) => {
@ -128,5 +146,5 @@ pub fn main_core0() {
task::spawn(report_async_rtio_errors());
comms::main(timer, cfg);
comms::main(timer, cfg, io_expander0, io_expander1);
}