Port io_expander code from Kasli #214
|
@ -32,6 +32,7 @@ use crate::moninj;
|
||||||
use crate::mgmt;
|
use crate::mgmt;
|
||||||
use crate::analyzer;
|
use crate::analyzer;
|
||||||
use crate::rtio_mgt::{self, resolve_channel_name};
|
use crate::rtio_mgt::{self, resolve_channel_name};
|
||||||
|
use crate::io_expander;
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
use crate::pl;
|
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);
|
let net_addresses = net_settings::get_addresses(&cfg);
|
||||||
info!("network addresses: {}", net_addresses);
|
info!("network addresses: {}", net_addresses);
|
||||||
|
|
||||||
|
@ -494,6 +495,11 @@ pub fn main(timer: GlobalTimer, cfg: Config) {
|
||||||
let _ = stream.flush().await;
|
let _ = stream.flush().await;
|
||||||
let _ = stream.abort().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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::pl::csr;
|
|
||||||
use crate::i2c;
|
use crate::i2c;
|
||||||
|
use log::info;
|
||||||
|
|
||||||
// Only the bare minimum registers. Bits/IO connections equivalent between IC types.
|
// Only the bare minimum registers. Bits/IO connections equivalent between IC types.
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
struct Registers {
|
struct Registers {
|
||||||
// PCA9539 equivalent register names in comments
|
// PCA9539 equivalent register names in comments
|
||||||
iodira: u8, // Configuration Port 0
|
iodira: u8, // Configuration Port 0
|
||||||
|
@ -10,6 +11,7 @@ struct Registers {
|
||||||
gpiob: u8, // Output Port 1
|
gpiob: u8, // Output Port 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
pub struct IoExpander {
|
pub struct IoExpander {
|
||||||
busno: i32,
|
busno: i32,
|
||||||
port: u8,
|
port: u8,
|
||||||
|
@ -21,8 +23,18 @@ pub struct IoExpander {
|
||||||
registers: Registers,
|
registers: Registers,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "target_kasli_soc"))]
|
||||||
|
pub struct IoExpander;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "target_kasli_soc"))]
|
||||||
impl IoExpander {
|
impl IoExpander {
|
||||||
|
pub fn new(index: u8) -> Result<Self, &'static str> {
|
||||||
|
Ok(IoExpander {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
|
impl IoExpander {
|
||||||
pub fn new(index: u8) -> Result<Self, &'static str> {
|
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_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)];
|
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"),
|
_ => return Err("incorrect I/O expander index"),
|
||||||
};
|
};
|
||||||
if !io_expander.check_ack()? {
|
if !io_expander.check_ack()? {
|
||||||
#[cfg(feature = "log")]
|
info!(
|
||||||
log::info!(
|
|
||||||
"MCP23017 io expander {} not found. Checking for PCA9539.",
|
"MCP23017 io expander {} not found. Checking for PCA9539.",
|
||||||
index
|
index
|
||||||
);
|
);
|
||||||
|
@ -81,19 +92,13 @@ impl IoExpander {
|
||||||
Ok(io_expander)
|
Ok(io_expander)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
|
||||||
fn select(&self) -> Result<(), &'static str> {
|
fn select(&self) -> Result<(), &'static str> {
|
||||||
let mask: i32 = 1 << self.port;
|
let mask: u16 = 1 << self.port;
|
||||||
i2c::switch_select(self.busno, 0x70, mask);
|
i2c::switch_select(self.busno, 0x70, mask as u8 as i32);
|
||||||
i2c::switch_select(self.busno, 0x71, (mask >> 8));
|
i2c::switch_select(self.busno, 0x71, (mask >> 8) as u8 as i32);
|
||||||
Ok(())
|
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> {
|
fn write(&self, addr: u8, value: u8) -> Result<(), &'static str> {
|
||||||
i2c::start(self.busno);
|
i2c::start(self.busno);
|
||||||
i2c::write(self.busno, self.address as i32);
|
i2c::write(self.busno, self.address as i32);
|
||||||
|
@ -148,8 +153,7 @@ impl IoExpander {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn service(&mut self) -> Result<(), &'static str> {
|
pub fn service(&mut self) -> Result<(), &'static str> {
|
||||||
for (led, port, bit) in self.virtual_led_mapping.iter() {
|
for (_led, port, bit) in self.virtual_led_mapping.iter() {
|
||||||
//let level = unsafe { (csr::virtual_leds::status_read() >> led) & 1 };
|
|
||||||
self.set(*port, *bit, true);
|
self.set(*port, *bit, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,6 @@ mod mgmt;
|
||||||
mod analyzer;
|
mod analyzer;
|
||||||
mod irq;
|
mod irq;
|
||||||
mod i2c;
|
mod i2c;
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
|
||||||
mod io_expander;
|
mod io_expander;
|
||||||
|
|
||||||
static mut SEEN_ASYNC_ERRORS: u8 = 0;
|
static mut SEEN_ASYNC_ERRORS: u8 = 0;
|
||||||
|
@ -116,6 +115,25 @@ pub fn main_core0() {
|
||||||
|
|
||||||
i2c::init();
|
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();
|
||||||
|
|||||||
|
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() {
|
let cfg = match Config::new() {
|
||||||
Ok(cfg) => cfg,
|
Ok(cfg) => cfg,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -128,5 +146,5 @@ pub fn main_core0() {
|
||||||
|
|
||||||
task::spawn(report_async_rtio_errors());
|
task::spawn(report_async_rtio_errors());
|
||||||
|
|
||||||
comms::main(timer, cfg);
|
comms::main(timer, cfg, io_expander0, io_expander1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Needs to be done in satman as well.
Maybe do it in another PR? It looks like i2c logic in satman needs to be refactored to make io_expander shared
Looks like it's a super simple "refactoring" but ok if you want...