1 /*
2  * Marvell 88E6xxx Switch Global (1) Registers support
3  *
4  * Copyright (c) 2008 Marvell Semiconductor
5  *
6  * Copyright (c) 2016 Vivien Didelot <vivien.didelot@savoirfairelinux.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  */
13 
14 #include "mv88e6xxx.h"
15 #include "global1.h"
16 
17 int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
18 {
19 	int addr = chip->info->global1_addr;
20 
21 	return mv88e6xxx_read(chip, addr, reg, val);
22 }
23 
24 int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
25 {
26 	int addr = chip->info->global1_addr;
27 
28 	return mv88e6xxx_write(chip, addr, reg, val);
29 }
30 
31 int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
32 {
33 	return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
34 }
35 
36 /* Offset 0x00: Switch Global Status Register */
37 
38 static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
39 {
40 	u16 state;
41 	int i, err;
42 
43 	for (i = 0; i < 16; ++i) {
44 		err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
45 		if (err)
46 			return err;
47 
48 		/* Check the value of the PPUState bits 15:14 */
49 		state &= GLOBAL_STATUS_PPU_STATE_MASK;
50 		if (state == GLOBAL_STATUS_PPU_STATE_POLLING)
51 			return 0;
52 
53 		usleep_range(1000, 2000);
54 	}
55 
56 	return -ETIMEDOUT;
57 }
58 
59 static int mv88e6352_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
60 {
61 	u16 state;
62 	int i, err;
63 
64 	for (i = 0; i < 16; ++i) {
65 		err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
66 		if (err)
67 			return err;
68 
69 		/* Check the value of the PPUState (or InitState) bit 15 */
70 		if (state & GLOBAL_STATUS_PPU_STATE)
71 			return 0;
72 
73 		usleep_range(1000, 2000);
74 	}
75 
76 	return -ETIMEDOUT;
77 }
78 
79 static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip)
80 {
81 	const unsigned long timeout = jiffies + 1 * HZ;
82 	u16 val;
83 	int err;
84 
85 	/* Wait up to 1 second for the switch to be ready. The InitReady bit 11
86 	 * is set to a one when all units inside the device (ATU, VTU, etc.)
87 	 * have finished their initialization and are ready to accept frames.
88 	 */
89 	while (time_before(jiffies, timeout)) {
90 		err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &val);
91 		if (err)
92 			return err;
93 
94 		if (val & GLOBAL_STATUS_INIT_READY)
95 			break;
96 
97 		usleep_range(1000, 2000);
98 	}
99 
100 	if (time_after(jiffies, timeout))
101 		return -ETIMEDOUT;
102 
103 	return 0;
104 }
105 
106 /* Offset 0x04: Switch Global Control Register */
107 
108 int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip)
109 {
110 	u16 val;
111 	int err;
112 
113 	/* Set the SWReset bit 15 along with the PPUEn bit 14, to also restart
114 	 * the PPU, including re-doing PHY detection and initialization
115 	 */
116 	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
117 	if (err)
118 		return err;
119 
120 	val |= GLOBAL_CONTROL_SW_RESET;
121 	val |= GLOBAL_CONTROL_PPU_ENABLE;
122 
123 	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
124 	if (err)
125 		return err;
126 
127 	err = mv88e6xxx_g1_wait_init_ready(chip);
128 	if (err)
129 		return err;
130 
131 	return mv88e6185_g1_wait_ppu_polling(chip);
132 }
133 
134 int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip)
135 {
136 	u16 val;
137 	int err;
138 
139 	/* Set the SWReset bit 15 */
140 	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
141 	if (err)
142 		return err;
143 
144 	val |= GLOBAL_CONTROL_SW_RESET;
145 
146 	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
147 	if (err)
148 		return err;
149 
150 	err = mv88e6xxx_g1_wait_init_ready(chip);
151 	if (err)
152 		return err;
153 
154 	return mv88e6352_g1_wait_ppu_polling(chip);
155 }
156 
157 /* Offset 0x1a: Monitor Control */
158 /* Offset 0x1a: Monitor & MGMT Control on some devices */
159 
160 int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
161 {
162 	u16 reg;
163 	int err;
164 
165 	err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, &reg);
166 	if (err)
167 		return err;
168 
169 	reg &= ~(GLOBAL_MONITOR_CONTROL_INGRESS_MASK |
170 		 GLOBAL_MONITOR_CONTROL_EGRESS_MASK);
171 
172 	reg |= port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
173 		port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT;
174 
175 	return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
176 }
177 
178 /* Older generations also call this the ARP destination. It has been
179  * generalized in more modern devices such that more than ARP can
180  * egress it
181  */
182 int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
183 {
184 	u16 reg;
185 	int err;
186 
187 	err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, &reg);
188 	if (err)
189 		return err;
190 
191 	reg &= ~GLOBAL_MONITOR_CONTROL_ARP_MASK;
192 	reg |= port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
193 
194 	return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
195 }
196 
197 static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip,
198 				      u16 pointer, u8 data)
199 {
200 	u16 reg;
201 
202 	reg = GLOBAL_MONITOR_CONTROL_UPDATE | pointer | data;
203 
204 	return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
205 }
206 
207 int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
208 {
209 	int err;
210 
211 	err = mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_INGRESS,
212 					 port);
213 	if (err)
214 		return err;
215 
216 	return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_EGRESS,
217 					  port);
218 }
219 
220 int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
221 {
222 	return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_CPU_DEST,
223 					  port);
224 }
225 
226 int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
227 {
228 	int err;
229 
230 	/* 01:c2:80:00:00:00:00-01:c2:80:00:00:00:07 are Management */
231 	err = mv88e6390_g1_monitor_write(
232 		chip, GLOBAL_MONITOR_CONTROL_0180C280000000XLO, 0xff);
233 	if (err)
234 		return err;
235 
236 	/* 01:c2:80:00:00:00:08-01:c2:80:00:00:00:0f are Management */
237 	err = mv88e6390_g1_monitor_write(
238 		chip, GLOBAL_MONITOR_CONTROL_0180C280000000XHI, 0xff);
239 	if (err)
240 		return err;
241 
242 	/* 01:c2:80:00:00:00:20-01:c2:80:00:00:00:27 are Management */
243 	err = mv88e6390_g1_monitor_write(
244 		chip, GLOBAL_MONITOR_CONTROL_0180C280000002XLO, 0xff);
245 	if (err)
246 		return err;
247 
248 	/* 01:c2:80:00:00:00:28-01:c2:80:00:00:00:2f are Management */
249 	return mv88e6390_g1_monitor_write(
250 		chip, GLOBAL_MONITOR_CONTROL_0180C280000002XHI, 0xff);
251 }
252 
253 /* Offset 0x1c: Global Control 2 */
254 
255 int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
256 {
257 	u16 val;
258 	int err;
259 
260 	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL_2, &val);
261 	if (err)
262 		return err;
263 
264 	val |= GLOBAL_CONTROL_2_HIST_RX_TX;
265 
266 	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2, val);
267 
268 	return err;
269 }
270 
271 /* Offset 0x1d: Statistics Operation 2 */
272 
273 int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
274 {
275 	return mv88e6xxx_g1_wait(chip, GLOBAL_STATS_OP, GLOBAL_STATS_OP_BUSY);
276 }
277 
278 int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
279 {
280 	int err;
281 
282 	/* Snapshot the hardware statistics counters for this port. */
283 	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
284 				 GLOBAL_STATS_OP_CAPTURE_PORT |
285 				 GLOBAL_STATS_OP_HIST_RX_TX | port);
286 	if (err)
287 		return err;
288 
289 	/* Wait for the snapshotting to complete. */
290 	return mv88e6xxx_g1_stats_wait(chip);
291 }
292 
293 int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
294 {
295 	port = (port + 1) << 5;
296 
297 	return mv88e6xxx_g1_stats_snapshot(chip, port);
298 }
299 
300 int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
301 {
302 	int err;
303 
304 	port = (port + 1) << 5;
305 
306 	/* Snapshot the hardware statistics counters for this port. */
307 	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
308 				 GLOBAL_STATS_OP_CAPTURE_PORT | port);
309 	if (err)
310 		return err;
311 
312 	/* Wait for the snapshotting to complete. */
313 	return mv88e6xxx_g1_stats_wait(chip);
314 }
315 
316 void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val)
317 {
318 	u32 value;
319 	u16 reg;
320 	int err;
321 
322 	*val = 0;
323 
324 	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
325 				 GLOBAL_STATS_OP_READ_CAPTURED | stat);
326 	if (err)
327 		return;
328 
329 	err = mv88e6xxx_g1_stats_wait(chip);
330 	if (err)
331 		return;
332 
333 	err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, &reg);
334 	if (err)
335 		return;
336 
337 	value = reg << 16;
338 
339 	err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, &reg);
340 	if (err)
341 		return;
342 
343 	*val = value | reg;
344 }
345