xref: /freebsd/sys/dev/dpaa/fman_port.c (revision 7a40b8a89e7da2a7e8d8e132bc37885b22e9bfb1)
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), &params);
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