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