1 /*
2 * Copyright (c) 2026 Justin Hibbits
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7 #include <sys/param.h>
8 #include <sys/bus.h>
9 #include <sys/kernel.h>
10 #include <sys/module.h>
11 #include <dev/ofw/ofw_bus_subr.h>
12 #include <machine/bus.h>
13 #include "fman.h"
14 #include "fman_parser.h"
15 #include "fman_port.h"
16 #include "fman_if.h"
17 #include "fman_port_if.h"
18
19 struct fman_port_rsrc {
20 uint32_t num;
21 uint32_t extra;
22 };
23
24 #define MAX_BM_POOLS 64
25 struct fman_port_softc {
26 device_t sc_dev;
27 struct resource *sc_mem;
28 int sc_port_id;
29 int sc_port_speed;
30 int sc_port_type;
31
32 int sc_revision_major;
33 int sc_revision_minor;
34
35 int sc_max_frame_length;
36 int sc_bm_max_pools;
37 int sc_max_port_fifo_size;
38 int sc_qman_channel_id;
39
40 int sc_deq_byte_count;
41 int sc_deq_high_priority;
42 int sc_tx_deq_pipeline_depth;
43
44 int sc_default_fqid;
45 int sc_err_fqid;
46 int pcd_base_fqid;
47 int pcd_fqs_count;
48
49 int sc_max_ext_portals;
50 int sc_max_sub_portals;
51
52 struct fman_port_rsrc sc_open_dmas;
53 struct fman_port_rsrc sc_tasks;
54 struct fman_port_rsrc sc_fifo_bufs;
55
56 struct fman_port_buffer_pool sc_bpools[FMAN_PORT_MAX_POOLS];
57 };
58
59 #define TX_10G_PORT_BASE 0x30
60 #define RX_10G_PORT_BASE 0x10
61
62 #define FMAN_PORT_TYPE_TX 0
63 #define FMAN_PORT_TYPE_RX 1
64
65 #define PORT_RX 0x01
66 #define PORT_TX 0x02
67 #define PORT_V3 0x04
68
69 #define FMBM_RCFG 0x000
70 #define BMI_PORT_CFG_EN 0x80000000
71 #define FMBM_RST 0x004
72 #define FMBM_RDA 0x008
73 #define RDA_WOPT 0x00100000
74 #define FMBM_RFP 0x00c
75 #define FMBM_RFED 0x010
76 #define BMI_RX_FRAME_END_CUT_SHIFT 16
77 #define FMBM_RICP 0x014 /* Counts are units of 16 bytes */
78 #define RICP_ICEOF_M 0x001f0000
79 #define RICP_ICEOF_S 16
80 #define RICP_ICIOF_M 0x00000f00
81 #define RICP_ICIOF_S 8
82 #define RICP_ICSZ_S 0x0000001f
83 #define FMBM_RIM 0x018
84 #define FMBM_REBM 0x01c
85 #define REBM_BSM_M 0x01ff0000
86 #define REBM_BSM_S 16
87 #define REBM_BEM_M 0x000001ff
88 #define FMBM_RFNE 0x020
89 #define FMBM_RFCA 0x024
90 #define RFCA_OR 0x80000000
91 #define RFCA_COLOR 0x0c000000
92 #define RFCA_SYNC 0x03000000
93 #define RFCA_SYNC_REQ 0x02000000
94 #define RFCA_MR 0x003f0000
95 #define RFCA_MR_DEF 0x003c0000
96 #define FMBM_RFPNE 0x028
97 #define FMBM_RETH 0x038
98 #define RETH_ETHE 0x80000000 /* Excessive Threshold Enable */
99 #define FMBM_RFQID 0x060
100 #define FMBM_REFQID 0x064
101 #define FMBM_RFSDM 0x068
102 #define FMBM_RFSEM 0x06c
103 #define FMBM_RFENE 0x070
104 #define FMBM_REBMPI(i) (0x100 + (4 * (i)))
105 #define REBMPI_VAL 0x80000000
106 #define REBMPI_ACE 0x40000000
107 #define REBMPI_BPID_S 16
108 #define FMBM_RSTC 0x0200
109 #define RSTC_EN 0x80000000
110
111 #define FMBM_TCFG 0x000
112 #define FMBM_TST 0x004
113 #define FMBM_TDA 0x008
114 #define FMBM_TFP 0x00c
115 #define BMI_FIFO_PIPELINE_DEPTH_SHIFT 12
116 #define FMBM_TFED 0x010
117 #define FMBM_TICP 0x014
118 #define TICP_ICEOF_M 0x001f0000
119 #define TICP_ICEOF_S 16
120 #define TICP_ICIOF_M 0x00000f00
121 #define TICP_ICIOF_S 8
122 #define TICP_ICSZ_S 0x0000001f
123 #define FMBM_TFDNE 0x018
124 #define FMBM_TFCA 0x01c
125 #define TFCA_MR_DEF 0
126 #define TFCA_ATTR_ORDER 0x80000000
127 #define FMBM_TCFQID 0x020
128 #define FMBM_TEFQID 0x024
129 #define FMBM_TFENE 0x028
130 #define FMBM_TFNE 0x070
131 #define TFNE_EBD 0x80000000
132
133 #define FMQM_PNC 0x400
134 #define PNC_EN 0x80000000
135 #define PNC_STEN 0x80000000
136 #define FMQM_PNS 0x404
137 #define PNS_DEQ_FD_BSY 0x20000000
138 #define FMQM_PNEN 0x41c
139 #define FMQM_PNDN 0x42c
140 #define FMQM_PNDC 0x430
141 #define QMI_DEQ_CFG_PRI 0x80000000
142 #define QMI_DEQ_CFG_TYPE1 0x10000000
143 #define QMI_DEQ_CFG_TYPE2 0x20000000
144 #define QMI_DEQ_CFG_TYPE3 0x30000000
145 #define QMI_DEQ_CFG_PREFETCH_PARTIAL 0x01000000
146 #define QMI_DEQ_CFG_PREFETCH_FULL 0x03000000
147 #define QMI_DEQ_CFG_SP_MASK 0xf
148 #define QMI_DEQ_CFG_SP_SHIFT 20
149
150 #define HWP_PCAC 0xbf8
151 #define HWP_PCAC_PSTOP 0x00000001
152 #define HWP_HXS_PCAC_PSTAT 0x00000100
153 #define HWP_HXS_SSA(x) (0x800 + x * 2 * sizeof(uint32_t))
154 #define HWP_HXS_LCV(x) (0x800 + (x * 2 + 1) * sizeof(uint32_t))
155 #define HWP_HXS_TCP 0xA
156 #define HWP_HXS_UDP 0xB
157 #define HXS_SH_PAD_REM 0x80000000
158 #define HWP_HXS_COUNT 16
159
160 #define PORT_MAX_FRAME_LENGTH 9600
161
162 #define NIA_ORDER_RESTORE 0x00800000
163 #define NIA_ENG_BMI 0x00500000
164 #define NIA_ENG_QMI_DEQ 0x00580000
165 #define NIA_ENG_QMI_ENQ 0x00540000
166 #define NIA_ENG_HWP 0x00440000
167 #define NIA_ENG_HWK 0x00480000
168 #define NIA_BMI_AC_TX_RELEASE 0x000002c0
169 #define NIA_BMI_AC_TX 0x00000274
170 #define NIA_BMI_AC_RELEASE 0x000000c0
171 #define NIA_BMI_AC_ENQ_FRAME 0x00000002
172 #define NIA_BMI_AC_FETCH_ALLFRAME 0x0000020c
173
174 #define BMI_RX_ERR (FM_FD_ERR_DMA | FM_FD_ERR_FPE | \
175 FM_FD_ERR_FSE | FM_FD_ERR_DIS | \
176 FM_FD_ERR_EOF | FM_FD_ERR_NSS | \
177 FM_FD_ERR_KSO | FM_FD_ERR_IPP | \
178 FM_FD_ERR_PTE | FM_FD_ERR_PHE | \
179 FM_FD_ERR_BLE)
180
181 /* Default configurations */
182 #define DEFAULT_RX_CUT_END_BYTES 4
183
184 static struct ofw_compat_data compats[] = {
185 { "fsl,fman-v2-port-rx", PORT_RX },
186 { "fsl,fman-v2-port-tx", PORT_TX },
187 { "fsl,fman-v3-port-rx", PORT_V3 | PORT_RX },
188 { "fsl,fman-v3-port-tx", PORT_V3 | PORT_TX },
189 { NULL, 0 }
190 };
191
192 static int
fman_port_probe(device_t dev)193 fman_port_probe(device_t dev)
194 {
195 if (ofw_bus_search_compatible(dev, compats)->ocd_str == NULL)
196 return (ENXIO);
197
198 device_set_desc(dev, "FMan port");
199
200 return (BUS_PROBE_DEFAULT);
201 }
202
203 static int
fman_port_attach(device_t dev)204 fman_port_attach(device_t dev)
205 {
206 struct fman_port_softc *sc;
207 phandle_t node;
208 pcell_t cell;
209 uintptr_t compat_data =
210 ofw_bus_search_compatible(dev, compats)->ocd_data;
211 int port_speed = 1000;
212 int port_type;
213
214 sc = device_get_softc(dev);
215 sc->sc_dev = dev;
216
217 node = ofw_bus_get_node(dev);
218 if (OF_getencprop(node, "cell-index", &cell, sizeof(cell)) < 0) {
219 device_printf(dev, "No cell-index property");
220 return (ENXIO);
221 }
222
223 sc->sc_port_id = cell;
224
225 sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 0,
226 RF_ACTIVE | RF_SHAREABLE);
227
228 if (sc->sc_mem == NULL) {
229 device_printf(dev, "failed to allocate MMIO");
230 return (ENXIO);
231 }
232
233 FMAN_GET_REVISION(device_get_parent(dev),
234 &sc->sc_revision_major, &sc->sc_revision_minor);
235
236 if ((compat_data & PORT_TX) == PORT_TX)
237 port_type = FMAN_PORT_TYPE_TX;
238 else
239 port_type = FMAN_PORT_TYPE_RX;
240
241 if ((compat_data & PORT_V3) == PORT_V3) {
242 if (OF_hasprop(node, "fsl,fman-10g-port"))
243 port_speed = 10000;
244 } else {
245 if ((compat_data & PORT_TX) &&
246 sc->sc_port_id > TX_10G_PORT_BASE)
247 port_speed = 10000;
248 else if ((compat_data & PORT_RX) &&
249 sc->sc_port_id > RX_10G_PORT_BASE)
250 port_speed = 10000;
251 }
252
253 if (sc->sc_port_speed == 10000) {
254 sc->sc_deq_high_priority = true;
255 sc->sc_deq_byte_count = 0x1400;
256 } else {
257 sc->sc_deq_high_priority = false;
258 sc->sc_deq_byte_count = 0x0400;
259 }
260
261 sc->sc_port_type = port_type;
262 sc->sc_port_speed = port_speed;
263
264 sc->sc_bm_max_pools = MAX_BM_POOLS;
265 sc->sc_max_frame_length = PORT_MAX_FRAME_LENGTH;
266
267 if (port_type == FMAN_PORT_TYPE_TX)
268 sc->sc_qman_channel_id =
269 FMAN_GET_QMAN_CHANNEL_ID(device_get_parent(dev),
270 sc->sc_port_id);
271
272 OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev);
273
274 return (0);
275 }
276
277 static int
fman_port_detach(device_t dev)278 fman_port_detach(device_t dev)
279 {
280 struct fman_port_softc *sc = device_get_softc(dev);
281
282 if (sc->sc_mem != NULL)
283 bus_release_resource(dev, sc->sc_mem);
284
285 return (0);
286 }
287
288 static int
fman_port_config(device_t dev,struct fman_port_params * params)289 fman_port_config(device_t dev, struct fman_port_params *params)
290 {
291 struct fman_port_softc *sc = device_get_softc(dev);
292
293 sc->sc_default_fqid = params->dflt_fqid;
294 sc->sc_err_fqid = params->err_fqid;
295
296 sc->sc_max_port_fifo_size =
297 FMAN_GET_BMI_MAX_FIFO_SIZE(device_get_parent(dev));
298 switch (sc->sc_revision_major) {
299 case 2:
300 case 3:
301 sc->sc_max_ext_portals = 4;
302 sc->sc_max_sub_portals = 12;
303 break;
304 case 6:
305 sc->sc_max_ext_portals = 8;
306 sc->sc_max_sub_portals = 16;
307 break;
308 }
309 if (sc->sc_revision_major >= 6 &&
310 sc->sc_port_type == FMAN_PORT_TYPE_TX && sc->sc_port_speed == 1000)
311 /* Errata A005127 workaround */
312 bus_write_4(sc->sc_mem, FMBM_TFP, 0x00001013);
313
314 sc->sc_tasks.extra = 0;
315
316 switch (sc->sc_port_speed) {
317 case 10000:
318 if (sc->sc_revision_major < 6) {
319 sc->sc_tasks.num = 16;
320 if (sc->sc_port_type == FMAN_PORT_TYPE_RX)
321 sc->sc_tasks.extra = 8;
322 } else
323 sc->sc_tasks.num = 14;
324 break;
325 case 1000:
326 if (sc->sc_revision_major >= 6)
327 sc->sc_tasks.num = 4;
328 else {
329 sc->sc_tasks.num = 3;
330 if (sc->sc_port_type == FMAN_PORT_TYPE_RX)
331 sc->sc_tasks.extra = 2;
332 }
333 break;
334 default:
335 sc->sc_tasks.num = 0;
336 break;
337 }
338
339 /* Open DMAs */
340 if (sc->sc_revision_major >= 6) {
341 sc->sc_open_dmas.extra = 0;
342 if (sc->sc_port_speed == 10000) {
343 if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
344 sc->sc_open_dmas.num = 12;
345 else
346 sc->sc_open_dmas.num = 8;
347 } else {
348 if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
349 sc->sc_open_dmas.num = 3;
350 else
351 sc->sc_open_dmas.num = 2;
352 }
353 } else {
354 if (sc->sc_port_speed == 10000) {
355 sc->sc_open_dmas.num = 8;
356 sc->sc_open_dmas.num = 8;
357 } else {
358 sc->sc_open_dmas.num = 1;
359 sc->sc_open_dmas.extra = 1;
360 }
361 }
362
363 /* FIFO bufs */
364 if (sc->sc_revision_major >= 6) {
365 if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
366 if (sc->sc_port_speed == 10000)
367 sc->sc_fifo_bufs.num = 64;
368 else
369 sc->sc_fifo_bufs.num = 50;
370 else
371 if (sc->sc_port_speed == 10000)
372 sc->sc_fifo_bufs.num = 96;
373 else
374 sc->sc_fifo_bufs.num = 50;
375 } else {
376 if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
377 if (sc->sc_port_speed == 10000)
378 sc->sc_fifo_bufs.num = 48;
379 else
380 sc->sc_fifo_bufs.num = 44;
381 else
382 if (sc->sc_port_speed == 10000)
383 sc->sc_fifo_bufs.num = 48;
384 else
385 sc->sc_fifo_bufs.num = 45;
386 }
387
388 sc->sc_fifo_bufs.extra = 0;
389 sc->sc_fifo_bufs.num *= FMAN_BMI_FIFO_UNITS;
390
391 if (sc->sc_port_type == FMAN_PORT_TYPE_RX)
392 for (int i = 0; i < params->rx_params.num_pools; i++)
393 sc->sc_bpools[i] = params->rx_params.bpools[i];
394
395 /* TODO: buf_margins? See fman_sp_build_buffer_struct */
396
397 return (0);
398 }
399
400 static int
fman_port_init_bmi_rx(struct fman_port_softc * sc)401 fman_port_init_bmi_rx(struct fman_port_softc *sc)
402 {
403 uint32_t reg;
404
405 /* TODO: Sort the buffer pool list. */
406 /* TODO: Backup pools */
407 /* TODO: Depletion mode */
408 for (int i = 0; i < FMAN_PORT_MAX_POOLS; i++) {
409 /* Initialize the external pool info */
410 if (sc->sc_bpools[i].size != 0) {
411 bus_write_4(sc->sc_mem, FMBM_REBMPI(i),
412 REBMPI_VAL | REBMPI_ACE |
413 (sc->sc_bpools[i].bpid << REBMPI_BPID_S) |
414 sc->sc_bpools[i].size);
415 } else
416 /* Mark invalid if zero */
417 bus_write_4(sc->sc_mem, FMBM_REBMPI(i), 0);
418 }
419
420 bus_write_4(sc->sc_mem, FMBM_RDA, RDA_WOPT);
421
422 bus_write_4(sc->sc_mem, FMBM_RFCA,
423 RFCA_OR | RFCA_SYNC_REQ | RFCA_MR_DEF);
424
425 bus_write_4(sc->sc_mem, FMBM_RFPNE,
426 NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME);
427 bus_write_4(sc->sc_mem, FMBM_RFENE,
428 NIA_ENG_QMI_ENQ | NIA_ORDER_RESTORE);
429
430 bus_write_4(sc->sc_mem, FMBM_RFQID, sc->sc_default_fqid);
431 bus_write_4(sc->sc_mem, FMBM_REFQID, sc->sc_err_fqid);
432
433 if (sc->sc_revision_major < 6)
434 bus_write_4(sc->sc_mem, FMBM_RETH, RETH_ETHE);
435
436 /* Errata A006320 makes CFED field bad */
437 if (sc->sc_revision_major == 6 && (sc->sc_revision_minor == 0))
438 /* These are under errata A006320 */;
439 else
440 bus_write_4(sc->sc_mem, FMBM_RFED,
441 DEFAULT_RX_CUT_END_BYTES << BMI_RX_FRAME_END_CUT_SHIFT);
442
443 /* Insert internal context ahead of the frame */
444 reg = sizeof(struct fman_internal_context) << REBM_BSM_S;
445 bus_write_4(sc->sc_mem, FMBM_REBM, reg);
446 reg = howmany(FMAN_PARSE_RESULT_OFF, 0x10) << RICP_ICIOF_S;
447 reg |= howmany(sizeof(struct fman_internal_context), 0x10);
448 bus_write_4(sc->sc_mem, FMBM_RICP, reg);
449
450 bus_write_4(sc->sc_mem, FMBM_RFNE, NIA_ENG_HWP);
451 bus_write_4(sc->sc_mem, FMBM_RFSDM, FM_FD_ERR_DIS);
452 bus_write_4(sc->sc_mem, FMBM_RFSEM, BMI_RX_ERR & ~FM_FD_ERR_DIS);
453
454 return (0);
455 }
456
457 static int
fman_port_init_bmi_tx(struct fman_port_softc * sc)458 fman_port_init_bmi_tx(struct fman_port_softc *sc)
459 {
460 uint32_t reg;
461 int depth;
462
463 bus_write_4(sc->sc_mem, FMBM_TCFG, 0);
464 bus_write_4(sc->sc_mem, FMBM_TDA, 0);
465 bus_write_4(sc->sc_mem, FMBM_TFED, 0);
466 if (sc->sc_port_speed == 10000)
467 depth = 4;
468 else if (sc->sc_revision_major >= 6)
469 depth = 2;
470 else
471 depth = 1;
472 sc->sc_tx_deq_pipeline_depth = depth;
473 reg = ((depth - 1) << BMI_FIFO_PIPELINE_DEPTH_SHIFT) | 0x13;
474 bus_write_4(sc->sc_mem, FMBM_TFP, reg);
475
476 /* Default color: green */
477 bus_write_4(sc->sc_mem, FMBM_TFCA,
478 TFCA_MR_DEF | TFCA_ATTR_ORDER);
479
480 bus_write_4(sc->sc_mem, FMBM_TFDNE, NIA_ENG_QMI_DEQ);
481 bus_write_4(sc->sc_mem, FMBM_TFENE,
482 NIA_ENG_QMI_ENQ | NIA_ORDER_RESTORE);
483
484 /* Insert internal context ahead of the frame */
485 reg = howmany(FMAN_PARSE_RESULT_OFF, 0x10) << TICP_ICIOF_S;
486 reg |= howmany(sizeof(struct fman_internal_context), 0x10);
487 bus_write_4(sc->sc_mem, FMBM_TICP, reg);
488
489 if (sc->sc_revision_major >= 6)
490 bus_write_4(sc->sc_mem, FMBM_TFNE,
491 (sc->sc_default_fqid == 0 ? TFNE_EBD : 0) |
492 NIA_BMI_AC_FETCH_ALLFRAME);
493 bus_write_4(sc->sc_mem, FMBM_TCFQID, sc->sc_default_fqid);
494 bus_write_4(sc->sc_mem, FMBM_TEFQID, sc->sc_err_fqid);
495
496 return (0);
497 }
498
499 static int
fman_port_init_hwp(struct fman_port_softc * sc)500 fman_port_init_hwp(struct fman_port_softc *sc)
501 {
502 int i;
503
504 /* Stop the parser so we can initialize it for our uses */
505 bus_write_4(sc->sc_mem, HWP_PCAC, HWP_PCAC_PSTOP);
506
507 for (i = 0; i < 100 &&
508 (bus_read_4(sc->sc_mem, HWP_PCAC) & HWP_HXS_PCAC_PSTAT) != 0; i++) {
509 DELAY(10);
510 }
511 if (i == 100) {
512 device_printf(sc->sc_dev, "Timeout stopping HW parser\n");
513 return (ENXIO);
514 }
515
516 /* set the parser examination config */
517 for (i = 0; i < HWP_HXS_COUNT; i++) {
518 bus_write_4(sc->sc_mem, HWP_HXS_SSA(i), 0);
519 bus_write_4(sc->sc_mem, HWP_HXS_LCV(i), 0xffffffff);
520 }
521 bus_write_4(sc->sc_mem, HWP_HXS_SSA(HWP_HXS_TCP), HXS_SH_PAD_REM);
522 bus_write_4(sc->sc_mem, HWP_HXS_SSA(HWP_HXS_UDP), HXS_SH_PAD_REM);
523
524 /* Re-enable the parser */
525 bus_write_4(sc->sc_mem, HWP_PCAC, 0);
526
527 return (0);
528 }
529
530 static int
fman_port_init_qmi(struct fman_port_softc * sc)531 fman_port_init_qmi(struct fman_port_softc *sc)
532 {
533 uint32_t reg;
534
535 if (sc->sc_port_type == FMAN_PORT_TYPE_RX) {
536 bus_write_4(sc->sc_mem, FMQM_PNEN,
537 NIA_ENG_BMI | NIA_BMI_AC_RELEASE);
538 return (0);
539 }
540
541 /* TX port */
542 bus_write_4(sc->sc_mem, FMQM_PNDN,
543 NIA_ENG_BMI | NIA_BMI_AC_TX);
544 /* TX port */
545 bus_write_4(sc->sc_mem, FMQM_PNEN,
546 NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE);
547
548 reg = 0;
549
550 if (sc->sc_deq_high_priority)
551 reg |= QMI_DEQ_CFG_PRI;
552
553 reg |= QMI_DEQ_CFG_TYPE1;
554 reg |= QMI_DEQ_CFG_PREFETCH_FULL;
555 reg |= (sc->sc_qman_channel_id & QMI_DEQ_CFG_SP_MASK) << QMI_DEQ_CFG_SP_SHIFT;
556 reg |= sc->sc_deq_byte_count;
557 bus_write_4(sc->sc_mem, FMQM_PNDC, reg);
558
559 return (0);
560 }
561
562 static int
fman_port_init(device_t dev)563 fman_port_init(device_t dev)
564 {
565 struct fman_port_init_params params;
566 struct fman_port_softc *sc = device_get_softc(dev);
567 int err;
568
569 if (sc->sc_port_type == FMAN_PORT_TYPE_RX) {
570 /* Set up RX buffers and fifo */
571 }
572 params.port_id = sc->sc_port_id;
573 params.is_rx_port = (sc->sc_port_type == FMAN_PORT_TYPE_RX);
574 params.num_tasks = sc->sc_tasks.num;
575 params.extra_tasks = sc->sc_tasks.extra;
576 params.open_dmas = sc->sc_open_dmas.num;
577 params.extra_dmas = sc->sc_open_dmas.extra;
578 params.fifo_size = sc->sc_fifo_bufs.num;
579 params.extra_fifo_size = sc->sc_fifo_bufs.extra;
580 params.max_frame_length = sc->sc_max_frame_length;
581 params.deq_pipeline_size = sc->sc_tx_deq_pipeline_depth;
582
583 /* TODO: verify_size_of_fifo() from Linux driver */
584 err = FMAN_SET_PORT_PARAMS(device_get_parent(dev), ¶ms);
585
586 if (err != 0)
587 return (err);
588
589 if (sc->sc_port_type == FMAN_PORT_TYPE_TX)
590 err = fman_port_init_bmi_tx(sc);
591 else {
592 err = fman_port_init_bmi_rx(sc);
593 if (err == 0)
594 fman_port_init_hwp(sc);
595 }
596
597 if (err != 0)
598 return (err);
599
600 err = fman_port_init_qmi(sc);
601
602 /* TODO: keygen here */
603
604 return (err);
605 }
606
607 static int
fman_port_disable(device_t dev)608 fman_port_disable(device_t dev)
609 {
610 struct fman_port_softc *sc;
611 uint32_t reg;
612 int count;
613
614 sc = device_get_softc(dev);
615
616 switch (sc->sc_port_type) {
617 case FMAN_PORT_TYPE_TX:
618 reg = bus_read_4(sc->sc_mem, FMQM_PNC);
619 bus_write_4(sc->sc_mem, FMQM_PNC, reg & ~PNC_EN);
620 for (count = 0; count < 100; count++) {
621 DELAY(10);
622 reg = bus_read_4(sc->sc_mem, FMQM_PNS);
623 if (!(reg & PNS_DEQ_FD_BSY))
624 break;
625 }
626 if (count == 100)
627 device_printf(sc->sc_dev, "Timeout stopping QMI\n");
628 reg = bus_read_4(sc->sc_mem, FMBM_TCFG);
629 bus_write_4(sc->sc_mem, FMBM_TCFG, reg & ~BMI_PORT_CFG_EN);
630 for (count = 0; count < 100; count++) {
631 DELAY(10);
632 reg = bus_read_4(sc->sc_mem, FMBM_TST);
633 if (!(reg & PNS_DEQ_FD_BSY))
634 break;
635 }
636 if (count == 100)
637 device_printf(sc->sc_dev, "Timeout stopping BMI");
638 break;
639 case FMAN_PORT_TYPE_RX:
640 reg = bus_read_4(sc->sc_mem, FMBM_RCFG);
641 bus_write_4(sc->sc_mem, FMBM_RCFG, reg & ~BMI_PORT_CFG_EN);
642 for (count = 0; count < 100; count++) {
643 DELAY(10);
644 reg = bus_read_4(sc->sc_mem, FMBM_RST);
645 if (!(reg & PNS_DEQ_FD_BSY))
646 break;
647 }
648 if (count == 100)
649 device_printf(sc->sc_dev, "Timeout stopping BMI");
650 break;
651 }
652
653 return (0);
654 }
655
656 static int
fman_port_enable(device_t dev)657 fman_port_enable(device_t dev)
658 {
659 struct fman_port_softc *sc;
660 uint32_t reg;
661
662 sc = device_get_softc(dev);
663 switch (sc->sc_port_type) {
664 case FMAN_PORT_TYPE_TX:
665 reg = bus_read_4(sc->sc_mem, FMQM_PNC);
666 bus_write_4(sc->sc_mem, FMQM_PNC, reg | PNC_EN | PNC_STEN);
667 reg = bus_read_4(sc->sc_mem, FMBM_TCFG);
668 bus_write_4(sc->sc_mem, FMBM_TCFG, reg | BMI_PORT_CFG_EN);
669 break;
670 case FMAN_PORT_TYPE_RX:
671 reg = bus_read_4(sc->sc_mem, FMBM_RCFG);
672 bus_write_4(sc->sc_mem, FMQM_PNC, reg | PNC_EN | PNC_STEN);
673 bus_write_4(sc->sc_mem, FMBM_RCFG, reg | BMI_PORT_CFG_EN);
674 bus_write_4(sc->sc_mem, FMBM_RSTC, RSTC_EN);
675 break;
676 }
677
678 return (0);
679 }
680
681 static device_method_t fman_port_methods[] = {
682 DEVMETHOD(device_probe, fman_port_probe),
683 DEVMETHOD(device_attach, fman_port_attach),
684 DEVMETHOD(device_detach, fman_port_detach),
685
686 DEVMETHOD(fman_port_config, fman_port_config),
687 DEVMETHOD(fman_port_init, fman_port_init),
688 DEVMETHOD(fman_port_enable, fman_port_enable),
689 DEVMETHOD(fman_port_disable, fman_port_disable),
690
691 DEVMETHOD_END
692 };
693
694 DEFINE_CLASS_0(fman_port, fman_port_driver, fman_port_methods,
695 sizeof(struct fman_port_softc));
696 EARLY_DRIVER_MODULE(fman_port, fman, fman_port_driver, 0, 0,
697 BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE);
698