1 /* 2 * Copyright (c) 2026 Justin Hibbits 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * FMan RX port driver. 7 */ 8 9 #include <sys/param.h> 10 #include <sys/bus.h> 11 #include <sys/kernel.h> 12 #include <sys/module.h> 13 14 #include <dev/ofw/ofw_bus.h> 15 #include <dev/ofw/ofw_bus_subr.h> 16 #include <machine/bus.h> 17 18 #include "fman.h" 19 #include "fman_parser.h" 20 #include "fman_port.h" 21 #include "fman_port_var.h" 22 #include "fman_if.h" 23 #include "fman_port_if.h" 24 25 #define RX_10G_PORT_BASE 0x10 26 27 /* BMI Rx registers. */ 28 #define FMBM_RCFG 0x000 29 #define FMBM_RST 0x004 30 #define FMBM_RDA 0x008 31 #define RDA_WOPT 0x00100000 32 #define FMBM_RFP 0x00c 33 #define FMBM_RFED 0x010 34 #define BMI_RX_FRAME_END_CUT_SHIFT 16 35 #define FMBM_RICP 0x014 /* Counts are units of 16 bytes */ 36 #define RICP_ICEOF_M 0x001f0000 37 #define RICP_ICEOF_S 16 38 #define RICP_ICIOF_M 0x00000f00 39 #define RICP_ICIOF_S 8 40 #define RICP_ICSZ_S 0x0000001f 41 #define FMBM_RIM 0x018 42 #define FMBM_REBM 0x01c 43 #define REBM_BSM_M 0x01ff0000 44 #define REBM_BSM_S 16 45 #define REBM_BEM_M 0x000001ff 46 #define FMBM_RFNE 0x020 47 #define FMBM_RFCA 0x024 48 #define RFCA_OR 0x80000000 49 #define RFCA_COLOR 0x0c000000 50 #define RFCA_SYNC 0x03000000 51 #define RFCA_SYNC_REQ 0x02000000 52 #define RFCA_MR 0x003f0000 53 #define RFCA_MR_DEF 0x003c0000 54 #define FMBM_RFPNE 0x028 55 #define FMBM_RETH 0x038 56 #define RETH_ETHE 0x80000000 /* Excessive Threshold Enable */ 57 #define FMBM_RFQID 0x060 58 #define FMBM_REFQID 0x064 59 #define FMBM_RFSDM 0x068 60 #define FMBM_RFSEM 0x06c 61 #define FMBM_RFENE 0x070 62 #define FMBM_REBMPI(i) (0x100 + (4 * (i))) 63 #define REBMPI_VAL 0x80000000 64 #define REBMPI_ACE 0x40000000 65 #define REBMPI_BPID_S 16 66 #define FMBM_RSTC 0x0200 67 #define RSTC_EN 0x80000000 68 69 /* Hardware Parser (HWP). */ 70 #define HWP_PCAC 0xbf8 71 #define HWP_PCAC_PSTOP 0x00000001 72 #define HWP_HXS_PCAC_PSTAT 0x00000100 73 #define HWP_HXS_SSA(x) (0x800 + x * 2 * sizeof(uint32_t)) 74 #define HWP_HXS_LCV(x) (0x800 + (x * 2 + 1) * sizeof(uint32_t)) 75 #define HWP_HXS_TCP 0xA 76 #define HWP_HXS_UDP 0xB 77 #define HXS_SH_PAD_REM 0x80000000 78 #define HWP_HXS_COUNT 16 79 80 #define BMI_RX_ERR (FM_FD_ERR_DMA | FM_FD_ERR_FPE | \ 81 FM_FD_ERR_FSE | FM_FD_ERR_DIS | \ 82 FM_FD_ERR_EOF | FM_FD_ERR_NSS | \ 83 FM_FD_ERR_KSO | FM_FD_ERR_IPP | \ 84 FM_FD_ERR_PTE | FM_FD_ERR_PHE | \ 85 FM_FD_ERR_BLE) 86 87 #define DEFAULT_RX_CUT_END_BYTES 4 88 89 struct fman_port_rx_softc { 90 struct fman_port_softc sc_base; 91 struct fman_port_buffer_pool sc_bpools[FMAN_PORT_MAX_POOLS]; 92 }; 93 94 static struct ofw_compat_data rx_compats[] = { 95 { "fsl,fman-v2-port-rx", 0 }, 96 { "fsl,fman-v3-port-rx", PORT_V3 }, 97 { NULL, 0 } 98 }; 99 100 static int 101 fman_port_rx_probe(device_t dev) 102 { 103 104 if (ofw_bus_search_compatible(dev, rx_compats)->ocd_str == NULL) 105 return (ENXIO); 106 107 device_set_desc(dev, "FMan RX port"); 108 return (BUS_PROBE_DEFAULT); 109 } 110 111 static int 112 fman_port_rx_attach(device_t dev) 113 { 114 struct fman_port_rx_softc *sc; 115 uintptr_t compat_data; 116 int port_speed; 117 118 sc = device_get_softc(dev); 119 compat_data = ofw_bus_search_compatible(dev, rx_compats)->ocd_data; 120 121 port_speed = 1000; 122 if ((compat_data & PORT_V3) == PORT_V3) { 123 if (OF_hasprop(ofw_bus_get_node(dev), "fsl,fman-10g-port")) 124 port_speed = 10000; 125 } else { 126 int cell = 0; 127 OF_getencprop(ofw_bus_get_node(dev), "cell-index", &cell, 128 sizeof(cell)); 129 if (cell > RX_10G_PORT_BASE) 130 port_speed = 10000; 131 } 132 133 return (fman_port_attach_common(dev, &sc->sc_base, port_speed)); 134 } 135 136 static int 137 fman_port_rx_detach(device_t dev) 138 { 139 struct fman_port_rx_softc *sc = device_get_softc(dev); 140 141 return (fman_port_detach_common(dev, &sc->sc_base)); 142 } 143 144 static int 145 fman_port_rx_config(device_t dev, struct fman_port_params *params) 146 { 147 struct fman_port_rx_softc *sc = device_get_softc(dev); 148 struct fman_port_softc *base = &sc->sc_base; 149 150 fman_port_config_common(base, params); 151 152 base->sc_tasks.extra = 0; 153 base->sc_open_dmas.extra = 0; 154 switch (base->sc_port_speed) { 155 case 10000: 156 if (base->sc_revision_major < 6) { 157 base->sc_tasks.num = 16; 158 base->sc_open_dmas.num = 8; 159 base->sc_open_dmas.extra = 8; 160 base->sc_fifo_bufs.num = 48; 161 } else { 162 base->sc_tasks.num = 14; 163 base->sc_open_dmas.num = 8; 164 base->sc_fifo_bufs.num = 96; 165 } 166 break; 167 case 1000: 168 if (base->sc_revision_major < 6) { 169 base->sc_tasks.num = 3; 170 base->sc_tasks.extra = 2; 171 base->sc_open_dmas.num = 1; 172 base->sc_open_dmas.extra = 1; 173 base->sc_fifo_bufs.num = 45; 174 } else { 175 base->sc_tasks.num = 4; 176 base->sc_open_dmas.num = 2; 177 base->sc_fifo_bufs.num = 50; 178 } 179 break; 180 default: 181 base->sc_tasks.num = 0; 182 break; 183 } 184 185 base->sc_fifo_bufs.extra = 0; 186 base->sc_fifo_bufs.num *= FMAN_BMI_FIFO_UNITS; 187 188 for (int i = 0; i < params->rx_params.num_pools; i++) 189 sc->sc_bpools[i] = params->rx_params.bpools[i]; 190 191 /* TODO: buf_margins? See fman_sp_build_buffer_struct */ 192 return (0); 193 } 194 195 static int 196 fman_port_rx_init_bmi(struct fman_port_rx_softc *sc) 197 { 198 struct fman_port_softc *base = &sc->sc_base; 199 uint32_t reg; 200 201 /* TODO: Sort the buffer pool list. */ 202 /* TODO: Backup pools */ 203 /* TODO: Depletion mode */ 204 for (int i = 0; i < FMAN_PORT_MAX_POOLS; i++) { 205 if (sc->sc_bpools[i].size != 0) { 206 bus_write_4(base->sc_mem, FMBM_REBMPI(i), 207 REBMPI_VAL | REBMPI_ACE | 208 (sc->sc_bpools[i].bpid << REBMPI_BPID_S) | 209 sc->sc_bpools[i].size); 210 } else 211 bus_write_4(base->sc_mem, FMBM_REBMPI(i), 0); 212 } 213 214 bus_write_4(base->sc_mem, FMBM_RDA, RDA_WOPT); 215 216 bus_write_4(base->sc_mem, FMBM_RFCA, 217 RFCA_OR | RFCA_SYNC_REQ | RFCA_MR_DEF); 218 219 /* 220 * Route the Parser output through KeyGen (HWK), not straight to 221 * BMI enqueue. KG then hands off to BMI-enqueue via its own 222 * default NIA (FMKG_GCR low bits, programmed by fman_kg_init as 223 * NIA_ENG_BMI|NIA_BMI_AC_ENQ_FRAME). Ports with no bound KG 224 * scheme fall through KG's default path to the port's dflt_fqid, 225 * matching the old direct-to-BMI behaviour; ports with a scheme 226 * bound (via fman_kg_alloc_hash_scheme, e.g. from the dpaa_eth 227 * RSS setup) get real hash distribution. 228 */ 229 bus_write_4(base->sc_mem, FMBM_RFPNE, NIA_ENG_HWK); 230 bus_write_4(base->sc_mem, FMBM_RFENE, 231 NIA_ENG_QMI_ENQ | NIA_ORDER_RESTORE); 232 233 bus_write_4(base->sc_mem, FMBM_RFQID, base->sc_default_fqid); 234 bus_write_4(base->sc_mem, FMBM_REFQID, base->sc_err_fqid); 235 236 if (base->sc_revision_major < 6) 237 bus_write_4(base->sc_mem, FMBM_RETH, RETH_ETHE); 238 239 /* Errata A006320 makes CFED field bad */ 240 if (base->sc_revision_major == 6 && base->sc_revision_minor == 0) 241 /* These are under errata A006320 */; 242 else 243 bus_write_4(base->sc_mem, FMBM_RFED, 244 DEFAULT_RX_CUT_END_BYTES << BMI_RX_FRAME_END_CUT_SHIFT); 245 246 /* Insert internal context ahead of the frame */ 247 reg = sizeof(struct fman_internal_context) << REBM_BSM_S; 248 bus_write_4(base->sc_mem, FMBM_REBM, reg); 249 reg = howmany(FMAN_PARSE_RESULT_OFF, 0x10) << RICP_ICIOF_S; 250 reg |= howmany(sizeof(struct fman_internal_context), 0x10); 251 bus_write_4(base->sc_mem, FMBM_RICP, reg); 252 253 bus_write_4(base->sc_mem, FMBM_RFNE, NIA_ENG_HWP); 254 bus_write_4(base->sc_mem, FMBM_RFSDM, FM_FD_ERR_DIS); 255 bus_write_4(base->sc_mem, FMBM_RFSEM, BMI_RX_ERR & ~FM_FD_ERR_DIS); 256 257 return (0); 258 } 259 260 static int 261 fman_port_rx_init_hwp(struct fman_port_rx_softc *sc) 262 { 263 struct fman_port_softc *base = &sc->sc_base; 264 int i; 265 266 bus_write_4(base->sc_mem, HWP_PCAC, HWP_PCAC_PSTOP); 267 for (i = 0; i < 100 && 268 (bus_read_4(base->sc_mem, HWP_PCAC) & HWP_HXS_PCAC_PSTAT) != 0; 269 i++) { 270 DELAY(10); 271 } 272 if (i == 100) { 273 device_printf(base->sc_dev, "Timeout stopping HW parser\n"); 274 return (ENXIO); 275 } 276 277 for (i = 0; i < HWP_HXS_COUNT; i++) { 278 bus_write_4(base->sc_mem, HWP_HXS_SSA(i), 0); 279 bus_write_4(base->sc_mem, HWP_HXS_LCV(i), 0xffffffff); 280 } 281 bus_write_4(base->sc_mem, HWP_HXS_SSA(HWP_HXS_TCP), HXS_SH_PAD_REM); 282 bus_write_4(base->sc_mem, HWP_HXS_SSA(HWP_HXS_UDP), HXS_SH_PAD_REM); 283 284 bus_write_4(base->sc_mem, HWP_PCAC, 0); 285 return (0); 286 } 287 288 static int 289 fman_port_rx_init(device_t dev) 290 { 291 struct fman_port_rx_softc *sc = device_get_softc(dev); 292 struct fman_port_softc *base = &sc->sc_base; 293 struct fman_port_init_params params; 294 int err; 295 296 params.port_id = base->sc_port_id; 297 params.is_rx_port = true; 298 params.num_tasks = base->sc_tasks.num; 299 params.extra_tasks = base->sc_tasks.extra; 300 params.open_dmas = base->sc_open_dmas.num; 301 params.extra_dmas = base->sc_open_dmas.extra; 302 params.fifo_size = base->sc_fifo_bufs.num; 303 params.extra_fifo_size = base->sc_fifo_bufs.extra; 304 params.max_frame_length = base->sc_max_frame_length; 305 params.deq_pipeline_size = 0; 306 307 /* TODO: verify_size_of_fifo() from Linux driver */ 308 err = FMAN_SET_PORT_PARAMS(device_get_parent(dev), ¶ms); 309 if (err != 0) 310 return (err); 311 312 err = fman_port_rx_init_bmi(sc); 313 if (err == 0) 314 err = fman_port_rx_init_hwp(sc); 315 if (err != 0) 316 return (err); 317 318 bus_write_4(base->sc_mem, FMQM_PNEN, 319 NIA_ENG_BMI | NIA_BMI_AC_RELEASE); 320 321 /* TODO: keygen here */ 322 return (0); 323 } 324 325 static int 326 fman_port_rx_disable(device_t dev) 327 { 328 struct fman_port_rx_softc *sc = device_get_softc(dev); 329 struct fman_port_softc *base = &sc->sc_base; 330 uint32_t reg; 331 int count; 332 333 reg = bus_read_4(base->sc_mem, FMBM_RCFG); 334 bus_write_4(base->sc_mem, FMBM_RCFG, reg & ~BMI_PORT_CFG_EN); 335 for (count = 0; count < 100; count++) { 336 DELAY(10); 337 reg = bus_read_4(base->sc_mem, FMBM_RST); 338 if (!(reg & PNS_DEQ_FD_BSY)) 339 break; 340 } 341 if (count == 100) 342 device_printf(base->sc_dev, "Timeout stopping BMI\n"); 343 344 return (0); 345 } 346 347 static int 348 fman_port_rx_enable(device_t dev) 349 { 350 struct fman_port_rx_softc *sc = device_get_softc(dev); 351 struct fman_port_softc *base = &sc->sc_base; 352 uint32_t reg; 353 354 reg = bus_read_4(base->sc_mem, FMQM_PNC); 355 bus_write_4(base->sc_mem, FMQM_PNC, reg | PNC_EN | PNC_STEN); 356 357 reg = bus_read_4(base->sc_mem, FMBM_RCFG); 358 bus_write_4(base->sc_mem, FMBM_RCFG, reg | BMI_PORT_CFG_EN); 359 360 bus_write_4(base->sc_mem, FMBM_RSTC, RSTC_EN); 361 362 return (0); 363 } 364 365 void 366 fman_port_rx_use_kg(device_t dev, bool enable) 367 { 368 struct fman_port_rx_softc *sc = device_get_softc(dev); 369 370 bus_write_4(sc->sc_base.sc_mem, FMBM_RFPNE, 371 enable ? NIA_ENG_HWK : 372 (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)); 373 } 374 375 static device_method_t fman_port_rx_methods[] = { 376 DEVMETHOD(device_probe, fman_port_rx_probe), 377 DEVMETHOD(device_attach, fman_port_rx_attach), 378 DEVMETHOD(device_detach, fman_port_rx_detach), 379 380 DEVMETHOD(fman_port_config, fman_port_rx_config), 381 DEVMETHOD(fman_port_init, fman_port_rx_init), 382 DEVMETHOD(fman_port_enable, fman_port_rx_enable), 383 DEVMETHOD(fman_port_disable, fman_port_rx_disable), 384 385 DEVMETHOD_END 386 }; 387 388 DEFINE_CLASS_0(fman_port_rx, fman_port_rx_driver, fman_port_rx_methods, 389 sizeof(struct fman_port_rx_softc)); 390 EARLY_DRIVER_MODULE(fman_port_rx, fman, fman_port_rx_driver, 0, 0, 391 BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE); 392