mt7530.c (7f54cc9772ced2d76ac11832f0ada43798443ac9) mt7530.c (cb675afcddbbeb2bfa6596e3bc236bc026cd425f)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Mediatek MT7530 DSA Switch driver
4 * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.com>
5 */
6#include <linux/etherdevice.h>
7#include <linux/if_bridge.h>
8#include <linux/iopoll.h>
9#include <linux/mdio.h>
10#include <linux/mfd/syscon.h>
11#include <linux/module.h>
12#include <linux/netdevice.h>
13#include <linux/of_irq.h>
14#include <linux/of_mdio.h>
15#include <linux/of_net.h>
16#include <linux/of_platform.h>
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Mediatek MT7530 DSA Switch driver
4 * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.com>
5 */
6#include <linux/etherdevice.h>
7#include <linux/if_bridge.h>
8#include <linux/iopoll.h>
9#include <linux/mdio.h>
10#include <linux/mfd/syscon.h>
11#include <linux/module.h>
12#include <linux/netdevice.h>
13#include <linux/of_irq.h>
14#include <linux/of_mdio.h>
15#include <linux/of_net.h>
16#include <linux/of_platform.h>
17#include <linux/pcs/pcs-mtk-lynxi.h>
18#include <linux/phylink.h>
19#include <linux/regmap.h>
20#include <linux/regulator/consumer.h>
21#include <linux/reset.h>
22#include <linux/gpio/consumer.h>
23#include <linux/gpio/driver.h>
24#include <net/dsa.h>
25

--- 161 unchanged lines hidden (view full) ---

187
188static void
189core_clear(struct mt7530_priv *priv, u32 reg, u32 val)
190{
191 core_rmw(priv, reg, val, 0);
192}
193
194static int
17#include <linux/phylink.h>
18#include <linux/regmap.h>
19#include <linux/regulator/consumer.h>
20#include <linux/reset.h>
21#include <linux/gpio/consumer.h>
22#include <linux/gpio/driver.h>
23#include <net/dsa.h>
24

--- 161 unchanged lines hidden (view full) ---

186
187static void
188core_clear(struct mt7530_priv *priv, u32 reg, u32 val)
189{
190 core_rmw(priv, reg, val, 0);
191}
192
193static int
195mt7530_regmap_write(void *context, unsigned int reg, unsigned int val)
196{
197 struct mii_bus *bus = context;
198 u16 page, r, lo, hi;
199 int ret;
200
201 page = (reg >> 6) & 0x3ff;
202 r = (reg >> 2) & 0xf;
203 lo = val & 0xffff;
204 hi = val >> 16;
205
206 /* MT7530 uses 31 as the pseudo port */
207 ret = bus->write(bus, 0x1f, 0x1f, page);
208 if (ret < 0)
209 return ret;
210
211 ret = bus->write(bus, 0x1f, r, lo);
212 if (ret < 0)
213 return ret;
214
215 ret = bus->write(bus, 0x1f, 0x10, hi);
216 return ret;
217}
218
219static int
220mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val)
221{
222 int ret;
223
224 ret = regmap_write(priv->regmap, reg, val);
225
226 if (ret < 0)
227 dev_err(priv->dev,
228 "failed to write mt7530 register\n");
229
230 return ret;
231}
232
194mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val)
195{
196 int ret;
197
198 ret = regmap_write(priv->regmap, reg, val);
199
200 if (ret < 0)
201 dev_err(priv->dev,
202 "failed to write mt7530 register\n");
203
204 return ret;
205}
206
233static int
234mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val)
235{
236 struct mii_bus *bus = context;
237 u16 page, r, lo, hi;
238 int ret;
239
240 page = (reg >> 6) & 0x3ff;
241 r = (reg >> 2) & 0xf;
242
243 /* MT7530 uses 31 as the pseudo port */
244 ret = bus->write(bus, 0x1f, 0x1f, page);
245 if (ret < 0)
246 return ret;
247
248 lo = bus->read(bus, 0x1f, r);
249 hi = bus->read(bus, 0x1f, 0x10);
250
251 *val = (hi << 16) | (lo & 0xffff);
252
253 return 0;
254}
255
256static u32
257mt7530_mii_read(struct mt7530_priv *priv, u32 reg)
258{
259 int ret;
260 u32 val;
261
262 ret = regmap_read(priv->regmap, reg, &val);
263 if (ret) {

--- 2676 unchanged lines hidden (view full) ---

2940
2941static const struct phylink_pcs_ops mt7530_pcs_ops = {
2942 .pcs_validate = mt753x_pcs_validate,
2943 .pcs_get_state = mt7530_pcs_get_state,
2944 .pcs_config = mt753x_pcs_config,
2945 .pcs_an_restart = mt7530_pcs_an_restart,
2946};
2947
207static u32
208mt7530_mii_read(struct mt7530_priv *priv, u32 reg)
209{
210 int ret;
211 u32 val;
212
213 ret = regmap_read(priv->regmap, reg, &val);
214 if (ret) {

--- 2676 unchanged lines hidden (view full) ---

2891
2892static const struct phylink_pcs_ops mt7530_pcs_ops = {
2893 .pcs_validate = mt753x_pcs_validate,
2894 .pcs_get_state = mt7530_pcs_get_state,
2895 .pcs_config = mt753x_pcs_config,
2896 .pcs_an_restart = mt7530_pcs_an_restart,
2897};
2898
2948static void
2949mt7530_mdio_regmap_lock(void *mdio_lock)
2950{
2951 mutex_lock_nested(mdio_lock, MDIO_MUTEX_NESTED);
2952}
2953
2954static void
2955mt7530_mdio_regmap_unlock(void *mdio_lock)
2956{
2957 mutex_unlock(mdio_lock);
2958}
2959
2960static const struct regmap_bus mt7530_regmap_bus = {
2961 .reg_write = mt7530_regmap_write,
2962 .reg_read = mt7530_regmap_read,
2963};
2964
2965static int
2899static int
2966mt7531_create_sgmii(struct mt7530_priv *priv)
2967{
2968 struct regmap_config *mt7531_pcs_config[2];
2969 struct phylink_pcs *pcs;
2970 struct regmap *regmap;
2971 int i, ret = 0;
2972
2973 for (i = 0; i < 2; i++) {
2974 mt7531_pcs_config[i] = devm_kzalloc(priv->dev,
2975 sizeof(struct regmap_config),
2976 GFP_KERNEL);
2977 if (!mt7531_pcs_config[i]) {
2978 ret = -ENOMEM;
2979 break;
2980 }
2981
2982 mt7531_pcs_config[i]->name = i ? "port6" : "port5";
2983 mt7531_pcs_config[i]->reg_bits = 16;
2984 mt7531_pcs_config[i]->val_bits = 32;
2985 mt7531_pcs_config[i]->reg_stride = 4;
2986 mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i);
2987 mt7531_pcs_config[i]->max_register = 0x17c;
2988 mt7531_pcs_config[i]->lock = mt7530_mdio_regmap_lock;
2989 mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock;
2990 mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock;
2991
2992 regmap = devm_regmap_init(priv->dev,
2993 &mt7530_regmap_bus, priv->bus,
2994 mt7531_pcs_config[i]);
2995 if (IS_ERR(regmap)) {
2996 ret = PTR_ERR(regmap);
2997 break;
2998 }
2999 pcs = mtk_pcs_lynxi_create(priv->dev, regmap,
3000 MT7531_PHYA_CTRL_SIGNAL3, 0);
3001 if (!pcs) {
3002 ret = -ENXIO;
3003 break;
3004 }
3005 priv->ports[5 + i].sgmii_pcs = pcs;
3006 }
3007
3008 if (ret && i)
3009 mtk_pcs_lynxi_destroy(priv->ports[5].sgmii_pcs);
3010
3011 return ret;
3012}
3013
3014static int
3015mt753x_setup(struct dsa_switch *ds)
3016{
3017 struct mt7530_priv *priv = ds->priv;
3018 int i, ret;
3019
3020 /* Initialise the PCS devices */
3021 for (i = 0; i < priv->ds->num_ports; i++) {
3022 priv->pcs[i].pcs.ops = priv->info->pcs_ops;

--- 41 unchanged lines hidden (view full) ---

3064 if (!e->tx_lpi_enabled)
3065 /* Force LPI Mode without a delay */
3066 set |= LPI_MODE_EN;
3067 mt7530_rmw(priv, MT7530_PMEEECR_P(port), mask, set);
3068
3069 return 0;
3070}
3071
2900mt753x_setup(struct dsa_switch *ds)
2901{
2902 struct mt7530_priv *priv = ds->priv;
2903 int i, ret;
2904
2905 /* Initialise the PCS devices */
2906 for (i = 0; i < priv->ds->num_ports; i++) {
2907 priv->pcs[i].pcs.ops = priv->info->pcs_ops;

--- 41 unchanged lines hidden (view full) ---

2949 if (!e->tx_lpi_enabled)
2950 /* Force LPI Mode without a delay */
2951 set |= LPI_MODE_EN;
2952 mt7530_rmw(priv, MT7530_PMEEECR_P(port), mask, set);
2953
2954 return 0;
2955}
2956
3072static const struct dsa_switch_ops mt7530_switch_ops = {
2957const struct dsa_switch_ops mt7530_switch_ops = {
3073 .get_tag_protocol = mtk_get_tag_protocol,
3074 .setup = mt753x_setup,
3075 .get_strings = mt7530_get_strings,
3076 .get_ethtool_stats = mt7530_get_ethtool_stats,
3077 .get_sset_count = mt7530_get_sset_count,
3078 .set_ageing_time = mt7530_set_ageing_time,
3079 .port_enable = mt7530_port_enable,
3080 .port_disable = mt7530_port_disable,

--- 17 unchanged lines hidden (view full) ---

3098 .phylink_get_caps = mt753x_phylink_get_caps,
3099 .phylink_mac_select_pcs = mt753x_phylink_mac_select_pcs,
3100 .phylink_mac_config = mt753x_phylink_mac_config,
3101 .phylink_mac_link_down = mt753x_phylink_mac_link_down,
3102 .phylink_mac_link_up = mt753x_phylink_mac_link_up,
3103 .get_mac_eee = mt753x_get_mac_eee,
3104 .set_mac_eee = mt753x_set_mac_eee,
3105};
2958 .get_tag_protocol = mtk_get_tag_protocol,
2959 .setup = mt753x_setup,
2960 .get_strings = mt7530_get_strings,
2961 .get_ethtool_stats = mt7530_get_ethtool_stats,
2962 .get_sset_count = mt7530_get_sset_count,
2963 .set_ageing_time = mt7530_set_ageing_time,
2964 .port_enable = mt7530_port_enable,
2965 .port_disable = mt7530_port_disable,

--- 17 unchanged lines hidden (view full) ---

2983 .phylink_get_caps = mt753x_phylink_get_caps,
2984 .phylink_mac_select_pcs = mt753x_phylink_mac_select_pcs,
2985 .phylink_mac_config = mt753x_phylink_mac_config,
2986 .phylink_mac_link_down = mt753x_phylink_mac_link_down,
2987 .phylink_mac_link_up = mt753x_phylink_mac_link_up,
2988 .get_mac_eee = mt753x_get_mac_eee,
2989 .set_mac_eee = mt753x_set_mac_eee,
2990};
2991EXPORT_SYMBOL_GPL(mt7530_switch_ops);
3106
2992
3107static const struct mt753x_info mt753x_table[] = {
2993const struct mt753x_info mt753x_table[] = {
3108 [ID_MT7621] = {
3109 .id = ID_MT7621,
3110 .pcs_ops = &mt7530_pcs_ops,
3111 .sw_setup = mt7530_setup,
3112 .phy_read_c22 = mt7530_phy_read_c22,
3113 .phy_write_c22 = mt7530_phy_write_c22,
3114 .phy_read_c45 = mt7530_phy_read_c45,
3115 .phy_write_c45 = mt7530_phy_write_c45,

--- 22 unchanged lines hidden (view full) ---

3138 .phy_read_c45 = mt7531_ind_c45_phy_read,
3139 .phy_write_c45 = mt7531_ind_c45_phy_write,
3140 .pad_setup = mt7531_pad_setup,
3141 .cpu_port_config = mt7531_cpu_port_config,
3142 .mac_port_get_caps = mt7531_mac_port_get_caps,
3143 .mac_port_config = mt7531_mac_config,
3144 },
3145};
2994 [ID_MT7621] = {
2995 .id = ID_MT7621,
2996 .pcs_ops = &mt7530_pcs_ops,
2997 .sw_setup = mt7530_setup,
2998 .phy_read_c22 = mt7530_phy_read_c22,
2999 .phy_write_c22 = mt7530_phy_write_c22,
3000 .phy_read_c45 = mt7530_phy_read_c45,
3001 .phy_write_c45 = mt7530_phy_write_c45,

--- 22 unchanged lines hidden (view full) ---

3024 .phy_read_c45 = mt7531_ind_c45_phy_read,
3025 .phy_write_c45 = mt7531_ind_c45_phy_write,
3026 .pad_setup = mt7531_pad_setup,
3027 .cpu_port_config = mt7531_cpu_port_config,
3028 .mac_port_get_caps = mt7531_mac_port_get_caps,
3029 .mac_port_config = mt7531_mac_config,
3030 },
3031};
3032EXPORT_SYMBOL_GPL(mt753x_table);
3146
3033
3147static const struct of_device_id mt7530_of_match[] = {
3148 { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], },
3149 { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], },
3150 { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], },
3151 { /* sentinel */ },
3152};
3153MODULE_DEVICE_TABLE(of, mt7530_of_match);
3154
3155static int
3034int
3156mt7530_probe_common(struct mt7530_priv *priv)
3157{
3158 struct device *dev = priv->dev;
3159
3160 priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL);
3161 if (!priv->ds)
3162 return -ENOMEM;
3163

--- 20 unchanged lines hidden (view full) ---

3184 priv->dev = dev;
3185 priv->ds->priv = priv;
3186 priv->ds->ops = &mt7530_switch_ops;
3187 mutex_init(&priv->reg_mutex);
3188 dev_set_drvdata(dev, priv);
3189
3190 return 0;
3191}
3035mt7530_probe_common(struct mt7530_priv *priv)
3036{
3037 struct device *dev = priv->dev;
3038
3039 priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL);
3040 if (!priv->ds)
3041 return -ENOMEM;
3042

--- 20 unchanged lines hidden (view full) ---

3063 priv->dev = dev;
3064 priv->ds->priv = priv;
3065 priv->ds->ops = &mt7530_switch_ops;
3066 mutex_init(&priv->reg_mutex);
3067 dev_set_drvdata(dev, priv);
3068
3069 return 0;
3070}
3071EXPORT_SYMBOL_GPL(mt7530_probe_common);
3192
3072
3193static int
3194mt7530_probe(struct mdio_device *mdiodev)
3195{
3196 static struct regmap_config *regmap_config;
3197 struct mt7530_priv *priv;
3198 struct device_node *dn;
3199 int ret;
3200
3201 dn = mdiodev->dev.of_node;
3202
3203 priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
3204 if (!priv)
3205 return -ENOMEM;
3206
3207 priv->bus = mdiodev->bus;
3208 priv->dev = &mdiodev->dev;
3209
3210 ret = mt7530_probe_common(priv);
3211 if (ret)
3212 return ret;
3213
3214 /* Use medatek,mcm property to distinguish hardware type that would
3215 * cause a little bit differences on power-on sequence.
3216 * Not MCM that indicates switch works as the remote standalone
3217 * integrated circuit so the GPIO pin would be used to complete
3218 * the reset, otherwise memory-mapped register accessing used
3219 * through syscon provides in the case of MCM.
3220 */
3221 priv->mcm = of_property_read_bool(dn, "mediatek,mcm");
3222 if (priv->mcm) {
3223 dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n");
3224
3225 priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm");
3226 if (IS_ERR(priv->rstc)) {
3227 dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
3228 return PTR_ERR(priv->rstc);
3229 }
3230 } else {
3231 priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset",
3232 GPIOD_OUT_LOW);
3233 if (IS_ERR(priv->reset)) {
3234 dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
3235 return PTR_ERR(priv->reset);
3236 }
3237 }
3238
3239 if (priv->id == ID_MT7530) {
3240 priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
3241 if (IS_ERR(priv->core_pwr))
3242 return PTR_ERR(priv->core_pwr);
3243
3244 priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io");
3245 if (IS_ERR(priv->io_pwr))
3246 return PTR_ERR(priv->io_pwr);
3247 }
3248
3249 regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config),
3250 GFP_KERNEL);
3251 if (!regmap_config)
3252 return -ENOMEM;
3253
3254 regmap_config->reg_bits = 16;
3255 regmap_config->val_bits = 32;
3256 regmap_config->reg_stride = 4;
3257 regmap_config->max_register = MT7530_CREV;
3258 regmap_config->disable_locking = true;
3259 priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus,
3260 priv->bus, regmap_config);
3261 if (IS_ERR(priv->regmap))
3262 return PTR_ERR(priv->regmap);
3263
3264 if (priv->id == ID_MT7531) {
3265 ret = mt7531_create_sgmii(priv);
3266 if (ret)
3267 return ret;
3268 }
3269
3270 return dsa_register_switch(priv->ds);
3271}
3272
3273static void
3073void
3274mt7530_remove_common(struct mt7530_priv *priv)
3275{
3276 if (priv->irq)
3277 mt7530_free_irq(priv);
3278
3279 dsa_unregister_switch(priv->ds);
3280
3281 mutex_destroy(&priv->reg_mutex);
3282}
3074mt7530_remove_common(struct mt7530_priv *priv)
3075{
3076 if (priv->irq)
3077 mt7530_free_irq(priv);
3078
3079 dsa_unregister_switch(priv->ds);
3080
3081 mutex_destroy(&priv->reg_mutex);
3082}
3083EXPORT_SYMBOL_GPL(mt7530_remove_common);
3283
3084
3284static void
3285mt7530_remove(struct mdio_device *mdiodev)
3286{
3287 struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
3288 int ret = 0, i;
3289
3290 if (!priv)
3291 return;
3292
3293 ret = regulator_disable(priv->core_pwr);
3294 if (ret < 0)
3295 dev_err(priv->dev,
3296 "Failed to disable core power: %d\n", ret);
3297
3298 ret = regulator_disable(priv->io_pwr);
3299 if (ret < 0)
3300 dev_err(priv->dev, "Failed to disable io pwr: %d\n",
3301 ret);
3302
3303 mt7530_remove_common(priv);
3304
3305 for (i = 0; i < 2; ++i)
3306 mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs);
3307}
3308
3309static void mt7530_shutdown(struct mdio_device *mdiodev)
3310{
3311 struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
3312
3313 if (!priv)
3314 return;
3315
3316 dsa_switch_shutdown(priv->ds);
3317
3318 dev_set_drvdata(&mdiodev->dev, NULL);
3319}
3320
3321static struct mdio_driver mt7530_mdio_driver = {
3322 .probe = mt7530_probe,
3323 .remove = mt7530_remove,
3324 .shutdown = mt7530_shutdown,
3325 .mdiodrv.driver = {
3326 .name = "mt7530",
3327 .of_match_table = mt7530_of_match,
3328 },
3329};
3330
3331mdio_module_driver(mt7530_mdio_driver);
3332
3333MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
3334MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch");
3335MODULE_LICENSE("GPL");
3085MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
3086MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch");
3087MODULE_LICENSE("GPL");