eth_phy_lan867x/plca.rs
1// SPDX-License-Identifier: GPL-2.0-or-later OR Apache-2.0
2// Copyright (c) Viacheslav Bocharov <v@baodeep.com> and JetHome (r)
3
4//! PLCA (Physical Layer Collision Avoidance) configuration types.
5//!
6//! `PlcaConfig` is the input to `PhyLan867x::configure_plca`,
7//! `PlcaStatus` the output of `PhyLan867x::plca_status`, and
8//! `PlcaError` the error type shared by `configure_plca`,
9//! `disable_plca`, and `plca_status`. The methods themselves are
10//! implemented on `PhyLan867x` in `lib.rs`.
11
12/// PLCA configuration (IEEE 802.3 Clause 148).
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15pub struct PlcaConfig {
16 /// Local node ID. `0` = bus coordinator (must be exactly one on the
17 /// segment), `1..=0xFE` = follower.
18 ///
19 /// `0xFF` is rejected by `configure_plca` — the silicon uses it as
20 /// a sentinel that disables PLCA, so the driver refuses to write it
21 /// via the configure path. Use `disable_plca` instead.
22 pub node_id: u8,
23 /// Total node count on the segment (`NCNT`). Must be ≥ active node
24 /// count. Only the coordinator strictly cares about this; followers
25 /// may set it to 0 and still operate, but supplying the right number
26 /// makes diagnostics meaningful on every node.
27 pub node_count: u8,
28 /// Burst-mode max additional packets per transmit opportunity.
29 /// `0` = burst disabled (one frame per TXOP — Clause 148 default).
30 pub burst_count: u8,
31 /// Burst timer in BT (100 ns units). `0` is a sentinel meaning
32 /// "use the chip default" (`0x80` = 128 BT) — `configure_plca`
33 /// substitutes `0x80` before writing `PLCA_BURST.BTMR`.
34 ///
35 /// Note: the chip's `BTMR` field is always written as part of
36 /// `PLCA_BURST` regardless of `burst_count`. The silicon honours
37 /// `BTMR` only when `MAXBC > 0` (i.e. burst is actually enabled),
38 /// so a non-zero `burst_timer` with `burst_count == 0` is harmless
39 /// — it lands in the register but never gates a TXOP.
40 pub burst_timer: u8,
41}
42
43impl Default for PlcaConfig {
44 /// Coordinator with an 8-node segment, no burst.
45 fn default() -> Self {
46 Self {
47 node_id: 0,
48 node_count: 8,
49 burst_count: 0,
50 burst_timer: 0,
51 }
52 }
53}
54
55/// PLCA runtime state.
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
57#[cfg_attr(feature = "defmt", derive(defmt::Format))]
58pub struct PlcaStatus {
59 /// PLCA reconciliation sublayer enabled (`PLCA_CTRL0.EN`).
60 pub enabled: bool,
61 /// Local node ID (`PLCA_CTRL1.ID`).
62 pub node_id: u8,
63 /// `node_id == 0`. The coordinator transmits the periodic BEACONs.
64 pub is_coordinator: bool,
65 /// `PLCA_STS.PST` — BEACONs are being transmitted (coordinator) or
66 /// received (follower) regularly. The closest thing to a "link is
67 /// up" signal on a 10BASE-T1S multidrop bus.
68 pub stable: bool,
69}
70
71/// Errors from PLCA-related driver methods.
72#[derive(Debug)]
73#[non_exhaustive]
74#[cfg_attr(feature = "defmt", derive(defmt::Format))]
75pub enum PlcaError<E> {
76 /// MDIO bus error (passthrough).
77 Mdio(E),
78 /// Configuration values are invalid: `node_id == 0xFF` (silicon
79 /// reserved sentinel for "disabled"), or a follower with
80 /// `node_id ≥ node_count` such that no transmit opportunity is
81 /// ever granted to this node.
82 InvalidConfig,
83}