1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
use alloc::string::String;

/// Represents the `compatible` property of a DeviceTree [`Node`].
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Compatible {
    /// Cadence QSPI NOR peripherals
    CdnsQspiNor,
    /// Cadence USB3 peripherals
    CdnsUsb3,
    /// Synopsys DesignWare APB I2C peripherals
    DwApbI2c,
    /// Synopsys DesignWare APB UART peripherals
    DwApbUart,
    /// Synopsys DesignWare AXI DMAC peripherals
    DwAxiDmac,
    /// Synopsys DesignWare Ethernet MAC peripherals
    DwMac,
    /// Synopsys DesignWare MMC peripherals
    DwMmc,
    /// Starfive JH7110 AON CRG peripherals
    Jh7110AonCrg,
    /// Starfive JH7110 AON Pinctrl peripherals
    Jh7110AonPinctrl,
    /// Starfive JH7110 AON Syscon peripherals
    Jh7110AonSyscon,
    /// Starfive JH7110 Crypto peripherals
    Jh7110Crypto,
    /// Starfive JH7110 ISP CRG peripherals
    Jh7110IspCrg,
    /// Starfive JH7110 ISP SYSCON peripherals
    Jh7110IspSyscon,
    /// Starfive JH7110 MIPI TX DPHY peripherals
    Jh7110MipiTxDphy,
    /// Starfive JH7110 PMU peripherals
    Jh7110Pmu,
    /// Starfive JH7110 STG CRG peripherals
    Jh7110StgCrg,
    /// Starfive JH7110 STG Syscon peripherals
    Jh7110StgSyscon,
    /// Starfive JH7110 SYS CRG peripherals
    Jh7110SysCrg,
    /// Starfive JH7110 SYS Pinctrl peripherals
    Jh7110SysPinctrl,
    /// Starfive JH7110 SYS Syscon peripherals
    Jh7110SysSyscon,
    /// Starfive JH7110 TDM peripherals
    Jh7110Tdm,
    /// Starfive JH7110 TRNG peripherals
    Jh7110Trng,
    /// Starfive JH7110 USB peripherals
    Jh7110Usb,
    /// Starfive JH7110 USB PHY peripherals
    Jh7110UsbPhy,
    /// Starfive JH7110 VOUTCRG peripherals
    Jh7110VoutCrg,
    /// Starfive JH7110 VOUT Syscon peripherals
    Jh7110VoutSyscon,
    /// Starfive JH7110 WDT peripherals
    Jh7110Wdt,
    /// ARM pl022 SSP SPI peripherals
    Pl022SspSpi,
    /// ARM PL080 DMAC peripherals
    Pl080Dmac,
    /// RISC-V CLINT (Core-local Interrupt Controller)
    RiscvClint,
    /// RISC-V PLIC (Platform-level Interrupt Controller)
    RiscvPlic,
    /// Opencores PTC PWM v1 (PWM/Timer/Counter)
    OcPwm,
    /// OpenEdges Orbit Memory Controller
    OeOmc,
    /// OpenEdges Orbit PHY
    OeOphy,
    /// Unknown compatibility string
    Unknown(String),
    /// No compatible property
    None,
}

impl Compatible {
    /// Gets whether this is a known [Compatible] peripheral.
    pub const fn is_known(&self) -> bool {
        !(matches!(self, Self::Unknown(_)) || matches!(self, Self::None))
    }
}

impl From<&str> for Compatible {
    fn from(val: &str) -> Self {
        if val.contains("cdns,qspi-nor") || val.contains("cdns,xspi-nor") {
            Self::CdnsQspiNor
        } else if val.contains("cdns,usb3") {
            Self::CdnsUsb3
        } else if val.contains("dw-apb-i2c") || val.contains("designware-i2c") {
            Self::DwApbI2c
        } else if val.contains("dw-apb-uart") {
            Self::DwApbUart
        } else if val.contains("snps,dw-axi-dmac") {
            Self::DwAxiDmac
        } else if val.contains("snps,dwmac") {
            Self::DwMac
        } else if val.contains("snps,dwmmc") || val.contains("starfive,jh7110-mmc") {
            // NOTE: add more matching strings for additional models as implementations are added.
            Self::DwMmc
        } else if val.contains("starfive,jh7110-aoncrg") {
            Self::Jh7110AonCrg
        } else if val.contains("starfive,jh7110-aon-pinctrl") {
            Self::Jh7110AonPinctrl
        } else if val.contains("starfive,jh7110-aon-syscon") {
            Self::Jh7110AonSyscon
        } else if val.contains("starfive,jh7110-crypto") {
            Self::Jh7110Crypto
        } else if val.contains("starfive,jh7110-ispcrg") {
            Self::Jh7110IspCrg
        } else if val.contains("starfive,jh7110-isp-syscon") {
            Self::Jh7110IspSyscon
        } else if val.contains("starfive,jh7110-mipitx-dphy") {
            Self::Jh7110MipiTxDphy
        } else if val.contains("starfive,jh7110-pmu") {
            Self::Jh7110Pmu
        } else if val.contains("starfive,jh7110-stgcrg") {
            Self::Jh7110StgCrg
        } else if val.contains("starfive,jh7110-stg-syscon") {
            Self::Jh7110StgSyscon
        } else if val.contains("starfive,jh7110-syscrg") {
            Self::Jh7110SysCrg
        } else if val.contains("starfive,jh7110-sys-pinctrl") {
            Self::Jh7110SysPinctrl
        } else if val.contains("starfive,jh7110-sys-syscon") {
            Self::Jh7110SysSyscon
        } else if val.contains("starfive,jh7110-tdm") {
            Self::Jh7110Tdm
        } else if val.contains("starfive,jh7110-trng") {
            Self::Jh7110Trng
        } else if val.contains("starfive,jh7110-usb-phy") {
            Self::Jh7110UsbPhy
        } else if val.contains("starfive,jh7110-usb") {
            Self::Jh7110Usb
        } else if val.contains("starfive,jh7110-vout-syscon") {
            Self::Jh7110VoutSyscon
        } else if val.contains("starfive,jh7110-voutcrg") {
            Self::Jh7110VoutCrg
        } else if val.contains("starfive,jh7110-wdt") {
            Self::Jh7110Wdt
        } else if val.contains("arm,pl022") {
            Self::Pl022SspSpi
        } else if val.contains("arm,pl080") {
            Self::Pl080Dmac
        } else if val.contains("riscv,clint") {
            Self::RiscvClint
        } else if val.contains("riscv,plic") {
            Self::RiscvPlic
        } else if val.contains("opencores,pwm-v1") {
            Self::OcPwm
        } else if val.contains("openedges,omc") {
            Self::OeOmc
        } else if val.contains("openedges,ophy") {
            Self::OeOphy
        } else if val.is_empty() {
            Self::None
        } else {
            Self::Unknown(val.into())
        }
    }
}

impl From<&device_tree::Node> for Compatible {
    fn from(val: &device_tree::Node) -> Self {
        val.prop_str("compatible").unwrap_or("").into()
    }
}

impl From<device_tree::Node> for Compatible {
    fn from(val: device_tree::Node) -> Self {
        (&val).into()
    }
}