1 From ab58c737bc723f52e787e1767bbbf0fcbe39a27b Mon Sep 17 00:00:00 2001
2 From: Biwen Li <biwen.li@nxp.com>
3 Date: Wed, 17 Apr 2019 18:58:43 +0800
4 Subject: [PATCH] mc-bus: support layerscape
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
9 This is an integrated patch of mc-bus for layerscape
11 Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com>
12 Signed-off-by: Biwen Li <biwen.li@nxp.com>
13 Signed-off-by: Bogdan Purcareata <bogdan.purcareata@nxp.com>
14 Signed-off-by: Cristian Sovaiala <cristian.sovaiala@freescale.com>
15 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
16 Signed-off-by: Guanhua Gao <guanhua.gao@nxp.com>
17 Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
18 Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
19 Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
20 Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
21 Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
22 Signed-off-by: Lijun Pan <Lijun.Pan@freescale.com>
23 Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com>
24 Signed-off-by: Radu Alexe <radu.alexe@nxp.com>
25 Signed-off-by: Razvan Stefanescu <razvan.stefanescu@nxp.com>
26 Signed-off-by: Roy Pledge <roy.pledge@nxp.com>
27 Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
29 drivers/bus/Kconfig | 2 +
30 drivers/bus/Makefile | 4 +
31 drivers/bus/fsl-mc/Kconfig | 23 +
32 drivers/bus/fsl-mc/Makefile | 21 +
33 .../{staging/fsl-mc/bus => bus/fsl-mc}/dpbp.c | 97 +-
34 .../fsl-mc/bus => bus/fsl-mc}/dpcon.c | 103 +-
35 drivers/bus/fsl-mc/dpmcp.c | 99 ++
36 .../fsl-mc/bus => bus/fsl-mc}/dprc-driver.c | 96 +-
37 .../{staging/fsl-mc/bus => bus/fsl-mc}/dprc.c | 289 +----
38 .../bus => bus/fsl-mc}/fsl-mc-allocator.c | 123 +-
39 .../fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c | 322 +++++-
40 .../fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c | 16 +-
41 drivers/bus/fsl-mc/fsl-mc-private.h | 223 ++++
42 drivers/bus/fsl-mc/fsl-mc-restool.c | 219 ++++
43 .../fsl-mc/bus => bus/fsl-mc}/mc-io.c | 51 +-
44 .../fsl-mc/bus => bus/fsl-mc}/mc-sys.c | 33 +-
45 drivers/irqchip/Kconfig | 6 +
46 drivers/irqchip/Makefile | 1 +
47 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 98 ++
48 .../staging/fsl-dpaa2/ethernet/dpaa2-eth.c | 2 +-
49 .../staging/fsl-dpaa2/ethernet/dpaa2-eth.h | 3 +-
50 drivers/staging/fsl-dpaa2/ethernet/dpni.c | 2 +-
51 drivers/staging/fsl-mc/bus/Kconfig | 15 +-
52 drivers/staging/fsl-mc/bus/Makefile | 13 -
53 drivers/staging/fsl-mc/bus/dpio/dpio-driver.c | 2 +-
54 .../staging/fsl-mc/bus/dpio/dpio-service.c | 2 +-
55 drivers/staging/fsl-mc/bus/dpio/dpio.c | 14 +-
56 drivers/staging/fsl-mc/bus/dpmcp-cmd.h | 56 -
57 drivers/staging/fsl-mc/bus/dpmcp.h | 60 -
58 drivers/staging/fsl-mc/bus/dpmng-cmd.h | 58 -
59 drivers/staging/fsl-mc/bus/dprc-cmd.h | 451 --------
60 drivers/staging/fsl-mc/bus/dprc.h | 268 -----
61 .../fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c | 1 +
62 include/linux/fsl/mc.h | 1029 +++++++++++++++++
63 include/uapi/linux/fsl_mc.h | 31 +
64 35 files changed, 2302 insertions(+), 1531 deletions(-)
65 create mode 100644 drivers/bus/fsl-mc/Kconfig
66 create mode 100644 drivers/bus/fsl-mc/Makefile
67 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpbp.c (67%)
68 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dpcon.c (70%)
69 create mode 100644 drivers/bus/fsl-mc/dpmcp.c
70 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc-driver.c (93%)
71 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/dprc.c (68%)
72 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-allocator.c (84%)
73 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-bus.c (75%)
74 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/fsl-mc-msi.c (96%)
75 create mode 100644 drivers/bus/fsl-mc/fsl-mc-private.h
76 create mode 100644 drivers/bus/fsl-mc/fsl-mc-restool.c
77 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-io.c (89%)
78 rename drivers/{staging/fsl-mc/bus => bus/fsl-mc}/mc-sys.c (90%)
79 create mode 100644 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
80 delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp-cmd.h
81 delete mode 100644 drivers/staging/fsl-mc/bus/dpmcp.h
82 delete mode 100644 drivers/staging/fsl-mc/bus/dpmng-cmd.h
83 delete mode 100644 drivers/staging/fsl-mc/bus/dprc-cmd.h
84 delete mode 100644 drivers/staging/fsl-mc/bus/dprc.h
85 create mode 100644 include/linux/fsl/mc.h
86 create mode 100644 include/uapi/linux/fsl_mc.h
88 --- a/drivers/bus/Kconfig
89 +++ b/drivers/bus/Kconfig
90 @@ -184,4 +184,6 @@ config DA8XX_MSTPRI
91 configuration. Allows to adjust the priorities of all master
94 +source "drivers/bus/fsl-mc/Kconfig"
97 --- a/drivers/bus/Makefile
98 +++ b/drivers/bus/Makefile
99 @@ -8,6 +8,10 @@ obj-$(CONFIG_ARM_CCI) += arm-cci.o
100 obj-$(CONFIG_ARM_CCN) += arm-ccn.o
102 obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o
105 +obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
107 obj-$(CONFIG_IMX_WEIM) += imx-weim.o
108 obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o
109 obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o
111 +++ b/drivers/bus/fsl-mc/Kconfig
113 +# SPDX-License-Identifier: GPL-2.0
117 +# Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
121 + bool "QorIQ DPAA2 fsl-mc bus driver"
122 + depends on OF && (ARCH_LAYERSCAPE || (COMPILE_TEST && (ARM || ARM64 || X86 || PPC)))
123 + select GENERIC_MSI_IRQ_DOMAIN
125 + Driver to enable the bus infrastructure for the QorIQ DPAA2
126 + architecture. The fsl-mc bus driver handles discovery of
127 + DPAA2 objects (which are represented as Linux devices) and
128 + binding objects to drivers.
130 +config FSL_MC_RESTOOL
131 + bool "Management Complex (MC) restool support"
132 + depends on FSL_MC_BUS
134 + Provides kernel support for the Management Complex resource
135 + manager user-space tool - restool.
137 +++ b/drivers/bus/fsl-mc/Makefile
139 +# SPDX-License-Identifier: GPL-2.0
141 +# Freescale Management Complex (MC) bus drivers
143 +# Copyright (C) 2014 Freescale Semiconductor, Inc.
145 +obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o
147 +mc-bus-driver-objs := fsl-mc-bus.o \
154 + fsl-mc-allocator.o \
158 +# MC restool kernel support
159 +obj-$(CONFIG_FSL_MC_RESTOOL) += fsl-mc-restool.o
160 --- a/drivers/staging/fsl-mc/bus/dpbp.c
163 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
165 - * Copyright 2013-2016 Freescale Semiconductor Inc.
168 -#include <linux/kernel.h>
169 -#include "../include/mc.h"
170 -#include "../include/dpbp.h"
172 -#include "dpbp-cmd.h"
175 - * dpbp_open() - Open a control session for the specified object.
176 - * @mc_io: Pointer to MC portal's I/O object
177 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
178 - * @dpbp_id: DPBP unique ID
179 - * @token: Returned token; use in subsequent API calls
181 - * This function can be used to open a control session for an
182 - * already created object; an object may have been declared in
183 - * the DPL or by calling the dpbp_create function.
184 - * This function returns a unique authentication token,
185 - * associated with the specific object ID and the specific MC
186 - * portal; this token must be used in all subsequent commands for
187 - * this specific object
189 - * Return: '0' on Success; Error code otherwise.
191 -int dpbp_open(struct fsl_mc_io *mc_io,
196 - struct mc_command cmd = { 0 };
197 - struct dpbp_cmd_open *cmd_params;
200 - /* prepare command */
201 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN,
203 - cmd_params = (struct dpbp_cmd_open *)cmd.params;
204 - cmd_params->dpbp_id = cpu_to_le32(dpbp_id);
206 - /* send command to mc*/
207 - err = mc_send_command(mc_io, &cmd);
211 - /* retrieve response parameters */
212 - *token = mc_cmd_hdr_read_token(&cmd);
216 -EXPORT_SYMBOL(dpbp_open);
219 - * dpbp_close() - Close the control session of the object
220 - * @mc_io: Pointer to MC portal's I/O object
221 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
222 - * @token: Token of DPBP object
224 - * After this function is called, no further operations are
225 - * allowed on the object without opening a new control session.
227 - * Return: '0' on Success; Error code otherwise.
229 -int dpbp_close(struct fsl_mc_io *mc_io,
233 - struct mc_command cmd = { 0 };
235 - /* prepare command */
236 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags,
239 - /* send command to mc*/
240 - return mc_send_command(mc_io, &cmd);
242 -EXPORT_SYMBOL(dpbp_close);
245 - * dpbp_enable() - Enable the DPBP.
246 - * @mc_io: Pointer to MC portal's I/O object
247 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
248 - * @token: Token of DPBP object
250 - * Return: '0' on Success; Error code otherwise.
252 -int dpbp_enable(struct fsl_mc_io *mc_io,
256 - struct mc_command cmd = { 0 };
258 - /* prepare command */
259 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags,
262 - /* send command to mc*/
263 - return mc_send_command(mc_io, &cmd);
265 -EXPORT_SYMBOL(dpbp_enable);
268 - * dpbp_disable() - Disable the DPBP.
269 - * @mc_io: Pointer to MC portal's I/O object
270 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
271 - * @token: Token of DPBP object
273 - * Return: '0' on Success; Error code otherwise.
275 -int dpbp_disable(struct fsl_mc_io *mc_io,
279 - struct mc_command cmd = { 0 };
281 - /* prepare command */
282 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE,
285 - /* send command to mc*/
286 - return mc_send_command(mc_io, &cmd);
288 -EXPORT_SYMBOL(dpbp_disable);
291 - * dpbp_is_enabled() - Check if the DPBP is enabled.
292 - * @mc_io: Pointer to MC portal's I/O object
293 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
294 - * @token: Token of DPBP object
295 - * @en: Returns '1' if object is enabled; '0' otherwise
297 - * Return: '0' on Success; Error code otherwise.
299 -int dpbp_is_enabled(struct fsl_mc_io *mc_io,
304 - struct mc_command cmd = { 0 };
305 - struct dpbp_rsp_is_enabled *rsp_params;
307 - /* prepare command */
308 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_IS_ENABLED, cmd_flags,
311 - /* send command to mc*/
312 - err = mc_send_command(mc_io, &cmd);
316 - /* retrieve response parameters */
317 - rsp_params = (struct dpbp_rsp_is_enabled *)cmd.params;
318 - *en = rsp_params->enabled & DPBP_ENABLE;
322 -EXPORT_SYMBOL(dpbp_is_enabled);
325 - * dpbp_reset() - Reset the DPBP, returns the object to initial state.
326 - * @mc_io: Pointer to MC portal's I/O object
327 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
328 - * @token: Token of DPBP object
330 - * Return: '0' on Success; Error code otherwise.
332 -int dpbp_reset(struct fsl_mc_io *mc_io,
336 - struct mc_command cmd = { 0 };
338 - /* prepare command */
339 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET,
342 - /* send command to mc*/
343 - return mc_send_command(mc_io, &cmd);
345 -EXPORT_SYMBOL(dpbp_reset);
348 - * dpbp_get_attributes - Retrieve DPBP attributes.
350 - * @mc_io: Pointer to MC portal's I/O object
351 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
352 - * @token: Token of DPBP object
353 - * @attr: Returned object's attributes
355 - * Return: '0' on Success; Error code otherwise.
357 -int dpbp_get_attributes(struct fsl_mc_io *mc_io,
360 - struct dpbp_attr *attr)
362 - struct mc_command cmd = { 0 };
363 - struct dpbp_rsp_get_attributes *rsp_params;
366 - /* prepare command */
367 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR,
370 - /* send command to mc*/
371 - err = mc_send_command(mc_io, &cmd);
375 - /* retrieve response parameters */
376 - rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params;
377 - attr->bpid = le16_to_cpu(rsp_params->bpid);
378 - attr->id = le32_to_cpu(rsp_params->id);
382 -EXPORT_SYMBOL(dpbp_get_attributes);
385 - * dpbp_get_api_version - Get Data Path Buffer Pool API version
386 - * @mc_io: Pointer to Mc portal's I/O object
387 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
388 - * @major_ver: Major version of Buffer Pool API
389 - * @minor_ver: Minor version of Buffer Pool API
391 - * Return: '0' on Success; Error code otherwise.
393 -int dpbp_get_api_version(struct fsl_mc_io *mc_io,
398 - struct mc_command cmd = { 0 };
401 - /* prepare command */
402 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_API_VERSION,
405 - /* send command to mc */
406 - err = mc_send_command(mc_io, &cmd);
410 - /* retrieve response parameters */
411 - mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
415 -EXPORT_SYMBOL(dpbp_get_api_version);
417 +++ b/drivers/bus/fsl-mc/dpbp.c
419 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
421 + * Copyright 2013-2016 Freescale Semiconductor Inc.
424 +#include <linux/kernel.h>
425 +#include <linux/fsl/mc.h>
426 +#include <linux/fsl/mc.h>
428 +#include "fsl-mc-private.h"
431 + * dpbp_open() - Open a control session for the specified object.
432 + * @mc_io: Pointer to MC portal's I/O object
433 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
434 + * @dpbp_id: DPBP unique ID
435 + * @token: Returned token; use in subsequent API calls
437 + * This function can be used to open a control session for an
438 + * already created object; an object may have been declared in
439 + * the DPL or by calling the dpbp_create function.
440 + * This function returns a unique authentication token,
441 + * associated with the specific object ID and the specific MC
442 + * portal; this token must be used in all subsequent commands for
443 + * this specific object
445 + * Return: '0' on Success; Error code otherwise.
447 +int dpbp_open(struct fsl_mc_io *mc_io,
452 + struct fsl_mc_command cmd = { 0 };
453 + struct dpbp_cmd_open *cmd_params;
456 + /* prepare command */
457 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN,
459 + cmd_params = (struct dpbp_cmd_open *)cmd.params;
460 + cmd_params->dpbp_id = cpu_to_le32(dpbp_id);
462 + /* send command to mc*/
463 + err = mc_send_command(mc_io, &cmd);
467 + /* retrieve response parameters */
468 + *token = mc_cmd_hdr_read_token(&cmd);
472 +EXPORT_SYMBOL_GPL(dpbp_open);
475 + * dpbp_close() - Close the control session of the object
476 + * @mc_io: Pointer to MC portal's I/O object
477 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
478 + * @token: Token of DPBP object
480 + * After this function is called, no further operations are
481 + * allowed on the object without opening a new control session.
483 + * Return: '0' on Success; Error code otherwise.
485 +int dpbp_close(struct fsl_mc_io *mc_io,
489 + struct fsl_mc_command cmd = { 0 };
491 + /* prepare command */
492 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags,
495 + /* send command to mc*/
496 + return mc_send_command(mc_io, &cmd);
498 +EXPORT_SYMBOL_GPL(dpbp_close);
501 + * dpbp_enable() - Enable the DPBP.
502 + * @mc_io: Pointer to MC portal's I/O object
503 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
504 + * @token: Token of DPBP object
506 + * Return: '0' on Success; Error code otherwise.
508 +int dpbp_enable(struct fsl_mc_io *mc_io,
512 + struct fsl_mc_command cmd = { 0 };
514 + /* prepare command */
515 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags,
518 + /* send command to mc*/
519 + return mc_send_command(mc_io, &cmd);
521 +EXPORT_SYMBOL_GPL(dpbp_enable);
524 + * dpbp_disable() - Disable the DPBP.
525 + * @mc_io: Pointer to MC portal's I/O object
526 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
527 + * @token: Token of DPBP object
529 + * Return: '0' on Success; Error code otherwise.
531 +int dpbp_disable(struct fsl_mc_io *mc_io,
535 + struct fsl_mc_command cmd = { 0 };
537 + /* prepare command */
538 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE,
541 + /* send command to mc*/
542 + return mc_send_command(mc_io, &cmd);
544 +EXPORT_SYMBOL_GPL(dpbp_disable);
547 + * dpbp_reset() - Reset the DPBP, returns the object to initial state.
548 + * @mc_io: Pointer to MC portal's I/O object
549 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
550 + * @token: Token of DPBP object
552 + * Return: '0' on Success; Error code otherwise.
554 +int dpbp_reset(struct fsl_mc_io *mc_io,
558 + struct fsl_mc_command cmd = { 0 };
560 + /* prepare command */
561 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET,
564 + /* send command to mc*/
565 + return mc_send_command(mc_io, &cmd);
567 +EXPORT_SYMBOL_GPL(dpbp_reset);
570 + * dpbp_get_attributes - Retrieve DPBP attributes.
572 + * @mc_io: Pointer to MC portal's I/O object
573 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
574 + * @token: Token of DPBP object
575 + * @attr: Returned object's attributes
577 + * Return: '0' on Success; Error code otherwise.
579 +int dpbp_get_attributes(struct fsl_mc_io *mc_io,
582 + struct dpbp_attr *attr)
584 + struct fsl_mc_command cmd = { 0 };
585 + struct dpbp_rsp_get_attributes *rsp_params;
588 + /* prepare command */
589 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR,
592 + /* send command to mc*/
593 + err = mc_send_command(mc_io, &cmd);
597 + /* retrieve response parameters */
598 + rsp_params = (struct dpbp_rsp_get_attributes *)cmd.params;
599 + attr->bpid = le16_to_cpu(rsp_params->bpid);
600 + attr->id = le32_to_cpu(rsp_params->id);
604 +EXPORT_SYMBOL_GPL(dpbp_get_attributes);
605 --- a/drivers/staging/fsl-mc/bus/dpcon.c
608 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
610 - * Copyright 2013-2016 Freescale Semiconductor Inc.
613 -#include <linux/kernel.h>
614 -#include "../include/mc.h"
615 -#include "../include/dpcon.h"
617 -#include "dpcon-cmd.h"
620 - * dpcon_open() - Open a control session for the specified object
621 - * @mc_io: Pointer to MC portal's I/O object
622 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
623 - * @dpcon_id: DPCON unique ID
624 - * @token: Returned token; use in subsequent API calls
626 - * This function can be used to open a control session for an
627 - * already created object; an object may have been declared in
628 - * the DPL or by calling the dpcon_create() function.
629 - * This function returns a unique authentication token,
630 - * associated with the specific object ID and the specific MC
631 - * portal; this token must be used in all subsequent commands for
632 - * this specific object.
634 - * Return: '0' on Success; Error code otherwise.
636 -int dpcon_open(struct fsl_mc_io *mc_io,
641 - struct mc_command cmd = { 0 };
642 - struct dpcon_cmd_open *dpcon_cmd;
645 - /* prepare command */
646 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN,
649 - dpcon_cmd = (struct dpcon_cmd_open *)cmd.params;
650 - dpcon_cmd->dpcon_id = cpu_to_le32(dpcon_id);
652 - /* send command to mc*/
653 - err = mc_send_command(mc_io, &cmd);
657 - /* retrieve response parameters */
658 - *token = mc_cmd_hdr_read_token(&cmd);
662 -EXPORT_SYMBOL(dpcon_open);
665 - * dpcon_close() - Close the control session of the object
666 - * @mc_io: Pointer to MC portal's I/O object
667 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
668 - * @token: Token of DPCON object
670 - * After this function is called, no further operations are
671 - * allowed on the object without opening a new control session.
673 - * Return: '0' on Success; Error code otherwise.
675 -int dpcon_close(struct fsl_mc_io *mc_io,
679 - struct mc_command cmd = { 0 };
681 - /* prepare command */
682 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE,
686 - /* send command to mc*/
687 - return mc_send_command(mc_io, &cmd);
689 -EXPORT_SYMBOL(dpcon_close);
692 - * dpcon_enable() - Enable the DPCON
693 - * @mc_io: Pointer to MC portal's I/O object
694 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
695 - * @token: Token of DPCON object
697 - * Return: '0' on Success; Error code otherwise
699 -int dpcon_enable(struct fsl_mc_io *mc_io,
703 - struct mc_command cmd = { 0 };
705 - /* prepare command */
706 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE,
710 - /* send command to mc*/
711 - return mc_send_command(mc_io, &cmd);
713 -EXPORT_SYMBOL(dpcon_enable);
716 - * dpcon_disable() - Disable the DPCON
717 - * @mc_io: Pointer to MC portal's I/O object
718 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
719 - * @token: Token of DPCON object
721 - * Return: '0' on Success; Error code otherwise
723 -int dpcon_disable(struct fsl_mc_io *mc_io,
727 - struct mc_command cmd = { 0 };
729 - /* prepare command */
730 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE,
734 - /* send command to mc*/
735 - return mc_send_command(mc_io, &cmd);
737 -EXPORT_SYMBOL(dpcon_disable);
740 - * dpcon_is_enabled() - Check if the DPCON is enabled.
741 - * @mc_io: Pointer to MC portal's I/O object
742 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
743 - * @token: Token of DPCON object
744 - * @en: Returns '1' if object is enabled; '0' otherwise
746 - * Return: '0' on Success; Error code otherwise.
748 -int dpcon_is_enabled(struct fsl_mc_io *mc_io,
753 - struct mc_command cmd = { 0 };
754 - struct dpcon_rsp_is_enabled *dpcon_rsp;
757 - /* prepare command */
758 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_IS_ENABLED,
762 - /* send command to mc*/
763 - err = mc_send_command(mc_io, &cmd);
767 - /* retrieve response parameters */
768 - dpcon_rsp = (struct dpcon_rsp_is_enabled *)cmd.params;
769 - *en = dpcon_rsp->enabled & DPCON_ENABLE;
773 -EXPORT_SYMBOL(dpcon_is_enabled);
776 - * dpcon_reset() - Reset the DPCON, returns the object to initial state.
777 - * @mc_io: Pointer to MC portal's I/O object
778 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
779 - * @token: Token of DPCON object
781 - * Return: '0' on Success; Error code otherwise.
783 -int dpcon_reset(struct fsl_mc_io *mc_io,
787 - struct mc_command cmd = { 0 };
789 - /* prepare command */
790 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET,
793 - /* send command to mc*/
794 - return mc_send_command(mc_io, &cmd);
796 -EXPORT_SYMBOL(dpcon_reset);
799 - * dpcon_get_attributes() - Retrieve DPCON attributes.
800 - * @mc_io: Pointer to MC portal's I/O object
801 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
802 - * @token: Token of DPCON object
803 - * @attr: Object's attributes
805 - * Return: '0' on Success; Error code otherwise.
807 -int dpcon_get_attributes(struct fsl_mc_io *mc_io,
810 - struct dpcon_attr *attr)
812 - struct mc_command cmd = { 0 };
813 - struct dpcon_rsp_get_attr *dpcon_rsp;
816 - /* prepare command */
817 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR,
821 - /* send command to mc*/
822 - err = mc_send_command(mc_io, &cmd);
826 - /* retrieve response parameters */
827 - dpcon_rsp = (struct dpcon_rsp_get_attr *)cmd.params;
828 - attr->id = le32_to_cpu(dpcon_rsp->id);
829 - attr->qbman_ch_id = le16_to_cpu(dpcon_rsp->qbman_ch_id);
830 - attr->num_priorities = dpcon_rsp->num_priorities;
834 -EXPORT_SYMBOL(dpcon_get_attributes);
837 - * dpcon_set_notification() - Set DPCON notification destination
838 - * @mc_io: Pointer to MC portal's I/O object
839 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
840 - * @token: Token of DPCON object
841 - * @cfg: Notification parameters
843 - * Return: '0' on Success; Error code otherwise
845 -int dpcon_set_notification(struct fsl_mc_io *mc_io,
848 - struct dpcon_notification_cfg *cfg)
850 - struct mc_command cmd = { 0 };
851 - struct dpcon_cmd_set_notification *dpcon_cmd;
853 - /* prepare command */
854 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION,
857 - dpcon_cmd = (struct dpcon_cmd_set_notification *)cmd.params;
858 - dpcon_cmd->dpio_id = cpu_to_le32(cfg->dpio_id);
859 - dpcon_cmd->priority = cfg->priority;
860 - dpcon_cmd->user_ctx = cpu_to_le64(cfg->user_ctx);
862 - /* send command to mc*/
863 - return mc_send_command(mc_io, &cmd);
865 -EXPORT_SYMBOL(dpcon_set_notification);
868 - * dpcon_get_api_version - Get Data Path Concentrator API version
869 - * @mc_io: Pointer to MC portal's DPCON object
870 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
871 - * @major_ver: Major version of DPCON API
872 - * @minor_ver: Minor version of DPCON API
874 - * Return: '0' on Success; Error code otherwise
876 -int dpcon_get_api_version(struct fsl_mc_io *mc_io,
881 - struct mc_command cmd = { 0 };
884 - /* prepare command */
885 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_API_VERSION,
888 - /* send command to mc */
889 - err = mc_send_command(mc_io, &cmd);
893 - /* retrieve response parameters */
894 - mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
898 -EXPORT_SYMBOL(dpcon_get_api_version);
900 +++ b/drivers/bus/fsl-mc/dpcon.c
902 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
904 + * Copyright 2013-2016 Freescale Semiconductor Inc.
907 +#include <linux/kernel.h>
908 +#include <linux/fsl/mc.h>
909 +#include <linux/fsl/mc.h>
911 +#include "fsl-mc-private.h"
914 + * dpcon_open() - Open a control session for the specified object
915 + * @mc_io: Pointer to MC portal's I/O object
916 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
917 + * @dpcon_id: DPCON unique ID
918 + * @token: Returned token; use in subsequent API calls
920 + * This function can be used to open a control session for an
921 + * already created object; an object may have been declared in
922 + * the DPL or by calling the dpcon_create() function.
923 + * This function returns a unique authentication token,
924 + * associated with the specific object ID and the specific MC
925 + * portal; this token must be used in all subsequent commands for
926 + * this specific object.
928 + * Return: '0' on Success; Error code otherwise.
930 +int dpcon_open(struct fsl_mc_io *mc_io,
935 + struct fsl_mc_command cmd = { 0 };
936 + struct dpcon_cmd_open *dpcon_cmd;
939 + /* prepare command */
940 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN,
943 + dpcon_cmd = (struct dpcon_cmd_open *)cmd.params;
944 + dpcon_cmd->dpcon_id = cpu_to_le32(dpcon_id);
946 + /* send command to mc*/
947 + err = mc_send_command(mc_io, &cmd);
951 + /* retrieve response parameters */
952 + *token = mc_cmd_hdr_read_token(&cmd);
956 +EXPORT_SYMBOL_GPL(dpcon_open);
959 + * dpcon_close() - Close the control session of the object
960 + * @mc_io: Pointer to MC portal's I/O object
961 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
962 + * @token: Token of DPCON object
964 + * After this function is called, no further operations are
965 + * allowed on the object without opening a new control session.
967 + * Return: '0' on Success; Error code otherwise.
969 +int dpcon_close(struct fsl_mc_io *mc_io,
973 + struct fsl_mc_command cmd = { 0 };
975 + /* prepare command */
976 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE,
980 + /* send command to mc*/
981 + return mc_send_command(mc_io, &cmd);
983 +EXPORT_SYMBOL_GPL(dpcon_close);
986 + * dpcon_enable() - Enable the DPCON
987 + * @mc_io: Pointer to MC portal's I/O object
988 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
989 + * @token: Token of DPCON object
991 + * Return: '0' on Success; Error code otherwise
993 +int dpcon_enable(struct fsl_mc_io *mc_io,
997 + struct fsl_mc_command cmd = { 0 };
999 + /* prepare command */
1000 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE,
1004 + /* send command to mc*/
1005 + return mc_send_command(mc_io, &cmd);
1007 +EXPORT_SYMBOL_GPL(dpcon_enable);
1010 + * dpcon_disable() - Disable the DPCON
1011 + * @mc_io: Pointer to MC portal's I/O object
1012 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1013 + * @token: Token of DPCON object
1015 + * Return: '0' on Success; Error code otherwise
1017 +int dpcon_disable(struct fsl_mc_io *mc_io,
1021 + struct fsl_mc_command cmd = { 0 };
1023 + /* prepare command */
1024 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE,
1028 + /* send command to mc*/
1029 + return mc_send_command(mc_io, &cmd);
1031 +EXPORT_SYMBOL_GPL(dpcon_disable);
1034 + * dpcon_reset() - Reset the DPCON, returns the object to initial state.
1035 + * @mc_io: Pointer to MC portal's I/O object
1036 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1037 + * @token: Token of DPCON object
1039 + * Return: '0' on Success; Error code otherwise.
1041 +int dpcon_reset(struct fsl_mc_io *mc_io,
1045 + struct fsl_mc_command cmd = { 0 };
1047 + /* prepare command */
1048 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET,
1049 + cmd_flags, token);
1051 + /* send command to mc*/
1052 + return mc_send_command(mc_io, &cmd);
1054 +EXPORT_SYMBOL_GPL(dpcon_reset);
1057 + * dpcon_get_attributes() - Retrieve DPCON attributes.
1058 + * @mc_io: Pointer to MC portal's I/O object
1059 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1060 + * @token: Token of DPCON object
1061 + * @attr: Object's attributes
1063 + * Return: '0' on Success; Error code otherwise.
1065 +int dpcon_get_attributes(struct fsl_mc_io *mc_io,
1068 + struct dpcon_attr *attr)
1070 + struct fsl_mc_command cmd = { 0 };
1071 + struct dpcon_rsp_get_attr *dpcon_rsp;
1074 + /* prepare command */
1075 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR,
1079 + /* send command to mc*/
1080 + err = mc_send_command(mc_io, &cmd);
1084 + /* retrieve response parameters */
1085 + dpcon_rsp = (struct dpcon_rsp_get_attr *)cmd.params;
1086 + attr->id = le32_to_cpu(dpcon_rsp->id);
1087 + attr->qbman_ch_id = le16_to_cpu(dpcon_rsp->qbman_ch_id);
1088 + attr->num_priorities = dpcon_rsp->num_priorities;
1092 +EXPORT_SYMBOL_GPL(dpcon_get_attributes);
1095 + * dpcon_set_notification() - Set DPCON notification destination
1096 + * @mc_io: Pointer to MC portal's I/O object
1097 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1098 + * @token: Token of DPCON object
1099 + * @cfg: Notification parameters
1101 + * Return: '0' on Success; Error code otherwise
1103 +int dpcon_set_notification(struct fsl_mc_io *mc_io,
1106 + struct dpcon_notification_cfg *cfg)
1108 + struct fsl_mc_command cmd = { 0 };
1109 + struct dpcon_cmd_set_notification *dpcon_cmd;
1111 + /* prepare command */
1112 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION,
1115 + dpcon_cmd = (struct dpcon_cmd_set_notification *)cmd.params;
1116 + dpcon_cmd->dpio_id = cpu_to_le32(cfg->dpio_id);
1117 + dpcon_cmd->priority = cfg->priority;
1118 + dpcon_cmd->user_ctx = cpu_to_le64(cfg->user_ctx);
1120 + /* send command to mc*/
1121 + return mc_send_command(mc_io, &cmd);
1123 +EXPORT_SYMBOL_GPL(dpcon_set_notification);
1125 +++ b/drivers/bus/fsl-mc/dpmcp.c
1127 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
1129 + * Copyright 2013-2016 Freescale Semiconductor Inc.
1132 +#include <linux/kernel.h>
1133 +#include <linux/fsl/mc.h>
1135 +#include "fsl-mc-private.h"
1138 + * dpmcp_open() - Open a control session for the specified object.
1139 + * @mc_io: Pointer to MC portal's I/O object
1140 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1141 + * @dpmcp_id: DPMCP unique ID
1142 + * @token: Returned token; use in subsequent API calls
1144 + * This function can be used to open a control session for an
1145 + * already created object; an object may have been declared in
1146 + * the DPL or by calling the dpmcp_create function.
1147 + * This function returns a unique authentication token,
1148 + * associated with the specific object ID and the specific MC
1149 + * portal; this token must be used in all subsequent commands for
1150 + * this specific object
1152 + * Return: '0' on Success; Error code otherwise.
1154 +int dpmcp_open(struct fsl_mc_io *mc_io,
1159 + struct fsl_mc_command cmd = { 0 };
1160 + struct dpmcp_cmd_open *cmd_params;
1163 + /* prepare command */
1164 + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN,
1166 + cmd_params = (struct dpmcp_cmd_open *)cmd.params;
1167 + cmd_params->dpmcp_id = cpu_to_le32(dpmcp_id);
1169 + /* send command to mc*/
1170 + err = mc_send_command(mc_io, &cmd);
1174 + /* retrieve response parameters */
1175 + *token = mc_cmd_hdr_read_token(&cmd);
1181 + * dpmcp_close() - Close the control session of the object
1182 + * @mc_io: Pointer to MC portal's I/O object
1183 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1184 + * @token: Token of DPMCP object
1186 + * After this function is called, no further operations are
1187 + * allowed on the object without opening a new control session.
1189 + * Return: '0' on Success; Error code otherwise.
1191 +int dpmcp_close(struct fsl_mc_io *mc_io,
1195 + struct fsl_mc_command cmd = { 0 };
1197 + /* prepare command */
1198 + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE,
1199 + cmd_flags, token);
1201 + /* send command to mc*/
1202 + return mc_send_command(mc_io, &cmd);
1206 + * dpmcp_reset() - Reset the DPMCP, returns the object to initial state.
1207 + * @mc_io: Pointer to MC portal's I/O object
1208 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
1209 + * @token: Token of DPMCP object
1211 + * Return: '0' on Success; Error code otherwise.
1213 +int dpmcp_reset(struct fsl_mc_io *mc_io,
1217 + struct fsl_mc_command cmd = { 0 };
1219 + /* prepare command */
1220 + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET,
1221 + cmd_flags, token);
1223 + /* send command to mc*/
1224 + return mc_send_command(mc_io, &cmd);
1226 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c
1229 -// SPDX-License-Identifier: GPL-2.0
1231 - * Freescale data path resource container (DPRC) driver
1233 - * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
1234 - * Author: German Rivera <German.Rivera@freescale.com>
1238 -#include <linux/module.h>
1239 -#include <linux/slab.h>
1240 -#include <linux/interrupt.h>
1241 -#include <linux/msi.h>
1242 -#include "../include/mc.h"
1244 -#include "dprc-cmd.h"
1245 -#include "fsl-mc-private.h"
1247 -#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc"
1249 -struct fsl_mc_child_objs {
1251 - struct fsl_mc_obj_desc *child_array;
1254 -static bool fsl_mc_device_match(struct fsl_mc_device *mc_dev,
1255 - struct fsl_mc_obj_desc *obj_desc)
1257 - return mc_dev->obj_desc.id == obj_desc->id &&
1258 - strcmp(mc_dev->obj_desc.type, obj_desc->type) == 0;
1262 -static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
1265 - struct fsl_mc_child_objs *objs;
1266 - struct fsl_mc_device *mc_dev;
1270 - mc_dev = to_fsl_mc_device(dev);
1273 - for (i = 0; i < objs->child_count; i++) {
1274 - struct fsl_mc_obj_desc *obj_desc = &objs->child_array[i];
1276 - if (strlen(obj_desc->type) != 0 &&
1277 - fsl_mc_device_match(mc_dev, obj_desc))
1281 - if (i == objs->child_count)
1282 - fsl_mc_device_remove(mc_dev);
1287 -static int __fsl_mc_device_remove(struct device *dev, void *data)
1291 - fsl_mc_device_remove(to_fsl_mc_device(dev));
1296 - * dprc_remove_devices - Removes devices for objects removed from a DPRC
1298 - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
1299 - * @obj_desc_array: array of object descriptors for child objects currently
1300 - * present in the DPRC in the MC.
1301 - * @num_child_objects_in_mc: number of entries in obj_desc_array
1303 - * Synchronizes the state of the Linux bus driver with the actual state of
1304 - * the MC by removing devices that represent MC objects that have
1305 - * been dynamically removed in the physical DPRC.
1307 -static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev,
1308 - struct fsl_mc_obj_desc *obj_desc_array,
1309 - int num_child_objects_in_mc)
1311 - if (num_child_objects_in_mc != 0) {
1313 - * Remove child objects that are in the DPRC in Linux,
1314 - * but not in the MC:
1316 - struct fsl_mc_child_objs objs;
1318 - objs.child_count = num_child_objects_in_mc;
1319 - objs.child_array = obj_desc_array;
1320 - device_for_each_child(&mc_bus_dev->dev, &objs,
1321 - __fsl_mc_device_remove_if_not_in_mc);
1324 - * There are no child objects for this DPRC in the MC.
1325 - * So, remove all the child devices from Linux:
1327 - device_for_each_child(&mc_bus_dev->dev, NULL,
1328 - __fsl_mc_device_remove);
1332 -static int __fsl_mc_device_match(struct device *dev, void *data)
1334 - struct fsl_mc_obj_desc *obj_desc = data;
1335 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
1337 - return fsl_mc_device_match(mc_dev, obj_desc);
1340 -static struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc
1342 - struct fsl_mc_device
1345 - struct device *dev;
1347 - dev = device_find_child(&mc_bus_dev->dev, obj_desc,
1348 - __fsl_mc_device_match);
1350 - return dev ? to_fsl_mc_device(dev) : NULL;
1354 - * check_plugged_state_change - Check change in an MC object's plugged state
1356 - * @mc_dev: pointer to the fsl-mc device for a given MC object
1357 - * @obj_desc: pointer to the MC object's descriptor in the MC
1359 - * If the plugged state has changed from unplugged to plugged, the fsl-mc
1360 - * device is bound to the corresponding device driver.
1361 - * If the plugged state has changed from plugged to unplugged, the fsl-mc
1362 - * device is unbound from the corresponding device driver.
1364 -static void check_plugged_state_change(struct fsl_mc_device *mc_dev,
1365 - struct fsl_mc_obj_desc *obj_desc)
1368 - u32 plugged_flag_at_mc =
1369 - obj_desc->state & FSL_MC_OBJ_STATE_PLUGGED;
1371 - if (plugged_flag_at_mc !=
1372 - (mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED)) {
1373 - if (plugged_flag_at_mc) {
1374 - mc_dev->obj_desc.state |= FSL_MC_OBJ_STATE_PLUGGED;
1375 - error = device_attach(&mc_dev->dev);
1377 - dev_err(&mc_dev->dev,
1378 - "device_attach() failed: %d\n",
1382 - mc_dev->obj_desc.state &= ~FSL_MC_OBJ_STATE_PLUGGED;
1383 - device_release_driver(&mc_dev->dev);
1389 - * dprc_add_new_devices - Adds devices to the logical bus for a DPRC
1391 - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
1392 - * @obj_desc_array: array of device descriptors for child devices currently
1393 - * present in the physical DPRC.
1394 - * @num_child_objects_in_mc: number of entries in obj_desc_array
1396 - * Synchronizes the state of the Linux bus driver with the actual
1397 - * state of the MC by adding objects that have been newly discovered
1398 - * in the physical DPRC.
1400 -static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
1401 - struct fsl_mc_obj_desc *obj_desc_array,
1402 - int num_child_objects_in_mc)
1407 - for (i = 0; i < num_child_objects_in_mc; i++) {
1408 - struct fsl_mc_device *child_dev;
1409 - struct fsl_mc_obj_desc *obj_desc = &obj_desc_array[i];
1411 - if (strlen(obj_desc->type) == 0)
1415 - * Check if device is already known to Linux:
1417 - child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev);
1419 - check_plugged_state_change(child_dev, obj_desc);
1420 - put_device(&child_dev->dev);
1424 - error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev,
1432 - * dprc_scan_objects - Discover objects in a DPRC
1434 - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
1435 - * @total_irq_count: total number of IRQs needed by objects in the DPRC.
1437 - * Detects objects added and removed from a DPRC and synchronizes the
1438 - * state of the Linux bus driver, MC by adding and removing
1439 - * devices accordingly.
1440 - * Two types of devices can be found in a DPRC: allocatable objects (e.g.,
1441 - * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni).
1442 - * All allocatable devices needed to be probed before all non-allocatable
1443 - * devices, to ensure that device drivers for non-allocatable
1444 - * devices can allocate any type of allocatable devices.
1445 - * That is, we need to ensure that the corresponding resource pools are
1446 - * populated before they can get allocation requests from probe callbacks
1447 - * of the device drivers for the non-allocatable devices.
1449 -static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
1450 - unsigned int *total_irq_count)
1452 - int num_child_objects;
1453 - int dprc_get_obj_failures;
1455 - unsigned int irq_count = mc_bus_dev->obj_desc.irq_count;
1456 - struct fsl_mc_obj_desc *child_obj_desc_array = NULL;
1458 - error = dprc_get_obj_count(mc_bus_dev->mc_io,
1460 - mc_bus_dev->mc_handle,
1461 - &num_child_objects);
1463 - dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n",
1468 - if (num_child_objects != 0) {
1471 - child_obj_desc_array =
1472 - devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects,
1473 - sizeof(*child_obj_desc_array),
1475 - if (!child_obj_desc_array)
1479 - * Discover objects currently present in the physical DPRC:
1481 - dprc_get_obj_failures = 0;
1482 - for (i = 0; i < num_child_objects; i++) {
1483 - struct fsl_mc_obj_desc *obj_desc =
1484 - &child_obj_desc_array[i];
1486 - error = dprc_get_obj(mc_bus_dev->mc_io,
1488 - mc_bus_dev->mc_handle,
1491 - dev_err(&mc_bus_dev->dev,
1492 - "dprc_get_obj(i=%d) failed: %d\n",
1495 - * Mark the obj entry as "invalid", by using the
1496 - * empty string as obj type:
1498 - obj_desc->type[0] = '\0';
1499 - obj_desc->id = error;
1500 - dprc_get_obj_failures++;
1505 - * add a quirk for all versions of dpsec < 4.0...none
1506 - * are coherent regardless of what the MC reports.
1508 - if ((strcmp(obj_desc->type, "dpseci") == 0) &&
1509 - (obj_desc->ver_major < 4))
1510 - obj_desc->flags |=
1511 - FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY;
1513 - irq_count += obj_desc->irq_count;
1514 - dev_dbg(&mc_bus_dev->dev,
1515 - "Discovered object: type %s, id %d\n",
1516 - obj_desc->type, obj_desc->id);
1519 - if (dprc_get_obj_failures != 0) {
1520 - dev_err(&mc_bus_dev->dev,
1521 - "%d out of %d devices could not be retrieved\n",
1522 - dprc_get_obj_failures, num_child_objects);
1526 - *total_irq_count = irq_count;
1527 - dprc_remove_devices(mc_bus_dev, child_obj_desc_array,
1528 - num_child_objects);
1530 - dprc_add_new_devices(mc_bus_dev, child_obj_desc_array,
1531 - num_child_objects);
1533 - if (child_obj_desc_array)
1534 - devm_kfree(&mc_bus_dev->dev, child_obj_desc_array);
1540 - * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state
1542 - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
1544 - * Scans the physical DPRC and synchronizes the state of the Linux
1545 - * bus driver with the actual state of the MC by adding and removing
1546 - * devices as appropriate.
1548 -static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
1551 - unsigned int irq_count;
1552 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
1554 - fsl_mc_init_all_resource_pools(mc_bus_dev);
1557 - * Discover objects in the DPRC:
1559 - mutex_lock(&mc_bus->scan_mutex);
1560 - error = dprc_scan_objects(mc_bus_dev, &irq_count);
1561 - mutex_unlock(&mc_bus->scan_mutex);
1565 - if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) {
1566 - if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
1567 - dev_warn(&mc_bus_dev->dev,
1568 - "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
1569 - irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
1572 - error = fsl_mc_populate_irq_pool(
1574 - FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
1581 - fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
1586 - * dprc_irq0_handler - Regular ISR for DPRC interrupt 0
1588 - * @irq: IRQ number of the interrupt being handled
1589 - * @arg: Pointer to device structure
1591 -static irqreturn_t dprc_irq0_handler(int irq_num, void *arg)
1593 - return IRQ_WAKE_THREAD;
1597 - * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0
1599 - * @irq: IRQ number of the interrupt being handled
1600 - * @arg: Pointer to device structure
1602 -static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
1606 - struct device *dev = arg;
1607 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
1608 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
1609 - struct fsl_mc_io *mc_io = mc_dev->mc_io;
1610 - struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc;
1612 - dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n",
1613 - irq_num, smp_processor_id());
1615 - if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC)))
1616 - return IRQ_HANDLED;
1618 - mutex_lock(&mc_bus->scan_mutex);
1619 - if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num))
1623 - error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
1627 - "dprc_get_irq_status() failed: %d\n", error);
1631 - error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
1635 - "dprc_clear_irq_status() failed: %d\n", error);
1639 - if (status & (DPRC_IRQ_EVENT_OBJ_ADDED |
1640 - DPRC_IRQ_EVENT_OBJ_REMOVED |
1641 - DPRC_IRQ_EVENT_CONTAINER_DESTROYED |
1642 - DPRC_IRQ_EVENT_OBJ_DESTROYED |
1643 - DPRC_IRQ_EVENT_OBJ_CREATED)) {
1644 - unsigned int irq_count;
1646 - error = dprc_scan_objects(mc_dev, &irq_count);
1649 - * If the error is -ENXIO, we ignore it, as it indicates
1650 - * that the object scan was aborted, as we detected that
1651 - * an object was removed from the DPRC in the MC, while
1652 - * we were scanning the DPRC.
1654 - if (error != -ENXIO) {
1655 - dev_err(dev, "dprc_scan_objects() failed: %d\n",
1662 - if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
1664 - "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
1665 - irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
1670 - mutex_unlock(&mc_bus->scan_mutex);
1671 - return IRQ_HANDLED;
1675 - * Disable and clear interrupt for a given DPRC object
1677 -static int disable_dprc_irq(struct fsl_mc_device *mc_dev)
1680 - struct fsl_mc_io *mc_io = mc_dev->mc_io;
1682 - WARN_ON(mc_dev->obj_desc.irq_count != 1);
1685 - * Disable generation of interrupt, while we configure it:
1687 - error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0);
1689 - dev_err(&mc_dev->dev,
1690 - "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
1696 - * Disable all interrupt causes for the interrupt:
1698 - error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0);
1700 - dev_err(&mc_dev->dev,
1701 - "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
1707 - * Clear any leftover interrupts:
1709 - error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U);
1711 - dev_err(&mc_dev->dev,
1712 - "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n",
1720 -static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev)
1723 - struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
1725 - WARN_ON(mc_dev->obj_desc.irq_count != 1);
1728 - * NOTE: devm_request_threaded_irq() invokes the device-specific
1729 - * function that programs the MSI physically in the device
1731 - error = devm_request_threaded_irq(&mc_dev->dev,
1732 - irq->msi_desc->irq,
1733 - dprc_irq0_handler,
1734 - dprc_irq0_handler_thread,
1735 - IRQF_NO_SUSPEND | IRQF_ONESHOT,
1736 - dev_name(&mc_dev->dev),
1739 - dev_err(&mc_dev->dev,
1740 - "devm_request_threaded_irq() failed: %d\n",
1748 -static int enable_dprc_irq(struct fsl_mc_device *mc_dev)
1753 - * Enable all interrupt causes for the interrupt:
1755 - error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0,
1758 - dev_err(&mc_dev->dev,
1759 - "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
1766 - * Enable generation of the interrupt:
1768 - error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1);
1770 - dev_err(&mc_dev->dev,
1771 - "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
1781 - * Setup interrupt for a given DPRC device
1783 -static int dprc_setup_irq(struct fsl_mc_device *mc_dev)
1787 - error = fsl_mc_allocate_irqs(mc_dev);
1791 - error = disable_dprc_irq(mc_dev);
1793 - goto error_free_irqs;
1795 - error = register_dprc_irq_handler(mc_dev);
1797 - goto error_free_irqs;
1799 - error = enable_dprc_irq(mc_dev);
1801 - goto error_free_irqs;
1806 - fsl_mc_free_irqs(mc_dev);
1811 - * dprc_probe - callback invoked when a DPRC is being bound to this driver
1813 - * @mc_dev: Pointer to fsl-mc device representing a DPRC
1815 - * It opens the physical DPRC in the MC.
1816 - * It scans the DPRC to discover the MC objects contained in it.
1817 - * It creates the interrupt pool for the MC bus associated with the DPRC.
1818 - * It configures the interrupts for the DPRC device itself.
1820 -static int dprc_probe(struct fsl_mc_device *mc_dev)
1823 - size_t region_size;
1824 - struct device *parent_dev = mc_dev->dev.parent;
1825 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
1826 - bool mc_io_created = false;
1827 - bool msi_domain_set = false;
1828 - u16 major_ver, minor_ver;
1830 - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
1833 - if (WARN_ON(dev_get_msi_domain(&mc_dev->dev)))
1836 - if (!mc_dev->mc_io) {
1838 - * This is a child DPRC:
1840 - if (WARN_ON(!dev_is_fsl_mc(parent_dev)))
1843 - if (WARN_ON(mc_dev->obj_desc.region_count == 0))
1846 - region_size = resource_size(mc_dev->regions);
1848 - error = fsl_create_mc_io(&mc_dev->dev,
1849 - mc_dev->regions[0].start,
1852 - FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
1857 - mc_io_created = true;
1860 - * Inherit parent MSI domain:
1862 - dev_set_msi_domain(&mc_dev->dev,
1863 - dev_get_msi_domain(parent_dev));
1864 - msi_domain_set = true;
1867 - * This is a root DPRC
1869 - struct irq_domain *mc_msi_domain;
1871 - if (WARN_ON(dev_is_fsl_mc(parent_dev)))
1874 - error = fsl_mc_find_msi_domain(parent_dev,
1877 - dev_warn(&mc_dev->dev,
1878 - "WARNING: MC bus without interrupt support\n");
1880 - dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
1881 - msi_domain_set = true;
1885 - error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
1886 - &mc_dev->mc_handle);
1888 - dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error);
1889 - goto error_cleanup_msi_domain;
1892 - error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle,
1893 - &mc_bus->dprc_attr);
1895 - dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n",
1897 - goto error_cleanup_open;
1900 - error = dprc_get_api_version(mc_dev->mc_io, 0,
1904 - dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n",
1906 - goto error_cleanup_open;
1909 - if (major_ver < DPRC_MIN_VER_MAJOR ||
1910 - (major_ver == DPRC_MIN_VER_MAJOR &&
1911 - minor_ver < DPRC_MIN_VER_MINOR)) {
1912 - dev_err(&mc_dev->dev,
1913 - "ERROR: DPRC version %d.%d not supported\n",
1914 - major_ver, minor_ver);
1915 - error = -ENOTSUPP;
1916 - goto error_cleanup_open;
1919 - mutex_init(&mc_bus->scan_mutex);
1922 - * Discover MC objects in DPRC object:
1924 - error = dprc_scan_container(mc_dev);
1926 - goto error_cleanup_open;
1929 - * Configure interrupt for the DPRC object associated with this MC bus:
1931 - error = dprc_setup_irq(mc_dev);
1933 - goto error_cleanup_open;
1935 - dev_info(&mc_dev->dev, "DPRC device bound to driver");
1938 -error_cleanup_open:
1939 - (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
1941 -error_cleanup_msi_domain:
1942 - if (msi_domain_set)
1943 - dev_set_msi_domain(&mc_dev->dev, NULL);
1945 - if (mc_io_created) {
1946 - fsl_destroy_mc_io(mc_dev->mc_io);
1947 - mc_dev->mc_io = NULL;
1954 - * Tear down interrupt for a given DPRC object
1956 -static void dprc_teardown_irq(struct fsl_mc_device *mc_dev)
1958 - struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
1960 - (void)disable_dprc_irq(mc_dev);
1962 - devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev);
1964 - fsl_mc_free_irqs(mc_dev);
1968 - * dprc_remove - callback invoked when a DPRC is being unbound from this driver
1970 - * @mc_dev: Pointer to fsl-mc device representing the DPRC
1972 - * It removes the DPRC's child objects from Linux (not from the MC) and
1973 - * closes the DPRC device in the MC.
1974 - * It tears down the interrupts that were configured for the DPRC device.
1975 - * It destroys the interrupt pool associated with this MC bus.
1977 -static int dprc_remove(struct fsl_mc_device *mc_dev)
1980 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
1982 - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
1984 - if (WARN_ON(!mc_dev->mc_io))
1987 - if (WARN_ON(!mc_bus->irq_resources))
1990 - if (dev_get_msi_domain(&mc_dev->dev))
1991 - dprc_teardown_irq(mc_dev);
1993 - device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
1995 - if (dev_get_msi_domain(&mc_dev->dev)) {
1996 - fsl_mc_cleanup_irq_pool(mc_bus);
1997 - dev_set_msi_domain(&mc_dev->dev, NULL);
2000 - fsl_mc_cleanup_all_resource_pools(mc_dev);
2002 - error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
2004 - dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error);
2006 - if (!fsl_mc_is_root_dprc(&mc_dev->dev)) {
2007 - fsl_destroy_mc_io(mc_dev->mc_io);
2008 - mc_dev->mc_io = NULL;
2011 - dev_info(&mc_dev->dev, "DPRC device unbound from driver");
2015 -static const struct fsl_mc_device_id match_id_table[] = {
2017 - .vendor = FSL_MC_VENDOR_FREESCALE,
2018 - .obj_type = "dprc"},
2022 -static struct fsl_mc_driver dprc_driver = {
2024 - .name = FSL_MC_DPRC_DRIVER_NAME,
2025 - .owner = THIS_MODULE,
2028 - .match_id_table = match_id_table,
2029 - .probe = dprc_probe,
2030 - .remove = dprc_remove,
2033 -int __init dprc_driver_init(void)
2035 - return fsl_mc_driver_register(&dprc_driver);
2038 -void dprc_driver_exit(void)
2040 - fsl_mc_driver_unregister(&dprc_driver);
2043 +++ b/drivers/bus/fsl-mc/dprc-driver.c
2045 +// SPDX-License-Identifier: GPL-2.0
2047 + * Freescale data path resource container (DPRC) driver
2049 + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
2050 + * Author: German Rivera <German.Rivera@freescale.com>
2054 +#include <linux/module.h>
2055 +#include <linux/slab.h>
2056 +#include <linux/interrupt.h>
2057 +#include <linux/msi.h>
2058 +#include <linux/fsl/mc.h>
2060 +#include "fsl-mc-private.h"
2062 +#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc"
2064 +struct fsl_mc_child_objs {
2066 + struct fsl_mc_obj_desc *child_array;
2069 +static bool fsl_mc_device_match(struct fsl_mc_device *mc_dev,
2070 + struct fsl_mc_obj_desc *obj_desc)
2072 + return mc_dev->obj_desc.id == obj_desc->id &&
2073 + strcmp(mc_dev->obj_desc.type, obj_desc->type) == 0;
2077 +static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
2080 + struct fsl_mc_child_objs *objs;
2081 + struct fsl_mc_device *mc_dev;
2083 + mc_dev = to_fsl_mc_device(dev);
2086 + for (i = 0; i < objs->child_count; i++) {
2087 + struct fsl_mc_obj_desc *obj_desc = &objs->child_array[i];
2089 + if (strlen(obj_desc->type) != 0 &&
2090 + fsl_mc_device_match(mc_dev, obj_desc))
2094 + if (i == objs->child_count)
2095 + fsl_mc_device_remove(mc_dev);
2100 +static int __fsl_mc_device_remove(struct device *dev, void *data)
2102 + fsl_mc_device_remove(to_fsl_mc_device(dev));
2107 + * dprc_remove_devices - Removes devices for objects removed from a DPRC
2109 + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
2110 + * @obj_desc_array: array of object descriptors for child objects currently
2111 + * present in the DPRC in the MC.
2112 + * @num_child_objects_in_mc: number of entries in obj_desc_array
2114 + * Synchronizes the state of the Linux bus driver with the actual state of
2115 + * the MC by removing devices that represent MC objects that have
2116 + * been dynamically removed in the physical DPRC.
2118 +static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev,
2119 + struct fsl_mc_obj_desc *obj_desc_array,
2120 + int num_child_objects_in_mc)
2122 + if (num_child_objects_in_mc != 0) {
2124 + * Remove child objects that are in the DPRC in Linux,
2125 + * but not in the MC:
2127 + struct fsl_mc_child_objs objs;
2129 + objs.child_count = num_child_objects_in_mc;
2130 + objs.child_array = obj_desc_array;
2131 + device_for_each_child(&mc_bus_dev->dev, &objs,
2132 + __fsl_mc_device_remove_if_not_in_mc);
2135 + * There are no child objects for this DPRC in the MC.
2136 + * So, remove all the child devices from Linux:
2138 + device_for_each_child(&mc_bus_dev->dev, NULL,
2139 + __fsl_mc_device_remove);
2143 +static int __fsl_mc_device_match(struct device *dev, void *data)
2145 + struct fsl_mc_obj_desc *obj_desc = data;
2146 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
2148 + return fsl_mc_device_match(mc_dev, obj_desc);
2151 +static struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc
2153 + struct fsl_mc_device
2156 + struct device *dev;
2158 + dev = device_find_child(&mc_bus_dev->dev, obj_desc,
2159 + __fsl_mc_device_match);
2161 + return dev ? to_fsl_mc_device(dev) : NULL;
2165 + * check_plugged_state_change - Check change in an MC object's plugged state
2167 + * @mc_dev: pointer to the fsl-mc device for a given MC object
2168 + * @obj_desc: pointer to the MC object's descriptor in the MC
2170 + * If the plugged state has changed from unplugged to plugged, the fsl-mc
2171 + * device is bound to the corresponding device driver.
2172 + * If the plugged state has changed from plugged to unplugged, the fsl-mc
2173 + * device is unbound from the corresponding device driver.
2175 +static void check_plugged_state_change(struct fsl_mc_device *mc_dev,
2176 + struct fsl_mc_obj_desc *obj_desc)
2179 + u32 plugged_flag_at_mc =
2180 + obj_desc->state & FSL_MC_OBJ_STATE_PLUGGED;
2182 + if (plugged_flag_at_mc !=
2183 + (mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED)) {
2184 + if (plugged_flag_at_mc) {
2185 + mc_dev->obj_desc.state |= FSL_MC_OBJ_STATE_PLUGGED;
2186 + error = device_attach(&mc_dev->dev);
2188 + dev_err(&mc_dev->dev,
2189 + "device_attach() failed: %d\n",
2193 + mc_dev->obj_desc.state &= ~FSL_MC_OBJ_STATE_PLUGGED;
2194 + device_release_driver(&mc_dev->dev);
2200 + * dprc_add_new_devices - Adds devices to the logical bus for a DPRC
2202 + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
2203 + * @driver_override: driver override to apply to new objects found in the
2204 + * DPRC, or NULL, if none.
2205 + * @obj_desc_array: array of device descriptors for child devices currently
2206 + * present in the physical DPRC.
2207 + * @num_child_objects_in_mc: number of entries in obj_desc_array
2209 + * Synchronizes the state of the Linux bus driver with the actual
2210 + * state of the MC by adding objects that have been newly discovered
2211 + * in the physical DPRC.
2213 +static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
2214 + const char *driver_override,
2215 + struct fsl_mc_obj_desc *obj_desc_array,
2216 + int num_child_objects_in_mc)
2221 + for (i = 0; i < num_child_objects_in_mc; i++) {
2222 + struct fsl_mc_device *child_dev;
2223 + struct fsl_mc_obj_desc *obj_desc = &obj_desc_array[i];
2225 + if (strlen(obj_desc->type) == 0)
2229 + * Check if device is already known to Linux:
2231 + child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev);
2233 + check_plugged_state_change(child_dev, obj_desc);
2234 + put_device(&child_dev->dev);
2238 + error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev,
2239 + driver_override, &child_dev);
2246 + * dprc_scan_objects - Discover objects in a DPRC
2248 + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
2249 + * @driver_override: driver override to apply to new objects found in the
2250 + * DPRC, or NULL, if none.
2251 + * @total_irq_count: If argument is provided the function populates the
2252 + * total number of IRQs created by objects in the DPRC.
2254 + * Detects objects added and removed from a DPRC and synchronizes the
2255 + * state of the Linux bus driver, MC by adding and removing
2256 + * devices accordingly.
2257 + * Two types of devices can be found in a DPRC: allocatable objects (e.g.,
2258 + * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni).
2259 + * All allocatable devices needed to be probed before all non-allocatable
2260 + * devices, to ensure that device drivers for non-allocatable
2261 + * devices can allocate any type of allocatable devices.
2262 + * That is, we need to ensure that the corresponding resource pools are
2263 + * populated before they can get allocation requests from probe callbacks
2264 + * of the device drivers for the non-allocatable devices.
2266 +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
2267 + const char *driver_override,
2268 + unsigned int *total_irq_count)
2270 + int num_child_objects;
2271 + int dprc_get_obj_failures;
2273 + unsigned int irq_count = mc_bus_dev->obj_desc.irq_count;
2274 + struct fsl_mc_obj_desc *child_obj_desc_array = NULL;
2275 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
2277 + error = dprc_get_obj_count(mc_bus_dev->mc_io,
2279 + mc_bus_dev->mc_handle,
2280 + &num_child_objects);
2282 + dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n",
2287 + if (num_child_objects != 0) {
2290 + child_obj_desc_array =
2291 + devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects,
2292 + sizeof(*child_obj_desc_array),
2294 + if (!child_obj_desc_array)
2298 + * Discover objects currently present in the physical DPRC:
2300 + dprc_get_obj_failures = 0;
2301 + for (i = 0; i < num_child_objects; i++) {
2302 + struct fsl_mc_obj_desc *obj_desc =
2303 + &child_obj_desc_array[i];
2305 + error = dprc_get_obj(mc_bus_dev->mc_io,
2307 + mc_bus_dev->mc_handle,
2310 + dev_err(&mc_bus_dev->dev,
2311 + "dprc_get_obj(i=%d) failed: %d\n",
2314 + * Mark the obj entry as "invalid", by using the
2315 + * empty string as obj type:
2317 + obj_desc->type[0] = '\0';
2318 + obj_desc->id = error;
2319 + dprc_get_obj_failures++;
2324 + * add a quirk for all versions of dpsec < 4.0...none
2325 + * are coherent regardless of what the MC reports.
2327 + if ((strcmp(obj_desc->type, "dpseci") == 0) &&
2328 + (obj_desc->ver_major < 4))
2329 + obj_desc->flags |=
2330 + FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY;
2332 + irq_count += obj_desc->irq_count;
2333 + dev_dbg(&mc_bus_dev->dev,
2334 + "Discovered object: type %s, id %d\n",
2335 + obj_desc->type, obj_desc->id);
2338 + if (dprc_get_obj_failures != 0) {
2339 + dev_err(&mc_bus_dev->dev,
2340 + "%d out of %d devices could not be retrieved\n",
2341 + dprc_get_obj_failures, num_child_objects);
2346 + * Allocate IRQ's before binding the scanned devices with their
2347 + * respective drivers.
2349 + if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) {
2350 + if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
2351 + dev_warn(&mc_bus_dev->dev,
2352 + "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
2353 + irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
2356 + error = fsl_mc_populate_irq_pool(mc_bus,
2357 + FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
2362 + if (total_irq_count)
2363 + *total_irq_count = irq_count;
2365 + dprc_remove_devices(mc_bus_dev, child_obj_desc_array,
2366 + num_child_objects);
2368 + dprc_add_new_devices(mc_bus_dev, driver_override, child_obj_desc_array,
2369 + num_child_objects);
2371 + if (child_obj_desc_array)
2372 + devm_kfree(&mc_bus_dev->dev, child_obj_desc_array);
2378 + * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state
2380 + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
2382 + * Scans the physical DPRC and synchronizes the state of the Linux
2383 + * bus driver with the actual state of the MC by adding and removing
2384 + * devices as appropriate.
2386 +static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
2389 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
2391 + fsl_mc_init_all_resource_pools(mc_bus_dev);
2394 + * Discover objects in the DPRC:
2396 + mutex_lock(&mc_bus->scan_mutex);
2397 + error = dprc_scan_objects(mc_bus_dev, NULL, NULL);
2398 + mutex_unlock(&mc_bus->scan_mutex);
2400 + fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
2408 + * dprc_irq0_handler - Regular ISR for DPRC interrupt 0
2410 + * @irq: IRQ number of the interrupt being handled
2411 + * @arg: Pointer to device structure
2413 +static irqreturn_t dprc_irq0_handler(int irq_num, void *arg)
2415 + return IRQ_WAKE_THREAD;
2419 + * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0
2421 + * @irq: IRQ number of the interrupt being handled
2422 + * @arg: Pointer to device structure
2424 +static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
2428 + struct device *dev = arg;
2429 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
2430 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
2431 + struct fsl_mc_io *mc_io = mc_dev->mc_io;
2432 + struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc;
2434 + dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n",
2435 + irq_num, smp_processor_id());
2437 + if (!(mc_dev->flags & FSL_MC_IS_DPRC))
2438 + return IRQ_HANDLED;
2440 + mutex_lock(&mc_bus->scan_mutex);
2441 + if (!msi_desc || msi_desc->irq != (u32)irq_num)
2445 + error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
2449 + "dprc_get_irq_status() failed: %d\n", error);
2453 + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
2457 + "dprc_clear_irq_status() failed: %d\n", error);
2461 + if (status & (DPRC_IRQ_EVENT_OBJ_ADDED |
2462 + DPRC_IRQ_EVENT_OBJ_REMOVED |
2463 + DPRC_IRQ_EVENT_CONTAINER_DESTROYED |
2464 + DPRC_IRQ_EVENT_OBJ_DESTROYED |
2465 + DPRC_IRQ_EVENT_OBJ_CREATED)) {
2466 + unsigned int irq_count;
2468 + error = dprc_scan_objects(mc_dev, NULL, &irq_count);
2471 + * If the error is -ENXIO, we ignore it, as it indicates
2472 + * that the object scan was aborted, as we detected that
2473 + * an object was removed from the DPRC in the MC, while
2474 + * we were scanning the DPRC.
2476 + if (error != -ENXIO) {
2477 + dev_err(dev, "dprc_scan_objects() failed: %d\n",
2484 + if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
2486 + "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
2487 + irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
2492 + mutex_unlock(&mc_bus->scan_mutex);
2493 + return IRQ_HANDLED;
2497 + * Disable and clear interrupt for a given DPRC object
2499 +static int disable_dprc_irq(struct fsl_mc_device *mc_dev)
2502 + struct fsl_mc_io *mc_io = mc_dev->mc_io;
2505 + * Disable generation of interrupt, while we configure it:
2507 + error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0);
2509 + dev_err(&mc_dev->dev,
2510 + "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
2516 + * Disable all interrupt causes for the interrupt:
2518 + error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0);
2520 + dev_err(&mc_dev->dev,
2521 + "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
2527 + * Clear any leftover interrupts:
2529 + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U);
2531 + dev_err(&mc_dev->dev,
2532 + "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n",
2540 +static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev)
2543 + struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
2546 + * NOTE: devm_request_threaded_irq() invokes the device-specific
2547 + * function that programs the MSI physically in the device
2549 + error = devm_request_threaded_irq(&mc_dev->dev,
2550 + irq->msi_desc->irq,
2551 + dprc_irq0_handler,
2552 + dprc_irq0_handler_thread,
2553 + IRQF_NO_SUSPEND | IRQF_ONESHOT,
2554 + dev_name(&mc_dev->dev),
2557 + dev_err(&mc_dev->dev,
2558 + "devm_request_threaded_irq() failed: %d\n",
2566 +static int enable_dprc_irq(struct fsl_mc_device *mc_dev)
2571 + * Enable all interrupt causes for the interrupt:
2573 + error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0,
2576 + dev_err(&mc_dev->dev,
2577 + "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
2584 + * Enable generation of the interrupt:
2586 + error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1);
2588 + dev_err(&mc_dev->dev,
2589 + "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
2599 + * Setup interrupt for a given DPRC device
2601 +static int dprc_setup_irq(struct fsl_mc_device *mc_dev)
2605 + error = fsl_mc_allocate_irqs(mc_dev);
2609 + error = disable_dprc_irq(mc_dev);
2611 + goto error_free_irqs;
2613 + error = register_dprc_irq_handler(mc_dev);
2615 + goto error_free_irqs;
2617 + error = enable_dprc_irq(mc_dev);
2619 + goto error_free_irqs;
2624 + fsl_mc_free_irqs(mc_dev);
2629 + * dprc_probe - callback invoked when a DPRC is being bound to this driver
2631 + * @mc_dev: Pointer to fsl-mc device representing a DPRC
2633 + * It opens the physical DPRC in the MC.
2634 + * It scans the DPRC to discover the MC objects contained in it.
2635 + * It creates the interrupt pool for the MC bus associated with the DPRC.
2636 + * It configures the interrupts for the DPRC device itself.
2638 +static int dprc_probe(struct fsl_mc_device *mc_dev)
2641 + size_t region_size;
2642 + struct device *parent_dev = mc_dev->dev.parent;
2643 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
2644 + bool mc_io_created = false;
2645 + bool msi_domain_set = false;
2646 + u16 major_ver, minor_ver;
2648 + if (!is_fsl_mc_bus_dprc(mc_dev))
2651 + if (dev_get_msi_domain(&mc_dev->dev))
2654 + if (!mc_dev->mc_io) {
2656 + * This is a child DPRC:
2658 + if (!dev_is_fsl_mc(parent_dev))
2661 + if (mc_dev->obj_desc.region_count == 0)
2664 + region_size = resource_size(mc_dev->regions);
2666 + error = fsl_create_mc_io(&mc_dev->dev,
2667 + mc_dev->regions[0].start,
2670 + FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
2675 + mc_io_created = true;
2678 + * Inherit parent MSI domain:
2680 + dev_set_msi_domain(&mc_dev->dev,
2681 + dev_get_msi_domain(parent_dev));
2682 + msi_domain_set = true;
2685 + * This is a root DPRC
2687 + struct irq_domain *mc_msi_domain;
2689 + if (dev_is_fsl_mc(parent_dev))
2692 + error = fsl_mc_find_msi_domain(parent_dev,
2695 + dev_warn(&mc_dev->dev,
2696 + "WARNING: MC bus without interrupt support\n");
2698 + dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
2699 + msi_domain_set = true;
2703 + error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
2704 + &mc_dev->mc_handle);
2706 + dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error);
2707 + goto error_cleanup_msi_domain;
2710 + error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle,
2711 + &mc_bus->dprc_attr);
2713 + dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n",
2715 + goto error_cleanup_open;
2718 + error = dprc_get_api_version(mc_dev->mc_io, 0,
2722 + dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n",
2724 + goto error_cleanup_open;
2727 + if (major_ver < DPRC_MIN_VER_MAJOR ||
2728 + (major_ver == DPRC_MIN_VER_MAJOR &&
2729 + minor_ver < DPRC_MIN_VER_MINOR)) {
2730 + dev_err(&mc_dev->dev,
2731 + "ERROR: DPRC version %d.%d not supported\n",
2732 + major_ver, minor_ver);
2733 + error = -ENOTSUPP;
2734 + goto error_cleanup_open;
2737 + mutex_init(&mc_bus->scan_mutex);
2740 + * Discover MC objects in DPRC object:
2742 + error = dprc_scan_container(mc_dev);
2744 + goto error_cleanup_open;
2747 + * Configure interrupt for the DPRC object associated with this MC bus:
2749 + error = dprc_setup_irq(mc_dev);
2751 + goto error_cleanup_open;
2753 + dev_info(&mc_dev->dev, "DPRC device bound to driver");
2756 +error_cleanup_open:
2757 + (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
2759 +error_cleanup_msi_domain:
2760 + if (msi_domain_set)
2761 + dev_set_msi_domain(&mc_dev->dev, NULL);
2763 + if (mc_io_created) {
2764 + fsl_destroy_mc_io(mc_dev->mc_io);
2765 + mc_dev->mc_io = NULL;
2772 + * Tear down interrupt for a given DPRC object
2774 +static void dprc_teardown_irq(struct fsl_mc_device *mc_dev)
2776 + struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
2778 + (void)disable_dprc_irq(mc_dev);
2780 + devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev);
2782 + fsl_mc_free_irqs(mc_dev);
2786 + * dprc_remove - callback invoked when a DPRC is being unbound from this driver
2788 + * @mc_dev: Pointer to fsl-mc device representing the DPRC
2790 + * It removes the DPRC's child objects from Linux (not from the MC) and
2791 + * closes the DPRC device in the MC.
2792 + * It tears down the interrupts that were configured for the DPRC device.
2793 + * It destroys the interrupt pool associated with this MC bus.
2795 +static int dprc_remove(struct fsl_mc_device *mc_dev)
2798 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
2800 + if (!is_fsl_mc_bus_dprc(mc_dev))
2802 + if (!mc_dev->mc_io)
2805 + if (!mc_bus->irq_resources)
2808 + if (dev_get_msi_domain(&mc_dev->dev))
2809 + dprc_teardown_irq(mc_dev);
2811 + device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
2813 + if (dev_get_msi_domain(&mc_dev->dev)) {
2814 + fsl_mc_cleanup_irq_pool(mc_bus);
2815 + dev_set_msi_domain(&mc_dev->dev, NULL);
2818 + fsl_mc_cleanup_all_resource_pools(mc_dev);
2820 + error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
2822 + dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error);
2824 + if (!fsl_mc_is_root_dprc(&mc_dev->dev)) {
2825 + fsl_destroy_mc_io(mc_dev->mc_io);
2826 + mc_dev->mc_io = NULL;
2829 + dev_info(&mc_dev->dev, "DPRC device unbound from driver");
2833 +static const struct fsl_mc_device_id match_id_table[] = {
2835 + .vendor = FSL_MC_VENDOR_FREESCALE,
2836 + .obj_type = "dprc"},
2840 +static struct fsl_mc_driver dprc_driver = {
2842 + .name = FSL_MC_DPRC_DRIVER_NAME,
2843 + .owner = THIS_MODULE,
2846 + .match_id_table = match_id_table,
2847 + .probe = dprc_probe,
2848 + .remove = dprc_remove,
2851 +int __init dprc_driver_init(void)
2853 + return fsl_mc_driver_register(&dprc_driver);
2856 +void dprc_driver_exit(void)
2858 + fsl_mc_driver_unregister(&dprc_driver);
2860 --- a/drivers/staging/fsl-mc/bus/dprc.c
2863 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2865 - * Copyright 2013-2016 Freescale Semiconductor Inc.
2868 -#include <linux/kernel.h>
2869 -#include "../include/mc.h"
2872 -#include "dprc-cmd.h"
2875 - * dprc_open() - Open DPRC object for use
2876 - * @mc_io: Pointer to MC portal's I/O object
2877 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2878 - * @container_id: Container ID to open
2879 - * @token: Returned token of DPRC object
2881 - * Return: '0' on Success; Error code otherwise.
2883 - * @warning Required before any operation on the object.
2885 -int dprc_open(struct fsl_mc_io *mc_io,
2890 - struct mc_command cmd = { 0 };
2891 - struct dprc_cmd_open *cmd_params;
2894 - /* prepare command */
2895 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags,
2897 - cmd_params = (struct dprc_cmd_open *)cmd.params;
2898 - cmd_params->container_id = cpu_to_le32(container_id);
2900 - /* send command to mc*/
2901 - err = mc_send_command(mc_io, &cmd);
2905 - /* retrieve response parameters */
2906 - *token = mc_cmd_hdr_read_token(&cmd);
2910 -EXPORT_SYMBOL(dprc_open);
2913 - * dprc_close() - Close the control session of the object
2914 - * @mc_io: Pointer to MC portal's I/O object
2915 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2916 - * @token: Token of DPRC object
2918 - * After this function is called, no further operations are
2919 - * allowed on the object without opening a new control session.
2921 - * Return: '0' on Success; Error code otherwise.
2923 -int dprc_close(struct fsl_mc_io *mc_io,
2927 - struct mc_command cmd = { 0 };
2929 - /* prepare command */
2930 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags,
2933 - /* send command to mc*/
2934 - return mc_send_command(mc_io, &cmd);
2936 -EXPORT_SYMBOL(dprc_close);
2939 - * dprc_get_irq() - Get IRQ information from the DPRC.
2940 - * @mc_io: Pointer to MC portal's I/O object
2941 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2942 - * @token: Token of DPRC object
2943 - * @irq_index: The interrupt index to configure
2944 - * @type: Interrupt type: 0 represents message interrupt
2945 - * type (both irq_addr and irq_val are valid)
2946 - * @irq_cfg: IRQ attributes
2948 - * Return: '0' on Success; Error code otherwise.
2950 -int dprc_get_irq(struct fsl_mc_io *mc_io,
2955 - struct dprc_irq_cfg *irq_cfg)
2957 - struct mc_command cmd = { 0 };
2958 - struct dprc_cmd_get_irq *cmd_params;
2959 - struct dprc_rsp_get_irq *rsp_params;
2962 - /* prepare command */
2963 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ,
2966 - cmd_params = (struct dprc_cmd_get_irq *)cmd.params;
2967 - cmd_params->irq_index = irq_index;
2969 - /* send command to mc*/
2970 - err = mc_send_command(mc_io, &cmd);
2974 - /* retrieve response parameters */
2975 - rsp_params = (struct dprc_rsp_get_irq *)cmd.params;
2976 - irq_cfg->val = le32_to_cpu(rsp_params->irq_val);
2977 - irq_cfg->paddr = le64_to_cpu(rsp_params->irq_addr);
2978 - irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num);
2979 - *type = le32_to_cpu(rsp_params->type);
2985 - * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt.
2986 - * @mc_io: Pointer to MC portal's I/O object
2987 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
2988 - * @token: Token of DPRC object
2989 - * @irq_index: Identifies the interrupt index to configure
2990 - * @irq_cfg: IRQ configuration
2992 - * Return: '0' on Success; Error code otherwise.
2994 -int dprc_set_irq(struct fsl_mc_io *mc_io,
2998 - struct dprc_irq_cfg *irq_cfg)
3000 - struct mc_command cmd = { 0 };
3001 - struct dprc_cmd_set_irq *cmd_params;
3003 - /* prepare command */
3004 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ,
3007 - cmd_params = (struct dprc_cmd_set_irq *)cmd.params;
3008 - cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
3009 - cmd_params->irq_index = irq_index;
3010 - cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
3011 - cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
3013 - /* send command to mc*/
3014 - return mc_send_command(mc_io, &cmd);
3018 - * dprc_get_irq_enable() - Get overall interrupt state.
3019 - * @mc_io: Pointer to MC portal's I/O object
3020 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3021 - * @token: Token of DPRC object
3022 - * @irq_index: The interrupt index to configure
3023 - * @en: Returned interrupt state - enable = 1, disable = 0
3025 - * Return: '0' on Success; Error code otherwise.
3027 -int dprc_get_irq_enable(struct fsl_mc_io *mc_io,
3033 - struct mc_command cmd = { 0 };
3034 - struct dprc_cmd_get_irq_enable *cmd_params;
3035 - struct dprc_rsp_get_irq_enable *rsp_params;
3038 - /* prepare command */
3039 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_ENABLE,
3040 - cmd_flags, token);
3041 - cmd_params = (struct dprc_cmd_get_irq_enable *)cmd.params;
3042 - cmd_params->irq_index = irq_index;
3044 - /* send command to mc*/
3045 - err = mc_send_command(mc_io, &cmd);
3049 - /* retrieve response parameters */
3050 - rsp_params = (struct dprc_rsp_get_irq_enable *)cmd.params;
3051 - *en = rsp_params->enabled & DPRC_ENABLE;
3057 - * dprc_set_irq_enable() - Set overall interrupt state.
3058 - * @mc_io: Pointer to MC portal's I/O object
3059 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3060 - * @token: Token of DPRC object
3061 - * @irq_index: The interrupt index to configure
3062 - * @en: Interrupt state - enable = 1, disable = 0
3064 - * Allows GPP software to control when interrupts are generated.
3065 - * Each interrupt can have up to 32 causes. The enable/disable control's the
3066 - * overall interrupt state. if the interrupt is disabled no causes will cause
3069 - * Return: '0' on Success; Error code otherwise.
3071 -int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
3077 - struct mc_command cmd = { 0 };
3078 - struct dprc_cmd_set_irq_enable *cmd_params;
3080 - /* prepare command */
3081 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE,
3082 - cmd_flags, token);
3083 - cmd_params = (struct dprc_cmd_set_irq_enable *)cmd.params;
3084 - cmd_params->enable = en & DPRC_ENABLE;
3085 - cmd_params->irq_index = irq_index;
3087 - /* send command to mc*/
3088 - return mc_send_command(mc_io, &cmd);
3092 - * dprc_get_irq_mask() - Get interrupt mask.
3093 - * @mc_io: Pointer to MC portal's I/O object
3094 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3095 - * @token: Token of DPRC object
3096 - * @irq_index: The interrupt index to configure
3097 - * @mask: Returned event mask to trigger interrupt
3099 - * Every interrupt can have up to 32 causes and the interrupt model supports
3100 - * masking/unmasking each cause independently
3102 - * Return: '0' on Success; Error code otherwise.
3104 -int dprc_get_irq_mask(struct fsl_mc_io *mc_io,
3110 - struct mc_command cmd = { 0 };
3111 - struct dprc_cmd_get_irq_mask *cmd_params;
3112 - struct dprc_rsp_get_irq_mask *rsp_params;
3115 - /* prepare command */
3116 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_MASK,
3117 - cmd_flags, token);
3118 - cmd_params = (struct dprc_cmd_get_irq_mask *)cmd.params;
3119 - cmd_params->irq_index = irq_index;
3121 - /* send command to mc*/
3122 - err = mc_send_command(mc_io, &cmd);
3126 - /* retrieve response parameters */
3127 - rsp_params = (struct dprc_rsp_get_irq_mask *)cmd.params;
3128 - *mask = le32_to_cpu(rsp_params->mask);
3134 - * dprc_set_irq_mask() - Set interrupt mask.
3135 - * @mc_io: Pointer to MC portal's I/O object
3136 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3137 - * @token: Token of DPRC object
3138 - * @irq_index: The interrupt index to configure
3139 - * @mask: event mask to trigger interrupt;
3141 - * 0 = ignore event
3142 - * 1 = consider event for asserting irq
3144 - * Every interrupt can have up to 32 causes and the interrupt model supports
3145 - * masking/unmasking each cause independently
3147 - * Return: '0' on Success; Error code otherwise.
3149 -int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
3155 - struct mc_command cmd = { 0 };
3156 - struct dprc_cmd_set_irq_mask *cmd_params;
3158 - /* prepare command */
3159 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK,
3160 - cmd_flags, token);
3161 - cmd_params = (struct dprc_cmd_set_irq_mask *)cmd.params;
3162 - cmd_params->mask = cpu_to_le32(mask);
3163 - cmd_params->irq_index = irq_index;
3165 - /* send command to mc*/
3166 - return mc_send_command(mc_io, &cmd);
3170 - * dprc_get_irq_status() - Get the current status of any pending interrupts.
3171 - * @mc_io: Pointer to MC portal's I/O object
3172 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3173 - * @token: Token of DPRC object
3174 - * @irq_index: The interrupt index to configure
3175 - * @status: Returned interrupts status - one bit per cause:
3176 - * 0 = no interrupt pending
3177 - * 1 = interrupt pending
3179 - * Return: '0' on Success; Error code otherwise.
3181 -int dprc_get_irq_status(struct fsl_mc_io *mc_io,
3187 - struct mc_command cmd = { 0 };
3188 - struct dprc_cmd_get_irq_status *cmd_params;
3189 - struct dprc_rsp_get_irq_status *rsp_params;
3192 - /* prepare command */
3193 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS,
3194 - cmd_flags, token);
3195 - cmd_params = (struct dprc_cmd_get_irq_status *)cmd.params;
3196 - cmd_params->status = cpu_to_le32(*status);
3197 - cmd_params->irq_index = irq_index;
3199 - /* send command to mc*/
3200 - err = mc_send_command(mc_io, &cmd);
3204 - /* retrieve response parameters */
3205 - rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params;
3206 - *status = le32_to_cpu(rsp_params->status);
3212 - * dprc_clear_irq_status() - Clear a pending interrupt's status
3213 - * @mc_io: Pointer to MC portal's I/O object
3214 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3215 - * @token: Token of DPRC object
3216 - * @irq_index: The interrupt index to configure
3217 - * @status: bits to clear (W1C) - one bit per cause:
3218 - * 0 = don't change
3219 - * 1 = clear status bit
3221 - * Return: '0' on Success; Error code otherwise.
3223 -int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
3229 - struct mc_command cmd = { 0 };
3230 - struct dprc_cmd_clear_irq_status *cmd_params;
3232 - /* prepare command */
3233 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS,
3234 - cmd_flags, token);
3235 - cmd_params = (struct dprc_cmd_clear_irq_status *)cmd.params;
3236 - cmd_params->status = cpu_to_le32(status);
3237 - cmd_params->irq_index = irq_index;
3239 - /* send command to mc*/
3240 - return mc_send_command(mc_io, &cmd);
3244 - * dprc_get_attributes() - Obtains container attributes
3245 - * @mc_io: Pointer to MC portal's I/O object
3246 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3247 - * @token: Token of DPRC object
3248 - * @attributes Returned container attributes
3250 - * Return: '0' on Success; Error code otherwise.
3252 -int dprc_get_attributes(struct fsl_mc_io *mc_io,
3255 - struct dprc_attributes *attr)
3257 - struct mc_command cmd = { 0 };
3258 - struct dprc_rsp_get_attributes *rsp_params;
3261 - /* prepare command */
3262 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR,
3266 - /* send command to mc*/
3267 - err = mc_send_command(mc_io, &cmd);
3271 - /* retrieve response parameters */
3272 - rsp_params = (struct dprc_rsp_get_attributes *)cmd.params;
3273 - attr->container_id = le32_to_cpu(rsp_params->container_id);
3274 - attr->icid = le16_to_cpu(rsp_params->icid);
3275 - attr->options = le32_to_cpu(rsp_params->options);
3276 - attr->portal_id = le32_to_cpu(rsp_params->portal_id);
3282 - * dprc_get_obj_count() - Obtains the number of objects in the DPRC
3283 - * @mc_io: Pointer to MC portal's I/O object
3284 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3285 - * @token: Token of DPRC object
3286 - * @obj_count: Number of objects assigned to the DPRC
3288 - * Return: '0' on Success; Error code otherwise.
3290 -int dprc_get_obj_count(struct fsl_mc_io *mc_io,
3295 - struct mc_command cmd = { 0 };
3296 - struct dprc_rsp_get_obj_count *rsp_params;
3299 - /* prepare command */
3300 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT,
3301 - cmd_flags, token);
3303 - /* send command to mc*/
3304 - err = mc_send_command(mc_io, &cmd);
3308 - /* retrieve response parameters */
3309 - rsp_params = (struct dprc_rsp_get_obj_count *)cmd.params;
3310 - *obj_count = le32_to_cpu(rsp_params->obj_count);
3314 -EXPORT_SYMBOL(dprc_get_obj_count);
3317 - * dprc_get_obj() - Get general information on an object
3318 - * @mc_io: Pointer to MC portal's I/O object
3319 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3320 - * @token: Token of DPRC object
3321 - * @obj_index: Index of the object to be queried (< obj_count)
3322 - * @obj_desc: Returns the requested object descriptor
3324 - * The object descriptors are retrieved one by one by incrementing
3325 - * obj_index up to (not including) the value of obj_count returned
3326 - * from dprc_get_obj_count(). dprc_get_obj_count() must
3327 - * be called prior to dprc_get_obj().
3329 - * Return: '0' on Success; Error code otherwise.
3331 -int dprc_get_obj(struct fsl_mc_io *mc_io,
3335 - struct fsl_mc_obj_desc *obj_desc)
3337 - struct mc_command cmd = { 0 };
3338 - struct dprc_cmd_get_obj *cmd_params;
3339 - struct dprc_rsp_get_obj *rsp_params;
3342 - /* prepare command */
3343 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ,
3346 - cmd_params = (struct dprc_cmd_get_obj *)cmd.params;
3347 - cmd_params->obj_index = cpu_to_le32(obj_index);
3349 - /* send command to mc*/
3350 - err = mc_send_command(mc_io, &cmd);
3354 - /* retrieve response parameters */
3355 - rsp_params = (struct dprc_rsp_get_obj *)cmd.params;
3356 - obj_desc->id = le32_to_cpu(rsp_params->id);
3357 - obj_desc->vendor = le16_to_cpu(rsp_params->vendor);
3358 - obj_desc->irq_count = rsp_params->irq_count;
3359 - obj_desc->region_count = rsp_params->region_count;
3360 - obj_desc->state = le32_to_cpu(rsp_params->state);
3361 - obj_desc->ver_major = le16_to_cpu(rsp_params->version_major);
3362 - obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor);
3363 - obj_desc->flags = le16_to_cpu(rsp_params->flags);
3364 - strncpy(obj_desc->type, rsp_params->type, 16);
3365 - obj_desc->type[15] = '\0';
3366 - strncpy(obj_desc->label, rsp_params->label, 16);
3367 - obj_desc->label[15] = '\0';
3370 -EXPORT_SYMBOL(dprc_get_obj);
3373 - * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt.
3374 - * @mc_io: Pointer to MC portal's I/O object
3375 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3376 - * @token: Token of DPRC object
3377 - * @obj_type: Type of the object to set its IRQ
3378 - * @obj_id: ID of the object to set its IRQ
3379 - * @irq_index: The interrupt index to configure
3380 - * @irq_cfg: IRQ configuration
3382 - * Return: '0' on Success; Error code otherwise.
3384 -int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
3390 - struct dprc_irq_cfg *irq_cfg)
3392 - struct mc_command cmd = { 0 };
3393 - struct dprc_cmd_set_obj_irq *cmd_params;
3395 - /* prepare command */
3396 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ,
3399 - cmd_params = (struct dprc_cmd_set_obj_irq *)cmd.params;
3400 - cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
3401 - cmd_params->irq_index = irq_index;
3402 - cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
3403 - cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
3404 - cmd_params->obj_id = cpu_to_le32(obj_id);
3405 - strncpy(cmd_params->obj_type, obj_type, 16);
3406 - cmd_params->obj_type[15] = '\0';
3408 - /* send command to mc*/
3409 - return mc_send_command(mc_io, &cmd);
3411 -EXPORT_SYMBOL(dprc_set_obj_irq);
3414 - * dprc_get_obj_irq() - Get IRQ information from object.
3415 - * @mc_io: Pointer to MC portal's I/O object
3416 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3417 - * @token: Token of DPRC object
3418 - * @obj_type: Type od the object to get its IRQ
3419 - * @obj_id: ID of the object to get its IRQ
3420 - * @irq_index: The interrupt index to configure
3421 - * @type: Interrupt type: 0 represents message interrupt
3422 - * type (both irq_addr and irq_val are valid)
3423 - * @irq_cfg: The returned IRQ attributes
3425 - * Return: '0' on Success; Error code otherwise.
3427 -int dprc_get_obj_irq(struct fsl_mc_io *mc_io,
3434 - struct dprc_irq_cfg *irq_cfg)
3436 - struct mc_command cmd = { 0 };
3437 - struct dprc_cmd_get_obj_irq *cmd_params;
3438 - struct dprc_rsp_get_obj_irq *rsp_params;
3441 - /* prepare command */
3442 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_IRQ,
3445 - cmd_params = (struct dprc_cmd_get_obj_irq *)cmd.params;
3446 - cmd_params->obj_id = cpu_to_le32(obj_id);
3447 - cmd_params->irq_index = irq_index;
3448 - strncpy(cmd_params->obj_type, obj_type, 16);
3449 - cmd_params->obj_type[15] = '\0';
3451 - /* send command to mc*/
3452 - err = mc_send_command(mc_io, &cmd);
3456 - /* retrieve response parameters */
3457 - rsp_params = (struct dprc_rsp_get_obj_irq *)cmd.params;
3458 - irq_cfg->val = le32_to_cpu(rsp_params->irq_val);
3459 - irq_cfg->paddr = le64_to_cpu(rsp_params->irq_addr);
3460 - irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num);
3461 - *type = le32_to_cpu(rsp_params->type);
3465 -EXPORT_SYMBOL(dprc_get_obj_irq);
3468 - * dprc_get_res_count() - Obtains the number of free resources that are assigned
3469 - * to this container, by pool type
3470 - * @mc_io: Pointer to MC portal's I/O object
3471 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3472 - * @token: Token of DPRC object
3473 - * @type: pool type
3474 - * @res_count: Returned number of free resources of the given
3475 - * resource type that are assigned to this DPRC
3477 - * Return: '0' on Success; Error code otherwise.
3479 -int dprc_get_res_count(struct fsl_mc_io *mc_io,
3485 - struct mc_command cmd = { 0 };
3486 - struct dprc_cmd_get_res_count *cmd_params;
3487 - struct dprc_rsp_get_res_count *rsp_params;
3490 - /* prepare command */
3491 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT,
3492 - cmd_flags, token);
3493 - cmd_params = (struct dprc_cmd_get_res_count *)cmd.params;
3494 - strncpy(cmd_params->type, type, 16);
3495 - cmd_params->type[15] = '\0';
3497 - /* send command to mc*/
3498 - err = mc_send_command(mc_io, &cmd);
3502 - /* retrieve response parameters */
3503 - rsp_params = (struct dprc_rsp_get_res_count *)cmd.params;
3504 - *res_count = le32_to_cpu(rsp_params->res_count);
3508 -EXPORT_SYMBOL(dprc_get_res_count);
3511 - * dprc_get_obj_region() - Get region information for a specified object.
3512 - * @mc_io: Pointer to MC portal's I/O object
3513 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3514 - * @token: Token of DPRC object
3515 - * @obj_type; Object type as returned in dprc_get_obj()
3516 - * @obj_id: Unique object instance as returned in dprc_get_obj()
3517 - * @region_index: The specific region to query
3518 - * @region_desc: Returns the requested region descriptor
3520 - * Return: '0' on Success; Error code otherwise.
3522 -int dprc_get_obj_region(struct fsl_mc_io *mc_io,
3528 - struct dprc_region_desc *region_desc)
3530 - struct mc_command cmd = { 0 };
3531 - struct dprc_cmd_get_obj_region *cmd_params;
3532 - struct dprc_rsp_get_obj_region *rsp_params;
3535 - /* prepare command */
3536 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG,
3537 - cmd_flags, token);
3538 - cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params;
3539 - cmd_params->obj_id = cpu_to_le32(obj_id);
3540 - cmd_params->region_index = region_index;
3541 - strncpy(cmd_params->obj_type, obj_type, 16);
3542 - cmd_params->obj_type[15] = '\0';
3544 - /* send command to mc*/
3545 - err = mc_send_command(mc_io, &cmd);
3549 - /* retrieve response parameters */
3550 - rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params;
3551 - region_desc->base_offset = le64_to_cpu(rsp_params->base_addr);
3552 - region_desc->size = le32_to_cpu(rsp_params->size);
3556 -EXPORT_SYMBOL(dprc_get_obj_region);
3559 - * dprc_get_api_version - Get Data Path Resource Container API version
3560 - * @mc_io: Pointer to Mc portal's I/O object
3561 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3562 - * @major_ver: Major version of Data Path Resource Container API
3563 - * @minor_ver: Minor version of Data Path Resource Container API
3565 - * Return: '0' on Success; Error code otherwise.
3567 -int dprc_get_api_version(struct fsl_mc_io *mc_io,
3572 - struct mc_command cmd = { 0 };
3575 - /* prepare command */
3576 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION,
3579 - /* send command to mc */
3580 - err = mc_send_command(mc_io, &cmd);
3584 - /* retrieve response parameters */
3585 - mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
3591 - * dprc_get_container_id - Get container ID associated with a given portal.
3592 - * @mc_io: Pointer to Mc portal's I/O object
3593 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3594 - * @container_id: Requested container id
3596 - * Return: '0' on Success; Error code otherwise.
3598 -int dprc_get_container_id(struct fsl_mc_io *mc_io,
3600 - int *container_id)
3602 - struct mc_command cmd = { 0 };
3605 - /* prepare command */
3606 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID,
3610 - /* send command to mc*/
3611 - err = mc_send_command(mc_io, &cmd);
3615 - /* retrieve response parameters */
3616 - *container_id = (int)mc_cmd_read_object_id(&cmd);
3621 +++ b/drivers/bus/fsl-mc/dprc.c
3623 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
3625 + * Copyright 2013-2016 Freescale Semiconductor Inc.
3628 +#include <linux/kernel.h>
3629 +#include <linux/fsl/mc.h>
3631 +#include "fsl-mc-private.h"
3634 + * dprc_open() - Open DPRC object for use
3635 + * @mc_io: Pointer to MC portal's I/O object
3636 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3637 + * @container_id: Container ID to open
3638 + * @token: Returned token of DPRC object
3640 + * Return: '0' on Success; Error code otherwise.
3642 + * @warning Required before any operation on the object.
3644 +int dprc_open(struct fsl_mc_io *mc_io,
3649 + struct fsl_mc_command cmd = { 0 };
3650 + struct dprc_cmd_open *cmd_params;
3653 + /* prepare command */
3654 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags,
3656 + cmd_params = (struct dprc_cmd_open *)cmd.params;
3657 + cmd_params->container_id = cpu_to_le32(container_id);
3659 + /* send command to mc*/
3660 + err = mc_send_command(mc_io, &cmd);
3664 + /* retrieve response parameters */
3665 + *token = mc_cmd_hdr_read_token(&cmd);
3669 +EXPORT_SYMBOL_GPL(dprc_open);
3672 + * dprc_close() - Close the control session of the object
3673 + * @mc_io: Pointer to MC portal's I/O object
3674 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3675 + * @token: Token of DPRC object
3677 + * After this function is called, no further operations are
3678 + * allowed on the object without opening a new control session.
3680 + * Return: '0' on Success; Error code otherwise.
3682 +int dprc_close(struct fsl_mc_io *mc_io,
3686 + struct fsl_mc_command cmd = { 0 };
3688 + /* prepare command */
3689 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags,
3692 + /* send command to mc*/
3693 + return mc_send_command(mc_io, &cmd);
3695 +EXPORT_SYMBOL_GPL(dprc_close);
3698 + * dprc_reset_container - Reset child container.
3699 + * @mc_io: Pointer to MC portal's I/O object
3700 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3701 + * @token: Token of DPRC object
3702 + * @child_container_id: ID of the container to reset
3704 + * In case a software context crashes or becomes non-responsive, the parent
3705 + * may wish to reset its resources container before the software context is
3708 + * This routine informs all objects assigned to the child container that the
3709 + * container is being reset, so they may perform any cleanup operations that are
3710 + * needed. All objects handles that were owned by the child container shall be
3713 + * Note that such request may be submitted even if the child software context
3714 + * has not crashed, but the resulting object cleanup operations will not be
3717 + * Return: '0' on Success; Error code otherwise.
3719 +int dprc_reset_container(struct fsl_mc_io *mc_io,
3722 + int child_container_id)
3724 + struct fsl_mc_command cmd = { 0 };
3725 + struct dprc_cmd_reset_container *cmd_params;
3727 + /* prepare command */
3728 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT,
3729 + cmd_flags, token);
3730 + cmd_params = (struct dprc_cmd_reset_container *)cmd.params;
3731 + cmd_params->child_container_id = cpu_to_le32(child_container_id);
3733 + /* send command to mc*/
3734 + return mc_send_command(mc_io, &cmd);
3736 +EXPORT_SYMBOL_GPL(dprc_reset_container);
3739 + * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt.
3740 + * @mc_io: Pointer to MC portal's I/O object
3741 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3742 + * @token: Token of DPRC object
3743 + * @irq_index: Identifies the interrupt index to configure
3744 + * @irq_cfg: IRQ configuration
3746 + * Return: '0' on Success; Error code otherwise.
3748 +int dprc_set_irq(struct fsl_mc_io *mc_io,
3752 + struct dprc_irq_cfg *irq_cfg)
3754 + struct fsl_mc_command cmd = { 0 };
3755 + struct dprc_cmd_set_irq *cmd_params;
3757 + /* prepare command */
3758 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ,
3761 + cmd_params = (struct dprc_cmd_set_irq *)cmd.params;
3762 + cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
3763 + cmd_params->irq_index = irq_index;
3764 + cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
3765 + cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
3767 + /* send command to mc*/
3768 + return mc_send_command(mc_io, &cmd);
3772 + * dprc_set_irq_enable() - Set overall interrupt state.
3773 + * @mc_io: Pointer to MC portal's I/O object
3774 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3775 + * @token: Token of DPRC object
3776 + * @irq_index: The interrupt index to configure
3777 + * @en: Interrupt state - enable = 1, disable = 0
3779 + * Allows GPP software to control when interrupts are generated.
3780 + * Each interrupt can have up to 32 causes. The enable/disable control's the
3781 + * overall interrupt state. if the interrupt is disabled no causes will cause
3784 + * Return: '0' on Success; Error code otherwise.
3786 +int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
3792 + struct fsl_mc_command cmd = { 0 };
3793 + struct dprc_cmd_set_irq_enable *cmd_params;
3795 + /* prepare command */
3796 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE,
3797 + cmd_flags, token);
3798 + cmd_params = (struct dprc_cmd_set_irq_enable *)cmd.params;
3799 + cmd_params->enable = en & DPRC_ENABLE;
3800 + cmd_params->irq_index = irq_index;
3802 + /* send command to mc*/
3803 + return mc_send_command(mc_io, &cmd);
3807 + * dprc_set_irq_mask() - Set interrupt mask.
3808 + * @mc_io: Pointer to MC portal's I/O object
3809 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3810 + * @token: Token of DPRC object
3811 + * @irq_index: The interrupt index to configure
3812 + * @mask: event mask to trigger interrupt;
3814 + * 0 = ignore event
3815 + * 1 = consider event for asserting irq
3817 + * Every interrupt can have up to 32 causes and the interrupt model supports
3818 + * masking/unmasking each cause independently
3820 + * Return: '0' on Success; Error code otherwise.
3822 +int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
3828 + struct fsl_mc_command cmd = { 0 };
3829 + struct dprc_cmd_set_irq_mask *cmd_params;
3831 + /* prepare command */
3832 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK,
3833 + cmd_flags, token);
3834 + cmd_params = (struct dprc_cmd_set_irq_mask *)cmd.params;
3835 + cmd_params->mask = cpu_to_le32(mask);
3836 + cmd_params->irq_index = irq_index;
3838 + /* send command to mc*/
3839 + return mc_send_command(mc_io, &cmd);
3843 + * dprc_get_irq_status() - Get the current status of any pending interrupts.
3844 + * @mc_io: Pointer to MC portal's I/O object
3845 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3846 + * @token: Token of DPRC object
3847 + * @irq_index: The interrupt index to configure
3848 + * @status: Returned interrupts status - one bit per cause:
3849 + * 0 = no interrupt pending
3850 + * 1 = interrupt pending
3852 + * Return: '0' on Success; Error code otherwise.
3854 +int dprc_get_irq_status(struct fsl_mc_io *mc_io,
3860 + struct fsl_mc_command cmd = { 0 };
3861 + struct dprc_cmd_get_irq_status *cmd_params;
3862 + struct dprc_rsp_get_irq_status *rsp_params;
3865 + /* prepare command */
3866 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS,
3867 + cmd_flags, token);
3868 + cmd_params = (struct dprc_cmd_get_irq_status *)cmd.params;
3869 + cmd_params->status = cpu_to_le32(*status);
3870 + cmd_params->irq_index = irq_index;
3872 + /* send command to mc*/
3873 + err = mc_send_command(mc_io, &cmd);
3877 + /* retrieve response parameters */
3878 + rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params;
3879 + *status = le32_to_cpu(rsp_params->status);
3885 + * dprc_clear_irq_status() - Clear a pending interrupt's status
3886 + * @mc_io: Pointer to MC portal's I/O object
3887 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3888 + * @token: Token of DPRC object
3889 + * @irq_index: The interrupt index to configure
3890 + * @status: bits to clear (W1C) - one bit per cause:
3891 + * 0 = don't change
3892 + * 1 = clear status bit
3894 + * Return: '0' on Success; Error code otherwise.
3896 +int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
3902 + struct fsl_mc_command cmd = { 0 };
3903 + struct dprc_cmd_clear_irq_status *cmd_params;
3905 + /* prepare command */
3906 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS,
3907 + cmd_flags, token);
3908 + cmd_params = (struct dprc_cmd_clear_irq_status *)cmd.params;
3909 + cmd_params->status = cpu_to_le32(status);
3910 + cmd_params->irq_index = irq_index;
3912 + /* send command to mc*/
3913 + return mc_send_command(mc_io, &cmd);
3917 + * dprc_get_attributes() - Obtains container attributes
3918 + * @mc_io: Pointer to MC portal's I/O object
3919 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3920 + * @token: Token of DPRC object
3921 + * @attributes Returned container attributes
3923 + * Return: '0' on Success; Error code otherwise.
3925 +int dprc_get_attributes(struct fsl_mc_io *mc_io,
3928 + struct dprc_attributes *attr)
3930 + struct fsl_mc_command cmd = { 0 };
3931 + struct dprc_rsp_get_attributes *rsp_params;
3934 + /* prepare command */
3935 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR,
3939 + /* send command to mc*/
3940 + err = mc_send_command(mc_io, &cmd);
3944 + /* retrieve response parameters */
3945 + rsp_params = (struct dprc_rsp_get_attributes *)cmd.params;
3946 + attr->container_id = le32_to_cpu(rsp_params->container_id);
3947 + attr->icid = le32_to_cpu(rsp_params->icid);
3948 + attr->options = le32_to_cpu(rsp_params->options);
3949 + attr->portal_id = le32_to_cpu(rsp_params->portal_id);
3955 + * dprc_get_obj_count() - Obtains the number of objects in the DPRC
3956 + * @mc_io: Pointer to MC portal's I/O object
3957 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3958 + * @token: Token of DPRC object
3959 + * @obj_count: Number of objects assigned to the DPRC
3961 + * Return: '0' on Success; Error code otherwise.
3963 +int dprc_get_obj_count(struct fsl_mc_io *mc_io,
3968 + struct fsl_mc_command cmd = { 0 };
3969 + struct dprc_rsp_get_obj_count *rsp_params;
3972 + /* prepare command */
3973 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT,
3974 + cmd_flags, token);
3976 + /* send command to mc*/
3977 + err = mc_send_command(mc_io, &cmd);
3981 + /* retrieve response parameters */
3982 + rsp_params = (struct dprc_rsp_get_obj_count *)cmd.params;
3983 + *obj_count = le32_to_cpu(rsp_params->obj_count);
3987 +EXPORT_SYMBOL_GPL(dprc_get_obj_count);
3990 + * dprc_get_obj() - Get general information on an object
3991 + * @mc_io: Pointer to MC portal's I/O object
3992 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
3993 + * @token: Token of DPRC object
3994 + * @obj_index: Index of the object to be queried (< obj_count)
3995 + * @obj_desc: Returns the requested object descriptor
3997 + * The object descriptors are retrieved one by one by incrementing
3998 + * obj_index up to (not including) the value of obj_count returned
3999 + * from dprc_get_obj_count(). dprc_get_obj_count() must
4000 + * be called prior to dprc_get_obj().
4002 + * Return: '0' on Success; Error code otherwise.
4004 +int dprc_get_obj(struct fsl_mc_io *mc_io,
4008 + struct fsl_mc_obj_desc *obj_desc)
4010 + struct fsl_mc_command cmd = { 0 };
4011 + struct dprc_cmd_get_obj *cmd_params;
4012 + struct dprc_rsp_get_obj *rsp_params;
4015 + /* prepare command */
4016 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ,
4019 + cmd_params = (struct dprc_cmd_get_obj *)cmd.params;
4020 + cmd_params->obj_index = cpu_to_le32(obj_index);
4022 + /* send command to mc*/
4023 + err = mc_send_command(mc_io, &cmd);
4027 + /* retrieve response parameters */
4028 + rsp_params = (struct dprc_rsp_get_obj *)cmd.params;
4029 + obj_desc->id = le32_to_cpu(rsp_params->id);
4030 + obj_desc->vendor = le16_to_cpu(rsp_params->vendor);
4031 + obj_desc->irq_count = rsp_params->irq_count;
4032 + obj_desc->region_count = rsp_params->region_count;
4033 + obj_desc->state = le32_to_cpu(rsp_params->state);
4034 + obj_desc->ver_major = le16_to_cpu(rsp_params->version_major);
4035 + obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor);
4036 + obj_desc->flags = le16_to_cpu(rsp_params->flags);
4037 + strncpy(obj_desc->type, rsp_params->type, 16);
4038 + obj_desc->type[15] = '\0';
4039 + strncpy(obj_desc->label, rsp_params->label, 16);
4040 + obj_desc->label[15] = '\0';
4043 +EXPORT_SYMBOL_GPL(dprc_get_obj);
4046 + * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt.
4047 + * @mc_io: Pointer to MC portal's I/O object
4048 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4049 + * @token: Token of DPRC object
4050 + * @obj_type: Type of the object to set its IRQ
4051 + * @obj_id: ID of the object to set its IRQ
4052 + * @irq_index: The interrupt index to configure
4053 + * @irq_cfg: IRQ configuration
4055 + * Return: '0' on Success; Error code otherwise.
4057 +int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
4063 + struct dprc_irq_cfg *irq_cfg)
4065 + struct fsl_mc_command cmd = { 0 };
4066 + struct dprc_cmd_set_obj_irq *cmd_params;
4068 + /* prepare command */
4069 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ,
4072 + cmd_params = (struct dprc_cmd_set_obj_irq *)cmd.params;
4073 + cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
4074 + cmd_params->irq_index = irq_index;
4075 + cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr);
4076 + cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
4077 + cmd_params->obj_id = cpu_to_le32(obj_id);
4078 + strncpy(cmd_params->obj_type, obj_type, 16);
4079 + cmd_params->obj_type[15] = '\0';
4081 + /* send command to mc*/
4082 + return mc_send_command(mc_io, &cmd);
4084 +EXPORT_SYMBOL_GPL(dprc_set_obj_irq);
4087 + * dprc_get_obj_region() - Get region information for a specified object.
4088 + * @mc_io: Pointer to MC portal's I/O object
4089 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4090 + * @token: Token of DPRC object
4091 + * @obj_type; Object type as returned in dprc_get_obj()
4092 + * @obj_id: Unique object instance as returned in dprc_get_obj()
4093 + * @region_index: The specific region to query
4094 + * @region_desc: Returns the requested region descriptor
4096 + * Return: '0' on Success; Error code otherwise.
4098 +int dprc_get_obj_region(struct fsl_mc_io *mc_io,
4104 + struct dprc_region_desc *region_desc)
4106 + struct fsl_mc_command cmd = { 0 };
4107 + struct dprc_cmd_get_obj_region *cmd_params;
4108 + struct dprc_rsp_get_obj_region *rsp_params;
4111 + /* prepare command */
4112 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG,
4113 + cmd_flags, token);
4114 + cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params;
4115 + cmd_params->obj_id = cpu_to_le32(obj_id);
4116 + cmd_params->region_index = region_index;
4117 + strncpy(cmd_params->obj_type, obj_type, 16);
4118 + cmd_params->obj_type[15] = '\0';
4120 + /* send command to mc*/
4121 + err = mc_send_command(mc_io, &cmd);
4125 + /* retrieve response parameters */
4126 + rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params;
4127 + region_desc->base_offset = le32_to_cpu(rsp_params->base_offset);
4128 + region_desc->size = le32_to_cpu(rsp_params->size);
4129 + region_desc->type = rsp_params->type;
4130 + region_desc->flags = le32_to_cpu(rsp_params->flags);
4131 + region_desc->base_address = le64_to_cpu(rsp_params->base_addr);
4135 +EXPORT_SYMBOL_GPL(dprc_get_obj_region);
4138 + * dprc_get_api_version - Get Data Path Resource Container API version
4139 + * @mc_io: Pointer to Mc portal's I/O object
4140 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4141 + * @major_ver: Major version of Data Path Resource Container API
4142 + * @minor_ver: Minor version of Data Path Resource Container API
4144 + * Return: '0' on Success; Error code otherwise.
4146 +int dprc_get_api_version(struct fsl_mc_io *mc_io,
4151 + struct fsl_mc_command cmd = { 0 };
4154 + /* prepare command */
4155 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION,
4158 + /* send command to mc */
4159 + err = mc_send_command(mc_io, &cmd);
4163 + /* retrieve response parameters */
4164 + mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
4170 + * dprc_get_container_id - Get container ID associated with a given portal.
4171 + * @mc_io: Pointer to Mc portal's I/O object
4172 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
4173 + * @container_id: Requested container id
4175 + * Return: '0' on Success; Error code otherwise.
4177 +int dprc_get_container_id(struct fsl_mc_io *mc_io,
4179 + int *container_id)
4181 + struct fsl_mc_command cmd = { 0 };
4184 + /* prepare command */
4185 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID,
4189 + /* send command to mc*/
4190 + err = mc_send_command(mc_io, &cmd);
4194 + /* retrieve response parameters */
4195 + *container_id = (int)mc_cmd_read_object_id(&cmd);
4199 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c
4202 -// SPDX-License-Identifier: GPL-2.0
4204 - * fsl-mc object allocator driver
4206 - * Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
4210 -#include <linux/module.h>
4211 -#include <linux/msi.h>
4212 -#include "../include/mc.h"
4214 -#include "fsl-mc-private.h"
4216 -static bool __must_check fsl_mc_is_allocatable(const char *obj_type)
4218 - return strcmp(obj_type, "dpbp") == 0 ||
4219 - strcmp(obj_type, "dpmcp") == 0 ||
4220 - strcmp(obj_type, "dpcon") == 0;
4224 - * fsl_mc_resource_pool_add_device - add allocatable object to a resource
4225 - * pool of a given fsl-mc bus
4227 - * @mc_bus: pointer to the fsl-mc bus
4228 - * @pool_type: pool type
4229 - * @mc_dev: pointer to allocatable fsl-mc device
4231 -static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
4233 - enum fsl_mc_pool_type
4235 - struct fsl_mc_device
4238 - struct fsl_mc_resource_pool *res_pool;
4239 - struct fsl_mc_resource *resource;
4240 - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
4241 - int error = -EINVAL;
4243 - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
4245 - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
4247 - if (WARN_ON(mc_dev->resource))
4250 - res_pool = &mc_bus->resource_pools[pool_type];
4251 - if (WARN_ON(res_pool->type != pool_type))
4253 - if (WARN_ON(res_pool->mc_bus != mc_bus))
4256 - mutex_lock(&res_pool->mutex);
4258 - if (WARN_ON(res_pool->max_count < 0))
4260 - if (WARN_ON(res_pool->free_count < 0 ||
4261 - res_pool->free_count > res_pool->max_count))
4264 - resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource),
4268 - dev_err(&mc_bus_dev->dev,
4269 - "Failed to allocate memory for fsl_mc_resource\n");
4273 - resource->type = pool_type;
4274 - resource->id = mc_dev->obj_desc.id;
4275 - resource->data = mc_dev;
4276 - resource->parent_pool = res_pool;
4277 - INIT_LIST_HEAD(&resource->node);
4278 - list_add_tail(&resource->node, &res_pool->free_list);
4279 - mc_dev->resource = resource;
4280 - res_pool->free_count++;
4281 - res_pool->max_count++;
4284 - mutex_unlock(&res_pool->mutex);
4290 - * fsl_mc_resource_pool_remove_device - remove an allocatable device from a
4293 - * @mc_dev: pointer to allocatable fsl-mc device
4295 - * It permanently removes an allocatable fsl-mc device from the resource
4296 - * pool. It's an error if the device is in use.
4298 -static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
4301 - struct fsl_mc_device *mc_bus_dev;
4302 - struct fsl_mc_bus *mc_bus;
4303 - struct fsl_mc_resource_pool *res_pool;
4304 - struct fsl_mc_resource *resource;
4305 - int error = -EINVAL;
4307 - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
4310 - resource = mc_dev->resource;
4311 - if (WARN_ON(!resource || resource->data != mc_dev))
4314 - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
4315 - mc_bus = to_fsl_mc_bus(mc_bus_dev);
4316 - res_pool = resource->parent_pool;
4317 - if (WARN_ON(res_pool != &mc_bus->resource_pools[resource->type]))
4320 - mutex_lock(&res_pool->mutex);
4322 - if (WARN_ON(res_pool->max_count <= 0))
4324 - if (WARN_ON(res_pool->free_count <= 0 ||
4325 - res_pool->free_count > res_pool->max_count))
4329 - * If the device is currently allocated, its resource is not
4330 - * in the free list and thus, the device cannot be removed.
4332 - if (list_empty(&resource->node)) {
4334 - dev_err(&mc_bus_dev->dev,
4335 - "Device %s cannot be removed from resource pool\n",
4336 - dev_name(&mc_dev->dev));
4340 - list_del_init(&resource->node);
4341 - res_pool->free_count--;
4342 - res_pool->max_count--;
4344 - devm_kfree(&mc_bus_dev->dev, resource);
4345 - mc_dev->resource = NULL;
4348 - mutex_unlock(&res_pool->mutex);
4353 -static const char *const fsl_mc_pool_type_strings[] = {
4354 - [FSL_MC_POOL_DPMCP] = "dpmcp",
4355 - [FSL_MC_POOL_DPBP] = "dpbp",
4356 - [FSL_MC_POOL_DPCON] = "dpcon",
4357 - [FSL_MC_POOL_IRQ] = "irq",
4360 -static int __must_check object_type_to_pool_type(const char *object_type,
4361 - enum fsl_mc_pool_type
4366 - for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) {
4367 - if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) {
4376 -int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
4377 - enum fsl_mc_pool_type pool_type,
4378 - struct fsl_mc_resource **new_resource)
4380 - struct fsl_mc_resource_pool *res_pool;
4381 - struct fsl_mc_resource *resource;
4382 - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
4383 - int error = -EINVAL;
4385 - BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) !=
4386 - FSL_MC_NUM_POOL_TYPES);
4388 - *new_resource = NULL;
4389 - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
4392 - res_pool = &mc_bus->resource_pools[pool_type];
4393 - if (WARN_ON(res_pool->mc_bus != mc_bus))
4396 - mutex_lock(&res_pool->mutex);
4397 - resource = list_first_entry_or_null(&res_pool->free_list,
4398 - struct fsl_mc_resource, node);
4401 - WARN_ON(res_pool->free_count != 0);
4403 - dev_err(&mc_bus_dev->dev,
4404 - "No more resources of type %s left\n",
4405 - fsl_mc_pool_type_strings[pool_type]);
4409 - if (WARN_ON(resource->type != pool_type))
4411 - if (WARN_ON(resource->parent_pool != res_pool))
4413 - if (WARN_ON(res_pool->free_count <= 0 ||
4414 - res_pool->free_count > res_pool->max_count))
4417 - list_del_init(&resource->node);
4419 - res_pool->free_count--;
4422 - mutex_unlock(&res_pool->mutex);
4423 - *new_resource = resource;
4427 -EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate);
4429 -void fsl_mc_resource_free(struct fsl_mc_resource *resource)
4431 - struct fsl_mc_resource_pool *res_pool;
4433 - res_pool = resource->parent_pool;
4434 - if (WARN_ON(resource->type != res_pool->type))
4437 - mutex_lock(&res_pool->mutex);
4438 - if (WARN_ON(res_pool->free_count < 0 ||
4439 - res_pool->free_count >= res_pool->max_count))
4442 - if (WARN_ON(!list_empty(&resource->node)))
4445 - list_add_tail(&resource->node, &res_pool->free_list);
4446 - res_pool->free_count++;
4448 - mutex_unlock(&res_pool->mutex);
4450 -EXPORT_SYMBOL_GPL(fsl_mc_resource_free);
4453 - * fsl_mc_object_allocate - Allocates an fsl-mc object of the given
4454 - * pool type from a given fsl-mc bus instance
4456 - * @mc_dev: fsl-mc device which is used in conjunction with the
4457 - * allocated object
4458 - * @pool_type: pool type
4459 - * @new_mc_dev: pointer to area where the pointer to the allocated device
4460 - * is to be returned
4462 - * Allocatable objects are always used in conjunction with some functional
4463 - * device. This function allocates an object of the specified type from
4464 - * the DPRC containing the functional device.
4466 - * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC
4467 - * portals are allocated using fsl_mc_portal_allocate(), instead of
4470 -int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
4471 - enum fsl_mc_pool_type pool_type,
4472 - struct fsl_mc_device **new_mc_adev)
4474 - struct fsl_mc_device *mc_bus_dev;
4475 - struct fsl_mc_bus *mc_bus;
4476 - struct fsl_mc_device *mc_adev;
4477 - int error = -EINVAL;
4478 - struct fsl_mc_resource *resource = NULL;
4480 - *new_mc_adev = NULL;
4481 - if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC))
4484 - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent)))
4487 - if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP))
4490 - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
4491 - mc_bus = to_fsl_mc_bus(mc_bus_dev);
4492 - error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource);
4496 - mc_adev = resource->data;
4497 - if (WARN_ON(!mc_adev))
4500 - *new_mc_adev = mc_adev;
4504 - fsl_mc_resource_free(resource);
4508 -EXPORT_SYMBOL_GPL(fsl_mc_object_allocate);
4511 - * fsl_mc_object_free - Returns an fsl-mc object to the resource
4512 - * pool where it came from.
4513 - * @mc_adev: Pointer to the fsl-mc device
4515 -void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
4517 - struct fsl_mc_resource *resource;
4519 - resource = mc_adev->resource;
4520 - if (WARN_ON(resource->type == FSL_MC_POOL_DPMCP))
4522 - if (WARN_ON(resource->data != mc_adev))
4525 - fsl_mc_resource_free(resource);
4527 -EXPORT_SYMBOL_GPL(fsl_mc_object_free);
4530 - * A DPRC and the devices in the DPRC all share the same GIC-ITS device
4531 - * ID. A block of IRQs is pre-allocated and maintained in a pool
4532 - * from which devices can allocate them when needed.
4536 - * Initialize the interrupt pool associated with an fsl-mc bus.
4537 - * It allocates a block of IRQs from the GIC-ITS.
4539 -int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
4540 - unsigned int irq_count)
4543 - struct msi_desc *msi_desc;
4544 - struct fsl_mc_device_irq *irq_resources;
4545 - struct fsl_mc_device_irq *mc_dev_irq;
4547 - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
4548 - struct fsl_mc_resource_pool *res_pool =
4549 - &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
4551 - if (WARN_ON(irq_count == 0 ||
4552 - irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS))
4555 - error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
4559 - irq_resources = devm_kzalloc(&mc_bus_dev->dev,
4560 - sizeof(*irq_resources) * irq_count,
4562 - if (!irq_resources) {
4564 - goto cleanup_msi_irqs;
4567 - for (i = 0; i < irq_count; i++) {
4568 - mc_dev_irq = &irq_resources[i];
4571 - * NOTE: This mc_dev_irq's MSI addr/value pair will be set
4572 - * by the fsl_mc_msi_write_msg() callback
4574 - mc_dev_irq->resource.type = res_pool->type;
4575 - mc_dev_irq->resource.data = mc_dev_irq;
4576 - mc_dev_irq->resource.parent_pool = res_pool;
4577 - INIT_LIST_HEAD(&mc_dev_irq->resource.node);
4578 - list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
4581 - for_each_msi_entry(msi_desc, &mc_bus_dev->dev) {
4582 - mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index];
4583 - mc_dev_irq->msi_desc = msi_desc;
4584 - mc_dev_irq->resource.id = msi_desc->irq;
4587 - res_pool->max_count = irq_count;
4588 - res_pool->free_count = irq_count;
4589 - mc_bus->irq_resources = irq_resources;
4593 - fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
4596 -EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
4599 - * Teardown the interrupt pool associated with an fsl-mc bus.
4600 - * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
4602 -void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
4604 - struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
4605 - struct fsl_mc_resource_pool *res_pool =
4606 - &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
4608 - if (WARN_ON(!mc_bus->irq_resources))
4611 - if (WARN_ON(res_pool->max_count == 0))
4614 - if (WARN_ON(res_pool->free_count != res_pool->max_count))
4617 - INIT_LIST_HEAD(&res_pool->free_list);
4618 - res_pool->max_count = 0;
4619 - res_pool->free_count = 0;
4620 - mc_bus->irq_resources = NULL;
4621 - fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
4623 -EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
4626 - * Allocate the IRQs required by a given fsl-mc device.
4628 -int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
4632 - int res_allocated_count = 0;
4633 - int error = -EINVAL;
4634 - struct fsl_mc_device_irq **irqs = NULL;
4635 - struct fsl_mc_bus *mc_bus;
4636 - struct fsl_mc_resource_pool *res_pool;
4638 - if (WARN_ON(mc_dev->irqs))
4641 - irq_count = mc_dev->obj_desc.irq_count;
4642 - if (WARN_ON(irq_count == 0))
4645 - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
4646 - mc_bus = to_fsl_mc_bus(mc_dev);
4648 - mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
4650 - if (WARN_ON(!mc_bus->irq_resources))
4653 - res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
4654 - if (res_pool->free_count < irq_count) {
4655 - dev_err(&mc_dev->dev,
4656 - "Not able to allocate %u irqs for device\n", irq_count);
4660 - irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]),
4665 - for (i = 0; i < irq_count; i++) {
4666 - struct fsl_mc_resource *resource;
4668 - error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
4671 - goto error_resource_alloc;
4673 - irqs[i] = to_fsl_mc_irq(resource);
4674 - res_allocated_count++;
4676 - WARN_ON(irqs[i]->mc_dev);
4677 - irqs[i]->mc_dev = mc_dev;
4678 - irqs[i]->dev_irq_index = i;
4681 - mc_dev->irqs = irqs;
4684 -error_resource_alloc:
4685 - for (i = 0; i < res_allocated_count; i++) {
4686 - irqs[i]->mc_dev = NULL;
4687 - fsl_mc_resource_free(&irqs[i]->resource);
4692 -EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
4695 - * Frees the IRQs that were allocated for an fsl-mc device.
4697 -void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
4701 - struct fsl_mc_bus *mc_bus;
4702 - struct fsl_mc_device_irq **irqs = mc_dev->irqs;
4704 - if (WARN_ON(!irqs))
4707 - irq_count = mc_dev->obj_desc.irq_count;
4709 - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
4710 - mc_bus = to_fsl_mc_bus(mc_dev);
4712 - mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
4714 - if (WARN_ON(!mc_bus->irq_resources))
4717 - for (i = 0; i < irq_count; i++) {
4718 - WARN_ON(!irqs[i]->mc_dev);
4719 - irqs[i]->mc_dev = NULL;
4720 - fsl_mc_resource_free(&irqs[i]->resource);
4723 - mc_dev->irqs = NULL;
4725 -EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
4727 -void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
4730 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
4732 - for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) {
4733 - struct fsl_mc_resource_pool *res_pool =
4734 - &mc_bus->resource_pools[pool_type];
4736 - res_pool->type = pool_type;
4737 - res_pool->max_count = 0;
4738 - res_pool->free_count = 0;
4739 - res_pool->mc_bus = mc_bus;
4740 - INIT_LIST_HEAD(&res_pool->free_list);
4741 - mutex_init(&res_pool->mutex);
4745 -static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
4746 - enum fsl_mc_pool_type pool_type)
4748 - struct fsl_mc_resource *resource;
4749 - struct fsl_mc_resource *next;
4750 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
4751 - struct fsl_mc_resource_pool *res_pool =
4752 - &mc_bus->resource_pools[pool_type];
4753 - int free_count = 0;
4755 - WARN_ON(res_pool->type != pool_type);
4756 - WARN_ON(res_pool->free_count != res_pool->max_count);
4758 - list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
4760 - WARN_ON(resource->type != res_pool->type);
4761 - WARN_ON(resource->parent_pool != res_pool);
4762 - devm_kfree(&mc_bus_dev->dev, resource);
4765 - WARN_ON(free_count != res_pool->free_count);
4768 -void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
4772 - for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++)
4773 - fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type);
4777 - * fsl_mc_allocator_probe - callback invoked when an allocatable device is
4778 - * being added to the system
4780 -static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
4782 - enum fsl_mc_pool_type pool_type;
4783 - struct fsl_mc_device *mc_bus_dev;
4784 - struct fsl_mc_bus *mc_bus;
4787 - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
4790 - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
4791 - if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev)))
4794 - mc_bus = to_fsl_mc_bus(mc_bus_dev);
4795 - error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type);
4799 - error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev);
4803 - dev_dbg(&mc_dev->dev,
4804 - "Allocatable fsl-mc device bound to fsl_mc_allocator driver");
4809 - * fsl_mc_allocator_remove - callback invoked when an allocatable device is
4810 - * being removed from the system
4812 -static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
4816 - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
4819 - if (mc_dev->resource) {
4820 - error = fsl_mc_resource_pool_remove_device(mc_dev);
4825 - dev_dbg(&mc_dev->dev,
4826 - "Allocatable fsl-mc device unbound from fsl_mc_allocator driver");
4830 -static const struct fsl_mc_device_id match_id_table[] = {
4832 - .vendor = FSL_MC_VENDOR_FREESCALE,
4833 - .obj_type = "dpbp",
4836 - .vendor = FSL_MC_VENDOR_FREESCALE,
4837 - .obj_type = "dpmcp",
4840 - .vendor = FSL_MC_VENDOR_FREESCALE,
4841 - .obj_type = "dpcon",
4846 -static struct fsl_mc_driver fsl_mc_allocator_driver = {
4848 - .name = "fsl_mc_allocator",
4851 - .match_id_table = match_id_table,
4852 - .probe = fsl_mc_allocator_probe,
4853 - .remove = fsl_mc_allocator_remove,
4856 -int __init fsl_mc_allocator_driver_init(void)
4858 - return fsl_mc_driver_register(&fsl_mc_allocator_driver);
4861 -void fsl_mc_allocator_driver_exit(void)
4863 - fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
4866 +++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
4868 +// SPDX-License-Identifier: GPL-2.0
4870 + * fsl-mc object allocator driver
4872 + * Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
4876 +#include <linux/module.h>
4877 +#include <linux/msi.h>
4878 +#include <linux/fsl/mc.h>
4880 +#include "fsl-mc-private.h"
4882 +static bool __must_check fsl_mc_is_allocatable(struct fsl_mc_device *mc_dev)
4884 + return is_fsl_mc_bus_dpbp(mc_dev) ||
4885 + is_fsl_mc_bus_dpmcp(mc_dev) ||
4886 + is_fsl_mc_bus_dpcon(mc_dev);
4890 + * fsl_mc_resource_pool_add_device - add allocatable object to a resource
4891 + * pool of a given fsl-mc bus
4893 + * @mc_bus: pointer to the fsl-mc bus
4894 + * @pool_type: pool type
4895 + * @mc_dev: pointer to allocatable fsl-mc device
4897 +static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
4899 + enum fsl_mc_pool_type
4901 + struct fsl_mc_device
4904 + struct fsl_mc_resource_pool *res_pool;
4905 + struct fsl_mc_resource *resource;
4906 + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
4907 + int error = -EINVAL;
4909 + if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
4911 + if (!fsl_mc_is_allocatable(mc_dev))
4913 + if (mc_dev->resource)
4916 + res_pool = &mc_bus->resource_pools[pool_type];
4917 + if (res_pool->type != pool_type)
4919 + if (res_pool->mc_bus != mc_bus)
4922 + mutex_lock(&res_pool->mutex);
4924 + if (res_pool->max_count < 0)
4926 + if (res_pool->free_count < 0 ||
4927 + res_pool->free_count > res_pool->max_count)
4930 + resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource),
4934 + dev_err(&mc_bus_dev->dev,
4935 + "Failed to allocate memory for fsl_mc_resource\n");
4939 + resource->type = pool_type;
4940 + resource->id = mc_dev->obj_desc.id;
4941 + resource->data = mc_dev;
4942 + resource->parent_pool = res_pool;
4943 + INIT_LIST_HEAD(&resource->node);
4944 + list_add_tail(&resource->node, &res_pool->free_list);
4945 + mc_dev->resource = resource;
4946 + res_pool->free_count++;
4947 + res_pool->max_count++;
4950 + mutex_unlock(&res_pool->mutex);
4956 + * fsl_mc_resource_pool_remove_device - remove an allocatable device from a
4959 + * @mc_dev: pointer to allocatable fsl-mc device
4961 + * It permanently removes an allocatable fsl-mc device from the resource
4962 + * pool. It's an error if the device is in use.
4964 +static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
4967 + struct fsl_mc_device *mc_bus_dev;
4968 + struct fsl_mc_bus *mc_bus;
4969 + struct fsl_mc_resource_pool *res_pool;
4970 + struct fsl_mc_resource *resource;
4971 + int error = -EINVAL;
4973 + if (!fsl_mc_is_allocatable(mc_dev))
4976 + resource = mc_dev->resource;
4977 + if (!resource || resource->data != mc_dev)
4980 + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
4981 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
4982 + res_pool = resource->parent_pool;
4983 + if (res_pool != &mc_bus->resource_pools[resource->type])
4986 + mutex_lock(&res_pool->mutex);
4988 + if (res_pool->max_count <= 0)
4990 + if (res_pool->free_count <= 0 ||
4991 + res_pool->free_count > res_pool->max_count)
4995 + * If the device is currently allocated, its resource is not
4996 + * in the free list and thus, the device cannot be removed.
4998 + if (list_empty(&resource->node)) {
5000 + dev_err(&mc_bus_dev->dev,
5001 + "Device %s cannot be removed from resource pool\n",
5002 + dev_name(&mc_dev->dev));
5006 + list_del_init(&resource->node);
5007 + res_pool->free_count--;
5008 + res_pool->max_count--;
5010 + devm_kfree(&mc_bus_dev->dev, resource);
5011 + mc_dev->resource = NULL;
5014 + mutex_unlock(&res_pool->mutex);
5019 +static const char *const fsl_mc_pool_type_strings[] = {
5020 + [FSL_MC_POOL_DPMCP] = "dpmcp",
5021 + [FSL_MC_POOL_DPBP] = "dpbp",
5022 + [FSL_MC_POOL_DPCON] = "dpcon",
5023 + [FSL_MC_POOL_IRQ] = "irq",
5026 +static int __must_check object_type_to_pool_type(const char *object_type,
5027 + enum fsl_mc_pool_type
5032 + for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) {
5033 + if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) {
5042 +int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
5043 + enum fsl_mc_pool_type pool_type,
5044 + struct fsl_mc_resource **new_resource)
5046 + struct fsl_mc_resource_pool *res_pool;
5047 + struct fsl_mc_resource *resource;
5048 + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
5049 + int error = -EINVAL;
5051 + BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) !=
5052 + FSL_MC_NUM_POOL_TYPES);
5054 + *new_resource = NULL;
5055 + if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
5058 + res_pool = &mc_bus->resource_pools[pool_type];
5059 + if (res_pool->mc_bus != mc_bus)
5062 + mutex_lock(&res_pool->mutex);
5063 + resource = list_first_entry_or_null(&res_pool->free_list,
5064 + struct fsl_mc_resource, node);
5068 + dev_err(&mc_bus_dev->dev,
5069 + "No more resources of type %s left\n",
5070 + fsl_mc_pool_type_strings[pool_type]);
5074 + if (resource->type != pool_type)
5076 + if (resource->parent_pool != res_pool)
5078 + if (res_pool->free_count <= 0 ||
5079 + res_pool->free_count > res_pool->max_count)
5082 + list_del_init(&resource->node);
5084 + res_pool->free_count--;
5087 + mutex_unlock(&res_pool->mutex);
5088 + *new_resource = resource;
5092 +EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate);
5094 +void fsl_mc_resource_free(struct fsl_mc_resource *resource)
5096 + struct fsl_mc_resource_pool *res_pool;
5098 + res_pool = resource->parent_pool;
5099 + if (resource->type != res_pool->type)
5102 + mutex_lock(&res_pool->mutex);
5103 + if (res_pool->free_count < 0 ||
5104 + res_pool->free_count >= res_pool->max_count)
5107 + if (!list_empty(&resource->node))
5110 + list_add_tail(&resource->node, &res_pool->free_list);
5111 + res_pool->free_count++;
5113 + mutex_unlock(&res_pool->mutex);
5115 +EXPORT_SYMBOL_GPL(fsl_mc_resource_free);
5118 + * fsl_mc_object_allocate - Allocates an fsl-mc object of the given
5119 + * pool type from a given fsl-mc bus instance
5121 + * @mc_dev: fsl-mc device which is used in conjunction with the
5122 + * allocated object
5123 + * @pool_type: pool type
5124 + * @new_mc_dev: pointer to area where the pointer to the allocated device
5125 + * is to be returned
5127 + * Allocatable objects are always used in conjunction with some functional
5128 + * device. This function allocates an object of the specified type from
5129 + * the DPRC containing the functional device.
5131 + * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC
5132 + * portals are allocated using fsl_mc_portal_allocate(), instead of
5135 +int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
5136 + enum fsl_mc_pool_type pool_type,
5137 + struct fsl_mc_device **new_mc_adev)
5139 + struct fsl_mc_device *mc_bus_dev;
5140 + struct fsl_mc_bus *mc_bus;
5141 + struct fsl_mc_device *mc_adev;
5142 + int error = -EINVAL;
5143 + struct fsl_mc_resource *resource = NULL;
5145 + *new_mc_adev = NULL;
5146 + if (mc_dev->flags & FSL_MC_IS_DPRC)
5149 + if (!dev_is_fsl_mc(mc_dev->dev.parent))
5152 + if (pool_type == FSL_MC_POOL_DPMCP)
5155 + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
5156 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
5157 + error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource);
5161 + mc_adev = resource->data;
5165 + mc_adev->consumer_link = device_link_add(&mc_dev->dev,
5167 + DL_FLAG_AUTOREMOVE_CONSUMER);
5168 + if (!mc_adev->consumer_link) {
5173 + *new_mc_adev = mc_adev;
5177 + fsl_mc_resource_free(resource);
5181 +EXPORT_SYMBOL_GPL(fsl_mc_object_allocate);
5184 + * fsl_mc_object_free - Returns an fsl-mc object to the resource
5185 + * pool where it came from.
5186 + * @mc_adev: Pointer to the fsl-mc device
5188 +void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
5190 + struct fsl_mc_resource *resource;
5192 + resource = mc_adev->resource;
5193 + if (resource->type == FSL_MC_POOL_DPMCP)
5195 + if (resource->data != mc_adev)
5198 + fsl_mc_resource_free(resource);
5200 + device_link_del(mc_adev->consumer_link);
5201 + mc_adev->consumer_link = NULL;
5203 +EXPORT_SYMBOL_GPL(fsl_mc_object_free);
5206 + * A DPRC and the devices in the DPRC all share the same GIC-ITS device
5207 + * ID. A block of IRQs is pre-allocated and maintained in a pool
5208 + * from which devices can allocate them when needed.
5212 + * Initialize the interrupt pool associated with an fsl-mc bus.
5213 + * It allocates a block of IRQs from the GIC-ITS.
5215 +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
5216 + unsigned int irq_count)
5219 + struct msi_desc *msi_desc;
5220 + struct fsl_mc_device_irq *irq_resources;
5221 + struct fsl_mc_device_irq *mc_dev_irq;
5223 + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
5224 + struct fsl_mc_resource_pool *res_pool =
5225 + &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
5227 + if (irq_count == 0 ||
5228 + irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)
5231 + error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
5235 + irq_resources = devm_kzalloc(&mc_bus_dev->dev,
5236 + sizeof(*irq_resources) * irq_count,
5238 + if (!irq_resources) {
5240 + goto cleanup_msi_irqs;
5243 + for (i = 0; i < irq_count; i++) {
5244 + mc_dev_irq = &irq_resources[i];
5247 + * NOTE: This mc_dev_irq's MSI addr/value pair will be set
5248 + * by the fsl_mc_msi_write_msg() callback
5250 + mc_dev_irq->resource.type = res_pool->type;
5251 + mc_dev_irq->resource.data = mc_dev_irq;
5252 + mc_dev_irq->resource.parent_pool = res_pool;
5253 + INIT_LIST_HEAD(&mc_dev_irq->resource.node);
5254 + list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
5257 + for_each_msi_entry(msi_desc, &mc_bus_dev->dev) {
5258 + mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index];
5259 + mc_dev_irq->msi_desc = msi_desc;
5260 + mc_dev_irq->resource.id = msi_desc->irq;
5263 + res_pool->max_count = irq_count;
5264 + res_pool->free_count = irq_count;
5265 + mc_bus->irq_resources = irq_resources;
5269 + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
5272 +EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
5275 + * Teardown the interrupt pool associated with an fsl-mc bus.
5276 + * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
5278 +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
5280 + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
5281 + struct fsl_mc_resource_pool *res_pool =
5282 + &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
5284 + if (!mc_bus->irq_resources)
5287 + if (res_pool->max_count == 0)
5290 + if (res_pool->free_count != res_pool->max_count)
5293 + INIT_LIST_HEAD(&res_pool->free_list);
5294 + res_pool->max_count = 0;
5295 + res_pool->free_count = 0;
5296 + mc_bus->irq_resources = NULL;
5297 + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
5299 +EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
5302 + * Allocate the IRQs required by a given fsl-mc device.
5304 +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
5308 + int res_allocated_count = 0;
5309 + int error = -EINVAL;
5310 + struct fsl_mc_device_irq **irqs = NULL;
5311 + struct fsl_mc_bus *mc_bus;
5312 + struct fsl_mc_resource_pool *res_pool;
5317 + irq_count = mc_dev->obj_desc.irq_count;
5318 + if (irq_count == 0)
5321 + if (is_fsl_mc_bus_dprc(mc_dev))
5322 + mc_bus = to_fsl_mc_bus(mc_dev);
5324 + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
5326 + if (!mc_bus->irq_resources)
5329 + res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
5330 + if (res_pool->free_count < irq_count) {
5331 + dev_err(&mc_dev->dev,
5332 + "Not able to allocate %u irqs for device\n", irq_count);
5336 + irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]),
5341 + for (i = 0; i < irq_count; i++) {
5342 + struct fsl_mc_resource *resource;
5344 + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
5347 + goto error_resource_alloc;
5349 + irqs[i] = to_fsl_mc_irq(resource);
5350 + res_allocated_count++;
5352 + irqs[i]->mc_dev = mc_dev;
5353 + irqs[i]->dev_irq_index = i;
5356 + mc_dev->irqs = irqs;
5359 +error_resource_alloc:
5360 + for (i = 0; i < res_allocated_count; i++) {
5361 + irqs[i]->mc_dev = NULL;
5362 + fsl_mc_resource_free(&irqs[i]->resource);
5367 +EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
5370 + * Frees the IRQs that were allocated for an fsl-mc device.
5372 +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
5376 + struct fsl_mc_bus *mc_bus;
5377 + struct fsl_mc_device_irq **irqs = mc_dev->irqs;
5382 + irq_count = mc_dev->obj_desc.irq_count;
5384 + if (is_fsl_mc_bus_dprc(mc_dev))
5385 + mc_bus = to_fsl_mc_bus(mc_dev);
5387 + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
5389 + if (!mc_bus->irq_resources)
5392 + for (i = 0; i < irq_count; i++) {
5393 + irqs[i]->mc_dev = NULL;
5394 + fsl_mc_resource_free(&irqs[i]->resource);
5397 + mc_dev->irqs = NULL;
5399 +EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
5401 +void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
5404 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
5406 + for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) {
5407 + struct fsl_mc_resource_pool *res_pool =
5408 + &mc_bus->resource_pools[pool_type];
5410 + res_pool->type = pool_type;
5411 + res_pool->max_count = 0;
5412 + res_pool->free_count = 0;
5413 + res_pool->mc_bus = mc_bus;
5414 + INIT_LIST_HEAD(&res_pool->free_list);
5415 + mutex_init(&res_pool->mutex);
5418 +EXPORT_SYMBOL_GPL(fsl_mc_init_all_resource_pools);
5420 +static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
5421 + enum fsl_mc_pool_type pool_type)
5423 + struct fsl_mc_resource *resource;
5424 + struct fsl_mc_resource *next;
5425 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
5426 + struct fsl_mc_resource_pool *res_pool =
5427 + &mc_bus->resource_pools[pool_type];
5428 + int free_count = 0;
5430 + list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
5432 + devm_kfree(&mc_bus_dev->dev, resource);
5436 +void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
5440 + for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++)
5441 + fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type);
5443 +EXPORT_SYMBOL_GPL(fsl_mc_cleanup_all_resource_pools);
5446 + * fsl_mc_allocator_probe - callback invoked when an allocatable device is
5447 + * being added to the system
5449 +static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
5451 + enum fsl_mc_pool_type pool_type;
5452 + struct fsl_mc_device *mc_bus_dev;
5453 + struct fsl_mc_bus *mc_bus;
5456 + if (!fsl_mc_is_allocatable(mc_dev))
5459 + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
5460 + if (!dev_is_fsl_mc(&mc_bus_dev->dev))
5463 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
5464 + error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type);
5468 + error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev);
5472 + dev_dbg(&mc_dev->dev,
5473 + "Allocatable fsl-mc device bound to fsl_mc_allocator driver");
5478 + * fsl_mc_allocator_remove - callback invoked when an allocatable device is
5479 + * being removed from the system
5481 +static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
5485 + if (!fsl_mc_is_allocatable(mc_dev))
5488 + if (mc_dev->resource) {
5489 + error = fsl_mc_resource_pool_remove_device(mc_dev);
5494 + dev_dbg(&mc_dev->dev,
5495 + "Allocatable fsl-mc device unbound from fsl_mc_allocator driver");
5499 +static const struct fsl_mc_device_id match_id_table[] = {
5501 + .vendor = FSL_MC_VENDOR_FREESCALE,
5502 + .obj_type = "dpbp",
5505 + .vendor = FSL_MC_VENDOR_FREESCALE,
5506 + .obj_type = "dpmcp",
5509 + .vendor = FSL_MC_VENDOR_FREESCALE,
5510 + .obj_type = "dpcon",
5515 +static struct fsl_mc_driver fsl_mc_allocator_driver = {
5517 + .name = "fsl_mc_allocator",
5520 + .match_id_table = match_id_table,
5521 + .probe = fsl_mc_allocator_probe,
5522 + .remove = fsl_mc_allocator_remove,
5525 +int __init fsl_mc_allocator_driver_init(void)
5527 + return fsl_mc_driver_register(&fsl_mc_allocator_driver);
5530 +void fsl_mc_allocator_driver_exit(void)
5532 + fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
5534 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c
5537 -// SPDX-License-Identifier: GPL-2.0
5539 - * Freescale Management Complex (MC) bus driver
5541 - * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
5542 - * Author: German Rivera <German.Rivera@freescale.com>
5546 -#define pr_fmt(fmt) "fsl-mc: " fmt
5548 -#include <linux/module.h>
5549 -#include <linux/of_device.h>
5550 -#include <linux/of_address.h>
5551 -#include <linux/ioport.h>
5552 -#include <linux/slab.h>
5553 -#include <linux/limits.h>
5554 -#include <linux/bitops.h>
5555 -#include <linux/msi.h>
5556 -#include <linux/dma-mapping.h>
5558 -#include "fsl-mc-private.h"
5559 -#include "dprc-cmd.h"
5560 -#include "dpmng-cmd.h"
5563 - * Default DMA mask for devices on a fsl-mc bus
5565 -#define FSL_MC_DEFAULT_DMA_MASK (~0ULL)
5568 - * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device
5569 - * @root_mc_bus_dev: fsl-mc device representing the root DPRC
5570 - * @num_translation_ranges: number of entries in addr_translation_ranges
5571 - * @translation_ranges: array of bus to system address translation ranges
5574 - struct fsl_mc_device *root_mc_bus_dev;
5575 - u8 num_translation_ranges;
5576 - struct fsl_mc_addr_translation_range *translation_ranges;
5580 - * struct fsl_mc_addr_translation_range - bus to system address translation
5582 - * @mc_region_type: Type of MC region for the range being translated
5583 - * @start_mc_offset: Start MC offset of the range being translated
5584 - * @end_mc_offset: MC offset of the first byte after the range (last MC
5585 - * offset of the range is end_mc_offset - 1)
5586 - * @start_phys_addr: system physical address corresponding to start_mc_addr
5588 -struct fsl_mc_addr_translation_range {
5589 - enum dprc_region_type mc_region_type;
5590 - u64 start_mc_offset;
5591 - u64 end_mc_offset;
5592 - phys_addr_t start_phys_addr;
5596 - * struct mc_version
5597 - * @major: Major version number: incremented on API compatibility changes
5598 - * @minor: Minor version number: incremented on API additions (that are
5599 - * backward compatible); reset when major version is incremented
5600 - * @revision: Internal revision number: incremented on implementation changes
5601 - * and/or bug fixes that have no impact on API
5603 -struct mc_version {
5610 - * fsl_mc_bus_match - device to driver matching callback
5611 - * @dev: the fsl-mc device to match against
5612 - * @drv: the device driver to search for matching fsl-mc object type
5615 - * Returns 1 on success, 0 otherwise.
5617 -static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
5619 - const struct fsl_mc_device_id *id;
5620 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5621 - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
5622 - bool found = false;
5624 - if (!mc_drv->match_id_table)
5628 - * If the object is not 'plugged' don't match.
5629 - * Only exception is the root DPRC, which is a special case.
5631 - if ((mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED) == 0 &&
5632 - !fsl_mc_is_root_dprc(&mc_dev->dev))
5636 - * Traverse the match_id table of the given driver, trying to find
5637 - * a matching for the given device.
5639 - for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) {
5640 - if (id->vendor == mc_dev->obj_desc.vendor &&
5641 - strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) {
5649 - dev_dbg(dev, "%smatched\n", found ? "" : "not ");
5654 - * fsl_mc_bus_uevent - callback invoked when a device is added
5656 -static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
5658 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5660 - if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s",
5661 - mc_dev->obj_desc.vendor,
5662 - mc_dev->obj_desc.type))
5668 -static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
5671 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5673 - return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor,
5674 - mc_dev->obj_desc.type);
5676 -static DEVICE_ATTR_RO(modalias);
5678 -static struct attribute *fsl_mc_dev_attrs[] = {
5679 - &dev_attr_modalias.attr,
5683 -ATTRIBUTE_GROUPS(fsl_mc_dev);
5685 -struct bus_type fsl_mc_bus_type = {
5687 - .match = fsl_mc_bus_match,
5688 - .uevent = fsl_mc_bus_uevent,
5689 - .dev_groups = fsl_mc_dev_groups,
5691 -EXPORT_SYMBOL_GPL(fsl_mc_bus_type);
5693 -static int fsl_mc_driver_probe(struct device *dev)
5695 - struct fsl_mc_driver *mc_drv;
5696 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5699 - if (WARN_ON(!dev->driver))
5702 - mc_drv = to_fsl_mc_driver(dev->driver);
5703 - if (WARN_ON(!mc_drv->probe))
5706 - error = mc_drv->probe(mc_dev);
5708 - dev_err(dev, "%s failed: %d\n", __func__, error);
5715 -static int fsl_mc_driver_remove(struct device *dev)
5717 - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
5718 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5721 - if (WARN_ON(!dev->driver))
5724 - error = mc_drv->remove(mc_dev);
5726 - dev_err(dev, "%s failed: %d\n", __func__, error);
5733 -static void fsl_mc_driver_shutdown(struct device *dev)
5735 - struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
5736 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5738 - mc_drv->shutdown(mc_dev);
5742 - * __fsl_mc_driver_register - registers a child device driver with the
5745 - * This function is implicitly invoked from the registration function of
5746 - * fsl_mc device drivers, which is generated by the
5747 - * module_fsl_mc_driver() macro.
5749 -int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver,
5750 - struct module *owner)
5754 - mc_driver->driver.owner = owner;
5755 - mc_driver->driver.bus = &fsl_mc_bus_type;
5757 - if (mc_driver->probe)
5758 - mc_driver->driver.probe = fsl_mc_driver_probe;
5760 - if (mc_driver->remove)
5761 - mc_driver->driver.remove = fsl_mc_driver_remove;
5763 - if (mc_driver->shutdown)
5764 - mc_driver->driver.shutdown = fsl_mc_driver_shutdown;
5766 - error = driver_register(&mc_driver->driver);
5768 - pr_err("driver_register() failed for %s: %d\n",
5769 - mc_driver->driver.name, error);
5775 -EXPORT_SYMBOL_GPL(__fsl_mc_driver_register);
5778 - * fsl_mc_driver_unregister - unregisters a device driver from the
5781 -void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver)
5783 - driver_unregister(&mc_driver->driver);
5785 -EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister);
5788 - * mc_get_version() - Retrieves the Management Complex firmware
5789 - * version information
5790 - * @mc_io: Pointer to opaque I/O object
5791 - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
5792 - * @mc_ver_info: Returned version information structure
5794 - * Return: '0' on Success; Error code otherwise.
5796 -static int mc_get_version(struct fsl_mc_io *mc_io,
5798 - struct mc_version *mc_ver_info)
5800 - struct mc_command cmd = { 0 };
5801 - struct dpmng_rsp_get_version *rsp_params;
5804 - /* prepare command */
5805 - cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION,
5809 - /* send command to mc*/
5810 - err = mc_send_command(mc_io, &cmd);
5814 - /* retrieve response parameters */
5815 - rsp_params = (struct dpmng_rsp_get_version *)cmd.params;
5816 - mc_ver_info->revision = le32_to_cpu(rsp_params->revision);
5817 - mc_ver_info->major = le32_to_cpu(rsp_params->version_major);
5818 - mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor);
5824 - * fsl_mc_get_root_dprc - function to traverse to the root dprc
5826 -static void fsl_mc_get_root_dprc(struct device *dev,
5827 - struct device **root_dprc_dev)
5829 - if (WARN_ON(!dev)) {
5830 - *root_dprc_dev = NULL;
5831 - } else if (WARN_ON(!dev_is_fsl_mc(dev))) {
5832 - *root_dprc_dev = NULL;
5834 - *root_dprc_dev = dev;
5835 - while (dev_is_fsl_mc((*root_dprc_dev)->parent))
5836 - *root_dprc_dev = (*root_dprc_dev)->parent;
5840 -static int get_dprc_attr(struct fsl_mc_io *mc_io,
5841 - int container_id, struct dprc_attributes *attr)
5846 - error = dprc_open(mc_io, 0, container_id, &dprc_handle);
5848 - dev_err(mc_io->dev, "dprc_open() failed: %d\n", error);
5852 - memset(attr, 0, sizeof(struct dprc_attributes));
5853 - error = dprc_get_attributes(mc_io, 0, dprc_handle, attr);
5855 - dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n",
5857 - goto common_cleanup;
5863 - (void)dprc_close(mc_io, 0, dprc_handle);
5867 -static int get_dprc_icid(struct fsl_mc_io *mc_io,
5868 - int container_id, u16 *icid)
5870 - struct dprc_attributes attr;
5873 - error = get_dprc_attr(mc_io, container_id, &attr);
5875 - *icid = attr.icid;
5880 -static int translate_mc_addr(struct fsl_mc_device *mc_dev,
5881 - enum dprc_region_type mc_region_type,
5882 - u64 mc_offset, phys_addr_t *phys_addr)
5885 - struct device *root_dprc_dev;
5886 - struct fsl_mc *mc;
5888 - fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev);
5889 - if (WARN_ON(!root_dprc_dev))
5891 - mc = dev_get_drvdata(root_dprc_dev->parent);
5893 - if (mc->num_translation_ranges == 0) {
5895 - * Do identity mapping:
5897 - *phys_addr = mc_offset;
5901 - for (i = 0; i < mc->num_translation_ranges; i++) {
5902 - struct fsl_mc_addr_translation_range *range =
5903 - &mc->translation_ranges[i];
5905 - if (mc_region_type == range->mc_region_type &&
5906 - mc_offset >= range->start_mc_offset &&
5907 - mc_offset < range->end_mc_offset) {
5908 - *phys_addr = range->start_phys_addr +
5909 - (mc_offset - range->start_mc_offset);
5917 -static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
5918 - struct fsl_mc_device *mc_bus_dev)
5922 - struct resource *regions;
5923 - struct fsl_mc_obj_desc *obj_desc = &mc_dev->obj_desc;
5924 - struct device *parent_dev = mc_dev->dev.parent;
5925 - enum dprc_region_type mc_region_type;
5927 - if (strcmp(obj_desc->type, "dprc") == 0 ||
5928 - strcmp(obj_desc->type, "dpmcp") == 0) {
5929 - mc_region_type = DPRC_REGION_TYPE_MC_PORTAL;
5930 - } else if (strcmp(obj_desc->type, "dpio") == 0) {
5931 - mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL;
5934 - * This function should not have been called for this MC object
5935 - * type, as this object type is not supposed to have MMIO
5942 - regions = kmalloc_array(obj_desc->region_count,
5943 - sizeof(regions[0]), GFP_KERNEL);
5947 - for (i = 0; i < obj_desc->region_count; i++) {
5948 - struct dprc_region_desc region_desc;
5950 - error = dprc_get_obj_region(mc_bus_dev->mc_io,
5952 - mc_bus_dev->mc_handle,
5954 - obj_desc->id, i, ®ion_desc);
5956 - dev_err(parent_dev,
5957 - "dprc_get_obj_region() failed: %d\n", error);
5958 - goto error_cleanup_regions;
5961 - WARN_ON(region_desc.size == 0);
5962 - error = translate_mc_addr(mc_dev, mc_region_type,
5963 - region_desc.base_offset,
5964 - ®ions[i].start);
5966 - dev_err(parent_dev,
5967 - "Invalid MC offset: %#x (for %s.%d\'s region %d)\n",
5968 - region_desc.base_offset,
5969 - obj_desc->type, obj_desc->id, i);
5970 - goto error_cleanup_regions;
5973 - regions[i].end = regions[i].start + region_desc.size - 1;
5974 - regions[i].name = "fsl-mc object MMIO region";
5975 - regions[i].flags = IORESOURCE_IO;
5976 - if (region_desc.flags & DPRC_REGION_CACHEABLE)
5977 - regions[i].flags |= IORESOURCE_CACHEABLE;
5980 - mc_dev->regions = regions;
5983 -error_cleanup_regions:
5989 - * fsl_mc_is_root_dprc - function to check if a given device is a root dprc
5991 -bool fsl_mc_is_root_dprc(struct device *dev)
5993 - struct device *root_dprc_dev;
5995 - fsl_mc_get_root_dprc(dev, &root_dprc_dev);
5996 - if (!root_dprc_dev)
5998 - return dev == root_dprc_dev;
6001 -static void fsl_mc_device_release(struct device *dev)
6003 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6005 - kfree(mc_dev->regions);
6007 - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
6008 - kfree(to_fsl_mc_bus(mc_dev));
6014 - * Add a newly discovered fsl-mc device to be visible in Linux
6016 -int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
6017 - struct fsl_mc_io *mc_io,
6018 - struct device *parent_dev,
6019 - struct fsl_mc_device **new_mc_dev)
6022 - struct fsl_mc_device *mc_dev = NULL;
6023 - struct fsl_mc_bus *mc_bus = NULL;
6024 - struct fsl_mc_device *parent_mc_dev;
6026 - if (dev_is_fsl_mc(parent_dev))
6027 - parent_mc_dev = to_fsl_mc_device(parent_dev);
6029 - parent_mc_dev = NULL;
6031 - if (strcmp(obj_desc->type, "dprc") == 0) {
6033 - * Allocate an MC bus device object:
6035 - mc_bus = kzalloc(sizeof(*mc_bus), GFP_KERNEL);
6039 - mc_dev = &mc_bus->mc_dev;
6042 - * Allocate a regular fsl_mc_device object:
6044 - mc_dev = kzalloc(sizeof(*mc_dev), GFP_KERNEL);
6049 - mc_dev->obj_desc = *obj_desc;
6050 - mc_dev->mc_io = mc_io;
6051 - device_initialize(&mc_dev->dev);
6052 - mc_dev->dev.parent = parent_dev;
6053 - mc_dev->dev.bus = &fsl_mc_bus_type;
6054 - mc_dev->dev.release = fsl_mc_device_release;
6055 - dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id);
6057 - if (strcmp(obj_desc->type, "dprc") == 0) {
6058 - struct fsl_mc_io *mc_io2;
6060 - mc_dev->flags |= FSL_MC_IS_DPRC;
6063 - * To get the DPRC's ICID, we need to open the DPRC
6064 - * in get_dprc_icid(). For child DPRCs, we do so using the
6065 - * parent DPRC's MC portal instead of the child DPRC's MC
6066 - * portal, in case the child DPRC is already opened with
6067 - * its own portal (e.g., the DPRC used by AIOP).
6069 - * NOTE: There cannot be more than one active open for a
6070 - * given MC object, using the same MC portal.
6072 - if (parent_mc_dev) {
6074 - * device being added is a child DPRC device
6076 - mc_io2 = parent_mc_dev->mc_io;
6079 - * device being added is the root DPRC device
6081 - if (WARN_ON(!mc_io)) {
6083 - goto error_cleanup_dev;
6089 - error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid);
6091 - goto error_cleanup_dev;
6094 - * A non-DPRC object has to be a child of a DPRC, use the
6095 - * parent's ICID and interrupt domain.
6097 - mc_dev->icid = parent_mc_dev->icid;
6098 - mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK;
6099 - mc_dev->dev.dma_mask = &mc_dev->dma_mask;
6100 - dev_set_msi_domain(&mc_dev->dev,
6101 - dev_get_msi_domain(&parent_mc_dev->dev));
6105 - * Get MMIO regions for the device from the MC:
6107 - * NOTE: the root DPRC is a special case as its MMIO region is
6108 - * obtained from the device tree
6110 - if (parent_mc_dev && obj_desc->region_count != 0) {
6111 - error = fsl_mc_device_get_mmio_regions(mc_dev,
6114 - goto error_cleanup_dev;
6117 - /* Objects are coherent, unless 'no shareability' flag set. */
6118 - if (!(obj_desc->flags & FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY))
6119 - arch_setup_dma_ops(&mc_dev->dev, 0, 0, NULL, true);
6122 - * The device-specific probe callback will get invoked by device_add()
6124 - error = device_add(&mc_dev->dev);
6126 - dev_err(parent_dev,
6127 - "device_add() failed for device %s: %d\n",
6128 - dev_name(&mc_dev->dev), error);
6129 - goto error_cleanup_dev;
6132 - dev_dbg(parent_dev, "added %s\n", dev_name(&mc_dev->dev));
6134 - *new_mc_dev = mc_dev;
6138 - kfree(mc_dev->regions);
6144 -EXPORT_SYMBOL_GPL(fsl_mc_device_add);
6147 - * fsl_mc_device_remove - Remove an fsl-mc device from being visible to
6150 - * @mc_dev: Pointer to an fsl-mc device
6152 -void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
6155 - * The device-specific remove callback will get invoked by device_del()
6157 - device_del(&mc_dev->dev);
6158 - put_device(&mc_dev->dev);
6160 -EXPORT_SYMBOL_GPL(fsl_mc_device_remove);
6162 -static int parse_mc_ranges(struct device *dev,
6164 - int *mc_addr_cells,
6165 - int *mc_size_cells,
6166 - const __be32 **ranges_start)
6168 - const __be32 *prop;
6169 - int range_tuple_cell_count;
6172 - struct device_node *mc_node = dev->of_node;
6174 - *ranges_start = of_get_property(mc_node, "ranges", &ranges_len);
6175 - if (!(*ranges_start) || !ranges_len) {
6177 - "missing or empty ranges property for device tree node '%s'\n",
6182 - *paddr_cells = of_n_addr_cells(mc_node);
6184 - prop = of_get_property(mc_node, "#address-cells", NULL);
6186 - *mc_addr_cells = be32_to_cpup(prop);
6188 - *mc_addr_cells = *paddr_cells;
6190 - prop = of_get_property(mc_node, "#size-cells", NULL);
6192 - *mc_size_cells = be32_to_cpup(prop);
6194 - *mc_size_cells = of_n_size_cells(mc_node);
6196 - range_tuple_cell_count = *paddr_cells + *mc_addr_cells +
6199 - tuple_len = range_tuple_cell_count * sizeof(__be32);
6200 - if (ranges_len % tuple_len != 0) {
6201 - dev_err(dev, "malformed ranges property '%s'\n", mc_node->name);
6205 - return ranges_len / tuple_len;
6208 -static int get_mc_addr_translation_ranges(struct device *dev,
6209 - struct fsl_mc_addr_translation_range
6215 - int mc_addr_cells;
6216 - int mc_size_cells;
6218 - const __be32 *ranges_start;
6219 - const __be32 *cell;
6221 - ret = parse_mc_ranges(dev,
6229 - *num_ranges = ret;
6232 - * Missing or empty ranges property ("ranges;") for the
6233 - * 'fsl,qoriq-mc' node. In this case, identity mapping
6240 - *ranges = devm_kcalloc(dev, *num_ranges,
6241 - sizeof(struct fsl_mc_addr_translation_range),
6246 - cell = ranges_start;
6247 - for (i = 0; i < *num_ranges; ++i) {
6248 - struct fsl_mc_addr_translation_range *range = &(*ranges)[i];
6250 - range->mc_region_type = of_read_number(cell, 1);
6251 - range->start_mc_offset = of_read_number(cell + 1,
6252 - mc_addr_cells - 1);
6253 - cell += mc_addr_cells;
6254 - range->start_phys_addr = of_read_number(cell, paddr_cells);
6255 - cell += paddr_cells;
6256 - range->end_mc_offset = range->start_mc_offset +
6257 - of_read_number(cell, mc_size_cells);
6259 - cell += mc_size_cells;
6266 - * fsl_mc_bus_probe - callback invoked when the root MC bus is being
6269 -static int fsl_mc_bus_probe(struct platform_device *pdev)
6271 - struct fsl_mc_obj_desc obj_desc;
6273 - struct fsl_mc *mc;
6274 - struct fsl_mc_device *mc_bus_dev = NULL;
6275 - struct fsl_mc_io *mc_io = NULL;
6277 - phys_addr_t mc_portal_phys_addr;
6278 - u32 mc_portal_size;
6279 - struct mc_version mc_version;
6280 - struct resource res;
6282 - mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
6286 - platform_set_drvdata(pdev, mc);
6289 - * Get physical address of MC portal for the root DPRC:
6291 - error = of_address_to_resource(pdev->dev.of_node, 0, &res);
6293 - dev_err(&pdev->dev,
6294 - "of_address_to_resource() failed for %pOF\n",
6295 - pdev->dev.of_node);
6299 - mc_portal_phys_addr = res.start;
6300 - mc_portal_size = resource_size(&res);
6301 - error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr,
6302 - mc_portal_size, NULL,
6303 - FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io);
6307 - error = mc_get_version(mc_io, 0, &mc_version);
6309 - dev_err(&pdev->dev,
6310 - "mc_get_version() failed with error %d\n", error);
6311 - goto error_cleanup_mc_io;
6314 - dev_info(&pdev->dev, "MC firmware version: %u.%u.%u\n",
6315 - mc_version.major, mc_version.minor, mc_version.revision);
6317 - error = get_mc_addr_translation_ranges(&pdev->dev,
6318 - &mc->translation_ranges,
6319 - &mc->num_translation_ranges);
6321 - goto error_cleanup_mc_io;
6323 - error = dprc_get_container_id(mc_io, 0, &container_id);
6325 - dev_err(&pdev->dev,
6326 - "dprc_get_container_id() failed: %d\n", error);
6327 - goto error_cleanup_mc_io;
6330 - memset(&obj_desc, 0, sizeof(struct fsl_mc_obj_desc));
6331 - error = dprc_get_api_version(mc_io, 0,
6332 - &obj_desc.ver_major,
6333 - &obj_desc.ver_minor);
6335 - goto error_cleanup_mc_io;
6337 - obj_desc.vendor = FSL_MC_VENDOR_FREESCALE;
6338 - strcpy(obj_desc.type, "dprc");
6339 - obj_desc.id = container_id;
6340 - obj_desc.irq_count = 1;
6341 - obj_desc.region_count = 0;
6343 - error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, &mc_bus_dev);
6345 - goto error_cleanup_mc_io;
6347 - mc->root_mc_bus_dev = mc_bus_dev;
6350 -error_cleanup_mc_io:
6351 - fsl_destroy_mc_io(mc_io);
6356 - * fsl_mc_bus_remove - callback invoked when the root MC bus is being
6359 -static int fsl_mc_bus_remove(struct platform_device *pdev)
6361 - struct fsl_mc *mc = platform_get_drvdata(pdev);
6363 - if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev)))
6366 - fsl_mc_device_remove(mc->root_mc_bus_dev);
6368 - fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io);
6369 - mc->root_mc_bus_dev->mc_io = NULL;
6374 -static const struct of_device_id fsl_mc_bus_match_table[] = {
6375 - {.compatible = "fsl,qoriq-mc",},
6379 -MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table);
6381 -static struct platform_driver fsl_mc_bus_driver = {
6383 - .name = "fsl_mc_bus",
6385 - .of_match_table = fsl_mc_bus_match_table,
6387 - .probe = fsl_mc_bus_probe,
6388 - .remove = fsl_mc_bus_remove,
6391 -static int __init fsl_mc_bus_driver_init(void)
6395 - error = bus_register(&fsl_mc_bus_type);
6397 - pr_err("bus type registration failed: %d\n", error);
6398 - goto error_cleanup_cache;
6401 - error = platform_driver_register(&fsl_mc_bus_driver);
6403 - pr_err("platform_driver_register() failed: %d\n", error);
6404 - goto error_cleanup_bus;
6407 - error = dprc_driver_init();
6409 - goto error_cleanup_driver;
6411 - error = fsl_mc_allocator_driver_init();
6413 - goto error_cleanup_dprc_driver;
6415 - error = its_fsl_mc_msi_init();
6417 - goto error_cleanup_mc_allocator;
6421 -error_cleanup_mc_allocator:
6422 - fsl_mc_allocator_driver_exit();
6424 -error_cleanup_dprc_driver:
6425 - dprc_driver_exit();
6427 -error_cleanup_driver:
6428 - platform_driver_unregister(&fsl_mc_bus_driver);
6431 - bus_unregister(&fsl_mc_bus_type);
6433 -error_cleanup_cache:
6436 -postcore_initcall(fsl_mc_bus_driver_init);
6438 +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
6440 +// SPDX-License-Identifier: GPL-2.0
6442 + * Freescale Management Complex (MC) bus driver
6444 + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
6445 + * Author: German Rivera <German.Rivera@freescale.com>
6449 +#define pr_fmt(fmt) "fsl-mc: " fmt
6451 +#include <linux/module.h>
6452 +#include <linux/of_device.h>
6453 +#include <linux/of_address.h>
6454 +#include <linux/ioport.h>
6455 +#include <linux/slab.h>
6456 +#include <linux/limits.h>
6457 +#include <linux/bitops.h>
6458 +#include <linux/msi.h>
6459 +#include <linux/dma-mapping.h>
6461 +#include "fsl-mc-private.h"
6464 + * Default DMA mask for devices on a fsl-mc bus
6466 +#define FSL_MC_DEFAULT_DMA_MASK (~0ULL)
6469 + * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device
6470 + * @root_mc_bus_dev: fsl-mc device representing the root DPRC
6471 + * @num_translation_ranges: number of entries in addr_translation_ranges
6472 + * @translation_ranges: array of bus to system address translation ranges
6475 + struct fsl_mc_device *root_mc_bus_dev;
6476 + u8 num_translation_ranges;
6477 + struct fsl_mc_addr_translation_range *translation_ranges;
6481 + * struct fsl_mc_addr_translation_range - bus to system address translation
6483 + * @mc_region_type: Type of MC region for the range being translated
6484 + * @start_mc_offset: Start MC offset of the range being translated
6485 + * @end_mc_offset: MC offset of the first byte after the range (last MC
6486 + * offset of the range is end_mc_offset - 1)
6487 + * @start_phys_addr: system physical address corresponding to start_mc_addr
6489 +struct fsl_mc_addr_translation_range {
6490 + enum dprc_region_type mc_region_type;
6491 + u64 start_mc_offset;
6492 + u64 end_mc_offset;
6493 + phys_addr_t start_phys_addr;
6497 + * struct mc_version
6498 + * @major: Major version number: incremented on API compatibility changes
6499 + * @minor: Minor version number: incremented on API additions (that are
6500 + * backward compatible); reset when major version is incremented
6501 + * @revision: Internal revision number: incremented on implementation changes
6502 + * and/or bug fixes that have no impact on API
6504 +struct mc_version {
6511 + * fsl_mc_bus_match - device to driver matching callback
6512 + * @dev: the fsl-mc device to match against
6513 + * @drv: the device driver to search for matching fsl-mc object type
6516 + * Returns 1 on success, 0 otherwise.
6518 +static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
6520 + const struct fsl_mc_device_id *id;
6521 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6522 + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
6523 + bool found = false;
6525 + /* When driver_override is set, only bind to the matching driver */
6526 + if (mc_dev->driver_override) {
6527 + found = !strcmp(mc_dev->driver_override, mc_drv->driver.name);
6531 + if (!mc_drv->match_id_table)
6535 + * If the object is not 'plugged' don't match.
6536 + * Only exception is the root DPRC, which is a special case.
6538 + if ((mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED) == 0 &&
6539 + !fsl_mc_is_root_dprc(&mc_dev->dev))
6543 + * Traverse the match_id table of the given driver, trying to find
6544 + * a matching for the given device.
6546 + for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) {
6547 + if (id->vendor == mc_dev->obj_desc.vendor &&
6548 + strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) {
6556 + dev_dbg(dev, "%smatched\n", found ? "" : "not ");
6561 + * fsl_mc_bus_uevent - callback invoked when a device is added
6563 +static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
6565 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6567 + if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s",
6568 + mc_dev->obj_desc.vendor,
6569 + mc_dev->obj_desc.type))
6575 +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
6578 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6580 + return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor,
6581 + mc_dev->obj_desc.type);
6583 +static DEVICE_ATTR_RO(modalias);
6585 +static ssize_t rescan_store(struct device *dev,
6586 + struct device_attribute *attr,
6587 + const char *buf, size_t count)
6589 + struct fsl_mc_device *root_mc_dev;
6590 + struct fsl_mc_bus *root_mc_bus;
6591 + unsigned long val;
6593 + if (!fsl_mc_is_root_dprc(dev))
6596 + root_mc_dev = to_fsl_mc_device(dev);
6597 + root_mc_bus = to_fsl_mc_bus(root_mc_dev);
6599 + if (kstrtoul(buf, 0, &val) < 0)
6603 + mutex_lock(&root_mc_bus->scan_mutex);
6604 + dprc_scan_objects(root_mc_dev, NULL, NULL);
6605 + mutex_unlock(&root_mc_bus->scan_mutex);
6610 +static DEVICE_ATTR_WO(rescan);
6612 +static ssize_t driver_override_store(struct device *dev,
6613 + struct device_attribute *attr,
6614 + const char *buf, size_t count)
6616 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6617 + const char *driver_override, *old = mc_dev->driver_override;
6620 + if (WARN_ON(dev->bus != &fsl_mc_bus_type))
6623 + if (count >= (PAGE_SIZE - 1))
6626 + driver_override = kstrndup(buf, count, GFP_KERNEL);
6627 + if (!driver_override)
6630 + cp = strchr(driver_override, '\n');
6634 + if (strlen(driver_override)) {
6635 + mc_dev->driver_override = driver_override;
6637 + kfree(driver_override);
6638 + mc_dev->driver_override = NULL;
6646 +static ssize_t driver_override_show(struct device *dev,
6647 + struct device_attribute *attr, char *buf)
6649 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6651 + return snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override);
6653 +static DEVICE_ATTR_RW(driver_override);
6655 +static struct attribute *fsl_mc_dev_attrs[] = {
6656 + &dev_attr_modalias.attr,
6657 + &dev_attr_rescan.attr,
6658 + &dev_attr_driver_override.attr,
6662 +ATTRIBUTE_GROUPS(fsl_mc_dev);
6664 +static int scan_fsl_mc_bus(struct device *dev, void *data)
6666 + struct fsl_mc_device *root_mc_dev;
6667 + struct fsl_mc_bus *root_mc_bus;
6669 + if (!fsl_mc_is_root_dprc(dev))
6672 + root_mc_dev = to_fsl_mc_device(dev);
6673 + root_mc_bus = to_fsl_mc_bus(root_mc_dev);
6674 + mutex_lock(&root_mc_bus->scan_mutex);
6675 + dprc_scan_objects(root_mc_dev, NULL, NULL);
6676 + mutex_unlock(&root_mc_bus->scan_mutex);
6682 +static ssize_t bus_rescan_store(struct bus_type *bus,
6683 + const char *buf, size_t count)
6685 + unsigned long val;
6687 + if (kstrtoul(buf, 0, &val) < 0)
6691 + bus_for_each_dev(bus, NULL, NULL, scan_fsl_mc_bus);
6695 +static BUS_ATTR(rescan, 0220, NULL, bus_rescan_store);
6697 +static struct attribute *fsl_mc_bus_attrs[] = {
6698 + &bus_attr_rescan.attr,
6702 +static const struct attribute_group fsl_mc_bus_group = {
6703 + .attrs = fsl_mc_bus_attrs,
6706 +static const struct attribute_group *fsl_mc_bus_groups[] = {
6707 + &fsl_mc_bus_group,
6711 +struct bus_type fsl_mc_bus_type = {
6713 + .match = fsl_mc_bus_match,
6714 + .uevent = fsl_mc_bus_uevent,
6715 + .dev_groups = fsl_mc_dev_groups,
6716 + .bus_groups = fsl_mc_bus_groups,
6718 +EXPORT_SYMBOL_GPL(fsl_mc_bus_type);
6720 +struct device_type fsl_mc_bus_dprc_type = {
6721 + .name = "fsl_mc_bus_dprc"
6724 +struct device_type fsl_mc_bus_dpni_type = {
6725 + .name = "fsl_mc_bus_dpni"
6728 +struct device_type fsl_mc_bus_dpio_type = {
6729 + .name = "fsl_mc_bus_dpio"
6732 +struct device_type fsl_mc_bus_dpsw_type = {
6733 + .name = "fsl_mc_bus_dpsw"
6736 +struct device_type fsl_mc_bus_dpdmux_type = {
6737 + .name = "fsl_mc_bus_dpdmux"
6740 +struct device_type fsl_mc_bus_dpbp_type = {
6741 + .name = "fsl_mc_bus_dpbp"
6744 +struct device_type fsl_mc_bus_dpcon_type = {
6745 + .name = "fsl_mc_bus_dpcon"
6748 +struct device_type fsl_mc_bus_dpmcp_type = {
6749 + .name = "fsl_mc_bus_dpmcp"
6752 +struct device_type fsl_mc_bus_dpmac_type = {
6753 + .name = "fsl_mc_bus_dpmac"
6756 +struct device_type fsl_mc_bus_dprtc_type = {
6757 + .name = "fsl_mc_bus_dprtc"
6760 +struct device_type fsl_mc_bus_dpseci_type = {
6761 + .name = "fsl_mc_bus_dpseci"
6764 +struct device_type fsl_mc_bus_dpdcei_type = {
6765 + .name = "fsl_mc_bus_dpdcei"
6768 +struct device_type fsl_mc_bus_dpaiop_type = {
6769 + .name = "fsl_mc_bus_dpaiop"
6772 +struct device_type fsl_mc_bus_dpci_type = {
6773 + .name = "fsl_mc_bus_dpci"
6776 +struct device_type fsl_mc_bus_dpdmai_type = {
6777 + .name = "fsl_mc_bus_dpdmai"
6780 +static struct device_type *fsl_mc_get_device_type(const char *type)
6782 + static const struct {
6783 + struct device_type *dev_type;
6786 + { &fsl_mc_bus_dprc_type, "dprc" },
6787 + { &fsl_mc_bus_dpni_type, "dpni" },
6788 + { &fsl_mc_bus_dpio_type, "dpio" },
6789 + { &fsl_mc_bus_dpsw_type, "dpsw" },
6790 + { &fsl_mc_bus_dpdmux_type, "dpdmux" },
6791 + { &fsl_mc_bus_dpbp_type, "dpbp" },
6792 + { &fsl_mc_bus_dpcon_type, "dpcon" },
6793 + { &fsl_mc_bus_dpmcp_type, "dpmcp" },
6794 + { &fsl_mc_bus_dpmac_type, "dpmac" },
6795 + { &fsl_mc_bus_dprtc_type, "dprtc" },
6796 + { &fsl_mc_bus_dpseci_type, "dpseci" },
6797 + { &fsl_mc_bus_dpdcei_type, "dpdcei" },
6798 + { &fsl_mc_bus_dpaiop_type, "dpaiop" },
6799 + { &fsl_mc_bus_dpci_type, "dpci" },
6800 + { &fsl_mc_bus_dpdmai_type, "dpdmai" },
6805 + for (i = 0; dev_types[i].dev_type; i++)
6806 + if (!strcmp(dev_types[i].type, type))
6807 + return dev_types[i].dev_type;
6812 +static int fsl_mc_driver_probe(struct device *dev)
6814 + struct fsl_mc_driver *mc_drv;
6815 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6818 + mc_drv = to_fsl_mc_driver(dev->driver);
6820 + error = mc_drv->probe(mc_dev);
6822 + if (error != -EPROBE_DEFER)
6823 + dev_err(dev, "%s failed: %d\n", __func__, error);
6830 +static int fsl_mc_driver_remove(struct device *dev)
6832 + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
6833 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6836 + error = mc_drv->remove(mc_dev);
6838 + dev_err(dev, "%s failed: %d\n", __func__, error);
6845 +static void fsl_mc_driver_shutdown(struct device *dev)
6847 + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
6848 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6850 + mc_drv->shutdown(mc_dev);
6854 + * __fsl_mc_driver_register - registers a child device driver with the
6857 + * This function is implicitly invoked from the registration function of
6858 + * fsl_mc device drivers, which is generated by the
6859 + * module_fsl_mc_driver() macro.
6861 +int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver,
6862 + struct module *owner)
6866 + mc_driver->driver.owner = owner;
6867 + mc_driver->driver.bus = &fsl_mc_bus_type;
6869 + if (mc_driver->probe)
6870 + mc_driver->driver.probe = fsl_mc_driver_probe;
6872 + if (mc_driver->remove)
6873 + mc_driver->driver.remove = fsl_mc_driver_remove;
6875 + if (mc_driver->shutdown)
6876 + mc_driver->driver.shutdown = fsl_mc_driver_shutdown;
6878 + error = driver_register(&mc_driver->driver);
6880 + pr_err("driver_register() failed for %s: %d\n",
6881 + mc_driver->driver.name, error);
6887 +EXPORT_SYMBOL_GPL(__fsl_mc_driver_register);
6890 + * fsl_mc_driver_unregister - unregisters a device driver from the
6893 +void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver)
6895 + driver_unregister(&mc_driver->driver);
6897 +EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister);
6900 + * mc_get_version() - Retrieves the Management Complex firmware
6901 + * version information
6902 + * @mc_io: Pointer to opaque I/O object
6903 + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
6904 + * @mc_ver_info: Returned version information structure
6906 + * Return: '0' on Success; Error code otherwise.
6908 +static int mc_get_version(struct fsl_mc_io *mc_io,
6910 + struct mc_version *mc_ver_info)
6912 + struct fsl_mc_command cmd = { 0 };
6913 + struct dpmng_rsp_get_version *rsp_params;
6916 + /* prepare command */
6917 + cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION,
6921 + /* send command to mc*/
6922 + err = mc_send_command(mc_io, &cmd);
6926 + /* retrieve response parameters */
6927 + rsp_params = (struct dpmng_rsp_get_version *)cmd.params;
6928 + mc_ver_info->revision = le32_to_cpu(rsp_params->revision);
6929 + mc_ver_info->major = le32_to_cpu(rsp_params->version_major);
6930 + mc_ver_info->minor = le32_to_cpu(rsp_params->version_minor);
6936 + * fsl_mc_get_root_dprc - function to traverse to the root dprc
6938 +void fsl_mc_get_root_dprc(struct device *dev,
6939 + struct device **root_dprc_dev)
6942 + *root_dprc_dev = NULL;
6943 + } else if (!dev_is_fsl_mc(dev)) {
6944 + *root_dprc_dev = NULL;
6946 + *root_dprc_dev = dev;
6947 + while (dev_is_fsl_mc((*root_dprc_dev)->parent))
6948 + *root_dprc_dev = (*root_dprc_dev)->parent;
6951 +EXPORT_SYMBOL_GPL(fsl_mc_get_root_dprc);
6953 +static int get_dprc_attr(struct fsl_mc_io *mc_io,
6954 + int container_id, struct dprc_attributes *attr)
6959 + error = dprc_open(mc_io, 0, container_id, &dprc_handle);
6961 + dev_err(mc_io->dev, "dprc_open() failed: %d\n", error);
6965 + memset(attr, 0, sizeof(struct dprc_attributes));
6966 + error = dprc_get_attributes(mc_io, 0, dprc_handle, attr);
6968 + dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n",
6970 + goto common_cleanup;
6976 + (void)dprc_close(mc_io, 0, dprc_handle);
6980 +static int get_dprc_icid(struct fsl_mc_io *mc_io,
6981 + int container_id, u32 *icid)
6983 + struct dprc_attributes attr;
6986 + error = get_dprc_attr(mc_io, container_id, &attr);
6988 + *icid = attr.icid;
6993 +static int translate_mc_addr(struct fsl_mc_device *mc_dev,
6994 + enum dprc_region_type mc_region_type,
6995 + u64 mc_offset, phys_addr_t *phys_addr)
6998 + struct device *root_dprc_dev;
6999 + struct fsl_mc *mc;
7001 + fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev);
7002 + mc = dev_get_drvdata(root_dprc_dev->parent);
7004 + if (mc->num_translation_ranges == 0) {
7006 + * Do identity mapping:
7008 + *phys_addr = mc_offset;
7012 + for (i = 0; i < mc->num_translation_ranges; i++) {
7013 + struct fsl_mc_addr_translation_range *range =
7014 + &mc->translation_ranges[i];
7016 + if (mc_region_type == range->mc_region_type &&
7017 + mc_offset >= range->start_mc_offset &&
7018 + mc_offset < range->end_mc_offset) {
7019 + *phys_addr = range->start_phys_addr +
7020 + (mc_offset - range->start_mc_offset);
7028 +static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
7029 + struct fsl_mc_device *mc_bus_dev)
7033 + struct resource *regions;
7034 + struct fsl_mc_obj_desc *obj_desc = &mc_dev->obj_desc;
7035 + struct device *parent_dev = mc_dev->dev.parent;
7036 + enum dprc_region_type mc_region_type;
7038 + if (is_fsl_mc_bus_dprc(mc_dev) ||
7039 + is_fsl_mc_bus_dpmcp(mc_dev)) {
7040 + mc_region_type = DPRC_REGION_TYPE_MC_PORTAL;
7041 + } else if (is_fsl_mc_bus_dpio(mc_dev)) {
7042 + mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL;
7045 + * This function should not have been called for this MC object
7046 + * type, as this object type is not supposed to have MMIO
7052 + regions = kmalloc_array(obj_desc->region_count,
7053 + sizeof(regions[0]), GFP_KERNEL);
7057 + for (i = 0; i < obj_desc->region_count; i++) {
7058 + struct dprc_region_desc region_desc;
7060 + error = dprc_get_obj_region(mc_bus_dev->mc_io,
7062 + mc_bus_dev->mc_handle,
7064 + obj_desc->id, i, ®ion_desc);
7066 + dev_err(parent_dev,
7067 + "dprc_get_obj_region() failed: %d\n", error);
7068 + goto error_cleanup_regions;
7070 + /* Older MC only returned region offset and no base address
7071 + * If base address is in the region_desc use it otherwise
7072 + * revert to old mechanism
7074 + if (region_desc.base_address)
7075 + regions[i].start = region_desc.base_address +
7076 + region_desc.base_offset;
7078 + error = translate_mc_addr(mc_dev, mc_region_type,
7079 + region_desc.base_offset,
7080 + ®ions[i].start);
7082 + dev_err(parent_dev,
7083 + "Invalid MC offset: %#x (for %s.%d\'s region %d)\n",
7084 + region_desc.base_offset,
7085 + obj_desc->type, obj_desc->id, i);
7086 + goto error_cleanup_regions;
7089 + regions[i].end = regions[i].start + region_desc.size - 1;
7090 + regions[i].name = "fsl-mc object MMIO region";
7091 + regions[i].flags = IORESOURCE_IO;
7092 + if (region_desc.flags & DPRC_REGION_CACHEABLE)
7093 + regions[i].flags |= IORESOURCE_CACHEABLE;
7094 + if (region_desc.flags & DPRC_REGION_SHAREABLE)
7095 + regions[i].flags |= IORESOURCE_MEM;
7098 + mc_dev->regions = regions;
7101 +error_cleanup_regions:
7107 + * fsl_mc_is_root_dprc - function to check if a given device is a root dprc
7109 +bool fsl_mc_is_root_dprc(struct device *dev)
7111 + struct device *root_dprc_dev;
7113 + fsl_mc_get_root_dprc(dev, &root_dprc_dev);
7114 + if (!root_dprc_dev)
7116 + return dev == root_dprc_dev;
7119 +static void fsl_mc_device_release(struct device *dev)
7121 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
7123 + kfree(mc_dev->regions);
7125 + if (is_fsl_mc_bus_dprc(mc_dev))
7126 + kfree(to_fsl_mc_bus(mc_dev));
7132 + * Add a newly discovered fsl-mc device to be visible in Linux
7134 +int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
7135 + struct fsl_mc_io *mc_io,
7136 + struct device *parent_dev,
7137 + const char *driver_override,
7138 + struct fsl_mc_device **new_mc_dev)
7141 + struct fsl_mc_device *mc_dev = NULL;
7142 + struct fsl_mc_bus *mc_bus = NULL;
7143 + struct fsl_mc_device *parent_mc_dev;
7145 + if (dev_is_fsl_mc(parent_dev))
7146 + parent_mc_dev = to_fsl_mc_device(parent_dev);
7148 + parent_mc_dev = NULL;
7150 + if (strcmp(obj_desc->type, "dprc") == 0) {
7152 + * Allocate an MC bus device object:
7154 + mc_bus = kzalloc(sizeof(*mc_bus), GFP_KERNEL);
7158 + mc_dev = &mc_bus->mc_dev;
7161 + * Allocate a regular fsl_mc_device object:
7163 + mc_dev = kzalloc(sizeof(*mc_dev), GFP_KERNEL);
7168 + mc_dev->obj_desc = *obj_desc;
7169 + mc_dev->mc_io = mc_io;
7171 + if (driver_override) {
7173 + * We trust driver_override, so we don't need to use
7176 + mc_dev->driver_override = kstrdup(driver_override, GFP_KERNEL);
7177 + if (!mc_dev->driver_override) {
7179 + goto error_cleanup_dev;
7183 + device_initialize(&mc_dev->dev);
7184 + mc_dev->dev.parent = parent_dev;
7185 + mc_dev->dev.bus = &fsl_mc_bus_type;
7186 + mc_dev->dev.release = fsl_mc_device_release;
7187 + mc_dev->dev.type = fsl_mc_get_device_type(obj_desc->type);
7188 + if (!mc_dev->dev.type) {
7190 + dev_err(parent_dev, "unknown device type %s\n", obj_desc->type);
7191 + goto error_cleanup_dev;
7193 + dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id);
7195 + if (strcmp(obj_desc->type, "dprc") == 0) {
7196 + struct fsl_mc_io *mc_io2;
7198 + mc_dev->flags |= FSL_MC_IS_DPRC;
7201 + * To get the DPRC's ICID, we need to open the DPRC
7202 + * in get_dprc_icid(). For child DPRCs, we do so using the
7203 + * parent DPRC's MC portal instead of the child DPRC's MC
7204 + * portal, in case the child DPRC is already opened with
7205 + * its own portal (e.g., the DPRC used by AIOP).
7207 + * NOTE: There cannot be more than one active open for a
7208 + * given MC object, using the same MC portal.
7210 + if (parent_mc_dev) {
7212 + * device being added is a child DPRC device
7214 + mc_io2 = parent_mc_dev->mc_io;
7217 + * device being added is the root DPRC device
7221 + goto error_cleanup_dev;
7227 + error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid);
7229 + goto error_cleanup_dev;
7232 + * A non-DPRC object has to be a child of a DPRC, use the
7233 + * parent's ICID and interrupt domain.
7235 + mc_dev->icid = parent_mc_dev->icid;
7236 + mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK;
7237 + mc_dev->dev.dma_mask = &mc_dev->dma_mask;
7238 + mc_dev->dev.coherent_dma_mask = mc_dev->dma_mask;
7239 + dev_set_msi_domain(&mc_dev->dev,
7240 + dev_get_msi_domain(&parent_mc_dev->dev));
7244 + * Get MMIO regions for the device from the MC:
7246 + * NOTE: the root DPRC is a special case as its MMIO region is
7247 + * obtained from the device tree
7249 + if (parent_mc_dev && obj_desc->region_count != 0) {
7250 + error = fsl_mc_device_get_mmio_regions(mc_dev,
7253 + goto error_cleanup_dev;
7257 + * The device-specific probe callback will get invoked by device_add()
7259 + error = device_add(&mc_dev->dev);
7261 + dev_err(parent_dev,
7262 + "device_add() failed for device %s: %d\n",
7263 + dev_name(&mc_dev->dev), error);
7264 + goto error_cleanup_dev;
7267 + dev_dbg(parent_dev, "added %s\n", dev_name(&mc_dev->dev));
7269 + *new_mc_dev = mc_dev;
7273 + kfree(mc_dev->regions);
7279 +EXPORT_SYMBOL_GPL(fsl_mc_device_add);
7282 + * fsl_mc_device_remove - Remove an fsl-mc device from being visible to
7285 + * @mc_dev: Pointer to an fsl-mc device
7287 +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
7289 + kfree(mc_dev->driver_override);
7290 + mc_dev->driver_override = NULL;
7293 + * The device-specific remove callback will get invoked by device_del()
7295 + device_del(&mc_dev->dev);
7296 + put_device(&mc_dev->dev);
7298 +EXPORT_SYMBOL_GPL(fsl_mc_device_remove);
7300 +static int parse_mc_ranges(struct device *dev,
7302 + int *mc_addr_cells,
7303 + int *mc_size_cells,
7304 + const __be32 **ranges_start)
7306 + const __be32 *prop;
7307 + int range_tuple_cell_count;
7310 + struct device_node *mc_node = dev->of_node;
7312 + *ranges_start = of_get_property(mc_node, "ranges", &ranges_len);
7313 + if (!(*ranges_start) || !ranges_len) {
7315 + "missing or empty ranges property for device tree node '%s'\n",
7320 + *paddr_cells = of_n_addr_cells(mc_node);
7322 + prop = of_get_property(mc_node, "#address-cells", NULL);
7324 + *mc_addr_cells = be32_to_cpup(prop);
7326 + *mc_addr_cells = *paddr_cells;
7328 + prop = of_get_property(mc_node, "#size-cells", NULL);
7330 + *mc_size_cells = be32_to_cpup(prop);
7332 + *mc_size_cells = of_n_size_cells(mc_node);
7334 + range_tuple_cell_count = *paddr_cells + *mc_addr_cells +
7337 + tuple_len = range_tuple_cell_count * sizeof(__be32);
7338 + if (ranges_len % tuple_len != 0) {
7339 + dev_err(dev, "malformed ranges property '%s'\n", mc_node->name);
7343 + return ranges_len / tuple_len;
7346 +static int get_mc_addr_translation_ranges(struct device *dev,
7347 + struct fsl_mc_addr_translation_range
7353 + int mc_addr_cells;
7354 + int mc_size_cells;
7356 + const __be32 *ranges_start;
7357 + const __be32 *cell;
7359 + ret = parse_mc_ranges(dev,
7367 + *num_ranges = ret;
7370 + * Missing or empty ranges property ("ranges;") for the
7371 + * 'fsl,qoriq-mc' node. In this case, identity mapping
7378 + *ranges = devm_kcalloc(dev, *num_ranges,
7379 + sizeof(struct fsl_mc_addr_translation_range),
7384 + cell = ranges_start;
7385 + for (i = 0; i < *num_ranges; ++i) {
7386 + struct fsl_mc_addr_translation_range *range = &(*ranges)[i];
7388 + range->mc_region_type = of_read_number(cell, 1);
7389 + range->start_mc_offset = of_read_number(cell + 1,
7390 + mc_addr_cells - 1);
7391 + cell += mc_addr_cells;
7392 + range->start_phys_addr = of_read_number(cell, paddr_cells);
7393 + cell += paddr_cells;
7394 + range->end_mc_offset = range->start_mc_offset +
7395 + of_read_number(cell, mc_size_cells);
7397 + cell += mc_size_cells;
7404 + * fsl_mc_bus_probe - callback invoked when the root MC bus is being
7407 +static int fsl_mc_bus_probe(struct platform_device *pdev)
7409 + struct fsl_mc_obj_desc obj_desc;
7411 + struct fsl_mc *mc;
7412 + struct fsl_mc_device *mc_bus_dev = NULL;
7413 + struct fsl_mc_io *mc_io = NULL;
7414 + struct fsl_mc_bus *mc_bus = NULL;
7416 + phys_addr_t mc_portal_phys_addr;
7417 + u32 mc_portal_size;
7418 + struct mc_version mc_version;
7419 + struct resource res;
7421 + mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
7425 + platform_set_drvdata(pdev, mc);
7428 + * Get physical address of MC portal for the root DPRC:
7430 + error = of_address_to_resource(pdev->dev.of_node, 0, &res);
7432 + dev_err(&pdev->dev,
7433 + "of_address_to_resource() failed for %pOF\n",
7434 + pdev->dev.of_node);
7438 + mc_portal_phys_addr = res.start;
7439 + mc_portal_size = resource_size(&res);
7440 + error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr,
7441 + mc_portal_size, NULL,
7442 + FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io);
7446 + error = mc_get_version(mc_io, 0, &mc_version);
7448 + dev_err(&pdev->dev,
7449 + "mc_get_version() failed with error %d\n", error);
7450 + goto error_cleanup_mc_io;
7453 + dev_info(&pdev->dev, "MC firmware version: %u.%u.%u\n",
7454 + mc_version.major, mc_version.minor, mc_version.revision);
7456 + error = get_mc_addr_translation_ranges(&pdev->dev,
7457 + &mc->translation_ranges,
7458 + &mc->num_translation_ranges);
7460 + goto error_cleanup_mc_io;
7462 + error = dprc_get_container_id(mc_io, 0, &container_id);
7464 + dev_err(&pdev->dev,
7465 + "dprc_get_container_id() failed: %d\n", error);
7466 + goto error_cleanup_mc_io;
7469 + memset(&obj_desc, 0, sizeof(struct fsl_mc_obj_desc));
7470 + error = dprc_get_api_version(mc_io, 0,
7471 + &obj_desc.ver_major,
7472 + &obj_desc.ver_minor);
7474 + goto error_cleanup_mc_io;
7476 + obj_desc.vendor = FSL_MC_VENDOR_FREESCALE;
7477 + strcpy(obj_desc.type, "dprc");
7478 + obj_desc.id = container_id;
7479 + obj_desc.irq_count = 1;
7480 + obj_desc.region_count = 0;
7482 + error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, NULL,
7485 + goto error_cleanup_mc_io;
7487 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
7488 + error = fsl_mc_restool_create_device_file(mc_bus);
7490 + goto error_cleanup_device;
7492 + mc->root_mc_bus_dev = mc_bus_dev;
7496 +error_cleanup_device:
7497 + fsl_mc_device_remove(mc_bus_dev);
7499 +error_cleanup_mc_io:
7500 + fsl_destroy_mc_io(mc_io);
7505 + * fsl_mc_bus_remove - callback invoked when the root MC bus is being
7508 +static int fsl_mc_bus_remove(struct platform_device *pdev)
7510 + struct fsl_mc *mc = platform_get_drvdata(pdev);
7511 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc->root_mc_bus_dev);
7513 + if (!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))
7516 + fsl_mc_restool_remove_device_file(mc_bus);
7517 + fsl_mc_device_remove(mc->root_mc_bus_dev);
7519 + fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io);
7520 + mc->root_mc_bus_dev->mc_io = NULL;
7525 +static const struct of_device_id fsl_mc_bus_match_table[] = {
7526 + {.compatible = "fsl,qoriq-mc",},
7530 +MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table);
7532 +static struct platform_driver fsl_mc_bus_driver = {
7534 + .name = "fsl_mc_bus",
7536 + .of_match_table = fsl_mc_bus_match_table,
7538 + .probe = fsl_mc_bus_probe,
7539 + .remove = fsl_mc_bus_remove,
7542 +static int __init fsl_mc_bus_driver_init(void)
7546 + error = bus_register(&fsl_mc_bus_type);
7548 + pr_err("bus type registration failed: %d\n", error);
7549 + goto error_cleanup_cache;
7552 + error = platform_driver_register(&fsl_mc_bus_driver);
7554 + pr_err("platform_driver_register() failed: %d\n", error);
7555 + goto error_cleanup_bus;
7558 + error = dprc_driver_init();
7560 + goto error_cleanup_driver;
7562 + error = fsl_mc_allocator_driver_init();
7564 + goto error_cleanup_dprc_driver;
7566 + error = fsl_mc_restool_init();
7568 + goto error_cleanup_mc_allocator;
7572 +error_cleanup_mc_allocator:
7573 + fsl_mc_allocator_driver_exit();
7575 +error_cleanup_dprc_driver:
7576 + dprc_driver_exit();
7578 +error_cleanup_driver:
7579 + platform_driver_unregister(&fsl_mc_bus_driver);
7582 + bus_unregister(&fsl_mc_bus_type);
7584 +error_cleanup_cache:
7587 +postcore_initcall(fsl_mc_bus_driver_init);
7588 --- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c
7591 -// SPDX-License-Identifier: GPL-2.0
7593 - * Freescale Management Complex (MC) bus driver MSI support
7595 - * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
7596 - * Author: German Rivera <German.Rivera@freescale.com>
7600 -#include <linux/of_device.h>
7601 -#include <linux/of_address.h>
7602 -#include <linux/of_irq.h>
7603 -#include <linux/irq.h>
7604 -#include <linux/irqdomain.h>
7605 -#include <linux/msi.h>
7606 -#include "fsl-mc-private.h"
7608 -#ifdef GENERIC_MSI_DOMAIN_OPS
7610 - * Generate a unique ID identifying the interrupt (only used within the MSI
7611 - * irqdomain. Combine the icid with the interrupt index.
7613 -static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev,
7614 - struct msi_desc *desc)
7617 - * Make the base hwirq value for ICID*10000 so it is readable
7618 - * as a decimal value in /proc/interrupts.
7620 - return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000));
7623 -static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg,
7624 - struct msi_desc *desc)
7627 - arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev),
7631 -#define fsl_mc_msi_set_desc NULL
7634 -static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info)
7636 - struct msi_domain_ops *ops = info->ops;
7638 - if (WARN_ON(!ops))
7642 - * set_desc should not be set by the caller
7644 - if (!ops->set_desc)
7645 - ops->set_desc = fsl_mc_msi_set_desc;
7648 -static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
7649 - struct fsl_mc_device_irq *mc_dev_irq)
7652 - struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev;
7653 - struct msi_desc *msi_desc = mc_dev_irq->msi_desc;
7654 - struct dprc_irq_cfg irq_cfg;
7657 - * msi_desc->msg.address is 0x0 when this function is invoked in
7658 - * the free_irq() code path. In this case, for the MC, we don't
7659 - * really need to "unprogram" the MSI, so we just return.
7661 - if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0)
7664 - if (WARN_ON(!owner_mc_dev))
7667 - irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) |
7668 - msi_desc->msg.address_lo;
7669 - irq_cfg.val = msi_desc->msg.data;
7670 - irq_cfg.irq_num = msi_desc->irq;
7672 - if (owner_mc_dev == mc_bus_dev) {
7674 - * IRQ is for the mc_bus_dev's DPRC itself
7676 - error = dprc_set_irq(mc_bus_dev->mc_io,
7677 - MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
7678 - mc_bus_dev->mc_handle,
7679 - mc_dev_irq->dev_irq_index,
7682 - dev_err(&owner_mc_dev->dev,
7683 - "dprc_set_irq() failed: %d\n", error);
7687 - * IRQ is for for a child device of mc_bus_dev
7689 - error = dprc_set_obj_irq(mc_bus_dev->mc_io,
7690 - MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
7691 - mc_bus_dev->mc_handle,
7692 - owner_mc_dev->obj_desc.type,
7693 - owner_mc_dev->obj_desc.id,
7694 - mc_dev_irq->dev_irq_index,
7697 - dev_err(&owner_mc_dev->dev,
7698 - "dprc_obj_set_irq() failed: %d\n", error);
7704 - * NOTE: This function is invoked with interrupts disabled
7706 -static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
7707 - struct msi_msg *msg)
7709 - struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data);
7710 - struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev);
7711 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
7712 - struct fsl_mc_device_irq *mc_dev_irq =
7713 - &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index];
7715 - WARN_ON(mc_dev_irq->msi_desc != msi_desc);
7716 - msi_desc->msg = *msg;
7719 - * Program the MSI (paddr, value) pair in the device:
7721 - __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq);
7724 -static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
7726 - struct irq_chip *chip = info->chip;
7728 - if (WARN_ON((!chip)))
7732 - * irq_write_msi_msg should not be set by the caller
7734 - if (!chip->irq_write_msi_msg)
7735 - chip->irq_write_msi_msg = fsl_mc_msi_write_msg;
7739 - * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain
7740 - * @np: Optional device-tree node of the interrupt controller
7741 - * @info: MSI domain info
7742 - * @parent: Parent irq domain
7744 - * Updates the domain and chip ops and creates a fsl-mc MSI
7745 - * interrupt domain.
7748 - * A domain pointer or NULL in case of failure.
7750 -struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
7751 - struct msi_domain_info *info,
7752 - struct irq_domain *parent)
7754 - struct irq_domain *domain;
7756 - if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
7757 - fsl_mc_msi_update_dom_ops(info);
7758 - if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
7759 - fsl_mc_msi_update_chip_ops(info);
7761 - domain = msi_create_irq_domain(fwnode, info, parent);
7763 - irq_domain_update_bus_token(domain, DOMAIN_BUS_FSL_MC_MSI);
7768 -int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
7769 - struct irq_domain **mc_msi_domain)
7771 - struct irq_domain *msi_domain;
7772 - struct device_node *mc_of_node = mc_platform_dev->of_node;
7774 - msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
7775 - DOMAIN_BUS_FSL_MC_MSI);
7776 - if (!msi_domain) {
7777 - pr_err("Unable to find fsl-mc MSI domain for %pOF\n",
7783 - *mc_msi_domain = msi_domain;
7787 -static void fsl_mc_msi_free_descs(struct device *dev)
7789 - struct msi_desc *desc, *tmp;
7791 - list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
7792 - list_del(&desc->list);
7793 - free_msi_entry(desc);
7797 -static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count)
7802 - struct msi_desc *msi_desc;
7804 - for (i = 0; i < irq_count; i++) {
7805 - msi_desc = alloc_msi_entry(dev, 1, NULL);
7807 - dev_err(dev, "Failed to allocate msi entry\n");
7809 - goto cleanup_msi_descs;
7812 - msi_desc->fsl_mc.msi_index = i;
7813 - INIT_LIST_HEAD(&msi_desc->list);
7814 - list_add_tail(&msi_desc->list, dev_to_msi_list(dev));
7820 - fsl_mc_msi_free_descs(dev);
7824 -int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
7825 - unsigned int irq_count)
7827 - struct irq_domain *msi_domain;
7830 - if (WARN_ON(!list_empty(dev_to_msi_list(dev))))
7833 - error = fsl_mc_msi_alloc_descs(dev, irq_count);
7837 - msi_domain = dev_get_msi_domain(dev);
7838 - if (WARN_ON(!msi_domain)) {
7840 - goto cleanup_msi_descs;
7844 - * NOTE: Calling this function will trigger the invocation of the
7845 - * its_fsl_mc_msi_prepare() callback
7847 - error = msi_domain_alloc_irqs(msi_domain, dev, irq_count);
7850 - dev_err(dev, "Failed to allocate IRQs\n");
7851 - goto cleanup_msi_descs;
7857 - fsl_mc_msi_free_descs(dev);
7861 -void fsl_mc_msi_domain_free_irqs(struct device *dev)
7863 - struct irq_domain *msi_domain;
7865 - msi_domain = dev_get_msi_domain(dev);
7866 - if (WARN_ON(!msi_domain))
7869 - msi_domain_free_irqs(msi_domain, dev);
7871 - if (WARN_ON(list_empty(dev_to_msi_list(dev))))
7874 - fsl_mc_msi_free_descs(dev);
7877 +++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
7879 +// SPDX-License-Identifier: GPL-2.0
7881 + * Freescale Management Complex (MC) bus driver MSI support
7883 + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
7884 + * Author: German Rivera <German.Rivera@freescale.com>
7888 +#include <linux/of_device.h>
7889 +#include <linux/of_address.h>
7890 +#include <linux/of_irq.h>
7891 +#include <linux/irq.h>
7892 +#include <linux/irqdomain.h>
7893 +#include <linux/msi.h>
7895 +#include "fsl-mc-private.h"
7897 +#ifdef GENERIC_MSI_DOMAIN_OPS
7899 + * Generate a unique ID identifying the interrupt (only used within the MSI
7900 + * irqdomain. Combine the icid with the interrupt index.
7902 +static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev,
7903 + struct msi_desc *desc)
7906 + * Make the base hwirq value for ICID*10000 so it is readable
7907 + * as a decimal value in /proc/interrupts.
7909 + return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000));
7912 +static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg,
7913 + struct msi_desc *desc)
7916 + arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev),
7920 +#define fsl_mc_msi_set_desc NULL
7923 +static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info)
7925 + struct msi_domain_ops *ops = info->ops;
7931 + * set_desc should not be set by the caller
7933 + if (!ops->set_desc)
7934 + ops->set_desc = fsl_mc_msi_set_desc;
7937 +static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
7938 + struct fsl_mc_device_irq *mc_dev_irq)
7941 + struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev;
7942 + struct msi_desc *msi_desc = mc_dev_irq->msi_desc;
7943 + struct dprc_irq_cfg irq_cfg;
7946 + * msi_desc->msg.address is 0x0 when this function is invoked in
7947 + * the free_irq() code path. In this case, for the MC, we don't
7948 + * really need to "unprogram" the MSI, so we just return.
7950 + if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0)
7953 + if (!owner_mc_dev)
7956 + irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) |
7957 + msi_desc->msg.address_lo;
7958 + irq_cfg.val = msi_desc->msg.data;
7959 + irq_cfg.irq_num = msi_desc->irq;
7961 + if (owner_mc_dev == mc_bus_dev) {
7963 + * IRQ is for the mc_bus_dev's DPRC itself
7965 + error = dprc_set_irq(mc_bus_dev->mc_io,
7966 + MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
7967 + mc_bus_dev->mc_handle,
7968 + mc_dev_irq->dev_irq_index,
7971 + dev_err(&owner_mc_dev->dev,
7972 + "dprc_set_irq() failed: %d\n", error);
7976 + * IRQ is for for a child device of mc_bus_dev
7978 + error = dprc_set_obj_irq(mc_bus_dev->mc_io,
7979 + MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
7980 + mc_bus_dev->mc_handle,
7981 + owner_mc_dev->obj_desc.type,
7982 + owner_mc_dev->obj_desc.id,
7983 + mc_dev_irq->dev_irq_index,
7986 + dev_err(&owner_mc_dev->dev,
7987 + "dprc_obj_set_irq() failed: %d\n", error);
7993 + * NOTE: This function is invoked with interrupts disabled
7995 +static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
7996 + struct msi_msg *msg)
7998 + struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data);
7999 + struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev);
8000 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
8001 + struct fsl_mc_device_irq *mc_dev_irq =
8002 + &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index];
8004 + msi_desc->msg = *msg;
8007 + * Program the MSI (paddr, value) pair in the device:
8009 + __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq);
8012 +static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
8014 + struct irq_chip *chip = info->chip;
8020 + * irq_write_msi_msg should not be set by the caller
8022 + if (!chip->irq_write_msi_msg)
8023 + chip->irq_write_msi_msg = fsl_mc_msi_write_msg;
8027 + * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain
8028 + * @np: Optional device-tree node of the interrupt controller
8029 + * @info: MSI domain info
8030 + * @parent: Parent irq domain
8032 + * Updates the domain and chip ops and creates a fsl-mc MSI
8033 + * interrupt domain.
8036 + * A domain pointer or NULL in case of failure.
8038 +struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
8039 + struct msi_domain_info *info,
8040 + struct irq_domain *parent)
8042 + struct irq_domain *domain;
8044 + if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
8045 + fsl_mc_msi_update_dom_ops(info);
8046 + if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
8047 + fsl_mc_msi_update_chip_ops(info);
8049 + domain = msi_create_irq_domain(fwnode, info, parent);
8051 + irq_domain_update_bus_token(domain, DOMAIN_BUS_FSL_MC_MSI);
8056 +int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
8057 + struct irq_domain **mc_msi_domain)
8059 + struct irq_domain *msi_domain;
8060 + struct device_node *mc_of_node = mc_platform_dev->of_node;
8062 + msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
8063 + DOMAIN_BUS_FSL_MC_MSI);
8064 + if (!msi_domain) {
8065 + pr_err("Unable to find fsl-mc MSI domain for %pOF\n",
8071 + *mc_msi_domain = msi_domain;
8075 +static void fsl_mc_msi_free_descs(struct device *dev)
8077 + struct msi_desc *desc, *tmp;
8079 + list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
8080 + list_del(&desc->list);
8081 + free_msi_entry(desc);
8085 +static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count)
8090 + struct msi_desc *msi_desc;
8092 + for (i = 0; i < irq_count; i++) {
8093 + msi_desc = alloc_msi_entry(dev, 1, NULL);
8095 + dev_err(dev, "Failed to allocate msi entry\n");
8097 + goto cleanup_msi_descs;
8100 + msi_desc->fsl_mc.msi_index = i;
8101 + INIT_LIST_HEAD(&msi_desc->list);
8102 + list_add_tail(&msi_desc->list, dev_to_msi_list(dev));
8108 + fsl_mc_msi_free_descs(dev);
8112 +int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
8113 + unsigned int irq_count)
8115 + struct irq_domain *msi_domain;
8118 + if (!list_empty(dev_to_msi_list(dev)))
8121 + error = fsl_mc_msi_alloc_descs(dev, irq_count);
8125 + msi_domain = dev_get_msi_domain(dev);
8126 + if (!msi_domain) {
8128 + goto cleanup_msi_descs;
8132 + * NOTE: Calling this function will trigger the invocation of the
8133 + * its_fsl_mc_msi_prepare() callback
8135 + error = msi_domain_alloc_irqs(msi_domain, dev, irq_count);
8138 + dev_err(dev, "Failed to allocate IRQs\n");
8139 + goto cleanup_msi_descs;
8145 + fsl_mc_msi_free_descs(dev);
8149 +void fsl_mc_msi_domain_free_irqs(struct device *dev)
8151 + struct irq_domain *msi_domain;
8153 + msi_domain = dev_get_msi_domain(dev);
8157 + msi_domain_free_irqs(msi_domain, dev);
8159 + if (list_empty(dev_to_msi_list(dev)))
8162 + fsl_mc_msi_free_descs(dev);
8165 +++ b/drivers/bus/fsl-mc/fsl-mc-private.h
8167 +/* SPDX-License-Identifier: GPL-2.0 */
8169 + * Freescale Management Complex (MC) bus private declarations
8171 + * Copyright (C) 2016 Freescale Semiconductor, Inc.
8174 +#ifndef _FSL_MC_PRIVATE_H_
8175 +#define _FSL_MC_PRIVATE_H_
8177 +#include <linux/fsl/mc.h>
8178 +#include <linux/mutex.h>
8179 +#include <linux/cdev.h>
8180 +#include <linux/ioctl.h>
8183 + * Data Path Management Complex (DPMNG) General API
8186 +/* DPMNG command versioning */
8187 +#define DPMNG_CMD_BASE_VERSION 1
8188 +#define DPMNG_CMD_ID_OFFSET 4
8190 +#define DPMNG_CMD(id) (((id) << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION)
8192 +/* DPMNG command IDs */
8193 +#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831)
8195 +struct dpmng_rsp_get_version {
8197 + __le32 version_major;
8198 + __le32 version_minor;
8202 + * Data Path Management Command Portal (DPMCP) API
8205 +/* Minimal supported DPMCP Version */
8206 +#define DPMCP_MIN_VER_MAJOR 3
8207 +#define DPMCP_MIN_VER_MINOR 0
8209 +/* DPMCP command versioning */
8210 +#define DPMCP_CMD_BASE_VERSION 1
8211 +#define DPMCP_CMD_ID_OFFSET 4
8213 +#define DPMCP_CMD(id) (((id) << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION)
8215 +/* DPMCP command IDs */
8216 +#define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800)
8217 +#define DPMCP_CMDID_OPEN DPMCP_CMD(0x80b)
8218 +#define DPMCP_CMDID_RESET DPMCP_CMD(0x005)
8220 +struct dpmcp_cmd_open {
8225 + * Initialization and runtime control APIs for DPMCP
8227 +int dpmcp_open(struct fsl_mc_io *mc_io,
8232 +int dpmcp_close(struct fsl_mc_io *mc_io,
8236 +int dpmcp_reset(struct fsl_mc_io *mc_io,
8241 + * Data Path Buffer Pool (DPBP) API
8245 +#define DPBP_VER_MAJOR 3
8246 +#define DPBP_VER_MINOR 2
8248 +/* Command versioning */
8249 +#define DPBP_CMD_BASE_VERSION 1
8250 +#define DPBP_CMD_ID_OFFSET 4
8252 +#define DPBP_CMD(id) (((id) << DPBP_CMD_ID_OFFSET) | DPBP_CMD_BASE_VERSION)
8255 +#define DPBP_CMDID_CLOSE DPBP_CMD(0x800)
8256 +#define DPBP_CMDID_OPEN DPBP_CMD(0x804)
8258 +#define DPBP_CMDID_ENABLE DPBP_CMD(0x002)
8259 +#define DPBP_CMDID_DISABLE DPBP_CMD(0x003)
8260 +#define DPBP_CMDID_GET_ATTR DPBP_CMD(0x004)
8261 +#define DPBP_CMDID_RESET DPBP_CMD(0x005)
8263 +struct dpbp_cmd_open {
8267 +#define DPBP_ENABLE 0x1
8269 +struct dpbp_rsp_get_attributes {
8270 + /* response word 0 */
8274 + /* response word 1 */
8275 + __le16 version_major;
8276 + __le16 version_minor;
8280 + * Data Path Concentrator (DPCON) API
8283 +/* DPCON Version */
8284 +#define DPCON_VER_MAJOR 3
8285 +#define DPCON_VER_MINOR 2
8287 +/* Command versioning */
8288 +#define DPCON_CMD_BASE_VERSION 1
8289 +#define DPCON_CMD_ID_OFFSET 4
8291 +#define DPCON_CMD(id) (((id) << DPCON_CMD_ID_OFFSET) | DPCON_CMD_BASE_VERSION)
8294 +#define DPCON_CMDID_CLOSE DPCON_CMD(0x800)
8295 +#define DPCON_CMDID_OPEN DPCON_CMD(0x808)
8297 +#define DPCON_CMDID_ENABLE DPCON_CMD(0x002)
8298 +#define DPCON_CMDID_DISABLE DPCON_CMD(0x003)
8299 +#define DPCON_CMDID_GET_ATTR DPCON_CMD(0x004)
8300 +#define DPCON_CMDID_RESET DPCON_CMD(0x005)
8302 +#define DPCON_CMDID_SET_NOTIFICATION DPCON_CMD(0x100)
8304 +struct dpcon_cmd_open {
8308 +#define DPCON_ENABLE 1
8310 +struct dpcon_rsp_get_attr {
8311 + /* response word 0 */
8313 + __le16 qbman_ch_id;
8314 + u8 num_priorities;
8318 +struct dpcon_cmd_set_notification {
8327 +int __must_check fsl_mc_device_add(struct fsl_mc_obj_desc *obj_desc,
8328 + struct fsl_mc_io *mc_io,
8329 + struct device *parent_dev,
8330 + const char *driver_override,
8331 + struct fsl_mc_device **new_mc_dev);
8333 +int __init dprc_driver_init(void);
8335 +void dprc_driver_exit(void);
8337 +int __init fsl_mc_allocator_driver_init(void);
8339 +void fsl_mc_allocator_driver_exit(void);
8341 +int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
8342 + enum fsl_mc_pool_type pool_type,
8343 + struct fsl_mc_resource
8346 +void fsl_mc_resource_free(struct fsl_mc_resource *resource);
8348 +int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
8349 + unsigned int irq_count);
8351 +void fsl_mc_msi_domain_free_irqs(struct device *dev);
8353 +int __must_check fsl_create_mc_io(struct device *dev,
8354 + phys_addr_t mc_portal_phys_addr,
8355 + u32 mc_portal_size,
8356 + struct fsl_mc_device *dpmcp_dev,
8357 + u32 flags, struct fsl_mc_io **new_mc_io);
8359 +void fsl_destroy_mc_io(struct fsl_mc_io *mc_io);
8361 +bool fsl_mc_is_root_dprc(struct device *dev);
8363 +#ifdef CONFIG_FSL_MC_RESTOOL
8365 +int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus);
8367 +void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus);
8369 +int fsl_mc_restool_init(void);
8373 +static inline int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus)
8378 +static inline void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus)
8382 +static inline int fsl_mc_restool_init(void)
8389 +#endif /* _FSL_MC_PRIVATE_H_ */
8391 +++ b/drivers/bus/fsl-mc/fsl-mc-restool.c
8393 +// SPDX-License-Identifier: GPL-2.0
8395 + * Management Complex (MC) restool support
8397 + * Copyright 2018 NXP
8401 +#include <linux/slab.h>
8402 +#include <linux/cdev.h>
8403 +#include <linux/fs.h>
8404 +#include <linux/uaccess.h>
8406 +#include "fsl-mc-private.h"
8408 +#define FSL_MC_BUS_MAX_MINORS 1
8410 +static struct class *fsl_mc_bus_class;
8411 +static int fsl_mc_bus_major;
8413 +static int fsl_mc_restool_send_command(unsigned long arg,
8414 + struct fsl_mc_io *mc_io)
8416 + struct fsl_mc_command mc_cmd;
8419 + error = copy_from_user(&mc_cmd, (void __user *)arg, sizeof(mc_cmd));
8423 + error = mc_send_command(mc_io, &mc_cmd);
8427 + error = copy_to_user((void __user *)arg, &mc_cmd, sizeof(mc_cmd));
8434 +int fsl_mc_restool_init(void)
8439 + fsl_mc_bus_class = class_create(THIS_MODULE, "fsl_mc_bus");
8440 + if (IS_ERR(fsl_mc_bus_class)) {
8441 + error = PTR_ERR(fsl_mc_bus_class);
8445 + error = alloc_chrdev_region(&dev, 0,
8446 + FSL_MC_BUS_MAX_MINORS,
8451 + fsl_mc_bus_major = MAJOR(dev);
8456 +static int fsl_mc_restool_dev_open(struct inode *inode, struct file *filep)
8458 + struct fsl_mc_device *root_mc_device;
8459 + struct fsl_mc_restool *mc_restool;
8460 + struct fsl_mc_bus *mc_bus;
8461 + struct fsl_mc_io *dynamic_mc_io;
8464 + mc_restool = container_of(inode->i_cdev, struct fsl_mc_restool, cdev);
8465 + mc_bus = container_of(mc_restool, struct fsl_mc_bus, restool_misc);
8466 + root_mc_device = &mc_bus->mc_dev;
8468 + mutex_lock(&mc_restool->mutex);
8470 + if (!mc_restool->local_instance_in_use) {
8471 + filep->private_data = root_mc_device->mc_io;
8472 + mc_restool->local_instance_in_use = true;
8474 + dynamic_mc_io = kzalloc(sizeof(*dynamic_mc_io), GFP_KERNEL);
8475 + if (!dynamic_mc_io) {
8477 + goto error_alloc_mc_io;
8480 + error = fsl_mc_portal_allocate(root_mc_device, 0,
8483 + pr_err("Could not allocate MC portal\n");
8484 + goto error_portal_allocate;
8487 + mc_restool->dynamic_instance_count++;
8488 + filep->private_data = dynamic_mc_io;
8491 + mutex_unlock(&mc_restool->mutex);
8495 +error_portal_allocate:
8496 + kfree(dynamic_mc_io);
8499 + mutex_unlock(&mc_restool->mutex);
8504 +static int fsl_mc_restool_dev_release(struct inode *inode, struct file *filep)
8506 + struct fsl_mc_device *root_mc_device;
8507 + struct fsl_mc_restool *mc_restool;
8508 + struct fsl_mc_bus *mc_bus;
8509 + struct fsl_mc_io *mc_io;
8511 + mc_restool = container_of(inode->i_cdev, struct fsl_mc_restool, cdev);
8512 + mc_bus = container_of(mc_restool, struct fsl_mc_bus, restool_misc);
8513 + root_mc_device = &mc_bus->mc_dev;
8514 + mc_io = filep->private_data;
8516 + mutex_lock(&mc_restool->mutex);
8518 + if (WARN_ON(!mc_restool->local_instance_in_use &&
8519 + mc_restool->dynamic_instance_count == 0)) {
8520 + mutex_unlock(&mc_restool->mutex);
8524 + if (filep->private_data == root_mc_device->mc_io) {
8525 + mc_restool->local_instance_in_use = false;
8527 + fsl_mc_portal_free(mc_io);
8529 + mc_restool->dynamic_instance_count--;
8532 + filep->private_data = NULL;
8533 + mutex_unlock(&mc_restool->mutex);
8538 +static long fsl_mc_restool_dev_ioctl(struct file *file,
8540 + unsigned long arg)
8545 + case RESTOOL_SEND_MC_COMMAND:
8546 + error = fsl_mc_restool_send_command(arg, file->private_data);
8549 + pr_err("%s: unexpected ioctl call number\n", __func__);
8556 +static const struct file_operations fsl_mc_restool_dev_fops = {
8557 + .owner = THIS_MODULE,
8558 + .open = fsl_mc_restool_dev_open,
8559 + .release = fsl_mc_restool_dev_release,
8560 + .unlocked_ioctl = fsl_mc_restool_dev_ioctl,
8563 +int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus)
8565 + struct fsl_mc_device *mc_dev = &mc_bus->mc_dev;
8566 + struct fsl_mc_restool *mc_restool = &mc_bus->restool_misc;
8569 + mc_restool = &mc_bus->restool_misc;
8570 + mc_restool->dev = MKDEV(fsl_mc_bus_major, 0);
8571 + cdev_init(&mc_restool->cdev, &fsl_mc_restool_dev_fops);
8573 + error = cdev_add(&mc_restool->cdev,
8575 + FSL_MC_BUS_MAX_MINORS);
8579 + mc_restool->device = device_create(fsl_mc_bus_class,
8584 + dev_name(&mc_dev->dev));
8585 + if (IS_ERR(mc_restool->device)) {
8586 + error = PTR_ERR(mc_restool->device);
8587 + goto error_device_create;
8590 + mutex_init(&mc_restool->mutex);
8594 +error_device_create:
8595 + cdev_del(&mc_restool->cdev);
8600 +void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus)
8602 + struct fsl_mc_restool *mc_restool = &mc_bus->restool_misc;
8604 + if (WARN_ON(mc_restool->local_instance_in_use))
8607 + if (WARN_ON(mc_restool->dynamic_instance_count != 0))
8610 + cdev_del(&mc_restool->cdev);
8612 --- a/drivers/staging/fsl-mc/bus/mc-io.c
8615 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
8617 - * Copyright 2013-2016 Freescale Semiconductor Inc.
8621 -#include <linux/io.h>
8622 -#include "../include/mc.h"
8624 -#include "fsl-mc-private.h"
8626 -#include "dpmcp-cmd.h"
8628 -static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io,
8629 - struct fsl_mc_device *dpmcp_dev)
8633 - if (WARN_ON(!dpmcp_dev))
8636 - if (WARN_ON(mc_io->dpmcp_dev))
8639 - if (WARN_ON(dpmcp_dev->mc_io))
8642 - error = dpmcp_open(mc_io,
8644 - dpmcp_dev->obj_desc.id,
8645 - &dpmcp_dev->mc_handle);
8649 - mc_io->dpmcp_dev = dpmcp_dev;
8650 - dpmcp_dev->mc_io = mc_io;
8654 -static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io)
8657 - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8659 - if (WARN_ON(!dpmcp_dev))
8662 - if (WARN_ON(dpmcp_dev->mc_io != mc_io))
8665 - error = dpmcp_close(mc_io,
8667 - dpmcp_dev->mc_handle);
8669 - dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n",
8673 - mc_io->dpmcp_dev = NULL;
8674 - dpmcp_dev->mc_io = NULL;
8678 - * Creates an MC I/O object
8680 - * @dev: device to be associated with the MC I/O object
8681 - * @mc_portal_phys_addr: physical address of the MC portal to use
8682 - * @mc_portal_size: size in bytes of the MC portal
8683 - * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O
8684 - * object or NULL if none.
8685 - * @flags: flags for the new MC I/O object
8686 - * @new_mc_io: Area to return pointer to newly created MC I/O object
8688 - * Returns '0' on Success; Error code otherwise.
8690 -int __must_check fsl_create_mc_io(struct device *dev,
8691 - phys_addr_t mc_portal_phys_addr,
8692 - u32 mc_portal_size,
8693 - struct fsl_mc_device *dpmcp_dev,
8694 - u32 flags, struct fsl_mc_io **new_mc_io)
8697 - struct fsl_mc_io *mc_io;
8698 - void __iomem *mc_portal_virt_addr;
8699 - struct resource *res;
8701 - mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL);
8706 - mc_io->flags = flags;
8707 - mc_io->portal_phys_addr = mc_portal_phys_addr;
8708 - mc_io->portal_size = mc_portal_size;
8709 - if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
8710 - spin_lock_init(&mc_io->spinlock);
8712 - mutex_init(&mc_io->mutex);
8714 - res = devm_request_mem_region(dev,
8715 - mc_portal_phys_addr,
8720 - "devm_request_mem_region failed for MC portal %pa\n",
8721 - &mc_portal_phys_addr);
8725 - mc_portal_virt_addr = devm_ioremap_nocache(dev,
8726 - mc_portal_phys_addr,
8728 - if (!mc_portal_virt_addr) {
8730 - "devm_ioremap_nocache failed for MC portal %pa\n",
8731 - &mc_portal_phys_addr);
8735 - mc_io->portal_virt_addr = mc_portal_virt_addr;
8737 - error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev);
8739 - goto error_destroy_mc_io;
8742 - *new_mc_io = mc_io;
8745 -error_destroy_mc_io:
8746 - fsl_destroy_mc_io(mc_io);
8751 - * Destroys an MC I/O object
8753 - * @mc_io: MC I/O object to destroy
8755 -void fsl_destroy_mc_io(struct fsl_mc_io *mc_io)
8757 - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8760 - fsl_mc_io_unset_dpmcp(mc_io);
8762 - devm_iounmap(mc_io->dev, mc_io->portal_virt_addr);
8763 - devm_release_mem_region(mc_io->dev,
8764 - mc_io->portal_phys_addr,
8765 - mc_io->portal_size);
8767 - mc_io->portal_virt_addr = NULL;
8768 - devm_kfree(mc_io->dev, mc_io);
8772 - * fsl_mc_portal_allocate - Allocates an MC portal
8774 - * @mc_dev: MC device for which the MC portal is to be allocated
8775 - * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated
8777 - * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object
8778 - * that wraps the allocated MC portal is to be returned
8780 - * This function allocates an MC portal from the device's parent DPRC,
8781 - * from the corresponding MC bus' pool of MC portals and wraps
8782 - * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the
8783 - * portal is allocated from its own MC bus.
8785 -int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
8787 - struct fsl_mc_io **new_mc_io)
8789 - struct fsl_mc_device *mc_bus_dev;
8790 - struct fsl_mc_bus *mc_bus;
8791 - phys_addr_t mc_portal_phys_addr;
8792 - size_t mc_portal_size;
8793 - struct fsl_mc_device *dpmcp_dev;
8794 - int error = -EINVAL;
8795 - struct fsl_mc_resource *resource = NULL;
8796 - struct fsl_mc_io *mc_io = NULL;
8798 - if (mc_dev->flags & FSL_MC_IS_DPRC) {
8799 - mc_bus_dev = mc_dev;
8801 - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent)))
8804 - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
8807 - mc_bus = to_fsl_mc_bus(mc_bus_dev);
8808 - *new_mc_io = NULL;
8809 - error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource);
8814 - dpmcp_dev = resource->data;
8815 - if (WARN_ON(!dpmcp_dev))
8816 - goto error_cleanup_resource;
8818 - if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR ||
8819 - (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR &&
8820 - dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) {
8821 - dev_err(&dpmcp_dev->dev,
8822 - "ERROR: Version %d.%d of DPMCP not supported.\n",
8823 - dpmcp_dev->obj_desc.ver_major,
8824 - dpmcp_dev->obj_desc.ver_minor);
8825 - error = -ENOTSUPP;
8826 - goto error_cleanup_resource;
8829 - if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0))
8830 - goto error_cleanup_resource;
8832 - mc_portal_phys_addr = dpmcp_dev->regions[0].start;
8833 - mc_portal_size = resource_size(dpmcp_dev->regions);
8835 - if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size))
8836 - goto error_cleanup_resource;
8838 - error = fsl_create_mc_io(&mc_bus_dev->dev,
8839 - mc_portal_phys_addr,
8840 - mc_portal_size, dpmcp_dev,
8841 - mc_io_flags, &mc_io);
8843 - goto error_cleanup_resource;
8845 - *new_mc_io = mc_io;
8848 -error_cleanup_resource:
8849 - fsl_mc_resource_free(resource);
8852 -EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate);
8855 - * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals
8856 - * of a given MC bus
8858 - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
8860 -void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
8862 - struct fsl_mc_device *dpmcp_dev;
8863 - struct fsl_mc_resource *resource;
8866 - * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed
8867 - * to have a DPMCP object associated with.
8869 - dpmcp_dev = mc_io->dpmcp_dev;
8870 - if (WARN_ON(!dpmcp_dev))
8873 - resource = dpmcp_dev->resource;
8874 - if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP))
8877 - if (WARN_ON(resource->data != dpmcp_dev))
8880 - fsl_destroy_mc_io(mc_io);
8881 - fsl_mc_resource_free(resource);
8883 -EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
8886 - * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object
8888 - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
8890 -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
8893 - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8895 - if (WARN_ON(!dpmcp_dev))
8898 - error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle);
8900 - dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error);
8906 -EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
8908 +++ b/drivers/bus/fsl-mc/mc-io.c
8910 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
8912 + * Copyright 2013-2016 Freescale Semiconductor Inc.
8916 +#include <linux/io.h>
8917 +#include <linux/fsl/mc.h>
8919 +#include "fsl-mc-private.h"
8921 +static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io,
8922 + struct fsl_mc_device *dpmcp_dev)
8926 + if (mc_io->dpmcp_dev)
8929 + if (dpmcp_dev->mc_io)
8932 + error = dpmcp_open(mc_io,
8934 + dpmcp_dev->obj_desc.id,
8935 + &dpmcp_dev->mc_handle);
8939 + mc_io->dpmcp_dev = dpmcp_dev;
8940 + dpmcp_dev->mc_io = mc_io;
8944 +static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io)
8947 + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8949 + error = dpmcp_close(mc_io,
8951 + dpmcp_dev->mc_handle);
8953 + dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n",
8957 + mc_io->dpmcp_dev = NULL;
8958 + dpmcp_dev->mc_io = NULL;
8962 + * Creates an MC I/O object
8964 + * @dev: device to be associated with the MC I/O object
8965 + * @mc_portal_phys_addr: physical address of the MC portal to use
8966 + * @mc_portal_size: size in bytes of the MC portal
8967 + * @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O
8968 + * object or NULL if none.
8969 + * @flags: flags for the new MC I/O object
8970 + * @new_mc_io: Area to return pointer to newly created MC I/O object
8972 + * Returns '0' on Success; Error code otherwise.
8974 +int __must_check fsl_create_mc_io(struct device *dev,
8975 + phys_addr_t mc_portal_phys_addr,
8976 + u32 mc_portal_size,
8977 + struct fsl_mc_device *dpmcp_dev,
8978 + u32 flags, struct fsl_mc_io **new_mc_io)
8981 + struct fsl_mc_io *mc_io;
8982 + void __iomem *mc_portal_virt_addr;
8983 + struct resource *res;
8985 + mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL);
8990 + mc_io->flags = flags;
8991 + mc_io->portal_phys_addr = mc_portal_phys_addr;
8992 + mc_io->portal_size = mc_portal_size;
8993 + if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
8994 + spin_lock_init(&mc_io->spinlock);
8996 + mutex_init(&mc_io->mutex);
8998 + res = devm_request_mem_region(dev,
8999 + mc_portal_phys_addr,
9004 + "devm_request_mem_region failed for MC portal %pa\n",
9005 + &mc_portal_phys_addr);
9009 + mc_portal_virt_addr = devm_ioremap_nocache(dev,
9010 + mc_portal_phys_addr,
9012 + if (!mc_portal_virt_addr) {
9014 + "devm_ioremap_nocache failed for MC portal %pa\n",
9015 + &mc_portal_phys_addr);
9019 + mc_io->portal_virt_addr = mc_portal_virt_addr;
9021 + error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev);
9023 + goto error_destroy_mc_io;
9026 + *new_mc_io = mc_io;
9029 +error_destroy_mc_io:
9030 + fsl_destroy_mc_io(mc_io);
9035 + * Destroys an MC I/O object
9037 + * @mc_io: MC I/O object to destroy
9039 +void fsl_destroy_mc_io(struct fsl_mc_io *mc_io)
9041 + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
9044 + fsl_mc_io_unset_dpmcp(mc_io);
9046 + devm_iounmap(mc_io->dev, mc_io->portal_virt_addr);
9047 + devm_release_mem_region(mc_io->dev,
9048 + mc_io->portal_phys_addr,
9049 + mc_io->portal_size);
9051 + mc_io->portal_virt_addr = NULL;
9052 + devm_kfree(mc_io->dev, mc_io);
9056 + * fsl_mc_portal_allocate - Allocates an MC portal
9058 + * @mc_dev: MC device for which the MC portal is to be allocated
9059 + * @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated
9061 + * @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object
9062 + * that wraps the allocated MC portal is to be returned
9064 + * This function allocates an MC portal from the device's parent DPRC,
9065 + * from the corresponding MC bus' pool of MC portals and wraps
9066 + * it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the
9067 + * portal is allocated from its own MC bus.
9069 +int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
9071 + struct fsl_mc_io **new_mc_io)
9073 + struct fsl_mc_device *mc_bus_dev;
9074 + struct fsl_mc_bus *mc_bus;
9075 + phys_addr_t mc_portal_phys_addr;
9076 + size_t mc_portal_size;
9077 + struct fsl_mc_device *dpmcp_dev;
9078 + int error = -EINVAL;
9079 + struct fsl_mc_resource *resource = NULL;
9080 + struct fsl_mc_io *mc_io = NULL;
9082 + if (fsl_mc_is_root_dprc(&mc_dev->dev)) {
9083 + mc_bus_dev = mc_dev;
9085 + if (!dev_is_fsl_mc(mc_dev->dev.parent))
9088 + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
9091 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
9092 + *new_mc_io = NULL;
9093 + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource);
9098 + dpmcp_dev = resource->data;
9100 + if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR ||
9101 + (dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR &&
9102 + dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) {
9103 + dev_err(&dpmcp_dev->dev,
9104 + "ERROR: Version %d.%d of DPMCP not supported.\n",
9105 + dpmcp_dev->obj_desc.ver_major,
9106 + dpmcp_dev->obj_desc.ver_minor);
9107 + error = -ENOTSUPP;
9108 + goto error_cleanup_resource;
9111 + mc_portal_phys_addr = dpmcp_dev->regions[0].start;
9112 + mc_portal_size = resource_size(dpmcp_dev->regions);
9114 + error = fsl_create_mc_io(&mc_bus_dev->dev,
9115 + mc_portal_phys_addr,
9116 + mc_portal_size, dpmcp_dev,
9117 + mc_io_flags, &mc_io);
9119 + goto error_cleanup_resource;
9121 + dpmcp_dev->consumer_link = device_link_add(&mc_dev->dev,
9123 + DL_FLAG_AUTOREMOVE_CONSUMER);
9124 + if (!dpmcp_dev->consumer_link) {
9126 + goto error_cleanup_mc_io;
9129 + *new_mc_io = mc_io;
9132 +error_cleanup_mc_io:
9133 + fsl_destroy_mc_io(mc_io);
9134 +error_cleanup_resource:
9135 + fsl_mc_resource_free(resource);
9138 +EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate);
9141 + * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals
9142 + * of a given MC bus
9144 + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
9146 +void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
9148 + struct fsl_mc_device *dpmcp_dev;
9149 + struct fsl_mc_resource *resource;
9152 + * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed
9153 + * to have a DPMCP object associated with.
9155 + dpmcp_dev = mc_io->dpmcp_dev;
9157 + resource = dpmcp_dev->resource;
9158 + if (!resource || resource->type != FSL_MC_POOL_DPMCP)
9161 + if (resource->data != dpmcp_dev)
9164 + fsl_destroy_mc_io(mc_io);
9165 + fsl_mc_resource_free(resource);
9167 + device_link_del(dpmcp_dev->consumer_link);
9168 + dpmcp_dev->consumer_link = NULL;
9170 +EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
9173 + * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object
9175 + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
9177 +int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
9180 + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
9182 + error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle);
9184 + dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error);
9190 +EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
9191 --- a/drivers/staging/fsl-mc/bus/mc-sys.c
9194 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
9196 - * Copyright 2013-2016 Freescale Semiconductor Inc.
9198 - * I/O services to send MC commands to the MC hardware
9202 -#include <linux/delay.h>
9203 -#include <linux/slab.h>
9204 -#include <linux/ioport.h>
9205 -#include <linux/device.h>
9206 -#include <linux/io.h>
9207 -#include <linux/io-64-nonatomic-hi-lo.h>
9208 -#include "../include/mc.h"
9213 - * Timeout in milliseconds to wait for the completion of an MC command
9215 -#define MC_CMD_COMPLETION_TIMEOUT_MS 500
9218 - * usleep_range() min and max values used to throttle down polling
9219 - * iterations while waiting for MC command completion
9221 -#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10
9222 -#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500
9224 -static enum mc_cmd_status mc_cmd_hdr_read_status(struct mc_command *cmd)
9226 - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
9228 - return (enum mc_cmd_status)hdr->status;
9231 -static u16 mc_cmd_hdr_read_cmdid(struct mc_command *cmd)
9233 - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
9234 - u16 cmd_id = le16_to_cpu(hdr->cmd_id);
9239 -static int mc_status_to_error(enum mc_cmd_status status)
9241 - static const int mc_status_to_error_map[] = {
9242 - [MC_CMD_STATUS_OK] = 0,
9243 - [MC_CMD_STATUS_AUTH_ERR] = -EACCES,
9244 - [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM,
9245 - [MC_CMD_STATUS_DMA_ERR] = -EIO,
9246 - [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO,
9247 - [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT,
9248 - [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL,
9249 - [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM,
9250 - [MC_CMD_STATUS_BUSY] = -EBUSY,
9251 - [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP,
9252 - [MC_CMD_STATUS_INVALID_STATE] = -ENODEV,
9255 - if (WARN_ON((u32)status >= ARRAY_SIZE(mc_status_to_error_map)))
9258 - return mc_status_to_error_map[status];
9261 -static const char *mc_status_to_string(enum mc_cmd_status status)
9263 - static const char *const status_strings[] = {
9264 - [MC_CMD_STATUS_OK] = "Command completed successfully",
9265 - [MC_CMD_STATUS_READY] = "Command ready to be processed",
9266 - [MC_CMD_STATUS_AUTH_ERR] = "Authentication error",
9267 - [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege",
9268 - [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error",
9269 - [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error",
9270 - [MC_CMD_STATUS_TIMEOUT] = "Operation timed out",
9271 - [MC_CMD_STATUS_NO_RESOURCE] = "No resources",
9272 - [MC_CMD_STATUS_NO_MEMORY] = "No memory available",
9273 - [MC_CMD_STATUS_BUSY] = "Device is busy",
9274 - [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation",
9275 - [MC_CMD_STATUS_INVALID_STATE] = "Invalid state"
9278 - if ((unsigned int)status >= ARRAY_SIZE(status_strings))
9279 - return "Unknown MC error";
9281 - return status_strings[status];
9285 - * mc_write_command - writes a command to a Management Complex (MC) portal
9287 - * @portal: pointer to an MC portal
9288 - * @cmd: pointer to a filled command
9290 -static inline void mc_write_command(struct mc_command __iomem *portal,
9291 - struct mc_command *cmd)
9295 - /* copy command parameters into the portal */
9296 - for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
9298 - * Data is already in the expected LE byte-order. Do an
9299 - * extra LE -> CPU conversion so that the CPU -> LE done in
9300 - * the device io write api puts it back in the right order.
9302 - writeq_relaxed(le64_to_cpu(cmd->params[i]), &portal->params[i]);
9304 - /* submit the command by writing the header */
9305 - writeq(le64_to_cpu(cmd->header), &portal->header);
9309 - * mc_read_response - reads the response for the last MC command from a
9310 - * Management Complex (MC) portal
9312 - * @portal: pointer to an MC portal
9313 - * @resp: pointer to command response buffer
9315 - * Returns MC_CMD_STATUS_OK on Success; Error code otherwise.
9317 -static inline enum mc_cmd_status mc_read_response(struct mc_command __iomem *
9319 - struct mc_command *resp)
9322 - enum mc_cmd_status status;
9324 - /* Copy command response header from MC portal: */
9325 - resp->header = cpu_to_le64(readq_relaxed(&portal->header));
9326 - status = mc_cmd_hdr_read_status(resp);
9327 - if (status != MC_CMD_STATUS_OK)
9330 - /* Copy command response data from MC portal: */
9331 - for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
9333 - * Data is expected to be in LE byte-order. Do an
9334 - * extra CPU -> LE to revert the LE -> CPU done in
9335 - * the device io read api.
9338 - cpu_to_le64(readq_relaxed(&portal->params[i]));
9344 - * Waits for the completion of an MC command doing preemptible polling.
9345 - * uslepp_range() is called between polling iterations.
9347 - * @mc_io: MC I/O object to be used
9348 - * @cmd: command buffer to receive MC response
9349 - * @mc_status: MC command completion status
9351 -static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io,
9352 - struct mc_command *cmd,
9353 - enum mc_cmd_status *mc_status)
9355 - enum mc_cmd_status status;
9356 - unsigned long jiffies_until_timeout =
9357 - jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS);
9360 - * Wait for response from the MC hardware:
9363 - status = mc_read_response(mc_io->portal_virt_addr, cmd);
9364 - if (status != MC_CMD_STATUS_READY)
9368 - * TODO: When MC command completion interrupts are supported
9369 - * call wait function here instead of usleep_range()
9371 - usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS,
9372 - MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
9374 - if (time_after_eq(jiffies, jiffies_until_timeout)) {
9375 - dev_dbg(mc_io->dev,
9376 - "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n",
9377 - &mc_io->portal_phys_addr,
9378 - (unsigned int)mc_cmd_hdr_read_token(cmd),
9379 - (unsigned int)mc_cmd_hdr_read_cmdid(cmd));
9381 - return -ETIMEDOUT;
9385 - *mc_status = status;
9390 - * Waits for the completion of an MC command doing atomic polling.
9391 - * udelay() is called between polling iterations.
9393 - * @mc_io: MC I/O object to be used
9394 - * @cmd: command buffer to receive MC response
9395 - * @mc_status: MC command completion status
9397 -static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io,
9398 - struct mc_command *cmd,
9399 - enum mc_cmd_status *mc_status)
9401 - enum mc_cmd_status status;
9402 - unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000;
9404 - BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) %
9405 - MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0);
9408 - status = mc_read_response(mc_io->portal_virt_addr, cmd);
9409 - if (status != MC_CMD_STATUS_READY)
9412 - udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
9413 - timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS;
9414 - if (timeout_usecs == 0) {
9415 - dev_dbg(mc_io->dev,
9416 - "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n",
9417 - &mc_io->portal_phys_addr,
9418 - (unsigned int)mc_cmd_hdr_read_token(cmd),
9419 - (unsigned int)mc_cmd_hdr_read_cmdid(cmd));
9421 - return -ETIMEDOUT;
9425 - *mc_status = status;
9430 - * Sends a command to the MC device using the given MC I/O object
9432 - * @mc_io: MC I/O object to be used
9433 - * @cmd: command to be sent
9435 - * Returns '0' on Success; Error code otherwise.
9437 -int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd)
9440 - enum mc_cmd_status status;
9441 - unsigned long irq_flags = 0;
9443 - if (WARN_ON(in_irq() &&
9444 - !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)))
9447 - if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
9448 - spin_lock_irqsave(&mc_io->spinlock, irq_flags);
9450 - mutex_lock(&mc_io->mutex);
9453 - * Send command to the MC hardware:
9455 - mc_write_command(mc_io->portal_virt_addr, cmd);
9458 - * Wait for response from the MC hardware:
9460 - if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
9461 - error = mc_polling_wait_preemptible(mc_io, cmd, &status);
9463 - error = mc_polling_wait_atomic(mc_io, cmd, &status);
9468 - if (status != MC_CMD_STATUS_OK) {
9469 - dev_dbg(mc_io->dev,
9470 - "MC command failed: portal: %pa, dprc handle: %#x, command: %#x, status: %s (%#x)\n",
9471 - &mc_io->portal_phys_addr,
9472 - (unsigned int)mc_cmd_hdr_read_token(cmd),
9473 - (unsigned int)mc_cmd_hdr_read_cmdid(cmd),
9474 - mc_status_to_string(status),
9475 - (unsigned int)status);
9477 - error = mc_status_to_error(status);
9483 - if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
9484 - spin_unlock_irqrestore(&mc_io->spinlock, irq_flags);
9486 - mutex_unlock(&mc_io->mutex);
9490 -EXPORT_SYMBOL(mc_send_command);
9492 +++ b/drivers/bus/fsl-mc/mc-sys.c
9494 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
9496 + * Copyright 2013-2016 Freescale Semiconductor Inc.
9498 + * I/O services to send MC commands to the MC hardware
9502 +#include <linux/delay.h>
9503 +#include <linux/slab.h>
9504 +#include <linux/ioport.h>
9505 +#include <linux/device.h>
9506 +#include <linux/io.h>
9507 +#include <linux/io-64-nonatomic-hi-lo.h>
9508 +#include <linux/fsl/mc.h>
9510 +#include "fsl-mc-private.h"
9513 + * Timeout in milliseconds to wait for the completion of an MC command
9515 +#define MC_CMD_COMPLETION_TIMEOUT_MS 15000
9518 + * usleep_range() min and max values used to throttle down polling
9519 + * iterations while waiting for MC command completion
9521 +#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10
9522 +#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500
9524 +static enum mc_cmd_status mc_cmd_hdr_read_status(struct fsl_mc_command *cmd)
9526 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
9528 + return (enum mc_cmd_status)hdr->status;
9531 +static u16 mc_cmd_hdr_read_cmdid(struct fsl_mc_command *cmd)
9533 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
9534 + u16 cmd_id = le16_to_cpu(hdr->cmd_id);
9539 +static int mc_status_to_error(enum mc_cmd_status status)
9541 + static const int mc_status_to_error_map[] = {
9542 + [MC_CMD_STATUS_OK] = 0,
9543 + [MC_CMD_STATUS_AUTH_ERR] = -EACCES,
9544 + [MC_CMD_STATUS_NO_PRIVILEGE] = -EPERM,
9545 + [MC_CMD_STATUS_DMA_ERR] = -EIO,
9546 + [MC_CMD_STATUS_CONFIG_ERR] = -ENXIO,
9547 + [MC_CMD_STATUS_TIMEOUT] = -ETIMEDOUT,
9548 + [MC_CMD_STATUS_NO_RESOURCE] = -ENAVAIL,
9549 + [MC_CMD_STATUS_NO_MEMORY] = -ENOMEM,
9550 + [MC_CMD_STATUS_BUSY] = -EBUSY,
9551 + [MC_CMD_STATUS_UNSUPPORTED_OP] = -ENOTSUPP,
9552 + [MC_CMD_STATUS_INVALID_STATE] = -ENODEV,
9555 + if ((u32)status >= ARRAY_SIZE(mc_status_to_error_map))
9558 + return mc_status_to_error_map[status];
9561 +static const char *mc_status_to_string(enum mc_cmd_status status)
9563 + static const char *const status_strings[] = {
9564 + [MC_CMD_STATUS_OK] = "Command completed successfully",
9565 + [MC_CMD_STATUS_READY] = "Command ready to be processed",
9566 + [MC_CMD_STATUS_AUTH_ERR] = "Authentication error",
9567 + [MC_CMD_STATUS_NO_PRIVILEGE] = "No privilege",
9568 + [MC_CMD_STATUS_DMA_ERR] = "DMA or I/O error",
9569 + [MC_CMD_STATUS_CONFIG_ERR] = "Configuration error",
9570 + [MC_CMD_STATUS_TIMEOUT] = "Operation timed out",
9571 + [MC_CMD_STATUS_NO_RESOURCE] = "No resources",
9572 + [MC_CMD_STATUS_NO_MEMORY] = "No memory available",
9573 + [MC_CMD_STATUS_BUSY] = "Device is busy",
9574 + [MC_CMD_STATUS_UNSUPPORTED_OP] = "Unsupported operation",
9575 + [MC_CMD_STATUS_INVALID_STATE] = "Invalid state"
9578 + if ((unsigned int)status >= ARRAY_SIZE(status_strings))
9579 + return "Unknown MC error";
9581 + return status_strings[status];
9585 + * mc_write_command - writes a command to a Management Complex (MC) portal
9587 + * @portal: pointer to an MC portal
9588 + * @cmd: pointer to a filled command
9590 +static inline void mc_write_command(struct fsl_mc_command __iomem *portal,
9591 + struct fsl_mc_command *cmd)
9595 + /* copy command parameters into the portal */
9596 + for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
9598 + * Data is already in the expected LE byte-order. Do an
9599 + * extra LE -> CPU conversion so that the CPU -> LE done in
9600 + * the device io write api puts it back in the right order.
9602 + writeq_relaxed(le64_to_cpu(cmd->params[i]), &portal->params[i]);
9604 + /* submit the command by writing the header */
9605 + writeq(le64_to_cpu(cmd->header), &portal->header);
9609 + * mc_read_response - reads the response for the last MC command from a
9610 + * Management Complex (MC) portal
9612 + * @portal: pointer to an MC portal
9613 + * @resp: pointer to command response buffer
9615 + * Returns MC_CMD_STATUS_OK on Success; Error code otherwise.
9617 +static inline enum mc_cmd_status mc_read_response(struct fsl_mc_command __iomem
9619 + struct fsl_mc_command *resp)
9622 + enum mc_cmd_status status;
9624 + /* Copy command response header from MC portal: */
9625 + resp->header = cpu_to_le64(readq_relaxed(&portal->header));
9626 + status = mc_cmd_hdr_read_status(resp);
9627 + if (status != MC_CMD_STATUS_OK)
9630 + /* Copy command response data from MC portal: */
9631 + for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
9633 + * Data is expected to be in LE byte-order. Do an
9634 + * extra CPU -> LE to revert the LE -> CPU done in
9635 + * the device io read api.
9638 + cpu_to_le64(readq_relaxed(&portal->params[i]));
9644 + * Waits for the completion of an MC command doing preemptible polling.
9645 + * uslepp_range() is called between polling iterations.
9647 + * @mc_io: MC I/O object to be used
9648 + * @cmd: command buffer to receive MC response
9649 + * @mc_status: MC command completion status
9651 +static int mc_polling_wait_preemptible(struct fsl_mc_io *mc_io,
9652 + struct fsl_mc_command *cmd,
9653 + enum mc_cmd_status *mc_status)
9655 + enum mc_cmd_status status;
9656 + unsigned long jiffies_until_timeout =
9657 + jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS);
9660 + * Wait for response from the MC hardware:
9663 + status = mc_read_response(mc_io->portal_virt_addr, cmd);
9664 + if (status != MC_CMD_STATUS_READY)
9668 + * TODO: When MC command completion interrupts are supported
9669 + * call wait function here instead of usleep_range()
9671 + usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS,
9672 + MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
9674 + if (time_after_eq(jiffies, jiffies_until_timeout)) {
9675 + dev_dbg(mc_io->dev,
9676 + "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n",
9677 + &mc_io->portal_phys_addr,
9678 + (unsigned int)mc_cmd_hdr_read_token(cmd),
9679 + (unsigned int)mc_cmd_hdr_read_cmdid(cmd));
9681 + return -ETIMEDOUT;
9685 + *mc_status = status;
9690 + * Waits for the completion of an MC command doing atomic polling.
9691 + * udelay() is called between polling iterations.
9693 + * @mc_io: MC I/O object to be used
9694 + * @cmd: command buffer to receive MC response
9695 + * @mc_status: MC command completion status
9697 +static int mc_polling_wait_atomic(struct fsl_mc_io *mc_io,
9698 + struct fsl_mc_command *cmd,
9699 + enum mc_cmd_status *mc_status)
9701 + enum mc_cmd_status status;
9702 + unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000;
9704 + BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) %
9705 + MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0);
9708 + status = mc_read_response(mc_io->portal_virt_addr, cmd);
9709 + if (status != MC_CMD_STATUS_READY)
9712 + udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
9713 + timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS;
9714 + if (timeout_usecs == 0) {
9715 + dev_dbg(mc_io->dev,
9716 + "MC command timed out (portal: %pa, dprc handle: %#x, command: %#x)\n",
9717 + &mc_io->portal_phys_addr,
9718 + (unsigned int)mc_cmd_hdr_read_token(cmd),
9719 + (unsigned int)mc_cmd_hdr_read_cmdid(cmd));
9721 + return -ETIMEDOUT;
9725 + *mc_status = status;
9730 + * Sends a command to the MC device using the given MC I/O object
9732 + * @mc_io: MC I/O object to be used
9733 + * @cmd: command to be sent
9735 + * Returns '0' on Success; Error code otherwise.
9737 +int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd)
9740 + enum mc_cmd_status status;
9741 + unsigned long irq_flags = 0;
9743 + if (in_irq() && !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
9746 + if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
9747 + spin_lock_irqsave(&mc_io->spinlock, irq_flags);
9749 + mutex_lock(&mc_io->mutex);
9752 + * Send command to the MC hardware:
9754 + mc_write_command(mc_io->portal_virt_addr, cmd);
9757 + * Wait for response from the MC hardware:
9759 + if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
9760 + error = mc_polling_wait_preemptible(mc_io, cmd, &status);
9762 + error = mc_polling_wait_atomic(mc_io, cmd, &status);
9767 + if (status != MC_CMD_STATUS_OK) {
9768 + dev_dbg(mc_io->dev,
9769 + "MC command failed: portal: %pa, dprc handle: %#x, command: %#x, status: %s (%#x)\n",
9770 + &mc_io->portal_phys_addr,
9771 + (unsigned int)mc_cmd_hdr_read_token(cmd),
9772 + (unsigned int)mc_cmd_hdr_read_cmdid(cmd),
9773 + mc_status_to_string(status),
9774 + (unsigned int)status);
9776 + error = mc_status_to_error(status);
9782 + if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
9783 + spin_unlock_irqrestore(&mc_io->spinlock, irq_flags);
9785 + mutex_unlock(&mc_io->mutex);
9789 +EXPORT_SYMBOL_GPL(mc_send_command);
9790 --- a/drivers/irqchip/Kconfig
9791 +++ b/drivers/irqchip/Kconfig
9792 @@ -42,6 +42,12 @@ config ARM_GIC_V3_ITS
9796 +config ARM_GIC_V3_ITS_FSL_MC
9798 + depends on ARM_GIC_V3_ITS
9799 + depends on FSL_MC_BUS
9800 + default ARM_GIC_V3_ITS
9805 --- a/drivers/irqchip/Makefile
9806 +++ b/drivers/irqchip/Makefile
9807 @@ -30,6 +30,7 @@ obj-$(CONFIG_ARCH_REALVIEW) += irq-gic-
9808 obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o
9809 obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o
9810 obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-pci-msi.o irq-gic-v3-its-platform-msi.o irq-gic-v4.o
9811 +obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) += irq-gic-v3-its-fsl-mc-msi.o
9812 obj-$(CONFIG_PARTITION_PERCPU) += irq-partition-percpu.o
9813 obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o
9814 obj-$(CONFIG_ARM_NVIC) += irq-nvic.o
9816 +++ b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
9818 +// SPDX-License-Identifier: GPL-2.0
9820 + * Freescale Management Complex (MC) bus driver MSI support
9822 + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
9823 + * Author: German Rivera <German.Rivera@freescale.com>
9827 +#include <linux/of_device.h>
9828 +#include <linux/of_address.h>
9829 +#include <linux/irq.h>
9830 +#include <linux/msi.h>
9831 +#include <linux/of.h>
9832 +#include <linux/of_irq.h>
9833 +#include <linux/fsl/mc.h>
9835 +static struct irq_chip its_msi_irq_chip = {
9836 + .name = "ITS-fMSI",
9837 + .irq_mask = irq_chip_mask_parent,
9838 + .irq_unmask = irq_chip_unmask_parent,
9839 + .irq_eoi = irq_chip_eoi_parent,
9840 + .irq_set_affinity = msi_domain_set_affinity
9843 +static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain,
9844 + struct device *dev,
9845 + int nvec, msi_alloc_info_t *info)
9847 + struct fsl_mc_device *mc_bus_dev;
9848 + struct msi_domain_info *msi_info;
9850 + if (!dev_is_fsl_mc(dev))
9853 + mc_bus_dev = to_fsl_mc_device(dev);
9854 + if (!(mc_bus_dev->flags & FSL_MC_IS_DPRC))
9858 + * Set the device Id to be passed to the GIC-ITS:
9860 + * NOTE: This device id corresponds to the IOMMU stream ID
9861 + * associated with the DPRC object (ICID).
9863 + info->scratchpad[0].ul = mc_bus_dev->icid;
9864 + msi_info = msi_get_domain_info(msi_domain->parent);
9865 + return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info);
9868 +static struct msi_domain_ops its_fsl_mc_msi_ops __ro_after_init = {
9869 + .msi_prepare = its_fsl_mc_msi_prepare,
9872 +static struct msi_domain_info its_fsl_mc_msi_domain_info = {
9873 + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
9874 + .ops = &its_fsl_mc_msi_ops,
9875 + .chip = &its_msi_irq_chip,
9878 +static const struct of_device_id its_device_id[] = {
9879 + { .compatible = "arm,gic-v3-its", },
9883 +static int __init its_fsl_mc_msi_init(void)
9885 + struct device_node *np;
9886 + struct irq_domain *parent;
9887 + struct irq_domain *mc_msi_domain;
9889 + for (np = of_find_matching_node(NULL, its_device_id); np;
9890 + np = of_find_matching_node(np, its_device_id)) {
9891 + if (!of_property_read_bool(np, "msi-controller"))
9894 + parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS);
9895 + if (!parent || !msi_get_domain_info(parent)) {
9896 + pr_err("%pOF: unable to locate ITS domain\n", np);
9900 + mc_msi_domain = fsl_mc_msi_create_irq_domain(
9901 + of_node_to_fwnode(np),
9902 + &its_fsl_mc_msi_domain_info,
9904 + if (!mc_msi_domain) {
9905 + pr_err("%pOF: unable to create fsl-mc domain\n", np);
9909 + pr_info("fsl-mc MSI: %pOF domain created\n", np);
9915 +early_initcall(its_fsl_mc_msi_init);
9916 --- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
9917 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
9919 #include <linux/filter.h>
9920 #include <linux/atomic.h>
9921 #include <net/sock.h>
9922 -#include "../../fsl-mc/include/mc.h"
9923 +#include <linux/fsl/mc.h>
9924 #include "dpaa2-eth.h"
9925 #include "dpaa2-eth-ceetm.h"
9927 --- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
9928 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
9930 #include <linux/dcbnl.h>
9931 #include <linux/netdevice.h>
9932 #include <linux/if_vlan.h>
9933 +#include <linux/fsl/mc.h>
9934 #include <linux/filter.h>
9936 #include "../../fsl-mc/include/dpaa2-io.h"
9937 #include "../../fsl-mc/include/dpaa2-fd.h"
9938 -#include "../../fsl-mc/include/dpbp.h"
9939 -#include "../../fsl-mc/include/dpcon.h"
9941 #include "dpni-cmd.h"
9943 --- a/drivers/staging/fsl-dpaa2/ethernet/dpni.c
9944 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.c
9947 #include <linux/kernel.h>
9948 #include <linux/errno.h>
9949 -#include "../../fsl-mc/include/mc.h"
9950 +#include <linux/fsl/mc.h>
9952 #include "dpni-cmd.h"
9954 --- a/drivers/staging/fsl-mc/bus/Kconfig
9955 +++ b/drivers/staging/fsl-mc/bus/Kconfig
9957 # Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
9961 - bool "QorIQ DPAA2 fsl-mc bus driver"
9962 - depends on OF && (ARCH_LAYERSCAPE || (COMPILE_TEST && (ARM || ARM64 || X86_LOCAL_APIC || PPC)))
9963 - select GENERIC_MSI_IRQ_DOMAIN
9965 - Driver to enable the bus infrastructure for the QorIQ DPAA2
9966 - architecture. The fsl-mc bus driver handles discovery of
9967 - DPAA2 objects (which are represented as Linux devices) and
9968 - binding objects to drivers.
9971 tristate "QorIQ DPAA2 DPIO driver"
9972 @@ -24,3 +15,9 @@ config FSL_MC_DPIO
9973 other DPAA2 objects. This driver does not expose the DPIO
9974 objects individually, but groups them under a service layer
9977 +config FSL_QBMAN_DEBUG
9978 + tristate "Freescale QBMAN Debug APIs"
9979 + depends on FSL_MC_DPIO
9981 + QBMan debug assistant APIs.
9982 --- a/drivers/staging/fsl-mc/bus/Makefile
9983 +++ b/drivers/staging/fsl-mc/bus/Makefile
9986 # Copyright (C) 2014 Freescale Semiconductor, Inc.
9988 -obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o
9990 -mc-bus-driver-objs := fsl-mc-bus.o \
9995 - fsl-mc-allocator.o \
9997 - irq-gic-v3-its-fsl-mc-msi.o \
10003 obj-$(CONFIG_FSL_MC_DPIO) += dpio/
10004 --- a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c
10005 +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c
10007 #include <linux/delay.h>
10008 #include <linux/io.h>
10010 -#include "../../include/mc.h"
10011 +#include <linux/fsl/mc.h>
10012 #include "../../include/dpaa2-io.h"
10014 #include "qbman-portal.h"
10015 --- a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c
10016 +++ b/drivers/staging/fsl-mc/bus/dpio/dpio-service.c
10020 #include <linux/types.h>
10021 -#include "../../include/mc.h"
10022 +#include <linux/fsl/mc.h>
10023 #include "../../include/dpaa2-io.h"
10024 #include <linux/init.h>
10025 #include <linux/module.h>
10026 --- a/drivers/staging/fsl-mc/bus/dpio/dpio.c
10027 +++ b/drivers/staging/fsl-mc/bus/dpio/dpio.c
10031 #include <linux/kernel.h>
10032 -#include "../../include/mc.h"
10033 +#include <linux/fsl/mc.h>
10036 #include "dpio-cmd.h"
10037 @@ -37,7 +37,7 @@ int dpio_open(struct fsl_mc_io *mc_io,
10041 - struct mc_command cmd = { 0 };
10042 + struct fsl_mc_command cmd = { 0 };
10043 struct dpio_cmd_open *dpio_cmd;
10046 @@ -70,7 +70,7 @@ int dpio_close(struct fsl_mc_io *mc_io,
10050 - struct mc_command cmd = { 0 };
10051 + struct fsl_mc_command cmd = { 0 };
10053 /* prepare command */
10054 cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE,
10055 @@ -92,7 +92,7 @@ int dpio_enable(struct fsl_mc_io *mc_io,
10059 - struct mc_command cmd = { 0 };
10060 + struct fsl_mc_command cmd = { 0 };
10062 /* prepare command */
10063 cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE,
10064 @@ -114,7 +114,7 @@ int dpio_disable(struct fsl_mc_io *mc_io
10068 - struct mc_command cmd = { 0 };
10069 + struct fsl_mc_command cmd = { 0 };
10071 /* prepare command */
10072 cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE,
10073 @@ -138,7 +138,7 @@ int dpio_get_attributes(struct fsl_mc_io
10075 struct dpio_attr *attr)
10077 - struct mc_command cmd = { 0 };
10078 + struct fsl_mc_command cmd = { 0 };
10079 struct dpio_rsp_get_attr *dpio_rsp;
10082 @@ -180,7 +180,7 @@ int dpio_get_api_version(struct fsl_mc_i
10086 - struct mc_command cmd = { 0 };
10087 + struct fsl_mc_command cmd = { 0 };
10090 /* prepare command */
10091 --- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
10095 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10097 - * Redistribution and use in source and binary forms, with or without
10098 - * modification, are permitted provided that the following conditions are met:
10099 - * * Redistributions of source code must retain the above copyright
10100 - * notice, this list of conditions and the following disclaimer.
10101 - * * Redistributions in binary form must reproduce the above copyright
10102 - * notice, this list of conditions and the following disclaimer in the
10103 - * documentation and/or other materials provided with the distribution.
10104 - * * Neither the name of the above-listed copyright holders nor the
10105 - * names of any contributors may be used to endorse or promote products
10106 - * derived from this software without specific prior written permission.
10108 - * ALTERNATIVELY, this software may be distributed under the terms of the
10109 - * GNU General Public License ("GPL") as published by the Free Software
10110 - * Foundation, either version 2 of that License or (at your option) any
10113 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10114 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10115 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10116 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
10117 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
10118 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
10119 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
10120 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
10121 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
10122 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
10123 - * POSSIBILITY OF SUCH DAMAGE.
10125 -#ifndef _FSL_DPMCP_CMD_H
10126 -#define _FSL_DPMCP_CMD_H
10128 -/* Minimal supported DPMCP Version */
10129 -#define DPMCP_MIN_VER_MAJOR 3
10130 -#define DPMCP_MIN_VER_MINOR 0
10132 -/* Command versioning */
10133 -#define DPMCP_CMD_BASE_VERSION 1
10134 -#define DPMCP_CMD_ID_OFFSET 4
10136 -#define DPMCP_CMD(id) (((id) << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION)
10139 -#define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800)
10140 -#define DPMCP_CMDID_OPEN DPMCP_CMD(0x80b)
10141 -#define DPMCP_CMDID_GET_API_VERSION DPMCP_CMD(0xa0b)
10143 -#define DPMCP_CMDID_RESET DPMCP_CMD(0x005)
10145 -struct dpmcp_cmd_open {
10149 -#endif /* _FSL_DPMCP_CMD_H */
10150 --- a/drivers/staging/fsl-mc/bus/dpmcp.h
10154 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10156 - * Redistribution and use in source and binary forms, with or without
10157 - * modification, are permitted provided that the following conditions are met:
10158 - * * Redistributions of source code must retain the above copyright
10159 - * notice, this list of conditions and the following disclaimer.
10160 - * * Redistributions in binary form must reproduce the above copyright
10161 - * notice, this list of conditions and the following disclaimer in the
10162 - * documentation and/or other materials provided with the distribution.
10163 - * * Neither the name of the above-listed copyright holders nor the
10164 - * names of any contributors may be used to endorse or promote products
10165 - * derived from this software without specific prior written permission.
10167 - * ALTERNATIVELY, this software may be distributed under the terms of the
10168 - * GNU General Public License ("GPL") as published by the Free Software
10169 - * Foundation, either version 2 of that License or (at your option) any
10172 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10173 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10174 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10175 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
10176 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
10177 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
10178 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
10179 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
10180 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
10181 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
10182 - * POSSIBILITY OF SUCH DAMAGE.
10184 -#ifndef __FSL_DPMCP_H
10185 -#define __FSL_DPMCP_H
10188 - * Data Path Management Command Portal API
10189 - * Contains initialization APIs and runtime control APIs for DPMCP
10194 -int dpmcp_open(struct fsl_mc_io *mc_io,
10199 -int dpmcp_close(struct fsl_mc_io *mc_io,
10203 -int dpmcp_get_api_version(struct fsl_mc_io *mc_io,
10208 -int dpmcp_reset(struct fsl_mc_io *mc_io,
10212 -#endif /* __FSL_DPMCP_H */
10213 --- a/drivers/staging/fsl-mc/bus/dpmng-cmd.h
10217 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10219 - * Redistribution and use in source and binary forms, with or without
10220 - * modification, are permitted provided that the following conditions are met:
10221 - * * Redistributions of source code must retain the above copyright
10222 - * notice, this list of conditions and the following disclaimer.
10223 - * * Redistributions in binary form must reproduce the above copyright
10224 - * notice, this list of conditions and the following disclaimer in the
10225 - * documentation and/or other materials provided with the distribution.
10226 - * * Neither the name of the above-listed copyright holders nor the
10227 - * names of any contributors may be used to endorse or promote products
10228 - * derived from this software without specific prior written permission.
10230 - * ALTERNATIVELY, this software may be distributed under the terms of the
10231 - * GNU General Public License ("GPL") as published by the Free Software
10232 - * Foundation, either version 2 of that License or (at your option) any
10235 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10236 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10237 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10238 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
10239 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
10240 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
10241 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
10242 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
10243 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
10244 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
10245 - * POSSIBILITY OF SUCH DAMAGE.
10251 - * defines portal commands
10255 -#ifndef __FSL_DPMNG_CMD_H
10256 -#define __FSL_DPMNG_CMD_H
10258 -/* Command versioning */
10259 -#define DPMNG_CMD_BASE_VERSION 1
10260 -#define DPMNG_CMD_ID_OFFSET 4
10262 -#define DPMNG_CMD(id) (((id) << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION)
10265 -#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831)
10267 -struct dpmng_rsp_get_version {
10269 - __le32 version_major;
10270 - __le32 version_minor;
10273 -#endif /* __FSL_DPMNG_CMD_H */
10274 --- a/drivers/staging/fsl-mc/bus/dprc-cmd.h
10278 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10280 - * Redistribution and use in source and binary forms, with or without
10281 - * modification, are permitted provided that the following conditions are met:
10282 - * * Redistributions of source code must retain the above copyright
10283 - * notice, this list of conditions and the following disclaimer.
10284 - * * Redistributions in binary form must reproduce the above copyright
10285 - * notice, this list of conditions and the following disclaimer in the
10286 - * documentation and/or other materials provided with the distribution.
10287 - * * Neither the name of the above-listed copyright holders nor the
10288 - * names of any contributors may be used to endorse or promote products
10289 - * derived from this software without specific prior written permission.
10291 - * ALTERNATIVELY, this software may be distributed under the terms of the
10292 - * GNU General Public License ("GPL") as published by the Free Software
10293 - * Foundation, either version 2 of that License or (at your option) any
10296 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10297 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10298 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10299 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
10300 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
10301 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
10302 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
10303 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
10304 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
10305 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
10306 - * POSSIBILITY OF SUCH DAMAGE.
10312 - * defines dprc portal commands
10316 -#ifndef _FSL_DPRC_CMD_H
10317 -#define _FSL_DPRC_CMD_H
10319 -/* Minimal supported DPRC Version */
10320 -#define DPRC_MIN_VER_MAJOR 6
10321 -#define DPRC_MIN_VER_MINOR 0
10323 -/* Command versioning */
10324 -#define DPRC_CMD_BASE_VERSION 1
10325 -#define DPRC_CMD_ID_OFFSET 4
10327 -#define DPRC_CMD(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION)
10330 -#define DPRC_CMDID_CLOSE DPRC_CMD(0x800)
10331 -#define DPRC_CMDID_OPEN DPRC_CMD(0x805)
10332 -#define DPRC_CMDID_GET_API_VERSION DPRC_CMD(0xa05)
10334 -#define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004)
10336 -#define DPRC_CMDID_SET_IRQ DPRC_CMD(0x010)
10337 -#define DPRC_CMDID_GET_IRQ DPRC_CMD(0x011)
10338 -#define DPRC_CMDID_SET_IRQ_ENABLE DPRC_CMD(0x012)
10339 -#define DPRC_CMDID_GET_IRQ_ENABLE DPRC_CMD(0x013)
10340 -#define DPRC_CMDID_SET_IRQ_MASK DPRC_CMD(0x014)
10341 -#define DPRC_CMDID_GET_IRQ_MASK DPRC_CMD(0x015)
10342 -#define DPRC_CMDID_GET_IRQ_STATUS DPRC_CMD(0x016)
10343 -#define DPRC_CMDID_CLEAR_IRQ_STATUS DPRC_CMD(0x017)
10345 -#define DPRC_CMDID_GET_CONT_ID DPRC_CMD(0x830)
10346 -#define DPRC_CMDID_GET_OBJ_COUNT DPRC_CMD(0x159)
10347 -#define DPRC_CMDID_GET_OBJ DPRC_CMD(0x15A)
10348 -#define DPRC_CMDID_GET_RES_COUNT DPRC_CMD(0x15B)
10349 -#define DPRC_CMDID_GET_OBJ_REG DPRC_CMD(0x15E)
10350 -#define DPRC_CMDID_SET_OBJ_IRQ DPRC_CMD(0x15F)
10351 -#define DPRC_CMDID_GET_OBJ_IRQ DPRC_CMD(0x160)
10353 -struct dprc_cmd_open {
10354 - __le32 container_id;
10357 -struct dprc_cmd_create_container {
10364 - __le32 portal_id;
10365 - /* cmd words 2-3 */
10369 -struct dprc_rsp_create_container {
10370 - /* response word 0 */
10372 - /* response word 1 */
10373 - __le32 child_container_id;
10375 - /* response word 2 */
10376 - __le64 child_portal_addr;
10379 -struct dprc_cmd_destroy_container {
10380 - __le32 child_container_id;
10383 -struct dprc_cmd_reset_container {
10384 - __le32 child_container_id;
10387 -struct dprc_cmd_set_irq {
10398 -struct dprc_cmd_get_irq {
10403 -struct dprc_rsp_get_irq {
10404 - /* response word 0 */
10407 - /* response word 1 */
10409 - /* response word 2 */
10414 -#define DPRC_ENABLE 0x1
10416 -struct dprc_cmd_set_irq_enable {
10422 -struct dprc_cmd_get_irq_enable {
10427 -struct dprc_rsp_get_irq_enable {
10431 -struct dprc_cmd_set_irq_mask {
10436 -struct dprc_cmd_get_irq_mask {
10441 -struct dprc_rsp_get_irq_mask {
10445 -struct dprc_cmd_get_irq_status {
10450 -struct dprc_rsp_get_irq_status {
10454 -struct dprc_cmd_clear_irq_status {
10459 -struct dprc_rsp_get_attributes {
10460 - /* response word 0 */
10461 - __le32 container_id;
10464 - /* response word 1 */
10466 - __le32 portal_id;
10469 -struct dprc_cmd_set_res_quota {
10471 - __le32 child_container_id;
10474 - /* cmd words 1-2 */
10478 -struct dprc_cmd_get_res_quota {
10480 - __le32 child_container_id;
10482 - /* cmd word 1-2 */
10486 -struct dprc_rsp_get_res_quota {
10491 -struct dprc_cmd_assign {
10493 - __le32 container_id;
10497 - __le32 id_base_align;
10498 - /* cmd word 2-3 */
10502 -struct dprc_cmd_unassign {
10504 - __le32 child_container_id;
10508 - __le32 id_base_align;
10509 - /* cmd word 2-3 */
10513 -struct dprc_rsp_get_pool_count {
10514 - __le32 pool_count;
10517 -struct dprc_cmd_get_pool {
10518 - __le32 pool_index;
10521 -struct dprc_rsp_get_pool {
10522 - /* response word 0 */
10524 - /* response word 1-2 */
10528 -struct dprc_rsp_get_obj_count {
10530 - __le32 obj_count;
10533 -struct dprc_cmd_get_obj {
10534 - __le32 obj_index;
10537 -struct dprc_rsp_get_obj {
10538 - /* response word 0 */
10541 - /* response word 1 */
10546 - /* response word 2 */
10547 - __le16 version_major;
10548 - __le16 version_minor;
10551 - /* response word 3-4 */
10553 - /* response word 5-6 */
10557 -struct dprc_cmd_get_obj_desc {
10561 - /* cmd word 1-2 */
10565 -struct dprc_rsp_get_obj_desc {
10566 - /* response word 0 */
10569 - /* response word 1 */
10574 - /* response word 2 */
10575 - __le16 version_major;
10576 - __le16 version_minor;
10579 - /* response word 3-4 */
10581 - /* response word 5-6 */
10585 -struct dprc_cmd_get_res_count {
10588 - /* cmd word 1-2 */
10592 -struct dprc_rsp_get_res_count {
10593 - __le32 res_count;
10596 -struct dprc_cmd_get_res_ids {
10604 - /* cmd word 2-3 */
10608 -struct dprc_rsp_get_res_ids {
10609 - /* response word 0 */
10613 - /* response word 1 */
10618 -struct dprc_cmd_get_obj_region {
10624 - /* cmd word 1-2 */
10626 - /* cmd word 3-4 */
10630 -struct dprc_rsp_get_obj_region {
10631 - /* response word 0 */
10633 - /* response word 1 */
10634 - __le64 base_addr;
10635 - /* response word 2 */
10639 -struct dprc_cmd_set_obj_label {
10643 - /* cmd word 1-2 */
10645 - /* cmd word 3-4 */
10649 -struct dprc_cmd_set_obj_irq {
10659 - /* cmd word 3-4 */
10663 -struct dprc_cmd_get_obj_irq {
10668 - /* cmd word 1-2 */
10672 -struct dprc_rsp_get_obj_irq {
10673 - /* response word 0 */
10676 - /* response word 1 */
10678 - /* response word 2 */
10683 -struct dprc_cmd_connect {
10686 - __le32 ep1_interface_id;
10689 - __le32 ep2_interface_id;
10690 - /* cmd word 2-3 */
10694 - __le32 committed_rate;
10695 - /* cmd word 5-6 */
10699 -struct dprc_cmd_disconnect {
10702 - __le32 interface_id;
10703 - /* cmd word 1-2 */
10707 -struct dprc_cmd_get_connection {
10710 - __le32 ep1_interface_id;
10711 - /* cmd word 1-2 */
10715 -struct dprc_rsp_get_connection {
10716 - /* response word 0-2 */
10718 - /* response word 3 */
10720 - __le32 ep2_interface_id;
10721 - /* response word 4-5 */
10723 - /* response word 6 */
10727 -#endif /* _FSL_DPRC_CMD_H */
10728 --- a/drivers/staging/fsl-mc/bus/dprc.h
10732 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10734 - * Redistribution and use in source and binary forms, with or without
10735 - * modification, are permitted provided that the following conditions are met:
10736 - * * Redistributions of source code must retain the above copyright
10737 - * notice, this list of conditions and the following disclaimer.
10738 - * * Redistributions in binary form must reproduce the above copyright
10739 - * notice, this list of conditions and the following disclaimer in the
10740 - * documentation and/or other materials provided with the distribution.
10741 - * * Neither the name of the above-listed copyright holders nor the
10742 - * names of any contributors may be used to endorse or promote products
10743 - * derived from this software without specific prior written permission.
10746 - * ALTERNATIVELY, this software may be distributed under the terms of the
10747 - * GNU General Public License ("GPL") as published by the Free Software
10748 - * Foundation, either version 2 of that License or (at your option) any
10751 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10752 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10753 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10754 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
10755 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
10756 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
10757 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
10758 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
10759 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
10760 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
10761 - * POSSIBILITY OF SUCH DAMAGE.
10763 -#ifndef _FSL_DPRC_H
10764 -#define _FSL_DPRC_H
10767 - * Data Path Resource Container API
10768 - * Contains DPRC API for managing and querying DPAA resources
10772 -struct fsl_mc_obj_desc;
10774 -int dprc_open(struct fsl_mc_io *mc_io,
10776 - int container_id,
10779 -int dprc_close(struct fsl_mc_io *mc_io,
10786 -#define DPRC_IRQ_INDEX 0
10788 -/* Number of dprc's IRQs */
10789 -#define DPRC_NUM_OF_IRQS 1
10791 -/* DPRC IRQ events */
10793 -/* IRQ event - Indicates that a new object added to the container */
10794 -#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001
10795 -/* IRQ event - Indicates that an object was removed from the container */
10796 -#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002
10797 -/* IRQ event - Indicates that resources added to the container */
10798 -#define DPRC_IRQ_EVENT_RES_ADDED 0x00000004
10799 -/* IRQ event - Indicates that resources removed from the container */
10800 -#define DPRC_IRQ_EVENT_RES_REMOVED 0x00000008
10802 - * IRQ event - Indicates that one of the descendant containers that opened by
10803 - * this container is destroyed
10805 -#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010
10808 - * IRQ event - Indicates that on one of the container's opened object is
10811 -#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020
10813 -/* Irq event - Indicates that object is created at the container */
10814 -#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040
10817 - * struct dprc_irq_cfg - IRQ configuration
10818 - * @paddr: Address that must be written to signal a message-based interrupt
10819 - * @val: Value to write into irq_addr address
10820 - * @irq_num: A user defined number associated with this IRQ
10822 -struct dprc_irq_cfg {
10823 - phys_addr_t paddr;
10828 -int dprc_set_irq(struct fsl_mc_io *mc_io,
10832 - struct dprc_irq_cfg *irq_cfg);
10834 -int dprc_get_irq(struct fsl_mc_io *mc_io,
10839 - struct dprc_irq_cfg *irq_cfg);
10841 -int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
10847 -int dprc_get_irq_enable(struct fsl_mc_io *mc_io,
10853 -int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
10859 -int dprc_get_irq_mask(struct fsl_mc_io *mc_io,
10865 -int dprc_get_irq_status(struct fsl_mc_io *mc_io,
10871 -int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
10878 - * struct dprc_attributes - Container attributes
10879 - * @container_id: Container's ID
10880 - * @icid: Container's ICID
10881 - * @portal_id: Container's portal ID
10882 - * @options: Container's options as set at container's creation
10884 -struct dprc_attributes {
10885 - int container_id;
10891 -int dprc_get_attributes(struct fsl_mc_io *mc_io,
10894 - struct dprc_attributes *attributes);
10896 -int dprc_get_obj_count(struct fsl_mc_io *mc_io,
10901 -int dprc_get_obj(struct fsl_mc_io *mc_io,
10905 - struct fsl_mc_obj_desc *obj_desc);
10907 -int dprc_get_obj_desc(struct fsl_mc_io *mc_io,
10912 - struct fsl_mc_obj_desc *obj_desc);
10914 -int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
10920 - struct dprc_irq_cfg *irq_cfg);
10922 -int dprc_get_obj_irq(struct fsl_mc_io *mc_io,
10929 - struct dprc_irq_cfg *irq_cfg);
10931 -int dprc_get_res_count(struct fsl_mc_io *mc_io,
10938 - * enum dprc_iter_status - Iteration status
10939 - * @DPRC_ITER_STATUS_FIRST: Perform first iteration
10940 - * @DPRC_ITER_STATUS_MORE: Indicates more/next iteration is needed
10941 - * @DPRC_ITER_STATUS_LAST: Indicates last iteration
10943 -enum dprc_iter_status {
10944 - DPRC_ITER_STATUS_FIRST = 0,
10945 - DPRC_ITER_STATUS_MORE = 1,
10946 - DPRC_ITER_STATUS_LAST = 2
10949 -/* Region flags */
10950 -/* Cacheable - Indicates that region should be mapped as cacheable */
10951 -#define DPRC_REGION_CACHEABLE 0x00000001
10954 - * enum dprc_region_type - Region type
10955 - * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region
10956 - * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region
10958 -enum dprc_region_type {
10959 - DPRC_REGION_TYPE_MC_PORTAL,
10960 - DPRC_REGION_TYPE_QBMAN_PORTAL
10964 - * struct dprc_region_desc - Mappable region descriptor
10965 - * @base_offset: Region offset from region's base address.
10966 - * For DPMCP and DPRC objects, region base is offset from SoC MC portals
10967 - * base address; For DPIO, region base is offset from SoC QMan portals
10969 - * @size: Region size (in bytes)
10970 - * @flags: Region attributes
10971 - * @type: Portal region type
10973 -struct dprc_region_desc {
10977 - enum dprc_region_type type;
10980 -int dprc_get_obj_region(struct fsl_mc_io *mc_io,
10986 - struct dprc_region_desc *region_desc);
10988 -int dprc_get_api_version(struct fsl_mc_io *mc_io,
10993 -int dprc_get_container_id(struct fsl_mc_io *mc_io,
10995 - int *container_id);
10997 -#endif /* _FSL_DPRC_H */
10999 --- a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
11000 +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c
11002 #include <linux/msi.h>
11003 #include <linux/of.h>
11004 #include <linux/of_irq.h>
11005 +#include <linux/fsl/mc.h>
11006 #include "fsl-mc-private.h"
11008 static struct irq_chip its_msi_irq_chip = {
11010 +++ b/include/linux/fsl/mc.h
11012 +/* SPDX-License-Identifier: GPL-2.0 */
11014 + * Freescale Management Complex (MC) bus public interface
11016 + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
11017 + * Author: German Rivera <German.Rivera@freescale.com>
11020 +#ifndef _FSL_MC_H_
11021 +#define _FSL_MC_H_
11023 +#include <linux/device.h>
11024 +#include <linux/mod_devicetable.h>
11025 +#include <linux/interrupt.h>
11026 +#include <linux/cdev.h>
11027 +#include <uapi/linux/fsl_mc.h>
11029 +#define FSL_MC_VENDOR_FREESCALE 0x1957
11031 +struct irq_domain;
11032 +struct msi_domain_info;
11034 +struct fsl_mc_device;
11038 + * struct fsl_mc_driver - MC object device driver object
11039 + * @driver: Generic device driver
11040 + * @match_id_table: table of supported device matching Ids
11041 + * @probe: Function called when a device is added
11042 + * @remove: Function called when a device is removed
11043 + * @shutdown: Function called at shutdown time to quiesce the device
11044 + * @suspend: Function called when a device is stopped
11045 + * @resume: Function called when a device is resumed
11047 + * Generic DPAA device driver object for device drivers that are registered
11048 + * with a DPRC bus. This structure is to be embedded in each device-specific
11049 + * driver structure.
11051 +struct fsl_mc_driver {
11052 + struct device_driver driver;
11053 + const struct fsl_mc_device_id *match_id_table;
11054 + int (*probe)(struct fsl_mc_device *dev);
11055 + int (*remove)(struct fsl_mc_device *dev);
11056 + void (*shutdown)(struct fsl_mc_device *dev);
11057 + int (*suspend)(struct fsl_mc_device *dev, pm_message_t state);
11058 + int (*resume)(struct fsl_mc_device *dev);
11061 +#define to_fsl_mc_driver(_drv) \
11062 + container_of(_drv, struct fsl_mc_driver, driver)
11064 +#define to_fsl_mc_bus(_mc_dev) \
11065 + container_of(_mc_dev, struct fsl_mc_bus, mc_dev)
11068 + * enum fsl_mc_pool_type - Types of allocatable MC bus resources
11070 + * Entries in these enum are used as indices in the array of resource
11071 + * pools of an fsl_mc_bus object.
11073 +enum fsl_mc_pool_type {
11074 + FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */
11075 + FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */
11076 + FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */
11080 + * NOTE: New resource pool types must be added before this entry
11082 + FSL_MC_NUM_POOL_TYPES
11086 + * struct fsl_mc_resource - MC generic resource
11087 + * @type: type of resource
11088 + * @id: unique MC resource Id within the resources of the same type
11089 + * @data: pointer to resource-specific data if the resource is currently
11090 + * allocated, or NULL if the resource is not currently allocated.
11091 + * @parent_pool: pointer to the parent resource pool from which this
11092 + * resource is allocated from.
11093 + * @node: Node in the free list of the corresponding resource pool
11095 + * NOTE: This structure is to be embedded as a field of specific
11096 + * MC resource structures.
11098 +struct fsl_mc_resource {
11099 + enum fsl_mc_pool_type type;
11102 + struct fsl_mc_resource_pool *parent_pool;
11103 + struct list_head node;
11107 + * struct fsl_mc_device_irq - MC object device message-based interrupt
11108 + * @msi_desc: pointer to MSI descriptor allocated by fsl_mc_msi_alloc_descs()
11109 + * @mc_dev: MC object device that owns this interrupt
11110 + * @dev_irq_index: device-relative IRQ index
11111 + * @resource: MC generic resource associated with the interrupt
11113 +struct fsl_mc_device_irq {
11114 + struct msi_desc *msi_desc;
11115 + struct fsl_mc_device *mc_dev;
11116 + u8 dev_irq_index;
11117 + struct fsl_mc_resource resource;
11120 +#define to_fsl_mc_irq(_mc_resource) \
11121 + container_of(_mc_resource, struct fsl_mc_device_irq, resource)
11123 +/* Opened state - Indicates that an object is open by at least one owner */
11124 +#define FSL_MC_OBJ_STATE_OPEN 0x00000001
11125 +/* Plugged state - Indicates that the object is plugged */
11126 +#define FSL_MC_OBJ_STATE_PLUGGED 0x00000002
11129 + * Shareability flag - Object flag indicating no memory shareability.
11130 + * the object generates memory accesses that are non coherent with other
11132 + * user is responsible for proper memory handling through IOMMU configuration.
11134 +#define FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001
11137 + * struct fsl_mc_obj_desc - Object descriptor
11138 + * @type: Type of object: NULL terminated string
11139 + * @id: ID of logical object resource
11140 + * @vendor: Object vendor identifier
11141 + * @ver_major: Major version number
11142 + * @ver_minor: Minor version number
11143 + * @irq_count: Number of interrupts supported by the object
11144 + * @region_count: Number of mappable regions supported by the object
11145 + * @state: Object state: combination of FSL_MC_OBJ_STATE_ states
11146 + * @label: Object label: NULL terminated string
11147 + * @flags: Object's flags
11149 +struct fsl_mc_obj_desc {
11163 + * Bit masks for a MC object device (struct fsl_mc_device) flags
11165 +#define FSL_MC_IS_DPRC 0x0001
11168 + * struct fsl_mc_device - MC object device object
11169 + * @dev: Linux driver model device object
11170 + * @dma_mask: Default DMA mask
11171 + * @flags: MC object device flags
11172 + * @icid: Isolation context ID for the device
11173 + * @mc_handle: MC handle for the corresponding MC object opened
11174 + * @mc_io: Pointer to MC IO object assigned to this device or
11176 + * @obj_desc: MC description of the DPAA device
11177 + * @regions: pointer to array of MMIO region entries
11178 + * @irqs: pointer to array of pointers to interrupts allocated to this device
11179 + * @resource: generic resource associated with this MC object device, if any.
11180 + * @driver_override: Driver name to force a match
11182 + * Generic device object for MC object devices that are "attached" to a
11186 + * - For a non-DPRC object its icid is the same as its parent DPRC's icid.
11187 + * - The SMMU notifier callback gets invoked after device_add() has been
11188 + * called for an MC object device, but before the device-specific probe
11189 + * callback gets called.
11190 + * - DP_OBJ_DPRC objects are the only MC objects that have built-in MC
11191 + * portals. For all other MC objects, their device drivers are responsible for
11192 + * allocating MC portals for them by calling fsl_mc_portal_allocate().
11193 + * - Some types of MC objects (e.g., DP_OBJ_DPBP, DP_OBJ_DPCON) are
11194 + * treated as resources that can be allocated/deallocated from the
11195 + * corresponding resource pool in the object's parent DPRC, using the
11196 + * fsl_mc_object_allocate()/fsl_mc_object_free() functions. These MC objects
11197 + * are known as "allocatable" objects. For them, the corresponding
11198 + * fsl_mc_device's 'resource' points to the associated resource object.
11199 + * For MC objects that are not allocatable (e.g., DP_OBJ_DPRC, DP_OBJ_DPNI),
11200 + * 'resource' is NULL.
11202 +struct fsl_mc_device {
11203 + struct device dev;
11208 + struct fsl_mc_io *mc_io;
11209 + struct fsl_mc_obj_desc obj_desc;
11210 + struct resource *regions;
11211 + struct fsl_mc_device_irq **irqs;
11212 + struct fsl_mc_resource *resource;
11213 + const char *driver_override;
11214 + struct device_link *consumer_link;
11217 +#define to_fsl_mc_device(_dev) \
11218 + container_of(_dev, struct fsl_mc_device, dev)
11220 +struct mc_cmd_header {
11229 +enum mc_cmd_status {
11230 + MC_CMD_STATUS_OK = 0x0, /* Completed successfully */
11231 + MC_CMD_STATUS_READY = 0x1, /* Ready to be processed */
11232 + MC_CMD_STATUS_AUTH_ERR = 0x3, /* Authentication error */
11233 + MC_CMD_STATUS_NO_PRIVILEGE = 0x4, /* No privilege */
11234 + MC_CMD_STATUS_DMA_ERR = 0x5, /* DMA or I/O error */
11235 + MC_CMD_STATUS_CONFIG_ERR = 0x6, /* Configuration error */
11236 + MC_CMD_STATUS_TIMEOUT = 0x7, /* Operation timed out */
11237 + MC_CMD_STATUS_NO_RESOURCE = 0x8, /* No resources */
11238 + MC_CMD_STATUS_NO_MEMORY = 0x9, /* No memory available */
11239 + MC_CMD_STATUS_BUSY = 0xA, /* Device is busy */
11240 + MC_CMD_STATUS_UNSUPPORTED_OP = 0xB, /* Unsupported operation */
11241 + MC_CMD_STATUS_INVALID_STATE = 0xC /* Invalid state */
11245 + * MC command flags
11248 +/* High priority flag */
11249 +#define MC_CMD_FLAG_PRI 0x80
11250 +/* Command completion flag */
11251 +#define MC_CMD_FLAG_INTR_DIS 0x01
11253 +static inline u64 mc_encode_cmd_header(u16 cmd_id,
11258 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&header;
11260 + hdr->cmd_id = cpu_to_le16(cmd_id);
11261 + hdr->token = cpu_to_le16(token);
11262 + hdr->status = MC_CMD_STATUS_READY;
11263 + if (cmd_flags & MC_CMD_FLAG_PRI)
11264 + hdr->flags_hw = MC_CMD_FLAG_PRI;
11265 + if (cmd_flags & MC_CMD_FLAG_INTR_DIS)
11266 + hdr->flags_sw = MC_CMD_FLAG_INTR_DIS;
11271 +static inline u16 mc_cmd_hdr_read_token(struct fsl_mc_command *cmd)
11273 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
11274 + u16 token = le16_to_cpu(hdr->token);
11279 +struct mc_rsp_create {
11280 + __le32 object_id;
11283 +struct mc_rsp_api_ver {
11284 + __le16 major_ver;
11285 + __le16 minor_ver;
11288 +static inline u32 mc_cmd_read_object_id(struct fsl_mc_command *cmd)
11290 + struct mc_rsp_create *rsp_params;
11292 + rsp_params = (struct mc_rsp_create *)cmd->params;
11293 + return le32_to_cpu(rsp_params->object_id);
11296 +static inline void mc_cmd_read_api_version(struct fsl_mc_command *cmd,
11300 + struct mc_rsp_api_ver *rsp_params;
11302 + rsp_params = (struct mc_rsp_api_ver *)cmd->params;
11303 + *major_ver = le16_to_cpu(rsp_params->major_ver);
11304 + *minor_ver = le16_to_cpu(rsp_params->minor_ver);
11308 + * Bit masks for a MC I/O object (struct fsl_mc_io) flags
11310 +#define FSL_MC_IO_ATOMIC_CONTEXT_PORTAL 0x0001
11313 + * struct fsl_mc_io - MC I/O object to be passed-in to mc_send_command()
11314 + * @dev: device associated with this Mc I/O object
11315 + * @flags: flags for mc_send_command()
11316 + * @portal_size: MC command portal size in bytes
11317 + * @portal_phys_addr: MC command portal physical address
11318 + * @portal_virt_addr: MC command portal virtual address
11319 + * @dpmcp_dev: pointer to the DPMCP device associated with the MC portal.
11321 + * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not
11323 + * @mutex: Mutex to serialize mc_send_command() calls that use the same MC
11324 + * portal, if the fsl_mc_io object was created with the
11325 + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag off. mc_send_command() calls for this
11326 + * fsl_mc_io object must be made only from non-atomic context.
11328 + * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is
11330 + * @spinlock: Spinlock to serialize mc_send_command() calls that use the same MC
11331 + * portal, if the fsl_mc_io object was created with the
11332 + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag on. mc_send_command() calls for this
11333 + * fsl_mc_io object can be made from atomic or non-atomic context.
11335 +struct fsl_mc_io {
11336 + struct device *dev;
11339 + phys_addr_t portal_phys_addr;
11340 + void __iomem *portal_virt_addr;
11341 + struct fsl_mc_device *dpmcp_dev;
11344 + * This field is only meaningful if the
11345 + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not set
11347 + struct mutex mutex; /* serializes mc_send_command() */
11350 + * This field is only meaningful if the
11351 + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is set
11353 + spinlock_t spinlock; /* serializes mc_send_command() */
11357 +int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd);
11359 +#ifdef CONFIG_FSL_MC_BUS
11360 +#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type)
11362 +/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */
11363 +#define dev_is_fsl_mc(_dev) (0)
11366 +/* Macro to check if a device is a container device */
11367 +#define fsl_mc_is_cont_dev(_dev) (to_fsl_mc_device(_dev)->flags & \
11370 +/* Macro to get the container device of a MC device */
11371 +#define fsl_mc_cont_dev(_dev) (fsl_mc_is_cont_dev(_dev) ? \
11372 + (_dev) : (_dev)->parent)
11374 +#define fsl_mc_is_dev_coherent(_dev) \
11375 + (!((to_fsl_mc_device(_dev))->obj_desc.flags & \
11376 + FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY))
11379 + * module_fsl_mc_driver() - Helper macro for drivers that don't do
11380 + * anything special in module init/exit. This eliminates a lot of
11381 + * boilerplate. Each module may only use this macro once, and
11382 + * calling it replaces module_init() and module_exit()
11384 +#define module_fsl_mc_driver(__fsl_mc_driver) \
11385 + module_driver(__fsl_mc_driver, fsl_mc_driver_register, \
11386 + fsl_mc_driver_unregister)
11388 +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev);
11391 + * Macro to avoid include chaining to get THIS_MODULE
11393 +#define fsl_mc_driver_register(drv) \
11394 + __fsl_mc_driver_register(drv, THIS_MODULE)
11396 +int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver,
11397 + struct module *owner);
11399 +void fsl_mc_driver_unregister(struct fsl_mc_driver *driver);
11401 +int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
11403 + struct fsl_mc_io **new_mc_io);
11405 +void fsl_mc_portal_free(struct fsl_mc_io *mc_io);
11407 +int fsl_mc_portal_reset(struct fsl_mc_io *mc_io);
11409 +int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
11410 + enum fsl_mc_pool_type pool_type,
11411 + struct fsl_mc_device **new_mc_adev);
11413 +void fsl_mc_object_free(struct fsl_mc_device *mc_adev);
11415 +struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
11416 + struct msi_domain_info *info,
11417 + struct irq_domain *parent);
11419 +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev);
11421 +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev);
11423 +extern struct bus_type fsl_mc_bus_type;
11425 +extern struct device_type fsl_mc_bus_dprc_type;
11426 +extern struct device_type fsl_mc_bus_dpni_type;
11427 +extern struct device_type fsl_mc_bus_dpio_type;
11428 +extern struct device_type fsl_mc_bus_dpsw_type;
11429 +extern struct device_type fsl_mc_bus_dpdmux_type;
11430 +extern struct device_type fsl_mc_bus_dpbp_type;
11431 +extern struct device_type fsl_mc_bus_dpcon_type;
11432 +extern struct device_type fsl_mc_bus_dpmcp_type;
11433 +extern struct device_type fsl_mc_bus_dpmac_type;
11434 +extern struct device_type fsl_mc_bus_dprtc_type;
11435 +extern struct device_type fsl_mc_bus_dpseci_type;
11436 +extern struct device_type fsl_mc_bus_dpdcei_type;
11437 +extern struct device_type fsl_mc_bus_dpaiop_type;
11438 +extern struct device_type fsl_mc_bus_dpci_type;
11439 +extern struct device_type fsl_mc_bus_dpdmai_type;
11441 +static inline bool is_fsl_mc_bus_dprc(const struct fsl_mc_device *mc_dev)
11443 + return mc_dev->dev.type == &fsl_mc_bus_dprc_type;
11446 +static inline bool is_fsl_mc_bus_dpni(const struct fsl_mc_device *mc_dev)
11448 + return mc_dev->dev.type == &fsl_mc_bus_dpni_type;
11451 +static inline bool is_fsl_mc_bus_dpio(const struct fsl_mc_device *mc_dev)
11453 + return mc_dev->dev.type == &fsl_mc_bus_dpio_type;
11456 +static inline bool is_fsl_mc_bus_dpsw(const struct fsl_mc_device *mc_dev)
11458 + return mc_dev->dev.type == &fsl_mc_bus_dpsw_type;
11461 +static inline bool is_fsl_mc_bus_dpdmux(const struct fsl_mc_device *mc_dev)
11463 + return mc_dev->dev.type == &fsl_mc_bus_dpdmux_type;
11466 +static inline bool is_fsl_mc_bus_dpbp(const struct fsl_mc_device *mc_dev)
11468 + return mc_dev->dev.type == &fsl_mc_bus_dpbp_type;
11471 +static inline bool is_fsl_mc_bus_dpcon(const struct fsl_mc_device *mc_dev)
11473 + return mc_dev->dev.type == &fsl_mc_bus_dpcon_type;
11476 +static inline bool is_fsl_mc_bus_dpmcp(const struct fsl_mc_device *mc_dev)
11478 + return mc_dev->dev.type == &fsl_mc_bus_dpmcp_type;
11481 +static inline bool is_fsl_mc_bus_dpmac(const struct fsl_mc_device *mc_dev)
11483 + return mc_dev->dev.type == &fsl_mc_bus_dpmac_type;
11486 +static inline bool is_fsl_mc_bus_dprtc(const struct fsl_mc_device *mc_dev)
11488 + return mc_dev->dev.type == &fsl_mc_bus_dprtc_type;
11491 +static inline bool is_fsl_mc_bus_dpseci(const struct fsl_mc_device *mc_dev)
11493 + return mc_dev->dev.type == &fsl_mc_bus_dpseci_type;
11496 +static inline bool is_fsl_mc_bus_dpdcei(const struct fsl_mc_device *mc_dev)
11498 + return mc_dev->dev.type == &fsl_mc_bus_dpdcei_type;
11501 +static inline bool is_fsl_mc_bus_dpaiop(const struct fsl_mc_device *mc_dev)
11503 + return mc_dev->dev.type == &fsl_mc_bus_dpaiop_type;
11506 +static inline bool is_fsl_mc_bus_dpci(const struct fsl_mc_device *mc_dev)
11508 + return mc_dev->dev.type == &fsl_mc_bus_dpci_type;
11511 +static inline bool is_fsl_mc_bus_dpdmai(const struct fsl_mc_device *mc_dev)
11513 + return mc_dev->dev.type == &fsl_mc_bus_dpdmai_type;
11517 + * Data Path Resource Container (DPRC) API
11520 +/* Minimal supported DPRC Version */
11521 +#define DPRC_MIN_VER_MAJOR 6
11522 +#define DPRC_MIN_VER_MINOR 0
11524 +/* DPRC command versioning */
11525 +#define DPRC_CMD_BASE_VERSION 1
11526 +#define DPRC_CMD_2ND_VERSION 2
11527 +#define DPRC_CMD_ID_OFFSET 4
11529 +#define DPRC_CMD(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION)
11530 +#define DPRC_CMD_V2(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_2ND_VERSION)
11532 +/* DPRC command IDs */
11533 +#define DPRC_CMDID_CLOSE DPRC_CMD(0x800)
11534 +#define DPRC_CMDID_OPEN DPRC_CMD(0x805)
11535 +#define DPRC_CMDID_GET_API_VERSION DPRC_CMD(0xa05)
11537 +#define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004)
11538 +#define DPRC_CMDID_RESET_CONT DPRC_CMD(0x005)
11540 +#define DPRC_CMDID_SET_IRQ DPRC_CMD(0x010)
11541 +#define DPRC_CMDID_SET_IRQ_ENABLE DPRC_CMD(0x012)
11542 +#define DPRC_CMDID_SET_IRQ_MASK DPRC_CMD(0x014)
11543 +#define DPRC_CMDID_GET_IRQ_STATUS DPRC_CMD(0x016)
11544 +#define DPRC_CMDID_CLEAR_IRQ_STATUS DPRC_CMD(0x017)
11546 +#define DPRC_CMDID_GET_CONT_ID DPRC_CMD(0x830)
11547 +#define DPRC_CMDID_GET_OBJ_COUNT DPRC_CMD(0x159)
11548 +#define DPRC_CMDID_GET_OBJ DPRC_CMD(0x15A)
11549 +#define DPRC_CMDID_GET_OBJ_REG DPRC_CMD_V2(0x15E)
11550 +#define DPRC_CMDID_SET_OBJ_IRQ DPRC_CMD(0x15F)
11552 +struct dprc_cmd_open {
11553 + __le32 container_id;
11556 +struct dprc_cmd_reset_container {
11557 + __le32 child_container_id;
11560 +struct dprc_cmd_set_irq {
11571 +#define DPRC_ENABLE 0x1
11573 +struct dprc_cmd_set_irq_enable {
11579 +struct dprc_cmd_set_irq_mask {
11584 +struct dprc_cmd_get_irq_status {
11589 +struct dprc_rsp_get_irq_status {
11593 +struct dprc_cmd_clear_irq_status {
11598 +struct dprc_rsp_get_attributes {
11599 + /* response word 0 */
11600 + __le32 container_id;
11602 + /* response word 1 */
11604 + __le32 portal_id;
11607 +struct dprc_rsp_get_obj_count {
11609 + __le32 obj_count;
11612 +struct dprc_cmd_get_obj {
11613 + __le32 obj_index;
11616 +struct dprc_rsp_get_obj {
11617 + /* response word 0 */
11620 + /* response word 1 */
11625 + /* response word 2 */
11626 + __le16 version_major;
11627 + __le16 version_minor;
11630 + /* response word 3-4 */
11632 + /* response word 5-6 */
11636 +struct dprc_cmd_get_obj_region {
11642 + /* cmd word 1-2 */
11644 + /* cmd word 3-4 */
11648 +struct dprc_rsp_get_obj_region {
11649 + /* response word 0 */
11651 + /* response word 1 */
11652 + __le32 base_offset;
11654 + /* response word 2 */
11658 + /* response word 3 */
11661 + /* response word 4 */
11662 + __le64 base_addr;
11665 +struct dprc_cmd_set_obj_irq {
11675 + /* cmd word 3-4 */
11680 + * DPRC API for managing and querying DPAA resources
11682 +int dprc_open(struct fsl_mc_io *mc_io,
11684 + int container_id,
11687 +int dprc_close(struct fsl_mc_io *mc_io,
11691 +/* DPRC IRQ events */
11693 +/* IRQ event - Indicates that a new object added to the container */
11694 +#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001
11695 +/* IRQ event - Indicates that an object was removed from the container */
11696 +#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002
11698 + * IRQ event - Indicates that one of the descendant containers that opened by
11699 + * this container is destroyed
11701 +#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010
11704 + * IRQ event - Indicates that on one of the container's opened object is
11707 +#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020
11709 +/* Irq event - Indicates that object is created at the container */
11710 +#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040
11713 + * struct dprc_irq_cfg - IRQ configuration
11714 + * @paddr: Address that must be written to signal a message-based interrupt
11715 + * @val: Value to write into irq_addr address
11716 + * @irq_num: A user defined number associated with this IRQ
11718 +struct dprc_irq_cfg {
11719 + phys_addr_t paddr;
11724 +int dprc_set_irq(struct fsl_mc_io *mc_io,
11728 + struct dprc_irq_cfg *irq_cfg);
11730 +int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
11736 +int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
11742 +int dprc_get_irq_status(struct fsl_mc_io *mc_io,
11748 +int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
11755 + * struct dprc_attributes - Container attributes
11756 + * @container_id: Container's ID
11757 + * @icid: Container's ICID
11758 + * @portal_id: Container's portal ID
11759 + * @options: Container's options as set at container's creation
11761 +struct dprc_attributes {
11762 + int container_id;
11768 +int dprc_get_attributes(struct fsl_mc_io *mc_io,
11771 + struct dprc_attributes *attributes);
11773 +int dprc_get_obj_count(struct fsl_mc_io *mc_io,
11778 +int dprc_get_obj(struct fsl_mc_io *mc_io,
11782 + struct fsl_mc_obj_desc *obj_desc);
11784 +int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
11790 + struct dprc_irq_cfg *irq_cfg);
11792 +/* Region flags */
11793 +/* Cacheable - Indicates that region should be mapped as cacheable */
11794 +#define DPRC_REGION_CACHEABLE 0x00000001
11795 +#define DPRC_REGION_SHAREABLE 0x00000002
11798 + * enum dprc_region_type - Region type
11799 + * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region
11800 + * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region
11802 +enum dprc_region_type {
11803 + DPRC_REGION_TYPE_MC_PORTAL,
11804 + DPRC_REGION_TYPE_QBMAN_PORTAL,
11805 + DPRC_REGION_TYPE_QBMAN_MEM_BACKED_PORTAL
11809 + * struct dprc_region_desc - Mappable region descriptor
11810 + * @base_offset: Region offset from region's base address.
11811 + * For DPMCP and DPRC objects, region base is offset from SoC MC portals
11812 + * base address; For DPIO, region base is offset from SoC QMan portals
11814 + * @size: Region size (in bytes)
11815 + * @flags: Region attributes
11816 + * @type: Portal region type
11818 +struct dprc_region_desc {
11822 + enum dprc_region_type type;
11823 + u64 base_address;
11826 +int dprc_get_obj_region(struct fsl_mc_io *mc_io,
11832 + struct dprc_region_desc *region_desc);
11834 +int dprc_get_api_version(struct fsl_mc_io *mc_io,
11839 +int dprc_get_container_id(struct fsl_mc_io *mc_io,
11841 + int *container_id);
11843 +int dprc_reset_container(struct fsl_mc_io *mc_io,
11846 + int child_container_id);
11849 + * Data Path Buffer Pool (DPBP) API
11850 + * Contains initialization APIs and runtime control APIs for DPBP
11853 +int dpbp_open(struct fsl_mc_io *mc_io,
11858 +int dpbp_close(struct fsl_mc_io *mc_io,
11862 +int dpbp_enable(struct fsl_mc_io *mc_io,
11866 +int dpbp_disable(struct fsl_mc_io *mc_io,
11870 +int dpbp_reset(struct fsl_mc_io *mc_io,
11875 + * struct dpbp_attr - Structure representing DPBP attributes
11876 + * @id: DPBP object ID
11877 + * @bpid: Hardware buffer pool ID; should be used as an argument in
11878 + * acquire/release operations on buffers
11880 +struct dpbp_attr {
11885 +int dpbp_get_attributes(struct fsl_mc_io *mc_io,
11888 + struct dpbp_attr *attr);
11890 +/* Data Path Concentrator (DPCON) API
11891 + * Contains initialization APIs and runtime control APIs for DPCON
11895 + * Use it to disable notifications; see dpcon_set_notification()
11897 +#define DPCON_INVALID_DPIO_ID (int)(-1)
11899 +int dpcon_open(struct fsl_mc_io *mc_io,
11904 +int dpcon_close(struct fsl_mc_io *mc_io,
11908 +int dpcon_enable(struct fsl_mc_io *mc_io,
11912 +int dpcon_disable(struct fsl_mc_io *mc_io,
11916 +int dpcon_reset(struct fsl_mc_io *mc_io,
11921 + * struct dpcon_attr - Structure representing DPCON attributes
11922 + * @id: DPCON object ID
11923 + * @qbman_ch_id: Channel ID to be used by dequeue operation
11924 + * @num_priorities: Number of priorities for the DPCON channel (1-8)
11926 +struct dpcon_attr {
11929 + u8 num_priorities;
11932 +int dpcon_get_attributes(struct fsl_mc_io *mc_io,
11935 + struct dpcon_attr *attr);
11938 + * struct dpcon_notification_cfg - Structure representing notification params
11939 + * @dpio_id: DPIO object ID; must be configured with a notification channel;
11940 + * to disable notifications set it to 'DPCON_INVALID_DPIO_ID';
11941 + * @priority: Priority selection within the DPIO channel; valid values
11942 + * are 0-7, depending on the number of priorities in that channel
11943 + * @user_ctx: User context value provided with each CDAN message
11945 +struct dpcon_notification_cfg {
11951 +int dpcon_set_notification(struct fsl_mc_io *mc_io,
11954 + struct dpcon_notification_cfg *cfg);
11956 +struct irq_domain;
11957 +struct msi_domain_info;
11960 + * Maximum number of total IRQs that can be pre-allocated for an MC bus'
11963 +#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256
11966 + * struct fsl_mc_resource_pool - Pool of MC resources of a given
11968 + * @type: type of resources in the pool
11969 + * @max_count: maximum number of resources in the pool
11970 + * @free_count: number of free resources in the pool
11971 + * @mutex: mutex to serialize access to the pool's free list
11972 + * @free_list: anchor node of list of free resources in the pool
11973 + * @mc_bus: pointer to the MC bus that owns this resource pool
11975 +struct fsl_mc_resource_pool {
11976 + enum fsl_mc_pool_type type;
11979 + struct mutex mutex; /* serializes access to free_list */
11980 + struct list_head free_list;
11981 + struct fsl_mc_bus *mc_bus;
11985 + * struct fsl_mc_restool - information associated with a restool device file
11986 + * @cdev: struct char device linked to the root dprc
11987 + * @dev: dev_t for the char device to be added
11988 + * @device: newly created device in /dev
11989 + * @mutex: mutex lock to serialize the open/release operations
11990 + * @local_instance_in_use: local MC I/O instance in use or not
11991 + * @dynamic_instance_count: number of dynamically created MC I/O instances
11993 +struct fsl_mc_restool {
11994 + struct cdev cdev;
11996 + struct device *device;
11997 + struct mutex mutex; /* serialize open/release operations */
11998 + bool local_instance_in_use;
11999 + u32 dynamic_instance_count;
12003 + * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC
12004 + * @mc_dev: fsl-mc device for the bus device itself.
12005 + * @resource_pools: array of resource pools (one pool per resource type)
12006 + * for this MC bus. These resources represent allocatable entities
12007 + * from the physical DPRC.
12008 + * @irq_resources: Pointer to array of IRQ objects for the IRQ pool
12009 + * @scan_mutex: Serializes bus scanning
12010 + * @dprc_attr: DPRC attributes
12011 + * @restool_misc: struct that abstracts the interaction with userspace restool
12013 +struct fsl_mc_bus {
12014 + struct fsl_mc_device mc_dev;
12015 + struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES];
12016 + struct fsl_mc_device_irq *irq_resources;
12017 + struct mutex scan_mutex; /* serializes bus scanning */
12018 + struct dprc_attributes dprc_attr;
12019 + struct fsl_mc_restool restool_misc;
12022 +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
12023 + const char *driver_override,
12024 + unsigned int *total_irq_count);
12026 +int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
12027 + struct irq_domain **mc_msi_domain);
12029 +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
12030 + unsigned int irq_count);
12032 +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus);
12034 +void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
12036 +void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
12038 +void fsl_mc_get_root_dprc(struct device *dev, struct device **root_dprc_dev);
12040 +#endif /* _FSL_MC_H_ */
12042 +++ b/include/uapi/linux/fsl_mc.h
12044 +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
12046 + * Management Complex (MC) userspace public interface
12048 + * Copyright 2018 NXP
12051 +#ifndef _UAPI_FSL_MC_H_
12052 +#define _UAPI_FSL_MC_H_
12054 +#define MC_CMD_NUM_OF_PARAMS 7
12057 + * struct fsl_mc_command - Management Complex (MC) command structure
12058 + * @header: MC command header
12059 + * @params: MC command parameters
12061 + * Used by RESTOOL_SEND_MC_COMMAND
12063 +struct fsl_mc_command {
12065 + __u64 params[MC_CMD_NUM_OF_PARAMS];
12068 +#define RESTOOL_IOCTL_TYPE 'R'
12069 +#define RESTOOL_IOCTL_SEQ 0xE0
12071 +#define RESTOOL_SEND_MC_COMMAND \
12072 + _IOWR(RESTOOL_IOCTL_TYPE, RESTOOL_IOCTL_SEQ, struct fsl_mc_command)
12074 +#endif /* _UAPI_FSL_MC_H_ */