layerscape: update patches-4.14 to LSDK 19.03
[openwrt/staging/chunkeey.git] / target / linux / layerscape / patches-4.14 / 708-mc-bus-support-layerscape.patch
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
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 This is an integrated patch of mc-bus for layerscape
10
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>
28 ---
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
87
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
92 peripherals.
93
94 +source "drivers/bus/fsl-mc/Kconfig"
95 +
96 endmenu
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
101
102 obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o
103 +
104 +# DPAA2 fsl-mc bus
105 +obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
106 +
107 obj-$(CONFIG_IMX_WEIM) += imx-weim.o
108 obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o
109 obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o
110 --- /dev/null
111 +++ b/drivers/bus/fsl-mc/Kconfig
112 @@ -0,0 +1,23 @@
113 +# SPDX-License-Identifier: GPL-2.0
114 +#
115 +# DPAA2 fsl-mc bus
116 +#
117 +# Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
118 +#
119 +
120 +config FSL_MC_BUS
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
124 + help
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.
129 +
130 +config FSL_MC_RESTOOL
131 + bool "Management Complex (MC) restool support"
132 + depends on FSL_MC_BUS
133 + help
134 + Provides kernel support for the Management Complex resource
135 + manager user-space tool - restool.
136 --- /dev/null
137 +++ b/drivers/bus/fsl-mc/Makefile
138 @@ -0,0 +1,21 @@
139 +# SPDX-License-Identifier: GPL-2.0
140 +#
141 +# Freescale Management Complex (MC) bus drivers
142 +#
143 +# Copyright (C) 2014 Freescale Semiconductor, Inc.
144 +#
145 +obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o
146 +
147 +mc-bus-driver-objs := fsl-mc-bus.o \
148 + mc-sys.o \
149 + mc-io.o \
150 + dpbp.o \
151 + dpcon.o \
152 + dprc.o \
153 + dprc-driver.o \
154 + fsl-mc-allocator.o \
155 + fsl-mc-msi.o \
156 + dpmcp.o
157 +
158 +# MC restool kernel support
159 +obj-$(CONFIG_FSL_MC_RESTOOL) += fsl-mc-restool.o
160 --- a/drivers/staging/fsl-mc/bus/dpbp.c
161 +++ /dev/null
162 @@ -1,253 +0,0 @@
163 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
164 -/*
165 - * Copyright 2013-2016 Freescale Semiconductor Inc.
166 - *
167 - */
168 -#include <linux/kernel.h>
169 -#include "../include/mc.h"
170 -#include "../include/dpbp.h"
171 -
172 -#include "dpbp-cmd.h"
173 -
174 -/**
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
180 - *
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
188 - *
189 - * Return: '0' on Success; Error code otherwise.
190 - */
191 -int dpbp_open(struct fsl_mc_io *mc_io,
192 - u32 cmd_flags,
193 - int dpbp_id,
194 - u16 *token)
195 -{
196 - struct mc_command cmd = { 0 };
197 - struct dpbp_cmd_open *cmd_params;
198 - int err;
199 -
200 - /* prepare command */
201 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN,
202 - cmd_flags, 0);
203 - cmd_params = (struct dpbp_cmd_open *)cmd.params;
204 - cmd_params->dpbp_id = cpu_to_le32(dpbp_id);
205 -
206 - /* send command to mc*/
207 - err = mc_send_command(mc_io, &cmd);
208 - if (err)
209 - return err;
210 -
211 - /* retrieve response parameters */
212 - *token = mc_cmd_hdr_read_token(&cmd);
213 -
214 - return err;
215 -}
216 -EXPORT_SYMBOL(dpbp_open);
217 -
218 -/**
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
223 - *
224 - * After this function is called, no further operations are
225 - * allowed on the object without opening a new control session.
226 - *
227 - * Return: '0' on Success; Error code otherwise.
228 - */
229 -int dpbp_close(struct fsl_mc_io *mc_io,
230 - u32 cmd_flags,
231 - u16 token)
232 -{
233 - struct mc_command cmd = { 0 };
234 -
235 - /* prepare command */
236 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags,
237 - token);
238 -
239 - /* send command to mc*/
240 - return mc_send_command(mc_io, &cmd);
241 -}
242 -EXPORT_SYMBOL(dpbp_close);
243 -
244 -/**
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
249 - *
250 - * Return: '0' on Success; Error code otherwise.
251 - */
252 -int dpbp_enable(struct fsl_mc_io *mc_io,
253 - u32 cmd_flags,
254 - u16 token)
255 -{
256 - struct mc_command cmd = { 0 };
257 -
258 - /* prepare command */
259 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags,
260 - token);
261 -
262 - /* send command to mc*/
263 - return mc_send_command(mc_io, &cmd);
264 -}
265 -EXPORT_SYMBOL(dpbp_enable);
266 -
267 -/**
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
272 - *
273 - * Return: '0' on Success; Error code otherwise.
274 - */
275 -int dpbp_disable(struct fsl_mc_io *mc_io,
276 - u32 cmd_flags,
277 - u16 token)
278 -{
279 - struct mc_command cmd = { 0 };
280 -
281 - /* prepare command */
282 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE,
283 - cmd_flags, token);
284 -
285 - /* send command to mc*/
286 - return mc_send_command(mc_io, &cmd);
287 -}
288 -EXPORT_SYMBOL(dpbp_disable);
289 -
290 -/**
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
296 - *
297 - * Return: '0' on Success; Error code otherwise.
298 - */
299 -int dpbp_is_enabled(struct fsl_mc_io *mc_io,
300 - u32 cmd_flags,
301 - u16 token,
302 - int *en)
303 -{
304 - struct mc_command cmd = { 0 };
305 - struct dpbp_rsp_is_enabled *rsp_params;
306 - int err;
307 - /* prepare command */
308 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_IS_ENABLED, cmd_flags,
309 - token);
310 -
311 - /* send command to mc*/
312 - err = mc_send_command(mc_io, &cmd);
313 - if (err)
314 - return err;
315 -
316 - /* retrieve response parameters */
317 - rsp_params = (struct dpbp_rsp_is_enabled *)cmd.params;
318 - *en = rsp_params->enabled & DPBP_ENABLE;
319 -
320 - return 0;
321 -}
322 -EXPORT_SYMBOL(dpbp_is_enabled);
323 -
324 -/**
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
329 - *
330 - * Return: '0' on Success; Error code otherwise.
331 - */
332 -int dpbp_reset(struct fsl_mc_io *mc_io,
333 - u32 cmd_flags,
334 - u16 token)
335 -{
336 - struct mc_command cmd = { 0 };
337 -
338 - /* prepare command */
339 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET,
340 - cmd_flags, token);
341 -
342 - /* send command to mc*/
343 - return mc_send_command(mc_io, &cmd);
344 -}
345 -EXPORT_SYMBOL(dpbp_reset);
346 -
347 -/**
348 - * dpbp_get_attributes - Retrieve DPBP attributes.
349 - *
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
354 - *
355 - * Return: '0' on Success; Error code otherwise.
356 - */
357 -int dpbp_get_attributes(struct fsl_mc_io *mc_io,
358 - u32 cmd_flags,
359 - u16 token,
360 - struct dpbp_attr *attr)
361 -{
362 - struct mc_command cmd = { 0 };
363 - struct dpbp_rsp_get_attributes *rsp_params;
364 - int err;
365 -
366 - /* prepare command */
367 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR,
368 - cmd_flags, token);
369 -
370 - /* send command to mc*/
371 - err = mc_send_command(mc_io, &cmd);
372 - if (err)
373 - return err;
374 -
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);
379 -
380 - return 0;
381 -}
382 -EXPORT_SYMBOL(dpbp_get_attributes);
383 -
384 -/**
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
390 - *
391 - * Return: '0' on Success; Error code otherwise.
392 - */
393 -int dpbp_get_api_version(struct fsl_mc_io *mc_io,
394 - u32 cmd_flags,
395 - u16 *major_ver,
396 - u16 *minor_ver)
397 -{
398 - struct mc_command cmd = { 0 };
399 - int err;
400 -
401 - /* prepare command */
402 - cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_API_VERSION,
403 - cmd_flags, 0);
404 -
405 - /* send command to mc */
406 - err = mc_send_command(mc_io, &cmd);
407 - if (err)
408 - return err;
409 -
410 - /* retrieve response parameters */
411 - mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
412 -
413 - return 0;
414 -}
415 -EXPORT_SYMBOL(dpbp_get_api_version);
416 --- /dev/null
417 +++ b/drivers/bus/fsl-mc/dpbp.c
418 @@ -0,0 +1,186 @@
419 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
420 +/*
421 + * Copyright 2013-2016 Freescale Semiconductor Inc.
422 + *
423 + */
424 +#include <linux/kernel.h>
425 +#include <linux/fsl/mc.h>
426 +#include <linux/fsl/mc.h>
427 +
428 +#include "fsl-mc-private.h"
429 +
430 +/**
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
436 + *
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
444 + *
445 + * Return: '0' on Success; Error code otherwise.
446 + */
447 +int dpbp_open(struct fsl_mc_io *mc_io,
448 + u32 cmd_flags,
449 + int dpbp_id,
450 + u16 *token)
451 +{
452 + struct fsl_mc_command cmd = { 0 };
453 + struct dpbp_cmd_open *cmd_params;
454 + int err;
455 +
456 + /* prepare command */
457 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN,
458 + cmd_flags, 0);
459 + cmd_params = (struct dpbp_cmd_open *)cmd.params;
460 + cmd_params->dpbp_id = cpu_to_le32(dpbp_id);
461 +
462 + /* send command to mc*/
463 + err = mc_send_command(mc_io, &cmd);
464 + if (err)
465 + return err;
466 +
467 + /* retrieve response parameters */
468 + *token = mc_cmd_hdr_read_token(&cmd);
469 +
470 + return err;
471 +}
472 +EXPORT_SYMBOL_GPL(dpbp_open);
473 +
474 +/**
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
479 + *
480 + * After this function is called, no further operations are
481 + * allowed on the object without opening a new control session.
482 + *
483 + * Return: '0' on Success; Error code otherwise.
484 + */
485 +int dpbp_close(struct fsl_mc_io *mc_io,
486 + u32 cmd_flags,
487 + u16 token)
488 +{
489 + struct fsl_mc_command cmd = { 0 };
490 +
491 + /* prepare command */
492 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags,
493 + token);
494 +
495 + /* send command to mc*/
496 + return mc_send_command(mc_io, &cmd);
497 +}
498 +EXPORT_SYMBOL_GPL(dpbp_close);
499 +
500 +/**
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
505 + *
506 + * Return: '0' on Success; Error code otherwise.
507 + */
508 +int dpbp_enable(struct fsl_mc_io *mc_io,
509 + u32 cmd_flags,
510 + u16 token)
511 +{
512 + struct fsl_mc_command cmd = { 0 };
513 +
514 + /* prepare command */
515 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags,
516 + token);
517 +
518 + /* send command to mc*/
519 + return mc_send_command(mc_io, &cmd);
520 +}
521 +EXPORT_SYMBOL_GPL(dpbp_enable);
522 +
523 +/**
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
528 + *
529 + * Return: '0' on Success; Error code otherwise.
530 + */
531 +int dpbp_disable(struct fsl_mc_io *mc_io,
532 + u32 cmd_flags,
533 + u16 token)
534 +{
535 + struct fsl_mc_command cmd = { 0 };
536 +
537 + /* prepare command */
538 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE,
539 + cmd_flags, token);
540 +
541 + /* send command to mc*/
542 + return mc_send_command(mc_io, &cmd);
543 +}
544 +EXPORT_SYMBOL_GPL(dpbp_disable);
545 +
546 +/**
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
551 + *
552 + * Return: '0' on Success; Error code otherwise.
553 + */
554 +int dpbp_reset(struct fsl_mc_io *mc_io,
555 + u32 cmd_flags,
556 + u16 token)
557 +{
558 + struct fsl_mc_command cmd = { 0 };
559 +
560 + /* prepare command */
561 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET,
562 + cmd_flags, token);
563 +
564 + /* send command to mc*/
565 + return mc_send_command(mc_io, &cmd);
566 +}
567 +EXPORT_SYMBOL_GPL(dpbp_reset);
568 +
569 +/**
570 + * dpbp_get_attributes - Retrieve DPBP attributes.
571 + *
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
576 + *
577 + * Return: '0' on Success; Error code otherwise.
578 + */
579 +int dpbp_get_attributes(struct fsl_mc_io *mc_io,
580 + u32 cmd_flags,
581 + u16 token,
582 + struct dpbp_attr *attr)
583 +{
584 + struct fsl_mc_command cmd = { 0 };
585 + struct dpbp_rsp_get_attributes *rsp_params;
586 + int err;
587 +
588 + /* prepare command */
589 + cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR,
590 + cmd_flags, token);
591 +
592 + /* send command to mc*/
593 + err = mc_send_command(mc_io, &cmd);
594 + if (err)
595 + return err;
596 +
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);
601 +
602 + return 0;
603 +}
604 +EXPORT_SYMBOL_GPL(dpbp_get_attributes);
605 --- a/drivers/staging/fsl-mc/bus/dpcon.c
606 +++ /dev/null
607 @@ -1,291 +0,0 @@
608 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
609 -/*
610 - * Copyright 2013-2016 Freescale Semiconductor Inc.
611 - *
612 - */
613 -#include <linux/kernel.h>
614 -#include "../include/mc.h"
615 -#include "../include/dpcon.h"
616 -
617 -#include "dpcon-cmd.h"
618 -
619 -/**
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
625 - *
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.
633 - *
634 - * Return: '0' on Success; Error code otherwise.
635 - */
636 -int dpcon_open(struct fsl_mc_io *mc_io,
637 - u32 cmd_flags,
638 - int dpcon_id,
639 - u16 *token)
640 -{
641 - struct mc_command cmd = { 0 };
642 - struct dpcon_cmd_open *dpcon_cmd;
643 - int err;
644 -
645 - /* prepare command */
646 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN,
647 - cmd_flags,
648 - 0);
649 - dpcon_cmd = (struct dpcon_cmd_open *)cmd.params;
650 - dpcon_cmd->dpcon_id = cpu_to_le32(dpcon_id);
651 -
652 - /* send command to mc*/
653 - err = mc_send_command(mc_io, &cmd);
654 - if (err)
655 - return err;
656 -
657 - /* retrieve response parameters */
658 - *token = mc_cmd_hdr_read_token(&cmd);
659 -
660 - return 0;
661 -}
662 -EXPORT_SYMBOL(dpcon_open);
663 -
664 -/**
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
669 - *
670 - * After this function is called, no further operations are
671 - * allowed on the object without opening a new control session.
672 - *
673 - * Return: '0' on Success; Error code otherwise.
674 - */
675 -int dpcon_close(struct fsl_mc_io *mc_io,
676 - u32 cmd_flags,
677 - u16 token)
678 -{
679 - struct mc_command cmd = { 0 };
680 -
681 - /* prepare command */
682 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE,
683 - cmd_flags,
684 - token);
685 -
686 - /* send command to mc*/
687 - return mc_send_command(mc_io, &cmd);
688 -}
689 -EXPORT_SYMBOL(dpcon_close);
690 -
691 -/**
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
696 - *
697 - * Return: '0' on Success; Error code otherwise
698 - */
699 -int dpcon_enable(struct fsl_mc_io *mc_io,
700 - u32 cmd_flags,
701 - u16 token)
702 -{
703 - struct mc_command cmd = { 0 };
704 -
705 - /* prepare command */
706 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE,
707 - cmd_flags,
708 - token);
709 -
710 - /* send command to mc*/
711 - return mc_send_command(mc_io, &cmd);
712 -}
713 -EXPORT_SYMBOL(dpcon_enable);
714 -
715 -/**
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
720 - *
721 - * Return: '0' on Success; Error code otherwise
722 - */
723 -int dpcon_disable(struct fsl_mc_io *mc_io,
724 - u32 cmd_flags,
725 - u16 token)
726 -{
727 - struct mc_command cmd = { 0 };
728 -
729 - /* prepare command */
730 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE,
731 - cmd_flags,
732 - token);
733 -
734 - /* send command to mc*/
735 - return mc_send_command(mc_io, &cmd);
736 -}
737 -EXPORT_SYMBOL(dpcon_disable);
738 -
739 -/**
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
745 - *
746 - * Return: '0' on Success; Error code otherwise.
747 - */
748 -int dpcon_is_enabled(struct fsl_mc_io *mc_io,
749 - u32 cmd_flags,
750 - u16 token,
751 - int *en)
752 -{
753 - struct mc_command cmd = { 0 };
754 - struct dpcon_rsp_is_enabled *dpcon_rsp;
755 - int err;
756 -
757 - /* prepare command */
758 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_IS_ENABLED,
759 - cmd_flags,
760 - token);
761 -
762 - /* send command to mc*/
763 - err = mc_send_command(mc_io, &cmd);
764 - if (err)
765 - return err;
766 -
767 - /* retrieve response parameters */
768 - dpcon_rsp = (struct dpcon_rsp_is_enabled *)cmd.params;
769 - *en = dpcon_rsp->enabled & DPCON_ENABLE;
770 -
771 - return 0;
772 -}
773 -EXPORT_SYMBOL(dpcon_is_enabled);
774 -
775 -/**
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
780 - *
781 - * Return: '0' on Success; Error code otherwise.
782 - */
783 -int dpcon_reset(struct fsl_mc_io *mc_io,
784 - u32 cmd_flags,
785 - u16 token)
786 -{
787 - struct mc_command cmd = { 0 };
788 -
789 - /* prepare command */
790 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET,
791 - cmd_flags, token);
792 -
793 - /* send command to mc*/
794 - return mc_send_command(mc_io, &cmd);
795 -}
796 -EXPORT_SYMBOL(dpcon_reset);
797 -
798 -/**
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
804 - *
805 - * Return: '0' on Success; Error code otherwise.
806 - */
807 -int dpcon_get_attributes(struct fsl_mc_io *mc_io,
808 - u32 cmd_flags,
809 - u16 token,
810 - struct dpcon_attr *attr)
811 -{
812 - struct mc_command cmd = { 0 };
813 - struct dpcon_rsp_get_attr *dpcon_rsp;
814 - int err;
815 -
816 - /* prepare command */
817 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR,
818 - cmd_flags,
819 - token);
820 -
821 - /* send command to mc*/
822 - err = mc_send_command(mc_io, &cmd);
823 - if (err)
824 - return err;
825 -
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;
831 -
832 - return 0;
833 -}
834 -EXPORT_SYMBOL(dpcon_get_attributes);
835 -
836 -/**
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
842 - *
843 - * Return: '0' on Success; Error code otherwise
844 - */
845 -int dpcon_set_notification(struct fsl_mc_io *mc_io,
846 - u32 cmd_flags,
847 - u16 token,
848 - struct dpcon_notification_cfg *cfg)
849 -{
850 - struct mc_command cmd = { 0 };
851 - struct dpcon_cmd_set_notification *dpcon_cmd;
852 -
853 - /* prepare command */
854 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION,
855 - cmd_flags,
856 - token);
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);
861 -
862 - /* send command to mc*/
863 - return mc_send_command(mc_io, &cmd);
864 -}
865 -EXPORT_SYMBOL(dpcon_set_notification);
866 -
867 -/**
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
873 - *
874 - * Return: '0' on Success; Error code otherwise
875 - */
876 -int dpcon_get_api_version(struct fsl_mc_io *mc_io,
877 - u32 cmd_flags,
878 - u16 *major_ver,
879 - u16 *minor_ver)
880 -{
881 - struct mc_command cmd = { 0 };
882 - int err;
883 -
884 - /* prepare command */
885 - cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_API_VERSION,
886 - cmd_flags, 0);
887 -
888 - /* send command to mc */
889 - err = mc_send_command(mc_io, &cmd);
890 - if (err)
891 - return err;
892 -
893 - /* retrieve response parameters */
894 - mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
895 -
896 - return 0;
897 -}
898 -EXPORT_SYMBOL(dpcon_get_api_version);
899 --- /dev/null
900 +++ b/drivers/bus/fsl-mc/dpcon.c
901 @@ -0,0 +1,222 @@
902 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
903 +/*
904 + * Copyright 2013-2016 Freescale Semiconductor Inc.
905 + *
906 + */
907 +#include <linux/kernel.h>
908 +#include <linux/fsl/mc.h>
909 +#include <linux/fsl/mc.h>
910 +
911 +#include "fsl-mc-private.h"
912 +
913 +/**
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
919 + *
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.
927 + *
928 + * Return: '0' on Success; Error code otherwise.
929 + */
930 +int dpcon_open(struct fsl_mc_io *mc_io,
931 + u32 cmd_flags,
932 + int dpcon_id,
933 + u16 *token)
934 +{
935 + struct fsl_mc_command cmd = { 0 };
936 + struct dpcon_cmd_open *dpcon_cmd;
937 + int err;
938 +
939 + /* prepare command */
940 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN,
941 + cmd_flags,
942 + 0);
943 + dpcon_cmd = (struct dpcon_cmd_open *)cmd.params;
944 + dpcon_cmd->dpcon_id = cpu_to_le32(dpcon_id);
945 +
946 + /* send command to mc*/
947 + err = mc_send_command(mc_io, &cmd);
948 + if (err)
949 + return err;
950 +
951 + /* retrieve response parameters */
952 + *token = mc_cmd_hdr_read_token(&cmd);
953 +
954 + return 0;
955 +}
956 +EXPORT_SYMBOL_GPL(dpcon_open);
957 +
958 +/**
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
963 + *
964 + * After this function is called, no further operations are
965 + * allowed on the object without opening a new control session.
966 + *
967 + * Return: '0' on Success; Error code otherwise.
968 + */
969 +int dpcon_close(struct fsl_mc_io *mc_io,
970 + u32 cmd_flags,
971 + u16 token)
972 +{
973 + struct fsl_mc_command cmd = { 0 };
974 +
975 + /* prepare command */
976 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE,
977 + cmd_flags,
978 + token);
979 +
980 + /* send command to mc*/
981 + return mc_send_command(mc_io, &cmd);
982 +}
983 +EXPORT_SYMBOL_GPL(dpcon_close);
984 +
985 +/**
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
990 + *
991 + * Return: '0' on Success; Error code otherwise
992 + */
993 +int dpcon_enable(struct fsl_mc_io *mc_io,
994 + u32 cmd_flags,
995 + u16 token)
996 +{
997 + struct fsl_mc_command cmd = { 0 };
998 +
999 + /* prepare command */
1000 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE,
1001 + cmd_flags,
1002 + token);
1003 +
1004 + /* send command to mc*/
1005 + return mc_send_command(mc_io, &cmd);
1006 +}
1007 +EXPORT_SYMBOL_GPL(dpcon_enable);
1008 +
1009 +/**
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
1014 + *
1015 + * Return: '0' on Success; Error code otherwise
1016 + */
1017 +int dpcon_disable(struct fsl_mc_io *mc_io,
1018 + u32 cmd_flags,
1019 + u16 token)
1020 +{
1021 + struct fsl_mc_command cmd = { 0 };
1022 +
1023 + /* prepare command */
1024 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE,
1025 + cmd_flags,
1026 + token);
1027 +
1028 + /* send command to mc*/
1029 + return mc_send_command(mc_io, &cmd);
1030 +}
1031 +EXPORT_SYMBOL_GPL(dpcon_disable);
1032 +
1033 +/**
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
1038 + *
1039 + * Return: '0' on Success; Error code otherwise.
1040 + */
1041 +int dpcon_reset(struct fsl_mc_io *mc_io,
1042 + u32 cmd_flags,
1043 + u16 token)
1044 +{
1045 + struct fsl_mc_command cmd = { 0 };
1046 +
1047 + /* prepare command */
1048 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET,
1049 + cmd_flags, token);
1050 +
1051 + /* send command to mc*/
1052 + return mc_send_command(mc_io, &cmd);
1053 +}
1054 +EXPORT_SYMBOL_GPL(dpcon_reset);
1055 +
1056 +/**
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
1062 + *
1063 + * Return: '0' on Success; Error code otherwise.
1064 + */
1065 +int dpcon_get_attributes(struct fsl_mc_io *mc_io,
1066 + u32 cmd_flags,
1067 + u16 token,
1068 + struct dpcon_attr *attr)
1069 +{
1070 + struct fsl_mc_command cmd = { 0 };
1071 + struct dpcon_rsp_get_attr *dpcon_rsp;
1072 + int err;
1073 +
1074 + /* prepare command */
1075 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR,
1076 + cmd_flags,
1077 + token);
1078 +
1079 + /* send command to mc*/
1080 + err = mc_send_command(mc_io, &cmd);
1081 + if (err)
1082 + return err;
1083 +
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;
1089 +
1090 + return 0;
1091 +}
1092 +EXPORT_SYMBOL_GPL(dpcon_get_attributes);
1093 +
1094 +/**
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
1100 + *
1101 + * Return: '0' on Success; Error code otherwise
1102 + */
1103 +int dpcon_set_notification(struct fsl_mc_io *mc_io,
1104 + u32 cmd_flags,
1105 + u16 token,
1106 + struct dpcon_notification_cfg *cfg)
1107 +{
1108 + struct fsl_mc_command cmd = { 0 };
1109 + struct dpcon_cmd_set_notification *dpcon_cmd;
1110 +
1111 + /* prepare command */
1112 + cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION,
1113 + cmd_flags,
1114 + token);
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);
1119 +
1120 + /* send command to mc*/
1121 + return mc_send_command(mc_io, &cmd);
1122 +}
1123 +EXPORT_SYMBOL_GPL(dpcon_set_notification);
1124 --- /dev/null
1125 +++ b/drivers/bus/fsl-mc/dpmcp.c
1126 @@ -0,0 +1,99 @@
1127 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
1128 +/*
1129 + * Copyright 2013-2016 Freescale Semiconductor Inc.
1130 + *
1131 + */
1132 +#include <linux/kernel.h>
1133 +#include <linux/fsl/mc.h>
1134 +
1135 +#include "fsl-mc-private.h"
1136 +
1137 +/**
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
1143 + *
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
1151 + *
1152 + * Return: '0' on Success; Error code otherwise.
1153 + */
1154 +int dpmcp_open(struct fsl_mc_io *mc_io,
1155 + u32 cmd_flags,
1156 + int dpmcp_id,
1157 + u16 *token)
1158 +{
1159 + struct fsl_mc_command cmd = { 0 };
1160 + struct dpmcp_cmd_open *cmd_params;
1161 + int err;
1162 +
1163 + /* prepare command */
1164 + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN,
1165 + cmd_flags, 0);
1166 + cmd_params = (struct dpmcp_cmd_open *)cmd.params;
1167 + cmd_params->dpmcp_id = cpu_to_le32(dpmcp_id);
1168 +
1169 + /* send command to mc*/
1170 + err = mc_send_command(mc_io, &cmd);
1171 + if (err)
1172 + return err;
1173 +
1174 + /* retrieve response parameters */
1175 + *token = mc_cmd_hdr_read_token(&cmd);
1176 +
1177 + return err;
1178 +}
1179 +
1180 +/**
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
1185 + *
1186 + * After this function is called, no further operations are
1187 + * allowed on the object without opening a new control session.
1188 + *
1189 + * Return: '0' on Success; Error code otherwise.
1190 + */
1191 +int dpmcp_close(struct fsl_mc_io *mc_io,
1192 + u32 cmd_flags,
1193 + u16 token)
1194 +{
1195 + struct fsl_mc_command cmd = { 0 };
1196 +
1197 + /* prepare command */
1198 + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE,
1199 + cmd_flags, token);
1200 +
1201 + /* send command to mc*/
1202 + return mc_send_command(mc_io, &cmd);
1203 +}
1204 +
1205 +/**
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
1210 + *
1211 + * Return: '0' on Success; Error code otherwise.
1212 + */
1213 +int dpmcp_reset(struct fsl_mc_io *mc_io,
1214 + u32 cmd_flags,
1215 + u16 token)
1216 +{
1217 + struct fsl_mc_command cmd = { 0 };
1218 +
1219 + /* prepare command */
1220 + cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET,
1221 + cmd_flags, token);
1222 +
1223 + /* send command to mc*/
1224 + return mc_send_command(mc_io, &cmd);
1225 +}
1226 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c
1227 +++ /dev/null
1228 @@ -1,813 +0,0 @@
1229 -// SPDX-License-Identifier: GPL-2.0
1230 -/*
1231 - * Freescale data path resource container (DPRC) driver
1232 - *
1233 - * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
1234 - * Author: German Rivera <German.Rivera@freescale.com>
1235 - *
1236 - */
1237 -
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"
1243 -
1244 -#include "dprc-cmd.h"
1245 -#include "fsl-mc-private.h"
1246 -
1247 -#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc"
1248 -
1249 -struct fsl_mc_child_objs {
1250 - int child_count;
1251 - struct fsl_mc_obj_desc *child_array;
1252 -};
1253 -
1254 -static bool fsl_mc_device_match(struct fsl_mc_device *mc_dev,
1255 - struct fsl_mc_obj_desc *obj_desc)
1256 -{
1257 - return mc_dev->obj_desc.id == obj_desc->id &&
1258 - strcmp(mc_dev->obj_desc.type, obj_desc->type) == 0;
1259 -
1260 -}
1261 -
1262 -static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
1263 -{
1264 - int i;
1265 - struct fsl_mc_child_objs *objs;
1266 - struct fsl_mc_device *mc_dev;
1267 -
1268 - WARN_ON(!dev);
1269 - WARN_ON(!data);
1270 - mc_dev = to_fsl_mc_device(dev);
1271 - objs = data;
1272 -
1273 - for (i = 0; i < objs->child_count; i++) {
1274 - struct fsl_mc_obj_desc *obj_desc = &objs->child_array[i];
1275 -
1276 - if (strlen(obj_desc->type) != 0 &&
1277 - fsl_mc_device_match(mc_dev, obj_desc))
1278 - break;
1279 - }
1280 -
1281 - if (i == objs->child_count)
1282 - fsl_mc_device_remove(mc_dev);
1283 -
1284 - return 0;
1285 -}
1286 -
1287 -static int __fsl_mc_device_remove(struct device *dev, void *data)
1288 -{
1289 - WARN_ON(!dev);
1290 - WARN_ON(data);
1291 - fsl_mc_device_remove(to_fsl_mc_device(dev));
1292 - return 0;
1293 -}
1294 -
1295 -/**
1296 - * dprc_remove_devices - Removes devices for objects removed from a DPRC
1297 - *
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
1302 - *
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.
1306 - */
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)
1310 -{
1311 - if (num_child_objects_in_mc != 0) {
1312 - /*
1313 - * Remove child objects that are in the DPRC in Linux,
1314 - * but not in the MC:
1315 - */
1316 - struct fsl_mc_child_objs objs;
1317 -
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);
1322 - } else {
1323 - /*
1324 - * There are no child objects for this DPRC in the MC.
1325 - * So, remove all the child devices from Linux:
1326 - */
1327 - device_for_each_child(&mc_bus_dev->dev, NULL,
1328 - __fsl_mc_device_remove);
1329 - }
1330 -}
1331 -
1332 -static int __fsl_mc_device_match(struct device *dev, void *data)
1333 -{
1334 - struct fsl_mc_obj_desc *obj_desc = data;
1335 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
1336 -
1337 - return fsl_mc_device_match(mc_dev, obj_desc);
1338 -}
1339 -
1340 -static struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc
1341 - *obj_desc,
1342 - struct fsl_mc_device
1343 - *mc_bus_dev)
1344 -{
1345 - struct device *dev;
1346 -
1347 - dev = device_find_child(&mc_bus_dev->dev, obj_desc,
1348 - __fsl_mc_device_match);
1349 -
1350 - return dev ? to_fsl_mc_device(dev) : NULL;
1351 -}
1352 -
1353 -/**
1354 - * check_plugged_state_change - Check change in an MC object's plugged state
1355 - *
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
1358 - *
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.
1363 - */
1364 -static void check_plugged_state_change(struct fsl_mc_device *mc_dev,
1365 - struct fsl_mc_obj_desc *obj_desc)
1366 -{
1367 - int error;
1368 - u32 plugged_flag_at_mc =
1369 - obj_desc->state & FSL_MC_OBJ_STATE_PLUGGED;
1370 -
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);
1376 - if (error < 0) {
1377 - dev_err(&mc_dev->dev,
1378 - "device_attach() failed: %d\n",
1379 - error);
1380 - }
1381 - } else {
1382 - mc_dev->obj_desc.state &= ~FSL_MC_OBJ_STATE_PLUGGED;
1383 - device_release_driver(&mc_dev->dev);
1384 - }
1385 - }
1386 -}
1387 -
1388 -/**
1389 - * dprc_add_new_devices - Adds devices to the logical bus for a DPRC
1390 - *
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
1395 - *
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.
1399 - */
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)
1403 -{
1404 - int error;
1405 - int i;
1406 -
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];
1410 -
1411 - if (strlen(obj_desc->type) == 0)
1412 - continue;
1413 -
1414 - /*
1415 - * Check if device is already known to Linux:
1416 - */
1417 - child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev);
1418 - if (child_dev) {
1419 - check_plugged_state_change(child_dev, obj_desc);
1420 - put_device(&child_dev->dev);
1421 - continue;
1422 - }
1423 -
1424 - error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev,
1425 - &child_dev);
1426 - if (error < 0)
1427 - continue;
1428 - }
1429 -}
1430 -
1431 -/**
1432 - * dprc_scan_objects - Discover objects in a DPRC
1433 - *
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.
1436 - *
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.
1448 - */
1449 -static int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
1450 - unsigned int *total_irq_count)
1451 -{
1452 - int num_child_objects;
1453 - int dprc_get_obj_failures;
1454 - int error;
1455 - unsigned int irq_count = mc_bus_dev->obj_desc.irq_count;
1456 - struct fsl_mc_obj_desc *child_obj_desc_array = NULL;
1457 -
1458 - error = dprc_get_obj_count(mc_bus_dev->mc_io,
1459 - 0,
1460 - mc_bus_dev->mc_handle,
1461 - &num_child_objects);
1462 - if (error < 0) {
1463 - dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n",
1464 - error);
1465 - return error;
1466 - }
1467 -
1468 - if (num_child_objects != 0) {
1469 - int i;
1470 -
1471 - child_obj_desc_array =
1472 - devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects,
1473 - sizeof(*child_obj_desc_array),
1474 - GFP_KERNEL);
1475 - if (!child_obj_desc_array)
1476 - return -ENOMEM;
1477 -
1478 - /*
1479 - * Discover objects currently present in the physical DPRC:
1480 - */
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];
1485 -
1486 - error = dprc_get_obj(mc_bus_dev->mc_io,
1487 - 0,
1488 - mc_bus_dev->mc_handle,
1489 - i, obj_desc);
1490 - if (error < 0) {
1491 - dev_err(&mc_bus_dev->dev,
1492 - "dprc_get_obj(i=%d) failed: %d\n",
1493 - i, error);
1494 - /*
1495 - * Mark the obj entry as "invalid", by using the
1496 - * empty string as obj type:
1497 - */
1498 - obj_desc->type[0] = '\0';
1499 - obj_desc->id = error;
1500 - dprc_get_obj_failures++;
1501 - continue;
1502 - }
1503 -
1504 - /*
1505 - * add a quirk for all versions of dpsec < 4.0...none
1506 - * are coherent regardless of what the MC reports.
1507 - */
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;
1512 -
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);
1517 - }
1518 -
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);
1523 - }
1524 - }
1525 -
1526 - *total_irq_count = irq_count;
1527 - dprc_remove_devices(mc_bus_dev, child_obj_desc_array,
1528 - num_child_objects);
1529 -
1530 - dprc_add_new_devices(mc_bus_dev, child_obj_desc_array,
1531 - num_child_objects);
1532 -
1533 - if (child_obj_desc_array)
1534 - devm_kfree(&mc_bus_dev->dev, child_obj_desc_array);
1535 -
1536 - return 0;
1537 -}
1538 -
1539 -/**
1540 - * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state
1541 - *
1542 - * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
1543 - *
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.
1547 - */
1548 -static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
1549 -{
1550 - int error;
1551 - unsigned int irq_count;
1552 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
1553 -
1554 - fsl_mc_init_all_resource_pools(mc_bus_dev);
1555 -
1556 - /*
1557 - * Discover objects in the DPRC:
1558 - */
1559 - mutex_lock(&mc_bus->scan_mutex);
1560 - error = dprc_scan_objects(mc_bus_dev, &irq_count);
1561 - mutex_unlock(&mc_bus->scan_mutex);
1562 - if (error < 0)
1563 - goto error;
1564 -
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);
1570 - }
1571 -
1572 - error = fsl_mc_populate_irq_pool(
1573 - mc_bus,
1574 - FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
1575 - if (error < 0)
1576 - goto error;
1577 - }
1578 -
1579 - return 0;
1580 -error:
1581 - fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
1582 - return error;
1583 -}
1584 -
1585 -/**
1586 - * dprc_irq0_handler - Regular ISR for DPRC interrupt 0
1587 - *
1588 - * @irq: IRQ number of the interrupt being handled
1589 - * @arg: Pointer to device structure
1590 - */
1591 -static irqreturn_t dprc_irq0_handler(int irq_num, void *arg)
1592 -{
1593 - return IRQ_WAKE_THREAD;
1594 -}
1595 -
1596 -/**
1597 - * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0
1598 - *
1599 - * @irq: IRQ number of the interrupt being handled
1600 - * @arg: Pointer to device structure
1601 - */
1602 -static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
1603 -{
1604 - int error;
1605 - u32 status;
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;
1611 -
1612 - dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n",
1613 - irq_num, smp_processor_id());
1614 -
1615 - if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC)))
1616 - return IRQ_HANDLED;
1617 -
1618 - mutex_lock(&mc_bus->scan_mutex);
1619 - if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num))
1620 - goto out;
1621 -
1622 - status = 0;
1623 - error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
1624 - &status);
1625 - if (error < 0) {
1626 - dev_err(dev,
1627 - "dprc_get_irq_status() failed: %d\n", error);
1628 - goto out;
1629 - }
1630 -
1631 - error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
1632 - status);
1633 - if (error < 0) {
1634 - dev_err(dev,
1635 - "dprc_clear_irq_status() failed: %d\n", error);
1636 - goto out;
1637 - }
1638 -
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;
1645 -
1646 - error = dprc_scan_objects(mc_dev, &irq_count);
1647 - if (error < 0) {
1648 - /*
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.
1653 - */
1654 - if (error != -ENXIO) {
1655 - dev_err(dev, "dprc_scan_objects() failed: %d\n",
1656 - error);
1657 - }
1658 -
1659 - goto out;
1660 - }
1661 -
1662 - if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
1663 - dev_warn(dev,
1664 - "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
1665 - irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
1666 - }
1667 - }
1668 -
1669 -out:
1670 - mutex_unlock(&mc_bus->scan_mutex);
1671 - return IRQ_HANDLED;
1672 -}
1673 -
1674 -/*
1675 - * Disable and clear interrupt for a given DPRC object
1676 - */
1677 -static int disable_dprc_irq(struct fsl_mc_device *mc_dev)
1678 -{
1679 - int error;
1680 - struct fsl_mc_io *mc_io = mc_dev->mc_io;
1681 -
1682 - WARN_ON(mc_dev->obj_desc.irq_count != 1);
1683 -
1684 - /*
1685 - * Disable generation of interrupt, while we configure it:
1686 - */
1687 - error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0);
1688 - if (error < 0) {
1689 - dev_err(&mc_dev->dev,
1690 - "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
1691 - error);
1692 - return error;
1693 - }
1694 -
1695 - /*
1696 - * Disable all interrupt causes for the interrupt:
1697 - */
1698 - error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0);
1699 - if (error < 0) {
1700 - dev_err(&mc_dev->dev,
1701 - "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
1702 - error);
1703 - return error;
1704 - }
1705 -
1706 - /*
1707 - * Clear any leftover interrupts:
1708 - */
1709 - error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U);
1710 - if (error < 0) {
1711 - dev_err(&mc_dev->dev,
1712 - "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n",
1713 - error);
1714 - return error;
1715 - }
1716 -
1717 - return 0;
1718 -}
1719 -
1720 -static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev)
1721 -{
1722 - int error;
1723 - struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
1724 -
1725 - WARN_ON(mc_dev->obj_desc.irq_count != 1);
1726 -
1727 - /*
1728 - * NOTE: devm_request_threaded_irq() invokes the device-specific
1729 - * function that programs the MSI physically in the device
1730 - */
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),
1737 - &mc_dev->dev);
1738 - if (error < 0) {
1739 - dev_err(&mc_dev->dev,
1740 - "devm_request_threaded_irq() failed: %d\n",
1741 - error);
1742 - return error;
1743 - }
1744 -
1745 - return 0;
1746 -}
1747 -
1748 -static int enable_dprc_irq(struct fsl_mc_device *mc_dev)
1749 -{
1750 - int error;
1751 -
1752 - /*
1753 - * Enable all interrupt causes for the interrupt:
1754 - */
1755 - error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0,
1756 - ~0x0u);
1757 - if (error < 0) {
1758 - dev_err(&mc_dev->dev,
1759 - "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
1760 - error);
1761 -
1762 - return error;
1763 - }
1764 -
1765 - /*
1766 - * Enable generation of the interrupt:
1767 - */
1768 - error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1);
1769 - if (error < 0) {
1770 - dev_err(&mc_dev->dev,
1771 - "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
1772 - error);
1773 -
1774 - return error;
1775 - }
1776 -
1777 - return 0;
1778 -}
1779 -
1780 -/*
1781 - * Setup interrupt for a given DPRC device
1782 - */
1783 -static int dprc_setup_irq(struct fsl_mc_device *mc_dev)
1784 -{
1785 - int error;
1786 -
1787 - error = fsl_mc_allocate_irqs(mc_dev);
1788 - if (error < 0)
1789 - return error;
1790 -
1791 - error = disable_dprc_irq(mc_dev);
1792 - if (error < 0)
1793 - goto error_free_irqs;
1794 -
1795 - error = register_dprc_irq_handler(mc_dev);
1796 - if (error < 0)
1797 - goto error_free_irqs;
1798 -
1799 - error = enable_dprc_irq(mc_dev);
1800 - if (error < 0)
1801 - goto error_free_irqs;
1802 -
1803 - return 0;
1804 -
1805 -error_free_irqs:
1806 - fsl_mc_free_irqs(mc_dev);
1807 - return error;
1808 -}
1809 -
1810 -/**
1811 - * dprc_probe - callback invoked when a DPRC is being bound to this driver
1812 - *
1813 - * @mc_dev: Pointer to fsl-mc device representing a DPRC
1814 - *
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.
1819 - */
1820 -static int dprc_probe(struct fsl_mc_device *mc_dev)
1821 -{
1822 - int error;
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;
1829 -
1830 - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
1831 - return -EINVAL;
1832 -
1833 - if (WARN_ON(dev_get_msi_domain(&mc_dev->dev)))
1834 - return -EINVAL;
1835 -
1836 - if (!mc_dev->mc_io) {
1837 - /*
1838 - * This is a child DPRC:
1839 - */
1840 - if (WARN_ON(!dev_is_fsl_mc(parent_dev)))
1841 - return -EINVAL;
1842 -
1843 - if (WARN_ON(mc_dev->obj_desc.region_count == 0))
1844 - return -EINVAL;
1845 -
1846 - region_size = resource_size(mc_dev->regions);
1847 -
1848 - error = fsl_create_mc_io(&mc_dev->dev,
1849 - mc_dev->regions[0].start,
1850 - region_size,
1851 - NULL,
1852 - FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
1853 - &mc_dev->mc_io);
1854 - if (error < 0)
1855 - return error;
1856 -
1857 - mc_io_created = true;
1858 -
1859 - /*
1860 - * Inherit parent MSI domain:
1861 - */
1862 - dev_set_msi_domain(&mc_dev->dev,
1863 - dev_get_msi_domain(parent_dev));
1864 - msi_domain_set = true;
1865 - } else {
1866 - /*
1867 - * This is a root DPRC
1868 - */
1869 - struct irq_domain *mc_msi_domain;
1870 -
1871 - if (WARN_ON(dev_is_fsl_mc(parent_dev)))
1872 - return -EINVAL;
1873 -
1874 - error = fsl_mc_find_msi_domain(parent_dev,
1875 - &mc_msi_domain);
1876 - if (error < 0) {
1877 - dev_warn(&mc_dev->dev,
1878 - "WARNING: MC bus without interrupt support\n");
1879 - } else {
1880 - dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
1881 - msi_domain_set = true;
1882 - }
1883 - }
1884 -
1885 - error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
1886 - &mc_dev->mc_handle);
1887 - if (error < 0) {
1888 - dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error);
1889 - goto error_cleanup_msi_domain;
1890 - }
1891 -
1892 - error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle,
1893 - &mc_bus->dprc_attr);
1894 - if (error < 0) {
1895 - dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n",
1896 - error);
1897 - goto error_cleanup_open;
1898 - }
1899 -
1900 - error = dprc_get_api_version(mc_dev->mc_io, 0,
1901 - &major_ver,
1902 - &minor_ver);
1903 - if (error < 0) {
1904 - dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n",
1905 - error);
1906 - goto error_cleanup_open;
1907 - }
1908 -
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;
1917 - }
1918 -
1919 - mutex_init(&mc_bus->scan_mutex);
1920 -
1921 - /*
1922 - * Discover MC objects in DPRC object:
1923 - */
1924 - error = dprc_scan_container(mc_dev);
1925 - if (error < 0)
1926 - goto error_cleanup_open;
1927 -
1928 - /*
1929 - * Configure interrupt for the DPRC object associated with this MC bus:
1930 - */
1931 - error = dprc_setup_irq(mc_dev);
1932 - if (error < 0)
1933 - goto error_cleanup_open;
1934 -
1935 - dev_info(&mc_dev->dev, "DPRC device bound to driver");
1936 - return 0;
1937 -
1938 -error_cleanup_open:
1939 - (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
1940 -
1941 -error_cleanup_msi_domain:
1942 - if (msi_domain_set)
1943 - dev_set_msi_domain(&mc_dev->dev, NULL);
1944 -
1945 - if (mc_io_created) {
1946 - fsl_destroy_mc_io(mc_dev->mc_io);
1947 - mc_dev->mc_io = NULL;
1948 - }
1949 -
1950 - return error;
1951 -}
1952 -
1953 -/*
1954 - * Tear down interrupt for a given DPRC object
1955 - */
1956 -static void dprc_teardown_irq(struct fsl_mc_device *mc_dev)
1957 -{
1958 - struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
1959 -
1960 - (void)disable_dprc_irq(mc_dev);
1961 -
1962 - devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev);
1963 -
1964 - fsl_mc_free_irqs(mc_dev);
1965 -}
1966 -
1967 -/**
1968 - * dprc_remove - callback invoked when a DPRC is being unbound from this driver
1969 - *
1970 - * @mc_dev: Pointer to fsl-mc device representing the DPRC
1971 - *
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.
1976 - */
1977 -static int dprc_remove(struct fsl_mc_device *mc_dev)
1978 -{
1979 - int error;
1980 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
1981 -
1982 - if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
1983 - return -EINVAL;
1984 - if (WARN_ON(!mc_dev->mc_io))
1985 - return -EINVAL;
1986 -
1987 - if (WARN_ON(!mc_bus->irq_resources))
1988 - return -EINVAL;
1989 -
1990 - if (dev_get_msi_domain(&mc_dev->dev))
1991 - dprc_teardown_irq(mc_dev);
1992 -
1993 - device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
1994 -
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);
1998 - }
1999 -
2000 - fsl_mc_cleanup_all_resource_pools(mc_dev);
2001 -
2002 - error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
2003 - if (error < 0)
2004 - dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error);
2005 -
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;
2009 - }
2010 -
2011 - dev_info(&mc_dev->dev, "DPRC device unbound from driver");
2012 - return 0;
2013 -}
2014 -
2015 -static const struct fsl_mc_device_id match_id_table[] = {
2016 - {
2017 - .vendor = FSL_MC_VENDOR_FREESCALE,
2018 - .obj_type = "dprc"},
2019 - {.vendor = 0x0},
2020 -};
2021 -
2022 -static struct fsl_mc_driver dprc_driver = {
2023 - .driver = {
2024 - .name = FSL_MC_DPRC_DRIVER_NAME,
2025 - .owner = THIS_MODULE,
2026 - .pm = NULL,
2027 - },
2028 - .match_id_table = match_id_table,
2029 - .probe = dprc_probe,
2030 - .remove = dprc_remove,
2031 -};
2032 -
2033 -int __init dprc_driver_init(void)
2034 -{
2035 - return fsl_mc_driver_register(&dprc_driver);
2036 -}
2037 -
2038 -void dprc_driver_exit(void)
2039 -{
2040 - fsl_mc_driver_unregister(&dprc_driver);
2041 -}
2042 --- /dev/null
2043 +++ b/drivers/bus/fsl-mc/dprc-driver.c
2044 @@ -0,0 +1,815 @@
2045 +// SPDX-License-Identifier: GPL-2.0
2046 +/*
2047 + * Freescale data path resource container (DPRC) driver
2048 + *
2049 + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
2050 + * Author: German Rivera <German.Rivera@freescale.com>
2051 + *
2052 + */
2053 +
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>
2059 +
2060 +#include "fsl-mc-private.h"
2061 +
2062 +#define FSL_MC_DPRC_DRIVER_NAME "fsl_mc_dprc"
2063 +
2064 +struct fsl_mc_child_objs {
2065 + int child_count;
2066 + struct fsl_mc_obj_desc *child_array;
2067 +};
2068 +
2069 +static bool fsl_mc_device_match(struct fsl_mc_device *mc_dev,
2070 + struct fsl_mc_obj_desc *obj_desc)
2071 +{
2072 + return mc_dev->obj_desc.id == obj_desc->id &&
2073 + strcmp(mc_dev->obj_desc.type, obj_desc->type) == 0;
2074 +
2075 +}
2076 +
2077 +static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
2078 +{
2079 + int i;
2080 + struct fsl_mc_child_objs *objs;
2081 + struct fsl_mc_device *mc_dev;
2082 +
2083 + mc_dev = to_fsl_mc_device(dev);
2084 + objs = data;
2085 +
2086 + for (i = 0; i < objs->child_count; i++) {
2087 + struct fsl_mc_obj_desc *obj_desc = &objs->child_array[i];
2088 +
2089 + if (strlen(obj_desc->type) != 0 &&
2090 + fsl_mc_device_match(mc_dev, obj_desc))
2091 + break;
2092 + }
2093 +
2094 + if (i == objs->child_count)
2095 + fsl_mc_device_remove(mc_dev);
2096 +
2097 + return 0;
2098 +}
2099 +
2100 +static int __fsl_mc_device_remove(struct device *dev, void *data)
2101 +{
2102 + fsl_mc_device_remove(to_fsl_mc_device(dev));
2103 + return 0;
2104 +}
2105 +
2106 +/**
2107 + * dprc_remove_devices - Removes devices for objects removed from a DPRC
2108 + *
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
2113 + *
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.
2117 + */
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)
2121 +{
2122 + if (num_child_objects_in_mc != 0) {
2123 + /*
2124 + * Remove child objects that are in the DPRC in Linux,
2125 + * but not in the MC:
2126 + */
2127 + struct fsl_mc_child_objs objs;
2128 +
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);
2133 + } else {
2134 + /*
2135 + * There are no child objects for this DPRC in the MC.
2136 + * So, remove all the child devices from Linux:
2137 + */
2138 + device_for_each_child(&mc_bus_dev->dev, NULL,
2139 + __fsl_mc_device_remove);
2140 + }
2141 +}
2142 +
2143 +static int __fsl_mc_device_match(struct device *dev, void *data)
2144 +{
2145 + struct fsl_mc_obj_desc *obj_desc = data;
2146 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
2147 +
2148 + return fsl_mc_device_match(mc_dev, obj_desc);
2149 +}
2150 +
2151 +static struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc
2152 + *obj_desc,
2153 + struct fsl_mc_device
2154 + *mc_bus_dev)
2155 +{
2156 + struct device *dev;
2157 +
2158 + dev = device_find_child(&mc_bus_dev->dev, obj_desc,
2159 + __fsl_mc_device_match);
2160 +
2161 + return dev ? to_fsl_mc_device(dev) : NULL;
2162 +}
2163 +
2164 +/**
2165 + * check_plugged_state_change - Check change in an MC object's plugged state
2166 + *
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
2169 + *
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.
2174 + */
2175 +static void check_plugged_state_change(struct fsl_mc_device *mc_dev,
2176 + struct fsl_mc_obj_desc *obj_desc)
2177 +{
2178 + int error;
2179 + u32 plugged_flag_at_mc =
2180 + obj_desc->state & FSL_MC_OBJ_STATE_PLUGGED;
2181 +
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);
2187 + if (error < 0) {
2188 + dev_err(&mc_dev->dev,
2189 + "device_attach() failed: %d\n",
2190 + error);
2191 + }
2192 + } else {
2193 + mc_dev->obj_desc.state &= ~FSL_MC_OBJ_STATE_PLUGGED;
2194 + device_release_driver(&mc_dev->dev);
2195 + }
2196 + }
2197 +}
2198 +
2199 +/**
2200 + * dprc_add_new_devices - Adds devices to the logical bus for a DPRC
2201 + *
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
2208 + *
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.
2212 + */
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)
2217 +{
2218 + int error;
2219 + int i;
2220 +
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];
2224 +
2225 + if (strlen(obj_desc->type) == 0)
2226 + continue;
2227 +
2228 + /*
2229 + * Check if device is already known to Linux:
2230 + */
2231 + child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev);
2232 + if (child_dev) {
2233 + check_plugged_state_change(child_dev, obj_desc);
2234 + put_device(&child_dev->dev);
2235 + continue;
2236 + }
2237 +
2238 + error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev,
2239 + driver_override, &child_dev);
2240 + if (error < 0)
2241 + continue;
2242 + }
2243 +}
2244 +
2245 +/**
2246 + * dprc_scan_objects - Discover objects in a DPRC
2247 + *
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.
2253 + *
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.
2265 + */
2266 +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
2267 + const char *driver_override,
2268 + unsigned int *total_irq_count)
2269 +{
2270 + int num_child_objects;
2271 + int dprc_get_obj_failures;
2272 + int error;
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);
2276 +
2277 + error = dprc_get_obj_count(mc_bus_dev->mc_io,
2278 + 0,
2279 + mc_bus_dev->mc_handle,
2280 + &num_child_objects);
2281 + if (error < 0) {
2282 + dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n",
2283 + error);
2284 + return error;
2285 + }
2286 +
2287 + if (num_child_objects != 0) {
2288 + int i;
2289 +
2290 + child_obj_desc_array =
2291 + devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects,
2292 + sizeof(*child_obj_desc_array),
2293 + GFP_KERNEL);
2294 + if (!child_obj_desc_array)
2295 + return -ENOMEM;
2296 +
2297 + /*
2298 + * Discover objects currently present in the physical DPRC:
2299 + */
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];
2304 +
2305 + error = dprc_get_obj(mc_bus_dev->mc_io,
2306 + 0,
2307 + mc_bus_dev->mc_handle,
2308 + i, obj_desc);
2309 + if (error < 0) {
2310 + dev_err(&mc_bus_dev->dev,
2311 + "dprc_get_obj(i=%d) failed: %d\n",
2312 + i, error);
2313 + /*
2314 + * Mark the obj entry as "invalid", by using the
2315 + * empty string as obj type:
2316 + */
2317 + obj_desc->type[0] = '\0';
2318 + obj_desc->id = error;
2319 + dprc_get_obj_failures++;
2320 + continue;
2321 + }
2322 +
2323 + /*
2324 + * add a quirk for all versions of dpsec < 4.0...none
2325 + * are coherent regardless of what the MC reports.
2326 + */
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;
2331 +
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);
2336 + }
2337 +
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);
2342 + }
2343 + }
2344 +
2345 + /*
2346 + * Allocate IRQ's before binding the scanned devices with their
2347 + * respective drivers.
2348 + */
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);
2354 + }
2355 +
2356 + error = fsl_mc_populate_irq_pool(mc_bus,
2357 + FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
2358 + if (error < 0)
2359 + return error;
2360 + }
2361 +
2362 + if (total_irq_count)
2363 + *total_irq_count = irq_count;
2364 +
2365 + dprc_remove_devices(mc_bus_dev, child_obj_desc_array,
2366 + num_child_objects);
2367 +
2368 + dprc_add_new_devices(mc_bus_dev, driver_override, child_obj_desc_array,
2369 + num_child_objects);
2370 +
2371 + if (child_obj_desc_array)
2372 + devm_kfree(&mc_bus_dev->dev, child_obj_desc_array);
2373 +
2374 + return 0;
2375 +}
2376 +
2377 +/**
2378 + * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state
2379 + *
2380 + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
2381 + *
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.
2385 + */
2386 +static int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
2387 +{
2388 + int error;
2389 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
2390 +
2391 + fsl_mc_init_all_resource_pools(mc_bus_dev);
2392 +
2393 + /*
2394 + * Discover objects in the DPRC:
2395 + */
2396 + mutex_lock(&mc_bus->scan_mutex);
2397 + error = dprc_scan_objects(mc_bus_dev, NULL, NULL);
2398 + mutex_unlock(&mc_bus->scan_mutex);
2399 + if (error < 0) {
2400 + fsl_mc_cleanup_all_resource_pools(mc_bus_dev);
2401 + return error;
2402 + }
2403 +
2404 + return 0;
2405 +}
2406 +
2407 +/**
2408 + * dprc_irq0_handler - Regular ISR for DPRC interrupt 0
2409 + *
2410 + * @irq: IRQ number of the interrupt being handled
2411 + * @arg: Pointer to device structure
2412 + */
2413 +static irqreturn_t dprc_irq0_handler(int irq_num, void *arg)
2414 +{
2415 + return IRQ_WAKE_THREAD;
2416 +}
2417 +
2418 +/**
2419 + * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0
2420 + *
2421 + * @irq: IRQ number of the interrupt being handled
2422 + * @arg: Pointer to device structure
2423 + */
2424 +static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
2425 +{
2426 + int error;
2427 + u32 status;
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;
2433 +
2434 + dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n",
2435 + irq_num, smp_processor_id());
2436 +
2437 + if (!(mc_dev->flags & FSL_MC_IS_DPRC))
2438 + return IRQ_HANDLED;
2439 +
2440 + mutex_lock(&mc_bus->scan_mutex);
2441 + if (!msi_desc || msi_desc->irq != (u32)irq_num)
2442 + goto out;
2443 +
2444 + status = 0;
2445 + error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
2446 + &status);
2447 + if (error < 0) {
2448 + dev_err(dev,
2449 + "dprc_get_irq_status() failed: %d\n", error);
2450 + goto out;
2451 + }
2452 +
2453 + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
2454 + status);
2455 + if (error < 0) {
2456 + dev_err(dev,
2457 + "dprc_clear_irq_status() failed: %d\n", error);
2458 + goto out;
2459 + }
2460 +
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;
2467 +
2468 + error = dprc_scan_objects(mc_dev, NULL, &irq_count);
2469 + if (error < 0) {
2470 + /*
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.
2475 + */
2476 + if (error != -ENXIO) {
2477 + dev_err(dev, "dprc_scan_objects() failed: %d\n",
2478 + error);
2479 + }
2480 +
2481 + goto out;
2482 + }
2483 +
2484 + if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
2485 + dev_warn(dev,
2486 + "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
2487 + irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
2488 + }
2489 + }
2490 +
2491 +out:
2492 + mutex_unlock(&mc_bus->scan_mutex);
2493 + return IRQ_HANDLED;
2494 +}
2495 +
2496 +/*
2497 + * Disable and clear interrupt for a given DPRC object
2498 + */
2499 +static int disable_dprc_irq(struct fsl_mc_device *mc_dev)
2500 +{
2501 + int error;
2502 + struct fsl_mc_io *mc_io = mc_dev->mc_io;
2503 +
2504 + /*
2505 + * Disable generation of interrupt, while we configure it:
2506 + */
2507 + error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0);
2508 + if (error < 0) {
2509 + dev_err(&mc_dev->dev,
2510 + "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
2511 + error);
2512 + return error;
2513 + }
2514 +
2515 + /*
2516 + * Disable all interrupt causes for the interrupt:
2517 + */
2518 + error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0);
2519 + if (error < 0) {
2520 + dev_err(&mc_dev->dev,
2521 + "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
2522 + error);
2523 + return error;
2524 + }
2525 +
2526 + /*
2527 + * Clear any leftover interrupts:
2528 + */
2529 + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U);
2530 + if (error < 0) {
2531 + dev_err(&mc_dev->dev,
2532 + "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n",
2533 + error);
2534 + return error;
2535 + }
2536 +
2537 + return 0;
2538 +}
2539 +
2540 +static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev)
2541 +{
2542 + int error;
2543 + struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
2544 +
2545 + /*
2546 + * NOTE: devm_request_threaded_irq() invokes the device-specific
2547 + * function that programs the MSI physically in the device
2548 + */
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),
2555 + &mc_dev->dev);
2556 + if (error < 0) {
2557 + dev_err(&mc_dev->dev,
2558 + "devm_request_threaded_irq() failed: %d\n",
2559 + error);
2560 + return error;
2561 + }
2562 +
2563 + return 0;
2564 +}
2565 +
2566 +static int enable_dprc_irq(struct fsl_mc_device *mc_dev)
2567 +{
2568 + int error;
2569 +
2570 + /*
2571 + * Enable all interrupt causes for the interrupt:
2572 + */
2573 + error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0,
2574 + ~0x0u);
2575 + if (error < 0) {
2576 + dev_err(&mc_dev->dev,
2577 + "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
2578 + error);
2579 +
2580 + return error;
2581 + }
2582 +
2583 + /*
2584 + * Enable generation of the interrupt:
2585 + */
2586 + error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1);
2587 + if (error < 0) {
2588 + dev_err(&mc_dev->dev,
2589 + "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
2590 + error);
2591 +
2592 + return error;
2593 + }
2594 +
2595 + return 0;
2596 +}
2597 +
2598 +/*
2599 + * Setup interrupt for a given DPRC device
2600 + */
2601 +static int dprc_setup_irq(struct fsl_mc_device *mc_dev)
2602 +{
2603 + int error;
2604 +
2605 + error = fsl_mc_allocate_irqs(mc_dev);
2606 + if (error < 0)
2607 + return error;
2608 +
2609 + error = disable_dprc_irq(mc_dev);
2610 + if (error < 0)
2611 + goto error_free_irqs;
2612 +
2613 + error = register_dprc_irq_handler(mc_dev);
2614 + if (error < 0)
2615 + goto error_free_irqs;
2616 +
2617 + error = enable_dprc_irq(mc_dev);
2618 + if (error < 0)
2619 + goto error_free_irqs;
2620 +
2621 + return 0;
2622 +
2623 +error_free_irqs:
2624 + fsl_mc_free_irqs(mc_dev);
2625 + return error;
2626 +}
2627 +
2628 +/**
2629 + * dprc_probe - callback invoked when a DPRC is being bound to this driver
2630 + *
2631 + * @mc_dev: Pointer to fsl-mc device representing a DPRC
2632 + *
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.
2637 + */
2638 +static int dprc_probe(struct fsl_mc_device *mc_dev)
2639 +{
2640 + int error;
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;
2647 +
2648 + if (!is_fsl_mc_bus_dprc(mc_dev))
2649 + return -EINVAL;
2650 +
2651 + if (dev_get_msi_domain(&mc_dev->dev))
2652 + return -EINVAL;
2653 +
2654 + if (!mc_dev->mc_io) {
2655 + /*
2656 + * This is a child DPRC:
2657 + */
2658 + if (!dev_is_fsl_mc(parent_dev))
2659 + return -EINVAL;
2660 +
2661 + if (mc_dev->obj_desc.region_count == 0)
2662 + return -EINVAL;
2663 +
2664 + region_size = resource_size(mc_dev->regions);
2665 +
2666 + error = fsl_create_mc_io(&mc_dev->dev,
2667 + mc_dev->regions[0].start,
2668 + region_size,
2669 + NULL,
2670 + FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
2671 + &mc_dev->mc_io);
2672 + if (error < 0)
2673 + return error;
2674 +
2675 + mc_io_created = true;
2676 +
2677 + /*
2678 + * Inherit parent MSI domain:
2679 + */
2680 + dev_set_msi_domain(&mc_dev->dev,
2681 + dev_get_msi_domain(parent_dev));
2682 + msi_domain_set = true;
2683 + } else {
2684 + /*
2685 + * This is a root DPRC
2686 + */
2687 + struct irq_domain *mc_msi_domain;
2688 +
2689 + if (dev_is_fsl_mc(parent_dev))
2690 + return -EINVAL;
2691 +
2692 + error = fsl_mc_find_msi_domain(parent_dev,
2693 + &mc_msi_domain);
2694 + if (error < 0) {
2695 + dev_warn(&mc_dev->dev,
2696 + "WARNING: MC bus without interrupt support\n");
2697 + } else {
2698 + dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
2699 + msi_domain_set = true;
2700 + }
2701 + }
2702 +
2703 + error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
2704 + &mc_dev->mc_handle);
2705 + if (error < 0) {
2706 + dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error);
2707 + goto error_cleanup_msi_domain;
2708 + }
2709 +
2710 + error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle,
2711 + &mc_bus->dprc_attr);
2712 + if (error < 0) {
2713 + dev_err(&mc_dev->dev, "dprc_get_attributes() failed: %d\n",
2714 + error);
2715 + goto error_cleanup_open;
2716 + }
2717 +
2718 + error = dprc_get_api_version(mc_dev->mc_io, 0,
2719 + &major_ver,
2720 + &minor_ver);
2721 + if (error < 0) {
2722 + dev_err(&mc_dev->dev, "dprc_get_api_version() failed: %d\n",
2723 + error);
2724 + goto error_cleanup_open;
2725 + }
2726 +
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;
2735 + }
2736 +
2737 + mutex_init(&mc_bus->scan_mutex);
2738 +
2739 + /*
2740 + * Discover MC objects in DPRC object:
2741 + */
2742 + error = dprc_scan_container(mc_dev);
2743 + if (error < 0)
2744 + goto error_cleanup_open;
2745 +
2746 + /*
2747 + * Configure interrupt for the DPRC object associated with this MC bus:
2748 + */
2749 + error = dprc_setup_irq(mc_dev);
2750 + if (error < 0)
2751 + goto error_cleanup_open;
2752 +
2753 + dev_info(&mc_dev->dev, "DPRC device bound to driver");
2754 + return 0;
2755 +
2756 +error_cleanup_open:
2757 + (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
2758 +
2759 +error_cleanup_msi_domain:
2760 + if (msi_domain_set)
2761 + dev_set_msi_domain(&mc_dev->dev, NULL);
2762 +
2763 + if (mc_io_created) {
2764 + fsl_destroy_mc_io(mc_dev->mc_io);
2765 + mc_dev->mc_io = NULL;
2766 + }
2767 +
2768 + return error;
2769 +}
2770 +
2771 +/*
2772 + * Tear down interrupt for a given DPRC object
2773 + */
2774 +static void dprc_teardown_irq(struct fsl_mc_device *mc_dev)
2775 +{
2776 + struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
2777 +
2778 + (void)disable_dprc_irq(mc_dev);
2779 +
2780 + devm_free_irq(&mc_dev->dev, irq->msi_desc->irq, &mc_dev->dev);
2781 +
2782 + fsl_mc_free_irqs(mc_dev);
2783 +}
2784 +
2785 +/**
2786 + * dprc_remove - callback invoked when a DPRC is being unbound from this driver
2787 + *
2788 + * @mc_dev: Pointer to fsl-mc device representing the DPRC
2789 + *
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.
2794 + */
2795 +static int dprc_remove(struct fsl_mc_device *mc_dev)
2796 +{
2797 + int error;
2798 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
2799 +
2800 + if (!is_fsl_mc_bus_dprc(mc_dev))
2801 + return -EINVAL;
2802 + if (!mc_dev->mc_io)
2803 + return -EINVAL;
2804 +
2805 + if (!mc_bus->irq_resources)
2806 + return -EINVAL;
2807 +
2808 + if (dev_get_msi_domain(&mc_dev->dev))
2809 + dprc_teardown_irq(mc_dev);
2810 +
2811 + device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
2812 +
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);
2816 + }
2817 +
2818 + fsl_mc_cleanup_all_resource_pools(mc_dev);
2819 +
2820 + error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
2821 + if (error < 0)
2822 + dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error);
2823 +
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;
2827 + }
2828 +
2829 + dev_info(&mc_dev->dev, "DPRC device unbound from driver");
2830 + return 0;
2831 +}
2832 +
2833 +static const struct fsl_mc_device_id match_id_table[] = {
2834 + {
2835 + .vendor = FSL_MC_VENDOR_FREESCALE,
2836 + .obj_type = "dprc"},
2837 + {.vendor = 0x0},
2838 +};
2839 +
2840 +static struct fsl_mc_driver dprc_driver = {
2841 + .driver = {
2842 + .name = FSL_MC_DPRC_DRIVER_NAME,
2843 + .owner = THIS_MODULE,
2844 + .pm = NULL,
2845 + },
2846 + .match_id_table = match_id_table,
2847 + .probe = dprc_probe,
2848 + .remove = dprc_remove,
2849 +};
2850 +
2851 +int __init dprc_driver_init(void)
2852 +{
2853 + return fsl_mc_driver_register(&dprc_driver);
2854 +}
2855 +
2856 +void dprc_driver_exit(void)
2857 +{
2858 + fsl_mc_driver_unregister(&dprc_driver);
2859 +}
2860 --- a/drivers/staging/fsl-mc/bus/dprc.c
2861 +++ /dev/null
2862 @@ -1,757 +0,0 @@
2863 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2864 -/*
2865 - * Copyright 2013-2016 Freescale Semiconductor Inc.
2866 - *
2867 - */
2868 -#include <linux/kernel.h>
2869 -#include "../include/mc.h"
2870 -#include "dprc.h"
2871 -
2872 -#include "dprc-cmd.h"
2873 -
2874 -/**
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
2880 - *
2881 - * Return: '0' on Success; Error code otherwise.
2882 - *
2883 - * @warning Required before any operation on the object.
2884 - */
2885 -int dprc_open(struct fsl_mc_io *mc_io,
2886 - u32 cmd_flags,
2887 - int container_id,
2888 - u16 *token)
2889 -{
2890 - struct mc_command cmd = { 0 };
2891 - struct dprc_cmd_open *cmd_params;
2892 - int err;
2893 -
2894 - /* prepare command */
2895 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags,
2896 - 0);
2897 - cmd_params = (struct dprc_cmd_open *)cmd.params;
2898 - cmd_params->container_id = cpu_to_le32(container_id);
2899 -
2900 - /* send command to mc*/
2901 - err = mc_send_command(mc_io, &cmd);
2902 - if (err)
2903 - return err;
2904 -
2905 - /* retrieve response parameters */
2906 - *token = mc_cmd_hdr_read_token(&cmd);
2907 -
2908 - return 0;
2909 -}
2910 -EXPORT_SYMBOL(dprc_open);
2911 -
2912 -/**
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
2917 - *
2918 - * After this function is called, no further operations are
2919 - * allowed on the object without opening a new control session.
2920 - *
2921 - * Return: '0' on Success; Error code otherwise.
2922 - */
2923 -int dprc_close(struct fsl_mc_io *mc_io,
2924 - u32 cmd_flags,
2925 - u16 token)
2926 -{
2927 - struct mc_command cmd = { 0 };
2928 -
2929 - /* prepare command */
2930 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags,
2931 - token);
2932 -
2933 - /* send command to mc*/
2934 - return mc_send_command(mc_io, &cmd);
2935 -}
2936 -EXPORT_SYMBOL(dprc_close);
2937 -
2938 -/**
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
2947 - *
2948 - * Return: '0' on Success; Error code otherwise.
2949 - */
2950 -int dprc_get_irq(struct fsl_mc_io *mc_io,
2951 - u32 cmd_flags,
2952 - u16 token,
2953 - u8 irq_index,
2954 - int *type,
2955 - struct dprc_irq_cfg *irq_cfg)
2956 -{
2957 - struct mc_command cmd = { 0 };
2958 - struct dprc_cmd_get_irq *cmd_params;
2959 - struct dprc_rsp_get_irq *rsp_params;
2960 - int err;
2961 -
2962 - /* prepare command */
2963 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ,
2964 - cmd_flags,
2965 - token);
2966 - cmd_params = (struct dprc_cmd_get_irq *)cmd.params;
2967 - cmd_params->irq_index = irq_index;
2968 -
2969 - /* send command to mc*/
2970 - err = mc_send_command(mc_io, &cmd);
2971 - if (err)
2972 - return err;
2973 -
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);
2980 -
2981 - return 0;
2982 -}
2983 -
2984 -/**
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
2991 - *
2992 - * Return: '0' on Success; Error code otherwise.
2993 - */
2994 -int dprc_set_irq(struct fsl_mc_io *mc_io,
2995 - u32 cmd_flags,
2996 - u16 token,
2997 - u8 irq_index,
2998 - struct dprc_irq_cfg *irq_cfg)
2999 -{
3000 - struct mc_command cmd = { 0 };
3001 - struct dprc_cmd_set_irq *cmd_params;
3002 -
3003 - /* prepare command */
3004 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ,
3005 - cmd_flags,
3006 - token);
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);
3012 -
3013 - /* send command to mc*/
3014 - return mc_send_command(mc_io, &cmd);
3015 -}
3016 -
3017 -/**
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
3024 - *
3025 - * Return: '0' on Success; Error code otherwise.
3026 - */
3027 -int dprc_get_irq_enable(struct fsl_mc_io *mc_io,
3028 - u32 cmd_flags,
3029 - u16 token,
3030 - u8 irq_index,
3031 - u8 *en)
3032 -{
3033 - struct mc_command cmd = { 0 };
3034 - struct dprc_cmd_get_irq_enable *cmd_params;
3035 - struct dprc_rsp_get_irq_enable *rsp_params;
3036 - int err;
3037 -
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;
3043 -
3044 - /* send command to mc*/
3045 - err = mc_send_command(mc_io, &cmd);
3046 - if (err)
3047 - return err;
3048 -
3049 - /* retrieve response parameters */
3050 - rsp_params = (struct dprc_rsp_get_irq_enable *)cmd.params;
3051 - *en = rsp_params->enabled & DPRC_ENABLE;
3052 -
3053 - return 0;
3054 -}
3055 -
3056 -/**
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
3063 - *
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
3067 - * an interrupt.
3068 - *
3069 - * Return: '0' on Success; Error code otherwise.
3070 - */
3071 -int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
3072 - u32 cmd_flags,
3073 - u16 token,
3074 - u8 irq_index,
3075 - u8 en)
3076 -{
3077 - struct mc_command cmd = { 0 };
3078 - struct dprc_cmd_set_irq_enable *cmd_params;
3079 -
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;
3086 -
3087 - /* send command to mc*/
3088 - return mc_send_command(mc_io, &cmd);
3089 -}
3090 -
3091 -/**
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
3098 - *
3099 - * Every interrupt can have up to 32 causes and the interrupt model supports
3100 - * masking/unmasking each cause independently
3101 - *
3102 - * Return: '0' on Success; Error code otherwise.
3103 - */
3104 -int dprc_get_irq_mask(struct fsl_mc_io *mc_io,
3105 - u32 cmd_flags,
3106 - u16 token,
3107 - u8 irq_index,
3108 - u32 *mask)
3109 -{
3110 - struct mc_command cmd = { 0 };
3111 - struct dprc_cmd_get_irq_mask *cmd_params;
3112 - struct dprc_rsp_get_irq_mask *rsp_params;
3113 - int err;
3114 -
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;
3120 -
3121 - /* send command to mc*/
3122 - err = mc_send_command(mc_io, &cmd);
3123 - if (err)
3124 - return err;
3125 -
3126 - /* retrieve response parameters */
3127 - rsp_params = (struct dprc_rsp_get_irq_mask *)cmd.params;
3128 - *mask = le32_to_cpu(rsp_params->mask);
3129 -
3130 - return 0;
3131 -}
3132 -
3133 -/**
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;
3140 - * each bit:
3141 - * 0 = ignore event
3142 - * 1 = consider event for asserting irq
3143 - *
3144 - * Every interrupt can have up to 32 causes and the interrupt model supports
3145 - * masking/unmasking each cause independently
3146 - *
3147 - * Return: '0' on Success; Error code otherwise.
3148 - */
3149 -int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
3150 - u32 cmd_flags,
3151 - u16 token,
3152 - u8 irq_index,
3153 - u32 mask)
3154 -{
3155 - struct mc_command cmd = { 0 };
3156 - struct dprc_cmd_set_irq_mask *cmd_params;
3157 -
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;
3164 -
3165 - /* send command to mc*/
3166 - return mc_send_command(mc_io, &cmd);
3167 -}
3168 -
3169 -/**
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
3178 - *
3179 - * Return: '0' on Success; Error code otherwise.
3180 - */
3181 -int dprc_get_irq_status(struct fsl_mc_io *mc_io,
3182 - u32 cmd_flags,
3183 - u16 token,
3184 - u8 irq_index,
3185 - u32 *status)
3186 -{
3187 - struct mc_command cmd = { 0 };
3188 - struct dprc_cmd_get_irq_status *cmd_params;
3189 - struct dprc_rsp_get_irq_status *rsp_params;
3190 - int err;
3191 -
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;
3198 -
3199 - /* send command to mc*/
3200 - err = mc_send_command(mc_io, &cmd);
3201 - if (err)
3202 - return err;
3203 -
3204 - /* retrieve response parameters */
3205 - rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params;
3206 - *status = le32_to_cpu(rsp_params->status);
3207 -
3208 - return 0;
3209 -}
3210 -
3211 -/**
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
3220 - *
3221 - * Return: '0' on Success; Error code otherwise.
3222 - */
3223 -int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
3224 - u32 cmd_flags,
3225 - u16 token,
3226 - u8 irq_index,
3227 - u32 status)
3228 -{
3229 - struct mc_command cmd = { 0 };
3230 - struct dprc_cmd_clear_irq_status *cmd_params;
3231 -
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;
3238 -
3239 - /* send command to mc*/
3240 - return mc_send_command(mc_io, &cmd);
3241 -}
3242 -
3243 -/**
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
3249 - *
3250 - * Return: '0' on Success; Error code otherwise.
3251 - */
3252 -int dprc_get_attributes(struct fsl_mc_io *mc_io,
3253 - u32 cmd_flags,
3254 - u16 token,
3255 - struct dprc_attributes *attr)
3256 -{
3257 - struct mc_command cmd = { 0 };
3258 - struct dprc_rsp_get_attributes *rsp_params;
3259 - int err;
3260 -
3261 - /* prepare command */
3262 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR,
3263 - cmd_flags,
3264 - token);
3265 -
3266 - /* send command to mc*/
3267 - err = mc_send_command(mc_io, &cmd);
3268 - if (err)
3269 - return err;
3270 -
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);
3277 -
3278 - return 0;
3279 -}
3280 -
3281 -/**
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
3287 - *
3288 - * Return: '0' on Success; Error code otherwise.
3289 - */
3290 -int dprc_get_obj_count(struct fsl_mc_io *mc_io,
3291 - u32 cmd_flags,
3292 - u16 token,
3293 - int *obj_count)
3294 -{
3295 - struct mc_command cmd = { 0 };
3296 - struct dprc_rsp_get_obj_count *rsp_params;
3297 - int err;
3298 -
3299 - /* prepare command */
3300 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT,
3301 - cmd_flags, token);
3302 -
3303 - /* send command to mc*/
3304 - err = mc_send_command(mc_io, &cmd);
3305 - if (err)
3306 - return err;
3307 -
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);
3311 -
3312 - return 0;
3313 -}
3314 -EXPORT_SYMBOL(dprc_get_obj_count);
3315 -
3316 -/**
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
3323 - *
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().
3328 - *
3329 - * Return: '0' on Success; Error code otherwise.
3330 - */
3331 -int dprc_get_obj(struct fsl_mc_io *mc_io,
3332 - u32 cmd_flags,
3333 - u16 token,
3334 - int obj_index,
3335 - struct fsl_mc_obj_desc *obj_desc)
3336 -{
3337 - struct mc_command cmd = { 0 };
3338 - struct dprc_cmd_get_obj *cmd_params;
3339 - struct dprc_rsp_get_obj *rsp_params;
3340 - int err;
3341 -
3342 - /* prepare command */
3343 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ,
3344 - cmd_flags,
3345 - token);
3346 - cmd_params = (struct dprc_cmd_get_obj *)cmd.params;
3347 - cmd_params->obj_index = cpu_to_le32(obj_index);
3348 -
3349 - /* send command to mc*/
3350 - err = mc_send_command(mc_io, &cmd);
3351 - if (err)
3352 - return err;
3353 -
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';
3368 - return 0;
3369 -}
3370 -EXPORT_SYMBOL(dprc_get_obj);
3371 -
3372 -/**
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
3381 - *
3382 - * Return: '0' on Success; Error code otherwise.
3383 - */
3384 -int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
3385 - u32 cmd_flags,
3386 - u16 token,
3387 - char *obj_type,
3388 - int obj_id,
3389 - u8 irq_index,
3390 - struct dprc_irq_cfg *irq_cfg)
3391 -{
3392 - struct mc_command cmd = { 0 };
3393 - struct dprc_cmd_set_obj_irq *cmd_params;
3394 -
3395 - /* prepare command */
3396 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ,
3397 - cmd_flags,
3398 - token);
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';
3407 -
3408 - /* send command to mc*/
3409 - return mc_send_command(mc_io, &cmd);
3410 -}
3411 -EXPORT_SYMBOL(dprc_set_obj_irq);
3412 -
3413 -/**
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
3424 - *
3425 - * Return: '0' on Success; Error code otherwise.
3426 - */
3427 -int dprc_get_obj_irq(struct fsl_mc_io *mc_io,
3428 - u32 cmd_flags,
3429 - u16 token,
3430 - char *obj_type,
3431 - int obj_id,
3432 - u8 irq_index,
3433 - int *type,
3434 - struct dprc_irq_cfg *irq_cfg)
3435 -{
3436 - struct mc_command cmd = { 0 };
3437 - struct dprc_cmd_get_obj_irq *cmd_params;
3438 - struct dprc_rsp_get_obj_irq *rsp_params;
3439 - int err;
3440 -
3441 - /* prepare command */
3442 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_IRQ,
3443 - cmd_flags,
3444 - token);
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';
3450 -
3451 - /* send command to mc*/
3452 - err = mc_send_command(mc_io, &cmd);
3453 - if (err)
3454 - return err;
3455 -
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);
3462 -
3463 - return 0;
3464 -}
3465 -EXPORT_SYMBOL(dprc_get_obj_irq);
3466 -
3467 -/**
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
3476 - *
3477 - * Return: '0' on Success; Error code otherwise.
3478 - */
3479 -int dprc_get_res_count(struct fsl_mc_io *mc_io,
3480 - u32 cmd_flags,
3481 - u16 token,
3482 - char *type,
3483 - int *res_count)
3484 -{
3485 - struct mc_command cmd = { 0 };
3486 - struct dprc_cmd_get_res_count *cmd_params;
3487 - struct dprc_rsp_get_res_count *rsp_params;
3488 - int err;
3489 -
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';
3496 -
3497 - /* send command to mc*/
3498 - err = mc_send_command(mc_io, &cmd);
3499 - if (err)
3500 - return err;
3501 -
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);
3505 -
3506 - return 0;
3507 -}
3508 -EXPORT_SYMBOL(dprc_get_res_count);
3509 -
3510 -/**
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
3519 - *
3520 - * Return: '0' on Success; Error code otherwise.
3521 - */
3522 -int dprc_get_obj_region(struct fsl_mc_io *mc_io,
3523 - u32 cmd_flags,
3524 - u16 token,
3525 - char *obj_type,
3526 - int obj_id,
3527 - u8 region_index,
3528 - struct dprc_region_desc *region_desc)
3529 -{
3530 - struct mc_command cmd = { 0 };
3531 - struct dprc_cmd_get_obj_region *cmd_params;
3532 - struct dprc_rsp_get_obj_region *rsp_params;
3533 - int err;
3534 -
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';
3543 -
3544 - /* send command to mc*/
3545 - err = mc_send_command(mc_io, &cmd);
3546 - if (err)
3547 - return err;
3548 -
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);
3553 -
3554 - return 0;
3555 -}
3556 -EXPORT_SYMBOL(dprc_get_obj_region);
3557 -
3558 -/**
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
3564 - *
3565 - * Return: '0' on Success; Error code otherwise.
3566 - */
3567 -int dprc_get_api_version(struct fsl_mc_io *mc_io,
3568 - u32 cmd_flags,
3569 - u16 *major_ver,
3570 - u16 *minor_ver)
3571 -{
3572 - struct mc_command cmd = { 0 };
3573 - int err;
3574 -
3575 - /* prepare command */
3576 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION,
3577 - cmd_flags, 0);
3578 -
3579 - /* send command to mc */
3580 - err = mc_send_command(mc_io, &cmd);
3581 - if (err)
3582 - return err;
3583 -
3584 - /* retrieve response parameters */
3585 - mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
3586 -
3587 - return 0;
3588 -}
3589 -
3590 -/**
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
3595 - *
3596 - * Return: '0' on Success; Error code otherwise.
3597 - */
3598 -int dprc_get_container_id(struct fsl_mc_io *mc_io,
3599 - u32 cmd_flags,
3600 - int *container_id)
3601 -{
3602 - struct mc_command cmd = { 0 };
3603 - int err;
3604 -
3605 - /* prepare command */
3606 - cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID,
3607 - cmd_flags,
3608 - 0);
3609 -
3610 - /* send command to mc*/
3611 - err = mc_send_command(mc_io, &cmd);
3612 - if (err)
3613 - return err;
3614 -
3615 - /* retrieve response parameters */
3616 - *container_id = (int)mc_cmd_read_object_id(&cmd);
3617 -
3618 - return 0;
3619 -}
3620 --- /dev/null
3621 +++ b/drivers/bus/fsl-mc/dprc.c
3622 @@ -0,0 +1,576 @@
3623 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
3624 +/*
3625 + * Copyright 2013-2016 Freescale Semiconductor Inc.
3626 + *
3627 + */
3628 +#include <linux/kernel.h>
3629 +#include <linux/fsl/mc.h>
3630 +
3631 +#include "fsl-mc-private.h"
3632 +
3633 +/**
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
3639 + *
3640 + * Return: '0' on Success; Error code otherwise.
3641 + *
3642 + * @warning Required before any operation on the object.
3643 + */
3644 +int dprc_open(struct fsl_mc_io *mc_io,
3645 + u32 cmd_flags,
3646 + int container_id,
3647 + u16 *token)
3648 +{
3649 + struct fsl_mc_command cmd = { 0 };
3650 + struct dprc_cmd_open *cmd_params;
3651 + int err;
3652 +
3653 + /* prepare command */
3654 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags,
3655 + 0);
3656 + cmd_params = (struct dprc_cmd_open *)cmd.params;
3657 + cmd_params->container_id = cpu_to_le32(container_id);
3658 +
3659 + /* send command to mc*/
3660 + err = mc_send_command(mc_io, &cmd);
3661 + if (err)
3662 + return err;
3663 +
3664 + /* retrieve response parameters */
3665 + *token = mc_cmd_hdr_read_token(&cmd);
3666 +
3667 + return 0;
3668 +}
3669 +EXPORT_SYMBOL_GPL(dprc_open);
3670 +
3671 +/**
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
3676 + *
3677 + * After this function is called, no further operations are
3678 + * allowed on the object without opening a new control session.
3679 + *
3680 + * Return: '0' on Success; Error code otherwise.
3681 + */
3682 +int dprc_close(struct fsl_mc_io *mc_io,
3683 + u32 cmd_flags,
3684 + u16 token)
3685 +{
3686 + struct fsl_mc_command cmd = { 0 };
3687 +
3688 + /* prepare command */
3689 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags,
3690 + token);
3691 +
3692 + /* send command to mc*/
3693 + return mc_send_command(mc_io, &cmd);
3694 +}
3695 +EXPORT_SYMBOL_GPL(dprc_close);
3696 +
3697 +/**
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
3703 + *
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
3706 + * restarted.
3707 + *
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
3711 + * closed.
3712 + *
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
3715 + * aware of that.
3716 + *
3717 + * Return: '0' on Success; Error code otherwise.
3718 + */
3719 +int dprc_reset_container(struct fsl_mc_io *mc_io,
3720 + u32 cmd_flags,
3721 + u16 token,
3722 + int child_container_id)
3723 +{
3724 + struct fsl_mc_command cmd = { 0 };
3725 + struct dprc_cmd_reset_container *cmd_params;
3726 +
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);
3732 +
3733 + /* send command to mc*/
3734 + return mc_send_command(mc_io, &cmd);
3735 +}
3736 +EXPORT_SYMBOL_GPL(dprc_reset_container);
3737 +
3738 +/**
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
3745 + *
3746 + * Return: '0' on Success; Error code otherwise.
3747 + */
3748 +int dprc_set_irq(struct fsl_mc_io *mc_io,
3749 + u32 cmd_flags,
3750 + u16 token,
3751 + u8 irq_index,
3752 + struct dprc_irq_cfg *irq_cfg)
3753 +{
3754 + struct fsl_mc_command cmd = { 0 };
3755 + struct dprc_cmd_set_irq *cmd_params;
3756 +
3757 + /* prepare command */
3758 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ,
3759 + cmd_flags,
3760 + token);
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);
3766 +
3767 + /* send command to mc*/
3768 + return mc_send_command(mc_io, &cmd);
3769 +}
3770 +
3771 +/**
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
3778 + *
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
3782 + * an interrupt.
3783 + *
3784 + * Return: '0' on Success; Error code otherwise.
3785 + */
3786 +int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
3787 + u32 cmd_flags,
3788 + u16 token,
3789 + u8 irq_index,
3790 + u8 en)
3791 +{
3792 + struct fsl_mc_command cmd = { 0 };
3793 + struct dprc_cmd_set_irq_enable *cmd_params;
3794 +
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;
3801 +
3802 + /* send command to mc*/
3803 + return mc_send_command(mc_io, &cmd);
3804 +}
3805 +
3806 +/**
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;
3813 + * each bit:
3814 + * 0 = ignore event
3815 + * 1 = consider event for asserting irq
3816 + *
3817 + * Every interrupt can have up to 32 causes and the interrupt model supports
3818 + * masking/unmasking each cause independently
3819 + *
3820 + * Return: '0' on Success; Error code otherwise.
3821 + */
3822 +int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
3823 + u32 cmd_flags,
3824 + u16 token,
3825 + u8 irq_index,
3826 + u32 mask)
3827 +{
3828 + struct fsl_mc_command cmd = { 0 };
3829 + struct dprc_cmd_set_irq_mask *cmd_params;
3830 +
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;
3837 +
3838 + /* send command to mc*/
3839 + return mc_send_command(mc_io, &cmd);
3840 +}
3841 +
3842 +/**
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
3851 + *
3852 + * Return: '0' on Success; Error code otherwise.
3853 + */
3854 +int dprc_get_irq_status(struct fsl_mc_io *mc_io,
3855 + u32 cmd_flags,
3856 + u16 token,
3857 + u8 irq_index,
3858 + u32 *status)
3859 +{
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;
3863 + int err;
3864 +
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;
3871 +
3872 + /* send command to mc*/
3873 + err = mc_send_command(mc_io, &cmd);
3874 + if (err)
3875 + return err;
3876 +
3877 + /* retrieve response parameters */
3878 + rsp_params = (struct dprc_rsp_get_irq_status *)cmd.params;
3879 + *status = le32_to_cpu(rsp_params->status);
3880 +
3881 + return 0;
3882 +}
3883 +
3884 +/**
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
3893 + *
3894 + * Return: '0' on Success; Error code otherwise.
3895 + */
3896 +int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
3897 + u32 cmd_flags,
3898 + u16 token,
3899 + u8 irq_index,
3900 + u32 status)
3901 +{
3902 + struct fsl_mc_command cmd = { 0 };
3903 + struct dprc_cmd_clear_irq_status *cmd_params;
3904 +
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;
3911 +
3912 + /* send command to mc*/
3913 + return mc_send_command(mc_io, &cmd);
3914 +}
3915 +
3916 +/**
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
3922 + *
3923 + * Return: '0' on Success; Error code otherwise.
3924 + */
3925 +int dprc_get_attributes(struct fsl_mc_io *mc_io,
3926 + u32 cmd_flags,
3927 + u16 token,
3928 + struct dprc_attributes *attr)
3929 +{
3930 + struct fsl_mc_command cmd = { 0 };
3931 + struct dprc_rsp_get_attributes *rsp_params;
3932 + int err;
3933 +
3934 + /* prepare command */
3935 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR,
3936 + cmd_flags,
3937 + token);
3938 +
3939 + /* send command to mc*/
3940 + err = mc_send_command(mc_io, &cmd);
3941 + if (err)
3942 + return err;
3943 +
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);
3950 +
3951 + return 0;
3952 +}
3953 +
3954 +/**
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
3960 + *
3961 + * Return: '0' on Success; Error code otherwise.
3962 + */
3963 +int dprc_get_obj_count(struct fsl_mc_io *mc_io,
3964 + u32 cmd_flags,
3965 + u16 token,
3966 + int *obj_count)
3967 +{
3968 + struct fsl_mc_command cmd = { 0 };
3969 + struct dprc_rsp_get_obj_count *rsp_params;
3970 + int err;
3971 +
3972 + /* prepare command */
3973 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT,
3974 + cmd_flags, token);
3975 +
3976 + /* send command to mc*/
3977 + err = mc_send_command(mc_io, &cmd);
3978 + if (err)
3979 + return err;
3980 +
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);
3984 +
3985 + return 0;
3986 +}
3987 +EXPORT_SYMBOL_GPL(dprc_get_obj_count);
3988 +
3989 +/**
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
3996 + *
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().
4001 + *
4002 + * Return: '0' on Success; Error code otherwise.
4003 + */
4004 +int dprc_get_obj(struct fsl_mc_io *mc_io,
4005 + u32 cmd_flags,
4006 + u16 token,
4007 + int obj_index,
4008 + struct fsl_mc_obj_desc *obj_desc)
4009 +{
4010 + struct fsl_mc_command cmd = { 0 };
4011 + struct dprc_cmd_get_obj *cmd_params;
4012 + struct dprc_rsp_get_obj *rsp_params;
4013 + int err;
4014 +
4015 + /* prepare command */
4016 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ,
4017 + cmd_flags,
4018 + token);
4019 + cmd_params = (struct dprc_cmd_get_obj *)cmd.params;
4020 + cmd_params->obj_index = cpu_to_le32(obj_index);
4021 +
4022 + /* send command to mc*/
4023 + err = mc_send_command(mc_io, &cmd);
4024 + if (err)
4025 + return err;
4026 +
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';
4041 + return 0;
4042 +}
4043 +EXPORT_SYMBOL_GPL(dprc_get_obj);
4044 +
4045 +/**
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
4054 + *
4055 + * Return: '0' on Success; Error code otherwise.
4056 + */
4057 +int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
4058 + u32 cmd_flags,
4059 + u16 token,
4060 + char *obj_type,
4061 + int obj_id,
4062 + u8 irq_index,
4063 + struct dprc_irq_cfg *irq_cfg)
4064 +{
4065 + struct fsl_mc_command cmd = { 0 };
4066 + struct dprc_cmd_set_obj_irq *cmd_params;
4067 +
4068 + /* prepare command */
4069 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ,
4070 + cmd_flags,
4071 + token);
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';
4080 +
4081 + /* send command to mc*/
4082 + return mc_send_command(mc_io, &cmd);
4083 +}
4084 +EXPORT_SYMBOL_GPL(dprc_set_obj_irq);
4085 +
4086 +/**
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
4095 + *
4096 + * Return: '0' on Success; Error code otherwise.
4097 + */
4098 +int dprc_get_obj_region(struct fsl_mc_io *mc_io,
4099 + u32 cmd_flags,
4100 + u16 token,
4101 + char *obj_type,
4102 + int obj_id,
4103 + u8 region_index,
4104 + struct dprc_region_desc *region_desc)
4105 +{
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;
4109 + int err;
4110 +
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';
4119 +
4120 + /* send command to mc*/
4121 + err = mc_send_command(mc_io, &cmd);
4122 + if (err)
4123 + return err;
4124 +
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);
4132 +
4133 + return 0;
4134 +}
4135 +EXPORT_SYMBOL_GPL(dprc_get_obj_region);
4136 +
4137 +/**
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
4143 + *
4144 + * Return: '0' on Success; Error code otherwise.
4145 + */
4146 +int dprc_get_api_version(struct fsl_mc_io *mc_io,
4147 + u32 cmd_flags,
4148 + u16 *major_ver,
4149 + u16 *minor_ver)
4150 +{
4151 + struct fsl_mc_command cmd = { 0 };
4152 + int err;
4153 +
4154 + /* prepare command */
4155 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_API_VERSION,
4156 + cmd_flags, 0);
4157 +
4158 + /* send command to mc */
4159 + err = mc_send_command(mc_io, &cmd);
4160 + if (err)
4161 + return err;
4162 +
4163 + /* retrieve response parameters */
4164 + mc_cmd_read_api_version(&cmd, major_ver, minor_ver);
4165 +
4166 + return 0;
4167 +}
4168 +
4169 +/**
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
4174 + *
4175 + * Return: '0' on Success; Error code otherwise.
4176 + */
4177 +int dprc_get_container_id(struct fsl_mc_io *mc_io,
4178 + u32 cmd_flags,
4179 + int *container_id)
4180 +{
4181 + struct fsl_mc_command cmd = { 0 };
4182 + int err;
4183 +
4184 + /* prepare command */
4185 + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID,
4186 + cmd_flags,
4187 + 0);
4188 +
4189 + /* send command to mc*/
4190 + err = mc_send_command(mc_io, &cmd);
4191 + if (err)
4192 + return err;
4193 +
4194 + /* retrieve response parameters */
4195 + *container_id = (int)mc_cmd_read_object_id(&cmd);
4196 +
4197 + return 0;
4198 +}
4199 --- a/drivers/staging/fsl-mc/bus/fsl-mc-allocator.c
4200 +++ /dev/null
4201 @@ -1,663 +0,0 @@
4202 -// SPDX-License-Identifier: GPL-2.0
4203 -/*
4204 - * fsl-mc object allocator driver
4205 - *
4206 - * Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
4207 - *
4208 - */
4209 -
4210 -#include <linux/module.h>
4211 -#include <linux/msi.h>
4212 -#include "../include/mc.h"
4213 -
4214 -#include "fsl-mc-private.h"
4215 -
4216 -static bool __must_check fsl_mc_is_allocatable(const char *obj_type)
4217 -{
4218 - return strcmp(obj_type, "dpbp") == 0 ||
4219 - strcmp(obj_type, "dpmcp") == 0 ||
4220 - strcmp(obj_type, "dpcon") == 0;
4221 -}
4222 -
4223 -/**
4224 - * fsl_mc_resource_pool_add_device - add allocatable object to a resource
4225 - * pool of a given fsl-mc bus
4226 - *
4227 - * @mc_bus: pointer to the fsl-mc bus
4228 - * @pool_type: pool type
4229 - * @mc_dev: pointer to allocatable fsl-mc device
4230 - */
4231 -static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
4232 - *mc_bus,
4233 - enum fsl_mc_pool_type
4234 - pool_type,
4235 - struct fsl_mc_device
4236 - *mc_dev)
4237 -{
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;
4242 -
4243 - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
4244 - goto out;
4245 - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
4246 - goto out;
4247 - if (WARN_ON(mc_dev->resource))
4248 - goto out;
4249 -
4250 - res_pool = &mc_bus->resource_pools[pool_type];
4251 - if (WARN_ON(res_pool->type != pool_type))
4252 - goto out;
4253 - if (WARN_ON(res_pool->mc_bus != mc_bus))
4254 - goto out;
4255 -
4256 - mutex_lock(&res_pool->mutex);
4257 -
4258 - if (WARN_ON(res_pool->max_count < 0))
4259 - goto out_unlock;
4260 - if (WARN_ON(res_pool->free_count < 0 ||
4261 - res_pool->free_count > res_pool->max_count))
4262 - goto out_unlock;
4263 -
4264 - resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource),
4265 - GFP_KERNEL);
4266 - if (!resource) {
4267 - error = -ENOMEM;
4268 - dev_err(&mc_bus_dev->dev,
4269 - "Failed to allocate memory for fsl_mc_resource\n");
4270 - goto out_unlock;
4271 - }
4272 -
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++;
4282 - error = 0;
4283 -out_unlock:
4284 - mutex_unlock(&res_pool->mutex);
4285 -out:
4286 - return error;
4287 -}
4288 -
4289 -/**
4290 - * fsl_mc_resource_pool_remove_device - remove an allocatable device from a
4291 - * resource pool
4292 - *
4293 - * @mc_dev: pointer to allocatable fsl-mc device
4294 - *
4295 - * It permanently removes an allocatable fsl-mc device from the resource
4296 - * pool. It's an error if the device is in use.
4297 - */
4298 -static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
4299 - *mc_dev)
4300 -{
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;
4306 -
4307 - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
4308 - goto out;
4309 -
4310 - resource = mc_dev->resource;
4311 - if (WARN_ON(!resource || resource->data != mc_dev))
4312 - goto out;
4313 -
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]))
4318 - goto out;
4319 -
4320 - mutex_lock(&res_pool->mutex);
4321 -
4322 - if (WARN_ON(res_pool->max_count <= 0))
4323 - goto out_unlock;
4324 - if (WARN_ON(res_pool->free_count <= 0 ||
4325 - res_pool->free_count > res_pool->max_count))
4326 - goto out_unlock;
4327 -
4328 - /*
4329 - * If the device is currently allocated, its resource is not
4330 - * in the free list and thus, the device cannot be removed.
4331 - */
4332 - if (list_empty(&resource->node)) {
4333 - error = -EBUSY;
4334 - dev_err(&mc_bus_dev->dev,
4335 - "Device %s cannot be removed from resource pool\n",
4336 - dev_name(&mc_dev->dev));
4337 - goto out_unlock;
4338 - }
4339 -
4340 - list_del_init(&resource->node);
4341 - res_pool->free_count--;
4342 - res_pool->max_count--;
4343 -
4344 - devm_kfree(&mc_bus_dev->dev, resource);
4345 - mc_dev->resource = NULL;
4346 - error = 0;
4347 -out_unlock:
4348 - mutex_unlock(&res_pool->mutex);
4349 -out:
4350 - return error;
4351 -}
4352 -
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",
4358 -};
4359 -
4360 -static int __must_check object_type_to_pool_type(const char *object_type,
4361 - enum fsl_mc_pool_type
4362 - *pool_type)
4363 -{
4364 - unsigned int i;
4365 -
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) {
4368 - *pool_type = i;
4369 - return 0;
4370 - }
4371 - }
4372 -
4373 - return -EINVAL;
4374 -}
4375 -
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)
4379 -{
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;
4384 -
4385 - BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) !=
4386 - FSL_MC_NUM_POOL_TYPES);
4387 -
4388 - *new_resource = NULL;
4389 - if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
4390 - goto out;
4391 -
4392 - res_pool = &mc_bus->resource_pools[pool_type];
4393 - if (WARN_ON(res_pool->mc_bus != mc_bus))
4394 - goto out;
4395 -
4396 - mutex_lock(&res_pool->mutex);
4397 - resource = list_first_entry_or_null(&res_pool->free_list,
4398 - struct fsl_mc_resource, node);
4399 -
4400 - if (!resource) {
4401 - WARN_ON(res_pool->free_count != 0);
4402 - error = -ENXIO;
4403 - dev_err(&mc_bus_dev->dev,
4404 - "No more resources of type %s left\n",
4405 - fsl_mc_pool_type_strings[pool_type]);
4406 - goto out_unlock;
4407 - }
4408 -
4409 - if (WARN_ON(resource->type != pool_type))
4410 - goto out_unlock;
4411 - if (WARN_ON(resource->parent_pool != res_pool))
4412 - goto out_unlock;
4413 - if (WARN_ON(res_pool->free_count <= 0 ||
4414 - res_pool->free_count > res_pool->max_count))
4415 - goto out_unlock;
4416 -
4417 - list_del_init(&resource->node);
4418 -
4419 - res_pool->free_count--;
4420 - error = 0;
4421 -out_unlock:
4422 - mutex_unlock(&res_pool->mutex);
4423 - *new_resource = resource;
4424 -out:
4425 - return error;
4426 -}
4427 -EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate);
4428 -
4429 -void fsl_mc_resource_free(struct fsl_mc_resource *resource)
4430 -{
4431 - struct fsl_mc_resource_pool *res_pool;
4432 -
4433 - res_pool = resource->parent_pool;
4434 - if (WARN_ON(resource->type != res_pool->type))
4435 - return;
4436 -
4437 - mutex_lock(&res_pool->mutex);
4438 - if (WARN_ON(res_pool->free_count < 0 ||
4439 - res_pool->free_count >= res_pool->max_count))
4440 - goto out_unlock;
4441 -
4442 - if (WARN_ON(!list_empty(&resource->node)))
4443 - goto out_unlock;
4444 -
4445 - list_add_tail(&resource->node, &res_pool->free_list);
4446 - res_pool->free_count++;
4447 -out_unlock:
4448 - mutex_unlock(&res_pool->mutex);
4449 -}
4450 -EXPORT_SYMBOL_GPL(fsl_mc_resource_free);
4451 -
4452 -/**
4453 - * fsl_mc_object_allocate - Allocates an fsl-mc object of the given
4454 - * pool type from a given fsl-mc bus instance
4455 - *
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
4461 - *
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.
4465 - *
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
4468 - * this function.
4469 - */
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)
4473 -{
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;
4479 -
4480 - *new_mc_adev = NULL;
4481 - if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC))
4482 - goto error;
4483 -
4484 - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent)))
4485 - goto error;
4486 -
4487 - if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP))
4488 - goto error;
4489 -
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);
4493 - if (error < 0)
4494 - goto error;
4495 -
4496 - mc_adev = resource->data;
4497 - if (WARN_ON(!mc_adev))
4498 - goto error;
4499 -
4500 - *new_mc_adev = mc_adev;
4501 - return 0;
4502 -error:
4503 - if (resource)
4504 - fsl_mc_resource_free(resource);
4505 -
4506 - return error;
4507 -}
4508 -EXPORT_SYMBOL_GPL(fsl_mc_object_allocate);
4509 -
4510 -/**
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
4514 - */
4515 -void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
4516 -{
4517 - struct fsl_mc_resource *resource;
4518 -
4519 - resource = mc_adev->resource;
4520 - if (WARN_ON(resource->type == FSL_MC_POOL_DPMCP))
4521 - return;
4522 - if (WARN_ON(resource->data != mc_adev))
4523 - return;
4524 -
4525 - fsl_mc_resource_free(resource);
4526 -}
4527 -EXPORT_SYMBOL_GPL(fsl_mc_object_free);
4528 -
4529 -/*
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.
4533 - */
4534 -
4535 -/*
4536 - * Initialize the interrupt pool associated with an fsl-mc bus.
4537 - * It allocates a block of IRQs from the GIC-ITS.
4538 - */
4539 -int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
4540 - unsigned int irq_count)
4541 -{
4542 - unsigned int i;
4543 - struct msi_desc *msi_desc;
4544 - struct fsl_mc_device_irq *irq_resources;
4545 - struct fsl_mc_device_irq *mc_dev_irq;
4546 - int error;
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];
4550 -
4551 - if (WARN_ON(irq_count == 0 ||
4552 - irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS))
4553 - return -EINVAL;
4554 -
4555 - error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
4556 - if (error < 0)
4557 - return error;
4558 -
4559 - irq_resources = devm_kzalloc(&mc_bus_dev->dev,
4560 - sizeof(*irq_resources) * irq_count,
4561 - GFP_KERNEL);
4562 - if (!irq_resources) {
4563 - error = -ENOMEM;
4564 - goto cleanup_msi_irqs;
4565 - }
4566 -
4567 - for (i = 0; i < irq_count; i++) {
4568 - mc_dev_irq = &irq_resources[i];
4569 -
4570 - /*
4571 - * NOTE: This mc_dev_irq's MSI addr/value pair will be set
4572 - * by the fsl_mc_msi_write_msg() callback
4573 - */
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);
4579 - }
4580 -
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;
4585 - }
4586 -
4587 - res_pool->max_count = irq_count;
4588 - res_pool->free_count = irq_count;
4589 - mc_bus->irq_resources = irq_resources;
4590 - return 0;
4591 -
4592 -cleanup_msi_irqs:
4593 - fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
4594 - return error;
4595 -}
4596 -EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
4597 -
4598 -/**
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.
4601 - */
4602 -void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
4603 -{
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];
4607 -
4608 - if (WARN_ON(!mc_bus->irq_resources))
4609 - return;
4610 -
4611 - if (WARN_ON(res_pool->max_count == 0))
4612 - return;
4613 -
4614 - if (WARN_ON(res_pool->free_count != res_pool->max_count))
4615 - return;
4616 -
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);
4622 -}
4623 -EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
4624 -
4625 -/**
4626 - * Allocate the IRQs required by a given fsl-mc device.
4627 - */
4628 -int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
4629 -{
4630 - int i;
4631 - int irq_count;
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;
4637 -
4638 - if (WARN_ON(mc_dev->irqs))
4639 - return -EINVAL;
4640 -
4641 - irq_count = mc_dev->obj_desc.irq_count;
4642 - if (WARN_ON(irq_count == 0))
4643 - return -EINVAL;
4644 -
4645 - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
4646 - mc_bus = to_fsl_mc_bus(mc_dev);
4647 - else
4648 - mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
4649 -
4650 - if (WARN_ON(!mc_bus->irq_resources))
4651 - return -EINVAL;
4652 -
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);
4657 - return -ENOSPC;
4658 - }
4659 -
4660 - irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]),
4661 - GFP_KERNEL);
4662 - if (!irqs)
4663 - return -ENOMEM;
4664 -
4665 - for (i = 0; i < irq_count; i++) {
4666 - struct fsl_mc_resource *resource;
4667 -
4668 - error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
4669 - &resource);
4670 - if (error < 0)
4671 - goto error_resource_alloc;
4672 -
4673 - irqs[i] = to_fsl_mc_irq(resource);
4674 - res_allocated_count++;
4675 -
4676 - WARN_ON(irqs[i]->mc_dev);
4677 - irqs[i]->mc_dev = mc_dev;
4678 - irqs[i]->dev_irq_index = i;
4679 - }
4680 -
4681 - mc_dev->irqs = irqs;
4682 - return 0;
4683 -
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);
4688 - }
4689 -
4690 - return error;
4691 -}
4692 -EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
4693 -
4694 -/*
4695 - * Frees the IRQs that were allocated for an fsl-mc device.
4696 - */
4697 -void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
4698 -{
4699 - int i;
4700 - int irq_count;
4701 - struct fsl_mc_bus *mc_bus;
4702 - struct fsl_mc_device_irq **irqs = mc_dev->irqs;
4703 -
4704 - if (WARN_ON(!irqs))
4705 - return;
4706 -
4707 - irq_count = mc_dev->obj_desc.irq_count;
4708 -
4709 - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
4710 - mc_bus = to_fsl_mc_bus(mc_dev);
4711 - else
4712 - mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
4713 -
4714 - if (WARN_ON(!mc_bus->irq_resources))
4715 - return;
4716 -
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);
4721 - }
4722 -
4723 - mc_dev->irqs = NULL;
4724 -}
4725 -EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
4726 -
4727 -void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
4728 -{
4729 - int pool_type;
4730 - struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
4731 -
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];
4735 -
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);
4742 - }
4743 -}
4744 -
4745 -static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
4746 - enum fsl_mc_pool_type pool_type)
4747 -{
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;
4754 -
4755 - WARN_ON(res_pool->type != pool_type);
4756 - WARN_ON(res_pool->free_count != res_pool->max_count);
4757 -
4758 - list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
4759 - free_count++;
4760 - WARN_ON(resource->type != res_pool->type);
4761 - WARN_ON(resource->parent_pool != res_pool);
4762 - devm_kfree(&mc_bus_dev->dev, resource);
4763 - }
4764 -
4765 - WARN_ON(free_count != res_pool->free_count);
4766 -}
4767 -
4768 -void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
4769 -{
4770 - int pool_type;
4771 -
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);
4774 -}
4775 -
4776 -/**
4777 - * fsl_mc_allocator_probe - callback invoked when an allocatable device is
4778 - * being added to the system
4779 - */
4780 -static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
4781 -{
4782 - enum fsl_mc_pool_type pool_type;
4783 - struct fsl_mc_device *mc_bus_dev;
4784 - struct fsl_mc_bus *mc_bus;
4785 - int error;
4786 -
4787 - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
4788 - return -EINVAL;
4789 -
4790 - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
4791 - if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev)))
4792 - return -EINVAL;
4793 -
4794 - mc_bus = to_fsl_mc_bus(mc_bus_dev);
4795 - error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type);
4796 - if (error < 0)
4797 - return error;
4798 -
4799 - error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev);
4800 - if (error < 0)
4801 - return error;
4802 -
4803 - dev_dbg(&mc_dev->dev,
4804 - "Allocatable fsl-mc device bound to fsl_mc_allocator driver");
4805 - return 0;
4806 -}
4807 -
4808 -/**
4809 - * fsl_mc_allocator_remove - callback invoked when an allocatable device is
4810 - * being removed from the system
4811 - */
4812 -static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
4813 -{
4814 - int error;
4815 -
4816 - if (WARN_ON(!fsl_mc_is_allocatable(mc_dev->obj_desc.type)))
4817 - return -EINVAL;
4818 -
4819 - if (mc_dev->resource) {
4820 - error = fsl_mc_resource_pool_remove_device(mc_dev);
4821 - if (error < 0)
4822 - return error;
4823 - }
4824 -
4825 - dev_dbg(&mc_dev->dev,
4826 - "Allocatable fsl-mc device unbound from fsl_mc_allocator driver");
4827 - return 0;
4828 -}
4829 -
4830 -static const struct fsl_mc_device_id match_id_table[] = {
4831 - {
4832 - .vendor = FSL_MC_VENDOR_FREESCALE,
4833 - .obj_type = "dpbp",
4834 - },
4835 - {
4836 - .vendor = FSL_MC_VENDOR_FREESCALE,
4837 - .obj_type = "dpmcp",
4838 - },
4839 - {
4840 - .vendor = FSL_MC_VENDOR_FREESCALE,
4841 - .obj_type = "dpcon",
4842 - },
4843 - {.vendor = 0x0},
4844 -};
4845 -
4846 -static struct fsl_mc_driver fsl_mc_allocator_driver = {
4847 - .driver = {
4848 - .name = "fsl_mc_allocator",
4849 - .pm = NULL,
4850 - },
4851 - .match_id_table = match_id_table,
4852 - .probe = fsl_mc_allocator_probe,
4853 - .remove = fsl_mc_allocator_remove,
4854 -};
4855 -
4856 -int __init fsl_mc_allocator_driver_init(void)
4857 -{
4858 - return fsl_mc_driver_register(&fsl_mc_allocator_driver);
4859 -}
4860 -
4861 -void fsl_mc_allocator_driver_exit(void)
4862 -{
4863 - fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
4864 -}
4865 --- /dev/null
4866 +++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
4867 @@ -0,0 +1,666 @@
4868 +// SPDX-License-Identifier: GPL-2.0
4869 +/*
4870 + * fsl-mc object allocator driver
4871 + *
4872 + * Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
4873 + *
4874 + */
4875 +
4876 +#include <linux/module.h>
4877 +#include <linux/msi.h>
4878 +#include <linux/fsl/mc.h>
4879 +
4880 +#include "fsl-mc-private.h"
4881 +
4882 +static bool __must_check fsl_mc_is_allocatable(struct fsl_mc_device *mc_dev)
4883 +{
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);
4887 +}
4888 +
4889 +/**
4890 + * fsl_mc_resource_pool_add_device - add allocatable object to a resource
4891 + * pool of a given fsl-mc bus
4892 + *
4893 + * @mc_bus: pointer to the fsl-mc bus
4894 + * @pool_type: pool type
4895 + * @mc_dev: pointer to allocatable fsl-mc device
4896 + */
4897 +static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
4898 + *mc_bus,
4899 + enum fsl_mc_pool_type
4900 + pool_type,
4901 + struct fsl_mc_device
4902 + *mc_dev)
4903 +{
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;
4908 +
4909 + if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
4910 + goto out;
4911 + if (!fsl_mc_is_allocatable(mc_dev))
4912 + goto out;
4913 + if (mc_dev->resource)
4914 + goto out;
4915 +
4916 + res_pool = &mc_bus->resource_pools[pool_type];
4917 + if (res_pool->type != pool_type)
4918 + goto out;
4919 + if (res_pool->mc_bus != mc_bus)
4920 + goto out;
4921 +
4922 + mutex_lock(&res_pool->mutex);
4923 +
4924 + if (res_pool->max_count < 0)
4925 + goto out_unlock;
4926 + if (res_pool->free_count < 0 ||
4927 + res_pool->free_count > res_pool->max_count)
4928 + goto out_unlock;
4929 +
4930 + resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource),
4931 + GFP_KERNEL);
4932 + if (!resource) {
4933 + error = -ENOMEM;
4934 + dev_err(&mc_bus_dev->dev,
4935 + "Failed to allocate memory for fsl_mc_resource\n");
4936 + goto out_unlock;
4937 + }
4938 +
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++;
4948 + error = 0;
4949 +out_unlock:
4950 + mutex_unlock(&res_pool->mutex);
4951 +out:
4952 + return error;
4953 +}
4954 +
4955 +/**
4956 + * fsl_mc_resource_pool_remove_device - remove an allocatable device from a
4957 + * resource pool
4958 + *
4959 + * @mc_dev: pointer to allocatable fsl-mc device
4960 + *
4961 + * It permanently removes an allocatable fsl-mc device from the resource
4962 + * pool. It's an error if the device is in use.
4963 + */
4964 +static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
4965 + *mc_dev)
4966 +{
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;
4972 +
4973 + if (!fsl_mc_is_allocatable(mc_dev))
4974 + goto out;
4975 +
4976 + resource = mc_dev->resource;
4977 + if (!resource || resource->data != mc_dev)
4978 + goto out;
4979 +
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])
4984 + goto out;
4985 +
4986 + mutex_lock(&res_pool->mutex);
4987 +
4988 + if (res_pool->max_count <= 0)
4989 + goto out_unlock;
4990 + if (res_pool->free_count <= 0 ||
4991 + res_pool->free_count > res_pool->max_count)
4992 + goto out_unlock;
4993 +
4994 + /*
4995 + * If the device is currently allocated, its resource is not
4996 + * in the free list and thus, the device cannot be removed.
4997 + */
4998 + if (list_empty(&resource->node)) {
4999 + error = -EBUSY;
5000 + dev_err(&mc_bus_dev->dev,
5001 + "Device %s cannot be removed from resource pool\n",
5002 + dev_name(&mc_dev->dev));
5003 + goto out_unlock;
5004 + }
5005 +
5006 + list_del_init(&resource->node);
5007 + res_pool->free_count--;
5008 + res_pool->max_count--;
5009 +
5010 + devm_kfree(&mc_bus_dev->dev, resource);
5011 + mc_dev->resource = NULL;
5012 + error = 0;
5013 +out_unlock:
5014 + mutex_unlock(&res_pool->mutex);
5015 +out:
5016 + return error;
5017 +}
5018 +
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",
5024 +};
5025 +
5026 +static int __must_check object_type_to_pool_type(const char *object_type,
5027 + enum fsl_mc_pool_type
5028 + *pool_type)
5029 +{
5030 + unsigned int i;
5031 +
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) {
5034 + *pool_type = i;
5035 + return 0;
5036 + }
5037 + }
5038 +
5039 + return -EINVAL;
5040 +}
5041 +
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)
5045 +{
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;
5050 +
5051 + BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) !=
5052 + FSL_MC_NUM_POOL_TYPES);
5053 +
5054 + *new_resource = NULL;
5055 + if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
5056 + goto out;
5057 +
5058 + res_pool = &mc_bus->resource_pools[pool_type];
5059 + if (res_pool->mc_bus != mc_bus)
5060 + goto out;
5061 +
5062 + mutex_lock(&res_pool->mutex);
5063 + resource = list_first_entry_or_null(&res_pool->free_list,
5064 + struct fsl_mc_resource, node);
5065 +
5066 + if (!resource) {
5067 + error = -ENXIO;
5068 + dev_err(&mc_bus_dev->dev,
5069 + "No more resources of type %s left\n",
5070 + fsl_mc_pool_type_strings[pool_type]);
5071 + goto out_unlock;
5072 + }
5073 +
5074 + if (resource->type != pool_type)
5075 + goto out_unlock;
5076 + if (resource->parent_pool != res_pool)
5077 + goto out_unlock;
5078 + if (res_pool->free_count <= 0 ||
5079 + res_pool->free_count > res_pool->max_count)
5080 + goto out_unlock;
5081 +
5082 + list_del_init(&resource->node);
5083 +
5084 + res_pool->free_count--;
5085 + error = 0;
5086 +out_unlock:
5087 + mutex_unlock(&res_pool->mutex);
5088 + *new_resource = resource;
5089 +out:
5090 + return error;
5091 +}
5092 +EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate);
5093 +
5094 +void fsl_mc_resource_free(struct fsl_mc_resource *resource)
5095 +{
5096 + struct fsl_mc_resource_pool *res_pool;
5097 +
5098 + res_pool = resource->parent_pool;
5099 + if (resource->type != res_pool->type)
5100 + return;
5101 +
5102 + mutex_lock(&res_pool->mutex);
5103 + if (res_pool->free_count < 0 ||
5104 + res_pool->free_count >= res_pool->max_count)
5105 + goto out_unlock;
5106 +
5107 + if (!list_empty(&resource->node))
5108 + goto out_unlock;
5109 +
5110 + list_add_tail(&resource->node, &res_pool->free_list);
5111 + res_pool->free_count++;
5112 +out_unlock:
5113 + mutex_unlock(&res_pool->mutex);
5114 +}
5115 +EXPORT_SYMBOL_GPL(fsl_mc_resource_free);
5116 +
5117 +/**
5118 + * fsl_mc_object_allocate - Allocates an fsl-mc object of the given
5119 + * pool type from a given fsl-mc bus instance
5120 + *
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
5126 + *
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.
5130 + *
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
5133 + * this function.
5134 + */
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)
5138 +{
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;
5144 +
5145 + *new_mc_adev = NULL;
5146 + if (mc_dev->flags & FSL_MC_IS_DPRC)
5147 + goto error;
5148 +
5149 + if (!dev_is_fsl_mc(mc_dev->dev.parent))
5150 + goto error;
5151 +
5152 + if (pool_type == FSL_MC_POOL_DPMCP)
5153 + goto error;
5154 +
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);
5158 + if (error < 0)
5159 + goto error;
5160 +
5161 + mc_adev = resource->data;
5162 + if (!mc_adev)
5163 + goto error;
5164 +
5165 + mc_adev->consumer_link = device_link_add(&mc_dev->dev,
5166 + &mc_adev->dev,
5167 + DL_FLAG_AUTOREMOVE_CONSUMER);
5168 + if (!mc_adev->consumer_link) {
5169 + error = -EINVAL;
5170 + goto error;
5171 + }
5172 +
5173 + *new_mc_adev = mc_adev;
5174 + return 0;
5175 +error:
5176 + if (resource)
5177 + fsl_mc_resource_free(resource);
5178 +
5179 + return error;
5180 +}
5181 +EXPORT_SYMBOL_GPL(fsl_mc_object_allocate);
5182 +
5183 +/**
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
5187 + */
5188 +void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
5189 +{
5190 + struct fsl_mc_resource *resource;
5191 +
5192 + resource = mc_adev->resource;
5193 + if (resource->type == FSL_MC_POOL_DPMCP)
5194 + return;
5195 + if (resource->data != mc_adev)
5196 + return;
5197 +
5198 + fsl_mc_resource_free(resource);
5199 +
5200 + device_link_del(mc_adev->consumer_link);
5201 + mc_adev->consumer_link = NULL;
5202 +}
5203 +EXPORT_SYMBOL_GPL(fsl_mc_object_free);
5204 +
5205 +/*
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.
5209 + */
5210 +
5211 +/*
5212 + * Initialize the interrupt pool associated with an fsl-mc bus.
5213 + * It allocates a block of IRQs from the GIC-ITS.
5214 + */
5215 +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
5216 + unsigned int irq_count)
5217 +{
5218 + unsigned int i;
5219 + struct msi_desc *msi_desc;
5220 + struct fsl_mc_device_irq *irq_resources;
5221 + struct fsl_mc_device_irq *mc_dev_irq;
5222 + int error;
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];
5226 +
5227 + if (irq_count == 0 ||
5228 + irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)
5229 + return -EINVAL;
5230 +
5231 + error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
5232 + if (error < 0)
5233 + return error;
5234 +
5235 + irq_resources = devm_kzalloc(&mc_bus_dev->dev,
5236 + sizeof(*irq_resources) * irq_count,
5237 + GFP_KERNEL);
5238 + if (!irq_resources) {
5239 + error = -ENOMEM;
5240 + goto cleanup_msi_irqs;
5241 + }
5242 +
5243 + for (i = 0; i < irq_count; i++) {
5244 + mc_dev_irq = &irq_resources[i];
5245 +
5246 + /*
5247 + * NOTE: This mc_dev_irq's MSI addr/value pair will be set
5248 + * by the fsl_mc_msi_write_msg() callback
5249 + */
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);
5255 + }
5256 +
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;
5261 + }
5262 +
5263 + res_pool->max_count = irq_count;
5264 + res_pool->free_count = irq_count;
5265 + mc_bus->irq_resources = irq_resources;
5266 + return 0;
5267 +
5268 +cleanup_msi_irqs:
5269 + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
5270 + return error;
5271 +}
5272 +EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
5273 +
5274 +/**
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.
5277 + */
5278 +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
5279 +{
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];
5283 +
5284 + if (!mc_bus->irq_resources)
5285 + return;
5286 +
5287 + if (res_pool->max_count == 0)
5288 + return;
5289 +
5290 + if (res_pool->free_count != res_pool->max_count)
5291 + return;
5292 +
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);
5298 +}
5299 +EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
5300 +
5301 +/**
5302 + * Allocate the IRQs required by a given fsl-mc device.
5303 + */
5304 +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
5305 +{
5306 + int i;
5307 + int irq_count;
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;
5313 +
5314 + if (mc_dev->irqs)
5315 + return -EINVAL;
5316 +
5317 + irq_count = mc_dev->obj_desc.irq_count;
5318 + if (irq_count == 0)
5319 + return -EINVAL;
5320 +
5321 + if (is_fsl_mc_bus_dprc(mc_dev))
5322 + mc_bus = to_fsl_mc_bus(mc_dev);
5323 + else
5324 + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
5325 +
5326 + if (!mc_bus->irq_resources)
5327 + return -EINVAL;
5328 +
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);
5333 + return -ENOSPC;
5334 + }
5335 +
5336 + irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]),
5337 + GFP_KERNEL);
5338 + if (!irqs)
5339 + return -ENOMEM;
5340 +
5341 + for (i = 0; i < irq_count; i++) {
5342 + struct fsl_mc_resource *resource;
5343 +
5344 + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
5345 + &resource);
5346 + if (error < 0)
5347 + goto error_resource_alloc;
5348 +
5349 + irqs[i] = to_fsl_mc_irq(resource);
5350 + res_allocated_count++;
5351 +
5352 + irqs[i]->mc_dev = mc_dev;
5353 + irqs[i]->dev_irq_index = i;
5354 + }
5355 +
5356 + mc_dev->irqs = irqs;
5357 + return 0;
5358 +
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);
5363 + }
5364 +
5365 + return error;
5366 +}
5367 +EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
5368 +
5369 +/*
5370 + * Frees the IRQs that were allocated for an fsl-mc device.
5371 + */
5372 +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
5373 +{
5374 + int i;
5375 + int irq_count;
5376 + struct fsl_mc_bus *mc_bus;
5377 + struct fsl_mc_device_irq **irqs = mc_dev->irqs;
5378 +
5379 + if (!irqs)
5380 + return;
5381 +
5382 + irq_count = mc_dev->obj_desc.irq_count;
5383 +
5384 + if (is_fsl_mc_bus_dprc(mc_dev))
5385 + mc_bus = to_fsl_mc_bus(mc_dev);
5386 + else
5387 + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
5388 +
5389 + if (!mc_bus->irq_resources)
5390 + return;
5391 +
5392 + for (i = 0; i < irq_count; i++) {
5393 + irqs[i]->mc_dev = NULL;
5394 + fsl_mc_resource_free(&irqs[i]->resource);
5395 + }
5396 +
5397 + mc_dev->irqs = NULL;
5398 +}
5399 +EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
5400 +
5401 +void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
5402 +{
5403 + int pool_type;
5404 + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
5405 +
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];
5409 +
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);
5416 + }
5417 +}
5418 +EXPORT_SYMBOL_GPL(fsl_mc_init_all_resource_pools);
5419 +
5420 +static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
5421 + enum fsl_mc_pool_type pool_type)
5422 +{
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;
5429 +
5430 + list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
5431 + free_count++;
5432 + devm_kfree(&mc_bus_dev->dev, resource);
5433 + }
5434 +}
5435 +
5436 +void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
5437 +{
5438 + int pool_type;
5439 +
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);
5442 +}
5443 +EXPORT_SYMBOL_GPL(fsl_mc_cleanup_all_resource_pools);
5444 +
5445 +/**
5446 + * fsl_mc_allocator_probe - callback invoked when an allocatable device is
5447 + * being added to the system
5448 + */
5449 +static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
5450 +{
5451 + enum fsl_mc_pool_type pool_type;
5452 + struct fsl_mc_device *mc_bus_dev;
5453 + struct fsl_mc_bus *mc_bus;
5454 + int error;
5455 +
5456 + if (!fsl_mc_is_allocatable(mc_dev))
5457 + return -EINVAL;
5458 +
5459 + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
5460 + if (!dev_is_fsl_mc(&mc_bus_dev->dev))
5461 + return -EINVAL;
5462 +
5463 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
5464 + error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type);
5465 + if (error < 0)
5466 + return error;
5467 +
5468 + error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev);
5469 + if (error < 0)
5470 + return error;
5471 +
5472 + dev_dbg(&mc_dev->dev,
5473 + "Allocatable fsl-mc device bound to fsl_mc_allocator driver");
5474 + return 0;
5475 +}
5476 +
5477 +/**
5478 + * fsl_mc_allocator_remove - callback invoked when an allocatable device is
5479 + * being removed from the system
5480 + */
5481 +static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
5482 +{
5483 + int error;
5484 +
5485 + if (!fsl_mc_is_allocatable(mc_dev))
5486 + return -EINVAL;
5487 +
5488 + if (mc_dev->resource) {
5489 + error = fsl_mc_resource_pool_remove_device(mc_dev);
5490 + if (error < 0)
5491 + return error;
5492 + }
5493 +
5494 + dev_dbg(&mc_dev->dev,
5495 + "Allocatable fsl-mc device unbound from fsl_mc_allocator driver");
5496 + return 0;
5497 +}
5498 +
5499 +static const struct fsl_mc_device_id match_id_table[] = {
5500 + {
5501 + .vendor = FSL_MC_VENDOR_FREESCALE,
5502 + .obj_type = "dpbp",
5503 + },
5504 + {
5505 + .vendor = FSL_MC_VENDOR_FREESCALE,
5506 + .obj_type = "dpmcp",
5507 + },
5508 + {
5509 + .vendor = FSL_MC_VENDOR_FREESCALE,
5510 + .obj_type = "dpcon",
5511 + },
5512 + {.vendor = 0x0},
5513 +};
5514 +
5515 +static struct fsl_mc_driver fsl_mc_allocator_driver = {
5516 + .driver = {
5517 + .name = "fsl_mc_allocator",
5518 + .pm = NULL,
5519 + },
5520 + .match_id_table = match_id_table,
5521 + .probe = fsl_mc_allocator_probe,
5522 + .remove = fsl_mc_allocator_remove,
5523 +};
5524 +
5525 +int __init fsl_mc_allocator_driver_init(void)
5526 +{
5527 + return fsl_mc_driver_register(&fsl_mc_allocator_driver);
5528 +}
5529 +
5530 +void fsl_mc_allocator_driver_exit(void)
5531 +{
5532 + fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
5533 +}
5534 --- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c
5535 +++ /dev/null
5536 @@ -1,900 +0,0 @@
5537 -// SPDX-License-Identifier: GPL-2.0
5538 -/*
5539 - * Freescale Management Complex (MC) bus driver
5540 - *
5541 - * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
5542 - * Author: German Rivera <German.Rivera@freescale.com>
5543 - *
5544 - */
5545 -
5546 -#define pr_fmt(fmt) "fsl-mc: " fmt
5547 -
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>
5557 -
5558 -#include "fsl-mc-private.h"
5559 -#include "dprc-cmd.h"
5560 -#include "dpmng-cmd.h"
5561 -
5562 -/**
5563 - * Default DMA mask for devices on a fsl-mc bus
5564 - */
5565 -#define FSL_MC_DEFAULT_DMA_MASK (~0ULL)
5566 -
5567 -/**
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
5572 - */
5573 -struct fsl_mc {
5574 - struct fsl_mc_device *root_mc_bus_dev;
5575 - u8 num_translation_ranges;
5576 - struct fsl_mc_addr_translation_range *translation_ranges;
5577 -};
5578 -
5579 -/**
5580 - * struct fsl_mc_addr_translation_range - bus to system address translation
5581 - * range
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
5587 - */
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;
5593 -};
5594 -
5595 -/**
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
5602 - */
5603 -struct mc_version {
5604 - u32 major;
5605 - u32 minor;
5606 - u32 revision;
5607 -};
5608 -
5609 -/**
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
5613 - * structures
5614 - *
5615 - * Returns 1 on success, 0 otherwise.
5616 - */
5617 -static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
5618 -{
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;
5623 -
5624 - if (!mc_drv->match_id_table)
5625 - goto out;
5626 -
5627 - /*
5628 - * If the object is not 'plugged' don't match.
5629 - * Only exception is the root DPRC, which is a special case.
5630 - */
5631 - if ((mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED) == 0 &&
5632 - !fsl_mc_is_root_dprc(&mc_dev->dev))
5633 - goto out;
5634 -
5635 - /*
5636 - * Traverse the match_id table of the given driver, trying to find
5637 - * a matching for the given device.
5638 - */
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) {
5642 - found = true;
5643 -
5644 - break;
5645 - }
5646 - }
5647 -
5648 -out:
5649 - dev_dbg(dev, "%smatched\n", found ? "" : "not ");
5650 - return found;
5651 -}
5652 -
5653 -/**
5654 - * fsl_mc_bus_uevent - callback invoked when a device is added
5655 - */
5656 -static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
5657 -{
5658 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5659 -
5660 - if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s",
5661 - mc_dev->obj_desc.vendor,
5662 - mc_dev->obj_desc.type))
5663 - return -ENOMEM;
5664 -
5665 - return 0;
5666 -}
5667 -
5668 -static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
5669 - char *buf)
5670 -{
5671 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5672 -
5673 - return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor,
5674 - mc_dev->obj_desc.type);
5675 -}
5676 -static DEVICE_ATTR_RO(modalias);
5677 -
5678 -static struct attribute *fsl_mc_dev_attrs[] = {
5679 - &dev_attr_modalias.attr,
5680 - NULL,
5681 -};
5682 -
5683 -ATTRIBUTE_GROUPS(fsl_mc_dev);
5684 -
5685 -struct bus_type fsl_mc_bus_type = {
5686 - .name = "fsl-mc",
5687 - .match = fsl_mc_bus_match,
5688 - .uevent = fsl_mc_bus_uevent,
5689 - .dev_groups = fsl_mc_dev_groups,
5690 -};
5691 -EXPORT_SYMBOL_GPL(fsl_mc_bus_type);
5692 -
5693 -static int fsl_mc_driver_probe(struct device *dev)
5694 -{
5695 - struct fsl_mc_driver *mc_drv;
5696 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
5697 - int error;
5698 -
5699 - if (WARN_ON(!dev->driver))
5700 - return -EINVAL;
5701 -
5702 - mc_drv = to_fsl_mc_driver(dev->driver);
5703 - if (WARN_ON(!mc_drv->probe))
5704 - return -EINVAL;
5705 -
5706 - error = mc_drv->probe(mc_dev);
5707 - if (error < 0) {
5708 - dev_err(dev, "%s failed: %d\n", __func__, error);
5709 - return error;
5710 - }
5711 -
5712 - return 0;
5713 -}
5714 -
5715 -static int fsl_mc_driver_remove(struct device *dev)
5716 -{
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);
5719 - int error;
5720 -
5721 - if (WARN_ON(!dev->driver))
5722 - return -EINVAL;
5723 -
5724 - error = mc_drv->remove(mc_dev);
5725 - if (error < 0) {
5726 - dev_err(dev, "%s failed: %d\n", __func__, error);
5727 - return error;
5728 - }
5729 -
5730 - return 0;
5731 -}
5732 -
5733 -static void fsl_mc_driver_shutdown(struct device *dev)
5734 -{
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);
5737 -
5738 - mc_drv->shutdown(mc_dev);
5739 -}
5740 -
5741 -/**
5742 - * __fsl_mc_driver_register - registers a child device driver with the
5743 - * MC bus
5744 - *
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.
5748 - */
5749 -int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver,
5750 - struct module *owner)
5751 -{
5752 - int error;
5753 -
5754 - mc_driver->driver.owner = owner;
5755 - mc_driver->driver.bus = &fsl_mc_bus_type;
5756 -
5757 - if (mc_driver->probe)
5758 - mc_driver->driver.probe = fsl_mc_driver_probe;
5759 -
5760 - if (mc_driver->remove)
5761 - mc_driver->driver.remove = fsl_mc_driver_remove;
5762 -
5763 - if (mc_driver->shutdown)
5764 - mc_driver->driver.shutdown = fsl_mc_driver_shutdown;
5765 -
5766 - error = driver_register(&mc_driver->driver);
5767 - if (error < 0) {
5768 - pr_err("driver_register() failed for %s: %d\n",
5769 - mc_driver->driver.name, error);
5770 - return error;
5771 - }
5772 -
5773 - return 0;
5774 -}
5775 -EXPORT_SYMBOL_GPL(__fsl_mc_driver_register);
5776 -
5777 -/**
5778 - * fsl_mc_driver_unregister - unregisters a device driver from the
5779 - * MC bus
5780 - */
5781 -void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver)
5782 -{
5783 - driver_unregister(&mc_driver->driver);
5784 -}
5785 -EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister);
5786 -
5787 -/**
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
5793 - *
5794 - * Return: '0' on Success; Error code otherwise.
5795 - */
5796 -static int mc_get_version(struct fsl_mc_io *mc_io,
5797 - u32 cmd_flags,
5798 - struct mc_version *mc_ver_info)
5799 -{
5800 - struct mc_command cmd = { 0 };
5801 - struct dpmng_rsp_get_version *rsp_params;
5802 - int err;
5803 -
5804 - /* prepare command */
5805 - cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION,
5806 - cmd_flags,
5807 - 0);
5808 -
5809 - /* send command to mc*/
5810 - err = mc_send_command(mc_io, &cmd);
5811 - if (err)
5812 - return err;
5813 -
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);
5819 -
5820 - return 0;
5821 -}
5822 -
5823 -/**
5824 - * fsl_mc_get_root_dprc - function to traverse to the root dprc
5825 - */
5826 -static void fsl_mc_get_root_dprc(struct device *dev,
5827 - struct device **root_dprc_dev)
5828 -{
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;
5833 - } else {
5834 - *root_dprc_dev = dev;
5835 - while (dev_is_fsl_mc((*root_dprc_dev)->parent))
5836 - *root_dprc_dev = (*root_dprc_dev)->parent;
5837 - }
5838 -}
5839 -
5840 -static int get_dprc_attr(struct fsl_mc_io *mc_io,
5841 - int container_id, struct dprc_attributes *attr)
5842 -{
5843 - u16 dprc_handle;
5844 - int error;
5845 -
5846 - error = dprc_open(mc_io, 0, container_id, &dprc_handle);
5847 - if (error < 0) {
5848 - dev_err(mc_io->dev, "dprc_open() failed: %d\n", error);
5849 - return error;
5850 - }
5851 -
5852 - memset(attr, 0, sizeof(struct dprc_attributes));
5853 - error = dprc_get_attributes(mc_io, 0, dprc_handle, attr);
5854 - if (error < 0) {
5855 - dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n",
5856 - error);
5857 - goto common_cleanup;
5858 - }
5859 -
5860 - error = 0;
5861 -
5862 -common_cleanup:
5863 - (void)dprc_close(mc_io, 0, dprc_handle);
5864 - return error;
5865 -}
5866 -
5867 -static int get_dprc_icid(struct fsl_mc_io *mc_io,
5868 - int container_id, u16 *icid)
5869 -{
5870 - struct dprc_attributes attr;
5871 - int error;
5872 -
5873 - error = get_dprc_attr(mc_io, container_id, &attr);
5874 - if (error == 0)
5875 - *icid = attr.icid;
5876 -
5877 - return error;
5878 -}
5879 -
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)
5883 -{
5884 - int i;
5885 - struct device *root_dprc_dev;
5886 - struct fsl_mc *mc;
5887 -
5888 - fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev);
5889 - if (WARN_ON(!root_dprc_dev))
5890 - return -EINVAL;
5891 - mc = dev_get_drvdata(root_dprc_dev->parent);
5892 -
5893 - if (mc->num_translation_ranges == 0) {
5894 - /*
5895 - * Do identity mapping:
5896 - */
5897 - *phys_addr = mc_offset;
5898 - return 0;
5899 - }
5900 -
5901 - for (i = 0; i < mc->num_translation_ranges; i++) {
5902 - struct fsl_mc_addr_translation_range *range =
5903 - &mc->translation_ranges[i];
5904 -
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);
5910 - return 0;
5911 - }
5912 - }
5913 -
5914 - return -EFAULT;
5915 -}
5916 -
5917 -static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
5918 - struct fsl_mc_device *mc_bus_dev)
5919 -{
5920 - int i;
5921 - int error;
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;
5926 -
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;
5932 - } else {
5933 - /*
5934 - * This function should not have been called for this MC object
5935 - * type, as this object type is not supposed to have MMIO
5936 - * regions
5937 - */
5938 - WARN_ON(true);
5939 - return -EINVAL;
5940 - }
5941 -
5942 - regions = kmalloc_array(obj_desc->region_count,
5943 - sizeof(regions[0]), GFP_KERNEL);
5944 - if (!regions)
5945 - return -ENOMEM;
5946 -
5947 - for (i = 0; i < obj_desc->region_count; i++) {
5948 - struct dprc_region_desc region_desc;
5949 -
5950 - error = dprc_get_obj_region(mc_bus_dev->mc_io,
5951 - 0,
5952 - mc_bus_dev->mc_handle,
5953 - obj_desc->type,
5954 - obj_desc->id, i, &region_desc);
5955 - if (error < 0) {
5956 - dev_err(parent_dev,
5957 - "dprc_get_obj_region() failed: %d\n", error);
5958 - goto error_cleanup_regions;
5959 - }
5960 -
5961 - WARN_ON(region_desc.size == 0);
5962 - error = translate_mc_addr(mc_dev, mc_region_type,
5963 - region_desc.base_offset,
5964 - &regions[i].start);
5965 - if (error < 0) {
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;
5971 - }
5972 -
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;
5978 - }
5979 -
5980 - mc_dev->regions = regions;
5981 - return 0;
5982 -
5983 -error_cleanup_regions:
5984 - kfree(regions);
5985 - return error;
5986 -}
5987 -
5988 -/**
5989 - * fsl_mc_is_root_dprc - function to check if a given device is a root dprc
5990 - */
5991 -bool fsl_mc_is_root_dprc(struct device *dev)
5992 -{
5993 - struct device *root_dprc_dev;
5994 -
5995 - fsl_mc_get_root_dprc(dev, &root_dprc_dev);
5996 - if (!root_dprc_dev)
5997 - return false;
5998 - return dev == root_dprc_dev;
5999 -}
6000 -
6001 -static void fsl_mc_device_release(struct device *dev)
6002 -{
6003 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6004 -
6005 - kfree(mc_dev->regions);
6006 -
6007 - if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
6008 - kfree(to_fsl_mc_bus(mc_dev));
6009 - else
6010 - kfree(mc_dev);
6011 -}
6012 -
6013 -/**
6014 - * Add a newly discovered fsl-mc device to be visible in Linux
6015 - */
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)
6020 -{
6021 - int error;
6022 - struct fsl_mc_device *mc_dev = NULL;
6023 - struct fsl_mc_bus *mc_bus = NULL;
6024 - struct fsl_mc_device *parent_mc_dev;
6025 -
6026 - if (dev_is_fsl_mc(parent_dev))
6027 - parent_mc_dev = to_fsl_mc_device(parent_dev);
6028 - else
6029 - parent_mc_dev = NULL;
6030 -
6031 - if (strcmp(obj_desc->type, "dprc") == 0) {
6032 - /*
6033 - * Allocate an MC bus device object:
6034 - */
6035 - mc_bus = kzalloc(sizeof(*mc_bus), GFP_KERNEL);
6036 - if (!mc_bus)
6037 - return -ENOMEM;
6038 -
6039 - mc_dev = &mc_bus->mc_dev;
6040 - } else {
6041 - /*
6042 - * Allocate a regular fsl_mc_device object:
6043 - */
6044 - mc_dev = kzalloc(sizeof(*mc_dev), GFP_KERNEL);
6045 - if (!mc_dev)
6046 - return -ENOMEM;
6047 - }
6048 -
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);
6056 -
6057 - if (strcmp(obj_desc->type, "dprc") == 0) {
6058 - struct fsl_mc_io *mc_io2;
6059 -
6060 - mc_dev->flags |= FSL_MC_IS_DPRC;
6061 -
6062 - /*
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).
6068 - *
6069 - * NOTE: There cannot be more than one active open for a
6070 - * given MC object, using the same MC portal.
6071 - */
6072 - if (parent_mc_dev) {
6073 - /*
6074 - * device being added is a child DPRC device
6075 - */
6076 - mc_io2 = parent_mc_dev->mc_io;
6077 - } else {
6078 - /*
6079 - * device being added is the root DPRC device
6080 - */
6081 - if (WARN_ON(!mc_io)) {
6082 - error = -EINVAL;
6083 - goto error_cleanup_dev;
6084 - }
6085 -
6086 - mc_io2 = mc_io;
6087 - }
6088 -
6089 - error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid);
6090 - if (error < 0)
6091 - goto error_cleanup_dev;
6092 - } else {
6093 - /*
6094 - * A non-DPRC object has to be a child of a DPRC, use the
6095 - * parent's ICID and interrupt domain.
6096 - */
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));
6102 - }
6103 -
6104 - /*
6105 - * Get MMIO regions for the device from the MC:
6106 - *
6107 - * NOTE: the root DPRC is a special case as its MMIO region is
6108 - * obtained from the device tree
6109 - */
6110 - if (parent_mc_dev && obj_desc->region_count != 0) {
6111 - error = fsl_mc_device_get_mmio_regions(mc_dev,
6112 - parent_mc_dev);
6113 - if (error < 0)
6114 - goto error_cleanup_dev;
6115 - }
6116 -
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);
6120 -
6121 - /*
6122 - * The device-specific probe callback will get invoked by device_add()
6123 - */
6124 - error = device_add(&mc_dev->dev);
6125 - if (error < 0) {
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;
6130 - }
6131 -
6132 - dev_dbg(parent_dev, "added %s\n", dev_name(&mc_dev->dev));
6133 -
6134 - *new_mc_dev = mc_dev;
6135 - return 0;
6136 -
6137 -error_cleanup_dev:
6138 - kfree(mc_dev->regions);
6139 - kfree(mc_bus);
6140 - kfree(mc_dev);
6141 -
6142 - return error;
6143 -}
6144 -EXPORT_SYMBOL_GPL(fsl_mc_device_add);
6145 -
6146 -/**
6147 - * fsl_mc_device_remove - Remove an fsl-mc device from being visible to
6148 - * Linux
6149 - *
6150 - * @mc_dev: Pointer to an fsl-mc device
6151 - */
6152 -void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
6153 -{
6154 - /*
6155 - * The device-specific remove callback will get invoked by device_del()
6156 - */
6157 - device_del(&mc_dev->dev);
6158 - put_device(&mc_dev->dev);
6159 -}
6160 -EXPORT_SYMBOL_GPL(fsl_mc_device_remove);
6161 -
6162 -static int parse_mc_ranges(struct device *dev,
6163 - int *paddr_cells,
6164 - int *mc_addr_cells,
6165 - int *mc_size_cells,
6166 - const __be32 **ranges_start)
6167 -{
6168 - const __be32 *prop;
6169 - int range_tuple_cell_count;
6170 - int ranges_len;
6171 - int tuple_len;
6172 - struct device_node *mc_node = dev->of_node;
6173 -
6174 - *ranges_start = of_get_property(mc_node, "ranges", &ranges_len);
6175 - if (!(*ranges_start) || !ranges_len) {
6176 - dev_warn(dev,
6177 - "missing or empty ranges property for device tree node '%s'\n",
6178 - mc_node->name);
6179 - return 0;
6180 - }
6181 -
6182 - *paddr_cells = of_n_addr_cells(mc_node);
6183 -
6184 - prop = of_get_property(mc_node, "#address-cells", NULL);
6185 - if (prop)
6186 - *mc_addr_cells = be32_to_cpup(prop);
6187 - else
6188 - *mc_addr_cells = *paddr_cells;
6189 -
6190 - prop = of_get_property(mc_node, "#size-cells", NULL);
6191 - if (prop)
6192 - *mc_size_cells = be32_to_cpup(prop);
6193 - else
6194 - *mc_size_cells = of_n_size_cells(mc_node);
6195 -
6196 - range_tuple_cell_count = *paddr_cells + *mc_addr_cells +
6197 - *mc_size_cells;
6198 -
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);
6202 - return -EINVAL;
6203 - }
6204 -
6205 - return ranges_len / tuple_len;
6206 -}
6207 -
6208 -static int get_mc_addr_translation_ranges(struct device *dev,
6209 - struct fsl_mc_addr_translation_range
6210 - **ranges,
6211 - u8 *num_ranges)
6212 -{
6213 - int ret;
6214 - int paddr_cells;
6215 - int mc_addr_cells;
6216 - int mc_size_cells;
6217 - int i;
6218 - const __be32 *ranges_start;
6219 - const __be32 *cell;
6220 -
6221 - ret = parse_mc_ranges(dev,
6222 - &paddr_cells,
6223 - &mc_addr_cells,
6224 - &mc_size_cells,
6225 - &ranges_start);
6226 - if (ret < 0)
6227 - return ret;
6228 -
6229 - *num_ranges = ret;
6230 - if (!ret) {
6231 - /*
6232 - * Missing or empty ranges property ("ranges;") for the
6233 - * 'fsl,qoriq-mc' node. In this case, identity mapping
6234 - * will be used.
6235 - */
6236 - *ranges = NULL;
6237 - return 0;
6238 - }
6239 -
6240 - *ranges = devm_kcalloc(dev, *num_ranges,
6241 - sizeof(struct fsl_mc_addr_translation_range),
6242 - GFP_KERNEL);
6243 - if (!(*ranges))
6244 - return -ENOMEM;
6245 -
6246 - cell = ranges_start;
6247 - for (i = 0; i < *num_ranges; ++i) {
6248 - struct fsl_mc_addr_translation_range *range = &(*ranges)[i];
6249 -
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);
6258 -
6259 - cell += mc_size_cells;
6260 - }
6261 -
6262 - return 0;
6263 -}
6264 -
6265 -/**
6266 - * fsl_mc_bus_probe - callback invoked when the root MC bus is being
6267 - * added
6268 - */
6269 -static int fsl_mc_bus_probe(struct platform_device *pdev)
6270 -{
6271 - struct fsl_mc_obj_desc obj_desc;
6272 - int error;
6273 - struct fsl_mc *mc;
6274 - struct fsl_mc_device *mc_bus_dev = NULL;
6275 - struct fsl_mc_io *mc_io = NULL;
6276 - int container_id;
6277 - phys_addr_t mc_portal_phys_addr;
6278 - u32 mc_portal_size;
6279 - struct mc_version mc_version;
6280 - struct resource res;
6281 -
6282 - mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
6283 - if (!mc)
6284 - return -ENOMEM;
6285 -
6286 - platform_set_drvdata(pdev, mc);
6287 -
6288 - /*
6289 - * Get physical address of MC portal for the root DPRC:
6290 - */
6291 - error = of_address_to_resource(pdev->dev.of_node, 0, &res);
6292 - if (error < 0) {
6293 - dev_err(&pdev->dev,
6294 - "of_address_to_resource() failed for %pOF\n",
6295 - pdev->dev.of_node);
6296 - return error;
6297 - }
6298 -
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);
6304 - if (error < 0)
6305 - return error;
6306 -
6307 - error = mc_get_version(mc_io, 0, &mc_version);
6308 - if (error != 0) {
6309 - dev_err(&pdev->dev,
6310 - "mc_get_version() failed with error %d\n", error);
6311 - goto error_cleanup_mc_io;
6312 - }
6313 -
6314 - dev_info(&pdev->dev, "MC firmware version: %u.%u.%u\n",
6315 - mc_version.major, mc_version.minor, mc_version.revision);
6316 -
6317 - error = get_mc_addr_translation_ranges(&pdev->dev,
6318 - &mc->translation_ranges,
6319 - &mc->num_translation_ranges);
6320 - if (error < 0)
6321 - goto error_cleanup_mc_io;
6322 -
6323 - error = dprc_get_container_id(mc_io, 0, &container_id);
6324 - if (error < 0) {
6325 - dev_err(&pdev->dev,
6326 - "dprc_get_container_id() failed: %d\n", error);
6327 - goto error_cleanup_mc_io;
6328 - }
6329 -
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);
6334 - if (error < 0)
6335 - goto error_cleanup_mc_io;
6336 -
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;
6342 -
6343 - error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, &mc_bus_dev);
6344 - if (error < 0)
6345 - goto error_cleanup_mc_io;
6346 -
6347 - mc->root_mc_bus_dev = mc_bus_dev;
6348 - return 0;
6349 -
6350 -error_cleanup_mc_io:
6351 - fsl_destroy_mc_io(mc_io);
6352 - return error;
6353 -}
6354 -
6355 -/**
6356 - * fsl_mc_bus_remove - callback invoked when the root MC bus is being
6357 - * removed
6358 - */
6359 -static int fsl_mc_bus_remove(struct platform_device *pdev)
6360 -{
6361 - struct fsl_mc *mc = platform_get_drvdata(pdev);
6362 -
6363 - if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev)))
6364 - return -EINVAL;
6365 -
6366 - fsl_mc_device_remove(mc->root_mc_bus_dev);
6367 -
6368 - fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io);
6369 - mc->root_mc_bus_dev->mc_io = NULL;
6370 -
6371 - return 0;
6372 -}
6373 -
6374 -static const struct of_device_id fsl_mc_bus_match_table[] = {
6375 - {.compatible = "fsl,qoriq-mc",},
6376 - {},
6377 -};
6378 -
6379 -MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table);
6380 -
6381 -static struct platform_driver fsl_mc_bus_driver = {
6382 - .driver = {
6383 - .name = "fsl_mc_bus",
6384 - .pm = NULL,
6385 - .of_match_table = fsl_mc_bus_match_table,
6386 - },
6387 - .probe = fsl_mc_bus_probe,
6388 - .remove = fsl_mc_bus_remove,
6389 -};
6390 -
6391 -static int __init fsl_mc_bus_driver_init(void)
6392 -{
6393 - int error;
6394 -
6395 - error = bus_register(&fsl_mc_bus_type);
6396 - if (error < 0) {
6397 - pr_err("bus type registration failed: %d\n", error);
6398 - goto error_cleanup_cache;
6399 - }
6400 -
6401 - error = platform_driver_register(&fsl_mc_bus_driver);
6402 - if (error < 0) {
6403 - pr_err("platform_driver_register() failed: %d\n", error);
6404 - goto error_cleanup_bus;
6405 - }
6406 -
6407 - error = dprc_driver_init();
6408 - if (error < 0)
6409 - goto error_cleanup_driver;
6410 -
6411 - error = fsl_mc_allocator_driver_init();
6412 - if (error < 0)
6413 - goto error_cleanup_dprc_driver;
6414 -
6415 - error = its_fsl_mc_msi_init();
6416 - if (error < 0)
6417 - goto error_cleanup_mc_allocator;
6418 -
6419 - return 0;
6420 -
6421 -error_cleanup_mc_allocator:
6422 - fsl_mc_allocator_driver_exit();
6423 -
6424 -error_cleanup_dprc_driver:
6425 - dprc_driver_exit();
6426 -
6427 -error_cleanup_driver:
6428 - platform_driver_unregister(&fsl_mc_bus_driver);
6429 -
6430 -error_cleanup_bus:
6431 - bus_unregister(&fsl_mc_bus_type);
6432 -
6433 -error_cleanup_cache:
6434 - return error;
6435 -}
6436 -postcore_initcall(fsl_mc_bus_driver_init);
6437 --- /dev/null
6438 +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
6439 @@ -0,0 +1,1148 @@
6440 +// SPDX-License-Identifier: GPL-2.0
6441 +/*
6442 + * Freescale Management Complex (MC) bus driver
6443 + *
6444 + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
6445 + * Author: German Rivera <German.Rivera@freescale.com>
6446 + *
6447 + */
6448 +
6449 +#define pr_fmt(fmt) "fsl-mc: " fmt
6450 +
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>
6460 +
6461 +#include "fsl-mc-private.h"
6462 +
6463 +/**
6464 + * Default DMA mask for devices on a fsl-mc bus
6465 + */
6466 +#define FSL_MC_DEFAULT_DMA_MASK (~0ULL)
6467 +
6468 +/**
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
6473 + */
6474 +struct fsl_mc {
6475 + struct fsl_mc_device *root_mc_bus_dev;
6476 + u8 num_translation_ranges;
6477 + struct fsl_mc_addr_translation_range *translation_ranges;
6478 +};
6479 +
6480 +/**
6481 + * struct fsl_mc_addr_translation_range - bus to system address translation
6482 + * range
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
6488 + */
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;
6494 +};
6495 +
6496 +/**
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
6503 + */
6504 +struct mc_version {
6505 + u32 major;
6506 + u32 minor;
6507 + u32 revision;
6508 +};
6509 +
6510 +/**
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
6514 + * structures
6515 + *
6516 + * Returns 1 on success, 0 otherwise.
6517 + */
6518 +static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
6519 +{
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;
6524 +
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);
6528 + goto out;
6529 + }
6530 +
6531 + if (!mc_drv->match_id_table)
6532 + goto out;
6533 +
6534 + /*
6535 + * If the object is not 'plugged' don't match.
6536 + * Only exception is the root DPRC, which is a special case.
6537 + */
6538 + if ((mc_dev->obj_desc.state & FSL_MC_OBJ_STATE_PLUGGED) == 0 &&
6539 + !fsl_mc_is_root_dprc(&mc_dev->dev))
6540 + goto out;
6541 +
6542 + /*
6543 + * Traverse the match_id table of the given driver, trying to find
6544 + * a matching for the given device.
6545 + */
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) {
6549 + found = true;
6550 +
6551 + break;
6552 + }
6553 + }
6554 +
6555 +out:
6556 + dev_dbg(dev, "%smatched\n", found ? "" : "not ");
6557 + return found;
6558 +}
6559 +
6560 +/**
6561 + * fsl_mc_bus_uevent - callback invoked when a device is added
6562 + */
6563 +static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
6564 +{
6565 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6566 +
6567 + if (add_uevent_var(env, "MODALIAS=fsl-mc:v%08Xd%s",
6568 + mc_dev->obj_desc.vendor,
6569 + mc_dev->obj_desc.type))
6570 + return -ENOMEM;
6571 +
6572 + return 0;
6573 +}
6574 +
6575 +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
6576 + char *buf)
6577 +{
6578 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6579 +
6580 + return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor,
6581 + mc_dev->obj_desc.type);
6582 +}
6583 +static DEVICE_ATTR_RO(modalias);
6584 +
6585 +static ssize_t rescan_store(struct device *dev,
6586 + struct device_attribute *attr,
6587 + const char *buf, size_t count)
6588 +{
6589 + struct fsl_mc_device *root_mc_dev;
6590 + struct fsl_mc_bus *root_mc_bus;
6591 + unsigned long val;
6592 +
6593 + if (!fsl_mc_is_root_dprc(dev))
6594 + return -EINVAL;
6595 +
6596 + root_mc_dev = to_fsl_mc_device(dev);
6597 + root_mc_bus = to_fsl_mc_bus(root_mc_dev);
6598 +
6599 + if (kstrtoul(buf, 0, &val) < 0)
6600 + return -EINVAL;
6601 +
6602 + if (val) {
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);
6606 + }
6607 +
6608 + return count;
6609 +}
6610 +static DEVICE_ATTR_WO(rescan);
6611 +
6612 +static ssize_t driver_override_store(struct device *dev,
6613 + struct device_attribute *attr,
6614 + const char *buf, size_t count)
6615 +{
6616 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6617 + const char *driver_override, *old = mc_dev->driver_override;
6618 + char *cp;
6619 +
6620 + if (WARN_ON(dev->bus != &fsl_mc_bus_type))
6621 + return -EINVAL;
6622 +
6623 + if (count >= (PAGE_SIZE - 1))
6624 + return -EINVAL;
6625 +
6626 + driver_override = kstrndup(buf, count, GFP_KERNEL);
6627 + if (!driver_override)
6628 + return -ENOMEM;
6629 +
6630 + cp = strchr(driver_override, '\n');
6631 + if (cp)
6632 + *cp = '\0';
6633 +
6634 + if (strlen(driver_override)) {
6635 + mc_dev->driver_override = driver_override;
6636 + } else {
6637 + kfree(driver_override);
6638 + mc_dev->driver_override = NULL;
6639 + }
6640 +
6641 + kfree(old);
6642 +
6643 + return count;
6644 +}
6645 +
6646 +static ssize_t driver_override_show(struct device *dev,
6647 + struct device_attribute *attr, char *buf)
6648 +{
6649 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6650 +
6651 + return snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override);
6652 +}
6653 +static DEVICE_ATTR_RW(driver_override);
6654 +
6655 +static struct attribute *fsl_mc_dev_attrs[] = {
6656 + &dev_attr_modalias.attr,
6657 + &dev_attr_rescan.attr,
6658 + &dev_attr_driver_override.attr,
6659 + NULL,
6660 +};
6661 +
6662 +ATTRIBUTE_GROUPS(fsl_mc_dev);
6663 +
6664 +static int scan_fsl_mc_bus(struct device *dev, void *data)
6665 +{
6666 + struct fsl_mc_device *root_mc_dev;
6667 + struct fsl_mc_bus *root_mc_bus;
6668 +
6669 + if (!fsl_mc_is_root_dprc(dev))
6670 + goto exit;
6671 +
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);
6677 +
6678 +exit:
6679 + return 0;
6680 +}
6681 +
6682 +static ssize_t bus_rescan_store(struct bus_type *bus,
6683 + const char *buf, size_t count)
6684 +{
6685 + unsigned long val;
6686 +
6687 + if (kstrtoul(buf, 0, &val) < 0)
6688 + return -EINVAL;
6689 +
6690 + if (val)
6691 + bus_for_each_dev(bus, NULL, NULL, scan_fsl_mc_bus);
6692 +
6693 + return count;
6694 +}
6695 +static BUS_ATTR(rescan, 0220, NULL, bus_rescan_store);
6696 +
6697 +static struct attribute *fsl_mc_bus_attrs[] = {
6698 + &bus_attr_rescan.attr,
6699 + NULL,
6700 +};
6701 +
6702 +static const struct attribute_group fsl_mc_bus_group = {
6703 + .attrs = fsl_mc_bus_attrs,
6704 +};
6705 +
6706 +static const struct attribute_group *fsl_mc_bus_groups[] = {
6707 + &fsl_mc_bus_group,
6708 + NULL,
6709 +};
6710 +
6711 +struct bus_type fsl_mc_bus_type = {
6712 + .name = "fsl-mc",
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,
6717 +};
6718 +EXPORT_SYMBOL_GPL(fsl_mc_bus_type);
6719 +
6720 +struct device_type fsl_mc_bus_dprc_type = {
6721 + .name = "fsl_mc_bus_dprc"
6722 +};
6723 +
6724 +struct device_type fsl_mc_bus_dpni_type = {
6725 + .name = "fsl_mc_bus_dpni"
6726 +};
6727 +
6728 +struct device_type fsl_mc_bus_dpio_type = {
6729 + .name = "fsl_mc_bus_dpio"
6730 +};
6731 +
6732 +struct device_type fsl_mc_bus_dpsw_type = {
6733 + .name = "fsl_mc_bus_dpsw"
6734 +};
6735 +
6736 +struct device_type fsl_mc_bus_dpdmux_type = {
6737 + .name = "fsl_mc_bus_dpdmux"
6738 +};
6739 +
6740 +struct device_type fsl_mc_bus_dpbp_type = {
6741 + .name = "fsl_mc_bus_dpbp"
6742 +};
6743 +
6744 +struct device_type fsl_mc_bus_dpcon_type = {
6745 + .name = "fsl_mc_bus_dpcon"
6746 +};
6747 +
6748 +struct device_type fsl_mc_bus_dpmcp_type = {
6749 + .name = "fsl_mc_bus_dpmcp"
6750 +};
6751 +
6752 +struct device_type fsl_mc_bus_dpmac_type = {
6753 + .name = "fsl_mc_bus_dpmac"
6754 +};
6755 +
6756 +struct device_type fsl_mc_bus_dprtc_type = {
6757 + .name = "fsl_mc_bus_dprtc"
6758 +};
6759 +
6760 +struct device_type fsl_mc_bus_dpseci_type = {
6761 + .name = "fsl_mc_bus_dpseci"
6762 +};
6763 +
6764 +struct device_type fsl_mc_bus_dpdcei_type = {
6765 + .name = "fsl_mc_bus_dpdcei"
6766 +};
6767 +
6768 +struct device_type fsl_mc_bus_dpaiop_type = {
6769 + .name = "fsl_mc_bus_dpaiop"
6770 +};
6771 +
6772 +struct device_type fsl_mc_bus_dpci_type = {
6773 + .name = "fsl_mc_bus_dpci"
6774 +};
6775 +
6776 +struct device_type fsl_mc_bus_dpdmai_type = {
6777 + .name = "fsl_mc_bus_dpdmai"
6778 +};
6779 +
6780 +static struct device_type *fsl_mc_get_device_type(const char *type)
6781 +{
6782 + static const struct {
6783 + struct device_type *dev_type;
6784 + const char *type;
6785 + } dev_types[] = {
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" },
6801 + { NULL, NULL }
6802 + };
6803 + int i;
6804 +
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;
6808 +
6809 + return NULL;
6810 +}
6811 +
6812 +static int fsl_mc_driver_probe(struct device *dev)
6813 +{
6814 + struct fsl_mc_driver *mc_drv;
6815 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
6816 + int error;
6817 +
6818 + mc_drv = to_fsl_mc_driver(dev->driver);
6819 +
6820 + error = mc_drv->probe(mc_dev);
6821 + if (error < 0) {
6822 + if (error != -EPROBE_DEFER)
6823 + dev_err(dev, "%s failed: %d\n", __func__, error);
6824 + return error;
6825 + }
6826 +
6827 + return 0;
6828 +}
6829 +
6830 +static int fsl_mc_driver_remove(struct device *dev)
6831 +{
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);
6834 + int error;
6835 +
6836 + error = mc_drv->remove(mc_dev);
6837 + if (error < 0) {
6838 + dev_err(dev, "%s failed: %d\n", __func__, error);
6839 + return error;
6840 + }
6841 +
6842 + return 0;
6843 +}
6844 +
6845 +static void fsl_mc_driver_shutdown(struct device *dev)
6846 +{
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);
6849 +
6850 + mc_drv->shutdown(mc_dev);
6851 +}
6852 +
6853 +/**
6854 + * __fsl_mc_driver_register - registers a child device driver with the
6855 + * MC bus
6856 + *
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.
6860 + */
6861 +int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver,
6862 + struct module *owner)
6863 +{
6864 + int error;
6865 +
6866 + mc_driver->driver.owner = owner;
6867 + mc_driver->driver.bus = &fsl_mc_bus_type;
6868 +
6869 + if (mc_driver->probe)
6870 + mc_driver->driver.probe = fsl_mc_driver_probe;
6871 +
6872 + if (mc_driver->remove)
6873 + mc_driver->driver.remove = fsl_mc_driver_remove;
6874 +
6875 + if (mc_driver->shutdown)
6876 + mc_driver->driver.shutdown = fsl_mc_driver_shutdown;
6877 +
6878 + error = driver_register(&mc_driver->driver);
6879 + if (error < 0) {
6880 + pr_err("driver_register() failed for %s: %d\n",
6881 + mc_driver->driver.name, error);
6882 + return error;
6883 + }
6884 +
6885 + return 0;
6886 +}
6887 +EXPORT_SYMBOL_GPL(__fsl_mc_driver_register);
6888 +
6889 +/**
6890 + * fsl_mc_driver_unregister - unregisters a device driver from the
6891 + * MC bus
6892 + */
6893 +void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver)
6894 +{
6895 + driver_unregister(&mc_driver->driver);
6896 +}
6897 +EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister);
6898 +
6899 +/**
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
6905 + *
6906 + * Return: '0' on Success; Error code otherwise.
6907 + */
6908 +static int mc_get_version(struct fsl_mc_io *mc_io,
6909 + u32 cmd_flags,
6910 + struct mc_version *mc_ver_info)
6911 +{
6912 + struct fsl_mc_command cmd = { 0 };
6913 + struct dpmng_rsp_get_version *rsp_params;
6914 + int err;
6915 +
6916 + /* prepare command */
6917 + cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION,
6918 + cmd_flags,
6919 + 0);
6920 +
6921 + /* send command to mc*/
6922 + err = mc_send_command(mc_io, &cmd);
6923 + if (err)
6924 + return err;
6925 +
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);
6931 +
6932 + return 0;
6933 +}
6934 +
6935 +/**
6936 + * fsl_mc_get_root_dprc - function to traverse to the root dprc
6937 + */
6938 +void fsl_mc_get_root_dprc(struct device *dev,
6939 + struct device **root_dprc_dev)
6940 +{
6941 + if (!dev) {
6942 + *root_dprc_dev = NULL;
6943 + } else if (!dev_is_fsl_mc(dev)) {
6944 + *root_dprc_dev = NULL;
6945 + } else {
6946 + *root_dprc_dev = dev;
6947 + while (dev_is_fsl_mc((*root_dprc_dev)->parent))
6948 + *root_dprc_dev = (*root_dprc_dev)->parent;
6949 + }
6950 +}
6951 +EXPORT_SYMBOL_GPL(fsl_mc_get_root_dprc);
6952 +
6953 +static int get_dprc_attr(struct fsl_mc_io *mc_io,
6954 + int container_id, struct dprc_attributes *attr)
6955 +{
6956 + u16 dprc_handle;
6957 + int error;
6958 +
6959 + error = dprc_open(mc_io, 0, container_id, &dprc_handle);
6960 + if (error < 0) {
6961 + dev_err(mc_io->dev, "dprc_open() failed: %d\n", error);
6962 + return error;
6963 + }
6964 +
6965 + memset(attr, 0, sizeof(struct dprc_attributes));
6966 + error = dprc_get_attributes(mc_io, 0, dprc_handle, attr);
6967 + if (error < 0) {
6968 + dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n",
6969 + error);
6970 + goto common_cleanup;
6971 + }
6972 +
6973 + error = 0;
6974 +
6975 +common_cleanup:
6976 + (void)dprc_close(mc_io, 0, dprc_handle);
6977 + return error;
6978 +}
6979 +
6980 +static int get_dprc_icid(struct fsl_mc_io *mc_io,
6981 + int container_id, u32 *icid)
6982 +{
6983 + struct dprc_attributes attr;
6984 + int error;
6985 +
6986 + error = get_dprc_attr(mc_io, container_id, &attr);
6987 + if (error == 0)
6988 + *icid = attr.icid;
6989 +
6990 + return error;
6991 +}
6992 +
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)
6996 +{
6997 + int i;
6998 + struct device *root_dprc_dev;
6999 + struct fsl_mc *mc;
7000 +
7001 + fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev);
7002 + mc = dev_get_drvdata(root_dprc_dev->parent);
7003 +
7004 + if (mc->num_translation_ranges == 0) {
7005 + /*
7006 + * Do identity mapping:
7007 + */
7008 + *phys_addr = mc_offset;
7009 + return 0;
7010 + }
7011 +
7012 + for (i = 0; i < mc->num_translation_ranges; i++) {
7013 + struct fsl_mc_addr_translation_range *range =
7014 + &mc->translation_ranges[i];
7015 +
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);
7021 + return 0;
7022 + }
7023 + }
7024 +
7025 + return -EFAULT;
7026 +}
7027 +
7028 +static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
7029 + struct fsl_mc_device *mc_bus_dev)
7030 +{
7031 + int i;
7032 + int error;
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;
7037 +
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;
7043 + } else {
7044 + /*
7045 + * This function should not have been called for this MC object
7046 + * type, as this object type is not supposed to have MMIO
7047 + * regions
7048 + */
7049 + return -EINVAL;
7050 + }
7051 +
7052 + regions = kmalloc_array(obj_desc->region_count,
7053 + sizeof(regions[0]), GFP_KERNEL);
7054 + if (!regions)
7055 + return -ENOMEM;
7056 +
7057 + for (i = 0; i < obj_desc->region_count; i++) {
7058 + struct dprc_region_desc region_desc;
7059 +
7060 + error = dprc_get_obj_region(mc_bus_dev->mc_io,
7061 + 0,
7062 + mc_bus_dev->mc_handle,
7063 + obj_desc->type,
7064 + obj_desc->id, i, &region_desc);
7065 + if (error < 0) {
7066 + dev_err(parent_dev,
7067 + "dprc_get_obj_region() failed: %d\n", error);
7068 + goto error_cleanup_regions;
7069 + }
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
7073 + */
7074 + if (region_desc.base_address)
7075 + regions[i].start = region_desc.base_address +
7076 + region_desc.base_offset;
7077 + else
7078 + error = translate_mc_addr(mc_dev, mc_region_type,
7079 + region_desc.base_offset,
7080 + &regions[i].start);
7081 + if (error < 0) {
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;
7087 + }
7088 +
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;
7096 + }
7097 +
7098 + mc_dev->regions = regions;
7099 + return 0;
7100 +
7101 +error_cleanup_regions:
7102 + kfree(regions);
7103 + return error;
7104 +}
7105 +
7106 +/**
7107 + * fsl_mc_is_root_dprc - function to check if a given device is a root dprc
7108 + */
7109 +bool fsl_mc_is_root_dprc(struct device *dev)
7110 +{
7111 + struct device *root_dprc_dev;
7112 +
7113 + fsl_mc_get_root_dprc(dev, &root_dprc_dev);
7114 + if (!root_dprc_dev)
7115 + return false;
7116 + return dev == root_dprc_dev;
7117 +}
7118 +
7119 +static void fsl_mc_device_release(struct device *dev)
7120 +{
7121 + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
7122 +
7123 + kfree(mc_dev->regions);
7124 +
7125 + if (is_fsl_mc_bus_dprc(mc_dev))
7126 + kfree(to_fsl_mc_bus(mc_dev));
7127 + else
7128 + kfree(mc_dev);
7129 +}
7130 +
7131 +/**
7132 + * Add a newly discovered fsl-mc device to be visible in Linux
7133 + */
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)
7139 +{
7140 + int error;
7141 + struct fsl_mc_device *mc_dev = NULL;
7142 + struct fsl_mc_bus *mc_bus = NULL;
7143 + struct fsl_mc_device *parent_mc_dev;
7144 +
7145 + if (dev_is_fsl_mc(parent_dev))
7146 + parent_mc_dev = to_fsl_mc_device(parent_dev);
7147 + else
7148 + parent_mc_dev = NULL;
7149 +
7150 + if (strcmp(obj_desc->type, "dprc") == 0) {
7151 + /*
7152 + * Allocate an MC bus device object:
7153 + */
7154 + mc_bus = kzalloc(sizeof(*mc_bus), GFP_KERNEL);
7155 + if (!mc_bus)
7156 + return -ENOMEM;
7157 +
7158 + mc_dev = &mc_bus->mc_dev;
7159 + } else {
7160 + /*
7161 + * Allocate a regular fsl_mc_device object:
7162 + */
7163 + mc_dev = kzalloc(sizeof(*mc_dev), GFP_KERNEL);
7164 + if (!mc_dev)
7165 + return -ENOMEM;
7166 + }
7167 +
7168 + mc_dev->obj_desc = *obj_desc;
7169 + mc_dev->mc_io = mc_io;
7170 +
7171 + if (driver_override) {
7172 + /*
7173 + * We trust driver_override, so we don't need to use
7174 + * kstrndup() here
7175 + */
7176 + mc_dev->driver_override = kstrdup(driver_override, GFP_KERNEL);
7177 + if (!mc_dev->driver_override) {
7178 + error = -ENOMEM;
7179 + goto error_cleanup_dev;
7180 + }
7181 + }
7182 +
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) {
7189 + error = -ENODEV;
7190 + dev_err(parent_dev, "unknown device type %s\n", obj_desc->type);
7191 + goto error_cleanup_dev;
7192 + }
7193 + dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id);
7194 +
7195 + if (strcmp(obj_desc->type, "dprc") == 0) {
7196 + struct fsl_mc_io *mc_io2;
7197 +
7198 + mc_dev->flags |= FSL_MC_IS_DPRC;
7199 +
7200 + /*
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).
7206 + *
7207 + * NOTE: There cannot be more than one active open for a
7208 + * given MC object, using the same MC portal.
7209 + */
7210 + if (parent_mc_dev) {
7211 + /*
7212 + * device being added is a child DPRC device
7213 + */
7214 + mc_io2 = parent_mc_dev->mc_io;
7215 + } else {
7216 + /*
7217 + * device being added is the root DPRC device
7218 + */
7219 + if (!mc_io) {
7220 + error = -EINVAL;
7221 + goto error_cleanup_dev;
7222 + }
7223 +
7224 + mc_io2 = mc_io;
7225 + }
7226 +
7227 + error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid);
7228 + if (error < 0)
7229 + goto error_cleanup_dev;
7230 + } else {
7231 + /*
7232 + * A non-DPRC object has to be a child of a DPRC, use the
7233 + * parent's ICID and interrupt domain.
7234 + */
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));
7241 + }
7242 +
7243 + /*
7244 + * Get MMIO regions for the device from the MC:
7245 + *
7246 + * NOTE: the root DPRC is a special case as its MMIO region is
7247 + * obtained from the device tree
7248 + */
7249 + if (parent_mc_dev && obj_desc->region_count != 0) {
7250 + error = fsl_mc_device_get_mmio_regions(mc_dev,
7251 + parent_mc_dev);
7252 + if (error < 0)
7253 + goto error_cleanup_dev;
7254 + }
7255 +
7256 + /*
7257 + * The device-specific probe callback will get invoked by device_add()
7258 + */
7259 + error = device_add(&mc_dev->dev);
7260 + if (error < 0) {
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;
7265 + }
7266 +
7267 + dev_dbg(parent_dev, "added %s\n", dev_name(&mc_dev->dev));
7268 +
7269 + *new_mc_dev = mc_dev;
7270 + return 0;
7271 +
7272 +error_cleanup_dev:
7273 + kfree(mc_dev->regions);
7274 + kfree(mc_bus);
7275 + kfree(mc_dev);
7276 +
7277 + return error;
7278 +}
7279 +EXPORT_SYMBOL_GPL(fsl_mc_device_add);
7280 +
7281 +/**
7282 + * fsl_mc_device_remove - Remove an fsl-mc device from being visible to
7283 + * Linux
7284 + *
7285 + * @mc_dev: Pointer to an fsl-mc device
7286 + */
7287 +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
7288 +{
7289 + kfree(mc_dev->driver_override);
7290 + mc_dev->driver_override = NULL;
7291 +
7292 + /*
7293 + * The device-specific remove callback will get invoked by device_del()
7294 + */
7295 + device_del(&mc_dev->dev);
7296 + put_device(&mc_dev->dev);
7297 +}
7298 +EXPORT_SYMBOL_GPL(fsl_mc_device_remove);
7299 +
7300 +static int parse_mc_ranges(struct device *dev,
7301 + int *paddr_cells,
7302 + int *mc_addr_cells,
7303 + int *mc_size_cells,
7304 + const __be32 **ranges_start)
7305 +{
7306 + const __be32 *prop;
7307 + int range_tuple_cell_count;
7308 + int ranges_len;
7309 + int tuple_len;
7310 + struct device_node *mc_node = dev->of_node;
7311 +
7312 + *ranges_start = of_get_property(mc_node, "ranges", &ranges_len);
7313 + if (!(*ranges_start) || !ranges_len) {
7314 + dev_warn(dev,
7315 + "missing or empty ranges property for device tree node '%s'\n",
7316 + mc_node->name);
7317 + return 0;
7318 + }
7319 +
7320 + *paddr_cells = of_n_addr_cells(mc_node);
7321 +
7322 + prop = of_get_property(mc_node, "#address-cells", NULL);
7323 + if (prop)
7324 + *mc_addr_cells = be32_to_cpup(prop);
7325 + else
7326 + *mc_addr_cells = *paddr_cells;
7327 +
7328 + prop = of_get_property(mc_node, "#size-cells", NULL);
7329 + if (prop)
7330 + *mc_size_cells = be32_to_cpup(prop);
7331 + else
7332 + *mc_size_cells = of_n_size_cells(mc_node);
7333 +
7334 + range_tuple_cell_count = *paddr_cells + *mc_addr_cells +
7335 + *mc_size_cells;
7336 +
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);
7340 + return -EINVAL;
7341 + }
7342 +
7343 + return ranges_len / tuple_len;
7344 +}
7345 +
7346 +static int get_mc_addr_translation_ranges(struct device *dev,
7347 + struct fsl_mc_addr_translation_range
7348 + **ranges,
7349 + u8 *num_ranges)
7350 +{
7351 + int ret;
7352 + int paddr_cells;
7353 + int mc_addr_cells;
7354 + int mc_size_cells;
7355 + int i;
7356 + const __be32 *ranges_start;
7357 + const __be32 *cell;
7358 +
7359 + ret = parse_mc_ranges(dev,
7360 + &paddr_cells,
7361 + &mc_addr_cells,
7362 + &mc_size_cells,
7363 + &ranges_start);
7364 + if (ret < 0)
7365 + return ret;
7366 +
7367 + *num_ranges = ret;
7368 + if (!ret) {
7369 + /*
7370 + * Missing or empty ranges property ("ranges;") for the
7371 + * 'fsl,qoriq-mc' node. In this case, identity mapping
7372 + * will be used.
7373 + */
7374 + *ranges = NULL;
7375 + return 0;
7376 + }
7377 +
7378 + *ranges = devm_kcalloc(dev, *num_ranges,
7379 + sizeof(struct fsl_mc_addr_translation_range),
7380 + GFP_KERNEL);
7381 + if (!(*ranges))
7382 + return -ENOMEM;
7383 +
7384 + cell = ranges_start;
7385 + for (i = 0; i < *num_ranges; ++i) {
7386 + struct fsl_mc_addr_translation_range *range = &(*ranges)[i];
7387 +
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);
7396 +
7397 + cell += mc_size_cells;
7398 + }
7399 +
7400 + return 0;
7401 +}
7402 +
7403 +/**
7404 + * fsl_mc_bus_probe - callback invoked when the root MC bus is being
7405 + * added
7406 + */
7407 +static int fsl_mc_bus_probe(struct platform_device *pdev)
7408 +{
7409 + struct fsl_mc_obj_desc obj_desc;
7410 + int error;
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;
7415 + int container_id;
7416 + phys_addr_t mc_portal_phys_addr;
7417 + u32 mc_portal_size;
7418 + struct mc_version mc_version;
7419 + struct resource res;
7420 +
7421 + mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
7422 + if (!mc)
7423 + return -ENOMEM;
7424 +
7425 + platform_set_drvdata(pdev, mc);
7426 +
7427 + /*
7428 + * Get physical address of MC portal for the root DPRC:
7429 + */
7430 + error = of_address_to_resource(pdev->dev.of_node, 0, &res);
7431 + if (error < 0) {
7432 + dev_err(&pdev->dev,
7433 + "of_address_to_resource() failed for %pOF\n",
7434 + pdev->dev.of_node);
7435 + return error;
7436 + }
7437 +
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);
7443 + if (error < 0)
7444 + return error;
7445 +
7446 + error = mc_get_version(mc_io, 0, &mc_version);
7447 + if (error != 0) {
7448 + dev_err(&pdev->dev,
7449 + "mc_get_version() failed with error %d\n", error);
7450 + goto error_cleanup_mc_io;
7451 + }
7452 +
7453 + dev_info(&pdev->dev, "MC firmware version: %u.%u.%u\n",
7454 + mc_version.major, mc_version.minor, mc_version.revision);
7455 +
7456 + error = get_mc_addr_translation_ranges(&pdev->dev,
7457 + &mc->translation_ranges,
7458 + &mc->num_translation_ranges);
7459 + if (error < 0)
7460 + goto error_cleanup_mc_io;
7461 +
7462 + error = dprc_get_container_id(mc_io, 0, &container_id);
7463 + if (error < 0) {
7464 + dev_err(&pdev->dev,
7465 + "dprc_get_container_id() failed: %d\n", error);
7466 + goto error_cleanup_mc_io;
7467 + }
7468 +
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);
7473 + if (error < 0)
7474 + goto error_cleanup_mc_io;
7475 +
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;
7481 +
7482 + error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, NULL,
7483 + &mc_bus_dev);
7484 + if (error < 0)
7485 + goto error_cleanup_mc_io;
7486 +
7487 + mc_bus = to_fsl_mc_bus(mc_bus_dev);
7488 + error = fsl_mc_restool_create_device_file(mc_bus);
7489 + if (error < 0)
7490 + goto error_cleanup_device;
7491 +
7492 + mc->root_mc_bus_dev = mc_bus_dev;
7493 +
7494 + return 0;
7495 +
7496 +error_cleanup_device:
7497 + fsl_mc_device_remove(mc_bus_dev);
7498 +
7499 +error_cleanup_mc_io:
7500 + fsl_destroy_mc_io(mc_io);
7501 + return error;
7502 +}
7503 +
7504 +/**
7505 + * fsl_mc_bus_remove - callback invoked when the root MC bus is being
7506 + * removed
7507 + */
7508 +static int fsl_mc_bus_remove(struct platform_device *pdev)
7509 +{
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);
7512 +
7513 + if (!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))
7514 + return -EINVAL;
7515 +
7516 + fsl_mc_restool_remove_device_file(mc_bus);
7517 + fsl_mc_device_remove(mc->root_mc_bus_dev);
7518 +
7519 + fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io);
7520 + mc->root_mc_bus_dev->mc_io = NULL;
7521 +
7522 + return 0;
7523 +}
7524 +
7525 +static const struct of_device_id fsl_mc_bus_match_table[] = {
7526 + {.compatible = "fsl,qoriq-mc",},
7527 + {},
7528 +};
7529 +
7530 +MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table);
7531 +
7532 +static struct platform_driver fsl_mc_bus_driver = {
7533 + .driver = {
7534 + .name = "fsl_mc_bus",
7535 + .pm = NULL,
7536 + .of_match_table = fsl_mc_bus_match_table,
7537 + },
7538 + .probe = fsl_mc_bus_probe,
7539 + .remove = fsl_mc_bus_remove,
7540 +};
7541 +
7542 +static int __init fsl_mc_bus_driver_init(void)
7543 +{
7544 + int error;
7545 +
7546 + error = bus_register(&fsl_mc_bus_type);
7547 + if (error < 0) {
7548 + pr_err("bus type registration failed: %d\n", error);
7549 + goto error_cleanup_cache;
7550 + }
7551 +
7552 + error = platform_driver_register(&fsl_mc_bus_driver);
7553 + if (error < 0) {
7554 + pr_err("platform_driver_register() failed: %d\n", error);
7555 + goto error_cleanup_bus;
7556 + }
7557 +
7558 + error = dprc_driver_init();
7559 + if (error < 0)
7560 + goto error_cleanup_driver;
7561 +
7562 + error = fsl_mc_allocator_driver_init();
7563 + if (error < 0)
7564 + goto error_cleanup_dprc_driver;
7565 +
7566 + error = fsl_mc_restool_init();
7567 + if (error < 0)
7568 + goto error_cleanup_mc_allocator;
7569 +
7570 + return 0;
7571 +
7572 +error_cleanup_mc_allocator:
7573 + fsl_mc_allocator_driver_exit();
7574 +
7575 +error_cleanup_dprc_driver:
7576 + dprc_driver_exit();
7577 +
7578 +error_cleanup_driver:
7579 + platform_driver_unregister(&fsl_mc_bus_driver);
7580 +
7581 +error_cleanup_bus:
7582 + bus_unregister(&fsl_mc_bus_type);
7583 +
7584 +error_cleanup_cache:
7585 + return error;
7586 +}
7587 +postcore_initcall(fsl_mc_bus_driver_init);
7588 --- a/drivers/staging/fsl-mc/bus/fsl-mc-msi.c
7589 +++ /dev/null
7590 @@ -1,285 +0,0 @@
7591 -// SPDX-License-Identifier: GPL-2.0
7592 -/*
7593 - * Freescale Management Complex (MC) bus driver MSI support
7594 - *
7595 - * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
7596 - * Author: German Rivera <German.Rivera@freescale.com>
7597 - *
7598 - */
7599 -
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"
7607 -
7608 -#ifdef GENERIC_MSI_DOMAIN_OPS
7609 -/*
7610 - * Generate a unique ID identifying the interrupt (only used within the MSI
7611 - * irqdomain. Combine the icid with the interrupt index.
7612 - */
7613 -static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev,
7614 - struct msi_desc *desc)
7615 -{
7616 - /*
7617 - * Make the base hwirq value for ICID*10000 so it is readable
7618 - * as a decimal value in /proc/interrupts.
7619 - */
7620 - return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000));
7621 -}
7622 -
7623 -static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg,
7624 - struct msi_desc *desc)
7625 -{
7626 - arg->desc = desc;
7627 - arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev),
7628 - desc);
7629 -}
7630 -#else
7631 -#define fsl_mc_msi_set_desc NULL
7632 -#endif
7633 -
7634 -static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info)
7635 -{
7636 - struct msi_domain_ops *ops = info->ops;
7637 -
7638 - if (WARN_ON(!ops))
7639 - return;
7640 -
7641 - /*
7642 - * set_desc should not be set by the caller
7643 - */
7644 - if (!ops->set_desc)
7645 - ops->set_desc = fsl_mc_msi_set_desc;
7646 -}
7647 -
7648 -static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
7649 - struct fsl_mc_device_irq *mc_dev_irq)
7650 -{
7651 - int error;
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;
7655 -
7656 - /*
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.
7660 - */
7661 - if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0)
7662 - return;
7663 -
7664 - if (WARN_ON(!owner_mc_dev))
7665 - return;
7666 -
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;
7671 -
7672 - if (owner_mc_dev == mc_bus_dev) {
7673 - /*
7674 - * IRQ is for the mc_bus_dev's DPRC itself
7675 - */
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,
7680 - &irq_cfg);
7681 - if (error < 0) {
7682 - dev_err(&owner_mc_dev->dev,
7683 - "dprc_set_irq() failed: %d\n", error);
7684 - }
7685 - } else {
7686 - /*
7687 - * IRQ is for for a child device of mc_bus_dev
7688 - */
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,
7695 - &irq_cfg);
7696 - if (error < 0) {
7697 - dev_err(&owner_mc_dev->dev,
7698 - "dprc_obj_set_irq() failed: %d\n", error);
7699 - }
7700 - }
7701 -}
7702 -
7703 -/*
7704 - * NOTE: This function is invoked with interrupts disabled
7705 - */
7706 -static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
7707 - struct msi_msg *msg)
7708 -{
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];
7714 -
7715 - WARN_ON(mc_dev_irq->msi_desc != msi_desc);
7716 - msi_desc->msg = *msg;
7717 -
7718 - /*
7719 - * Program the MSI (paddr, value) pair in the device:
7720 - */
7721 - __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq);
7722 -}
7723 -
7724 -static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
7725 -{
7726 - struct irq_chip *chip = info->chip;
7727 -
7728 - if (WARN_ON((!chip)))
7729 - return;
7730 -
7731 - /*
7732 - * irq_write_msi_msg should not be set by the caller
7733 - */
7734 - if (!chip->irq_write_msi_msg)
7735 - chip->irq_write_msi_msg = fsl_mc_msi_write_msg;
7736 -}
7737 -
7738 -/**
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
7743 - *
7744 - * Updates the domain and chip ops and creates a fsl-mc MSI
7745 - * interrupt domain.
7746 - *
7747 - * Returns:
7748 - * A domain pointer or NULL in case of failure.
7749 - */
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)
7753 -{
7754 - struct irq_domain *domain;
7755 -
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);
7760 -
7761 - domain = msi_create_irq_domain(fwnode, info, parent);
7762 - if (domain)
7763 - irq_domain_update_bus_token(domain, DOMAIN_BUS_FSL_MC_MSI);
7764 -
7765 - return domain;
7766 -}
7767 -
7768 -int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
7769 - struct irq_domain **mc_msi_domain)
7770 -{
7771 - struct irq_domain *msi_domain;
7772 - struct device_node *mc_of_node = mc_platform_dev->of_node;
7773 -
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",
7778 - mc_of_node);
7779 -
7780 - return -ENOENT;
7781 - }
7782 -
7783 - *mc_msi_domain = msi_domain;
7784 - return 0;
7785 -}
7786 -
7787 -static void fsl_mc_msi_free_descs(struct device *dev)
7788 -{
7789 - struct msi_desc *desc, *tmp;
7790 -
7791 - list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
7792 - list_del(&desc->list);
7793 - free_msi_entry(desc);
7794 - }
7795 -}
7796 -
7797 -static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count)
7798 -
7799 -{
7800 - unsigned int i;
7801 - int error;
7802 - struct msi_desc *msi_desc;
7803 -
7804 - for (i = 0; i < irq_count; i++) {
7805 - msi_desc = alloc_msi_entry(dev, 1, NULL);
7806 - if (!msi_desc) {
7807 - dev_err(dev, "Failed to allocate msi entry\n");
7808 - error = -ENOMEM;
7809 - goto cleanup_msi_descs;
7810 - }
7811 -
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));
7815 - }
7816 -
7817 - return 0;
7818 -
7819 -cleanup_msi_descs:
7820 - fsl_mc_msi_free_descs(dev);
7821 - return error;
7822 -}
7823 -
7824 -int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
7825 - unsigned int irq_count)
7826 -{
7827 - struct irq_domain *msi_domain;
7828 - int error;
7829 -
7830 - if (WARN_ON(!list_empty(dev_to_msi_list(dev))))
7831 - return -EINVAL;
7832 -
7833 - error = fsl_mc_msi_alloc_descs(dev, irq_count);
7834 - if (error < 0)
7835 - return error;
7836 -
7837 - msi_domain = dev_get_msi_domain(dev);
7838 - if (WARN_ON(!msi_domain)) {
7839 - error = -EINVAL;
7840 - goto cleanup_msi_descs;
7841 - }
7842 -
7843 - /*
7844 - * NOTE: Calling this function will trigger the invocation of the
7845 - * its_fsl_mc_msi_prepare() callback
7846 - */
7847 - error = msi_domain_alloc_irqs(msi_domain, dev, irq_count);
7848 -
7849 - if (error) {
7850 - dev_err(dev, "Failed to allocate IRQs\n");
7851 - goto cleanup_msi_descs;
7852 - }
7853 -
7854 - return 0;
7855 -
7856 -cleanup_msi_descs:
7857 - fsl_mc_msi_free_descs(dev);
7858 - return error;
7859 -}
7860 -
7861 -void fsl_mc_msi_domain_free_irqs(struct device *dev)
7862 -{
7863 - struct irq_domain *msi_domain;
7864 -
7865 - msi_domain = dev_get_msi_domain(dev);
7866 - if (WARN_ON(!msi_domain))
7867 - return;
7868 -
7869 - msi_domain_free_irqs(msi_domain, dev);
7870 -
7871 - if (WARN_ON(list_empty(dev_to_msi_list(dev))))
7872 - return;
7873 -
7874 - fsl_mc_msi_free_descs(dev);
7875 -}
7876 --- /dev/null
7877 +++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
7878 @@ -0,0 +1,285 @@
7879 +// SPDX-License-Identifier: GPL-2.0
7880 +/*
7881 + * Freescale Management Complex (MC) bus driver MSI support
7882 + *
7883 + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
7884 + * Author: German Rivera <German.Rivera@freescale.com>
7885 + *
7886 + */
7887 +
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>
7894 +
7895 +#include "fsl-mc-private.h"
7896 +
7897 +#ifdef GENERIC_MSI_DOMAIN_OPS
7898 +/*
7899 + * Generate a unique ID identifying the interrupt (only used within the MSI
7900 + * irqdomain. Combine the icid with the interrupt index.
7901 + */
7902 +static irq_hw_number_t fsl_mc_domain_calc_hwirq(struct fsl_mc_device *dev,
7903 + struct msi_desc *desc)
7904 +{
7905 + /*
7906 + * Make the base hwirq value for ICID*10000 so it is readable
7907 + * as a decimal value in /proc/interrupts.
7908 + */
7909 + return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 10000));
7910 +}
7911 +
7912 +static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg,
7913 + struct msi_desc *desc)
7914 +{
7915 + arg->desc = desc;
7916 + arg->hwirq = fsl_mc_domain_calc_hwirq(to_fsl_mc_device(desc->dev),
7917 + desc);
7918 +}
7919 +#else
7920 +#define fsl_mc_msi_set_desc NULL
7921 +#endif
7922 +
7923 +static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info)
7924 +{
7925 + struct msi_domain_ops *ops = info->ops;
7926 +
7927 + if (!ops)
7928 + return;
7929 +
7930 + /*
7931 + * set_desc should not be set by the caller
7932 + */
7933 + if (!ops->set_desc)
7934 + ops->set_desc = fsl_mc_msi_set_desc;
7935 +}
7936 +
7937 +static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
7938 + struct fsl_mc_device_irq *mc_dev_irq)
7939 +{
7940 + int error;
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;
7944 +
7945 + /*
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.
7949 + */
7950 + if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0)
7951 + return;
7952 +
7953 + if (!owner_mc_dev)
7954 + return;
7955 +
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;
7960 +
7961 + if (owner_mc_dev == mc_bus_dev) {
7962 + /*
7963 + * IRQ is for the mc_bus_dev's DPRC itself
7964 + */
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,
7969 + &irq_cfg);
7970 + if (error < 0) {
7971 + dev_err(&owner_mc_dev->dev,
7972 + "dprc_set_irq() failed: %d\n", error);
7973 + }
7974 + } else {
7975 + /*
7976 + * IRQ is for for a child device of mc_bus_dev
7977 + */
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,
7984 + &irq_cfg);
7985 + if (error < 0) {
7986 + dev_err(&owner_mc_dev->dev,
7987 + "dprc_obj_set_irq() failed: %d\n", error);
7988 + }
7989 + }
7990 +}
7991 +
7992 +/*
7993 + * NOTE: This function is invoked with interrupts disabled
7994 + */
7995 +static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
7996 + struct msi_msg *msg)
7997 +{
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];
8003 +
8004 + msi_desc->msg = *msg;
8005 +
8006 + /*
8007 + * Program the MSI (paddr, value) pair in the device:
8008 + */
8009 + __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq);
8010 +}
8011 +
8012 +static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
8013 +{
8014 + struct irq_chip *chip = info->chip;
8015 +
8016 + if (!chip)
8017 + return;
8018 +
8019 + /*
8020 + * irq_write_msi_msg should not be set by the caller
8021 + */
8022 + if (!chip->irq_write_msi_msg)
8023 + chip->irq_write_msi_msg = fsl_mc_msi_write_msg;
8024 +}
8025 +
8026 +/**
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
8031 + *
8032 + * Updates the domain and chip ops and creates a fsl-mc MSI
8033 + * interrupt domain.
8034 + *
8035 + * Returns:
8036 + * A domain pointer or NULL in case of failure.
8037 + */
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)
8041 +{
8042 + struct irq_domain *domain;
8043 +
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);
8048 +
8049 + domain = msi_create_irq_domain(fwnode, info, parent);
8050 + if (domain)
8051 + irq_domain_update_bus_token(domain, DOMAIN_BUS_FSL_MC_MSI);
8052 +
8053 + return domain;
8054 +}
8055 +
8056 +int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
8057 + struct irq_domain **mc_msi_domain)
8058 +{
8059 + struct irq_domain *msi_domain;
8060 + struct device_node *mc_of_node = mc_platform_dev->of_node;
8061 +
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",
8066 + mc_of_node);
8067 +
8068 + return -ENOENT;
8069 + }
8070 +
8071 + *mc_msi_domain = msi_domain;
8072 + return 0;
8073 +}
8074 +
8075 +static void fsl_mc_msi_free_descs(struct device *dev)
8076 +{
8077 + struct msi_desc *desc, *tmp;
8078 +
8079 + list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
8080 + list_del(&desc->list);
8081 + free_msi_entry(desc);
8082 + }
8083 +}
8084 +
8085 +static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count)
8086 +
8087 +{
8088 + unsigned int i;
8089 + int error;
8090 + struct msi_desc *msi_desc;
8091 +
8092 + for (i = 0; i < irq_count; i++) {
8093 + msi_desc = alloc_msi_entry(dev, 1, NULL);
8094 + if (!msi_desc) {
8095 + dev_err(dev, "Failed to allocate msi entry\n");
8096 + error = -ENOMEM;
8097 + goto cleanup_msi_descs;
8098 + }
8099 +
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));
8103 + }
8104 +
8105 + return 0;
8106 +
8107 +cleanup_msi_descs:
8108 + fsl_mc_msi_free_descs(dev);
8109 + return error;
8110 +}
8111 +
8112 +int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
8113 + unsigned int irq_count)
8114 +{
8115 + struct irq_domain *msi_domain;
8116 + int error;
8117 +
8118 + if (!list_empty(dev_to_msi_list(dev)))
8119 + return -EINVAL;
8120 +
8121 + error = fsl_mc_msi_alloc_descs(dev, irq_count);
8122 + if (error < 0)
8123 + return error;
8124 +
8125 + msi_domain = dev_get_msi_domain(dev);
8126 + if (!msi_domain) {
8127 + error = -EINVAL;
8128 + goto cleanup_msi_descs;
8129 + }
8130 +
8131 + /*
8132 + * NOTE: Calling this function will trigger the invocation of the
8133 + * its_fsl_mc_msi_prepare() callback
8134 + */
8135 + error = msi_domain_alloc_irqs(msi_domain, dev, irq_count);
8136 +
8137 + if (error) {
8138 + dev_err(dev, "Failed to allocate IRQs\n");
8139 + goto cleanup_msi_descs;
8140 + }
8141 +
8142 + return 0;
8143 +
8144 +cleanup_msi_descs:
8145 + fsl_mc_msi_free_descs(dev);
8146 + return error;
8147 +}
8148 +
8149 +void fsl_mc_msi_domain_free_irqs(struct device *dev)
8150 +{
8151 + struct irq_domain *msi_domain;
8152 +
8153 + msi_domain = dev_get_msi_domain(dev);
8154 + if (!msi_domain)
8155 + return;
8156 +
8157 + msi_domain_free_irqs(msi_domain, dev);
8158 +
8159 + if (list_empty(dev_to_msi_list(dev)))
8160 + return;
8161 +
8162 + fsl_mc_msi_free_descs(dev);
8163 +}
8164 --- /dev/null
8165 +++ b/drivers/bus/fsl-mc/fsl-mc-private.h
8166 @@ -0,0 +1,223 @@
8167 +/* SPDX-License-Identifier: GPL-2.0 */
8168 +/*
8169 + * Freescale Management Complex (MC) bus private declarations
8170 + *
8171 + * Copyright (C) 2016 Freescale Semiconductor, Inc.
8172 + *
8173 + */
8174 +#ifndef _FSL_MC_PRIVATE_H_
8175 +#define _FSL_MC_PRIVATE_H_
8176 +
8177 +#include <linux/fsl/mc.h>
8178 +#include <linux/mutex.h>
8179 +#include <linux/cdev.h>
8180 +#include <linux/ioctl.h>
8181 +
8182 +/*
8183 + * Data Path Management Complex (DPMNG) General API
8184 + */
8185 +
8186 +/* DPMNG command versioning */
8187 +#define DPMNG_CMD_BASE_VERSION 1
8188 +#define DPMNG_CMD_ID_OFFSET 4
8189 +
8190 +#define DPMNG_CMD(id) (((id) << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION)
8191 +
8192 +/* DPMNG command IDs */
8193 +#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831)
8194 +
8195 +struct dpmng_rsp_get_version {
8196 + __le32 revision;
8197 + __le32 version_major;
8198 + __le32 version_minor;
8199 +};
8200 +
8201 +/*
8202 + * Data Path Management Command Portal (DPMCP) API
8203 + */
8204 +
8205 +/* Minimal supported DPMCP Version */
8206 +#define DPMCP_MIN_VER_MAJOR 3
8207 +#define DPMCP_MIN_VER_MINOR 0
8208 +
8209 +/* DPMCP command versioning */
8210 +#define DPMCP_CMD_BASE_VERSION 1
8211 +#define DPMCP_CMD_ID_OFFSET 4
8212 +
8213 +#define DPMCP_CMD(id) (((id) << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION)
8214 +
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)
8219 +
8220 +struct dpmcp_cmd_open {
8221 + __le32 dpmcp_id;
8222 +};
8223 +
8224 +/*
8225 + * Initialization and runtime control APIs for DPMCP
8226 + */
8227 +int dpmcp_open(struct fsl_mc_io *mc_io,
8228 + u32 cmd_flags,
8229 + int dpmcp_id,
8230 + u16 *token);
8231 +
8232 +int dpmcp_close(struct fsl_mc_io *mc_io,
8233 + u32 cmd_flags,
8234 + u16 token);
8235 +
8236 +int dpmcp_reset(struct fsl_mc_io *mc_io,
8237 + u32 cmd_flags,
8238 + u16 token);
8239 +
8240 +/*
8241 + * Data Path Buffer Pool (DPBP) API
8242 + */
8243 +
8244 +/* DPBP Version */
8245 +#define DPBP_VER_MAJOR 3
8246 +#define DPBP_VER_MINOR 2
8247 +
8248 +/* Command versioning */
8249 +#define DPBP_CMD_BASE_VERSION 1
8250 +#define DPBP_CMD_ID_OFFSET 4
8251 +
8252 +#define DPBP_CMD(id) (((id) << DPBP_CMD_ID_OFFSET) | DPBP_CMD_BASE_VERSION)
8253 +
8254 +/* Command IDs */
8255 +#define DPBP_CMDID_CLOSE DPBP_CMD(0x800)
8256 +#define DPBP_CMDID_OPEN DPBP_CMD(0x804)
8257 +
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)
8262 +
8263 +struct dpbp_cmd_open {
8264 + __le32 dpbp_id;
8265 +};
8266 +
8267 +#define DPBP_ENABLE 0x1
8268 +
8269 +struct dpbp_rsp_get_attributes {
8270 + /* response word 0 */
8271 + __le16 pad;
8272 + __le16 bpid;
8273 + __le32 id;
8274 + /* response word 1 */
8275 + __le16 version_major;
8276 + __le16 version_minor;
8277 +};
8278 +
8279 +/*
8280 + * Data Path Concentrator (DPCON) API
8281 + */
8282 +
8283 +/* DPCON Version */
8284 +#define DPCON_VER_MAJOR 3
8285 +#define DPCON_VER_MINOR 2
8286 +
8287 +/* Command versioning */
8288 +#define DPCON_CMD_BASE_VERSION 1
8289 +#define DPCON_CMD_ID_OFFSET 4
8290 +
8291 +#define DPCON_CMD(id) (((id) << DPCON_CMD_ID_OFFSET) | DPCON_CMD_BASE_VERSION)
8292 +
8293 +/* Command IDs */
8294 +#define DPCON_CMDID_CLOSE DPCON_CMD(0x800)
8295 +#define DPCON_CMDID_OPEN DPCON_CMD(0x808)
8296 +
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)
8301 +
8302 +#define DPCON_CMDID_SET_NOTIFICATION DPCON_CMD(0x100)
8303 +
8304 +struct dpcon_cmd_open {
8305 + __le32 dpcon_id;
8306 +};
8307 +
8308 +#define DPCON_ENABLE 1
8309 +
8310 +struct dpcon_rsp_get_attr {
8311 + /* response word 0 */
8312 + __le32 id;
8313 + __le16 qbman_ch_id;
8314 + u8 num_priorities;
8315 + u8 pad;
8316 +};
8317 +
8318 +struct dpcon_cmd_set_notification {
8319 + /* cmd word 0 */
8320 + __le32 dpio_id;
8321 + u8 priority;
8322 + u8 pad[3];
8323 + /* cmd word 1 */
8324 + __le64 user_ctx;
8325 +};
8326 +
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);
8332 +
8333 +int __init dprc_driver_init(void);
8334 +
8335 +void dprc_driver_exit(void);
8336 +
8337 +int __init fsl_mc_allocator_driver_init(void);
8338 +
8339 +void fsl_mc_allocator_driver_exit(void);
8340 +
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
8344 + **new_resource);
8345 +
8346 +void fsl_mc_resource_free(struct fsl_mc_resource *resource);
8347 +
8348 +int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
8349 + unsigned int irq_count);
8350 +
8351 +void fsl_mc_msi_domain_free_irqs(struct device *dev);
8352 +
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);
8358 +
8359 +void fsl_destroy_mc_io(struct fsl_mc_io *mc_io);
8360 +
8361 +bool fsl_mc_is_root_dprc(struct device *dev);
8362 +
8363 +#ifdef CONFIG_FSL_MC_RESTOOL
8364 +
8365 +int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus);
8366 +
8367 +void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus);
8368 +
8369 +int fsl_mc_restool_init(void);
8370 +
8371 +#else
8372 +
8373 +static inline int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus)
8374 +{
8375 + return 0;
8376 +}
8377 +
8378 +static inline void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus)
8379 +{
8380 +}
8381 +
8382 +static inline int fsl_mc_restool_init(void)
8383 +{
8384 + return 0;
8385 +}
8386 +
8387 +#endif
8388 +
8389 +#endif /* _FSL_MC_PRIVATE_H_ */
8390 --- /dev/null
8391 +++ b/drivers/bus/fsl-mc/fsl-mc-restool.c
8392 @@ -0,0 +1,219 @@
8393 +// SPDX-License-Identifier: GPL-2.0
8394 +/*
8395 + * Management Complex (MC) restool support
8396 + *
8397 + * Copyright 2018 NXP
8398 + *
8399 + */
8400 +
8401 +#include <linux/slab.h>
8402 +#include <linux/cdev.h>
8403 +#include <linux/fs.h>
8404 +#include <linux/uaccess.h>
8405 +
8406 +#include "fsl-mc-private.h"
8407 +
8408 +#define FSL_MC_BUS_MAX_MINORS 1
8409 +
8410 +static struct class *fsl_mc_bus_class;
8411 +static int fsl_mc_bus_major;
8412 +
8413 +static int fsl_mc_restool_send_command(unsigned long arg,
8414 + struct fsl_mc_io *mc_io)
8415 +{
8416 + struct fsl_mc_command mc_cmd;
8417 + int error;
8418 +
8419 + error = copy_from_user(&mc_cmd, (void __user *)arg, sizeof(mc_cmd));
8420 + if (error)
8421 + return -EFAULT;
8422 +
8423 + error = mc_send_command(mc_io, &mc_cmd);
8424 + if (error)
8425 + return error;
8426 +
8427 + error = copy_to_user((void __user *)arg, &mc_cmd, sizeof(mc_cmd));
8428 + if (error)
8429 + return -EFAULT;
8430 +
8431 + return 0;
8432 +}
8433 +
8434 +int fsl_mc_restool_init(void)
8435 +{
8436 + dev_t dev;
8437 + int error;
8438 +
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);
8442 + return error;
8443 + }
8444 +
8445 + error = alloc_chrdev_region(&dev, 0,
8446 + FSL_MC_BUS_MAX_MINORS,
8447 + "fsl_mc_bus");
8448 + if (error < 0)
8449 + return error;
8450 +
8451 + fsl_mc_bus_major = MAJOR(dev);
8452 +
8453 + return 0;
8454 +}
8455 +
8456 +static int fsl_mc_restool_dev_open(struct inode *inode, struct file *filep)
8457 +{
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;
8462 + int error;
8463 +
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;
8467 +
8468 + mutex_lock(&mc_restool->mutex);
8469 +
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;
8473 + } else {
8474 + dynamic_mc_io = kzalloc(sizeof(*dynamic_mc_io), GFP_KERNEL);
8475 + if (!dynamic_mc_io) {
8476 + error = -ENOMEM;
8477 + goto error_alloc_mc_io;
8478 + }
8479 +
8480 + error = fsl_mc_portal_allocate(root_mc_device, 0,
8481 + &dynamic_mc_io);
8482 + if (error) {
8483 + pr_err("Could not allocate MC portal\n");
8484 + goto error_portal_allocate;
8485 + }
8486 +
8487 + mc_restool->dynamic_instance_count++;
8488 + filep->private_data = dynamic_mc_io;
8489 + }
8490 +
8491 + mutex_unlock(&mc_restool->mutex);
8492 +
8493 + return 0;
8494 +
8495 +error_portal_allocate:
8496 + kfree(dynamic_mc_io);
8497 +
8498 +error_alloc_mc_io:
8499 + mutex_unlock(&mc_restool->mutex);
8500 +
8501 + return error;
8502 +}
8503 +
8504 +static int fsl_mc_restool_dev_release(struct inode *inode, struct file *filep)
8505 +{
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;
8510 +
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;
8515 +
8516 + mutex_lock(&mc_restool->mutex);
8517 +
8518 + if (WARN_ON(!mc_restool->local_instance_in_use &&
8519 + mc_restool->dynamic_instance_count == 0)) {
8520 + mutex_unlock(&mc_restool->mutex);
8521 + return -EINVAL;
8522 + }
8523 +
8524 + if (filep->private_data == root_mc_device->mc_io) {
8525 + mc_restool->local_instance_in_use = false;
8526 + } else {
8527 + fsl_mc_portal_free(mc_io);
8528 + kfree(mc_io);
8529 + mc_restool->dynamic_instance_count--;
8530 + }
8531 +
8532 + filep->private_data = NULL;
8533 + mutex_unlock(&mc_restool->mutex);
8534 +
8535 + return 0;
8536 +}
8537 +
8538 +static long fsl_mc_restool_dev_ioctl(struct file *file,
8539 + unsigned int cmd,
8540 + unsigned long arg)
8541 +{
8542 + int error;
8543 +
8544 + switch (cmd) {
8545 + case RESTOOL_SEND_MC_COMMAND:
8546 + error = fsl_mc_restool_send_command(arg, file->private_data);
8547 + break;
8548 + default:
8549 + pr_err("%s: unexpected ioctl call number\n", __func__);
8550 + error = -EINVAL;
8551 + }
8552 +
8553 + return error;
8554 +}
8555 +
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,
8561 +};
8562 +
8563 +int fsl_mc_restool_create_device_file(struct fsl_mc_bus *mc_bus)
8564 +{
8565 + struct fsl_mc_device *mc_dev = &mc_bus->mc_dev;
8566 + struct fsl_mc_restool *mc_restool = &mc_bus->restool_misc;
8567 + int error;
8568 +
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);
8572 +
8573 + error = cdev_add(&mc_restool->cdev,
8574 + mc_restool->dev,
8575 + FSL_MC_BUS_MAX_MINORS);
8576 + if (error)
8577 + return error;
8578 +
8579 + mc_restool->device = device_create(fsl_mc_bus_class,
8580 + NULL,
8581 + mc_restool->dev,
8582 + NULL,
8583 + "%s",
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;
8588 + }
8589 +
8590 + mutex_init(&mc_restool->mutex);
8591 +
8592 + return 0;
8593 +
8594 +error_device_create:
8595 + cdev_del(&mc_restool->cdev);
8596 +
8597 + return error;
8598 +}
8599 +
8600 +void fsl_mc_restool_remove_device_file(struct fsl_mc_bus *mc_bus)
8601 +{
8602 + struct fsl_mc_restool *mc_restool = &mc_bus->restool_misc;
8603 +
8604 + if (WARN_ON(mc_restool->local_instance_in_use))
8605 + return;
8606 +
8607 + if (WARN_ON(mc_restool->dynamic_instance_count != 0))
8608 + return;
8609 +
8610 + cdev_del(&mc_restool->cdev);
8611 +}
8612 --- a/drivers/staging/fsl-mc/bus/mc-io.c
8613 +++ /dev/null
8614 @@ -1,292 +0,0 @@
8615 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
8616 -/*
8617 - * Copyright 2013-2016 Freescale Semiconductor Inc.
8618 - *
8619 - */
8620 -
8621 -#include <linux/io.h>
8622 -#include "../include/mc.h"
8623 -
8624 -#include "fsl-mc-private.h"
8625 -#include "dpmcp.h"
8626 -#include "dpmcp-cmd.h"
8627 -
8628 -static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io,
8629 - struct fsl_mc_device *dpmcp_dev)
8630 -{
8631 - int error;
8632 -
8633 - if (WARN_ON(!dpmcp_dev))
8634 - return -EINVAL;
8635 -
8636 - if (WARN_ON(mc_io->dpmcp_dev))
8637 - return -EINVAL;
8638 -
8639 - if (WARN_ON(dpmcp_dev->mc_io))
8640 - return -EINVAL;
8641 -
8642 - error = dpmcp_open(mc_io,
8643 - 0,
8644 - dpmcp_dev->obj_desc.id,
8645 - &dpmcp_dev->mc_handle);
8646 - if (error < 0)
8647 - return error;
8648 -
8649 - mc_io->dpmcp_dev = dpmcp_dev;
8650 - dpmcp_dev->mc_io = mc_io;
8651 - return 0;
8652 -}
8653 -
8654 -static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io)
8655 -{
8656 - int error;
8657 - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8658 -
8659 - if (WARN_ON(!dpmcp_dev))
8660 - return;
8661 -
8662 - if (WARN_ON(dpmcp_dev->mc_io != mc_io))
8663 - return;
8664 -
8665 - error = dpmcp_close(mc_io,
8666 - 0,
8667 - dpmcp_dev->mc_handle);
8668 - if (error < 0) {
8669 - dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n",
8670 - error);
8671 - }
8672 -
8673 - mc_io->dpmcp_dev = NULL;
8674 - dpmcp_dev->mc_io = NULL;
8675 -}
8676 -
8677 -/**
8678 - * Creates an MC I/O object
8679 - *
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
8687 - *
8688 - * Returns '0' on Success; Error code otherwise.
8689 - */
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)
8695 -{
8696 - int error;
8697 - struct fsl_mc_io *mc_io;
8698 - void __iomem *mc_portal_virt_addr;
8699 - struct resource *res;
8700 -
8701 - mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL);
8702 - if (!mc_io)
8703 - return -ENOMEM;
8704 -
8705 - mc_io->dev = dev;
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);
8711 - else
8712 - mutex_init(&mc_io->mutex);
8713 -
8714 - res = devm_request_mem_region(dev,
8715 - mc_portal_phys_addr,
8716 - mc_portal_size,
8717 - "mc_portal");
8718 - if (!res) {
8719 - dev_err(dev,
8720 - "devm_request_mem_region failed for MC portal %pa\n",
8721 - &mc_portal_phys_addr);
8722 - return -EBUSY;
8723 - }
8724 -
8725 - mc_portal_virt_addr = devm_ioremap_nocache(dev,
8726 - mc_portal_phys_addr,
8727 - mc_portal_size);
8728 - if (!mc_portal_virt_addr) {
8729 - dev_err(dev,
8730 - "devm_ioremap_nocache failed for MC portal %pa\n",
8731 - &mc_portal_phys_addr);
8732 - return -ENXIO;
8733 - }
8734 -
8735 - mc_io->portal_virt_addr = mc_portal_virt_addr;
8736 - if (dpmcp_dev) {
8737 - error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev);
8738 - if (error < 0)
8739 - goto error_destroy_mc_io;
8740 - }
8741 -
8742 - *new_mc_io = mc_io;
8743 - return 0;
8744 -
8745 -error_destroy_mc_io:
8746 - fsl_destroy_mc_io(mc_io);
8747 - return error;
8748 -}
8749 -
8750 -/**
8751 - * Destroys an MC I/O object
8752 - *
8753 - * @mc_io: MC I/O object to destroy
8754 - */
8755 -void fsl_destroy_mc_io(struct fsl_mc_io *mc_io)
8756 -{
8757 - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8758 -
8759 - if (dpmcp_dev)
8760 - fsl_mc_io_unset_dpmcp(mc_io);
8761 -
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);
8766 -
8767 - mc_io->portal_virt_addr = NULL;
8768 - devm_kfree(mc_io->dev, mc_io);
8769 -}
8770 -
8771 -/**
8772 - * fsl_mc_portal_allocate - Allocates an MC portal
8773 - *
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
8776 - * MC portal.
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
8779 - *
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.
8784 - */
8785 -int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
8786 - u16 mc_io_flags,
8787 - struct fsl_mc_io **new_mc_io)
8788 -{
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;
8797 -
8798 - if (mc_dev->flags & FSL_MC_IS_DPRC) {
8799 - mc_bus_dev = mc_dev;
8800 - } else {
8801 - if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent)))
8802 - return error;
8803 -
8804 - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
8805 - }
8806 -
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);
8810 - if (error < 0)
8811 - return error;
8812 -
8813 - error = -EINVAL;
8814 - dpmcp_dev = resource->data;
8815 - if (WARN_ON(!dpmcp_dev))
8816 - goto error_cleanup_resource;
8817 -
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;
8827 - }
8828 -
8829 - if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0))
8830 - goto error_cleanup_resource;
8831 -
8832 - mc_portal_phys_addr = dpmcp_dev->regions[0].start;
8833 - mc_portal_size = resource_size(dpmcp_dev->regions);
8834 -
8835 - if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size))
8836 - goto error_cleanup_resource;
8837 -
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);
8842 - if (error < 0)
8843 - goto error_cleanup_resource;
8844 -
8845 - *new_mc_io = mc_io;
8846 - return 0;
8847 -
8848 -error_cleanup_resource:
8849 - fsl_mc_resource_free(resource);
8850 - return error;
8851 -}
8852 -EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate);
8853 -
8854 -/**
8855 - * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals
8856 - * of a given MC bus
8857 - *
8858 - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
8859 - */
8860 -void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
8861 -{
8862 - struct fsl_mc_device *dpmcp_dev;
8863 - struct fsl_mc_resource *resource;
8864 -
8865 - /*
8866 - * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed
8867 - * to have a DPMCP object associated with.
8868 - */
8869 - dpmcp_dev = mc_io->dpmcp_dev;
8870 - if (WARN_ON(!dpmcp_dev))
8871 - return;
8872 -
8873 - resource = dpmcp_dev->resource;
8874 - if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP))
8875 - return;
8876 -
8877 - if (WARN_ON(resource->data != dpmcp_dev))
8878 - return;
8879 -
8880 - fsl_destroy_mc_io(mc_io);
8881 - fsl_mc_resource_free(resource);
8882 -}
8883 -EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
8884 -
8885 -/**
8886 - * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object
8887 - *
8888 - * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
8889 - */
8890 -int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
8891 -{
8892 - int error;
8893 - struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8894 -
8895 - if (WARN_ON(!dpmcp_dev))
8896 - return -EINVAL;
8897 -
8898 - error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle);
8899 - if (error < 0) {
8900 - dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error);
8901 - return error;
8902 - }
8903 -
8904 - return 0;
8905 -}
8906 -EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
8907 --- /dev/null
8908 +++ b/drivers/bus/fsl-mc/mc-io.c
8909 @@ -0,0 +1,281 @@
8910 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
8911 +/*
8912 + * Copyright 2013-2016 Freescale Semiconductor Inc.
8913 + *
8914 + */
8915 +
8916 +#include <linux/io.h>
8917 +#include <linux/fsl/mc.h>
8918 +
8919 +#include "fsl-mc-private.h"
8920 +
8921 +static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io,
8922 + struct fsl_mc_device *dpmcp_dev)
8923 +{
8924 + int error;
8925 +
8926 + if (mc_io->dpmcp_dev)
8927 + return -EINVAL;
8928 +
8929 + if (dpmcp_dev->mc_io)
8930 + return -EINVAL;
8931 +
8932 + error = dpmcp_open(mc_io,
8933 + 0,
8934 + dpmcp_dev->obj_desc.id,
8935 + &dpmcp_dev->mc_handle);
8936 + if (error < 0)
8937 + return error;
8938 +
8939 + mc_io->dpmcp_dev = dpmcp_dev;
8940 + dpmcp_dev->mc_io = mc_io;
8941 + return 0;
8942 +}
8943 +
8944 +static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io)
8945 +{
8946 + int error;
8947 + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
8948 +
8949 + error = dpmcp_close(mc_io,
8950 + 0,
8951 + dpmcp_dev->mc_handle);
8952 + if (error < 0) {
8953 + dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n",
8954 + error);
8955 + }
8956 +
8957 + mc_io->dpmcp_dev = NULL;
8958 + dpmcp_dev->mc_io = NULL;
8959 +}
8960 +
8961 +/**
8962 + * Creates an MC I/O object
8963 + *
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
8971 + *
8972 + * Returns '0' on Success; Error code otherwise.
8973 + */
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)
8979 +{
8980 + int error;
8981 + struct fsl_mc_io *mc_io;
8982 + void __iomem *mc_portal_virt_addr;
8983 + struct resource *res;
8984 +
8985 + mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL);
8986 + if (!mc_io)
8987 + return -ENOMEM;
8988 +
8989 + mc_io->dev = dev;
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);
8995 + else
8996 + mutex_init(&mc_io->mutex);
8997 +
8998 + res = devm_request_mem_region(dev,
8999 + mc_portal_phys_addr,
9000 + mc_portal_size,
9001 + "mc_portal");
9002 + if (!res) {
9003 + dev_err(dev,
9004 + "devm_request_mem_region failed for MC portal %pa\n",
9005 + &mc_portal_phys_addr);
9006 + return -EBUSY;
9007 + }
9008 +
9009 + mc_portal_virt_addr = devm_ioremap_nocache(dev,
9010 + mc_portal_phys_addr,
9011 + mc_portal_size);
9012 + if (!mc_portal_virt_addr) {
9013 + dev_err(dev,
9014 + "devm_ioremap_nocache failed for MC portal %pa\n",
9015 + &mc_portal_phys_addr);
9016 + return -ENXIO;
9017 + }
9018 +
9019 + mc_io->portal_virt_addr = mc_portal_virt_addr;
9020 + if (dpmcp_dev) {
9021 + error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev);
9022 + if (error < 0)
9023 + goto error_destroy_mc_io;
9024 + }
9025 +
9026 + *new_mc_io = mc_io;
9027 + return 0;
9028 +
9029 +error_destroy_mc_io:
9030 + fsl_destroy_mc_io(mc_io);
9031 + return error;
9032 +}
9033 +
9034 +/**
9035 + * Destroys an MC I/O object
9036 + *
9037 + * @mc_io: MC I/O object to destroy
9038 + */
9039 +void fsl_destroy_mc_io(struct fsl_mc_io *mc_io)
9040 +{
9041 + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
9042 +
9043 + if (dpmcp_dev)
9044 + fsl_mc_io_unset_dpmcp(mc_io);
9045 +
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);
9050 +
9051 + mc_io->portal_virt_addr = NULL;
9052 + devm_kfree(mc_io->dev, mc_io);
9053 +}
9054 +
9055 +/**
9056 + * fsl_mc_portal_allocate - Allocates an MC portal
9057 + *
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
9060 + * MC portal.
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
9063 + *
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.
9068 + */
9069 +int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
9070 + u16 mc_io_flags,
9071 + struct fsl_mc_io **new_mc_io)
9072 +{
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;
9081 +
9082 + if (fsl_mc_is_root_dprc(&mc_dev->dev)) {
9083 + mc_bus_dev = mc_dev;
9084 + } else {
9085 + if (!dev_is_fsl_mc(mc_dev->dev.parent))
9086 + return error;
9087 +
9088 + mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
9089 + }
9090 +
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);
9094 + if (error < 0)
9095 + return error;
9096 +
9097 + error = -EINVAL;
9098 + dpmcp_dev = resource->data;
9099 +
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;
9109 + }
9110 +
9111 + mc_portal_phys_addr = dpmcp_dev->regions[0].start;
9112 + mc_portal_size = resource_size(dpmcp_dev->regions);
9113 +
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);
9118 + if (error < 0)
9119 + goto error_cleanup_resource;
9120 +
9121 + dpmcp_dev->consumer_link = device_link_add(&mc_dev->dev,
9122 + &dpmcp_dev->dev,
9123 + DL_FLAG_AUTOREMOVE_CONSUMER);
9124 + if (!dpmcp_dev->consumer_link) {
9125 + error = -EINVAL;
9126 + goto error_cleanup_mc_io;
9127 + }
9128 +
9129 + *new_mc_io = mc_io;
9130 + return 0;
9131 +
9132 +error_cleanup_mc_io:
9133 + fsl_destroy_mc_io(mc_io);
9134 +error_cleanup_resource:
9135 + fsl_mc_resource_free(resource);
9136 + return error;
9137 +}
9138 +EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate);
9139 +
9140 +/**
9141 + * fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals
9142 + * of a given MC bus
9143 + *
9144 + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
9145 + */
9146 +void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
9147 +{
9148 + struct fsl_mc_device *dpmcp_dev;
9149 + struct fsl_mc_resource *resource;
9150 +
9151 + /*
9152 + * Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed
9153 + * to have a DPMCP object associated with.
9154 + */
9155 + dpmcp_dev = mc_io->dpmcp_dev;
9156 +
9157 + resource = dpmcp_dev->resource;
9158 + if (!resource || resource->type != FSL_MC_POOL_DPMCP)
9159 + return;
9160 +
9161 + if (resource->data != dpmcp_dev)
9162 + return;
9163 +
9164 + fsl_destroy_mc_io(mc_io);
9165 + fsl_mc_resource_free(resource);
9166 +
9167 + device_link_del(dpmcp_dev->consumer_link);
9168 + dpmcp_dev->consumer_link = NULL;
9169 +}
9170 +EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
9171 +
9172 +/**
9173 + * fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object
9174 + *
9175 + * @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
9176 + */
9177 +int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
9178 +{
9179 + int error;
9180 + struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
9181 +
9182 + error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle);
9183 + if (error < 0) {
9184 + dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error);
9185 + return error;
9186 + }
9187 +
9188 + return 0;
9189 +}
9190 +EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
9191 --- a/drivers/staging/fsl-mc/bus/mc-sys.c
9192 +++ /dev/null
9193 @@ -1,297 +0,0 @@
9194 -// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
9195 -/*
9196 - * Copyright 2013-2016 Freescale Semiconductor Inc.
9197 - *
9198 - * I/O services to send MC commands to the MC hardware
9199 - *
9200 - */
9201 -
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"
9209 -
9210 -#include "dpmcp.h"
9211 -
9212 -/**
9213 - * Timeout in milliseconds to wait for the completion of an MC command
9214 - */
9215 -#define MC_CMD_COMPLETION_TIMEOUT_MS 500
9216 -
9217 -/*
9218 - * usleep_range() min and max values used to throttle down polling
9219 - * iterations while waiting for MC command completion
9220 - */
9221 -#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10
9222 -#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500
9223 -
9224 -static enum mc_cmd_status mc_cmd_hdr_read_status(struct mc_command *cmd)
9225 -{
9226 - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
9227 -
9228 - return (enum mc_cmd_status)hdr->status;
9229 -}
9230 -
9231 -static u16 mc_cmd_hdr_read_cmdid(struct mc_command *cmd)
9232 -{
9233 - struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
9234 - u16 cmd_id = le16_to_cpu(hdr->cmd_id);
9235 -
9236 - return cmd_id;
9237 -}
9238 -
9239 -static int mc_status_to_error(enum mc_cmd_status status)
9240 -{
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,
9253 - };
9254 -
9255 - if (WARN_ON((u32)status >= ARRAY_SIZE(mc_status_to_error_map)))
9256 - return -EINVAL;
9257 -
9258 - return mc_status_to_error_map[status];
9259 -}
9260 -
9261 -static const char *mc_status_to_string(enum mc_cmd_status status)
9262 -{
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"
9276 - };
9277 -
9278 - if ((unsigned int)status >= ARRAY_SIZE(status_strings))
9279 - return "Unknown MC error";
9280 -
9281 - return status_strings[status];
9282 -}
9283 -
9284 -/**
9285 - * mc_write_command - writes a command to a Management Complex (MC) portal
9286 - *
9287 - * @portal: pointer to an MC portal
9288 - * @cmd: pointer to a filled command
9289 - */
9290 -static inline void mc_write_command(struct mc_command __iomem *portal,
9291 - struct mc_command *cmd)
9292 -{
9293 - int i;
9294 -
9295 - /* copy command parameters into the portal */
9296 - for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
9297 - /*
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.
9301 - */
9302 - writeq_relaxed(le64_to_cpu(cmd->params[i]), &portal->params[i]);
9303 -
9304 - /* submit the command by writing the header */
9305 - writeq(le64_to_cpu(cmd->header), &portal->header);
9306 -}
9307 -
9308 -/**
9309 - * mc_read_response - reads the response for the last MC command from a
9310 - * Management Complex (MC) portal
9311 - *
9312 - * @portal: pointer to an MC portal
9313 - * @resp: pointer to command response buffer
9314 - *
9315 - * Returns MC_CMD_STATUS_OK on Success; Error code otherwise.
9316 - */
9317 -static inline enum mc_cmd_status mc_read_response(struct mc_command __iomem *
9318 - portal,
9319 - struct mc_command *resp)
9320 -{
9321 - int i;
9322 - enum mc_cmd_status status;
9323 -
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)
9328 - return status;
9329 -
9330 - /* Copy command response data from MC portal: */
9331 - for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
9332 - /*
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.
9336 - */
9337 - resp->params[i] =
9338 - cpu_to_le64(readq_relaxed(&portal->params[i]));
9339 -
9340 - return status;
9341 -}
9342 -
9343 -/**
9344 - * Waits for the completion of an MC command doing preemptible polling.
9345 - * uslepp_range() is called between polling iterations.
9346 - *
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
9350 - */
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)
9354 -{
9355 - enum mc_cmd_status status;
9356 - unsigned long jiffies_until_timeout =
9357 - jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS);
9358 -
9359 - /*
9360 - * Wait for response from the MC hardware:
9361 - */
9362 - for (;;) {
9363 - status = mc_read_response(mc_io->portal_virt_addr, cmd);
9364 - if (status != MC_CMD_STATUS_READY)
9365 - break;
9366 -
9367 - /*
9368 - * TODO: When MC command completion interrupts are supported
9369 - * call wait function here instead of usleep_range()
9370 - */
9371 - usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS,
9372 - MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
9373 -
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));
9380 -
9381 - return -ETIMEDOUT;
9382 - }
9383 - }
9384 -
9385 - *mc_status = status;
9386 - return 0;
9387 -}
9388 -
9389 -/**
9390 - * Waits for the completion of an MC command doing atomic polling.
9391 - * udelay() is called between polling iterations.
9392 - *
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
9396 - */
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)
9400 -{
9401 - enum mc_cmd_status status;
9402 - unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000;
9403 -
9404 - BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) %
9405 - MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0);
9406 -
9407 - for (;;) {
9408 - status = mc_read_response(mc_io->portal_virt_addr, cmd);
9409 - if (status != MC_CMD_STATUS_READY)
9410 - break;
9411 -
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));
9420 -
9421 - return -ETIMEDOUT;
9422 - }
9423 - }
9424 -
9425 - *mc_status = status;
9426 - return 0;
9427 -}
9428 -
9429 -/**
9430 - * Sends a command to the MC device using the given MC I/O object
9431 - *
9432 - * @mc_io: MC I/O object to be used
9433 - * @cmd: command to be sent
9434 - *
9435 - * Returns '0' on Success; Error code otherwise.
9436 - */
9437 -int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd)
9438 -{
9439 - int error;
9440 - enum mc_cmd_status status;
9441 - unsigned long irq_flags = 0;
9442 -
9443 - if (WARN_ON(in_irq() &&
9444 - !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)))
9445 - return -EINVAL;
9446 -
9447 - if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
9448 - spin_lock_irqsave(&mc_io->spinlock, irq_flags);
9449 - else
9450 - mutex_lock(&mc_io->mutex);
9451 -
9452 - /*
9453 - * Send command to the MC hardware:
9454 - */
9455 - mc_write_command(mc_io->portal_virt_addr, cmd);
9456 -
9457 - /*
9458 - * Wait for response from the MC hardware:
9459 - */
9460 - if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
9461 - error = mc_polling_wait_preemptible(mc_io, cmd, &status);
9462 - else
9463 - error = mc_polling_wait_atomic(mc_io, cmd, &status);
9464 -
9465 - if (error < 0)
9466 - goto common_exit;
9467 -
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);
9476 -
9477 - error = mc_status_to_error(status);
9478 - goto common_exit;
9479 - }
9480 -
9481 - error = 0;
9482 -common_exit:
9483 - if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
9484 - spin_unlock_irqrestore(&mc_io->spinlock, irq_flags);
9485 - else
9486 - mutex_unlock(&mc_io->mutex);
9487 -
9488 - return error;
9489 -}
9490 -EXPORT_SYMBOL(mc_send_command);
9491 --- /dev/null
9492 +++ b/drivers/bus/fsl-mc/mc-sys.c
9493 @@ -0,0 +1,296 @@
9494 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
9495 +/*
9496 + * Copyright 2013-2016 Freescale Semiconductor Inc.
9497 + *
9498 + * I/O services to send MC commands to the MC hardware
9499 + *
9500 + */
9501 +
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>
9509 +
9510 +#include "fsl-mc-private.h"
9511 +
9512 +/**
9513 + * Timeout in milliseconds to wait for the completion of an MC command
9514 + */
9515 +#define MC_CMD_COMPLETION_TIMEOUT_MS 15000
9516 +
9517 +/*
9518 + * usleep_range() min and max values used to throttle down polling
9519 + * iterations while waiting for MC command completion
9520 + */
9521 +#define MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS 10
9522 +#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500
9523 +
9524 +static enum mc_cmd_status mc_cmd_hdr_read_status(struct fsl_mc_command *cmd)
9525 +{
9526 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
9527 +
9528 + return (enum mc_cmd_status)hdr->status;
9529 +}
9530 +
9531 +static u16 mc_cmd_hdr_read_cmdid(struct fsl_mc_command *cmd)
9532 +{
9533 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
9534 + u16 cmd_id = le16_to_cpu(hdr->cmd_id);
9535 +
9536 + return cmd_id;
9537 +}
9538 +
9539 +static int mc_status_to_error(enum mc_cmd_status status)
9540 +{
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,
9553 + };
9554 +
9555 + if ((u32)status >= ARRAY_SIZE(mc_status_to_error_map))
9556 + return -EINVAL;
9557 +
9558 + return mc_status_to_error_map[status];
9559 +}
9560 +
9561 +static const char *mc_status_to_string(enum mc_cmd_status status)
9562 +{
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"
9576 + };
9577 +
9578 + if ((unsigned int)status >= ARRAY_SIZE(status_strings))
9579 + return "Unknown MC error";
9580 +
9581 + return status_strings[status];
9582 +}
9583 +
9584 +/**
9585 + * mc_write_command - writes a command to a Management Complex (MC) portal
9586 + *
9587 + * @portal: pointer to an MC portal
9588 + * @cmd: pointer to a filled command
9589 + */
9590 +static inline void mc_write_command(struct fsl_mc_command __iomem *portal,
9591 + struct fsl_mc_command *cmd)
9592 +{
9593 + int i;
9594 +
9595 + /* copy command parameters into the portal */
9596 + for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
9597 + /*
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.
9601 + */
9602 + writeq_relaxed(le64_to_cpu(cmd->params[i]), &portal->params[i]);
9603 +
9604 + /* submit the command by writing the header */
9605 + writeq(le64_to_cpu(cmd->header), &portal->header);
9606 +}
9607 +
9608 +/**
9609 + * mc_read_response - reads the response for the last MC command from a
9610 + * Management Complex (MC) portal
9611 + *
9612 + * @portal: pointer to an MC portal
9613 + * @resp: pointer to command response buffer
9614 + *
9615 + * Returns MC_CMD_STATUS_OK on Success; Error code otherwise.
9616 + */
9617 +static inline enum mc_cmd_status mc_read_response(struct fsl_mc_command __iomem
9618 + *portal,
9619 + struct fsl_mc_command *resp)
9620 +{
9621 + int i;
9622 + enum mc_cmd_status status;
9623 +
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)
9628 + return status;
9629 +
9630 + /* Copy command response data from MC portal: */
9631 + for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++)
9632 + /*
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.
9636 + */
9637 + resp->params[i] =
9638 + cpu_to_le64(readq_relaxed(&portal->params[i]));
9639 +
9640 + return status;
9641 +}
9642 +
9643 +/**
9644 + * Waits for the completion of an MC command doing preemptible polling.
9645 + * uslepp_range() is called between polling iterations.
9646 + *
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
9650 + */
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)
9654 +{
9655 + enum mc_cmd_status status;
9656 + unsigned long jiffies_until_timeout =
9657 + jiffies + msecs_to_jiffies(MC_CMD_COMPLETION_TIMEOUT_MS);
9658 +
9659 + /*
9660 + * Wait for response from the MC hardware:
9661 + */
9662 + for (;;) {
9663 + status = mc_read_response(mc_io->portal_virt_addr, cmd);
9664 + if (status != MC_CMD_STATUS_READY)
9665 + break;
9666 +
9667 + /*
9668 + * TODO: When MC command completion interrupts are supported
9669 + * call wait function here instead of usleep_range()
9670 + */
9671 + usleep_range(MC_CMD_COMPLETION_POLLING_MIN_SLEEP_USECS,
9672 + MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
9673 +
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));
9680 +
9681 + return -ETIMEDOUT;
9682 + }
9683 + }
9684 +
9685 + *mc_status = status;
9686 + return 0;
9687 +}
9688 +
9689 +/**
9690 + * Waits for the completion of an MC command doing atomic polling.
9691 + * udelay() is called between polling iterations.
9692 + *
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
9696 + */
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)
9700 +{
9701 + enum mc_cmd_status status;
9702 + unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000;
9703 +
9704 + BUILD_BUG_ON((MC_CMD_COMPLETION_TIMEOUT_MS * 1000) %
9705 + MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS != 0);
9706 +
9707 + for (;;) {
9708 + status = mc_read_response(mc_io->portal_virt_addr, cmd);
9709 + if (status != MC_CMD_STATUS_READY)
9710 + break;
9711 +
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));
9720 +
9721 + return -ETIMEDOUT;
9722 + }
9723 + }
9724 +
9725 + *mc_status = status;
9726 + return 0;
9727 +}
9728 +
9729 +/**
9730 + * Sends a command to the MC device using the given MC I/O object
9731 + *
9732 + * @mc_io: MC I/O object to be used
9733 + * @cmd: command to be sent
9734 + *
9735 + * Returns '0' on Success; Error code otherwise.
9736 + */
9737 +int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd)
9738 +{
9739 + int error;
9740 + enum mc_cmd_status status;
9741 + unsigned long irq_flags = 0;
9742 +
9743 + if (in_irq() && !(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
9744 + return -EINVAL;
9745 +
9746 + if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
9747 + spin_lock_irqsave(&mc_io->spinlock, irq_flags);
9748 + else
9749 + mutex_lock(&mc_io->mutex);
9750 +
9751 + /*
9752 + * Send command to the MC hardware:
9753 + */
9754 + mc_write_command(mc_io->portal_virt_addr, cmd);
9755 +
9756 + /*
9757 + * Wait for response from the MC hardware:
9758 + */
9759 + if (!(mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL))
9760 + error = mc_polling_wait_preemptible(mc_io, cmd, &status);
9761 + else
9762 + error = mc_polling_wait_atomic(mc_io, cmd, &status);
9763 +
9764 + if (error < 0)
9765 + goto common_exit;
9766 +
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);
9775 +
9776 + error = mc_status_to_error(status);
9777 + goto common_exit;
9778 + }
9779 +
9780 + error = 0;
9781 +common_exit:
9782 + if (mc_io->flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
9783 + spin_unlock_irqrestore(&mc_io->spinlock, irq_flags);
9784 + else
9785 + mutex_unlock(&mc_io->mutex);
9786 +
9787 + return error;
9788 +}
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
9793 depends on PCI
9794 depends on PCI_MSI
9795
9796 +config ARM_GIC_V3_ITS_FSL_MC
9797 + bool
9798 + depends on ARM_GIC_V3_ITS
9799 + depends on FSL_MC_BUS
9800 + default ARM_GIC_V3_ITS
9801 +
9802 config ARM_NVIC
9803 bool
9804 select IRQ_DOMAIN
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
9815 --- /dev/null
9816 +++ b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
9817 @@ -0,0 +1,98 @@
9818 +// SPDX-License-Identifier: GPL-2.0
9819 +/*
9820 + * Freescale Management Complex (MC) bus driver MSI support
9821 + *
9822 + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
9823 + * Author: German Rivera <German.Rivera@freescale.com>
9824 + *
9825 + */
9826 +
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>
9834 +
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
9841 +};
9842 +
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)
9846 +{
9847 + struct fsl_mc_device *mc_bus_dev;
9848 + struct msi_domain_info *msi_info;
9849 +
9850 + if (!dev_is_fsl_mc(dev))
9851 + return -EINVAL;
9852 +
9853 + mc_bus_dev = to_fsl_mc_device(dev);
9854 + if (!(mc_bus_dev->flags & FSL_MC_IS_DPRC))
9855 + return -EINVAL;
9856 +
9857 + /*
9858 + * Set the device Id to be passed to the GIC-ITS:
9859 + *
9860 + * NOTE: This device id corresponds to the IOMMU stream ID
9861 + * associated with the DPRC object (ICID).
9862 + */
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);
9866 +}
9867 +
9868 +static struct msi_domain_ops its_fsl_mc_msi_ops __ro_after_init = {
9869 + .msi_prepare = its_fsl_mc_msi_prepare,
9870 +};
9871 +
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,
9876 +};
9877 +
9878 +static const struct of_device_id its_device_id[] = {
9879 + { .compatible = "arm,gic-v3-its", },
9880 + {},
9881 +};
9882 +
9883 +static int __init its_fsl_mc_msi_init(void)
9884 +{
9885 + struct device_node *np;
9886 + struct irq_domain *parent;
9887 + struct irq_domain *mc_msi_domain;
9888 +
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"))
9892 + continue;
9893 +
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);
9897 + continue;
9898 + }
9899 +
9900 + mc_msi_domain = fsl_mc_msi_create_irq_domain(
9901 + of_node_to_fwnode(np),
9902 + &its_fsl_mc_msi_domain_info,
9903 + parent);
9904 + if (!mc_msi_domain) {
9905 + pr_err("%pOF: unable to create fsl-mc domain\n", np);
9906 + continue;
9907 + }
9908 +
9909 + pr_info("fsl-mc MSI: %pOF domain created\n", np);
9910 + }
9911 +
9912 + return 0;
9913 +}
9914 +
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
9918 @@ -16,7 +16,7 @@
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"
9926
9927 --- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
9928 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
9929 @@ -9,12 +9,11 @@
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>
9935
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"
9940 #include "dpni.h"
9941 #include "dpni-cmd.h"
9942
9943 --- a/drivers/staging/fsl-dpaa2/ethernet/dpni.c
9944 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.c
9945 @@ -4,7 +4,7 @@
9946 */
9947 #include <linux/kernel.h>
9948 #include <linux/errno.h>
9949 -#include "../../fsl-mc/include/mc.h"
9950 +#include <linux/fsl/mc.h>
9951 #include "dpni.h"
9952 #include "dpni-cmd.h"
9953
9954 --- a/drivers/staging/fsl-mc/bus/Kconfig
9955 +++ b/drivers/staging/fsl-mc/bus/Kconfig
9956 @@ -5,15 +5,6 @@
9957 # Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
9958 #
9959
9960 -config FSL_MC_BUS
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
9964 - help
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.
9969
9970 config FSL_MC_DPIO
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
9975 API.
9976 +
9977 +config FSL_QBMAN_DEBUG
9978 + tristate "Freescale QBMAN Debug APIs"
9979 + depends on FSL_MC_DPIO
9980 + help
9981 + QBMan debug assistant APIs.
9982 --- a/drivers/staging/fsl-mc/bus/Makefile
9983 +++ b/drivers/staging/fsl-mc/bus/Makefile
9984 @@ -4,19 +4,6 @@
9985 #
9986 # Copyright (C) 2014 Freescale Semiconductor, Inc.
9987 #
9988 -obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o
9989 -
9990 -mc-bus-driver-objs := fsl-mc-bus.o \
9991 - mc-sys.o \
9992 - mc-io.o \
9993 - dprc.o \
9994 - dprc-driver.o \
9995 - fsl-mc-allocator.o \
9996 - fsl-mc-msi.o \
9997 - irq-gic-v3-its-fsl-mc-msi.o \
9998 - dpmcp.o \
9999 - dpbp.o \
10000 - dpcon.o
10001
10002 # MC DPIO driver
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
10006 @@ -15,7 +15,7 @@
10007 #include <linux/delay.h>
10008 #include <linux/io.h>
10009
10010 -#include "../../include/mc.h"
10011 +#include <linux/fsl/mc.h>
10012 #include "../../include/dpaa2-io.h"
10013
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
10017 @@ -5,7 +5,7 @@
10018 *
10019 */
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
10028 @@ -5,7 +5,7 @@
10029 *
10030 */
10031 #include <linux/kernel.h>
10032 -#include "../../include/mc.h"
10033 +#include <linux/fsl/mc.h>
10034
10035 #include "dpio.h"
10036 #include "dpio-cmd.h"
10037 @@ -37,7 +37,7 @@ int dpio_open(struct fsl_mc_io *mc_io,
10038 int dpio_id,
10039 u16 *token)
10040 {
10041 - struct mc_command cmd = { 0 };
10042 + struct fsl_mc_command cmd = { 0 };
10043 struct dpio_cmd_open *dpio_cmd;
10044 int err;
10045
10046 @@ -70,7 +70,7 @@ int dpio_close(struct fsl_mc_io *mc_io,
10047 u32 cmd_flags,
10048 u16 token)
10049 {
10050 - struct mc_command cmd = { 0 };
10051 + struct fsl_mc_command cmd = { 0 };
10052
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,
10056 u32 cmd_flags,
10057 u16 token)
10058 {
10059 - struct mc_command cmd = { 0 };
10060 + struct fsl_mc_command cmd = { 0 };
10061
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
10065 u32 cmd_flags,
10066 u16 token)
10067 {
10068 - struct mc_command cmd = { 0 };
10069 + struct fsl_mc_command cmd = { 0 };
10070
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
10074 u16 token,
10075 struct dpio_attr *attr)
10076 {
10077 - struct mc_command cmd = { 0 };
10078 + struct fsl_mc_command cmd = { 0 };
10079 struct dpio_rsp_get_attr *dpio_rsp;
10080 int err;
10081
10082 @@ -180,7 +180,7 @@ int dpio_get_api_version(struct fsl_mc_i
10083 u16 *major_ver,
10084 u16 *minor_ver)
10085 {
10086 - struct mc_command cmd = { 0 };
10087 + struct fsl_mc_command cmd = { 0 };
10088 int err;
10089
10090 /* prepare command */
10091 --- a/drivers/staging/fsl-mc/bus/dpmcp-cmd.h
10092 +++ /dev/null
10093 @@ -1,56 +0,0 @@
10094 -/*
10095 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10096 - *
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.
10107 - *
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
10111 - * later version.
10112 - *
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.
10124 - */
10125 -#ifndef _FSL_DPMCP_CMD_H
10126 -#define _FSL_DPMCP_CMD_H
10127 -
10128 -/* Minimal supported DPMCP Version */
10129 -#define DPMCP_MIN_VER_MAJOR 3
10130 -#define DPMCP_MIN_VER_MINOR 0
10131 -
10132 -/* Command versioning */
10133 -#define DPMCP_CMD_BASE_VERSION 1
10134 -#define DPMCP_CMD_ID_OFFSET 4
10135 -
10136 -#define DPMCP_CMD(id) (((id) << DPMCP_CMD_ID_OFFSET) | DPMCP_CMD_BASE_VERSION)
10137 -
10138 -/* Command IDs */
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)
10142 -
10143 -#define DPMCP_CMDID_RESET DPMCP_CMD(0x005)
10144 -
10145 -struct dpmcp_cmd_open {
10146 - __le32 dpmcp_id;
10147 -};
10148 -
10149 -#endif /* _FSL_DPMCP_CMD_H */
10150 --- a/drivers/staging/fsl-mc/bus/dpmcp.h
10151 +++ /dev/null
10152 @@ -1,60 +0,0 @@
10153 -/*
10154 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10155 - *
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.
10166 - *
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
10170 - * later version.
10171 - *
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.
10183 - */
10184 -#ifndef __FSL_DPMCP_H
10185 -#define __FSL_DPMCP_H
10186 -
10187 -/*
10188 - * Data Path Management Command Portal API
10189 - * Contains initialization APIs and runtime control APIs for DPMCP
10190 - */
10191 -
10192 -struct fsl_mc_io;
10193 -
10194 -int dpmcp_open(struct fsl_mc_io *mc_io,
10195 - u32 cmd_flags,
10196 - int dpmcp_id,
10197 - u16 *token);
10198 -
10199 -int dpmcp_close(struct fsl_mc_io *mc_io,
10200 - u32 cmd_flags,
10201 - u16 token);
10202 -
10203 -int dpmcp_get_api_version(struct fsl_mc_io *mc_io,
10204 - u32 cmd_flags,
10205 - u16 *major_ver,
10206 - u16 *minor_ver);
10207 -
10208 -int dpmcp_reset(struct fsl_mc_io *mc_io,
10209 - u32 cmd_flags,
10210 - u16 token);
10211 -
10212 -#endif /* __FSL_DPMCP_H */
10213 --- a/drivers/staging/fsl-mc/bus/dpmng-cmd.h
10214 +++ /dev/null
10215 @@ -1,58 +0,0 @@
10216 -/*
10217 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10218 - *
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.
10229 - *
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
10233 - * later version.
10234 - *
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.
10246 - */
10247 -
10248 -/*
10249 - * dpmng-cmd.h
10250 - *
10251 - * defines portal commands
10252 - *
10253 - */
10254 -
10255 -#ifndef __FSL_DPMNG_CMD_H
10256 -#define __FSL_DPMNG_CMD_H
10257 -
10258 -/* Command versioning */
10259 -#define DPMNG_CMD_BASE_VERSION 1
10260 -#define DPMNG_CMD_ID_OFFSET 4
10261 -
10262 -#define DPMNG_CMD(id) (((id) << DPMNG_CMD_ID_OFFSET) | DPMNG_CMD_BASE_VERSION)
10263 -
10264 -/* Command IDs */
10265 -#define DPMNG_CMDID_GET_VERSION DPMNG_CMD(0x831)
10266 -
10267 -struct dpmng_rsp_get_version {
10268 - __le32 revision;
10269 - __le32 version_major;
10270 - __le32 version_minor;
10271 -};
10272 -
10273 -#endif /* __FSL_DPMNG_CMD_H */
10274 --- a/drivers/staging/fsl-mc/bus/dprc-cmd.h
10275 +++ /dev/null
10276 @@ -1,451 +0,0 @@
10277 -/*
10278 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10279 - *
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.
10290 - *
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
10294 - * later version.
10295 - *
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.
10307 - */
10308 -
10309 -/*
10310 - * dprc-cmd.h
10311 - *
10312 - * defines dprc portal commands
10313 - *
10314 - */
10315 -
10316 -#ifndef _FSL_DPRC_CMD_H
10317 -#define _FSL_DPRC_CMD_H
10318 -
10319 -/* Minimal supported DPRC Version */
10320 -#define DPRC_MIN_VER_MAJOR 6
10321 -#define DPRC_MIN_VER_MINOR 0
10322 -
10323 -/* Command versioning */
10324 -#define DPRC_CMD_BASE_VERSION 1
10325 -#define DPRC_CMD_ID_OFFSET 4
10326 -
10327 -#define DPRC_CMD(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION)
10328 -
10329 -/* Command IDs */
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)
10333 -
10334 -#define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004)
10335 -
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)
10344 -
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)
10352 -
10353 -struct dprc_cmd_open {
10354 - __le32 container_id;
10355 -};
10356 -
10357 -struct dprc_cmd_create_container {
10358 - /* cmd word 0 */
10359 - __le32 options;
10360 - __le16 icid;
10361 - __le16 pad0;
10362 - /* cmd word 1 */
10363 - __le32 pad1;
10364 - __le32 portal_id;
10365 - /* cmd words 2-3 */
10366 - u8 label[16];
10367 -};
10368 -
10369 -struct dprc_rsp_create_container {
10370 - /* response word 0 */
10371 - __le64 pad0;
10372 - /* response word 1 */
10373 - __le32 child_container_id;
10374 - __le32 pad1;
10375 - /* response word 2 */
10376 - __le64 child_portal_addr;
10377 -};
10378 -
10379 -struct dprc_cmd_destroy_container {
10380 - __le32 child_container_id;
10381 -};
10382 -
10383 -struct dprc_cmd_reset_container {
10384 - __le32 child_container_id;
10385 -};
10386 -
10387 -struct dprc_cmd_set_irq {
10388 - /* cmd word 0 */
10389 - __le32 irq_val;
10390 - u8 irq_index;
10391 - u8 pad[3];
10392 - /* cmd word 1 */
10393 - __le64 irq_addr;
10394 - /* cmd word 2 */
10395 - __le32 irq_num;
10396 -};
10397 -
10398 -struct dprc_cmd_get_irq {
10399 - __le32 pad;
10400 - u8 irq_index;
10401 -};
10402 -
10403 -struct dprc_rsp_get_irq {
10404 - /* response word 0 */
10405 - __le32 irq_val;
10406 - __le32 pad;
10407 - /* response word 1 */
10408 - __le64 irq_addr;
10409 - /* response word 2 */
10410 - __le32 irq_num;
10411 - __le32 type;
10412 -};
10413 -
10414 -#define DPRC_ENABLE 0x1
10415 -
10416 -struct dprc_cmd_set_irq_enable {
10417 - u8 enable;
10418 - u8 pad[3];
10419 - u8 irq_index;
10420 -};
10421 -
10422 -struct dprc_cmd_get_irq_enable {
10423 - __le32 pad;
10424 - u8 irq_index;
10425 -};
10426 -
10427 -struct dprc_rsp_get_irq_enable {
10428 - u8 enabled;
10429 -};
10430 -
10431 -struct dprc_cmd_set_irq_mask {
10432 - __le32 mask;
10433 - u8 irq_index;
10434 -};
10435 -
10436 -struct dprc_cmd_get_irq_mask {
10437 - __le32 pad;
10438 - u8 irq_index;
10439 -};
10440 -
10441 -struct dprc_rsp_get_irq_mask {
10442 - __le32 mask;
10443 -};
10444 -
10445 -struct dprc_cmd_get_irq_status {
10446 - __le32 status;
10447 - u8 irq_index;
10448 -};
10449 -
10450 -struct dprc_rsp_get_irq_status {
10451 - __le32 status;
10452 -};
10453 -
10454 -struct dprc_cmd_clear_irq_status {
10455 - __le32 status;
10456 - u8 irq_index;
10457 -};
10458 -
10459 -struct dprc_rsp_get_attributes {
10460 - /* response word 0 */
10461 - __le32 container_id;
10462 - __le16 icid;
10463 - __le16 pad;
10464 - /* response word 1 */
10465 - __le32 options;
10466 - __le32 portal_id;
10467 -};
10468 -
10469 -struct dprc_cmd_set_res_quota {
10470 - /* cmd word 0 */
10471 - __le32 child_container_id;
10472 - __le16 quota;
10473 - __le16 pad;
10474 - /* cmd words 1-2 */
10475 - u8 type[16];
10476 -};
10477 -
10478 -struct dprc_cmd_get_res_quota {
10479 - /* cmd word 0 */
10480 - __le32 child_container_id;
10481 - __le32 pad;
10482 - /* cmd word 1-2 */
10483 - u8 type[16];
10484 -};
10485 -
10486 -struct dprc_rsp_get_res_quota {
10487 - __le32 pad;
10488 - __le16 quota;
10489 -};
10490 -
10491 -struct dprc_cmd_assign {
10492 - /* cmd word 0 */
10493 - __le32 container_id;
10494 - __le32 options;
10495 - /* cmd word 1 */
10496 - __le32 num;
10497 - __le32 id_base_align;
10498 - /* cmd word 2-3 */
10499 - u8 type[16];
10500 -};
10501 -
10502 -struct dprc_cmd_unassign {
10503 - /* cmd word 0 */
10504 - __le32 child_container_id;
10505 - __le32 options;
10506 - /* cmd word 1 */
10507 - __le32 num;
10508 - __le32 id_base_align;
10509 - /* cmd word 2-3 */
10510 - u8 type[16];
10511 -};
10512 -
10513 -struct dprc_rsp_get_pool_count {
10514 - __le32 pool_count;
10515 -};
10516 -
10517 -struct dprc_cmd_get_pool {
10518 - __le32 pool_index;
10519 -};
10520 -
10521 -struct dprc_rsp_get_pool {
10522 - /* response word 0 */
10523 - __le64 pad;
10524 - /* response word 1-2 */
10525 - u8 type[16];
10526 -};
10527 -
10528 -struct dprc_rsp_get_obj_count {
10529 - __le32 pad;
10530 - __le32 obj_count;
10531 -};
10532 -
10533 -struct dprc_cmd_get_obj {
10534 - __le32 obj_index;
10535 -};
10536 -
10537 -struct dprc_rsp_get_obj {
10538 - /* response word 0 */
10539 - __le32 pad0;
10540 - __le32 id;
10541 - /* response word 1 */
10542 - __le16 vendor;
10543 - u8 irq_count;
10544 - u8 region_count;
10545 - __le32 state;
10546 - /* response word 2 */
10547 - __le16 version_major;
10548 - __le16 version_minor;
10549 - __le16 flags;
10550 - __le16 pad1;
10551 - /* response word 3-4 */
10552 - u8 type[16];
10553 - /* response word 5-6 */
10554 - u8 label[16];
10555 -};
10556 -
10557 -struct dprc_cmd_get_obj_desc {
10558 - /* cmd word 0 */
10559 - __le32 obj_id;
10560 - __le32 pad;
10561 - /* cmd word 1-2 */
10562 - u8 type[16];
10563 -};
10564 -
10565 -struct dprc_rsp_get_obj_desc {
10566 - /* response word 0 */
10567 - __le32 pad0;
10568 - __le32 id;
10569 - /* response word 1 */
10570 - __le16 vendor;
10571 - u8 irq_count;
10572 - u8 region_count;
10573 - __le32 state;
10574 - /* response word 2 */
10575 - __le16 version_major;
10576 - __le16 version_minor;
10577 - __le16 flags;
10578 - __le16 pad1;
10579 - /* response word 3-4 */
10580 - u8 type[16];
10581 - /* response word 5-6 */
10582 - u8 label[16];
10583 -};
10584 -
10585 -struct dprc_cmd_get_res_count {
10586 - /* cmd word 0 */
10587 - __le64 pad;
10588 - /* cmd word 1-2 */
10589 - u8 type[16];
10590 -};
10591 -
10592 -struct dprc_rsp_get_res_count {
10593 - __le32 res_count;
10594 -};
10595 -
10596 -struct dprc_cmd_get_res_ids {
10597 - /* cmd word 0 */
10598 - u8 pad0[5];
10599 - u8 iter_status;
10600 - __le16 pad1;
10601 - /* cmd word 1 */
10602 - __le32 base_id;
10603 - __le32 last_id;
10604 - /* cmd word 2-3 */
10605 - u8 type[16];
10606 -};
10607 -
10608 -struct dprc_rsp_get_res_ids {
10609 - /* response word 0 */
10610 - u8 pad0[5];
10611 - u8 iter_status;
10612 - __le16 pad1;
10613 - /* response word 1 */
10614 - __le32 base_id;
10615 - __le32 last_id;
10616 -};
10617 -
10618 -struct dprc_cmd_get_obj_region {
10619 - /* cmd word 0 */
10620 - __le32 obj_id;
10621 - __le16 pad0;
10622 - u8 region_index;
10623 - u8 pad1;
10624 - /* cmd word 1-2 */
10625 - __le64 pad2[2];
10626 - /* cmd word 3-4 */
10627 - u8 obj_type[16];
10628 -};
10629 -
10630 -struct dprc_rsp_get_obj_region {
10631 - /* response word 0 */
10632 - __le64 pad;
10633 - /* response word 1 */
10634 - __le64 base_addr;
10635 - /* response word 2 */
10636 - __le32 size;
10637 -};
10638 -
10639 -struct dprc_cmd_set_obj_label {
10640 - /* cmd word 0 */
10641 - __le32 obj_id;
10642 - __le32 pad;
10643 - /* cmd word 1-2 */
10644 - u8 label[16];
10645 - /* cmd word 3-4 */
10646 - u8 obj_type[16];
10647 -};
10648 -
10649 -struct dprc_cmd_set_obj_irq {
10650 - /* cmd word 0 */
10651 - __le32 irq_val;
10652 - u8 irq_index;
10653 - u8 pad[3];
10654 - /* cmd word 1 */
10655 - __le64 irq_addr;
10656 - /* cmd word 2 */
10657 - __le32 irq_num;
10658 - __le32 obj_id;
10659 - /* cmd word 3-4 */
10660 - u8 obj_type[16];
10661 -};
10662 -
10663 -struct dprc_cmd_get_obj_irq {
10664 - /* cmd word 0 */
10665 - __le32 obj_id;
10666 - u8 irq_index;
10667 - u8 pad[3];
10668 - /* cmd word 1-2 */
10669 - u8 obj_type[16];
10670 -};
10671 -
10672 -struct dprc_rsp_get_obj_irq {
10673 - /* response word 0 */
10674 - __le32 irq_val;
10675 - __le32 pad;
10676 - /* response word 1 */
10677 - __le64 irq_addr;
10678 - /* response word 2 */
10679 - __le32 irq_num;
10680 - __le32 type;
10681 -};
10682 -
10683 -struct dprc_cmd_connect {
10684 - /* cmd word 0 */
10685 - __le32 ep1_id;
10686 - __le32 ep1_interface_id;
10687 - /* cmd word 1 */
10688 - __le32 ep2_id;
10689 - __le32 ep2_interface_id;
10690 - /* cmd word 2-3 */
10691 - u8 ep1_type[16];
10692 - /* cmd word 4 */
10693 - __le32 max_rate;
10694 - __le32 committed_rate;
10695 - /* cmd word 5-6 */
10696 - u8 ep2_type[16];
10697 -};
10698 -
10699 -struct dprc_cmd_disconnect {
10700 - /* cmd word 0 */
10701 - __le32 id;
10702 - __le32 interface_id;
10703 - /* cmd word 1-2 */
10704 - u8 type[16];
10705 -};
10706 -
10707 -struct dprc_cmd_get_connection {
10708 - /* cmd word 0 */
10709 - __le32 ep1_id;
10710 - __le32 ep1_interface_id;
10711 - /* cmd word 1-2 */
10712 - u8 ep1_type[16];
10713 -};
10714 -
10715 -struct dprc_rsp_get_connection {
10716 - /* response word 0-2 */
10717 - __le64 pad[3];
10718 - /* response word 3 */
10719 - __le32 ep2_id;
10720 - __le32 ep2_interface_id;
10721 - /* response word 4-5 */
10722 - u8 ep2_type[16];
10723 - /* response word 6 */
10724 - __le32 state;
10725 -};
10726 -
10727 -#endif /* _FSL_DPRC_CMD_H */
10728 --- a/drivers/staging/fsl-mc/bus/dprc.h
10729 +++ /dev/null
10730 @@ -1,268 +0,0 @@
10731 -/*
10732 - * Copyright 2013-2016 Freescale Semiconductor Inc.
10733 - *
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.
10744 - *
10745 - *
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
10749 - * later version.
10750 - *
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.
10762 - */
10763 -#ifndef _FSL_DPRC_H
10764 -#define _FSL_DPRC_H
10765 -
10766 -/*
10767 - * Data Path Resource Container API
10768 - * Contains DPRC API for managing and querying DPAA resources
10769 - */
10770 -
10771 -struct fsl_mc_io;
10772 -struct fsl_mc_obj_desc;
10773 -
10774 -int dprc_open(struct fsl_mc_io *mc_io,
10775 - u32 cmd_flags,
10776 - int container_id,
10777 - u16 *token);
10778 -
10779 -int dprc_close(struct fsl_mc_io *mc_io,
10780 - u32 cmd_flags,
10781 - u16 token);
10782 -
10783 -/* IRQ */
10784 -
10785 -/* IRQ index */
10786 -#define DPRC_IRQ_INDEX 0
10787 -
10788 -/* Number of dprc's IRQs */
10789 -#define DPRC_NUM_OF_IRQS 1
10790 -
10791 -/* DPRC IRQ events */
10792 -
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
10801 -/*
10802 - * IRQ event - Indicates that one of the descendant containers that opened by
10803 - * this container is destroyed
10804 - */
10805 -#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010
10806 -
10807 -/*
10808 - * IRQ event - Indicates that on one of the container's opened object is
10809 - * destroyed
10810 - */
10811 -#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020
10812 -
10813 -/* Irq event - Indicates that object is created at the container */
10814 -#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040
10815 -
10816 -/**
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
10821 - */
10822 -struct dprc_irq_cfg {
10823 - phys_addr_t paddr;
10824 - u32 val;
10825 - int irq_num;
10826 -};
10827 -
10828 -int dprc_set_irq(struct fsl_mc_io *mc_io,
10829 - u32 cmd_flags,
10830 - u16 token,
10831 - u8 irq_index,
10832 - struct dprc_irq_cfg *irq_cfg);
10833 -
10834 -int dprc_get_irq(struct fsl_mc_io *mc_io,
10835 - u32 cmd_flags,
10836 - u16 token,
10837 - u8 irq_index,
10838 - int *type,
10839 - struct dprc_irq_cfg *irq_cfg);
10840 -
10841 -int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
10842 - u32 cmd_flags,
10843 - u16 token,
10844 - u8 irq_index,
10845 - u8 en);
10846 -
10847 -int dprc_get_irq_enable(struct fsl_mc_io *mc_io,
10848 - u32 cmd_flags,
10849 - u16 token,
10850 - u8 irq_index,
10851 - u8 *en);
10852 -
10853 -int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
10854 - u32 cmd_flags,
10855 - u16 token,
10856 - u8 irq_index,
10857 - u32 mask);
10858 -
10859 -int dprc_get_irq_mask(struct fsl_mc_io *mc_io,
10860 - u32 cmd_flags,
10861 - u16 token,
10862 - u8 irq_index,
10863 - u32 *mask);
10864 -
10865 -int dprc_get_irq_status(struct fsl_mc_io *mc_io,
10866 - u32 cmd_flags,
10867 - u16 token,
10868 - u8 irq_index,
10869 - u32 *status);
10870 -
10871 -int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
10872 - u32 cmd_flags,
10873 - u16 token,
10874 - u8 irq_index,
10875 - u32 status);
10876 -
10877 -/**
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
10883 - */
10884 -struct dprc_attributes {
10885 - int container_id;
10886 - u16 icid;
10887 - int portal_id;
10888 - u64 options;
10889 -};
10890 -
10891 -int dprc_get_attributes(struct fsl_mc_io *mc_io,
10892 - u32 cmd_flags,
10893 - u16 token,
10894 - struct dprc_attributes *attributes);
10895 -
10896 -int dprc_get_obj_count(struct fsl_mc_io *mc_io,
10897 - u32 cmd_flags,
10898 - u16 token,
10899 - int *obj_count);
10900 -
10901 -int dprc_get_obj(struct fsl_mc_io *mc_io,
10902 - u32 cmd_flags,
10903 - u16 token,
10904 - int obj_index,
10905 - struct fsl_mc_obj_desc *obj_desc);
10906 -
10907 -int dprc_get_obj_desc(struct fsl_mc_io *mc_io,
10908 - u32 cmd_flags,
10909 - u16 token,
10910 - char *obj_type,
10911 - int obj_id,
10912 - struct fsl_mc_obj_desc *obj_desc);
10913 -
10914 -int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
10915 - u32 cmd_flags,
10916 - u16 token,
10917 - char *obj_type,
10918 - int obj_id,
10919 - u8 irq_index,
10920 - struct dprc_irq_cfg *irq_cfg);
10921 -
10922 -int dprc_get_obj_irq(struct fsl_mc_io *mc_io,
10923 - u32 cmd_flags,
10924 - u16 token,
10925 - char *obj_type,
10926 - int obj_id,
10927 - u8 irq_index,
10928 - int *type,
10929 - struct dprc_irq_cfg *irq_cfg);
10930 -
10931 -int dprc_get_res_count(struct fsl_mc_io *mc_io,
10932 - u32 cmd_flags,
10933 - u16 token,
10934 - char *type,
10935 - int *res_count);
10936 -
10937 -/**
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
10942 - */
10943 -enum dprc_iter_status {
10944 - DPRC_ITER_STATUS_FIRST = 0,
10945 - DPRC_ITER_STATUS_MORE = 1,
10946 - DPRC_ITER_STATUS_LAST = 2
10947 -};
10948 -
10949 -/* Region flags */
10950 -/* Cacheable - Indicates that region should be mapped as cacheable */
10951 -#define DPRC_REGION_CACHEABLE 0x00000001
10952 -
10953 -/**
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
10957 - */
10958 -enum dprc_region_type {
10959 - DPRC_REGION_TYPE_MC_PORTAL,
10960 - DPRC_REGION_TYPE_QBMAN_PORTAL
10961 -};
10962 -
10963 -/**
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
10968 - * base address
10969 - * @size: Region size (in bytes)
10970 - * @flags: Region attributes
10971 - * @type: Portal region type
10972 - */
10973 -struct dprc_region_desc {
10974 - u32 base_offset;
10975 - u32 size;
10976 - u32 flags;
10977 - enum dprc_region_type type;
10978 -};
10979 -
10980 -int dprc_get_obj_region(struct fsl_mc_io *mc_io,
10981 - u32 cmd_flags,
10982 - u16 token,
10983 - char *obj_type,
10984 - int obj_id,
10985 - u8 region_index,
10986 - struct dprc_region_desc *region_desc);
10987 -
10988 -int dprc_get_api_version(struct fsl_mc_io *mc_io,
10989 - u32 cmd_flags,
10990 - u16 *major_ver,
10991 - u16 *minor_ver);
10992 -
10993 -int dprc_get_container_id(struct fsl_mc_io *mc_io,
10994 - u32 cmd_flags,
10995 - int *container_id);
10996 -
10997 -#endif /* _FSL_DPRC_H */
10998 -
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
11001 @@ -13,6 +13,7 @@
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"
11007
11008 static struct irq_chip its_msi_irq_chip = {
11009 --- /dev/null
11010 +++ b/include/linux/fsl/mc.h
11011 @@ -0,0 +1,1029 @@
11012 +/* SPDX-License-Identifier: GPL-2.0 */
11013 +/*
11014 + * Freescale Management Complex (MC) bus public interface
11015 + *
11016 + * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
11017 + * Author: German Rivera <German.Rivera@freescale.com>
11018 + *
11019 + */
11020 +#ifndef _FSL_MC_H_
11021 +#define _FSL_MC_H_
11022 +
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>
11028 +
11029 +#define FSL_MC_VENDOR_FREESCALE 0x1957
11030 +
11031 +struct irq_domain;
11032 +struct msi_domain_info;
11033 +
11034 +struct fsl_mc_device;
11035 +struct fsl_mc_io;
11036 +
11037 +/**
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
11046 + *
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.
11050 + */
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);
11059 +};
11060 +
11061 +#define to_fsl_mc_driver(_drv) \
11062 + container_of(_drv, struct fsl_mc_driver, driver)
11063 +
11064 +#define to_fsl_mc_bus(_mc_dev) \
11065 + container_of(_mc_dev, struct fsl_mc_bus, mc_dev)
11066 +
11067 +/**
11068 + * enum fsl_mc_pool_type - Types of allocatable MC bus resources
11069 + *
11070 + * Entries in these enum are used as indices in the array of resource
11071 + * pools of an fsl_mc_bus object.
11072 + */
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 */
11077 + FSL_MC_POOL_IRQ,
11078 +
11079 + /*
11080 + * NOTE: New resource pool types must be added before this entry
11081 + */
11082 + FSL_MC_NUM_POOL_TYPES
11083 +};
11084 +
11085 +/**
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
11094 + *
11095 + * NOTE: This structure is to be embedded as a field of specific
11096 + * MC resource structures.
11097 + */
11098 +struct fsl_mc_resource {
11099 + enum fsl_mc_pool_type type;
11100 + s32 id;
11101 + void *data;
11102 + struct fsl_mc_resource_pool *parent_pool;
11103 + struct list_head node;
11104 +};
11105 +
11106 +/**
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
11112 + */
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;
11118 +};
11119 +
11120 +#define to_fsl_mc_irq(_mc_resource) \
11121 + container_of(_mc_resource, struct fsl_mc_device_irq, resource)
11122 +
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
11127 +
11128 +/**
11129 + * Shareability flag - Object flag indicating no memory shareability.
11130 + * the object generates memory accesses that are non coherent with other
11131 + * masters;
11132 + * user is responsible for proper memory handling through IOMMU configuration.
11133 + */
11134 +#define FSL_MC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001
11135 +
11136 +/**
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
11148 + */
11149 +struct fsl_mc_obj_desc {
11150 + char type[16];
11151 + int id;
11152 + u16 vendor;
11153 + u16 ver_major;
11154 + u16 ver_minor;
11155 + u8 irq_count;
11156 + u8 region_count;
11157 + u32 state;
11158 + char label[16];
11159 + u16 flags;
11160 +};
11161 +
11162 +/**
11163 + * Bit masks for a MC object device (struct fsl_mc_device) flags
11164 + */
11165 +#define FSL_MC_IS_DPRC 0x0001
11166 +
11167 +/**
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
11175 + * NULL if none.
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
11181 + *
11182 + * Generic device object for MC object devices that are "attached" to a
11183 + * MC bus.
11184 + *
11185 + * NOTES:
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.
11201 + */
11202 +struct fsl_mc_device {
11203 + struct device dev;
11204 + u64 dma_mask;
11205 + u16 flags;
11206 + u32 icid;
11207 + u16 mc_handle;
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;
11215 +};
11216 +
11217 +#define to_fsl_mc_device(_dev) \
11218 + container_of(_dev, struct fsl_mc_device, dev)
11219 +
11220 +struct mc_cmd_header {
11221 + u8 src_id;
11222 + u8 flags_hw;
11223 + u8 status;
11224 + u8 flags_sw;
11225 + __le16 token;
11226 + __le16 cmd_id;
11227 +};
11228 +
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 */
11242 +};
11243 +
11244 +/*
11245 + * MC command flags
11246 + */
11247 +
11248 +/* High priority flag */
11249 +#define MC_CMD_FLAG_PRI 0x80
11250 +/* Command completion flag */
11251 +#define MC_CMD_FLAG_INTR_DIS 0x01
11252 +
11253 +static inline u64 mc_encode_cmd_header(u16 cmd_id,
11254 + u32 cmd_flags,
11255 + u16 token)
11256 +{
11257 + u64 header = 0;
11258 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&header;
11259 +
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;
11267 +
11268 + return header;
11269 +}
11270 +
11271 +static inline u16 mc_cmd_hdr_read_token(struct fsl_mc_command *cmd)
11272 +{
11273 + struct mc_cmd_header *hdr = (struct mc_cmd_header *)&cmd->header;
11274 + u16 token = le16_to_cpu(hdr->token);
11275 +
11276 + return token;
11277 +}
11278 +
11279 +struct mc_rsp_create {
11280 + __le32 object_id;
11281 +};
11282 +
11283 +struct mc_rsp_api_ver {
11284 + __le16 major_ver;
11285 + __le16 minor_ver;
11286 +};
11287 +
11288 +static inline u32 mc_cmd_read_object_id(struct fsl_mc_command *cmd)
11289 +{
11290 + struct mc_rsp_create *rsp_params;
11291 +
11292 + rsp_params = (struct mc_rsp_create *)cmd->params;
11293 + return le32_to_cpu(rsp_params->object_id);
11294 +}
11295 +
11296 +static inline void mc_cmd_read_api_version(struct fsl_mc_command *cmd,
11297 + u16 *major_ver,
11298 + u16 *minor_ver)
11299 +{
11300 + struct mc_rsp_api_ver *rsp_params;
11301 +
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);
11305 +}
11306 +
11307 +/**
11308 + * Bit masks for a MC I/O object (struct fsl_mc_io) flags
11309 + */
11310 +#define FSL_MC_IO_ATOMIC_CONTEXT_PORTAL 0x0001
11311 +
11312 +/**
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.
11320 + *
11321 + * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not
11322 + * set:
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.
11327 + *
11328 + * Fields are only meaningful if the FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is
11329 + * set:
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.
11334 + */
11335 +struct fsl_mc_io {
11336 + struct device *dev;
11337 + u16 flags;
11338 + u32 portal_size;
11339 + phys_addr_t portal_phys_addr;
11340 + void __iomem *portal_virt_addr;
11341 + struct fsl_mc_device *dpmcp_dev;
11342 + union {
11343 + /*
11344 + * This field is only meaningful if the
11345 + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is not set
11346 + */
11347 + struct mutex mutex; /* serializes mc_send_command() */
11348 +
11349 + /*
11350 + * This field is only meaningful if the
11351 + * FSL_MC_IO_ATOMIC_CONTEXT_PORTAL flag is set
11352 + */
11353 + spinlock_t spinlock; /* serializes mc_send_command() */
11354 + };
11355 +};
11356 +
11357 +int mc_send_command(struct fsl_mc_io *mc_io, struct fsl_mc_command *cmd);
11358 +
11359 +#ifdef CONFIG_FSL_MC_BUS
11360 +#define dev_is_fsl_mc(_dev) ((_dev)->bus == &fsl_mc_bus_type)
11361 +#else
11362 +/* If fsl-mc bus is not present device cannot belong to fsl-mc bus */
11363 +#define dev_is_fsl_mc(_dev) (0)
11364 +#endif
11365 +
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 & \
11368 + FSL_MC_IS_DPRC)
11369 +
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)
11373 +
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))
11377 +
11378 +/*
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()
11383 + */
11384 +#define module_fsl_mc_driver(__fsl_mc_driver) \
11385 + module_driver(__fsl_mc_driver, fsl_mc_driver_register, \
11386 + fsl_mc_driver_unregister)
11387 +
11388 +void fsl_mc_device_remove(struct fsl_mc_device *mc_dev);
11389 +
11390 +/*
11391 + * Macro to avoid include chaining to get THIS_MODULE
11392 + */
11393 +#define fsl_mc_driver_register(drv) \
11394 + __fsl_mc_driver_register(drv, THIS_MODULE)
11395 +
11396 +int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver,
11397 + struct module *owner);
11398 +
11399 +void fsl_mc_driver_unregister(struct fsl_mc_driver *driver);
11400 +
11401 +int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
11402 + u16 mc_io_flags,
11403 + struct fsl_mc_io **new_mc_io);
11404 +
11405 +void fsl_mc_portal_free(struct fsl_mc_io *mc_io);
11406 +
11407 +int fsl_mc_portal_reset(struct fsl_mc_io *mc_io);
11408 +
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);
11412 +
11413 +void fsl_mc_object_free(struct fsl_mc_device *mc_adev);
11414 +
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);
11418 +
11419 +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev);
11420 +
11421 +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev);
11422 +
11423 +extern struct bus_type fsl_mc_bus_type;
11424 +
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;
11440 +
11441 +static inline bool is_fsl_mc_bus_dprc(const struct fsl_mc_device *mc_dev)
11442 +{
11443 + return mc_dev->dev.type == &fsl_mc_bus_dprc_type;
11444 +}
11445 +
11446 +static inline bool is_fsl_mc_bus_dpni(const struct fsl_mc_device *mc_dev)
11447 +{
11448 + return mc_dev->dev.type == &fsl_mc_bus_dpni_type;
11449 +}
11450 +
11451 +static inline bool is_fsl_mc_bus_dpio(const struct fsl_mc_device *mc_dev)
11452 +{
11453 + return mc_dev->dev.type == &fsl_mc_bus_dpio_type;
11454 +}
11455 +
11456 +static inline bool is_fsl_mc_bus_dpsw(const struct fsl_mc_device *mc_dev)
11457 +{
11458 + return mc_dev->dev.type == &fsl_mc_bus_dpsw_type;
11459 +}
11460 +
11461 +static inline bool is_fsl_mc_bus_dpdmux(const struct fsl_mc_device *mc_dev)
11462 +{
11463 + return mc_dev->dev.type == &fsl_mc_bus_dpdmux_type;
11464 +}
11465 +
11466 +static inline bool is_fsl_mc_bus_dpbp(const struct fsl_mc_device *mc_dev)
11467 +{
11468 + return mc_dev->dev.type == &fsl_mc_bus_dpbp_type;
11469 +}
11470 +
11471 +static inline bool is_fsl_mc_bus_dpcon(const struct fsl_mc_device *mc_dev)
11472 +{
11473 + return mc_dev->dev.type == &fsl_mc_bus_dpcon_type;
11474 +}
11475 +
11476 +static inline bool is_fsl_mc_bus_dpmcp(const struct fsl_mc_device *mc_dev)
11477 +{
11478 + return mc_dev->dev.type == &fsl_mc_bus_dpmcp_type;
11479 +}
11480 +
11481 +static inline bool is_fsl_mc_bus_dpmac(const struct fsl_mc_device *mc_dev)
11482 +{
11483 + return mc_dev->dev.type == &fsl_mc_bus_dpmac_type;
11484 +}
11485 +
11486 +static inline bool is_fsl_mc_bus_dprtc(const struct fsl_mc_device *mc_dev)
11487 +{
11488 + return mc_dev->dev.type == &fsl_mc_bus_dprtc_type;
11489 +}
11490 +
11491 +static inline bool is_fsl_mc_bus_dpseci(const struct fsl_mc_device *mc_dev)
11492 +{
11493 + return mc_dev->dev.type == &fsl_mc_bus_dpseci_type;
11494 +}
11495 +
11496 +static inline bool is_fsl_mc_bus_dpdcei(const struct fsl_mc_device *mc_dev)
11497 +{
11498 + return mc_dev->dev.type == &fsl_mc_bus_dpdcei_type;
11499 +}
11500 +
11501 +static inline bool is_fsl_mc_bus_dpaiop(const struct fsl_mc_device *mc_dev)
11502 +{
11503 + return mc_dev->dev.type == &fsl_mc_bus_dpaiop_type;
11504 +}
11505 +
11506 +static inline bool is_fsl_mc_bus_dpci(const struct fsl_mc_device *mc_dev)
11507 +{
11508 + return mc_dev->dev.type == &fsl_mc_bus_dpci_type;
11509 +}
11510 +
11511 +static inline bool is_fsl_mc_bus_dpdmai(const struct fsl_mc_device *mc_dev)
11512 +{
11513 + return mc_dev->dev.type == &fsl_mc_bus_dpdmai_type;
11514 +}
11515 +
11516 +/*
11517 + * Data Path Resource Container (DPRC) API
11518 + */
11519 +
11520 +/* Minimal supported DPRC Version */
11521 +#define DPRC_MIN_VER_MAJOR 6
11522 +#define DPRC_MIN_VER_MINOR 0
11523 +
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
11528 +
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)
11531 +
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)
11536 +
11537 +#define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004)
11538 +#define DPRC_CMDID_RESET_CONT DPRC_CMD(0x005)
11539 +
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)
11545 +
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)
11551 +
11552 +struct dprc_cmd_open {
11553 + __le32 container_id;
11554 +};
11555 +
11556 +struct dprc_cmd_reset_container {
11557 + __le32 child_container_id;
11558 +};
11559 +
11560 +struct dprc_cmd_set_irq {
11561 + /* cmd word 0 */
11562 + __le32 irq_val;
11563 + u8 irq_index;
11564 + u8 pad[3];
11565 + /* cmd word 1 */
11566 + __le64 irq_addr;
11567 + /* cmd word 2 */
11568 + __le32 irq_num;
11569 +};
11570 +
11571 +#define DPRC_ENABLE 0x1
11572 +
11573 +struct dprc_cmd_set_irq_enable {
11574 + u8 enable;
11575 + u8 pad[3];
11576 + u8 irq_index;
11577 +};
11578 +
11579 +struct dprc_cmd_set_irq_mask {
11580 + __le32 mask;
11581 + u8 irq_index;
11582 +};
11583 +
11584 +struct dprc_cmd_get_irq_status {
11585 + __le32 status;
11586 + u8 irq_index;
11587 +};
11588 +
11589 +struct dprc_rsp_get_irq_status {
11590 + __le32 status;
11591 +};
11592 +
11593 +struct dprc_cmd_clear_irq_status {
11594 + __le32 status;
11595 + u8 irq_index;
11596 +};
11597 +
11598 +struct dprc_rsp_get_attributes {
11599 + /* response word 0 */
11600 + __le32 container_id;
11601 + __le32 icid;
11602 + /* response word 1 */
11603 + __le32 options;
11604 + __le32 portal_id;
11605 +};
11606 +
11607 +struct dprc_rsp_get_obj_count {
11608 + __le32 pad;
11609 + __le32 obj_count;
11610 +};
11611 +
11612 +struct dprc_cmd_get_obj {
11613 + __le32 obj_index;
11614 +};
11615 +
11616 +struct dprc_rsp_get_obj {
11617 + /* response word 0 */
11618 + __le32 pad0;
11619 + __le32 id;
11620 + /* response word 1 */
11621 + __le16 vendor;
11622 + u8 irq_count;
11623 + u8 region_count;
11624 + __le32 state;
11625 + /* response word 2 */
11626 + __le16 version_major;
11627 + __le16 version_minor;
11628 + __le16 flags;
11629 + __le16 pad1;
11630 + /* response word 3-4 */
11631 + u8 type[16];
11632 + /* response word 5-6 */
11633 + u8 label[16];
11634 +};
11635 +
11636 +struct dprc_cmd_get_obj_region {
11637 + /* cmd word 0 */
11638 + __le32 obj_id;
11639 + __le16 pad0;
11640 + u8 region_index;
11641 + u8 pad1;
11642 + /* cmd word 1-2 */
11643 + __le64 pad2[2];
11644 + /* cmd word 3-4 */
11645 + u8 obj_type[16];
11646 +};
11647 +
11648 +struct dprc_rsp_get_obj_region {
11649 + /* response word 0 */
11650 + __le64 pad0;
11651 + /* response word 1 */
11652 + __le32 base_offset;
11653 + __le32 pad1;
11654 + /* response word 2 */
11655 + __le32 size;
11656 + u8 type;
11657 + u8 pad2[3];
11658 + /* response word 3 */
11659 + __le32 flags;
11660 + __le32 pad3;
11661 + /* response word 4 */
11662 + __le64 base_addr;
11663 +};
11664 +
11665 +struct dprc_cmd_set_obj_irq {
11666 + /* cmd word 0 */
11667 + __le32 irq_val;
11668 + u8 irq_index;
11669 + u8 pad[3];
11670 + /* cmd word 1 */
11671 + __le64 irq_addr;
11672 + /* cmd word 2 */
11673 + __le32 irq_num;
11674 + __le32 obj_id;
11675 + /* cmd word 3-4 */
11676 + u8 obj_type[16];
11677 +};
11678 +
11679 +/*
11680 + * DPRC API for managing and querying DPAA resources
11681 + */
11682 +int dprc_open(struct fsl_mc_io *mc_io,
11683 + u32 cmd_flags,
11684 + int container_id,
11685 + u16 *token);
11686 +
11687 +int dprc_close(struct fsl_mc_io *mc_io,
11688 + u32 cmd_flags,
11689 + u16 token);
11690 +
11691 +/* DPRC IRQ events */
11692 +
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
11697 +/*
11698 + * IRQ event - Indicates that one of the descendant containers that opened by
11699 + * this container is destroyed
11700 + */
11701 +#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010
11702 +
11703 +/*
11704 + * IRQ event - Indicates that on one of the container's opened object is
11705 + * destroyed
11706 + */
11707 +#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020
11708 +
11709 +/* Irq event - Indicates that object is created at the container */
11710 +#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040
11711 +
11712 +/**
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
11717 + */
11718 +struct dprc_irq_cfg {
11719 + phys_addr_t paddr;
11720 + u32 val;
11721 + int irq_num;
11722 +};
11723 +
11724 +int dprc_set_irq(struct fsl_mc_io *mc_io,
11725 + u32 cmd_flags,
11726 + u16 token,
11727 + u8 irq_index,
11728 + struct dprc_irq_cfg *irq_cfg);
11729 +
11730 +int dprc_set_irq_enable(struct fsl_mc_io *mc_io,
11731 + u32 cmd_flags,
11732 + u16 token,
11733 + u8 irq_index,
11734 + u8 en);
11735 +
11736 +int dprc_set_irq_mask(struct fsl_mc_io *mc_io,
11737 + u32 cmd_flags,
11738 + u16 token,
11739 + u8 irq_index,
11740 + u32 mask);
11741 +
11742 +int dprc_get_irq_status(struct fsl_mc_io *mc_io,
11743 + u32 cmd_flags,
11744 + u16 token,
11745 + u8 irq_index,
11746 + u32 *status);
11747 +
11748 +int dprc_clear_irq_status(struct fsl_mc_io *mc_io,
11749 + u32 cmd_flags,
11750 + u16 token,
11751 + u8 irq_index,
11752 + u32 status);
11753 +
11754 +/**
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
11760 + */
11761 +struct dprc_attributes {
11762 + int container_id;
11763 + u32 icid;
11764 + int portal_id;
11765 + u64 options;
11766 +};
11767 +
11768 +int dprc_get_attributes(struct fsl_mc_io *mc_io,
11769 + u32 cmd_flags,
11770 + u16 token,
11771 + struct dprc_attributes *attributes);
11772 +
11773 +int dprc_get_obj_count(struct fsl_mc_io *mc_io,
11774 + u32 cmd_flags,
11775 + u16 token,
11776 + int *obj_count);
11777 +
11778 +int dprc_get_obj(struct fsl_mc_io *mc_io,
11779 + u32 cmd_flags,
11780 + u16 token,
11781 + int obj_index,
11782 + struct fsl_mc_obj_desc *obj_desc);
11783 +
11784 +int dprc_set_obj_irq(struct fsl_mc_io *mc_io,
11785 + u32 cmd_flags,
11786 + u16 token,
11787 + char *obj_type,
11788 + int obj_id,
11789 + u8 irq_index,
11790 + struct dprc_irq_cfg *irq_cfg);
11791 +
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
11796 +
11797 +/**
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
11801 + */
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
11806 +};
11807 +
11808 +/**
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
11813 + * base address
11814 + * @size: Region size (in bytes)
11815 + * @flags: Region attributes
11816 + * @type: Portal region type
11817 + */
11818 +struct dprc_region_desc {
11819 + u32 base_offset;
11820 + u32 size;
11821 + u32 flags;
11822 + enum dprc_region_type type;
11823 + u64 base_address;
11824 +};
11825 +
11826 +int dprc_get_obj_region(struct fsl_mc_io *mc_io,
11827 + u32 cmd_flags,
11828 + u16 token,
11829 + char *obj_type,
11830 + int obj_id,
11831 + u8 region_index,
11832 + struct dprc_region_desc *region_desc);
11833 +
11834 +int dprc_get_api_version(struct fsl_mc_io *mc_io,
11835 + u32 cmd_flags,
11836 + u16 *major_ver,
11837 + u16 *minor_ver);
11838 +
11839 +int dprc_get_container_id(struct fsl_mc_io *mc_io,
11840 + u32 cmd_flags,
11841 + int *container_id);
11842 +
11843 +int dprc_reset_container(struct fsl_mc_io *mc_io,
11844 + u32 cmd_flags,
11845 + u16 token,
11846 + int child_container_id);
11847 +
11848 +/*
11849 + * Data Path Buffer Pool (DPBP) API
11850 + * Contains initialization APIs and runtime control APIs for DPBP
11851 + */
11852 +
11853 +int dpbp_open(struct fsl_mc_io *mc_io,
11854 + u32 cmd_flags,
11855 + int dpbp_id,
11856 + u16 *token);
11857 +
11858 +int dpbp_close(struct fsl_mc_io *mc_io,
11859 + u32 cmd_flags,
11860 + u16 token);
11861 +
11862 +int dpbp_enable(struct fsl_mc_io *mc_io,
11863 + u32 cmd_flags,
11864 + u16 token);
11865 +
11866 +int dpbp_disable(struct fsl_mc_io *mc_io,
11867 + u32 cmd_flags,
11868 + u16 token);
11869 +
11870 +int dpbp_reset(struct fsl_mc_io *mc_io,
11871 + u32 cmd_flags,
11872 + u16 token);
11873 +
11874 +/**
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
11879 + */
11880 +struct dpbp_attr {
11881 + int id;
11882 + u16 bpid;
11883 +};
11884 +
11885 +int dpbp_get_attributes(struct fsl_mc_io *mc_io,
11886 + u32 cmd_flags,
11887 + u16 token,
11888 + struct dpbp_attr *attr);
11889 +
11890 +/* Data Path Concentrator (DPCON) API
11891 + * Contains initialization APIs and runtime control APIs for DPCON
11892 + */
11893 +
11894 +/**
11895 + * Use it to disable notifications; see dpcon_set_notification()
11896 + */
11897 +#define DPCON_INVALID_DPIO_ID (int)(-1)
11898 +
11899 +int dpcon_open(struct fsl_mc_io *mc_io,
11900 + u32 cmd_flags,
11901 + int dpcon_id,
11902 + u16 *token);
11903 +
11904 +int dpcon_close(struct fsl_mc_io *mc_io,
11905 + u32 cmd_flags,
11906 + u16 token);
11907 +
11908 +int dpcon_enable(struct fsl_mc_io *mc_io,
11909 + u32 cmd_flags,
11910 + u16 token);
11911 +
11912 +int dpcon_disable(struct fsl_mc_io *mc_io,
11913 + u32 cmd_flags,
11914 + u16 token);
11915 +
11916 +int dpcon_reset(struct fsl_mc_io *mc_io,
11917 + u32 cmd_flags,
11918 + u16 token);
11919 +
11920 +/**
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)
11925 + */
11926 +struct dpcon_attr {
11927 + int id;
11928 + u16 qbman_ch_id;
11929 + u8 num_priorities;
11930 +};
11931 +
11932 +int dpcon_get_attributes(struct fsl_mc_io *mc_io,
11933 + u32 cmd_flags,
11934 + u16 token,
11935 + struct dpcon_attr *attr);
11936 +
11937 +/**
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
11944 + */
11945 +struct dpcon_notification_cfg {
11946 + int dpio_id;
11947 + u8 priority;
11948 + u64 user_ctx;
11949 +};
11950 +
11951 +int dpcon_set_notification(struct fsl_mc_io *mc_io,
11952 + u32 cmd_flags,
11953 + u16 token,
11954 + struct dpcon_notification_cfg *cfg);
11955 +
11956 +struct irq_domain;
11957 +struct msi_domain_info;
11958 +
11959 +/**
11960 + * Maximum number of total IRQs that can be pre-allocated for an MC bus'
11961 + * IRQ pool
11962 + */
11963 +#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256
11964 +
11965 +/**
11966 + * struct fsl_mc_resource_pool - Pool of MC resources of a given
11967 + * type
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
11974 + */
11975 +struct fsl_mc_resource_pool {
11976 + enum fsl_mc_pool_type type;
11977 + int max_count;
11978 + int free_count;
11979 + struct mutex mutex; /* serializes access to free_list */
11980 + struct list_head free_list;
11981 + struct fsl_mc_bus *mc_bus;
11982 +};
11983 +
11984 +/**
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
11992 + */
11993 +struct fsl_mc_restool {
11994 + struct cdev cdev;
11995 + dev_t dev;
11996 + struct device *device;
11997 + struct mutex mutex; /* serialize open/release operations */
11998 + bool local_instance_in_use;
11999 + u32 dynamic_instance_count;
12000 +};
12001 +
12002 +/**
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
12012 + */
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;
12020 +};
12021 +
12022 +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
12023 + const char *driver_override,
12024 + unsigned int *total_irq_count);
12025 +
12026 +int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
12027 + struct irq_domain **mc_msi_domain);
12028 +
12029 +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
12030 + unsigned int irq_count);
12031 +
12032 +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus);
12033 +
12034 +void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
12035 +
12036 +void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev);
12037 +
12038 +void fsl_mc_get_root_dprc(struct device *dev, struct device **root_dprc_dev);
12039 +
12040 +#endif /* _FSL_MC_H_ */
12041 --- /dev/null
12042 +++ b/include/uapi/linux/fsl_mc.h
12043 @@ -0,0 +1,31 @@
12044 +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
12045 +/*
12046 + * Management Complex (MC) userspace public interface
12047 + *
12048 + * Copyright 2018 NXP
12049 + *
12050 + */
12051 +#ifndef _UAPI_FSL_MC_H_
12052 +#define _UAPI_FSL_MC_H_
12053 +
12054 +#define MC_CMD_NUM_OF_PARAMS 7
12055 +
12056 +/**
12057 + * struct fsl_mc_command - Management Complex (MC) command structure
12058 + * @header: MC command header
12059 + * @params: MC command parameters
12060 + *
12061 + * Used by RESTOOL_SEND_MC_COMMAND
12062 + */
12063 +struct fsl_mc_command {
12064 + __u64 header;
12065 + __u64 params[MC_CMD_NUM_OF_PARAMS];
12066 +};
12067 +
12068 +#define RESTOOL_IOCTL_TYPE 'R'
12069 +#define RESTOOL_IOCTL_SEQ 0xE0
12070 +
12071 +#define RESTOOL_SEND_MC_COMMAND \
12072 + _IOWR(RESTOOL_IOCTL_TYPE, RESTOOL_IOCTL_SEQ, struct fsl_mc_command)
12073 +
12074 +#endif /* _UAPI_FSL_MC_H_ */