Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Marvell 88E6xxx Address Translation Unit (ATU) support
0004  *
0005  * Copyright (c) 2008 Marvell Semiconductor
0006  * Copyright (c) 2017 Savoir-faire Linux, Inc.
0007  */
0008 
0009 #include <linux/bitfield.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/irqdomain.h>
0012 
0013 #include "chip.h"
0014 #include "global1.h"
0015 
0016 /* Offset 0x01: ATU FID Register */
0017 
0018 static int mv88e6xxx_g1_atu_fid_write(struct mv88e6xxx_chip *chip, u16 fid)
0019 {
0020     return mv88e6xxx_g1_write(chip, MV88E6352_G1_ATU_FID, fid & 0xfff);
0021 }
0022 
0023 /* Offset 0x0A: ATU Control Register */
0024 
0025 int mv88e6xxx_g1_atu_set_learn2all(struct mv88e6xxx_chip *chip, bool learn2all)
0026 {
0027     u16 val;
0028     int err;
0029 
0030     err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL, &val);
0031     if (err)
0032         return err;
0033 
0034     if (learn2all)
0035         val |= MV88E6XXX_G1_ATU_CTL_LEARN2ALL;
0036     else
0037         val &= ~MV88E6XXX_G1_ATU_CTL_LEARN2ALL;
0038 
0039     return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_CTL, val);
0040 }
0041 
0042 int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip,
0043                   unsigned int msecs)
0044 {
0045     const unsigned int coeff = chip->info->age_time_coeff;
0046     const unsigned int min = 0x01 * coeff;
0047     const unsigned int max = 0xff * coeff;
0048     u8 age_time;
0049     u16 val;
0050     int err;
0051 
0052     if (msecs < min || msecs > max)
0053         return -ERANGE;
0054 
0055     /* Round to nearest multiple of coeff */
0056     age_time = (msecs + coeff / 2) / coeff;
0057 
0058     err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL, &val);
0059     if (err)
0060         return err;
0061 
0062     /* AgeTime is 11:4 bits */
0063     val &= ~0xff0;
0064     val |= age_time << 4;
0065 
0066     err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_CTL, val);
0067     if (err)
0068         return err;
0069 
0070     dev_dbg(chip->dev, "AgeTime set to 0x%02x (%d ms)\n", age_time,
0071         age_time * coeff);
0072 
0073     return 0;
0074 }
0075 
0076 int mv88e6165_g1_atu_get_hash(struct mv88e6xxx_chip *chip, u8 *hash)
0077 {
0078     int err;
0079     u16 val;
0080 
0081     err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL, &val);
0082     if (err)
0083         return err;
0084 
0085     *hash = val & MV88E6161_G1_ATU_CTL_HASH_MASK;
0086 
0087     return 0;
0088 }
0089 
0090 int mv88e6165_g1_atu_set_hash(struct mv88e6xxx_chip *chip, u8 hash)
0091 {
0092     int err;
0093     u16 val;
0094 
0095     if (hash & ~MV88E6161_G1_ATU_CTL_HASH_MASK)
0096         return -EINVAL;
0097 
0098     err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL, &val);
0099     if (err)
0100         return err;
0101 
0102     val &= ~MV88E6161_G1_ATU_CTL_HASH_MASK;
0103     val |= hash;
0104 
0105     return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_CTL, val);
0106 }
0107 
0108 /* Offset 0x0B: ATU Operation Register */
0109 
0110 static int mv88e6xxx_g1_atu_op_wait(struct mv88e6xxx_chip *chip)
0111 {
0112     int bit = __bf_shf(MV88E6XXX_G1_ATU_OP_BUSY);
0113 
0114     return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_ATU_OP, bit, 0);
0115 }
0116 
0117 static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op)
0118 {
0119     u16 val;
0120     int err;
0121 
0122     /* FID bits are dispatched all around gradually as more are supported */
0123     if (mv88e6xxx_num_databases(chip) > 256) {
0124         err = mv88e6xxx_g1_atu_fid_write(chip, fid);
0125         if (err)
0126             return err;
0127     } else {
0128         if (mv88e6xxx_num_databases(chip) > 64) {
0129             /* ATU DBNum[7:4] are located in ATU Control 15:12 */
0130             err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL,
0131                         &val);
0132             if (err)
0133                 return err;
0134 
0135             val = (val & 0x0fff) | ((fid << 8) & 0xf000);
0136             err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_CTL,
0137                          val);
0138             if (err)
0139                 return err;
0140         } else if (mv88e6xxx_num_databases(chip) > 16) {
0141             /* ATU DBNum[5:4] are located in ATU Operation 9:8 */
0142             op |= (fid & 0x30) << 4;
0143         }
0144 
0145         /* ATU DBNum[3:0] are located in ATU Operation 3:0 */
0146         op |= fid & 0xf;
0147     }
0148 
0149     err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_OP,
0150                  MV88E6XXX_G1_ATU_OP_BUSY | op);
0151     if (err)
0152         return err;
0153 
0154     return mv88e6xxx_g1_atu_op_wait(chip);
0155 }
0156 
0157 int mv88e6xxx_g1_atu_get_next(struct mv88e6xxx_chip *chip, u16 fid)
0158 {
0159     return mv88e6xxx_g1_atu_op(chip, fid, MV88E6XXX_G1_ATU_OP_GET_NEXT_DB);
0160 }
0161 
0162 /* Offset 0x0C: ATU Data Register */
0163 
0164 static int mv88e6xxx_g1_atu_data_read(struct mv88e6xxx_chip *chip,
0165                       struct mv88e6xxx_atu_entry *entry)
0166 {
0167     u16 val;
0168     int err;
0169 
0170     err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_DATA, &val);
0171     if (err)
0172         return err;
0173 
0174     entry->state = val & 0xf;
0175     if (entry->state) {
0176         entry->trunk = !!(val & MV88E6XXX_G1_ATU_DATA_TRUNK);
0177         entry->portvec = (val >> 4) & mv88e6xxx_port_mask(chip);
0178     }
0179 
0180     return 0;
0181 }
0182 
0183 static int mv88e6xxx_g1_atu_data_write(struct mv88e6xxx_chip *chip,
0184                        struct mv88e6xxx_atu_entry *entry)
0185 {
0186     u16 data = entry->state & 0xf;
0187 
0188     if (entry->state) {
0189         if (entry->trunk)
0190             data |= MV88E6XXX_G1_ATU_DATA_TRUNK;
0191 
0192         data |= (entry->portvec & mv88e6xxx_port_mask(chip)) << 4;
0193     }
0194 
0195     return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_DATA, data);
0196 }
0197 
0198 /* Offset 0x0D: ATU MAC Address Register Bytes 0 & 1
0199  * Offset 0x0E: ATU MAC Address Register Bytes 2 & 3
0200  * Offset 0x0F: ATU MAC Address Register Bytes 4 & 5
0201  */
0202 
0203 static int mv88e6xxx_g1_atu_mac_read(struct mv88e6xxx_chip *chip,
0204                      struct mv88e6xxx_atu_entry *entry)
0205 {
0206     u16 val;
0207     int i, err;
0208 
0209     for (i = 0; i < 3; i++) {
0210         err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_MAC01 + i, &val);
0211         if (err)
0212             return err;
0213 
0214         entry->mac[i * 2] = val >> 8;
0215         entry->mac[i * 2 + 1] = val & 0xff;
0216     }
0217 
0218     return 0;
0219 }
0220 
0221 static int mv88e6xxx_g1_atu_mac_write(struct mv88e6xxx_chip *chip,
0222                       struct mv88e6xxx_atu_entry *entry)
0223 {
0224     u16 val;
0225     int i, err;
0226 
0227     for (i = 0; i < 3; i++) {
0228         val = (entry->mac[i * 2] << 8) | entry->mac[i * 2 + 1];
0229         err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_MAC01 + i, val);
0230         if (err)
0231             return err;
0232     }
0233 
0234     return 0;
0235 }
0236 
0237 /* Address Translation Unit operations */
0238 
0239 int mv88e6xxx_g1_atu_getnext(struct mv88e6xxx_chip *chip, u16 fid,
0240                  struct mv88e6xxx_atu_entry *entry)
0241 {
0242     int err;
0243 
0244     err = mv88e6xxx_g1_atu_op_wait(chip);
0245     if (err)
0246         return err;
0247 
0248     /* Write the MAC address to iterate from only once */
0249     if (!entry->state) {
0250         err = mv88e6xxx_g1_atu_mac_write(chip, entry);
0251         if (err)
0252             return err;
0253     }
0254 
0255     err = mv88e6xxx_g1_atu_op(chip, fid, MV88E6XXX_G1_ATU_OP_GET_NEXT_DB);
0256     if (err)
0257         return err;
0258 
0259     err = mv88e6xxx_g1_atu_data_read(chip, entry);
0260     if (err)
0261         return err;
0262 
0263     return mv88e6xxx_g1_atu_mac_read(chip, entry);
0264 }
0265 
0266 int mv88e6xxx_g1_atu_loadpurge(struct mv88e6xxx_chip *chip, u16 fid,
0267                    struct mv88e6xxx_atu_entry *entry)
0268 {
0269     int err;
0270 
0271     err = mv88e6xxx_g1_atu_op_wait(chip);
0272     if (err)
0273         return err;
0274 
0275     err = mv88e6xxx_g1_atu_mac_write(chip, entry);
0276     if (err)
0277         return err;
0278 
0279     err = mv88e6xxx_g1_atu_data_write(chip, entry);
0280     if (err)
0281         return err;
0282 
0283     return mv88e6xxx_g1_atu_op(chip, fid, MV88E6XXX_G1_ATU_OP_LOAD_DB);
0284 }
0285 
0286 static int mv88e6xxx_g1_atu_flushmove(struct mv88e6xxx_chip *chip, u16 fid,
0287                       struct mv88e6xxx_atu_entry *entry,
0288                       bool all)
0289 {
0290     u16 op;
0291     int err;
0292 
0293     err = mv88e6xxx_g1_atu_op_wait(chip);
0294     if (err)
0295         return err;
0296 
0297     err = mv88e6xxx_g1_atu_data_write(chip, entry);
0298     if (err)
0299         return err;
0300 
0301     /* Flush/Move all or non-static entries from all or a given database */
0302     if (all && fid)
0303         op = MV88E6XXX_G1_ATU_OP_FLUSH_MOVE_ALL_DB;
0304     else if (fid)
0305         op = MV88E6XXX_G1_ATU_OP_FLUSH_MOVE_NON_STATIC_DB;
0306     else if (all)
0307         op = MV88E6XXX_G1_ATU_OP_FLUSH_MOVE_ALL;
0308     else
0309         op = MV88E6XXX_G1_ATU_OP_FLUSH_MOVE_NON_STATIC;
0310 
0311     return mv88e6xxx_g1_atu_op(chip, fid, op);
0312 }
0313 
0314 int mv88e6xxx_g1_atu_flush(struct mv88e6xxx_chip *chip, u16 fid, bool all)
0315 {
0316     struct mv88e6xxx_atu_entry entry = {
0317         .state = 0, /* Null EntryState means Flush */
0318     };
0319 
0320     return mv88e6xxx_g1_atu_flushmove(chip, fid, &entry, all);
0321 }
0322 
0323 static int mv88e6xxx_g1_atu_move(struct mv88e6xxx_chip *chip, u16 fid,
0324                  int from_port, int to_port, bool all)
0325 {
0326     struct mv88e6xxx_atu_entry entry = { 0 };
0327     unsigned long mask;
0328     int shift;
0329 
0330     if (!chip->info->atu_move_port_mask)
0331         return -EOPNOTSUPP;
0332 
0333     mask = chip->info->atu_move_port_mask;
0334     shift = bitmap_weight(&mask, 16);
0335 
0336     entry.state = 0xf; /* Full EntryState means Move */
0337     entry.portvec = from_port & mask;
0338     entry.portvec |= (to_port & mask) << shift;
0339 
0340     return mv88e6xxx_g1_atu_flushmove(chip, fid, &entry, all);
0341 }
0342 
0343 int mv88e6xxx_g1_atu_remove(struct mv88e6xxx_chip *chip, u16 fid, int port,
0344                 bool all)
0345 {
0346     int from_port = port;
0347     int to_port = chip->info->atu_move_port_mask;
0348 
0349     return mv88e6xxx_g1_atu_move(chip, fid, from_port, to_port, all);
0350 }
0351 
0352 static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
0353 {
0354     struct mv88e6xxx_chip *chip = dev_id;
0355     struct mv88e6xxx_atu_entry entry;
0356     int spid;
0357     int err;
0358     u16 val;
0359 
0360     mv88e6xxx_reg_lock(chip);
0361 
0362     err = mv88e6xxx_g1_atu_op(chip, 0,
0363                   MV88E6XXX_G1_ATU_OP_GET_CLR_VIOLATION);
0364     if (err)
0365         goto out;
0366 
0367     err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_OP, &val);
0368     if (err)
0369         goto out;
0370 
0371     err = mv88e6xxx_g1_atu_data_read(chip, &entry);
0372     if (err)
0373         goto out;
0374 
0375     err = mv88e6xxx_g1_atu_mac_read(chip, &entry);
0376     if (err)
0377         goto out;
0378 
0379     spid = entry.state;
0380 
0381     if (val & MV88E6XXX_G1_ATU_OP_AGE_OUT_VIOLATION) {
0382         dev_err_ratelimited(chip->dev,
0383                     "ATU age out violation for %pM\n",
0384                     entry.mac);
0385     }
0386 
0387     if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) {
0388         dev_err_ratelimited(chip->dev,
0389                     "ATU member violation for %pM portvec %x spid %d\n",
0390                     entry.mac, entry.portvec, spid);
0391         chip->ports[spid].atu_member_violation++;
0392     }
0393 
0394     if (val & MV88E6XXX_G1_ATU_OP_MISS_VIOLATION) {
0395         dev_err_ratelimited(chip->dev,
0396                     "ATU miss violation for %pM portvec %x spid %d\n",
0397                     entry.mac, entry.portvec, spid);
0398         chip->ports[spid].atu_miss_violation++;
0399     }
0400 
0401     if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) {
0402         dev_err_ratelimited(chip->dev,
0403                     "ATU full violation for %pM portvec %x spid %d\n",
0404                     entry.mac, entry.portvec, spid);
0405         chip->ports[spid].atu_full_violation++;
0406     }
0407     mv88e6xxx_reg_unlock(chip);
0408 
0409     return IRQ_HANDLED;
0410 
0411 out:
0412     mv88e6xxx_reg_unlock(chip);
0413 
0414     dev_err(chip->dev, "ATU problem: error %d while handling interrupt\n",
0415         err);
0416     return IRQ_HANDLED;
0417 }
0418 
0419 int mv88e6xxx_g1_atu_prob_irq_setup(struct mv88e6xxx_chip *chip)
0420 {
0421     int err;
0422 
0423     chip->atu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
0424                           MV88E6XXX_G1_STS_IRQ_ATU_PROB);
0425     if (chip->atu_prob_irq < 0)
0426         return chip->atu_prob_irq;
0427 
0428     snprintf(chip->atu_prob_irq_name, sizeof(chip->atu_prob_irq_name),
0429          "mv88e6xxx-%s-g1-atu-prob", dev_name(chip->dev));
0430 
0431     err = request_threaded_irq(chip->atu_prob_irq, NULL,
0432                    mv88e6xxx_g1_atu_prob_irq_thread_fn,
0433                    IRQF_ONESHOT, chip->atu_prob_irq_name,
0434                    chip);
0435     if (err)
0436         irq_dispose_mapping(chip->atu_prob_irq);
0437 
0438     return err;
0439 }
0440 
0441 void mv88e6xxx_g1_atu_prob_irq_free(struct mv88e6xxx_chip *chip)
0442 {
0443     free_irq(chip->atu_prob_irq, chip);
0444     irq_dispose_mapping(chip->atu_prob_irq);
0445 }