1a935c052SVivien Didelot /*
2a935c052SVivien Didelot  * Marvell 88E6xxx Switch Global (1) Registers support
3a935c052SVivien Didelot  *
4a935c052SVivien Didelot  * Copyright (c) 2008 Marvell Semiconductor
5a935c052SVivien Didelot  *
64333d619SVivien Didelot  * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
74333d619SVivien Didelot  *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
8a935c052SVivien Didelot  *
9a935c052SVivien Didelot  * This program is free software; you can redistribute it and/or modify
10a935c052SVivien Didelot  * it under the terms of the GNU General Public License as published by
11a935c052SVivien Didelot  * the Free Software Foundation; either version 2 of the License, or
12a935c052SVivien Didelot  * (at your option) any later version.
13a935c052SVivien Didelot  */
14a935c052SVivien Didelot 
154d5f2ba7SVivien Didelot #include "chip.h"
16a935c052SVivien Didelot #include "global1.h"
17a935c052SVivien Didelot 
18a935c052SVivien Didelot int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
19a935c052SVivien Didelot {
20a935c052SVivien Didelot 	int addr = chip->info->global1_addr;
21a935c052SVivien Didelot 
22a935c052SVivien Didelot 	return mv88e6xxx_read(chip, addr, reg, val);
23a935c052SVivien Didelot }
24a935c052SVivien Didelot 
25a935c052SVivien Didelot int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
26a935c052SVivien Didelot {
27a935c052SVivien Didelot 	int addr = chip->info->global1_addr;
28a935c052SVivien Didelot 
29a935c052SVivien Didelot 	return mv88e6xxx_write(chip, addr, reg, val);
30a935c052SVivien Didelot }
31a935c052SVivien Didelot 
32a935c052SVivien Didelot int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
33a935c052SVivien Didelot {
34a935c052SVivien Didelot 	return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
35a935c052SVivien Didelot }
36a605a0feSAndrew Lunn 
3717e708baSVivien Didelot /* Offset 0x00: Switch Global Status Register */
3817e708baSVivien Didelot 
39a199d8b6SVivien Didelot static int mv88e6185_g1_wait_ppu_disabled(struct mv88e6xxx_chip *chip)
40a199d8b6SVivien Didelot {
41a199d8b6SVivien Didelot 	u16 state;
42a199d8b6SVivien Didelot 	int i, err;
43a199d8b6SVivien Didelot 
44a199d8b6SVivien Didelot 	for (i = 0; i < 16; i++) {
45a199d8b6SVivien Didelot 		err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
46a199d8b6SVivien Didelot 		if (err)
47a199d8b6SVivien Didelot 			return err;
48a199d8b6SVivien Didelot 
49a199d8b6SVivien Didelot 		/* Check the value of the PPUState bits 15:14 */
50a199d8b6SVivien Didelot 		state &= GLOBAL_STATUS_PPU_STATE_MASK;
51a199d8b6SVivien Didelot 		if (state != GLOBAL_STATUS_PPU_STATE_POLLING)
52a199d8b6SVivien Didelot 			return 0;
53a199d8b6SVivien Didelot 
54a199d8b6SVivien Didelot 		usleep_range(1000, 2000);
55a199d8b6SVivien Didelot 	}
56a199d8b6SVivien Didelot 
57a199d8b6SVivien Didelot 	return -ETIMEDOUT;
58a199d8b6SVivien Didelot }
59a199d8b6SVivien Didelot 
6017e708baSVivien Didelot static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
6117e708baSVivien Didelot {
6217e708baSVivien Didelot 	u16 state;
6317e708baSVivien Didelot 	int i, err;
6417e708baSVivien Didelot 
6517e708baSVivien Didelot 	for (i = 0; i < 16; ++i) {
6617e708baSVivien Didelot 		err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
6717e708baSVivien Didelot 		if (err)
6817e708baSVivien Didelot 			return err;
6917e708baSVivien Didelot 
7017e708baSVivien Didelot 		/* Check the value of the PPUState bits 15:14 */
7117e708baSVivien Didelot 		state &= GLOBAL_STATUS_PPU_STATE_MASK;
7217e708baSVivien Didelot 		if (state == GLOBAL_STATUS_PPU_STATE_POLLING)
7317e708baSVivien Didelot 			return 0;
7417e708baSVivien Didelot 
7517e708baSVivien Didelot 		usleep_range(1000, 2000);
7617e708baSVivien Didelot 	}
7717e708baSVivien Didelot 
7817e708baSVivien Didelot 	return -ETIMEDOUT;
7917e708baSVivien Didelot }
8017e708baSVivien Didelot 
8117e708baSVivien Didelot static int mv88e6352_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
8217e708baSVivien Didelot {
8317e708baSVivien Didelot 	u16 state;
8417e708baSVivien Didelot 	int i, err;
8517e708baSVivien Didelot 
8617e708baSVivien Didelot 	for (i = 0; i < 16; ++i) {
8717e708baSVivien Didelot 		err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
8817e708baSVivien Didelot 		if (err)
8917e708baSVivien Didelot 			return err;
9017e708baSVivien Didelot 
9117e708baSVivien Didelot 		/* Check the value of the PPUState (or InitState) bit 15 */
9217e708baSVivien Didelot 		if (state & GLOBAL_STATUS_PPU_STATE)
9317e708baSVivien Didelot 			return 0;
9417e708baSVivien Didelot 
9517e708baSVivien Didelot 		usleep_range(1000, 2000);
9617e708baSVivien Didelot 	}
9717e708baSVivien Didelot 
9817e708baSVivien Didelot 	return -ETIMEDOUT;
9917e708baSVivien Didelot }
10017e708baSVivien Didelot 
10117e708baSVivien Didelot static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip)
10217e708baSVivien Didelot {
10317e708baSVivien Didelot 	const unsigned long timeout = jiffies + 1 * HZ;
10417e708baSVivien Didelot 	u16 val;
10517e708baSVivien Didelot 	int err;
10617e708baSVivien Didelot 
10717e708baSVivien Didelot 	/* Wait up to 1 second for the switch to be ready. The InitReady bit 11
10817e708baSVivien Didelot 	 * is set to a one when all units inside the device (ATU, VTU, etc.)
10917e708baSVivien Didelot 	 * have finished their initialization and are ready to accept frames.
11017e708baSVivien Didelot 	 */
11117e708baSVivien Didelot 	while (time_before(jiffies, timeout)) {
11217e708baSVivien Didelot 		err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &val);
11317e708baSVivien Didelot 		if (err)
11417e708baSVivien Didelot 			return err;
11517e708baSVivien Didelot 
11617e708baSVivien Didelot 		if (val & GLOBAL_STATUS_INIT_READY)
11717e708baSVivien Didelot 			break;
11817e708baSVivien Didelot 
11917e708baSVivien Didelot 		usleep_range(1000, 2000);
12017e708baSVivien Didelot 	}
12117e708baSVivien Didelot 
12217e708baSVivien Didelot 	if (time_after(jiffies, timeout))
12317e708baSVivien Didelot 		return -ETIMEDOUT;
12417e708baSVivien Didelot 
12517e708baSVivien Didelot 	return 0;
12617e708baSVivien Didelot }
12717e708baSVivien Didelot 
12817e708baSVivien Didelot /* Offset 0x04: Switch Global Control Register */
12917e708baSVivien Didelot 
13017e708baSVivien Didelot int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip)
13117e708baSVivien Didelot {
13217e708baSVivien Didelot 	u16 val;
13317e708baSVivien Didelot 	int err;
13417e708baSVivien Didelot 
13517e708baSVivien Didelot 	/* Set the SWReset bit 15 along with the PPUEn bit 14, to also restart
13617e708baSVivien Didelot 	 * the PPU, including re-doing PHY detection and initialization
13717e708baSVivien Didelot 	 */
13817e708baSVivien Didelot 	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
13917e708baSVivien Didelot 	if (err)
14017e708baSVivien Didelot 		return err;
14117e708baSVivien Didelot 
14217e708baSVivien Didelot 	val |= GLOBAL_CONTROL_SW_RESET;
14317e708baSVivien Didelot 	val |= GLOBAL_CONTROL_PPU_ENABLE;
14417e708baSVivien Didelot 
14517e708baSVivien Didelot 	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
14617e708baSVivien Didelot 	if (err)
14717e708baSVivien Didelot 		return err;
14817e708baSVivien Didelot 
14917e708baSVivien Didelot 	err = mv88e6xxx_g1_wait_init_ready(chip);
15017e708baSVivien Didelot 	if (err)
15117e708baSVivien Didelot 		return err;
15217e708baSVivien Didelot 
15317e708baSVivien Didelot 	return mv88e6185_g1_wait_ppu_polling(chip);
15417e708baSVivien Didelot }
15517e708baSVivien Didelot 
15617e708baSVivien Didelot int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip)
15717e708baSVivien Didelot {
15817e708baSVivien Didelot 	u16 val;
15917e708baSVivien Didelot 	int err;
16017e708baSVivien Didelot 
16117e708baSVivien Didelot 	/* Set the SWReset bit 15 */
16217e708baSVivien Didelot 	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
16317e708baSVivien Didelot 	if (err)
16417e708baSVivien Didelot 		return err;
16517e708baSVivien Didelot 
16617e708baSVivien Didelot 	val |= GLOBAL_CONTROL_SW_RESET;
16717e708baSVivien Didelot 
16817e708baSVivien Didelot 	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
16917e708baSVivien Didelot 	if (err)
17017e708baSVivien Didelot 		return err;
17117e708baSVivien Didelot 
17217e708baSVivien Didelot 	err = mv88e6xxx_g1_wait_init_ready(chip);
17317e708baSVivien Didelot 	if (err)
17417e708baSVivien Didelot 		return err;
17517e708baSVivien Didelot 
17617e708baSVivien Didelot 	return mv88e6352_g1_wait_ppu_polling(chip);
17717e708baSVivien Didelot }
17817e708baSVivien Didelot 
179a199d8b6SVivien Didelot int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip)
180a199d8b6SVivien Didelot {
181a199d8b6SVivien Didelot 	u16 val;
182a199d8b6SVivien Didelot 	int err;
183a199d8b6SVivien Didelot 
184a199d8b6SVivien Didelot 	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
185a199d8b6SVivien Didelot 	if (err)
186a199d8b6SVivien Didelot 		return err;
187a199d8b6SVivien Didelot 
188a199d8b6SVivien Didelot 	val |= GLOBAL_CONTROL_PPU_ENABLE;
189a199d8b6SVivien Didelot 
190a199d8b6SVivien Didelot 	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
191a199d8b6SVivien Didelot 	if (err)
192a199d8b6SVivien Didelot 		return err;
193a199d8b6SVivien Didelot 
194a199d8b6SVivien Didelot 	return mv88e6185_g1_wait_ppu_polling(chip);
195a199d8b6SVivien Didelot }
196a199d8b6SVivien Didelot 
197a199d8b6SVivien Didelot int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip)
198a199d8b6SVivien Didelot {
199a199d8b6SVivien Didelot 	u16 val;
200a199d8b6SVivien Didelot 	int err;
201a199d8b6SVivien Didelot 
202a199d8b6SVivien Didelot 	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
203a199d8b6SVivien Didelot 	if (err)
204a199d8b6SVivien Didelot 		return err;
205a199d8b6SVivien Didelot 
206a199d8b6SVivien Didelot 	val &= ~GLOBAL_CONTROL_PPU_ENABLE;
207a199d8b6SVivien Didelot 
208a199d8b6SVivien Didelot 	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
209a199d8b6SVivien Didelot 	if (err)
210a199d8b6SVivien Didelot 		return err;
211a199d8b6SVivien Didelot 
212a199d8b6SVivien Didelot 	return mv88e6185_g1_wait_ppu_disabled(chip);
213a199d8b6SVivien Didelot }
214a199d8b6SVivien Didelot 
21533641994SAndrew Lunn /* Offset 0x1a: Monitor Control */
21633641994SAndrew Lunn /* Offset 0x1a: Monitor & MGMT Control on some devices */
21733641994SAndrew Lunn 
21833641994SAndrew Lunn int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
21933641994SAndrew Lunn {
22033641994SAndrew Lunn 	u16 reg;
22133641994SAndrew Lunn 	int err;
22233641994SAndrew Lunn 
22333641994SAndrew Lunn 	err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, &reg);
22433641994SAndrew Lunn 	if (err)
22533641994SAndrew Lunn 		return err;
22633641994SAndrew Lunn 
22733641994SAndrew Lunn 	reg &= ~(GLOBAL_MONITOR_CONTROL_INGRESS_MASK |
22833641994SAndrew Lunn 		 GLOBAL_MONITOR_CONTROL_EGRESS_MASK);
22933641994SAndrew Lunn 
23033641994SAndrew Lunn 	reg |= port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
23133641994SAndrew Lunn 		port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT;
23233641994SAndrew Lunn 
23333641994SAndrew Lunn 	return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
23433641994SAndrew Lunn }
23533641994SAndrew Lunn 
23633641994SAndrew Lunn /* Older generations also call this the ARP destination. It has been
23733641994SAndrew Lunn  * generalized in more modern devices such that more than ARP can
23833641994SAndrew Lunn  * egress it
23933641994SAndrew Lunn  */
24033641994SAndrew Lunn int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
24133641994SAndrew Lunn {
24233641994SAndrew Lunn 	u16 reg;
24333641994SAndrew Lunn 	int err;
24433641994SAndrew Lunn 
24533641994SAndrew Lunn 	err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, &reg);
24633641994SAndrew Lunn 	if (err)
24733641994SAndrew Lunn 		return err;
24833641994SAndrew Lunn 
24933641994SAndrew Lunn 	reg &= ~GLOBAL_MONITOR_CONTROL_ARP_MASK;
25033641994SAndrew Lunn 	reg |= port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
25133641994SAndrew Lunn 
25233641994SAndrew Lunn 	return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
25333641994SAndrew Lunn }
25433641994SAndrew Lunn 
25533641994SAndrew Lunn static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip,
25633641994SAndrew Lunn 				      u16 pointer, u8 data)
25733641994SAndrew Lunn {
25833641994SAndrew Lunn 	u16 reg;
25933641994SAndrew Lunn 
26033641994SAndrew Lunn 	reg = GLOBAL_MONITOR_CONTROL_UPDATE | pointer | data;
26133641994SAndrew Lunn 
26233641994SAndrew Lunn 	return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
26333641994SAndrew Lunn }
26433641994SAndrew Lunn 
26533641994SAndrew Lunn int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
26633641994SAndrew Lunn {
26733641994SAndrew Lunn 	int err;
26833641994SAndrew Lunn 
26933641994SAndrew Lunn 	err = mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_INGRESS,
27033641994SAndrew Lunn 					 port);
27133641994SAndrew Lunn 	if (err)
27233641994SAndrew Lunn 		return err;
27333641994SAndrew Lunn 
27433641994SAndrew Lunn 	return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_EGRESS,
27533641994SAndrew Lunn 					  port);
27633641994SAndrew Lunn }
27733641994SAndrew Lunn 
27833641994SAndrew Lunn int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
27933641994SAndrew Lunn {
28033641994SAndrew Lunn 	return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_CPU_DEST,
28133641994SAndrew Lunn 					  port);
28233641994SAndrew Lunn }
28333641994SAndrew Lunn 
2846e55f698SAndrew Lunn int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
2856e55f698SAndrew Lunn {
2866e55f698SAndrew Lunn 	int err;
2876e55f698SAndrew Lunn 
2886e55f698SAndrew Lunn 	/* 01:c2:80:00:00:00:00-01:c2:80:00:00:00:07 are Management */
2896e55f698SAndrew Lunn 	err = mv88e6390_g1_monitor_write(
2906e55f698SAndrew Lunn 		chip, GLOBAL_MONITOR_CONTROL_0180C280000000XLO, 0xff);
2916e55f698SAndrew Lunn 	if (err)
2926e55f698SAndrew Lunn 		return err;
2936e55f698SAndrew Lunn 
2946e55f698SAndrew Lunn 	/* 01:c2:80:00:00:00:08-01:c2:80:00:00:00:0f are Management */
2956e55f698SAndrew Lunn 	err = mv88e6390_g1_monitor_write(
2966e55f698SAndrew Lunn 		chip, GLOBAL_MONITOR_CONTROL_0180C280000000XHI, 0xff);
2976e55f698SAndrew Lunn 	if (err)
2986e55f698SAndrew Lunn 		return err;
2996e55f698SAndrew Lunn 
3006e55f698SAndrew Lunn 	/* 01:c2:80:00:00:00:20-01:c2:80:00:00:00:27 are Management */
3016e55f698SAndrew Lunn 	err = mv88e6390_g1_monitor_write(
3026e55f698SAndrew Lunn 		chip, GLOBAL_MONITOR_CONTROL_0180C280000002XLO, 0xff);
3036e55f698SAndrew Lunn 	if (err)
3046e55f698SAndrew Lunn 		return err;
3056e55f698SAndrew Lunn 
3066e55f698SAndrew Lunn 	/* 01:c2:80:00:00:00:28-01:c2:80:00:00:00:2f are Management */
3076e55f698SAndrew Lunn 	return mv88e6390_g1_monitor_write(
3086e55f698SAndrew Lunn 		chip, GLOBAL_MONITOR_CONTROL_0180C280000002XHI, 0xff);
3096e55f698SAndrew Lunn }
3106e55f698SAndrew Lunn 
311de227387SAndrew Lunn /* Offset 0x1c: Global Control 2 */
312de227387SAndrew Lunn 
313de227387SAndrew Lunn int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
314de227387SAndrew Lunn {
315de227387SAndrew Lunn 	u16 val;
316de227387SAndrew Lunn 	int err;
317de227387SAndrew Lunn 
318de227387SAndrew Lunn 	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL_2, &val);
319de227387SAndrew Lunn 	if (err)
320de227387SAndrew Lunn 		return err;
321de227387SAndrew Lunn 
322de227387SAndrew Lunn 	val |= GLOBAL_CONTROL_2_HIST_RX_TX;
323de227387SAndrew Lunn 
324de227387SAndrew Lunn 	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2, val);
325de227387SAndrew Lunn 
326de227387SAndrew Lunn 	return err;
327de227387SAndrew Lunn }
328de227387SAndrew Lunn 
329de227387SAndrew Lunn /* Offset 0x1d: Statistics Operation 2 */
330de227387SAndrew Lunn 
3317f9ef3afSAndrew Lunn int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
332a605a0feSAndrew Lunn {
333a605a0feSAndrew Lunn 	return mv88e6xxx_g1_wait(chip, GLOBAL_STATS_OP, GLOBAL_STATS_OP_BUSY);
334a605a0feSAndrew Lunn }
335a605a0feSAndrew Lunn 
336a605a0feSAndrew Lunn int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
337a605a0feSAndrew Lunn {
338a605a0feSAndrew Lunn 	int err;
339a605a0feSAndrew Lunn 
340a605a0feSAndrew Lunn 	/* Snapshot the hardware statistics counters for this port. */
341a605a0feSAndrew Lunn 	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
342a605a0feSAndrew Lunn 				 GLOBAL_STATS_OP_CAPTURE_PORT |
343a605a0feSAndrew Lunn 				 GLOBAL_STATS_OP_HIST_RX_TX | port);
344a605a0feSAndrew Lunn 	if (err)
345a605a0feSAndrew Lunn 		return err;
346a605a0feSAndrew Lunn 
347a605a0feSAndrew Lunn 	/* Wait for the snapshotting to complete. */
348a605a0feSAndrew Lunn 	return mv88e6xxx_g1_stats_wait(chip);
349a605a0feSAndrew Lunn }
350a605a0feSAndrew Lunn 
351a605a0feSAndrew Lunn int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
352a605a0feSAndrew Lunn {
353a605a0feSAndrew Lunn 	port = (port + 1) << 5;
354a605a0feSAndrew Lunn 
355a605a0feSAndrew Lunn 	return mv88e6xxx_g1_stats_snapshot(chip, port);
356a605a0feSAndrew Lunn }
35779523473SAndrew Lunn 
35879523473SAndrew Lunn int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
35979523473SAndrew Lunn {
36079523473SAndrew Lunn 	int err;
36179523473SAndrew Lunn 
36279523473SAndrew Lunn 	port = (port + 1) << 5;
36379523473SAndrew Lunn 
36479523473SAndrew Lunn 	/* Snapshot the hardware statistics counters for this port. */
36579523473SAndrew Lunn 	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
36679523473SAndrew Lunn 				 GLOBAL_STATS_OP_CAPTURE_PORT | port);
36779523473SAndrew Lunn 	if (err)
36879523473SAndrew Lunn 		return err;
36979523473SAndrew Lunn 
37079523473SAndrew Lunn 	/* Wait for the snapshotting to complete. */
37179523473SAndrew Lunn 	return mv88e6xxx_g1_stats_wait(chip);
37279523473SAndrew Lunn }
3737f9ef3afSAndrew Lunn 
3747f9ef3afSAndrew Lunn void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val)
3757f9ef3afSAndrew Lunn {
3767f9ef3afSAndrew Lunn 	u32 value;
3777f9ef3afSAndrew Lunn 	u16 reg;
3787f9ef3afSAndrew Lunn 	int err;
3797f9ef3afSAndrew Lunn 
3807f9ef3afSAndrew Lunn 	*val = 0;
3817f9ef3afSAndrew Lunn 
3827f9ef3afSAndrew Lunn 	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
3837f9ef3afSAndrew Lunn 				 GLOBAL_STATS_OP_READ_CAPTURED | stat);
3847f9ef3afSAndrew Lunn 	if (err)
3857f9ef3afSAndrew Lunn 		return;
3867f9ef3afSAndrew Lunn 
3877f9ef3afSAndrew Lunn 	err = mv88e6xxx_g1_stats_wait(chip);
3887f9ef3afSAndrew Lunn 	if (err)
3897f9ef3afSAndrew Lunn 		return;
3907f9ef3afSAndrew Lunn 
3917f9ef3afSAndrew Lunn 	err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, &reg);
3927f9ef3afSAndrew Lunn 	if (err)
3937f9ef3afSAndrew Lunn 		return;
3947f9ef3afSAndrew Lunn 
3957f9ef3afSAndrew Lunn 	value = reg << 16;
3967f9ef3afSAndrew Lunn 
3977f9ef3afSAndrew Lunn 	err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, &reg);
3987f9ef3afSAndrew Lunn 	if (err)
3997f9ef3afSAndrew Lunn 		return;
4007f9ef3afSAndrew Lunn 
4017f9ef3afSAndrew Lunn 	*val = value | reg;
4027f9ef3afSAndrew Lunn }
403