blob: 688547026e15fc3b34ec68c03cae9920e7a31f49 [file] [log] [blame]
Vivien Didelota935c052016-09-29 12:21:53 -04001/*
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
17int 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
24int 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
31int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
32{
33 return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
34}
Andrew Lunna605a0f2016-11-21 23:26:58 +010035
Andrew Lunn33641992016-12-03 04:35:17 +010036/* Offset 0x1a: Monitor Control */
37/* Offset 0x1a: Monitor & MGMT Control on some devices */
38
39int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
40{
41 u16 reg;
42 int err;
43
44 err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, &reg);
45 if (err)
46 return err;
47
48 reg &= ~(GLOBAL_MONITOR_CONTROL_INGRESS_MASK |
49 GLOBAL_MONITOR_CONTROL_EGRESS_MASK);
50
51 reg |= port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
52 port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT;
53
54 return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
55}
56
57/* Older generations also call this the ARP destination. It has been
58 * generalized in more modern devices such that more than ARP can
59 * egress it
60 */
61int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
62{
63 u16 reg;
64 int err;
65
66 err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, &reg);
67 if (err)
68 return err;
69
70 reg &= ~GLOBAL_MONITOR_CONTROL_ARP_MASK;
71 reg |= port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
72
73 return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
74}
75
76static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip,
77 u16 pointer, u8 data)
78{
79 u16 reg;
80
81 reg = GLOBAL_MONITOR_CONTROL_UPDATE | pointer | data;
82
83 return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
84}
85
86int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
87{
88 int err;
89
90 err = mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_INGRESS,
91 port);
92 if (err)
93 return err;
94
95 return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_EGRESS,
96 port);
97}
98
99int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
100{
101 return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_CPU_DEST,
102 port);
103}
104
Andrew Lunnde2273872016-11-21 23:27:01 +0100105/* Offset 0x1c: Global Control 2 */
106
107int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
108{
109 u16 val;
110 int err;
111
112 err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL_2, &val);
113 if (err)
114 return err;
115
116 val |= GLOBAL_CONTROL_2_HIST_RX_TX;
117
118 err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2, val);
119
120 return err;
121}
122
123/* Offset 0x1d: Statistics Operation 2 */
124
Andrew Lunn7f9ef3a2016-11-21 23:27:05 +0100125int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
Andrew Lunna605a0f2016-11-21 23:26:58 +0100126{
127 return mv88e6xxx_g1_wait(chip, GLOBAL_STATS_OP, GLOBAL_STATS_OP_BUSY);
128}
129
130int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
131{
132 int err;
133
134 /* Snapshot the hardware statistics counters for this port. */
135 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
136 GLOBAL_STATS_OP_CAPTURE_PORT |
137 GLOBAL_STATS_OP_HIST_RX_TX | port);
138 if (err)
139 return err;
140
141 /* Wait for the snapshotting to complete. */
142 return mv88e6xxx_g1_stats_wait(chip);
143}
144
145int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
146{
147 port = (port + 1) << 5;
148
149 return mv88e6xxx_g1_stats_snapshot(chip, port);
150}
Andrew Lunn79523472016-11-21 23:27:00 +0100151
152int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
153{
154 int err;
155
156 port = (port + 1) << 5;
157
158 /* Snapshot the hardware statistics counters for this port. */
159 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
160 GLOBAL_STATS_OP_CAPTURE_PORT | port);
161 if (err)
162 return err;
163
164 /* Wait for the snapshotting to complete. */
165 return mv88e6xxx_g1_stats_wait(chip);
166}
Andrew Lunn7f9ef3a2016-11-21 23:27:05 +0100167
168void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val)
169{
170 u32 value;
171 u16 reg;
172 int err;
173
174 *val = 0;
175
176 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
177 GLOBAL_STATS_OP_READ_CAPTURED | stat);
178 if (err)
179 return;
180
181 err = mv88e6xxx_g1_stats_wait(chip);
182 if (err)
183 return;
184
185 err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, &reg);
186 if (err)
187 return;
188
189 value = reg << 16;
190
191 err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, &reg);
192 if (err)
193 return;
194
195 *val = value | reg;
196}