Commit bce254b8 authored by Luiz Angelo Daros de Luca's avatar Luiz Angelo Daros de Luca Committed by David S. Miller

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: default avatarLuiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: default avatarVladimir Oltean <olteanv@gmail.com>
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ded3813b
...@@ -16,37 +16,29 @@ menuconfig NET_DSA_REALTEK ...@@ -16,37 +16,29 @@ menuconfig NET_DSA_REALTEK
if NET_DSA_REALTEK if NET_DSA_REALTEK
config NET_DSA_REALTEK_MDIO config NET_DSA_REALTEK_MDIO
tristate "Realtek MDIO interface driver" tristate "Realtek MDIO interface support"
depends on OF 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 help
Select to enable support for registering switches configured Select to enable support for registering switches configured
through MDIO. through MDIO.
config NET_DSA_REALTEK_SMI config NET_DSA_REALTEK_SMI
tristate "Realtek SMI interface driver" tristate "Realtek SMI interface support"
depends on OF 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 help
Select to enable support for registering switches connected Select to enable support for registering switches connected
through SMI. through SMI.
config NET_DSA_REALTEK_RTL8365MB config NET_DSA_REALTEK_RTL8365MB
tristate "Realtek RTL8365MB switch subdriver" tristate "Realtek RTL8365MB switch driver"
imply NET_DSA_REALTEK_SMI depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO
imply NET_DSA_REALTEK_MDIO
select NET_DSA_TAG_RTL8_4 select NET_DSA_TAG_RTL8_4
help help
Select to enable support for Realtek RTL8365MB-VC and RTL8367S. Select to enable support for Realtek RTL8365MB-VC and RTL8367S.
config NET_DSA_REALTEK_RTL8366RB config NET_DSA_REALTEK_RTL8366RB
tristate "Realtek RTL8366RB switch subdriver" tristate "Realtek RTL8366RB switch driver"
imply NET_DSA_REALTEK_SMI depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO
imply NET_DSA_REALTEK_MDIO
select NET_DSA_TAG_RTL4_A select NET_DSA_TAG_RTL4_A
help help
Select to enable support for Realtek RTL8366RB. Select to enable support for Realtek RTL8366RB.
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include "realtek.h" #include "realtek.h"
#include "realtek-mdio.h"
/* Read/write via mdiobus */ /* Read/write via mdiobus */
#define REALTEK_MDIO_CTRL0_REG 31 #define REALTEK_MDIO_CTRL0_REG 31
...@@ -140,7 +141,19 @@ static const struct regmap_config realtek_mdio_nolock_regmap_config = { ...@@ -140,7 +141,19 @@ static const struct regmap_config realtek_mdio_nolock_regmap_config = {
.disable_locking = true, .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 realtek_priv *priv;
struct device *dev = &mdiodev->dev; struct device *dev = &mdiodev->dev;
...@@ -235,8 +248,20 @@ static int realtek_mdio_probe(struct mdio_device *mdiodev) ...@@ -235,8 +248,20 @@ static int realtek_mdio_probe(struct mdio_device *mdiodev)
return 0; 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); struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
...@@ -249,8 +274,21 @@ static void realtek_mdio_remove(struct mdio_device *mdiodev) ...@@ -249,8 +274,21 @@ static void realtek_mdio_remove(struct mdio_device *mdiodev)
if (priv->reset) if (priv->reset)
gpiod_set_value(priv->reset, 1); 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); struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
...@@ -261,29 +299,7 @@ static void realtek_mdio_shutdown(struct mdio_device *mdiodev) ...@@ -261,29 +299,7 @@ static void realtek_mdio_shutdown(struct mdio_device *mdiodev)
dev_set_drvdata(&mdiodev->dev, NULL); dev_set_drvdata(&mdiodev->dev, NULL);
} }
EXPORT_SYMBOL_NS_GPL(realtek_mdio_shutdown, REALTEK_DSA);
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);
MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>"); MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface"); MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface");
......
/* 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 */
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/if_bridge.h> #include <linux/if_bridge.h>
#include "realtek.h" #include "realtek.h"
#include "realtek-smi.h"
#define REALTEK_SMI_ACK_RETRY_COUNT 5 #define REALTEK_SMI_ACK_RETRY_COUNT 5
...@@ -408,7 +409,19 @@ static int realtek_smi_setup_mdio(struct dsa_switch *ds) ...@@ -408,7 +409,19 @@ static int realtek_smi_setup_mdio(struct dsa_switch *ds)
return ret; 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; const struct realtek_variant *var;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -505,8 +518,20 @@ static int realtek_smi_probe(struct platform_device *pdev) ...@@ -505,8 +518,20 @@ static int realtek_smi_probe(struct platform_device *pdev)
} }
return 0; 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); struct realtek_priv *priv = platform_get_drvdata(pdev);
...@@ -521,8 +546,21 @@ static void realtek_smi_remove(struct platform_device *pdev) ...@@ -521,8 +546,21 @@ static void realtek_smi_remove(struct platform_device *pdev)
if (priv->reset) if (priv->reset)
gpiod_set_value(priv->reset, 1); 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); struct realtek_priv *priv = platform_get_drvdata(pdev);
...@@ -533,34 +571,7 @@ static void realtek_smi_shutdown(struct platform_device *pdev) ...@@ -533,34 +571,7 @@ static void realtek_smi_shutdown(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
} }
EXPORT_SYMBOL_NS_GPL(realtek_smi_shutdown, REALTEK_DSA);
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);
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>"); MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface"); MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
......
/* 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 */
...@@ -101,6 +101,8 @@ ...@@ -101,6 +101,8 @@
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include "realtek.h" #include "realtek.h"
#include "realtek-smi.h"
#include "realtek-mdio.h"
/* Family-specific data and limits */ /* Family-specific data and limits */
#define RTL8365MB_PHYADDRMAX 7 #define RTL8365MB_PHYADDRMAX 7
...@@ -2172,7 +2174,57 @@ const struct realtek_variant rtl8365mb_variant = { ...@@ -2172,7 +2174,57 @@ const struct realtek_variant rtl8365mb_variant = {
.cmd_write = 0xb8, .cmd_write = 0xb8,
.chip_data_sz = sizeof(struct rtl8365mb), .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_AUTHOR("Alvin Šipraga <alsi@bang-olufsen.dk>");
MODULE_DESCRIPTION("Driver for RTL8365MB-VC ethernet switch"); MODULE_DESCRIPTION("Driver for RTL8365MB-VC ethernet switch");
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include "realtek.h" #include "realtek.h"
#include "realtek-smi.h"
#include "realtek-mdio.h"
#define RTL8366RB_PORT_NUM_CPU 5 #define RTL8366RB_PORT_NUM_CPU 5
#define RTL8366RB_NUM_PORTS 6 #define RTL8366RB_NUM_PORTS 6
...@@ -1933,7 +1935,57 @@ const struct realtek_variant rtl8366rb_variant = { ...@@ -1933,7 +1935,57 @@ const struct realtek_variant rtl8366rb_variant = {
.cmd_write = 0xa8, .cmd_write = 0xa8,
.chip_data_sz = sizeof(struct rtl8366rb), .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_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
MODULE_DESCRIPTION("Driver for RTL8366RB ethernet switch"); MODULE_DESCRIPTION("Driver for RTL8366RB ethernet switch");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment