Merge Official Source

Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
Tianling Shen 2024-01-28 12:19:24 +08:00
commit 9b7e61b88e
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
66 changed files with 4883 additions and 406 deletions

View File

@ -380,9 +380,7 @@ define KernelPackage/phy-aquantia
TITLE:=Aquantia Ethernet PHYs
DEPENDS:=+kmod-libphy +kmod-hwmon-core +kmod-lib-crc-ccitt
KCONFIG:=CONFIG_AQUANTIA_PHY
FILES:= \
$(LINUX_DIR)/drivers/net/phy/aquantia.ko@lt6.1 \
$(LINUX_DIR)/drivers/net/phy/aquantia/aquantia.ko@ge6.1
FILES:=$(LINUX_DIR)/drivers/net/phy/aquantia/aquantia.ko
AUTOLOAD:=$(call AutoLoad,18,aquantia,1)
endef

View File

@ -559,7 +559,7 @@ get_board_phy_name() (
local ref_path="$3"
json_select "$key"
json_get_values path
json_get_vars path
json_select ..
[ "${ref_path%+*}" = "$path" ] && fallback_phy=$key
@ -591,7 +591,7 @@ rename_board_phy_by_name() (
json_load_file /etc/board.json
json_select wlan
json_select "${phy%.*}" || return 0
json_get_values path
json_get_vars path
prev_phy="$(iwinfo nl80211 phyname "path=$path${suffix:++$suffix}")"
[ -n "$prev_phy" ] || return 0

View File

@ -79,7 +79,7 @@
}
--- a/drivers/net/wireless/ath/ath9k/common-debug.c
+++ b/drivers/net/wireless/ath/ath9k/common-debug.c
@@ -316,3 +316,55 @@ void ath9k_cmn_debug_eeprom(struct dentr
@@ -315,3 +315,55 @@ void ath9k_cmn_debug_eeprom(struct dentr
&fops_eeprom);
}
EXPORT_SYMBOL(ath9k_cmn_debug_eeprom);

View File

@ -1,8 +1,8 @@
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1562,6 +1562,50 @@ static const struct file_operations fops
#endif
@@ -1468,6 +1468,50 @@ void ath9k_deinit_debug(struct ath_softc
ath9k_cmn_spectral_deinit_debug(&sc->spec_priv);
}
+static ssize_t read_file_diag(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
@ -51,7 +51,7 @@
int ath9k_init_debug(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
@@ -1589,6 +1633,8 @@ int ath9k_init_debug(struct ath_hw *ah)
@@ -1491,6 +1535,8 @@ int ath9k_init_debug(struct ath_hw *ah)
debugfs_create_file("gpio_led", S_IWUSR,
sc->debug.debugfs_phy, sc, &fops_gpio_led);
#endif

View File

@ -55,7 +55,7 @@
ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -870,7 +870,8 @@ static void ath9k_init_txpower_limits(st
@@ -871,7 +871,8 @@ static void ath9k_init_txpower_limits(st
if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ);
@ -65,7 +65,7 @@
}
static const struct ieee80211_iface_limit if_limits[] = {
@@ -1048,6 +1049,18 @@ static void ath9k_set_hw_capab(struct at
@@ -1049,6 +1050,18 @@ static void ath9k_set_hw_capab(struct at
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
}
@ -84,7 +84,7 @@
int ath9k_init_device(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops)
{
@@ -1095,6 +1108,8 @@ int ath9k_init_device(u16 devid, struct
@@ -1096,6 +1109,8 @@ int ath9k_init_device(u16 devid, struct
wiphy_read_of_freq_limits(hw->wiphy);

View File

@ -13,7 +13,7 @@
static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops)
{
@@ -803,6 +809,9 @@ static int ath9k_init_softc(u16 devid, s
@@ -804,6 +810,9 @@ static int ath9k_init_softc(u16 devid, s
if (ret)
goto err_hw;

View File

@ -1,191 +0,0 @@
From 4e32024cbb14230af3048e249e84f8c2b25ce45a Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.com>
Date: Thu, 28 Oct 2021 15:03:16 +0100
Subject: [PATCH] brcmfmac: Read alternative firmware names from DT
Add the ability to load the names of alternative firmwares from the
Device Tree node. This permits separate firmwares for 43436s and 43438
and allows downstream firmwares to coexist with upstream.
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
---
.../wireless/broadcom/brcm80211/brcmfmac/of.c | 36 ++++++++++++++
.../wireless/broadcom/brcm80211/brcmfmac/of.h | 7 +++
.../broadcom/brcm80211/brcmfmac/sdio.c | 47 +++++++++++++++++--
3 files changed, 87 insertions(+), 3 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
@@ -11,6 +11,7 @@
#include "debug.h"
#include "core.h"
#include "common.h"
+#include "firmware.h"
#include "of.h"
static int brcmf_of_get_country_codes(struct device *dev,
@@ -175,3 +176,38 @@ void brcmf_of_probe(struct device *dev,
sdio->oob_irq_nr = irq;
sdio->oob_irq_flags = irqf;
}
+
+struct brcmf_firmware_mapping *
+brcmf_of_fwnames(struct device *dev, u32 *fwname_count)
+{
+ struct device_node *np = dev->of_node;
+ struct brcmf_firmware_mapping *fwnames;
+ struct device_node *map_np, *fw_np;
+ int of_count;
+ int count = 0;
+
+ map_np = of_get_child_by_name(np, "firmwares");
+ of_count = of_get_child_count(map_np);
+ if (!of_count)
+ return NULL;
+
+ fwnames = devm_kcalloc(dev, of_count,
+ sizeof(struct brcmf_firmware_mapping),
+ GFP_KERNEL);
+
+ for_each_child_of_node(map_np, fw_np)
+ {
+ struct brcmf_firmware_mapping *cur = &fwnames[count];
+
+ if (of_property_read_u32(fw_np, "chipid", &cur->chipid) ||
+ of_property_read_u32(fw_np, "revmask", &cur->revmask))
+ continue;
+ cur->fw_base = of_get_property(fw_np, "fw_base", NULL);
+ if (cur->fw_base)
+ count++;
+ }
+
+ *fwname_count = count;
+
+ return count ? fwnames : NULL;
+}
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
@@ -5,9 +5,20 @@
#ifdef CONFIG_OF
void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
struct brcmf_mp_device *settings);
+#ifdef CPTCFG_BRCMFMAC_SDIO
+struct brcmf_firmware_mapping *
+brcmf_of_fwnames(struct device *dev, u32 *map_count);
+#endif
#else
static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
struct brcmf_mp_device *settings)
{
}
+#ifdef CPTCFG_BRCMFMAC_SDIO
+static struct brcmf_firmware_mapping *
+brcmf_of_fwnames(struct device *dev, u32 *map_count)
+{
+ return NULL;
+}
+#endif
#endif /* CONFIG_OF */
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -35,6 +35,7 @@
#include "core.h"
#include "common.h"
#include "bcdc.h"
+#include "of.h"
#define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500)
#define CTL_DONE_TIMEOUT msecs_to_jiffies(2500)
@@ -632,7 +633,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "b
/* per-board firmware binaries */
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.bin");
-static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
+static const struct brcmf_firmware_mapping sdio_fwnames[] = {
BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0),
BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4),
@@ -660,6 +661,9 @@ static const struct brcmf_firmware_mappi
BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752)
};
+static const struct brcmf_firmware_mapping *brcmf_sdio_fwnames = sdio_fwnames;
+static u32 brcmf_sdio_fwnames_count = ARRAY_SIZE(sdio_fwnames);
+
#define TXCTL_CREDITS 2
static void pkt_align(struct sk_buff *p, int len, int align)
@@ -4201,6 +4205,9 @@ static const struct brcmf_bus_ops brcmf_
#define BRCMF_SDIO_FW_NVRAM 1
#define BRCMF_SDIO_FW_CLM 2
+static struct brcmf_fw_request *
+brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus);
+
static void brcmf_sdio_firmware_callback(struct device *dev, int err,
struct brcmf_fw_request *fwreq)
{
@@ -4216,6 +4223,22 @@ static void brcmf_sdio_firmware_callback
brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
+ if (err && brcmf_sdio_fwnames != sdio_fwnames) {
+ /* Try again with the standard firmware names */
+ brcmf_sdio_fwnames = sdio_fwnames;
+ brcmf_sdio_fwnames_count = ARRAY_SIZE(sdio_fwnames);
+ kfree(fwreq);
+ fwreq = brcmf_sdio_prepare_fw_request(bus);
+ if (!fwreq) {
+ err = -ENOMEM;
+ goto fail;
+ }
+ err = brcmf_fw_get_firmwares(dev, fwreq,
+ brcmf_sdio_firmware_callback);
+ if (!err)
+ return;
+ }
+
if (err)
goto fail;
@@ -4426,7 +4449,7 @@ brcmf_sdio_prepare_fw_request(struct brc
fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev,
brcmf_sdio_fwnames,
- ARRAY_SIZE(brcmf_sdio_fwnames),
+ brcmf_sdio_fwnames_count,
fwnames, ARRAY_SIZE(fwnames));
if (!fwreq)
return NULL;
@@ -4446,6 +4469,9 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
struct brcmf_sdio *bus;
struct workqueue_struct *wq;
struct brcmf_fw_request *fwreq;
+ struct brcmf_firmware_mapping *of_fwnames, *fwnames = NULL;
+ const int fwname_size = sizeof(struct brcmf_firmware_mapping);
+ u32 of_fw_count;
brcmf_dbg(TRACE, "Enter\n");
@@ -4528,6 +4554,21 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
brcmf_dbg(INFO, "completed!!\n");
+ of_fwnames = brcmf_of_fwnames(sdiodev->dev, &of_fw_count);
+ if (of_fwnames)
+ fwnames = devm_kcalloc(sdiodev->dev,
+ of_fw_count + brcmf_sdio_fwnames_count,
+ fwname_size, GFP_KERNEL);
+
+ if (fwnames) {
+ /* The array is scanned in order, so overrides come first */
+ memcpy(fwnames, of_fwnames, of_fw_count * fwname_size);
+ memcpy(fwnames + of_fw_count, sdio_fwnames,
+ brcmf_sdio_fwnames_count * fwname_size);
+ brcmf_sdio_fwnames = fwnames;
+ brcmf_sdio_fwnames_count += of_fw_count;
+ }
+
fwreq = brcmf_sdio_prepare_fw_request(bus);
if (!fwreq) {
ret = -ENOMEM;

View File

@ -0,0 +1,38 @@
brcmfmac: disable dump_survey on Raspberry Pi
Enabling this causes slow iwinfo calls on Raspberry Pi and LuCI slows down
when wireless is enabled.
https://github.com/openwrt/openwrt/issues/14013
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -7987,6 +7987,7 @@ static s32 brcmf_translate_country_code(
return 0;
}
+#if !defined(CONFIG_ARCH_BCM2835)
static int
brcmf_parse_dump_obss(char *buf, struct brcmf_dump_survey *survey)
{
@@ -8209,6 +8210,7 @@ exit:
brcmf_set_mpc(ifp, 1);
return err;
}
+#endif /* CONFIG_ARCH_BCM2835 */
static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
struct regulatory_request *req)
@@ -8361,8 +8363,10 @@ struct brcmf_cfg80211_info *brcmf_cfg802
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))
ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;
#endif
+#if !defined(CONFIG_ARCH_BCM2835)
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_DUMP_OBSS))
ops->dump_survey = brcmf_cfg80211_dump_survey;
+#endif /* CONFIG_ARCH_BCM2835 */
err = wiphy_register(wiphy);
if (err < 0) {

View File

@ -18,7 +18,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2422,6 +2422,13 @@ static void sta_stats_decode_rate(struct
@@ -2423,6 +2423,13 @@ static void sta_stats_decode_rate(struct
sband = local->hw.wiphy->bands[band];

View File

@ -46,6 +46,7 @@ MAKE_FLAGS+= \
SoC=$(CONFIG_TARGET_SUBTARGET) \
PTP_FEATURE=disable SWCONFIG_FEATURE=disable \
ISISC_ENABLE=disable IN_QCA803X_PHY=FALSE \
IN_QCA808X_PHY=FALSE \
$(LNX_CONFIG_OPTS)
ifeq ($(CONFIG_TARGET_SUBTARGET), "ipq807x")

View File

@ -5,9 +5,9 @@ PKG_RELEASE=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/libubox.git
PKG_MIRROR_HASH:=daf411244a7f87c09c383c6fb69636a038c85f351bba93e80cc9aa530301199e
PKG_SOURCE_DATE:=2023-12-04.1
PKG_SOURCE_VERSION:=ca3f6d0cdb1e588283c42d039779ceab303ceef2
PKG_MIRROR_HASH:=071139fed757bea240d4ba8f55a0ff5a81862d23e16b39fc871ae07da78ae6a4
PKG_SOURCE_DATE:=2024-01-26
PKG_SOURCE_VERSION:=c1be505732e6d254464973bdeacb955214c76c46
PKG_ABI_VERSION:=$(call abi_version_str,$(PKG_SOURCE_DATE))
CMAKE_INSTALL:=1

View File

@ -11,9 +11,9 @@ PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/iwinfo.git
PKG_SOURCE_DATE:=2023-07-01
PKG_SOURCE_VERSION:=ca79f64154b107f192ec3c1ba631816cb8b07922
PKG_MIRROR_HASH:=5eddf584a1c3ed5637162d6bfc573ed1ce3691fcb38bdd55bf9f1e11e82ccc46
PKG_SOURCE_DATE:=2023-11-19
PKG_SOURCE_VERSION:=a34977c0760c93480491c8eb94da656b57d7f4cc
PKG_MIRROR_HASH:=cb01671a2a9155f8ba55751ab1fe28488c5821212dd97ba5b79653640abb787e
PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
PKG_LICENSE:=GPL-2.0

View File

@ -41,7 +41,6 @@ define Package/bcm27xx-userland
CATEGORY:=Utilities
DEPENDS:=@TARGET_bcm27xx
TITLE:=BCM27xx userland tools
DEFAULT:=y if TARGET_bcm27xx
endef
define Package/bcm27xx-userland/description

View File

@ -22,7 +22,7 @@ include $(INCLUDE_DIR)/target.mk
DEFAULT_PACKAGES := $(filter-out urngd,$(DEFAULT_PACKAGES))
DEFAULT_PACKAGES += \
bcm27xx-gpu-fw \
bcm27xx-gpu-fw bcm27xx-utils \
kmod-usb-hid \
kmod-sound-core kmod-sound-arm-bcm2835 \
kmod-fs-vfat kmod-nls-cp437 kmod-nls-iso8859-1 \

View File

@ -26,6 +26,7 @@ CONFIG_ARM64_CNP=y
CONFIG_ARM64_EPAN=y
CONFIG_ARM64_ERRATUM_1319367=y
CONFIG_ARM64_HW_AFDBM=y
CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y
CONFIG_ARM64_PAGE_SHIFT=12
CONFIG_ARM64_PAN=y
CONFIG_ARM64_PA_BITS=48
@ -36,7 +37,7 @@ CONFIG_ARM64_SVE=y
CONFIG_ARM64_TAGGED_ADDR_ABI=y
CONFIG_ARM64_VA_BITS=39
CONFIG_ARM64_VA_BITS_39=y
CONFIG_ARM64_WORKAROUND_CLEAN_CACHE=y
CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y
CONFIG_ARM_AMBA=y
CONFIG_ARM_ARCH_TIMER=y
CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y

View File

@ -0,0 +1,99 @@
From 5e61fe157a27afc7c0d4f7bcbceefdca536c015f Mon Sep 17 00:00:00 2001
From: Maxime Chevallier <maxime.chevallier@bootlin.com>
Date: Wed, 17 Aug 2022 14:32:52 +0200
Subject: [PATCH] net: phy: Introduce QUSGMII PHY mode
The QUSGMII mode is a derivative of Cisco's USXGMII standard. This
standard is pretty similar to SGMII, but allows for faster speeds, and
has the build-in bits for Quad and Octa variants (like QSGMII).
The main difference with SGMII/QSGMII is that USXGMII/QUSGMII re-uses
the preamble to carry various information, named 'Extensions'.
As of today, the USXGMII standard only mentions the "PCH" extension,
which is used to convey timestamps, allowing in-band signaling of PTP
timestamps without having to modify the frame itself.
This commit adds support for that mode. When no extension is in use, it
behaves exactly like QSGMII, although it's not compatible with QSGMII.
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
Documentation/networking/phy.rst | 9 +++++++++
drivers/net/phy/phylink.c | 3 +++
include/linux/phy.h | 4 ++++
3 files changed, 16 insertions(+)
--- a/Documentation/networking/phy.rst
+++ b/Documentation/networking/phy.rst
@@ -303,6 +303,15 @@ Some of the interface modes are describe
rate of 125Mpbs using a 4B/5B encoding scheme, resulting in an underlying
data rate of 100Mpbs.
+``PHY_INTERFACE_MODE_QUSGMII``
+ This defines the Cisco the Quad USGMII mode, which is the Quad variant of
+ the USGMII (Universal SGMII) link. It's very similar to QSGMII, but uses
+ a Packet Control Header (PCH) instead of the 7 bytes preamble to carry not
+ only the port id, but also so-called "extensions". The only documented
+ extension so-far in the specification is the inclusion of timestamps, for
+ PTP-enabled PHYs. This mode isn't compatible with QSGMII, but offers the
+ same capabilities in terms of link speed and negociation.
+
Pause frames / flow control
===========================
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -367,6 +367,7 @@ void phylink_get_linkmodes(unsigned long
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_QSGMII:
+ case PHY_INTERFACE_MODE_QUSGMII:
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_GMII:
caps |= MAC_1000HD | MAC_1000FD;
@@ -630,6 +631,7 @@ static int phylink_parse_mode(struct phy
switch (pl->link_config.interface) {
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_QSGMII:
+ case PHY_INTERFACE_MODE_QUSGMII:
phylink_set(pl->supported, 10baseT_Half);
phylink_set(pl->supported, 10baseT_Full);
phylink_set(pl->supported, 100baseT_Half);
@@ -2956,6 +2958,7 @@ void phylink_mii_c22_pcs_get_state(struc
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_QSGMII:
+ case PHY_INTERFACE_MODE_QUSGMII:
phylink_decode_sgmii_word(state, lpa);
break;
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -115,6 +115,7 @@ extern const int phy_10gbit_features_arr
* @PHY_INTERFACE_MODE_25GBASER: 25G BaseR
* @PHY_INTERFACE_MODE_USXGMII: Universal Serial 10GE MII
* @PHY_INTERFACE_MODE_10GKR: 10GBASE-KR - with Clause 73 AN
+ * @PHY_INTERFACE_MODE_QUSGMII: Quad Universal SGMII
* @PHY_INTERFACE_MODE_MAX: Book keeping
*
* Describes the interface between the MAC and PHY.
@@ -152,6 +153,7 @@ typedef enum {
PHY_INTERFACE_MODE_USXGMII,
/* 10GBASE-KR - with Clause 73 AN */
PHY_INTERFACE_MODE_10GKR,
+ PHY_INTERFACE_MODE_QUSGMII,
PHY_INTERFACE_MODE_MAX,
} phy_interface_t;
@@ -267,6 +269,8 @@ static inline const char *phy_modes(phy_
return "10gbase-kr";
case PHY_INTERFACE_MODE_100BASEX:
return "100base-x";
+ case PHY_INTERFACE_MODE_QUSGMII:
+ return "qusgmii";
default:
return "unknown";
}

View File

@ -0,0 +1,93 @@
From c04ade27cb7b952b6b9b9a0efa0a6129cc63f2ae Mon Sep 17 00:00:00 2001
From: Maxime Chevallier <maxime.chevallier@bootlin.com>
Date: Wed, 17 Aug 2022 14:32:54 +0200
Subject: [PATCH] net: phy: Add helper to derive the number of ports from a phy
mode
Some phy modes such as QSGMII multiplex several MAC<->PHY links on one
single physical interface. QSGMII used to be the only one supported, but
other modes such as QUSGMII also carry multiple links.
This helper allows getting the number of links that are multiplexed
on a given interface.
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/phy-core.c | 52 ++++++++++++++++++++++++++++++++++++++
include/linux/phy.h | 2 ++
2 files changed, 54 insertions(+)
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -74,6 +74,58 @@ const char *phy_duplex_to_str(unsigned i
}
EXPORT_SYMBOL_GPL(phy_duplex_to_str);
+/**
+ * phy_interface_num_ports - Return the number of links that can be carried by
+ * a given MAC-PHY physical link. Returns 0 if this is
+ * unknown, the number of links else.
+ *
+ * @interface: The interface mode we want to get the number of ports
+ */
+int phy_interface_num_ports(phy_interface_t interface)
+{
+ switch (interface) {
+ case PHY_INTERFACE_MODE_NA:
+ return 0;
+ case PHY_INTERFACE_MODE_INTERNAL:
+ case PHY_INTERFACE_MODE_MII:
+ case PHY_INTERFACE_MODE_GMII:
+ case PHY_INTERFACE_MODE_TBI:
+ case PHY_INTERFACE_MODE_REVMII:
+ case PHY_INTERFACE_MODE_RMII:
+ case PHY_INTERFACE_MODE_REVRMII:
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ case PHY_INTERFACE_MODE_RTBI:
+ case PHY_INTERFACE_MODE_XGMII:
+ case PHY_INTERFACE_MODE_XLGMII:
+ case PHY_INTERFACE_MODE_MOCA:
+ case PHY_INTERFACE_MODE_TRGMII:
+ case PHY_INTERFACE_MODE_USXGMII:
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_SMII:
+ case PHY_INTERFACE_MODE_1000BASEX:
+ case PHY_INTERFACE_MODE_2500BASEX:
+ case PHY_INTERFACE_MODE_5GBASER:
+ case PHY_INTERFACE_MODE_10GBASER:
+ case PHY_INTERFACE_MODE_25GBASER:
+ case PHY_INTERFACE_MODE_10GKR:
+ case PHY_INTERFACE_MODE_100BASEX:
+ case PHY_INTERFACE_MODE_RXAUI:
+ case PHY_INTERFACE_MODE_XAUI:
+ return 1;
+ case PHY_INTERFACE_MODE_QSGMII:
+ case PHY_INTERFACE_MODE_QUSGMII:
+ return 4;
+ case PHY_INTERFACE_MODE_MAX:
+ WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode");
+ return 0;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(phy_interface_num_ports);
+
/* A mapping of all SUPPORTED settings to speed/duplex. This table
* must be grouped by speed and sorted in descending match priority
* - iow, descending speed.
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -964,6 +964,8 @@ struct phy_fixup {
const char *phy_speed_to_str(int speed);
const char *phy_duplex_to_str(unsigned int duplex);
+int phy_interface_num_ports(phy_interface_t interface);
+
/* A structure for mapping a particular speed and duplex
* combination to a particular SUPPORTED and ADVERTISED value
*/

View File

@ -0,0 +1,96 @@
From 05ad5d4581c3c1cc724fe50d4652833fb9f3037b Mon Sep 17 00:00:00 2001
From: Sean Anderson <sean.anderson@seco.com>
Date: Fri, 2 Sep 2022 18:02:39 -0400
Subject: [PATCH] net: phy: Add 1000BASE-KX interface mode
Add 1000BASE-KX interface mode. This 1G backplane ethernet as described in
clause 70. Clause 73 autonegotiation is mandatory, and only full duplex
operation is supported.
Although at the PMA level this interface mode is identical to
1000BASE-X, it uses a different form of in-band autonegation. This
justifies a separate interface mode, since the interface mode (along
with the MLO_AN_* autonegotiation mode) sets the type of autonegotiation
which will be used on a link. This results in more than just electrical
differences between the link modes.
With regard to 1000BASE-X, 1000BASE-KX holds a similar position to
SGMII: same signaling, but different autonegotiation. PCS drivers
(which typically handle in-band autonegotiation) may only support
1000BASE-X, and not 1000BASE-KX. Similarly, the phy mode is used to
configure serdes phys with phy_set_mode_ext. Due to the different
electrical standards (SFI or XFI vs Clause 70), they will likely want to
use different configuration. Adding a phy interface mode for
1000BASE-KX helps simplify configuration in these areas.
Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
Documentation/networking/phy.rst | 6 ++++++
drivers/net/phy/phy-core.c | 1 +
drivers/net/phy/phylink.c | 1 +
include/linux/phy.h | 4 ++++
4 files changed, 12 insertions(+)
--- a/Documentation/networking/phy.rst
+++ b/Documentation/networking/phy.rst
@@ -312,6 +312,12 @@ Some of the interface modes are describe
PTP-enabled PHYs. This mode isn't compatible with QSGMII, but offers the
same capabilities in terms of link speed and negociation.
+``PHY_INTERFACE_MODE_1000BASEKX``
+ This is 1000BASE-X as defined by IEEE 802.3 Clause 36 with Clause 73
+ autonegotiation. Generally, it will be used with a Clause 70 PMD. To
+ contrast with the 1000BASE-X phy mode used for Clause 38 and 39 PMDs, this
+ interface mode has different autonegotiation and only supports full duplex.
+
Pause frames / flow control
===========================
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -114,6 +114,7 @@ int phy_interface_num_ports(phy_interfac
case PHY_INTERFACE_MODE_100BASEX:
case PHY_INTERFACE_MODE_RXAUI:
case PHY_INTERFACE_MODE_XAUI:
+ case PHY_INTERFACE_MODE_1000BASEKX:
return 1;
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -390,6 +390,7 @@ void phylink_get_linkmodes(unsigned long
case PHY_INTERFACE_MODE_1000BASEX:
caps |= MAC_1000HD;
fallthrough;
+ case PHY_INTERFACE_MODE_1000BASEKX:
case PHY_INTERFACE_MODE_TRGMII:
caps |= MAC_1000FD;
break;
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -116,6 +116,7 @@ extern const int phy_10gbit_features_arr
* @PHY_INTERFACE_MODE_USXGMII: Universal Serial 10GE MII
* @PHY_INTERFACE_MODE_10GKR: 10GBASE-KR - with Clause 73 AN
* @PHY_INTERFACE_MODE_QUSGMII: Quad Universal SGMII
+ * @PHY_INTERFACE_MODE_1000BASEKX: 1000Base-KX - with Clause 73 AN
* @PHY_INTERFACE_MODE_MAX: Book keeping
*
* Describes the interface between the MAC and PHY.
@@ -154,6 +155,7 @@ typedef enum {
/* 10GBASE-KR - with Clause 73 AN */
PHY_INTERFACE_MODE_10GKR,
PHY_INTERFACE_MODE_QUSGMII,
+ PHY_INTERFACE_MODE_1000BASEKX,
PHY_INTERFACE_MODE_MAX,
} phy_interface_t;
@@ -251,6 +253,8 @@ static inline const char *phy_modes(phy_
return "trgmii";
case PHY_INTERFACE_MODE_1000BASEX:
return "1000base-x";
+ case PHY_INTERFACE_MODE_1000BASEKX:
+ return "1000base-kx";
case PHY_INTERFACE_MODE_2500BASEX:
return "2500base-x";
case PHY_INTERFACE_MODE_5GBASER:

View File

@ -0,0 +1,294 @@
From 0c3e10cb44232833a50cb8e3e784c432906a60c1 Mon Sep 17 00:00:00 2001
From: Sean Anderson <sean.anderson@seco.com>
Date: Tue, 20 Sep 2022 18:12:31 -0400
Subject: [PATCH] net: phy: Add support for rate matching
This adds support for rate matching (also known as rate adaptation) to
the phy subsystem. The general idea is that the phy interface runs at
one speed, and the MAC throttles the rate at which it sends packets to
the link speed. There's a good overview of several techniques for
achieving this at [1]. This patch adds support for three: pause-frame
based (such as in Aquantia phys), CRS-based (such as in 10PASS-TS and
2BASE-TL), and open-loop-based (such as in 10GBASE-W).
This patch makes a few assumptions and a few non assumptions about the
types of rate matching available. First, it assumes that different phys
may use different forms of rate matching. Second, it assumes that phys
can use rate matching for any of their supported link speeds (e.g. if a
phy supports 10BASE-T and XGMII, then it can adapt XGMII to 10BASE-T).
Third, it does not assume that all interface modes will use the same
form of rate matching. Fourth, it does not assume that all phy devices
will support rate matching (even if some do). Relaxing or strengthening
these (non-)assumptions could result in a different API. For example, if
all interface modes were assumed to use the same form of rate matching,
then a bitmask of interface modes supportting rate matching would
suffice.
For some better visibility into the process, the current rate matching
mode is exposed as part of the ethtool ksettings. For the moment, only
read access is supported. I'm not sure what userspace might want to
configure yet (disable it altogether, disable just one mode, specify the
mode to use, etc.). For the moment, since only pause-based rate
adaptation support is added in the next few commits, rate matching can
be disabled altogether by adjusting the advertisement.
802.3 calls this feature "rate adaptation" in clause 49 (10GBASE-R) and
"rate matching" in clause 61 (10PASS-TL and 2BASE-TS). Aquantia also calls
this feature "rate adaptation". I chose "rate matching" because it is
shorter, and because Russell doesn't think "adaptation" is correct in this
context.
Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
Documentation/networking/ethtool-netlink.rst | 2 ++
drivers/net/phy/phy-core.c | 21 +++++++++++++++
drivers/net/phy/phy.c | 28 ++++++++++++++++++++
include/linux/phy.h | 22 ++++++++++++++-
include/uapi/linux/ethtool.h | 18 +++++++++++--
include/uapi/linux/ethtool_netlink.h | 1 +
net/ethtool/ioctl.c | 1 +
net/ethtool/linkmodes.c | 5 ++++
8 files changed, 95 insertions(+), 3 deletions(-)
--- a/Documentation/networking/ethtool-netlink.rst
+++ b/Documentation/networking/ethtool-netlink.rst
@@ -418,6 +418,7 @@ Kernel response contents:
``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode
``ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG`` u8 Master/slave port mode
``ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE`` u8 Master/slave port state
+ ``ETHTOOL_A_LINKMODES_RATE_MATCHING`` u8 PHY rate matching
========================================== ====== ==========================
For ``ETHTOOL_A_LINKMODES_OURS``, value represents advertised modes and mask
@@ -441,6 +442,7 @@ Request contents:
``ETHTOOL_A_LINKMODES_SPEED`` u32 link speed (Mb/s)
``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode
``ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG`` u8 Master/slave port mode
+ ``ETHTOOL_A_LINKMODES_RATE_MATCHING`` u8 PHY rate matching
``ETHTOOL_A_LINKMODES_LANES`` u32 lanes
========================================== ====== ==========================
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -75,6 +75,27 @@ const char *phy_duplex_to_str(unsigned i
EXPORT_SYMBOL_GPL(phy_duplex_to_str);
/**
+ * phy_rate_matching_to_str - Return a string describing the rate matching
+ *
+ * @rate_matching: Type of rate matching to describe
+ */
+const char *phy_rate_matching_to_str(int rate_matching)
+{
+ switch (rate_matching) {
+ case RATE_MATCH_NONE:
+ return "none";
+ case RATE_MATCH_PAUSE:
+ return "pause";
+ case RATE_MATCH_CRS:
+ return "crs";
+ case RATE_MATCH_OPEN_LOOP:
+ return "open-loop";
+ }
+ return "Unsupported (update phy-core.c)";
+}
+EXPORT_SYMBOL_GPL(phy_rate_matching_to_str);
+
+/**
* phy_interface_num_ports - Return the number of links that can be carried by
* a given MAC-PHY physical link. Returns 0 if this is
* unknown, the number of links else.
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -127,6 +127,33 @@ void phy_print_status(struct phy_device
EXPORT_SYMBOL(phy_print_status);
/**
+ * phy_get_rate_matching - determine if rate matching is supported
+ * @phydev: The phy device to return rate matching for
+ * @iface: The interface mode to use
+ *
+ * This determines the type of rate matching (if any) that @phy supports
+ * using @iface. @iface may be %PHY_INTERFACE_MODE_NA to determine if any
+ * interface supports rate matching.
+ *
+ * Return: The type of rate matching @phy supports for @iface, or
+ * %RATE_MATCH_NONE.
+ */
+int phy_get_rate_matching(struct phy_device *phydev,
+ phy_interface_t iface)
+{
+ int ret = RATE_MATCH_NONE;
+
+ if (phydev->drv->get_rate_matching) {
+ mutex_lock(&phydev->lock);
+ ret = phydev->drv->get_rate_matching(phydev, iface);
+ mutex_unlock(&phydev->lock);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(phy_get_rate_matching);
+
+/**
* phy_config_interrupt - configure the PHY device for the requested interrupts
* @phydev: the phy_device struct
* @interrupts: interrupt flags to configure for this @phydev
@@ -268,6 +295,7 @@ void phy_ethtool_ksettings_get(struct ph
cmd->base.duplex = phydev->duplex;
cmd->base.master_slave_cfg = phydev->master_slave_get;
cmd->base.master_slave_state = phydev->master_slave_state;
+ cmd->base.rate_matching = phydev->rate_matching;
if (phydev->interface == PHY_INTERFACE_MODE_MOCA)
cmd->base.port = PORT_BNC;
else
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -280,7 +280,6 @@ static inline const char *phy_modes(phy_
}
}
-
#define PHY_INIT_TIMEOUT 100000
#define PHY_FORCE_TIMEOUT 10
@@ -573,6 +572,7 @@ struct macsec_ops;
* @lp_advertising: Current link partner advertised linkmodes
* @eee_broken_modes: Energy efficient ethernet modes which should be prohibited
* @autoneg: Flag autoneg being used
+ * @rate_matching: Current rate matching mode
* @link: Current link state
* @autoneg_complete: Flag auto negotiation of the link has completed
* @mdix: Current crossover
@@ -639,6 +639,8 @@ struct phy_device {
unsigned irq_suspended:1;
unsigned irq_rerun:1;
+ int rate_matching;
+
enum phy_state state;
u32 dev_flags;
@@ -801,6 +803,21 @@ struct phy_driver {
*/
int (*get_features)(struct phy_device *phydev);
+ /**
+ * @get_rate_matching: Get the supported type of rate matching for a
+ * particular phy interface. This is used by phy consumers to determine
+ * whether to advertise lower-speed modes for that interface. It is
+ * assumed that if a rate matching mode is supported on an interface,
+ * then that interface's rate can be adapted to all slower link speeds
+ * supported by the phy. If iface is %PHY_INTERFACE_MODE_NA, and the phy
+ * supports any kind of rate matching for any interface, then it must
+ * return that rate matching mode (preferring %RATE_MATCH_PAUSE to
+ * %RATE_MATCH_CRS). If the interface is not supported, this should
+ * return %RATE_MATCH_NONE.
+ */
+ int (*get_rate_matching)(struct phy_device *phydev,
+ phy_interface_t iface);
+
/* PHY Power Management */
/** @suspend: Suspend the hardware, saving state if needed */
int (*suspend)(struct phy_device *phydev);
@@ -967,6 +984,7 @@ struct phy_fixup {
const char *phy_speed_to_str(int speed);
const char *phy_duplex_to_str(unsigned int duplex);
+const char *phy_rate_matching_to_str(int rate_matching);
int phy_interface_num_ports(phy_interface_t interface);
@@ -1675,6 +1693,8 @@ int phy_disable_interrupts(struct phy_de
void phy_request_interrupt(struct phy_device *phydev);
void phy_free_interrupt(struct phy_device *phydev);
void phy_print_status(struct phy_device *phydev);
+int phy_get_rate_matching(struct phy_device *phydev,
+ phy_interface_t iface);
int phy_set_max_speed(struct phy_device *phydev, u32 max_speed);
void phy_remove_link_mode(struct phy_device *phydev, u32 link_mode);
void phy_advertise_supported(struct phy_device *phydev);
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -1809,6 +1809,20 @@ static inline int ethtool_validate_duple
#define MASTER_SLAVE_STATE_SLAVE 3
#define MASTER_SLAVE_STATE_ERR 4
+/* These are used to throttle the rate of data on the phy interface when the
+ * native speed of the interface is higher than the link speed. These should
+ * not be used for phy interfaces which natively support multiple speeds (e.g.
+ * MII or SGMII).
+ */
+/* No rate matching performed. */
+#define RATE_MATCH_NONE 0
+/* The phy sends pause frames to throttle the MAC. */
+#define RATE_MATCH_PAUSE 1
+/* The phy asserts CRS to prevent the MAC from transmitting. */
+#define RATE_MATCH_CRS 2
+/* The MAC is programmed with a sufficiently-large IPG. */
+#define RATE_MATCH_OPEN_LOOP 3
+
/* Which connector port. */
#define PORT_TP 0x00
#define PORT_AUI 0x01
@@ -2002,8 +2016,8 @@ enum ethtool_reset_flags {
* reported consistently by PHYLIB. Read-only.
* @master_slave_cfg: Master/slave port mode.
* @master_slave_state: Master/slave port state.
+ * @rate_matching: Rate adaptation performed by the PHY
* @reserved: Reserved for future use; see the note on reserved space.
- * @reserved1: Reserved for future use; see the note on reserved space.
* @link_mode_masks: Variable length bitmaps.
*
* If autonegotiation is disabled, the speed and @duplex represent the
@@ -2054,7 +2068,7 @@ struct ethtool_link_settings {
__u8 transceiver;
__u8 master_slave_cfg;
__u8 master_slave_state;
- __u8 reserved1[1];
+ __u8 rate_matching;
__u32 reserved[7];
__u32 link_mode_masks[0];
/* layout of link_mode_masks fields:
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -238,6 +238,7 @@ enum {
ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG, /* u8 */
ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE, /* u8 */
ETHTOOL_A_LINKMODES_LANES, /* u32 */
+ ETHTOOL_A_LINKMODES_RATE_MATCHING, /* u8 */
/* add new constants above here */
__ETHTOOL_A_LINKMODES_CNT,
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -559,6 +559,7 @@ static int ethtool_get_link_ksettings(st
= __ETHTOOL_LINK_MODE_MASK_NU32;
link_ksettings.base.master_slave_cfg = MASTER_SLAVE_CFG_UNSUPPORTED;
link_ksettings.base.master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED;
+ link_ksettings.base.rate_matching = RATE_MATCH_NONE;
return store_link_ksettings_for_user(useraddr, &link_ksettings);
}
--- a/net/ethtool/linkmodes.c
+++ b/net/ethtool/linkmodes.c
@@ -70,6 +70,7 @@ static int linkmodes_reply_size(const st
+ nla_total_size(sizeof(u32)) /* LINKMODES_SPEED */
+ nla_total_size(sizeof(u32)) /* LINKMODES_LANES */
+ nla_total_size(sizeof(u8)) /* LINKMODES_DUPLEX */
+ + nla_total_size(sizeof(u8)) /* LINKMODES_RATE_MATCHING */
+ 0;
ret = ethnl_bitset_size(ksettings->link_modes.advertising,
ksettings->link_modes.supported,
@@ -143,6 +144,10 @@ static int linkmodes_fill_reply(struct s
lsettings->master_slave_state))
return -EMSGSIZE;
+ if (nla_put_u8(skb, ETHTOOL_A_LINKMODES_RATE_MATCHING,
+ lsettings->rate_matching))
+ return -EMSGSIZE;
+
return 0;
}

View File

@ -0,0 +1,58 @@
From 12cf1b89a66828719b2135891b65bd5d03eedea9 Mon Sep 17 00:00:00 2001
From: Bhadram Varka <vbhadram@nvidia.com>
Date: Tue, 21 Jun 2022 09:10:27 +0530
Subject: [PATCH] net: phy: Add support for AQR113C EPHY
Add support multi-gigabit and single-port Ethernet
PHY transceiver (AQR113C).
Signed-off-by: Bhadram Varka <vbhadram@nvidia.com>
Link: https://lore.kernel.org/r/20220621034027.56508-1-vbhadram@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/aquantia_main.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
--- a/drivers/net/phy/aquantia_main.c
+++ b/drivers/net/phy/aquantia_main.c
@@ -22,6 +22,7 @@
#define PHY_ID_AQR107 0x03a1b4e0
#define PHY_ID_AQCS109 0x03a1b5c2
#define PHY_ID_AQR405 0x03a1b4b0
+#define PHY_ID_AQR113C 0x31c31c12
#define MDIO_PHYXS_VEND_IF_STATUS 0xe812
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3)
@@ -744,6 +745,24 @@ static struct phy_driver aqr_driver[] =
.handle_interrupt = aqr_handle_interrupt,
.read_status = aqr_read_status,
},
+{
+ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C),
+ .name = "Aquantia AQR113C",
+ .probe = aqr107_probe,
+ .config_init = aqr107_config_init,
+ .config_aneg = aqr_config_aneg,
+ .config_intr = aqr_config_intr,
+ .handle_interrupt = aqr_handle_interrupt,
+ .read_status = aqr107_read_status,
+ .get_tunable = aqr107_get_tunable,
+ .set_tunable = aqr107_set_tunable,
+ .suspend = aqr107_suspend,
+ .resume = aqr107_resume,
+ .get_sset_count = aqr107_get_sset_count,
+ .get_strings = aqr107_get_strings,
+ .get_stats = aqr107_get_stats,
+ .link_change_notify = aqr107_link_change_notify,
+},
};
module_phy_driver(aqr_driver);
@@ -756,6 +775,7 @@ static struct mdio_device_id __maybe_unu
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR107) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR405) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) },
{ }
};

View File

@ -0,0 +1,71 @@
From 7de26bf144f6a72858ab60afb2bd2b43265ee0ad Mon Sep 17 00:00:00 2001
From: Sean Anderson <sean.anderson@seco.com>
Date: Tue, 20 Sep 2022 18:12:34 -0400
Subject: [PATCH] net: phy: aquantia: Add some additional phy interfaces
These are documented in the AQR115 register reference. I haven't tested
them, but perhaps they'll be useful to someone.
Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/aquantia_main.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
--- a/drivers/net/phy/aquantia_main.c
+++ b/drivers/net/phy/aquantia_main.c
@@ -27,9 +27,12 @@
#define MDIO_PHYXS_VEND_IF_STATUS 0xe812
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3)
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR 0
+#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX 1
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI 2
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII 3
+#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI 4
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6
+#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI 7
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10
#define MDIO_AN_VEND_PROV 0xc400
@@ -401,15 +404,24 @@ static int aqr107_read_status(struct phy
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR:
phydev->interface = PHY_INTERFACE_MODE_10GKR;
break;
+ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX:
+ phydev->interface = PHY_INTERFACE_MODE_1000BASEKX;
+ break;
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI:
phydev->interface = PHY_INTERFACE_MODE_10GBASER;
break;
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII:
phydev->interface = PHY_INTERFACE_MODE_USXGMII;
break;
+ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI:
+ phydev->interface = PHY_INTERFACE_MODE_XAUI;
+ break;
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII:
phydev->interface = PHY_INTERFACE_MODE_SGMII;
break;
+ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI:
+ phydev->interface = PHY_INTERFACE_MODE_RXAUI;
+ break;
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII:
phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
break;
@@ -522,11 +534,14 @@ static int aqr107_config_init(struct phy
/* Check that the PHY interface type is compatible */
if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
+ phydev->interface != PHY_INTERFACE_MODE_1000BASEKX &&
phydev->interface != PHY_INTERFACE_MODE_2500BASEX &&
phydev->interface != PHY_INTERFACE_MODE_XGMII &&
phydev->interface != PHY_INTERFACE_MODE_USXGMII &&
phydev->interface != PHY_INTERFACE_MODE_10GKR &&
- phydev->interface != PHY_INTERFACE_MODE_10GBASER)
+ phydev->interface != PHY_INTERFACE_MODE_10GBASER &&
+ phydev->interface != PHY_INTERFACE_MODE_XAUI &&
+ phydev->interface != PHY_INTERFACE_MODE_RXAUI)
return -ENODEV;
WARN(phydev->interface == PHY_INTERFACE_MODE_XGMII,

View File

@ -0,0 +1,148 @@
From 3c42563b30417afc8855a3b4c1b38c2f36f78657 Mon Sep 17 00:00:00 2001
From: Sean Anderson <sean.anderson@seco.com>
Date: Tue, 20 Sep 2022 18:12:35 -0400
Subject: [PATCH] net: phy: aquantia: Add support for rate matching
This adds support for rate matching for phys similar to the AQR107. We
assume that all phys using aqr107_read_status support rate matching.
However, it could be possible to determine support based on the firmware
revision if there are phys discovered which do not support rate
matching. However, as rate matching is advertised in the datasheets for
these phys, I suspect it is supported most boards.
Despite the name, the "config" registers are updated with the current
rate matching method (if any). Because they appear to be updated
automatically, I don't know if these registers can be used to disable
rate matching.
Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/aquantia_main.c | 51 ++++++++++++++++++++++++++++++---
1 file changed, 47 insertions(+), 4 deletions(-)
--- a/drivers/net/phy/aquantia_main.c
+++ b/drivers/net/phy/aquantia_main.c
@@ -97,6 +97,19 @@
#define VEND1_GLOBAL_GEN_STAT2 0xc831
#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15)
+/* The following registers all have similar layouts; first the registers... */
+#define VEND1_GLOBAL_CFG_10M 0x0310
+#define VEND1_GLOBAL_CFG_100M 0x031b
+#define VEND1_GLOBAL_CFG_1G 0x031c
+#define VEND1_GLOBAL_CFG_2_5G 0x031d
+#define VEND1_GLOBAL_CFG_5G 0x031e
+#define VEND1_GLOBAL_CFG_10G 0x031f
+/* ...and now the fields */
+#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7)
+#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0
+#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1
+#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2
+
#define VEND1_GLOBAL_RSVD_STAT1 0xc885
#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4)
#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0)
@@ -347,40 +360,57 @@ static int aqr_read_status(struct phy_de
static int aqr107_read_rate(struct phy_device *phydev)
{
+ u32 config_reg;
int val;
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1);
if (val < 0)
return val;
+ if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX)
+ phydev->duplex = DUPLEX_FULL;
+ else
+ phydev->duplex = DUPLEX_HALF;
+
switch (FIELD_GET(MDIO_AN_TX_VEND_STATUS1_RATE_MASK, val)) {
case MDIO_AN_TX_VEND_STATUS1_10BASET:
phydev->speed = SPEED_10;
+ config_reg = VEND1_GLOBAL_CFG_10M;
break;
case MDIO_AN_TX_VEND_STATUS1_100BASETX:
phydev->speed = SPEED_100;
+ config_reg = VEND1_GLOBAL_CFG_100M;
break;
case MDIO_AN_TX_VEND_STATUS1_1000BASET:
phydev->speed = SPEED_1000;
+ config_reg = VEND1_GLOBAL_CFG_1G;
break;
case MDIO_AN_TX_VEND_STATUS1_2500BASET:
phydev->speed = SPEED_2500;
+ config_reg = VEND1_GLOBAL_CFG_2_5G;
break;
case MDIO_AN_TX_VEND_STATUS1_5000BASET:
phydev->speed = SPEED_5000;
+ config_reg = VEND1_GLOBAL_CFG_5G;
break;
case MDIO_AN_TX_VEND_STATUS1_10GBASET:
phydev->speed = SPEED_10000;
+ config_reg = VEND1_GLOBAL_CFG_10G;
break;
default:
phydev->speed = SPEED_UNKNOWN;
- break;
+ return 0;
}
- if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX)
- phydev->duplex = DUPLEX_FULL;
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, config_reg);
+ if (val < 0)
+ return val;
+
+ if (FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val) ==
+ VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE)
+ phydev->rate_matching = RATE_MATCH_PAUSE;
else
- phydev->duplex = DUPLEX_HALF;
+ phydev->rate_matching = RATE_MATCH_NONE;
return 0;
}
@@ -647,6 +677,16 @@ static int aqr107_wait_processor_intensi
return 0;
}
+static int aqr107_get_rate_matching(struct phy_device *phydev,
+ phy_interface_t iface)
+{
+ if (iface == PHY_INTERFACE_MODE_10GBASER ||
+ iface == PHY_INTERFACE_MODE_2500BASEX ||
+ iface == PHY_INTERFACE_MODE_NA)
+ return RATE_MATCH_PAUSE;
+ return RATE_MATCH_NONE;
+}
+
static int aqr107_suspend(struct phy_device *phydev)
{
int err;
@@ -720,6 +760,7 @@ static struct phy_driver aqr_driver[] =
PHY_ID_MATCH_MODEL(PHY_ID_AQR107),
.name = "Aquantia AQR107",
.probe = aqr107_probe,
+ .get_rate_matching = aqr107_get_rate_matching,
.config_init = aqr107_config_init,
.config_aneg = aqr_config_aneg,
.config_intr = aqr_config_intr,
@@ -738,6 +779,7 @@ static struct phy_driver aqr_driver[] =
PHY_ID_MATCH_MODEL(PHY_ID_AQCS109),
.name = "Aquantia AQCS109",
.probe = aqr107_probe,
+ .get_rate_matching = aqr107_get_rate_matching,
.config_init = aqcs109_config_init,
.config_aneg = aqr_config_aneg,
.config_intr = aqr_config_intr,
@@ -764,6 +806,7 @@ static struct phy_driver aqr_driver[] =
PHY_ID_MATCH_MODEL(PHY_ID_AQR113C),
.name = "Aquantia AQR113C",
.probe = aqr107_probe,
+ .get_rate_matching = aqr107_get_rate_matching,
.config_init = aqr107_config_init,
.config_aneg = aqr_config_aneg,
.config_intr = aqr_config_intr,

View File

@ -0,0 +1,183 @@
From e1fbfa4a995d42e02e22b0dff2f8b4fdee1504b3 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Tue, 14 Nov 2023 15:08:42 +0100
Subject: [PATCH 2/3] net: phy: aquantia: move MMD_VEND define to header
Move MMD_VEND define to header to clean things up and in preparation for
firmware loading support that require some define placed in
aquantia_main.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/aquantia/aquantia.h | 69 +++++++++++++++++++++++
drivers/net/phy/aquantia/aquantia_hwmon.c | 14 -----
drivers/net/phy/aquantia/aquantia_main.c | 55 ------------------
3 files changed, 69 insertions(+), 69 deletions(-)
--- a/drivers/net/phy/aquantia/aquantia.h
+++ b/drivers/net/phy/aquantia/aquantia.h
@@ -9,6 +9,75 @@
#include <linux/device.h>
#include <linux/phy.h>
+/* Vendor specific 1, MDIO_MMD_VEND1 */
+#define VEND1_GLOBAL_FW_ID 0x0020
+#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8)
+#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0)
+
+/* The following registers all have similar layouts; first the registers... */
+#define VEND1_GLOBAL_CFG_10M 0x0310
+#define VEND1_GLOBAL_CFG_100M 0x031b
+#define VEND1_GLOBAL_CFG_1G 0x031c
+#define VEND1_GLOBAL_CFG_2_5G 0x031d
+#define VEND1_GLOBAL_CFG_5G 0x031e
+#define VEND1_GLOBAL_CFG_10G 0x031f
+/* ...and now the fields */
+#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7)
+#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0
+#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1
+#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2
+
+/* Vendor specific 1, MDIO_MMD_VEND2 */
+#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421
+#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422
+#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423
+#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424
+#define VEND1_THERMAL_STAT1 0xc820
+#define VEND1_THERMAL_STAT2 0xc821
+#define VEND1_THERMAL_STAT2_VALID BIT(0)
+#define VEND1_GENERAL_STAT1 0xc830
+#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14)
+#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13)
+#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12)
+#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11)
+
+#define VEND1_GLOBAL_GEN_STAT2 0xc831
+#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15)
+
+#define VEND1_GLOBAL_RSVD_STAT1 0xc885
+#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4)
+#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0)
+
+#define VEND1_GLOBAL_RSVD_STAT9 0xc88d
+#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0)
+#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23
+
+#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00
+#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01
+
+#define VEND1_GLOBAL_INT_STD_MASK 0xff00
+#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15)
+#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14)
+#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13)
+#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12)
+#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11)
+#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10)
+#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9)
+#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8)
+#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7)
+#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6)
+#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0)
+
+#define VEND1_GLOBAL_INT_VEND_MASK 0xff01
+#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15)
+#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14)
+#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13)
+#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12)
+#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11)
+#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2)
+#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1)
+#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0)
+
#if IS_REACHABLE(CONFIG_HWMON)
int aqr_hwmon_probe(struct phy_device *phydev);
#else
--- a/drivers/net/phy/aquantia/aquantia_hwmon.c
+++ b/drivers/net/phy/aquantia/aquantia_hwmon.c
@@ -13,20 +13,6 @@
#include "aquantia.h"
-/* Vendor specific 1, MDIO_MMD_VEND2 */
-#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421
-#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422
-#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423
-#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424
-#define VEND1_THERMAL_STAT1 0xc820
-#define VEND1_THERMAL_STAT2 0xc821
-#define VEND1_THERMAL_STAT2_VALID BIT(0)
-#define VEND1_GENERAL_STAT1 0xc830
-#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14)
-#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13)
-#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12)
-#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11)
-
#if IS_REACHABLE(CONFIG_HWMON)
static umode_t aqr_hwmon_is_visible(const void *data,
--- a/drivers/net/phy/aquantia/aquantia_main.c
+++ b/drivers/net/phy/aquantia/aquantia_main.c
@@ -89,61 +89,6 @@
#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a
#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b
-/* Vendor specific 1, MDIO_MMD_VEND1 */
-#define VEND1_GLOBAL_FW_ID 0x0020
-#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8)
-#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0)
-
-#define VEND1_GLOBAL_GEN_STAT2 0xc831
-#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15)
-
-/* The following registers all have similar layouts; first the registers... */
-#define VEND1_GLOBAL_CFG_10M 0x0310
-#define VEND1_GLOBAL_CFG_100M 0x031b
-#define VEND1_GLOBAL_CFG_1G 0x031c
-#define VEND1_GLOBAL_CFG_2_5G 0x031d
-#define VEND1_GLOBAL_CFG_5G 0x031e
-#define VEND1_GLOBAL_CFG_10G 0x031f
-/* ...and now the fields */
-#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7)
-#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0
-#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1
-#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2
-
-#define VEND1_GLOBAL_RSVD_STAT1 0xc885
-#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4)
-#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0)
-
-#define VEND1_GLOBAL_RSVD_STAT9 0xc88d
-#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0)
-#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23
-
-#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00
-#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01
-
-#define VEND1_GLOBAL_INT_STD_MASK 0xff00
-#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15)
-#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14)
-#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13)
-#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12)
-#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11)
-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10)
-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9)
-#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8)
-#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7)
-#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6)
-#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0)
-
-#define VEND1_GLOBAL_INT_VEND_MASK 0xff01
-#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15)
-#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14)
-#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13)
-#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12)
-#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11)
-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2)
-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1)
-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0)
-
/* Sleep and timeout for checking if the Processor-Intensive
* MDIO operation is finished
*/

View File

@ -0,0 +1,504 @@
From e93984ebc1c82bd34f7a1b3391efaceee0a8ae96 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Tue, 14 Nov 2023 15:08:43 +0100
Subject: [PATCH 3/3] net: phy: aquantia: add firmware load support
Aquantia PHY-s require firmware to be loaded before they start operating.
It can be automatically loaded in case when there is a SPI-NOR connected
to Aquantia PHY-s or can be loaded from the host via MDIO.
This patch adds support for loading the firmware via MDIO as in most cases
there is no SPI-NOR being used to save on cost.
Firmware loading code itself is ported from mainline U-boot with cleanups.
The firmware has mixed values both in big and little endian.
PHY core itself is big-endian but it expects values to be in little-endian.
The firmware is little-endian but CRC-16 value for it is stored at the end
of firmware in big-endian.
It seems the PHY does the conversion internally from firmware that is
little-endian to the PHY that is big-endian on using the mailbox
but mailbox returns a big-endian CRC-16 to verify the written data
integrity.
Co-developed-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: Robert Marko <robimarko@gmail.com>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/phy/aquantia/Kconfig | 1 +
drivers/net/phy/aquantia/Makefile | 2 +-
drivers/net/phy/aquantia/aquantia.h | 32 ++
drivers/net/phy/aquantia/aquantia_firmware.c | 370 +++++++++++++++++++
drivers/net/phy/aquantia/aquantia_main.c | 6 +
5 files changed, 410 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/phy/aquantia/aquantia_firmware.c
--- a/drivers/net/phy/aquantia/Kconfig
+++ b/drivers/net/phy/aquantia/Kconfig
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
config AQUANTIA_PHY
tristate "Aquantia PHYs"
+ select CRC_CCITT
help
Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405
--- a/drivers/net/phy/aquantia/Makefile
+++ b/drivers/net/phy/aquantia/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-aquantia-objs += aquantia_main.o
+aquantia-objs += aquantia_main.o aquantia_firmware.o
ifdef CONFIG_HWMON
aquantia-objs += aquantia_hwmon.o
endif
--- a/drivers/net/phy/aquantia/aquantia.h
+++ b/drivers/net/phy/aquantia/aquantia.h
@@ -10,10 +10,35 @@
#include <linux/phy.h>
/* Vendor specific 1, MDIO_MMD_VEND1 */
+#define VEND1_GLOBAL_SC 0x0
+#define VEND1_GLOBAL_SC_SOFT_RESET BIT(15)
+#define VEND1_GLOBAL_SC_LOW_POWER BIT(11)
+
#define VEND1_GLOBAL_FW_ID 0x0020
#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8)
#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE1 0x0200
+#define VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE BIT(15)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE BIT(14)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET BIT(12)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE1_BUSY BIT(8)
+
+#define VEND1_GLOBAL_MAILBOX_INTERFACE2 0x0201
+#define VEND1_GLOBAL_MAILBOX_INTERFACE3 0x0202
+#define VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR_MASK GENMASK(15, 0)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR_MASK, (u16)((x) >> 16))
+#define VEND1_GLOBAL_MAILBOX_INTERFACE4 0x0203
+#define VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR_MASK GENMASK(15, 2)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR_MASK, (u16)(x))
+
+#define VEND1_GLOBAL_MAILBOX_INTERFACE5 0x0204
+#define VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA_MASK GENMASK(15, 0)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA_MASK, (u16)((x) >> 16))
+#define VEND1_GLOBAL_MAILBOX_INTERFACE6 0x0205
+#define VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA_MASK GENMASK(15, 0)
+#define VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA_MASK, (u16)(x))
+
/* The following registers all have similar layouts; first the registers... */
#define VEND1_GLOBAL_CFG_10M 0x0310
#define VEND1_GLOBAL_CFG_100M 0x031b
@@ -28,6 +53,11 @@
#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2
/* Vendor specific 1, MDIO_MMD_VEND2 */
+#define VEND1_GLOBAL_CONTROL2 0xc001
+#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_RST BIT(15)
+#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD BIT(6)
+#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL BIT(0)
+
#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421
#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422
#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423
@@ -83,3 +113,5 @@ int aqr_hwmon_probe(struct phy_device *p
#else
static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; }
#endif
+
+int aqr_firmware_load(struct phy_device *phydev);
--- /dev/null
+++ b/drivers/net/phy/aquantia/aquantia_firmware.c
@@ -0,0 +1,370 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bitfield.h>
+#include <linux/of.h>
+#include <linux/firmware.h>
+#include <linux/crc-ccitt.h>
+#include <linux/nvmem-consumer.h>
+
+#include <asm/unaligned.h>
+
+#include "aquantia.h"
+
+#define UP_RESET_SLEEP 100
+
+/* addresses of memory segments in the phy */
+#define DRAM_BASE_ADDR 0x3FFE0000
+#define IRAM_BASE_ADDR 0x40000000
+
+/* firmware image format constants */
+#define VERSION_STRING_SIZE 0x40
+#define VERSION_STRING_OFFSET 0x0200
+/* primary offset is written at an offset from the start of the fw blob */
+#define PRIMARY_OFFSET_OFFSET 0x8
+/* primary offset needs to be then added to a base offset */
+#define PRIMARY_OFFSET_SHIFT 12
+#define PRIMARY_OFFSET(x) ((x) << PRIMARY_OFFSET_SHIFT)
+#define HEADER_OFFSET 0x300
+
+struct aqr_fw_header {
+ u32 padding;
+ u8 iram_offset[3];
+ u8 iram_size[3];
+ u8 dram_offset[3];
+ u8 dram_size[3];
+} __packed;
+
+enum aqr_fw_src {
+ AQR_FW_SRC_NVMEM = 0,
+ AQR_FW_SRC_FS,
+};
+
+static const char * const aqr_fw_src_string[] = {
+ [AQR_FW_SRC_NVMEM] = "NVMEM",
+ [AQR_FW_SRC_FS] = "FS",
+};
+
+/* AQR firmware doesn't have fixed offsets for iram and dram section
+ * but instead provide an header with the offset to use on reading
+ * and parsing the firmware.
+ *
+ * AQR firmware can't be trusted and each offset is validated to be
+ * not negative and be in the size of the firmware itself.
+ */
+static bool aqr_fw_validate_get(size_t size, size_t offset, size_t get_size)
+{
+ return offset + get_size <= size;
+}
+
+static int aqr_fw_get_be16(const u8 *data, size_t offset, size_t size, u16 *value)
+{
+ if (!aqr_fw_validate_get(size, offset, sizeof(u16)))
+ return -EINVAL;
+
+ *value = get_unaligned_be16(data + offset);
+
+ return 0;
+}
+
+static int aqr_fw_get_le16(const u8 *data, size_t offset, size_t size, u16 *value)
+{
+ if (!aqr_fw_validate_get(size, offset, sizeof(u16)))
+ return -EINVAL;
+
+ *value = get_unaligned_le16(data + offset);
+
+ return 0;
+}
+
+static int aqr_fw_get_le24(const u8 *data, size_t offset, size_t size, u32 *value)
+{
+ if (!aqr_fw_validate_get(size, offset, sizeof(u8) * 3))
+ return -EINVAL;
+
+ *value = get_unaligned_le24(data + offset);
+
+ return 0;
+}
+
+/* load data into the phy's memory */
+static int aqr_fw_load_memory(struct phy_device *phydev, u32 addr,
+ const u8 *data, size_t len)
+{
+ u16 crc = 0, up_crc;
+ size_t pos;
+
+ /* PHY expect addr in LE */
+ addr = (__force u32)cpu_to_le32(addr);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_GLOBAL_MAILBOX_INTERFACE1,
+ VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_GLOBAL_MAILBOX_INTERFACE3,
+ VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR(addr));
+ phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_GLOBAL_MAILBOX_INTERFACE4,
+ VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR(addr));
+
+ /* We assume and enforce the size to be word aligned.
+ * If a firmware that is not word aligned is found, please report upstream.
+ */
+ for (pos = 0; pos < len; pos += sizeof(u32)) {
+ u32 word;
+
+ /* FW data is always stored in little-endian */
+ word = get_unaligned((const u32 *)(data + pos));
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE5,
+ VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(word));
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE6,
+ VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA(word));
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE1,
+ VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE |
+ VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE);
+
+ /* calculate CRC as we load data to the mailbox.
+ * We convert word to big-endian as PHY is BE and mailbox will
+ * return a BE CRC.
+ */
+ word = (__force u32)cpu_to_be32(word);
+ crc = crc_ccitt_false(crc, (u8 *)&word, sizeof(word));
+ }
+
+ up_crc = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE2);
+ if (crc != up_crc) {
+ phydev_err(phydev, "CRC mismatch: calculated 0x%04x PHY 0x%04x\n",
+ crc, up_crc);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int aqr_fw_boot(struct phy_device *phydev, const u8 *data, size_t size,
+ enum aqr_fw_src fw_src)
+{
+ u16 calculated_crc, read_crc, read_primary_offset;
+ u32 iram_offset = 0, iram_size = 0;
+ u32 dram_offset = 0, dram_size = 0;
+ char version[VERSION_STRING_SIZE];
+ u32 primary_offset = 0;
+ int ret;
+
+ /* extract saved CRC at the end of the fw
+ * CRC is saved in big-endian as PHY is BE
+ */
+ ret = aqr_fw_get_be16(data, size - sizeof(u16), size, &read_crc);
+ if (ret) {
+ phydev_err(phydev, "bad firmware CRC in firmware\n");
+ return ret;
+ }
+ calculated_crc = crc_ccitt_false(0, data, size - sizeof(u16));
+ if (read_crc != calculated_crc) {
+ phydev_err(phydev, "bad firmware CRC: file 0x%04x calculated 0x%04x\n",
+ read_crc, calculated_crc);
+ return -EINVAL;
+ }
+
+ /* Get the primary offset to extract DRAM and IRAM sections. */
+ ret = aqr_fw_get_le16(data, PRIMARY_OFFSET_OFFSET, size, &read_primary_offset);
+ if (ret) {
+ phydev_err(phydev, "bad primary offset in firmware\n");
+ return ret;
+ }
+ primary_offset = PRIMARY_OFFSET(read_primary_offset);
+
+ /* Find the DRAM and IRAM sections within the firmware file.
+ * Make sure the fw_header is correctly in the firmware.
+ */
+ if (!aqr_fw_validate_get(size, primary_offset + HEADER_OFFSET,
+ sizeof(struct aqr_fw_header))) {
+ phydev_err(phydev, "bad fw_header in firmware\n");
+ return -EINVAL;
+ }
+
+ /* offset are in LE and values needs to be converted to cpu endian */
+ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET +
+ offsetof(struct aqr_fw_header, iram_offset),
+ size, &iram_offset);
+ if (ret) {
+ phydev_err(phydev, "bad iram offset in firmware\n");
+ return ret;
+ }
+ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET +
+ offsetof(struct aqr_fw_header, iram_size),
+ size, &iram_size);
+ if (ret) {
+ phydev_err(phydev, "invalid iram size in firmware\n");
+ return ret;
+ }
+ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET +
+ offsetof(struct aqr_fw_header, dram_offset),
+ size, &dram_offset);
+ if (ret) {
+ phydev_err(phydev, "bad dram offset in firmware\n");
+ return ret;
+ }
+ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET +
+ offsetof(struct aqr_fw_header, dram_size),
+ size, &dram_size);
+ if (ret) {
+ phydev_err(phydev, "invalid dram size in firmware\n");
+ return ret;
+ }
+
+ /* Increment the offset with the primary offset.
+ * Validate iram/dram offset and size.
+ */
+ iram_offset += primary_offset;
+ if (iram_size % sizeof(u32)) {
+ phydev_err(phydev, "iram size if not aligned to word size. Please report this upstream!\n");
+ return -EINVAL;
+ }
+ if (!aqr_fw_validate_get(size, iram_offset, iram_size)) {
+ phydev_err(phydev, "invalid iram offset for iram size\n");
+ return -EINVAL;
+ }
+
+ dram_offset += primary_offset;
+ if (dram_size % sizeof(u32)) {
+ phydev_err(phydev, "dram size if not aligned to word size. Please report this upstream!\n");
+ return -EINVAL;
+ }
+ if (!aqr_fw_validate_get(size, dram_offset, dram_size)) {
+ phydev_err(phydev, "invalid iram offset for iram size\n");
+ return -EINVAL;
+ }
+
+ phydev_dbg(phydev, "primary %d IRAM offset=%d size=%d DRAM offset=%d size=%d\n",
+ primary_offset, iram_offset, iram_size, dram_offset, dram_size);
+
+ if (!aqr_fw_validate_get(size, dram_offset + VERSION_STRING_OFFSET,
+ VERSION_STRING_SIZE)) {
+ phydev_err(phydev, "invalid version in firmware\n");
+ return -EINVAL;
+ }
+ strscpy(version, (char *)data + dram_offset + VERSION_STRING_OFFSET,
+ VERSION_STRING_SIZE);
+ if (version[0] == '\0') {
+ phydev_err(phydev, "invalid version in firmware\n");
+ return -EINVAL;
+ }
+ phydev_info(phydev, "loading firmware version '%s' from '%s'\n", version,
+ aqr_fw_src_string[fw_src]);
+
+ /* stall the microcprocessor */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2,
+ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL | VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD);
+
+ phydev_dbg(phydev, "loading DRAM 0x%08x from offset=%d size=%d\n",
+ DRAM_BASE_ADDR, dram_offset, dram_size);
+ ret = aqr_fw_load_memory(phydev, DRAM_BASE_ADDR, data + dram_offset,
+ dram_size);
+ if (ret)
+ return ret;
+
+ phydev_dbg(phydev, "loading IRAM 0x%08x from offset=%d size=%d\n",
+ IRAM_BASE_ADDR, iram_offset, iram_size);
+ ret = aqr_fw_load_memory(phydev, IRAM_BASE_ADDR, data + iram_offset,
+ iram_size);
+ if (ret)
+ return ret;
+
+ /* make sure soft reset and low power mode are clear */
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_SC,
+ VEND1_GLOBAL_SC_SOFT_RESET | VEND1_GLOBAL_SC_LOW_POWER);
+
+ /* Release the microprocessor. UP_RESET must be held for 100 usec. */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2,
+ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL |
+ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD |
+ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_RST);
+ usleep_range(UP_RESET_SLEEP, UP_RESET_SLEEP * 2);
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2,
+ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD);
+
+ return 0;
+}
+
+static int aqr_firmware_load_nvmem(struct phy_device *phydev)
+{
+ struct nvmem_cell *cell;
+ size_t size;
+ u8 *buf;
+ int ret;
+
+ cell = nvmem_cell_get(&phydev->mdio.dev, "firmware");
+ if (IS_ERR(cell))
+ return PTR_ERR(cell);
+
+ buf = nvmem_cell_read(cell, &size);
+ if (IS_ERR(buf)) {
+ ret = PTR_ERR(buf);
+ goto exit;
+ }
+
+ ret = aqr_fw_boot(phydev, buf, size, AQR_FW_SRC_NVMEM);
+ if (ret)
+ phydev_err(phydev, "firmware loading failed: %d\n", ret);
+
+ kfree(buf);
+exit:
+ nvmem_cell_put(cell);
+
+ return ret;
+}
+
+static int aqr_firmware_load_fs(struct phy_device *phydev)
+{
+ struct device *dev = &phydev->mdio.dev;
+ const struct firmware *fw;
+ const char *fw_name;
+ int ret;
+
+ ret = of_property_read_string(dev->of_node, "firmware-name",
+ &fw_name);
+ if (ret)
+ return ret;
+
+ ret = request_firmware(&fw, fw_name, dev);
+ if (ret) {
+ phydev_err(phydev, "failed to find FW file %s (%d)\n",
+ fw_name, ret);
+ return ret;
+ }
+
+ ret = aqr_fw_boot(phydev, fw->data, fw->size, AQR_FW_SRC_FS);
+ if (ret)
+ phydev_err(phydev, "firmware loading failed: %d\n", ret);
+
+ release_firmware(fw);
+
+ return ret;
+}
+
+int aqr_firmware_load(struct phy_device *phydev)
+{
+ int ret;
+
+ /* Check if the firmware is not already loaded by pooling
+ * the current version returned by the PHY. If 0 is returned,
+ * no firmware is loaded.
+ */
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID);
+ if (ret > 0)
+ goto exit;
+
+ ret = aqr_firmware_load_nvmem(phydev);
+ if (!ret)
+ goto exit;
+
+ ret = aqr_firmware_load_fs(phydev);
+ if (ret)
+ return ret;
+
+exit:
+ return 0;
+}
--- a/drivers/net/phy/aquantia/aquantia_main.c
+++ b/drivers/net/phy/aquantia/aquantia_main.c
@@ -658,11 +658,17 @@ static int aqr107_resume(struct phy_devi
static int aqr107_probe(struct phy_device *phydev)
{
+ int ret;
+
phydev->priv = devm_kzalloc(&phydev->mdio.dev,
sizeof(struct aqr107_priv), GFP_KERNEL);
if (!phydev->priv)
return -ENOMEM;
+ ret = aqr_firmware_load(phydev);
+ if (ret)
+ return ret;
+
return aqr_hwmon_probe(phydev);
}

View File

@ -31,7 +31,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
F: drivers/net/phy/motorcomm.c
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -245,7 +245,7 @@ config MOTORCOMM_PHY
@@ -242,7 +242,7 @@ config MOTORCOMM_PHY
tristate "Motorcomm PHYs"
help
Enables support for Motorcomm network PHYs.

View File

@ -22,7 +22,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -245,7 +245,7 @@ config MOTORCOMM_PHY
@@ -242,7 +242,7 @@ config MOTORCOMM_PHY
tristate "Motorcomm PHYs"
help
Enables support for Motorcomm network PHYs.

View File

@ -19,7 +19,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -245,7 +245,7 @@ config MOTORCOMM_PHY
@@ -242,7 +242,7 @@ config MOTORCOMM_PHY
tristate "Motorcomm PHYs"
help
Enables support for Motorcomm network PHYs.

View File

@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -756,6 +756,18 @@ static void phylink_resolve_flow(struct
@@ -759,6 +759,18 @@ static void phylink_resolve_flow(struct
}
}
@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
static void phylink_mac_config(struct phylink *pl,
const struct phylink_link_state *state)
{
@@ -787,6 +799,7 @@ static void phylink_major_config(struct
@@ -790,6 +802,7 @@ static void phylink_major_config(struct
const struct phylink_link_state *state)
{
struct phylink_pcs *pcs = NULL;
@ -44,7 +44,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
int err;
phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
@@ -799,8 +812,12 @@ static void phylink_major_config(struct
@@ -802,8 +815,12 @@ static void phylink_major_config(struct
pcs);
return;
}
@ -57,7 +57,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
if (pl->mac_ops->mac_prepare) {
err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode,
state->interface);
@@ -814,8 +831,10 @@ static void phylink_major_config(struct
@@ -817,8 +834,10 @@ static void phylink_major_config(struct
/* If we have a new PCS, switch to the new PCS after preparing the MAC
* for the change.
*/
@ -70,7 +70,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
phylink_mac_config(pl, state);
@@ -841,6 +860,8 @@ static void phylink_major_config(struct
@@ -844,6 +863,8 @@ static void phylink_major_config(struct
phylink_err(pl, "mac_finish failed: %pe\n",
ERR_PTR(err));
}

View File

@ -27,7 +27,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -764,7 +764,7 @@ static void phylink_pcs_poll_stop(struct
@@ -767,7 +767,7 @@ static void phylink_pcs_poll_stop(struct
static void phylink_pcs_poll_start(struct phylink *pl)
{

View File

@ -35,7 +35,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
bool mac_link_dropped;
bool using_mac_select_pcs;
@@ -795,6 +800,22 @@ static void phylink_mac_pcs_an_restart(s
@@ -798,6 +803,22 @@ static void phylink_mac_pcs_an_restart(s
}
}
@ -58,7 +58,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
static void phylink_major_config(struct phylink *pl, bool restart,
const struct phylink_link_state *state)
{
@@ -832,12 +853,16 @@ static void phylink_major_config(struct
@@ -835,12 +856,16 @@ static void phylink_major_config(struct
* for the change.
*/
if (pcs_changed) {
@ -75,7 +75,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
if (pl->pcs_ops) {
err = pl->pcs_ops->pcs_config(pl->pcs, pl->cur_link_an_mode,
state->interface,
@@ -1261,6 +1286,7 @@ struct phylink *phylink_create(struct ph
@@ -1264,6 +1289,7 @@ struct phylink *phylink_create(struct ph
pl->link_config.speed = SPEED_UNKNOWN;
pl->link_config.duplex = DUPLEX_UNKNOWN;
pl->link_config.an_enabled = true;
@ -83,7 +83,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
pl->mac_ops = mac_ops;
__set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
timer_setup(&pl->link_poll, phylink_fixed_poll, 0);
@@ -1652,6 +1678,8 @@ void phylink_start(struct phylink *pl)
@@ -1655,6 +1681,8 @@ void phylink_start(struct phylink *pl)
if (pl->netdev)
netif_carrier_off(pl->netdev);
@ -92,7 +92,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
/* Apply the link configuration to the MAC when starting. This allows
* a fixed-link to start with the correct parameters, and also
* ensures that we set the appropriate advertisement for Serdes links.
@@ -1662,6 +1690,8 @@ void phylink_start(struct phylink *pl)
@@ -1665,6 +1693,8 @@ void phylink_start(struct phylink *pl)
*/
phylink_mac_initial_config(pl, true);
@ -101,7 +101,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
phylink_run_resolve(pl);
@@ -1681,16 +1711,9 @@ void phylink_start(struct phylink *pl)
@@ -1684,16 +1714,9 @@ void phylink_start(struct phylink *pl)
poll = true;
}
@ -120,7 +120,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
if (poll)
mod_timer(&pl->link_poll, jiffies + HZ);
if (pl->phydev)
@@ -1727,6 +1750,10 @@ void phylink_stop(struct phylink *pl)
@@ -1730,6 +1753,10 @@ void phylink_stop(struct phylink *pl)
}
phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED);

View File

@ -153,7 +153,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
#include <linux/linkmode.h>
#include <linux/netlink.h>
#include <linux/mdio.h>
@@ -582,6 +583,7 @@ struct macsec_ops;
@@ -590,6 +591,7 @@ struct macsec_ops;
* @phy_num_led_triggers: Number of triggers in @phy_led_triggers
* @led_link_trigger: LED trigger for link up/down
* @last_triggered: last LED trigger for link speed
@ -161,7 +161,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
* @master_slave_set: User requested master/slave configuration
* @master_slave_get: Current master/slave advertisement
* @master_slave_state: Current master/slave configuration
@@ -668,6 +670,7 @@ struct phy_device {
@@ -678,6 +680,7 @@ struct phy_device {
struct phy_led_trigger *led_link_trigger;
#endif
@ -169,7 +169,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
/*
* Interrupt number for this PHY
@@ -739,6 +742,19 @@ struct phy_tdr_config {
@@ -749,6 +752,19 @@ struct phy_tdr_config {
#define PHY_PAIR_ALL -1
/**

View File

@ -59,7 +59,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
init_data.fwnode = of_fwnode_handle(led);
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -745,15 +745,19 @@ struct phy_tdr_config {
@@ -755,15 +755,19 @@ struct phy_tdr_config {
* struct phy_led: An LED driven by the PHY
*
* @list: List of LEDs
@ -79,7 +79,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
/**
* struct phy_driver - Driver structure for a particular PHY type
*
@@ -953,6 +957,15 @@ struct phy_driver {
@@ -978,6 +982,15 @@ struct phy_driver {
int (*get_sqi)(struct phy_device *dev);
/** @get_sqi_max: Get the maximum signal quality indication */
int (*get_sqi_max)(struct phy_device *dev);

View File

@ -52,7 +52,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
init_data.fwnode = of_fwnode_handle(led);
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -966,6 +966,18 @@ struct phy_driver {
@@ -991,6 +991,18 @@ struct phy_driver {
*/
int (*led_brightness_set)(struct phy_device *dev,
u8 index, enum led_brightness value);

View File

@ -123,7 +123,7 @@ Signed-off-by: Justin Stitt <justinstitt@google.com>
#endif /* _LINUX_ETHTOOL_H */
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -1953,6 +1953,13 @@ __printf(2, 3) void ethtool_sprintf(u8 *
@@ -1954,6 +1954,13 @@ __printf(2, 3) void ethtool_sprintf(u8 *
}
EXPORT_SYMBOL(ethtool_sprintf);

View File

@ -0,0 +1,408 @@
From 7196062b64ee470b91015f3d2e82d225948258ea Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 25 Jan 2024 21:37:01 +0100
Subject: [PATCH 5/5] net: phy: at803x: add LED support for qca808x
Add LED support for QCA8081 PHY.
Documentation for this LEDs PHY is very scarce even with NDA access
to Documentation for OEMs. Only the blink pattern are documented and are
very confusing most of the time. No documentation is present about
forcing the LED on/off or to always blink.
Those settings were reversed by poking the regs and trying to find the
correct bits to trigger these modes. Some bits mode are not clear and
maybe the documentation option are not 100% correct. For the sake of LED
support the reversed option are enough to add support for current LED
APIs.
Supported HW control modes are:
- tx
- rx
- link_10
- link_100
- link_1000
- link_2500
- half_duplex
- full_duplex
Also add support for LED polarity set to set LED polarity to active
high or low. QSDK sets this value to high by default but PHY reset value
doesn't have this enabled by default.
QSDK also sets 2 additional bits but their usage is not clear, info about
this is added in the header. It was verified that for correct function
of the LED if active high is needed, only BIT 6 is needed.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/20240125203702.4552-6-ansuelsmth@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/at803x.c | 327 +++++++++++++++++++++++++++++++++++++++
1 file changed, 327 insertions(+)
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -301,6 +301,87 @@
/* Added for reference of existence but should be handled by wait_for_completion already */
#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3))
+#define QCA808X_MMD7_LED_GLOBAL 0x8073
+#define QCA808X_LED_BLINK_1 GENMASK(11, 6)
+#define QCA808X_LED_BLINK_2 GENMASK(5, 0)
+/* Values are the same for both BLINK_1 and BLINK_2 */
+#define QCA808X_LED_BLINK_FREQ_MASK GENMASK(5, 3)
+#define QCA808X_LED_BLINK_FREQ_2HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x0)
+#define QCA808X_LED_BLINK_FREQ_4HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x1)
+#define QCA808X_LED_BLINK_FREQ_8HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x2)
+#define QCA808X_LED_BLINK_FREQ_16HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x3)
+#define QCA808X_LED_BLINK_FREQ_32HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x4)
+#define QCA808X_LED_BLINK_FREQ_64HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x5)
+#define QCA808X_LED_BLINK_FREQ_128HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x6)
+#define QCA808X_LED_BLINK_FREQ_256HZ FIELD_PREP(QCA808X_LED_BLINK_FREQ_MASK, 0x7)
+#define QCA808X_LED_BLINK_DUTY_MASK GENMASK(2, 0)
+#define QCA808X_LED_BLINK_DUTY_50_50 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x0)
+#define QCA808X_LED_BLINK_DUTY_75_25 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x1)
+#define QCA808X_LED_BLINK_DUTY_25_75 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x2)
+#define QCA808X_LED_BLINK_DUTY_33_67 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x3)
+#define QCA808X_LED_BLINK_DUTY_67_33 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x4)
+#define QCA808X_LED_BLINK_DUTY_17_83 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x5)
+#define QCA808X_LED_BLINK_DUTY_83_17 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x6)
+#define QCA808X_LED_BLINK_DUTY_8_92 FIELD_PREP(QCA808X_LED_BLINK_DUTY_MASK, 0x7)
+
+#define QCA808X_MMD7_LED2_CTRL 0x8074
+#define QCA808X_MMD7_LED2_FORCE_CTRL 0x8075
+#define QCA808X_MMD7_LED1_CTRL 0x8076
+#define QCA808X_MMD7_LED1_FORCE_CTRL 0x8077
+#define QCA808X_MMD7_LED0_CTRL 0x8078
+#define QCA808X_MMD7_LED_CTRL(x) (0x8078 - ((x) * 2))
+
+/* LED hw control pattern is the same for every LED */
+#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0)
+#define QCA808X_LED_SPEED2500_ON BIT(15)
+#define QCA808X_LED_SPEED2500_BLINK BIT(14)
+/* Follow blink trigger even if duplex or speed condition doesn't match */
+#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13)
+#define QCA808X_LED_FULL_DUPLEX_ON BIT(12)
+#define QCA808X_LED_HALF_DUPLEX_ON BIT(11)
+#define QCA808X_LED_TX_BLINK BIT(10)
+#define QCA808X_LED_RX_BLINK BIT(9)
+#define QCA808X_LED_TX_ON_10MS BIT(8)
+#define QCA808X_LED_RX_ON_10MS BIT(7)
+#define QCA808X_LED_SPEED1000_ON BIT(6)
+#define QCA808X_LED_SPEED100_ON BIT(5)
+#define QCA808X_LED_SPEED10_ON BIT(4)
+#define QCA808X_LED_COLLISION_BLINK BIT(3)
+#define QCA808X_LED_SPEED1000_BLINK BIT(2)
+#define QCA808X_LED_SPEED100_BLINK BIT(1)
+#define QCA808X_LED_SPEED10_BLINK BIT(0)
+
+#define QCA808X_MMD7_LED0_FORCE_CTRL 0x8079
+#define QCA808X_MMD7_LED_FORCE_CTRL(x) (0x8079 - ((x) * 2))
+
+/* LED force ctrl is the same for every LED
+ * No documentation exist for this, not even internal one
+ * with NDA as QCOM gives only info about configuring
+ * hw control pattern rules and doesn't indicate any way
+ * to force the LED to specific mode.
+ * These define comes from reverse and testing and maybe
+ * lack of some info or some info are not entirely correct.
+ * For the basic LED control and hw control these finding
+ * are enough to support LED control in all the required APIs.
+ *
+ * On doing some comparison with implementation with qca807x,
+ * it was found that it's 1:1 equal to it and confirms all the
+ * reverse done. It was also found further specification with the
+ * force mode and the blink modes.
+ */
+#define QCA808X_LED_FORCE_EN BIT(15)
+#define QCA808X_LED_FORCE_MODE_MASK GENMASK(14, 13)
+#define QCA808X_LED_FORCE_BLINK_1 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x3)
+#define QCA808X_LED_FORCE_BLINK_2 FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x2)
+#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x1)
+#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MODE_MASK, 0x0)
+
+#define QCA808X_MMD7_LED_POLARITY_CTRL 0x901a
+/* QSDK sets by default 0x46 to this reg that sets BIT 6 for
+ * LED to active high. It's not clear what BIT 3 and BIT 4 does.
+ */
+#define QCA808X_LED_ACTIVE_HIGH BIT(6)
+
/* QCA808X 1G chip type */
#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d
#define QCA808X_PHY_CHIP_TYPE_1G BIT(0)
@@ -346,6 +427,7 @@ struct at803x_priv {
struct regulator_dev *vddio_rdev;
struct regulator_dev *vddh_rdev;
u64 stats[ARRAY_SIZE(qca83xx_hw_stats)];
+ int led_polarity_mode;
};
struct at803x_context {
@@ -706,6 +788,9 @@ static int at803x_probe(struct phy_devic
if (!priv)
return -ENOMEM;
+ /* Init LED polarity mode to -1 */
+ priv->led_polarity_mode = -1;
+
phydev->priv = priv;
ret = at803x_parse_dt(phydev);
@@ -2235,6 +2320,242 @@ static void qca808x_link_change_notify(s
phydev->link ? QCA8081_PHY_FIFO_RSTN : 0);
}
+static int qca808x_led_parse_netdev(struct phy_device *phydev, unsigned long rules,
+ u16 *offload_trigger)
+{
+ /* Parsing specific to netdev trigger */
+ if (test_bit(TRIGGER_NETDEV_TX, &rules))
+ *offload_trigger |= QCA808X_LED_TX_BLINK;
+ if (test_bit(TRIGGER_NETDEV_RX, &rules))
+ *offload_trigger |= QCA808X_LED_RX_BLINK;
+ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules))
+ *offload_trigger |= QCA808X_LED_SPEED10_ON;
+ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules))
+ *offload_trigger |= QCA808X_LED_SPEED100_ON;
+ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules))
+ *offload_trigger |= QCA808X_LED_SPEED1000_ON;
+ if (test_bit(TRIGGER_NETDEV_LINK_2500, &rules))
+ *offload_trigger |= QCA808X_LED_SPEED2500_ON;
+ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules))
+ *offload_trigger |= QCA808X_LED_HALF_DUPLEX_ON;
+ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules))
+ *offload_trigger |= QCA808X_LED_FULL_DUPLEX_ON;
+
+ if (rules && !*offload_trigger)
+ return -EOPNOTSUPP;
+
+ /* Enable BLINK_CHECK_BYPASS by default to make the LED
+ * blink even with duplex or speed mode not enabled.
+ */
+ *offload_trigger |= QCA808X_LED_BLINK_CHECK_BYPASS;
+
+ return 0;
+}
+
+static int qca808x_led_hw_control_enable(struct phy_device *phydev, u8 index)
+{
+ u16 reg;
+
+ if (index > 2)
+ return -EINVAL;
+
+ reg = QCA808X_MMD7_LED_FORCE_CTRL(index);
+
+ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg,
+ QCA808X_LED_FORCE_EN);
+}
+
+static int qca808x_led_hw_is_supported(struct phy_device *phydev, u8 index,
+ unsigned long rules)
+{
+ u16 offload_trigger = 0;
+
+ if (index > 2)
+ return -EINVAL;
+
+ return qca808x_led_parse_netdev(phydev, rules, &offload_trigger);
+}
+
+static int qca808x_led_hw_control_set(struct phy_device *phydev, u8 index,
+ unsigned long rules)
+{
+ u16 reg, offload_trigger = 0;
+ int ret;
+
+ if (index > 2)
+ return -EINVAL;
+
+ reg = QCA808X_MMD7_LED_CTRL(index);
+
+ ret = qca808x_led_parse_netdev(phydev, rules, &offload_trigger);
+ if (ret)
+ return ret;
+
+ ret = qca808x_led_hw_control_enable(phydev, index);
+ if (ret)
+ return ret;
+
+ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg,
+ QCA808X_LED_PATTERN_MASK,
+ offload_trigger);
+}
+
+static bool qca808x_led_hw_control_status(struct phy_device *phydev, u8 index)
+{
+ u16 reg;
+ int val;
+
+ if (index > 2)
+ return false;
+
+ reg = QCA808X_MMD7_LED_FORCE_CTRL(index);
+
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg);
+
+ return !(val & QCA808X_LED_FORCE_EN);
+}
+
+static int qca808x_led_hw_control_get(struct phy_device *phydev, u8 index,
+ unsigned long *rules)
+{
+ u16 reg;
+ int val;
+
+ if (index > 2)
+ return -EINVAL;
+
+ /* Check if we have hw control enabled */
+ if (qca808x_led_hw_control_status(phydev, index))
+ return -EINVAL;
+
+ reg = QCA808X_MMD7_LED_CTRL(index);
+
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, reg);
+ if (val & QCA808X_LED_TX_BLINK)
+ set_bit(TRIGGER_NETDEV_TX, rules);
+ if (val & QCA808X_LED_RX_BLINK)
+ set_bit(TRIGGER_NETDEV_RX, rules);
+ if (val & QCA808X_LED_SPEED10_ON)
+ set_bit(TRIGGER_NETDEV_LINK_10, rules);
+ if (val & QCA808X_LED_SPEED100_ON)
+ set_bit(TRIGGER_NETDEV_LINK_100, rules);
+ if (val & QCA808X_LED_SPEED1000_ON)
+ set_bit(TRIGGER_NETDEV_LINK_1000, rules);
+ if (val & QCA808X_LED_SPEED2500_ON)
+ set_bit(TRIGGER_NETDEV_LINK_2500, rules);
+ if (val & QCA808X_LED_HALF_DUPLEX_ON)
+ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules);
+ if (val & QCA808X_LED_FULL_DUPLEX_ON)
+ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules);
+
+ return 0;
+}
+
+static int qca808x_led_hw_control_reset(struct phy_device *phydev, u8 index)
+{
+ u16 reg;
+
+ if (index > 2)
+ return -EINVAL;
+
+ reg = QCA808X_MMD7_LED_CTRL(index);
+
+ return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg,
+ QCA808X_LED_PATTERN_MASK);
+}
+
+static int qca808x_led_brightness_set(struct phy_device *phydev,
+ u8 index, enum led_brightness value)
+{
+ u16 reg;
+ int ret;
+
+ if (index > 2)
+ return -EINVAL;
+
+ if (!value) {
+ ret = qca808x_led_hw_control_reset(phydev, index);
+ if (ret)
+ return ret;
+ }
+
+ reg = QCA808X_MMD7_LED_FORCE_CTRL(index);
+
+ return phy_modify_mmd(phydev, MDIO_MMD_AN, reg,
+ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK,
+ QCA808X_LED_FORCE_EN | value ? QCA808X_LED_FORCE_ON :
+ QCA808X_LED_FORCE_OFF);
+}
+
+static int qca808x_led_blink_set(struct phy_device *phydev, u8 index,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ int ret;
+ u16 reg;
+
+ if (index > 2)
+ return -EINVAL;
+
+ reg = QCA808X_MMD7_LED_FORCE_CTRL(index);
+
+ /* Set blink to 50% off, 50% on at 4Hz by default */
+ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_GLOBAL,
+ QCA808X_LED_BLINK_FREQ_MASK | QCA808X_LED_BLINK_DUTY_MASK,
+ QCA808X_LED_BLINK_FREQ_4HZ | QCA808X_LED_BLINK_DUTY_50_50);
+ if (ret)
+ return ret;
+
+ /* We use BLINK_1 for normal blinking */
+ ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg,
+ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_MODE_MASK,
+ QCA808X_LED_FORCE_EN | QCA808X_LED_FORCE_BLINK_1);
+ if (ret)
+ return ret;
+
+ /* We set blink to 4Hz, aka 250ms */
+ *delay_on = 250 / 2;
+ *delay_off = 250 / 2;
+
+ return 0;
+}
+
+static int qca808x_led_polarity_set(struct phy_device *phydev, int index,
+ unsigned long modes)
+{
+ struct at803x_priv *priv = phydev->priv;
+ bool active_low = false;
+ u32 mode;
+
+ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
+ switch (mode) {
+ case PHY_LED_ACTIVE_LOW:
+ active_low = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ /* PHY polarity is global and can't be set per LED.
+ * To detect this, check if last requested polarity mode
+ * match the new one.
+ */
+ if (priv->led_polarity_mode >= 0 &&
+ priv->led_polarity_mode != active_low) {
+ phydev_err(phydev, "PHY polarity is global. Mismatched polarity on different LED\n");
+ return -EINVAL;
+ }
+
+ /* Save the last PHY polarity mode */
+ priv->led_polarity_mode = active_low;
+
+ return phy_modify_mmd(phydev, MDIO_MMD_AN,
+ QCA808X_MMD7_LED_POLARITY_CTRL,
+ QCA808X_LED_ACTIVE_HIGH,
+ active_low ? 0 : QCA808X_LED_ACTIVE_HIGH);
+}
+
static struct phy_driver at803x_driver[] = {
{
/* Qualcomm Atheros AR8035 */
@@ -2411,6 +2732,12 @@ static struct phy_driver at803x_driver[]
.cable_test_start = qca808x_cable_test_start,
.cable_test_get_status = qca808x_cable_test_get_status,
.link_change_notify = qca808x_link_change_notify,
+ .led_brightness_set = qca808x_led_brightness_set,
+ .led_blink_set = qca808x_led_blink_set,
+ .led_hw_is_supported = qca808x_led_hw_is_supported,
+ .led_hw_control_set = qca808x_led_hw_control_set,
+ .led_hw_control_get = qca808x_led_hw_control_get,
+ .led_polarity_set = qca808x_led_polarity_set,
}, };
module_phy_driver(at803x_driver);

View File

@ -0,0 +1,111 @@
From bc8e1da69a68d9871773b657d18400a7941cbdef Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Tue, 28 Nov 2023 04:00:10 +0000
Subject: [PATCH] leds: trigger: netdev: Extend speeds up to 10G
Add 2.5G, 5G and 10G as available speeds to the netdev LED trigger.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/99e7d3304c6bba7f4863a4a80764a869855f2085.1701143925.git.daniel@makrotopia.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/leds/trigger/ledtrig-netdev.c | 32 ++++++++++++++++++++++++++-
include/linux/leds.h | 3 +++
2 files changed, 34 insertions(+), 1 deletion(-)
--- a/drivers/leds/trigger/ledtrig-netdev.c
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -99,6 +99,18 @@ static void set_baseline_state(struct le
trigger_data->link_speed == SPEED_1000)
blink_on = true;
+ if (test_bit(TRIGGER_NETDEV_LINK_2500, &trigger_data->mode) &&
+ trigger_data->link_speed == SPEED_2500)
+ blink_on = true;
+
+ if (test_bit(TRIGGER_NETDEV_LINK_5000, &trigger_data->mode) &&
+ trigger_data->link_speed == SPEED_5000)
+ blink_on = true;
+
+ if (test_bit(TRIGGER_NETDEV_LINK_10000, &trigger_data->mode) &&
+ trigger_data->link_speed == SPEED_10000)
+ blink_on = true;
+
if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) &&
trigger_data->duplex == DUPLEX_HALF)
blink_on = true;
@@ -286,6 +298,9 @@ static ssize_t netdev_led_attr_show(stru
case TRIGGER_NETDEV_LINK_10:
case TRIGGER_NETDEV_LINK_100:
case TRIGGER_NETDEV_LINK_1000:
+ case TRIGGER_NETDEV_LINK_2500:
+ case TRIGGER_NETDEV_LINK_5000:
+ case TRIGGER_NETDEV_LINK_10000:
case TRIGGER_NETDEV_HALF_DUPLEX:
case TRIGGER_NETDEV_FULL_DUPLEX:
case TRIGGER_NETDEV_TX:
@@ -316,6 +331,9 @@ static ssize_t netdev_led_attr_store(str
case TRIGGER_NETDEV_LINK_10:
case TRIGGER_NETDEV_LINK_100:
case TRIGGER_NETDEV_LINK_1000:
+ case TRIGGER_NETDEV_LINK_2500:
+ case TRIGGER_NETDEV_LINK_5000:
+ case TRIGGER_NETDEV_LINK_10000:
case TRIGGER_NETDEV_HALF_DUPLEX:
case TRIGGER_NETDEV_FULL_DUPLEX:
case TRIGGER_NETDEV_TX:
@@ -334,7 +352,10 @@ static ssize_t netdev_led_attr_store(str
if (test_bit(TRIGGER_NETDEV_LINK, &mode) &&
(test_bit(TRIGGER_NETDEV_LINK_10, &mode) ||
test_bit(TRIGGER_NETDEV_LINK_100, &mode) ||
- test_bit(TRIGGER_NETDEV_LINK_1000, &mode)))
+ test_bit(TRIGGER_NETDEV_LINK_1000, &mode) ||
+ test_bit(TRIGGER_NETDEV_LINK_2500, &mode) ||
+ test_bit(TRIGGER_NETDEV_LINK_5000, &mode) ||
+ test_bit(TRIGGER_NETDEV_LINK_10000, &mode)))
return -EINVAL;
cancel_delayed_work_sync(&trigger_data->work);
@@ -364,6 +385,9 @@ DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETD
DEFINE_NETDEV_TRIGGER(link_10, TRIGGER_NETDEV_LINK_10);
DEFINE_NETDEV_TRIGGER(link_100, TRIGGER_NETDEV_LINK_100);
DEFINE_NETDEV_TRIGGER(link_1000, TRIGGER_NETDEV_LINK_1000);
+DEFINE_NETDEV_TRIGGER(link_2500, TRIGGER_NETDEV_LINK_2500);
+DEFINE_NETDEV_TRIGGER(link_5000, TRIGGER_NETDEV_LINK_5000);
+DEFINE_NETDEV_TRIGGER(link_10000, TRIGGER_NETDEV_LINK_10000);
DEFINE_NETDEV_TRIGGER(half_duplex, TRIGGER_NETDEV_HALF_DUPLEX);
DEFINE_NETDEV_TRIGGER(full_duplex, TRIGGER_NETDEV_FULL_DUPLEX);
DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX);
@@ -422,6 +446,9 @@ static struct attribute *netdev_trig_att
&dev_attr_link_10.attr,
&dev_attr_link_100.attr,
&dev_attr_link_1000.attr,
+ &dev_attr_link_2500.attr,
+ &dev_attr_link_5000.attr,
+ &dev_attr_link_10000.attr,
&dev_attr_full_duplex.attr,
&dev_attr_half_duplex.attr,
&dev_attr_rx.attr,
@@ -519,6 +546,9 @@ static void netdev_trig_work(struct work
test_bit(TRIGGER_NETDEV_LINK_10, &trigger_data->mode) ||
test_bit(TRIGGER_NETDEV_LINK_100, &trigger_data->mode) ||
test_bit(TRIGGER_NETDEV_LINK_1000, &trigger_data->mode) ||
+ test_bit(TRIGGER_NETDEV_LINK_2500, &trigger_data->mode) ||
+ test_bit(TRIGGER_NETDEV_LINK_5000, &trigger_data->mode) ||
+ test_bit(TRIGGER_NETDEV_LINK_10000, &trigger_data->mode) ||
test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &trigger_data->mode) ||
test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &trigger_data->mode);
interval = jiffies_to_msecs(
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -533,6 +533,9 @@ enum led_trigger_netdev_modes {
TRIGGER_NETDEV_LINK_10,
TRIGGER_NETDEV_LINK_100,
TRIGGER_NETDEV_LINK_1000,
+ TRIGGER_NETDEV_LINK_2500,
+ TRIGGER_NETDEV_LINK_5000,
+ TRIGGER_NETDEV_LINK_10000,
TRIGGER_NETDEV_HALF_DUPLEX,
TRIGGER_NETDEV_FULL_DUPLEX,
TRIGGER_NETDEV_TX,

View File

@ -0,0 +1,98 @@
From 7ae215ee7bb855f13c80565470fc7f67db4ba82f Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 25 Jan 2024 21:36:59 +0100
Subject: [PATCH 3/5] net: phy: add support for PHY LEDs polarity modes
Add support for PHY LEDs polarity modes. Some PHY require LED to be set
to active low to be turned ON. Adds support for this by declaring
active-low property in DT.
PHY driver needs to declare .led_polarity_set() to configure LED
polarity modes. Function will pass the index with the LED index and a
bitmap with all the required modes to set.
Current supported modes are:
- active-low with the flag PHY_LED_ACTIVE_LOW. LED is set to active-low
to turn it ON.
- inactive-high-impedance with the flag PHY_LED_INACTIVE_HIGH_IMPEDANCE.
LED is set to high impedance to turn it OFF.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/20240125203702.4552-4-ansuelsmth@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/phy_device.c | 16 ++++++++++++++++
include/linux/phy.h | 22 ++++++++++++++++++++++
2 files changed, 38 insertions(+)
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -3034,6 +3034,7 @@ static int of_phy_led(struct phy_device
struct device *dev = &phydev->mdio.dev;
struct led_init_data init_data = {};
struct led_classdev *cdev;
+ unsigned long modes = 0;
struct phy_led *phyled;
u32 index;
int err;
@@ -3051,6 +3052,21 @@ static int of_phy_led(struct phy_device
if (index > U8_MAX)
return -EINVAL;
+ if (of_property_read_bool(led, "active-low"))
+ set_bit(PHY_LED_ACTIVE_LOW, &modes);
+ if (of_property_read_bool(led, "inactive-high-impedance"))
+ set_bit(PHY_LED_INACTIVE_HIGH_IMPEDANCE, &modes);
+
+ if (modes) {
+ /* Return error if asked to set polarity modes but not supported */
+ if (!phydev->drv->led_polarity_set)
+ return -EINVAL;
+
+ err = phydev->drv->led_polarity_set(phydev, index, modes);
+ if (err)
+ return err;
+ }
+
phyled->index = index;
if (phydev->drv->led_brightness_set)
cdev->brightness_set_blocking = phy_led_set_brightness;
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -787,6 +787,15 @@ struct phy_led {
#define to_phy_led(d) container_of(d, struct phy_led, led_cdev)
+/* Modes for PHY LED configuration */
+enum phy_led_modes {
+ PHY_LED_ACTIVE_LOW = 0,
+ PHY_LED_INACTIVE_HIGH_IMPEDANCE = 1,
+
+ /* keep it last */
+ __PHY_LED_MODES_NUM,
+};
+
/**
* struct phy_driver - Driver structure for a particular PHY type
*
@@ -1055,6 +1064,19 @@ struct phy_driver {
int (*led_hw_control_get)(struct phy_device *dev, u8 index,
unsigned long *rules);
+ /**
+ * @led_polarity_set: Set the LED polarity modes
+ * @dev: PHY device which has the LED
+ * @index: Which LED of the PHY device
+ * @modes: bitmap of LED polarity modes
+ *
+ * Configure LED with all the required polarity modes in @modes
+ * to make it correctly turn ON or OFF.
+ *
+ * Returns 0, or an error code.
+ */
+ int (*led_polarity_set)(struct phy_device *dev, int index,
+ unsigned long modes);
};
#define to_phy_driver(d) container_of(to_mdio_common_driver(d), \
struct phy_driver, mdiodrv)

View File

@ -7,20 +7,17 @@ PHYs AQR113C and AQR813.
Signed-off-by: Birger Koblitz <git@birger-koblitz.de>
--- a/drivers/net/phy/aquantia_main.c
+++ b/drivers/net/phy/aquantia_main.c
@@ -20,8 +20,10 @@
#define PHY_ID_AQR105 0x03a1b4a2
#define PHY_ID_AQR106 0x03a1b4d0
#define PHY_ID_AQR107 0x03a1b4e0
+#define PHY_ID_AQR113C 0x31c31c12
--- a/drivers/net/phy/aquantia/aquantia_main.c
+++ b/drivers/net/phy/aquantia/aquantia_main.c
@@ -23,6 +23,7 @@
#define PHY_ID_AQCS109 0x03a1b5c2
#define PHY_ID_AQR405 0x03a1b4b0
#define PHY_ID_AQR113C 0x31c31c12
+#define PHY_ID_AQR813 0x31c31cb2
#define MDIO_PHYXS_VEND_IF_STATUS 0xe812
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3)
@@ -381,6 +383,49 @@ static int aqr107_read_rate(struct phy_d
@@ -360,6 +361,49 @@ static int aqr107_read_rate(struct phy_d
return 0;
}
@ -70,7 +67,7 @@ Signed-off-by: Birger Koblitz <git@birger-koblitz.de>
static int aqr107_read_status(struct phy_device *phydev)
{
int val, ret;
@@ -511,7 +556,7 @@ static void aqr107_chip_info(struct phy_
@@ -499,7 +543,7 @@ static void aqr107_chip_info(struct phy_
build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val);
prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val);
@ -79,35 +76,19 @@ Signed-off-by: Birger Koblitz <git@birger-koblitz.de>
fw_major, fw_minor, build_id, prov_id);
}
@@ -719,6 +764,24 @@ static struct phy_driver aqr_driver[] =
@@ -762,7 +806,7 @@ static struct phy_driver aqr_driver[] =
.config_aneg = aqr_config_aneg,
.config_intr = aqr_config_intr,
.handle_interrupt = aqr_handle_interrupt,
- .read_status = aqr107_read_status,
+ .read_status = aqr113c_read_status,
.get_tunable = aqr107_get_tunable,
.set_tunable = aqr107_set_tunable,
.suspend = aqr107_suspend,
@@ -772,6 +816,24 @@ static struct phy_driver aqr_driver[] =
.get_stats = aqr107_get_stats,
.link_change_notify = aqr107_link_change_notify,
},
{
+ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C),
+ .name = "Aquantia AQR113C",
+ .probe = aqr107_probe,
+ .config_init = aqr107_config_init,
+ .config_aneg = aqr_config_aneg,
+ .config_intr = aqr_config_intr,
+ .handle_interrupt = aqr_handle_interrupt,
+ .read_status = aqr113c_read_status,
+ .get_tunable = aqr107_get_tunable,
+ .set_tunable = aqr107_set_tunable,
+ .suspend = aqr107_suspend,
+ .resume = aqr107_resume,
+ .get_sset_count = aqr107_get_sset_count,
+ .get_strings = aqr107_get_strings,
+ .get_stats = aqr107_get_stats,
+ .link_change_notify = aqr107_link_change_notify,
+},
+{
PHY_ID_MATCH_MODEL(PHY_ID_AQCS109),
.name = "Aquantia AQCS109",
.probe = aqr107_probe,
@@ -744,6 +807,24 @@ static struct phy_driver aqr_driver[] =
.handle_interrupt = aqr_handle_interrupt,
.read_status = aqr_read_status,
},
+{
+ PHY_ID_MATCH_MODEL(PHY_ID_AQR813),
+ .name = "Aquantia AQR813",
@ -129,13 +110,10 @@ Signed-off-by: Birger Koblitz <git@birger-koblitz.de>
};
module_phy_driver(aqr_driver);
@@ -754,8 +835,10 @@ static struct mdio_device_id __maybe_unu
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR105) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR106) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR107) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) },
@@ -785,6 +847,7 @@ static struct mdio_device_id __maybe_unu
{ PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR405) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) },
{ }
};

View File

@ -10,24 +10,21 @@ different firmware on the PHY.
Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
---
drivers/net/phy/aquantia_main.c | 88 +++++++++++++++++++++++++++++++++++++++++
drivers/net/phy/aquantia/aquantia_main.c | 88 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
--- a/drivers/net/phy/aquantia_main.c
+++ b/drivers/net/phy/aquantia_main.c
@@ -20,9 +20,11 @@
#define PHY_ID_AQR105 0x03a1b4a2
#define PHY_ID_AQR106 0x03a1b4d0
#define PHY_ID_AQR107 0x03a1b4e0
+#define PHY_ID_AQR112 0x03a1b662
#define PHY_ID_AQR113C 0x31c31c12
#define PHY_ID_AQCS109 0x03a1b5c2
--- a/drivers/net/phy/aquantia/aquantia_main.c
+++ b/drivers/net/phy/aquantia/aquantia_main.c
@@ -24,6 +24,8 @@
#define PHY_ID_AQR405 0x03a1b4b0
+#define PHY_ID_AQR412 0x03a1b712
#define PHY_ID_AQR113C 0x31c31c12
#define PHY_ID_AQR813 0x31c31cb2
+#define PHY_ID_AQR112 0x03a1b662
+#define PHY_ID_AQR412 0x03a1b712
#define MDIO_PHYXS_VEND_IF_STATUS 0xe812
@@ -135,6 +137,29 @@
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3)
@@ -96,6 +98,29 @@
#define AQR107_OP_IN_PROG_SLEEP 1000
#define AQR107_OP_IN_PROG_TIMEOUT 100000
@ -57,7 +54,7 @@ Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
struct aqr107_hw_stat {
const char *name;
int reg;
@@ -266,6 +291,51 @@ static int aqr_config_aneg(struct phy_de
@@ -227,6 +252,51 @@ static int aqr_config_aneg(struct phy_de
return genphy_c45_check_and_restart_aneg(phydev, changed);
}
@ -109,7 +106,7 @@ Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
static int aqr_config_intr(struct phy_device *phydev)
{
bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED;
@@ -825,6 +895,30 @@ static struct phy_driver aqr_driver[] =
@@ -834,6 +904,30 @@ static struct phy_driver aqr_driver[] =
.get_stats = aqr107_get_stats,
.link_change_notify = aqr107_link_change_notify,
},
@ -140,15 +137,12 @@ Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
};
module_phy_driver(aqr_driver);
@@ -835,9 +929,11 @@ static struct mdio_device_id __maybe_unu
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR105) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR106) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR107) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) },
@@ -848,6 +942,8 @@ static struct mdio_device_id __maybe_unu
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR405) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR813) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) },
{ }
};

View File

@ -9,12 +9,12 @@ these protocols leads to link issues on system side.
Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
---
drivers/net/phy/aquantia_main.c | 8 +++++++-
drivers/net/phy/aquantia/aquantia_main.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/drivers/net/phy/aquantia_main.c
+++ b/drivers/net/phy/aquantia_main.c
@@ -324,10 +324,16 @@ static int aqr_config_aneg_set_prot(stru
--- a/drivers/net/phy/aquantia/aquantia_main.c
+++ b/drivers/net/phy/aquantia/aquantia_main.c
@@ -285,10 +285,16 @@ static int aqr_config_aneg_set_prot(stru
phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GSTART_RATE,
aquantia_syscfg[if_type].start_rate);

View File

@ -5,20 +5,20 @@ Subject: [PATCH] PONRTSYS-8842: aquantia: Add AQR113 driver support
Add a new entry for AQR113 PHY_ID
---
drivers/net/phy/aquantia_main.c | 10 ++++++++++
drivers/net/phy/aquantia/aquantia_main.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/drivers/net/phy/aquantia_main.c
+++ b/drivers/net/phy/aquantia_main.c
@@ -21,6 +21,7 @@
#define PHY_ID_AQR106 0x03a1b4d0
#define PHY_ID_AQR107 0x03a1b4e0
--- a/drivers/net/phy/aquantia/aquantia_main.c
+++ b/drivers/net/phy/aquantia/aquantia_main.c
@@ -26,6 +26,7 @@
#define PHY_ID_AQR813 0x31c31cb2
#define PHY_ID_AQR112 0x03a1b662
#define PHY_ID_AQR412 0x03a1b712
+#define PHY_ID_AQR113 0x31c31c40
#define PHY_ID_AQR113C 0x31c31c12
#define PHY_ID_AQCS109 0x03a1b5c2
#define PHY_ID_AQR405 0x03a1b4b0
@@ -914,6 +915,14 @@ static struct phy_driver aqr_driver[] =
#define MDIO_PHYXS_VEND_IF_STATUS 0xe812
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3)
@@ -923,6 +924,14 @@ static struct phy_driver aqr_driver[] =
.get_stats = aqr107_get_stats,
},
{
@ -33,11 +33,11 @@ Add a new entry for AQR113 PHY_ID
PHY_ID_MATCH_MODEL(PHY_ID_AQR412),
.name = "Aquantia AQR412",
.probe = aqr107_probe,
@@ -936,6 +945,7 @@ static struct mdio_device_id __maybe_unu
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR106) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR107) },
@@ -950,6 +959,7 @@ static struct mdio_device_id __maybe_unu
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR813) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR112) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR412) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR405) },
{ }
};

View File

@ -7,21 +7,21 @@ As advised by Ian Chang this PHY is used in Puzzle devices.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/phy/aquantia_main.c | 10 ++++++++++
drivers/net/phy/aquantia/aquantia_main.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/drivers/net/phy/aquantia_main.c
+++ b/drivers/net/phy/aquantia_main.c
@@ -21,6 +21,8 @@
#define PHY_ID_AQR106 0x03a1b4d0
#define PHY_ID_AQR107 0x03a1b4e0
--- a/drivers/net/phy/aquantia/aquantia_main.c
+++ b/drivers/net/phy/aquantia/aquantia_main.c
@@ -27,6 +27,8 @@
#define PHY_ID_AQR112 0x03a1b662
#define PHY_ID_AQR412 0x03a1b712
#define PHY_ID_AQR113 0x31c31c40
+#define PHY_ID_AQR112C 0x03a1b790
+#define PHY_ID_AQR112R 0x31c31d12
#define PHY_ID_AQR113 0x31c31c40
#define PHY_ID_AQR113C 0x31c31c12
#define PHY_ID_AQCS109 0x03a1b5c2
@@ -915,6 +917,30 @@ static struct phy_driver aqr_driver[] =
#define MDIO_PHYXS_VEND_IF_STATUS 0xe812
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3)
@@ -924,6 +926,30 @@ static struct phy_driver aqr_driver[] =
.get_stats = aqr107_get_stats,
},
{
@ -52,12 +52,12 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
PHY_ID_MATCH_MODEL(PHY_ID_AQR113),
.name = "Aquantia AQR113",
.config_aneg = aqr_config_aneg,
@@ -945,6 +971,8 @@ static struct mdio_device_id __maybe_unu
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR106) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR107) },
@@ -960,6 +986,8 @@ static struct mdio_device_id __maybe_unu
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR112) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR412) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR113) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112C) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112R) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR113) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) },
{ }
};

View File

@ -10,18 +10,18 @@ This is a 5GbE chip but it reports support for 10G. Implement config_init()
to set max speed to 5G.
Signed-off-by: Thomas Kupper <thomas.kupper@gmail.com>
--- a/drivers/net/phy/aquantia_main.c
+++ b/drivers/net/phy/aquantia_main.c
@@ -20,6 +20,8 @@
#define PHY_ID_AQR105 0x03a1b4a2
#define PHY_ID_AQR106 0x03a1b4d0
#define PHY_ID_AQR107 0x03a1b4e0
--- a/drivers/net/phy/aquantia/aquantia_main.c
+++ b/drivers/net/phy/aquantia/aquantia_main.c
@@ -24,6 +24,8 @@
#define PHY_ID_AQR405 0x03a1b4b0
#define PHY_ID_AQR113C 0x31c31c12
#define PHY_ID_AQR813 0x31c31cb2
+#define PHY_ID_AQR111 0x03a1b610
+#define PHY_ID_AQR111B0 0x03a1b612
#define PHY_ID_AQR112 0x03a1b662
#define PHY_ID_AQR112C 0x03a1b790
#define PHY_ID_AQR112R 0x31c31d12
@@ -686,6 +688,33 @@ static int aqcs109_config_init(struct ph
#define PHY_ID_AQR412 0x03a1b712
#define PHY_ID_AQR113 0x31c31c40
@@ -676,6 +678,33 @@ static int aqcs109_config_init(struct ph
return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
}
@ -55,7 +55,7 @@ Signed-off-by: Thomas Kupper <thomas.kupper@gmail.com>
static void aqr107_link_change_notify(struct phy_device *phydev)
{
u8 fw_major, fw_minor;
@@ -905,6 +934,42 @@ static struct phy_driver aqr_driver[] =
@@ -914,6 +943,42 @@ static struct phy_driver aqr_driver[] =
.link_change_notify = aqr107_link_change_notify,
},
{
@ -98,12 +98,12 @@ Signed-off-by: Thomas Kupper <thomas.kupper@gmail.com>
PHY_ID_MATCH_MODEL(PHY_ID_AQR112),
.name = "Aquantia AQR112",
.probe = aqr107_probe,
@@ -970,6 +1035,8 @@ static struct mdio_device_id __maybe_unu
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR105) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR106) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR107) },
@@ -983,6 +1048,8 @@ static struct mdio_device_id __maybe_unu
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR405) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR813) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR111) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR112) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR112C) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR112R) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR412) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR113) },

View File

@ -57,7 +57,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
const unsigned long *advertising);
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -931,7 +931,6 @@ static int phylink_change_inband_advert(
@@ -934,7 +934,6 @@ static int phylink_change_inband_advert(
return 0;
}
@ -65,7 +65,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
static void phylink_mac_pcs_get_state(struct phylink *pl,
struct phylink_link_state *state)
{
@@ -3015,6 +3014,52 @@ void phylink_mii_c22_pcs_get_state(struc
@@ -3019,6 +3018,52 @@ void phylink_mii_c22_pcs_get_state(struc
EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_get_state);
/**
@ -118,7 +118,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
* phylink_mii_c22_pcs_set_advertisement() - configure the clause 37 PCS
* advertisement
* @pcs: a pointer to a &struct mdio_device.
@@ -3086,6 +3131,46 @@ int phylink_mii_c22_pcs_set_advertisemen
@@ -3090,6 +3135,46 @@ int phylink_mii_c22_pcs_set_advertisemen
EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_set_advertisement);
/**

View File

@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
sysfs_remove_link(&dev->dev.kobj, "phydev");
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -843,6 +843,12 @@ struct phy_driver {
@@ -868,6 +868,12 @@ struct phy_driver {
/** @handle_interrupt: Override default interrupt handling */
irqreturn_t (*handle_interrupt)(struct phy_device *phydev);

View File

@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
sysfs_remove_link(&dev->dev.kobj, "phydev");
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -887,6 +887,12 @@ struct phy_driver {
@@ -896,6 +896,12 @@ struct phy_driver {
/** @handle_interrupt: Override default interrupt handling */
irqreturn_t (*handle_interrupt)(struct phy_device *phydev);

View File

@ -240,7 +240,7 @@ define Device/meraki_mr42
BLOCKSIZE := 128k
PAGESIZE := 2048
KERNEL_LOADADDR = 0x44208000
DEVICE_PACKAGES := -swconfig -kmod-ata-ahci -kmod-ata-ahci-platform \
DEVICE_PACKAGES := -kmod-ata-ahci -kmod-ata-ahci-platform \
-kmod-usb-ohci -kmod-usb2 -kmod-usb-ledtrig-usbport \
-kmod-phy-qcom-ipq806x-usb -kmod-usb3 -kmod-usb-dwc3-qcom \
-uboot-envtools ath10k-firmware-qca9887-ct \
@ -258,7 +258,7 @@ define Device/meraki_mr52
PAGESIZE := 2048
KERNEL_LOADADDR = 0x44208000
DEVICE_DTS_CONFIG := config@2
DEVICE_PACKAGES := -swconfig -kmod-ata-ahci -kmod-ata-ahci-platform \
DEVICE_PACKAGES := -kmod-ata-ahci -kmod-ata-ahci-platform \
-kmod-usb-ohci -kmod-usb2 -kmod-usb-ledtrig-usbport \
-kmod-phy-qcom-ipq806x-usb -kmod-usb3 -kmod-usb-dwc3-qcom \
-uboot-envtools ath10k-firmware-qca9887-ct \

View File

@ -11,9 +11,19 @@ Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com>
include/linux/phy.h | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -136,6 +136,7 @@ int phy_interface_num_ports(phy_interfac
case PHY_INTERFACE_MODE_RXAUI:
case PHY_INTERFACE_MODE_XAUI:
case PHY_INTERFACE_MODE_1000BASEKX:
+ case PHY_INTERFACE_MODE_2500SGMII:
return 1;
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -398,6 +398,7 @@ void phylink_get_linkmodes(unsigned long
@@ -400,6 +400,7 @@ void phylink_get_linkmodes(unsigned long
caps |= MAC_1000FD;
break;
@ -21,7 +31,7 @@ Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com>
case PHY_INTERFACE_MODE_2500BASEX:
caps |= MAC_2500FD;
break;
@@ -651,6 +652,10 @@ static int phylink_parse_mode(struct phy
@@ -654,6 +655,10 @@ static int phylink_parse_mode(struct phy
phylink_set(pl->supported, 2500baseX_Full);
break;
@ -34,18 +44,18 @@ Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com>
break;
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -153,6 +153,7 @@ typedef enum {
PHY_INTERFACE_MODE_USXGMII,
/* 10GBASE-KR - with Clause 73 AN */
@@ -157,6 +157,7 @@ typedef enum {
PHY_INTERFACE_MODE_10GKR,
PHY_INTERFACE_MODE_QUSGMII,
PHY_INTERFACE_MODE_1000BASEKX,
+ PHY_INTERFACE_MODE_2500SGMII,
PHY_INTERFACE_MODE_MAX,
} phy_interface_t;
@@ -268,6 +269,8 @@ static inline const char *phy_modes(phy_
return "10gbase-kr";
case PHY_INTERFACE_MODE_100BASEX:
@@ -276,6 +277,8 @@ static inline const char *phy_modes(phy_
return "100base-x";
case PHY_INTERFACE_MODE_QUSGMII:
return "qusgmii";
+ case PHY_INTERFACE_MODE_2500SGMII:
+ return "sgmii-2500";
default:

View File

@ -1,6 +1,6 @@
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -367,6 +367,12 @@ config ROCKCHIP_PHY
@@ -364,6 +364,12 @@ config ROCKCHIP_PHY
help
Currently supports the integrated Ethernet PHY.
@ -15,7 +15,7 @@
help
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -95,6 +95,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o
@@ -91,6 +91,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_REALTEK_PHY) += realtek.o
obj-$(CONFIG_RENESAS_PHY) += uPD60620.o
obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o

View File

@ -42,7 +42,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
L: linux-i2c@vger.kernel.org
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -293,6 +293,18 @@ config MEDIATEK_GE_PHY
@@ -290,6 +290,18 @@ config MEDIATEK_GE_PHY
help
Supports the MediaTek Gigabit Ethernet PHYs.
@ -63,7 +63,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
help
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o
@@ -77,6 +77,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o
obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o
obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o
obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o

View File

@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -305,6 +305,13 @@ config MEDIATEK_GE_SOC_PHY
@@ -302,6 +302,13 @@ config MEDIATEK_GE_SOC_PHY
present in the SoCs efuse and will dynamically calibrate VCM
(common-mode voltage) during startup.
@ -29,7 +29,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
help
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -80,6 +80,7 @@ obj-$(CONFIG_MARVELL_10G_PHY) += marvell
@@ -76,6 +76,7 @@ obj-$(CONFIG_MARVELL_10G_PHY) += marvell
obj-$(CONFIG_MARVELL_PHY) += marvell.o
obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o
obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o

View File

@ -55,6 +55,7 @@ CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_ARM_PSCI_FW=y
# CONFIG_ARM_QCOM_CPUFREQ_HW is not set
CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y
CONFIG_AT803X_PHY=y
CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_SD=y

View File

@ -260,7 +260,99 @@
spi-max-frequency = <50000000>;
partitions {
compatible = "qcom,smem-part";
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "0:sbl1";
reg = <0x0 0x50000>;
read-only;
};
partition@50000 {
label = "0:mibib";
reg = <0x50000 0x10000>;
read-only;
};
partition@60000 {
label = "0:qsee";
reg = <0x60000 0x180000>;
read-only;
};
partition@1e0000 {
label = "0:devcfg";
reg = <0x1e0000 0x10000>;
read-only;
};
partition@1f0000 {
label = "0:apdp";
reg = <0x1f0000 0x10000>;
read-only;
};
partition@200000 {
label = "0:rpm";
reg = <0x200000 0x40000>;
read-only;
};
partition@240000 {
label = "0:cdt";
reg = <0x240000 0x10000>;
read-only;
};
partition@250000 {
label = "0:appsblenv";
reg = <0x250000 0x20000>;
};
partition@270000 {
label = "0:appsbl";
reg = <0x250000 0x100000>;
read-only;
};
partition@370000 {
label = "0:art";
reg = <0x370000 0x40000>;
read-only;
};
partition@3b0000 {
label = "0:ethphyfw1";
reg = <0x3b0000 0x80000>;
compatible = "nvmem-cells";
#address-cells = <1>;
#size-cells = <1>;
aqr0_fw: firmware@0 {
reg = <0x0 0x5fc02>;
};
};
partition@430000 {
label = "0:ethphyfw2";
reg = <0x430000 0x80000>;
compatible = "nvmem-cells";
#address-cells = <1>;
#size-cells = <1>;
aqr1_fw: firmware@0 {
reg = <0x0 0x5fc02>;
};
};
partition@4b0000 {
label = "reserved";
reg = <0x4b0000 0x350000>;
};
};
};
};
@ -275,13 +367,19 @@
aqr113c_0: ethernet-phy@0 {
compatible ="ethernet-phy-ieee802.3-c45";
reg = <0>;
reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>;
reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>;
firmware-name = "marvell/AQR-G4_v5.4.C-AQR_CIG_WF-1945_0x0_ID44778_VER1630.cld";
nvmem-cell-names = "firmware";
nvmem-cells = <&aqr0_fw>;
};
aqr113c_8: ethernet-phy@8 {
compatible ="ethernet-phy-ieee802.3-c45";
reg = <8>;
reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>;
reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>;
firmware-name = "marvell/AQR-G4_v5.4.C-AQR_CIG_WF-1945_0x8_ID44776_VER1630.cld";
nvmem-cell-names = "firmware";
nvmem-cells = <&aqr1_fw>;
};
qca8075_16: ethernet-phy@16 {

View File

@ -8,6 +8,7 @@
#include "ipq8074-ess.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
/ {
model = "Yuncore AX880";
@ -313,12 +314,36 @@
compatible = "ethernet-phy-id004d.d101";
reg = <24>;
reset-gpios = <&tlmm 33 GPIO_ACTIVE_LOW>;
leds {
#address-cells = <1>;
#size-cells = <0>;
led@0 {
reg = <0>;
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_WAN;
default-state = "keep";
};
};
};
qca8081_28: ethernet-phy@28 {
compatible = "ethernet-phy-id004d.d101";
reg = <28>;
reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>;
leds {
#address-cells = <1>;
#size-cells = <0>;
led@0 {
reg = <0>;
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_LAN;
default-state = "keep";
};
};
};
};

View File

@ -378,6 +378,18 @@
compatible = "ethernet-phy-id004d.d101";
reg = <24>;
reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>;
leds {
#address-cells = <1>;
#size-cells = <0>;
led@0 {
reg = <0>;
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_WAN;
default-state = "keep";
};
};
};
};

View File

@ -163,6 +163,25 @@
compatible = "ethernet-phy-id004d.d101";
reg = <28>;
reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>;
leds {
#address-cells = <1>;
#size-cells = <0>;
led@0 {
reg = <0>;
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_WAN;
default-state = "keep";
};
led@1 {
reg = <1>;
color = <LED_COLOR_ID_YELLOW>;
function = LED_FUNCTION_WAN;
default-state = "keep";
};
};
};
};

View File

@ -10,6 +10,10 @@ arcadyan,aw1000)
ucidef_set_led_netdev "5g" "5G" "green:5g" "wwan0"
ucidef_set_led_netdev "wan" "WAN" "green:internet" "wan"
;;
dynalink,dl-wrx36)
ucidef_set_led_netdev "wan-port-link-green" "WAN-PORT-LINK-GREEN" "90000.mdio-1:1c:green:wan" "wan" "link_2500"
ucidef_set_led_netdev "wan-port-link-yellow" "WAN-PORT-LINK-YELLOW" "90000.mdio-1:1c:yellow:wan" "wan" "tx rx link_10 link_100 link_1000"
;;
edgecore,eap102)
ucidef_set_led_netdev "wan" "WAN" "green:wanpoe" "wan"
;;
@ -34,6 +38,9 @@ xiaomi,ax3600|\
xiaomi,ax3600-stock)
ucidef_set_led_netdev "wan" "WAN" "blue:network" "wan" "link"
;;
xiaomi,ax9000)
ucidef_set_led_netdev "wan-port-link" "WAN-PORT-LINK" "90000.mdio-1:18:green:wan" "wan" "tx rx link_10 link_100 link_1000 link_2500"
;;
qnap,301w)
ucidef_set_led_netdev "lan1" "LAN1" "green:lan1" "lan1"
ucidef_set_led_netdev "lan2" "LAN2" "green:lan2" "lan2"
@ -42,6 +49,10 @@ qnap,301w)
ucidef_set_led_netdev "10G_1" "10G_1" "green:10g_1" "10g-1"
ucidef_set_led_netdev "10G_2" "10G_2" "green:10g_2" "10g-2"
;;
yuncore,ax880)
ucidef_set_led_netdev "wan-port-link" "WAN-PORT-LINK" "90000.mdio-1:18:green:wan" "wan" "tx rx link_10 link_100 link_1000 link_2500"
ucidef_set_led_netdev "lan-port-link" "LAN-PORT-LINK" "90000.mdio-1:1c:green:lan" "lan" "tx rx link_10 link_100 link_1000 link_2500"
;;
esac
board_config_flush

View File

@ -33,7 +33,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
phy_led_trigger_change_speed(phydev);
}
@@ -563,7 +563,7 @@ int phy_start_cable_test(struct phy_devi
@@ -591,7 +591,7 @@ int phy_start_cable_test(struct phy_devi
goto out;
/* Mark the carrier down until the test is complete */
@ -42,7 +42,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
netif_testing_on(dev);
err = phydev->drv->cable_test_start(phydev);
@@ -634,7 +634,7 @@ int phy_start_cable_test_tdr(struct phy_
@@ -662,7 +662,7 @@ int phy_start_cable_test_tdr(struct phy_
goto out;
/* Mark the carrier down until the test is complete */
@ -51,7 +51,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
netif_testing_on(dev);
err = phydev->drv->cable_test_tdr_start(phydev, config);
@@ -706,7 +706,7 @@ static int phy_check_link_status(struct
@@ -734,7 +734,7 @@ static int phy_check_link_status(struct
phy_link_up(phydev);
} else if (!phydev->link && phydev->state != PHY_NOLINK) {
phydev->state = PHY_NOLINK;
@ -60,7 +60,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
}
return 0;
@@ -1192,7 +1192,7 @@ void phy_state_machine(struct work_struc
@@ -1220,7 +1220,7 @@ void phy_state_machine(struct work_struc
case PHY_HALTED:
if (phydev->link) {
phydev->link = 0;
@ -95,7 +95,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
phydev->mii_ts->link_state(phydev->mii_ts, phydev);
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1370,7 +1370,8 @@ void phylink_destroy(struct phylink *pl)
@@ -1373,7 +1373,8 @@ void phylink_destroy(struct phylink *pl)
}
EXPORT_SYMBOL_GPL(phylink_destroy);
@ -107,7 +107,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
bool tx_pause, rx_pause;
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -706,7 +706,7 @@ struct phy_device {
@@ -716,7 +716,7 @@ struct phy_device {
u8 mdix;
u8 mdix_ctrl;

View File

@ -11,7 +11,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -706,7 +706,10 @@ static int phy_check_link_status(struct
@@ -734,7 +734,10 @@ static int phy_check_link_status(struct
phy_link_up(phydev);
} else if (!phydev->link && phydev->state != PHY_NOLINK) {
phydev->state = PHY_NOLINK;
@ -23,7 +23,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
}
return 0;
@@ -1192,7 +1195,10 @@ void phy_state_machine(struct work_struc
@@ -1220,7 +1223,10 @@ void phy_state_machine(struct work_struc
case PHY_HALTED:
if (phydev->link) {
phydev->link = 0;
@ -37,7 +37,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
break;
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -622,6 +622,7 @@ struct phy_device {
@@ -630,6 +630,7 @@ struct phy_device {
unsigned downshifted_rate:1;
unsigned is_on_sfp_module:1;
unsigned mac_managed_pm:1;

View File

@ -21,7 +21,7 @@ Submitted-by: John Crispin <john@phrozen.org>
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -984,6 +984,10 @@ struct phy_driver {
@@ -1009,6 +1009,10 @@ struct phy_driver {
int (*led_blink_set)(struct phy_device *dev, u8 index,
unsigned long *delay_on,
unsigned long *delay_off);

View File

@ -21,7 +21,7 @@ Submitted-by: John Crispin <john@phrozen.org>
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1991,6 +1991,11 @@ int phylink_ethtool_ksettings_set(struct
@@ -1994,6 +1994,11 @@ int phylink_ethtool_ksettings_set(struct
* the presence of a PHY, this should not be changed as that
* should be determined from the media side advertisement.
*/
@ -33,7 +33,7 @@ Submitted-by: John Crispin <john@phrozen.org>
return phy_ethtool_ksettings_set(pl->phydev, kset);
}
@@ -2294,8 +2299,11 @@ int phylink_ethtool_get_eee(struct phyli
@@ -2297,8 +2302,11 @@ int phylink_ethtool_get_eee(struct phyli
ASSERT_RTNL();
@ -46,7 +46,7 @@ Submitted-by: John Crispin <john@phrozen.org>
return ret;
}
@@ -2312,8 +2320,11 @@ int phylink_ethtool_set_eee(struct phyli
@@ -2315,8 +2323,11 @@ int phylink_ethtool_set_eee(struct phyli
ASSERT_RTNL();

View File

@ -13,9 +13,19 @@ Submitted-by: Birger Koblitz <git@birger-koblitz.de>
include/linux/phy.h | 3 +++
2 file changed, 5 insertions(+)
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -124,6 +124,7 @@ int phy_interface_num_ports(phy_interfac
case PHY_INTERFACE_MODE_MOCA:
case PHY_INTERFACE_MODE_TRGMII:
case PHY_INTERFACE_MODE_USXGMII:
+ case PHY_INTERFACE_MODE_HSGMII:
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_SMII:
case PHY_INTERFACE_MODE_1000BASEX:
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -408,6 +408,7 @@ void phylink_get_linkmodes(unsigned long
@@ -410,6 +410,7 @@ void phylink_get_linkmodes(unsigned long
case PHY_INTERFACE_MODE_XGMII:
case PHY_INTERFACE_MODE_RXAUI:
@ -23,7 +33,7 @@ Submitted-by: Birger Koblitz <git@birger-koblitz.de>
case PHY_INTERFACE_MODE_XAUI:
case PHY_INTERFACE_MODE_10GBASER:
case PHY_INTERFACE_MODE_10GKR:
@@ -662,6 +663,7 @@ static int phylink_parse_mode(struct phy
@@ -665,6 +666,7 @@ static int phylink_parse_mode(struct phy
fallthrough;
case PHY_INTERFACE_MODE_USXGMII:
case PHY_INTERFACE_MODE_10GKR:
@ -33,7 +43,7 @@ Submitted-by: Birger Koblitz <git@birger-koblitz.de>
phylink_set(pl->supported, 10baseT_Full);
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -139,6 +139,7 @@ typedef enum {
@@ -141,6 +141,7 @@ typedef enum {
PHY_INTERFACE_MODE_XGMII,
PHY_INTERFACE_MODE_XLGMII,
PHY_INTERFACE_MODE_MOCA,
@ -41,7 +51,7 @@ Submitted-by: Birger Koblitz <git@birger-koblitz.de>
PHY_INTERFACE_MODE_QSGMII,
PHY_INTERFACE_MODE_TRGMII,
PHY_INTERFACE_MODE_100BASEX,
@@ -244,6 +245,8 @@ static inline const char *phy_modes(phy_
@@ -248,6 +249,8 @@ static inline const char *phy_modes(phy_
return "xlgmii";
case PHY_INTERFACE_MODE_MOCA:
return "moca";

View File

@ -14,7 +14,7 @@ Submitted-by: Birger Koblitz <mail@birger-koblitz.de>
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -357,6 +357,12 @@ config REALTEK_PHY
@@ -354,6 +354,12 @@ config REALTEK_PHY
help
Supports the Realtek 821x PHY.
@ -29,7 +29,7 @@ Submitted-by: Birger Koblitz <mail@birger-koblitz.de>
help
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -93,6 +93,7 @@ obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp
@@ -89,6 +89,7 @@ obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp
obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_REALTEK_PHY) += realtek.o

View File

@ -21,7 +21,7 @@ Submitted-by: John Crispin <john@phrozen.org>
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -280,7 +280,7 @@ static inline const char *phy_modes(phy_
@@ -287,7 +287,7 @@ static inline const char *phy_modes(phy_
#define PHY_INIT_TIMEOUT 100000
#define PHY_FORCE_TIMEOUT 10

View File

@ -443,7 +443,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
* @dev: target MDIO device
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -482,10 +482,16 @@ int __phy_read_mmd(struct phy_device *ph
@@ -557,10 +557,16 @@ int __phy_read_mmd(struct phy_device *ph
struct mii_bus *bus = phydev->mdio.bus;
int phy_addr = phydev->mdio.addr;
@ -464,7 +464,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
}
return val;
}
@@ -538,12 +544,18 @@ int __phy_write_mmd(struct phy_device *p
@@ -613,12 +619,18 @@ int __phy_write_mmd(struct phy_device *p
struct mii_bus *bus = phydev->mdio.bus;
int phy_addr = phydev->mdio.addr;
@ -487,7 +487,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
}
return ret;
}
@@ -749,6 +761,13 @@ EXPORT_SYMBOL_GPL(phy_modify_mmd);
@@ -824,6 +836,13 @@ EXPORT_SYMBOL_GPL(phy_modify_mmd);
static int __phy_read_page(struct phy_device *phydev)
{
@ -501,7 +501,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
if (WARN_ONCE(!phydev->drv->read_page, "read_page callback not available, PHY driver not loaded?\n"))
return -EOPNOTSUPP;
@@ -757,6 +776,13 @@ static int __phy_read_page(struct phy_de
@@ -832,6 +851,13 @@ static int __phy_read_page(struct phy_de
static int __phy_write_page(struct phy_device *phydev, int page)
{
@ -515,7 +515,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
if (WARN_ONCE(!phydev->drv->write_page, "write_page callback not available, PHY driver not loaded?\n"))
return -EOPNOTSUPP;
@@ -858,6 +884,18 @@ int phy_read_paged(struct phy_device *ph
@@ -933,6 +959,18 @@ int phy_read_paged(struct phy_device *ph
{
int ret = 0, oldpage;
@ -534,7 +534,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
oldpage = phy_select_page(phydev, page);
if (oldpage >= 0)
ret = __phy_read(phydev, regnum);
@@ -879,6 +917,18 @@ int phy_write_paged(struct phy_device *p
@@ -954,6 +992,18 @@ int phy_write_paged(struct phy_device *p
{
int ret = 0, oldpage;
@ -665,7 +665,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define MDIO_DEVICE_IS_PHY 0x80000000
/**
@@ -421,6 +422,22 @@ struct mii_bus {
@@ -428,6 +429,22 @@ struct mii_bus {
/** @shared: shared state across different PHYs */
struct phy_package_shared *shared[PHY_MAX_ADDR];
@ -688,7 +688,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
};
#define to_mii_bus(d) container_of(d, struct mii_bus, dev)
@@ -1795,6 +1812,66 @@ static inline int __phy_package_read(str
@@ -1825,6 +1842,66 @@ static inline int __phy_package_read(str
return __mdiobus_read(phydev->mdio.bus, shared->addr, regnum);
}
@ -755,7 +755,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
static inline int phy_package_write(struct phy_device *phydev,
u32 regnum, u16 val)
{
@@ -1817,6 +1894,72 @@ static inline int __phy_package_write(st
@@ -1847,6 +1924,72 @@ static inline int __phy_package_write(st
return __mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val);
}