1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Microchip switch driver main logic 4 * 5 * Copyright (C) 2017-2018 Microchip Technology Inc. 6 */ 7 8 #include <linux/delay.h> 9 #include <linux/export.h> 10 #include <linux/gpio.h> 11 #include <linux/gpio/consumer.h> 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 #include <linux/platform_data/microchip-ksz.h> 15 #include <linux/phy.h> 16 #include <linux/etherdevice.h> 17 #include <linux/if_bridge.h> 18 #include <linux/of_gpio.h> 19 #include <linux/of_net.h> 20 #include <net/dsa.h> 21 #include <net/switchdev.h> 22 23 #include "ksz_priv.h" 24 25 void ksz_update_port_member(struct ksz_device *dev, int port) 26 { 27 struct ksz_port *p; 28 int i; 29 30 for (i = 0; i < dev->port_cnt; i++) { 31 if (i == port || i == dev->cpu_port) 32 continue; 33 p = &dev->ports[i]; 34 if (!(dev->member & (1 << i))) 35 continue; 36 37 /* Port is a member of the bridge and is forwarding. */ 38 if (p->stp_state == BR_STATE_FORWARDING && 39 p->member != dev->member) 40 dev->dev_ops->cfg_port_member(dev, i, dev->member); 41 } 42 } 43 EXPORT_SYMBOL_GPL(ksz_update_port_member); 44 45 int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg) 46 { 47 struct ksz_device *dev = ds->priv; 48 u16 val = 0xffff; 49 50 dev->dev_ops->r_phy(dev, addr, reg, &val); 51 52 return val; 53 } 54 EXPORT_SYMBOL_GPL(ksz_phy_read16); 55 56 int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val) 57 { 58 struct ksz_device *dev = ds->priv; 59 60 dev->dev_ops->w_phy(dev, addr, reg, val); 61 62 return 0; 63 } 64 EXPORT_SYMBOL_GPL(ksz_phy_write16); 65 66 int ksz_sset_count(struct dsa_switch *ds, int port, int sset) 67 { 68 struct ksz_device *dev = ds->priv; 69 70 if (sset != ETH_SS_STATS) 71 return 0; 72 73 return dev->mib_cnt; 74 } 75 EXPORT_SYMBOL_GPL(ksz_sset_count); 76 77 int ksz_port_bridge_join(struct dsa_switch *ds, int port, 78 struct net_device *br) 79 { 80 struct ksz_device *dev = ds->priv; 81 82 dev->br_member |= (1 << port); 83 84 /* port_stp_state_set() will be called after to put the port in 85 * appropriate state so there is no need to do anything. 86 */ 87 88 return 0; 89 } 90 EXPORT_SYMBOL_GPL(ksz_port_bridge_join); 91 92 void ksz_port_bridge_leave(struct dsa_switch *ds, int port, 93 struct net_device *br) 94 { 95 struct ksz_device *dev = ds->priv; 96 97 dev->br_member &= ~(1 << port); 98 dev->member &= ~(1 << port); 99 100 /* port_stp_state_set() will be called after to put the port in 101 * forwarding state so there is no need to do anything. 102 */ 103 } 104 EXPORT_SYMBOL_GPL(ksz_port_bridge_leave); 105 106 void ksz_port_fast_age(struct dsa_switch *ds, int port) 107 { 108 struct ksz_device *dev = ds->priv; 109 110 dev->dev_ops->flush_dyn_mac_table(dev, port); 111 } 112 EXPORT_SYMBOL_GPL(ksz_port_fast_age); 113 114 int ksz_port_vlan_prepare(struct dsa_switch *ds, int port, 115 const struct switchdev_obj_port_vlan *vlan) 116 { 117 /* nothing needed */ 118 119 return 0; 120 } 121 EXPORT_SYMBOL_GPL(ksz_port_vlan_prepare); 122 123 int ksz_port_fdb_dump(struct dsa_switch *ds, int port, dsa_fdb_dump_cb_t *cb, 124 void *data) 125 { 126 struct ksz_device *dev = ds->priv; 127 int ret = 0; 128 u16 i = 0; 129 u16 entries = 0; 130 u8 timestamp = 0; 131 u8 fid; 132 u8 member; 133 struct alu_struct alu; 134 135 do { 136 alu.is_static = false; 137 ret = dev->dev_ops->r_dyn_mac_table(dev, i, alu.mac, &fid, 138 &member, ×tamp, 139 &entries); 140 if (!ret && (member & BIT(port))) { 141 ret = cb(alu.mac, alu.fid, alu.is_static, data); 142 if (ret) 143 break; 144 } 145 i++; 146 } while (i < entries); 147 if (i >= entries) 148 ret = 0; 149 150 return ret; 151 } 152 EXPORT_SYMBOL_GPL(ksz_port_fdb_dump); 153 154 int ksz_port_mdb_prepare(struct dsa_switch *ds, int port, 155 const struct switchdev_obj_port_mdb *mdb) 156 { 157 /* nothing to do */ 158 return 0; 159 } 160 EXPORT_SYMBOL_GPL(ksz_port_mdb_prepare); 161 162 void ksz_port_mdb_add(struct dsa_switch *ds, int port, 163 const struct switchdev_obj_port_mdb *mdb) 164 { 165 struct ksz_device *dev = ds->priv; 166 struct alu_struct alu; 167 int index; 168 int empty = 0; 169 170 alu.port_forward = 0; 171 for (index = 0; index < dev->num_statics; index++) { 172 if (!dev->dev_ops->r_sta_mac_table(dev, index, &alu)) { 173 /* Found one already in static MAC table. */ 174 if (!memcmp(alu.mac, mdb->addr, ETH_ALEN) && 175 alu.fid == mdb->vid) 176 break; 177 /* Remember the first empty entry. */ 178 } else if (!empty) { 179 empty = index + 1; 180 } 181 } 182 183 /* no available entry */ 184 if (index == dev->num_statics && !empty) 185 return; 186 187 /* add entry */ 188 if (index == dev->num_statics) { 189 index = empty - 1; 190 memset(&alu, 0, sizeof(alu)); 191 memcpy(alu.mac, mdb->addr, ETH_ALEN); 192 alu.is_static = true; 193 } 194 alu.port_forward |= BIT(port); 195 if (mdb->vid) { 196 alu.is_use_fid = true; 197 198 /* Need a way to map VID to FID. */ 199 alu.fid = mdb->vid; 200 } 201 dev->dev_ops->w_sta_mac_table(dev, index, &alu); 202 } 203 EXPORT_SYMBOL_GPL(ksz_port_mdb_add); 204 205 int ksz_port_mdb_del(struct dsa_switch *ds, int port, 206 const struct switchdev_obj_port_mdb *mdb) 207 { 208 struct ksz_device *dev = ds->priv; 209 struct alu_struct alu; 210 int index; 211 int ret = 0; 212 213 for (index = 0; index < dev->num_statics; index++) { 214 if (!dev->dev_ops->r_sta_mac_table(dev, index, &alu)) { 215 /* Found one already in static MAC table. */ 216 if (!memcmp(alu.mac, mdb->addr, ETH_ALEN) && 217 alu.fid == mdb->vid) 218 break; 219 } 220 } 221 222 /* no available entry */ 223 if (index == dev->num_statics) 224 goto exit; 225 226 /* clear port */ 227 alu.port_forward &= ~BIT(port); 228 if (!alu.port_forward) 229 alu.is_static = false; 230 dev->dev_ops->w_sta_mac_table(dev, index, &alu); 231 232 exit: 233 return ret; 234 } 235 EXPORT_SYMBOL_GPL(ksz_port_mdb_del); 236 237 int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy) 238 { 239 struct ksz_device *dev = ds->priv; 240 241 /* setup slave port */ 242 dev->dev_ops->port_setup(dev, port, false); 243 244 /* port_stp_state_set() will be called after to enable the port so 245 * there is no need to do anything. 246 */ 247 248 return 0; 249 } 250 EXPORT_SYMBOL_GPL(ksz_enable_port); 251 252 void ksz_disable_port(struct dsa_switch *ds, int port, struct phy_device *phy) 253 { 254 struct ksz_device *dev = ds->priv; 255 256 dev->on_ports &= ~(1 << port); 257 dev->live_ports &= ~(1 << port); 258 259 /* port_stp_state_set() will be called after to disable the port so 260 * there is no need to do anything. 261 */ 262 } 263 EXPORT_SYMBOL_GPL(ksz_disable_port); 264 265 struct ksz_device *ksz_switch_alloc(struct device *base, 266 const struct ksz_io_ops *ops, 267 void *priv) 268 { 269 struct dsa_switch *ds; 270 struct ksz_device *swdev; 271 272 ds = dsa_switch_alloc(base, DSA_MAX_PORTS); 273 if (!ds) 274 return NULL; 275 276 swdev = devm_kzalloc(base, sizeof(*swdev), GFP_KERNEL); 277 if (!swdev) 278 return NULL; 279 280 ds->priv = swdev; 281 swdev->dev = base; 282 283 swdev->ds = ds; 284 swdev->priv = priv; 285 swdev->ops = ops; 286 287 return swdev; 288 } 289 EXPORT_SYMBOL(ksz_switch_alloc); 290 291 int ksz_switch_register(struct ksz_device *dev, 292 const struct ksz_dev_ops *ops) 293 { 294 int ret; 295 296 if (dev->pdata) 297 dev->chip_id = dev->pdata->chip_id; 298 299 dev->reset_gpio = devm_gpiod_get_optional(dev->dev, "reset", 300 GPIOD_OUT_LOW); 301 if (IS_ERR(dev->reset_gpio)) 302 return PTR_ERR(dev->reset_gpio); 303 304 if (dev->reset_gpio) { 305 gpiod_set_value(dev->reset_gpio, 1); 306 mdelay(10); 307 gpiod_set_value(dev->reset_gpio, 0); 308 } 309 310 mutex_init(&dev->reg_mutex); 311 mutex_init(&dev->stats_mutex); 312 mutex_init(&dev->alu_mutex); 313 mutex_init(&dev->vlan_mutex); 314 315 dev->dev_ops = ops; 316 317 if (dev->dev_ops->detect(dev)) 318 return -EINVAL; 319 320 ret = dev->dev_ops->init(dev); 321 if (ret) 322 return ret; 323 324 dev->interface = PHY_INTERFACE_MODE_MII; 325 if (dev->dev->of_node) { 326 ret = of_get_phy_mode(dev->dev->of_node); 327 if (ret >= 0) 328 dev->interface = ret; 329 } 330 331 ret = dsa_register_switch(dev->ds); 332 if (ret) { 333 dev->dev_ops->exit(dev); 334 return ret; 335 } 336 337 return 0; 338 } 339 EXPORT_SYMBOL(ksz_switch_register); 340 341 void ksz_switch_remove(struct ksz_device *dev) 342 { 343 dev->dev_ops->exit(dev); 344 dsa_unregister_switch(dev->ds); 345 346 if (dev->reset_gpio) 347 gpiod_set_value(dev->reset_gpio, 1); 348 349 } 350 EXPORT_SYMBOL(ksz_switch_remove); 351 352 MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>"); 353 MODULE_DESCRIPTION("Microchip KSZ Series Switch DSA Driver"); 354 MODULE_LICENSE("GPL"); 355