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