Re: [PATCH net-next v2 6/6] net: phy: add Applied Micro QT2025 PHY driver
From: FUJITA Tomonori <fujita.tomonori@gmail.com>
Date: 2024-08-01 01:55:54
Also in:
rust-for-linux
Subsystem:
applied micro qt2025 phy driver, ethernet phy library, ethernet phy library [rust], networking drivers, rust, the rest · Maintainers:
FUJITA Tomonori, Andrew Lunn, Heiner Kallweit, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Miguel Ojeda, Linus Torvalds
Hi Trevor, On Wed, 31 Jul 2024 13:21:36 +0900 FUJITA Tomonori [off-list ref] wrote:
+impl Driver for PhyQT2025 {
+ const NAME: &'static CStr = c_str!("QT2025 10Gpbs SFP+");
+ const PHY_DEVICE_ID: phy::DeviceId = phy::DeviceId::new_with_exact_mask(0x0043A400);
+
+ fn probe(dev: &mut phy::Device) -> Result<()> {
+ // The hardware is configurable?
+ let hw_id = dev.read(C45::new(Mmd::PMAPMD, 0xd001))?;
+ if (hw_id >> 8) & 0xff != 0xb3 {
+ return Ok(());
+ }
+
+ // The 8051 will remain in the reset state.
+ dev.write(C45::new(Mmd::PMAPMD, 0xC300), 0x0000)?;
+ // Configure the 8051 clock frequency.
+ dev.write(C45::new(Mmd::PMAPMD, 0xC302), 0x0004)?;
+ // Non loopback mode.
+ dev.write(C45::new(Mmd::PMAPMD, 0xC319), 0x0038)?;
+ // Global control bit to select between LAN and WAN (WIS) mode.
+ dev.write(C45::new(Mmd::PMAPMD, 0xC31A), 0x0098)?;
+ dev.write(C45::new(Mmd::PCS, 0x0026), 0x0E00)?;
+ dev.write(C45::new(Mmd::PCS, 0x0027), 0x0893)?;
+ dev.write(C45::new(Mmd::PCS, 0x0028), 0xA528)?;
+ dev.write(C45::new(Mmd::PCS, 0x0029), 0x0003)?;
+ // Configure transmit and recovered clock.
+ dev.write(C45::new(Mmd::PMAPMD, 0xC30A), 0x06E1)?;
+ // The 8051 will finish the reset state.
+ dev.write(C45::new(Mmd::PMAPMD, 0xC300), 0x0002)?;
+ // The 8051 will start running from the boot ROM.
+ dev.write(C45::new(Mmd::PCS, 0xE854), 0x00C0)?;You said that it might be nicer to put the above in a table previously, I think. The following looks nicer? If so, I will use the table in v3.
diff --git a/drivers/net/phy/qt2025.rs b/drivers/net/phy/qt2025.rs
index b93472865bde..1b89495d7017 100644
--- a/drivers/net/phy/qt2025.rs
+++ b/drivers/net/phy/qt2025.rs@@ -27,6 +27,27 @@ struct PhyQT2025; +const QT2025_INIT_ROUTINE: &[(C45, u16)] = &[ + // The 8051 will remain in the reset state. + (C45::new(Mmd::PMAPMD, 0xC300), 0x0000), + // Configure the 8051 clock frequency. + (C45::new(Mmd::PMAPMD, 0xC302), 0x0004), + // Non loopback mode. + (C45::new(Mmd::PMAPMD, 0xC319), 0x0038), + // Global control bit to select between LAN and WAN (WIS) mode. + (C45::new(Mmd::PMAPMD, 0xC31A), 0x0098), + (C45::new(Mmd::PCS, 0x0026), 0x0E00), + (C45::new(Mmd::PCS, 0x0027), 0x0893), + (C45::new(Mmd::PCS, 0x0028), 0xA528), + (C45::new(Mmd::PCS, 0x0029), 0x0003), + // Configure transmit and recovered clock. + (C45::new(Mmd::PMAPMD, 0xC30A), 0x06E1), + // The 8051 will finish the reset state. + (C45::new(Mmd::PMAPMD, 0xC300), 0x0002), + // The 8051 will start running from the boot ROM. + (C45::new(Mmd::PCS, 0xE854), 0x00C0), +]; + #[vtable] impl Driver for PhyQT2025 { const NAME: &'static CStr = c_str!("QT2025 10Gpbs SFP+");
@@ -39,24 +60,9 @@ fn probe(dev: &mut phy::Device) -> Result<()> { return Ok(()); } - // The 8051 will remain in the reset state. - dev.write(C45::new(Mmd::PMAPMD, 0xC300), 0x0000)?; - // Configure the 8051 clock frequency. - dev.write(C45::new(Mmd::PMAPMD, 0xC302), 0x0004)?; - // Non loopback mode. - dev.write(C45::new(Mmd::PMAPMD, 0xC319), 0x0038)?; - // Global control bit to select between LAN and WAN (WIS) mode. - dev.write(C45::new(Mmd::PMAPMD, 0xC31A), 0x0098)?; - dev.write(C45::new(Mmd::PCS, 0x0026), 0x0E00)?; - dev.write(C45::new(Mmd::PCS, 0x0027), 0x0893)?; - dev.write(C45::new(Mmd::PCS, 0x0028), 0xA528)?; - dev.write(C45::new(Mmd::PCS, 0x0029), 0x0003)?; - // Configure transmit and recovered clock. - dev.write(C45::new(Mmd::PMAPMD, 0xC30A), 0x06E1)?; - // The 8051 will finish the reset state. - dev.write(C45::new(Mmd::PMAPMD, 0xC300), 0x0002)?; - // The 8051 will start running from the boot ROM. - dev.write(C45::new(Mmd::PCS, 0xE854), 0x00C0)?; + for (reg, val) in QT2025_INIT_ROUTINE { + dev.write(*reg, *val)?; + } let fw = Firmware::request(c_str!("qt2025-2.0.3.3.fw"), dev.as_ref())?; if fw.data().len() > SZ_16K + SZ_8K {
diff --git a/rust/kernel/net/phy/reg.rs b/rust/kernel/net/phy/reg.rs
index 4cf47335539b..603adfd369c1 100644
--- a/rust/kernel/net/phy/reg.rs
+++ b/rust/kernel/net/phy/reg.rs@@ -49,6 +49,7 @@ pub trait Register: private::Sealed { } /// A single MDIO clause 22 register address (5 bits). +#[derive(Clone, Copy)] pub struct C22(u8); impl C22 {
@@ -131,6 +132,7 @@ fn read_status(dev: &mut Device) -> Result<u16> { } /// A single MDIO clause 45 register device and address. +#[derive(Clone, Copy)] pub struct Mmd(u8); impl Mmd {
@@ -174,6 +176,7 @@ impl Mmd { /// a port, then a 16-bit register address to access a location within /// that device. `C45` represents this by storing a [`Mmd`] and /// a register number. +#[derive(Clone, Copy)] pub struct C45 { devad: Mmd, regnum: u16,
@@ -181,7 +184,7 @@ pub struct C45 { impl C45 { /// Creates a new instance of `C45`. - pub fn new(devad: Mmd, regnum: u16) -> Self { + pub const fn new(devad: Mmd, regnum: u16) -> Self { Self { devad, regnum } } }