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