1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Marvell 88E6xxx Address Translation Unit (ATU) support 4 * 5 * Copyright (c) 2008 Marvell Semiconductor 6 * Copyright (c) 2017 Savoir-faire Linux, Inc. 7 */ 8 9 #include <linux/bitfield.h> 10 #include <linux/interrupt.h> 11 #include <linux/irqdomain.h> 12 13 #include "chip.h" 14 #include "global1.h" 15 16 /* Offset 0x01: ATU FID Register */ 17 18 static int mv88e6xxx_g1_atu_fid_write(struct mv88e6xxx_chip *chip, u16 fid) 19 { 20 return mv88e6xxx_g1_write(chip, MV88E6352_G1_ATU_FID, fid & 0xfff); 21 } 22 23 /* Offset 0x0A: ATU Control Register */ 24 25 int mv88e6xxx_g1_atu_set_learn2all(struct mv88e6xxx_chip *chip, bool learn2all) 26 { 27 u16 val; 28 int err; 29 30 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL, &val); 31 if (err) 32 return err; 33 34 if (learn2all) 35 val |= MV88E6XXX_G1_ATU_CTL_LEARN2ALL; 36 else 37 val &= ~MV88E6XXX_G1_ATU_CTL_LEARN2ALL; 38 39 return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_CTL, val); 40 } 41 42 int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip, 43 unsigned int msecs) 44 { 45 const unsigned int coeff = chip->info->age_time_coeff; 46 const unsigned int min = 0x01 * coeff; 47 const unsigned int max = 0xff * coeff; 48 u8 age_time; 49 u16 val; 50 int err; 51 52 if (msecs < min || msecs > max) 53 return -ERANGE; 54 55 /* Round to nearest multiple of coeff */ 56 age_time = (msecs + coeff / 2) / coeff; 57 58 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL, &val); 59 if (err) 60 return err; 61 62 /* AgeTime is 11:4 bits */ 63 val &= ~0xff0; 64 val |= age_time << 4; 65 66 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_CTL, val); 67 if (err) 68 return err; 69 70 dev_dbg(chip->dev, "AgeTime set to 0x%02x (%d ms)\n", age_time, 71 age_time * coeff); 72 73 return 0; 74 } 75 76 /* Offset 0x0B: ATU Operation Register */ 77 78 static int mv88e6xxx_g1_atu_op_wait(struct mv88e6xxx_chip *chip) 79 { 80 int bit = __bf_shf(MV88E6XXX_G1_ATU_OP_BUSY); 81 82 return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_ATU_OP, bit, 0); 83 } 84 85 static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op) 86 { 87 u16 val; 88 int err; 89 90 /* FID bits are dispatched all around gradually as more are supported */ 91 if (mv88e6xxx_num_databases(chip) > 256) { 92 err = mv88e6xxx_g1_atu_fid_write(chip, fid); 93 if (err) 94 return err; 95 } else { 96 if (mv88e6xxx_num_databases(chip) > 64) { 97 /* ATU DBNum[7:4] are located in ATU Control 15:12 */ 98 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL, 99 &val); 100 if (err) 101 return err; 102 103 val = (val & 0x0fff) | ((fid << 8) & 0xf000); 104 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_CTL, 105 val); 106 if (err) 107 return err; 108 } else if (mv88e6xxx_num_databases(chip) > 16) { 109 /* ATU DBNum[5:4] are located in ATU Operation 9:8 */ 110 op |= (fid & 0x30) << 4; 111 } 112 113 /* ATU DBNum[3:0] are located in ATU Operation 3:0 */ 114 op |= fid & 0xf; 115 } 116 117 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_OP, 118 MV88E6XXX_G1_ATU_OP_BUSY | op); 119 if (err) 120 return err; 121 122 return mv88e6xxx_g1_atu_op_wait(chip); 123 } 124 125 /* Offset 0x0C: ATU Data Register */ 126 127 static int mv88e6xxx_g1_atu_data_read(struct mv88e6xxx_chip *chip, 128 struct mv88e6xxx_atu_entry *entry) 129 { 130 u16 val; 131 int err; 132 133 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_DATA, &val); 134 if (err) 135 return err; 136 137 entry->state = val & 0xf; 138 if (entry->state) { 139 entry->trunk = !!(val & MV88E6XXX_G1_ATU_DATA_TRUNK); 140 entry->portvec = (val >> 4) & mv88e6xxx_port_mask(chip); 141 } 142 143 return 0; 144 } 145 146 static int mv88e6xxx_g1_atu_data_write(struct mv88e6xxx_chip *chip, 147 struct mv88e6xxx_atu_entry *entry) 148 { 149 u16 data = entry->state & 0xf; 150 151 if (entry->state) { 152 if (entry->trunk) 153 data |= MV88E6XXX_G1_ATU_DATA_TRUNK; 154 155 data |= (entry->portvec & mv88e6xxx_port_mask(chip)) << 4; 156 } 157 158 return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_DATA, data); 159 } 160 161 /* Offset 0x0D: ATU MAC Address Register Bytes 0 & 1 162 * Offset 0x0E: ATU MAC Address Register Bytes 2 & 3 163 * Offset 0x0F: ATU MAC Address Register Bytes 4 & 5 164 */ 165 166 static int mv88e6xxx_g1_atu_mac_read(struct mv88e6xxx_chip *chip, 167 struct mv88e6xxx_atu_entry *entry) 168 { 169 u16 val; 170 int i, err; 171 172 for (i = 0; i < 3; i++) { 173 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_MAC01 + i, &val); 174 if (err) 175 return err; 176 177 entry->mac[i * 2] = val >> 8; 178 entry->mac[i * 2 + 1] = val & 0xff; 179 } 180 181 return 0; 182 } 183 184 static int mv88e6xxx_g1_atu_mac_write(struct mv88e6xxx_chip *chip, 185 struct mv88e6xxx_atu_entry *entry) 186 { 187 u16 val; 188 int i, err; 189 190 for (i = 0; i < 3; i++) { 191 val = (entry->mac[i * 2] << 8) | entry->mac[i * 2 + 1]; 192 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_MAC01 + i, val); 193 if (err) 194 return err; 195 } 196 197 return 0; 198 } 199 200 /* Address Translation Unit operations */ 201 202 int mv88e6xxx_g1_atu_getnext(struct mv88e6xxx_chip *chip, u16 fid, 203 struct mv88e6xxx_atu_entry *entry) 204 { 205 int err; 206 207 err = mv88e6xxx_g1_atu_op_wait(chip); 208 if (err) 209 return err; 210 211 /* Write the MAC address to iterate from only once */ 212 if (!entry->state) { 213 err = mv88e6xxx_g1_atu_mac_write(chip, entry); 214 if (err) 215 return err; 216 } 217 218 err = mv88e6xxx_g1_atu_op(chip, fid, MV88E6XXX_G1_ATU_OP_GET_NEXT_DB); 219 if (err) 220 return err; 221 222 err = mv88e6xxx_g1_atu_data_read(chip, entry); 223 if (err) 224 return err; 225 226 return mv88e6xxx_g1_atu_mac_read(chip, entry); 227 } 228 229 int mv88e6xxx_g1_atu_loadpurge(struct mv88e6xxx_chip *chip, u16 fid, 230 struct mv88e6xxx_atu_entry *entry) 231 { 232 int err; 233 234 err = mv88e6xxx_g1_atu_op_wait(chip); 235 if (err) 236 return err; 237 238 err = mv88e6xxx_g1_atu_mac_write(chip, entry); 239 if (err) 240 return err; 241 242 err = mv88e6xxx_g1_atu_data_write(chip, entry); 243 if (err) 244 return err; 245 246 return mv88e6xxx_g1_atu_op(chip, fid, MV88E6XXX_G1_ATU_OP_LOAD_DB); 247 } 248 249 static int mv88e6xxx_g1_atu_flushmove(struct mv88e6xxx_chip *chip, u16 fid, 250 struct mv88e6xxx_atu_entry *entry, 251 bool all) 252 { 253 u16 op; 254 int err; 255 256 err = mv88e6xxx_g1_atu_op_wait(chip); 257 if (err) 258 return err; 259 260 err = mv88e6xxx_g1_atu_data_write(chip, entry); 261 if (err) 262 return err; 263 264 /* Flush/Move all or non-static entries from all or a given database */ 265 if (all && fid) 266 op = MV88E6XXX_G1_ATU_OP_FLUSH_MOVE_ALL_DB; 267 else if (fid) 268 op = MV88E6XXX_G1_ATU_OP_FLUSH_MOVE_NON_STATIC_DB; 269 else if (all) 270 op = MV88E6XXX_G1_ATU_OP_FLUSH_MOVE_ALL; 271 else 272 op = MV88E6XXX_G1_ATU_OP_FLUSH_MOVE_NON_STATIC; 273 274 return mv88e6xxx_g1_atu_op(chip, fid, op); 275 } 276 277 int mv88e6xxx_g1_atu_flush(struct mv88e6xxx_chip *chip, u16 fid, bool all) 278 { 279 struct mv88e6xxx_atu_entry entry = { 280 .state = 0, /* Null EntryState means Flush */ 281 }; 282 283 return mv88e6xxx_g1_atu_flushmove(chip, fid, &entry, all); 284 } 285 286 static int mv88e6xxx_g1_atu_move(struct mv88e6xxx_chip *chip, u16 fid, 287 int from_port, int to_port, bool all) 288 { 289 struct mv88e6xxx_atu_entry entry = { 0 }; 290 unsigned long mask; 291 int shift; 292 293 if (!chip->info->atu_move_port_mask) 294 return -EOPNOTSUPP; 295 296 mask = chip->info->atu_move_port_mask; 297 shift = bitmap_weight(&mask, 16); 298 299 entry.state = 0xf, /* Full EntryState means Move */ 300 entry.portvec = from_port & mask; 301 entry.portvec |= (to_port & mask) << shift; 302 303 return mv88e6xxx_g1_atu_flushmove(chip, fid, &entry, all); 304 } 305 306 int mv88e6xxx_g1_atu_remove(struct mv88e6xxx_chip *chip, u16 fid, int port, 307 bool all) 308 { 309 int from_port = port; 310 int to_port = chip->info->atu_move_port_mask; 311 312 return mv88e6xxx_g1_atu_move(chip, fid, from_port, to_port, all); 313 } 314 315 static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id) 316 { 317 struct mv88e6xxx_chip *chip = dev_id; 318 struct mv88e6xxx_atu_entry entry; 319 int spid; 320 int err; 321 u16 val; 322 323 mv88e6xxx_reg_lock(chip); 324 325 err = mv88e6xxx_g1_atu_op(chip, 0, 326 MV88E6XXX_G1_ATU_OP_GET_CLR_VIOLATION); 327 if (err) 328 goto out; 329 330 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_OP, &val); 331 if (err) 332 goto out; 333 334 err = mv88e6xxx_g1_atu_data_read(chip, &entry); 335 if (err) 336 goto out; 337 338 err = mv88e6xxx_g1_atu_mac_read(chip, &entry); 339 if (err) 340 goto out; 341 342 spid = entry.state; 343 344 if (val & MV88E6XXX_G1_ATU_OP_AGE_OUT_VIOLATION) { 345 dev_err_ratelimited(chip->dev, 346 "ATU age out violation for %pM\n", 347 entry.mac); 348 } 349 350 if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) { 351 dev_err_ratelimited(chip->dev, 352 "ATU member violation for %pM portvec %x spid %d\n", 353 entry.mac, entry.portvec, spid); 354 chip->ports[spid].atu_member_violation++; 355 } 356 357 if (val & MV88E6XXX_G1_ATU_OP_MISS_VIOLATION) { 358 dev_err_ratelimited(chip->dev, 359 "ATU miss violation for %pM portvec %x spid %d\n", 360 entry.mac, entry.portvec, spid); 361 chip->ports[spid].atu_miss_violation++; 362 } 363 364 if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) { 365 dev_err_ratelimited(chip->dev, 366 "ATU full violation for %pM portvec %x spid %d\n", 367 entry.mac, entry.portvec, spid); 368 chip->ports[spid].atu_full_violation++; 369 } 370 mv88e6xxx_reg_unlock(chip); 371 372 return IRQ_HANDLED; 373 374 out: 375 mv88e6xxx_reg_unlock(chip); 376 377 dev_err(chip->dev, "ATU problem: error %d while handling interrupt\n", 378 err); 379 return IRQ_HANDLED; 380 } 381 382 int mv88e6xxx_g1_atu_prob_irq_setup(struct mv88e6xxx_chip *chip) 383 { 384 int err; 385 386 chip->atu_prob_irq = irq_find_mapping(chip->g1_irq.domain, 387 MV88E6XXX_G1_STS_IRQ_ATU_PROB); 388 if (chip->atu_prob_irq < 0) 389 return chip->atu_prob_irq; 390 391 err = request_threaded_irq(chip->atu_prob_irq, NULL, 392 mv88e6xxx_g1_atu_prob_irq_thread_fn, 393 IRQF_ONESHOT, "mv88e6xxx-g1-atu-prob", 394 chip); 395 if (err) 396 irq_dispose_mapping(chip->atu_prob_irq); 397 398 return err; 399 } 400 401 void mv88e6xxx_g1_atu_prob_irq_free(struct mv88e6xxx_chip *chip) 402 { 403 free_irq(chip->atu_prob_irq, chip); 404 irq_dispose_mapping(chip->atu_prob_irq); 405 } 406