1 1.25 andvar /* $NetBSD: octeon_gmx.c,v 1.25 2025/02/24 07:11:24 andvar Exp $ */ 2 1.1 hikaru 3 1.1 hikaru /* 4 1.1 hikaru * Copyright (c) 2007 Internet Initiative Japan, Inc. 5 1.1 hikaru * All rights reserved. 6 1.1 hikaru * 7 1.1 hikaru * Redistribution and use in source and binary forms, with or without 8 1.1 hikaru * modification, are permitted provided that the following conditions 9 1.1 hikaru * are met: 10 1.1 hikaru * 1. Redistributions of source code must retain the above copyright 11 1.1 hikaru * notice, this list of conditions and the following disclaimer. 12 1.1 hikaru * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 hikaru * notice, this list of conditions and the following disclaimer in the 14 1.1 hikaru * documentation and/or other materials provided with the distribution. 15 1.1 hikaru * 16 1.1 hikaru * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 17 1.1 hikaru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 1.1 hikaru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.1 hikaru * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 1.1 hikaru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.1 hikaru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 1.1 hikaru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.1 hikaru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 1.1 hikaru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 hikaru * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 hikaru * SUCH DAMAGE. 27 1.1 hikaru */ 28 1.1 hikaru 29 1.1 hikaru #include <sys/cdefs.h> 30 1.25 andvar __KERNEL_RCSID(0, "$NetBSD: octeon_gmx.c,v 1.25 2025/02/24 07:11:24 andvar Exp $"); 31 1.1 hikaru 32 1.1 hikaru #include <sys/param.h> 33 1.1 hikaru #include <sys/systm.h> 34 1.15 simonb #include <sys/bus.h> 35 1.1 hikaru #include <sys/cpu.h> 36 1.1 hikaru #include <sys/device.h> 37 1.1 hikaru #include <sys/lock.h> 38 1.1 hikaru #include <sys/cdefs.h> 39 1.16 thorpej #include <sys/kmem.h> 40 1.1 hikaru #include <sys/syslog.h> 41 1.1 hikaru 42 1.1 hikaru #include <mips/locore.h> 43 1.1 hikaru #include <mips/include/cpuregs.h> 44 1.1 hikaru 45 1.15 simonb #include <mips/cavium/dev/octeon_asxvar.h> 46 1.1 hikaru #include <mips/cavium/dev/octeon_ciureg.h> 47 1.1 hikaru #include <mips/cavium/dev/octeon_gmxreg.h> 48 1.15 simonb #include <mips/cavium/dev/octeon_gmxvar.h> 49 1.15 simonb #include <mips/cavium/dev/octeon_ipdvar.h> 50 1.15 simonb #include <mips/cavium/dev/octeon_pipvar.h> 51 1.15 simonb #include <mips/cavium/dev/octeon_smivar.h> 52 1.15 simonb 53 1.1 hikaru #include <mips/cavium/include/iobusvar.h> 54 1.15 simonb 55 1.15 simonb /* 56 1.15 simonb * CNnnXX packet interface 57 1.15 simonb * 58 1.15 simonb * 59 1.15 simonb * CN30XX - 1 GMX interface x 3 ports 60 1.15 simonb * CN31XX - 1 GMX interface x 3 ports 61 1.15 simonb * CN38XX - 2 GMX interfaces x 4 ports 62 1.15 simonb * CN50XX - 1 GMX interface x 3 ports 63 1.15 simonb * CN52XX - 1 GMX interface x 4 ports 64 1.15 simonb * CN56XX - 2 GMX interfaces x 4 ports 65 1.15 simonb * CN58XX - 2 GMX interfaces x 4 ports 66 1.15 simonb * CN61XX - 2 GMX interfaces x 4 ports 67 1.15 simonb * CN63XX - 1 GMX interface x 4 ports 68 1.15 simonb * CN66XX - 2 GMX interfaces x 4 ports 69 1.15 simonb * CN68XX - 5 GMX interfaces x 4 ports 70 1.15 simonb * CN70XX - 2 GMX interfaces x 4 ports 71 1.15 simonb * CNF71XX - 1 GMX interface x 2 ports 72 1.15 simonb */ 73 1.1 hikaru 74 1.1 hikaru #define dprintf(...) 75 1.11 simonb #define CNMAC_KASSERT KASSERT 76 1.1 hikaru 77 1.1 hikaru #define ADDR2UINT64(u, a) \ 78 1.1 hikaru do { \ 79 1.1 hikaru u = \ 80 1.1 hikaru (((uint64_t)a[0] << 40) | ((uint64_t)a[1] << 32) | \ 81 1.1 hikaru ((uint64_t)a[2] << 24) | ((uint64_t)a[3] << 16) | \ 82 1.1 hikaru ((uint64_t)a[4] << 8) | ((uint64_t)a[5] << 0)); \ 83 1.1 hikaru } while (0) 84 1.1 hikaru #define UINT642ADDR(a, u) \ 85 1.1 hikaru do { \ 86 1.1 hikaru a[0] = (uint8_t)((u) >> 40); a[1] = (uint8_t)((u) >> 32); \ 87 1.1 hikaru a[2] = (uint8_t)((u) >> 24); a[3] = (uint8_t)((u) >> 16); \ 88 1.1 hikaru a[4] = (uint8_t)((u) >> 8); a[5] = (uint8_t)((u) >> 0); \ 89 1.1 hikaru } while (0) 90 1.1 hikaru 91 1.1 hikaru #define _GMX_RD8(sc, off) \ 92 1.1 hikaru bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_gmx->sc_regh, (off)) 93 1.1 hikaru #define _GMX_WR8(sc, off, v) \ 94 1.1 hikaru bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_gmx->sc_regh, (off), (v)) 95 1.1 hikaru #define _GMX_PORT_RD8(sc, off) \ 96 1.1 hikaru bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_regh, (off)) 97 1.1 hikaru #define _GMX_PORT_WR8(sc, off, v) \ 98 1.1 hikaru bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_regh, (off), (v)) 99 1.1 hikaru 100 1.15 simonb #define PCS_READ_8(sc, reg) \ 101 1.15 simonb bus_space_read_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_pcs_regh, (reg)) 102 1.15 simonb #define PCS_WRITE_8(sc, reg, val) \ 103 1.15 simonb bus_space_write_8((sc)->sc_port_gmx->sc_regt, (sc)->sc_port_pcs_regh, (reg), (val)) 104 1.15 simonb 105 1.11 simonb struct octgmx_port_ops { 106 1.11 simonb int (*port_ops_enable)(struct octgmx_port_softc *, int); 107 1.11 simonb int (*port_ops_speed)(struct octgmx_port_softc *); 108 1.11 simonb int (*port_ops_timing)(struct octgmx_port_softc *); 109 1.1 hikaru }; 110 1.1 hikaru 111 1.11 simonb static int octgmx_match(device_t, struct cfdata *, void *); 112 1.11 simonb static void octgmx_attach(device_t, device_t, void *); 113 1.11 simonb static int octgmx_print(void *, const char *); 114 1.11 simonb static int octgmx_init(struct octgmx_softc *); 115 1.15 simonb 116 1.15 simonb static int octgmx_link_enable(struct octgmx_port_softc *, int); 117 1.11 simonb static int octgmx_rx_frm_ctl_xable(struct octgmx_port_softc *, uint64_t, 118 1.11 simonb int); 119 1.15 simonb static void octgmx_tx_int_enable(struct octgmx_port_softc *, int); 120 1.15 simonb static void octgmx_rx_int_enable(struct octgmx_port_softc *, int); 121 1.15 simonb static int octgmx_rx_frm_ctl_enable(struct octgmx_port_softc *, uint64_t); 122 1.15 simonb static int octgmx_rx_frm_ctl_disable(struct octgmx_port_softc *, uint64_t); 123 1.15 simonb static int octgmx_tx_thresh(struct octgmx_port_softc *, int); 124 1.11 simonb 125 1.11 simonb static int octgmx_rgmii_enable(struct octgmx_port_softc *, int); 126 1.11 simonb static int octgmx_rgmii_speed(struct octgmx_port_softc *); 127 1.11 simonb static int octgmx_rgmii_speed_newlink(struct octgmx_port_softc *, 128 1.1 hikaru uint64_t *); 129 1.11 simonb static int octgmx_rgmii_speed_speed(struct octgmx_port_softc *); 130 1.11 simonb static int octgmx_rgmii_timing(struct octgmx_port_softc *); 131 1.15 simonb 132 1.15 simonb static int octgmx_sgmii_enable(struct octgmx_port_softc *, int); 133 1.15 simonb static int octgmx_sgmii_speed(struct octgmx_port_softc *); 134 1.15 simonb static int octgmx_sgmii_timing(struct octgmx_port_softc *); 135 1.11 simonb 136 1.11 simonb static const int octgmx_rx_adr_cam_regs[] = { 137 1.1 hikaru GMX0_RX0_ADR_CAM0, GMX0_RX0_ADR_CAM1, GMX0_RX0_ADR_CAM2, 138 1.1 hikaru GMX0_RX0_ADR_CAM3, GMX0_RX0_ADR_CAM4, GMX0_RX0_ADR_CAM5 139 1.1 hikaru }; 140 1.1 hikaru 141 1.18 simonb static struct octgmx_port_ops octgmx_port_ops_mii = { 142 1.1 hikaru /* XXX not implemented */ 143 1.1 hikaru }; 144 1.1 hikaru 145 1.18 simonb static struct octgmx_port_ops octgmx_port_ops_gmii = { 146 1.11 simonb .port_ops_enable = octgmx_rgmii_enable, 147 1.11 simonb .port_ops_speed = octgmx_rgmii_speed, 148 1.11 simonb .port_ops_timing = octgmx_rgmii_timing, 149 1.1 hikaru }; 150 1.1 hikaru 151 1.18 simonb static struct octgmx_port_ops octgmx_port_ops_rgmii = { 152 1.11 simonb .port_ops_enable = octgmx_rgmii_enable, 153 1.11 simonb .port_ops_speed = octgmx_rgmii_speed, 154 1.11 simonb .port_ops_timing = octgmx_rgmii_timing, 155 1.15 simonb }; 156 1.15 simonb 157 1.18 simonb static struct octgmx_port_ops octgmx_port_ops_sgmii = { 158 1.15 simonb .port_ops_enable = octgmx_sgmii_enable, 159 1.15 simonb .port_ops_speed = octgmx_sgmii_speed, 160 1.15 simonb .port_ops_timing = octgmx_sgmii_timing, 161 1.1 hikaru }; 162 1.1 hikaru 163 1.18 simonb static struct octgmx_port_ops octgmx_port_ops_spi42 = { 164 1.1 hikaru /* XXX not implemented */ 165 1.1 hikaru }; 166 1.1 hikaru 167 1.18 simonb static struct octgmx_port_ops *octgmx_port_ops[] = { 168 1.11 simonb [GMX_MII_PORT] = &octgmx_port_ops_mii, 169 1.11 simonb [GMX_GMII_PORT] = &octgmx_port_ops_gmii, 170 1.11 simonb [GMX_RGMII_PORT] = &octgmx_port_ops_rgmii, 171 1.15 simonb [GMX_SGMII_PORT] = &octgmx_port_ops_sgmii, 172 1.11 simonb [GMX_SPI42_PORT] = &octgmx_port_ops_spi42 173 1.1 hikaru }; 174 1.15 simonb static const char *octgmx_port_types[] = { 175 1.15 simonb [GMX_MII_PORT] = "MII", 176 1.15 simonb [GMX_GMII_PORT] = "GMII", 177 1.15 simonb [GMX_RGMII_PORT] = "RGMII", 178 1.15 simonb [GMX_SGMII_PORT] = "SGMII", 179 1.15 simonb [GMX_SPI42_PORT] = "SPI-4.2" 180 1.15 simonb }; 181 1.1 hikaru 182 1.11 simonb CFATTACH_DECL_NEW(octgmx, sizeof(struct octgmx_softc), 183 1.11 simonb octgmx_match, octgmx_attach, NULL, NULL); 184 1.1 hikaru 185 1.1 hikaru static int 186 1.11 simonb octgmx_match(device_t parent, struct cfdata *cf, void *aux) 187 1.1 hikaru { 188 1.1 hikaru struct iobus_attach_args *aa = aux; 189 1.1 hikaru 190 1.1 hikaru if (strcmp(cf->cf_name, aa->aa_name) != 0) 191 1.1 hikaru return 0; 192 1.1 hikaru if (cf->cf_unit != aa->aa_unitno) 193 1.1 hikaru return 0; 194 1.1 hikaru return 1; 195 1.1 hikaru } 196 1.1 hikaru 197 1.1 hikaru static void 198 1.11 simonb octgmx_attach(device_t parent, device_t self, void *aux) 199 1.1 hikaru { 200 1.11 simonb struct octgmx_softc *sc = device_private(self); 201 1.1 hikaru struct iobus_attach_args *aa = aux; 202 1.15 simonb struct octsmi_softc *smi; 203 1.15 simonb struct octgmx_port_softc *port_sc; 204 1.11 simonb struct octgmx_attach_args gmx_aa; 205 1.15 simonb int port, status; 206 1.1 hikaru int i; 207 1.1 hikaru 208 1.1 hikaru sc->sc_dev = self; 209 1.1 hikaru sc->sc_regt = aa->aa_bust; 210 1.1 hikaru sc->sc_unitno = aa->aa_unitno; 211 1.1 hikaru 212 1.1 hikaru aprint_normal("\n"); 213 1.1 hikaru 214 1.1 hikaru status = bus_space_map(sc->sc_regt, aa->aa_unit->addr, 215 1.15 simonb GMX_PORT_SIZE, 0, &sc->sc_regh); 216 1.1 hikaru if (status != 0) 217 1.1 hikaru panic(": can't map register"); 218 1.1 hikaru 219 1.11 simonb octgmx_init(sc); 220 1.1 hikaru 221 1.16 thorpej sc->sc_ports = kmem_zalloc(sizeof(*sc->sc_ports) * sc->sc_nports, 222 1.16 thorpej KM_SLEEP); 223 1.1 hikaru 224 1.1 hikaru for (i = 0; i < sc->sc_nports; i++) { 225 1.15 simonb port = GMX_PORT_NUM(sc->sc_unitno, i); 226 1.15 simonb smi = octsmi_lookup(/*XXX*/0, port); 227 1.15 simonb if (smi == NULL) 228 1.15 simonb continue; 229 1.15 simonb 230 1.1 hikaru port_sc = &sc->sc_ports[i]; 231 1.1 hikaru port_sc->sc_port_gmx = sc; 232 1.15 simonb port_sc->sc_port_no = port; 233 1.1 hikaru port_sc->sc_port_type = sc->sc_port_types[i]; 234 1.11 simonb port_sc->sc_port_ops = octgmx_port_ops[port_sc->sc_port_type]; 235 1.1 hikaru status = bus_space_map(sc->sc_regt, 236 1.15 simonb aa->aa_unit->addr + GMX_PORT_SIZE * i, 237 1.15 simonb GMX_PORT_SIZE, 0, &port_sc->sc_port_regh); 238 1.1 hikaru if (status != 0) 239 1.1 hikaru panic(": can't map port register"); 240 1.1 hikaru 241 1.15 simonb switch (port_sc->sc_port_type) { 242 1.15 simonb case GMX_MII_PORT: 243 1.15 simonb case GMX_GMII_PORT: 244 1.15 simonb case GMX_RGMII_PORT: { 245 1.15 simonb struct octasx_attach_args asx_aa; 246 1.15 simonb 247 1.15 simonb asx_aa.aa_port = i; 248 1.15 simonb asx_aa.aa_regt = aa->aa_bust; 249 1.15 simonb octasx_init(&asx_aa, &port_sc->sc_port_asx); 250 1.15 simonb break; 251 1.15 simonb } 252 1.15 simonb case GMX_SGMII_PORT: 253 1.15 simonb if (bus_space_map(sc->sc_regt, 254 1.15 simonb PCS_BASE(sc->sc_unitno, i), PCS_SIZE, 0, 255 1.15 simonb &port_sc->sc_port_pcs_regh)) 256 1.15 simonb panic("could not map PCS registers"); 257 1.15 simonb break; 258 1.15 simonb default: 259 1.15 simonb /* nothing */ 260 1.15 simonb break; 261 1.15 simonb } 262 1.15 simonb 263 1.1 hikaru (void)memset(&gmx_aa, 0, sizeof(gmx_aa)); 264 1.1 hikaru gmx_aa.ga_regt = aa->aa_bust; 265 1.1 hikaru gmx_aa.ga_addr = aa->aa_unit->addr; 266 1.1 hikaru gmx_aa.ga_name = "cnmac"; 267 1.15 simonb gmx_aa.ga_portno = port_sc->sc_port_no; 268 1.1 hikaru gmx_aa.ga_port_type = sc->sc_port_types[i]; 269 1.15 simonb gmx_aa.ga_smi = smi; 270 1.1 hikaru gmx_aa.ga_gmx = sc; 271 1.1 hikaru gmx_aa.ga_gmx_port = port_sc; 272 1.20 thorpej config_found(self, &gmx_aa, octgmx_print, CFARGS_NONE); 273 1.1 hikaru } 274 1.1 hikaru } 275 1.1 hikaru 276 1.1 hikaru static int 277 1.11 simonb octgmx_print(void *aux, const char *pnp) 278 1.1 hikaru { 279 1.11 simonb struct octgmx_attach_args *ga = aux; 280 1.1 hikaru 281 1.15 simonb aprint_normal(": address=0x%" PRIx64 ": %s\n", ga->ga_addr, 282 1.15 simonb octgmx_port_types[ga->ga_port_type]); 283 1.1 hikaru 284 1.1 hikaru return UNCONF; 285 1.1 hikaru } 286 1.1 hikaru 287 1.1 hikaru static int 288 1.11 simonb octgmx_init(struct octgmx_softc *sc) 289 1.1 hikaru { 290 1.1 hikaru int result = 0; 291 1.1 hikaru uint64_t inf_mode; 292 1.1 hikaru const mips_prid_t cpu_id = mips_options.mips_cpu_id; 293 1.1 hikaru 294 1.1 hikaru inf_mode = bus_space_read_8(sc->sc_regt, sc->sc_regh, GMX0_INF_MODE); 295 1.1 hikaru if ((inf_mode & INF_MODE_EN) == 0) { 296 1.15 simonb aprint_normal("ports are disabled\n"); 297 1.1 hikaru sc->sc_nports = 0; 298 1.1 hikaru return 1; 299 1.1 hikaru } 300 1.1 hikaru 301 1.1 hikaru if (MIPS_PRID_CID(cpu_id) != MIPS_PRID_CID_CAVIUM) 302 1.1 hikaru return 1; 303 1.1 hikaru 304 1.1 hikaru switch (MIPS_PRID_IMPL(cpu_id)) { 305 1.1 hikaru case MIPS_CN31XX: 306 1.1 hikaru /* 307 1.1 hikaru * Packet Interface Configuration 308 1.1 hikaru * GMX Registers, Interface Mode Register, GMX0_INF_MODE 309 1.1 hikaru */ 310 1.1 hikaru if ((inf_mode & INF_MODE_TYPE) == 0) { 311 1.1 hikaru /* all three ports configured as RGMII */ 312 1.1 hikaru sc->sc_nports = 3; 313 1.1 hikaru sc->sc_port_types[0] = GMX_RGMII_PORT; 314 1.1 hikaru sc->sc_port_types[1] = GMX_RGMII_PORT; 315 1.1 hikaru sc->sc_port_types[2] = GMX_RGMII_PORT; 316 1.1 hikaru } else { 317 1.1 hikaru /* port 0: RGMII, port 1: GMII, port 2: disabled */ 318 1.1 hikaru sc->sc_nports = 2; 319 1.1 hikaru sc->sc_port_types[0] = GMX_RGMII_PORT; 320 1.1 hikaru sc->sc_port_types[1] = GMX_GMII_PORT; 321 1.1 hikaru } 322 1.1 hikaru break; 323 1.1 hikaru case MIPS_CN30XX: 324 1.1 hikaru case MIPS_CN50XX: 325 1.1 hikaru /* 326 1.1 hikaru * Packet Interface Configuration 327 1.1 hikaru * GMX Registers, Interface Mode Register, GMX0_INF_MODE 328 1.1 hikaru */ 329 1.1 hikaru if ((inf_mode & INF_MODE_P0MII) == 0) 330 1.1 hikaru sc->sc_port_types[0] = GMX_RGMII_PORT; 331 1.1 hikaru else 332 1.1 hikaru sc->sc_port_types[0] = GMX_MII_PORT; 333 1.1 hikaru if ((inf_mode & INF_MODE_TYPE) == 0) { 334 1.25 andvar /* port 1 and 2 are configured as RGMII ports */ 335 1.1 hikaru sc->sc_nports = 3; 336 1.1 hikaru sc->sc_port_types[1] = GMX_RGMII_PORT; 337 1.1 hikaru sc->sc_port_types[2] = GMX_RGMII_PORT; 338 1.1 hikaru } else { 339 1.1 hikaru /* port 1: GMII/MII, port 2: disabled */ 340 1.22 andvar /* GMII or MII port is selected by GMX_PRT1_CFG[SPEED] */ 341 1.1 hikaru sc->sc_nports = 2; 342 1.1 hikaru sc->sc_port_types[1] = GMX_GMII_PORT; 343 1.1 hikaru } 344 1.1 hikaru #if 0 /* XXX XXX XXX */ 345 1.1 hikaru /* port 2 is in CN3010/CN5010 only */ 346 1.1 hikaru if ((octeon_model(id) != OCTEON_MODEL_CN3010) && 347 1.1 hikaru (octeon_model(id) != OCTEON_MODEL_CN5010)) 348 1.1 hikaru if (sc->sc_nports == 3) 349 1.1 hikaru sc->sc_nports = 2; 350 1.1 hikaru #endif 351 1.1 hikaru break; 352 1.15 simonb case MIPS_CN70XX: 353 1.15 simonb switch (inf_mode & INF_MODE_MODE) { 354 1.15 simonb case INF_MODE_MODE_SGMII: 355 1.15 simonb sc->sc_nports = 4; 356 1.15 simonb for (int i = 0; i < sc->sc_nports; i++) 357 1.15 simonb sc->sc_port_types[i] = GMX_SGMII_PORT; 358 1.15 simonb break; 359 1.15 simonb #ifdef notyet 360 1.15 simonb case INF_MODE_MODE_XAUI: 361 1.15 simonb #endif 362 1.15 simonb default: 363 1.15 simonb sc->sc_nports = 0; 364 1.15 simonb result = 1; 365 1.15 simonb } 366 1.15 simonb break; 367 1.1 hikaru default: 368 1.1 hikaru aprint_normal("unsupported octeon model: 0x%x\n", cpu_id); 369 1.1 hikaru sc->sc_nports = 0; 370 1.1 hikaru result = 1; 371 1.1 hikaru break; 372 1.1 hikaru } 373 1.1 hikaru 374 1.1 hikaru return result; 375 1.1 hikaru } 376 1.1 hikaru 377 1.1 hikaru /* XXX RGMII specific */ 378 1.15 simonb static int 379 1.11 simonb octgmx_link_enable(struct octgmx_port_softc *sc, int enable) 380 1.1 hikaru { 381 1.1 hikaru uint64_t prt_cfg; 382 1.1 hikaru 383 1.11 simonb octgmx_tx_int_enable(sc, enable); 384 1.11 simonb octgmx_rx_int_enable(sc, enable); 385 1.1 hikaru 386 1.1 hikaru prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG); 387 1.1 hikaru if (enable) { 388 1.11 simonb if (octgmx_link_status(sc)) { 389 1.1 hikaru SET(prt_cfg, PRTN_CFG_EN); 390 1.1 hikaru } 391 1.1 hikaru } else { 392 1.1 hikaru CLR(prt_cfg, PRTN_CFG_EN); 393 1.1 hikaru } 394 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg); 395 1.1 hikaru /* software should read back to flush the write operation. */ 396 1.1 hikaru (void)_GMX_PORT_RD8(sc, GMX0_PRT0_CFG); 397 1.1 hikaru 398 1.1 hikaru return 0; 399 1.1 hikaru } 400 1.1 hikaru 401 1.1 hikaru /* XXX RGMII specific */ 402 1.1 hikaru int 403 1.11 simonb octgmx_stats_init(struct octgmx_port_softc *sc) 404 1.1 hikaru { 405 1.15 simonb _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS, 0); 406 1.15 simonb _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_DRP, 0); 407 1.15 simonb _GMX_PORT_WR8(sc, GMX0_RX0_STATS_PKTS_BAD, 0); 408 1.15 simonb _GMX_PORT_WR8(sc, GMX0_TX0_STAT0, 0); 409 1.15 simonb _GMX_PORT_WR8(sc, GMX0_TX0_STAT1, 0); 410 1.15 simonb _GMX_PORT_WR8(sc, GMX0_TX0_STAT3, 0); 411 1.15 simonb _GMX_PORT_WR8(sc, GMX0_TX0_STAT9, 0); 412 1.1 hikaru 413 1.1 hikaru return 0; 414 1.1 hikaru } 415 1.1 hikaru 416 1.1 hikaru int 417 1.11 simonb octgmx_tx_stats_rd_clr(struct octgmx_port_softc *sc, int enable) 418 1.1 hikaru { 419 1.15 simonb _GMX_PORT_WR8(sc, GMX0_TX0_STATS_CTL, enable ? 1 : 0); 420 1.1 hikaru return 0; 421 1.1 hikaru } 422 1.1 hikaru 423 1.1 hikaru int 424 1.11 simonb octgmx_rx_stats_rd_clr(struct octgmx_port_softc *sc, int enable) 425 1.1 hikaru { 426 1.15 simonb _GMX_PORT_WR8(sc, GMX0_RX0_STATS_CTL, enable ? 1 : 0); 427 1.1 hikaru return 0; 428 1.1 hikaru } 429 1.1 hikaru 430 1.1 hikaru static int 431 1.11 simonb octgmx_tx_ovr_bp_enable(struct octgmx_port_softc *sc, int enable) 432 1.1 hikaru { 433 1.1 hikaru uint64_t ovr_bp; 434 1.15 simonb int index = GMX_PORT_INDEX(sc->sc_port_no); 435 1.1 hikaru 436 1.1 hikaru ovr_bp = _GMX_RD8(sc, GMX0_TX_OVR_BP); 437 1.1 hikaru if (enable) { 438 1.15 simonb CLR(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_EN)); 439 1.15 simonb SET(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_BP)); 440 1.1 hikaru /* XXX really??? */ 441 1.15 simonb SET(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_IGN_FULL)); 442 1.1 hikaru } else { 443 1.15 simonb SET(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_EN)); 444 1.15 simonb CLR(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_BP)); 445 1.1 hikaru /* XXX really??? */ 446 1.15 simonb SET(ovr_bp, __SHIFTIN(__BIT(index), TX_OVR_BP_IGN_FULL)); 447 1.1 hikaru } 448 1.1 hikaru _GMX_WR8(sc, GMX0_TX_OVR_BP, ovr_bp); 449 1.1 hikaru return 0; 450 1.1 hikaru } 451 1.1 hikaru 452 1.1 hikaru static int 453 1.11 simonb octgmx_rx_pause_enable(struct octgmx_port_softc *sc, int enable) 454 1.1 hikaru { 455 1.1 hikaru if (enable) { 456 1.11 simonb octgmx_rx_frm_ctl_enable(sc, RXN_FRM_CTL_CTL_BCK); 457 1.1 hikaru } else { 458 1.11 simonb octgmx_rx_frm_ctl_disable(sc, RXN_FRM_CTL_CTL_BCK); 459 1.1 hikaru } 460 1.1 hikaru 461 1.1 hikaru return 0; 462 1.1 hikaru } 463 1.1 hikaru 464 1.15 simonb static void 465 1.11 simonb octgmx_tx_int_enable(struct octgmx_port_softc *sc, int enable) 466 1.1 hikaru { 467 1.1 hikaru uint64_t tx_int_xxx = 0; 468 1.1 hikaru 469 1.1 hikaru SET(tx_int_xxx, 470 1.1 hikaru TX_INT_REG_LATE_COL | 471 1.1 hikaru TX_INT_REG_XSDEF | 472 1.1 hikaru TX_INT_REG_XSCOL | 473 1.1 hikaru TX_INT_REG_UNDFLW | 474 1.1 hikaru TX_INT_REG_PKO_NXA); 475 1.1 hikaru _GMX_WR8(sc, GMX0_TX_INT_REG, tx_int_xxx); 476 1.1 hikaru _GMX_WR8(sc, GMX0_TX_INT_EN, enable ? tx_int_xxx : 0); 477 1.1 hikaru } 478 1.1 hikaru 479 1.15 simonb static void 480 1.11 simonb octgmx_rx_int_enable(struct octgmx_port_softc *sc, int enable) 481 1.1 hikaru { 482 1.1 hikaru uint64_t rx_int_xxx = 0; 483 1.1 hikaru 484 1.1 hikaru SET(rx_int_xxx, 0 | 485 1.1 hikaru RXN_INT_REG_PHY_DUPX | 486 1.1 hikaru RXN_INT_REG_PHY_SPD | 487 1.1 hikaru RXN_INT_REG_PHY_LINK | 488 1.1 hikaru RXN_INT_REG_IFGERR | 489 1.1 hikaru RXN_INT_REG_COLDET | 490 1.1 hikaru RXN_INT_REG_FALERR | 491 1.1 hikaru RXN_INT_REG_RSVERR | 492 1.1 hikaru RXN_INT_REG_PCTERR | 493 1.1 hikaru RXN_INT_REG_OVRERR | 494 1.1 hikaru RXN_INT_REG_NIBERR | 495 1.1 hikaru RXN_INT_REG_SKPERR | 496 1.1 hikaru RXN_INT_REG_RCVERR | 497 1.1 hikaru RXN_INT_REG_LENERR | 498 1.1 hikaru RXN_INT_REG_ALNERR | 499 1.1 hikaru RXN_INT_REG_FCSERR | 500 1.1 hikaru RXN_INT_REG_JABBER | 501 1.1 hikaru RXN_INT_REG_MAXERR | 502 1.1 hikaru RXN_INT_REG_CAREXT | 503 1.1 hikaru RXN_INT_REG_MINERR); 504 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_INT_REG, rx_int_xxx); 505 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_INT_EN, enable ? rx_int_xxx : 0); 506 1.1 hikaru } 507 1.1 hikaru 508 1.15 simonb static int 509 1.11 simonb octgmx_rx_frm_ctl_enable(struct octgmx_port_softc *sc, uint64_t rx_frm_ctl) 510 1.1 hikaru { 511 1.15 simonb struct ifnet *ifp = &sc->sc_port_ec->ec_if; 512 1.15 simonb unsigned int maxlen; 513 1.15 simonb 514 1.15 simonb maxlen = roundup(ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + 515 1.15 simonb ETHER_VLAN_ENCAP_LEN, 8); 516 1.15 simonb _GMX_PORT_WR8(sc, GMX0_RX0_JABBER, maxlen); 517 1.1 hikaru 518 1.11 simonb return octgmx_rx_frm_ctl_xable(sc, rx_frm_ctl, 1); 519 1.1 hikaru } 520 1.1 hikaru 521 1.15 simonb static int 522 1.11 simonb octgmx_rx_frm_ctl_disable(struct octgmx_port_softc *sc, uint64_t rx_frm_ctl) 523 1.1 hikaru { 524 1.11 simonb return octgmx_rx_frm_ctl_xable(sc, rx_frm_ctl, 0); 525 1.1 hikaru } 526 1.1 hikaru 527 1.1 hikaru static int 528 1.11 simonb octgmx_rx_frm_ctl_xable(struct octgmx_port_softc *sc, uint64_t rx_frm_ctl, 529 1.11 simonb int enable) 530 1.1 hikaru { 531 1.1 hikaru uint64_t tmp; 532 1.1 hikaru 533 1.1 hikaru tmp = _GMX_PORT_RD8(sc, GMX0_RX0_FRM_CTL); 534 1.1 hikaru if (enable) 535 1.1 hikaru SET(tmp, rx_frm_ctl); 536 1.1 hikaru else 537 1.1 hikaru CLR(tmp, rx_frm_ctl); 538 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_RX0_FRM_CTL, tmp); 539 1.1 hikaru 540 1.1 hikaru return 0; 541 1.1 hikaru } 542 1.1 hikaru 543 1.15 simonb static int 544 1.11 simonb octgmx_tx_thresh(struct octgmx_port_softc *sc, int cnt) 545 1.1 hikaru { 546 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_THRESH, cnt); 547 1.1 hikaru return 0; 548 1.1 hikaru } 549 1.1 hikaru 550 1.1 hikaru int 551 1.15 simonb octgmx_set_mac_addr(struct octgmx_port_softc *sc, const uint8_t *addr) 552 1.1 hikaru { 553 1.15 simonb uint64_t mac; 554 1.15 simonb int i; 555 1.1 hikaru 556 1.1 hikaru ADDR2UINT64(mac, addr); 557 1.15 simonb 558 1.15 simonb octgmx_link_enable(sc, 0); 559 1.15 simonb sc->sc_mac = mac; 560 1.15 simonb 561 1.15 simonb _GMX_PORT_WR8(sc, GMX0_SMAC0, mac); 562 1.15 simonb for (i = 0; i < 6; i++) 563 1.15 simonb _GMX_PORT_WR8(sc, octgmx_rx_adr_cam_regs[i], addr[i]); 564 1.15 simonb 565 1.15 simonb octgmx_link_enable(sc, 1); 566 1.15 simonb 567 1.1 hikaru return 0; 568 1.1 hikaru } 569 1.1 hikaru 570 1.1 hikaru int 571 1.11 simonb octgmx_set_filter(struct octgmx_port_softc *sc) 572 1.1 hikaru { 573 1.15 simonb struct ethercom *ec = sc->sc_port_ec; 574 1.15 simonb struct ifnet *ifp = &ec->ec_if; 575 1.15 simonb struct ether_multi *enm; 576 1.15 simonb struct ether_multistep step; 577 1.15 simonb uint64_t ctl = 0; 578 1.15 simonb int multi = 0; 579 1.15 simonb uint64_t cam_en = 1; /* enable CAM 0 for self MAC addr */ 580 1.15 simonb 581 1.15 simonb octgmx_link_enable(sc, 0); 582 1.15 simonb 583 1.15 simonb if (ISSET(ifp->if_flags, IFF_BROADCAST)) { 584 1.15 simonb dprintf("accept broadcast\n"); 585 1.15 simonb SET(ctl, RXN_ADR_CTL_BCST); 586 1.15 simonb } 587 1.15 simonb if (ISSET(ifp->if_flags, IFF_PROMISC)) { 588 1.23 gutterid dprintf("promiscuous (reject cam)\n"); 589 1.15 simonb CLR(ctl, RXN_ADR_CTL_CAM_MODE); 590 1.15 simonb } else { 591 1.23 gutterid dprintf("not promiscuous (accept cam)\n"); 592 1.15 simonb SET(ctl, RXN_ADR_CTL_CAM_MODE); 593 1.15 simonb } 594 1.15 simonb 595 1.15 simonb /* 596 1.21 andvar * Note first entry is self MAC address; other 7 entries are available 597 1.15 simonb * for multicast addresses. 598 1.15 simonb */ 599 1.15 simonb 600 1.15 simonb ETHER_LOCK(ec); 601 1.15 simonb ETHER_FIRST_MULTI(step, ec, enm); 602 1.15 simonb while (enm != NULL) { 603 1.15 simonb int i; 604 1.15 simonb 605 1.15 simonb dprintf("%d: lo(%02x:%02x:%02x:%02x:%02x:%02x) - " 606 1.15 simonb "hi(%02x:%02x:%02x:%02x:%02x:%02x)\n", 607 1.15 simonb multi + 1, 608 1.15 simonb enm->enm_addrlo[0], enm->enm_addrlo[1], 609 1.15 simonb enm->enm_addrlo[2], enm->enm_addrlo[3], 610 1.15 simonb enm->enm_addrlo[4], enm->enm_addrlo[5], 611 1.15 simonb enm->enm_addrhi[0], enm->enm_addrhi[1], 612 1.15 simonb enm->enm_addrhi[2], enm->enm_addrhi[3], 613 1.15 simonb enm->enm_addrhi[4], enm->enm_addrhi[5]); 614 1.15 simonb if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { 615 1.15 simonb dprintf("all multicast\n"); 616 1.15 simonb SET(ifp->if_flags, IFF_ALLMULTI); 617 1.15 simonb ETHER_UNLOCK(ec); 618 1.15 simonb goto setmulti; 619 1.15 simonb } 620 1.15 simonb multi++; 621 1.15 simonb 622 1.15 simonb /* XXX XXX XXX */ 623 1.15 simonb if (multi >= 8) { 624 1.15 simonb SET(ifp->if_flags, IFF_ALLMULTI); 625 1.15 simonb ETHER_UNLOCK(ec); 626 1.15 simonb goto setmulti; 627 1.15 simonb } 628 1.15 simonb /* XXX XXX XXX */ 629 1.15 simonb 630 1.15 simonb /* XXX XXX XXX */ 631 1.15 simonb SET(cam_en, __BIT(multi)); 632 1.15 simonb /* XXX XXX XXX */ 633 1.15 simonb 634 1.15 simonb for (i = 0; i < 6; i++) { 635 1.15 simonb uint64_t tmp; 636 1.15 simonb 637 1.15 simonb /* XXX XXX XXX */ 638 1.15 simonb tmp = _GMX_PORT_RD8(sc, octgmx_rx_adr_cam_regs[i]); 639 1.15 simonb CLR(tmp, 0xffULL << (8 * multi)); 640 1.15 simonb SET(tmp, (uint64_t)enm->enm_addrlo[i] << (8 * multi)); 641 1.15 simonb _GMX_PORT_WR8(sc, octgmx_rx_adr_cam_regs[i], tmp); 642 1.15 simonb /* XXX XXX XXX */ 643 1.15 simonb 644 1.15 simonb } 645 1.15 simonb for (i = 0; i < 6; i++) 646 1.15 simonb dprintf("cam%d = 0x%016lx\n", i, 647 1.15 simonb _GMX_PORT_RD8(sc, octgmx_rx_adr_cam_regs[i])); 648 1.15 simonb ETHER_NEXT_MULTI(step, enm); 649 1.15 simonb } 650 1.15 simonb ETHER_UNLOCK(ec); 651 1.15 simonb CLR(ifp->if_flags, IFF_ALLMULTI); 652 1.15 simonb 653 1.15 simonb CNMAC_KASSERT(enm == NULL); 654 1.15 simonb 655 1.15 simonb setmulti: 656 1.15 simonb /* XXX XXX XXX */ 657 1.15 simonb if (ISSET(ifp->if_flags, IFF_ALLMULTI) || 658 1.15 simonb ISSET(ifp->if_flags, IFF_PROMISC)) { 659 1.15 simonb /* XXX XXX XXX */ 660 1.15 simonb dprintf("accept all multicast\n"); 661 1.15 simonb ctl |= __SHIFTIN(RXN_ADR_CTL_MCST_ACCEPT, RXN_ADR_CTL_MCST); 662 1.15 simonb /* XXX XXX XXX */ 663 1.15 simonb } else if (multi) { 664 1.15 simonb /* XXX XXX XXX */ 665 1.15 simonb dprintf("use cam\n"); 666 1.15 simonb ctl |= __SHIFTIN(RXN_ADR_CTL_MCST_AFCAM, RXN_ADR_CTL_MCST); 667 1.15 simonb /* XXX XXX XXX */ 668 1.15 simonb } else { 669 1.15 simonb /* XXX XXX XXX */ 670 1.15 simonb dprintf("reject all multicast\n"); 671 1.15 simonb ctl |= __SHIFTIN(RXN_ADR_CTL_MCST_REJECT, RXN_ADR_CTL_MCST); 672 1.15 simonb /* XXX XXX XXX */ 673 1.15 simonb } 674 1.15 simonb /* XXX XXX XXX */ 675 1.15 simonb 676 1.15 simonb /* XXX XXX XXX */ 677 1.15 simonb if (ISSET(ifp->if_flags, IFF_PROMISC)) { 678 1.15 simonb cam_en = 0x00ULL; 679 1.15 simonb } else if (ISSET(ifp->if_flags, IFF_ALLMULTI)) { 680 1.15 simonb cam_en = 0x01ULL; 681 1.15 simonb } 682 1.15 simonb /* XXX XXX XXX */ 683 1.15 simonb 684 1.15 simonb dprintf("ctl = %#lx, cam_en = %#lx\n", ctl, cam_en); 685 1.15 simonb _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CTL, ctl); 686 1.15 simonb _GMX_PORT_WR8(sc, GMX0_RX0_ADR_CAM_EN, cam_en); 687 1.15 simonb 688 1.15 simonb octgmx_link_enable(sc, 1); 689 1.15 simonb 690 1.1 hikaru return 0; 691 1.1 hikaru } 692 1.1 hikaru 693 1.1 hikaru int 694 1.11 simonb octgmx_port_enable(struct octgmx_port_softc *sc, int enable) 695 1.1 hikaru { 696 1.1 hikaru (*sc->sc_port_ops->port_ops_enable)(sc, enable); 697 1.1 hikaru return 0; 698 1.1 hikaru } 699 1.1 hikaru 700 1.1 hikaru int 701 1.11 simonb octgmx_reset_speed(struct octgmx_port_softc *sc) 702 1.1 hikaru { 703 1.1 hikaru struct ifnet *ifp = &sc->sc_port_ec->ec_if; 704 1.1 hikaru if (ISSET(sc->sc_port_mii->mii_flags, MIIF_DOINGAUTO)) { 705 1.1 hikaru log(LOG_WARNING, 706 1.1 hikaru "%s: autonegotiation has not been completed yet\n", 707 1.1 hikaru ifp->if_xname); 708 1.1 hikaru return 1; 709 1.1 hikaru } 710 1.1 hikaru (*sc->sc_port_ops->port_ops_speed)(sc); 711 1.1 hikaru return 0; 712 1.1 hikaru } 713 1.1 hikaru 714 1.1 hikaru int 715 1.11 simonb octgmx_reset_timing(struct octgmx_port_softc *sc) 716 1.1 hikaru { 717 1.1 hikaru (*sc->sc_port_ops->port_ops_timing)(sc); 718 1.1 hikaru return 0; 719 1.1 hikaru } 720 1.1 hikaru 721 1.1 hikaru int 722 1.11 simonb octgmx_reset_flowctl(struct octgmx_port_softc *sc) 723 1.1 hikaru { 724 1.1 hikaru struct ifmedia_entry *ife = sc->sc_port_mii->mii_media.ifm_cur; 725 1.1 hikaru 726 1.1 hikaru /* 727 1.1 hikaru * Get flow control negotiation result. 728 1.1 hikaru */ 729 1.1 hikaru if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO && 730 1.1 hikaru (sc->sc_port_mii->mii_media_active & IFM_ETH_FMASK) != 731 1.1 hikaru sc->sc_port_flowflags) { 732 1.1 hikaru sc->sc_port_flowflags = 733 1.1 hikaru sc->sc_port_mii->mii_media_active & IFM_ETH_FMASK; 734 1.1 hikaru sc->sc_port_mii->mii_media_active &= ~IFM_ETH_FMASK; 735 1.1 hikaru } 736 1.1 hikaru 737 1.1 hikaru /* 738 1.1 hikaru * 802.3x Flow Control Capabilities 739 1.1 hikaru */ 740 1.1 hikaru if (sc->sc_port_flowflags & IFM_ETH_TXPAUSE) { 741 1.11 simonb octgmx_tx_ovr_bp_enable(sc, 1); 742 1.1 hikaru } else { 743 1.11 simonb octgmx_tx_ovr_bp_enable(sc, 0); 744 1.1 hikaru } 745 1.1 hikaru if (sc->sc_port_flowflags & IFM_ETH_RXPAUSE) { 746 1.11 simonb octgmx_rx_pause_enable(sc, 1); 747 1.1 hikaru } else { 748 1.11 simonb octgmx_rx_pause_enable(sc, 0); 749 1.1 hikaru } 750 1.1 hikaru 751 1.1 hikaru return 0; 752 1.1 hikaru } 753 1.1 hikaru 754 1.1 hikaru static int 755 1.11 simonb octgmx_rgmii_enable(struct octgmx_port_softc *sc, int enable) 756 1.1 hikaru { 757 1.1 hikaru uint64_t mode; 758 1.1 hikaru 759 1.1 hikaru /* XXX XXX XXX */ 760 1.1 hikaru mode = _GMX_RD8(sc, GMX0_INF_MODE); 761 1.1 hikaru if (ISSET(mode, INF_MODE_EN)) { 762 1.11 simonb octasx_enable(sc->sc_port_asx, 1); 763 1.1 hikaru } 764 1.1 hikaru /* XXX XXX XXX */ 765 1.1 hikaru return 0; 766 1.1 hikaru } 767 1.1 hikaru 768 1.1 hikaru static int 769 1.11 simonb octgmx_rgmii_speed(struct octgmx_port_softc *sc) 770 1.1 hikaru { 771 1.1 hikaru struct ifnet *ifp = &sc->sc_port_ec->ec_if; 772 1.1 hikaru uint64_t newlink; 773 1.1 hikaru int baudrate; 774 1.1 hikaru 775 1.1 hikaru /* XXX XXX XXX */ 776 1.11 simonb octgmx_link_enable(sc, 1); 777 1.1 hikaru 778 1.11 simonb octgmx_rgmii_speed_newlink(sc, &newlink); 779 1.1 hikaru if (sc->sc_link == newlink) { 780 1.1 hikaru return 0; 781 1.1 hikaru } 782 1.1 hikaru sc->sc_link = newlink; 783 1.1 hikaru 784 1.12 simonb switch (__SHIFTOUT(sc->sc_link, RXN_RX_INBND_SPEED)) { 785 1.1 hikaru case RXN_RX_INBND_SPEED_2_5: 786 1.1 hikaru baudrate = IF_Mbps(10); 787 1.1 hikaru break; 788 1.1 hikaru case RXN_RX_INBND_SPEED_25: 789 1.1 hikaru baudrate = IF_Mbps(100); 790 1.1 hikaru break; 791 1.1 hikaru case RXN_RX_INBND_SPEED_125: 792 1.1 hikaru baudrate = IF_Mbps(1000); 793 1.1 hikaru break; 794 1.1 hikaru default: 795 1.1 hikaru baudrate = 0/* XXX */; 796 1.3 maxv panic("unable to get baudrate"); 797 1.1 hikaru break; 798 1.1 hikaru } 799 1.1 hikaru ifp->if_baudrate = baudrate; 800 1.1 hikaru 801 1.11 simonb octgmx_link_enable(sc, 0); 802 1.1 hikaru 803 1.1 hikaru /* 804 1.1 hikaru * wait a max_packet_time 805 1.1 hikaru * max_packet_time(us) = (max_packet_size(bytes) * 8) / link_speed(Mbps) 806 1.1 hikaru */ 807 1.1 hikaru delay((GMX_FRM_MAX_SIZ * 8) / (baudrate / 1000000)); 808 1.1 hikaru 809 1.11 simonb octgmx_rgmii_speed_speed(sc); 810 1.1 hikaru 811 1.11 simonb octgmx_link_enable(sc, 1); 812 1.11 simonb octasx_enable(sc->sc_port_asx, 1); 813 1.1 hikaru 814 1.1 hikaru return 0; 815 1.1 hikaru } 816 1.1 hikaru 817 1.1 hikaru static int 818 1.11 simonb octgmx_rgmii_speed_newlink(struct octgmx_port_softc *sc, uint64_t *rnewlink) 819 1.1 hikaru { 820 1.15 simonb uint64_t newlink; 821 1.1 hikaru 822 1.15 simonb /* Inband status does not seem to work */ 823 1.15 simonb newlink = _GMX_PORT_RD8(sc, GMX0_RX0_RX_INBND); 824 1.1 hikaru 825 1.1 hikaru *rnewlink = newlink; 826 1.1 hikaru return 0; 827 1.1 hikaru } 828 1.1 hikaru 829 1.1 hikaru static int 830 1.11 simonb octgmx_rgmii_speed_speed(struct octgmx_port_softc *sc) 831 1.1 hikaru { 832 1.1 hikaru uint64_t prt_cfg; 833 1.1 hikaru uint64_t tx_clk, tx_slot, tx_burst; 834 1.1 hikaru 835 1.1 hikaru prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG); 836 1.1 hikaru 837 1.19 simonb switch (__SHIFTOUT(sc->sc_link, RXN_RX_INBND_SPEED)) { 838 1.1 hikaru case RXN_RX_INBND_SPEED_2_5: 839 1.1 hikaru /* 10Mbps */ 840 1.1 hikaru /* 841 1.1 hikaru * GMX Tx Clock Generation Registers 842 1.1 hikaru * 8ns x 50 = 400ns (2.5MHz TXC clock) 843 1.1 hikaru */ 844 1.1 hikaru tx_clk = 50; 845 1.1 hikaru /* 846 1.1 hikaru * TX Slottime Counter Registers 847 1.1 hikaru * 10/100Mbps: set SLOT to 0x40 848 1.1 hikaru */ 849 1.1 hikaru tx_slot = 0x40; 850 1.1 hikaru /* 851 1.1 hikaru * TX Burst-Counter Registers 852 1.1 hikaru * 10/100Mbps: set BURST to 0x0 853 1.1 hikaru */ 854 1.1 hikaru tx_burst = 0; 855 1.1 hikaru /* 856 1.1 hikaru * GMX Tx Port Configuration Registers 857 1.1 hikaru * Slot time for half-duplex operation 858 1.1 hikaru * 0 = 512 bittimes (10/100Mbps operation) 859 1.1 hikaru */ 860 1.1 hikaru CLR(prt_cfg, PRTN_CFG_SLOTTIME); 861 1.1 hikaru /* 862 1.1 hikaru * GMX Port Configuration Registers 863 1.1 hikaru * Link speed 864 1.1 hikaru * 0 = 10/100Mbps operation 865 1.1 hikaru * in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1 866 1.1 hikaru */ 867 1.1 hikaru CLR(prt_cfg, PRTN_CFG_SPEED); 868 1.1 hikaru break; 869 1.1 hikaru case RXN_RX_INBND_SPEED_25: 870 1.1 hikaru /* 100Mbps */ 871 1.1 hikaru /* 872 1.1 hikaru * GMX Tx Clock Generation Registers 873 1.1 hikaru * 8ns x 5 = 40ns (25.0MHz TXC clock) 874 1.1 hikaru */ 875 1.1 hikaru tx_clk = 5; 876 1.1 hikaru /* 877 1.1 hikaru * TX Slottime Counter Registers 878 1.1 hikaru * 10/100Mbps: set SLOT to 0x40 879 1.1 hikaru */ 880 1.1 hikaru tx_slot = 0x40; 881 1.1 hikaru /* 882 1.1 hikaru * TX Burst-Counter Registers 883 1.1 hikaru * 10/100Mbps: set BURST to 0x0 884 1.1 hikaru */ 885 1.1 hikaru tx_burst = 0; 886 1.1 hikaru /* 887 1.1 hikaru * GMX Tx Port Configuration Registers 888 1.1 hikaru * Slot time for half-duplex operation 889 1.1 hikaru * 0 = 512 bittimes (10/100Mbps operation) 890 1.1 hikaru */ 891 1.1 hikaru CLR(prt_cfg, PRTN_CFG_SLOTTIME); 892 1.1 hikaru /* 893 1.1 hikaru * GMX Port Configuration Registers 894 1.1 hikaru * Link speed 895 1.1 hikaru * 0 = 10/100Mbps operation 896 1.1 hikaru * in RGMII mode: GMX0_TX(0..2)_CLK[CLK_CNT] > 1 897 1.1 hikaru */ 898 1.1 hikaru CLR(prt_cfg, PRTN_CFG_SPEED); 899 1.1 hikaru break; 900 1.1 hikaru case RXN_RX_INBND_SPEED_125: 901 1.1 hikaru /* 1000Mbps */ 902 1.1 hikaru /* 903 1.1 hikaru * GMX Tx Clock Generation Registers 904 1.1 hikaru * 8ns x 1 = 8ns (125.0MHz TXC clock) 905 1.1 hikaru */ 906 1.1 hikaru tx_clk = 1; 907 1.1 hikaru /* 908 1.1 hikaru * TX Slottime Counter Registers 909 1.1 hikaru * > 1000Mbps: set SLOT to 0x200 910 1.1 hikaru */ 911 1.1 hikaru tx_slot = 0x200; 912 1.1 hikaru /* 913 1.1 hikaru * "TX Burst-Counter Registers 914 1.1 hikaru * > 1000Mbps: set BURST to 0x2000 915 1.1 hikaru */ 916 1.1 hikaru tx_burst = 0x2000; 917 1.1 hikaru /* 918 1.1 hikaru * GMX Tx Port Configuration Registers 919 1.1 hikaru * Slot time for half-duplex operation 920 1.1 hikaru * 1 = 4096 bittimes (1000Mbps operation) 921 1.1 hikaru */ 922 1.1 hikaru SET(prt_cfg, PRTN_CFG_SLOTTIME); 923 1.1 hikaru /* 924 1.1 hikaru * GMX Port Configuration Registers 925 1.1 hikaru * Link speed 926 1.1 hikaru * 1 = 1000Mbps operation 927 1.1 hikaru */ 928 1.1 hikaru SET(prt_cfg, PRTN_CFG_SPEED); 929 1.1 hikaru break; 930 1.1 hikaru default: 931 1.1 hikaru /* NOT REACHED! */ 932 1.1 hikaru /* Following configuration is default value of system. 933 1.1 hikaru */ 934 1.1 hikaru tx_clk = 1; 935 1.1 hikaru tx_slot = 0x200; 936 1.1 hikaru tx_burst = 0x2000; 937 1.1 hikaru SET(prt_cfg, PRTN_CFG_SLOTTIME); 938 1.1 hikaru SET(prt_cfg, PRTN_CFG_SPEED); 939 1.1 hikaru break; 940 1.1 hikaru } 941 1.1 hikaru 942 1.1 hikaru /* Setup Duplex mode(negotiated) */ 943 1.1 hikaru /* 944 1.1 hikaru * GMX Port Configuration Registers 945 1.1 hikaru * Duplex mode: 0 = half-duplex mode, 1=full-duplex 946 1.1 hikaru */ 947 1.12 simonb if (__SHIFTOUT(sc->sc_link, RXN_RX_INBND_DUPLEX)) { 948 1.1 hikaru /* Full-Duplex */ 949 1.1 hikaru SET(prt_cfg, PRTN_CFG_DUPLEX); 950 1.1 hikaru } else { 951 1.1 hikaru /* Half-Duplex */ 952 1.1 hikaru CLR(prt_cfg, PRTN_CFG_DUPLEX); 953 1.1 hikaru } 954 1.1 hikaru 955 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_CLK, tx_clk); 956 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_SLOT, tx_slot); 957 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_TX0_BURST, tx_burst); 958 1.1 hikaru _GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg); 959 1.1 hikaru 960 1.1 hikaru return 0; 961 1.1 hikaru } 962 1.1 hikaru 963 1.1 hikaru static int 964 1.11 simonb octgmx_rgmii_timing(struct octgmx_port_softc *sc) 965 1.1 hikaru { 966 1.1 hikaru uint64_t rx_frm_ctl; 967 1.1 hikaru 968 1.1 hikaru /* RGMII TX Threshold Registers 969 1.1 hikaru * Number of 16-byte ticks to accumulate in the TX FIFO before 970 1.1 hikaru * sending on the RGMII interface. This field should be large 971 1.1 hikaru * enough to prevent underflow on the RGMII interface and must 972 1.1 hikaru * never be set to less than 0x4. This register cannot exceed 973 1.1 hikaru * the TX FIFO depth of 0x40 words. 974 1.1 hikaru */ 975 1.1 hikaru /* Default parameter of CN30XX */ 976 1.11 simonb octgmx_tx_thresh(sc, 32); 977 1.1 hikaru 978 1.1 hikaru rx_frm_ctl = 0 | 979 1.1 hikaru /* RXN_FRM_CTL_NULL_DIS | (cn5xxx only) */ 980 1.1 hikaru /* RXN_FRM_CTL_PRE_ALIGN | (cn5xxx only) */ 981 1.1 hikaru /* RXN_FRM_CTL_PAD_LEN | (cn3xxx only) */ 982 1.1 hikaru /* RXN_FRM_CTL_VLAN_LEN | (cn3xxx only) */ 983 1.1 hikaru RXN_FRM_CTL_PRE_FREE | 984 1.1 hikaru RXN_FRM_CTL_CTL_SMAC | 985 1.1 hikaru RXN_FRM_CTL_CTL_MCST | 986 1.1 hikaru RXN_FRM_CTL_CTL_DRP | 987 1.1 hikaru RXN_FRM_CTL_PRE_STRP | 988 1.1 hikaru RXN_FRM_CTL_PRE_CHK; 989 1.11 simonb octgmx_rx_frm_ctl_enable(sc, rx_frm_ctl); 990 1.1 hikaru 991 1.1 hikaru /* RGMII RX Clock-Delay Registers 992 1.1 hikaru * Delay setting to place n RXC (RGMII receive clock) delay line. 993 1.1 hikaru * The intrinsic delay can range from 50ps to 80ps per tap, 994 1.1 hikaru * which corresponds to skews of 1.25ns to 2.00ns at 25 taps(CSR+1). 995 1.1 hikaru * This is the best match for the RGMII specification which wants 996 1.1 hikaru * 1ns - 2.6ns of skew. 997 1.1 hikaru */ 998 1.1 hikaru /* RGMII TX Clock-Delay Registers 999 1.1 hikaru * Delay setting to place n TXC (RGMII transmit clock) delay line. 1000 1.1 hikaru */ 1001 1.1 hikaru 1002 1.11 simonb octasx_clk_set(sc->sc_port_asx, 1003 1.9 mrg sc->sc_clk_tx_setting, sc->sc_clk_rx_setting); 1004 1.1 hikaru 1005 1.1 hikaru return 0; 1006 1.1 hikaru } 1007 1.1 hikaru 1008 1.1 hikaru static int 1009 1.15 simonb octgmx_sgmii_enable(struct octgmx_port_softc *sc, int enable) 1010 1.1 hikaru { 1011 1.15 simonb uint64_t ctl_reg, status, timer_count; 1012 1.15 simonb uint64_t cpu_freq_mhz = curcpu()->ci_cpu_freq / 1000000; 1013 1.15 simonb int done; 1014 1.1 hikaru int i; 1015 1.1 hikaru 1016 1.15 simonb if (!enable) 1017 1.15 simonb return 0; 1018 1.1 hikaru 1019 1.15 simonb /* Set link timer interval to 1.6ms. Timer multiple is 1024 (2^10). */ 1020 1.15 simonb /* 1021 1.15 simonb * XXX Should set timer to 10ms if not in SGMII mode (ie, 1022 1.15 simonb * "cavium,sgmii-mac-1000x-mode" property exists 1023 1.15 simonb */ 1024 1.15 simonb timer_count = PCS_READ_8(sc, PCS_LINK_TIMER_COUNT); 1025 1.15 simonb CLR(timer_count, PCS_LINK_TIMER_COUNT_MASK); 1026 1.15 simonb SET(timer_count, 1027 1.15 simonb __SHIFTIN((1600 * cpu_freq_mhz) >> 10, PCS_LINK_TIMER_COUNT_MASK)); 1028 1.15 simonb PCS_WRITE_8(sc, PCS_LINK_TIMER_COUNT, timer_count); 1029 1.15 simonb 1030 1.15 simonb /* Reset the PCS. */ 1031 1.15 simonb ctl_reg = PCS_READ_8(sc, PCS_MR_CONTROL); 1032 1.15 simonb SET(ctl_reg, PCS_MR_CONTROL_RESET); 1033 1.15 simonb PCS_WRITE_8(sc, PCS_MR_CONTROL, ctl_reg); 1034 1.15 simonb 1035 1.15 simonb /* Wait for the reset to complete. */ 1036 1.15 simonb done = 0; 1037 1.15 simonb for (i = 0; i < 1000000; i++) { 1038 1.15 simonb ctl_reg = PCS_READ_8(sc, PCS_MR_CONTROL); 1039 1.15 simonb if (!ISSET(ctl_reg, PCS_MR_CONTROL_RESET)) { 1040 1.15 simonb done = 1; 1041 1.15 simonb break; 1042 1.15 simonb } 1043 1.15 simonb } 1044 1.15 simonb if (!done) { 1045 1.15 simonb printf("SGMII reset timeout on port %d\n", sc->sc_port_no); 1046 1.15 simonb return 1; 1047 1.15 simonb } 1048 1.1 hikaru 1049 1.15 simonb /* Start a new SGMII autonegotiation. */ 1050 1.15 simonb SET(ctl_reg, PCS_MR_CONTROL_AN_EN); 1051 1.15 simonb SET(ctl_reg, PCS_MR_CONTROL_RST_AN); 1052 1.15 simonb CLR(ctl_reg, PCS_MR_CONTROL_PWR_DN); 1053 1.15 simonb PCS_WRITE_8(sc, PCS_MR_CONTROL, ctl_reg); 1054 1.15 simonb 1055 1.15 simonb /* Wait for the SGMII autonegotiation to complete. */ 1056 1.15 simonb done = 0; 1057 1.15 simonb for (i = 0; i < 1000000; i++) { 1058 1.15 simonb status = PCS_READ_8(sc, PCS_MR_STATUS); 1059 1.15 simonb if (ISSET(status, PCS_MR_STATUS_AN_CPT)) { 1060 1.15 simonb done = 1; 1061 1.15 simonb break; 1062 1.15 simonb } 1063 1.15 simonb } 1064 1.15 simonb if (!done) { 1065 1.15 simonb printf("SGMII autonegotiation timeout on port %d\n", 1066 1.15 simonb sc->sc_port_no); 1067 1.15 simonb return 1; 1068 1.15 simonb } 1069 1.1 hikaru 1070 1.1 hikaru return 0; 1071 1.1 hikaru } 1072 1.1 hikaru 1073 1.1 hikaru static int 1074 1.15 simonb octgmx_sgmii_speed(struct octgmx_port_softc *sc) 1075 1.1 hikaru { 1076 1.15 simonb uint64_t misc_ctl, prt_cfg; 1077 1.15 simonb int tx_burst, tx_slot; 1078 1.1 hikaru 1079 1.11 simonb octgmx_link_enable(sc, 0); 1080 1.1 hikaru 1081 1.15 simonb prt_cfg = _GMX_PORT_RD8(sc, GMX0_PRT0_CFG); 1082 1.1 hikaru 1083 1.15 simonb if (ISSET(sc->sc_port_mii->mii_media_active, IFM_FDX)) 1084 1.15 simonb SET(prt_cfg, PRTN_CFG_DUPLEX); 1085 1.15 simonb else 1086 1.15 simonb CLR(prt_cfg, PRTN_CFG_DUPLEX); 1087 1.1 hikaru 1088 1.15 simonb misc_ctl = PCS_READ_8(sc, PCS_MISC_CTL); 1089 1.15 simonb CLR(misc_ctl, PCS_MISC_CTL_SAMP_PT); 1090 1.1 hikaru 1091 1.15 simonb /* Disable the GMX port if the link is down. */ 1092 1.15 simonb if (octgmx_link_status(sc)) 1093 1.15 simonb CLR(misc_ctl, PCS_MISC_CTL_GMXENO); 1094 1.15 simonb else 1095 1.15 simonb SET(misc_ctl, PCS_MISC_CTL_GMXENO); 1096 1.1 hikaru 1097 1.15 simonb switch (sc->sc_port_ec->ec_if.if_baudrate) { 1098 1.15 simonb case IF_Mbps(10): 1099 1.15 simonb tx_slot = 0x40; 1100 1.15 simonb tx_burst = 0; 1101 1.15 simonb CLR(prt_cfg, PRTN_CFG_SPEED); 1102 1.15 simonb SET(prt_cfg, PRTN_CFG_SPEED_MSB); 1103 1.15 simonb CLR(prt_cfg, PRTN_CFG_SLOTTIME); 1104 1.15 simonb misc_ctl |= 25 & PCS_MISC_CTL_SAMP_PT; 1105 1.15 simonb break; 1106 1.15 simonb case IF_Mbps(100): 1107 1.15 simonb tx_slot = 0x40; 1108 1.15 simonb tx_burst = 0; 1109 1.15 simonb CLR(prt_cfg, PRTN_CFG_SPEED); 1110 1.15 simonb CLR(prt_cfg, PRTN_CFG_SPEED_MSB); 1111 1.15 simonb CLR(prt_cfg, PRTN_CFG_SLOTTIME); 1112 1.15 simonb misc_ctl |= 5 & PCS_MISC_CTL_SAMP_PT; 1113 1.15 simonb break; 1114 1.15 simonb case IF_Gbps(1): 1115 1.15 simonb default: 1116 1.15 simonb tx_slot = 0x200; 1117 1.15 simonb tx_burst = 0x2000; 1118 1.15 simonb SET(prt_cfg, PRTN_CFG_SPEED); 1119 1.15 simonb CLR(prt_cfg, PRTN_CFG_SPEED_MSB); 1120 1.15 simonb SET(prt_cfg, PRTN_CFG_SLOTTIME); 1121 1.15 simonb misc_ctl |= 1 & PCS_MISC_CTL_SAMP_PT; 1122 1.15 simonb break; 1123 1.15 simonb } 1124 1.1 hikaru 1125 1.15 simonb PCS_WRITE_8(sc, PCS_MISC_CTL, misc_ctl); 1126 1.1 hikaru 1127 1.15 simonb _GMX_PORT_WR8(sc, GMX0_TX0_SLOT, tx_slot); 1128 1.15 simonb _GMX_PORT_WR8(sc, GMX0_TX0_BURST, tx_burst); 1129 1.15 simonb _GMX_PORT_WR8(sc, GMX0_PRT0_CFG, prt_cfg); 1130 1.1 hikaru 1131 1.15 simonb octgmx_link_enable(sc, 1); 1132 1.1 hikaru 1133 1.15 simonb return 0; 1134 1.15 simonb } 1135 1.1 hikaru 1136 1.15 simonb static int 1137 1.15 simonb octgmx_sgmii_timing(struct octgmx_port_softc *sc) 1138 1.15 simonb { 1139 1.15 simonb uint64_t rx_frm_ctl; 1140 1.1 hikaru 1141 1.15 simonb octgmx_tx_thresh(sc, 32); 1142 1.1 hikaru 1143 1.15 simonb rx_frm_ctl = 1144 1.15 simonb RXN_FRM_CTL_PRE_FREE | 1145 1.15 simonb RXN_FRM_CTL_CTL_SMAC | 1146 1.15 simonb RXN_FRM_CTL_CTL_MCST | 1147 1.15 simonb RXN_FRM_CTL_CTL_DRP | 1148 1.15 simonb RXN_FRM_CTL_PRE_STRP | 1149 1.15 simonb RXN_FRM_CTL_PRE_CHK; 1150 1.15 simonb octgmx_rx_frm_ctl_enable(sc, rx_frm_ctl); 1151 1.1 hikaru 1152 1.1 hikaru return 0; 1153 1.1 hikaru } 1154 1.1 hikaru 1155 1.1 hikaru void 1156 1.11 simonb octgmx_stats(struct octgmx_port_softc *sc) 1157 1.1 hikaru { 1158 1.1 hikaru struct ifnet *ifp = &sc->sc_port_ec->ec_if; 1159 1.1 hikaru uint64_t tmp; 1160 1.1 hikaru 1161 1.1 hikaru /* 1162 1.1 hikaru * GMX0_RX0_STATS_PKTS is not count. 1163 1.22 andvar * input packet is counted when received packet in if_cnmac. 1164 1.1 hikaru */ 1165 1.1 hikaru /* 1166 1.1 hikaru * GMX0_RX0_STATS_PKTS_BAD count is included 1167 1.1 hikaru * receive error of work queue entry. 1168 1.1 hikaru * this is not add to input packet errors of interface. 1169 1.1 hikaru */ 1170 1.8 thorpej net_stat_ref_t nsr = IF_STAT_GETREF(ifp); 1171 1.24 riastrad if_statadd_ref(ifp, nsr, if_iqdrops, 1172 1.8 thorpej (uint32_t)_GMX_PORT_RD8(sc, GMX0_RX0_STATS_PKTS_DRP)); 1173 1.24 riastrad if_statadd_ref(ifp, nsr, if_opackets, 1174 1.8 thorpej (uint32_t)_GMX_PORT_RD8(sc, GMX0_TX0_STAT3)); 1175 1.1 hikaru 1176 1.1 hikaru tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT0); 1177 1.24 riastrad if_statadd_ref(ifp, nsr, if_oerrors, 1178 1.8 thorpej (uint32_t)tmp + ((uint32_t)(tmp >> 32) * 16)); 1179 1.24 riastrad if_statadd_ref(ifp, nsr, if_collisions, (uint32_t)tmp); 1180 1.1 hikaru 1181 1.1 hikaru tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT1); 1182 1.24 riastrad if_statadd_ref(ifp, nsr, if_collisions, 1183 1.8 thorpej (uint32_t)tmp + (uint32_t)(tmp >> 32)); 1184 1.1 hikaru 1185 1.1 hikaru tmp = _GMX_PORT_RD8(sc, GMX0_TX0_STAT9); 1186 1.24 riastrad if_statadd_ref(ifp, nsr, if_oerrors, (uint32_t)(tmp >> 32)); 1187 1.8 thorpej IF_STAT_PUTREF(ifp); 1188 1.1 hikaru } 1189