1 /* 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 17 int 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 24 int 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 31 int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask) 32 { 33 return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask); 34 } 35 36 /* Offset 0x00: Switch Global Status Register */ 37 38 static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip) 39 { 40 u16 state; 41 int i, err; 42 43 for (i = 0; i < 16; ++i) { 44 err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state); 45 if (err) 46 return err; 47 48 /* Check the value of the PPUState bits 15:14 */ 49 state &= GLOBAL_STATUS_PPU_STATE_MASK; 50 if (state == GLOBAL_STATUS_PPU_STATE_POLLING) 51 return 0; 52 53 usleep_range(1000, 2000); 54 } 55 56 return -ETIMEDOUT; 57 } 58 59 static int mv88e6352_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip) 60 { 61 u16 state; 62 int i, err; 63 64 for (i = 0; i < 16; ++i) { 65 err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state); 66 if (err) 67 return err; 68 69 /* Check the value of the PPUState (or InitState) bit 15 */ 70 if (state & GLOBAL_STATUS_PPU_STATE) 71 return 0; 72 73 usleep_range(1000, 2000); 74 } 75 76 return -ETIMEDOUT; 77 } 78 79 static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip) 80 { 81 const unsigned long timeout = jiffies + 1 * HZ; 82 u16 val; 83 int err; 84 85 /* Wait up to 1 second for the switch to be ready. The InitReady bit 11 86 * is set to a one when all units inside the device (ATU, VTU, etc.) 87 * have finished their initialization and are ready to accept frames. 88 */ 89 while (time_before(jiffies, timeout)) { 90 err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &val); 91 if (err) 92 return err; 93 94 if (val & GLOBAL_STATUS_INIT_READY) 95 break; 96 97 usleep_range(1000, 2000); 98 } 99 100 if (time_after(jiffies, timeout)) 101 return -ETIMEDOUT; 102 103 return 0; 104 } 105 106 /* Offset 0x04: Switch Global Control Register */ 107 108 int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip) 109 { 110 u16 val; 111 int err; 112 113 /* Set the SWReset bit 15 along with the PPUEn bit 14, to also restart 114 * the PPU, including re-doing PHY detection and initialization 115 */ 116 err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val); 117 if (err) 118 return err; 119 120 val |= GLOBAL_CONTROL_SW_RESET; 121 val |= GLOBAL_CONTROL_PPU_ENABLE; 122 123 err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val); 124 if (err) 125 return err; 126 127 err = mv88e6xxx_g1_wait_init_ready(chip); 128 if (err) 129 return err; 130 131 return mv88e6185_g1_wait_ppu_polling(chip); 132 } 133 134 int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip) 135 { 136 u16 val; 137 int err; 138 139 /* Set the SWReset bit 15 */ 140 err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val); 141 if (err) 142 return err; 143 144 val |= GLOBAL_CONTROL_SW_RESET; 145 146 err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val); 147 if (err) 148 return err; 149 150 err = mv88e6xxx_g1_wait_init_ready(chip); 151 if (err) 152 return err; 153 154 return mv88e6352_g1_wait_ppu_polling(chip); 155 } 156 157 /* Offset 0x1a: Monitor Control */ 158 /* Offset 0x1a: Monitor & MGMT Control on some devices */ 159 160 int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port) 161 { 162 u16 reg; 163 int err; 164 165 err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, ®); 166 if (err) 167 return err; 168 169 reg &= ~(GLOBAL_MONITOR_CONTROL_INGRESS_MASK | 170 GLOBAL_MONITOR_CONTROL_EGRESS_MASK); 171 172 reg |= port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT | 173 port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT; 174 175 return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg); 176 } 177 178 /* Older generations also call this the ARP destination. It has been 179 * generalized in more modern devices such that more than ARP can 180 * egress it 181 */ 182 int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port) 183 { 184 u16 reg; 185 int err; 186 187 err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, ®); 188 if (err) 189 return err; 190 191 reg &= ~GLOBAL_MONITOR_CONTROL_ARP_MASK; 192 reg |= port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT; 193 194 return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg); 195 } 196 197 static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip, 198 u16 pointer, u8 data) 199 { 200 u16 reg; 201 202 reg = GLOBAL_MONITOR_CONTROL_UPDATE | pointer | data; 203 204 return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg); 205 } 206 207 int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port) 208 { 209 int err; 210 211 err = mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_INGRESS, 212 port); 213 if (err) 214 return err; 215 216 return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_EGRESS, 217 port); 218 } 219 220 int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port) 221 { 222 return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_CPU_DEST, 223 port); 224 } 225 226 int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip) 227 { 228 int err; 229 230 /* 01:c2:80:00:00:00:00-01:c2:80:00:00:00:07 are Management */ 231 err = mv88e6390_g1_monitor_write( 232 chip, GLOBAL_MONITOR_CONTROL_0180C280000000XLO, 0xff); 233 if (err) 234 return err; 235 236 /* 01:c2:80:00:00:00:08-01:c2:80:00:00:00:0f are Management */ 237 err = mv88e6390_g1_monitor_write( 238 chip, GLOBAL_MONITOR_CONTROL_0180C280000000XHI, 0xff); 239 if (err) 240 return err; 241 242 /* 01:c2:80:00:00:00:20-01:c2:80:00:00:00:27 are Management */ 243 err = mv88e6390_g1_monitor_write( 244 chip, GLOBAL_MONITOR_CONTROL_0180C280000002XLO, 0xff); 245 if (err) 246 return err; 247 248 /* 01:c2:80:00:00:00:28-01:c2:80:00:00:00:2f are Management */ 249 return mv88e6390_g1_monitor_write( 250 chip, GLOBAL_MONITOR_CONTROL_0180C280000002XHI, 0xff); 251 } 252 253 /* Offset 0x1c: Global Control 2 */ 254 255 int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip) 256 { 257 u16 val; 258 int err; 259 260 err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL_2, &val); 261 if (err) 262 return err; 263 264 val |= GLOBAL_CONTROL_2_HIST_RX_TX; 265 266 err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2, val); 267 268 return err; 269 } 270 271 /* Offset 0x1d: Statistics Operation 2 */ 272 273 int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip) 274 { 275 return mv88e6xxx_g1_wait(chip, GLOBAL_STATS_OP, GLOBAL_STATS_OP_BUSY); 276 } 277 278 int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port) 279 { 280 int err; 281 282 /* Snapshot the hardware statistics counters for this port. */ 283 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP, 284 GLOBAL_STATS_OP_CAPTURE_PORT | 285 GLOBAL_STATS_OP_HIST_RX_TX | port); 286 if (err) 287 return err; 288 289 /* Wait for the snapshotting to complete. */ 290 return mv88e6xxx_g1_stats_wait(chip); 291 } 292 293 int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port) 294 { 295 port = (port + 1) << 5; 296 297 return mv88e6xxx_g1_stats_snapshot(chip, port); 298 } 299 300 int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port) 301 { 302 int err; 303 304 port = (port + 1) << 5; 305 306 /* Snapshot the hardware statistics counters for this port. */ 307 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP, 308 GLOBAL_STATS_OP_CAPTURE_PORT | port); 309 if (err) 310 return err; 311 312 /* Wait for the snapshotting to complete. */ 313 return mv88e6xxx_g1_stats_wait(chip); 314 } 315 316 void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val) 317 { 318 u32 value; 319 u16 reg; 320 int err; 321 322 *val = 0; 323 324 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP, 325 GLOBAL_STATS_OP_READ_CAPTURED | stat); 326 if (err) 327 return; 328 329 err = mv88e6xxx_g1_stats_wait(chip); 330 if (err) 331 return; 332 333 err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, ®); 334 if (err) 335 return; 336 337 value = reg << 16; 338 339 err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, ®); 340 if (err) 341 return; 342 343 *val = value | reg; 344 } 345