Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Marvell 88E6xxx Switch Global 2 Registers support
0004  *
0005  * Copyright (c) 2008 Marvell Semiconductor
0006  *
0007  * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
0008  *  Vivien Didelot <vivien.didelot@savoirfairelinux.com>
0009  *
0010  * Copyright (c) 2017 National Instruments
0011  *  Brandon Streiff <brandon.streiff@ni.com>
0012  */
0013 
0014 #include <linux/bitfield.h>
0015 
0016 #include "global2.h"
0017 
0018 /* Offset 0x16: AVB Command Register
0019  * Offset 0x17: AVB Data Register
0020  *
0021  * There are two different versions of this register interface:
0022  *    "6352": 3-bit "op" field, 4-bit "port" field.
0023  *    "6390": 2-bit "op" field, 5-bit "port" field.
0024  *
0025  * The "op" codes are different between the two, as well as the special
0026  * port fields for global PTP and TAI configuration.
0027  */
0028 
0029 /* mv88e6xxx_g2_avb_read -- Read one or multiple 16-bit words.
0030  * The hardware supports snapshotting up to four contiguous registers.
0031  */
0032 static int mv88e6xxx_g2_avb_wait(struct mv88e6xxx_chip *chip)
0033 {
0034     int bit = __bf_shf(MV88E6352_G2_AVB_CMD_BUSY);
0035 
0036     return mv88e6xxx_g2_wait_bit(chip, MV88E6352_G2_AVB_CMD, bit, 0);
0037 }
0038 
0039 static int mv88e6xxx_g2_avb_read(struct mv88e6xxx_chip *chip, u16 readop,
0040                  u16 *data, int len)
0041 {
0042     int err;
0043     int i;
0044 
0045     err = mv88e6xxx_g2_avb_wait(chip);
0046     if (err)
0047         return err;
0048 
0049     /* Hardware can only snapshot four words. */
0050     if (len > 4)
0051         return -E2BIG;
0052 
0053     err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_CMD,
0054                  MV88E6352_G2_AVB_CMD_BUSY | readop);
0055     if (err)
0056         return err;
0057 
0058     err = mv88e6xxx_g2_avb_wait(chip);
0059     if (err)
0060         return err;
0061 
0062     for (i = 0; i < len; ++i) {
0063         err = mv88e6xxx_g2_read(chip, MV88E6352_G2_AVB_DATA,
0064                     &data[i]);
0065         if (err)
0066             return err;
0067     }
0068 
0069     return 0;
0070 }
0071 
0072 /* mv88e6xxx_g2_avb_write -- Write one 16-bit word. */
0073 static int mv88e6xxx_g2_avb_write(struct mv88e6xxx_chip *chip, u16 writeop,
0074                   u16 data)
0075 {
0076     int err;
0077 
0078     err = mv88e6xxx_g2_avb_wait(chip);
0079     if (err)
0080         return err;
0081 
0082     err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_DATA, data);
0083     if (err)
0084         return err;
0085 
0086     err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_CMD,
0087                  MV88E6352_G2_AVB_CMD_BUSY | writeop);
0088 
0089     return mv88e6xxx_g2_avb_wait(chip);
0090 }
0091 
0092 static int mv88e6352_g2_avb_port_ptp_read(struct mv88e6xxx_chip *chip,
0093                       int port, int addr, u16 *data,
0094                       int len)
0095 {
0096     u16 readop = (len == 1 ? MV88E6352_G2_AVB_CMD_OP_READ :
0097                  MV88E6352_G2_AVB_CMD_OP_READ_INCR) |
0098              (port << 8) | (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) |
0099              addr;
0100 
0101     return mv88e6xxx_g2_avb_read(chip, readop, data, len);
0102 }
0103 
0104 static int mv88e6352_g2_avb_port_ptp_write(struct mv88e6xxx_chip *chip,
0105                        int port, int addr, u16 data)
0106 {
0107     u16 writeop = MV88E6352_G2_AVB_CMD_OP_WRITE | (port << 8) |
0108               (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) | addr;
0109 
0110     return mv88e6xxx_g2_avb_write(chip, writeop, data);
0111 }
0112 
0113 static int mv88e6352_g2_avb_ptp_read(struct mv88e6xxx_chip *chip, int addr,
0114                      u16 *data, int len)
0115 {
0116     return mv88e6352_g2_avb_port_ptp_read(chip,
0117                     MV88E6352_G2_AVB_CMD_PORT_PTPGLOBAL,
0118                     addr, data, len);
0119 }
0120 
0121 static int mv88e6352_g2_avb_ptp_write(struct mv88e6xxx_chip *chip, int addr,
0122                       u16 data)
0123 {
0124     return mv88e6352_g2_avb_port_ptp_write(chip,
0125                     MV88E6352_G2_AVB_CMD_PORT_PTPGLOBAL,
0126                     addr, data);
0127 }
0128 
0129 static int mv88e6352_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
0130                      u16 *data, int len)
0131 {
0132     return mv88e6352_g2_avb_port_ptp_read(chip,
0133                     MV88E6352_G2_AVB_CMD_PORT_TAIGLOBAL,
0134                     addr, data, len);
0135 }
0136 
0137 static int mv88e6352_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
0138                       u16 data)
0139 {
0140     return mv88e6352_g2_avb_port_ptp_write(chip,
0141                     MV88E6352_G2_AVB_CMD_PORT_TAIGLOBAL,
0142                     addr, data);
0143 }
0144 
0145 const struct mv88e6xxx_avb_ops mv88e6352_avb_ops = {
0146     .port_ptp_read      = mv88e6352_g2_avb_port_ptp_read,
0147     .port_ptp_write     = mv88e6352_g2_avb_port_ptp_write,
0148     .ptp_read       = mv88e6352_g2_avb_ptp_read,
0149     .ptp_write      = mv88e6352_g2_avb_ptp_write,
0150     .tai_read       = mv88e6352_g2_avb_tai_read,
0151     .tai_write      = mv88e6352_g2_avb_tai_write,
0152 };
0153 
0154 static int mv88e6165_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
0155                      u16 *data, int len)
0156 {
0157     return mv88e6352_g2_avb_port_ptp_read(chip,
0158                     MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL,
0159                     addr, data, len);
0160 }
0161 
0162 static int mv88e6165_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
0163                       u16 data)
0164 {
0165     return mv88e6352_g2_avb_port_ptp_write(chip,
0166                     MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL,
0167                     addr, data);
0168 }
0169 
0170 const struct mv88e6xxx_avb_ops mv88e6165_avb_ops = {
0171     .port_ptp_read      = mv88e6352_g2_avb_port_ptp_read,
0172     .port_ptp_write     = mv88e6352_g2_avb_port_ptp_write,
0173     .ptp_read       = mv88e6352_g2_avb_ptp_read,
0174     .ptp_write      = mv88e6352_g2_avb_ptp_write,
0175     .tai_read       = mv88e6165_g2_avb_tai_read,
0176     .tai_write      = mv88e6165_g2_avb_tai_write,
0177 };
0178 
0179 static int mv88e6390_g2_avb_port_ptp_read(struct mv88e6xxx_chip *chip,
0180                       int port, int addr, u16 *data,
0181                       int len)
0182 {
0183     u16 readop = (len == 1 ? MV88E6390_G2_AVB_CMD_OP_READ :
0184                  MV88E6390_G2_AVB_CMD_OP_READ_INCR) |
0185              (port << 8) | (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) |
0186              addr;
0187 
0188     return mv88e6xxx_g2_avb_read(chip, readop, data, len);
0189 }
0190 
0191 static int mv88e6390_g2_avb_port_ptp_write(struct mv88e6xxx_chip *chip,
0192                        int port, int addr, u16 data)
0193 {
0194     u16 writeop = MV88E6390_G2_AVB_CMD_OP_WRITE | (port << 8) |
0195               (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) | addr;
0196 
0197     return mv88e6xxx_g2_avb_write(chip, writeop, data);
0198 }
0199 
0200 static int mv88e6390_g2_avb_ptp_read(struct mv88e6xxx_chip *chip, int addr,
0201                      u16 *data, int len)
0202 {
0203     return mv88e6390_g2_avb_port_ptp_read(chip,
0204                     MV88E6390_G2_AVB_CMD_PORT_PTPGLOBAL,
0205                     addr, data, len);
0206 }
0207 
0208 static int mv88e6390_g2_avb_ptp_write(struct mv88e6xxx_chip *chip, int addr,
0209                       u16 data)
0210 {
0211     return mv88e6390_g2_avb_port_ptp_write(chip,
0212                     MV88E6390_G2_AVB_CMD_PORT_PTPGLOBAL,
0213                     addr, data);
0214 }
0215 
0216 static int mv88e6390_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
0217                      u16 *data, int len)
0218 {
0219     return mv88e6390_g2_avb_port_ptp_read(chip,
0220                     MV88E6390_G2_AVB_CMD_PORT_TAIGLOBAL,
0221                     addr, data, len);
0222 }
0223 
0224 static int mv88e6390_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
0225                       u16 data)
0226 {
0227     return mv88e6390_g2_avb_port_ptp_write(chip,
0228                     MV88E6390_G2_AVB_CMD_PORT_TAIGLOBAL,
0229                     addr, data);
0230 }
0231 
0232 const struct mv88e6xxx_avb_ops mv88e6390_avb_ops = {
0233     .port_ptp_read      = mv88e6390_g2_avb_port_ptp_read,
0234     .port_ptp_write     = mv88e6390_g2_avb_port_ptp_write,
0235     .ptp_read       = mv88e6390_g2_avb_ptp_read,
0236     .ptp_write      = mv88e6390_g2_avb_ptp_write,
0237     .tai_read       = mv88e6390_g2_avb_tai_read,
0238     .tai_write      = mv88e6390_g2_avb_tai_write,
0239 };