GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / net / dsa / mv88e6xxx / global2_avb.c
1 /*
2  * Marvell 88E6xxx Switch Global 2 Registers support
3  *
4  * Copyright (c) 2008 Marvell Semiconductor
5  *
6  * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
7  *      Vivien Didelot <vivien.didelot@savoirfairelinux.com>
8  *
9  * Copyright (c) 2017 National Instruments
10  *      Brandon Streiff <brandon.streiff@ni.com>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  */
17
18 #include "global2.h"
19
20 /* Offset 0x16: AVB Command Register
21  * Offset 0x17: AVB Data Register
22  *
23  * There are two different versions of this register interface:
24  *    "6352": 3-bit "op" field, 4-bit "port" field.
25  *    "6390": 2-bit "op" field, 5-bit "port" field.
26  *
27  * The "op" codes are different between the two, as well as the special
28  * port fields for global PTP and TAI configuration.
29  */
30
31 /* mv88e6xxx_g2_avb_read -- Read one or multiple 16-bit words.
32  * The hardware supports snapshotting up to four contiguous registers.
33  */
34 static int mv88e6xxx_g2_avb_read(struct mv88e6xxx_chip *chip, u16 readop,
35                                  u16 *data, int len)
36 {
37         int err;
38         int i;
39
40         /* Hardware can only snapshot four words. */
41         if (len > 4)
42                 return -E2BIG;
43
44         err = mv88e6xxx_g2_update(chip, MV88E6352_G2_AVB_CMD, readop);
45         if (err)
46                 return err;
47
48         for (i = 0; i < len; ++i) {
49                 err = mv88e6xxx_g2_read(chip, MV88E6352_G2_AVB_DATA,
50                                         &data[i]);
51                 if (err)
52                         return err;
53         }
54
55         return 0;
56 }
57
58 /* mv88e6xxx_g2_avb_write -- Write one 16-bit word. */
59 static int mv88e6xxx_g2_avb_write(struct mv88e6xxx_chip *chip, u16 writeop,
60                                   u16 data)
61 {
62         int err;
63
64         err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_DATA, data);
65         if (err)
66                 return err;
67
68         return mv88e6xxx_g2_update(chip, MV88E6352_G2_AVB_CMD, writeop);
69 }
70
71 static int mv88e6352_g2_avb_port_ptp_read(struct mv88e6xxx_chip *chip,
72                                           int port, int addr, u16 *data,
73                                           int len)
74 {
75         u16 readop = (len == 1 ? MV88E6352_G2_AVB_CMD_OP_READ :
76                                  MV88E6352_G2_AVB_CMD_OP_READ_INCR) |
77                      (port << 8) | (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) |
78                      addr;
79
80         return mv88e6xxx_g2_avb_read(chip, readop, data, len);
81 }
82
83 static int mv88e6352_g2_avb_port_ptp_write(struct mv88e6xxx_chip *chip,
84                                            int port, int addr, u16 data)
85 {
86         u16 writeop = MV88E6352_G2_AVB_CMD_OP_WRITE | (port << 8) |
87                       (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) | addr;
88
89         return mv88e6xxx_g2_avb_write(chip, writeop, data);
90 }
91
92 static int mv88e6352_g2_avb_ptp_read(struct mv88e6xxx_chip *chip, int addr,
93                                      u16 *data, int len)
94 {
95         return mv88e6352_g2_avb_port_ptp_read(chip,
96                                         MV88E6352_G2_AVB_CMD_PORT_PTPGLOBAL,
97                                         addr, data, len);
98 }
99
100 static int mv88e6352_g2_avb_ptp_write(struct mv88e6xxx_chip *chip, int addr,
101                                       u16 data)
102 {
103         return mv88e6352_g2_avb_port_ptp_write(chip,
104                                         MV88E6352_G2_AVB_CMD_PORT_PTPGLOBAL,
105                                         addr, data);
106 }
107
108 static int mv88e6352_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
109                                      u16 *data, int len)
110 {
111         return mv88e6352_g2_avb_port_ptp_read(chip,
112                                         MV88E6352_G2_AVB_CMD_PORT_TAIGLOBAL,
113                                         addr, data, len);
114 }
115
116 static int mv88e6352_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
117                                       u16 data)
118 {
119         return mv88e6352_g2_avb_port_ptp_write(chip,
120                                         MV88E6352_G2_AVB_CMD_PORT_TAIGLOBAL,
121                                         addr, data);
122 }
123
124 const struct mv88e6xxx_avb_ops mv88e6352_avb_ops = {
125         .port_ptp_read          = mv88e6352_g2_avb_port_ptp_read,
126         .port_ptp_write         = mv88e6352_g2_avb_port_ptp_write,
127         .ptp_read               = mv88e6352_g2_avb_ptp_read,
128         .ptp_write              = mv88e6352_g2_avb_ptp_write,
129         .tai_read               = mv88e6352_g2_avb_tai_read,
130         .tai_write              = mv88e6352_g2_avb_tai_write,
131 };
132
133 static int mv88e6165_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
134                                      u16 *data, int len)
135 {
136         return mv88e6352_g2_avb_port_ptp_read(chip,
137                                         MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL,
138                                         addr, data, len);
139 }
140
141 static int mv88e6165_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
142                                       u16 data)
143 {
144         return mv88e6352_g2_avb_port_ptp_write(chip,
145                                         MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL,
146                                         addr, data);
147 }
148
149 const struct mv88e6xxx_avb_ops mv88e6165_avb_ops = {
150         .port_ptp_read          = mv88e6352_g2_avb_port_ptp_read,
151         .port_ptp_write         = mv88e6352_g2_avb_port_ptp_write,
152         .ptp_read               = mv88e6352_g2_avb_ptp_read,
153         .ptp_write              = mv88e6352_g2_avb_ptp_write,
154         .tai_read               = mv88e6165_g2_avb_tai_read,
155         .tai_write              = mv88e6165_g2_avb_tai_write,
156 };
157
158 static int mv88e6390_g2_avb_port_ptp_read(struct mv88e6xxx_chip *chip,
159                                           int port, int addr, u16 *data,
160                                           int len)
161 {
162         u16 readop = (len == 1 ? MV88E6390_G2_AVB_CMD_OP_READ :
163                                  MV88E6390_G2_AVB_CMD_OP_READ_INCR) |
164                      (port << 8) | (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) |
165                      addr;
166
167         return mv88e6xxx_g2_avb_read(chip, readop, data, len);
168 }
169
170 static int mv88e6390_g2_avb_port_ptp_write(struct mv88e6xxx_chip *chip,
171                                            int port, int addr, u16 data)
172 {
173         u16 writeop = MV88E6390_G2_AVB_CMD_OP_WRITE | (port << 8) |
174                       (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) | addr;
175
176         return mv88e6xxx_g2_avb_write(chip, writeop, data);
177 }
178
179 static int mv88e6390_g2_avb_ptp_read(struct mv88e6xxx_chip *chip, int addr,
180                                      u16 *data, int len)
181 {
182         return mv88e6390_g2_avb_port_ptp_read(chip,
183                                         MV88E6390_G2_AVB_CMD_PORT_PTPGLOBAL,
184                                         addr, data, len);
185 }
186
187 static int mv88e6390_g2_avb_ptp_write(struct mv88e6xxx_chip *chip, int addr,
188                                       u16 data)
189 {
190         return mv88e6390_g2_avb_port_ptp_write(chip,
191                                         MV88E6390_G2_AVB_CMD_PORT_PTPGLOBAL,
192                                         addr, data);
193 }
194
195 static int mv88e6390_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
196                                      u16 *data, int len)
197 {
198         return mv88e6390_g2_avb_port_ptp_read(chip,
199                                         MV88E6390_G2_AVB_CMD_PORT_TAIGLOBAL,
200                                         addr, data, len);
201 }
202
203 static int mv88e6390_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
204                                       u16 data)
205 {
206         return mv88e6390_g2_avb_port_ptp_write(chip,
207                                         MV88E6390_G2_AVB_CMD_PORT_TAIGLOBAL,
208                                         addr, data);
209 }
210
211 const struct mv88e6xxx_avb_ops mv88e6390_avb_ops = {
212         .port_ptp_read          = mv88e6390_g2_avb_port_ptp_read,
213         .port_ptp_write         = mv88e6390_g2_avb_port_ptp_write,
214         .ptp_read               = mv88e6390_g2_avb_ptp_read,
215         .ptp_write              = mv88e6390_g2_avb_ptp_write,
216         .tai_read               = mv88e6390_g2_avb_tai_read,
217         .tai_write              = mv88e6390_g2_avb_tai_write,
218 };