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 3633641994SAndrew Lunn /* Offset 0x1a: Monitor Control */ 3733641994SAndrew Lunn /* Offset 0x1a: Monitor & MGMT Control on some devices */ 3833641994SAndrew Lunn 3933641994SAndrew Lunn int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port) 4033641994SAndrew Lunn { 4133641994SAndrew Lunn u16 reg; 4233641994SAndrew Lunn int err; 4333641994SAndrew Lunn 4433641994SAndrew Lunn err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, ®); 4533641994SAndrew Lunn if (err) 4633641994SAndrew Lunn return err; 4733641994SAndrew Lunn 4833641994SAndrew Lunn reg &= ~(GLOBAL_MONITOR_CONTROL_INGRESS_MASK | 4933641994SAndrew Lunn GLOBAL_MONITOR_CONTROL_EGRESS_MASK); 5033641994SAndrew Lunn 5133641994SAndrew Lunn reg |= port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT | 5233641994SAndrew Lunn port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT; 5333641994SAndrew Lunn 5433641994SAndrew Lunn return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg); 5533641994SAndrew Lunn } 5633641994SAndrew Lunn 5733641994SAndrew Lunn /* Older generations also call this the ARP destination. It has been 5833641994SAndrew Lunn * generalized in more modern devices such that more than ARP can 5933641994SAndrew Lunn * egress it 6033641994SAndrew Lunn */ 6133641994SAndrew Lunn int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port) 6233641994SAndrew Lunn { 6333641994SAndrew Lunn u16 reg; 6433641994SAndrew Lunn int err; 6533641994SAndrew Lunn 6633641994SAndrew Lunn err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, ®); 6733641994SAndrew Lunn if (err) 6833641994SAndrew Lunn return err; 6933641994SAndrew Lunn 7033641994SAndrew Lunn reg &= ~GLOBAL_MONITOR_CONTROL_ARP_MASK; 7133641994SAndrew Lunn reg |= port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT; 7233641994SAndrew Lunn 7333641994SAndrew Lunn return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg); 7433641994SAndrew Lunn } 7533641994SAndrew Lunn 7633641994SAndrew Lunn static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip, 7733641994SAndrew Lunn u16 pointer, u8 data) 7833641994SAndrew Lunn { 7933641994SAndrew Lunn u16 reg; 8033641994SAndrew Lunn 8133641994SAndrew Lunn reg = GLOBAL_MONITOR_CONTROL_UPDATE | pointer | data; 8233641994SAndrew Lunn 8333641994SAndrew Lunn return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg); 8433641994SAndrew Lunn } 8533641994SAndrew Lunn 8633641994SAndrew Lunn int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port) 8733641994SAndrew Lunn { 8833641994SAndrew Lunn int err; 8933641994SAndrew Lunn 9033641994SAndrew Lunn err = mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_INGRESS, 9133641994SAndrew Lunn port); 9233641994SAndrew Lunn if (err) 9333641994SAndrew Lunn return err; 9433641994SAndrew Lunn 9533641994SAndrew Lunn return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_EGRESS, 9633641994SAndrew Lunn port); 9733641994SAndrew Lunn } 9833641994SAndrew Lunn 9933641994SAndrew Lunn int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port) 10033641994SAndrew Lunn { 10133641994SAndrew Lunn return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_CPU_DEST, 10233641994SAndrew Lunn port); 10333641994SAndrew Lunn } 10433641994SAndrew Lunn 1056e55f698SAndrew Lunn int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip) 1066e55f698SAndrew Lunn { 1076e55f698SAndrew Lunn int err; 1086e55f698SAndrew Lunn 1096e55f698SAndrew Lunn /* 01:c2:80:00:00:00:00-01:c2:80:00:00:00:07 are Management */ 1106e55f698SAndrew Lunn err = mv88e6390_g1_monitor_write( 1116e55f698SAndrew Lunn chip, GLOBAL_MONITOR_CONTROL_0180C280000000XLO, 0xff); 1126e55f698SAndrew Lunn if (err) 1136e55f698SAndrew Lunn return err; 1146e55f698SAndrew Lunn 1156e55f698SAndrew Lunn /* 01:c2:80:00:00:00:08-01:c2:80:00:00:00:0f are Management */ 1166e55f698SAndrew Lunn err = mv88e6390_g1_monitor_write( 1176e55f698SAndrew Lunn chip, GLOBAL_MONITOR_CONTROL_0180C280000000XHI, 0xff); 1186e55f698SAndrew Lunn if (err) 1196e55f698SAndrew Lunn return err; 1206e55f698SAndrew Lunn 1216e55f698SAndrew Lunn /* 01:c2:80:00:00:00:20-01:c2:80:00:00:00:27 are Management */ 1226e55f698SAndrew Lunn err = mv88e6390_g1_monitor_write( 1236e55f698SAndrew Lunn chip, GLOBAL_MONITOR_CONTROL_0180C280000002XLO, 0xff); 1246e55f698SAndrew Lunn if (err) 1256e55f698SAndrew Lunn return err; 1266e55f698SAndrew Lunn 1276e55f698SAndrew Lunn /* 01:c2:80:00:00:00:28-01:c2:80:00:00:00:2f are Management */ 1286e55f698SAndrew Lunn return mv88e6390_g1_monitor_write( 1296e55f698SAndrew Lunn chip, GLOBAL_MONITOR_CONTROL_0180C280000002XHI, 0xff); 1306e55f698SAndrew Lunn } 1316e55f698SAndrew Lunn 132de227387SAndrew Lunn /* Offset 0x1c: Global Control 2 */ 133de227387SAndrew Lunn 134de227387SAndrew Lunn int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip) 135de227387SAndrew Lunn { 136de227387SAndrew Lunn u16 val; 137de227387SAndrew Lunn int err; 138de227387SAndrew Lunn 139de227387SAndrew Lunn err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL_2, &val); 140de227387SAndrew Lunn if (err) 141de227387SAndrew Lunn return err; 142de227387SAndrew Lunn 143de227387SAndrew Lunn val |= GLOBAL_CONTROL_2_HIST_RX_TX; 144de227387SAndrew Lunn 145de227387SAndrew Lunn err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2, val); 146de227387SAndrew Lunn 147de227387SAndrew Lunn return err; 148de227387SAndrew Lunn } 149de227387SAndrew Lunn 150de227387SAndrew Lunn /* Offset 0x1d: Statistics Operation 2 */ 151de227387SAndrew Lunn 1527f9ef3afSAndrew Lunn int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip) 153a605a0feSAndrew Lunn { 154a605a0feSAndrew Lunn return mv88e6xxx_g1_wait(chip, GLOBAL_STATS_OP, GLOBAL_STATS_OP_BUSY); 155a605a0feSAndrew Lunn } 156a605a0feSAndrew Lunn 157a605a0feSAndrew Lunn int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port) 158a605a0feSAndrew Lunn { 159a605a0feSAndrew Lunn int err; 160a605a0feSAndrew Lunn 161a605a0feSAndrew Lunn /* Snapshot the hardware statistics counters for this port. */ 162a605a0feSAndrew Lunn err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP, 163a605a0feSAndrew Lunn GLOBAL_STATS_OP_CAPTURE_PORT | 164a605a0feSAndrew Lunn GLOBAL_STATS_OP_HIST_RX_TX | port); 165a605a0feSAndrew Lunn if (err) 166a605a0feSAndrew Lunn return err; 167a605a0feSAndrew Lunn 168a605a0feSAndrew Lunn /* Wait for the snapshotting to complete. */ 169a605a0feSAndrew Lunn return mv88e6xxx_g1_stats_wait(chip); 170a605a0feSAndrew Lunn } 171a605a0feSAndrew Lunn 172a605a0feSAndrew Lunn int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port) 173a605a0feSAndrew Lunn { 174a605a0feSAndrew Lunn port = (port + 1) << 5; 175a605a0feSAndrew Lunn 176a605a0feSAndrew Lunn return mv88e6xxx_g1_stats_snapshot(chip, port); 177a605a0feSAndrew Lunn } 17879523473SAndrew Lunn 17979523473SAndrew Lunn int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port) 18079523473SAndrew Lunn { 18179523473SAndrew Lunn int err; 18279523473SAndrew Lunn 18379523473SAndrew Lunn port = (port + 1) << 5; 18479523473SAndrew Lunn 18579523473SAndrew Lunn /* Snapshot the hardware statistics counters for this port. */ 18679523473SAndrew Lunn err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP, 18779523473SAndrew Lunn GLOBAL_STATS_OP_CAPTURE_PORT | port); 18879523473SAndrew Lunn if (err) 18979523473SAndrew Lunn return err; 19079523473SAndrew Lunn 19179523473SAndrew Lunn /* Wait for the snapshotting to complete. */ 19279523473SAndrew Lunn return mv88e6xxx_g1_stats_wait(chip); 19379523473SAndrew Lunn } 1947f9ef3afSAndrew Lunn 1957f9ef3afSAndrew Lunn void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val) 1967f9ef3afSAndrew Lunn { 1977f9ef3afSAndrew Lunn u32 value; 1987f9ef3afSAndrew Lunn u16 reg; 1997f9ef3afSAndrew Lunn int err; 2007f9ef3afSAndrew Lunn 2017f9ef3afSAndrew Lunn *val = 0; 2027f9ef3afSAndrew Lunn 2037f9ef3afSAndrew Lunn err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP, 2047f9ef3afSAndrew Lunn GLOBAL_STATS_OP_READ_CAPTURED | stat); 2057f9ef3afSAndrew Lunn if (err) 2067f9ef3afSAndrew Lunn return; 2077f9ef3afSAndrew Lunn 2087f9ef3afSAndrew Lunn err = mv88e6xxx_g1_stats_wait(chip); 2097f9ef3afSAndrew Lunn if (err) 2107f9ef3afSAndrew Lunn return; 2117f9ef3afSAndrew Lunn 2127f9ef3afSAndrew Lunn err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, ®); 2137f9ef3afSAndrew Lunn if (err) 2147f9ef3afSAndrew Lunn return; 2157f9ef3afSAndrew Lunn 2167f9ef3afSAndrew Lunn value = reg << 16; 2177f9ef3afSAndrew Lunn 2187f9ef3afSAndrew Lunn err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, ®); 2197f9ef3afSAndrew Lunn if (err) 2207f9ef3afSAndrew Lunn return; 2217f9ef3afSAndrew Lunn 2227f9ef3afSAndrew Lunn *val = value | reg; 2237f9ef3afSAndrew Lunn } 224