A driver for the KSZ8863 (MLL/FLL/RLL) Ethernet Switch.
This driver is split into two main modules:
miim
for the MII Management Interface (MIIM).smi
for the Serial Management Interface (SMI).
While these two terms often refer to same protocol, their usage in the KSZ8863 documentation refers to two distinct protocols and sets of registers. Please refer to the datasheet for details.
These modules contain a type and module for every documented register along with
typed access to each of their respective fields. High-level read/write/modify
access to these registers are provided via the Miim
and Smi
types
respectively.
Note that the SPI and I2C interfaces are not currently supported, though PRs are welcome.
At the foundation of this crate are the miim::{Read, Write}
and smi::{Read, Write}
traits. The first step is to implement these for your respective MIIM
and SMI interfaces. For details on how to implement these, visit sections
3.3.10
and 3.3.11
of the datasheet.
Implementing these traits unlocks high level access via the Smi
and Miim
interface type wrappers. These types provide short-hand methods for reading,
writing and modifying registers and their individual fields. The provided API
for these types is inspired by the svd2rust
crate.
Here is an example of using the Miim
.
use ksz8863::{miim, Miim};
fn main() {
// ... Setup our device and `miim_iface`...
// Wrap the type that impls the Read/Write traits with `Miim`.
// Note: We could also wrap `&mut miim_iface` here if we only local scope access is needed.
let mut miim = Miim(miim_iface);
// Specify which phy we want to communicate with via its PHY address.
let mut phy = miim.phy(0);
// Read the value of the "Basic Control Register".
assert_eq!(phy.bcr().read().unwrap(), miim::Bcr::default());
// Modify the "Force 100BT" field of the "Basic Control Register" in place.
let mut bcr = phy.bcr();
assert!(bcr.read().unwrap().read().force_fd().bit_is_clear());
bcr.modify(|w| w.force_fd().set_bit()).unwrap();
let reg = bcr.read().unwrap();
assert!(reg != miim::Bcr::default());
assert!(reg.read().force_fd().bit_is_set());
}
The Smi
API is similar, but we don't need to specify a PHY.
use ksz8863::{smi, Smi};
fn main() {
// ... Setup our device and `smi_iface`...
let mut smi = Smi(smi_iface);
assert_eq!(smi.gc1().read().unwrap(), smi::Gc1::default());
smi.gc1().modify(|w| w.tx_flow_control().clear_bit()).unwrap();
assert!(smi.gc1().read().unwrap() != smi::Gc1::default());
}
The Address
type in each module represents the unique index at which the
register is located.
The State
type from each module is a dynamic representation of register state,
useful for storing the state of multiple registers in a collection.
The Map
type from each module is a collection that is guaranteed to contain
the state of all registers. This is useful for remotely monitoring the state of
registers while reducing I/O, and for simulating an MIIM/SMI interface in the
case that you don't have access to one.
hash-32
provideshash32::Hash
implementations from thehash32
crate.serde
providesDeserialize
andSerialize
implementations.ufmt
providesufmt::uDebug
implementations.
All of these features are opt-in and disabled by default.