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"); |