1 /* 2 * Marvell 88E6xxx Switch Global (1) Registers support 3 * 4 * Copyright (c) 2008 Marvell Semiconductor 5 * 6 * Copyright (c) 2016-2017 Savoir-faire Linux Inc. 7 * Vivien Didelot <vivien.didelot@savoirfairelinux.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 */ 14 15 #include "mv88e6xxx.h" 16 #include "global1.h" 17 18 int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val) 19 { 20 int addr = chip->info->global1_addr; 21 22 return mv88e6xxx_read(chip, addr, reg, val); 23 } 24 25 int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val) 26 { 27 int addr = chip->info->global1_addr; 28 29 return mv88e6xxx_write(chip, addr, reg, val); 30 } 31 32 int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask) 33 { 34 return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask); 35 } 36 37 /* Offset 0x00: Switch Global Status Register */ 38 39 static int mv88e6185_g1_wait_ppu_disabled(struct mv88e6xxx_chip *chip) 40 { 41 u16 state; 42 int i, err; 43 44 for (i = 0; i < 16; i++) { 45 err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state); 46 if (err) 47 return err; 48 49 /* Check the value of the PPUState bits 15:14 */ 50 state &= GLOBAL_STATUS_PPU_STATE_MASK; 51 if (state != GLOBAL_STATUS_PPU_STATE_POLLING) 52 return 0; 53 54 usleep_range(1000, 2000); 55 } 56 57 return -ETIMEDOUT; 58 } 59 60 static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip) 61 { 62 u16 state; 63 int i, err; 64 65 for (i = 0; i < 16; ++i) { 66 err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state); 67 if (err) 68 return err; 69 70 /* Check the value of the PPUState bits 15:14 */ 71 state &= GLOBAL_STATUS_PPU_STATE_MASK; 72 if (state == GLOBAL_STATUS_PPU_STATE_POLLING) 73 return 0; 74 75 usleep_range(1000, 2000); 76 } 77 78 return -ETIMEDOUT; 79 } 80 81 static int mv88e6352_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip) 82 { 83 u16 state; 84 int i, err; 85 86 for (i = 0; i < 16; ++i) { 87 err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state); 88 if (err) 89 return err; 90 91 /* Check the value of the PPUState (or InitState) bit 15 */ 92 if (state & GLOBAL_STATUS_PPU_STATE) 93 return 0; 94 95 usleep_range(1000, 2000); 96 } 97 98 return -ETIMEDOUT; 99 } 100 101 static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip) 102 { 103 const unsigned long timeout = jiffies + 1 * HZ; 104 u16 val; 105 int err; 106 107 /* Wait up to 1 second for the switch to be ready. The InitReady bit 11 108 * is set to a one when all units inside the device (ATU, VTU, etc.) 109 * have finished their initialization and are ready to accept frames. 110 */ 111 while (time_before(jiffies, timeout)) { 112 err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &val); 113 if (err) 114 return err; 115 116 if (val & GLOBAL_STATUS_INIT_READY) 117 break; 118 119 usleep_range(1000, 2000); 120 } 121 122 if (time_after(jiffies, timeout)) 123 return -ETIMEDOUT; 124 125 return 0; 126 } 127 128 /* Offset 0x04: Switch Global Control Register */ 129 130 int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip) 131 { 132 u16 val; 133 int err; 134 135 /* Set the SWReset bit 15 along with the PPUEn bit 14, to also restart 136 * the PPU, including re-doing PHY detection and initialization 137 */ 138 err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val); 139 if (err) 140 return err; 141 142 val |= GLOBAL_CONTROL_SW_RESET; 143 val |= GLOBAL_CONTROL_PPU_ENABLE; 144 145 err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val); 146 if (err) 147 return err; 148 149 err = mv88e6xxx_g1_wait_init_ready(chip); 150 if (err) 151 return err; 152 153 return mv88e6185_g1_wait_ppu_polling(chip); 154 } 155 156 int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip) 157 { 158 u16 val; 159 int err; 160 161 /* Set the SWReset bit 15 */ 162 err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val); 163 if (err) 164 return err; 165 166 val |= GLOBAL_CONTROL_SW_RESET; 167 168 err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val); 169 if (err) 170 return err; 171 172 err = mv88e6xxx_g1_wait_init_ready(chip); 173 if (err) 174 return err; 175 176 return mv88e6352_g1_wait_ppu_polling(chip); 177 } 178 179 int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip) 180 { 181 u16 val; 182 int err; 183 184 err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val); 185 if (err) 186 return err; 187 188 val |= GLOBAL_CONTROL_PPU_ENABLE; 189 190 err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val); 191 if (err) 192 return err; 193 194 return mv88e6185_g1_wait_ppu_polling(chip); 195 } 196 197 int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip) 198 { 199 u16 val; 200 int err; 201 202 err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val); 203 if (err) 204 return err; 205 206 val &= ~GLOBAL_CONTROL_PPU_ENABLE; 207 208 err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val); 209 if (err) 210 return err; 211 212 return mv88e6185_g1_wait_ppu_disabled(chip); 213 } 214 215 /* Offset 0x1a: Monitor Control */ 216 /* Offset 0x1a: Monitor & MGMT Control on some devices */ 217 218 int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port) 219 { 220 u16 reg; 221 int err; 222 223 err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, ®); 224 if (err) 225 return err; 226 227 reg &= ~(GLOBAL_MONITOR_CONTROL_INGRESS_MASK | 228 GLOBAL_MONITOR_CONTROL_EGRESS_MASK); 229 230 reg |= port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT | 231 port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT; 232 233 return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg); 234 } 235 236 /* Older generations also call this the ARP destination. It has been 237 * generalized in more modern devices such that more than ARP can 238 * egress it 239 */ 240 int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port) 241 { 242 u16 reg; 243 int err; 244 245 err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, ®); 246 if (err) 247 return err; 248 249 reg &= ~GLOBAL_MONITOR_CONTROL_ARP_MASK; 250 reg |= port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT; 251 252 return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg); 253 } 254 255 static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip, 256 u16 pointer, u8 data) 257 { 258 u16 reg; 259 260 reg = GLOBAL_MONITOR_CONTROL_UPDATE | pointer | data; 261 262 return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg); 263 } 264 265 int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port) 266 { 267 int err; 268 269 err = mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_INGRESS, 270 port); 271 if (err) 272 return err; 273 274 return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_EGRESS, 275 port); 276 } 277 278 int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port) 279 { 280 return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_CPU_DEST, 281 port); 282 } 283 284 int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip) 285 { 286 int err; 287 288 /* 01:c2:80:00:00:00:00-01:c2:80:00:00:00:07 are Management */ 289 err = mv88e6390_g1_monitor_write( 290 chip, GLOBAL_MONITOR_CONTROL_0180C280000000XLO, 0xff); 291 if (err) 292 return err; 293 294 /* 01:c2:80:00:00:00:08-01:c2:80:00:00:00:0f are Management */ 295 err = mv88e6390_g1_monitor_write( 296 chip, GLOBAL_MONITOR_CONTROL_0180C280000000XHI, 0xff); 297 if (err) 298 return err; 299 300 /* 01:c2:80:00:00:00:20-01:c2:80:00:00:00:27 are Management */ 301 err = mv88e6390_g1_monitor_write( 302 chip, GLOBAL_MONITOR_CONTROL_0180C280000002XLO, 0xff); 303 if (err) 304 return err; 305 306 /* 01:c2:80:00:00:00:28-01:c2:80:00:00:00:2f are Management */ 307 return mv88e6390_g1_monitor_write( 308 chip, GLOBAL_MONITOR_CONTROL_0180C280000002XHI, 0xff); 309 } 310 311 /* Offset 0x1c: Global Control 2 */ 312 313 int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip) 314 { 315 u16 val; 316 int err; 317 318 err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL_2, &val); 319 if (err) 320 return err; 321 322 val |= GLOBAL_CONTROL_2_HIST_RX_TX; 323 324 err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2, val); 325 326 return err; 327 } 328 329 /* Offset 0x1d: Statistics Operation 2 */ 330 331 int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip) 332 { 333 return mv88e6xxx_g1_wait(chip, GLOBAL_STATS_OP, GLOBAL_STATS_OP_BUSY); 334 } 335 336 int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port) 337 { 338 int err; 339 340 /* Snapshot the hardware statistics counters for this port. */ 341 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP, 342 GLOBAL_STATS_OP_CAPTURE_PORT | 343 GLOBAL_STATS_OP_HIST_RX_TX | port); 344 if (err) 345 return err; 346 347 /* Wait for the snapshotting to complete. */ 348 return mv88e6xxx_g1_stats_wait(chip); 349 } 350 351 int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port) 352 { 353 port = (port + 1) << 5; 354 355 return mv88e6xxx_g1_stats_snapshot(chip, port); 356 } 357 358 int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port) 359 { 360 int err; 361 362 port = (port + 1) << 5; 363 364 /* Snapshot the hardware statistics counters for this port. */ 365 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP, 366 GLOBAL_STATS_OP_CAPTURE_PORT | port); 367 if (err) 368 return err; 369 370 /* Wait for the snapshotting to complete. */ 371 return mv88e6xxx_g1_stats_wait(chip); 372 } 373 374 void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val) 375 { 376 u32 value; 377 u16 reg; 378 int err; 379 380 *val = 0; 381 382 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP, 383 GLOBAL_STATS_OP_READ_CAPTURED | stat); 384 if (err) 385 return; 386 387 err = mv88e6xxx_g1_stats_wait(chip); 388 if (err) 389 return; 390 391 err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, ®); 392 if (err) 393 return; 394 395 value = reg << 16; 396 397 err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, ®); 398 if (err) 399 return; 400 401 *val = value | reg; 402 } 403