mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00
kernel: netdevices: add realtek DSA modules
Uses upstream DSA switch modules (rtl8365mb, rtl8366), similar to RTL8367C and rtl8366rb swconfig drivers. The package dependencies exclude targets built without kernel CONFIG_OF. It also fixes the rtl8366rb LED support. Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com> Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
parent
bf665a29b2
commit
0263cb3835
@ -567,6 +567,65 @@ endef
|
||||
|
||||
$(eval $(call KernelPackage,dsa-qca8k))
|
||||
|
||||
|
||||
define KernelPackage/dsa-realtek
|
||||
SUBMENU:=$(NETWORK_DEVICES_MENU)
|
||||
TITLE:=Realtek common module RTL83xx DSA switch family
|
||||
DEPENDS:=@LINUX_6_6||LINUX_6_12 +kmod-dsa +kmod-phy-realtek +kmod-regmap-core
|
||||
KCONFIG:= \
|
||||
CONFIG_NET_DSA_REALTEK \
|
||||
CONFIG_NET_DSA_REALTEK_MDIO=y \
|
||||
CONFIG_NET_DSA_REALTEK_SMI=y
|
||||
FILES:= $(LINUX_DIR)/drivers/net/dsa/realtek/realtek_dsa.ko
|
||||
endef
|
||||
|
||||
define KernelPackage/dsa-realtek/description
|
||||
Common kernel module for Realtek RTL83xx DSA switch family
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,dsa-realtek))
|
||||
|
||||
|
||||
define KernelPackage/dsa-rtl8366rb
|
||||
SUBMENU:=$(NETWORK_DEVICES_MENU)
|
||||
TITLE:=Realtek RTL8365MB switch DSA support
|
||||
DEPENDS:=+kmod-dsa-realtek @!TARGET_x86 @!TARGET_bcm47xx @!TARGET_uml
|
||||
KCONFIG:= \
|
||||
CONFIG_NET_DSA_REALTEK_RTL8366RB \
|
||||
CONFIG_NET_DSA_TAG_RTL4_A
|
||||
FILES:= \
|
||||
$(LINUX_DIR)/drivers/net/dsa/realtek/rtl8366.ko \
|
||||
$(LINUX_DIR)/net/dsa/tag_rtl4_a.ko
|
||||
AUTOLOAD:=$(call AutoLoad,42,rtl8366,1)
|
||||
endef
|
||||
|
||||
define KernelPackage/dsa-rtl8366rb/description
|
||||
DSA based kernel modules for the Realtek RTL8366RB switch family
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,dsa-rtl8366rb))
|
||||
|
||||
|
||||
define KernelPackage/dsa-rtl8365mb
|
||||
SUBMENU:=$(NETWORK_DEVICES_MENU)
|
||||
TITLE:=Realtek RTL8365MB switch DSA support
|
||||
DEPENDS:=+kmod-dsa-realtek @!TARGET_x86 @!TARGET_bcm47xx @!TARGET_uml
|
||||
KCONFIG:= \
|
||||
CONFIG_NET_DSA_REALTEK_RTL8365MB \
|
||||
CONFIG_NET_DSA_TAG_RTL8_4
|
||||
FILES:= \
|
||||
$(LINUX_DIR)/drivers/net/dsa/realtek/rtl8365mb.ko \
|
||||
$(LINUX_DIR)/net/dsa/tag_rtl8_4.ko
|
||||
AUTOLOAD:=$(call AutoLoad,42,rtl8365mb,1)
|
||||
endef
|
||||
|
||||
define KernelPackage/dsa-rtl8365mb/description
|
||||
DSA based kernel modules for the Realtek RTL8365MB switch family
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,dsa-rtl8365mb))
|
||||
|
||||
|
||||
define KernelPackage/swconfig
|
||||
SUBMENU:=$(NETWORK_DEVICES_MENU)
|
||||
TITLE:=switch configuration API
|
||||
|
@ -0,0 +1,66 @@
|
||||
From d48a5472b8f2b29800bb25913f9403765005f1bc Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
|
||||
Date: Mon, 18 Sep 2023 21:19:14 +0200
|
||||
Subject: [PATCH] net: dsa: realtek: Convert to platform remove callback
|
||||
returning void
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The .remove() callback for a platform driver returns an int which makes
|
||||
many driver authors wrongly assume it's possible to do error handling by
|
||||
returning an error code. However the value returned is ignored (apart
|
||||
from emitting a warning) and this typically results in resource leaks.
|
||||
To improve here there is a quest to make the remove callback return
|
||||
void. In the first step of this quest all drivers are converted to
|
||||
.remove_new() which already returns void. Eventually after all drivers
|
||||
are converted, .remove_new() is renamed to .remove().
|
||||
|
||||
Trivially convert this driver from always returning zero in the remove
|
||||
callback to the void returning variant.
|
||||
|
||||
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
---
|
||||
drivers/net/dsa/realtek/realtek-smi.c | 8 +++-----
|
||||
1 file changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/realtek/realtek-smi.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-smi.c
|
||||
@@ -506,12 +506,12 @@ static int realtek_smi_probe(struct plat
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int realtek_smi_remove(struct platform_device *pdev)
|
||||
+static void realtek_smi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct realtek_priv *priv = platform_get_drvdata(pdev);
|
||||
|
||||
if (!priv)
|
||||
- return 0;
|
||||
+ return;
|
||||
|
||||
dsa_unregister_switch(priv->ds);
|
||||
if (priv->slave_mii_bus)
|
||||
@@ -520,8 +520,6 @@ static int realtek_smi_remove(struct pla
|
||||
/* leave the device reset asserted */
|
||||
if (priv->reset)
|
||||
gpiod_set_value(priv->reset, 1);
|
||||
-
|
||||
- return 0;
|
||||
}
|
||||
|
||||
static void realtek_smi_shutdown(struct platform_device *pdev)
|
||||
@@ -559,7 +557,7 @@ static struct platform_driver realtek_sm
|
||||
.of_match_table = realtek_smi_of_match,
|
||||
},
|
||||
.probe = realtek_smi_probe,
|
||||
- .remove = realtek_smi_remove,
|
||||
+ .remove_new = realtek_smi_remove,
|
||||
.shutdown = realtek_smi_shutdown,
|
||||
};
|
||||
module_platform_driver(realtek_smi_driver);
|
@ -0,0 +1,30 @@
|
||||
From 33f4336cbd32c21717b60d013693a0bd51a27db6 Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Fri, 9 Feb 2024 02:03:37 -0300
|
||||
Subject: net: dsa: realtek: drop cleanup from realtek_ops
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
It was never used and never referenced.
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/realtek/realtek.h | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/dsa/realtek/realtek.h
|
||||
+++ b/drivers/net/dsa/realtek/realtek.h
|
||||
@@ -91,7 +91,6 @@ struct realtek_ops {
|
||||
int (*detect)(struct realtek_priv *priv);
|
||||
int (*reset_chip)(struct realtek_priv *priv);
|
||||
int (*setup)(struct realtek_priv *priv);
|
||||
- void (*cleanup)(struct realtek_priv *priv);
|
||||
int (*get_mib_counter)(struct realtek_priv *priv,
|
||||
int port,
|
||||
struct rtl8366_mib_counter *mib,
|
@ -0,0 +1,146 @@
|
||||
From ded3813b44fe11a3bbd2c9d7df8870e8c19a7ccd Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Fri, 9 Feb 2024 02:03:38 -0300
|
||||
Subject: net: dsa: realtek: introduce REALTEK_DSA namespace
|
||||
|
||||
Create a namespace to group the exported symbols.
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/realtek/realtek-mdio.c | 1 +
|
||||
drivers/net/dsa/realtek/realtek-smi.c | 1 +
|
||||
drivers/net/dsa/realtek/rtl8365mb.c | 1 +
|
||||
drivers/net/dsa/realtek/rtl8366-core.c | 22 +++++++++++-----------
|
||||
drivers/net/dsa/realtek/rtl8366rb.c | 1 +
|
||||
5 files changed, 15 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/realtek/realtek-mdio.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
|
||||
@@ -288,3 +288,4 @@ mdio_module_driver(realtek_mdio_driver);
|
||||
MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
|
||||
MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface");
|
||||
MODULE_LICENSE("GPL");
|
||||
+MODULE_IMPORT_NS(REALTEK_DSA);
|
||||
--- a/drivers/net/dsa/realtek/realtek-smi.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-smi.c
|
||||
@@ -565,3 +565,4 @@ module_platform_driver(realtek_smi_drive
|
||||
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
|
||||
MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
|
||||
MODULE_LICENSE("GPL");
|
||||
+MODULE_IMPORT_NS(REALTEK_DSA);
|
||||
--- a/drivers/net/dsa/realtek/rtl8365mb.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
|
||||
@@ -2178,3 +2178,4 @@ EXPORT_SYMBOL_GPL(rtl8365mb_variant);
|
||||
MODULE_AUTHOR("Alvin Šipraga <alsi@bang-olufsen.dk>");
|
||||
MODULE_DESCRIPTION("Driver for RTL8365MB-VC ethernet switch");
|
||||
MODULE_LICENSE("GPL");
|
||||
+MODULE_IMPORT_NS(REALTEK_DSA);
|
||||
--- a/drivers/net/dsa/realtek/rtl8366-core.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl8366-core.c
|
||||
@@ -34,7 +34,7 @@ int rtl8366_mc_is_used(struct realtek_pr
|
||||
|
||||
return 0;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(rtl8366_mc_is_used);
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl8366_mc_is_used, REALTEK_DSA);
|
||||
|
||||
/**
|
||||
* rtl8366_obtain_mc() - retrieve or allocate a VLAN member configuration
|
||||
@@ -187,7 +187,7 @@ int rtl8366_set_vlan(struct realtek_priv
|
||||
|
||||
return ret;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(rtl8366_set_vlan);
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl8366_set_vlan, REALTEK_DSA);
|
||||
|
||||
int rtl8366_set_pvid(struct realtek_priv *priv, unsigned int port,
|
||||
unsigned int vid)
|
||||
@@ -217,7 +217,7 @@ int rtl8366_set_pvid(struct realtek_priv
|
||||
|
||||
return 0;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(rtl8366_set_pvid);
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl8366_set_pvid, REALTEK_DSA);
|
||||
|
||||
int rtl8366_enable_vlan4k(struct realtek_priv *priv, bool enable)
|
||||
{
|
||||
@@ -243,7 +243,7 @@ int rtl8366_enable_vlan4k(struct realtek
|
||||
priv->vlan4k_enabled = enable;
|
||||
return 0;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(rtl8366_enable_vlan4k);
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl8366_enable_vlan4k, REALTEK_DSA);
|
||||
|
||||
int rtl8366_enable_vlan(struct realtek_priv *priv, bool enable)
|
||||
{
|
||||
@@ -265,7 +265,7 @@ int rtl8366_enable_vlan(struct realtek_p
|
||||
|
||||
return ret;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(rtl8366_enable_vlan);
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl8366_enable_vlan, REALTEK_DSA);
|
||||
|
||||
int rtl8366_reset_vlan(struct realtek_priv *priv)
|
||||
{
|
||||
@@ -290,7 +290,7 @@ int rtl8366_reset_vlan(struct realtek_pr
|
||||
|
||||
return 0;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(rtl8366_reset_vlan);
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl8366_reset_vlan, REALTEK_DSA);
|
||||
|
||||
int rtl8366_vlan_add(struct dsa_switch *ds, int port,
|
||||
const struct switchdev_obj_port_vlan *vlan,
|
||||
@@ -345,7 +345,7 @@ int rtl8366_vlan_add(struct dsa_switch *
|
||||
|
||||
return 0;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(rtl8366_vlan_add);
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl8366_vlan_add, REALTEK_DSA);
|
||||
|
||||
int rtl8366_vlan_del(struct dsa_switch *ds, int port,
|
||||
const struct switchdev_obj_port_vlan *vlan)
|
||||
@@ -389,7 +389,7 @@ int rtl8366_vlan_del(struct dsa_switch *
|
||||
|
||||
return 0;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(rtl8366_vlan_del);
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl8366_vlan_del, REALTEK_DSA);
|
||||
|
||||
void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
|
||||
uint8_t *data)
|
||||
@@ -407,7 +407,7 @@ void rtl8366_get_strings(struct dsa_swit
|
||||
mib->name, ETH_GSTRING_LEN);
|
||||
}
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(rtl8366_get_strings);
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl8366_get_strings, REALTEK_DSA);
|
||||
|
||||
int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset)
|
||||
{
|
||||
@@ -421,7 +421,7 @@ int rtl8366_get_sset_count(struct dsa_sw
|
||||
|
||||
return priv->num_mib_counters;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(rtl8366_get_sset_count);
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl8366_get_sset_count, REALTEK_DSA);
|
||||
|
||||
void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
|
||||
{
|
||||
@@ -445,4 +445,4 @@ void rtl8366_get_ethtool_stats(struct ds
|
||||
data[i] = mibvalue;
|
||||
}
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(rtl8366_get_ethtool_stats);
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl8366_get_ethtool_stats, REALTEK_DSA);
|
||||
--- a/drivers/net/dsa/realtek/rtl8366rb.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
|
||||
@@ -1852,3 +1852,4 @@ EXPORT_SYMBOL_GPL(rtl8366rb_variant);
|
||||
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
|
||||
MODULE_DESCRIPTION("Driver for RTL8366RB ethernet switch");
|
||||
MODULE_LICENSE("GPL");
|
||||
+MODULE_IMPORT_NS(REALTEK_DSA);
|
@ -0,0 +1,539 @@
|
||||
From bce254b839abe67577bebdef0838796af409c229 Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Fri, 9 Feb 2024 02:03:39 -0300
|
||||
Subject: net: dsa: realtek: convert variants into real drivers
|
||||
|
||||
Previously, the interface modules realtek-smi and realtek-mdio served as
|
||||
a platform and an MDIO driver, respectively. Each interface module
|
||||
redundantly specified the same compatible strings for both variants and
|
||||
referenced symbols from the variants.
|
||||
|
||||
Now, each variant module has been transformed into a unified driver
|
||||
serving both as a platform and an MDIO driver. This modification
|
||||
reverses the relationship between the interface and variant modules,
|
||||
with the variant module now utilizing symbols from the interface
|
||||
modules.
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/realtek/Kconfig | 20 +++----
|
||||
drivers/net/dsa/realtek/realtek-mdio.c | 68 +++++++++++++++---------
|
||||
drivers/net/dsa/realtek/realtek-mdio.h | 48 +++++++++++++++++
|
||||
drivers/net/dsa/realtek/realtek-smi.c | 73 +++++++++++++++-----------
|
||||
drivers/net/dsa/realtek/realtek-smi.h | 48 +++++++++++++++++
|
||||
drivers/net/dsa/realtek/rtl8365mb.c | 54 ++++++++++++++++++-
|
||||
drivers/net/dsa/realtek/rtl8366rb.c | 54 ++++++++++++++++++-
|
||||
7 files changed, 292 insertions(+), 73 deletions(-)
|
||||
create mode 100644 drivers/net/dsa/realtek/realtek-mdio.h
|
||||
create mode 100644 drivers/net/dsa/realtek/realtek-smi.h
|
||||
|
||||
--- a/drivers/net/dsa/realtek/Kconfig
|
||||
+++ b/drivers/net/dsa/realtek/Kconfig
|
||||
@@ -16,37 +16,29 @@ menuconfig NET_DSA_REALTEK
|
||||
if NET_DSA_REALTEK
|
||||
|
||||
config NET_DSA_REALTEK_MDIO
|
||||
- tristate "Realtek MDIO interface driver"
|
||||
+ tristate "Realtek MDIO interface support"
|
||||
depends on OF
|
||||
- depends on NET_DSA_REALTEK_RTL8365MB || NET_DSA_REALTEK_RTL8366RB
|
||||
- depends on NET_DSA_REALTEK_RTL8365MB || !NET_DSA_REALTEK_RTL8365MB
|
||||
- depends on NET_DSA_REALTEK_RTL8366RB || !NET_DSA_REALTEK_RTL8366RB
|
||||
help
|
||||
Select to enable support for registering switches configured
|
||||
through MDIO.
|
||||
|
||||
config NET_DSA_REALTEK_SMI
|
||||
- tristate "Realtek SMI interface driver"
|
||||
+ tristate "Realtek SMI interface support"
|
||||
depends on OF
|
||||
- depends on NET_DSA_REALTEK_RTL8365MB || NET_DSA_REALTEK_RTL8366RB
|
||||
- depends on NET_DSA_REALTEK_RTL8365MB || !NET_DSA_REALTEK_RTL8365MB
|
||||
- depends on NET_DSA_REALTEK_RTL8366RB || !NET_DSA_REALTEK_RTL8366RB
|
||||
help
|
||||
Select to enable support for registering switches connected
|
||||
through SMI.
|
||||
|
||||
config NET_DSA_REALTEK_RTL8365MB
|
||||
- tristate "Realtek RTL8365MB switch subdriver"
|
||||
- imply NET_DSA_REALTEK_SMI
|
||||
- imply NET_DSA_REALTEK_MDIO
|
||||
+ tristate "Realtek RTL8365MB switch driver"
|
||||
+ depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO
|
||||
select NET_DSA_TAG_RTL8_4
|
||||
help
|
||||
Select to enable support for Realtek RTL8365MB-VC and RTL8367S.
|
||||
|
||||
config NET_DSA_REALTEK_RTL8366RB
|
||||
- tristate "Realtek RTL8366RB switch subdriver"
|
||||
- imply NET_DSA_REALTEK_SMI
|
||||
- imply NET_DSA_REALTEK_MDIO
|
||||
+ tristate "Realtek RTL8366RB switch driver"
|
||||
+ depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO
|
||||
select NET_DSA_TAG_RTL4_A
|
||||
help
|
||||
Select to enable support for Realtek RTL8366RB.
|
||||
--- a/drivers/net/dsa/realtek/realtek-mdio.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "realtek.h"
|
||||
+#include "realtek-mdio.h"
|
||||
|
||||
/* Read/write via mdiobus */
|
||||
#define REALTEK_MDIO_CTRL0_REG 31
|
||||
@@ -140,7 +141,19 @@ static const struct regmap_config realte
|
||||
.disable_locking = true,
|
||||
};
|
||||
|
||||
-static int realtek_mdio_probe(struct mdio_device *mdiodev)
|
||||
+/**
|
||||
+ * realtek_mdio_probe() - Probe a platform device for an MDIO-connected switch
|
||||
+ * @mdiodev: mdio_device to probe on.
|
||||
+ *
|
||||
+ * This function should be used as the .probe in an mdio_driver. It
|
||||
+ * initializes realtek_priv and read data from the device-tree node. The switch
|
||||
+ * is hard reset if a method is provided. It checks the switch chip ID and,
|
||||
+ * finally, a DSA switch is registered.
|
||||
+ *
|
||||
+ * Context: Can sleep. Takes and releases priv->map_lock.
|
||||
+ * Return: Returns 0 on success, a negative error on failure.
|
||||
+ */
|
||||
+int realtek_mdio_probe(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct realtek_priv *priv;
|
||||
struct device *dev = &mdiodev->dev;
|
||||
@@ -235,8 +248,20 @@ static int realtek_mdio_probe(struct mdi
|
||||
|
||||
return 0;
|
||||
}
|
||||
+EXPORT_SYMBOL_NS_GPL(realtek_mdio_probe, REALTEK_DSA);
|
||||
|
||||
-static void realtek_mdio_remove(struct mdio_device *mdiodev)
|
||||
+/**
|
||||
+ * realtek_mdio_remove() - Remove the driver of an MDIO-connected switch
|
||||
+ * @mdiodev: mdio_device to be removed.
|
||||
+ *
|
||||
+ * This function should be used as the .remove_new in an mdio_driver. First
|
||||
+ * it unregisters the DSA switch and cleans internal data. If a method is
|
||||
+ * provided, the hard reset is asserted to avoid traffic leakage.
|
||||
+ *
|
||||
+ * Context: Can sleep.
|
||||
+ * Return: Nothing.
|
||||
+ */
|
||||
+void realtek_mdio_remove(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
|
||||
|
||||
@@ -249,8 +274,21 @@ static void realtek_mdio_remove(struct m
|
||||
if (priv->reset)
|
||||
gpiod_set_value(priv->reset, 1);
|
||||
}
|
||||
+EXPORT_SYMBOL_NS_GPL(realtek_mdio_remove, REALTEK_DSA);
|
||||
|
||||
-static void realtek_mdio_shutdown(struct mdio_device *mdiodev)
|
||||
+/**
|
||||
+ * realtek_mdio_shutdown() - Shutdown the driver of a MDIO-connected switch
|
||||
+ * @mdiodev: mdio_device shutting down.
|
||||
+ *
|
||||
+ * This function should be used as the .shutdown in an mdio_driver. It shuts
|
||||
+ * down the DSA switch and cleans the platform driver data, to prevent
|
||||
+ * realtek_mdio_remove() from running afterwards, which is possible if the
|
||||
+ * parent bus implements its own .shutdown() as .remove().
|
||||
+ *
|
||||
+ * Context: Can sleep.
|
||||
+ * Return: Nothing.
|
||||
+ */
|
||||
+void realtek_mdio_shutdown(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
|
||||
|
||||
@@ -261,29 +299,7 @@ static void realtek_mdio_shutdown(struct
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
-
|
||||
-static const struct of_device_id realtek_mdio_of_match[] = {
|
||||
-#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB)
|
||||
- { .compatible = "realtek,rtl8366rb", .data = &rtl8366rb_variant, },
|
||||
-#endif
|
||||
-#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB)
|
||||
- { .compatible = "realtek,rtl8365mb", .data = &rtl8365mb_variant, },
|
||||
-#endif
|
||||
- { /* sentinel */ },
|
||||
-};
|
||||
-MODULE_DEVICE_TABLE(of, realtek_mdio_of_match);
|
||||
-
|
||||
-static struct mdio_driver realtek_mdio_driver = {
|
||||
- .mdiodrv.driver = {
|
||||
- .name = "realtek-mdio",
|
||||
- .of_match_table = realtek_mdio_of_match,
|
||||
- },
|
||||
- .probe = realtek_mdio_probe,
|
||||
- .remove = realtek_mdio_remove,
|
||||
- .shutdown = realtek_mdio_shutdown,
|
||||
-};
|
||||
-
|
||||
-mdio_module_driver(realtek_mdio_driver);
|
||||
+EXPORT_SYMBOL_NS_GPL(realtek_mdio_shutdown, REALTEK_DSA);
|
||||
|
||||
MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
|
||||
MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface");
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/dsa/realtek/realtek-mdio.h
|
||||
@@ -0,0 +1,48 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
+
|
||||
+#ifndef _REALTEK_MDIO_H
|
||||
+#define _REALTEK_MDIO_H
|
||||
+
|
||||
+#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_MDIO)
|
||||
+
|
||||
+static inline int realtek_mdio_driver_register(struct mdio_driver *drv)
|
||||
+{
|
||||
+ return mdio_driver_register(drv);
|
||||
+}
|
||||
+
|
||||
+static inline void realtek_mdio_driver_unregister(struct mdio_driver *drv)
|
||||
+{
|
||||
+ mdio_driver_unregister(drv);
|
||||
+}
|
||||
+
|
||||
+int realtek_mdio_probe(struct mdio_device *mdiodev);
|
||||
+void realtek_mdio_remove(struct mdio_device *mdiodev);
|
||||
+void realtek_mdio_shutdown(struct mdio_device *mdiodev);
|
||||
+
|
||||
+#else /* IS_ENABLED(CONFIG_NET_DSA_REALTEK_MDIO) */
|
||||
+
|
||||
+static inline int realtek_mdio_driver_register(struct mdio_driver *drv)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline void realtek_mdio_driver_unregister(struct mdio_driver *drv)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static inline int realtek_mdio_probe(struct mdio_device *mdiodev)
|
||||
+{
|
||||
+ return -ENOENT;
|
||||
+}
|
||||
+
|
||||
+static inline void realtek_mdio_remove(struct mdio_device *mdiodev)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static inline void realtek_mdio_shutdown(struct mdio_device *mdiodev)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+#endif /* IS_ENABLED(CONFIG_NET_DSA_REALTEK_MDIO) */
|
||||
+
|
||||
+#endif /* _REALTEK_MDIO_H */
|
||||
--- a/drivers/net/dsa/realtek/realtek-smi.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-smi.c
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <linux/if_bridge.h>
|
||||
|
||||
#include "realtek.h"
|
||||
+#include "realtek-smi.h"
|
||||
|
||||
#define REALTEK_SMI_ACK_RETRY_COUNT 5
|
||||
|
||||
@@ -408,7 +409,19 @@ err_put_node:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int realtek_smi_probe(struct platform_device *pdev)
|
||||
+/**
|
||||
+ * realtek_smi_probe() - Probe a platform device for an SMI-connected switch
|
||||
+ * @pdev: platform_device to probe on.
|
||||
+ *
|
||||
+ * This function should be used as the .probe in a platform_driver. It
|
||||
+ * initializes realtek_priv and read data from the device-tree node. The switch
|
||||
+ * is hard reset if a method is provided. It checks the switch chip ID and,
|
||||
+ * finally, a DSA switch is registered.
|
||||
+ *
|
||||
+ * Context: Can sleep. Takes and releases priv->map_lock.
|
||||
+ * Return: Returns 0 on success, a negative error on failure.
|
||||
+ */
|
||||
+int realtek_smi_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct realtek_variant *var;
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -505,8 +518,20 @@ static int realtek_smi_probe(struct plat
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+EXPORT_SYMBOL_NS_GPL(realtek_smi_probe, REALTEK_DSA);
|
||||
|
||||
-static void realtek_smi_remove(struct platform_device *pdev)
|
||||
+/**
|
||||
+ * realtek_smi_remove() - Remove the driver of a SMI-connected switch
|
||||
+ * @pdev: platform_device to be removed.
|
||||
+ *
|
||||
+ * This function should be used as the .remove_new in a platform_driver. First
|
||||
+ * it unregisters the DSA switch and cleans internal data. If a method is
|
||||
+ * provided, the hard reset is asserted to avoid traffic leakage.
|
||||
+ *
|
||||
+ * Context: Can sleep.
|
||||
+ * Return: Nothing.
|
||||
+ */
|
||||
+void realtek_smi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct realtek_priv *priv = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -521,8 +546,21 @@ static void realtek_smi_remove(struct pl
|
||||
if (priv->reset)
|
||||
gpiod_set_value(priv->reset, 1);
|
||||
}
|
||||
+EXPORT_SYMBOL_NS_GPL(realtek_smi_remove, REALTEK_DSA);
|
||||
|
||||
-static void realtek_smi_shutdown(struct platform_device *pdev)
|
||||
+/**
|
||||
+ * realtek_smi_shutdown() - Shutdown the driver of a SMI-connected switch
|
||||
+ * @pdev: platform_device shutting down.
|
||||
+ *
|
||||
+ * This function should be used as the .shutdown in a platform_driver. It shuts
|
||||
+ * down the DSA switch and cleans the platform driver data, to prevent
|
||||
+ * realtek_smi_remove() from running afterwards, which is possible if the
|
||||
+ * parent bus implements its own .shutdown() as .remove().
|
||||
+ *
|
||||
+ * Context: Can sleep.
|
||||
+ * Return: Nothing.
|
||||
+ */
|
||||
+void realtek_smi_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct realtek_priv *priv = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -533,34 +571,7 @@ static void realtek_smi_shutdown(struct
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
-
|
||||
-static const struct of_device_id realtek_smi_of_match[] = {
|
||||
-#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB)
|
||||
- {
|
||||
- .compatible = "realtek,rtl8366rb",
|
||||
- .data = &rtl8366rb_variant,
|
||||
- },
|
||||
-#endif
|
||||
-#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB)
|
||||
- {
|
||||
- .compatible = "realtek,rtl8365mb",
|
||||
- .data = &rtl8365mb_variant,
|
||||
- },
|
||||
-#endif
|
||||
- { /* sentinel */ },
|
||||
-};
|
||||
-MODULE_DEVICE_TABLE(of, realtek_smi_of_match);
|
||||
-
|
||||
-static struct platform_driver realtek_smi_driver = {
|
||||
- .driver = {
|
||||
- .name = "realtek-smi",
|
||||
- .of_match_table = realtek_smi_of_match,
|
||||
- },
|
||||
- .probe = realtek_smi_probe,
|
||||
- .remove_new = realtek_smi_remove,
|
||||
- .shutdown = realtek_smi_shutdown,
|
||||
-};
|
||||
-module_platform_driver(realtek_smi_driver);
|
||||
+EXPORT_SYMBOL_NS_GPL(realtek_smi_shutdown, REALTEK_DSA);
|
||||
|
||||
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
|
||||
MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/dsa/realtek/realtek-smi.h
|
||||
@@ -0,0 +1,48 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
+
|
||||
+#ifndef _REALTEK_SMI_H
|
||||
+#define _REALTEK_SMI_H
|
||||
+
|
||||
+#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_SMI)
|
||||
+
|
||||
+static inline int realtek_smi_driver_register(struct platform_driver *drv)
|
||||
+{
|
||||
+ return platform_driver_register(drv);
|
||||
+}
|
||||
+
|
||||
+static inline void realtek_smi_driver_unregister(struct platform_driver *drv)
|
||||
+{
|
||||
+ platform_driver_unregister(drv);
|
||||
+}
|
||||
+
|
||||
+int realtek_smi_probe(struct platform_device *pdev);
|
||||
+void realtek_smi_remove(struct platform_device *pdev);
|
||||
+void realtek_smi_shutdown(struct platform_device *pdev);
|
||||
+
|
||||
+#else /* IS_ENABLED(CONFIG_NET_DSA_REALTEK_SMI) */
|
||||
+
|
||||
+static inline int realtek_smi_driver_register(struct platform_driver *drv)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline void realtek_smi_driver_unregister(struct platform_driver *drv)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static inline int realtek_smi_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ return -ENOENT;
|
||||
+}
|
||||
+
|
||||
+static inline void realtek_smi_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static inline void realtek_smi_shutdown(struct platform_device *pdev)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+#endif /* IS_ENABLED(CONFIG_NET_DSA_REALTEK_SMI) */
|
||||
+
|
||||
+#endif /* _REALTEK_SMI_H */
|
||||
--- a/drivers/net/dsa/realtek/rtl8365mb.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
|
||||
@@ -101,6 +101,8 @@
|
||||
#include <linux/if_vlan.h>
|
||||
|
||||
#include "realtek.h"
|
||||
+#include "realtek-smi.h"
|
||||
+#include "realtek-mdio.h"
|
||||
|
||||
/* Family-specific data and limits */
|
||||
#define RTL8365MB_PHYADDRMAX 7
|
||||
@@ -2173,7 +2175,57 @@ const struct realtek_variant rtl8365mb_v
|
||||
.cmd_write = 0xb8,
|
||||
.chip_data_sz = sizeof(struct rtl8365mb),
|
||||
};
|
||||
-EXPORT_SYMBOL_GPL(rtl8365mb_variant);
|
||||
+
|
||||
+static const struct of_device_id rtl8365mb_of_match[] = {
|
||||
+ { .compatible = "realtek,rtl8365mb", .data = &rtl8365mb_variant, },
|
||||
+ { /* sentinel */ },
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, rtl8365mb_of_match);
|
||||
+
|
||||
+static struct platform_driver rtl8365mb_smi_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "rtl8365mb-smi",
|
||||
+ .of_match_table = rtl8365mb_of_match,
|
||||
+ },
|
||||
+ .probe = realtek_smi_probe,
|
||||
+ .remove_new = realtek_smi_remove,
|
||||
+ .shutdown = realtek_smi_shutdown,
|
||||
+};
|
||||
+
|
||||
+static struct mdio_driver rtl8365mb_mdio_driver = {
|
||||
+ .mdiodrv.driver = {
|
||||
+ .name = "rtl8365mb-mdio",
|
||||
+ .of_match_table = rtl8365mb_of_match,
|
||||
+ },
|
||||
+ .probe = realtek_mdio_probe,
|
||||
+ .remove = realtek_mdio_remove,
|
||||
+ .shutdown = realtek_mdio_shutdown,
|
||||
+};
|
||||
+
|
||||
+static int rtl8365mb_init(void)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = realtek_mdio_driver_register(&rtl8365mb_mdio_driver);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = realtek_smi_driver_register(&rtl8365mb_smi_driver);
|
||||
+ if (ret) {
|
||||
+ realtek_mdio_driver_unregister(&rtl8365mb_mdio_driver);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+module_init(rtl8365mb_init);
|
||||
+
|
||||
+static void __exit rtl8365mb_exit(void)
|
||||
+{
|
||||
+ realtek_smi_driver_unregister(&rtl8365mb_smi_driver);
|
||||
+ realtek_mdio_driver_unregister(&rtl8365mb_mdio_driver);
|
||||
+}
|
||||
+module_exit(rtl8365mb_exit);
|
||||
|
||||
MODULE_AUTHOR("Alvin Šipraga <alsi@bang-olufsen.dk>");
|
||||
MODULE_DESCRIPTION("Driver for RTL8365MB-VC ethernet switch");
|
||||
--- a/drivers/net/dsa/realtek/rtl8366rb.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "realtek.h"
|
||||
+#include "realtek-smi.h"
|
||||
+#include "realtek-mdio.h"
|
||||
|
||||
#define RTL8366RB_PORT_NUM_CPU 5
|
||||
#define RTL8366RB_NUM_PORTS 6
|
||||
@@ -1847,7 +1849,57 @@ const struct realtek_variant rtl8366rb_v
|
||||
.cmd_write = 0xa8,
|
||||
.chip_data_sz = sizeof(struct rtl8366rb),
|
||||
};
|
||||
-EXPORT_SYMBOL_GPL(rtl8366rb_variant);
|
||||
+
|
||||
+static const struct of_device_id rtl8366rb_of_match[] = {
|
||||
+ { .compatible = "realtek,rtl8366rb", .data = &rtl8366rb_variant, },
|
||||
+ { /* sentinel */ },
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, rtl8366rb_of_match);
|
||||
+
|
||||
+static struct platform_driver rtl8366rb_smi_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "rtl8366rb-smi",
|
||||
+ .of_match_table = rtl8366rb_of_match,
|
||||
+ },
|
||||
+ .probe = realtek_smi_probe,
|
||||
+ .remove_new = realtek_smi_remove,
|
||||
+ .shutdown = realtek_smi_shutdown,
|
||||
+};
|
||||
+
|
||||
+static struct mdio_driver rtl8366rb_mdio_driver = {
|
||||
+ .mdiodrv.driver = {
|
||||
+ .name = "rtl8366rb-mdio",
|
||||
+ .of_match_table = rtl8366rb_of_match,
|
||||
+ },
|
||||
+ .probe = realtek_mdio_probe,
|
||||
+ .remove = realtek_mdio_remove,
|
||||
+ .shutdown = realtek_mdio_shutdown,
|
||||
+};
|
||||
+
|
||||
+static int rtl8366rb_init(void)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = realtek_mdio_driver_register(&rtl8366rb_mdio_driver);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = realtek_smi_driver_register(&rtl8366rb_smi_driver);
|
||||
+ if (ret) {
|
||||
+ realtek_mdio_driver_unregister(&rtl8366rb_mdio_driver);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+module_init(rtl8366rb_init);
|
||||
+
|
||||
+static void __exit rtl8366rb_exit(void)
|
||||
+{
|
||||
+ realtek_smi_driver_unregister(&rtl8366rb_smi_driver);
|
||||
+ realtek_mdio_driver_unregister(&rtl8366rb_mdio_driver);
|
||||
+}
|
||||
+module_exit(rtl8366rb_exit);
|
||||
|
||||
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
|
||||
MODULE_DESCRIPTION("Driver for RTL8366RB ethernet switch");
|
@ -0,0 +1,91 @@
|
||||
From 4667a1db2f550d23e01ba655fce331196ead6e92 Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Fri, 9 Feb 2024 02:03:40 -0300
|
||||
Subject: net: dsa: realtek: keep variant reference in
|
||||
realtek_priv
|
||||
|
||||
Instead of copying values from the variant, we can keep a reference in
|
||||
realtek_priv.
|
||||
|
||||
This is a preliminary change for sharing code betwen interfaces. It will
|
||||
allow to move most of the probe into a common module while still allow
|
||||
code specific to each interface to read variant fields.
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/realtek/realtek-mdio.c | 4 +---
|
||||
drivers/net/dsa/realtek/realtek-smi.c | 10 ++++------
|
||||
drivers/net/dsa/realtek/realtek.h | 5 ++---
|
||||
3 files changed, 7 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/realtek/realtek-mdio.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
|
||||
@@ -196,9 +196,7 @@ int realtek_mdio_probe(struct mdio_devic
|
||||
priv->dev = &mdiodev->dev;
|
||||
priv->chip_data = (void *)priv + sizeof(*priv);
|
||||
|
||||
- priv->clk_delay = var->clk_delay;
|
||||
- priv->cmd_read = var->cmd_read;
|
||||
- priv->cmd_write = var->cmd_write;
|
||||
+ priv->variant = var;
|
||||
priv->ops = var->ops;
|
||||
|
||||
priv->write_reg_noack = realtek_mdio_write;
|
||||
--- a/drivers/net/dsa/realtek/realtek-smi.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-smi.c
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
static inline void realtek_smi_clk_delay(struct realtek_priv *priv)
|
||||
{
|
||||
- ndelay(priv->clk_delay);
|
||||
+ ndelay(priv->variant->clk_delay);
|
||||
}
|
||||
|
||||
static void realtek_smi_start(struct realtek_priv *priv)
|
||||
@@ -209,7 +209,7 @@ static int realtek_smi_read_reg(struct r
|
||||
realtek_smi_start(priv);
|
||||
|
||||
/* Send READ command */
|
||||
- ret = realtek_smi_write_byte(priv, priv->cmd_read);
|
||||
+ ret = realtek_smi_write_byte(priv, priv->variant->cmd_read);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -250,7 +250,7 @@ static int realtek_smi_write_reg(struct
|
||||
realtek_smi_start(priv);
|
||||
|
||||
/* Send WRITE command */
|
||||
- ret = realtek_smi_write_byte(priv, priv->cmd_write);
|
||||
+ ret = realtek_smi_write_byte(priv, priv->variant->cmd_write);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -459,9 +459,7 @@ int realtek_smi_probe(struct platform_de
|
||||
|
||||
/* Link forward and backward */
|
||||
priv->dev = dev;
|
||||
- priv->clk_delay = var->clk_delay;
|
||||
- priv->cmd_read = var->cmd_read;
|
||||
- priv->cmd_write = var->cmd_write;
|
||||
+ priv->variant = var;
|
||||
priv->ops = var->ops;
|
||||
|
||||
priv->setup_interface = realtek_smi_setup_mdio;
|
||||
--- a/drivers/net/dsa/realtek/realtek.h
|
||||
+++ b/drivers/net/dsa/realtek/realtek.h
|
||||
@@ -58,9 +58,8 @@ struct realtek_priv {
|
||||
struct mii_bus *bus;
|
||||
int mdio_addr;
|
||||
|
||||
- unsigned int clk_delay;
|
||||
- u8 cmd_read;
|
||||
- u8 cmd_write;
|
||||
+ const struct realtek_variant *variant;
|
||||
+
|
||||
spinlock_t lock; /* Locks around command writes */
|
||||
struct dsa_switch *ds;
|
||||
struct irq_domain *irqdomain;
|
@ -0,0 +1,875 @@
|
||||
From 8be040ecd94c1a9a137927d18534edfae0a9b68a Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Fri, 9 Feb 2024 02:03:41 -0300
|
||||
Subject: net: dsa: realtek: common rtl83xx module
|
||||
|
||||
Some code can be shared between both interface modules (MDIO and SMI)
|
||||
and among variants. These interface functions migrated to a common
|
||||
module:
|
||||
|
||||
- rtl83xx_lock
|
||||
- rtl83xx_unlock
|
||||
- rtl83xx_probe
|
||||
- rtl83xx_register_switch
|
||||
- rtl83xx_unregister_switch
|
||||
- rtl83xx_shutdown
|
||||
- rtl83xx_remove
|
||||
|
||||
The reset during probe was moved to the end of the common probe. This way,
|
||||
we avoid a reset if anything else fails.
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/realtek/Makefile | 2 +
|
||||
drivers/net/dsa/realtek/realtek-mdio.c | 152 +++-------------
|
||||
drivers/net/dsa/realtek/realtek-smi.c | 166 ++++-------------
|
||||
drivers/net/dsa/realtek/realtek.h | 1 +
|
||||
drivers/net/dsa/realtek/rtl8365mb.c | 9 +-
|
||||
drivers/net/dsa/realtek/rtl8366rb.c | 9 +-
|
||||
drivers/net/dsa/realtek/rtl83xx.c | 235 +++++++++++++++++++++++++
|
||||
drivers/net/dsa/realtek/rtl83xx.h | 21 +++
|
||||
8 files changed, 322 insertions(+), 273 deletions(-)
|
||||
create mode 100644 drivers/net/dsa/realtek/rtl83xx.c
|
||||
create mode 100644 drivers/net/dsa/realtek/rtl83xx.h
|
||||
|
||||
--- a/drivers/net/dsa/realtek/Makefile
|
||||
+++ b/drivers/net/dsa/realtek/Makefile
|
||||
@@ -1,4 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
+obj-$(CONFIG_NET_DSA_REALTEK) += realtek_dsa.o
|
||||
+realtek_dsa-objs := rtl83xx.o
|
||||
obj-$(CONFIG_NET_DSA_REALTEK_MDIO) += realtek-mdio.o
|
||||
obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
|
||||
obj-$(CONFIG_NET_DSA_REALTEK_RTL8366RB) += rtl8366.o
|
||||
--- a/drivers/net/dsa/realtek/realtek-mdio.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "realtek.h"
|
||||
#include "realtek-mdio.h"
|
||||
+#include "rtl83xx.h"
|
||||
|
||||
/* Read/write via mdiobus */
|
||||
#define REALTEK_MDIO_CTRL0_REG 31
|
||||
@@ -100,147 +101,41 @@ out_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static void realtek_mdio_lock(void *ctx)
|
||||
-{
|
||||
- struct realtek_priv *priv = ctx;
|
||||
-
|
||||
- mutex_lock(&priv->map_lock);
|
||||
-}
|
||||
-
|
||||
-static void realtek_mdio_unlock(void *ctx)
|
||||
-{
|
||||
- struct realtek_priv *priv = ctx;
|
||||
-
|
||||
- mutex_unlock(&priv->map_lock);
|
||||
-}
|
||||
-
|
||||
-static const struct regmap_config realtek_mdio_regmap_config = {
|
||||
- .reg_bits = 10, /* A4..A0 R4..R0 */
|
||||
- .val_bits = 16,
|
||||
- .reg_stride = 1,
|
||||
- /* PHY regs are at 0x8000 */
|
||||
- .max_register = 0xffff,
|
||||
- .reg_format_endian = REGMAP_ENDIAN_BIG,
|
||||
+static const struct realtek_interface_info realtek_mdio_info = {
|
||||
.reg_read = realtek_mdio_read,
|
||||
.reg_write = realtek_mdio_write,
|
||||
- .cache_type = REGCACHE_NONE,
|
||||
- .lock = realtek_mdio_lock,
|
||||
- .unlock = realtek_mdio_unlock,
|
||||
-};
|
||||
-
|
||||
-static const struct regmap_config realtek_mdio_nolock_regmap_config = {
|
||||
- .reg_bits = 10, /* A4..A0 R4..R0 */
|
||||
- .val_bits = 16,
|
||||
- .reg_stride = 1,
|
||||
- /* PHY regs are at 0x8000 */
|
||||
- .max_register = 0xffff,
|
||||
- .reg_format_endian = REGMAP_ENDIAN_BIG,
|
||||
- .reg_read = realtek_mdio_read,
|
||||
- .reg_write = realtek_mdio_write,
|
||||
- .cache_type = REGCACHE_NONE,
|
||||
- .disable_locking = true,
|
||||
};
|
||||
|
||||
/**
|
||||
* realtek_mdio_probe() - Probe a platform device for an MDIO-connected switch
|
||||
* @mdiodev: mdio_device to probe on.
|
||||
*
|
||||
- * This function should be used as the .probe in an mdio_driver. It
|
||||
- * initializes realtek_priv and read data from the device-tree node. The switch
|
||||
- * is hard reset if a method is provided. It checks the switch chip ID and,
|
||||
- * finally, a DSA switch is registered.
|
||||
+ * This function should be used as the .probe in an mdio_driver. After
|
||||
+ * calling the common probe function for both interfaces, it initializes the
|
||||
+ * values specific for MDIO-connected devices. Finally, it calls a common
|
||||
+ * function to register the DSA switch.
|
||||
*
|
||||
* Context: Can sleep. Takes and releases priv->map_lock.
|
||||
* Return: Returns 0 on success, a negative error on failure.
|
||||
*/
|
||||
int realtek_mdio_probe(struct mdio_device *mdiodev)
|
||||
{
|
||||
- struct realtek_priv *priv;
|
||||
struct device *dev = &mdiodev->dev;
|
||||
- const struct realtek_variant *var;
|
||||
- struct regmap_config rc;
|
||||
- struct device_node *np;
|
||||
+ struct realtek_priv *priv;
|
||||
int ret;
|
||||
|
||||
- var = of_device_get_match_data(dev);
|
||||
- if (!var)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- priv = devm_kzalloc(&mdiodev->dev,
|
||||
- size_add(sizeof(*priv), var->chip_data_sz),
|
||||
- GFP_KERNEL);
|
||||
- if (!priv)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- mutex_init(&priv->map_lock);
|
||||
-
|
||||
- rc = realtek_mdio_regmap_config;
|
||||
- rc.lock_arg = priv;
|
||||
- priv->map = devm_regmap_init(dev, NULL, priv, &rc);
|
||||
- if (IS_ERR(priv->map)) {
|
||||
- ret = PTR_ERR(priv->map);
|
||||
- dev_err(dev, "regmap init failed: %d\n", ret);
|
||||
- return ret;
|
||||
- }
|
||||
+ priv = rtl83xx_probe(dev, &realtek_mdio_info);
|
||||
+ if (IS_ERR(priv))
|
||||
+ return PTR_ERR(priv);
|
||||
|
||||
- rc = realtek_mdio_nolock_regmap_config;
|
||||
- priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
|
||||
- if (IS_ERR(priv->map_nolock)) {
|
||||
- ret = PTR_ERR(priv->map_nolock);
|
||||
- dev_err(dev, "regmap init failed: %d\n", ret);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- priv->mdio_addr = mdiodev->addr;
|
||||
priv->bus = mdiodev->bus;
|
||||
- priv->dev = &mdiodev->dev;
|
||||
- priv->chip_data = (void *)priv + sizeof(*priv);
|
||||
-
|
||||
- priv->variant = var;
|
||||
- priv->ops = var->ops;
|
||||
-
|
||||
+ priv->mdio_addr = mdiodev->addr;
|
||||
priv->write_reg_noack = realtek_mdio_write;
|
||||
+ priv->ds_ops = priv->variant->ds_ops_mdio;
|
||||
|
||||
- np = dev->of_node;
|
||||
-
|
||||
- dev_set_drvdata(dev, priv);
|
||||
-
|
||||
- /* TODO: if power is software controlled, set up any regulators here */
|
||||
- priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
|
||||
-
|
||||
- priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
||||
- if (IS_ERR(priv->reset)) {
|
||||
- dev_err(dev, "failed to get RESET GPIO\n");
|
||||
- return PTR_ERR(priv->reset);
|
||||
- }
|
||||
-
|
||||
- if (priv->reset) {
|
||||
- gpiod_set_value(priv->reset, 1);
|
||||
- dev_dbg(dev, "asserted RESET\n");
|
||||
- msleep(REALTEK_HW_STOP_DELAY);
|
||||
- gpiod_set_value(priv->reset, 0);
|
||||
- msleep(REALTEK_HW_START_DELAY);
|
||||
- dev_dbg(dev, "deasserted RESET\n");
|
||||
- }
|
||||
-
|
||||
- ret = priv->ops->detect(priv);
|
||||
- if (ret) {
|
||||
- dev_err(dev, "unable to detect switch\n");
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL);
|
||||
- if (!priv->ds)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- priv->ds->dev = dev;
|
||||
- priv->ds->num_ports = priv->num_ports;
|
||||
- priv->ds->priv = priv;
|
||||
- priv->ds->ops = var->ds_ops_mdio;
|
||||
-
|
||||
- ret = dsa_register_switch(priv->ds);
|
||||
+ ret = rtl83xx_register_switch(priv);
|
||||
if (ret) {
|
||||
- dev_err(priv->dev, "unable to register switch ret = %d\n", ret);
|
||||
+ rtl83xx_remove(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -253,8 +148,7 @@ EXPORT_SYMBOL_NS_GPL(realtek_mdio_probe,
|
||||
* @mdiodev: mdio_device to be removed.
|
||||
*
|
||||
* This function should be used as the .remove_new in an mdio_driver. First
|
||||
- * it unregisters the DSA switch and cleans internal data. If a method is
|
||||
- * provided, the hard reset is asserted to avoid traffic leakage.
|
||||
+ * it unregisters the DSA switch and then it calls the common remove function.
|
||||
*
|
||||
* Context: Can sleep.
|
||||
* Return: Nothing.
|
||||
@@ -266,11 +160,9 @@ void realtek_mdio_remove(struct mdio_dev
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
- dsa_unregister_switch(priv->ds);
|
||||
+ rtl83xx_unregister_switch(priv);
|
||||
|
||||
- /* leave the device reset asserted */
|
||||
- if (priv->reset)
|
||||
- gpiod_set_value(priv->reset, 1);
|
||||
+ rtl83xx_remove(priv);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(realtek_mdio_remove, REALTEK_DSA);
|
||||
|
||||
@@ -278,10 +170,8 @@ EXPORT_SYMBOL_NS_GPL(realtek_mdio_remove
|
||||
* realtek_mdio_shutdown() - Shutdown the driver of a MDIO-connected switch
|
||||
* @mdiodev: mdio_device shutting down.
|
||||
*
|
||||
- * This function should be used as the .shutdown in an mdio_driver. It shuts
|
||||
- * down the DSA switch and cleans the platform driver data, to prevent
|
||||
- * realtek_mdio_remove() from running afterwards, which is possible if the
|
||||
- * parent bus implements its own .shutdown() as .remove().
|
||||
+ * This function should be used as the .shutdown in a platform_driver. It calls
|
||||
+ * the common shutdown function.
|
||||
*
|
||||
* Context: Can sleep.
|
||||
* Return: Nothing.
|
||||
@@ -293,9 +183,7 @@ void realtek_mdio_shutdown(struct mdio_d
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
- dsa_switch_shutdown(priv->ds);
|
||||
-
|
||||
- dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
+ rtl83xx_shutdown(priv);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(realtek_mdio_shutdown, REALTEK_DSA);
|
||||
|
||||
--- a/drivers/net/dsa/realtek/realtek-smi.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-smi.c
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include "realtek.h"
|
||||
#include "realtek-smi.h"
|
||||
+#include "rtl83xx.h"
|
||||
|
||||
#define REALTEK_SMI_ACK_RETRY_COUNT 5
|
||||
|
||||
@@ -311,47 +312,6 @@ static int realtek_smi_read(void *ctx, u
|
||||
return realtek_smi_read_reg(priv, reg, val);
|
||||
}
|
||||
|
||||
-static void realtek_smi_lock(void *ctx)
|
||||
-{
|
||||
- struct realtek_priv *priv = ctx;
|
||||
-
|
||||
- mutex_lock(&priv->map_lock);
|
||||
-}
|
||||
-
|
||||
-static void realtek_smi_unlock(void *ctx)
|
||||
-{
|
||||
- struct realtek_priv *priv = ctx;
|
||||
-
|
||||
- mutex_unlock(&priv->map_lock);
|
||||
-}
|
||||
-
|
||||
-static const struct regmap_config realtek_smi_regmap_config = {
|
||||
- .reg_bits = 10, /* A4..A0 R4..R0 */
|
||||
- .val_bits = 16,
|
||||
- .reg_stride = 1,
|
||||
- /* PHY regs are at 0x8000 */
|
||||
- .max_register = 0xffff,
|
||||
- .reg_format_endian = REGMAP_ENDIAN_BIG,
|
||||
- .reg_read = realtek_smi_read,
|
||||
- .reg_write = realtek_smi_write,
|
||||
- .cache_type = REGCACHE_NONE,
|
||||
- .lock = realtek_smi_lock,
|
||||
- .unlock = realtek_smi_unlock,
|
||||
-};
|
||||
-
|
||||
-static const struct regmap_config realtek_smi_nolock_regmap_config = {
|
||||
- .reg_bits = 10, /* A4..A0 R4..R0 */
|
||||
- .val_bits = 16,
|
||||
- .reg_stride = 1,
|
||||
- /* PHY regs are at 0x8000 */
|
||||
- .max_register = 0xffff,
|
||||
- .reg_format_endian = REGMAP_ENDIAN_BIG,
|
||||
- .reg_read = realtek_smi_read,
|
||||
- .reg_write = realtek_smi_write,
|
||||
- .cache_type = REGCACHE_NONE,
|
||||
- .disable_locking = true,
|
||||
-};
|
||||
-
|
||||
static int realtek_smi_mdio_read(struct mii_bus *bus, int addr, int regnum)
|
||||
{
|
||||
struct realtek_priv *priv = bus->priv;
|
||||
@@ -409,111 +369,56 @@ err_put_node:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static const struct realtek_interface_info realtek_smi_info = {
|
||||
+ .reg_read = realtek_smi_read,
|
||||
+ .reg_write = realtek_smi_write,
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* realtek_smi_probe() - Probe a platform device for an SMI-connected switch
|
||||
* @pdev: platform_device to probe on.
|
||||
*
|
||||
- * This function should be used as the .probe in a platform_driver. It
|
||||
- * initializes realtek_priv and read data from the device-tree node. The switch
|
||||
- * is hard reset if a method is provided. It checks the switch chip ID and,
|
||||
- * finally, a DSA switch is registered.
|
||||
+ * This function should be used as the .probe in a platform_driver. After
|
||||
+ * calling the common probe function for both interfaces, it initializes the
|
||||
+ * values specific for SMI-connected devices. Finally, it calls a common
|
||||
+ * function to register the DSA switch.
|
||||
*
|
||||
* Context: Can sleep. Takes and releases priv->map_lock.
|
||||
* Return: Returns 0 on success, a negative error on failure.
|
||||
*/
|
||||
int realtek_smi_probe(struct platform_device *pdev)
|
||||
{
|
||||
- const struct realtek_variant *var;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct realtek_priv *priv;
|
||||
- struct regmap_config rc;
|
||||
- struct device_node *np;
|
||||
int ret;
|
||||
|
||||
- var = of_device_get_match_data(dev);
|
||||
- np = dev->of_node;
|
||||
-
|
||||
- priv = devm_kzalloc(dev, sizeof(*priv) + var->chip_data_sz, GFP_KERNEL);
|
||||
- if (!priv)
|
||||
- return -ENOMEM;
|
||||
- priv->chip_data = (void *)priv + sizeof(*priv);
|
||||
-
|
||||
- mutex_init(&priv->map_lock);
|
||||
-
|
||||
- rc = realtek_smi_regmap_config;
|
||||
- rc.lock_arg = priv;
|
||||
- priv->map = devm_regmap_init(dev, NULL, priv, &rc);
|
||||
- if (IS_ERR(priv->map)) {
|
||||
- ret = PTR_ERR(priv->map);
|
||||
- dev_err(dev, "regmap init failed: %d\n", ret);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- rc = realtek_smi_nolock_regmap_config;
|
||||
- priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
|
||||
- if (IS_ERR(priv->map_nolock)) {
|
||||
- ret = PTR_ERR(priv->map_nolock);
|
||||
- dev_err(dev, "regmap init failed: %d\n", ret);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- /* Link forward and backward */
|
||||
- priv->dev = dev;
|
||||
- priv->variant = var;
|
||||
- priv->ops = var->ops;
|
||||
-
|
||||
- priv->setup_interface = realtek_smi_setup_mdio;
|
||||
- priv->write_reg_noack = realtek_smi_write_reg_noack;
|
||||
-
|
||||
- dev_set_drvdata(dev, priv);
|
||||
- spin_lock_init(&priv->lock);
|
||||
-
|
||||
- /* TODO: if power is software controlled, set up any regulators here */
|
||||
-
|
||||
- priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
||||
- if (IS_ERR(priv->reset)) {
|
||||
- dev_err(dev, "failed to get RESET GPIO\n");
|
||||
- return PTR_ERR(priv->reset);
|
||||
- }
|
||||
- if (priv->reset) {
|
||||
- gpiod_set_value(priv->reset, 1);
|
||||
- dev_dbg(dev, "asserted RESET\n");
|
||||
- msleep(REALTEK_HW_STOP_DELAY);
|
||||
- gpiod_set_value(priv->reset, 0);
|
||||
- msleep(REALTEK_HW_START_DELAY);
|
||||
- dev_dbg(dev, "deasserted RESET\n");
|
||||
- }
|
||||
+ priv = rtl83xx_probe(dev, &realtek_smi_info);
|
||||
+ if (IS_ERR(priv))
|
||||
+ return PTR_ERR(priv);
|
||||
|
||||
/* Fetch MDIO pins */
|
||||
priv->mdc = devm_gpiod_get_optional(dev, "mdc", GPIOD_OUT_LOW);
|
||||
- if (IS_ERR(priv->mdc))
|
||||
+ if (IS_ERR(priv->mdc)) {
|
||||
+ rtl83xx_remove(priv);
|
||||
return PTR_ERR(priv->mdc);
|
||||
+ }
|
||||
+
|
||||
priv->mdio = devm_gpiod_get_optional(dev, "mdio", GPIOD_OUT_LOW);
|
||||
- if (IS_ERR(priv->mdio))
|
||||
+ if (IS_ERR(priv->mdio)) {
|
||||
+ rtl83xx_remove(priv);
|
||||
return PTR_ERR(priv->mdio);
|
||||
-
|
||||
- priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
|
||||
-
|
||||
- ret = priv->ops->detect(priv);
|
||||
- if (ret) {
|
||||
- dev_err(dev, "unable to detect switch\n");
|
||||
- return ret;
|
||||
}
|
||||
|
||||
- priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL);
|
||||
- if (!priv->ds)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- priv->ds->dev = dev;
|
||||
- priv->ds->num_ports = priv->num_ports;
|
||||
- priv->ds->priv = priv;
|
||||
+ priv->write_reg_noack = realtek_smi_write_reg_noack;
|
||||
+ priv->setup_interface = realtek_smi_setup_mdio;
|
||||
+ priv->ds_ops = priv->variant->ds_ops_smi;
|
||||
|
||||
- priv->ds->ops = var->ds_ops_smi;
|
||||
- ret = dsa_register_switch(priv->ds);
|
||||
+ ret = rtl83xx_register_switch(priv);
|
||||
if (ret) {
|
||||
- dev_err_probe(dev, ret, "unable to register switch\n");
|
||||
+ rtl83xx_remove(priv);
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(realtek_smi_probe, REALTEK_DSA);
|
||||
@@ -523,8 +428,8 @@ EXPORT_SYMBOL_NS_GPL(realtek_smi_probe,
|
||||
* @pdev: platform_device to be removed.
|
||||
*
|
||||
* This function should be used as the .remove_new in a platform_driver. First
|
||||
- * it unregisters the DSA switch and cleans internal data. If a method is
|
||||
- * provided, the hard reset is asserted to avoid traffic leakage.
|
||||
+ * it unregisters the DSA switch and cleans internal data. Finally, it calls
|
||||
+ * the common remove function.
|
||||
*
|
||||
* Context: Can sleep.
|
||||
* Return: Nothing.
|
||||
@@ -536,13 +441,12 @@ void realtek_smi_remove(struct platform_
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
- dsa_unregister_switch(priv->ds);
|
||||
+ rtl83xx_unregister_switch(priv);
|
||||
+
|
||||
if (priv->slave_mii_bus)
|
||||
of_node_put(priv->slave_mii_bus->dev.of_node);
|
||||
|
||||
- /* leave the device reset asserted */
|
||||
- if (priv->reset)
|
||||
- gpiod_set_value(priv->reset, 1);
|
||||
+ rtl83xx_remove(priv);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(realtek_smi_remove, REALTEK_DSA);
|
||||
|
||||
@@ -550,10 +454,8 @@ EXPORT_SYMBOL_NS_GPL(realtek_smi_remove,
|
||||
* realtek_smi_shutdown() - Shutdown the driver of a SMI-connected switch
|
||||
* @pdev: platform_device shutting down.
|
||||
*
|
||||
- * This function should be used as the .shutdown in a platform_driver. It shuts
|
||||
- * down the DSA switch and cleans the platform driver data, to prevent
|
||||
- * realtek_smi_remove() from running afterwards, which is possible if the
|
||||
- * parent bus implements its own .shutdown() as .remove().
|
||||
+ * This function should be used as the .shutdown in a platform_driver. It calls
|
||||
+ * the common shutdown function.
|
||||
*
|
||||
* Context: Can sleep.
|
||||
* Return: Nothing.
|
||||
@@ -565,9 +467,7 @@ void realtek_smi_shutdown(struct platfor
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
- dsa_switch_shutdown(priv->ds);
|
||||
-
|
||||
- platform_set_drvdata(pdev, NULL);
|
||||
+ rtl83xx_shutdown(priv);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(realtek_smi_shutdown, REALTEK_DSA);
|
||||
|
||||
--- a/drivers/net/dsa/realtek/realtek.h
|
||||
+++ b/drivers/net/dsa/realtek/realtek.h
|
||||
@@ -62,6 +62,7 @@ struct realtek_priv {
|
||||
|
||||
spinlock_t lock; /* Locks around command writes */
|
||||
struct dsa_switch *ds;
|
||||
+ const struct dsa_switch_ops *ds_ops;
|
||||
struct irq_domain *irqdomain;
|
||||
bool leds_disabled;
|
||||
|
||||
--- a/drivers/net/dsa/realtek/rtl8365mb.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
|
||||
@@ -103,6 +103,7 @@
|
||||
#include "realtek.h"
|
||||
#include "realtek-smi.h"
|
||||
#include "realtek-mdio.h"
|
||||
+#include "rtl83xx.h"
|
||||
|
||||
/* Family-specific data and limits */
|
||||
#define RTL8365MB_PHYADDRMAX 7
|
||||
@@ -691,7 +692,7 @@ static int rtl8365mb_phy_ocp_read(struct
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
- mutex_lock(&priv->map_lock);
|
||||
+ rtl83xx_lock(priv);
|
||||
|
||||
ret = rtl8365mb_phy_poll_busy(priv);
|
||||
if (ret)
|
||||
@@ -724,7 +725,7 @@ static int rtl8365mb_phy_ocp_read(struct
|
||||
*data = val & 0xFFFF;
|
||||
|
||||
out:
|
||||
- mutex_unlock(&priv->map_lock);
|
||||
+ rtl83xx_unlock(priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -735,7 +736,7 @@ static int rtl8365mb_phy_ocp_write(struc
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
- mutex_lock(&priv->map_lock);
|
||||
+ rtl83xx_lock(priv);
|
||||
|
||||
ret = rtl8365mb_phy_poll_busy(priv);
|
||||
if (ret)
|
||||
@@ -766,7 +767,7 @@ static int rtl8365mb_phy_ocp_write(struc
|
||||
goto out;
|
||||
|
||||
out:
|
||||
- mutex_unlock(&priv->map_lock);
|
||||
+ rtl83xx_unlock(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
--- a/drivers/net/dsa/realtek/rtl8366rb.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "realtek.h"
|
||||
#include "realtek-smi.h"
|
||||
#include "realtek-mdio.h"
|
||||
+#include "rtl83xx.h"
|
||||
|
||||
#define RTL8366RB_PORT_NUM_CPU 5
|
||||
#define RTL8366RB_NUM_PORTS 6
|
||||
@@ -1634,7 +1635,7 @@ static int rtl8366rb_phy_read(struct rea
|
||||
if (phy > RTL8366RB_PHY_NO_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
- mutex_lock(&priv->map_lock);
|
||||
+ rtl83xx_lock(priv);
|
||||
|
||||
ret = regmap_write(priv->map_nolock, RTL8366RB_PHY_ACCESS_CTRL_REG,
|
||||
RTL8366RB_PHY_CTRL_READ);
|
||||
@@ -1662,7 +1663,7 @@ static int rtl8366rb_phy_read(struct rea
|
||||
phy, regnum, reg, val);
|
||||
|
||||
out:
|
||||
- mutex_unlock(&priv->map_lock);
|
||||
+ rtl83xx_unlock(priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1676,7 +1677,7 @@ static int rtl8366rb_phy_write(struct re
|
||||
if (phy > RTL8366RB_PHY_NO_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
- mutex_lock(&priv->map_lock);
|
||||
+ rtl83xx_lock(priv);
|
||||
|
||||
ret = regmap_write(priv->map_nolock, RTL8366RB_PHY_ACCESS_CTRL_REG,
|
||||
RTL8366RB_PHY_CTRL_WRITE);
|
||||
@@ -1693,7 +1694,7 @@ static int rtl8366rb_phy_write(struct re
|
||||
goto out;
|
||||
|
||||
out:
|
||||
- mutex_unlock(&priv->map_lock);
|
||||
+ rtl83xx_unlock(priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/dsa/realtek/rtl83xx.c
|
||||
@@ -0,0 +1,236 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/of_device.h> /* krnl 6.1 only */
|
||||
+
|
||||
+#include "realtek.h"
|
||||
+#include "rtl83xx.h"
|
||||
+
|
||||
+/**
|
||||
+ * rtl83xx_lock() - Locks the mutex used by regmaps
|
||||
+ * @ctx: realtek_priv pointer
|
||||
+ *
|
||||
+ * This function is passed to regmap to be used as the lock function.
|
||||
+ * It is also used externally to block regmap before executing multiple
|
||||
+ * operations that must happen in sequence (which will use
|
||||
+ * realtek_priv.map_nolock instead).
|
||||
+ *
|
||||
+ * Context: Can sleep. Holds priv->map_lock lock.
|
||||
+ * Return: nothing
|
||||
+ */
|
||||
+void rtl83xx_lock(void *ctx)
|
||||
+{
|
||||
+ struct realtek_priv *priv = ctx;
|
||||
+
|
||||
+ mutex_lock(&priv->map_lock);
|
||||
+}
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl83xx_lock, REALTEK_DSA);
|
||||
+
|
||||
+/**
|
||||
+ * rtl83xx_unlock() - Unlocks the mutex used by regmaps
|
||||
+ * @ctx: realtek_priv pointer
|
||||
+ *
|
||||
+ * This function unlocks the lock acquired by rtl83xx_lock.
|
||||
+ *
|
||||
+ * Context: Releases priv->map_lock lock.
|
||||
+ * Return: nothing
|
||||
+ */
|
||||
+void rtl83xx_unlock(void *ctx)
|
||||
+{
|
||||
+ struct realtek_priv *priv = ctx;
|
||||
+
|
||||
+ mutex_unlock(&priv->map_lock);
|
||||
+}
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl83xx_unlock, REALTEK_DSA);
|
||||
+
|
||||
+/**
|
||||
+ * rtl83xx_probe() - probe a Realtek switch
|
||||
+ * @dev: the device being probed
|
||||
+ * @interface_info: specific management interface info.
|
||||
+ *
|
||||
+ * This function initializes realtek_priv and reads data from the device tree
|
||||
+ * node. The switch is hard resetted if a method is provided.
|
||||
+ *
|
||||
+ * Context: Can sleep.
|
||||
+ * Return: Pointer to the realtek_priv or ERR_PTR() in case of failure.
|
||||
+ *
|
||||
+ * The realtek_priv pointer does not need to be freed as it is controlled by
|
||||
+ * devres.
|
||||
+ */
|
||||
+struct realtek_priv *
|
||||
+rtl83xx_probe(struct device *dev,
|
||||
+ const struct realtek_interface_info *interface_info)
|
||||
+{
|
||||
+ const struct realtek_variant *var;
|
||||
+ struct realtek_priv *priv;
|
||||
+ struct regmap_config rc = {
|
||||
+ .reg_bits = 10, /* A4..A0 R4..R0 */
|
||||
+ .val_bits = 16,
|
||||
+ .reg_stride = 1,
|
||||
+ .max_register = 0xffff,
|
||||
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
|
||||
+ .reg_read = interface_info->reg_read,
|
||||
+ .reg_write = interface_info->reg_write,
|
||||
+ .cache_type = REGCACHE_NONE,
|
||||
+ .lock = rtl83xx_lock,
|
||||
+ .unlock = rtl83xx_unlock,
|
||||
+ };
|
||||
+ int ret;
|
||||
+
|
||||
+ var = of_device_get_match_data(dev);
|
||||
+ if (!var)
|
||||
+ return ERR_PTR(-EINVAL);
|
||||
+
|
||||
+ priv = devm_kzalloc(dev, size_add(sizeof(*priv), var->chip_data_sz),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
+
|
||||
+ mutex_init(&priv->map_lock);
|
||||
+
|
||||
+ rc.lock_arg = priv;
|
||||
+ priv->map = devm_regmap_init(dev, NULL, priv, &rc);
|
||||
+ if (IS_ERR(priv->map)) {
|
||||
+ ret = PTR_ERR(priv->map);
|
||||
+ dev_err(dev, "regmap init failed: %d\n", ret);
|
||||
+ return ERR_PTR(ret);
|
||||
+ }
|
||||
+
|
||||
+ rc.disable_locking = true;
|
||||
+ priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
|
||||
+ if (IS_ERR(priv->map_nolock)) {
|
||||
+ ret = PTR_ERR(priv->map_nolock);
|
||||
+ dev_err(dev, "regmap init failed: %d\n", ret);
|
||||
+ return ERR_PTR(ret);
|
||||
+ }
|
||||
+
|
||||
+ /* Link forward and backward */
|
||||
+ priv->dev = dev;
|
||||
+ priv->variant = var;
|
||||
+ priv->ops = var->ops;
|
||||
+ priv->chip_data = (void *)priv + sizeof(*priv);
|
||||
+
|
||||
+ spin_lock_init(&priv->lock);
|
||||
+
|
||||
+ priv->leds_disabled = of_property_read_bool(dev->of_node,
|
||||
+ "realtek,disable-leds");
|
||||
+
|
||||
+ /* TODO: if power is software controlled, set up any regulators here */
|
||||
+ priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
||||
+ if (IS_ERR(priv->reset)) {
|
||||
+ dev_err(dev, "failed to get RESET GPIO\n");
|
||||
+ return ERR_CAST(priv->reset);
|
||||
+ }
|
||||
+
|
||||
+ dev_set_drvdata(dev, priv);
|
||||
+
|
||||
+ if (priv->reset) {
|
||||
+ gpiod_set_value(priv->reset, 1);
|
||||
+ dev_dbg(dev, "asserted RESET\n");
|
||||
+ msleep(REALTEK_HW_STOP_DELAY);
|
||||
+ gpiod_set_value(priv->reset, 0);
|
||||
+ msleep(REALTEK_HW_START_DELAY);
|
||||
+ dev_dbg(dev, "deasserted RESET\n");
|
||||
+ }
|
||||
+
|
||||
+ return priv;
|
||||
+}
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl83xx_probe, REALTEK_DSA);
|
||||
+
|
||||
+/**
|
||||
+ * rtl83xx_register_switch() - detects and register a switch
|
||||
+ * @priv: realtek_priv pointer
|
||||
+ *
|
||||
+ * This function first checks the switch chip ID and register a DSA
|
||||
+ * switch.
|
||||
+ *
|
||||
+ * Context: Can sleep. Takes and releases priv->map_lock.
|
||||
+ * Return: 0 on success, negative value for failure.
|
||||
+ */
|
||||
+int rtl83xx_register_switch(struct realtek_priv *priv)
|
||||
+{
|
||||
+ struct dsa_switch *ds;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = priv->ops->detect(priv);
|
||||
+ if (ret) {
|
||||
+ dev_err_probe(priv->dev, ret, "unable to detect switch\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ds = devm_kzalloc(priv->dev, sizeof(*ds), GFP_KERNEL);
|
||||
+ if (!ds)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ds->priv = priv;
|
||||
+ ds->dev = priv->dev;
|
||||
+ ds->ops = priv->ds_ops;
|
||||
+ ds->num_ports = priv->num_ports;
|
||||
+ priv->ds = ds;
|
||||
+
|
||||
+ ret = dsa_register_switch(ds);
|
||||
+ if (ret) {
|
||||
+ dev_err_probe(priv->dev, ret, "unable to register switch\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl83xx_register_switch, REALTEK_DSA);
|
||||
+
|
||||
+/**
|
||||
+ * rtl83xx_unregister_switch() - unregister a switch
|
||||
+ * @priv: realtek_priv pointer
|
||||
+ *
|
||||
+ * This function unregister a DSA switch.
|
||||
+ *
|
||||
+ * Context: Can sleep.
|
||||
+ * Return: Nothing.
|
||||
+ */
|
||||
+void rtl83xx_unregister_switch(struct realtek_priv *priv)
|
||||
+{
|
||||
+ dsa_unregister_switch(priv->ds);
|
||||
+}
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl83xx_unregister_switch, REALTEK_DSA);
|
||||
+
|
||||
+/**
|
||||
+ * rtl83xx_shutdown() - shutdown a switch
|
||||
+ * @priv: realtek_priv pointer
|
||||
+ *
|
||||
+ * This function shuts down the DSA switch and cleans the platform driver data,
|
||||
+ * to prevent realtek_{smi,mdio}_remove() from running afterwards, which is
|
||||
+ * possible if the parent bus implements its own .shutdown() as .remove().
|
||||
+ *
|
||||
+ * Context: Can sleep.
|
||||
+ * Return: Nothing.
|
||||
+ */
|
||||
+void rtl83xx_shutdown(struct realtek_priv *priv)
|
||||
+{
|
||||
+ dsa_switch_shutdown(priv->ds);
|
||||
+
|
||||
+ dev_set_drvdata(priv->dev, NULL);
|
||||
+}
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl83xx_shutdown, REALTEK_DSA);
|
||||
+
|
||||
+/**
|
||||
+ * rtl83xx_remove() - Cleanup a realtek switch driver
|
||||
+ * @priv: realtek_priv pointer
|
||||
+ *
|
||||
+ * If a method is provided, this function asserts the hard reset of the switch
|
||||
+ * in order to avoid leaking traffic when the driver is gone.
|
||||
+ *
|
||||
+ * Context: Might sleep if priv->gdev->chip->can_sleep.
|
||||
+ * Return: nothing
|
||||
+ */
|
||||
+void rtl83xx_remove(struct realtek_priv *priv)
|
||||
+{
|
||||
+ /* leave the device reset asserted */
|
||||
+ if (priv->reset)
|
||||
+ gpiod_set_value(priv->reset, 1);
|
||||
+}
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, REALTEK_DSA);
|
||||
+
|
||||
+MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
|
||||
+MODULE_DESCRIPTION("Realtek DSA switches common module");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/dsa/realtek/rtl83xx.h
|
||||
@@ -0,0 +1,21 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
+
|
||||
+#ifndef _RTL83XX_H
|
||||
+#define _RTL83XX_H
|
||||
+
|
||||
+struct realtek_interface_info {
|
||||
+ int (*reg_read)(void *ctx, u32 reg, u32 *val);
|
||||
+ int (*reg_write)(void *ctx, u32 reg, u32 val);
|
||||
+};
|
||||
+
|
||||
+void rtl83xx_lock(void *ctx);
|
||||
+void rtl83xx_unlock(void *ctx);
|
||||
+struct realtek_priv *
|
||||
+rtl83xx_probe(struct device *dev,
|
||||
+ const struct realtek_interface_info *interface_info);
|
||||
+int rtl83xx_register_switch(struct realtek_priv *priv);
|
||||
+void rtl83xx_unregister_switch(struct realtek_priv *priv);
|
||||
+void rtl83xx_shutdown(struct realtek_priv *priv);
|
||||
+void rtl83xx_remove(struct realtek_priv *priv);
|
||||
+
|
||||
+#endif /* _RTL83XX_H */
|
@ -0,0 +1,93 @@
|
||||
From 98b75c1c149c653ad11a440636213eb070325158 Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Fri, 9 Feb 2024 02:03:42 -0300
|
||||
Subject: net: dsa: realtek: merge rtl83xx and interface
|
||||
modules into realtek_dsa
|
||||
|
||||
Since rtl83xx and realtek-{smi,mdio} are always loaded together,
|
||||
we can optimize resource usage by consolidating them into a single
|
||||
module.
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/realtek/Kconfig | 4 ++--
|
||||
drivers/net/dsa/realtek/Makefile | 11 +++++++++--
|
||||
drivers/net/dsa/realtek/realtek-mdio.c | 5 -----
|
||||
drivers/net/dsa/realtek/realtek-smi.c | 5 -----
|
||||
drivers/net/dsa/realtek/rtl83xx.c | 1 +
|
||||
5 files changed, 12 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/realtek/Kconfig
|
||||
+++ b/drivers/net/dsa/realtek/Kconfig
|
||||
@@ -16,14 +16,14 @@ menuconfig NET_DSA_REALTEK
|
||||
if NET_DSA_REALTEK
|
||||
|
||||
config NET_DSA_REALTEK_MDIO
|
||||
- tristate "Realtek MDIO interface support"
|
||||
+ bool "Realtek MDIO interface support"
|
||||
depends on OF
|
||||
help
|
||||
Select to enable support for registering switches configured
|
||||
through MDIO.
|
||||
|
||||
config NET_DSA_REALTEK_SMI
|
||||
- tristate "Realtek SMI interface support"
|
||||
+ bool "Realtek SMI interface support"
|
||||
depends on OF
|
||||
help
|
||||
Select to enable support for registering switches connected
|
||||
--- a/drivers/net/dsa/realtek/Makefile
|
||||
+++ b/drivers/net/dsa/realtek/Makefile
|
||||
@@ -1,8 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_NET_DSA_REALTEK) += realtek_dsa.o
|
||||
realtek_dsa-objs := rtl83xx.o
|
||||
-obj-$(CONFIG_NET_DSA_REALTEK_MDIO) += realtek-mdio.o
|
||||
-obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
|
||||
+
|
||||
+ifdef CONFIG_NET_DSA_REALTEK_MDIO
|
||||
+realtek_dsa-objs += realtek-mdio.o
|
||||
+endif
|
||||
+
|
||||
+ifdef CONFIG_NET_DSA_REALTEK_SMI
|
||||
+realtek_dsa-objs += realtek-smi.o
|
||||
+endif
|
||||
+
|
||||
obj-$(CONFIG_NET_DSA_REALTEK_RTL8366RB) += rtl8366.o
|
||||
rtl8366-objs := rtl8366-core.o rtl8366rb.o
|
||||
obj-$(CONFIG_NET_DSA_REALTEK_RTL8365MB) += rtl8365mb.o
|
||||
--- a/drivers/net/dsa/realtek/realtek-mdio.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
|
||||
@@ -186,8 +186,3 @@ void realtek_mdio_shutdown(struct mdio_d
|
||||
rtl83xx_shutdown(priv);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(realtek_mdio_shutdown, REALTEK_DSA);
|
||||
-
|
||||
-MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
|
||||
-MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface");
|
||||
-MODULE_LICENSE("GPL");
|
||||
-MODULE_IMPORT_NS(REALTEK_DSA);
|
||||
--- a/drivers/net/dsa/realtek/realtek-smi.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-smi.c
|
||||
@@ -470,8 +470,3 @@ void realtek_smi_shutdown(struct platfor
|
||||
rtl83xx_shutdown(priv);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(realtek_smi_shutdown, REALTEK_DSA);
|
||||
-
|
||||
-MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
|
||||
-MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
|
||||
-MODULE_LICENSE("GPL");
|
||||
-MODULE_IMPORT_NS(REALTEK_DSA);
|
||||
--- a/drivers/net/dsa/realtek/rtl83xx.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl83xx.c
|
||||
@@ -232,5 +232,6 @@ void rtl83xx_remove(struct realtek_priv
|
||||
EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, REALTEK_DSA);
|
||||
|
||||
MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
|
||||
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
|
||||
MODULE_DESCRIPTION("Realtek DSA switches common module");
|
||||
MODULE_LICENSE("GPL");
|
@ -0,0 +1,34 @@
|
||||
From 8685c98d45c54346caf005de69988e13c731c533 Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Fri, 9 Feb 2024 02:03:43 -0300
|
||||
Subject: net: dsa: realtek: get internal MDIO node by name
|
||||
|
||||
The binding docs requires for SMI-connected devices that the switch
|
||||
must have a child node named "mdio" and with a compatible string of
|
||||
"realtek,smi-mdio". Meanwile, for MDIO-connected switches, the binding
|
||||
docs only requires a child node named "mdio".
|
||||
|
||||
This patch changes the driver to use the common denominator for both
|
||||
interfaces, looking for the MDIO node by name, ignoring the compatible
|
||||
string.
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/realtek/realtek-smi.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/dsa/realtek/realtek-smi.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-smi.c
|
||||
@@ -333,7 +333,7 @@ static int realtek_smi_setup_mdio(struct
|
||||
struct device_node *mdio_np;
|
||||
int ret;
|
||||
|
||||
- mdio_np = of_get_compatible_child(priv->dev->of_node, "realtek,smi-mdio");
|
||||
+ mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio");
|
||||
if (!mdio_np) {
|
||||
dev_err(priv->dev, "no MDIO bus node\n");
|
||||
return -ENODEV;
|
@ -0,0 +1,83 @@
|
||||
From 68c66d8d8a19088967a0ab6bb98cb5ecc80ca0be Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Fri, 9 Feb 2024 02:03:44 -0300
|
||||
Subject: net: dsa: realtek: clean slave_mii_bus setup
|
||||
|
||||
Remove the line assigning dev.of_node in mdio_bus as subsequent
|
||||
of_mdiobus_register will always overwrite it.
|
||||
|
||||
As discussed in [1], allow the DSA core to be simplified, by not
|
||||
assigning ds->slave_mii_bus when the MDIO bus is described in OF, as it
|
||||
is unnecessary.
|
||||
|
||||
Since commit 3b73a7b8ec38 ("net: mdio_bus: add refcounting for fwnodes
|
||||
to mdiobus"), we can put the "mdio" node just after the MDIO bus
|
||||
registration.
|
||||
|
||||
[1] https://lkml.kernel.org/netdev/20231213120656.x46fyad6ls7sqyzv@skbuf/T/#u
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/realtek/realtek-smi.c | 13 +++----------
|
||||
1 file changed, 3 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/realtek/realtek-smi.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-smi.c
|
||||
@@ -331,7 +331,7 @@ static int realtek_smi_setup_mdio(struct
|
||||
{
|
||||
struct realtek_priv *priv = ds->priv;
|
||||
struct device_node *mdio_np;
|
||||
- int ret;
|
||||
+ int ret = 0;
|
||||
|
||||
mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio");
|
||||
if (!mdio_np) {
|
||||
@@ -344,15 +344,14 @@ static int realtek_smi_setup_mdio(struct
|
||||
ret = -ENOMEM;
|
||||
goto err_put_node;
|
||||
}
|
||||
+
|
||||
priv->slave_mii_bus->priv = priv;
|
||||
priv->slave_mii_bus->name = "SMI slave MII";
|
||||
priv->slave_mii_bus->read = realtek_smi_mdio_read;
|
||||
priv->slave_mii_bus->write = realtek_smi_mdio_write;
|
||||
snprintf(priv->slave_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
|
||||
ds->index);
|
||||
- priv->slave_mii_bus->dev.of_node = mdio_np;
|
||||
priv->slave_mii_bus->parent = priv->dev;
|
||||
- ds->slave_mii_bus = priv->slave_mii_bus;
|
||||
|
||||
ret = devm_of_mdiobus_register(priv->dev, priv->slave_mii_bus, mdio_np);
|
||||
if (ret) {
|
||||
@@ -361,8 +360,6 @@ static int realtek_smi_setup_mdio(struct
|
||||
goto err_put_node;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
-
|
||||
err_put_node:
|
||||
of_node_put(mdio_np);
|
||||
|
||||
@@ -428,8 +425,7 @@ EXPORT_SYMBOL_NS_GPL(realtek_smi_probe,
|
||||
* @pdev: platform_device to be removed.
|
||||
*
|
||||
* This function should be used as the .remove_new in a platform_driver. First
|
||||
- * it unregisters the DSA switch and cleans internal data. Finally, it calls
|
||||
- * the common remove function.
|
||||
+ * it unregisters the DSA switch and then it calls the common remove function.
|
||||
*
|
||||
* Context: Can sleep.
|
||||
* Return: Nothing.
|
||||
@@ -443,9 +439,6 @@ void realtek_smi_remove(struct platform_
|
||||
|
||||
rtl83xx_unregister_switch(priv);
|
||||
|
||||
- if (priv->slave_mii_bus)
|
||||
- of_node_put(priv->slave_mii_bus->dev.of_node);
|
||||
-
|
||||
rtl83xx_remove(priv);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(realtek_smi_remove, REALTEK_DSA);
|
@ -0,0 +1,198 @@
|
||||
From b4bd77971f3c290c4694ed710cc6967593b10bc2 Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Fri, 9 Feb 2024 02:03:45 -0300
|
||||
Subject: net: dsa: realtek: migrate slave_mii_bus setup to
|
||||
realtek_dsa
|
||||
|
||||
In the user MDIO driver, despite numerous references to SMI, including
|
||||
its compatible string, there's nothing inherently specific about the SMI
|
||||
interface in the user MDIO bus. Consequently, the code has been migrated
|
||||
to the rtl83xx module. All references to SMI have been eliminated.
|
||||
|
||||
The MDIO bus id was changed from Realtek-<switch id> to the switch
|
||||
devname suffixed with :slave_mii, giving more information about the bus
|
||||
it is referencing.
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/realtek/realtek-smi.c | 57 +---------------------
|
||||
drivers/net/dsa/realtek/rtl83xx.c | 68 +++++++++++++++++++++++++++
|
||||
drivers/net/dsa/realtek/rtl83xx.h | 1 +
|
||||
3 files changed, 70 insertions(+), 56 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/realtek/realtek-smi.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-smi.c
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/of.h>
|
||||
-#include <linux/of_mdio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -312,60 +311,6 @@ static int realtek_smi_read(void *ctx, u
|
||||
return realtek_smi_read_reg(priv, reg, val);
|
||||
}
|
||||
|
||||
-static int realtek_smi_mdio_read(struct mii_bus *bus, int addr, int regnum)
|
||||
-{
|
||||
- struct realtek_priv *priv = bus->priv;
|
||||
-
|
||||
- return priv->ops->phy_read(priv, addr, regnum);
|
||||
-}
|
||||
-
|
||||
-static int realtek_smi_mdio_write(struct mii_bus *bus, int addr, int regnum,
|
||||
- u16 val)
|
||||
-{
|
||||
- struct realtek_priv *priv = bus->priv;
|
||||
-
|
||||
- return priv->ops->phy_write(priv, addr, regnum, val);
|
||||
-}
|
||||
-
|
||||
-static int realtek_smi_setup_mdio(struct dsa_switch *ds)
|
||||
-{
|
||||
- struct realtek_priv *priv = ds->priv;
|
||||
- struct device_node *mdio_np;
|
||||
- int ret = 0;
|
||||
-
|
||||
- mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio");
|
||||
- if (!mdio_np) {
|
||||
- dev_err(priv->dev, "no MDIO bus node\n");
|
||||
- return -ENODEV;
|
||||
- }
|
||||
-
|
||||
- priv->slave_mii_bus = devm_mdiobus_alloc(priv->dev);
|
||||
- if (!priv->slave_mii_bus) {
|
||||
- ret = -ENOMEM;
|
||||
- goto err_put_node;
|
||||
- }
|
||||
-
|
||||
- priv->slave_mii_bus->priv = priv;
|
||||
- priv->slave_mii_bus->name = "SMI slave MII";
|
||||
- priv->slave_mii_bus->read = realtek_smi_mdio_read;
|
||||
- priv->slave_mii_bus->write = realtek_smi_mdio_write;
|
||||
- snprintf(priv->slave_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
|
||||
- ds->index);
|
||||
- priv->slave_mii_bus->parent = priv->dev;
|
||||
-
|
||||
- ret = devm_of_mdiobus_register(priv->dev, priv->slave_mii_bus, mdio_np);
|
||||
- if (ret) {
|
||||
- dev_err(priv->dev, "unable to register MDIO bus %s\n",
|
||||
- priv->slave_mii_bus->id);
|
||||
- goto err_put_node;
|
||||
- }
|
||||
-
|
||||
-err_put_node:
|
||||
- of_node_put(mdio_np);
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
static const struct realtek_interface_info realtek_smi_info = {
|
||||
.reg_read = realtek_smi_read,
|
||||
.reg_write = realtek_smi_write,
|
||||
@@ -407,7 +352,7 @@ int realtek_smi_probe(struct platform_de
|
||||
}
|
||||
|
||||
priv->write_reg_noack = realtek_smi_write_reg_noack;
|
||||
- priv->setup_interface = realtek_smi_setup_mdio;
|
||||
+ priv->setup_interface = rtl83xx_setup_user_mdio;
|
||||
priv->ds_ops = priv->variant->ds_ops_smi;
|
||||
|
||||
ret = rtl83xx_register_switch(priv);
|
||||
--- a/drivers/net/dsa/realtek/rtl83xx.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl83xx.c
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/of_device.h> /* krnl 6.1 only */
|
||||
+#include <linux/of_mdio.h>
|
||||
|
||||
#include "realtek.h"
|
||||
#include "rtl83xx.h"
|
||||
@@ -44,6 +45,73 @@ void rtl83xx_unlock(void *ctx)
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(rtl83xx_unlock, REALTEK_DSA);
|
||||
|
||||
+static int rtl83xx_user_mdio_read(struct mii_bus *bus, int addr, int regnum)
|
||||
+{
|
||||
+ struct realtek_priv *priv = bus->priv;
|
||||
+
|
||||
+ return priv->ops->phy_read(priv, addr, regnum);
|
||||
+}
|
||||
+
|
||||
+static int rtl83xx_user_mdio_write(struct mii_bus *bus, int addr, int regnum,
|
||||
+ u16 val)
|
||||
+{
|
||||
+ struct realtek_priv *priv = bus->priv;
|
||||
+
|
||||
+ return priv->ops->phy_write(priv, addr, regnum, val);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * rtl83xx_setup_user_mdio() - register the user mii bus driver
|
||||
+ * @ds: DSA switch associated with this slave_mii_bus
|
||||
+ *
|
||||
+ * Registers the MDIO bus for built-in Ethernet PHYs, and associates it with
|
||||
+ * the mandatory 'mdio' child OF node of the switch.
|
||||
+ *
|
||||
+ * Context: Can sleep.
|
||||
+ * Return: 0 on success, negative value for failure.
|
||||
+ */
|
||||
+int rtl83xx_setup_user_mdio(struct dsa_switch *ds)
|
||||
+{
|
||||
+ struct realtek_priv *priv = ds->priv;
|
||||
+ struct device_node *mdio_np;
|
||||
+ struct mii_bus *bus;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio");
|
||||
+ if (!mdio_np) {
|
||||
+ dev_err(priv->dev, "no MDIO bus node\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ bus = devm_mdiobus_alloc(priv->dev);
|
||||
+ if (!bus) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_put_node;
|
||||
+ }
|
||||
+
|
||||
+ bus->priv = priv;
|
||||
+ bus->name = "Realtek user MII";
|
||||
+ bus->read = rtl83xx_user_mdio_read;
|
||||
+ bus->write = rtl83xx_user_mdio_write;
|
||||
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s:slave_mii", dev_name(priv->dev));
|
||||
+ bus->parent = priv->dev;
|
||||
+
|
||||
+ ret = devm_of_mdiobus_register(priv->dev, bus, mdio_np);
|
||||
+ if (ret) {
|
||||
+ dev_err(priv->dev, "unable to register MDIO bus %s\n",
|
||||
+ bus->id);
|
||||
+ goto err_put_node;
|
||||
+ }
|
||||
+
|
||||
+ priv->slave_mii_bus = bus;
|
||||
+
|
||||
+err_put_node:
|
||||
+ of_node_put(mdio_np);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL_NS_GPL(rtl83xx_setup_user_mdio, REALTEK_DSA);
|
||||
+
|
||||
/**
|
||||
* rtl83xx_probe() - probe a Realtek switch
|
||||
* @dev: the device being probed
|
||||
--- a/drivers/net/dsa/realtek/rtl83xx.h
|
||||
+++ b/drivers/net/dsa/realtek/rtl83xx.h
|
||||
@@ -10,6 +10,7 @@ struct realtek_interface_info {
|
||||
|
||||
void rtl83xx_lock(void *ctx);
|
||||
void rtl83xx_unlock(void *ctx);
|
||||
+int rtl83xx_setup_user_mdio(struct dsa_switch *ds);
|
||||
struct realtek_priv *
|
||||
rtl83xx_probe(struct device *dev,
|
||||
const struct realtek_interface_info *interface_info);
|
@ -0,0 +1,261 @@
|
||||
From bba140a566ed075304c49c52ab32c0016cab624a Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Fri, 9 Feb 2024 02:03:46 -0300
|
||||
Subject: net: dsa: realtek: use the same mii bus driver for
|
||||
both interfaces
|
||||
|
||||
The realtek-mdio will now use this driver instead of the generic DSA
|
||||
driver ("dsa user smi"), which should not be used with OF[1].
|
||||
|
||||
With a single ds_ops for both interfaces, the ds_ops in realtek_priv is
|
||||
no longer necessary. Now, the realtek_variant.ds_ops can be used
|
||||
directly.
|
||||
|
||||
The realtek_priv.setup_interface() has been removed as we can directly
|
||||
call the new common function.
|
||||
|
||||
[1] https://lkml.kernel.org/netdev/20220630200423.tieprdu5fpabflj7@bang-olufsen.dk/T/
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/realtek/realtek-mdio.c | 1 -
|
||||
drivers/net/dsa/realtek/realtek-smi.c | 2 -
|
||||
drivers/net/dsa/realtek/realtek.h | 5 +--
|
||||
drivers/net/dsa/realtek/rtl8365mb.c | 49 +++---------------------
|
||||
drivers/net/dsa/realtek/rtl8366rb.c | 52 +++-----------------------
|
||||
drivers/net/dsa/realtek/rtl83xx.c | 2 +-
|
||||
6 files changed, 14 insertions(+), 97 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/realtek/realtek-mdio.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
|
||||
@@ -131,7 +131,6 @@ int realtek_mdio_probe(struct mdio_devic
|
||||
priv->bus = mdiodev->bus;
|
||||
priv->mdio_addr = mdiodev->addr;
|
||||
priv->write_reg_noack = realtek_mdio_write;
|
||||
- priv->ds_ops = priv->variant->ds_ops_mdio;
|
||||
|
||||
ret = rtl83xx_register_switch(priv);
|
||||
if (ret) {
|
||||
--- a/drivers/net/dsa/realtek/realtek-smi.c
|
||||
+++ b/drivers/net/dsa/realtek/realtek-smi.c
|
||||
@@ -352,8 +352,6 @@ int realtek_smi_probe(struct platform_de
|
||||
}
|
||||
|
||||
priv->write_reg_noack = realtek_smi_write_reg_noack;
|
||||
- priv->setup_interface = rtl83xx_setup_user_mdio;
|
||||
- priv->ds_ops = priv->variant->ds_ops_smi;
|
||||
|
||||
ret = rtl83xx_register_switch(priv);
|
||||
if (ret) {
|
||||
--- a/drivers/net/dsa/realtek/realtek.h
|
||||
+++ b/drivers/net/dsa/realtek/realtek.h
|
||||
@@ -62,7 +62,6 @@ struct realtek_priv {
|
||||
|
||||
spinlock_t lock; /* Locks around command writes */
|
||||
struct dsa_switch *ds;
|
||||
- const struct dsa_switch_ops *ds_ops;
|
||||
struct irq_domain *irqdomain;
|
||||
bool leds_disabled;
|
||||
|
||||
@@ -73,7 +72,6 @@ struct realtek_priv {
|
||||
struct rtl8366_mib_counter *mib_counters;
|
||||
|
||||
const struct realtek_ops *ops;
|
||||
- int (*setup_interface)(struct dsa_switch *ds);
|
||||
int (*write_reg_noack)(void *ctx, u32 addr, u32 data);
|
||||
|
||||
int vlan_enabled;
|
||||
@@ -115,8 +113,7 @@ struct realtek_ops {
|
||||
};
|
||||
|
||||
struct realtek_variant {
|
||||
- const struct dsa_switch_ops *ds_ops_smi;
|
||||
- const struct dsa_switch_ops *ds_ops_mdio;
|
||||
+ const struct dsa_switch_ops *ds_ops;
|
||||
const struct realtek_ops *ops;
|
||||
unsigned int clk_delay;
|
||||
u8 cmd_read;
|
||||
--- a/drivers/net/dsa/realtek/rtl8365mb.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
|
||||
@@ -828,17 +828,6 @@ static int rtl8365mb_phy_write(struct re
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int rtl8365mb_dsa_phy_read(struct dsa_switch *ds, int phy, int regnum)
|
||||
-{
|
||||
- return rtl8365mb_phy_read(ds->priv, phy, regnum);
|
||||
-}
|
||||
-
|
||||
-static int rtl8365mb_dsa_phy_write(struct dsa_switch *ds, int phy, int regnum,
|
||||
- u16 val)
|
||||
-{
|
||||
- return rtl8365mb_phy_write(ds->priv, phy, regnum, val);
|
||||
-}
|
||||
-
|
||||
static const struct rtl8365mb_extint *
|
||||
rtl8365mb_get_port_extint(struct realtek_priv *priv, int port)
|
||||
{
|
||||
@@ -2018,12 +2007,10 @@ static int rtl8365mb_setup(struct dsa_sw
|
||||
if (ret)
|
||||
goto out_teardown_irq;
|
||||
|
||||
- if (priv->setup_interface) {
|
||||
- ret = priv->setup_interface(ds);
|
||||
- if (ret) {
|
||||
- dev_err(priv->dev, "could not set up MDIO bus\n");
|
||||
- goto out_teardown_irq;
|
||||
- }
|
||||
+ ret = rtl83xx_setup_user_mdio(ds);
|
||||
+ if (ret) {
|
||||
+ dev_err(priv->dev, "could not set up MDIO bus\n");
|
||||
+ goto out_teardown_irq;
|
||||
}
|
||||
|
||||
/* Start statistics counter polling */
|
||||
@@ -2117,28 +2104,7 @@ static int rtl8365mb_detect(struct realt
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static const struct dsa_switch_ops rtl8365mb_switch_ops_smi = {
|
||||
- .get_tag_protocol = rtl8365mb_get_tag_protocol,
|
||||
- .change_tag_protocol = rtl8365mb_change_tag_protocol,
|
||||
- .setup = rtl8365mb_setup,
|
||||
- .teardown = rtl8365mb_teardown,
|
||||
- .phylink_get_caps = rtl8365mb_phylink_get_caps,
|
||||
- .phylink_mac_config = rtl8365mb_phylink_mac_config,
|
||||
- .phylink_mac_link_down = rtl8365mb_phylink_mac_link_down,
|
||||
- .phylink_mac_link_up = rtl8365mb_phylink_mac_link_up,
|
||||
- .port_stp_state_set = rtl8365mb_port_stp_state_set,
|
||||
- .get_strings = rtl8365mb_get_strings,
|
||||
- .get_ethtool_stats = rtl8365mb_get_ethtool_stats,
|
||||
- .get_sset_count = rtl8365mb_get_sset_count,
|
||||
- .get_eth_phy_stats = rtl8365mb_get_phy_stats,
|
||||
- .get_eth_mac_stats = rtl8365mb_get_mac_stats,
|
||||
- .get_eth_ctrl_stats = rtl8365mb_get_ctrl_stats,
|
||||
- .get_stats64 = rtl8365mb_get_stats64,
|
||||
- .port_change_mtu = rtl8365mb_port_change_mtu,
|
||||
- .port_max_mtu = rtl8365mb_port_max_mtu,
|
||||
-};
|
||||
-
|
||||
-static const struct dsa_switch_ops rtl8365mb_switch_ops_mdio = {
|
||||
+static const struct dsa_switch_ops rtl8365mb_switch_ops = {
|
||||
.get_tag_protocol = rtl8365mb_get_tag_protocol,
|
||||
.change_tag_protocol = rtl8365mb_change_tag_protocol,
|
||||
.setup = rtl8365mb_setup,
|
||||
@@ -2147,8 +2113,6 @@ static const struct dsa_switch_ops rtl83
|
||||
.phylink_mac_config = rtl8365mb_phylink_mac_config,
|
||||
.phylink_mac_link_down = rtl8365mb_phylink_mac_link_down,
|
||||
.phylink_mac_link_up = rtl8365mb_phylink_mac_link_up,
|
||||
- .phy_read = rtl8365mb_dsa_phy_read,
|
||||
- .phy_write = rtl8365mb_dsa_phy_write,
|
||||
.port_stp_state_set = rtl8365mb_port_stp_state_set,
|
||||
.get_strings = rtl8365mb_get_strings,
|
||||
.get_ethtool_stats = rtl8365mb_get_ethtool_stats,
|
||||
@@ -2168,8 +2132,7 @@ static const struct realtek_ops rtl8365m
|
||||
};
|
||||
|
||||
const struct realtek_variant rtl8365mb_variant = {
|
||||
- .ds_ops_smi = &rtl8365mb_switch_ops_smi,
|
||||
- .ds_ops_mdio = &rtl8365mb_switch_ops_mdio,
|
||||
+ .ds_ops = &rtl8365mb_switch_ops,
|
||||
.ops = &rtl8365mb_ops,
|
||||
.clk_delay = 10,
|
||||
.cmd_read = 0xb9,
|
||||
--- a/drivers/net/dsa/realtek/rtl8366rb.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
|
||||
@@ -1035,12 +1035,10 @@ static int rtl8366rb_setup(struct dsa_sw
|
||||
if (ret)
|
||||
dev_info(priv->dev, "no interrupt support\n");
|
||||
|
||||
- if (priv->setup_interface) {
|
||||
- ret = priv->setup_interface(ds);
|
||||
- if (ret) {
|
||||
- dev_err(priv->dev, "could not set up MDIO bus\n");
|
||||
- return -ENODEV;
|
||||
- }
|
||||
+ ret = rtl83xx_setup_user_mdio(ds);
|
||||
+ if (ret) {
|
||||
+ dev_err(priv->dev, "could not set up MDIO bus\n");
|
||||
+ return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1699,17 +1697,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int rtl8366rb_dsa_phy_read(struct dsa_switch *ds, int phy, int regnum)
|
||||
-{
|
||||
- return rtl8366rb_phy_read(ds->priv, phy, regnum);
|
||||
-}
|
||||
-
|
||||
-static int rtl8366rb_dsa_phy_write(struct dsa_switch *ds, int phy, int regnum,
|
||||
- u16 val)
|
||||
-{
|
||||
- return rtl8366rb_phy_write(ds->priv, phy, regnum, val);
|
||||
-}
|
||||
-
|
||||
static int rtl8366rb_reset_chip(struct realtek_priv *priv)
|
||||
{
|
||||
int timeout = 10;
|
||||
@@ -1775,35 +1762,9 @@ static int rtl8366rb_detect(struct realt
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static const struct dsa_switch_ops rtl8366rb_switch_ops_smi = {
|
||||
- .get_tag_protocol = rtl8366_get_tag_protocol,
|
||||
- .setup = rtl8366rb_setup,
|
||||
- .phylink_get_caps = rtl8366rb_phylink_get_caps,
|
||||
- .phylink_mac_link_up = rtl8366rb_mac_link_up,
|
||||
- .phylink_mac_link_down = rtl8366rb_mac_link_down,
|
||||
- .get_strings = rtl8366_get_strings,
|
||||
- .get_ethtool_stats = rtl8366_get_ethtool_stats,
|
||||
- .get_sset_count = rtl8366_get_sset_count,
|
||||
- .port_bridge_join = rtl8366rb_port_bridge_join,
|
||||
- .port_bridge_leave = rtl8366rb_port_bridge_leave,
|
||||
- .port_vlan_filtering = rtl8366rb_vlan_filtering,
|
||||
- .port_vlan_add = rtl8366_vlan_add,
|
||||
- .port_vlan_del = rtl8366_vlan_del,
|
||||
- .port_enable = rtl8366rb_port_enable,
|
||||
- .port_disable = rtl8366rb_port_disable,
|
||||
- .port_pre_bridge_flags = rtl8366rb_port_pre_bridge_flags,
|
||||
- .port_bridge_flags = rtl8366rb_port_bridge_flags,
|
||||
- .port_stp_state_set = rtl8366rb_port_stp_state_set,
|
||||
- .port_fast_age = rtl8366rb_port_fast_age,
|
||||
- .port_change_mtu = rtl8366rb_change_mtu,
|
||||
- .port_max_mtu = rtl8366rb_max_mtu,
|
||||
-};
|
||||
-
|
||||
-static const struct dsa_switch_ops rtl8366rb_switch_ops_mdio = {
|
||||
+static const struct dsa_switch_ops rtl8366rb_switch_ops = {
|
||||
.get_tag_protocol = rtl8366_get_tag_protocol,
|
||||
.setup = rtl8366rb_setup,
|
||||
- .phy_read = rtl8366rb_dsa_phy_read,
|
||||
- .phy_write = rtl8366rb_dsa_phy_write,
|
||||
.phylink_get_caps = rtl8366rb_phylink_get_caps,
|
||||
.phylink_mac_link_up = rtl8366rb_mac_link_up,
|
||||
.phylink_mac_link_down = rtl8366rb_mac_link_down,
|
||||
@@ -1842,8 +1803,7 @@ static const struct realtek_ops rtl8366r
|
||||
};
|
||||
|
||||
const struct realtek_variant rtl8366rb_variant = {
|
||||
- .ds_ops_smi = &rtl8366rb_switch_ops_smi,
|
||||
- .ds_ops_mdio = &rtl8366rb_switch_ops_mdio,
|
||||
+ .ds_ops = &rtl8366rb_switch_ops,
|
||||
.ops = &rtl8366rb_ops,
|
||||
.clk_delay = 10,
|
||||
.cmd_read = 0xa9,
|
||||
--- a/drivers/net/dsa/realtek/rtl83xx.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl83xx.c
|
||||
@@ -233,7 +233,7 @@ int rtl83xx_register_switch(struct realt
|
||||
|
||||
ds->priv = priv;
|
||||
ds->dev = priv->dev;
|
||||
- ds->ops = priv->ds_ops;
|
||||
+ ds->ops = priv->variant->ds_ops;
|
||||
ds->num_ports = priv->num_ports;
|
||||
priv->ds = ds;
|
||||
|
@ -0,0 +1,180 @@
|
||||
From 9fc469b2943d9b1ff2a7800f823e7cd7a5cac0ca Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Fri, 9 Feb 2024 02:03:47 -0300
|
||||
Subject: net: dsa: realtek: embed dsa_switch into realtek_priv
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Embed dsa_switch within realtek_priv to eliminate the need for a second
|
||||
memory allocation.
|
||||
|
||||
Suggested-by: Alvin Šipraga <alsi@bang-olufsen.dk>
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/realtek/realtek.h | 2 +-
|
||||
drivers/net/dsa/realtek/rtl8365mb.c | 15 +++++++++------
|
||||
drivers/net/dsa/realtek/rtl8366rb.c | 3 ++-
|
||||
drivers/net/dsa/realtek/rtl83xx.c | 15 +++++++--------
|
||||
4 files changed, 19 insertions(+), 16 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/realtek/realtek.h
|
||||
+++ b/drivers/net/dsa/realtek/realtek.h
|
||||
@@ -61,7 +61,7 @@ struct realtek_priv {
|
||||
const struct realtek_variant *variant;
|
||||
|
||||
spinlock_t lock; /* Locks around command writes */
|
||||
- struct dsa_switch *ds;
|
||||
+ struct dsa_switch ds;
|
||||
struct irq_domain *irqdomain;
|
||||
bool leds_disabled;
|
||||
|
||||
--- a/drivers/net/dsa/realtek/rtl8365mb.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
|
||||
@@ -870,6 +870,7 @@ static int rtl8365mb_ext_config_rgmii(st
|
||||
{
|
||||
const struct rtl8365mb_extint *extint =
|
||||
rtl8365mb_get_port_extint(priv, port);
|
||||
+ struct dsa_switch *ds = &priv->ds;
|
||||
struct device_node *dn;
|
||||
struct dsa_port *dp;
|
||||
int tx_delay = 0;
|
||||
@@ -880,7 +881,7 @@ static int rtl8365mb_ext_config_rgmii(st
|
||||
if (!extint)
|
||||
return -ENODEV;
|
||||
|
||||
- dp = dsa_to_port(priv->ds, port);
|
||||
+ dp = dsa_to_port(ds, port);
|
||||
dn = dp->dn;
|
||||
|
||||
/* Set the RGMII TX/RX delay
|
||||
@@ -1534,6 +1535,7 @@ static void rtl8365mb_get_stats64(struct
|
||||
static void rtl8365mb_stats_setup(struct realtek_priv *priv)
|
||||
{
|
||||
struct rtl8365mb *mb = priv->chip_data;
|
||||
+ struct dsa_switch *ds = &priv->ds;
|
||||
int i;
|
||||
|
||||
/* Per-chip global mutex to protect MIB counter access, since doing
|
||||
@@ -1544,7 +1546,7 @@ static void rtl8365mb_stats_setup(struct
|
||||
for (i = 0; i < priv->num_ports; i++) {
|
||||
struct rtl8365mb_port *p = &mb->ports[i];
|
||||
|
||||
- if (dsa_is_unused_port(priv->ds, i))
|
||||
+ if (dsa_is_unused_port(ds, i))
|
||||
continue;
|
||||
|
||||
/* Per-port spinlock to protect the stats64 data */
|
||||
@@ -1560,12 +1562,13 @@ static void rtl8365mb_stats_setup(struct
|
||||
static void rtl8365mb_stats_teardown(struct realtek_priv *priv)
|
||||
{
|
||||
struct rtl8365mb *mb = priv->chip_data;
|
||||
+ struct dsa_switch *ds = &priv->ds;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->num_ports; i++) {
|
||||
struct rtl8365mb_port *p = &mb->ports[i];
|
||||
|
||||
- if (dsa_is_unused_port(priv->ds, i))
|
||||
+ if (dsa_is_unused_port(ds, i))
|
||||
continue;
|
||||
|
||||
cancel_delayed_work_sync(&p->mib_work);
|
||||
@@ -1964,7 +1967,7 @@ static int rtl8365mb_setup(struct dsa_sw
|
||||
dev_info(priv->dev, "no interrupt support\n");
|
||||
|
||||
/* Configure CPU tagging */
|
||||
- dsa_switch_for_each_cpu_port(cpu_dp, priv->ds) {
|
||||
+ dsa_switch_for_each_cpu_port(cpu_dp, ds) {
|
||||
cpu->mask |= BIT(cpu_dp->index);
|
||||
|
||||
if (cpu->trap_port == RTL8365MB_MAX_NUM_PORTS)
|
||||
@@ -1979,7 +1982,7 @@ static int rtl8365mb_setup(struct dsa_sw
|
||||
for (i = 0; i < priv->num_ports; i++) {
|
||||
struct rtl8365mb_port *p = &mb->ports[i];
|
||||
|
||||
- if (dsa_is_unused_port(priv->ds, i))
|
||||
+ if (dsa_is_unused_port(ds, i))
|
||||
continue;
|
||||
|
||||
/* Forward only to the CPU */
|
||||
@@ -1996,7 +1999,7 @@ static int rtl8365mb_setup(struct dsa_sw
|
||||
* ports will still forward frames to the CPU despite being
|
||||
* administratively down by default.
|
||||
*/
|
||||
- rtl8365mb_port_stp_state_set(priv->ds, i, BR_STATE_DISABLED);
|
||||
+ rtl8365mb_port_stp_state_set(ds, i, BR_STATE_DISABLED);
|
||||
|
||||
/* Set up per-port private data */
|
||||
p->priv = priv;
|
||||
--- a/drivers/net/dsa/realtek/rtl8366rb.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
|
||||
@@ -1565,6 +1565,7 @@ static int rtl8366rb_get_mc_index(struct
|
||||
|
||||
static int rtl8366rb_set_mc_index(struct realtek_priv *priv, int port, int index)
|
||||
{
|
||||
+ struct dsa_switch *ds = &priv->ds;
|
||||
struct rtl8366rb *rb;
|
||||
bool pvid_enabled;
|
||||
int ret;
|
||||
@@ -1589,7 +1590,7 @@ static int rtl8366rb_set_mc_index(struct
|
||||
* not drop any untagged or C-tagged frames. Make sure to update the
|
||||
* filtering setting.
|
||||
*/
|
||||
- if (dsa_port_is_vlan_filtering(dsa_to_port(priv->ds, port)))
|
||||
+ if (dsa_port_is_vlan_filtering(dsa_to_port(ds, port)))
|
||||
ret = rtl8366rb_drop_untagged(priv, port, !pvid_enabled);
|
||||
|
||||
return ret;
|
||||
--- a/drivers/net/dsa/realtek/rtl83xx.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl83xx.c
|
||||
@@ -218,7 +218,7 @@ EXPORT_SYMBOL_NS_GPL(rtl83xx_probe, REAL
|
||||
*/
|
||||
int rtl83xx_register_switch(struct realtek_priv *priv)
|
||||
{
|
||||
- struct dsa_switch *ds;
|
||||
+ struct dsa_switch *ds = &priv->ds;
|
||||
int ret;
|
||||
|
||||
ret = priv->ops->detect(priv);
|
||||
@@ -227,15 +227,10 @@ int rtl83xx_register_switch(struct realt
|
||||
return ret;
|
||||
}
|
||||
|
||||
- ds = devm_kzalloc(priv->dev, sizeof(*ds), GFP_KERNEL);
|
||||
- if (!ds)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
ds->priv = priv;
|
||||
ds->dev = priv->dev;
|
||||
ds->ops = priv->variant->ds_ops;
|
||||
ds->num_ports = priv->num_ports;
|
||||
- priv->ds = ds;
|
||||
|
||||
ret = dsa_register_switch(ds);
|
||||
if (ret) {
|
||||
@@ -258,7 +253,9 @@ EXPORT_SYMBOL_NS_GPL(rtl83xx_register_sw
|
||||
*/
|
||||
void rtl83xx_unregister_switch(struct realtek_priv *priv)
|
||||
{
|
||||
- dsa_unregister_switch(priv->ds);
|
||||
+ struct dsa_switch *ds = &priv->ds;
|
||||
+
|
||||
+ dsa_unregister_switch(ds);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(rtl83xx_unregister_switch, REALTEK_DSA);
|
||||
|
||||
@@ -275,7 +272,9 @@ EXPORT_SYMBOL_NS_GPL(rtl83xx_unregister_
|
||||
*/
|
||||
void rtl83xx_shutdown(struct realtek_priv *priv)
|
||||
{
|
||||
- dsa_switch_shutdown(priv->ds);
|
||||
+ struct dsa_switch *ds = &priv->ds;
|
||||
+
|
||||
+ dsa_switch_shutdown(ds);
|
||||
|
||||
dev_set_drvdata(priv->dev, NULL);
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
From 32e4a5447ed9fa904a2dfcf4609c64bce053b4e8 Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Mon, 12 Feb 2024 18:34:33 -0300
|
||||
Subject: [PATCH] net: dsa: realtek: fix digital interface select macro for
|
||||
EXT0
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
While no supported devices currently utilize EXT0, the register reserves
|
||||
the bits for an EXT0. EXT0 is utilized by devices from the generation
|
||||
prior to rtl8365mb, such as those supported by the driver library
|
||||
rtl8367b.
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20240212-realtek-fix_ext0-v1-1-f3d2536d191a@gmail.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/dsa/realtek/rtl8365mb.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/realtek/rtl8365mb.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
|
||||
@@ -209,10 +209,10 @@
|
||||
#define RTL8365MB_EXT_PORT_MODE_100FX 13
|
||||
|
||||
/* External interface mode configuration registers 0~1 */
|
||||
-#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG0 0x1305 /* EXT1 */
|
||||
+#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG0 0x1305 /* EXT0,EXT1 */
|
||||
#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG1 0x13C3 /* EXT2 */
|
||||
#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG(_extint) \
|
||||
- ((_extint) == 1 ? RTL8365MB_DIGITAL_INTERFACE_SELECT_REG0 : \
|
||||
+ ((_extint) <= 1 ? RTL8365MB_DIGITAL_INTERFACE_SELECT_REG0 : \
|
||||
(_extint) == 2 ? RTL8365MB_DIGITAL_INTERFACE_SELECT_REG1 : \
|
||||
0x0)
|
||||
#define RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_MASK(_extint) \
|
@ -0,0 +1,34 @@
|
||||
From 28001bb1955fcfa63e535848c4289fcd7bb88daf Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Sun, 25 Feb 2024 13:29:53 -0300
|
||||
Subject: [PATCH 1/3] dt-bindings: net: dsa: realtek: reset-gpios is not
|
||||
required
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The 'reset-gpios' should not be mandatory. although they might be
|
||||
required for some devices if the switch reset was left asserted by a
|
||||
previous driver, such as the bootloader.
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Cc: devicetree@vger.kernel.org
|
||||
Acked-by: Arınç ÜNAL <arinc.unal@arinc9.com>
|
||||
Acked-by: Rob Herring <robh@kernel.org>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
Documentation/devicetree/bindings/net/dsa/realtek.yaml | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/net/dsa/realtek.yaml
|
||||
+++ b/Documentation/devicetree/bindings/net/dsa/realtek.yaml
|
||||
@@ -125,7 +125,6 @@ else:
|
||||
- mdc-gpios
|
||||
- mdio-gpios
|
||||
- mdio
|
||||
- - reset-gpios
|
||||
|
||||
required:
|
||||
- compatible
|
@ -0,0 +1,33 @@
|
||||
From 5fc2d68fc81801162188995e4d3dc0b26747dd76 Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Sun, 25 Feb 2024 13:29:54 -0300
|
||||
Subject: [PATCH 2/3] dt-bindings: net: dsa: realtek: add reset controller
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Realtek switches can use a reset controller instead of reset-gpios.
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Cc: devicetree@vger.kernel.org
|
||||
Acked-by: Arınç ÜNAL <arinc.unal@arinc9.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
|
||||
Acked-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
Documentation/devicetree/bindings/net/dsa/realtek.yaml | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/net/dsa/realtek.yaml
|
||||
+++ b/Documentation/devicetree/bindings/net/dsa/realtek.yaml
|
||||
@@ -59,6 +59,9 @@ properties:
|
||||
description: GPIO to be used to reset the whole device
|
||||
maxItems: 1
|
||||
|
||||
+ resets:
|
||||
+ maxItems: 1
|
||||
+
|
||||
realtek,disable-leds:
|
||||
type: boolean
|
||||
description: |
|
@ -0,0 +1,123 @@
|
||||
From 56998aa6b7f0f31ce8df23c00701af2d8e8a1f1a Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Sun, 25 Feb 2024 13:29:55 -0300
|
||||
Subject: [PATCH 3/3] net: dsa: realtek: support reset controller
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add support for resetting the device using a reset controller,
|
||||
complementing the existing GPIO reset functionality (reset-gpios).
|
||||
|
||||
Although the reset is optional and the driver performs a soft reset
|
||||
during setup, if the initial reset pin state was asserted, the driver
|
||||
will not detect the device until the reset is deasserted.
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/realtek/realtek.h | 2 ++
|
||||
drivers/net/dsa/realtek/rtl83xx.c | 42 +++++++++++++++++++++++++++----
|
||||
drivers/net/dsa/realtek/rtl83xx.h | 2 ++
|
||||
3 files changed, 41 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/realtek/realtek.h
|
||||
+++ b/drivers/net/dsa/realtek/realtek.h
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <net/dsa.h>
|
||||
+#include <linux/reset.h>
|
||||
|
||||
#define REALTEK_HW_STOP_DELAY 25 /* msecs */
|
||||
#define REALTEK_HW_START_DELAY 100 /* msecs */
|
||||
@@ -48,6 +49,7 @@ struct rtl8366_vlan_4k {
|
||||
|
||||
struct realtek_priv {
|
||||
struct device *dev;
|
||||
+ struct reset_control *reset_ctl;
|
||||
struct gpio_desc *reset;
|
||||
struct gpio_desc *mdc;
|
||||
struct gpio_desc *mdio;
|
||||
--- a/drivers/net/dsa/realtek/rtl83xx.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl83xx.c
|
||||
@@ -185,6 +185,13 @@ rtl83xx_probe(struct device *dev,
|
||||
"realtek,disable-leds");
|
||||
|
||||
/* TODO: if power is software controlled, set up any regulators here */
|
||||
+ priv->reset_ctl = devm_reset_control_get_optional(dev, NULL);
|
||||
+ if (IS_ERR(priv->reset_ctl)) {
|
||||
+ ret = PTR_ERR(priv->reset_ctl);
|
||||
+ dev_err_probe(dev, ret, "failed to get reset control\n");
|
||||
+ return ERR_CAST(priv->reset_ctl);
|
||||
+ }
|
||||
+
|
||||
priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(priv->reset)) {
|
||||
dev_err(dev, "failed to get RESET GPIO\n");
|
||||
@@ -193,11 +200,11 @@ rtl83xx_probe(struct device *dev,
|
||||
|
||||
dev_set_drvdata(dev, priv);
|
||||
|
||||
- if (priv->reset) {
|
||||
- gpiod_set_value(priv->reset, 1);
|
||||
+ if (priv->reset_ctl || priv->reset) {
|
||||
+ rtl83xx_reset_assert(priv);
|
||||
dev_dbg(dev, "asserted RESET\n");
|
||||
msleep(REALTEK_HW_STOP_DELAY);
|
||||
- gpiod_set_value(priv->reset, 0);
|
||||
+ rtl83xx_reset_deassert(priv);
|
||||
msleep(REALTEK_HW_START_DELAY);
|
||||
dev_dbg(dev, "deasserted RESET\n");
|
||||
}
|
||||
@@ -293,11 +300,36 @@ EXPORT_SYMBOL_NS_GPL(rtl83xx_shutdown, R
|
||||
void rtl83xx_remove(struct realtek_priv *priv)
|
||||
{
|
||||
/* leave the device reset asserted */
|
||||
- if (priv->reset)
|
||||
- gpiod_set_value(priv->reset, 1);
|
||||
+ rtl83xx_reset_assert(priv);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, REALTEK_DSA);
|
||||
|
||||
+void rtl83xx_reset_assert(struct realtek_priv *priv)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = reset_control_assert(priv->reset_ctl);
|
||||
+ if (ret)
|
||||
+ dev_warn(priv->dev,
|
||||
+ "Failed to assert the switch reset control: %pe\n",
|
||||
+ ERR_PTR(ret));
|
||||
+
|
||||
+ gpiod_set_value(priv->reset, true);
|
||||
+}
|
||||
+
|
||||
+void rtl83xx_reset_deassert(struct realtek_priv *priv)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = reset_control_deassert(priv->reset_ctl);
|
||||
+ if (ret)
|
||||
+ dev_warn(priv->dev,
|
||||
+ "Failed to deassert the switch reset control: %pe\n",
|
||||
+ ERR_PTR(ret));
|
||||
+
|
||||
+ gpiod_set_value(priv->reset, false);
|
||||
+}
|
||||
+
|
||||
MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
|
||||
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
|
||||
MODULE_DESCRIPTION("Realtek DSA switches common module");
|
||||
--- a/drivers/net/dsa/realtek/rtl83xx.h
|
||||
+++ b/drivers/net/dsa/realtek/rtl83xx.h
|
||||
@@ -18,5 +18,7 @@ int rtl83xx_register_switch(struct realt
|
||||
void rtl83xx_unregister_switch(struct realtek_priv *priv);
|
||||
void rtl83xx_shutdown(struct realtek_priv *priv);
|
||||
void rtl83xx_remove(struct realtek_priv *priv);
|
||||
+void rtl83xx_reset_assert(struct realtek_priv *priv);
|
||||
+void rtl83xx_reset_deassert(struct realtek_priv *priv);
|
||||
|
||||
#endif /* _RTL83XX_H */
|
@ -0,0 +1,45 @@
|
||||
From 4f580e9aced1816398c1c64f178302a22b8ea6e2 Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Sat, 27 Apr 2024 02:11:29 -0300
|
||||
Subject: [PATCH 2/3] net: dsa: realtek: do not assert reset on remove
|
||||
|
||||
The necessity of asserting the reset on removal was previously
|
||||
questioned, as DSA's own cleanup methods should suffice to prevent
|
||||
traffic leakage[1].
|
||||
|
||||
When a driver has subdrivers controlled by devres, they will be
|
||||
unregistered after the main driver's .remove is executed. If it asserts
|
||||
a reset, the subdrivers will be unable to communicate with the hardware
|
||||
during their cleanup. For LEDs, this means that they will fail to turn
|
||||
off, resulting in a timeout error.
|
||||
|
||||
[1] https://lore.kernel.org/r/20240123215606.26716-9-luizluca@gmail.com/
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/realtek/rtl83xx.c | 7 ++-----
|
||||
1 file changed, 2 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/realtek/rtl83xx.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl83xx.c
|
||||
@@ -291,16 +291,13 @@ EXPORT_SYMBOL_NS_GPL(rtl83xx_shutdown, R
|
||||
* rtl83xx_remove() - Cleanup a realtek switch driver
|
||||
* @priv: realtek_priv pointer
|
||||
*
|
||||
- * If a method is provided, this function asserts the hard reset of the switch
|
||||
- * in order to avoid leaking traffic when the driver is gone.
|
||||
+ * Placehold for common cleanup procedures.
|
||||
*
|
||||
- * Context: Might sleep if priv->gdev->chip->can_sleep.
|
||||
+ * Context: Any
|
||||
* Return: nothing
|
||||
*/
|
||||
void rtl83xx_remove(struct realtek_priv *priv)
|
||||
{
|
||||
- /* leave the device reset asserted */
|
||||
- rtl83xx_reset_assert(priv);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, REALTEK_DSA);
|
||||
|
@ -0,0 +1,396 @@
|
||||
From 32d617005475a71ebcc4ec8b2791e8d1481e9a10 Mon Sep 17 00:00:00 2001
|
||||
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Date: Sat, 27 Apr 2024 02:11:30 -0300
|
||||
Subject: [PATCH 3/3] net: dsa: realtek: add LED drivers for rtl8366rb
|
||||
|
||||
This commit introduces LED drivers for rtl8366rb, enabling LEDs to be
|
||||
described in the device tree using the same format as qca8k. Each port
|
||||
can configure up to 4 LEDs.
|
||||
|
||||
If all LEDs in a group use the default state "keep", they will use the
|
||||
default behavior after a reset. Changing the brightness of one LED,
|
||||
either manually or by a trigger, will disable the default hardware
|
||||
trigger and switch the entire LED group to manually controlled LEDs.
|
||||
Once in this mode, there is no way to revert to hardware-controlled LEDs
|
||||
(except by resetting the switch).
|
||||
|
||||
Software triggers function as expected with manually controlled LEDs.
|
||||
|
||||
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/realtek/rtl8366rb.c | 304 ++++++++++++++++++++++++----
|
||||
1 file changed, 265 insertions(+), 39 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/realtek/rtl8366rb.c
|
||||
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
|
||||
@@ -180,6 +180,7 @@
|
||||
#define RTL8366RB_VLAN_INGRESS_CTRL2_REG 0x037f
|
||||
|
||||
/* LED control registers */
|
||||
+/* The LED blink rate is global; it is used by all triggers in all groups. */
|
||||
#define RTL8366RB_LED_BLINKRATE_REG 0x0430
|
||||
#define RTL8366RB_LED_BLINKRATE_MASK 0x0007
|
||||
#define RTL8366RB_LED_BLINKRATE_28MS 0x0000
|
||||
@@ -195,31 +196,21 @@
|
||||
(4 * (led_group))
|
||||
#define RTL8366RB_LED_CTRL_MASK(led_group) \
|
||||
(0xf << RTL8366RB_LED_CTRL_OFFSET(led_group))
|
||||
-#define RTL8366RB_LED_OFF 0x0
|
||||
-#define RTL8366RB_LED_DUP_COL 0x1
|
||||
-#define RTL8366RB_LED_LINK_ACT 0x2
|
||||
-#define RTL8366RB_LED_SPD1000 0x3
|
||||
-#define RTL8366RB_LED_SPD100 0x4
|
||||
-#define RTL8366RB_LED_SPD10 0x5
|
||||
-#define RTL8366RB_LED_SPD1000_ACT 0x6
|
||||
-#define RTL8366RB_LED_SPD100_ACT 0x7
|
||||
-#define RTL8366RB_LED_SPD10_ACT 0x8
|
||||
-#define RTL8366RB_LED_SPD100_10_ACT 0x9
|
||||
-#define RTL8366RB_LED_FIBER 0xa
|
||||
-#define RTL8366RB_LED_AN_FAULT 0xb
|
||||
-#define RTL8366RB_LED_LINK_RX 0xc
|
||||
-#define RTL8366RB_LED_LINK_TX 0xd
|
||||
-#define RTL8366RB_LED_MASTER 0xe
|
||||
-#define RTL8366RB_LED_FORCE 0xf
|
||||
|
||||
/* The RTL8366RB_LED_X_X registers are used to manually set the LED state only
|
||||
* when the corresponding LED group in RTL8366RB_LED_CTRL_REG is
|
||||
- * RTL8366RB_LED_FORCE. Otherwise, it is ignored.
|
||||
+ * RTL8366RB_LEDGROUP_FORCE. Otherwise, it is ignored.
|
||||
*/
|
||||
#define RTL8366RB_LED_0_1_CTRL_REG 0x0432
|
||||
-#define RTL8366RB_LED_1_OFFSET 6
|
||||
#define RTL8366RB_LED_2_3_CTRL_REG 0x0433
|
||||
-#define RTL8366RB_LED_3_OFFSET 6
|
||||
+#define RTL8366RB_LED_X_X_CTRL_REG(led_group) \
|
||||
+ ((led_group) <= 1 ? \
|
||||
+ RTL8366RB_LED_0_1_CTRL_REG : \
|
||||
+ RTL8366RB_LED_2_3_CTRL_REG)
|
||||
+#define RTL8366RB_LED_0_X_CTRL_MASK GENMASK(5, 0)
|
||||
+#define RTL8366RB_LED_X_1_CTRL_MASK GENMASK(11, 6)
|
||||
+#define RTL8366RB_LED_2_X_CTRL_MASK GENMASK(5, 0)
|
||||
+#define RTL8366RB_LED_X_3_CTRL_MASK GENMASK(11, 6)
|
||||
|
||||
#define RTL8366RB_MIB_COUNT 33
|
||||
#define RTL8366RB_GLOBAL_MIB_COUNT 1
|
||||
@@ -363,14 +354,44 @@
|
||||
#define RTL8366RB_GREEN_FEATURE_TX BIT(0)
|
||||
#define RTL8366RB_GREEN_FEATURE_RX BIT(2)
|
||||
|
||||
+enum rtl8366_ledgroup_mode {
|
||||
+ RTL8366RB_LEDGROUP_OFF = 0x0,
|
||||
+ RTL8366RB_LEDGROUP_DUP_COL = 0x1,
|
||||
+ RTL8366RB_LEDGROUP_LINK_ACT = 0x2,
|
||||
+ RTL8366RB_LEDGROUP_SPD1000 = 0x3,
|
||||
+ RTL8366RB_LEDGROUP_SPD100 = 0x4,
|
||||
+ RTL8366RB_LEDGROUP_SPD10 = 0x5,
|
||||
+ RTL8366RB_LEDGROUP_SPD1000_ACT = 0x6,
|
||||
+ RTL8366RB_LEDGROUP_SPD100_ACT = 0x7,
|
||||
+ RTL8366RB_LEDGROUP_SPD10_ACT = 0x8,
|
||||
+ RTL8366RB_LEDGROUP_SPD100_10_ACT = 0x9,
|
||||
+ RTL8366RB_LEDGROUP_FIBER = 0xa,
|
||||
+ RTL8366RB_LEDGROUP_AN_FAULT = 0xb,
|
||||
+ RTL8366RB_LEDGROUP_LINK_RX = 0xc,
|
||||
+ RTL8366RB_LEDGROUP_LINK_TX = 0xd,
|
||||
+ RTL8366RB_LEDGROUP_MASTER = 0xe,
|
||||
+ RTL8366RB_LEDGROUP_FORCE = 0xf,
|
||||
+
|
||||
+ __RTL8366RB_LEDGROUP_MODE_MAX
|
||||
+};
|
||||
+
|
||||
+struct rtl8366rb_led {
|
||||
+ u8 port_num;
|
||||
+ u8 led_group;
|
||||
+ struct realtek_priv *priv;
|
||||
+ struct led_classdev cdev;
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* struct rtl8366rb - RTL8366RB-specific data
|
||||
* @max_mtu: per-port max MTU setting
|
||||
* @pvid_enabled: if PVID is set for respective port
|
||||
+ * @leds: per-port and per-ledgroup led info
|
||||
*/
|
||||
struct rtl8366rb {
|
||||
unsigned int max_mtu[RTL8366RB_NUM_PORTS];
|
||||
bool pvid_enabled[RTL8366RB_NUM_PORTS];
|
||||
+ struct rtl8366rb_led leds[RTL8366RB_NUM_PORTS][RTL8366RB_NUM_LEDGROUPS];
|
||||
};
|
||||
|
||||
static struct rtl8366_mib_counter rtl8366rb_mib_counters[] = {
|
||||
@@ -813,6 +834,217 @@ static int rtl8366rb_jam_table(const str
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int rb8366rb_set_ledgroup_mode(struct realtek_priv *priv,
|
||||
+ u8 led_group,
|
||||
+ enum rtl8366_ledgroup_mode mode)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = mode << RTL8366RB_LED_CTRL_OFFSET(led_group);
|
||||
+
|
||||
+ ret = regmap_update_bits(priv->map,
|
||||
+ RTL8366RB_LED_CTRL_REG,
|
||||
+ RTL8366RB_LED_CTRL_MASK(led_group),
|
||||
+ val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline u32 rtl8366rb_led_group_port_mask(u8 led_group, u8 port)
|
||||
+{
|
||||
+ switch (led_group) {
|
||||
+ case 0:
|
||||
+ return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
|
||||
+ case 1:
|
||||
+ return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
|
||||
+ case 2:
|
||||
+ return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
|
||||
+ case 3:
|
||||
+ return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int rb8366rb_get_port_led(struct rtl8366rb_led *led)
|
||||
+{
|
||||
+ struct realtek_priv *priv = led->priv;
|
||||
+ u8 led_group = led->led_group;
|
||||
+ u8 port_num = led->port_num;
|
||||
+ int ret;
|
||||
+ u32 val;
|
||||
+
|
||||
+ ret = regmap_read(priv->map, RTL8366RB_LED_X_X_CTRL_REG(led_group),
|
||||
+ &val);
|
||||
+ if (ret) {
|
||||
+ dev_err(priv->dev, "error reading LED on port %d group %d\n",
|
||||
+ led_group, port_num);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return !!(val & rtl8366rb_led_group_port_mask(led_group, port_num));
|
||||
+}
|
||||
+
|
||||
+static int rb8366rb_set_port_led(struct rtl8366rb_led *led, bool enable)
|
||||
+{
|
||||
+ struct realtek_priv *priv = led->priv;
|
||||
+ u8 led_group = led->led_group;
|
||||
+ u8 port_num = led->port_num;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = regmap_update_bits(priv->map,
|
||||
+ RTL8366RB_LED_X_X_CTRL_REG(led_group),
|
||||
+ rtl8366rb_led_group_port_mask(led_group,
|
||||
+ port_num),
|
||||
+ enable ? 0xffff : 0);
|
||||
+ if (ret) {
|
||||
+ dev_err(priv->dev, "error updating LED on port %d group %d\n",
|
||||
+ led_group, port_num);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Change the LED group to manual controlled LEDs if required */
|
||||
+ ret = rb8366rb_set_ledgroup_mode(priv, led_group,
|
||||
+ RTL8366RB_LEDGROUP_FORCE);
|
||||
+
|
||||
+ if (ret) {
|
||||
+ dev_err(priv->dev, "error updating LED GROUP group %d\n",
|
||||
+ led_group);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+rtl8366rb_cled_brightness_set_blocking(struct led_classdev *ldev,
|
||||
+ enum led_brightness brightness)
|
||||
+{
|
||||
+ struct rtl8366rb_led *led = container_of(ldev, struct rtl8366rb_led,
|
||||
+ cdev);
|
||||
+
|
||||
+ return rb8366rb_set_port_led(led, brightness == LED_ON);
|
||||
+}
|
||||
+
|
||||
+static int rtl8366rb_setup_led(struct realtek_priv *priv, struct dsa_port *dp,
|
||||
+ struct fwnode_handle *led_fwnode)
|
||||
+{
|
||||
+ struct rtl8366rb *rb = priv->chip_data;
|
||||
+ struct led_init_data init_data = { };
|
||||
+ enum led_default_state state;
|
||||
+ struct rtl8366rb_led *led;
|
||||
+ u32 led_group;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = fwnode_property_read_u32(led_fwnode, "reg", &led_group);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (led_group >= RTL8366RB_NUM_LEDGROUPS) {
|
||||
+ dev_warn(priv->dev, "Invalid LED reg %d defined for port %d",
|
||||
+ led_group, dp->index);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ led = &rb->leds[dp->index][led_group];
|
||||
+ led->port_num = dp->index;
|
||||
+ led->led_group = led_group;
|
||||
+ led->priv = priv;
|
||||
+
|
||||
+ state = led_init_default_state_get(led_fwnode);
|
||||
+ switch (state) {
|
||||
+ case LEDS_DEFSTATE_ON:
|
||||
+ led->cdev.brightness = 1;
|
||||
+ rb8366rb_set_port_led(led, 1);
|
||||
+ break;
|
||||
+ case LEDS_DEFSTATE_KEEP:
|
||||
+ led->cdev.brightness =
|
||||
+ rb8366rb_get_port_led(led);
|
||||
+ break;
|
||||
+ case LEDS_DEFSTATE_OFF:
|
||||
+ default:
|
||||
+ led->cdev.brightness = 0;
|
||||
+ rb8366rb_set_port_led(led, 0);
|
||||
+ }
|
||||
+
|
||||
+ led->cdev.max_brightness = 1;
|
||||
+ led->cdev.brightness_set_blocking =
|
||||
+ rtl8366rb_cled_brightness_set_blocking;
|
||||
+ init_data.fwnode = led_fwnode;
|
||||
+ init_data.devname_mandatory = true;
|
||||
+
|
||||
+ init_data.devicename = kasprintf(GFP_KERNEL, "Realtek-%d:0%d:%d",
|
||||
+ dp->ds->index, dp->index, led_group);
|
||||
+ if (!init_data.devicename)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ret = devm_led_classdev_register_ext(priv->dev, &led->cdev, &init_data);
|
||||
+ if (ret) {
|
||||
+ dev_warn(priv->dev, "Failed to init LED %d for port %d",
|
||||
+ led_group, dp->index);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int rtl8366rb_setup_all_leds_off(struct realtek_priv *priv)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ int i;
|
||||
+
|
||||
+ regmap_update_bits(priv->map,
|
||||
+ RTL8366RB_INTERRUPT_CONTROL_REG,
|
||||
+ RTL8366RB_P4_RGMII_LED,
|
||||
+ 0);
|
||||
+
|
||||
+ for (i = 0; i < RTL8366RB_NUM_LEDGROUPS; i++) {
|
||||
+ ret = rb8366rb_set_ledgroup_mode(priv, i,
|
||||
+ RTL8366RB_LEDGROUP_OFF);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int rtl8366rb_setup_leds(struct realtek_priv *priv)
|
||||
+{
|
||||
+ struct device_node *leds_np, *led_np;
|
||||
+ struct dsa_switch *ds = &priv->ds;
|
||||
+ struct dsa_port *dp;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ dsa_switch_for_each_port(dp, ds) {
|
||||
+ if (!dp->dn)
|
||||
+ continue;
|
||||
+
|
||||
+ leds_np = of_get_child_by_name(dp->dn, "leds");
|
||||
+ if (!leds_np) {
|
||||
+ dev_dbg(priv->dev, "No leds defined for port %d",
|
||||
+ dp->index);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ for_each_child_of_node(leds_np, led_np) {
|
||||
+ ret = rtl8366rb_setup_led(priv, dp,
|
||||
+ of_fwnode_handle(led_np));
|
||||
+ if (ret) {
|
||||
+ of_node_put(led_np);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ of_node_put(leds_np);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int rtl8366rb_setup(struct dsa_switch *ds)
|
||||
{
|
||||
struct realtek_priv *priv = ds->priv;
|
||||
@@ -821,7 +1053,6 @@ static int rtl8366rb_setup(struct dsa_sw
|
||||
u32 chip_ver = 0;
|
||||
u32 chip_id = 0;
|
||||
int jam_size;
|
||||
- u32 val;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
@@ -997,7 +1228,9 @@ static int rtl8366rb_setup(struct dsa_sw
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- /* Set blinking, TODO: make this configurable */
|
||||
+ /* Set blinking, used by all LED groups using HW triggers.
|
||||
+ * TODO: make this configurable
|
||||
+ */
|
||||
ret = regmap_update_bits(priv->map, RTL8366RB_LED_BLINKRATE_REG,
|
||||
RTL8366RB_LED_BLINKRATE_MASK,
|
||||
RTL8366RB_LED_BLINKRATE_56MS);
|
||||
@@ -1005,26 +1238,19 @@ static int rtl8366rb_setup(struct dsa_sw
|
||||
return ret;
|
||||
|
||||
/* Set up LED activity:
|
||||
- * Each port has 4 LEDs, we configure all ports to the same
|
||||
- * behaviour (no individual config) but we can set up each
|
||||
- * LED separately.
|
||||
+ * Each port has 4 LEDs on fixed groups. Each group shares the same
|
||||
+ * hardware trigger across all ports. LEDs can only be indiviually
|
||||
+ * controlled setting the LED group to fixed mode and using the driver
|
||||
+ * to toggle them LEDs on/off.
|
||||
*/
|
||||
if (priv->leds_disabled) {
|
||||
- /* Turn everything off */
|
||||
- regmap_update_bits(priv->map,
|
||||
- RTL8366RB_INTERRUPT_CONTROL_REG,
|
||||
- RTL8366RB_P4_RGMII_LED,
|
||||
- 0);
|
||||
-
|
||||
- for (i = 0; i < RTL8366RB_NUM_LEDGROUPS; i++) {
|
||||
- val = RTL8366RB_LED_OFF << RTL8366RB_LED_CTRL_OFFSET(i);
|
||||
- ret = regmap_update_bits(priv->map,
|
||||
- RTL8366RB_LED_CTRL_REG,
|
||||
- RTL8366RB_LED_CTRL_MASK(i),
|
||||
- val);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
- }
|
||||
+ ret = rtl8366rb_setup_all_leds_off(priv);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ } else {
|
||||
+ ret = rtl8366rb_setup_leds(priv);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
ret = rtl8366_reset_vlan(priv);
|
Loading…
Reference in New Issue
Block a user