Skip to content

Commit 8c345c5

Browse files
committed
1 parent 0935544 commit 8c345c5

File tree

2 files changed

+249
-0
lines changed

2 files changed

+249
-0
lines changed

drivers/net/dsa/mxl862xx/mxl862xx.c

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include <net/dsa.h>
2020
#include <linux/dsa/8021q.h>
2121
#include <linux/stddef.h>
22+
#include <linux/gpio/consumer.h>
23+
#include <linux/of_net.h>
2224

2325
#include "mxl862xx.h"
2426
#include "mxl862xx-api.h"
@@ -3696,12 +3698,221 @@ static const struct dsa_switch_ops mxl862xx_switch_ops = {
36963698
.setup = mxl862xx_setup,
36973699
};
36983700

3701+
static void sfp_monitor_work_func(struct work_struct *work)
3702+
{
3703+
struct combo_port_mux *mux = container_of(work, struct combo_port_mux, sfp_monitor_work.work);
3704+
struct dsa_switch *ds = mux->dp->ds;
3705+
struct dsa_port *dp = mux->dp;
3706+
struct net_device *dev = mux->dp->user;
3707+
unsigned int new_channel;
3708+
int sfp_present;
3709+
3710+
if (IS_ERR(mux->mod_def0_gpio) || IS_ERR(mux->chan_sel_gpio))
3711+
goto reschedule;
3712+
3713+
if (!netif_running(dev))
3714+
goto reschedule;
3715+
3716+
sfp_present = gpiod_get_value_cansleep(mux->mod_def0_gpio);
3717+
new_channel = sfp_present ? mux->sfp_present_channel : !mux->sfp_present_channel;
3718+
3719+
if (mux->initialized && mux->channel == new_channel)
3720+
goto reschedule;
3721+
3722+
rtnl_lock();
3723+
3724+
phylink_stop(dp->pl);
3725+
phylink_disconnect_phy(dp->pl);
3726+
3727+
dp->dn = mux->data[new_channel]->of_node;
3728+
dp->pl = mux->data[new_channel]->phylink;
3729+
3730+
phylink_of_phy_connect(dp->pl, dp->dn, 0);
3731+
phylink_start(dp->pl);
3732+
3733+
dev_info(ds->dev, "dsa mux: switch to channel%d\n", new_channel);
3734+
3735+
gpiod_set_value_cansleep(mux->chan_sel_gpio, new_channel);
3736+
3737+
rtnl_unlock();
3738+
3739+
mux->channel = new_channel;
3740+
mux->initialized = true;
3741+
3742+
reschedule:
3743+
mod_delayed_work(system_wq, &mux->sfp_monitor_work, msecs_to_jiffies(100));
3744+
}
3745+
3746+
static int ds_add_mux_channel(struct combo_port_mux *mux, struct device_node *np)
3747+
{
3748+
const __be32 *_id = of_get_property(np, "reg", NULL);
3749+
struct dsa_switch *ds = mux->dp->ds;
3750+
struct dp_mux_data *data;
3751+
struct phylink *phylink;
3752+
phy_interface_t phy_mode;
3753+
int id, err;
3754+
3755+
if (!_id) {
3756+
dev_err(ds->dev, "missing mux channel id\n");
3757+
return -EINVAL;
3758+
}
3759+
3760+
id = be32_to_cpup(_id);
3761+
if (id < 0 || id > 1) {
3762+
dev_err(ds->dev, "%d is not a valid mux channel id\n", id);
3763+
return -EINVAL;
3764+
}
3765+
3766+
data = kmalloc(sizeof(*data), GFP_KERNEL);
3767+
if (unlikely(!data)) {
3768+
dev_err(ds->dev, "failed to create mux data structure\n");
3769+
return -ENOMEM;
3770+
}
3771+
3772+
err = of_get_phy_mode(np, &phy_mode);
3773+
if (err) {
3774+
dev_err(ds->dev, "incorrect phy-mode\n");
3775+
goto err_free_data;
3776+
}
3777+
3778+
phylink = phylink_create(&mux->dp->pl_config,
3779+
of_fwnode_handle(np),
3780+
phy_mode, ds->phylink_mac_ops);
3781+
if (IS_ERR(phylink)) {
3782+
dev_err(ds->dev, "failed to create phylink structure\n");
3783+
err = PTR_ERR(phylink);
3784+
goto err_free_data;
3785+
}
3786+
3787+
data->of_node = np;
3788+
data->phylink = phylink;
3789+
mux->data[id] = data;
3790+
3791+
return 0;
3792+
3793+
err_free_data:
3794+
kfree(data);
3795+
return err;
3796+
}
3797+
3798+
static int ds_add_mux(struct mxl862xx_priv *priv, struct device_node *np)
3799+
{
3800+
const __be32 *_id = of_get_property(np, "reg", NULL);
3801+
struct device_node *child;
3802+
struct combo_port_mux *mux;
3803+
unsigned int id;
3804+
int err;
3805+
3806+
if (!_id) {
3807+
dev_err(priv->dev, "missing attach dp id\n");
3808+
return -EINVAL;
3809+
}
3810+
3811+
id = be32_to_cpup(_id);
3812+
if (id < 0 || id >= MAX_PORTS) {
3813+
dev_err(priv->dev, "%d is not a valid attach dp id\n", id);
3814+
return -EINVAL;
3815+
}
3816+
3817+
mux = kmalloc(sizeof(struct combo_port_mux), GFP_KERNEL);
3818+
if (unlikely(!mux)) {
3819+
dev_err(priv->dev, "failed to create mux structure\n");
3820+
return -ENOMEM;
3821+
}
3822+
3823+
mux->mod_def0_gpio = fwnode_gpiod_get_index(of_fwnode_handle(np),
3824+
"mod-def0", 0, GPIOD_IN |
3825+
GPIOD_FLAGS_BIT_NONEXCLUSIVE, "?");
3826+
3827+
if (IS_ERR(mux->mod_def0_gpio)) {
3828+
dev_err(priv->dev, "failed to requset gpio for mod-def0\n");
3829+
err = PTR_ERR(mux->mod_def0_gpio);
3830+
goto err_free_mux;
3831+
}
3832+
3833+
mux->chan_sel_gpio = fwnode_gpiod_get_index(of_fwnode_handle(np),
3834+
"chan-sel", 0, GPIOD_OUT_LOW, "?");
3835+
3836+
if (IS_ERR(mux->chan_sel_gpio)) {
3837+
dev_err(priv->dev, "failed to requset gpio for chan-sel\n");
3838+
err = PTR_ERR(mux->chan_sel_gpio);
3839+
goto err_put_mod_def0;
3840+
}
3841+
3842+
of_property_read_u32(np, "sfp-present-channel",
3843+
&mux->sfp_present_channel);
3844+
3845+
priv->ds_mux[id] = mux;
3846+
mux->dp = dsa_to_port(priv->ds, id);
3847+
/* configure default channel to 10G PHY */
3848+
mux->channel = !mux->sfp_present_channel;
3849+
mux->initialized = false;
3850+
3851+
for_each_child_of_node(np, child) {
3852+
err = ds_add_mux_channel(mux, child);
3853+
if (err) {
3854+
dev_err(priv->dev, "failed to add ds_mux\n");
3855+
of_node_put(child);
3856+
goto err_put_chan_sel;
3857+
}
3858+
}
3859+
3860+
INIT_DELAYED_WORK(&mux->sfp_monitor_work, sfp_monitor_work_func);
3861+
mod_delayed_work(system_wq, &mux->sfp_monitor_work, msecs_to_jiffies(3000));
3862+
3863+
return 0;
3864+
3865+
err_put_chan_sel:
3866+
gpiod_put(mux->chan_sel_gpio);
3867+
err_put_mod_def0:
3868+
gpiod_put(mux->mod_def0_gpio);
3869+
err_free_mux:
3870+
kfree(mux);
3871+
priv->ds_mux[id] = NULL;
3872+
return err;
3873+
}
3874+
3875+
static void mxl862xx_release_mux(struct mxl862xx_priv *priv, int id)
3876+
{
3877+
struct combo_port_mux *mux = priv->ds_mux[id];
3878+
int i;
3879+
3880+
if (!mux)
3881+
return;
3882+
3883+
cancel_delayed_work_sync(&mux->sfp_monitor_work);
3884+
3885+
if (!IS_ERR_OR_NULL(mux->mod_def0_gpio))
3886+
gpiod_put(mux->mod_def0_gpio);
3887+
3888+
if (!IS_ERR_OR_NULL(mux->chan_sel_gpio))
3889+
gpiod_put(mux->chan_sel_gpio);
3890+
3891+
for (i = 0; i < 2; i++) {
3892+
if (mux->data[i]) {
3893+
if (mux->data[i]->phylink)
3894+
phylink_destroy(mux->data[i]->phylink);
3895+
kfree(mux->data[i]);
3896+
}
3897+
}
3898+
kfree(mux);
3899+
priv->ds_mux[id] = NULL;
3900+
}
3901+
3902+
static void mxl862xx_release_all_muxes(struct mxl862xx_priv *priv)
3903+
{
3904+
int i;
3905+
for (i = 0; i < MAX_PORTS; i++)
3906+
mxl862xx_release_mux(priv, i);
3907+
}
3908+
36993909
static int mxl862xx_probe(struct mdio_device *mdiodev)
37003910
{
37013911
struct mxl862xx_sys_fw_image_version fw_version;
37023912
struct device *dev = &mdiodev->dev;
37033913
struct mxl862xx_priv *priv;
37043914
struct dsa_switch *ds;
3915+
struct device_node *mux_np;
37053916
int ret;
37063917

37073918
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -3766,13 +3977,34 @@ static int mxl862xx_probe(struct mdio_device *mdiodev)
37663977
dev_info(dev, "%s:%u: Enable force isolate", __func__, __LINE__);
37673978
}
37683979

3980+
mux_np = of_get_child_by_name(priv->ds->dev->of_node, "ds-mux-bus");
3981+
if (mux_np) {
3982+
struct device_node *child;
3983+
3984+
for_each_available_child_of_node(mux_np, child) {
3985+
if (!of_device_is_compatible(child,
3986+
"mxl862xx,ds-mux"))
3987+
continue;
3988+
3989+
if (!of_device_is_available(child))
3990+
continue;
3991+
3992+
ret = ds_add_mux(priv, child);
3993+
if (ret)
3994+
dev_err(dev, "failed to add mux\n");
3995+
3996+
of_node_put(mux_np);
3997+
};
3998+
}
3999+
37694000
return 0;
37704001
}
37714002

37724003
static void mxl862xx_remove(struct mdio_device *mdiodev)
37734004
{
37744005
struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
37754006

4007+
mxl862xx_release_all_muxes(ds->priv);
37764008
dsa_unregister_switch(ds);
37774009
}
37784010

drivers/net/dsa/mxl862xx/mxl862xx.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,22 @@ struct mxl862xx_pcs {
8787
int port;
8888
};
8989

90+
struct dp_mux_data {
91+
struct device_node *of_node;
92+
struct phylink *phylink;
93+
};
94+
95+
struct combo_port_mux {
96+
struct dsa_port *dp;
97+
struct gpio_desc *mod_def0_gpio;
98+
struct gpio_desc *chan_sel_gpio;
99+
struct dp_mux_data *data[2];
100+
unsigned int channel;
101+
unsigned int sfp_present_channel;
102+
struct delayed_work sfp_monitor_work;
103+
bool initialized;
104+
};
105+
90106
struct mxl862xx_priv {
91107
struct dsa_switch *ds;
92108
struct mii_bus *bus;
@@ -107,4 +123,5 @@ struct mxl862xx_priv {
107123
bool force_isolate;
108124
bool c22_extended;
109125
struct mxl862xx_pcs pcs_port_1;
126+
struct combo_port_mux *ds_mux[MAX_PORTS];
110127
};

0 commit comments

Comments
 (0)