expose pca954x_select api (#167)

PR accompanying to ARTIQ's PCA954X support (#1860).
Co-authored-by: mwojcik <mw@m-labs.hk>
Co-committed-by: mwojcik <mw@m-labs.hk>
This commit is contained in:
mwojcik 2022-03-02 10:52:27 +08:00 committed by sb10q
parent b56b50b147
commit 9a06cd9d27
4 changed files with 55 additions and 0 deletions

View File

@ -47,6 +47,7 @@ pub enum Packet {
I2cReadRequest { destination: u8, busno: u8, ack: bool }, I2cReadRequest { destination: u8, busno: u8, ack: bool },
I2cReadReply { succeeded: bool, data: u8 }, I2cReadReply { succeeded: bool, data: u8 },
I2cBasicReply { succeeded: bool }, I2cBasicReply { succeeded: bool },
I2cSwitchSelectRequest { destination: u8, busno: u8, address: u8, mask: u8 },
SpiSetConfigRequest { destination: u8, busno: u8, flags: u8, length: u8, div: u8, cs: u8 }, SpiSetConfigRequest { destination: u8, busno: u8, flags: u8, length: u8, div: u8, cs: u8 },
SpiWriteRequest { destination: u8, busno: u8, data: u32 }, SpiWriteRequest { destination: u8, busno: u8, data: u32 },
@ -152,6 +153,12 @@ impl Packet {
0x87 => Packet::I2cBasicReply { 0x87 => Packet::I2cBasicReply {
succeeded: reader.read_bool()? succeeded: reader.read_bool()?
}, },
0x88 => Packet::I2cSwitchSelectRequest {
destination: reader.read_u8()?,
busno: reader.read_u8()?,
address: reader.read_u8()?,
mask: reader.read_u8()?
},
0x90 => Packet::SpiSetConfigRequest { 0x90 => Packet::SpiSetConfigRequest {
destination: reader.read_u8()?, destination: reader.read_u8()?,
@ -301,6 +308,13 @@ impl Packet {
writer.write_u8(0x87)?; writer.write_u8(0x87)?;
writer.write_bool(succeeded)?; writer.write_bool(succeeded)?;
}, },
Packet::I2cSwitchSelectRequest { destination, busno, address, mask } => {
writer.write_u8(0x88)?;
writer.write_u8(destination)?;
writer.write_u8(busno)?;
writer.write_u8(address)?;
writer.write_u8(mask)?;
},
Packet::SpiSetConfigRequest { destination, busno, flags, length, div, cs } => { Packet::SpiSetConfigRequest { destination, busno, flags, length, div, cs } => {
writer.write_u8(0x90)?; writer.write_u8(0x90)?;

View File

@ -60,6 +60,29 @@ pub extern fn read(busno: i32, ack: bool) -> i32 {
} }
} }
pub extern fn switch_select(busno: i32, address: i32, mask: i32) {
if busno > 0 {
artiq_raise!("I2CError", "I2C bus could not be accessed");
}
let ch = match mask { //decode from mainline, PCA9548-centric API
0x00 => None,
0x01 => Some(0),
0x02 => Some(1),
0x04 => Some(2),
0x08 => Some(3),
0x10 => Some(4),
0x20 => Some(5),
0x40 => Some(6),
0x80 => Some(7),
_ => artiq_raise!("I2CError", "switch select supports only one channel")
};
unsafe {
if (&mut I2C_BUS).as_mut().unwrap().pca954x_select(address as u8, ch).is_err() {
artiq_raise!("I2CError", "switch select failed");
}
}
}
pub fn init() { pub fn init() {
let mut i2c = libboard_zynq::i2c::I2c::i2c0(); let mut i2c = libboard_zynq::i2c::I2c::i2c0();
i2c.init().expect("I2C bus initialization failed"); i2c.init().expect("I2C bus initialization failed");

View File

@ -116,6 +116,7 @@ pub fn resolve(required: &[u8]) -> Option<u32> {
api!(i2c_stop = i2c::stop), api!(i2c_stop = i2c::stop),
api!(i2c_write = i2c::write), api!(i2c_write = i2c::write),
api!(i2c_read = i2c::read), api!(i2c_read = i2c::read),
api!(i2c_switch_select = i2c::switch_select),
// Double-precision floating-point arithmetic helper functions // Double-precision floating-point arithmetic helper functions
// RTABI chapter 4.1.2, Table 2 // RTABI chapter 4.1.2, Table 2

View File

@ -282,6 +282,23 @@ fn process_aux_packet(_repeaters: &mut [repeater::Repeater],
&drtioaux::Packet::I2cReadReply { succeeded: false, data: 0xff }) &drtioaux::Packet::I2cReadReply { succeeded: false, data: 0xff })
} }
} }
drtioaux::Packet::I2cSwitchSelectRequest { destination: _destination, busno: _busno, address, mask } => {
forward!(_routing_table, _destination, *_rank, _repeaters, &packet, timer);
ch = match mask { //decode from mainline, PCA9548-centric API
0x00 => None,
0x01 => Some(0),
0x02 => Some(1),
0x04 => Some(2),
0x08 => Some(3),
0x10 => Some(4),
0x20 => Some(5),
0x40 => Some(6),
0x80 => Some(7),
_ => { return drtioaux::send(0, &drtioaux::Packet::I2cBasicReply { succeeded: false }); }
};
let succeeded = i2c.pca954x_select(address, ch).is_ok();
drtioaux::send(0, &drtioaux::Packet::I2cBasicReply { succeeded: succeeded })
}
drtioaux::Packet::SpiSetConfigRequest { destination: _destination, busno: _busno, drtioaux::Packet::SpiSetConfigRequest { destination: _destination, busno: _busno,
flags: _flags, length: _length, div: _div, cs: _cs } => { flags: _flags, length: _length, div: _div, cs: _cs } => {