xref: /freebsd/sys/dev/dpaa/fman_port_tx.c (revision 5d884fc07662760a2090928e98e51dc8162389a3)
1*5d884fc0SJustin Hibbits /*
2*5d884fc0SJustin Hibbits  * Copyright (c) 2026 Justin Hibbits
3*5d884fc0SJustin Hibbits  *
4*5d884fc0SJustin Hibbits  * SPDX-License-Identifier: BSD-2-Clause
5*5d884fc0SJustin Hibbits  *
6*5d884fc0SJustin Hibbits  * FMan TX port driver.
7*5d884fc0SJustin Hibbits  */
8*5d884fc0SJustin Hibbits 
9*5d884fc0SJustin Hibbits #include <sys/param.h>
10*5d884fc0SJustin Hibbits #include <sys/bus.h>
11*5d884fc0SJustin Hibbits #include <sys/kernel.h>
12*5d884fc0SJustin Hibbits #include <sys/module.h>
13*5d884fc0SJustin Hibbits 
14*5d884fc0SJustin Hibbits #include <dev/ofw/ofw_bus.h>
15*5d884fc0SJustin Hibbits #include <dev/ofw/ofw_bus_subr.h>
16*5d884fc0SJustin Hibbits #include <machine/bus.h>
17*5d884fc0SJustin Hibbits 
18*5d884fc0SJustin Hibbits #include "fman.h"
19*5d884fc0SJustin Hibbits #include "fman_parser.h"
20*5d884fc0SJustin Hibbits #include "fman_port.h"
21*5d884fc0SJustin Hibbits #include "fman_port_var.h"
22*5d884fc0SJustin Hibbits #include "fman_if.h"
23*5d884fc0SJustin Hibbits #include "fman_port_if.h"
24*5d884fc0SJustin Hibbits 
25*5d884fc0SJustin Hibbits #define	TX_10G_PORT_BASE	0x30
26*5d884fc0SJustin Hibbits 
27*5d884fc0SJustin Hibbits /* BMI Tx registers. */
28*5d884fc0SJustin Hibbits #define	FMBM_TCFG		0x000
29*5d884fc0SJustin Hibbits #define	FMBM_TST		0x004
30*5d884fc0SJustin Hibbits #define	FMBM_TDA		0x008
31*5d884fc0SJustin Hibbits #define	FMBM_TFP		0x00c
32*5d884fc0SJustin Hibbits #define	  BMI_FIFO_PIPELINE_DEPTH_SHIFT	12
33*5d884fc0SJustin Hibbits #define	FMBM_TFED		0x010
34*5d884fc0SJustin Hibbits #define	FMBM_TICP		0x014
35*5d884fc0SJustin Hibbits #define	  TICP_ICEOF_M		  0x001f0000
36*5d884fc0SJustin Hibbits #define	  TICP_ICEOF_S		  16
37*5d884fc0SJustin Hibbits #define	  TICP_ICIOF_M		  0x00000f00
38*5d884fc0SJustin Hibbits #define	  TICP_ICIOF_S		  8
39*5d884fc0SJustin Hibbits #define	  TICP_ICSZ_S		  0x0000001f
40*5d884fc0SJustin Hibbits #define	FMBM_TFDNE		0x018
41*5d884fc0SJustin Hibbits #define	FMBM_TFCA		0x01c
42*5d884fc0SJustin Hibbits #define	  TFCA_MR_DEF		  0
43*5d884fc0SJustin Hibbits #define	  TFCA_ATTR_ORDER	  0x80000000
44*5d884fc0SJustin Hibbits #define	FMBM_TCFQID		0x020
45*5d884fc0SJustin Hibbits #define	FMBM_TEFQID		0x024
46*5d884fc0SJustin Hibbits #define	FMBM_TFENE		0x028
47*5d884fc0SJustin Hibbits #define	FMBM_TFNE		0x070
48*5d884fc0SJustin Hibbits #define	  TFNE_EBD		  0x80000000
49*5d884fc0SJustin Hibbits 
50*5d884fc0SJustin Hibbits /* QMI dequeue-config (FMQM_PNDC) field layout: TX-only consumer. */
51*5d884fc0SJustin Hibbits #define	QMI_DEQ_CFG_PRI			0x80000000
52*5d884fc0SJustin Hibbits #define	QMI_DEQ_CFG_TYPE1		0x10000000
53*5d884fc0SJustin Hibbits #define	QMI_DEQ_CFG_TYPE2		0x20000000
54*5d884fc0SJustin Hibbits #define	QMI_DEQ_CFG_TYPE3		0x30000000
55*5d884fc0SJustin Hibbits #define	QMI_DEQ_CFG_PREFETCH_PARTIAL	0x01000000
56*5d884fc0SJustin Hibbits #define	QMI_DEQ_CFG_PREFETCH_FULL	0x03000000
57*5d884fc0SJustin Hibbits #define	QMI_DEQ_CFG_SP_MASK		0xf
58*5d884fc0SJustin Hibbits #define	QMI_DEQ_CFG_SP_SHIFT		20
59*5d884fc0SJustin Hibbits 
60*5d884fc0SJustin Hibbits struct fman_port_tx_softc {
61*5d884fc0SJustin Hibbits 	struct fman_port_softc sc_base;
62*5d884fc0SJustin Hibbits 
63*5d884fc0SJustin Hibbits 	int sc_deq_byte_count;
64*5d884fc0SJustin Hibbits 	int sc_deq_high_priority;
65*5d884fc0SJustin Hibbits 	int sc_tx_deq_pipeline_depth;
66*5d884fc0SJustin Hibbits 	int sc_qman_channel_id;
67*5d884fc0SJustin Hibbits };
68*5d884fc0SJustin Hibbits 
69*5d884fc0SJustin Hibbits static struct ofw_compat_data tx_compats[] = {
70*5d884fc0SJustin Hibbits 	{ "fsl,fman-v2-port-tx", 0 },
71*5d884fc0SJustin Hibbits 	{ "fsl,fman-v3-port-tx", PORT_V3 },
72*5d884fc0SJustin Hibbits 	{ NULL, 0 }
73*5d884fc0SJustin Hibbits };
74*5d884fc0SJustin Hibbits 
75*5d884fc0SJustin Hibbits static int
fman_port_tx_probe(device_t dev)76*5d884fc0SJustin Hibbits fman_port_tx_probe(device_t dev)
77*5d884fc0SJustin Hibbits {
78*5d884fc0SJustin Hibbits 
79*5d884fc0SJustin Hibbits 	if (ofw_bus_search_compatible(dev, tx_compats)->ocd_str == NULL)
80*5d884fc0SJustin Hibbits 		return (ENXIO);
81*5d884fc0SJustin Hibbits 
82*5d884fc0SJustin Hibbits 	device_set_desc(dev, "FMan TX port");
83*5d884fc0SJustin Hibbits 	return (BUS_PROBE_DEFAULT);
84*5d884fc0SJustin Hibbits }
85*5d884fc0SJustin Hibbits 
86*5d884fc0SJustin Hibbits static int
fman_port_tx_attach(device_t dev)87*5d884fc0SJustin Hibbits fman_port_tx_attach(device_t dev)
88*5d884fc0SJustin Hibbits {
89*5d884fc0SJustin Hibbits 	struct fman_port_tx_softc *sc;
90*5d884fc0SJustin Hibbits 	uintptr_t compat_data;
91*5d884fc0SJustin Hibbits 	int port_speed;
92*5d884fc0SJustin Hibbits 	int err;
93*5d884fc0SJustin Hibbits 
94*5d884fc0SJustin Hibbits 	sc = device_get_softc(dev);
95*5d884fc0SJustin Hibbits 	compat_data = ofw_bus_search_compatible(dev, tx_compats)->ocd_data;
96*5d884fc0SJustin Hibbits 
97*5d884fc0SJustin Hibbits 	port_speed = 1000;
98*5d884fc0SJustin Hibbits 	if ((compat_data & PORT_V3) == PORT_V3) {
99*5d884fc0SJustin Hibbits 		if (OF_hasprop(ofw_bus_get_node(dev), "fsl,fman-10g-port"))
100*5d884fc0SJustin Hibbits 			port_speed = 10000;
101*5d884fc0SJustin Hibbits 	} else {
102*5d884fc0SJustin Hibbits 		int cell = 0;
103*5d884fc0SJustin Hibbits 		OF_getencprop(ofw_bus_get_node(dev), "cell-index", &cell,
104*5d884fc0SJustin Hibbits 		    sizeof(cell));
105*5d884fc0SJustin Hibbits 		if (cell > TX_10G_PORT_BASE)
106*5d884fc0SJustin Hibbits 			port_speed = 10000;
107*5d884fc0SJustin Hibbits 	}
108*5d884fc0SJustin Hibbits 
109*5d884fc0SJustin Hibbits 	err = fman_port_attach_common(dev, &sc->sc_base, port_speed);
110*5d884fc0SJustin Hibbits 	if (err != 0)
111*5d884fc0SJustin Hibbits 		return (err);
112*5d884fc0SJustin Hibbits 
113*5d884fc0SJustin Hibbits 	if (port_speed == 10000) {
114*5d884fc0SJustin Hibbits 		sc->sc_deq_high_priority = true;
115*5d884fc0SJustin Hibbits 		sc->sc_deq_byte_count = 0x1400;
116*5d884fc0SJustin Hibbits 	} else {
117*5d884fc0SJustin Hibbits 		sc->sc_deq_high_priority = false;
118*5d884fc0SJustin Hibbits 		sc->sc_deq_byte_count = 0x0400;
119*5d884fc0SJustin Hibbits 	}
120*5d884fc0SJustin Hibbits 
121*5d884fc0SJustin Hibbits 	sc->sc_qman_channel_id = FMAN_GET_QMAN_CHANNEL_ID(
122*5d884fc0SJustin Hibbits 	    device_get_parent(dev), sc->sc_base.sc_port_id);
123*5d884fc0SJustin Hibbits 
124*5d884fc0SJustin Hibbits 	return (0);
125*5d884fc0SJustin Hibbits }
126*5d884fc0SJustin Hibbits 
127*5d884fc0SJustin Hibbits static int
fman_port_tx_detach(device_t dev)128*5d884fc0SJustin Hibbits fman_port_tx_detach(device_t dev)
129*5d884fc0SJustin Hibbits {
130*5d884fc0SJustin Hibbits 	struct fman_port_tx_softc *sc = device_get_softc(dev);
131*5d884fc0SJustin Hibbits 
132*5d884fc0SJustin Hibbits 	return (fman_port_detach_common(dev, &sc->sc_base));
133*5d884fc0SJustin Hibbits }
134*5d884fc0SJustin Hibbits 
135*5d884fc0SJustin Hibbits static int
fman_port_tx_config(device_t dev,struct fman_port_params * params)136*5d884fc0SJustin Hibbits fman_port_tx_config(device_t dev, struct fman_port_params *params)
137*5d884fc0SJustin Hibbits {
138*5d884fc0SJustin Hibbits 	struct fman_port_tx_softc *sc = device_get_softc(dev);
139*5d884fc0SJustin Hibbits 	struct fman_port_softc *base = &sc->sc_base;
140*5d884fc0SJustin Hibbits 
141*5d884fc0SJustin Hibbits 	fman_port_config_common(base, params);
142*5d884fc0SJustin Hibbits 
143*5d884fc0SJustin Hibbits 	if (base->sc_revision_major >= 6 && base->sc_port_speed == 1000)
144*5d884fc0SJustin Hibbits 		/* Errata A005127 workaround */
145*5d884fc0SJustin Hibbits 		bus_write_4(base->sc_mem, FMBM_TFP, 0x00001013);
146*5d884fc0SJustin Hibbits 
147*5d884fc0SJustin Hibbits 	base->sc_tasks.extra = 0;
148*5d884fc0SJustin Hibbits 	switch (base->sc_port_speed) {
149*5d884fc0SJustin Hibbits 	case 10000:
150*5d884fc0SJustin Hibbits 		base->sc_tasks.num = (base->sc_revision_major < 6) ? 16 : 14;
151*5d884fc0SJustin Hibbits 		break;
152*5d884fc0SJustin Hibbits 	case 1000:
153*5d884fc0SJustin Hibbits 		base->sc_tasks.num = (base->sc_revision_major >= 6) ? 4 : 3;
154*5d884fc0SJustin Hibbits 		break;
155*5d884fc0SJustin Hibbits 	default:
156*5d884fc0SJustin Hibbits 		base->sc_tasks.num = 0;
157*5d884fc0SJustin Hibbits 		break;
158*5d884fc0SJustin Hibbits 	}
159*5d884fc0SJustin Hibbits 
160*5d884fc0SJustin Hibbits 	if (base->sc_revision_major >= 6) {
161*5d884fc0SJustin Hibbits 		base->sc_open_dmas.extra = 0;
162*5d884fc0SJustin Hibbits 		base->sc_open_dmas.num =
163*5d884fc0SJustin Hibbits 		    (base->sc_port_speed == 10000) ? 12 : 3;
164*5d884fc0SJustin Hibbits 	} else if (base->sc_port_speed == 10000) {
165*5d884fc0SJustin Hibbits 		base->sc_open_dmas.num = 8;
166*5d884fc0SJustin Hibbits 		base->sc_open_dmas.extra = 8;
167*5d884fc0SJustin Hibbits 	} else {
168*5d884fc0SJustin Hibbits 		base->sc_open_dmas.num = 1;
169*5d884fc0SJustin Hibbits 		base->sc_open_dmas.extra = 1;
170*5d884fc0SJustin Hibbits 	}
171*5d884fc0SJustin Hibbits 
172*5d884fc0SJustin Hibbits 	if (base->sc_revision_major >= 6)
173*5d884fc0SJustin Hibbits 		base->sc_fifo_bufs.num =
174*5d884fc0SJustin Hibbits 		    (base->sc_port_speed == 10000) ? 64 : 50;
175*5d884fc0SJustin Hibbits 	else
176*5d884fc0SJustin Hibbits 		base->sc_fifo_bufs.num =
177*5d884fc0SJustin Hibbits 		    (base->sc_port_speed == 10000) ? 48 : 44;
178*5d884fc0SJustin Hibbits 	base->sc_fifo_bufs.extra = 0;
179*5d884fc0SJustin Hibbits 	base->sc_fifo_bufs.num *= FMAN_BMI_FIFO_UNITS;
180*5d884fc0SJustin Hibbits 
181*5d884fc0SJustin Hibbits 	/* TODO: buf_margins?  See fman_sp_build_buffer_struct */
182*5d884fc0SJustin Hibbits 	return (0);
183*5d884fc0SJustin Hibbits }
184*5d884fc0SJustin Hibbits 
185*5d884fc0SJustin Hibbits static int
fman_port_tx_init_bmi(struct fman_port_tx_softc * sc)186*5d884fc0SJustin Hibbits fman_port_tx_init_bmi(struct fman_port_tx_softc *sc)
187*5d884fc0SJustin Hibbits {
188*5d884fc0SJustin Hibbits 	struct fman_port_softc *base = &sc->sc_base;
189*5d884fc0SJustin Hibbits 	uint32_t reg;
190*5d884fc0SJustin Hibbits 	int depth;
191*5d884fc0SJustin Hibbits 
192*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMBM_TCFG, 0);
193*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMBM_TDA, 0);
194*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMBM_TFED, 0);
195*5d884fc0SJustin Hibbits 
196*5d884fc0SJustin Hibbits 	if (base->sc_port_speed == 10000)
197*5d884fc0SJustin Hibbits 		depth = 4;
198*5d884fc0SJustin Hibbits 	else if (base->sc_revision_major >= 6)
199*5d884fc0SJustin Hibbits 		depth = 2;
200*5d884fc0SJustin Hibbits 	else
201*5d884fc0SJustin Hibbits 		depth = 1;
202*5d884fc0SJustin Hibbits 	sc->sc_tx_deq_pipeline_depth = depth;
203*5d884fc0SJustin Hibbits 	reg = ((depth - 1) << BMI_FIFO_PIPELINE_DEPTH_SHIFT) | 0x13;
204*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMBM_TFP, reg);
205*5d884fc0SJustin Hibbits 
206*5d884fc0SJustin Hibbits 	/* Default color: green */
207*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMBM_TFCA, TFCA_MR_DEF | TFCA_ATTR_ORDER);
208*5d884fc0SJustin Hibbits 
209*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMBM_TFDNE, NIA_ENG_QMI_DEQ);
210*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMBM_TFENE,
211*5d884fc0SJustin Hibbits 	    NIA_ENG_QMI_ENQ | NIA_ORDER_RESTORE);
212*5d884fc0SJustin Hibbits 
213*5d884fc0SJustin Hibbits 	/* Insert internal context ahead of the frame */
214*5d884fc0SJustin Hibbits 	reg = howmany(FMAN_PARSE_RESULT_OFF, 0x10) << TICP_ICIOF_S;
215*5d884fc0SJustin Hibbits 	reg |= howmany(sizeof(struct fman_internal_context), 0x10);
216*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMBM_TICP, reg);
217*5d884fc0SJustin Hibbits 
218*5d884fc0SJustin Hibbits 	if (base->sc_revision_major >= 6)
219*5d884fc0SJustin Hibbits 		bus_write_4(base->sc_mem, FMBM_TFNE,
220*5d884fc0SJustin Hibbits 		    (base->sc_default_fqid == 0 ? TFNE_EBD : 0) |
221*5d884fc0SJustin Hibbits 		    NIA_BMI_AC_FETCH_ALLFRAME);
222*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMBM_TCFQID, base->sc_default_fqid);
223*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMBM_TEFQID, base->sc_err_fqid);
224*5d884fc0SJustin Hibbits 
225*5d884fc0SJustin Hibbits 	return (0);
226*5d884fc0SJustin Hibbits }
227*5d884fc0SJustin Hibbits 
228*5d884fc0SJustin Hibbits static int
fman_port_tx_init_qmi(struct fman_port_tx_softc * sc)229*5d884fc0SJustin Hibbits fman_port_tx_init_qmi(struct fman_port_tx_softc *sc)
230*5d884fc0SJustin Hibbits {
231*5d884fc0SJustin Hibbits 	struct fman_port_softc *base = &sc->sc_base;
232*5d884fc0SJustin Hibbits 	uint32_t reg;
233*5d884fc0SJustin Hibbits 
234*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMQM_PNDN, NIA_ENG_BMI | NIA_BMI_AC_TX);
235*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMQM_PNEN,
236*5d884fc0SJustin Hibbits 	    NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE);
237*5d884fc0SJustin Hibbits 
238*5d884fc0SJustin Hibbits 	reg = 0;
239*5d884fc0SJustin Hibbits 	if (sc->sc_deq_high_priority)
240*5d884fc0SJustin Hibbits 		reg |= QMI_DEQ_CFG_PRI;
241*5d884fc0SJustin Hibbits 	reg |= QMI_DEQ_CFG_TYPE1;
242*5d884fc0SJustin Hibbits 	reg |= QMI_DEQ_CFG_PREFETCH_FULL;
243*5d884fc0SJustin Hibbits 	reg |= (sc->sc_qman_channel_id & QMI_DEQ_CFG_SP_MASK) <<
244*5d884fc0SJustin Hibbits 	    QMI_DEQ_CFG_SP_SHIFT;
245*5d884fc0SJustin Hibbits 	reg |= sc->sc_deq_byte_count;
246*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMQM_PNDC, reg);
247*5d884fc0SJustin Hibbits 
248*5d884fc0SJustin Hibbits 	return (0);
249*5d884fc0SJustin Hibbits }
250*5d884fc0SJustin Hibbits 
251*5d884fc0SJustin Hibbits static int
fman_port_tx_init(device_t dev)252*5d884fc0SJustin Hibbits fman_port_tx_init(device_t dev)
253*5d884fc0SJustin Hibbits {
254*5d884fc0SJustin Hibbits 	struct fman_port_tx_softc *sc = device_get_softc(dev);
255*5d884fc0SJustin Hibbits 	struct fman_port_softc *base = &sc->sc_base;
256*5d884fc0SJustin Hibbits 	struct fman_port_init_params params;
257*5d884fc0SJustin Hibbits 	int err;
258*5d884fc0SJustin Hibbits 
259*5d884fc0SJustin Hibbits 	params.port_id = base->sc_port_id;
260*5d884fc0SJustin Hibbits 	params.is_rx_port = false;
261*5d884fc0SJustin Hibbits 	params.num_tasks = base->sc_tasks.num;
262*5d884fc0SJustin Hibbits 	params.extra_tasks = base->sc_tasks.extra;
263*5d884fc0SJustin Hibbits 	params.open_dmas = base->sc_open_dmas.num;
264*5d884fc0SJustin Hibbits 	params.extra_dmas = base->sc_open_dmas.extra;
265*5d884fc0SJustin Hibbits 	params.fifo_size = base->sc_fifo_bufs.num;
266*5d884fc0SJustin Hibbits 	params.extra_fifo_size = base->sc_fifo_bufs.extra;
267*5d884fc0SJustin Hibbits 	params.max_frame_length = base->sc_max_frame_length;
268*5d884fc0SJustin Hibbits 	params.deq_pipeline_size = sc->sc_tx_deq_pipeline_depth;
269*5d884fc0SJustin Hibbits 
270*5d884fc0SJustin Hibbits 	/* TODO: verify_size_of_fifo() from Linux driver */
271*5d884fc0SJustin Hibbits 	err = FMAN_SET_PORT_PARAMS(device_get_parent(dev), &params);
272*5d884fc0SJustin Hibbits 	if (err != 0)
273*5d884fc0SJustin Hibbits 		return (err);
274*5d884fc0SJustin Hibbits 
275*5d884fc0SJustin Hibbits 	err = fman_port_tx_init_bmi(sc);
276*5d884fc0SJustin Hibbits 	if (err != 0)
277*5d884fc0SJustin Hibbits 		return (err);
278*5d884fc0SJustin Hibbits 
279*5d884fc0SJustin Hibbits 	return (fman_port_tx_init_qmi(sc));
280*5d884fc0SJustin Hibbits }
281*5d884fc0SJustin Hibbits 
282*5d884fc0SJustin Hibbits static int
fman_port_tx_disable(device_t dev)283*5d884fc0SJustin Hibbits fman_port_tx_disable(device_t dev)
284*5d884fc0SJustin Hibbits {
285*5d884fc0SJustin Hibbits 	struct fman_port_tx_softc *sc = device_get_softc(dev);
286*5d884fc0SJustin Hibbits 	struct fman_port_softc *base = &sc->sc_base;
287*5d884fc0SJustin Hibbits 	uint32_t reg;
288*5d884fc0SJustin Hibbits 	int count;
289*5d884fc0SJustin Hibbits 
290*5d884fc0SJustin Hibbits 	reg = bus_read_4(base->sc_mem, FMQM_PNC);
291*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMQM_PNC, reg & ~PNC_EN);
292*5d884fc0SJustin Hibbits 	for (count = 0; count < 100; count++) {
293*5d884fc0SJustin Hibbits 		DELAY(10);
294*5d884fc0SJustin Hibbits 		reg = bus_read_4(base->sc_mem, FMQM_PNS);
295*5d884fc0SJustin Hibbits 		if (!(reg & PNS_DEQ_FD_BSY))
296*5d884fc0SJustin Hibbits 			break;
297*5d884fc0SJustin Hibbits 	}
298*5d884fc0SJustin Hibbits 	if (count == 100)
299*5d884fc0SJustin Hibbits 		device_printf(base->sc_dev, "Timeout stopping QMI\n");
300*5d884fc0SJustin Hibbits 
301*5d884fc0SJustin Hibbits 	reg = bus_read_4(base->sc_mem, FMBM_TCFG);
302*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMBM_TCFG, reg & ~BMI_PORT_CFG_EN);
303*5d884fc0SJustin Hibbits 	for (count = 0; count < 100; count++) {
304*5d884fc0SJustin Hibbits 		DELAY(10);
305*5d884fc0SJustin Hibbits 		reg = bus_read_4(base->sc_mem, FMBM_TST);
306*5d884fc0SJustin Hibbits 		if (!(reg & PNS_DEQ_FD_BSY))
307*5d884fc0SJustin Hibbits 			break;
308*5d884fc0SJustin Hibbits 	}
309*5d884fc0SJustin Hibbits 	if (count == 100)
310*5d884fc0SJustin Hibbits 		device_printf(base->sc_dev, "Timeout stopping BMI\n");
311*5d884fc0SJustin Hibbits 
312*5d884fc0SJustin Hibbits 	return (0);
313*5d884fc0SJustin Hibbits }
314*5d884fc0SJustin Hibbits 
315*5d884fc0SJustin Hibbits static int
fman_port_tx_enable(device_t dev)316*5d884fc0SJustin Hibbits fman_port_tx_enable(device_t dev)
317*5d884fc0SJustin Hibbits {
318*5d884fc0SJustin Hibbits 	struct fman_port_tx_softc *sc = device_get_softc(dev);
319*5d884fc0SJustin Hibbits 	struct fman_port_softc *base = &sc->sc_base;
320*5d884fc0SJustin Hibbits 	uint32_t reg;
321*5d884fc0SJustin Hibbits 
322*5d884fc0SJustin Hibbits 	reg = bus_read_4(base->sc_mem, FMQM_PNC);
323*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMQM_PNC, reg | PNC_EN | PNC_STEN);
324*5d884fc0SJustin Hibbits 
325*5d884fc0SJustin Hibbits 	reg = bus_read_4(base->sc_mem, FMBM_TCFG);
326*5d884fc0SJustin Hibbits 	bus_write_4(base->sc_mem, FMBM_TCFG, reg | BMI_PORT_CFG_EN);
327*5d884fc0SJustin Hibbits 
328*5d884fc0SJustin Hibbits 	return (0);
329*5d884fc0SJustin Hibbits }
330*5d884fc0SJustin Hibbits 
331*5d884fc0SJustin Hibbits static device_method_t fman_port_tx_methods[] = {
332*5d884fc0SJustin Hibbits 	DEVMETHOD(device_probe,		fman_port_tx_probe),
333*5d884fc0SJustin Hibbits 	DEVMETHOD(device_attach,	fman_port_tx_attach),
334*5d884fc0SJustin Hibbits 	DEVMETHOD(device_detach,	fman_port_tx_detach),
335*5d884fc0SJustin Hibbits 
336*5d884fc0SJustin Hibbits 	DEVMETHOD(fman_port_config,	fman_port_tx_config),
337*5d884fc0SJustin Hibbits 	DEVMETHOD(fman_port_init,	fman_port_tx_init),
338*5d884fc0SJustin Hibbits 	DEVMETHOD(fman_port_enable,	fman_port_tx_enable),
339*5d884fc0SJustin Hibbits 	DEVMETHOD(fman_port_disable,	fman_port_tx_disable),
340*5d884fc0SJustin Hibbits 
341*5d884fc0SJustin Hibbits 	DEVMETHOD_END
342*5d884fc0SJustin Hibbits };
343*5d884fc0SJustin Hibbits 
344*5d884fc0SJustin Hibbits DEFINE_CLASS_0(fman_port_tx, fman_port_tx_driver, fman_port_tx_methods,
345*5d884fc0SJustin Hibbits     sizeof(struct fman_port_tx_softc));
346*5d884fc0SJustin Hibbits EARLY_DRIVER_MODULE(fman_port_tx, fman, fman_port_tx_driver, 0, 0,
347*5d884fc0SJustin Hibbits     BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE);
348