global1.c 4.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/*
 * Marvell 88E6xxx Switch Global (1) Registers support
 *
 * Copyright (c) 2008 Marvell Semiconductor
 *
 * Copyright (c) 2016 Vivien Didelot <vivien.didelot@savoirfairelinux.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include "mv88e6xxx.h"
#include "global1.h"

int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
{
	int addr = chip->info->global1_addr;

	return mv88e6xxx_read(chip, addr, reg, val);
}

int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
{
	int addr = chip->info->global1_addr;

	return mv88e6xxx_write(chip, addr, reg, val);
}

int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
{
	return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
}
35

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
/* Offset 0x1a: Monitor Control */
/* Offset 0x1a: Monitor & MGMT Control on some devices */

int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
{
	u16 reg;
	int err;

	err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, &reg);
	if (err)
		return err;

	reg &= ~(GLOBAL_MONITOR_CONTROL_INGRESS_MASK |
		 GLOBAL_MONITOR_CONTROL_EGRESS_MASK);

	reg |= port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
		port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT;

	return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
}

/* Older generations also call this the ARP destination. It has been
 * generalized in more modern devices such that more than ARP can
 * egress it
 */
int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
{
	u16 reg;
	int err;

	err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, &reg);
	if (err)
		return err;

	reg &= ~GLOBAL_MONITOR_CONTROL_ARP_MASK;
	reg |= port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;

	return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
}

static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip,
				      u16 pointer, u8 data)
{
	u16 reg;

	reg = GLOBAL_MONITOR_CONTROL_UPDATE | pointer | data;

	return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
}

int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
{
	int err;

	err = mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_INGRESS,
					 port);
	if (err)
		return err;

	return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_EGRESS,
					  port);
}

int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
{
	return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_CPU_DEST,
					  port);
}

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
/* Offset 0x1c: Global Control 2 */

int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
{
	u16 val;
	int err;

	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL_2, &val);
	if (err)
		return err;

	val |= GLOBAL_CONTROL_2_HIST_RX_TX;

	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2, val);

	return err;
}

/* Offset 0x1d: Statistics Operation 2 */

125
int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
{
	return mv88e6xxx_g1_wait(chip, GLOBAL_STATS_OP, GLOBAL_STATS_OP_BUSY);
}

int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
{
	int err;

	/* Snapshot the hardware statistics counters for this port. */
	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
				 GLOBAL_STATS_OP_CAPTURE_PORT |
				 GLOBAL_STATS_OP_HIST_RX_TX | port);
	if (err)
		return err;

	/* Wait for the snapshotting to complete. */
	return mv88e6xxx_g1_stats_wait(chip);
}

int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
{
	port = (port + 1) << 5;

	return mv88e6xxx_g1_stats_snapshot(chip, port);
}
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166

int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
{
	int err;

	port = (port + 1) << 5;

	/* Snapshot the hardware statistics counters for this port. */
	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
				 GLOBAL_STATS_OP_CAPTURE_PORT | port);
	if (err)
		return err;

	/* Wait for the snapshotting to complete. */
	return mv88e6xxx_g1_stats_wait(chip);
}
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val)
{
	u32 value;
	u16 reg;
	int err;

	*val = 0;

	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
				 GLOBAL_STATS_OP_READ_CAPTURED | stat);
	if (err)
		return;

	err = mv88e6xxx_g1_stats_wait(chip);
	if (err)
		return;

	err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, &reg);
	if (err)
		return;

	value = reg << 16;

	err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, &reg);
	if (err)
		return;

	*val = value | reg;
}