Skip to main content

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}