layerscape: upgrade kernel to 4.14
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.14 / 704-dpaa2-mac-phy-support-layerscape.patch
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");