OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From 92cf25fe454dd42136e717ba679a9dba740db0e7 Mon Sep 17 00:00:00 2001 |
2 | From: Biwen Li <biwen.li@nxp.com> |
||
3 | Date: Tue, 30 Oct 2018 18:26:18 +0800 |
||
4 | Subject: [PATCH 10/40] dpaa2-mac-phy: support layerscape |
||
5 | This is an integrated patch of dpaa2-mac-phy for |
||
6 | layerscape |
||
7 | |||
8 | Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com> |
||
9 | Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com> |
||
10 | Signed-off-by: Bogdan Purcareata <bogdan.purcareata@nxp.com> |
||
11 | Signed-off-by: Constantin Tudor <constantin.tudor@nxp.com> |
||
12 | Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com> |
||
13 | Signed-off-by: Itai Katz <itai.katz@freescale.com> |
||
14 | Signed-off-by: J. German Rivera <German.Rivera@freescale.com> |
||
15 | Signed-off-by: Razvan Stefanescu <razvan.stefanescu@nxp.com> |
||
16 | Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com> |
||
17 | Signed-off-by: Biwen Li <biwen.li@nxp.com> |
||
18 | --- |
||
19 | drivers/staging/fsl-dpaa2/mac/Kconfig | 23 + |
||
20 | drivers/staging/fsl-dpaa2/mac/Makefile | 10 + |
||
21 | drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h | 172 ++++++ |
||
22 | drivers/staging/fsl-dpaa2/mac/dpmac.c | 619 ++++++++++++++++++++ |
||
23 | drivers/staging/fsl-dpaa2/mac/dpmac.h | 342 +++++++++++ |
||
24 | drivers/staging/fsl-dpaa2/mac/mac.c | 672 ++++++++++++++++++++++ |
||
25 | 6 files changed, 1838 insertions(+) |
||
26 | create mode 100644 drivers/staging/fsl-dpaa2/mac/Kconfig |
||
27 | create mode 100644 drivers/staging/fsl-dpaa2/mac/Makefile |
||
28 | create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h |
||
29 | create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac.c |
||
30 | create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac.h |
||
31 | create mode 100644 drivers/staging/fsl-dpaa2/mac/mac.c |
||
32 | |||
33 | --- /dev/null |
||
34 | +++ b/drivers/staging/fsl-dpaa2/mac/Kconfig |
||
35 | @@ -0,0 +1,23 @@ |
||
36 | +config FSL_DPAA2_MAC |
||
37 | + tristate "DPAA2 MAC / PHY interface" |
||
38 | + depends on FSL_MC_BUS && FSL_DPAA2 |
||
39 | + select MDIO_BUS_MUX_MMIOREG |
||
40 | + select FSL_XGMAC_MDIO |
||
41 | + select FIXED_PHY |
||
42 | + ---help--- |
||
43 | + Prototype driver for DPAA2 MAC / PHY interface object. |
||
44 | + This driver works as a proxy between phylib including phy drivers and |
||
45 | + the MC firmware. It receives updates on link state changes from PHY |
||
46 | + lib and forwards them to MC and receives interrupt from MC whenever |
||
47 | + a request is made to change the link state. |
||
48 | + |
||
49 | + |
||
50 | +config FSL_DPAA2_MAC_NETDEVS |
||
51 | + bool "Expose net interfaces for PHYs" |
||
52 | + default n |
||
53 | + depends on FSL_DPAA2_MAC |
||
54 | + ---help--- |
||
55 | + Exposes macX net interfaces which allow direct control over MACs and |
||
56 | + PHYs. |
||
57 | + . |
||
58 | + Leave disabled if unsure. |
||
59 | --- /dev/null |
||
60 | +++ b/drivers/staging/fsl-dpaa2/mac/Makefile |
||
61 | @@ -0,0 +1,10 @@ |
||
62 | + |
||
63 | +obj-$(CONFIG_FSL_DPAA2_MAC) += dpaa2-mac.o |
||
64 | + |
||
65 | +dpaa2-mac-objs := mac.o dpmac.o |
||
66 | + |
||
67 | +all: |
||
68 | + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules |
||
69 | + |
||
70 | +clean: |
||
71 | + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean |
||
72 | --- /dev/null |
||
73 | +++ b/drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h |
||
74 | @@ -0,0 +1,172 @@ |
||
75 | +/* Copyright 2013-2016 Freescale Semiconductor Inc. |
||
76 | + * |
||
77 | + * Redistribution and use in source and binary forms, with or without |
||
78 | + * modification, are permitted provided that the following conditions are met: |
||
79 | + * * Redistributions of source code must retain the above copyright |
||
80 | + * notice, this list of conditions and the following disclaimer. |
||
81 | + * * Redistributions in binary form must reproduce the above copyright |
||
82 | + * notice, this list of conditions and the following disclaimer in the |
||
83 | + * documentation and/or other materials provided with the distribution. |
||
84 | + * * Neither the name of the above-listed copyright holders nor the |
||
85 | + * names of any contributors may be used to endorse or promote products |
||
86 | + * derived from this software without specific prior written permission. |
||
87 | + * |
||
88 | + * |
||
89 | + * ALTERNATIVELY, this software may be distributed under the terms of the |
||
90 | + * GNU General Public License ("GPL") as published by the Free Software |
||
91 | + * Foundation, either version 2 of that License or (at your option) any |
||
92 | + * later version. |
||
93 | + * |
||
94 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
95 | + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
96 | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
97 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE |
||
98 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
99 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
100 | + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
101 | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
102 | + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
103 | + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
104 | + * POSSIBILITY OF SUCH DAMAGE. |
||
105 | + */ |
||
106 | +#ifndef _FSL_DPMAC_CMD_H |
||
107 | +#define _FSL_DPMAC_CMD_H |
||
108 | + |
||
109 | +/* DPMAC Version */ |
||
110 | +#define DPMAC_VER_MAJOR 4 |
||
111 | +#define DPMAC_VER_MINOR 2 |
||
112 | +#define DPMAC_CMD_BASE_VERSION 1 |
||
113 | +#define DPMAC_CMD_ID_OFFSET 4 |
||
114 | + |
||
115 | +#define DPMAC_CMD(id) (((id) << DPMAC_CMD_ID_OFFSET) | DPMAC_CMD_BASE_VERSION) |
||
116 | + |
||
117 | +/* Command IDs */ |
||
118 | +#define DPMAC_CMDID_CLOSE DPMAC_CMD(0x800) |
||
119 | +#define DPMAC_CMDID_OPEN DPMAC_CMD(0x80c) |
||
120 | +#define DPMAC_CMDID_CREATE DPMAC_CMD(0x90c) |
||
121 | +#define DPMAC_CMDID_DESTROY DPMAC_CMD(0x98c) |
||
122 | +#define DPMAC_CMDID_GET_API_VERSION DPMAC_CMD(0xa0c) |
||
123 | + |
||
124 | +#define DPMAC_CMDID_GET_ATTR DPMAC_CMD(0x004) |
||
125 | +#define DPMAC_CMDID_RESET DPMAC_CMD(0x005) |
||
126 | + |
||
127 | +#define DPMAC_CMDID_SET_IRQ_ENABLE DPMAC_CMD(0x012) |
||
128 | +#define DPMAC_CMDID_GET_IRQ_ENABLE DPMAC_CMD(0x013) |
||
129 | +#define DPMAC_CMDID_SET_IRQ_MASK DPMAC_CMD(0x014) |
||
130 | +#define DPMAC_CMDID_GET_IRQ_MASK DPMAC_CMD(0x015) |
||
131 | +#define DPMAC_CMDID_GET_IRQ_STATUS DPMAC_CMD(0x016) |
||
132 | +#define DPMAC_CMDID_CLEAR_IRQ_STATUS DPMAC_CMD(0x017) |
||
133 | + |
||
134 | +#define DPMAC_CMDID_GET_LINK_CFG DPMAC_CMD(0x0c2) |
||
135 | +#define DPMAC_CMDID_SET_LINK_STATE DPMAC_CMD(0x0c3) |
||
136 | +#define DPMAC_CMDID_GET_COUNTER DPMAC_CMD(0x0c4) |
||
137 | + |
||
138 | +#define DPMAC_CMDID_SET_PORT_MAC_ADDR DPMAC_CMD(0x0c5) |
||
139 | + |
||
140 | +/* Macros for accessing command fields smaller than 1byte */ |
||
141 | +#define DPMAC_MASK(field) \ |
||
142 | + GENMASK(DPMAC_##field##_SHIFT + DPMAC_##field##_SIZE - 1, \ |
||
143 | + DPMAC_##field##_SHIFT) |
||
144 | +#define dpmac_set_field(var, field, val) \ |
||
145 | + ((var) |= (((val) << DPMAC_##field##_SHIFT) & DPMAC_MASK(field))) |
||
146 | +#define dpmac_get_field(var, field) \ |
||
147 | + (((var) & DPMAC_MASK(field)) >> DPMAC_##field##_SHIFT) |
||
148 | + |
||
149 | +struct dpmac_cmd_open { |
||
150 | + u32 dpmac_id; |
||
151 | +}; |
||
152 | + |
||
153 | +struct dpmac_cmd_create { |
||
154 | + u32 mac_id; |
||
155 | +}; |
||
156 | + |
||
157 | +struct dpmac_cmd_destroy { |
||
158 | + u32 dpmac_id; |
||
159 | +}; |
||
160 | + |
||
161 | +struct dpmac_cmd_set_irq_enable { |
||
162 | + u8 enable; |
||
163 | + u8 pad[3]; |
||
164 | + u8 irq_index; |
||
165 | +}; |
||
166 | + |
||
167 | +struct dpmac_cmd_get_irq_enable { |
||
168 | + u32 pad; |
||
169 | + u8 irq_index; |
||
170 | +}; |
||
171 | + |
||
172 | +struct dpmac_rsp_get_irq_enable { |
||
173 | + u8 enabled; |
||
174 | +}; |
||
175 | + |
||
176 | +struct dpmac_cmd_set_irq_mask { |
||
177 | + u32 mask; |
||
178 | + u8 irq_index; |
||
179 | +}; |
||
180 | + |
||
181 | +struct dpmac_cmd_get_irq_mask { |
||
182 | + u32 pad; |
||
183 | + u8 irq_index; |
||
184 | +}; |
||
185 | + |
||
186 | +struct dpmac_rsp_get_irq_mask { |
||
187 | + u32 mask; |
||
188 | +}; |
||
189 | + |
||
190 | +struct dpmac_cmd_get_irq_status { |
||
191 | + u32 status; |
||
192 | + u8 irq_index; |
||
193 | +}; |
||
194 | + |
||
195 | +struct dpmac_rsp_get_irq_status { |
||
196 | + u32 status; |
||
197 | +}; |
||
198 | + |
||
199 | +struct dpmac_cmd_clear_irq_status { |
||
200 | + u32 status; |
||
201 | + u8 irq_index; |
||
202 | +}; |
||
203 | + |
||
204 | +struct dpmac_rsp_get_attributes { |
||
205 | + u8 eth_if; |
||
206 | + u8 link_type; |
||
207 | + u16 id; |
||
208 | + u32 max_rate; |
||
209 | +}; |
||
210 | + |
||
211 | +struct dpmac_rsp_get_link_cfg { |
||
212 | + u64 options; |
||
213 | + u32 rate; |
||
214 | +}; |
||
215 | + |
||
216 | +#define DPMAC_STATE_SIZE 1 |
||
217 | +#define DPMAC_STATE_SHIFT 0 |
||
218 | + |
||
219 | +struct dpmac_cmd_set_link_state { |
||
220 | + u64 options; |
||
221 | + u32 rate; |
||
222 | + u32 pad; |
||
223 | + /* only least significant bit is valid */ |
||
224 | + u8 up; |
||
225 | +}; |
||
226 | + |
||
227 | +struct dpmac_cmd_get_counter { |
||
228 | + u8 type; |
||
229 | +}; |
||
230 | + |
||
231 | +struct dpmac_rsp_get_counter { |
||
232 | + u64 pad; |
||
233 | + u64 counter; |
||
234 | +}; |
||
235 | + |
||
236 | +struct dpmac_rsp_get_api_version { |
||
237 | + u16 major; |
||
238 | + u16 minor; |
||
239 | +}; |
||
240 | + |
||
241 | +struct dpmac_cmd_set_port_mac_addr { |
||
242 | + u8 pad[2]; |
||
243 | + u8 addr[6]; |
||
244 | +}; |
||
245 | + |
||
246 | +#endif /* _FSL_DPMAC_CMD_H */ |
||
247 | --- /dev/null |
||
248 | +++ b/drivers/staging/fsl-dpaa2/mac/dpmac.c |
||
249 | @@ -0,0 +1,619 @@ |
||
250 | +/* Copyright 2013-2016 Freescale Semiconductor Inc. |
||
251 | + * |
||
252 | + * Redistribution and use in source and binary forms, with or without |
||
253 | + * modification, are permitted provided that the following conditions are met: |
||
254 | + * * Redistributions of source code must retain the above copyright |
||
255 | + * notice, this list of conditions and the following disclaimer. |
||
256 | + * * Redistributions in binary form must reproduce the above copyright |
||
257 | + * notice, this list of conditions and the following disclaimer in the |
||
258 | + * documentation and/or other materials provided with the distribution. |
||
259 | + * * Neither the name of the above-listed copyright holders nor the |
||
260 | + * names of any contributors may be used to endorse or promote products |
||
261 | + * derived from this software without specific prior written permission. |
||
262 | + * |
||
263 | + * |
||
264 | + * ALTERNATIVELY, this software may be distributed under the terms of the |
||
265 | + * GNU General Public License ("GPL") as published by the Free Software |
||
266 | + * Foundation, either version 2 of that License or (at your option) any |
||
267 | + * later version. |
||
268 | + * |
||
269 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
270 | + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
271 | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
272 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE |
||
273 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
274 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
275 | + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
276 | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
277 | + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
278 | + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
279 | + * POSSIBILITY OF SUCH DAMAGE. |
||
280 | + */ |
||
281 | +#include <linux/fsl/mc.h> |
||
282 | +#include "dpmac.h" |
||
283 | +#include "dpmac-cmd.h" |
||
284 | + |
||
285 | +/** |
||
286 | + * dpmac_open() - Open a control session for the specified object. |
||
287 | + * @mc_io: Pointer to MC portal's I/O object |
||
288 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
289 | + * @dpmac_id: DPMAC unique ID |
||
290 | + * @token: Returned token; use in subsequent API calls |
||
291 | + * |
||
292 | + * This function can be used to open a control session for an |
||
293 | + * already created object; an object may have been declared in |
||
294 | + * the DPL or by calling the dpmac_create function. |
||
295 | + * This function returns a unique authentication token, |
||
296 | + * associated with the specific object ID and the specific MC |
||
297 | + * portal; this token must be used in all subsequent commands for |
||
298 | + * this specific object |
||
299 | + * |
||
300 | + * Return: '0' on Success; Error code otherwise. |
||
301 | + */ |
||
302 | +int dpmac_open(struct fsl_mc_io *mc_io, |
||
303 | + u32 cmd_flags, |
||
304 | + int dpmac_id, |
||
305 | + u16 *token) |
||
306 | +{ |
||
307 | + struct dpmac_cmd_open *cmd_params; |
||
308 | + struct fsl_mc_command cmd = { 0 }; |
||
309 | + int err; |
||
310 | + |
||
311 | + /* prepare command */ |
||
312 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_OPEN, |
||
313 | + cmd_flags, |
||
314 | + 0); |
||
315 | + cmd_params = (struct dpmac_cmd_open *)cmd.params; |
||
316 | + cmd_params->dpmac_id = cpu_to_le32(dpmac_id); |
||
317 | + |
||
318 | + /* send command to mc*/ |
||
319 | + err = mc_send_command(mc_io, &cmd); |
||
320 | + if (err) |
||
321 | + return err; |
||
322 | + |
||
323 | + /* retrieve response parameters */ |
||
324 | + *token = mc_cmd_hdr_read_token(&cmd); |
||
325 | + |
||
326 | + return err; |
||
327 | +} |
||
328 | + |
||
329 | +/** |
||
330 | + * dpmac_close() - Close the control session of the object |
||
331 | + * @mc_io: Pointer to MC portal's I/O object |
||
332 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
333 | + * @token: Token of DPMAC object |
||
334 | + * |
||
335 | + * After this function is called, no further operations are |
||
336 | + * allowed on the object without opening a new control session. |
||
337 | + * |
||
338 | + * Return: '0' on Success; Error code otherwise. |
||
339 | + */ |
||
340 | +int dpmac_close(struct fsl_mc_io *mc_io, |
||
341 | + u32 cmd_flags, |
||
342 | + u16 token) |
||
343 | +{ |
||
344 | + struct fsl_mc_command cmd = { 0 }; |
||
345 | + |
||
346 | + /* prepare command */ |
||
347 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLOSE, cmd_flags, |
||
348 | + token); |
||
349 | + |
||
350 | + /* send command to mc*/ |
||
351 | + return mc_send_command(mc_io, &cmd); |
||
352 | +} |
||
353 | + |
||
354 | +/** |
||
355 | + * dpmac_create() - Create the DPMAC object. |
||
356 | + * @mc_io: Pointer to MC portal's I/O object |
||
357 | + * @dprc_token: Parent container token; '0' for default container |
||
358 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
359 | + * @cfg: Configuration structure |
||
360 | + * @obj_id: Returned object id |
||
361 | + * |
||
362 | + * Create the DPMAC object, allocate required resources and |
||
363 | + * perform required initialization. |
||
364 | + * |
||
365 | + * The function accepts an authentication token of a parent |
||
366 | + * container that this object should be assigned to. The token |
||
367 | + * can be '0' so the object will be assigned to the default container. |
||
368 | + * The newly created object can be opened with the returned |
||
369 | + * object id and using the container's associated tokens and MC portals. |
||
370 | + * |
||
371 | + * Return: '0' on Success; Error code otherwise. |
||
372 | + */ |
||
373 | +int dpmac_create(struct fsl_mc_io *mc_io, |
||
374 | + u16 dprc_token, |
||
375 | + u32 cmd_flags, |
||
376 | + const struct dpmac_cfg *cfg, |
||
377 | + u32 *obj_id) |
||
378 | +{ |
||
379 | + struct dpmac_cmd_create *cmd_params; |
||
380 | + struct fsl_mc_command cmd = { 0 }; |
||
381 | + int err; |
||
382 | + |
||
383 | + /* prepare command */ |
||
384 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CREATE, |
||
385 | + cmd_flags, |
||
386 | + dprc_token); |
||
387 | + cmd_params = (struct dpmac_cmd_create *)cmd.params; |
||
388 | + cmd_params->mac_id = cpu_to_le32(cfg->mac_id); |
||
389 | + |
||
390 | + /* send command to mc*/ |
||
391 | + err = mc_send_command(mc_io, &cmd); |
||
392 | + if (err) |
||
393 | + return err; |
||
394 | + |
||
395 | + /* retrieve response parameters */ |
||
396 | + *obj_id = mc_cmd_read_object_id(&cmd); |
||
397 | + |
||
398 | + return 0; |
||
399 | +} |
||
400 | + |
||
401 | +/** |
||
402 | + * dpmac_destroy() - Destroy the DPMAC object and release all its resources. |
||
403 | + * @mc_io: Pointer to MC portal's I/O object |
||
404 | + * @dprc_token: Parent container token; '0' for default container |
||
405 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
406 | + * @object_id: The object id; it must be a valid id within the container that |
||
407 | + * created this object; |
||
408 | + * |
||
409 | + * The function accepts the authentication token of the parent container that |
||
410 | + * created the object (not the one that currently owns the object). The object |
||
411 | + * is searched within parent using the provided 'object_id'. |
||
412 | + * All tokens to the object must be closed before calling destroy. |
||
413 | + * |
||
414 | + * Return: '0' on Success; error code otherwise. |
||
415 | + */ |
||
416 | +int dpmac_destroy(struct fsl_mc_io *mc_io, |
||
417 | + u16 dprc_token, |
||
418 | + u32 cmd_flags, |
||
419 | + u32 object_id) |
||
420 | +{ |
||
421 | + struct dpmac_cmd_destroy *cmd_params; |
||
422 | + struct fsl_mc_command cmd = { 0 }; |
||
423 | + |
||
424 | + /* prepare command */ |
||
425 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_DESTROY, |
||
426 | + cmd_flags, |
||
427 | + dprc_token); |
||
428 | + cmd_params = (struct dpmac_cmd_destroy *)cmd.params; |
||
429 | + cmd_params->dpmac_id = cpu_to_le32(object_id); |
||
430 | + |
||
431 | + /* send command to mc*/ |
||
432 | + return mc_send_command(mc_io, &cmd); |
||
433 | +} |
||
434 | + |
||
435 | +/** |
||
436 | + * dpmac_set_irq_enable() - Set overall interrupt state. |
||
437 | + * @mc_io: Pointer to MC portal's I/O object |
||
438 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
439 | + * @token: Token of DPMAC object |
||
440 | + * @irq_index: The interrupt index to configure |
||
441 | + * @en: Interrupt state - enable = 1, disable = 0 |
||
442 | + * |
||
443 | + * Allows GPP software to control when interrupts are generated. |
||
444 | + * Each interrupt can have up to 32 causes. The enable/disable control's the |
||
445 | + * overall interrupt state. if the interrupt is disabled no causes will cause |
||
446 | + * an interrupt. |
||
447 | + * |
||
448 | + * Return: '0' on Success; Error code otherwise. |
||
449 | + */ |
||
450 | +int dpmac_set_irq_enable(struct fsl_mc_io *mc_io, |
||
451 | + u32 cmd_flags, |
||
452 | + u16 token, |
||
453 | + u8 irq_index, |
||
454 | + u8 en) |
||
455 | +{ |
||
456 | + struct dpmac_cmd_set_irq_enable *cmd_params; |
||
457 | + struct fsl_mc_command cmd = { 0 }; |
||
458 | + |
||
459 | + /* prepare command */ |
||
460 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_ENABLE, |
||
461 | + cmd_flags, |
||
462 | + token); |
||
463 | + cmd_params = (struct dpmac_cmd_set_irq_enable *)cmd.params; |
||
464 | + cmd_params->irq_index = irq_index; |
||
465 | + cmd_params->enable = en; |
||
466 | + |
||
467 | + /* send command to mc*/ |
||
468 | + return mc_send_command(mc_io, &cmd); |
||
469 | +} |
||
470 | + |
||
471 | +/** |
||
472 | + * dpmac_get_irq_enable() - Get overall interrupt state |
||
473 | + * @mc_io: Pointer to MC portal's I/O object |
||
474 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
475 | + * @token: Token of DPMAC object |
||
476 | + * @irq_index: The interrupt index to configure |
||
477 | + * @en: Returned interrupt state - enable = 1, disable = 0 |
||
478 | + * |
||
479 | + * Return: '0' on Success; Error code otherwise. |
||
480 | + */ |
||
481 | +int dpmac_get_irq_enable(struct fsl_mc_io *mc_io, |
||
482 | + u32 cmd_flags, |
||
483 | + u16 token, |
||
484 | + u8 irq_index, |
||
485 | + u8 *en) |
||
486 | +{ |
||
487 | + struct dpmac_cmd_get_irq_enable *cmd_params; |
||
488 | + struct dpmac_rsp_get_irq_enable *rsp_params; |
||
489 | + struct fsl_mc_command cmd = { 0 }; |
||
490 | + int err; |
||
491 | + |
||
492 | + /* prepare command */ |
||
493 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_ENABLE, |
||
494 | + cmd_flags, |
||
495 | + token); |
||
496 | + cmd_params = (struct dpmac_cmd_get_irq_enable *)cmd.params; |
||
497 | + cmd_params->irq_index = irq_index; |
||
498 | + |
||
499 | + /* send command to mc*/ |
||
500 | + err = mc_send_command(mc_io, &cmd); |
||
501 | + if (err) |
||
502 | + return err; |
||
503 | + |
||
504 | + /* retrieve response parameters */ |
||
505 | + rsp_params = (struct dpmac_rsp_get_irq_enable *)cmd.params; |
||
506 | + *en = rsp_params->enabled; |
||
507 | + |
||
508 | + return 0; |
||
509 | +} |
||
510 | + |
||
511 | +/** |
||
512 | + * dpmac_set_irq_mask() - Set interrupt mask. |
||
513 | + * @mc_io: Pointer to MC portal's I/O object |
||
514 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
515 | + * @token: Token of DPMAC object |
||
516 | + * @irq_index: The interrupt index to configure |
||
517 | + * @mask: Event mask to trigger interrupt; |
||
518 | + * each bit: |
||
519 | + * 0 = ignore event |
||
520 | + * 1 = consider event for asserting IRQ |
||
521 | + * |
||
522 | + * Every interrupt can have up to 32 causes and the interrupt model supports |
||
523 | + * masking/unmasking each cause independently |
||
524 | + * |
||
525 | + * Return: '0' on Success; Error code otherwise. |
||
526 | + */ |
||
527 | +int dpmac_set_irq_mask(struct fsl_mc_io *mc_io, |
||
528 | + u32 cmd_flags, |
||
529 | + u16 token, |
||
530 | + u8 irq_index, |
||
531 | + u32 mask) |
||
532 | +{ |
||
533 | + struct dpmac_cmd_set_irq_mask *cmd_params; |
||
534 | + struct fsl_mc_command cmd = { 0 }; |
||
535 | + |
||
536 | + /* prepare command */ |
||
537 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_MASK, |
||
538 | + cmd_flags, |
||
539 | + token); |
||
540 | + cmd_params = (struct dpmac_cmd_set_irq_mask *)cmd.params; |
||
541 | + cmd_params->mask = cpu_to_le32(mask); |
||
542 | + cmd_params->irq_index = irq_index; |
||
543 | + |
||
544 | + /* send command to mc*/ |
||
545 | + return mc_send_command(mc_io, &cmd); |
||
546 | +} |
||
547 | + |
||
548 | +/** |
||
549 | + * dpmac_get_irq_mask() - Get interrupt mask. |
||
550 | + * @mc_io: Pointer to MC portal's I/O object |
||
551 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
552 | + * @token: Token of DPMAC object |
||
553 | + * @irq_index: The interrupt index to configure |
||
554 | + * @mask: Returned event mask to trigger interrupt |
||
555 | + * |
||
556 | + * Every interrupt can have up to 32 causes and the interrupt model supports |
||
557 | + * masking/unmasking each cause independently |
||
558 | + * |
||
559 | + * Return: '0' on Success; Error code otherwise. |
||
560 | + */ |
||
561 | +int dpmac_get_irq_mask(struct fsl_mc_io *mc_io, |
||
562 | + u32 cmd_flags, |
||
563 | + u16 token, |
||
564 | + u8 irq_index, |
||
565 | + u32 *mask) |
||
566 | +{ |
||
567 | + struct dpmac_cmd_get_irq_mask *cmd_params; |
||
568 | + struct dpmac_rsp_get_irq_mask *rsp_params; |
||
569 | + struct fsl_mc_command cmd = { 0 }; |
||
570 | + int err; |
||
571 | + |
||
572 | + /* prepare command */ |
||
573 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_MASK, |
||
574 | + cmd_flags, |
||
575 | + token); |
||
576 | + cmd_params = (struct dpmac_cmd_get_irq_mask *)cmd.params; |
||
577 | + cmd_params->irq_index = irq_index; |
||
578 | + |
||
579 | + /* send command to mc*/ |
||
580 | + err = mc_send_command(mc_io, &cmd); |
||
581 | + if (err) |
||
582 | + return err; |
||
583 | + |
||
584 | + /* retrieve response parameters */ |
||
585 | + rsp_params = (struct dpmac_rsp_get_irq_mask *)cmd.params; |
||
586 | + *mask = le32_to_cpu(rsp_params->mask); |
||
587 | + |
||
588 | + return 0; |
||
589 | +} |
||
590 | + |
||
591 | +/** |
||
592 | + * dpmac_get_irq_status() - Get the current status of any pending interrupts. |
||
593 | + * |
||
594 | + * @mc_io: Pointer to MC portal's I/O object |
||
595 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
596 | + * @token: Token of DPMAC object |
||
597 | + * @irq_index: The interrupt index to configure |
||
598 | + * @status: Returned interrupts status - one bit per cause: |
||
599 | + * 0 = no interrupt pending |
||
600 | + * 1 = interrupt pending |
||
601 | + * |
||
602 | + * Return: '0' on Success; Error code otherwise. |
||
603 | + */ |
||
604 | +int dpmac_get_irq_status(struct fsl_mc_io *mc_io, |
||
605 | + u32 cmd_flags, |
||
606 | + u16 token, |
||
607 | + u8 irq_index, |
||
608 | + u32 *status) |
||
609 | +{ |
||
610 | + struct dpmac_cmd_get_irq_status *cmd_params; |
||
611 | + struct dpmac_rsp_get_irq_status *rsp_params; |
||
612 | + struct fsl_mc_command cmd = { 0 }; |
||
613 | + int err; |
||
614 | + |
||
615 | + /* prepare command */ |
||
616 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_STATUS, |
||
617 | + cmd_flags, |
||
618 | + token); |
||
619 | + cmd_params = (struct dpmac_cmd_get_irq_status *)cmd.params; |
||
620 | + cmd_params->status = cpu_to_le32(*status); |
||
621 | + cmd_params->irq_index = irq_index; |
||
622 | + |
||
623 | + /* send command to mc*/ |
||
624 | + err = mc_send_command(mc_io, &cmd); |
||
625 | + if (err) |
||
626 | + return err; |
||
627 | + |
||
628 | + /* retrieve response parameters */ |
||
629 | + rsp_params = (struct dpmac_rsp_get_irq_status *)cmd.params; |
||
630 | + *status = le32_to_cpu(rsp_params->status); |
||
631 | + |
||
632 | + return 0; |
||
633 | +} |
||
634 | + |
||
635 | +/** |
||
636 | + * dpmac_clear_irq_status() - Clear a pending interrupt's status |
||
637 | + * |
||
638 | + * @mc_io: Pointer to MC portal's I/O object |
||
639 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
640 | + * @token: Token of DPMAC object |
||
641 | + * @irq_index: The interrupt index to configure |
||
642 | + * @status: Bits to clear (W1C) - one bit per cause: |
||
643 | + * 0 = don't change |
||
644 | + * 1 = clear status bit |
||
645 | + * |
||
646 | + * Return: '0' on Success; Error code otherwise. |
||
647 | + */ |
||
648 | +int dpmac_clear_irq_status(struct fsl_mc_io *mc_io, |
||
649 | + u32 cmd_flags, |
||
650 | + u16 token, |
||
651 | + u8 irq_index, |
||
652 | + u32 status) |
||
653 | +{ |
||
654 | + struct dpmac_cmd_clear_irq_status *cmd_params; |
||
655 | + struct fsl_mc_command cmd = { 0 }; |
||
656 | + |
||
657 | + /* prepare command */ |
||
658 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLEAR_IRQ_STATUS, |
||
659 | + cmd_flags, |
||
660 | + token); |
||
661 | + cmd_params = (struct dpmac_cmd_clear_irq_status *)cmd.params; |
||
662 | + cmd_params->status = cpu_to_le32(status); |
||
663 | + cmd_params->irq_index = irq_index; |
||
664 | + |
||
665 | + /* send command to mc*/ |
||
666 | + return mc_send_command(mc_io, &cmd); |
||
667 | +} |
||
668 | + |
||
669 | +/** |
||
670 | + * dpmac_get_attributes - Retrieve DPMAC attributes. |
||
671 | + * |
||
672 | + * @mc_io: Pointer to MC portal's I/O object |
||
673 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
674 | + * @token: Token of DPMAC object |
||
675 | + * @attr: Returned object's attributes |
||
676 | + * |
||
677 | + * Return: '0' on Success; Error code otherwise. |
||
678 | + */ |
||
679 | +int dpmac_get_attributes(struct fsl_mc_io *mc_io, |
||
680 | + u32 cmd_flags, |
||
681 | + u16 token, |
||
682 | + struct dpmac_attr *attr) |
||
683 | +{ |
||
684 | + struct dpmac_rsp_get_attributes *rsp_params; |
||
685 | + struct fsl_mc_command cmd = { 0 }; |
||
686 | + int err; |
||
687 | + |
||
688 | + /* prepare command */ |
||
689 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_ATTR, |
||
690 | + cmd_flags, |
||
691 | + token); |
||
692 | + |
||
693 | + /* send command to mc*/ |
||
694 | + err = mc_send_command(mc_io, &cmd); |
||
695 | + if (err) |
||
696 | + return err; |
||
697 | + |
||
698 | + /* retrieve response parameters */ |
||
699 | + rsp_params = (struct dpmac_rsp_get_attributes *)cmd.params; |
||
700 | + attr->eth_if = rsp_params->eth_if; |
||
701 | + attr->link_type = rsp_params->link_type; |
||
702 | + attr->id = le16_to_cpu(rsp_params->id); |
||
703 | + attr->max_rate = le32_to_cpu(rsp_params->max_rate); |
||
704 | + |
||
705 | + return 0; |
||
706 | +} |
||
707 | + |
||
708 | +/** |
||
709 | + * dpmac_get_link_cfg() - Get Ethernet link configuration |
||
710 | + * @mc_io: Pointer to opaque I/O object |
||
711 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
712 | + * @token: Token of DPMAC object |
||
713 | + * @cfg: Returned structure with the link configuration |
||
714 | + * |
||
715 | + * Return: '0' on Success; Error code otherwise. |
||
716 | + */ |
||
717 | +int dpmac_get_link_cfg(struct fsl_mc_io *mc_io, |
||
718 | + u32 cmd_flags, |
||
719 | + u16 token, |
||
720 | + struct dpmac_link_cfg *cfg) |
||
721 | +{ |
||
722 | + struct dpmac_rsp_get_link_cfg *rsp_params; |
||
723 | + struct fsl_mc_command cmd = { 0 }; |
||
724 | + int err = 0; |
||
725 | + |
||
726 | + /* prepare command */ |
||
727 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_LINK_CFG, |
||
728 | + cmd_flags, |
||
729 | + token); |
||
730 | + |
||
731 | + /* send command to mc*/ |
||
732 | + err = mc_send_command(mc_io, &cmd); |
||
733 | + if (err) |
||
734 | + return err; |
||
735 | + |
||
736 | + rsp_params = (struct dpmac_rsp_get_link_cfg *)cmd.params; |
||
737 | + cfg->options = le64_to_cpu(rsp_params->options); |
||
738 | + cfg->rate = le32_to_cpu(rsp_params->rate); |
||
739 | + |
||
740 | + return 0; |
||
741 | +} |
||
742 | + |
||
743 | +/** |
||
744 | + * dpmac_set_link_state() - Set the Ethernet link status |
||
745 | + * @mc_io: Pointer to opaque I/O object |
||
746 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
747 | + * @token: Token of DPMAC object |
||
748 | + * @link_state: Link state configuration |
||
749 | + * |
||
750 | + * Return: '0' on Success; Error code otherwise. |
||
751 | + */ |
||
752 | +int dpmac_set_link_state(struct fsl_mc_io *mc_io, |
||
753 | + u32 cmd_flags, |
||
754 | + u16 token, |
||
755 | + struct dpmac_link_state *link_state) |
||
756 | +{ |
||
757 | + struct dpmac_cmd_set_link_state *cmd_params; |
||
758 | + struct fsl_mc_command cmd = { 0 }; |
||
759 | + |
||
760 | + /* prepare command */ |
||
761 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE, |
||
762 | + cmd_flags, |
||
763 | + token); |
||
764 | + cmd_params = (struct dpmac_cmd_set_link_state *)cmd.params; |
||
765 | + cmd_params->options = cpu_to_le64(link_state->options); |
||
766 | + cmd_params->rate = cpu_to_le32(link_state->rate); |
||
767 | + cmd_params->up = dpmac_get_field(link_state->up, STATE); |
||
768 | + |
||
769 | + /* send command to mc*/ |
||
770 | + return mc_send_command(mc_io, &cmd); |
||
771 | +} |
||
772 | + |
||
773 | +/** |
||
774 | + * dpmac_get_counter() - Read a specific DPMAC counter |
||
775 | + * @mc_io: Pointer to opaque I/O object |
||
776 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
777 | + * @token: Token of DPMAC object |
||
778 | + * @type: The requested counter |
||
779 | + * @counter: Returned counter value |
||
780 | + * |
||
781 | + * Return: The requested counter; '0' otherwise. |
||
782 | + */ |
||
783 | +int dpmac_get_counter(struct fsl_mc_io *mc_io, |
||
784 | + u32 cmd_flags, |
||
785 | + u16 token, |
||
786 | + enum dpmac_counter type, |
||
787 | + u64 *counter) |
||
788 | +{ |
||
789 | + struct dpmac_cmd_get_counter *dpmac_cmd; |
||
790 | + struct dpmac_rsp_get_counter *dpmac_rsp; |
||
791 | + struct fsl_mc_command cmd = { 0 }; |
||
792 | + int err = 0; |
||
793 | + |
||
794 | + /* prepare command */ |
||
795 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_COUNTER, |
||
796 | + cmd_flags, |
||
797 | + token); |
||
798 | + dpmac_cmd = (struct dpmac_cmd_get_counter *)cmd.params; |
||
799 | + dpmac_cmd->type = type; |
||
800 | + |
||
801 | + /* send command to mc*/ |
||
802 | + err = mc_send_command(mc_io, &cmd); |
||
803 | + if (err) |
||
804 | + return err; |
||
805 | + |
||
806 | + dpmac_rsp = (struct dpmac_rsp_get_counter *)cmd.params; |
||
807 | + *counter = le64_to_cpu(dpmac_rsp->counter); |
||
808 | + |
||
809 | + return 0; |
||
810 | +} |
||
811 | + |
||
812 | +/* untested */ |
||
813 | +int dpmac_set_port_mac_addr(struct fsl_mc_io *mc_io, |
||
814 | + u32 cmd_flags, |
||
815 | + u16 token, |
||
816 | + const u8 addr[6]) |
||
817 | +{ |
||
818 | + struct dpmac_cmd_set_port_mac_addr *dpmac_cmd; |
||
819 | + struct fsl_mc_command cmd = { 0 }; |
||
820 | + |
||
821 | + /* prepare command */ |
||
822 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_PORT_MAC_ADDR, |
||
823 | + cmd_flags, |
||
824 | + token); |
||
825 | + dpmac_cmd = (struct dpmac_cmd_set_port_mac_addr *)cmd.params; |
||
826 | + dpmac_cmd->addr[0] = addr[5]; |
||
827 | + dpmac_cmd->addr[1] = addr[4]; |
||
828 | + dpmac_cmd->addr[2] = addr[3]; |
||
829 | + dpmac_cmd->addr[3] = addr[2]; |
||
830 | + dpmac_cmd->addr[4] = addr[1]; |
||
831 | + dpmac_cmd->addr[5] = addr[0]; |
||
832 | + |
||
833 | + /* send command to mc*/ |
||
834 | + return mc_send_command(mc_io, &cmd); |
||
835 | +} |
||
836 | + |
||
837 | +/** |
||
838 | + * dpmac_get_api_version() - Get Data Path MAC version |
||
839 | + * @mc_io: Pointer to MC portal's I/O object |
||
840 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
841 | + * @major_ver: Major version of data path mac API |
||
842 | + * @minor_ver: Minor version of data path mac API |
||
843 | + * |
||
844 | + * Return: '0' on Success; Error code otherwise. |
||
845 | + */ |
||
846 | +int dpmac_get_api_version(struct fsl_mc_io *mc_io, |
||
847 | + u32 cmd_flags, |
||
848 | + u16 *major_ver, |
||
849 | + u16 *minor_ver) |
||
850 | +{ |
||
851 | + struct dpmac_rsp_get_api_version *rsp_params; |
||
852 | + struct fsl_mc_command cmd = { 0 }; |
||
853 | + int err; |
||
854 | + |
||
855 | + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_API_VERSION, |
||
856 | + cmd_flags, |
||
857 | + 0); |
||
858 | + |
||
859 | + err = mc_send_command(mc_io, &cmd); |
||
860 | + if (err) |
||
861 | + return err; |
||
862 | + |
||
863 | + rsp_params = (struct dpmac_rsp_get_api_version *)cmd.params; |
||
864 | + *major_ver = le16_to_cpu(rsp_params->major); |
||
865 | + *minor_ver = le16_to_cpu(rsp_params->minor); |
||
866 | + |
||
867 | + return 0; |
||
868 | +} |
||
869 | --- /dev/null |
||
870 | +++ b/drivers/staging/fsl-dpaa2/mac/dpmac.h |
||
871 | @@ -0,0 +1,342 @@ |
||
872 | +/* Copyright 2013-2016 Freescale Semiconductor Inc. |
||
873 | + * |
||
874 | + * Redistribution and use in source and binary forms, with or without |
||
875 | + * modification, are permitted provided that the following conditions are met: |
||
876 | + * * Redistributions of source code must retain the above copyright |
||
877 | + * notice, this list of conditions and the following disclaimer. |
||
878 | + * * Redistributions in binary form must reproduce the above copyright |
||
879 | + * notice, this list of conditions and the following disclaimer in the |
||
880 | + * documentation and/or other materials provided with the distribution. |
||
881 | + * * Neither the name of the above-listed copyright holders nor the |
||
882 | + * names of any contributors may be used to endorse or promote products |
||
883 | + * derived from this software without specific prior written permission. |
||
884 | + * |
||
885 | + * |
||
886 | + * ALTERNATIVELY, this software may be distributed under the terms of the |
||
887 | + * GNU General Public License ("GPL") as published by the Free Software |
||
888 | + * Foundation, either version 2 of that License or (at your option) any |
||
889 | + * later version. |
||
890 | + * |
||
891 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
892 | + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
893 | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
894 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE |
||
895 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
896 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
897 | + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
898 | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
899 | + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
900 | + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
901 | + * POSSIBILITY OF SUCH DAMAGE. |
||
902 | + */ |
||
903 | +#ifndef __FSL_DPMAC_H |
||
904 | +#define __FSL_DPMAC_H |
||
905 | + |
||
906 | +/* Data Path MAC API |
||
907 | + * Contains initialization APIs and runtime control APIs for DPMAC |
||
908 | + */ |
||
909 | + |
||
910 | +struct fsl_mc_io; |
||
911 | + |
||
912 | +int dpmac_open(struct fsl_mc_io *mc_io, |
||
913 | + u32 cmd_flags, |
||
914 | + int dpmac_id, |
||
915 | + u16 *token); |
||
916 | + |
||
917 | +int dpmac_close(struct fsl_mc_io *mc_io, |
||
918 | + u32 cmd_flags, |
||
919 | + u16 token); |
||
920 | + |
||
921 | +/** |
||
922 | + * enum dpmac_link_type - DPMAC link type |
||
923 | + * @DPMAC_LINK_TYPE_NONE: No link |
||
924 | + * @DPMAC_LINK_TYPE_FIXED: Link is fixed type |
||
925 | + * @DPMAC_LINK_TYPE_PHY: Link by PHY ID |
||
926 | + * @DPMAC_LINK_TYPE_BACKPLANE: Backplane link type |
||
927 | + */ |
||
928 | +enum dpmac_link_type { |
||
929 | + DPMAC_LINK_TYPE_NONE, |
||
930 | + DPMAC_LINK_TYPE_FIXED, |
||
931 | + DPMAC_LINK_TYPE_PHY, |
||
932 | + DPMAC_LINK_TYPE_BACKPLANE |
||
933 | +}; |
||
934 | + |
||
935 | +/** |
||
936 | + * enum dpmac_eth_if - DPMAC Ethrnet interface |
||
937 | + * @DPMAC_ETH_IF_MII: MII interface |
||
938 | + * @DPMAC_ETH_IF_RMII: RMII interface |
||
939 | + * @DPMAC_ETH_IF_SMII: SMII interface |
||
940 | + * @DPMAC_ETH_IF_GMII: GMII interface |
||
941 | + * @DPMAC_ETH_IF_RGMII: RGMII interface |
||
942 | + * @DPMAC_ETH_IF_SGMII: SGMII interface |
||
943 | + * @DPMAC_ETH_IF_QSGMII: QSGMII interface |
||
944 | + * @DPMAC_ETH_IF_XAUI: XAUI interface |
||
945 | + * @DPMAC_ETH_IF_XFI: XFI interface |
||
946 | + */ |
||
947 | +enum dpmac_eth_if { |
||
948 | + DPMAC_ETH_IF_MII, |
||
949 | + DPMAC_ETH_IF_RMII, |
||
950 | + DPMAC_ETH_IF_SMII, |
||
951 | + DPMAC_ETH_IF_GMII, |
||
952 | + DPMAC_ETH_IF_RGMII, |
||
953 | + DPMAC_ETH_IF_SGMII, |
||
954 | + DPMAC_ETH_IF_QSGMII, |
||
955 | + DPMAC_ETH_IF_XAUI, |
||
956 | + DPMAC_ETH_IF_XFI |
||
957 | +}; |
||
958 | + |
||
959 | +/** |
||
960 | + * struct dpmac_cfg - Structure representing DPMAC configuration |
||
961 | + * @mac_id: Represents the Hardware MAC ID; in case of multiple WRIOP, |
||
962 | + * the MAC IDs are continuous. |
||
963 | + * For example: 2 WRIOPs, 16 MACs in each: |
||
964 | + * MAC IDs for the 1st WRIOP: 1-16, |
||
965 | + * MAC IDs for the 2nd WRIOP: 17-32. |
||
966 | + */ |
||
967 | +struct dpmac_cfg { |
||
968 | + u16 mac_id; |
||
969 | +}; |
||
970 | + |
||
971 | +int dpmac_create(struct fsl_mc_io *mc_io, |
||
972 | + u16 dprc_token, |
||
973 | + u32 cmd_flags, |
||
974 | + const struct dpmac_cfg *cfg, |
||
975 | + u32 *obj_id); |
||
976 | + |
||
977 | +int dpmac_destroy(struct fsl_mc_io *mc_io, |
||
978 | + u16 dprc_token, |
||
979 | + u32 cmd_flags, |
||
980 | + u32 object_id); |
||
981 | + |
||
982 | +/** |
||
983 | + * DPMAC IRQ Index and Events |
||
984 | + */ |
||
985 | + |
||
986 | +/** |
||
987 | + * IRQ index |
||
988 | + */ |
||
989 | +#define DPMAC_IRQ_INDEX 0 |
||
990 | +/** |
||
991 | + * IRQ event - indicates a change in link state |
||
992 | + */ |
||
993 | +#define DPMAC_IRQ_EVENT_LINK_CFG_REQ 0x00000001 |
||
994 | +/** |
||
995 | + * IRQ event - Indicates that the link state changed |
||
996 | + */ |
||
997 | +#define DPMAC_IRQ_EVENT_LINK_CHANGED 0x00000002 |
||
998 | + |
||
999 | +int dpmac_set_irq_enable(struct fsl_mc_io *mc_io, |
||
1000 | + u32 cmd_flags, |
||
1001 | + u16 token, |
||
1002 | + u8 irq_index, |
||
1003 | + u8 en); |
||
1004 | + |
||
1005 | +int dpmac_get_irq_enable(struct fsl_mc_io *mc_io, |
||
1006 | + u32 cmd_flags, |
||
1007 | + u16 token, |
||
1008 | + u8 irq_index, |
||
1009 | + u8 *en); |
||
1010 | + |
||
1011 | +int dpmac_set_irq_mask(struct fsl_mc_io *mc_io, |
||
1012 | + u32 cmd_flags, |
||
1013 | + u16 token, |
||
1014 | + u8 irq_index, |
||
1015 | + u32 mask); |
||
1016 | + |
||
1017 | +int dpmac_get_irq_mask(struct fsl_mc_io *mc_io, |
||
1018 | + u32 cmd_flags, |
||
1019 | + u16 token, |
||
1020 | + u8 irq_index, |
||
1021 | + u32 *mask); |
||
1022 | + |
||
1023 | +int dpmac_get_irq_status(struct fsl_mc_io *mc_io, |
||
1024 | + u32 cmd_flags, |
||
1025 | + u16 token, |
||
1026 | + u8 irq_index, |
||
1027 | + u32 *status); |
||
1028 | + |
||
1029 | +int dpmac_clear_irq_status(struct fsl_mc_io *mc_io, |
||
1030 | + u32 cmd_flags, |
||
1031 | + u16 token, |
||
1032 | + u8 irq_index, |
||
1033 | + u32 status); |
||
1034 | + |
||
1035 | +/** |
||
1036 | + * struct dpmac_attr - Structure representing DPMAC attributes |
||
1037 | + * @id: DPMAC object ID |
||
1038 | + * @max_rate: Maximum supported rate - in Mbps |
||
1039 | + * @eth_if: Ethernet interface |
||
1040 | + * @link_type: link type |
||
1041 | + */ |
||
1042 | +struct dpmac_attr { |
||
1043 | + u16 id; |
||
1044 | + u32 max_rate; |
||
1045 | + enum dpmac_eth_if eth_if; |
||
1046 | + enum dpmac_link_type link_type; |
||
1047 | +}; |
||
1048 | + |
||
1049 | +int dpmac_get_attributes(struct fsl_mc_io *mc_io, |
||
1050 | + u32 cmd_flags, |
||
1051 | + u16 token, |
||
1052 | + struct dpmac_attr *attr); |
||
1053 | + |
||
1054 | +/** |
||
1055 | + * DPMAC link configuration/state options |
||
1056 | + */ |
||
1057 | + |
||
1058 | +/** |
||
1059 | + * Enable auto-negotiation |
||
1060 | + */ |
||
1061 | +#define DPMAC_LINK_OPT_AUTONEG 0x0000000000000001ULL |
||
1062 | +/** |
||
1063 | + * Enable half-duplex mode |
||
1064 | + */ |
||
1065 | +#define DPMAC_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL |
||
1066 | +/** |
||
1067 | + * Enable pause frames |
||
1068 | + */ |
||
1069 | +#define DPMAC_LINK_OPT_PAUSE 0x0000000000000004ULL |
||
1070 | +/** |
||
1071 | + * Enable a-symmetric pause frames |
||
1072 | + */ |
||
1073 | +#define DPMAC_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL |
||
1074 | + |
||
1075 | +/** |
||
1076 | + * struct dpmac_link_cfg - Structure representing DPMAC link configuration |
||
1077 | + * @rate: Link's rate - in Mbps |
||
1078 | + * @options: Enable/Disable DPMAC link cfg features (bitmap) |
||
1079 | + */ |
||
1080 | +struct dpmac_link_cfg { |
||
1081 | + u32 rate; |
||
1082 | + u64 options; |
||
1083 | +}; |
||
1084 | + |
||
1085 | +int dpmac_get_link_cfg(struct fsl_mc_io *mc_io, |
||
1086 | + u32 cmd_flags, |
||
1087 | + u16 token, |
||
1088 | + struct dpmac_link_cfg *cfg); |
||
1089 | + |
||
1090 | +/** |
||
1091 | + * struct dpmac_link_state - DPMAC link configuration request |
||
1092 | + * @rate: Rate in Mbps |
||
1093 | + * @options: Enable/Disable DPMAC link cfg features (bitmap) |
||
1094 | + * @up: Link state |
||
1095 | + */ |
||
1096 | +struct dpmac_link_state { |
||
1097 | + u32 rate; |
||
1098 | + u64 options; |
||
1099 | + int up; |
||
1100 | +}; |
||
1101 | + |
||
1102 | +int dpmac_set_link_state(struct fsl_mc_io *mc_io, |
||
1103 | + u32 cmd_flags, |
||
1104 | + u16 token, |
||
1105 | + struct dpmac_link_state *link_state); |
||
1106 | + |
||
1107 | +/** |
||
1108 | + * enum dpmac_counter - DPMAC counter types |
||
1109 | + * @DPMAC_CNT_ING_FRAME_64: counts 64-bytes frames, good or bad. |
||
1110 | + * @DPMAC_CNT_ING_FRAME_127: counts 65- to 127-bytes frames, good or bad. |
||
1111 | + * @DPMAC_CNT_ING_FRAME_255: counts 128- to 255-bytes frames, good or bad. |
||
1112 | + * @DPMAC_CNT_ING_FRAME_511: counts 256- to 511-bytes frames, good or bad. |
||
1113 | + * @DPMAC_CNT_ING_FRAME_1023: counts 512- to 1023-bytes frames, good or bad. |
||
1114 | + * @DPMAC_CNT_ING_FRAME_1518: counts 1024- to 1518-bytes frames, good or bad. |
||
1115 | + * @DPMAC_CNT_ING_FRAME_1519_MAX: counts 1519-bytes frames and larger |
||
1116 | + * (up to max frame length specified), |
||
1117 | + * good or bad. |
||
1118 | + * @DPMAC_CNT_ING_FRAG: counts frames which are shorter than 64 bytes received |
||
1119 | + * with a wrong CRC |
||
1120 | + * @DPMAC_CNT_ING_JABBER: counts frames longer than the maximum frame length |
||
1121 | + * specified, with a bad frame check sequence. |
||
1122 | + * @DPMAC_CNT_ING_FRAME_DISCARD: counts dropped frames due to internal errors. |
||
1123 | + * Occurs when a receive FIFO overflows. |
||
1124 | + * Includes also frames truncated as a result of |
||
1125 | + * the receive FIFO overflow. |
||
1126 | + * @DPMAC_CNT_ING_ALIGN_ERR: counts frames with an alignment error |
||
1127 | + * (optional used for wrong SFD). |
||
1128 | + * @DPMAC_CNT_EGR_UNDERSIZED: counts frames transmitted that was less than 64 |
||
1129 | + * bytes long with a good CRC. |
||
1130 | + * @DPMAC_CNT_ING_OVERSIZED: counts frames longer than the maximum frame length |
||
1131 | + * specified, with a good frame check sequence. |
||
1132 | + * @DPMAC_CNT_ING_VALID_PAUSE_FRAME: counts valid pause frames (regular and PFC) |
||
1133 | + * @DPMAC_CNT_EGR_VALID_PAUSE_FRAME: counts valid pause frames transmitted |
||
1134 | + * (regular and PFC). |
||
1135 | + * @DPMAC_CNT_ING_BYTE: counts bytes received except preamble for all valid |
||
1136 | + * frames and valid pause frames. |
||
1137 | + * @DPMAC_CNT_ING_MCAST_FRAME: counts received multicast frames. |
||
1138 | + * @DPMAC_CNT_ING_BCAST_FRAME: counts received broadcast frames. |
||
1139 | + * @DPMAC_CNT_ING_ALL_FRAME: counts each good or bad frames received. |
||
1140 | + * @DPMAC_CNT_ING_UCAST_FRAME: counts received unicast frames. |
||
1141 | + * @DPMAC_CNT_ING_ERR_FRAME: counts frames received with an error |
||
1142 | + * (except for undersized/fragment frame). |
||
1143 | + * @DPMAC_CNT_EGR_BYTE: counts bytes transmitted except preamble for all valid |
||
1144 | + * frames and valid pause frames transmitted. |
||
1145 | + * @DPMAC_CNT_EGR_MCAST_FRAME: counts transmitted multicast frames. |
||
1146 | + * @DPMAC_CNT_EGR_BCAST_FRAME: counts transmitted broadcast frames. |
||
1147 | + * @DPMAC_CNT_EGR_UCAST_FRAME: counts transmitted unicast frames. |
||
1148 | + * @DPMAC_CNT_EGR_ERR_FRAME: counts frames transmitted with an error. |
||
1149 | + * @DPMAC_CNT_ING_GOOD_FRAME: counts frames received without error, including |
||
1150 | + * pause frames. |
||
1151 | + * @DPMAC_CNT_ENG_GOOD_FRAME: counts frames transmitted without error, including |
||
1152 | + * pause frames. |
||
1153 | + */ |
||
1154 | +enum dpmac_counter { |
||
1155 | + DPMAC_CNT_ING_FRAME_64, |
||
1156 | + DPMAC_CNT_ING_FRAME_127, |
||
1157 | + DPMAC_CNT_ING_FRAME_255, |
||
1158 | + DPMAC_CNT_ING_FRAME_511, |
||
1159 | + DPMAC_CNT_ING_FRAME_1023, |
||
1160 | + DPMAC_CNT_ING_FRAME_1518, |
||
1161 | + DPMAC_CNT_ING_FRAME_1519_MAX, |
||
1162 | + DPMAC_CNT_ING_FRAG, |
||
1163 | + DPMAC_CNT_ING_JABBER, |
||
1164 | + DPMAC_CNT_ING_FRAME_DISCARD, |
||
1165 | + DPMAC_CNT_ING_ALIGN_ERR, |
||
1166 | + DPMAC_CNT_EGR_UNDERSIZED, |
||
1167 | + DPMAC_CNT_ING_OVERSIZED, |
||
1168 | + DPMAC_CNT_ING_VALID_PAUSE_FRAME, |
||
1169 | + DPMAC_CNT_EGR_VALID_PAUSE_FRAME, |
||
1170 | + DPMAC_CNT_ING_BYTE, |
||
1171 | + DPMAC_CNT_ING_MCAST_FRAME, |
||
1172 | + DPMAC_CNT_ING_BCAST_FRAME, |
||
1173 | + DPMAC_CNT_ING_ALL_FRAME, |
||
1174 | + DPMAC_CNT_ING_UCAST_FRAME, |
||
1175 | + DPMAC_CNT_ING_ERR_FRAME, |
||
1176 | + DPMAC_CNT_EGR_BYTE, |
||
1177 | + DPMAC_CNT_EGR_MCAST_FRAME, |
||
1178 | + DPMAC_CNT_EGR_BCAST_FRAME, |
||
1179 | + DPMAC_CNT_EGR_UCAST_FRAME, |
||
1180 | + DPMAC_CNT_EGR_ERR_FRAME, |
||
1181 | + DPMAC_CNT_ING_GOOD_FRAME, |
||
1182 | + DPMAC_CNT_ENG_GOOD_FRAME |
||
1183 | +}; |
||
1184 | + |
||
1185 | +int dpmac_get_counter(struct fsl_mc_io *mc_io, |
||
1186 | + u32 cmd_flags, |
||
1187 | + u16 token, |
||
1188 | + enum dpmac_counter type, |
||
1189 | + u64 *counter); |
||
1190 | + |
||
1191 | +/** |
||
1192 | + * dpmac_set_port_mac_addr() - Set a MAC address associated with the physical |
||
1193 | + * port. This is not used for filtering, MAC is always in |
||
1194 | + * promiscuous mode, it is passed to DPNIs through DPNI API for |
||
1195 | + * application used. |
||
1196 | + * @mc_io: Pointer to opaque I/O object |
||
1197 | + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' |
||
1198 | + * @token: Token of DPMAC object |
||
1199 | + * @addr: MAC address to set |
||
1200 | + * |
||
1201 | + * Return: The requested counter; '0' otherwise. |
||
1202 | + */ |
||
1203 | +int dpmac_set_port_mac_addr(struct fsl_mc_io *mc_io, |
||
1204 | + u32 cmd_flags, |
||
1205 | + u16 token, |
||
1206 | + const u8 addr[6]); |
||
1207 | + |
||
1208 | +int dpmac_get_api_version(struct fsl_mc_io *mc_io, |
||
1209 | + u32 cmd_flags, |
||
1210 | + u16 *major_ver, |
||
1211 | + u16 *minor_ver); |
||
1212 | + |
||
1213 | +#endif /* __FSL_DPMAC_H */ |
||
1214 | --- /dev/null |
||
1215 | +++ b/drivers/staging/fsl-dpaa2/mac/mac.c |
||
1216 | @@ -0,0 +1,672 @@ |
||
1217 | +/* Copyright 2015 Freescale Semiconductor Inc. |
||
1218 | + * |
||
1219 | + * Redistribution and use in source and binary forms, with or without |
||
1220 | + * modification, are permitted provided that the following conditions are met: |
||
1221 | + * * Redistributions of source code must retain the above copyright |
||
1222 | + * notice, this list of conditions and the following disclaimer. |
||
1223 | + * * Redistributions in binary form must reproduce the above copyright |
||
1224 | + * notice, this list of conditions and the following disclaimer in the |
||
1225 | + * documentation and/or other materials provided with the distribution. |
||
1226 | + * * Neither the name of Freescale Semiconductor nor the |
||
1227 | + * names of its contributors may be used to endorse or promote products |
||
1228 | + * derived from this software without specific prior written permission. |
||
1229 | + * |
||
1230 | + * |
||
1231 | + * ALTERNATIVELY, this software may be distributed under the terms of the |
||
1232 | + * GNU General Public License ("GPL") as published by the Free Software |
||
1233 | + * Foundation, either version 2 of that License or (at your option) any |
||
1234 | + * later version. |
||
1235 | + * |
||
1236 | + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY |
||
1237 | + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||
1238 | + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||
1239 | + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY |
||
1240 | + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||
1241 | + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
1242 | + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||
1243 | + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
1244 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
1245 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
1246 | + */ |
||
1247 | + |
||
1248 | +#include <linux/module.h> |
||
1249 | + |
||
1250 | +#include <linux/netdevice.h> |
||
1251 | +#include <linux/etherdevice.h> |
||
1252 | +#include <linux/msi.h> |
||
1253 | +#include <linux/rtnetlink.h> |
||
1254 | +#include <linux/if_vlan.h> |
||
1255 | + |
||
1256 | +#include <uapi/linux/if_bridge.h> |
||
1257 | +#include <net/netlink.h> |
||
1258 | + |
||
1259 | +#include <linux/of.h> |
||
1260 | +#include <linux/of_mdio.h> |
||
1261 | +#include <linux/of_net.h> |
||
1262 | +#include <linux/phy.h> |
||
1263 | +#include <linux/phy_fixed.h> |
||
1264 | + |
||
1265 | +#include <linux/fsl/mc.h> |
||
1266 | + |
||
1267 | +#include "dpmac.h" |
||
1268 | +#include "dpmac-cmd.h" |
||
1269 | + |
||
1270 | +struct dpaa2_mac_priv { |
||
1271 | + struct net_device *netdev; |
||
1272 | + struct fsl_mc_device *mc_dev; |
||
1273 | + struct dpmac_attr attr; |
||
1274 | + struct dpmac_link_state old_state; |
||
1275 | +}; |
||
1276 | + |
||
1277 | +/* TODO: fix the 10G modes, mapping can't be right: |
||
1278 | + * XGMII is paralel |
||
1279 | + * XAUI is serial, using 8b/10b encoding |
||
1280 | + * XFI is also serial but using 64b/66b encoding |
||
1281 | + * they can't all map to XGMII... |
||
1282 | + * |
||
1283 | + * This must be kept in sync with enum dpmac_eth_if. |
||
1284 | + */ |
||
1285 | +static phy_interface_t dpaa2_mac_iface_mode[] = { |
||
1286 | + PHY_INTERFACE_MODE_MII, /* DPMAC_ETH_IF_MII */ |
||
1287 | + PHY_INTERFACE_MODE_RMII, /* DPMAC_ETH_IF_RMII */ |
||
1288 | + PHY_INTERFACE_MODE_SMII, /* DPMAC_ETH_IF_SMII */ |
||
1289 | + PHY_INTERFACE_MODE_GMII, /* DPMAC_ETH_IF_GMII */ |
||
1290 | + PHY_INTERFACE_MODE_RGMII, /* DPMAC_ETH_IF_RGMII */ |
||
1291 | + PHY_INTERFACE_MODE_SGMII, /* DPMAC_ETH_IF_SGMII */ |
||
1292 | + PHY_INTERFACE_MODE_QSGMII, /* DPMAC_ETH_IF_QSGMII */ |
||
1293 | + PHY_INTERFACE_MODE_XGMII, /* DPMAC_ETH_IF_XAUI */ |
||
1294 | + PHY_INTERFACE_MODE_XGMII, /* DPMAC_ETH_IF_XFI */ |
||
1295 | +}; |
||
1296 | + |
||
1297 | +static void dpaa2_mac_link_changed(struct net_device *netdev) |
||
1298 | +{ |
||
1299 | + struct phy_device *phydev; |
||
1300 | + struct dpmac_link_state state = { 0 }; |
||
1301 | + struct dpaa2_mac_priv *priv = netdev_priv(netdev); |
||
1302 | + int err; |
||
1303 | + |
||
1304 | + /* the PHY just notified us of link state change */ |
||
1305 | + phydev = netdev->phydev; |
||
1306 | + |
||
1307 | + state.up = !!phydev->link; |
||
1308 | + if (phydev->link) { |
||
1309 | + state.rate = phydev->speed; |
||
1310 | + |
||
1311 | + if (!phydev->duplex) |
||
1312 | + state.options |= DPMAC_LINK_OPT_HALF_DUPLEX; |
||
1313 | + if (phydev->autoneg) |
||
1314 | + state.options |= DPMAC_LINK_OPT_AUTONEG; |
||
1315 | + |
||
1316 | + netif_carrier_on(netdev); |
||
1317 | + } else { |
||
1318 | + netif_carrier_off(netdev); |
||
1319 | + } |
||
1320 | + |
||
1321 | + if (priv->old_state.up != state.up || |
||
1322 | + priv->old_state.rate != state.rate || |
||
1323 | + priv->old_state.options != state.options) { |
||
1324 | + priv->old_state = state; |
||
1325 | + phy_print_status(phydev); |
||
1326 | + } |
||
1327 | + |
||
1328 | + /* We must interrogate MC at all times, because we don't know |
||
1329 | + * when and whether a potential DPNI may have read the link state. |
||
1330 | + */ |
||
1331 | + err = dpmac_set_link_state(priv->mc_dev->mc_io, 0, |
||
1332 | + priv->mc_dev->mc_handle, &state); |
||
1333 | + if (unlikely(err)) |
||
1334 | + dev_err(&priv->mc_dev->dev, "dpmac_set_link_state: %d\n", err); |
||
1335 | +} |
||
1336 | + |
||
1337 | +static int dpaa2_mac_open(struct net_device *netdev) |
||
1338 | +{ |
||
1339 | + /* start PHY state machine */ |
||
1340 | + phy_start(netdev->phydev); |
||
1341 | + |
||
1342 | + return 0; |
||
1343 | +} |
||
1344 | + |
||
1345 | +static int dpaa2_mac_stop(struct net_device *netdev) |
||
1346 | +{ |
||
1347 | + if (!netdev->phydev) |
||
1348 | + goto done; |
||
1349 | + |
||
1350 | + /* stop PHY state machine */ |
||
1351 | + phy_stop(netdev->phydev); |
||
1352 | + |
||
1353 | + /* signal link down to firmware */ |
||
1354 | + netdev->phydev->link = 0; |
||
1355 | + dpaa2_mac_link_changed(netdev); |
||
1356 | + |
||
1357 | +done: |
||
1358 | + return 0; |
||
1359 | +} |
||
1360 | + |
||
1361 | +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS |
||
1362 | +static netdev_tx_t dpaa2_mac_drop_frame(struct sk_buff *skb, |
||
1363 | + struct net_device *dev) |
||
1364 | +{ |
||
1365 | + /* we don't support I/O for now, drop the frame */ |
||
1366 | + dev_kfree_skb_any(skb); |
||
1367 | + return NETDEV_TX_OK; |
||
1368 | +} |
||
1369 | + |
||
1370 | +static int dpaa2_mac_get_link_ksettings(struct net_device *netdev, |
||
1371 | + struct ethtool_link_ksettings *ks) |
||
1372 | +{ |
||
1373 | + phy_ethtool_ksettings_get(netdev->phydev, ks); |
||
1374 | + |
||
1375 | + return 0; |
||
1376 | +} |
||
1377 | + |
||
1378 | +static int dpaa2_mac_set_link_ksettings(struct net_device *netdev, |
||
1379 | + const struct ethtool_link_ksettings *ks) |
||
1380 | +{ |
||
1381 | + return phy_ethtool_ksettings_set(netdev->phydev, ks); |
||
1382 | +} |
||
1383 | + |
||
1384 | +static void dpaa2_mac_get_stats(struct net_device *netdev, |
||
1385 | + struct rtnl_link_stats64 *storage) |
||
1386 | +{ |
||
1387 | + struct dpaa2_mac_priv *priv = netdev_priv(netdev); |
||
1388 | + u64 tmp; |
||
1389 | + int err; |
||
1390 | + |
||
1391 | + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle, |
||
1392 | + DPMAC_CNT_EGR_MCAST_FRAME, |
||
1393 | + &storage->tx_packets); |
||
1394 | + if (err) |
||
1395 | + goto error; |
||
1396 | + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle, |
||
1397 | + DPMAC_CNT_EGR_BCAST_FRAME, &tmp); |
||
1398 | + if (err) |
||
1399 | + goto error; |
||
1400 | + storage->tx_packets += tmp; |
||
1401 | + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle, |
||
1402 | + DPMAC_CNT_EGR_UCAST_FRAME, &tmp); |
||
1403 | + if (err) |
||
1404 | + goto error; |
||
1405 | + storage->tx_packets += tmp; |
||
1406 | + |
||
1407 | + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle, |
||
1408 | + DPMAC_CNT_EGR_UNDERSIZED, &storage->tx_dropped); |
||
1409 | + if (err) |
||
1410 | + goto error; |
||
1411 | + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle, |
||
1412 | + DPMAC_CNT_EGR_BYTE, &storage->tx_bytes); |
||
1413 | + if (err) |
||
1414 | + goto error; |
||
1415 | + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle, |
||
1416 | + DPMAC_CNT_EGR_ERR_FRAME, &storage->tx_errors); |
||
1417 | + if (err) |
||
1418 | + goto error; |
||
1419 | + |
||
1420 | + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle, |
||
1421 | + DPMAC_CNT_ING_ALL_FRAME, &storage->rx_packets); |
||
1422 | + if (err) |
||
1423 | + goto error; |
||
1424 | + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle, |
||
1425 | + DPMAC_CNT_ING_MCAST_FRAME, &storage->multicast); |
||
1426 | + if (err) |
||
1427 | + goto error; |
||
1428 | + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle, |
||
1429 | + DPMAC_CNT_ING_FRAME_DISCARD, |
||
1430 | + &storage->rx_dropped); |
||
1431 | + if (err) |
||
1432 | + goto error; |
||
1433 | + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle, |
||
1434 | + DPMAC_CNT_ING_ALIGN_ERR, &storage->rx_errors); |
||
1435 | + if (err) |
||
1436 | + goto error; |
||
1437 | + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle, |
||
1438 | + DPMAC_CNT_ING_OVERSIZED, &tmp); |
||
1439 | + if (err) |
||
1440 | + goto error; |
||
1441 | + storage->rx_errors += tmp; |
||
1442 | + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle, |
||
1443 | + DPMAC_CNT_ING_BYTE, &storage->rx_bytes); |
||
1444 | + if (err) |
||
1445 | + goto error; |
||
1446 | + |
||
1447 | + return; |
||
1448 | +error: |
||
1449 | + netdev_err(netdev, "dpmac_get_counter err %d\n", err); |
||
1450 | +} |
||
1451 | + |
||
1452 | +static struct { |
||
1453 | + enum dpmac_counter id; |
||
1454 | + char name[ETH_GSTRING_LEN]; |
||
1455 | +} dpaa2_mac_counters[] = { |
||
1456 | + {DPMAC_CNT_ING_ALL_FRAME, "rx all frames"}, |
||
1457 | + {DPMAC_CNT_ING_GOOD_FRAME, "rx frames ok"}, |
||
1458 | + {DPMAC_CNT_ING_ERR_FRAME, "rx frame errors"}, |
||
1459 | + {DPMAC_CNT_ING_FRAME_DISCARD, "rx frame discards"}, |
||
1460 | + {DPMAC_CNT_ING_UCAST_FRAME, "rx u-cast"}, |
||
1461 | + {DPMAC_CNT_ING_BCAST_FRAME, "rx b-cast"}, |
||
1462 | + {DPMAC_CNT_ING_MCAST_FRAME, "rx m-cast"}, |
||
1463 | + {DPMAC_CNT_ING_FRAME_64, "rx 64 bytes"}, |
||
1464 | + {DPMAC_CNT_ING_FRAME_127, "rx 65-127 bytes"}, |
||
1465 | + {DPMAC_CNT_ING_FRAME_255, "rx 128-255 bytes"}, |
||
1466 | + {DPMAC_CNT_ING_FRAME_511, "rx 256-511 bytes"}, |
||
1467 | + {DPMAC_CNT_ING_FRAME_1023, "rx 512-1023 bytes"}, |
||
1468 | + {DPMAC_CNT_ING_FRAME_1518, "rx 1024-1518 bytes"}, |
||
1469 | + {DPMAC_CNT_ING_FRAME_1519_MAX, "rx 1519-max bytes"}, |
||
1470 | + {DPMAC_CNT_ING_FRAG, "rx frags"}, |
||
1471 | + {DPMAC_CNT_ING_JABBER, "rx jabber"}, |
||
1472 | + {DPMAC_CNT_ING_ALIGN_ERR, "rx align errors"}, |
||
1473 | + {DPMAC_CNT_ING_OVERSIZED, "rx oversized"}, |
||
1474 | + {DPMAC_CNT_ING_VALID_PAUSE_FRAME, "rx pause"}, |
||
1475 | + {DPMAC_CNT_ING_BYTE, "rx bytes"}, |
||
1476 | + {DPMAC_CNT_ENG_GOOD_FRAME, "tx frames ok"}, |
||
1477 | + {DPMAC_CNT_EGR_UCAST_FRAME, "tx u-cast"}, |
||
1478 | + {DPMAC_CNT_EGR_MCAST_FRAME, "tx m-cast"}, |
||
1479 | + {DPMAC_CNT_EGR_BCAST_FRAME, "tx b-cast"}, |
||
1480 | + {DPMAC_CNT_EGR_ERR_FRAME, "tx frame errors"}, |
||
1481 | + {DPMAC_CNT_EGR_UNDERSIZED, "tx undersized"}, |
||
1482 | + {DPMAC_CNT_EGR_VALID_PAUSE_FRAME, "tx b-pause"}, |
||
1483 | + {DPMAC_CNT_EGR_BYTE, "tx bytes"}, |
||
1484 | + |
||
1485 | +}; |
||
1486 | + |
||
1487 | +static void dpaa2_mac_get_strings(struct net_device *netdev, |
||
1488 | + u32 stringset, u8 *data) |
||
1489 | +{ |
||
1490 | + int i; |
||
1491 | + |
||
1492 | + switch (stringset) { |
||
1493 | + case ETH_SS_STATS: |
||
1494 | + for (i = 0; i < ARRAY_SIZE(dpaa2_mac_counters); i++) |
||
1495 | + memcpy(data + i * ETH_GSTRING_LEN, |
||
1496 | + dpaa2_mac_counters[i].name, |
||
1497 | + ETH_GSTRING_LEN); |
||
1498 | + break; |
||
1499 | + } |
||
1500 | +} |
||
1501 | + |
||
1502 | +static void dpaa2_mac_get_ethtool_stats(struct net_device *netdev, |
||
1503 | + struct ethtool_stats *stats, |
||
1504 | + u64 *data) |
||
1505 | +{ |
||
1506 | + struct dpaa2_mac_priv *priv = netdev_priv(netdev); |
||
1507 | + int i; |
||
1508 | + int err; |
||
1509 | + |
||
1510 | + for (i = 0; i < ARRAY_SIZE(dpaa2_mac_counters); i++) { |
||
1511 | + err = dpmac_get_counter(priv->mc_dev->mc_io, |
||
1512 | + 0, |
||
1513 | + priv->mc_dev->mc_handle, |
||
1514 | + dpaa2_mac_counters[i].id, &data[i]); |
||
1515 | + if (err) |
||
1516 | + netdev_err(netdev, "dpmac_get_counter[%s] err %d\n", |
||
1517 | + dpaa2_mac_counters[i].name, err); |
||
1518 | + } |
||
1519 | +} |
||
1520 | + |
||
1521 | +static int dpaa2_mac_get_sset_count(struct net_device *dev, int sset) |
||
1522 | +{ |
||
1523 | + switch (sset) { |
||
1524 | + case ETH_SS_STATS: |
||
1525 | + return ARRAY_SIZE(dpaa2_mac_counters); |
||
1526 | + default: |
||
1527 | + return -EOPNOTSUPP; |
||
1528 | + } |
||
1529 | +} |
||
1530 | + |
||
1531 | +static const struct net_device_ops dpaa2_mac_ndo_ops = { |
||
1532 | + .ndo_open = &dpaa2_mac_open, |
||
1533 | + .ndo_stop = &dpaa2_mac_stop, |
||
1534 | + .ndo_start_xmit = &dpaa2_mac_drop_frame, |
||
1535 | + .ndo_get_stats64 = &dpaa2_mac_get_stats, |
||
1536 | +}; |
||
1537 | + |
||
1538 | +static const struct ethtool_ops dpaa2_mac_ethtool_ops = { |
||
1539 | + .get_link_ksettings = &dpaa2_mac_get_link_ksettings, |
||
1540 | + .set_link_ksettings = &dpaa2_mac_set_link_ksettings, |
||
1541 | + .get_strings = &dpaa2_mac_get_strings, |
||
1542 | + .get_ethtool_stats = &dpaa2_mac_get_ethtool_stats, |
||
1543 | + .get_sset_count = &dpaa2_mac_get_sset_count, |
||
1544 | +}; |
||
1545 | +#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */ |
||
1546 | + |
||
1547 | +static void configure_link(struct dpaa2_mac_priv *priv, |
||
1548 | + struct dpmac_link_cfg *cfg) |
||
1549 | +{ |
||
1550 | + struct phy_device *phydev = priv->netdev->phydev; |
||
1551 | + |
||
1552 | + if (unlikely(!phydev)) |
||
1553 | + return; |
||
1554 | + |
||
1555 | + phydev->speed = cfg->rate; |
||
1556 | + phydev->duplex = !!(cfg->options & DPMAC_LINK_OPT_HALF_DUPLEX); |
||
1557 | + |
||
1558 | + if (cfg->options & DPMAC_LINK_OPT_AUTONEG) { |
||
1559 | + phydev->autoneg = 1; |
||
1560 | + phydev->advertising |= ADVERTISED_Autoneg; |
||
1561 | + } else { |
||
1562 | + phydev->autoneg = 0; |
||
1563 | + phydev->advertising &= ~ADVERTISED_Autoneg; |
||
1564 | + } |
||
1565 | + |
||
1566 | + phy_start_aneg(phydev); |
||
1567 | +} |
||
1568 | + |
||
1569 | +static irqreturn_t dpaa2_mac_irq_handler(int irq_num, void *arg) |
||
1570 | +{ |
||
1571 | + struct device *dev = (struct device *)arg; |
||
1572 | + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); |
||
1573 | + struct dpaa2_mac_priv *priv = dev_get_drvdata(dev); |
||
1574 | + struct dpmac_link_cfg link_cfg; |
||
1575 | + u32 status; |
||
1576 | + int err; |
||
1577 | + |
||
1578 | + err = dpmac_get_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle, |
||
1579 | + DPMAC_IRQ_INDEX, &status); |
||
1580 | + if (unlikely(err || !status)) |
||
1581 | + return IRQ_NONE; |
||
1582 | + |
||
1583 | + /* DPNI-initiated link configuration; 'ifconfig up' also calls this */ |
||
1584 | + if (status & DPMAC_IRQ_EVENT_LINK_CFG_REQ) { |
||
1585 | + err = dpmac_get_link_cfg(mc_dev->mc_io, 0, mc_dev->mc_handle, |
||
1586 | + &link_cfg); |
||
1587 | + if (unlikely(err)) |
||
1588 | + goto out; |
||
1589 | + |
||
1590 | + configure_link(priv, &link_cfg); |
||
1591 | + } |
||
1592 | + |
||
1593 | +out: |
||
1594 | + dpmac_clear_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle, |
||
1595 | + DPMAC_IRQ_INDEX, status); |
||
1596 | + |
||
1597 | + return IRQ_HANDLED; |
||
1598 | +} |
||
1599 | + |
||
1600 | +static int setup_irqs(struct fsl_mc_device *mc_dev) |
||
1601 | +{ |
||
1602 | + int err = 0; |
||
1603 | + struct fsl_mc_device_irq *irq; |
||
1604 | + |
||
1605 | + err = fsl_mc_allocate_irqs(mc_dev); |
||
1606 | + if (err) { |
||
1607 | + dev_err(&mc_dev->dev, "fsl_mc_allocate_irqs err %d\n", err); |
||
1608 | + return err; |
||
1609 | + } |
||
1610 | + |
||
1611 | + irq = mc_dev->irqs[0]; |
||
1612 | + err = devm_request_threaded_irq(&mc_dev->dev, irq->msi_desc->irq, |
||
1613 | + NULL, &dpaa2_mac_irq_handler, |
||
1614 | + IRQF_NO_SUSPEND | IRQF_ONESHOT, |
||
1615 | + dev_name(&mc_dev->dev), &mc_dev->dev); |
||
1616 | + if (err) { |
||
1617 | + dev_err(&mc_dev->dev, "devm_request_threaded_irq err %d\n", |
||
1618 | + err); |
||
1619 | + goto free_irq; |
||
1620 | + } |
||
1621 | + |
||
1622 | + err = dpmac_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, |
||
1623 | + DPMAC_IRQ_INDEX, DPMAC_IRQ_EVENT_LINK_CFG_REQ); |
||
1624 | + if (err) { |
||
1625 | + dev_err(&mc_dev->dev, "dpmac_set_irq_mask err %d\n", err); |
||
1626 | + goto free_irq; |
||
1627 | + } |
||
1628 | + err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, |
||
1629 | + DPMAC_IRQ_INDEX, 1); |
||
1630 | + if (err) { |
||
1631 | + dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err); |
||
1632 | + goto free_irq; |
||
1633 | + } |
||
1634 | + |
||
1635 | + return 0; |
||
1636 | + |
||
1637 | +free_irq: |
||
1638 | + fsl_mc_free_irqs(mc_dev); |
||
1639 | + |
||
1640 | + return err; |
||
1641 | +} |
||
1642 | + |
||
1643 | +static void teardown_irqs(struct fsl_mc_device *mc_dev) |
||
1644 | +{ |
||
1645 | + int err; |
||
1646 | + |
||
1647 | + err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, |
||
1648 | + DPMAC_IRQ_INDEX, 0); |
||
1649 | + if (err) |
||
1650 | + dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err); |
||
1651 | + |
||
1652 | + fsl_mc_free_irqs(mc_dev); |
||
1653 | +} |
||
1654 | + |
||
1655 | +static struct device_node *find_dpmac_node(struct device *dev, u16 dpmac_id) |
||
1656 | +{ |
||
1657 | + struct device_node *dpmacs, *dpmac = NULL; |
||
1658 | + struct device_node *mc_node = dev->of_node; |
||
1659 | + u32 id; |
||
1660 | + int err; |
||
1661 | + |
||
1662 | + dpmacs = of_find_node_by_name(mc_node, "dpmacs"); |
||
1663 | + if (!dpmacs) { |
||
1664 | + dev_err(dev, "No dpmacs subnode in device-tree\n"); |
||
1665 | + return NULL; |
||
1666 | + } |
||
1667 | + |
||
1668 | + while ((dpmac = of_get_next_child(dpmacs, dpmac))) { |
||
1669 | + err = of_property_read_u32(dpmac, "reg", &id); |
||
1670 | + if (err) |
||
1671 | + continue; |
||
1672 | + if (id == dpmac_id) |
||
1673 | + return dpmac; |
||
1674 | + } |
||
1675 | + |
||
1676 | + return NULL; |
||
1677 | +} |
||
1678 | + |
||
1679 | +static int dpaa2_mac_probe(struct fsl_mc_device *mc_dev) |
||
1680 | +{ |
||
1681 | + struct device *dev; |
||
1682 | + struct dpaa2_mac_priv *priv = NULL; |
||
1683 | + struct device_node *phy_node, *dpmac_node; |
||
1684 | + struct net_device *netdev; |
||
1685 | + phy_interface_t if_mode; |
||
1686 | + int err = 0; |
||
1687 | + |
||
1688 | + dev = &mc_dev->dev; |
||
1689 | + |
||
1690 | + /* prepare a net_dev structure to make the phy lib API happy */ |
||
1691 | + netdev = alloc_etherdev(sizeof(*priv)); |
||
1692 | + if (!netdev) { |
||
1693 | + dev_err(dev, "alloc_etherdev error\n"); |
||
1694 | + err = -ENOMEM; |
||
1695 | + goto err_exit; |
||
1696 | + } |
||
1697 | + priv = netdev_priv(netdev); |
||
1698 | + priv->mc_dev = mc_dev; |
||
1699 | + priv->netdev = netdev; |
||
1700 | + |
||
1701 | + SET_NETDEV_DEV(netdev, dev); |
||
1702 | + |
||
1703 | +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS |
||
1704 | + snprintf(netdev->name, IFNAMSIZ, "mac%d", mc_dev->obj_desc.id); |
||
1705 | +#endif |
||
1706 | + |
||
1707 | + dev_set_drvdata(dev, priv); |
||
1708 | + |
||
1709 | + /* We may need to issue MC commands while in atomic context */ |
||
1710 | + err = fsl_mc_portal_allocate(mc_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, |
||
1711 | + &mc_dev->mc_io); |
||
1712 | + if (err || !mc_dev->mc_io) { |
||
1713 | + dev_dbg(dev, "fsl_mc_portal_allocate error: %d\n", err); |
||
1714 | + err = -EPROBE_DEFER; |
||
1715 | + goto err_free_netdev; |
||
1716 | + } |
||
1717 | + |
||
1718 | + err = dpmac_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id, |
||
1719 | + &mc_dev->mc_handle); |
||
1720 | + if (err || !mc_dev->mc_handle) { |
||
1721 | + dev_err(dev, "dpmac_open error: %d\n", err); |
||
1722 | + err = -ENODEV; |
||
1723 | + goto err_free_mcp; |
||
1724 | + } |
||
1725 | + |
||
1726 | + err = dpmac_get_attributes(mc_dev->mc_io, 0, |
||
1727 | + mc_dev->mc_handle, &priv->attr); |
||
1728 | + if (err) { |
||
1729 | + dev_err(dev, "dpmac_get_attributes err %d\n", err); |
||
1730 | + err = -EINVAL; |
||
1731 | + goto err_close; |
||
1732 | + } |
||
1733 | + |
||
1734 | + /* Look up the DPMAC node in the device-tree. */ |
||
1735 | + dpmac_node = find_dpmac_node(dev, priv->attr.id); |
||
1736 | + if (!dpmac_node) { |
||
1737 | + dev_err(dev, "No dpmac@%d subnode found.\n", priv->attr.id); |
||
1738 | + err = -ENODEV; |
||
1739 | + goto err_close; |
||
1740 | + } |
||
1741 | + |
||
1742 | + err = setup_irqs(mc_dev); |
||
1743 | + if (err) { |
||
1744 | + err = -EFAULT; |
||
1745 | + goto err_close; |
||
1746 | + } |
||
1747 | + |
||
1748 | +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS |
||
1749 | + /* OPTIONAL, register netdev just to make it visible to the user */ |
||
1750 | + netdev->netdev_ops = &dpaa2_mac_ndo_ops; |
||
1751 | + netdev->ethtool_ops = &dpaa2_mac_ethtool_ops; |
||
1752 | + |
||
1753 | + /* phy starts up enabled so netdev should be up too */ |
||
1754 | + netdev->flags |= IFF_UP; |
||
1755 | + |
||
1756 | + err = register_netdev(priv->netdev); |
||
1757 | + if (err < 0) { |
||
1758 | + dev_err(dev, "register_netdev error %d\n", err); |
||
1759 | + err = -ENODEV; |
||
1760 | + goto err_free_irq; |
||
1761 | + } |
||
1762 | +#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */ |
||
1763 | + |
||
1764 | + /* probe the PHY as a fixed-link if there's a phy-handle defined |
||
1765 | + * in the device tree |
||
1766 | + */ |
||
1767 | + phy_node = of_parse_phandle(dpmac_node, "phy-handle", 0); |
||
1768 | + if (!phy_node) { |
||
1769 | + goto probe_fixed_link; |
||
1770 | + } |
||
1771 | + |
||
1772 | + if (priv->attr.eth_if < ARRAY_SIZE(dpaa2_mac_iface_mode)) { |
||
1773 | + if_mode = dpaa2_mac_iface_mode[priv->attr.eth_if]; |
||
1774 | + dev_dbg(dev, "\tusing if mode %s for eth_if %d\n", |
||
1775 | + phy_modes(if_mode), priv->attr.eth_if); |
||
1776 | + } else { |
||
1777 | + dev_warn(dev, "Unexpected interface mode %d, will probe as fixed link\n", |
||
1778 | + priv->attr.eth_if); |
||
1779 | + goto probe_fixed_link; |
||
1780 | + } |
||
1781 | + |
||
1782 | + /* try to connect to the PHY */ |
||
1783 | + netdev->phydev = of_phy_connect(netdev, phy_node, |
||
1784 | + &dpaa2_mac_link_changed, 0, if_mode); |
||
1785 | + if (!netdev->phydev) { |
||
1786 | + /* No need for dev_err(); the kernel's loud enough as it is. */ |
||
1787 | + dev_dbg(dev, "Can't of_phy_connect() now.\n"); |
||
1788 | + /* We might be waiting for the MDIO MUX to probe, so defer |
||
1789 | + * our own probing. |
||
1790 | + */ |
||
1791 | + err = -EPROBE_DEFER; |
||
1792 | + goto err_defer; |
||
1793 | + } |
||
1794 | + dev_info(dev, "Connected to %s PHY.\n", phy_modes(if_mode)); |
||
1795 | + |
||
1796 | +probe_fixed_link: |
||
1797 | + if (!netdev->phydev) { |
||
1798 | + struct fixed_phy_status status = { |
||
1799 | + .link = 1, |
||
1800 | + /* fixed-phys don't support 10Gbps speed for now */ |
||
1801 | + .speed = 1000, |
||
1802 | + .duplex = 1, |
||
1803 | + }; |
||
1804 | + |
||
1805 | + /* try to register a fixed link phy */ |
||
1806 | + netdev->phydev = fixed_phy_register(PHY_POLL, &status, -1, |
||
1807 | + NULL); |
||
1808 | + if (!netdev->phydev || IS_ERR(netdev->phydev)) { |
||
1809 | + dev_err(dev, "error trying to register fixed PHY\n"); |
||
1810 | + /* So we don't crash unregister_netdev() later on */ |
||
1811 | + netdev->phydev = NULL; |
||
1812 | + err = -EFAULT; |
||
1813 | + goto err_no_phy; |
||
1814 | + } |
||
1815 | + dev_info(dev, "Registered fixed PHY.\n"); |
||
1816 | + } |
||
1817 | + |
||
1818 | + dpaa2_mac_open(netdev); |
||
1819 | + |
||
1820 | + return 0; |
||
1821 | + |
||
1822 | +err_defer: |
||
1823 | +err_no_phy: |
||
1824 | +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS |
||
1825 | + unregister_netdev(netdev); |
||
1826 | +err_free_irq: |
||
1827 | +#endif |
||
1828 | + teardown_irqs(mc_dev); |
||
1829 | +err_close: |
||
1830 | + dpmac_close(mc_dev->mc_io, 0, mc_dev->mc_handle); |
||
1831 | +err_free_mcp: |
||
1832 | + fsl_mc_portal_free(mc_dev->mc_io); |
||
1833 | +err_free_netdev: |
||
1834 | + free_netdev(netdev); |
||
1835 | +err_exit: |
||
1836 | + return err; |
||
1837 | +} |
||
1838 | + |
||
1839 | +static int dpaa2_mac_remove(struct fsl_mc_device *mc_dev) |
||
1840 | +{ |
||
1841 | + struct device *dev = &mc_dev->dev; |
||
1842 | + struct dpaa2_mac_priv *priv = dev_get_drvdata(dev); |
||
1843 | + struct net_device *netdev = priv->netdev; |
||
1844 | + |
||
1845 | + dpaa2_mac_stop(netdev); |
||
1846 | + |
||
1847 | + if (phy_is_pseudo_fixed_link(netdev->phydev)) |
||
1848 | + fixed_phy_unregister(netdev->phydev); |
||
1849 | + else |
||
1850 | + phy_disconnect(netdev->phydev); |
||
1851 | + netdev->phydev = NULL; |
||
1852 | + |
||
1853 | +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS |
||
1854 | + unregister_netdev(priv->netdev); |
||
1855 | +#endif |
||
1856 | + teardown_irqs(priv->mc_dev); |
||
1857 | + dpmac_close(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle); |
||
1858 | + fsl_mc_portal_free(priv->mc_dev->mc_io); |
||
1859 | + free_netdev(priv->netdev); |
||
1860 | + |
||
1861 | + dev_set_drvdata(dev, NULL); |
||
1862 | + |
||
1863 | + return 0; |
||
1864 | +} |
||
1865 | + |
||
1866 | +static const struct fsl_mc_device_id dpaa2_mac_match_id_table[] = { |
||
1867 | + { |
||
1868 | + .vendor = FSL_MC_VENDOR_FREESCALE, |
||
1869 | + .obj_type = "dpmac", |
||
1870 | + }, |
||
1871 | + { .vendor = 0x0 } |
||
1872 | +}; |
||
1873 | +MODULE_DEVICE_TABLE(fslmc, dpaa2_mac_match_id_table); |
||
1874 | + |
||
1875 | +static struct fsl_mc_driver dpaa2_mac_drv = { |
||
1876 | + .driver = { |
||
1877 | + .name = KBUILD_MODNAME, |
||
1878 | + .owner = THIS_MODULE, |
||
1879 | + }, |
||
1880 | + .probe = dpaa2_mac_probe, |
||
1881 | + .remove = dpaa2_mac_remove, |
||
1882 | + .match_id_table = dpaa2_mac_match_id_table, |
||
1883 | +}; |
||
1884 | + |
||
1885 | +module_fsl_mc_driver(dpaa2_mac_drv); |
||
1886 | + |
||
1887 | +MODULE_LICENSE("GPL"); |
||
1888 | +MODULE_DESCRIPTION("DPAA2 PHY proxy interface driver"); |