aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/phy/Kconfig7
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/ax88796b_rust.rs7
-rw-r--r--drivers/net/phy/qt2025.rs103
4 files changed, 114 insertions, 4 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index f530fcd092fe..01b235b3bb7e 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -112,6 +112,13 @@ config ADIN1100_PHY
Currently supports the:
- ADIN1100 - Robust,Industrial, Low Power 10BASE-T1L Ethernet PHY
+config AMCC_QT2025_PHY
+ tristate "AMCC QT2025 PHY"
+ depends on RUST_PHYLIB_ABSTRACTIONS
+ depends on RUST_FW_LOADER_ABSTRACTIONS
+ help
+ Adds support for the Applied Micro Circuits Corporation QT2025 PHY.
+
source "drivers/net/phy/aquantia/Kconfig"
config AX88796B_PHY
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 33adb3df5f64..90f886844381 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_ADIN_PHY) += adin.o
obj-$(CONFIG_ADIN1100_PHY) += adin1100.o
obj-$(CONFIG_AIR_EN8811H_PHY) += air_en8811h.o
obj-$(CONFIG_AMD_PHY) += amd.o
+obj-$(CONFIG_AMCC_QT2025_PHY) += qt2025.o
obj-$(CONFIG_AQUANTIA_PHY) += aquantia/
ifdef CONFIG_AX88796B_RUST_PHY
obj-$(CONFIG_AX88796B_PHY) += ax88796b_rust.o
diff --git a/drivers/net/phy/ax88796b_rust.rs b/drivers/net/phy/ax88796b_rust.rs
index 5c92572962dc..8c7eb009d9fc 100644
--- a/drivers/net/phy/ax88796b_rust.rs
+++ b/drivers/net/phy/ax88796b_rust.rs
@@ -6,7 +6,7 @@
//! C version of this driver: [`drivers/net/phy/ax88796b.c`](./ax88796b.c)
use kernel::{
c_str,
- net::phy::{self, DeviceId, Driver},
+ net::phy::{self, reg::C22, DeviceId, Driver},
prelude::*,
uapi,
};
@@ -24,7 +24,6 @@ kernel::module_phy_driver! {
license: "GPL",
}
-const MII_BMCR: u16 = uapi::MII_BMCR as u16;
const BMCR_SPEED100: u16 = uapi::BMCR_SPEED100 as u16;
const BMCR_FULLDPLX: u16 = uapi::BMCR_FULLDPLX as u16;
@@ -33,7 +32,7 @@ const BMCR_FULLDPLX: u16 = uapi::BMCR_FULLDPLX as u16;
// Toggle BMCR_RESET bit off to accommodate broken AX8796B PHY implementation
// such as used on the Individual Computers' X-Surf 100 Zorro card.
fn asix_soft_reset(dev: &mut phy::Device) -> Result {
- dev.write(uapi::MII_BMCR as u16, 0)?;
+ dev.write(C22::BMCR, 0)?;
dev.genphy_soft_reset()
}
@@ -55,7 +54,7 @@ impl Driver for PhyAX88772A {
}
// If MII_LPA is 0, phy_resolve_aneg_linkmode() will fail to resolve
// linkmode so use MII_BMCR as default values.
- let ret = dev.read(MII_BMCR)?;
+ let ret = dev.read(C22::BMCR)?;
if ret & BMCR_SPEED100 != 0 {
dev.set_speed(uapi::SPEED_100);
diff --git a/drivers/net/phy/qt2025.rs b/drivers/net/phy/qt2025.rs
new file mode 100644
index 000000000000..28d8981f410b
--- /dev/null
+++ b/drivers/net/phy/qt2025.rs
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) Tehuti Networks Ltd.
+// Copyright (C) 2024 FUJITA Tomonori <fujita.tomonori@gmail.com>
+
+//! Applied Micro Circuits Corporation QT2025 PHY driver
+//!
+//! This driver is based on the vendor driver `QT2025_phy.c`. This source
+//! and firmware can be downloaded on the EN-9320SFP+ support site.
+//!
+//! The QT2025 PHY integrates an Intel 8051 micro-controller.
+
+use kernel::c_str;
+use kernel::error::code;
+use kernel::firmware::Firmware;
+use kernel::net::phy::{
+ self,
+ reg::{Mmd, C45},
+ DeviceId, Driver,
+};
+use kernel::prelude::*;
+use kernel::sizes::{SZ_16K, SZ_8K};
+
+kernel::module_phy_driver! {
+ drivers: [PhyQT2025],
+ device_table: [
+ DeviceId::new_with_driver::<PhyQT2025>(),
+ ],
+ name: "qt2025_phy",
+ author: "FUJITA Tomonori <fujita.tomonori@gmail.com>",
+ description: "AMCC QT2025 PHY driver",
+ license: "GPL",
+ firmware: ["qt2025-2.0.3.3.fw"],
+}
+
+struct PhyQT2025;
+
+#[vtable]
+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<()> {
+ // Check the hardware revision code.
+ // Only 0x3b works with this driver and firmware.
+ let hw_rev = dev.read(C45::new(Mmd::PMAPMD, 0xd001))?;
+ if (hw_rev >> 8) != 0xb3 {
+ return Err(code::ENODEV);
+ }
+
+ // `MICRO_RESETN`: hold the micro-controller in reset while configuring.
+ dev.write(C45::new(Mmd::PMAPMD, 0xc300), 0x0000)?;
+ // `SREFCLK_FREQ`: configure clock frequency of the micro-controller.
+ dev.write(C45::new(Mmd::PMAPMD, 0xc302), 0x0004)?;
+ // Non loopback mode.
+ dev.write(C45::new(Mmd::PMAPMD, 0xc319), 0x0038)?;
+ // `CUS_LAN_WAN_CONFIG`: select between LAN and WAN (WIS) mode.
+ dev.write(C45::new(Mmd::PMAPMD, 0xc31a), 0x0098)?;
+ // The following writes use standardized registers (3.38 through
+ // 3.41 5/10/25GBASE-R PCS test pattern seed B) for something else.
+ // We don't know what.
+ 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, 0xa30a), 0x06e1)?;
+ // `MICRO_RESETN`: release the micro-controller from the reset state.
+ dev.write(C45::new(Mmd::PMAPMD, 0xc300), 0x0002)?;
+ // The micro-controller will start running from the boot ROM.
+ dev.write(C45::new(Mmd::PCS, 0xe854), 0x00c0)?;
+
+ let fw = Firmware::request(c_str!("qt2025-2.0.3.3.fw"), dev.as_ref())?;
+ if fw.data().len() > SZ_16K + SZ_8K {
+ return Err(code::EFBIG);
+ }
+
+ // The 24kB of program memory space is accessible by MDIO.
+ // The first 16kB of memory is located in the address range 3.8000h - 3.BFFFh.
+ // The next 8kB of memory is located at 4.8000h - 4.9FFFh.
+ let mut dst_offset = 0;
+ let mut dst_mmd = Mmd::PCS;
+ for (src_idx, val) in fw.data().iter().enumerate() {
+ if src_idx == SZ_16K {
+ // Start writing to the next register with no offset
+ dst_offset = 0;
+ dst_mmd = Mmd::PHYXS;
+ }
+
+ dev.write(C45::new(dst_mmd, 0x8000 + dst_offset), (*val).into())?;
+
+ dst_offset += 1;
+ }
+ // The micro-controller will start running from SRAM.
+ dev.write(C45::new(Mmd::PCS, 0xe854), 0x0040)?;
+
+ // TODO: sleep here until the hw becomes ready.
+ Ok(())
+ }
+
+ fn read_status(dev: &mut phy::Device) -> Result<u16> {
+ dev.genphy_read_status::<C45>()
+ }
+}