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