Merge Official Source
Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
commit
9b7e61b88e
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
|
@ -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) {
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
}
|
|
@ -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
|
||||
*/
|
|
@ -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:
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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) },
|
||||
{ }
|
||||
};
|
||||
|
|
@ -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,
|
|
@ -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,
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
*/
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
|
@ -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,
|
|
@ -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)
|
|
@ -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) },
|
||||
{ }
|
||||
};
|
||||
|
|
|
@ -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) },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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) },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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) },
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user