1 | #include <machine/rtems-bsd-kernel-space.h> |
---|
2 | |
---|
3 | #include <rtems/bsd/local/opt_dpaa.h> |
---|
4 | |
---|
5 | /* |
---|
6 | * Copyright 2008 - 2015 Freescale Semiconductor Inc. |
---|
7 | * |
---|
8 | * Redistribution and use in source and binary forms, with or without |
---|
9 | * modification, are permitted provided that the following conditions are met: |
---|
10 | * * Redistributions of source code must retain the above copyright |
---|
11 | * notice, this list of conditions and the following disclaimer. |
---|
12 | * * Redistributions in binary form must reproduce the above copyright |
---|
13 | * notice, this list of conditions and the following disclaimer in the |
---|
14 | * documentation and/or other materials provided with the distribution. |
---|
15 | * * Neither the name of Freescale Semiconductor nor the |
---|
16 | * names of its contributors may be used to endorse or promote products |
---|
17 | * derived from this software without specific prior written permission. |
---|
18 | * |
---|
19 | * |
---|
20 | * ALTERNATIVELY, this software may be distributed under the terms of the |
---|
21 | * GNU General Public License ("GPL") as published by the Free Software |
---|
22 | * Foundation, either version 2 of that License or (at your option) any |
---|
23 | * later version. |
---|
24 | * |
---|
25 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY |
---|
26 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
---|
27 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
---|
28 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY |
---|
29 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
---|
30 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
---|
31 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
---|
32 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
---|
33 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
---|
34 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
35 | */ |
---|
36 | |
---|
37 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
38 | |
---|
39 | #include "fman_port.h" |
---|
40 | #include "fman.h" |
---|
41 | #include "fman_sp.h" |
---|
42 | |
---|
43 | #include <asm/mpc85xx.h> |
---|
44 | #include <linux/io.h> |
---|
45 | #include <linux/slab.h> |
---|
46 | #include <linux/module.h> |
---|
47 | #include <linux/interrupt.h> |
---|
48 | #include <linux/of_platform.h> |
---|
49 | #include <linux/of_address.h> |
---|
50 | |
---|
51 | /* Queue ID */ |
---|
52 | #define DFLT_FQ_ID 0x00FFFFFF |
---|
53 | |
---|
54 | /* General defines */ |
---|
55 | #define PORT_BMI_FIFO_UNITS 0x100 |
---|
56 | |
---|
57 | #define MAX_PORT_FIFO_SIZE(bmi_max_fifo_size) \ |
---|
58 | min((u32)bmi_max_fifo_size, (u32)1024 * FMAN_BMI_FIFO_UNITS) |
---|
59 | |
---|
60 | #define PORT_CG_MAP_NUM 8 |
---|
61 | #define PORT_PRS_RESULT_WORDS_NUM 8 |
---|
62 | #define PORT_IC_OFFSET_UNITS 0x10 |
---|
63 | |
---|
64 | #define MIN_EXT_BUF_SIZE 64 |
---|
65 | |
---|
66 | #define BMI_PORT_REGS_OFFSET 0 |
---|
67 | #define QMI_PORT_REGS_OFFSET 0x400 |
---|
68 | |
---|
69 | /* Default values */ |
---|
70 | #define DFLT_PORT_BUFFER_PREFIX_CONTEXT_DATA_ALIGN \ |
---|
71 | DFLT_FM_SP_BUFFER_PREFIX_CONTEXT_DATA_ALIGN |
---|
72 | |
---|
73 | #define DFLT_PORT_CUT_BYTES_FROM_END 4 |
---|
74 | |
---|
75 | #define DFLT_PORT_ERRORS_TO_DISCARD FM_PORT_FRM_ERR_CLS_DISCARD |
---|
76 | #define DFLT_PORT_MAX_FRAME_LENGTH 9600 |
---|
77 | |
---|
78 | #define DFLT_PORT_RX_FIFO_PRI_ELEVATION_LEV(bmi_max_fifo_size) \ |
---|
79 | MAX_PORT_FIFO_SIZE(bmi_max_fifo_size) |
---|
80 | |
---|
81 | #define DFLT_PORT_RX_FIFO_THRESHOLD(major, bmi_max_fifo_size) \ |
---|
82 | (major == 6 ? \ |
---|
83 | MAX_PORT_FIFO_SIZE(bmi_max_fifo_size) : \ |
---|
84 | (MAX_PORT_FIFO_SIZE(bmi_max_fifo_size) * 3 / 4)) \ |
---|
85 | |
---|
86 | #define DFLT_PORT_EXTRA_NUM_OF_FIFO_BUFS 0 |
---|
87 | |
---|
88 | /* QMI defines */ |
---|
89 | #define QMI_DEQ_CFG_SUBPORTAL_MASK 0x1f |
---|
90 | |
---|
91 | #define QMI_PORT_CFG_EN 0x80000000 |
---|
92 | #define QMI_PORT_STATUS_DEQ_FD_BSY 0x20000000 |
---|
93 | |
---|
94 | #define QMI_DEQ_CFG_PRI 0x80000000 |
---|
95 | #define QMI_DEQ_CFG_TYPE1 0x10000000 |
---|
96 | #define QMI_DEQ_CFG_TYPE2 0x20000000 |
---|
97 | #define QMI_DEQ_CFG_TYPE3 0x30000000 |
---|
98 | #define QMI_DEQ_CFG_PREFETCH_PARTIAL 0x01000000 |
---|
99 | #define QMI_DEQ_CFG_PREFETCH_FULL 0x03000000 |
---|
100 | #define QMI_DEQ_CFG_SP_MASK 0xf |
---|
101 | #define QMI_DEQ_CFG_SP_SHIFT 20 |
---|
102 | |
---|
103 | #define QMI_BYTE_COUNT_LEVEL_CONTROL(_type) \ |
---|
104 | (_type == FMAN_PORT_TYPE_TX ? 0x1400 : 0x400) |
---|
105 | |
---|
106 | /* BMI defins */ |
---|
107 | #define BMI_EBD_EN 0x80000000 |
---|
108 | |
---|
109 | #define BMI_PORT_CFG_EN 0x80000000 |
---|
110 | #define BMI_PORT_CFG_FDOVR 0x02000000 |
---|
111 | |
---|
112 | #define BMI_PORT_STATUS_BSY 0x80000000 |
---|
113 | |
---|
114 | #define BMI_DMA_ATTR_SWP_SHIFT FMAN_SP_DMA_ATTR_SWP_SHIFT |
---|
115 | #define BMI_DMA_ATTR_IC_STASH_ON 0x10000000 |
---|
116 | #define BMI_DMA_ATTR_HDR_STASH_ON 0x04000000 |
---|
117 | #define BMI_DMA_ATTR_SG_STASH_ON 0x01000000 |
---|
118 | #define BMI_DMA_ATTR_WRITE_OPTIMIZE FMAN_SP_DMA_ATTR_WRITE_OPTIMIZE |
---|
119 | |
---|
120 | #define BMI_RX_FIFO_PRI_ELEVATION_SHIFT 16 |
---|
121 | #define BMI_RX_FIFO_THRESHOLD_ETHE 0x80000000 |
---|
122 | |
---|
123 | #define BMI_FRAME_END_CS_IGNORE_SHIFT 24 |
---|
124 | #define BMI_FRAME_END_CS_IGNORE_MASK 0x0000001f |
---|
125 | |
---|
126 | #define BMI_RX_FRAME_END_CUT_SHIFT 16 |
---|
127 | #define BMI_RX_FRAME_END_CUT_MASK 0x0000001f |
---|
128 | |
---|
129 | #define BMI_IC_TO_EXT_SHIFT FMAN_SP_IC_TO_EXT_SHIFT |
---|
130 | #define BMI_IC_TO_EXT_MASK 0x0000001f |
---|
131 | #define BMI_IC_FROM_INT_SHIFT FMAN_SP_IC_FROM_INT_SHIFT |
---|
132 | #define BMI_IC_FROM_INT_MASK 0x0000000f |
---|
133 | #define BMI_IC_SIZE_MASK 0x0000001f |
---|
134 | |
---|
135 | #define BMI_INT_BUF_MARG_SHIFT 28 |
---|
136 | #define BMI_INT_BUF_MARG_MASK 0x0000000f |
---|
137 | #define BMI_EXT_BUF_MARG_START_SHIFT FMAN_SP_EXT_BUF_MARG_START_SHIFT |
---|
138 | #define BMI_EXT_BUF_MARG_START_MASK 0x000001ff |
---|
139 | #define BMI_EXT_BUF_MARG_END_MASK 0x000001ff |
---|
140 | |
---|
141 | #define BMI_CMD_MR_LEAC 0x00200000 |
---|
142 | #define BMI_CMD_MR_SLEAC 0x00100000 |
---|
143 | #define BMI_CMD_MR_MA 0x00080000 |
---|
144 | #define BMI_CMD_MR_DEAS 0x00040000 |
---|
145 | #define BMI_CMD_RX_MR_DEF (BMI_CMD_MR_LEAC | \ |
---|
146 | BMI_CMD_MR_SLEAC | \ |
---|
147 | BMI_CMD_MR_MA | \ |
---|
148 | BMI_CMD_MR_DEAS) |
---|
149 | #define BMI_CMD_TX_MR_DEF 0 |
---|
150 | |
---|
151 | #define BMI_CMD_ATTR_ORDER 0x80000000 |
---|
152 | #define BMI_CMD_ATTR_SYNC 0x02000000 |
---|
153 | #define BMI_CMD_ATTR_COLOR_SHIFT 26 |
---|
154 | |
---|
155 | #define BMI_FIFO_PIPELINE_DEPTH_SHIFT 12 |
---|
156 | #define BMI_FIFO_PIPELINE_DEPTH_MASK 0x0000000f |
---|
157 | #define BMI_NEXT_ENG_FD_BITS_SHIFT 24 |
---|
158 | |
---|
159 | #define BMI_EXT_BUF_POOL_VALID FMAN_SP_EXT_BUF_POOL_VALID |
---|
160 | #define BMI_EXT_BUF_POOL_EN_COUNTER FMAN_SP_EXT_BUF_POOL_EN_COUNTER |
---|
161 | #define BMI_EXT_BUF_POOL_BACKUP FMAN_SP_EXT_BUF_POOL_BACKUP |
---|
162 | #define BMI_EXT_BUF_POOL_ID_SHIFT 16 |
---|
163 | #define BMI_EXT_BUF_POOL_ID_MASK 0x003F0000 |
---|
164 | #define BMI_POOL_DEP_NUM_OF_POOLS_SHIFT 16 |
---|
165 | |
---|
166 | #define BMI_TX_FIFO_MIN_FILL_SHIFT 16 |
---|
167 | |
---|
168 | #define BMI_SG_DISABLE FMAN_SP_SG_DISABLE |
---|
169 | |
---|
170 | #define BMI_PRIORITY_ELEVATION_LEVEL ((0x3FF + 1) * PORT_BMI_FIFO_UNITS) |
---|
171 | #define BMI_FIFO_THRESHOLD ((0x3FF + 1) * PORT_BMI_FIFO_UNITS) |
---|
172 | |
---|
173 | #define BMI_DEQUEUE_PIPELINE_DEPTH(_type, _speed) \ |
---|
174 | ((_type == FMAN_PORT_TYPE_TX && _speed == 10000) ? 4 : 1) |
---|
175 | |
---|
176 | #define BMI_PORT_RFNE_FRWD_RPD 0x40000000 |
---|
177 | |
---|
178 | #define RX_ERRS_TO_ENQ \ |
---|
179 | (FM_PORT_FRM_ERR_DMA | \ |
---|
180 | FM_PORT_FRM_ERR_PHYSICAL | \ |
---|
181 | FM_PORT_FRM_ERR_SIZE | \ |
---|
182 | FM_PORT_FRM_ERR_EXTRACTION | \ |
---|
183 | FM_PORT_FRM_ERR_NO_SCHEME | \ |
---|
184 | FM_PORT_FRM_ERR_PRS_TIMEOUT | \ |
---|
185 | FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT | \ |
---|
186 | FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED | \ |
---|
187 | FM_PORT_FRM_ERR_PRS_HDR_ERR | \ |
---|
188 | FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW | \ |
---|
189 | FM_PORT_FRM_ERR_IPRE) |
---|
190 | |
---|
191 | /* NIA defines */ |
---|
192 | #define NIA_ORDER_RESTOR 0x00800000 |
---|
193 | #define NIA_ENG_FM_CTL 0x00000000 |
---|
194 | #define NIA_ENG_BMI 0x00500000 |
---|
195 | #define NIA_ENG_QMI_ENQ 0x00540000 |
---|
196 | #define NIA_ENG_QMI_DEQ 0x00580000 |
---|
197 | |
---|
198 | #define NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME 0x00000028 |
---|
199 | #define NIA_BMI_AC_ENQ_FRAME 0x00000002 |
---|
200 | #define NIA_BMI_AC_TX_RELEASE 0x000002C0 |
---|
201 | #define NIA_BMI_AC_RELEASE 0x000000C0 |
---|
202 | #define NIA_BMI_AC_TX 0x00000274 |
---|
203 | #define NIA_BMI_AC_FETCH_ALL_FRAME 0x0000020c |
---|
204 | |
---|
205 | /* Port IDs */ |
---|
206 | #define TX_10G_PORT_BASE 0x30 |
---|
207 | #define RX_10G_PORT_BASE 0x10 |
---|
208 | |
---|
209 | /* BMI Rx port register map */ |
---|
210 | struct fman_port_rx_bmi_regs { |
---|
211 | u32 fmbm_rcfg; /* Rx Configuration */ |
---|
212 | u32 fmbm_rst; /* Rx Status */ |
---|
213 | u32 fmbm_rda; /* Rx DMA attributes */ |
---|
214 | u32 fmbm_rfp; /* Rx FIFO Parameters */ |
---|
215 | u32 fmbm_rfed; /* Rx Frame End Data */ |
---|
216 | u32 fmbm_ricp; /* Rx Internal Context Parameters */ |
---|
217 | u32 fmbm_rim; /* Rx Internal Buffer Margins */ |
---|
218 | u32 fmbm_rebm; /* Rx External Buffer Margins */ |
---|
219 | u32 fmbm_rfne; /* Rx Frame Next Engine */ |
---|
220 | u32 fmbm_rfca; /* Rx Frame Command Attributes. */ |
---|
221 | u32 fmbm_rfpne; /* Rx Frame Parser Next Engine */ |
---|
222 | u32 fmbm_rpso; /* Rx Parse Start Offset */ |
---|
223 | u32 fmbm_rpp; /* Rx Policer Profile */ |
---|
224 | u32 fmbm_rccb; /* Rx Coarse Classification Base */ |
---|
225 | u32 fmbm_reth; /* Rx Excessive Threshold */ |
---|
226 | u32 reserved003c[1]; /* (0x03C 0x03F) */ |
---|
227 | u32 fmbm_rprai[PORT_PRS_RESULT_WORDS_NUM]; |
---|
228 | /* Rx Parse Results Array Init */ |
---|
229 | u32 fmbm_rfqid; /* Rx Frame Queue ID */ |
---|
230 | u32 fmbm_refqid; /* Rx Error Frame Queue ID */ |
---|
231 | u32 fmbm_rfsdm; /* Rx Frame Status Discard Mask */ |
---|
232 | u32 fmbm_rfsem; /* Rx Frame Status Error Mask */ |
---|
233 | u32 fmbm_rfene; /* Rx Frame Enqueue Next Engine */ |
---|
234 | u32 reserved0074[0x2]; /* (0x074-0x07C) */ |
---|
235 | u32 fmbm_rcmne; /* Rx Frame Continuous Mode Next Engine */ |
---|
236 | u32 reserved0080[0x20]; /* (0x080 0x0FF) */ |
---|
237 | u32 fmbm_ebmpi[FMAN_PORT_MAX_EXT_POOLS_NUM]; |
---|
238 | /* Buffer Manager pool Information- */ |
---|
239 | u32 fmbm_acnt[FMAN_PORT_MAX_EXT_POOLS_NUM]; /* Allocate Counter- */ |
---|
240 | u32 reserved0130[8]; /* 0x130/0x140 - 0x15F reserved - */ |
---|
241 | u32 fmbm_rcgm[PORT_CG_MAP_NUM]; /* Congestion Group Map */ |
---|
242 | u32 fmbm_mpd; /* BM Pool Depletion */ |
---|
243 | u32 reserved0184[0x1F]; /* (0x184 0x1FF) */ |
---|
244 | u32 fmbm_rstc; /* Rx Statistics Counters */ |
---|
245 | u32 fmbm_rfrc; /* Rx Frame Counter */ |
---|
246 | u32 fmbm_rfbc; /* Rx Bad Frames Counter */ |
---|
247 | u32 fmbm_rlfc; /* Rx Large Frames Counter */ |
---|
248 | u32 fmbm_rffc; /* Rx Filter Frames Counter */ |
---|
249 | u32 fmbm_rfdc; /* Rx Frame Discard Counter */ |
---|
250 | u32 fmbm_rfldec; /* Rx Frames List DMA Error Counter */ |
---|
251 | u32 fmbm_rodc; /* Rx Out of Buffers Discard nntr */ |
---|
252 | u32 fmbm_rbdc; /* Rx Buffers Deallocate Counter */ |
---|
253 | u32 fmbm_rpec; /* RX Prepare to enqueue Counte */ |
---|
254 | u32 reserved0224[0x16]; /* (0x224 0x27F) */ |
---|
255 | u32 fmbm_rpc; /* Rx Performance Counters */ |
---|
256 | u32 fmbm_rpcp; /* Rx Performance Count Parameters */ |
---|
257 | u32 fmbm_rccn; /* Rx Cycle Counter */ |
---|
258 | u32 fmbm_rtuc; /* Rx Tasks Utilization Counter */ |
---|
259 | u32 fmbm_rrquc; /* Rx Receive Queue Utilization cntr */ |
---|
260 | u32 fmbm_rduc; /* Rx DMA Utilization Counter */ |
---|
261 | u32 fmbm_rfuc; /* Rx FIFO Utilization Counter */ |
---|
262 | u32 fmbm_rpac; /* Rx Pause Activation Counter */ |
---|
263 | u32 reserved02a0[0x18]; /* (0x2A0 0x2FF) */ |
---|
264 | u32 fmbm_rdcfg[0x3]; /* Rx Debug Configuration */ |
---|
265 | u32 fmbm_rgpr; /* Rx General Purpose Register */ |
---|
266 | u32 reserved0310[0x3a]; |
---|
267 | }; |
---|
268 | |
---|
269 | /* BMI Tx port register map */ |
---|
270 | struct fman_port_tx_bmi_regs { |
---|
271 | u32 fmbm_tcfg; /* Tx Configuration */ |
---|
272 | u32 fmbm_tst; /* Tx Status */ |
---|
273 | u32 fmbm_tda; /* Tx DMA attributes */ |
---|
274 | u32 fmbm_tfp; /* Tx FIFO Parameters */ |
---|
275 | u32 fmbm_tfed; /* Tx Frame End Data */ |
---|
276 | u32 fmbm_ticp; /* Tx Internal Context Parameters */ |
---|
277 | u32 fmbm_tfdne; /* Tx Frame Dequeue Next Engine. */ |
---|
278 | u32 fmbm_tfca; /* Tx Frame Command attribute. */ |
---|
279 | u32 fmbm_tcfqid; /* Tx Confirmation Frame Queue ID. */ |
---|
280 | u32 fmbm_tefqid; /* Tx Frame Error Queue ID */ |
---|
281 | u32 fmbm_tfene; /* Tx Frame Enqueue Next Engine */ |
---|
282 | u32 fmbm_trlmts; /* Tx Rate Limiter Scale */ |
---|
283 | u32 fmbm_trlmt; /* Tx Rate Limiter */ |
---|
284 | u32 reserved0034[0x0e]; /* (0x034-0x6c) */ |
---|
285 | u32 fmbm_tccb; /* Tx Coarse Classification base */ |
---|
286 | u32 fmbm_tfne; /* Tx Frame Next Engine */ |
---|
287 | u32 fmbm_tpfcm[0x02]; |
---|
288 | /* Tx Priority based Flow Control (PFC) Mapping */ |
---|
289 | u32 fmbm_tcmne; /* Tx Frame Continuous Mode Next Engine */ |
---|
290 | u32 reserved0080[0x60]; /* (0x080-0x200) */ |
---|
291 | u32 fmbm_tstc; /* Tx Statistics Counters */ |
---|
292 | u32 fmbm_tfrc; /* Tx Frame Counter */ |
---|
293 | u32 fmbm_tfdc; /* Tx Frames Discard Counter */ |
---|
294 | u32 fmbm_tfledc; /* Tx Frame len error discard cntr */ |
---|
295 | u32 fmbm_tfufdc; /* Tx Frame unsprt frmt discard cntr */ |
---|
296 | u32 fmbm_tbdc; /* Tx Buffers Deallocate Counter */ |
---|
297 | u32 reserved0218[0x1A]; /* (0x218-0x280) */ |
---|
298 | u32 fmbm_tpc; /* Tx Performance Counters */ |
---|
299 | u32 fmbm_tpcp; /* Tx Performance Count Parameters */ |
---|
300 | u32 fmbm_tccn; /* Tx Cycle Counter */ |
---|
301 | u32 fmbm_ttuc; /* Tx Tasks Utilization Counter */ |
---|
302 | u32 fmbm_ttcquc; /* Tx Transmit conf Q util Counter */ |
---|
303 | u32 fmbm_tduc; /* Tx DMA Utilization Counter */ |
---|
304 | u32 fmbm_tfuc; /* Tx FIFO Utilization Counter */ |
---|
305 | u32 reserved029c[16]; /* (0x29C-0x2FF) */ |
---|
306 | u32 fmbm_tdcfg[0x3]; /* Tx Debug Configuration */ |
---|
307 | u32 fmbm_tgpr; /* Tx General Purpose Register */ |
---|
308 | u32 reserved0310[0x3a]; /* (0x310-0x3FF) */ |
---|
309 | }; |
---|
310 | |
---|
311 | /* BMI port register map */ |
---|
312 | union fman_port_bmi_regs { |
---|
313 | struct fman_port_rx_bmi_regs rx; |
---|
314 | struct fman_port_tx_bmi_regs tx; |
---|
315 | }; |
---|
316 | |
---|
317 | /* QMI port register map */ |
---|
318 | struct fman_port_qmi_regs { |
---|
319 | u32 fmqm_pnc; /* PortID n Configuration Register */ |
---|
320 | u32 fmqm_pns; /* PortID n Status Register */ |
---|
321 | u32 fmqm_pnts; /* PortID n Task Status Register */ |
---|
322 | u32 reserved00c[4]; /* 0xn00C - 0xn01B */ |
---|
323 | u32 fmqm_pnen; /* PortID n Enqueue NIA Register */ |
---|
324 | u32 fmqm_pnetfc; /* PortID n Enq Total Frame Counter */ |
---|
325 | u32 reserved024[2]; /* 0xn024 - 0x02B */ |
---|
326 | u32 fmqm_pndn; /* PortID n Dequeue NIA Register */ |
---|
327 | u32 fmqm_pndc; /* PortID n Dequeue Config Register */ |
---|
328 | u32 fmqm_pndtfc; /* PortID n Dequeue tot Frame cntr */ |
---|
329 | u32 fmqm_pndfdc; /* PortID n Dequeue FQID Dflt Cntr */ |
---|
330 | u32 fmqm_pndcc; /* PortID n Dequeue Confirm Counter */ |
---|
331 | }; |
---|
332 | |
---|
333 | /* QMI dequeue prefetch modes */ |
---|
334 | enum fman_port_deq_prefetch { |
---|
335 | FMAN_PORT_DEQ_NO_PREFETCH, /* No prefetch mode */ |
---|
336 | FMAN_PORT_DEQ_PART_PREFETCH, /* Partial prefetch mode */ |
---|
337 | FMAN_PORT_DEQ_FULL_PREFETCH /* Full prefetch mode */ |
---|
338 | }; |
---|
339 | |
---|
340 | /* A structure for defining FM port resources */ |
---|
341 | struct fman_port_rsrc { |
---|
342 | u32 num; /* Committed required resource */ |
---|
343 | u32 extra; /* Extra (not committed) required resource */ |
---|
344 | }; |
---|
345 | |
---|
346 | enum fman_port_dma_swap { |
---|
347 | FMAN_PORT_DMA_NO_SWAP, /* No swap, transfer data as is */ |
---|
348 | FMAN_PORT_DMA_SWAP_LE, |
---|
349 | /* The transferred data should be swapped in PPC Little Endian mode */ |
---|
350 | FMAN_PORT_DMA_SWAP_BE |
---|
351 | /* The transferred data should be swapped in Big Endian mode */ |
---|
352 | }; |
---|
353 | |
---|
354 | /* Default port color */ |
---|
355 | enum fman_port_color { |
---|
356 | FMAN_PORT_COLOR_GREEN, /* Default port color is green */ |
---|
357 | FMAN_PORT_COLOR_YELLOW, /* Default port color is yellow */ |
---|
358 | FMAN_PORT_COLOR_RED, /* Default port color is red */ |
---|
359 | FMAN_PORT_COLOR_OVERRIDE /* Ignore color */ |
---|
360 | }; |
---|
361 | |
---|
362 | /* QMI dequeue from the SP channel - types */ |
---|
363 | enum fman_port_deq_type { |
---|
364 | FMAN_PORT_DEQ_BY_PRI, |
---|
365 | /* Priority precedence and Intra-Class scheduling */ |
---|
366 | FMAN_PORT_DEQ_ACTIVE_FQ, |
---|
367 | /* Active FQ precedence and Intra-Class scheduling */ |
---|
368 | FMAN_PORT_DEQ_ACTIVE_FQ_NO_ICS |
---|
369 | /* Active FQ precedence and override Intra-Class scheduling */ |
---|
370 | }; |
---|
371 | |
---|
372 | /* External buffer pools configuration */ |
---|
373 | struct fman_port_bpools { |
---|
374 | u8 count; /* Num of pools to set up */ |
---|
375 | bool counters_enable; /* Enable allocate counters */ |
---|
376 | u8 grp_bp_depleted_num; |
---|
377 | /* Number of depleted pools - if reached the BMI indicates |
---|
378 | * the MAC to send a pause frame |
---|
379 | */ |
---|
380 | struct { |
---|
381 | u8 bpid; /* BM pool ID */ |
---|
382 | u16 size; |
---|
383 | /* Pool's size - must be in ascending order */ |
---|
384 | bool is_backup; |
---|
385 | /* If this is a backup pool */ |
---|
386 | bool grp_bp_depleted; |
---|
387 | /* Consider this buffer in multiple pools depletion criteria */ |
---|
388 | bool single_bp_depleted; |
---|
389 | /* Consider this buffer in single pool depletion criteria */ |
---|
390 | } bpool[FMAN_PORT_MAX_EXT_POOLS_NUM]; |
---|
391 | }; |
---|
392 | |
---|
393 | struct fman_port_cfg { |
---|
394 | u32 dflt_fqid; |
---|
395 | u32 err_fqid; |
---|
396 | u8 deq_sp; |
---|
397 | bool deq_high_priority; |
---|
398 | enum fman_port_deq_type deq_type; |
---|
399 | enum fman_port_deq_prefetch deq_prefetch_option; |
---|
400 | u16 deq_byte_cnt; |
---|
401 | u8 cheksum_last_bytes_ignore; |
---|
402 | u8 rx_cut_end_bytes; |
---|
403 | struct fman_buf_pool_depletion buf_pool_depletion; |
---|
404 | bool discard_override; |
---|
405 | bool en_buf_pool_depletion; |
---|
406 | struct fman_ext_pools ext_buf_pools; |
---|
407 | u32 tx_fifo_min_level; |
---|
408 | u32 tx_fifo_low_comf_level; |
---|
409 | u32 rx_pri_elevation; |
---|
410 | u32 rx_fifo_thr; |
---|
411 | struct fman_sp_buf_margins buf_margins; |
---|
412 | u32 int_buf_start_margin; |
---|
413 | struct fman_sp_int_context_data_copy int_context; |
---|
414 | u32 discard_mask; |
---|
415 | u32 err_mask; |
---|
416 | bool forward_reuse_int_context; |
---|
417 | struct fman_buffer_prefix_content buffer_prefix_content; |
---|
418 | bool dont_release_buf; |
---|
419 | bool set_num_of_tasks; |
---|
420 | bool set_num_of_open_dmas; |
---|
421 | bool set_size_of_fifo; |
---|
422 | bool bcb_workaround; |
---|
423 | |
---|
424 | u8 rx_fd_bits; |
---|
425 | u32 tx_fifo_deq_pipeline_depth; |
---|
426 | bool errata_A006675; |
---|
427 | bool errata_A006320; |
---|
428 | bool excessive_threshold_register; |
---|
429 | bool fmbm_rebm_has_sgd; |
---|
430 | bool fmbm_tfne_has_features; |
---|
431 | bool qmi_deq_options_support; |
---|
432 | |
---|
433 | enum fman_port_dma_swap dma_swap_data; |
---|
434 | bool dma_ic_stash_on; |
---|
435 | bool dma_header_stash_on; |
---|
436 | bool dma_sg_stash_on; |
---|
437 | bool dma_write_optimize; |
---|
438 | enum fman_port_color color; |
---|
439 | bool sync_req; |
---|
440 | |
---|
441 | bool no_scatter_gather; |
---|
442 | }; |
---|
443 | |
---|
444 | struct fman_port_rx_pools_params { |
---|
445 | u8 num_of_pools; |
---|
446 | u16 second_largest_buf_size; |
---|
447 | u16 largest_buf_size; |
---|
448 | }; |
---|
449 | |
---|
450 | struct fman_port_dts_params { |
---|
451 | void __iomem *base_addr; /* FMan port virtual memory */ |
---|
452 | enum fman_port_type type; /* Port type */ |
---|
453 | u16 speed; /* Port speed */ |
---|
454 | u8 id; /* HW Port Id */ |
---|
455 | u32 qman_channel_id; /* QMan channel id (non RX only) */ |
---|
456 | struct fman *fman; /* FMan Handle */ |
---|
457 | }; |
---|
458 | |
---|
459 | struct fman_port { |
---|
460 | void *fm; |
---|
461 | struct fman_rev_info rev_info; |
---|
462 | u8 port_id; |
---|
463 | enum fman_port_type port_type; |
---|
464 | u16 port_speed; |
---|
465 | |
---|
466 | union fman_port_bmi_regs __iomem *bmi_regs; |
---|
467 | struct fman_port_qmi_regs __iomem *qmi_regs; |
---|
468 | |
---|
469 | struct fman_sp_buffer_offsets buffer_offsets; |
---|
470 | |
---|
471 | u8 internal_buf_offset; |
---|
472 | struct fman_ext_pools ext_buf_pools; |
---|
473 | |
---|
474 | u16 max_frame_length; |
---|
475 | struct fman_port_rsrc open_dmas; |
---|
476 | struct fman_port_rsrc tasks; |
---|
477 | struct fman_port_rsrc fifo_bufs; |
---|
478 | struct fman_port_rx_pools_params rx_pools_params; |
---|
479 | |
---|
480 | struct fman_port_cfg *cfg; |
---|
481 | struct fman_port_dts_params dts_params; |
---|
482 | |
---|
483 | u8 ext_pools_num; |
---|
484 | u32 max_port_fifo_size; |
---|
485 | u32 max_num_of_ext_pools; |
---|
486 | u32 max_num_of_sub_portals; |
---|
487 | u32 bm_max_num_of_pools; |
---|
488 | }; |
---|
489 | |
---|
490 | static int init_bmi_rx(struct fman_port *port) |
---|
491 | { |
---|
492 | struct fman_port_rx_bmi_regs __iomem *regs = &port->bmi_regs->rx; |
---|
493 | struct fman_port_cfg *cfg = port->cfg; |
---|
494 | u32 tmp; |
---|
495 | |
---|
496 | /* Rx Configuration register */ |
---|
497 | tmp = 0; |
---|
498 | if (cfg->discard_override) |
---|
499 | tmp |= BMI_PORT_CFG_FDOVR; |
---|
500 | iowrite32be(tmp, ®s->fmbm_rcfg); |
---|
501 | |
---|
502 | /* DMA attributes */ |
---|
503 | tmp = (u32)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT; |
---|
504 | if (cfg->dma_ic_stash_on) |
---|
505 | tmp |= BMI_DMA_ATTR_IC_STASH_ON; |
---|
506 | if (cfg->dma_header_stash_on) |
---|
507 | tmp |= BMI_DMA_ATTR_HDR_STASH_ON; |
---|
508 | if (cfg->dma_sg_stash_on) |
---|
509 | tmp |= BMI_DMA_ATTR_SG_STASH_ON; |
---|
510 | if (cfg->dma_write_optimize) |
---|
511 | tmp |= BMI_DMA_ATTR_WRITE_OPTIMIZE; |
---|
512 | iowrite32be(tmp, ®s->fmbm_rda); |
---|
513 | |
---|
514 | /* Rx FIFO parameters */ |
---|
515 | tmp = (cfg->rx_pri_elevation / PORT_BMI_FIFO_UNITS - 1) << |
---|
516 | BMI_RX_FIFO_PRI_ELEVATION_SHIFT; |
---|
517 | tmp |= cfg->rx_fifo_thr / PORT_BMI_FIFO_UNITS - 1; |
---|
518 | iowrite32be(tmp, ®s->fmbm_rfp); |
---|
519 | |
---|
520 | if (cfg->excessive_threshold_register) |
---|
521 | /* always allow access to the extra resources */ |
---|
522 | iowrite32be(BMI_RX_FIFO_THRESHOLD_ETHE, ®s->fmbm_reth); |
---|
523 | |
---|
524 | /* Frame end data */ |
---|
525 | tmp = (cfg->cheksum_last_bytes_ignore & BMI_FRAME_END_CS_IGNORE_MASK) << |
---|
526 | BMI_FRAME_END_CS_IGNORE_SHIFT; |
---|
527 | tmp |= (cfg->rx_cut_end_bytes & BMI_RX_FRAME_END_CUT_MASK) << |
---|
528 | BMI_RX_FRAME_END_CUT_SHIFT; |
---|
529 | if (cfg->errata_A006320) |
---|
530 | tmp &= 0xffe0ffff; |
---|
531 | iowrite32be(tmp, ®s->fmbm_rfed); |
---|
532 | |
---|
533 | /* Internal context parameters */ |
---|
534 | tmp = ((cfg->int_context.ext_buf_offset / PORT_IC_OFFSET_UNITS) & |
---|
535 | BMI_IC_TO_EXT_MASK) << BMI_IC_TO_EXT_SHIFT; |
---|
536 | tmp |= ((cfg->int_context.int_context_offset / PORT_IC_OFFSET_UNITS) & |
---|
537 | BMI_IC_FROM_INT_MASK) << BMI_IC_FROM_INT_SHIFT; |
---|
538 | tmp |= (cfg->int_context.size / PORT_IC_OFFSET_UNITS) & |
---|
539 | BMI_IC_SIZE_MASK; |
---|
540 | iowrite32be(tmp, ®s->fmbm_ricp); |
---|
541 | |
---|
542 | /* Internal buffer offset */ |
---|
543 | tmp = ((cfg->int_buf_start_margin / PORT_IC_OFFSET_UNITS) & |
---|
544 | BMI_INT_BUF_MARG_MASK) << BMI_INT_BUF_MARG_SHIFT; |
---|
545 | iowrite32be(tmp, ®s->fmbm_rim); |
---|
546 | |
---|
547 | /* External buffer margins */ |
---|
548 | tmp = (cfg->buf_margins.start_margins & BMI_EXT_BUF_MARG_START_MASK) << |
---|
549 | BMI_EXT_BUF_MARG_START_SHIFT; |
---|
550 | tmp |= cfg->buf_margins.end_margins & BMI_EXT_BUF_MARG_END_MASK; |
---|
551 | if (cfg->fmbm_rebm_has_sgd && cfg->no_scatter_gather) |
---|
552 | tmp |= BMI_SG_DISABLE; |
---|
553 | iowrite32be(tmp, ®s->fmbm_rebm); |
---|
554 | |
---|
555 | /* Frame attributes */ |
---|
556 | tmp = BMI_CMD_RX_MR_DEF; |
---|
557 | tmp |= BMI_CMD_ATTR_ORDER; |
---|
558 | tmp |= (u32)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT; |
---|
559 | if (cfg->sync_req) |
---|
560 | tmp |= BMI_CMD_ATTR_SYNC; |
---|
561 | |
---|
562 | iowrite32be(tmp, ®s->fmbm_rfca); |
---|
563 | |
---|
564 | /* NIA */ |
---|
565 | tmp = (u32)cfg->rx_fd_bits << BMI_NEXT_ENG_FD_BITS_SHIFT; |
---|
566 | |
---|
567 | if (cfg->errata_A006675) |
---|
568 | tmp |= NIA_ENG_FM_CTL | |
---|
569 | NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME; |
---|
570 | else |
---|
571 | tmp |= NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME; |
---|
572 | iowrite32be(tmp, ®s->fmbm_rfne); |
---|
573 | |
---|
574 | /* Enqueue NIA */ |
---|
575 | iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, ®s->fmbm_rfene); |
---|
576 | |
---|
577 | /* Default/error queues */ |
---|
578 | iowrite32be((cfg->dflt_fqid & DFLT_FQ_ID), ®s->fmbm_rfqid); |
---|
579 | iowrite32be((cfg->err_fqid & DFLT_FQ_ID), ®s->fmbm_refqid); |
---|
580 | |
---|
581 | /* Discard/error masks */ |
---|
582 | iowrite32be(cfg->discard_mask, ®s->fmbm_rfsdm); |
---|
583 | iowrite32be(cfg->err_mask, ®s->fmbm_rfsem); |
---|
584 | |
---|
585 | return 0; |
---|
586 | } |
---|
587 | |
---|
588 | static int init_bmi_tx(struct fman_port *port) |
---|
589 | { |
---|
590 | struct fman_port_tx_bmi_regs __iomem *regs = &port->bmi_regs->tx; |
---|
591 | struct fman_port_cfg *cfg = port->cfg; |
---|
592 | u32 tmp; |
---|
593 | |
---|
594 | /* Tx Configuration register */ |
---|
595 | tmp = 0; |
---|
596 | iowrite32be(tmp, ®s->fmbm_tcfg); |
---|
597 | |
---|
598 | /* DMA attributes */ |
---|
599 | tmp = (u32)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT; |
---|
600 | if (cfg->dma_ic_stash_on) |
---|
601 | tmp |= BMI_DMA_ATTR_IC_STASH_ON; |
---|
602 | if (cfg->dma_header_stash_on) |
---|
603 | tmp |= BMI_DMA_ATTR_HDR_STASH_ON; |
---|
604 | if (cfg->dma_sg_stash_on) |
---|
605 | tmp |= BMI_DMA_ATTR_SG_STASH_ON; |
---|
606 | iowrite32be(tmp, ®s->fmbm_tda); |
---|
607 | |
---|
608 | /* Tx FIFO parameters */ |
---|
609 | tmp = (cfg->tx_fifo_min_level / PORT_BMI_FIFO_UNITS) << |
---|
610 | BMI_TX_FIFO_MIN_FILL_SHIFT; |
---|
611 | tmp |= ((cfg->tx_fifo_deq_pipeline_depth - 1) & |
---|
612 | BMI_FIFO_PIPELINE_DEPTH_MASK) << BMI_FIFO_PIPELINE_DEPTH_SHIFT; |
---|
613 | tmp |= (cfg->tx_fifo_low_comf_level / PORT_BMI_FIFO_UNITS) - 1; |
---|
614 | iowrite32be(tmp, ®s->fmbm_tfp); |
---|
615 | |
---|
616 | /* Frame end data */ |
---|
617 | tmp = (cfg->cheksum_last_bytes_ignore & BMI_FRAME_END_CS_IGNORE_MASK) << |
---|
618 | BMI_FRAME_END_CS_IGNORE_SHIFT; |
---|
619 | iowrite32be(tmp, ®s->fmbm_tfed); |
---|
620 | |
---|
621 | /* Internal context parameters */ |
---|
622 | tmp = ((cfg->int_context.ext_buf_offset / PORT_IC_OFFSET_UNITS) & |
---|
623 | BMI_IC_TO_EXT_MASK) << BMI_IC_TO_EXT_SHIFT; |
---|
624 | tmp |= ((cfg->int_context.int_context_offset / PORT_IC_OFFSET_UNITS) & |
---|
625 | BMI_IC_FROM_INT_MASK) << BMI_IC_FROM_INT_SHIFT; |
---|
626 | tmp |= (cfg->int_context.size / PORT_IC_OFFSET_UNITS) & |
---|
627 | BMI_IC_SIZE_MASK; |
---|
628 | iowrite32be(tmp, ®s->fmbm_ticp); |
---|
629 | |
---|
630 | /* Frame attributes */ |
---|
631 | tmp = BMI_CMD_TX_MR_DEF; |
---|
632 | tmp |= BMI_CMD_ATTR_ORDER; |
---|
633 | tmp |= (u32)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT; |
---|
634 | iowrite32be(tmp, ®s->fmbm_tfca); |
---|
635 | |
---|
636 | /* Dequeue NIA + enqueue NIA */ |
---|
637 | iowrite32be(NIA_ENG_QMI_DEQ, ®s->fmbm_tfdne); |
---|
638 | iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, ®s->fmbm_tfene); |
---|
639 | if (cfg->fmbm_tfne_has_features) |
---|
640 | iowrite32be(!cfg->dflt_fqid ? |
---|
641 | BMI_EBD_EN | NIA_BMI_AC_FETCH_ALL_FRAME : |
---|
642 | NIA_BMI_AC_FETCH_ALL_FRAME, ®s->fmbm_tfne); |
---|
643 | if (!cfg->dflt_fqid && cfg->dont_release_buf) { |
---|
644 | iowrite32be(DFLT_FQ_ID, ®s->fmbm_tcfqid); |
---|
645 | iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE, |
---|
646 | ®s->fmbm_tfene); |
---|
647 | if (cfg->fmbm_tfne_has_features) |
---|
648 | iowrite32be(ioread32be(®s->fmbm_tfne) & ~BMI_EBD_EN, |
---|
649 | ®s->fmbm_tfne); |
---|
650 | } |
---|
651 | |
---|
652 | /* Confirmation/error queues */ |
---|
653 | if (cfg->dflt_fqid || !cfg->dont_release_buf) |
---|
654 | iowrite32be(cfg->dflt_fqid & DFLT_FQ_ID, ®s->fmbm_tcfqid); |
---|
655 | iowrite32be((cfg->err_fqid & DFLT_FQ_ID), ®s->fmbm_tefqid); |
---|
656 | |
---|
657 | return 0; |
---|
658 | } |
---|
659 | |
---|
660 | static int init_qmi(struct fman_port *port) |
---|
661 | { |
---|
662 | struct fman_port_qmi_regs __iomem *regs = port->qmi_regs; |
---|
663 | struct fman_port_cfg *cfg = port->cfg; |
---|
664 | u32 tmp; |
---|
665 | |
---|
666 | /* Rx port configuration */ |
---|
667 | if (port->port_type == FMAN_PORT_TYPE_RX) { |
---|
668 | /* Enqueue NIA */ |
---|
669 | iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_RELEASE, ®s->fmqm_pnen); |
---|
670 | return 0; |
---|
671 | } |
---|
672 | |
---|
673 | /* Continue with Tx port configuration */ |
---|
674 | if (port->port_type == FMAN_PORT_TYPE_TX) { |
---|
675 | /* Enqueue NIA */ |
---|
676 | iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE, |
---|
677 | ®s->fmqm_pnen); |
---|
678 | /* Dequeue NIA */ |
---|
679 | iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX, ®s->fmqm_pndn); |
---|
680 | } |
---|
681 | |
---|
682 | /* Dequeue Configuration register */ |
---|
683 | tmp = 0; |
---|
684 | if (cfg->deq_high_priority) |
---|
685 | tmp |= QMI_DEQ_CFG_PRI; |
---|
686 | |
---|
687 | switch (cfg->deq_type) { |
---|
688 | case FMAN_PORT_DEQ_BY_PRI: |
---|
689 | tmp |= QMI_DEQ_CFG_TYPE1; |
---|
690 | break; |
---|
691 | case FMAN_PORT_DEQ_ACTIVE_FQ: |
---|
692 | tmp |= QMI_DEQ_CFG_TYPE2; |
---|
693 | break; |
---|
694 | case FMAN_PORT_DEQ_ACTIVE_FQ_NO_ICS: |
---|
695 | tmp |= QMI_DEQ_CFG_TYPE3; |
---|
696 | break; |
---|
697 | default: |
---|
698 | return -EINVAL; |
---|
699 | } |
---|
700 | |
---|
701 | if (cfg->qmi_deq_options_support) { |
---|
702 | switch (cfg->deq_prefetch_option) { |
---|
703 | case FMAN_PORT_DEQ_NO_PREFETCH: |
---|
704 | break; |
---|
705 | case FMAN_PORT_DEQ_PART_PREFETCH: |
---|
706 | tmp |= QMI_DEQ_CFG_PREFETCH_PARTIAL; |
---|
707 | break; |
---|
708 | case FMAN_PORT_DEQ_FULL_PREFETCH: |
---|
709 | tmp |= QMI_DEQ_CFG_PREFETCH_FULL; |
---|
710 | break; |
---|
711 | default: |
---|
712 | return -EINVAL; |
---|
713 | } |
---|
714 | } |
---|
715 | tmp |= (cfg->deq_sp & QMI_DEQ_CFG_SP_MASK) << QMI_DEQ_CFG_SP_SHIFT; |
---|
716 | tmp |= cfg->deq_byte_cnt; |
---|
717 | iowrite32be(tmp, ®s->fmqm_pndc); |
---|
718 | |
---|
719 | return 0; |
---|
720 | } |
---|
721 | |
---|
722 | static int init(struct fman_port *port) |
---|
723 | { |
---|
724 | int err; |
---|
725 | |
---|
726 | /* Init BMI registers */ |
---|
727 | switch (port->port_type) { |
---|
728 | case FMAN_PORT_TYPE_RX: |
---|
729 | err = init_bmi_rx(port); |
---|
730 | break; |
---|
731 | case FMAN_PORT_TYPE_TX: |
---|
732 | err = init_bmi_tx(port); |
---|
733 | break; |
---|
734 | default: |
---|
735 | return -EINVAL; |
---|
736 | } |
---|
737 | |
---|
738 | if (err) |
---|
739 | return err; |
---|
740 | |
---|
741 | /* Init QMI registers */ |
---|
742 | err = init_qmi(port); |
---|
743 | return err; |
---|
744 | |
---|
745 | return 0; |
---|
746 | } |
---|
747 | |
---|
748 | static int set_bpools(const struct fman_port *port, |
---|
749 | const struct fman_port_bpools *bp) |
---|
750 | { |
---|
751 | u32 __iomem *bp_reg, *bp_depl_reg; |
---|
752 | u32 tmp; |
---|
753 | u8 i, max_bp_num; |
---|
754 | bool grp_depl_used = false, rx_port; |
---|
755 | |
---|
756 | switch (port->port_type) { |
---|
757 | case FMAN_PORT_TYPE_RX: |
---|
758 | max_bp_num = port->ext_pools_num; |
---|
759 | rx_port = true; |
---|
760 | bp_reg = port->bmi_regs->rx.fmbm_ebmpi; |
---|
761 | bp_depl_reg = &port->bmi_regs->rx.fmbm_mpd; |
---|
762 | break; |
---|
763 | default: |
---|
764 | return -EINVAL; |
---|
765 | } |
---|
766 | |
---|
767 | if (rx_port) { |
---|
768 | /* Check buffers are provided in ascending order */ |
---|
769 | for (i = 0; (i < (bp->count - 1) && |
---|
770 | (i < FMAN_PORT_MAX_EXT_POOLS_NUM - 1)); i++) { |
---|
771 | if (bp->bpool[i].size > bp->bpool[i + 1].size) |
---|
772 | return -EINVAL; |
---|
773 | } |
---|
774 | } |
---|
775 | |
---|
776 | /* Set up external buffers pools */ |
---|
777 | for (i = 0; i < bp->count; i++) { |
---|
778 | tmp = BMI_EXT_BUF_POOL_VALID; |
---|
779 | tmp |= ((u32)bp->bpool[i].bpid << |
---|
780 | BMI_EXT_BUF_POOL_ID_SHIFT) & BMI_EXT_BUF_POOL_ID_MASK; |
---|
781 | |
---|
782 | if (rx_port) { |
---|
783 | if (bp->counters_enable) |
---|
784 | tmp |= BMI_EXT_BUF_POOL_EN_COUNTER; |
---|
785 | |
---|
786 | if (bp->bpool[i].is_backup) |
---|
787 | tmp |= BMI_EXT_BUF_POOL_BACKUP; |
---|
788 | |
---|
789 | tmp |= (u32)bp->bpool[i].size; |
---|
790 | } |
---|
791 | |
---|
792 | iowrite32be(tmp, &bp_reg[i]); |
---|
793 | } |
---|
794 | |
---|
795 | /* Clear unused pools */ |
---|
796 | for (i = bp->count; i < max_bp_num; i++) |
---|
797 | iowrite32be(0, &bp_reg[i]); |
---|
798 | |
---|
799 | /* Pools depletion */ |
---|
800 | tmp = 0; |
---|
801 | for (i = 0; i < FMAN_PORT_MAX_EXT_POOLS_NUM; i++) { |
---|
802 | if (bp->bpool[i].grp_bp_depleted) { |
---|
803 | grp_depl_used = true; |
---|
804 | tmp |= 0x80000000 >> i; |
---|
805 | } |
---|
806 | |
---|
807 | if (bp->bpool[i].single_bp_depleted) |
---|
808 | tmp |= 0x80 >> i; |
---|
809 | } |
---|
810 | |
---|
811 | if (grp_depl_used) |
---|
812 | tmp |= ((u32)bp->grp_bp_depleted_num - 1) << |
---|
813 | BMI_POOL_DEP_NUM_OF_POOLS_SHIFT; |
---|
814 | |
---|
815 | iowrite32be(tmp, bp_depl_reg); |
---|
816 | return 0; |
---|
817 | } |
---|
818 | |
---|
819 | static bool is_init_done(struct fman_port_cfg *cfg) |
---|
820 | { |
---|
821 | /* Checks if FMan port driver parameters were initialized */ |
---|
822 | if (!cfg) |
---|
823 | return true; |
---|
824 | |
---|
825 | return false; |
---|
826 | } |
---|
827 | |
---|
828 | static int verify_size_of_fifo(struct fman_port *port) |
---|
829 | { |
---|
830 | u32 min_fifo_size_required = 0, opt_fifo_size_for_b2b = 0; |
---|
831 | |
---|
832 | /* TX Ports */ |
---|
833 | if (port->port_type == FMAN_PORT_TYPE_TX) { |
---|
834 | min_fifo_size_required = (u32) |
---|
835 | (roundup(port->max_frame_length, |
---|
836 | FMAN_BMI_FIFO_UNITS) + (3 * FMAN_BMI_FIFO_UNITS)); |
---|
837 | |
---|
838 | min_fifo_size_required += |
---|
839 | port->cfg->tx_fifo_deq_pipeline_depth * |
---|
840 | FMAN_BMI_FIFO_UNITS; |
---|
841 | |
---|
842 | opt_fifo_size_for_b2b = min_fifo_size_required; |
---|
843 | |
---|
844 | /* Add some margin for back-to-back capability to improve |
---|
845 | * performance, allows the hardware to pipeline new frame dma |
---|
846 | * while the previous frame not yet transmitted. |
---|
847 | */ |
---|
848 | if (port->port_speed == 10000) |
---|
849 | opt_fifo_size_for_b2b += 3 * FMAN_BMI_FIFO_UNITS; |
---|
850 | else |
---|
851 | opt_fifo_size_for_b2b += 2 * FMAN_BMI_FIFO_UNITS; |
---|
852 | } |
---|
853 | |
---|
854 | /* RX Ports */ |
---|
855 | else if (port->port_type == FMAN_PORT_TYPE_RX) { |
---|
856 | if (port->rev_info.major >= 6) |
---|
857 | min_fifo_size_required = (u32) |
---|
858 | (roundup(port->max_frame_length, |
---|
859 | FMAN_BMI_FIFO_UNITS) + |
---|
860 | (5 * FMAN_BMI_FIFO_UNITS)); |
---|
861 | /* 4 according to spec + 1 for FOF>0 */ |
---|
862 | else |
---|
863 | min_fifo_size_required = (u32) |
---|
864 | (roundup(min(port->max_frame_length, |
---|
865 | port->rx_pools_params.largest_buf_size), |
---|
866 | FMAN_BMI_FIFO_UNITS) + |
---|
867 | (7 * FMAN_BMI_FIFO_UNITS)); |
---|
868 | |
---|
869 | opt_fifo_size_for_b2b = min_fifo_size_required; |
---|
870 | |
---|
871 | /* Add some margin for back-to-back capability to improve |
---|
872 | * performance,allows the hardware to pipeline new frame dma |
---|
873 | * while the previous frame not yet transmitted. |
---|
874 | */ |
---|
875 | if (port->port_speed == 10000) |
---|
876 | opt_fifo_size_for_b2b += 8 * FMAN_BMI_FIFO_UNITS; |
---|
877 | else |
---|
878 | opt_fifo_size_for_b2b += 3 * FMAN_BMI_FIFO_UNITS; |
---|
879 | } |
---|
880 | |
---|
881 | WARN_ON(min_fifo_size_required <= 0); |
---|
882 | WARN_ON(opt_fifo_size_for_b2b < min_fifo_size_required); |
---|
883 | |
---|
884 | /* Verify the size */ |
---|
885 | if (port->fifo_bufs.num < min_fifo_size_required) |
---|
886 | pr_debug("FIFO size should be enlarged to %d bytes\n", |
---|
887 | min_fifo_size_required); |
---|
888 | else if (port->fifo_bufs.num < opt_fifo_size_for_b2b) |
---|
889 | pr_debug("For b2b processing,FIFO may be enlarged to %d bytes\n", |
---|
890 | opt_fifo_size_for_b2b); |
---|
891 | |
---|
892 | return 0; |
---|
893 | } |
---|
894 | |
---|
895 | static int set_ext_buffer_pools(struct fman_port *port) |
---|
896 | { |
---|
897 | struct fman_ext_pools *ext_buf_pools = &port->cfg->ext_buf_pools; |
---|
898 | struct fman_buf_pool_depletion *buf_pool_depletion = |
---|
899 | &port->cfg->buf_pool_depletion; |
---|
900 | u8 ordered_array[FMAN_PORT_MAX_EXT_POOLS_NUM]; |
---|
901 | u16 sizes_array[BM_MAX_NUM_OF_POOLS]; |
---|
902 | int i = 0, j = 0, err; |
---|
903 | struct fman_port_bpools bpools; |
---|
904 | |
---|
905 | memset(&ordered_array, 0, sizeof(u8) * FMAN_PORT_MAX_EXT_POOLS_NUM); |
---|
906 | memset(&sizes_array, 0, sizeof(u16) * BM_MAX_NUM_OF_POOLS); |
---|
907 | memcpy(&port->ext_buf_pools, ext_buf_pools, |
---|
908 | sizeof(struct fman_ext_pools)); |
---|
909 | |
---|
910 | fman_sp_set_buf_pools_in_asc_order_of_buf_sizes(ext_buf_pools, |
---|
911 | ordered_array, |
---|
912 | sizes_array); |
---|
913 | |
---|
914 | memset(&bpools, 0, sizeof(struct fman_port_bpools)); |
---|
915 | bpools.count = ext_buf_pools->num_of_pools_used; |
---|
916 | bpools.counters_enable = true; |
---|
917 | for (i = 0; i < ext_buf_pools->num_of_pools_used; i++) { |
---|
918 | bpools.bpool[i].bpid = ordered_array[i]; |
---|
919 | bpools.bpool[i].size = sizes_array[ordered_array[i]]; |
---|
920 | } |
---|
921 | |
---|
922 | /* save pools parameters for later use */ |
---|
923 | port->rx_pools_params.num_of_pools = ext_buf_pools->num_of_pools_used; |
---|
924 | port->rx_pools_params.largest_buf_size = |
---|
925 | sizes_array[ordered_array[ext_buf_pools->num_of_pools_used - 1]]; |
---|
926 | port->rx_pools_params.second_largest_buf_size = |
---|
927 | sizes_array[ordered_array[ext_buf_pools->num_of_pools_used - 2]]; |
---|
928 | |
---|
929 | /* FMBM_RMPD reg. - pool depletion */ |
---|
930 | if (buf_pool_depletion->pools_grp_mode_enable) { |
---|
931 | bpools.grp_bp_depleted_num = buf_pool_depletion->num_of_pools; |
---|
932 | for (i = 0; i < port->bm_max_num_of_pools; i++) { |
---|
933 | if (buf_pool_depletion->pools_to_consider[i]) { |
---|
934 | for (j = 0; j < ext_buf_pools-> |
---|
935 | num_of_pools_used; j++) { |
---|
936 | if (i == ordered_array[j]) { |
---|
937 | bpools.bpool[j]. |
---|
938 | grp_bp_depleted = true; |
---|
939 | break; |
---|
940 | } |
---|
941 | } |
---|
942 | } |
---|
943 | } |
---|
944 | } |
---|
945 | |
---|
946 | if (buf_pool_depletion->single_pool_mode_enable) { |
---|
947 | for (i = 0; i < port->bm_max_num_of_pools; i++) { |
---|
948 | if (buf_pool_depletion-> |
---|
949 | pools_to_consider_for_single_mode[i]) { |
---|
950 | for (j = 0; j < ext_buf_pools-> |
---|
951 | num_of_pools_used; j++) { |
---|
952 | if (i == ordered_array[j]) { |
---|
953 | bpools.bpool[j]. |
---|
954 | single_bp_depleted = true; |
---|
955 | break; |
---|
956 | } |
---|
957 | } |
---|
958 | } |
---|
959 | } |
---|
960 | } |
---|
961 | |
---|
962 | err = set_bpools(port, &bpools); |
---|
963 | if (err != 0) { |
---|
964 | pr_err("FMan port: set_bpools\n"); |
---|
965 | return -EINVAL; |
---|
966 | } |
---|
967 | |
---|
968 | return 0; |
---|
969 | } |
---|
970 | |
---|
971 | static int init_low_level_driver(struct fman_port *port) |
---|
972 | { |
---|
973 | struct fman_port_cfg *cfg = port->cfg; |
---|
974 | u32 tmp_val; |
---|
975 | |
---|
976 | switch (port->port_type) { |
---|
977 | case FMAN_PORT_TYPE_RX: |
---|
978 | cfg->err_mask = (RX_ERRS_TO_ENQ & ~cfg->discard_mask); |
---|
979 | if (cfg->forward_reuse_int_context) |
---|
980 | cfg->rx_fd_bits = (u8)(BMI_PORT_RFNE_FRWD_RPD >> 24); |
---|
981 | break; |
---|
982 | default: |
---|
983 | break; |
---|
984 | } |
---|
985 | |
---|
986 | tmp_val = (u32)((port->internal_buf_offset % OFFSET_UNITS) ? |
---|
987 | (port->internal_buf_offset / OFFSET_UNITS + 1) : |
---|
988 | (port->internal_buf_offset / OFFSET_UNITS)); |
---|
989 | port->internal_buf_offset = (u8)(tmp_val * OFFSET_UNITS); |
---|
990 | port->cfg->int_buf_start_margin = port->internal_buf_offset; |
---|
991 | |
---|
992 | if (init(port) != 0) { |
---|
993 | pr_err("fman_port_init\n"); |
---|
994 | return -ENODEV; |
---|
995 | } |
---|
996 | |
---|
997 | /* The code bellow is a trick so the FM will not release the buffer |
---|
998 | * to BM nor will try to enqueue the frame to QM |
---|
999 | */ |
---|
1000 | if (port->port_type == FMAN_PORT_TYPE_TX) { |
---|
1001 | if (!cfg->dflt_fqid && cfg->dont_release_buf) { |
---|
1002 | /* override fmbm_tcfqid 0 with a false non-0 value. |
---|
1003 | * This will force FM to act according to tfene. |
---|
1004 | * Otherwise, if fmbm_tcfqid is 0 the FM will release |
---|
1005 | * buffers to BM regardless of fmbm_tfene |
---|
1006 | */ |
---|
1007 | out_be32(&port->bmi_regs->tx.fmbm_tcfqid, 0xFFFFFF); |
---|
1008 | out_be32(&port->bmi_regs->tx.fmbm_tfene, |
---|
1009 | NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE); |
---|
1010 | } |
---|
1011 | } |
---|
1012 | |
---|
1013 | return 0; |
---|
1014 | } |
---|
1015 | |
---|
1016 | static int fill_soc_specific_params(struct fman_port *port) |
---|
1017 | { |
---|
1018 | u32 bmi_max_fifo_size; |
---|
1019 | |
---|
1020 | bmi_max_fifo_size = fman_get_bmi_max_fifo_size(port->fm); |
---|
1021 | port->max_port_fifo_size = MAX_PORT_FIFO_SIZE(bmi_max_fifo_size); |
---|
1022 | port->bm_max_num_of_pools = 64; |
---|
1023 | |
---|
1024 | /* P4080 - Major 2 |
---|
1025 | * P2041/P3041/P5020/P5040 - Major 3 |
---|
1026 | * Tx/Bx - Major 6 |
---|
1027 | */ |
---|
1028 | switch (port->rev_info.major) { |
---|
1029 | case 2: |
---|
1030 | case 3: |
---|
1031 | port->max_num_of_ext_pools = 4; |
---|
1032 | port->max_num_of_sub_portals = 12; |
---|
1033 | break; |
---|
1034 | |
---|
1035 | case 6: |
---|
1036 | port->max_num_of_ext_pools = 8; |
---|
1037 | port->max_num_of_sub_portals = 16; |
---|
1038 | break; |
---|
1039 | |
---|
1040 | default: |
---|
1041 | pr_err("Unsupported FMan version\n"); |
---|
1042 | return -EINVAL; |
---|
1043 | } |
---|
1044 | |
---|
1045 | return 0; |
---|
1046 | } |
---|
1047 | |
---|
1048 | static int get_dflt_fifo_deq_pipeline_depth(u8 major, enum fman_port_type type, |
---|
1049 | u16 speed) |
---|
1050 | { |
---|
1051 | switch (type) { |
---|
1052 | case FMAN_PORT_TYPE_RX: |
---|
1053 | case FMAN_PORT_TYPE_TX: |
---|
1054 | switch (speed) { |
---|
1055 | case 10000: |
---|
1056 | return 4; |
---|
1057 | case 1000: |
---|
1058 | if (major >= 6) |
---|
1059 | return 2; |
---|
1060 | else |
---|
1061 | return 1; |
---|
1062 | default: |
---|
1063 | return 0; |
---|
1064 | } |
---|
1065 | default: |
---|
1066 | return 0; |
---|
1067 | } |
---|
1068 | } |
---|
1069 | |
---|
1070 | static int get_dflt_num_of_tasks(u8 major, enum fman_port_type type, |
---|
1071 | u16 speed) |
---|
1072 | { |
---|
1073 | switch (type) { |
---|
1074 | case FMAN_PORT_TYPE_RX: |
---|
1075 | case FMAN_PORT_TYPE_TX: |
---|
1076 | switch (speed) { |
---|
1077 | case 10000: |
---|
1078 | return 16; |
---|
1079 | case 1000: |
---|
1080 | if (major >= 6) |
---|
1081 | return 4; |
---|
1082 | else |
---|
1083 | return 3; |
---|
1084 | default: |
---|
1085 | return 0; |
---|
1086 | } |
---|
1087 | default: |
---|
1088 | return 0; |
---|
1089 | } |
---|
1090 | } |
---|
1091 | |
---|
1092 | static int get_dflt_extra_num_of_tasks(u8 major, enum fman_port_type type, |
---|
1093 | u16 speed) |
---|
1094 | { |
---|
1095 | switch (type) { |
---|
1096 | case FMAN_PORT_TYPE_RX: |
---|
1097 | /* FMan V3 */ |
---|
1098 | if (major >= 6) |
---|
1099 | return 0; |
---|
1100 | |
---|
1101 | /* FMan V2 */ |
---|
1102 | if (speed == 10000) |
---|
1103 | return 8; |
---|
1104 | else |
---|
1105 | return 2; |
---|
1106 | case FMAN_PORT_TYPE_TX: |
---|
1107 | default: |
---|
1108 | return 0; |
---|
1109 | } |
---|
1110 | } |
---|
1111 | |
---|
1112 | static int get_dflt_num_of_open_dmas(u8 major, enum fman_port_type type, |
---|
1113 | u16 speed) |
---|
1114 | { |
---|
1115 | int val; |
---|
1116 | |
---|
1117 | if (major >= 6) { |
---|
1118 | switch (type) { |
---|
1119 | case FMAN_PORT_TYPE_TX: |
---|
1120 | if (speed == 10000) |
---|
1121 | val = 12; |
---|
1122 | else |
---|
1123 | val = 3; |
---|
1124 | break; |
---|
1125 | case FMAN_PORT_TYPE_RX: |
---|
1126 | if (speed == 10000) |
---|
1127 | val = 8; |
---|
1128 | else |
---|
1129 | val = 2; |
---|
1130 | break; |
---|
1131 | default: |
---|
1132 | return 0; |
---|
1133 | } |
---|
1134 | } else { |
---|
1135 | switch (type) { |
---|
1136 | case FMAN_PORT_TYPE_TX: |
---|
1137 | case FMAN_PORT_TYPE_RX: |
---|
1138 | if (speed == 10000) |
---|
1139 | val = 8; |
---|
1140 | else |
---|
1141 | val = 1; |
---|
1142 | break; |
---|
1143 | default: |
---|
1144 | val = 0; |
---|
1145 | } |
---|
1146 | } |
---|
1147 | |
---|
1148 | return val; |
---|
1149 | } |
---|
1150 | |
---|
1151 | static int get_dflt_extra_num_of_open_dmas(u8 major, enum fman_port_type type, |
---|
1152 | u16 speed) |
---|
1153 | { |
---|
1154 | /* FMan V3 */ |
---|
1155 | if (major >= 6) |
---|
1156 | return 0; |
---|
1157 | |
---|
1158 | /* FMan V2 */ |
---|
1159 | switch (type) { |
---|
1160 | case FMAN_PORT_TYPE_RX: |
---|
1161 | case FMAN_PORT_TYPE_TX: |
---|
1162 | if (speed == 10000) |
---|
1163 | return 8; |
---|
1164 | else |
---|
1165 | return 1; |
---|
1166 | default: |
---|
1167 | return 0; |
---|
1168 | } |
---|
1169 | } |
---|
1170 | |
---|
1171 | static int get_dflt_num_of_fifo_bufs(u8 major, enum fman_port_type type, |
---|
1172 | u16 speed) |
---|
1173 | { |
---|
1174 | int val; |
---|
1175 | |
---|
1176 | if (major >= 6) { |
---|
1177 | switch (type) { |
---|
1178 | case FMAN_PORT_TYPE_TX: |
---|
1179 | if (speed == 10000) |
---|
1180 | val = 64; |
---|
1181 | else |
---|
1182 | val = 50; |
---|
1183 | break; |
---|
1184 | case FMAN_PORT_TYPE_RX: |
---|
1185 | if (speed == 10000) |
---|
1186 | val = 96; |
---|
1187 | else |
---|
1188 | val = 50; |
---|
1189 | break; |
---|
1190 | default: |
---|
1191 | val = 0; |
---|
1192 | } |
---|
1193 | } else { |
---|
1194 | switch (type) { |
---|
1195 | case FMAN_PORT_TYPE_TX: |
---|
1196 | if (speed == 10000) |
---|
1197 | val = 48; |
---|
1198 | else |
---|
1199 | val = 44; |
---|
1200 | break; |
---|
1201 | case FMAN_PORT_TYPE_RX: |
---|
1202 | if (speed == 10000) |
---|
1203 | val = 48; |
---|
1204 | else |
---|
1205 | val = 45; |
---|
1206 | break; |
---|
1207 | default: |
---|
1208 | val = 0; |
---|
1209 | } |
---|
1210 | } |
---|
1211 | |
---|
1212 | return val; |
---|
1213 | } |
---|
1214 | |
---|
1215 | static void set_dflt_cfg(struct fman_port *port, |
---|
1216 | struct fman_port_params *port_params) |
---|
1217 | { |
---|
1218 | struct fman_port_cfg *cfg = port->cfg; |
---|
1219 | |
---|
1220 | cfg->dma_swap_data = FMAN_PORT_DMA_NO_SWAP; |
---|
1221 | cfg->dma_write_optimize = true; |
---|
1222 | cfg->color = FMAN_PORT_COLOR_GREEN; |
---|
1223 | cfg->rx_cut_end_bytes = DFLT_PORT_CUT_BYTES_FROM_END; |
---|
1224 | cfg->rx_pri_elevation = BMI_PRIORITY_ELEVATION_LEVEL; |
---|
1225 | cfg->rx_fifo_thr = BMI_FIFO_THRESHOLD; |
---|
1226 | cfg->tx_fifo_low_comf_level = (5 * 1024); |
---|
1227 | cfg->deq_type = FMAN_PORT_DEQ_BY_PRI; |
---|
1228 | cfg->sync_req = true; |
---|
1229 | cfg->deq_prefetch_option = FMAN_PORT_DEQ_FULL_PREFETCH; |
---|
1230 | cfg->tx_fifo_deq_pipeline_depth = |
---|
1231 | BMI_DEQUEUE_PIPELINE_DEPTH(port->port_type, port->port_speed); |
---|
1232 | cfg->deq_byte_cnt = QMI_BYTE_COUNT_LEVEL_CONTROL(port->port_type); |
---|
1233 | |
---|
1234 | cfg->rx_pri_elevation = |
---|
1235 | DFLT_PORT_RX_FIFO_PRI_ELEVATION_LEV(port->max_port_fifo_size); |
---|
1236 | port->cfg->rx_fifo_thr = |
---|
1237 | DFLT_PORT_RX_FIFO_THRESHOLD(port->rev_info.major, |
---|
1238 | port->max_port_fifo_size); |
---|
1239 | |
---|
1240 | if ((port->rev_info.major == 6) && |
---|
1241 | ((port->rev_info.minor == 0) || (port->rev_info.minor == 3))) |
---|
1242 | cfg->errata_A006320 = true; |
---|
1243 | |
---|
1244 | /* Excessive Threshold register - exists for pre-FMv3 chips only */ |
---|
1245 | if (port->rev_info.major < 6) { |
---|
1246 | cfg->excessive_threshold_register = true; |
---|
1247 | } else { |
---|
1248 | cfg->fmbm_rebm_has_sgd = true; |
---|
1249 | cfg->fmbm_tfne_has_features = true; |
---|
1250 | } |
---|
1251 | |
---|
1252 | cfg->qmi_deq_options_support = true; |
---|
1253 | |
---|
1254 | cfg->buffer_prefix_content.data_align = |
---|
1255 | DFLT_PORT_BUFFER_PREFIX_CONTEXT_DATA_ALIGN; |
---|
1256 | } |
---|
1257 | |
---|
1258 | static void set_rx_dflt_cfg(struct fman_port *port, |
---|
1259 | struct fman_port_params *port_params) |
---|
1260 | { |
---|
1261 | port->cfg->discard_mask = DFLT_PORT_ERRORS_TO_DISCARD; |
---|
1262 | |
---|
1263 | memcpy(&port->cfg->ext_buf_pools, |
---|
1264 | &port_params->specific_params.rx_params.ext_buf_pools, |
---|
1265 | sizeof(struct fman_ext_pools)); |
---|
1266 | port->cfg->err_fqid = |
---|
1267 | port_params->specific_params.rx_params.err_fqid; |
---|
1268 | port->cfg->dflt_fqid = |
---|
1269 | port_params->specific_params.rx_params.dflt_fqid; |
---|
1270 | |
---|
1271 | /* Set BCB workaround on Rx ports, only for B4860 rev1 */ |
---|
1272 | if (port->rev_info.major >= 6) { |
---|
1273 | unsigned int svr; |
---|
1274 | |
---|
1275 | svr = mfspr(SPRN_SVR); |
---|
1276 | if ((SVR_SOC_VER(svr) == SVR_B4860) && (SVR_MAJ(svr) == 1)) |
---|
1277 | port->cfg->bcb_workaround = true; |
---|
1278 | } |
---|
1279 | } |
---|
1280 | |
---|
1281 | static void set_tx_dflt_cfg(struct fman_port *port, |
---|
1282 | struct fman_port_params *port_params, |
---|
1283 | struct fman_port_dts_params *dts_params) |
---|
1284 | { |
---|
1285 | port->cfg->tx_fifo_deq_pipeline_depth = |
---|
1286 | get_dflt_fifo_deq_pipeline_depth(port->rev_info.major, |
---|
1287 | port->port_type, |
---|
1288 | port->port_speed); |
---|
1289 | port->cfg->err_fqid = |
---|
1290 | port_params->specific_params.non_rx_params.err_fqid; |
---|
1291 | port->cfg->deq_sp = |
---|
1292 | (u8)(dts_params->qman_channel_id & QMI_DEQ_CFG_SUBPORTAL_MASK); |
---|
1293 | port->cfg->dflt_fqid = |
---|
1294 | port_params->specific_params.non_rx_params.dflt_fqid; |
---|
1295 | port->cfg->deq_high_priority = true; |
---|
1296 | } |
---|
1297 | |
---|
1298 | int fman_port_config(struct fman_port *port, struct fman_port_params *params) |
---|
1299 | { |
---|
1300 | void __iomem *base_addr = port->dts_params.base_addr; |
---|
1301 | int err; |
---|
1302 | |
---|
1303 | /* Allocate the FM driver's parameters structure */ |
---|
1304 | port->cfg = kzalloc(sizeof(*port->cfg), GFP_KERNEL); |
---|
1305 | if (!port->cfg) |
---|
1306 | goto err_params; |
---|
1307 | |
---|
1308 | /* Initialize FM port parameters which will be kept by the driver */ |
---|
1309 | port->port_type = port->dts_params.type; |
---|
1310 | port->port_speed = port->dts_params.speed; |
---|
1311 | port->port_id = port->dts_params.id; |
---|
1312 | port->fm = port->dts_params.fman; |
---|
1313 | port->ext_pools_num = (u8)8; |
---|
1314 | |
---|
1315 | /* get FM revision */ |
---|
1316 | fman_get_revision(port->fm, &port->rev_info); |
---|
1317 | |
---|
1318 | err = fill_soc_specific_params(port); |
---|
1319 | if (err) |
---|
1320 | goto err_port_cfg; |
---|
1321 | |
---|
1322 | switch (port->port_type) { |
---|
1323 | case FMAN_PORT_TYPE_RX: |
---|
1324 | set_rx_dflt_cfg(port, params); |
---|
1325 | case FMAN_PORT_TYPE_TX: |
---|
1326 | set_tx_dflt_cfg(port, params, &port->dts_params); |
---|
1327 | default: |
---|
1328 | set_dflt_cfg(port, params); |
---|
1329 | } |
---|
1330 | |
---|
1331 | /* Continue with other parameters */ |
---|
1332 | /* set memory map pointers */ |
---|
1333 | port->bmi_regs = (union fman_port_bmi_regs __iomem *) |
---|
1334 | (base_addr + BMI_PORT_REGS_OFFSET); |
---|
1335 | port->qmi_regs = (struct fman_port_qmi_regs __iomem *) |
---|
1336 | (base_addr + QMI_PORT_REGS_OFFSET); |
---|
1337 | |
---|
1338 | port->max_frame_length = DFLT_PORT_MAX_FRAME_LENGTH; |
---|
1339 | /* resource distribution. */ |
---|
1340 | |
---|
1341 | port->fifo_bufs.num = |
---|
1342 | get_dflt_num_of_fifo_bufs(port->rev_info.major, port->port_type, |
---|
1343 | port->port_speed) * FMAN_BMI_FIFO_UNITS; |
---|
1344 | port->fifo_bufs.extra = |
---|
1345 | DFLT_PORT_EXTRA_NUM_OF_FIFO_BUFS * FMAN_BMI_FIFO_UNITS; |
---|
1346 | |
---|
1347 | port->open_dmas.num = |
---|
1348 | get_dflt_num_of_open_dmas(port->rev_info.major, |
---|
1349 | port->port_type, port->port_speed); |
---|
1350 | port->open_dmas.extra = |
---|
1351 | get_dflt_extra_num_of_open_dmas(port->rev_info.major, |
---|
1352 | port->port_type, port->port_speed); |
---|
1353 | port->tasks.num = |
---|
1354 | get_dflt_num_of_tasks(port->rev_info.major, |
---|
1355 | port->port_type, port->port_speed); |
---|
1356 | port->tasks.extra = |
---|
1357 | get_dflt_extra_num_of_tasks(port->rev_info.major, |
---|
1358 | port->port_type, port->port_speed); |
---|
1359 | |
---|
1360 | /* FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 errata |
---|
1361 | * workaround |
---|
1362 | */ |
---|
1363 | if ((port->rev_info.major == 6) && (port->rev_info.minor == 0) && |
---|
1364 | (((port->port_type == FMAN_PORT_TYPE_TX) && |
---|
1365 | (port->port_speed == 1000)))) { |
---|
1366 | port->open_dmas.num = 16; |
---|
1367 | port->open_dmas.extra = 0; |
---|
1368 | } |
---|
1369 | |
---|
1370 | if (port->rev_info.major >= 6 && |
---|
1371 | port->port_type == FMAN_PORT_TYPE_TX && |
---|
1372 | port->port_speed == 1000) { |
---|
1373 | /* FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 Errata |
---|
1374 | * workaround |
---|
1375 | */ |
---|
1376 | if (port->rev_info.major >= 6) { |
---|
1377 | u32 reg; |
---|
1378 | |
---|
1379 | reg = 0x00001013; |
---|
1380 | out_be32(&port->bmi_regs->tx.fmbm_tfp, reg); |
---|
1381 | } |
---|
1382 | } |
---|
1383 | |
---|
1384 | return 0; |
---|
1385 | |
---|
1386 | err_port_cfg: |
---|
1387 | kfree(port->cfg); |
---|
1388 | err_params: |
---|
1389 | kfree(port); |
---|
1390 | return -EINVAL; |
---|
1391 | } |
---|
1392 | EXPORT_SYMBOL(fman_port_config); |
---|
1393 | |
---|
1394 | int fman_port_init(struct fman_port *port) |
---|
1395 | { |
---|
1396 | struct fman_port_cfg *cfg; |
---|
1397 | int err; |
---|
1398 | struct fman_port_init_params params; |
---|
1399 | |
---|
1400 | if (is_init_done(port->cfg)) |
---|
1401 | return -EINVAL; |
---|
1402 | |
---|
1403 | err = fman_sp_build_buffer_struct(&port->cfg->int_context, |
---|
1404 | &port->cfg->buffer_prefix_content, |
---|
1405 | &port->cfg->buf_margins, |
---|
1406 | &port->buffer_offsets, |
---|
1407 | &port->internal_buf_offset); |
---|
1408 | if (err) |
---|
1409 | return err; |
---|
1410 | |
---|
1411 | /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 Errata workaround */ |
---|
1412 | if (port->rev_info.major >= 6 && (port->cfg->bcb_workaround) && |
---|
1413 | ((port->port_type == FMAN_PORT_TYPE_RX) && |
---|
1414 | (port->port_speed == 1000))) { |
---|
1415 | port->cfg->discard_mask |= FM_PORT_FRM_ERR_PHYSICAL; |
---|
1416 | port->fifo_bufs.num += 4 * 1024; |
---|
1417 | } |
---|
1418 | |
---|
1419 | cfg = port->cfg; |
---|
1420 | |
---|
1421 | if (port->port_type == FMAN_PORT_TYPE_RX) { |
---|
1422 | /* Call the external Buffer routine which also checks fifo |
---|
1423 | * size and updates it if necessary |
---|
1424 | */ |
---|
1425 | /* define external buffer pools and pool depletion */ |
---|
1426 | err = set_ext_buffer_pools(port); |
---|
1427 | if (err) |
---|
1428 | return err; |
---|
1429 | /* check if the largest external buffer pool is large enough */ |
---|
1430 | if (cfg->buf_margins.start_margins + MIN_EXT_BUF_SIZE + |
---|
1431 | cfg->buf_margins.end_margins > |
---|
1432 | port->rx_pools_params.largest_buf_size) { |
---|
1433 | pr_err("buf_margins.start_margins (%d) + minimum buf size (64) + buf_margins.end_margins (%d) is larger than maximum external buffer size (%d)\n", |
---|
1434 | cfg->buf_margins.start_margins, |
---|
1435 | cfg->buf_margins.end_margins, |
---|
1436 | port->rx_pools_params.largest_buf_size); |
---|
1437 | return -EINVAL; |
---|
1438 | } |
---|
1439 | } |
---|
1440 | |
---|
1441 | /* Call FM module routine for communicating parameters */ |
---|
1442 | memset(¶ms, 0, sizeof(params)); |
---|
1443 | params.port_id = port->port_id; |
---|
1444 | params.port_type = port->port_type; |
---|
1445 | params.port_speed = port->port_speed; |
---|
1446 | params.num_of_tasks = (u8)port->tasks.num; |
---|
1447 | params.num_of_extra_tasks = (u8)port->tasks.extra; |
---|
1448 | params.num_of_open_dmas = (u8)port->open_dmas.num; |
---|
1449 | params.num_of_extra_open_dmas = (u8)port->open_dmas.extra; |
---|
1450 | |
---|
1451 | if (port->fifo_bufs.num) { |
---|
1452 | err = verify_size_of_fifo(port); |
---|
1453 | if (err) |
---|
1454 | return err; |
---|
1455 | } |
---|
1456 | params.size_of_fifo = port->fifo_bufs.num; |
---|
1457 | params.extra_size_of_fifo = port->fifo_bufs.extra; |
---|
1458 | params.deq_pipeline_depth = port->cfg->tx_fifo_deq_pipeline_depth; |
---|
1459 | params.max_frame_length = port->max_frame_length; |
---|
1460 | |
---|
1461 | err = fman_set_port_params(port->fm, ¶ms); |
---|
1462 | if (err) |
---|
1463 | return err; |
---|
1464 | |
---|
1465 | err = init_low_level_driver(port); |
---|
1466 | if (err) |
---|
1467 | return err; |
---|
1468 | |
---|
1469 | kfree(port->cfg); |
---|
1470 | port->cfg = NULL; |
---|
1471 | |
---|
1472 | return 0; |
---|
1473 | } |
---|
1474 | EXPORT_SYMBOL(fman_port_init); |
---|
1475 | |
---|
1476 | int fman_port_cfg_buf_prefix_content(struct fman_port *port, |
---|
1477 | struct fman_buffer_prefix_content * |
---|
1478 | buffer_prefix_content) |
---|
1479 | { |
---|
1480 | if (is_init_done(port->cfg)) |
---|
1481 | return -EINVAL; |
---|
1482 | |
---|
1483 | memcpy(&port->cfg->buffer_prefix_content, |
---|
1484 | buffer_prefix_content, |
---|
1485 | sizeof(struct fman_buffer_prefix_content)); |
---|
1486 | /* if data_align was not initialized by user, |
---|
1487 | * we return to driver's default |
---|
1488 | */ |
---|
1489 | if (!port->cfg->buffer_prefix_content.data_align) |
---|
1490 | port->cfg->buffer_prefix_content.data_align = |
---|
1491 | DFLT_PORT_BUFFER_PREFIX_CONTEXT_DATA_ALIGN; |
---|
1492 | |
---|
1493 | return 0; |
---|
1494 | } |
---|
1495 | EXPORT_SYMBOL(fman_port_cfg_buf_prefix_content); |
---|
1496 | |
---|
1497 | int fman_port_disable(struct fman_port *port) |
---|
1498 | { |
---|
1499 | u32 __iomem *bmi_cfg_reg, *bmi_status_reg, tmp; |
---|
1500 | bool rx_port, failure = false; |
---|
1501 | int count; |
---|
1502 | |
---|
1503 | if (!is_init_done(port->cfg)) |
---|
1504 | return -EINVAL; |
---|
1505 | |
---|
1506 | switch (port->port_type) { |
---|
1507 | case FMAN_PORT_TYPE_RX: |
---|
1508 | bmi_cfg_reg = &port->bmi_regs->rx.fmbm_rcfg; |
---|
1509 | bmi_status_reg = &port->bmi_regs->rx.fmbm_rst; |
---|
1510 | rx_port = true; |
---|
1511 | break; |
---|
1512 | case FMAN_PORT_TYPE_TX: |
---|
1513 | bmi_cfg_reg = &port->bmi_regs->tx.fmbm_tcfg; |
---|
1514 | bmi_status_reg = &port->bmi_regs->tx.fmbm_tst; |
---|
1515 | rx_port = false; |
---|
1516 | break; |
---|
1517 | default: |
---|
1518 | return -EINVAL; |
---|
1519 | } |
---|
1520 | |
---|
1521 | /* Disable QMI */ |
---|
1522 | if (!rx_port) { |
---|
1523 | tmp = ioread32be(&port->qmi_regs->fmqm_pnc) & ~QMI_PORT_CFG_EN; |
---|
1524 | iowrite32be(tmp, &port->qmi_regs->fmqm_pnc); |
---|
1525 | |
---|
1526 | /* Wait for QMI to finish FD handling */ |
---|
1527 | count = 100; |
---|
1528 | do { |
---|
1529 | udelay(10); |
---|
1530 | tmp = ioread32be(&port->qmi_regs->fmqm_pns); |
---|
1531 | } while ((tmp & QMI_PORT_STATUS_DEQ_FD_BSY) && --count); |
---|
1532 | |
---|
1533 | if (count == 0) { |
---|
1534 | /* Timeout */ |
---|
1535 | failure = true; |
---|
1536 | } |
---|
1537 | } |
---|
1538 | |
---|
1539 | /* Disable BMI */ |
---|
1540 | tmp = ioread32be(bmi_cfg_reg) & ~BMI_PORT_CFG_EN; |
---|
1541 | iowrite32be(tmp, bmi_cfg_reg); |
---|
1542 | |
---|
1543 | /* Wait for graceful stop end */ |
---|
1544 | count = 500; |
---|
1545 | do { |
---|
1546 | udelay(10); |
---|
1547 | tmp = ioread32be(bmi_status_reg); |
---|
1548 | } while ((tmp & BMI_PORT_STATUS_BSY) && --count); |
---|
1549 | |
---|
1550 | if (count == 0) { |
---|
1551 | /* Timeout */ |
---|
1552 | failure = true; |
---|
1553 | } |
---|
1554 | |
---|
1555 | if (failure) |
---|
1556 | pr_debug("FMan Port[%d]: BMI or QMI is Busy. Port forced down\n", |
---|
1557 | port->port_id); |
---|
1558 | |
---|
1559 | return 0; |
---|
1560 | } |
---|
1561 | EXPORT_SYMBOL(fman_port_disable); |
---|
1562 | |
---|
1563 | int fman_port_enable(struct fman_port *port) |
---|
1564 | { |
---|
1565 | u32 __iomem *bmi_cfg_reg, tmp; |
---|
1566 | bool rx_port; |
---|
1567 | |
---|
1568 | if (!is_init_done(port->cfg)) |
---|
1569 | return -EINVAL; |
---|
1570 | |
---|
1571 | switch (port->port_type) { |
---|
1572 | case FMAN_PORT_TYPE_RX: |
---|
1573 | bmi_cfg_reg = &port->bmi_regs->rx.fmbm_rcfg; |
---|
1574 | rx_port = true; |
---|
1575 | break; |
---|
1576 | case FMAN_PORT_TYPE_TX: |
---|
1577 | bmi_cfg_reg = &port->bmi_regs->tx.fmbm_tcfg; |
---|
1578 | rx_port = false; |
---|
1579 | break; |
---|
1580 | default: |
---|
1581 | return -EINVAL; |
---|
1582 | } |
---|
1583 | |
---|
1584 | /* Enable QMI */ |
---|
1585 | if (!rx_port) { |
---|
1586 | tmp = ioread32be(&port->qmi_regs->fmqm_pnc) | QMI_PORT_CFG_EN; |
---|
1587 | iowrite32be(tmp, &port->qmi_regs->fmqm_pnc); |
---|
1588 | } |
---|
1589 | |
---|
1590 | /* Enable BMI */ |
---|
1591 | tmp = ioread32be(bmi_cfg_reg) | BMI_PORT_CFG_EN; |
---|
1592 | iowrite32be(tmp, bmi_cfg_reg); |
---|
1593 | |
---|
1594 | return 0; |
---|
1595 | } |
---|
1596 | EXPORT_SYMBOL(fman_port_enable); |
---|
1597 | |
---|
1598 | struct fman_port *fman_port_bind(struct device *dev) |
---|
1599 | { |
---|
1600 | return (struct fman_port *)(dev_get_drvdata(get_device(dev))); |
---|
1601 | } |
---|
1602 | EXPORT_SYMBOL(fman_port_bind); |
---|
1603 | |
---|
1604 | u32 fman_port_get_qman_channel_id(struct fman_port *port) |
---|
1605 | { |
---|
1606 | return port->dts_params.qman_channel_id; |
---|
1607 | } |
---|
1608 | EXPORT_SYMBOL(fman_port_get_qman_channel_id); |
---|
1609 | |
---|
1610 | #ifndef __rtems__ |
---|
1611 | static int fman_port_probe(struct platform_device *of_dev) |
---|
1612 | #else /* __rtems__ */ |
---|
1613 | static int fman_port_probe(struct platform_device *of_dev, struct fman *fman) |
---|
1614 | #endif /* __rtems__ */ |
---|
1615 | { |
---|
1616 | struct fman_port *port; |
---|
1617 | #ifndef __rtems__ |
---|
1618 | struct fman *fman; |
---|
1619 | struct device_node *fm_node, *port_node; |
---|
1620 | #else /* __rtems__ */ |
---|
1621 | struct device_node *port_node; |
---|
1622 | #endif /* __rtems__ */ |
---|
1623 | struct resource res; |
---|
1624 | #ifndef __rtems__ |
---|
1625 | struct resource *dev_res; |
---|
1626 | #endif /* __rtems__ */ |
---|
1627 | const u32 *u32_prop; |
---|
1628 | int err = 0, lenp; |
---|
1629 | enum fman_port_type port_type; |
---|
1630 | u16 port_speed; |
---|
1631 | u8 port_id; |
---|
1632 | |
---|
1633 | port = kzalloc(sizeof(*port), GFP_KERNEL); |
---|
1634 | if (!port) |
---|
1635 | return -ENOMEM; |
---|
1636 | |
---|
1637 | port_node = of_node_get(of_dev->dev.of_node); |
---|
1638 | |
---|
1639 | /* Get the FM node */ |
---|
1640 | #ifndef __rtems__ |
---|
1641 | fm_node = of_get_parent(port_node); |
---|
1642 | if (!fm_node) { |
---|
1643 | pr_err("of_get_parent() failed\n"); |
---|
1644 | err = -ENODEV; |
---|
1645 | goto return_err; |
---|
1646 | } |
---|
1647 | |
---|
1648 | fman = dev_get_drvdata(&of_find_device_by_node(fm_node)->dev); |
---|
1649 | of_node_put(fm_node); |
---|
1650 | if (!fman) { |
---|
1651 | err = -EINVAL; |
---|
1652 | goto return_err; |
---|
1653 | } |
---|
1654 | #endif /* __rtems__ */ |
---|
1655 | |
---|
1656 | u32_prop = (const u32 *)of_get_property(port_node, "cell-index", &lenp); |
---|
1657 | if (!u32_prop) { |
---|
1658 | pr_err("of_get_property(%s, cell-index) failed\n", |
---|
1659 | port_node->full_name); |
---|
1660 | err = -EINVAL; |
---|
1661 | goto return_err; |
---|
1662 | } |
---|
1663 | if (WARN_ON(lenp != sizeof(u32))) { |
---|
1664 | err = -EINVAL; |
---|
1665 | goto return_err; |
---|
1666 | } |
---|
1667 | port_id = (u8)*u32_prop; |
---|
1668 | |
---|
1669 | port->dts_params.id = port_id; |
---|
1670 | |
---|
1671 | if (of_device_is_compatible(port_node, "fsl,fman-v3-port-tx")) { |
---|
1672 | port_type = FMAN_PORT_TYPE_TX; |
---|
1673 | port_speed = 1000; |
---|
1674 | u32_prop = (const u32 *)of_get_property(port_node, |
---|
1675 | "fsl,fman-10g-port", |
---|
1676 | &lenp); |
---|
1677 | if (u32_prop) |
---|
1678 | port_speed = 10000; |
---|
1679 | |
---|
1680 | } else if (of_device_is_compatible(port_node, "fsl,fman-v2-port-tx")) { |
---|
1681 | if (port_id >= TX_10G_PORT_BASE) |
---|
1682 | port_speed = 10000; |
---|
1683 | else |
---|
1684 | port_speed = 1000; |
---|
1685 | port_type = FMAN_PORT_TYPE_TX; |
---|
1686 | |
---|
1687 | } else if (of_device_is_compatible(port_node, "fsl,fman-v3-port-rx")) { |
---|
1688 | port_type = FMAN_PORT_TYPE_RX; |
---|
1689 | port_speed = 1000; |
---|
1690 | u32_prop = (const u32 *)of_get_property(port_node, |
---|
1691 | "fsl,fman-10g-port", &lenp); |
---|
1692 | if (u32_prop) |
---|
1693 | port_speed = 10000; |
---|
1694 | |
---|
1695 | } else if (of_device_is_compatible(port_node, "fsl,fman-v2-port-rx")) { |
---|
1696 | if (port_id >= RX_10G_PORT_BASE) |
---|
1697 | port_speed = 10000; |
---|
1698 | else |
---|
1699 | port_speed = 1000; |
---|
1700 | port_type = FMAN_PORT_TYPE_RX; |
---|
1701 | |
---|
1702 | } else { |
---|
1703 | pr_err("Illegal port type\n"); |
---|
1704 | err = -EINVAL; |
---|
1705 | goto return_err; |
---|
1706 | } |
---|
1707 | |
---|
1708 | port->dts_params.type = port_type; |
---|
1709 | port->dts_params.speed = port_speed; |
---|
1710 | |
---|
1711 | if (port_type == FMAN_PORT_TYPE_TX) { |
---|
1712 | u32 qman_channel_id; |
---|
1713 | |
---|
1714 | qman_channel_id = fman_get_qman_channel_id(fman, port_id); |
---|
1715 | if (qman_channel_id == 0) { |
---|
1716 | pr_err("incorrect qman-channel-id\n"); |
---|
1717 | err = -EINVAL; |
---|
1718 | goto return_err; |
---|
1719 | } |
---|
1720 | port->dts_params.qman_channel_id = qman_channel_id; |
---|
1721 | } |
---|
1722 | |
---|
1723 | err = of_address_to_resource(port_node, 0, &res); |
---|
1724 | if (err < 0) { |
---|
1725 | pr_err("of_address_to_resource() failed\n"); |
---|
1726 | err = -ENOMEM; |
---|
1727 | goto return_err; |
---|
1728 | } |
---|
1729 | |
---|
1730 | port->dts_params.fman = fman; |
---|
1731 | |
---|
1732 | of_node_put(port_node); |
---|
1733 | |
---|
1734 | #ifndef __rtems__ |
---|
1735 | dev_res = __devm_request_region(fman_get_device(fman), &res, |
---|
1736 | res.start, (res.end + 1 - res.start), |
---|
1737 | "fman-port"); |
---|
1738 | if (!dev_res) { |
---|
1739 | pr_err("__devm_request_region() failed\n"); |
---|
1740 | err = -EINVAL; |
---|
1741 | goto free_port; |
---|
1742 | } |
---|
1743 | #endif /* __rtems__ */ |
---|
1744 | |
---|
1745 | port->dts_params.base_addr = devm_ioremap(fman_get_device(fman), |
---|
1746 | res.start, |
---|
1747 | (res.end + 1 - res.start)); |
---|
1748 | if (port->dts_params.base_addr == 0) |
---|
1749 | pr_err("devm_ioremap() failed\n"); |
---|
1750 | |
---|
1751 | dev_set_drvdata(&of_dev->dev, port); |
---|
1752 | |
---|
1753 | return 0; |
---|
1754 | |
---|
1755 | return_err: |
---|
1756 | of_node_put(port_node); |
---|
1757 | #ifndef __rtems__ |
---|
1758 | free_port: |
---|
1759 | #endif /* __rtems__ */ |
---|
1760 | kfree(port); |
---|
1761 | return err; |
---|
1762 | } |
---|
1763 | |
---|
1764 | #ifndef __rtems__ |
---|
1765 | static const struct of_device_id fman_port_match[] = { |
---|
1766 | {.compatible = "fsl,fman-v3-port-rx"}, |
---|
1767 | {.compatible = "fsl,fman-v2-port-rx"}, |
---|
1768 | {.compatible = "fsl,fman-v3-port-tx"}, |
---|
1769 | {.compatible = "fsl,fman-v2-port-tx"}, |
---|
1770 | {} |
---|
1771 | }; |
---|
1772 | |
---|
1773 | MODULE_DEVICE_TABLE(of, fman_port_match); |
---|
1774 | |
---|
1775 | static struct platform_driver fman_port_driver = { |
---|
1776 | .driver = { |
---|
1777 | .name = "fsl-fman-port", |
---|
1778 | .of_match_table = fman_port_match, |
---|
1779 | }, |
---|
1780 | .probe = fman_port_probe, |
---|
1781 | }; |
---|
1782 | |
---|
1783 | builtin_platform_driver(fman_port_driver); |
---|
1784 | |
---|
1785 | #else /* __rtems__ */ |
---|
1786 | #include <sys/cdefs.h> |
---|
1787 | #include <sys/param.h> |
---|
1788 | #include <sys/systm.h> |
---|
1789 | #include <sys/bus.h> |
---|
1790 | #include <sys/kernel.h> |
---|
1791 | |
---|
1792 | static int |
---|
1793 | fman_port_dev_probe(device_t dev) |
---|
1794 | { |
---|
1795 | struct fman_ivars *ivars = device_get_ivars(dev); |
---|
1796 | int err; |
---|
1797 | |
---|
1798 | err = fman_port_probe(&ivars->of_dev, ivars->fman); |
---|
1799 | if (err == 0) { |
---|
1800 | device_set_desc(dev, "FMan Port"); |
---|
1801 | return (BUS_PROBE_DEFAULT); |
---|
1802 | } else { |
---|
1803 | return (ENXIO); |
---|
1804 | } |
---|
1805 | } |
---|
1806 | |
---|
1807 | static device_method_t fman_port_methods[] = { |
---|
1808 | /* Device interface */ |
---|
1809 | DEVMETHOD(device_probe, fman_port_dev_probe), |
---|
1810 | DEVMETHOD(device_attach, bus_generic_attach), |
---|
1811 | DEVMETHOD(device_detach, bus_generic_detach), |
---|
1812 | DEVMETHOD(device_suspend, bus_generic_suspend), |
---|
1813 | DEVMETHOD(device_resume, bus_generic_resume), |
---|
1814 | DEVMETHOD(device_shutdown, bus_generic_shutdown), |
---|
1815 | |
---|
1816 | DEVMETHOD_END |
---|
1817 | }; |
---|
1818 | |
---|
1819 | driver_t fman_port_driver = { |
---|
1820 | .name = "fman_port", |
---|
1821 | .methods = fman_port_methods |
---|
1822 | }; |
---|
1823 | |
---|
1824 | static devclass_t fman_port_devclass; |
---|
1825 | |
---|
1826 | DRIVER_MODULE(fman_port, fman_mac, fman_port_driver, fman_port_devclass, 0, 0); |
---|
1827 | #endif /* __rtems__ */ |
---|