1a935c052SVivien Didelot /*
2a935c052SVivien Didelot  * Marvell 88E6xxx Switch Global (1) Registers support
3a935c052SVivien Didelot  *
4a935c052SVivien Didelot  * Copyright (c) 2008 Marvell Semiconductor
5a935c052SVivien Didelot  *
6a935c052SVivien Didelot  * Copyright (c) 2016 Vivien Didelot <vivien.didelot@savoirfairelinux.com>
7a935c052SVivien Didelot  *
8a935c052SVivien Didelot  * This program is free software; you can redistribute it and/or modify
9a935c052SVivien Didelot  * it under the terms of the GNU General Public License as published by
10a935c052SVivien Didelot  * the Free Software Foundation; either version 2 of the License, or
11a935c052SVivien Didelot  * (at your option) any later version.
12a935c052SVivien Didelot  */
13a935c052SVivien Didelot 
14a935c052SVivien Didelot #include "mv88e6xxx.h"
15a935c052SVivien Didelot #include "global1.h"
16a935c052SVivien Didelot 
17a935c052SVivien Didelot int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
18a935c052SVivien Didelot {
19a935c052SVivien Didelot 	int addr = chip->info->global1_addr;
20a935c052SVivien Didelot 
21a935c052SVivien Didelot 	return mv88e6xxx_read(chip, addr, reg, val);
22a935c052SVivien Didelot }
23a935c052SVivien Didelot 
24a935c052SVivien Didelot int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
25a935c052SVivien Didelot {
26a935c052SVivien Didelot 	int addr = chip->info->global1_addr;
27a935c052SVivien Didelot 
28a935c052SVivien Didelot 	return mv88e6xxx_write(chip, addr, reg, val);
29a935c052SVivien Didelot }
30a935c052SVivien Didelot 
31a935c052SVivien Didelot int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
32a935c052SVivien Didelot {
33a935c052SVivien Didelot 	return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
34a935c052SVivien Didelot }
35a605a0feSAndrew Lunn 
36de227387SAndrew Lunn /* Offset 0x1c: Global Control 2 */
37de227387SAndrew Lunn 
38de227387SAndrew Lunn int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
39de227387SAndrew Lunn {
40de227387SAndrew Lunn 	u16 val;
41de227387SAndrew Lunn 	int err;
42de227387SAndrew Lunn 
43de227387SAndrew Lunn 	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL_2, &val);
44de227387SAndrew Lunn 	if (err)
45de227387SAndrew Lunn 		return err;
46de227387SAndrew Lunn 
47de227387SAndrew Lunn 	val |= GLOBAL_CONTROL_2_HIST_RX_TX;
48de227387SAndrew Lunn 
49de227387SAndrew Lunn 	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2, val);
50de227387SAndrew Lunn 
51de227387SAndrew Lunn 	return err;
52de227387SAndrew Lunn }
53de227387SAndrew Lunn 
54de227387SAndrew Lunn /* Offset 0x1d: Statistics Operation 2 */
55de227387SAndrew Lunn 
567f9ef3afSAndrew Lunn int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
57a605a0feSAndrew Lunn {
58a605a0feSAndrew Lunn 	return mv88e6xxx_g1_wait(chip, GLOBAL_STATS_OP, GLOBAL_STATS_OP_BUSY);
59a605a0feSAndrew Lunn }
60a605a0feSAndrew Lunn 
61a605a0feSAndrew Lunn int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
62a605a0feSAndrew Lunn {
63a605a0feSAndrew Lunn 	int err;
64a605a0feSAndrew Lunn 
65a605a0feSAndrew Lunn 	/* Snapshot the hardware statistics counters for this port. */
66a605a0feSAndrew Lunn 	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
67a605a0feSAndrew Lunn 				 GLOBAL_STATS_OP_CAPTURE_PORT |
68a605a0feSAndrew Lunn 				 GLOBAL_STATS_OP_HIST_RX_TX | port);
69a605a0feSAndrew Lunn 	if (err)
70a605a0feSAndrew Lunn 		return err;
71a605a0feSAndrew Lunn 
72a605a0feSAndrew Lunn 	/* Wait for the snapshotting to complete. */
73a605a0feSAndrew Lunn 	return mv88e6xxx_g1_stats_wait(chip);
74a605a0feSAndrew Lunn }
75a605a0feSAndrew Lunn 
76a605a0feSAndrew Lunn int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
77a605a0feSAndrew Lunn {
78a605a0feSAndrew Lunn 	port = (port + 1) << 5;
79a605a0feSAndrew Lunn 
80a605a0feSAndrew Lunn 	return mv88e6xxx_g1_stats_snapshot(chip, port);
81a605a0feSAndrew Lunn }
8279523473SAndrew Lunn 
8379523473SAndrew Lunn int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
8479523473SAndrew Lunn {
8579523473SAndrew Lunn 	int err;
8679523473SAndrew Lunn 
8779523473SAndrew Lunn 	port = (port + 1) << 5;
8879523473SAndrew Lunn 
8979523473SAndrew Lunn 	/* Snapshot the hardware statistics counters for this port. */
9079523473SAndrew Lunn 	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
9179523473SAndrew Lunn 				 GLOBAL_STATS_OP_CAPTURE_PORT | port);
9279523473SAndrew Lunn 	if (err)
9379523473SAndrew Lunn 		return err;
9479523473SAndrew Lunn 
9579523473SAndrew Lunn 	/* Wait for the snapshotting to complete. */
9679523473SAndrew Lunn 	return mv88e6xxx_g1_stats_wait(chip);
9779523473SAndrew Lunn }
987f9ef3afSAndrew Lunn 
997f9ef3afSAndrew Lunn void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val)
1007f9ef3afSAndrew Lunn {
1017f9ef3afSAndrew Lunn 	u32 value;
1027f9ef3afSAndrew Lunn 	u16 reg;
1037f9ef3afSAndrew Lunn 	int err;
1047f9ef3afSAndrew Lunn 
1057f9ef3afSAndrew Lunn 	*val = 0;
1067f9ef3afSAndrew Lunn 
1077f9ef3afSAndrew Lunn 	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
1087f9ef3afSAndrew Lunn 				 GLOBAL_STATS_OP_READ_CAPTURED | stat);
1097f9ef3afSAndrew Lunn 	if (err)
1107f9ef3afSAndrew Lunn 		return;
1117f9ef3afSAndrew Lunn 
1127f9ef3afSAndrew Lunn 	err = mv88e6xxx_g1_stats_wait(chip);
1137f9ef3afSAndrew Lunn 	if (err)
1147f9ef3afSAndrew Lunn 		return;
1157f9ef3afSAndrew Lunn 
1167f9ef3afSAndrew Lunn 	err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, &reg);
1177f9ef3afSAndrew Lunn 	if (err)
1187f9ef3afSAndrew Lunn 		return;
1197f9ef3afSAndrew Lunn 
1207f9ef3afSAndrew Lunn 	value = reg << 16;
1217f9ef3afSAndrew Lunn 
1227f9ef3afSAndrew Lunn 	err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, &reg);
1237f9ef3afSAndrew Lunn 	if (err)
1247f9ef3afSAndrew Lunn 		return;
1257f9ef3afSAndrew Lunn 
1267f9ef3afSAndrew Lunn 	*val = value | reg;
1277f9ef3afSAndrew Lunn }
128